1. 程式人生 > >Fabric鏈碼實戰(一)貸款還款

Fabric鏈碼實戰(一)貸款還款


title: Fabric鏈碼實戰(一)貸款還款
tags: Hyperledger, fabric ,區塊鏈,chaincode


功能簡述

假設需要用鏈碼開發簡單的貸款還款,要實現以下簡單的幾個業務需求:
1.通過賬戶身份證號,銀行名字進行貸款
2.過賬戶身份證號,銀行名字進行還款

功能實現

fabric-samples/chaincode下新建一個pay目錄用來存放程式碼。

1.建立結構體

建立銀行、賬戶、交易歷史和智慧合約結構體

//銀行、賬戶、定義交易歷史
//定義銀行
type Bank struct {
	//名字
	BankName string
`json:"BankName"` //金額 Amount int `json:"Amount"` //1:貸款 2:還款 Flag int `json:"Flag"` //起始時間 StartTime string `json:"StartTime"` //結束時間 EndTime string `json:"EndTime"` } //定義賬戶 type Account struct { //身份證號 CardNo string `json:"CardNo"` //使用者名稱 Aname string `json:"Aname"` //性別 Gender string `json:"Gender"`
//電話 Mobile string `json:"Mobile"` //銀行 Bank Bank `json:"Bank"` //交易歷史 Histroys []HistoryItem } //定義交易歷史 type HistoryItem struct { //交易id TxID string //賬戶 Account Account } type TraceChaincode struct { }

2.實現init函式和main函式


//初始化方法
func (t *TraceChaincode) Init(stub shim.ChaincodeStubInterface)
peer.Response { //初始化測試資料 initTest(stub) //測試方法 return shim.Success(nil) } //鏈碼入口invoke //loan:貸款 //repayment:還款 //initTest:測試初始化 func (t *TraceChaincode) Invoke(stub shim.ChaincodeStubInterface) peer.Response { //得到方法名和引數 fun, args := stub.GetFunctionAndParameters() //進行判斷 if fun == "loan" { //貸款 return loan(stub, args) } else if fun == "repayment" { //還款 return repayment(stub, args) } else if fun == "initTest" { return initTest(stub) } else { return shim.Error("方法名錯誤") } } func main() { err := shim.Start(new(TraceChaincode)) if err != nil { fmt.Println("啟動鏈碼時發生錯誤") } }

3.貸款和還款功能實現

//定義貸款和還款
const (
	Bank_Flag_Loan      = 1
	Bank_Flag_Repayment = 2
)

//貸款
//-c Args:[loan,賬戶身份證號,銀行名字,金額]
func loan(stub shim.ChaincodeStubInterface, args []string) peer.Response {
	//判斷引數
	if len(args) != 3 {
		return shim.Error("引數個數錯誤")
	}
	//判斷型別
	v, err := strconv.Atoi(args[2])
	if err != nil {
		return shim.Error("型別錯誤")
	}

	//組裝資料
	bank := Bank{
		BankName:  args[1],
		Amount:    v,
		Flag:      Bank_Flag_Loan,
		StartTime: "2011-01-10",
		EndTime:   "2021-01-09",
	}
	account := Account{
		CardNo: args[0],
		Aname:  "jack",
		Gender: "男",
		Mobile: "159999999",
		Bank:   bank,
	}

	//儲存狀態
	b := putAccount(stub, account)
	//判斷
	if ! b {
		return shim.Error("儲存貸款資料失敗")
	}
	return shim.Success([]byte("儲存貸款資料成功"))
}

//序列化並儲存
//引數將要儲存的賬戶傳過來,返回布林
func putAccount(stub shim.ChaincodeStubInterface, account Account) bool {
	//序列化
	accBytes, err := json.Marshal(account)
	if err != nil {
		return false
	}
	//儲存資料
	err = stub.PutState(account.CardNo, accBytes)
	if err != nil {
		return false
	}
	return true
}

//還款
//-c Args:[repayment,賬戶身份證號,銀行名字,金額]
func repayment(stub shim.ChaincodeStubInterface, args []string) peer.Response {
	if len(args) != 3 {
		return shim.Error("引數個數錯誤")
	}
	v, err := strconv.Atoi(args[2])
	if err != nil {
		return shim.Error("指定的還款金額錯誤")
	}
	//組裝資料
	bank := Bank{
		BankName:  args[1],
		Amount:    v,
		Flag:      Bank_Flag_Repayment,
		StartTime: "2011-01-10",
		EndTime:   "2021-01-09",
	}
	account := Account{
		CardNo: args[0],
		Aname:  "jack",
		Gender: "男",
		Mobile: "159999999",
		Bank:   bank,
	}
	b := putAccount(stub, account)
	if !b {
		return shim.Error("存款失敗")
	}
	return shim.Success([]byte("存款成功"))
}

4.實現測試方法

//測試方法
func initTest(stub shim.ChaincodeStubInterface) peer.Response {
	bank := Bank{
		BankName: "icbc",
		Amount:   6000,
		//貸款
		Flag:      1,
		StartTime: "2010-01-01",
		EndTime:   "2020-01-01",
	}
	bank1 := Bank{
		BankName: "abc",
		Amount:   1000,
		//還款
		Flag:      2,
		StartTime: "2010-02-01",
		EndTime:   "2020-02-01",
	}
	account := Account{
		CardNo:   "1234",
		Aname:    "jack",
		Gender:   "男",
		Mobile:   "15900000",
		Bank:     bank1,
		Histroys: nil,
	}
	account1 := Account{
		CardNo:   "123444",
		Aname:    "jack2",
		Gender:   "男",
		Mobile:   "1590000000",
		Bank:     bank,
		Histroys: nil,
	}

	//物件序列化,儲存
	accBytes, err := json.Marshal(account)
	if err != nil {
		return shim.Error("序列化賬戶失敗")
	}
	accBytes1, err := json.Marshal(account1)
	if err != nil {
		return shim.Error("序列化賬戶1失敗")
	}

	//儲存
	err = stub.PutState(account.CardNo, accBytes)
	if err != nil {
		return shim.Error("儲存賬戶失敗")
	}
	err = stub.PutState(account.CardNo, accBytes1)
	if err != nil {
		return shim.Error("儲存賬戶1失敗")
	}
	return shim.Success(nil)
}

部署和測試

把我們的程式碼放入之前建立的pay目錄下

詳細部署可以檢視我之前文章:

https://blog.csdn.net/yang731227/article/details/84551623

1. 開啟網路

開啟第一個終端
切換到chaincode-docker-devmode目錄
執行下面命令:

###刪除所有活躍的容器###
docker rm -f $(docker ps -aq)
###清理網路快取###
docker network prune
###開啟網路###
docker-compose -f docker-compose-simple.yaml up

2.安裝鏈碼

開啟第二個終端

###進入Docker容器cli###
docker exec -it chaincode bash
###進入到鏈碼對應目錄###
cd pay
###啟動節點###
CORE_PEER_ADDRESS=peer:7051 CORE_CHAINCODE_ID_NAME=mycc:0 ./pay

3.操作鏈碼

開啟第三個終端

###啟動 cli###
docker exec -it cli /bin/bash
###安裝鏈碼###
peer chaincode install -p chaincodedev/chaincode/pay -n mycc -v 0
###例項化鏈碼###
peer chaincode instantiate -n mycc -v 0 -c '{"Args":["init"]}' -C myc

4.呼叫鏈碼

###呼叫測試方法###
peer chaincode invoke -C myc -n mycc -c '{"Args":["initTest"]}'
###貸款###
peer chaincode invoke -C myc -n mycc -c '{"Args":["loan","110229","icbc","5000000"]}'
###還款###
peer chaincode invoke -C myc -n mycc -c '{"Args":["repayment","110229","icbc","500"]}'