/* Copyright 33.cn Corp. 2017 All Rights Reserved. Chaincode for Meidi Corp. Chang history: 2017/4/12 Building successfully. 2017/4/11 init version. */ package main import ( "encoding/json" "errors" "fmt" "strconv" "time" "github.com/hyperledger/fabric/core/chaincode/shim" pb "github.com/hyperledger/fabric/protos/peer" ) var ( transactionNo int = 0 layout = "2006-01-02 15:04:05" loc *time.Location ) func init() { loc, _ = time.LoadLocation("Asia/Shanghai") } // SimpleChaincode example simple Chaincode implementation type SimpleChaincode struct { } type Bill struct { Acceptor string `json:"acceptor"` AcceptorActno string `json:"acceptorActno"` AcceptorBankId int `json:"acceptorBankId"` AcceptorBankName string `json:"acceptorBankName"` CanTransfer string `json:"canTransfer"` DraftNumber string `json:"draftNumber"` DraftState string `json:"draftState"` DraftType string `json:"draftType"` FaceAmount int64 `json:"faceAmount"` MaturityDate string `json:"maturityDate"` PayeeAccount string `json:"payeeAccount"` PayeeBankName string `json:"payeeBankName"` PayeeName string `json:"payeeName"` RemitDate string `json:"remitDate"` RemitterAccount string `json:"remitterAccount"` RemitterBankName string `json:"remitterBankName"` RemitterName string `json:"remitterName"` CreateTime string `json:"createTime"` UpdateTime string `json:"updateTime"` } type BillFail struct { DraftNumber string `json:"draftNumber"` ErrInfo string `json:"errInfo"` } type BatchResult struct { SuccNum int `json:"succNum"` FailNum int `json:"failNum"` FailInfos []BillFail `json:"billFails"` } // Record all operation include the create/change or the bill type Transaction struct { BillId string Operation string BillStatus string Time int64 ID int } func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response { return shim.Success(nil) } func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response { function, args := stub.GetFunctionAndParameters() if function == "createBill" { return t.createBill(stub, args) } else if function == "createBillBatch" { return t.createBillBatch(stub, args) } else if function == "changeBillStatus" { return t.changeBillStatus(stub, args) } else if function == "queryBill" { return t.queryBill(stub, args) } else if function == "queryTransaction" { return t.queryTransaction(stub, args) } return shim.Error("Invalid invoke function name. Expecting \"createBill\" \"changeBillStaus\" \"queryBill\" \"queryTransaction\"") } func (t *SimpleChaincode) createBill(stub shim.ChaincodeStubInterface, args []string) pb.Response { if len(args) != 17 { fmt.Println("createBill: args numbers is:", len(args)) return shim.Error("createBill(): Incorrect number of arguments. Expecting 11") } orbankId, err := strconv.Atoi(args[2]) if err != nil { fmt.Println("createBill: args[2] is:", args[2]) return shim.Error("Expecting integer value for asset holding") } amount, err := strconv.ParseInt(args[8], 10, 64) if err != nil { fmt.Println("createBill: args[8] is:", args[8]) return shim.Error("Expecting integer value for asset holding") } datetime := time.Now().In(loc).Format(layout) bill := Bill{ Acceptor: args[0], AcceptorActno: args[1], AcceptorBankId: orbankId, AcceptorBankName: args[3], CanTransfer: args[4], DraftNumber: args[5], DraftState: args[6], DraftType: args[7], FaceAmount: amount, MaturityDate: args[9], PayeeAccount: args[10], PayeeBankName: args[11], PayeeName: args[12], RemitDate: args[13], RemitterAccount: args[14], RemitterBankName: args[15], RemitterName: args[16], CreateTime: datetime, UpdateTime: datetime, } err = writeBill(stub, bill) if err != nil { fmt.Println("createBill: writeBill fail:", err.Error()) return shim.Error("createBill(): Fail to write the bill" + err.Error()) } return shim.Success(nil) } func (t *SimpleChaincode) createBillBatch(stub shim.ChaincodeStubInterface, args []string) pb.Response { if len(args) != 1 { fmt.Println("createBillBatch: args numbers is:", len(args)) return shim.Error("createBillBatch: Incorrect number of arguments. Expecting 11") } var billInfos []Bill err := json.Unmarshal([]byte(args[0]), &billInfos) if err != nil { fmt.Println("getBillById: Unmarshal fail:", err.Error()) return shim.Error("createBillBatch(): json.Unmarshal fail:" + err.Error()) } datetime := time.Now().In(loc).Format(layout) result := BatchResult{} for _, bill := range billInfos { bill.CreateTime = datetime bill.UpdateTime = datetime err = writeBill(stub, bill) if err != nil { b := BillFail{ DraftNumber: bill.DraftNumber, ErrInfo: err.Error(), } result.FailInfos = append(result.FailInfos, b) result.FailNum++ fmt.Println("createBillBatch: writeBill fail:", err.Error()) } else { result.SuccNum++ } } billBytes, err := json.Marshal(&result) if err != nil { fmt.Println("createBillBatch: Marshal fail:", err.Error()) return shim.Error("createBillBatch(): json.Marshal fail:" + err.Error()) } return shim.Success(billBytes) } // Change the Bill status func (t *SimpleChaincode) changeBillStatus(stub shim.ChaincodeStubInterface, args []string) pb.Response { if len(args) != 2 { fmt.Println("changeBillStatus: args numbers is :", len(args)) return shim.Error("changeBillStatus(): Incorrect number of arguments. Expecting 2") } /* var bill Bill status, err := strconv.Atoi(args[1]) if err != nil { return shim.Error("changeBillStatus(): status want Integer number") } bill, _, err = getBillById(stub, args[0]) if err != nil { return shim.Error("changeBillStatus(): Fail to get Bill" + err.Error()) } bill.Status = status err = writeBill(stub, bill) if err != nil { shim.Error("changeBillStatus():fail to write Bill" + err.Error()) } transaction := Transaction{BillId: args[0], Operation: "changeStatus", BillStatus: status, Time: time.Now().Unix(), ID: transactionNo} err = writeTransaction(stub, transaction) if err != nil { return shim.Error("changeBillStatus(): Fail to write the transaction" + err.Error()) } transactionNo += 1 */ return shim.Success(nil) } // Query Bill info func (t *SimpleChaincode) queryBill(stub shim.ChaincodeStubInterface, args []string) pb.Response { if len(args) != 1 { fmt.Println("queryBill: args numbers is :", len(args)) return shim.Error("queryBill(): Incorrect number of arguments. Expecting 1") } _, billBytes, err := getBillById(stub, args[0]) if err != nil { fmt.Println("getBillById fail:", err.Error()) return shim.Error("queryBill(): Fail to get Bill" + err.Error()) } return shim.Success(billBytes) } // Query Transaction info func (t *SimpleChaincode) queryTransaction(stub shim.ChaincodeStubInterface, args []string) pb.Response { if len(args) != 1 { fmt.Println("queryTransaction args numbers is:", len(args)) return shim.Error("queryTransaction(): Incorrect number of arguments. Expecting 1") } _, transBytes, err := getTransactionById(stub, args[0]) if err != nil { fmt.Println("getTransactionById fail:", err.Error()) return shim.Error("queryBill(): Fail to get Bill" + err.Error()) } return shim.Success(transBytes) } // Write Bill info into the fabric func writeBill(stub shim.ChaincodeStubInterface, bill Bill) error { billBytes, err := json.Marshal(&bill) if err != nil { fmt.Println("writeBill: Marshal fail:", err.Error()) return errors.New("writeBill():" + err.Error()) } err = stub.PutState("Bill:"+bill.DraftNumber, billBytes) if err != nil { fmt.Println("writeBill: PutState fail:", err.Error()) return errors.New("writeBill(): PutState Error" + err.Error()) } return nil } //Write the transaction info into the Fabric func writeTransaction(stub shim.ChaincodeStubInterface, transaction Transaction) error { var tsId string tsBytes, err := json.Marshal(&transaction) if err != nil { fmt.Println("writeTransaction: Marshal fail:", err.Error()) return errors.New("writeTransaction():" + err.Error()) } tsId = strconv.Itoa(transaction.ID) if err != nil { fmt.Println("writeTransaction: Itoa fail:", err.Error()) return errors.New("writeTransaction(): want Integer number") } err = stub.PutState("Transaction:"+tsId, tsBytes) if err != nil { fmt.Println("writeTransaction: PutState fail:", err.Error()) return errors.New("writeTransaction(): PutState Error" + err.Error()) } return nil } func getBillById(stub shim.ChaincodeStubInterface, id string) (Bill, []byte, error) { var bill Bill billBytes, err := stub.GetState("Bill:" + id) if err != nil { fmt.Println("getBillById: GetState fail:", err.Error()) fmt.Println("Error retrieving cpBytes") } err = json.Unmarshal(billBytes, &bill) if err != nil { fmt.Println("getBillById: Unmarshal fail:", err.Error()) fmt.Println("Error unmarshalling Bill") } return bill, billBytes, nil } func getTransactionById(stub shim.ChaincodeStubInterface, id string) (Transaction, []byte, error) { var transaction Transaction transBytes, err := stub.GetState("transaction:" + id) if err != nil { fmt.Println("Error retrieving transBytes") } err = json.Unmarshal(transBytes, &transaction) if err != nil { fmt.Println("Error unmarshalling transaction") } return transaction, transBytes, nil } func main() { err := shim.Start(new(SimpleChaincode)) if err != nil { fmt.Printf("Error starting Simple chaincode: %s", err) } }