package main import ( "github.com/hyperledger/fabric-chaincode-go/shim" "github.com/hyperledger/fabric-protos-go/peer" "fmt" "encoding/json" "bytes" ) type Education struct { ObjectType string `json:"docType"` Name string `json:"Name"` // 姓名 Gender string `json:"Gender"` // 性别 Nation string `json:"Nation"` // 民族 EntityID string `json:"EntityID"` // 身份证号 Place string `json:"Place"` // 籍贯 BirthDay string `json:"BirthDay"` // 出生日期 EnrollDate string `json:"EnrollDate"` // 入学日期 GraduationDate string `json:"GraduationDate"` // 毕(结)业日期 SchoolName string `json:"SchoolName"` // 学校名称 Major string `json:"Major"` // 专业 QuaType string `json:"QuaType"` // 学历类别 Length string `json:"Length"` // 学制 Mode string `json:"Mode"` // 学习形式 Level string `json:"Level"` // 层次 Graduation string `json:"Graduation"` // 毕(结)业 CertNo string `json:"CertNo"` // 证书编号 Photo string `json:"Photo"` // 照片 Historys []HistoryItem // 当前edu的历史记录 } type HistoryItem struct { TxId string Education Education } type EducationChaincode struct { } func (t *EducationChaincode) Init(stub shim.ChaincodeStubInterface) peer.Response{ fmt.Println(" ==== Init ====") return shim.Success(nil) } func (t *EducationChaincode) Invoke(stub shim.ChaincodeStubInterface) peer.Response{ // 获取用户意图 fun, args := stub.GetFunctionAndParameters() if fun == "addEdu"{ return t.addEdu(stub, args) // 添加信息 }else if fun == "queryEduByCertNoAndName" { return t.queryEduByCertNoAndName(stub, args) // 根据证书编号及姓名查询信息 }else if fun == "queryEduInfoByEntityID" { return t.queryEduInfoByEntityID(stub, args) // 根据身份证号码及姓名查询详情 }else if fun == "updateEdu" { return t.updateEdu(stub, args) // 根据证书编号更新信息 }else if fun == "delEdu"{ return t.delEdu(stub, args) // 根据证书编号删除信息 } return shim.Error("指定的函数名称错误") } const DOC_TYPE = "eduObj" // 保存edu // args: education func PutEdu(stub shim.ChaincodeStubInterface, edu Education) ([]byte, bool) { edu.ObjectType = DOC_TYPE b, err := json.Marshal(edu) if err != nil { return nil, false } // 保存edu状态 err = stub.PutState(edu.EntityID, b) if err != nil { return nil, false } return b, true } // 根据身份证号码查询信息状态 // args: entityID func GetEduInfo(stub shim.ChaincodeStubInterface, entityID string) (Education, bool) { var edu Education // 根据身份证号码查询信息状态 b, err := stub.GetState(entityID) if err != nil { return edu, false } if b == nil { return edu, false } // 对查询到的状态进行反序列化 err = json.Unmarshal(b, &edu) if err != nil { return edu, false } // 返回结果 return edu, true } // 根据指定的查询字符串实现富查询 func getEduByQueryString(stub shim.ChaincodeStubInterface, queryString string) ([]byte, error) { resultsIterator, err := stub.GetQueryResult(queryString) if err != nil { return nil, err } defer resultsIterator.Close() // buffer is a JSON array containing QueryRecords var buffer bytes.Buffer bArrayMemberAlreadyWritten := false for resultsIterator.HasNext() { queryResponse, err := resultsIterator.Next() if err != nil { return nil, err } // Add a comma before array members, suppress it for the first array member if bArrayMemberAlreadyWritten == true { buffer.WriteString(",") } // Record is a JSON object, so we write as-is buffer.WriteString(string(queryResponse.Value)) bArrayMemberAlreadyWritten = true } fmt.Printf("- getQueryResultForQueryString queryResult:\n%s\n", buffer.String()) return buffer.Bytes(), nil } // 添加信息 // args: educationObject // 身份证号为 key, Education 为 value func (t *EducationChaincode) addEdu(stub shim.ChaincodeStubInterface, args []string) peer.Response { if len(args) != 2{ return shim.Error("给定的参数个数不符合要求") } var edu Education err := json.Unmarshal([]byte(args[0]), &edu) if err != nil { return shim.Error("反序列化信息时发生错误") } // 查重: 身份证号码必须唯一 _, exist := GetEduInfo(stub, edu.EntityID) if exist { return shim.Error("要添加的身份证号码已存在") } _, bl := PutEdu(stub, edu) if !bl { return shim.Error("保存信息时发生错误") } err = stub.SetEvent(args[1], []byte{}) if err != nil { return shim.Error(err.Error()) } return shim.Success([]byte("信息添加成功")) } // 根据证书编号及姓名查询信息 // args: CertNo, name func (t *EducationChaincode) queryEduByCertNoAndName(stub shim.ChaincodeStubInterface, args []string) peer.Response { if len(args) != 2 { return shim.Error("给定的参数个数不符合要求") } CertNo := args[0] name := args[1] // 拼装CouchDB所需要的查询字符串(是标准的一个JSON串) // queryString := fmt.Sprintf("{\"selector\":{\"docType\":\"eduObj\", \"CertNo\":\"%s\"}}", CertNo) queryString := fmt.Sprintf("{\"selector\":{\"docType\":\"%s\", \"CertNo\":\"%s\", \"Name\":\"%s\"}}", DOC_TYPE, CertNo, name) // 查询数据 result, err := getEduByQueryString(stub, queryString) if err != nil { return shim.Error("根据证书编号及姓名查询信息时发生错误") } if result == nil { return shim.Error("根据指定的证书编号及姓名没有查询到相关的信息") } return shim.Success(result) } // 根据身份证号码查询详情(溯源) // args: entityID func (t *EducationChaincode) queryEduInfoByEntityID(stub shim.ChaincodeStubInterface, args []string) peer.Response { if len(args) != 1 { return shim.Error("给定的参数个数不符合要求") } // 根据身份证号码查询edu状态 b, err := stub.GetState(args[0]) if err != nil { return shim.Error("根据身份证号码查询信息失败") } if b == nil { return shim.Error("根据身份证号码没有查询到相关的信息") } // 对查询到的状态进行反序列化 var edu Education err = json.Unmarshal(b, &edu) if err != nil { return shim.Error("反序列化edu信息失败") } // 获取历史变更数据 iterator, err := stub.GetHistoryForKey(edu.EntityID) if err != nil { return shim.Error("根据指定的身份证号码查询对应的历史变更数据失败") } defer iterator.Close() // 迭代处理 var historys []HistoryItem var hisEdu Education for iterator.HasNext() { hisData, err := iterator.Next() if err != nil { return shim.Error("获取edu的历史变更数据失败") } var historyItem HistoryItem historyItem.TxId = hisData.TxId json.Unmarshal(hisData.Value, &hisEdu) if hisData.Value == nil { var empty Education historyItem.Education = empty }else { historyItem.Education = hisEdu } historys = append(historys, historyItem) } edu.Historys = historys // 返回 result, err := json.Marshal(edu) if err != nil { return shim.Error("序列化edu信息时发生错误") } return shim.Success(result) } // 根据身份证号更新信息 // args: educationObject func (t *EducationChaincode) updateEdu(stub shim.ChaincodeStubInterface, args []string) peer.Response { if len(args) != 2{ return shim.Error("给定的参数个数不符合要求") } var info Education err := json.Unmarshal([]byte(args[0]), &info) if err != nil { return shim.Error("反序列化edu信息失败") } // 根据身份证号码查询信息 result, bl := GetEduInfo(stub, info.EntityID) if !bl{ return shim.Error("根据身份证号码查询信息时发生错误") } result.Name = info.Name result.BirthDay = info.BirthDay result.Nation = info.Nation result.Gender = info.Gender result.Place = info.Place result.EntityID = info.EntityID result.Photo = info.Photo result.EnrollDate = info.EnrollDate result.GraduationDate = info.GraduationDate result.SchoolName = info.SchoolName result.Major = info.Major result.QuaType = info.QuaType result.Length = info.Length result.Mode = info.Mode result.Level = info.Level result.Graduation = info.Graduation result.CertNo = info.CertNo; _, bl = PutEdu(stub, result) if !bl { return shim.Error("保存信息信息时发生错误") } err = stub.SetEvent(args[1], []byte{}) if err != nil { return shim.Error(err.Error()) } return shim.Success([]byte("信息更新成功")) } // 根据身份证号删除信息(暂不提供) // args: entityID func (t *EducationChaincode) delEdu(stub shim.ChaincodeStubInterface, args []string) peer.Response { if len(args) != 2{ return shim.Error("给定的参数个数不符合要求") } /*var edu Education result, bl := GetEduInfo(stub, info.EntityID) err := json.Unmarshal(result, &edu) if err != nil { return shim.Error("反序列化信息时发生错误") }*/ err := stub.DelState(args[0]) if err != nil { return shim.Error("删除信息时发生错误") } err = stub.SetEvent(args[1], []byte{}) if err != nil { return shim.Error(err.Error()) } return shim.Success([]byte("信息删除成功")) } func main(){ err := shim.Start(new(EducationChaincode)) if err != nil{ fmt.Printf("启动EducationChaincode时发生错误: %s", err) } }