Fabric链码实战(一)贷款还款

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yang731227/article/details/84584924

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"]}'

猜你喜欢

转载自blog.csdn.net/yang731227/article/details/84584924