本文主要是介绍链码编写规范,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
目录
- 前言
- 代码
- 一、判断参数的个数
- 二、判断参数是否为空
- 三、明确组合键
- 四、判断参数的正确性
- 五、判断公司是否存在
- 六、判断是否有权限修改订单
- 七、判断订单状态是否正确
- 八、修改订单信息
- 九、序列化
- 十、存入账本
前言
链码也就是智能合约,在网络当中扮演着逻辑处理的角色,也就是业务逻辑,所以说链码还是比较重要的。我们先来看一下链码,这个链码是我写的。代码较长大家可以用目录跳转。
代码
package mainimport ("bytes""encoding/json""fmt""github.com/hyperledger/fabric/core/chaincode/shim""github.com/hyperledger/fabric/protos/peer""strconv""time"
)const (TransactionKeyPrefix = "transaction"TxStatusNew = "新建(待确认)"TxStatusConfirm = "新建(已确认)"TxStatusPayForAnother = "申请代付"TxStatusPay = "已付款(未核实)"TxStatusPayed = "已付款(已核实)"TxStatusRefusePay = "代付被拒"TxStatusShip = "已发货(未核实)"TxstatusShiped = "已发货(已核实)"TxStatusRepay = "已还款(未核实)"TxStatusRepayed = "已还款(已核实)"
)type SupplyChainFinance struct {
}// 新建 -> 已确认 -> 申请代付 -> 已付款 ->确认付款-> 已发货 -> 确认发货 -> 已还款 -> 确认已还款
// |
// 拒绝付款 ->回到上一步
type Transaction struct {Id string `json:"id"` // 单号Description string `json:"description"` // 备注Value uint64 `json:"value"` // 金额(单位为一分钱)ShipmentNumber string `json:"shipment_number"` // 物流号PaymentTxNumber string `json:"payment_tx_number"` // 付款转账号RepaymentTxNumber string `json:"repayment_tx_number"` // 还款转账号Status string `json:"status"` // 订单状态 ----请使用上面const中的常量来标记订单状态CreateDate time.Time `json:"create_date"` // 创建时间PaymentDate time.Time `json:"payment_date"` // 付款时间RepaymentDate time.Time `json:"repayment_date"` // 应还款时间RepayDate time.Time `json:"repay_date"` // 实际还款时间Supplier string `json:"supplier"` // 供应商Company string `json:"company"` // 采购商FinancialOrg string `json:"financial_org"` // 金融机构
}type Company struct {Name string `json:"name"` //企业名Phone string `json:"phone"` //联系电话Account string `json:"account"` //登录账号Password string `json:"password"` //登录密码Address string `json:"address"` //地址CompanyType string `json:"company_type"` //企业类型,供应商,采购商,金融机构EnterpriseCode string `json:"enterprise_code"` //企业统一社会信用代码BankCard string `json:"bank_card"` //银行卡号码Balance uint64 `json:"balance"` //余额CreateDate time.Time `json:"create_date"` //创建时间
}// 企业的3种类型
var companyArg = map[string]string{"financial_org": "financial_org", "supplier": "supplier", "buyer": "buyer"}/**@Author: dd@Date: 2020/5/13 16:22@Desc: 智能合约初始化,要求必须创建3个企业,分别为供应商、采购商、金融企业 ,Company.Name="datainsights" (必需) *@Param:@Return:
**/
func (s *SupplyChainFinance) Init(stub shim.ChaincodeStubInterface) peer.Response {//实例化三个企业comp1:=Company{Name: "金融机构",Phone: "21131",Account: "1001",Password: "123456",Address: "test",CompanyType: companyArg["financial_org"],EnterpriseCode: "test",BankCard: "20000122123",Balance: 20000,CreateDate: time.Now(),}comp2:=Company{Name: "供应商",Phone: "21135311",Account: "1002",Password: "123456",Address: "test",CompanyType: companyArg["supplier"],EnterpriseCode: "test",BankCard: "5344123",Balance: 20000,CreateDate: time.Now(),}comp3:=Company{Name: "采购商",Phone: "12312313",Account: "1003",Password: "123456",Address: "test",CompanyType: companyArg["buyer"],EnterpriseCode: "test",BankCard: "21223123",Balance: 20000,CreateDate: time.Now(),}//存入数组comps:=[]Company{comp1,comp2,comp3}//遍历数组for i:=0;i<len(comps);i++{//序列化compByte,err:=json.Marshal(comps[i])if err != nil {return shim.Error("marshal error ")}res:=createCompany(stub,[]string{string(compByte)})if res.Status!=shim.OK{return peer.Response{Status: res.Status,Message: res.Message,Payload: nil,XXX_NoUnkeyedLiteral: struct{}{},XXX_unrecognized: nil,XXX_sizecache: 0,}}}return shim.Success(nil)
}func (s *SupplyChainFinance) Invoke(stub shim.ChaincodeStubInterface) peer.Response {funcName, args := stub.GetFunctionAndParameters()switch funcName {case "newTransaction":return newTransaction(stub, args)case "createCompany":return createCompany(stub, args)case "confirmTransaction":return confirmTransaction(stub, args)case "applyPayForAnother":return applyPayForAnother(stub, args)case "payTransaction":return payTransaction(stub, args)case "affirmPay":return affirmPay(stub, args)case "refusePayTransaction":return refusePayTransaction(stub, args)case "updateShipmentInfo":return updateShipmentInfo(stub, args)case "verifyShipmentInfo":return verifyShipmentInfo(stub, args)case "repayTransaction":return repayTransaction(stub, args)case "verifyRepay":return verifyRepay(stub, args)case "autoRepay":return autoRepay(stub, args)case "getTransactions":return getTransactions(stub, args)case "getTrByBuyer":return getTrByBuyer(stub, args)case "getTransactionHistory":return getTransactionHistory(stub, args)case "getCompany":return getCompany(stub, args)default:return shim.Error(fmt.Sprintf("unsupported function: %s", funcName))}
}/**@Author: dd@Date: 2020/5/13 16:48@Desc: 根据company.CompanyType来创建3种不同的企业*@Param: Company@Return: res = peer.Response, 要求返回结果时能够返回正确相应的响应码:shim.ERROR,shim.ERRORTHRESHOLD,shim.OK
**/
func createCompany(stub shim.ChaincodeStubInterface, args []string) peer.Response {
// 验证参数if len(args)!=1{return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "参数长度错误",Payload: nil,XXX_NoUnkeyedLiteral: struct{}{},XXX_unrecognized: nil,XXX_sizecache: 0,}}if args[0]==""{return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "参数为空",Payload: nil,}}
// 反序列化var comp Companyif err:=json.Unmarshal([]byte(args[0]),&comp);err!=nil{return shim.Error("unmarshal error ")}
// 验证参数if comp.Account==""||comp.Address==""||comp.Balance<0||comp.BankCard==""||comp.EnterpriseCode==""||comp.Name==""||comp.Password==""||comp.Phone==""{return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "必要参数为空",Payload: nil,}}if comp.CompanyType!=companyArg["financial_org"]||comp.CompanyType!=companyArg["supplier"]||comp.CompanyType!=companyArg["buyer"]{return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "没有此企业类型",Payload: nil,}}
// 创建组合键compKey,err:=stub.CreateCompositeKey(comp.CompanyType,[]string{comp.Name})if err != nil {return shim.Error("create key error ")}
// 序列化存入账本compByte,err:=json.Marshal(comp)if err != nil {return shim.Error("marshal error ")}if err:=stub.PutState(compKey,compByte);err!=nil{return shim.Error("put state error ")}return shim.Success(compByte)
}/**@Author: dd@Date: 2020/5/15 18:01@Desc: 创建新的交易 *@Param: {id:string, Value:int, supplier:string, create_date:time.Time, company:string}@Return:
**/
func newTransaction(stub shim.ChaincodeStubInterface, args []string) peer.Response {if len(args)!=1{return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "参数长度错误",Payload: nil,}}if args[0]==""{return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "参数为空",Payload: nil,}}
// 反序列化var tran Transactionif err:=json.Unmarshal([]byte(args[0]),&tran);err!=nil{return shim.Error("unmarshal error")}
// 验证必要参数if tran.Id==""||tran.Value<0||tran.Supplier==""||tran.Company==""{return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "参数为空或者订单金额小于0",Payload: nil,}}//if !valideCompany(stub,companyArg["supplier"],tran.Supplier){// return peer.Response{// Status: shim.ERRORTHRESHOLD,// Message: "未找到此企业",// Payload: nil,// }//}//if !valideCompany(stub,companyArg["buyer"],tran.Company){// return peer.Response{// Status: shim.ERRORTHRESHOLD,// Message: "未找到此企业",// Payload: nil,// }//}
// 修改订单状态tran.Status=TxStatusNew
// 创建组合键tranKey,err:=stub.CreateCompositeKey(TransactionKeyPrefix,[]string{tran.Id})if err != nil {return shim.Error("create key error ")}
// 序列化存入账本tranByte,err:=json.Marshal(tran)if err != nil {return shim.Error("marshal error ")}if err:=stub.PutState(tranKey,tranByte);err!=nil{return shim.Error("put state error ")}return shim.Success(tranByte)
}/**@Author: dd@Date: 2020/5/15 18:00@Desc: 供应商确认交易 *@Param: {id:string, supplier:string}@Return:
**/
func confirmTransaction(stub shim.ChaincodeStubInterface, args []string) peer.Response {if len(args)!=2{return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "参数长度错误",Payload: nil,}}if args[0]==""||args[1]==""{return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "参数为空",Payload: nil,}}//创建组合键tranKey,err:=stub.CreateCompositeKey(TransactionKeyPrefix,[]string{args[0]})if err != nil {return shim.Error("create error ")}// 从账本中获取数据tranByte,err:=stub.GetState(tranKey)if err != nil {return shim.Error("get state error ")}// 反序列化var tran Transactionif err:=json.Unmarshal(tranByte,&tran);err!=nil{return shim.Error("unmarshal error")}// 验证是否拥有权限if tran.Supplier!=args[1]{return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "无权限修改此订单",Payload: nil,}}// 判断订单状态if tran.Status!=TxStatusNew{return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "订单状态出错",Payload: nil,}}// 修改订单信息tran.Status=TxStatusConfirm// 序列化存入账本tranByteNew,err:=json.Marshal(tran)if err != nil {return shim.Error("marshal error ")}if err:=stub.PutState(tranKey,tranByteNew);err!=nil{return shim.Error("put state error ")}return shim.Success(tranByteNew)
}/**@Author: dd@Date: 2020/5/15 17:57@Desc: 向金融机构申请代付 *@Param: {id:string, company:string, financial_org:string, repayment_date:time.Time}@Return:
**/
func applyPayForAnother(stub shim.ChaincodeStubInterface, args []string) peer.Response {if len(args)!=1{return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "参数长度错误",Payload: nil,}}if args[0]==""{return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "参数为空",Payload: nil,}}// 反序列化var tran Transactionif err:=json.Unmarshal([]byte(args[0]),&tran);err!=nil{return shim.Error("unmarshal error")}// 验证必要参数if tran.Id==""||tran.Company==""||tran.FinancialOrg==""{return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "参数为空",Payload: nil,}}// 判断是否存在此企业if !valideCompany(stub,companyArg["financial_org"],tran.FinancialOrg){return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "未找到此企业",Payload: nil,}}//创建组合键tranKey,err:=stub.CreateCompositeKey(TransactionKeyPrefix,[]string{tran.Id})if err != nil {return shim.Error("create error ")}// 从账本中获取数据tranByte,err:=stub.GetState(tranKey)if err != nil {return shim.Error("get state error ")}// 反序列化var tran1 Transactionif err:=json.Unmarshal(tranByte,&tran1);err!=nil{return shim.Error("unmarshal error")}// 验证是否拥有权限if tran1.Company!=tran.Company{return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "无权限修改此订单",Payload: nil,}}// 判断订单状态if tran1.Status!=TxStatusRefusePay||tran1.Status!=TxStatusConfirm{return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "订单状态出错",Payload: nil,}}// 修改订单状信息tran1.Status=TxStatusPayForAnothertran1.RepaymentDate=tran.RepaymentDatetran1.FinancialOrg=tran.FinancialOrg// 序列化存入账本tranByteNew,err:=json.Marshal(tran1)if err != nil {return shim.Error("marshal error ")}if err:=stub.PutState(tranKey,tranByteNew);err!=nil{return shim.Error("put state error ")}return shim.Success(tranByteNew)
}/**@Author: dd@Date: 2020/5/15 17:57@Desc: 付款 *@Param: {id:string,PaymentTxNumber:string,financial_org:string,payment_date:time.Time}@Return:
**/
func payTransaction(stub shim.ChaincodeStubInterface, args []string) peer.Response {if len(args)!=1{return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "参数长度错误",Payload: nil,}}if args[0]==""{return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "参数为空",Payload: nil,}}// 反序列化var tran Transactionif err:=json.Unmarshal([]byte(args[0]),&tran);err!=nil{return shim.Error("unmarshal error")}// 验证必要参数if tran.Id==""||tran.PaymentTxNumber==""||tran.FinancialOrg==""{return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "参数为空",Payload: nil,}}//创建组合键tranKey,err:=stub.CreateCompositeKey(TransactionKeyPrefix,[]string{tran.Id})if err != nil {return shim.Error("create error ")}// 从账本中获取数据tranByte,err:=stub.GetState(tranKey)if err != nil {return shim.Error("get state error ")}// 反序列化var tran1 Transactionif err:=json.Unmarshal(tranByte,&tran1);err!=nil{return shim.Error("unmarshal error")}// 验证是否拥有权限if tran1.FinancialOrg!=tran.FinancialOrg{return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "无权限修改此订单",Payload: nil,}}// 判断订单状态if tran1.Status!=TxStatusPayForAnother{return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "订单状态出错",Payload: nil,}}//执行转账res:=transferAccounts(stub,tran1.FinancialOrg,companyArg["financial_org"],tran1.Supplier,companyArg["supplier"],tran1.Value)if res.Status!=shim.OK{return peer.Response{Status: res.Status,Message: res.Message,Payload: nil,}}// 修改订单信息tran1.Status=TxStatusPaytran1.PaymentTxNumber=tran.PaymentTxNumbertran1.PaymentDate=tran.PaymentDate// 序列化存入账本tranByteNew,err:=json.Marshal(tran1)if err != nil {return shim.Error("marshal error ")}if err:=stub.PutState(tranKey,tranByteNew);err!=nil{return shim.Error("put state error ")}return shim.Success(tranByteNew)
}/**@Author: dd@Date: 2020/5/15 18:00@Desc: 供应商核实付款 *@Param: {id:string, supplier:string}@Return:
**/
func affirmPay(stub shim.ChaincodeStubInterface, args []string) peer.Response {if len(args)!=2{return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "参数长度错误",Payload: nil,}}if args[0]==""||args[1]==""{return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "参数为空",Payload: nil,}}//创建组合键tranKey,err:=stub.CreateCompositeKey(TransactionKeyPrefix,[]string{args[0]})if err != nil {return shim.Error("create error ")}// 从账本中获取数据tranByte,err:=stub.GetState(tranKey)if err != nil {return shim.Error("get state error ")}// 反序列化var tran Transactionif err:=json.Unmarshal(tranByte,&tran);err!=nil{return shim.Error("unmarshal error")}// 验证是否拥有权限if tran.Supplier!=args[1]{return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "无权限修改此订单",Payload: nil,}}// 判断订单状态if tran.Status!=TxStatusPay{return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "订单状态出错",Payload: nil,}}// 修改订单信息tran.Status=TxStatusPayed// 序列化存入账本tranByteNew,err:=json.Marshal(tran)if err != nil {return shim.Error("marshal error ")}if err:=stub.PutState(tranKey,tranByteNew);err!=nil{return shim.Error("put state error ")}return shim.Success(tranByte)
}/**@Author: dd@Date: 2020/5/15 17:55@Desc: 拒绝付款要求 *@Param: {id:string,description:string,financial_org:string}@Return:
**/
func refusePayTransaction(stub shim.ChaincodeStubInterface, args []string) peer.Response {if len(args)!=3{return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "参数长度错误",Payload: nil,}}if args[0]==""||args[1]==""||args[2]==""{return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "参数为空",Payload: nil,}}//创建组合键tranKey,err:=stub.CreateCompositeKey(TransactionKeyPrefix,[]string{args[0]})if err != nil {return shim.Error("create error ")}// 从账本中获取数据tranByte,err:=stub.GetState(tranKey)if err != nil {return shim.Error("get state error ")}// 反序列化var tran Transactionif err:=json.Unmarshal(tranByte,&tran);err!=nil{return shim.Error("unmarshal error")}// 验证是否拥有权限if tran.FinancialOrg!=args[2]{return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "无权限修改此订单",Payload: nil,}}// 判断订单状态if tran.Status!=TxStatusPayForAnother||tran.Status!=TxStatusRefusePay{return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "订单状态出错",Payload: nil,}}// 修改订单信息tran.Status=TxStatusRefusePaytran.Description=args[1]// 序列化存入账本tranByteNew,err:=json.Marshal(tran)if err != nil {return shim.Error("marshal error ")}if err:=stub.PutState(tranKey,tranByteNew);err!=nil{return shim.Error("put state error ")}return shim.Success(tranByteNew)
}/**@Author: dd@Date: 2020/5/15 17:54@Desc: 供应商发货 *@Param: {id:string,shipment_number:string,supplier:string}@Return:
**/
func updateShipmentInfo(stub shim.ChaincodeStubInterface, args []string) peer.Response {if len(args)!=3{return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "参数长度错误",Payload: nil,}}if args[0]==""||args[1]==""||args[2]==""{return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "参数为空",Payload: nil,}}//创建组合键tranKey,err:=stub.CreateCompositeKey(TransactionKeyPrefix,[]string{args[0]})if err != nil {return shim.Error("create error ")}// 从账本中获取数据tranByte,err:=stub.GetState(tranKey)if err != nil {return shim.Error("get state error ")}// 反序列化var tran Transactionif err:=json.Unmarshal(tranByte,&tran);err!=nil{return shim.Error("unmarshal error")}// 验证是否拥有权限if tran.Supplier!=args[2]{return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "无权限修改此订单",Payload: nil,}}// 判断订单状态if tran.Status!=TxStatusPayed{return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "订单状态出错",Payload: nil,}}// 修改订单信息tran.Status=TxStatusShiptran.ShipmentNumber=args[1]// 序列化存入账本tranByteNew,err:=json.Marshal(tran)if err != nil {return shim.Error("marshal error ")}if err:=stub.PutState(tranKey,tranByteNew);err!=nil{return shim.Error("put state error ")}return shim.Success(tranByteNew)
}/**@Author: dd@Date: 2020/5/15 17:53@Desc: 买方收货 *@Param: {id:string,company:string}@Return:
**/
func verifyShipmentInfo(stub shim.ChaincodeStubInterface, args []string) peer.Response {if len(args)!=2{return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "参数长度错误",Payload: nil,}}if args[0]==""||args[1]==""{return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "参数为空",Payload: nil,}}//创建组合键tranKey,err:=stub.CreateCompositeKey(TransactionKeyPrefix,[]string{args[0]})if err != nil {return shim.Error("create error ")}// 从账本中获取数据tranByte,err:=stub.GetState(tranKey)if err != nil {return shim.Error("get state error ")}// 反序列化var tran Transactionif err:=json.Unmarshal(tranByte,&tran);err!=nil{return shim.Error("unmarshal error")}// 验证是否拥有权限if tran.Company!=args[1]{return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "无权限修改此订单",Payload: nil,}}// 判断订单状态if tran.Status!=TxStatusShip{return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "订单状态出错",Payload: nil,}}// 修改订单信息tran.Status=TxstatusShiped// 序列化存入账本tranByteNew,err:=json.Marshal(tran)if err != nil {return shim.Error("marshal error ")}if err:=stub.PutState(tranKey,tranByteNew);err!=nil{return shim.Error("put state error ")}return shim.Success(tranByteNew)
}/**@Author: dd@Date: 2020/5/15 17:50@Desc: 买方还款 *@Param: {id:string,repayment_tx_number:string,tx_to_update:time.Time,company:string}@Return:
**/
func repayTransaction(stub shim.ChaincodeStubInterface, args []string) peer.Response {if len(args)!=1{return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "参数长度错误",Payload: nil,}}if args[0]==""{return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "参数为空",Payload: nil,}}// 反序列化var tran Transactionif err:=json.Unmarshal([]byte(args[0]),&tran);err!=nil{return shim.Error("unmarshal error")}// 验证必要参数if tran.Id==""||tran.RepaymentTxNumber==""||tran.Company==""{return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "参数为空",Payload: nil,}}//创建组合键tranKey,err:=stub.CreateCompositeKey(TransactionKeyPrefix,[]string{tran.Id})if err != nil {return shim.Error("create error ")}// 从账本中获取数据tranByte,err:=stub.GetState(tranKey)if err != nil {return shim.Error("get state error ")}// 反序列化var tran1 Transactionif err:=json.Unmarshal(tranByte,&tran1);err!=nil{return shim.Error("unmarshal error")}// 验证是否拥有权限if tran1.Company!=tran.Company{return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "无权限修改此订单",Payload: nil,}}// 判断订单状态if tran1.Status!=TxstatusShiped{return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "订单状态出错",Payload: nil,}}//执行转账res:=transferAccounts(stub,tran1.Company,companyArg["buyer"],tran1.FinancialOrg,companyArg["financial_org"],tran1.Value)if res.Status!=shim.OK{return peer.Response{Status: res.Status,Message: res.Message,Payload: nil,}}// 修改订单信息tran1.Status=TxStatusRepaytran1.RepaymentTxNumber=tran.RepaymentTxNumbertran1.RepayDate=tran.RepayDate// 序列化存入账本tranByteNew,err:=json.Marshal(tran1)if err != nil {return shim.Error("marshal error ")}if err:=stub.PutState(tranKey,tranByteNew);err!=nil{return shim.Error("put state error ")}return shim.Success(tranByteNew)
}/**@Author: dd@Date: 2020/5/15 17:48@Desc: 金融机构确认还款 *@Param: {id:string,financial_org:string}@Return:
**/
func verifyRepay(stub shim.ChaincodeStubInterface, args []string) peer.Response {if len(args)!=2{return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "参数长度错误",Payload: nil,}}if args[0]==""||args[1]==""{return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "参数为空",Payload: nil,}}//创建组合键tranKey,err:=stub.CreateCompositeKey(TransactionKeyPrefix,[]string{args[0]})if err != nil {return shim.Error("create error ")}// 从账本中获取数据tranByte,err:=stub.GetState(tranKey)if err != nil {return shim.Error("get state error ")}// 反序列化var tran Transactionif err:=json.Unmarshal(tranByte,&tran);err!=nil{return shim.Error("unmarshal error")}// 验证是否拥有权限if tran.FinancialOrg!=args[1]{return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "无权限修改此订单",Payload: nil,}}// 判断订单状态if tran.Status!=TxStatusRepay{return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "订单状态出错",Payload: nil,}}// 修改订单信息tran.Status=TxStatusRepayed// 序列化存入账本tranByteNew,err:=json.Marshal(tran)if err != nil {return shim.Error("marshal error ")}if err:=stub.PutState(tranKey,tranByteNew);err!=nil{return shim.Error("put state error ")}return shim.Success(tranByteNew)
}
/**@Author: dd@Date: 2020/5/15 17:48@Desc: 自动还款 *@Param: { time:string }@Return:
**/
func autoRepay(stub shim.ChaincodeStubInterface, args []string) peer.Response {//验证参数if len(args)!=1{return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "参数长度错误",Payload: nil,}}if args[0]==""{return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "参数为空",Payload: nil,}}nowTime,err:=time.Parse("2006-01-02 13:04:05",args[0])if err != nil {return shim.Error("time parse error")}
// 获取所有订单// 查询所有订单res:=getTransactions(stub,[]string{})if res.Status!=shim.OK{return peer.Response{Status: res.Status,Message: res.Message,Payload: nil,}}// 反序列化var trans []Transactionif err:=json.Unmarshal(res.Payload,&trans);err!=nil{return shim.Error("unmarshal error ")}
// 遍历数组for i:=0;i<len(trans);i++{//判断是否超时if trans[i].RepaymentDate.Unix()<nowTime.Unix(){//执行转账res:=transferAccounts(stub,trans[i].Company,companyArg["buyer"],trans[i].FinancialOrg,companyArg["financial_org"],trans[i].Value)if res.Status!=shim.OK{return peer.Response{Status: res.Status,Message: res.Message,Payload: nil,}}//修改订单状态trans[i].Status=TxStatusRepayed//创建组合键tranKey,err:=stub.CreateCompositeKey(TransactionKeyPrefix,[]string{trans[i].Id})if err != nil {return shim.Error("create key error ")}//序列化存入账本tranByte,err:=json.Marshal(trans[i])if err != nil {return shim.Error("marshal error ")}if err:=stub.PutState(tranKey,tranByte);err!=nil{return shim.Error("put state error ")}}}return shim.Success(nil)
}/**@Author: dd@Date: 2020/5/14 17:40@Desc: 验证公司是否存在 *@Param: companyType:string, name:string@Return: bool,存在返回true,不存在返回false
**/
func valideCompany(stub shim.ChaincodeStubInterface, companyType, name string) bool {// 验证参数if companyType==""||name==""{return false}if companyType!=companyArg["financial_org"]||companyType!=companyArg["supplier"]||companyType!=companyArg["buyer"]{return false}
// 创建组合键compKey,err:=stub.CreateCompositeKey(companyType,[]string{name})if err != nil {return false}
// 从账本中获取数据compByte,err:=stub.GetState(compKey)if err != nil {return false}if len(compByte)==0{return false}return true
}/**@Author: dd@Date: 2020/5/14 17:41@Desc: 转账 从out转到in *@Param:@Return:
**/
func transferAccounts(stub shim.ChaincodeStubInterface, out, outType, in, inType string, number uint64) peer.Response {if out==""||outType==""||in==""||inType==""||number<=0{return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "参数为空",Payload: nil,}}if out!=companyArg["financial_org"]||out!=companyArg["supplier"]||out!=companyArg["buyer"]||in!=companyArg["financial_org"]||in!=companyArg["supplier"]||in!=companyArg["buyer"]{return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "没有此企业类型",Payload: nil,}}
// 验证企业是否存在if !valideCompany(stub,outType,out){return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "未找到此企业",Payload: nil,}}if !valideCompany(stub,inType,in){return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "未找到此企业",Payload: nil,}}
// 创建组合键outKey,err:=stub.CreateCompositeKey(outType,[]string{out})if err != nil {return shim.Error("create key error ")}
// 从账本中获取数据outByte,err:=json.Marshal(outKey)if err != nil {return shim.Error("marshal error ")}
// 反序列化var outcomp Companyif err:=json.Unmarshal(outByte,&outcomp);err!=nil{return shim.Error("unmarshal error ")}// 创建组合键inKey,err:=stub.CreateCompositeKey(inType,[]string{in})if err != nil {return shim.Error("create key error ")}
// 从账本中获取数据inByte,err:=json.Marshal(inKey)if err != nil {return shim.Error("marshal error ")}
// 反序列化var incomp Companyif err:=json.Unmarshal(inByte,&incomp);err!=nil{return shim.Error("unmarshal error ")}
// 判断余额if outcomp.Balance<number{return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "余额不足",Payload: nil,}}outcomp.Balance-=numberincomp.Balance+=number
// 序列化存入账本outByteNew,err:=json.Marshal(outcomp)if err != nil {return shim.Error("marshal error ")}if err:=stub.PutState(outKey,outByteNew);err!=nil{return shim.Error("put state error ")}// 序列化存入账本inByteNew,err:=json.Marshal(incomp)if err != nil {return shim.Error("marshal error ")}if err:=stub.PutState(inKey,inByteNew);err!=nil{return shim.Error("put state error ")}return shim.Success(nil)
}/**@Author: dd@Date: 2020/5/15 17:45@Desc: 根据企业类型获取企业信息 *@Param: companyType:string 企业类型@Return: companys:[]Company
**/
func getCompany(stub shim.ChaincodeStubInterface, args []string) peer.Response {
// 验证参数if len(args)!=1{return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "参数长度错误",Payload: nil,}}if args[0]==""{return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "参数为空",Payload: nil,}}if args[0]!=companyArg["financial_org"]||args[0]!=companyArg["supplier"]||args[0]!=companyArg["buyer"]{return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "没有此企业类型",Payload: nil,}}
// 根据前缀从账本中获取数据result,err:=stub.GetStateByPartialCompositeKey(args[0],[]string{})if err != nil {return shim.Error("GetStateByPartialCompositeKey error ")}var comps []Company
// 最后关闭结果集defer result.Close()
// 遍历结果集for result.HasNext(){val,err:=result.Next()if err != nil {return shim.Error("next error ")}// 反序列化var comp Companyif err:=json.Unmarshal(val.GetValue(),&comp);err!=nil{return shim.Error("unmarshal error")}// 追加至数组comps= append(comps, comp)}compsByte,err:=json.Marshal(comps)if err != nil {return shim.Error("marshal error ")}return shim.Success(compsByte)
}/**@Author: dd@Date: 2020/5/15 17:37@Desc: 获取买方的交易信息 *@Param: buyer 买方公司名@Return: {transactions:[]Transaction,unfinished:int,total:int,violateTreaty:int}分别为此买方的交易信息、未完成交易数、交易总数、违约交易数(实际还款时间RepayDate大于应还款时间RepaymentDate)z
**/
func getTrByBuyer(stub shim.ChaincodeStubInterface, args []string) peer.Response {// 验证参数if len(args)!=1{return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "参数长度错误",Payload: nil,}}if args[0]==""{return peer.Response{Status: shim.ERRORTHRESHOLD,Message: "参数为空",Payload: nil,}}
// 查询所有订单res:=getTransactions(stub,[]string{})if res.Status!=shim.OK{return peer.Response{Status: res.Status,Message: res.Message,Payload: nil,}}
// 反序列化var trans []Transactionif err:=json.Unmarshal(res.Payload,&trans);err!=nil{return shim.Error("unmarshal error ")}var unfinished,total,violateTreaty intvar transactions []Transaction// 遍历数组for i:=0;i<len(trans);i++{// 寻找买家订单if trans[i].Company==args[0]{transactions= append(transactions, trans[i])total++if trans[i].Status!=TxStatusRepayed{unfinished++}if trans[i].RepaymentDate.Unix()<trans[i].RepayDate.Unix(){violateTreaty++}}}buyertrans:=make(map[string]interface{})buyertrans["transactions"]=transactionsbuyertrans["unfinished"]=unfinishedbuyertrans["total"]=totalbuyertrans["violateTreaty"]=violateTreaty
// 序列化buyertransByte,err:=json.Marshal(buyertrans)if err != nil {return shim.Error("marshal error ")}return shim.Success(buyertransByte)
}/**@Author: dd@Date: 2020/5/15 18:04@Desc: 获取交易信息 根据Id查询交易,不传数组则查询所有@Param: [id0,id1] []string@Return: transactions []Transaction
**/
func getTransactions(stub shim.ChaincodeStubInterface, args []string) peer.Response {// 检查参数的个数if len(args) > 1 {return shim.Error("invalid args.")}// 所有要查询的key,如果为空则查询所有var keys []string// 验证参数的正确性if len(args) == 1 {// 将第一个参数取出来反序列化为[]stringvar argKeys []stringif err := json.Unmarshal([]byte(args[0]), &argKeys); err != nil {return shim.Error(fmt.Sprintf("unmarshal error: %s", err))}keys = append(keys, argKeys...)}var transactions []Transactionif len(keys) == 0 {// 传入的keys长度为0,则查找并返回所有数据// 通过主键从区块链查找相关的数据resultIterator, err := stub.GetStateByPartialCompositeKey(TransactionKeyPrefix, keys)if err != nil {return shim.Error(fmt.Sprintf("query transactions error: %s", err))}defer resultIterator.Close()// 检查返回的数据是否为空,不为空则遍历数据,否则返回空数组for resultIterator.HasNext() {val, err := resultIterator.Next()if err != nil {return shim.Error(fmt.Sprintf("resultIterator error: %s", err))}var transaction Transactionif err := json.Unmarshal(val.GetValue(), &transaction); err != nil {return shim.Error(fmt.Sprintf("unmarshal error: %s", err))}transactions = append(transactions, transaction)}} else {// 传入的keys长度不为0,查找相应的数据并返回for _, v := range keys {// 创建组合键key, err := stub.CreateCompositeKey(TransactionKeyPrefix, []string{v})if err != nil {return shim.Error(fmt.Sprintf("CreateCompositeKey error: %s", err))}// 从账本中获取数据partBytes, err := stub.GetState(key)if err != nil {return shim.Error(fmt.Sprintf("GetState error: %s", err))}if len(partBytes) != 0 {// 反序列化数据var transaction Transactionerr = json.Unmarshal(partBytes, &transaction)if err != nil {return shim.Error(fmt.Sprintf("Unmarshal error: %s", err))}// 追加进结果数组transactions = append(transactions, transaction)}}}//序列化数据result, err := json.Marshal(transactions)if err != nil {return shim.Error(fmt.Sprintf("marshal error: %s", err))}return shim.Success(result)
}/**@Author: dd@Date: 2020/5/15 18:07@Desc: 查询此交易的历史信息@Param: id:string@Return:
**/
func getTransactionHistory(stub shim.ChaincodeStubInterface, args []string) peer.Response {// 检查参数的个数if len(args) != 1 {return shim.Error("只需要一个参数:订单id")}// 创建组合键compositeKey, err := stub.CreateCompositeKey(TransactionKeyPrefix, args)if err != nil {return shim.Error(fmt.Sprintf("CreateCompositeKey error: %s", err))}// 获取该key的历史,返回一个迭代器resultIterator, err := stub.GetHistoryForKey(compositeKey)if err != nil {return shim.Error(fmt.Sprintf("GetHistoryForKey error: %s", err))}defer resultIterator.Close()// buffer是一个包含了订单历史记录的JSON数组var buffer bytes.Bufferbuffer.WriteString("[")bArrayMemberAlreadyWritten := false// 遍历迭代器,将值取出来for resultIterator.HasNext() {response, err := resultIterator.Next()if err != nil {return shim.Error(err.Error())}// 在数组元素前加",",第一个元素前不加if bArrayMemberAlreadyWritten == true {buffer.WriteString(",")}buffer.WriteString("{\"TxId\":")buffer.WriteString("\"")buffer.WriteString(response.TxId)buffer.WriteString("\"")buffer.WriteString(", \"Value\":")// 如果该记录的操作是删除,则返回null,否则返回数据的值if response.IsDelete {buffer.WriteString("null")} else {buffer.WriteString(string(response.Value))}buffer.WriteString(", \"Timestamp\":")buffer.WriteString("\"")buffer.WriteString(time.Unix(response.Timestamp.Seconds, int64(response.Timestamp.Nanos)).String())buffer.WriteString("\"")buffer.WriteString(", \"IsDelete\":")buffer.WriteString("\"")buffer.WriteString(strconv.FormatBool(response.IsDelete))buffer.WriteString("\"")buffer.WriteString("}")bArrayMemberAlreadyWritten = true}buffer.WriteString("]")fmt.Printf("getHistoryForPatent returning:\n%s\n", buffer.String())// 返回结果return shim.Success(buffer.Bytes())
}func main() {err := shim.Start(new(SupplyChainFinance))if err != nil {fmt.Printf("Error starting chaincode: %s", err)}
}
一、判断参数的个数
在链码交互时,我们传入的参数都是字符串数组。那么我们需要判断其传入参数个数是否正确。如果错误了,我们需要手动抛出错误信息
二、判断参数是否为空
我们需要对传入的一些参数进行非空判断,如果该参数为空,则手动抛出错误信息。
三、明确组合键
对于如何创建组合键,已结构体的那个字段来创建组合键,我们需要判断一下,用哪个字段创建
组合键比较好一点,根据方法的相关参数。
四、判断参数的正确性
在一些情况下,我们不光要判断参数是否为空,还需要判断参数的正确性,比如说,时间,还有金额之类的。
五、判断公司是否存在
在一些特定情况下我们需要判断公司是否存在如果不存在则手动抛错。
六、判断是否有权限修改订单
对于修改订单我们需要判断它是否拥有权限来修改此订单,如果不能则手动抛错。
七、判断订单状态是否正确
在修改订单状态的时候我们需要判断订单的状态是否正确、防止跳过系统流程的某一步骤。
八、修改订单信息
参数及权限还有订单状态校验完成后,我们便可以修改订单信息。
九、序列化
我们需要明确序列化哪个?千万不要序列化错了。
十、存入账本
修改完订单一定要存入账本,千万不要存错了。
这篇关于链码编写规范的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!