混子日记——校园征信项目3

本文介绍了一个基于Fabric的校园征信系统,详细阐述了链代码的设计与实现过程,包括数据结构设计和链代码的具体实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

基于fabric的校园征信系统——链代码的设计与实现

链代码的设计

       我们已经完成了组织节点的部署,接下来我么就要针对项目来设计相应的链代码,也就是设计想要存入区块中的数据的数据结构。在Fabric账本中数据都是以key,value的形式进行存放的,key为string类型,value可以为json格式,所以它可以很简单也可以很复杂,具体针对实际情况进行设计。
       对于我们校园征信的项目,为减轻编程工作量,我们简化数据内容,以unionchannel为例,通道中中至少要保存以下数据:
unionchannel数据信息

       数据内容参考高校学生档案管理规范:太原理工大学学生诚信档案管理办法
       如图所示学生征信档案内容包含学生基本信息,学校记录信息,第三方征信平台信息。前两项数据应由学校维护,后者应由加入联盟链的第三方的征信机构维护,加入联盟的企业可通过身份证号进行档案的查询,所以该数据放在unionchannel的账本中由三方共同维护和使用。其他各组织的不公开数据由各自channel中的账本进行读写和维护。
       在链码中对应的结构体声明如下:
       学生基本信息应包含学生姓名,性别,籍贯,出生日期,民族,身份证号,入学日期,毕业日期,学校名称,专业名称

// 学生基本信息 
type StuInfo struct {
	StuName         string `json:"stuname"`    // 学生姓名 
	StuSex          string `json:"stusex"` // 学生性别
	NativePlace     string `json:"nativeplace"`    //籍贯 
	Birthday        string `json:"birthday"`  // 出生日期
	Nation          string `json:"nation"`  // 民族
	IDNum           string `json:"idnum"` // 身份证号
	AdmissionDate   string `json:"admissiondate"` // 入学日期
	GraduationTime  string `json:"graduationtime"` // 毕业日期
	SchName         string `json:"schname"` // 学校名称
	SubName         string `json:"subname"` // 专业名称
}

       学校记录信息应包含学生绩点,在校优良记录,在校不良记录,助学贷款信息,毕业评语。

// 学校记录信息 
type SchInfo struct {
	StuGPA            string `json:"stugpa"`    // 学生绩点 
	ExcellentRecord   string `json:"excellentrecord"` // 优良记录
	BadRecord         string `json:"badrecord"`    //不良记录 
	StuLoan           string `json:"stuloan"`  // 助学贷款记录
	GraduationComment string `json:"graduationcomment"`  // 毕业评价

}

       第三方征信机构信息应包含银行卡透支情况,花呗逾期情况,滴滴欠款情况,芝麻信用积分。

// 征信机构信息 
type CreInfo struct {
	BankOverdraft       string `json:"bankoverdraft"`    // 信用卡透支记录 
	AntCreditPayOverDue string `json:"antcreditpayoverdue"` // 花呗逾期记录
	DidiTaxiArrears     string `json:"diditaxiarrears"`    //滴滴欠款记录 
	SesameCredit        string `json:"sesamecredit"`  // 芝麻信用积分

}

       将三个信息结构体封装到StuCreInfo结构体当中

// 学生征信档案 
type StuCreInfo struct {
	StuInfo     StuInfo `json:"stuinfo"`    // 学生基本信息 
	SchInfo     SchInfo `json:"schinfo"` // 学校记录信息
	CreInfo     CreInfo `json:"creinfo"`    //征信机构信息
}

       为了降低复杂程度,我们将数据类型都设置成string类型,其他组织各自channel中要存储的数据同样参考组织实际需要进行设计,与unionchannel类似。

链代码的实现

       每个链码程序都必须实现链码接口 ,接口中的方法会在响应传来的交易时被调用。Init方法会在链码接收到instantiate(实例化)或者upgrade(升级)交易时被调用,执行必要的初始化操作,包括初始化应用的状态;Invoke方法会在响应调用交易时被调用以执行交易。
       链码在开发过程中需要实现链码接口,交易的类型决定了哪个接口函数将会被调用,如instantiate和upgrade类型会调用链码的Init接口,而invoke类型的交易则调用链码的Invoke接口。链码的接口定义如下:

type Chaincode interface {
   Init(stub ChaincodeStubInterface) pb.Response
   Invoke(stub ChaincodeStubInterface) pb.Response
}

       shim.ChaincodeStubInterface接口用于访问及修改账本,并实现链码之间的互相调用,为编写链码的业务逻辑提供了大量实用的方法。
       链码的必要结构如下:

package main

//引入必要的包
import(
"github.com/hyperledger/fabric/core/chaincode/shim"
pb"github.com/hyperledger/fabric/protos/peer"
)

//声明一个结构体
type SimpleChaincode struct {}

//为结构体添加Init方法
func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response{
  //在该方法中实现链码初始化或升级时的处理逻辑
  //编写时可灵活使用stub中的API
}

//为结构体添加Invoke方法
func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response{
  //在该方法中实现链码运行中被调用或查询时的处理逻辑
  //编写时可灵活使用stub中的API
}

//主函数,需要调用shim.Start( )方法
func main() {
  err:=shim.Start(new(SimpleChaincode))
  if err != nil {
     fmt.Printf("Error starting Simple chaincode: %s", err)
    }
}

       接下来我们来实现项目的链代码:

package union
import(
	"encoding/json"
	"fmt"
	"github.com/hyperledger/fabric/core/chaincode/shim"
	"github.com/hyperledger/fabric/protos/peer"
)

//学生征信链代码
type Unionchaincode struct{
}
// 学生基本信息
type StuInfo struct {
	StuName         string `json:"stuname"`    // 学生姓名
	StuSex          string `json:"stusex"` // 学生性别
	NativePlace     string `json:"nativeplace"`    //籍贯
	Birthday        string `json:"birthday"`  // 出生日期
	Nation          string `json:"nation"`  // 民族
	IDNum           string `json:"idnum"` // 身份证号
	AdmissionDate   string `json:"admissiondate"` // 入学日期
	GraduationTime  string `json:"graduationtime"` // 毕业日期
	SchName         string `json:"schname"` // 学校名称
	SubName         string `json:"subname"` // 专业名称
}
// 学校记录信息
type SchInfo struct {
	StuGPA            string `json:"stugpa"`    // 学生绩点
	ExcellentRecord   string `json:"excellentrecord"` // 优良记录
	BadRecord         string `json:"badrecord"`    //不良记录
	StuLoan           string `json:"stuloan"`  // 助学贷款记录
	GraduationComment string `json:"graduationcomment"`  // 毕业评价

}
// 征信机构信息
type CreInfo struct {
	BankOverdraft       string `json:"bankoverdraft"`    // 信用卡透支记录
	AntCreditPayOverDue string `json:"antcreditpayoverdue"` // 花呗逾期记录
	DidiTaxiArrears     string `json:"diditaxiarrears"`    //滴滴欠款记录
	SesameCredit        string `json:"sesamecredit"`  // 芝麻信用积分

}
// 学生征信档案
type StuCreInfo struct {
	StuInfo     StuInfo `json:"stuinfo"`    // 学生基本信息
	SchInfo     SchInfo `json:"schinfo"` // 学校记录信息
	CreInfo     CreInfo `json:"creinfo"`    //征信机构信息
}
//Init函数
func (this *Unionchaincode) Init(stub shim.ChaincodeStubInterface) peer.Response{
	return shim.Success([]byte(""))
}

//Invoke函数
func (this *Unionchaincode) Invoke(stub shim.ChaincodeStubInterface) peer.Response{
	// 通过函数名匹配对应的链代码函数调用
	function, params := stub.GetFunctionAndParameters()
	if function == "addStuInfo" {
		// 添加学生基本信息
		return this.addStuInfo(stub, params)
	} else if function == "getStuInfo" {
		// 获取学生基本信息
		return this.getStuInfo(stub, params)
	} else if function == "addSchInfo" {
		// 添加学校填写信息
		return this.addSchInfo(stub, params)
	} else if function == "getSchInfo" {
		// 获取学校填写信息
		return this.getSchInfo(stub, params)
	} else if function == "addCreInfo" {
		// 添加征信机构信息
		return this.addCreInfo(stub, params)
	} else if function == "getCreInfo" {
		// 获取征信机构信息
		return this.getCreInfo(stub, params)
	}
	// 没有任何函数被匹配到,返回错误消息
	fmt.Println("==== fn = ", function)
	return shim.Error("Received unknow function invocation")
}

//main函数
func main() {
	err:=shim.Start(new(Unionchaincode))
	if err != nil {
		fmt.Printf("Error starting Union chaincode: %s", err)
	}
}
//StuInfo中的IDNum作为key
func (this *Unionchaincode) addStuInfo(stub shim.ChaincodeStubInterface, params []string) peer.Response{
	//定义一个学生档案结构体
	var stucreinfo StuCreInfo
	//判断参数个数是否正确
	if len(params) !=10 {
		return shim.Error("Incorrect number oof arguments.")
	}
	//判断身份证号是否为空
	if params[5] == "" {
		return shim.Error("IdNum can't be empty.")
	}
	//将传入的参数分别赋值给key和及结构体
	key := params[5]
	stucreinfo.StuInfo.StuName = params[0]
	stucreinfo.StuInfo.StuSex = params[1]
	stucreinfo.StuInfo.NativePlace = params[2]
	stucreinfo.StuInfo.Birthday = params[3]
	stucreinfo.StuInfo.Nation = params[4]
	stucreinfo.StuInfo.IDNum = params[5]
	stucreinfo.StuInfo.AdmissionDate = params[6]
	stucreinfo.StuInfo.GraduationTime = params[7]
	stucreinfo.StuInfo.SchName = params[8]
	stucreinfo.StuInfo.SubName = params[9]
	//将结构体转换为json格式
	stucreinfobytes,  err := json.Marshal(stucreinfo)
	if err != nil {
		shim.Error(err.Error())
	}
	//将key,value上传到链上
	err = stub.PutState(key, stucreinfobytes)
	if err != nil {
		shim.Error(err.Error())
	}
	return shim.Success([]byte("addStuInfo: OK"))
}
func (this *Unionchaincode) getStuInfo(stub shim.ChaincodeStubInterface, params []string) peer.Response {
	//判断参数个数是否正确
	if len(params) != 1 {
		return shim.Error("Incorrect number of arguments.")
	}
	//将参数赋值给key
	key := params[0]
	//获取历史信息迭代器
	resultIterator, err := stub.GetHistoryForKey(key)
	if err != nil {
		shim.Error(err.Error())
	}
	var stuInfo StuInfo
	//释放迭代器
	defer resultIterator.Close()
	//遍历结果集
	if resultIterator.HasNext() {
		var stuCreInfo StuCreInfo
		response, err := resultIterator.Next()
		if err != nil {
			return shim.Error(err.Error())
		}
		err = json.Unmarshal(response.Value, &stuCreInfo)
		if err != nil {
			shim.Error(err.Error())
		}
		if stuCreInfo.StuInfo.IDNum != "" {
			stuInfo = stuCreInfo.StuInfo
		}
	}
	stuInfobytes, err := json.Marshal(stuInfo)
	if err != nil {
		return shim.Error(err.Error())
	}
	//返回StuInfo的json格式数据
	return shim.Success(stuInfobytes)
}

       以上代码是学生基本信息的添加与查询,其他信息的功能实现与其类似,这里不再赘述。链代码的设计和已经完成,那么Fabric端的相关工作已经完成,在后续我们将进行后端的业务逻辑的代码编写以及fabric-sdk-go的应用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值