链码编写规范

前言

链码也就是智能合约,在网络当中扮演着逻辑处理的角色,也就是业务逻辑,所以说链码还是比较重要的。我们先来看一下链码,这个链码是我写的。代码较长大家可以用目录跳转。

代码

package main

import (
	"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 Company
	if 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 Transaction
	if 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 Transaction
	if 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 Transaction
	if 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 Transaction
	if 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=TxStatusPayForAnother
	tran1.RepaymentDate=tran.RepaymentDate
	tran1.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 Transaction
	if 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 Transaction
	if 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=TxStatusPay
	tran1.PaymentTxNumber=tran.PaymentTxNumber
	tran1.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 Transaction
	if 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 Transaction
	if 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=TxStatusRefusePay
	tran.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 Transaction
	if 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=TxStatusShip
	tran.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 Transaction
	if 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 Transaction
	if 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 Transaction
	if 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=TxStatusRepay
	tran1.RepaymentTxNumber=tran.RepaymentTxNumber
	tran1.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 Transaction
	if 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 []Transaction
	if 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 Company
	if 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 Company
	if 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-=number
	incomp.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 Company
		if 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 []Transaction
	if err:=json.Unmarshal(res.Payload,&trans);err!=nil{
		return shim.Error("unmarshal error ")
	}
	var unfinished,total,violateTreaty int
	var 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"]=transactions
	buyertrans["unfinished"]=unfinished
	buyertrans["total"]=total
	buyertrans["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 {
		// 将第一个参数取出来反序列化为[]string
		var argKeys []string
		if err := json.Unmarshal([]byte(args[0]), &argKeys); err != nil {
			return shim.Error(fmt.Sprintf("unmarshal error: %s", err))
		}

		keys = append(keys, argKeys...)
	}

	var transactions []Transaction
	if 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 Transaction
			if 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 Transaction
				err = 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.Buffer
	buffer.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)
	}
}

一、判断参数的个数

在链码交互时,我们传入的参数都是字符串数组。那么我们需要判断其传入参数个数是否正确。如果错误了,我们需要手动抛出错误信息

二、判断参数是否为空

我们需要对传入的一些参数进行非空判断,如果该参数为空,则手动抛出错误信息。

三、明确组合键

对于如何创建组合键,已结构体的那个字段来创建组合键,我们需要判断一下,用哪个字段创建
组合键比较好一点,根据方法的相关参数。

四、判断参数的正确性

在一些情况下,我们不光要判断参数是否为空,还需要判断参数的正确性,比如说,时间,还有金额之类的。

五、判断公司是否存在

在一些特定情况下我们需要判断公司是否存在如果不存在则手动抛错。

六、判断是否有权限修改订单

对于修改订单我们需要判断它是否拥有权限来修改此订单,如果不能则手动抛错。

七、判断订单状态是否正确

在修改订单状态的时候我们需要判断订单的状态是否正确、防止跳过系统流程的某一步骤。

八、修改订单信息

参数及权限还有订单状态校验完成后,我们便可以修改订单信息。

九、序列化

我们需要明确序列化哪个?千万不要序列化错了。

十、存入账本

修改完订单一定要存入账本,千万不要存错了。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

患孤

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值