作者 yangfu

1. 对接数据 2.本地存储链数据

  1 +package command
  2 +
  3 +import (
  4 + "fmt"
  5 + "reflect"
  6 + "strings"
  7 +
  8 + "github.com/beego/beego/v2/core/validation"
  9 +)
  10 +
  11 +type UpChainCommand struct {
  12 + // 数据来源 例如:app.model
  13 + Source string `cname:"数据来源 例如:app.model" json:"source" valid:"Required"`
  14 + // 来源数据唯一ID
  15 + PrimaryId string `cname:"来源数据唯一ID" json:"primaryId" valid:"Required"`
  16 + // 溯源ID 标记同一个系列的数据;例如订单相关事件
  17 + IssueId string `cname:"溯源ID 标记同一个系列的数据;例如订单相关事件" json:"issueId"`
  18 + // 数据体
  19 + Data string `cname:"数据体" json:"data" valid:"Required"`
  20 +}
  21 +
  22 +func (upChainCommand *UpChainCommand) Valid(validation *validation.Validation) {
  23 + //validation.SetError("CustomValid", "未实现的自定义认证")
  24 +}
  25 +
  26 +func (upChainCommand *UpChainCommand) ValidateCommand() error {
  27 + valid := validation.Validation{}
  28 + b, err := valid.Valid(upChainCommand)
  29 + if err != nil {
  30 + return err
  31 + }
  32 + if !b {
  33 + elem := reflect.TypeOf(upChainCommand).Elem()
  34 + for _, validErr := range valid.Errors {
  35 + field, isExist := elem.FieldByName(validErr.Field)
  36 + if isExist {
  37 + return fmt.Errorf(strings.Replace(validErr.Message, validErr.Field, field.Tag.Get("cname"), -1))
  38 + } else {
  39 + return fmt.Errorf(validErr.Message)
  40 + }
  41 + }
  42 + }
  43 + return nil
  44 +}
  1 +package service
  2 +
  3 +import (
  4 + "fmt"
  5 + "github.com/linmadan/egglib-go/core/application"
  6 + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/application/blockChain/command"
  7 + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/application/factory"
  8 + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/domain"
  9 + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/infrastructure/blockchain"
  10 + "time"
  11 +)
  12 +
  13 +// 区块链服务
  14 +type BlockChainService struct {
  15 +}
  16 +
  17 +// 数据上链
  18 +func (blockChainService *BlockChainService) UpChain(upChainCommand *command.UpChainCommand) (interface{}, error) {
  19 + if err := upChainCommand.ValidateCommand(); err != nil {
  20 + return nil, application.ThrowError(application.ARG_ERROR, err.Error())
  21 + }
  22 + transactionContext, err := factory.CreateTransactionContext(nil)
  23 + if err != nil {
  24 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  25 + }
  26 + if err := transactionContext.StartTransaction(); err != nil {
  27 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  28 + }
  29 + defer func() {
  30 + transactionContext.RollbackTransaction()
  31 + }()
  32 +
  33 + upChain := &domain.UpChain{
  34 + Source: upChainCommand.Source,
  35 + PrimaryId: upChainCommand.PrimaryId,
  36 + IssueId: upChainCommand.IssueId,
  37 + Data: upChainCommand.Data,
  38 + UpChainStatus: 2,
  39 + CreatedAt: time.Now(),
  40 + }
  41 +
  42 + // 1. 查重
  43 + upChainRepository, _, _ := factory.FastPgUpChain(transactionContext, 0)
  44 + if item, err := upChainRepository.FindOne(map[string]interface{}{"source": upChain.Source, "primaryId": upChain.PrimaryId}); err == nil && item != nil {
  45 + return nil, fmt.Errorf("duplicate message %v %v", upChain.Source, upChain.PrimaryId)
  46 + }
  47 +
  48 + // 2.上链
  49 + bc := &blockchain.BSNBlockChain{
  50 + PublicPem: []byte(""),
  51 + Host: "",
  52 + PublicKey: "",
  53 + }
  54 + options := blockchain.NewUpToChainOptions(upChain.Source, upChain.PrimaryId, upChain.Data).WithInnerPrimaryIssueId(upChain.IssueId)
  55 + upToChainResponse, err := bc.UpToChain(options)
  56 + if err != nil || upToChainResponse == nil {
  57 + upChain.UpFail()
  58 + } else {
  59 + upChain.UpSuccess(string(*upToChainResponse))
  60 + }
  61 +
  62 + // 3.保存记录
  63 + if upChain, err = upChainRepository.Save(upChain); err != nil {
  64 + return nil, err
  65 + }
  66 +
  67 + if err := transactionContext.CommitTransaction(); err != nil {
  68 + return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  69 + }
  70 + return upChain, nil
  71 +}
  72 +
  73 +func NewBlockChainService(options map[string]interface{}) *BlockChainService {
  74 + newBlockChainService := &BlockChainService{}
  75 + return newBlockChainService
  76 +}
@@ -169,6 +169,32 @@ func FastPgMenu(transactionContext application.TransactionContext, menuId int64) @@ -169,6 +169,32 @@ func FastPgMenu(transactionContext application.TransactionContext, menuId int64)
169 return rep, mod, err 169 return rep, mod, err
170 } 170 }
171 171
  172 +// FastPgUpChain 快速返回区块链
  173 +//
  174 +// transactionContext 事务
  175 +// upChain upChainId
  176 +func FastPgUpChain(transactionContext application.TransactionContext, upChainId int64) (domain.UpChainRepository, *domain.UpChain, error) {
  177 + var rep domain.UpChainRepository
  178 + var mod *domain.UpChain
  179 + var err error
  180 + if value, err := CreateUpChainRepository(map[string]interface{}{
  181 + "transactionContext": transactionContext,
  182 + }); err != nil {
  183 + return nil, nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
  184 + } else {
  185 + rep = value
  186 + }
  187 + if upChainId > 0 {
  188 + if mod, err = rep.FindOne(map[string]interface{}{"upChainId": upChainId}); err != nil {
  189 + if err == domain.ErrorNotFound {
  190 + return nil, nil, application.ThrowError(application.RES_NO_FIND_ERROR, "该组织不存在")
  191 + }
  192 + return nil, nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
  193 + }
  194 + }
  195 + return rep, mod, err
  196 +}
  197 +
172 // FastPgCustomizeMenu 快速返回领域自定义菜单 198 // FastPgCustomizeMenu 快速返回领域自定义菜单
173 // 199 //
174 // transactionContext 事务 200 // transactionContext 事务
@@ -69,3 +69,11 @@ func CreateAccountDestroyRecordRepository(options map[string]interface{}) (domai @@ -69,3 +69,11 @@ func CreateAccountDestroyRecordRepository(options map[string]interface{}) (domai
69 } 69 }
70 return repository.NewAccountDestroyRecordRepository(transactionContext) 70 return repository.NewAccountDestroyRecordRepository(transactionContext)
71 } 71 }
  72 +
  73 +func CreateUpChainRepository(options map[string]interface{}) (domain.UpChainRepository, error) {
  74 + var transactionContext *pg.TransactionContext
  75 + if value, ok := options["transactionContext"]; ok {
  76 + transactionContext = value.(*pg.TransactionContext)
  77 + }
  78 + return repository.NewUpChainRepository(transactionContext)
  79 +}
  1 +package domain
  2 +
  3 +import "time"
  4 +
  5 +// 上链数据
  6 +type UpChain struct {
  7 + // 上链数据唯一标识
  8 + UpChainId int64 `json:"upChainId,string"`
  9 + // 数据来源 例如:app.model
  10 + Source string `json:"source"`
  11 + // 来源数据唯一ID
  12 + PrimaryId string `json:"primaryId"`
  13 + // 溯源ID 标记同一个系列的数据;例如订单相关事件
  14 + IssueId string `json:"issueId"`
  15 + // 数据体
  16 + Data string `json:"data"`
  17 + // 数据块hash
  18 + Hash string `json:"hash"`
  19 + // 上链状态 1:成功 2:失败
  20 + UpChainStatus int `json:"upChainStatus"`
  21 + // 创建时间
  22 + CreatedAt time.Time `json:"createdAt"`
  23 +}
  24 +
  25 +type UpChainRepository interface {
  26 + Save(upChain *UpChain) (*UpChain, error)
  27 + Remove(upChain *UpChain) (*UpChain, error)
  28 + FindOne(queryOptions map[string]interface{}) (*UpChain, error)
  29 + Find(queryOptions map[string]interface{}) (int64, []*UpChain, error)
  30 +}
  31 +
  32 +func (upChain *UpChain) Identify() interface{} {
  33 + if upChain.UpChainId == 0 {
  34 + return nil
  35 + }
  36 + return upChain.UpChainId
  37 +}
  38 +
  39 +func (upChain *UpChain) Update(data map[string]interface{}) error {
  40 + //if source, ok := data["source"]; ok {
  41 + // upChain.Source = source.(string)
  42 + //}
  43 + //if primaryId, ok := data["primaryId"]; ok {
  44 + // upChain.PrimaryId = primaryId.(string)
  45 + //}
  46 + //if issueId, ok := data["issueId"]; ok {
  47 + // upChain.IssueId = issueId.(string)
  48 + //}
  49 + //if data, ok := data["data"]; ok {
  50 + // upChain.Data = data.(string)
  51 + //}
  52 + if hash, ok := data["hash"]; ok {
  53 + upChain.Hash = hash.(string)
  54 + }
  55 + if upChainStatus, ok := data["upChainStatus"]; ok {
  56 + upChain.UpChainStatus = upChainStatus.(int)
  57 + }
  58 + if createdAt, ok := data["createdAt"]; ok {
  59 + upChain.CreatedAt = createdAt.(time.Time)
  60 + }
  61 + return nil
  62 +}
  63 +
  64 +func (upChain *UpChain) UpSuccess(hashData string) {
  65 + if len(upChain.Hash) > 0 {
  66 + return
  67 + }
  68 + upChain.Hash = hashData
  69 + upChain.UpChainStatus = 1
  70 +}
  71 +
  72 +func (upChain *UpChain) UpFail() {
  73 + if len(upChain.Hash) > 0 {
  74 + return
  75 + }
  76 + upChain.Hash = ""
  77 + upChain.UpChainStatus = 2
  78 +}
@@ -8,7 +8,7 @@ import ( @@ -8,7 +8,7 @@ import (
8 "github.com/beego/beego/v2/client/httplib" 8 "github.com/beego/beego/v2/client/httplib"
9 "github.com/linmadan/egglib-go/utils/json" 9 "github.com/linmadan/egglib-go/utils/json"
10 "net/http" 10 "net/http"
11 - "net/url" 11 + "net/http/httputil"
12 "sort" 12 "sort"
13 "time" 13 "time"
14 ) 14 )
@@ -16,7 +16,7 @@ import ( @@ -16,7 +16,7 @@ import (
16 type ( 16 type (
17 BSNBlockChain struct { 17 BSNBlockChain struct {
18 PublicPem []byte 18 PublicPem []byte
19 - privatePem []byte 19 + PrivatePem []byte
20 PublicKey string 20 PublicKey string
21 Host string 21 Host string
22 } 22 }
@@ -50,6 +50,8 @@ type ( @@ -50,6 +50,8 @@ type (
50 InnerPrimaryKey string `json:"innerPrimaryKey,omitempty"` 50 InnerPrimaryKey string `json:"innerPrimaryKey,omitempty"`
51 // type为3时必填 51 // type为3时必填
52 Value string `json:"value,omitempty"` 52 Value string `json:"value,omitempty"`
  53 + // 当type=1或者2必填,为false只显示密文,为true溯源才会显示原文
  54 + ShowValue bool `json:"showValue"`
53 } 55 }
54 GetTokenResponse struct { 56 GetTokenResponse struct {
55 Token string `json:"token"` 57 Token string `json:"token"`
@@ -68,17 +70,22 @@ func (c *BSNBlockChain) UpToChain(options *UpToChainOptions) (*UpToChainResponse @@ -68,17 +70,22 @@ func (c *BSNBlockChain) UpToChain(options *UpToChainOptions) (*UpToChainResponse
68 if err != nil { 70 if err != nil {
69 return nil, err 71 return nil, err
70 } 72 }
  73 + data, _ := httputil.DumpRequest(req.GetRequest(), true)
  74 + fmt.Println(string(data))
71 var upToChainResponse UpToChainResponse 75 var upToChainResponse UpToChainResponse
72 _, err = c.HandlerResponse(req, &upToChainResponse) 76 _, err = c.HandlerResponse(req, &upToChainResponse)
  77 +
73 return &upToChainResponse, err 78 return &upToChainResponse, err
74 } 79 }
75 80
76 // 浏览器溯源验真申请 81 // 浏览器溯源验真申请
77 func (c *BSNBlockChain) GetToken(options *GetTokenRequest) (*GetTokenResponse, error) { 82 func (c *BSNBlockChain) GetToken(options *GetTokenRequest) (*GetTokenResponse, error) {
78 - req, err := c.MakeRequest(options, "/getToken", "getToken", http.MethodPost) 83 + req, err := c.MakeRequest(options, "/chainApi/getToken", "getToken", http.MethodPost)
79 if err != nil { 84 if err != nil {
80 return nil, err 85 return nil, err
81 } 86 }
  87 + data, _ := httputil.DumpRequest(req.GetRequest(), true)
  88 + fmt.Println(string(data))
82 var getTokenResponse = GetTokenResponse{} 89 var getTokenResponse = GetTokenResponse{}
83 _, err = c.HandlerResponse(req, &getTokenResponse) 90 _, err = c.HandlerResponse(req, &getTokenResponse)
84 return &getTokenResponse, err 91 return &getTokenResponse, err
@@ -100,7 +107,8 @@ func (c *BSNBlockChain) Signature(body map[string]interface{}, method string) (s @@ -100,7 +107,8 @@ func (c *BSNBlockChain) Signature(body map[string]interface{}, method string) (s
100 } 107 }
101 encryptString.WriteString(fmt.Sprintf("method=%v", method)) 108 encryptString.WriteString(fmt.Sprintf("method=%v", method))
102 109
103 - encryptData, err := RsaEncrypt(c.PublicPem, encryptString.Bytes()) 110 + // 此处用私钥签名
  111 + encryptData, err := RsaSign(c.PrivatePem, encryptString.Bytes())
104 if err != nil { 112 if err != nil {
105 return "", err 113 return "", err
106 } 114 }
@@ -116,8 +124,8 @@ func (c *BSNBlockChain) MakeRequest(obj interface{}, action string, signAction, @@ -116,8 +124,8 @@ func (c *BSNBlockChain) MakeRequest(obj interface{}, action string, signAction,
116 return nil, err 124 return nil, err
117 } 125 }
118 req := httplib.NewBeegoRequest(c.Host+action, httpMethod) 126 req := httplib.NewBeegoRequest(c.Host+action, httpMethod)
119 - req.Header("pubKey", url.QueryEscape(string(c.PublicKey)))  
120 - req.Header("signature", url.QueryEscape(secret)) 127 + req.Header("pubKey", c.PublicKey) //url.QueryEscape(string(c.PublicKey))
  128 + req.Header("signature", secret) //url.QueryEscape(secret)
121 req.SetTimeout(time.Second*5, time.Second*5) 129 req.SetTimeout(time.Second*5, time.Second*5)
122 if httpMethod == http.MethodPost || httpMethod == http.MethodPut { 130 if httpMethod == http.MethodPost || httpMethod == http.MethodPut {
123 req.JSONBody(obj) 131 req.JSONBody(obj)
@@ -127,6 +135,7 @@ func (c *BSNBlockChain) MakeRequest(obj interface{}, action string, signAction, @@ -127,6 +135,7 @@ func (c *BSNBlockChain) MakeRequest(obj interface{}, action string, signAction,
127 135
128 func (c *BSNBlockChain) HandlerResponse(req *httplib.BeegoHTTPRequest, value interface{}) (*Response, error) { 136 func (c *BSNBlockChain) HandlerResponse(req *httplib.BeegoHTTPRequest, value interface{}) (*Response, error) {
129 response := &Response{} 137 response := &Response{}
  138 + //req.DumpBody(true)
130 data, err := req.Bytes() 139 data, err := req.Bytes()
131 if err != nil { 140 if err != nil {
132 return nil, err 141 return nil, err
@@ -142,6 +151,9 @@ func (c *BSNBlockChain) HandlerResponse(req *httplib.BeegoHTTPRequest, value int @@ -142,6 +151,9 @@ func (c *BSNBlockChain) HandlerResponse(req *httplib.BeegoHTTPRequest, value int
142 if err != nil { 151 if err != nil {
143 return nil, err 152 return nil, err
144 } 153 }
  154 + if response.Code != 0 {
  155 + return nil, fmt.Errorf("upchain code:%v msg:%v", response.Code, response.Message)
  156 + }
145 json.Unmarshal(response.Data, value) 157 json.Unmarshal(response.Data, value)
146 return response, nil 158 return response, nil
147 } 159 }
@@ -14,6 +14,24 @@ import ( @@ -14,6 +14,24 @@ import (
14 "testing" 14 "testing"
15 ) 15 )
16 16
  17 +//var priK = []byte(`-----BEGIN RSA PRIVATE KEY-----
  18 +//MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEA2H6x0D1mg5QbXfU7
  19 +//MZKltypRj+eZktPKIApyEqRsyLqe3sRSd1Eh+VqKlQ9QFI8dae3t0USWlVmyfIDM
  20 +//0ly85QIDAQABAkAPnKNJ9wOLfYSzs9l+66pTmROkovjqI6exw88SFRVbLCgM8maa
  21 +//GOWEP/nhZDlQYBKHUqG0/KsLkeyLGkE8N7JBAiEA8lM3npA3q+Kmhy+lmQbfHFPQ
  22 +//31OSkA+RaW/LPn0lP50CIQDktlF3iDk5kxnzgT/3lvvKhHInUh+pH5F19C6MymMD
  23 +//6QIgLxDct655MahnAdDOUCeWhBD/e7DmwZZUfu8Ywb1a070CIArsUjO9Q85mIiUp
  24 +//FR8EDP59GN6b43s2UMIraVW8DMKRAiEAnnMPbDsD2HsQbgmNNEqETUxYGVyO+p7w
  25 +//OZZReuOyvCM=
  26 +//-----END RSA PRIVATE KEY-----`)
  27 +//var pubPem = `-----BEGIN PUBLIC KEY-----
  28 +//MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANh+sdA9ZoOUG131OzGSpbcqUY/nmZLT
  29 +//yiAKchKkbMi6nt7EUndRIflaipUPUBSPHWnt7dFElpVZsnyAzNJcvOUCAwEAAQ==
  30 +//-----END PUBLIC KEY-----`
  31 +//var pubKey = "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANh+sdA9ZoOUG131OzGSpbcqUY/nmZLT\nyiAKchKkbMi6nt7EUndRIflaipUPUBSPHWnt7dFElpVZsnyAzNJcvOUCAwEAAQ=="
  32 +//
  33 +//var host = "http://allied-creation-gateway-dev.fjmaimaimai.com"
  34 +
17 var priK = []byte(`-----BEGIN RSA PRIVATE KEY----- 35 var priK = []byte(`-----BEGIN RSA PRIVATE KEY-----
18 MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEA2H6x0D1mg5QbXfU7 36 MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEA2H6x0D1mg5QbXfU7
19 MZKltypRj+eZktPKIApyEqRsyLqe3sRSd1Eh+VqKlQ9QFI8dae3t0USWlVmyfIDM 37 MZKltypRj+eZktPKIApyEqRsyLqe3sRSd1Eh+VqKlQ9QFI8dae3t0USWlVmyfIDM
@@ -28,15 +46,15 @@ var pubPem = `-----BEGIN PUBLIC KEY----- @@ -28,15 +46,15 @@ var pubPem = `-----BEGIN PUBLIC KEY-----
28 MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANh+sdA9ZoOUG131OzGSpbcqUY/nmZLT 46 MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANh+sdA9ZoOUG131OzGSpbcqUY/nmZLT
29 yiAKchKkbMi6nt7EUndRIflaipUPUBSPHWnt7dFElpVZsnyAzNJcvOUCAwEAAQ== 47 yiAKchKkbMi6nt7EUndRIflaipUPUBSPHWnt7dFElpVZsnyAzNJcvOUCAwEAAQ==
30 -----END PUBLIC KEY-----` 48 -----END PUBLIC KEY-----`
31 -var pubKey = "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANh+sdA9ZoOUG131OzGSpbcqUY/nmZLT\nyiAKchKkbMi6nt7EUndRIflaipUPUBSPHWnt7dFElpVZsnyAzNJcvOUCAwEAAQ==" 49 +var pubKey = "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANh+sdA9ZoOUG131OzGSpbcqUY/nmZLTyiAKchKkbMi6nt7EUndRIflaipUPUBSPHWnt7dFElpVZsnyAzNJcvOUCAwEAAQ=="
32 50
33 -var host = "http://allied-creation-gateway-dev.fjmaimaimai.com" 51 +var host = "http://101.34.29.149:9092/test"
34 52
35 func TestSignature(t *testing.T) { 53 func TestSignature(t *testing.T) {
36 options := NewUpToChainOptions("table", "1", "149848948").WithDesc("desc") 54 options := NewUpToChainOptions("table", "1", "149848948").WithDesc("desc")
37 //options := NewUpToChainOptions("table", "", "").WithDesc("") 55 //options := NewUpToChainOptions("table", "", "").WithDesc("")
38 bsn := &BSNBlockChain{ 56 bsn := &BSNBlockChain{
39 - privatePem: priK, 57 + PrivatePem: priK,
40 PublicPem: []byte(pubPem), 58 PublicPem: []byte(pubPem),
41 } 59 }
42 bInfo := &UpToChainRequest{} 60 bInfo := &UpToChainRequest{}
@@ -105,29 +123,34 @@ func TestGenerateRSA(t *testing.T) { @@ -105,29 +123,34 @@ func TestGenerateRSA(t *testing.T) {
105 123
106 func TestBSNBlockChain_UpToChain(t *testing.T) { 124 func TestBSNBlockChain_UpToChain(t *testing.T) {
107 bc := &BSNBlockChain{ 125 bc := &BSNBlockChain{
108 - PublicPem: []byte(pubPem),  
109 - Host: host,  
110 - PublicKey: pubKey, 126 + PublicPem: []byte(pubPem),
  127 + Host: host,
  128 + PublicKey: pubKey,
  129 + PrivatePem: priK,
111 } 130 }
112 - options := NewUpToChainOptions("table", "1", "149848948").WithDesc("desc")  
113 - _, err := bc.UpToChain(options) 131 + options := NewUpToChainOptions("table", "2", "149848948").WithDesc("desc")
  132 + rsp, err := bc.UpToChain(options)
114 if err != nil { 133 if err != nil {
115 t.Fatal(err) 134 t.Fatal(err)
116 } 135 }
  136 + t.Log(string(*rsp))
117 } 137 }
118 138
119 func TestBSNBlockChain_GetToken(t *testing.T) { 139 func TestBSNBlockChain_GetToken(t *testing.T) {
120 bc := &BSNBlockChain{ 140 bc := &BSNBlockChain{
121 - PublicPem: []byte(pubPem),  
122 - Host: host,  
123 - PublicKey: pubKey, 141 + PublicPem: []byte(pubPem),
  142 + Host: host,
  143 + PublicKey: pubKey,
  144 + PrivatePem: priK,
124 } 145 }
125 options := &GetTokenRequest{ 146 options := &GetTokenRequest{
126 - Type: 1,  
127 - TsTxId: "", 147 + Type: 1,
  148 + TsTxId: "54df75d3bead65d144a1123d1f18af8bb4db65420c5c449631e9a93b81fcdb93",
  149 + ShowValue: true,
128 } 150 }
129 - _, err := bc.GetToken(options) 151 + token, err := bc.GetToken(options)
130 if err != nil { 152 if err != nil {
131 t.Fatal(err) 153 t.Fatal(err)
132 } 154 }
  155 + t.Log(token.Token)
133 } 156 }
@@ -2,17 +2,17 @@ package blockchain @@ -2,17 +2,17 @@ package blockchain
2 2
3 type UpToChainOptions struct { 3 type UpToChainOptions struct {
4 // 上链数据的数据库、数据表等的标识值 (非必填) 4 // 上链数据的数据库、数据表等的标识值 (非必填)
5 - InnerDBTable string `json:"innerDBTable"` 5 + InnerDBTable string `json:"innerDBTable,omitempty"`
6 // 上链数据的唯一标识主键值 (非必填) 6 // 上链数据的唯一标识主键值 (非必填)
7 - InnerPrimaryKey string `json:"innerPrimaryKey"` 7 + InnerPrimaryKey string `json:"innerPrimaryKey,omitempty"`
8 // 上链记录的一个标记值(IssueId), 数据溯源出所有相关事件内容,例如快递单号,过滤出该快递的所有相关事件内容并用于展示 (非必填) 8 // 上链记录的一个标记值(IssueId), 数据溯源出所有相关事件内容,例如快递单号,过滤出该快递的所有相关事件内容并用于展示 (非必填)
9 - InnerPrimaryIssueId string `json:"innerPrimaryIssueId"` 9 + InnerPrimaryIssueId string `json:"innerPrimaryIssueId,omitempty"`
10 // 作用与key1相同 (非必填) 10 // 作用与key1相同 (非必填)
11 - InnerSecondIssueId string `json:"innerSecondIssueId"` 11 + InnerSecondIssueId string `json:"innerSecondIssueId,omitempty"`
12 // 数据原文 (必填) 12 // 数据原文 (必填)
13 Value string `json:"value"` 13 Value string `json:"value"`
14 // 数据描述: 对value的描述,无论needHash为何值,本字段均会原文存储到链上 14 // 数据描述: 对value的描述,无论needHash为何值,本字段均会原文存储到链上
15 - Desc string `json:"desc"` 15 + Desc string `json:"desc,omitempty"`
16 // 是否哈希: true: 需要哈希,会将value进行hash上链,false:不需要哈希,明文上链,链上所有用户都可看到明文,默认false 16 // 是否哈希: true: 需要哈希,会将value进行hash上链,false:不需要哈希,明文上链,链上所有用户都可看到明文,默认false
17 NeedHash bool `json:"needHash"` 17 NeedHash bool `json:"needHash"`
18 } 18 }
1 package blockchain 1 package blockchain
2 2
3 import ( 3 import (
  4 + "crypto"
4 "crypto/md5" 5 "crypto/md5"
5 "crypto/rand" 6 "crypto/rand"
6 "crypto/rsa" 7 "crypto/rsa"
@@ -11,8 +12,29 @@ import ( @@ -11,8 +12,29 @@ import (
11 "fmt" 12 "fmt"
12 ) 13 )
13 14
14 -// 加密  
15 -func RsaEncrypt(publicKey []byte, origData []byte) ([]byte, error) { 15 +// rsa签名
  16 +func RsaSign(publicKey []byte, origData []byte) ([]byte, error) {
  17 + block, _ := pem.Decode(publicKey)
  18 + if block == nil {
  19 + return nil, errors.New("public key error")
  20 + }
  21 + pubInterface, err := x509.ParsePKCS8PrivateKey(block.Bytes)
  22 + if err != nil {
  23 + return nil, err
  24 + }
  25 +
  26 + fmt.Println(string(origData))
  27 + // md5
  28 + hash := md5.New()
  29 + hash.Write([]byte(origData))
  30 + pub := pubInterface.(*rsa.PrivateKey)
  31 + fmt.Println(hash.Sum(nil))
  32 + return rsa.SignPKCS1v15(rand.Reader, pub, crypto.MD5, hash.Sum(nil))
  33 + //pub := pubInterface.(*rsa.PublicKey)
  34 + //return rsa.EncryptPKCS1v15(rand.Reader, pub, origData)
  35 +}
  36 +
  37 +func RsaEncryptBak(publicKey []byte, origData []byte) ([]byte, error) {
16 block, _ := pem.Decode(publicKey) 38 block, _ := pem.Decode(publicKey)
17 if block == nil { 39 if block == nil {
18 return nil, errors.New("public key error") 40 return nil, errors.New("public key error")
@@ -22,6 +44,7 @@ func RsaEncrypt(publicKey []byte, origData []byte) ([]byte, error) { @@ -22,6 +44,7 @@ func RsaEncrypt(publicKey []byte, origData []byte) ([]byte, error) {
22 return nil, err 44 return nil, err
23 } 45 }
24 46
  47 + fmt.Println(string(origData))
25 // md5 48 // md5
26 hash := md5.New() 49 hash := md5.New()
27 hash.Write([]byte(origData)) 50 hash.Write([]byte(origData))
  1 +package models
  2 +
  3 +import "time"
  4 +
  5 +type UpChain struct {
  6 + tableName string `comment:"上链数据" pg:"up_chain,alias:up_chain"`
  7 + // 上链数据唯一标识
  8 + UpChainId int64 `comment:"上链数据唯一标识" pg:"pk:up_chain_id"`
  9 + // 数据来源 例如:app.model
  10 + Source string `comment:"数据来源 例如:app.model"`
  11 + // 来源数据唯一ID
  12 + PrimaryId string `comment:"来源数据唯一ID"`
  13 + // 溯源ID 标记同一个系列的数据;例如订单相关事件
  14 + IssueId string `comment:"溯源ID 标记同一个系列的数据;例如订单相关事件"`
  15 + // 数据体
  16 + Data string `comment:"数据体"`
  17 + // 数据块hash
  18 + Hash string `comment:"数据块hash"`
  19 + // 上链状态 1:成功 2:失败
  20 + UpChainStatus int `comment:"上链状态 1:成功 2:失败"`
  21 + // 创建时间
  22 + CreatedAt time.Time `comment:"创建时间"`
  23 +}
  1 +package transform
  2 +
  3 +import (
  4 + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/domain"
  5 + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/infrastructure/pg/models"
  6 +)
  7 +
  8 +func TransformToUpChainDomainModelFromPgModels(upChainModel *models.UpChain) (*domain.UpChain, error) {
  9 + return &domain.UpChain{
  10 + UpChainId: upChainModel.UpChainId,
  11 + Source: upChainModel.Source,
  12 + PrimaryId: upChainModel.PrimaryId,
  13 + IssueId: upChainModel.IssueId,
  14 + Data: upChainModel.Data,
  15 + Hash: upChainModel.Hash,
  16 + UpChainStatus: upChainModel.UpChainStatus,
  17 + CreatedAt: upChainModel.CreatedAt,
  18 + }, nil
  19 +}
  1 +package repository
  2 +
  3 +import (
  4 + "fmt"
  5 + "github.com/go-pg/pg/v10"
  6 +
  7 + "github.com/linmadan/egglib-go/persistent/pg/sqlbuilder"
  8 + pgTransaction "github.com/linmadan/egglib-go/transaction/pg"
  9 + "github.com/linmadan/egglib-go/utils/snowflake"
  10 + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/domain"
  11 + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/infrastructure/pg/models"
  12 + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/infrastructure/pg/transform"
  13 +)
  14 +
  15 +type UpChainRepository struct {
  16 + transactionContext *pgTransaction.TransactionContext
  17 +}
  18 +
  19 +func (repository *UpChainRepository) nextIdentify() (int64, error) {
  20 + IdWorker, err := snowflake.NewIdWorker(1)
  21 + if err != nil {
  22 + return 0, err
  23 + }
  24 + id, err := IdWorker.NextId()
  25 + return id, err
  26 +}
  27 +func (repository *UpChainRepository) Save(upChain *domain.UpChain) (*domain.UpChain, error) {
  28 + sqlBuildFields := []string{
  29 + "up_chain_id",
  30 + "source",
  31 + "primary_id",
  32 + "issue_id",
  33 + "data",
  34 + "hash",
  35 + "up_chain_status",
  36 + "created_at",
  37 + }
  38 + insertFieldsSnippet := sqlbuilder.SqlFieldsSnippet(sqlBuildFields)
  39 + insertPlaceHoldersSnippet := sqlbuilder.SqlPlaceHoldersSnippet(sqlBuildFields)
  40 + returningFieldsSnippet := sqlbuilder.SqlFieldsSnippet(sqlBuildFields)
  41 + updateFields := sqlbuilder.RemoveSqlFields(sqlBuildFields, "upChain_id")
  42 + updateFieldsSnippet := sqlbuilder.SqlUpdateFieldsSnippet(updateFields)
  43 + tx := repository.transactionContext.PgTx
  44 + if upChain.Identify() == nil {
  45 + upChainId, err := repository.nextIdentify()
  46 + if err != nil {
  47 + return upChain, err
  48 + } else {
  49 + upChain.UpChainId = upChainId
  50 + }
  51 + if _, err := tx.QueryOne(
  52 + pg.Scan(
  53 + &upChain.UpChainId,
  54 + &upChain.Source,
  55 + &upChain.PrimaryId,
  56 + &upChain.IssueId,
  57 + &upChain.Data,
  58 + &upChain.Hash,
  59 + &upChain.UpChainStatus,
  60 + &upChain.CreatedAt,
  61 + ),
  62 + fmt.Sprintf("INSERT INTO up_chains (%s) VALUES (%s) RETURNING %s", insertFieldsSnippet, insertPlaceHoldersSnippet, returningFieldsSnippet),
  63 + upChain.UpChainId,
  64 + upChain.Source,
  65 + upChain.PrimaryId,
  66 + upChain.IssueId,
  67 + upChain.Data,
  68 + upChain.Hash,
  69 + upChain.UpChainStatus,
  70 + upChain.CreatedAt,
  71 + ); err != nil {
  72 + return upChain, err
  73 + }
  74 + } else {
  75 + if _, err := tx.QueryOne(
  76 + pg.Scan(
  77 + &upChain.UpChainId,
  78 + &upChain.Source,
  79 + &upChain.PrimaryId,
  80 + &upChain.IssueId,
  81 + &upChain.Data,
  82 + &upChain.Hash,
  83 + &upChain.UpChainStatus,
  84 + &upChain.CreatedAt,
  85 + ),
  86 + fmt.Sprintf("UPDATE up_chains SET %s WHERE up_chain_id=? RETURNING %s", updateFieldsSnippet, returningFieldsSnippet),
  87 + upChain.Source,
  88 + upChain.PrimaryId,
  89 + upChain.IssueId,
  90 + upChain.Data,
  91 + upChain.Hash,
  92 + upChain.UpChainStatus,
  93 + upChain.CreatedAt,
  94 + upChain.Identify(),
  95 + ); err != nil {
  96 + return upChain, err
  97 + }
  98 + }
  99 + return upChain, nil
  100 +}
  101 +func (repository *UpChainRepository) Remove(upChain *domain.UpChain) (*domain.UpChain, error) {
  102 + tx := repository.transactionContext.PgTx
  103 + upChainModel := new(models.UpChain)
  104 + upChainModel.UpChainId = upChain.Identify().(int64)
  105 + if _, err := tx.Model(upChainModel).WherePK().Delete(); err != nil {
  106 + return upChain, err
  107 + }
  108 + return upChain, nil
  109 +}
  110 +func (repository *UpChainRepository) FindOne(queryOptions map[string]interface{}) (*domain.UpChain, error) {
  111 + tx := repository.transactionContext.PgTx
  112 + upChainModel := new(models.UpChain)
  113 + query := sqlbuilder.BuildQuery(tx.Model(upChainModel), queryOptions)
  114 + query.SetWhereByQueryOption("up_chain.up_chain_id = ?", "upChainId")
  115 + query.SetWhereByQueryOption("up_chain.source = ?", "source")
  116 + query.SetWhereByQueryOption("up_chain.primary_id = ?", "primaryId")
  117 + if err := query.First(); err != nil {
  118 + if err.Error() == "pg: no rows in result set" {
  119 + return nil, fmt.Errorf("没有此资源")
  120 + } else {
  121 + return nil, err
  122 + }
  123 + }
  124 + if upChainModel.UpChainId == 0 {
  125 + return nil, nil
  126 + } else {
  127 + return transform.TransformToUpChainDomainModelFromPgModels(upChainModel)
  128 + }
  129 +}
  130 +func (repository *UpChainRepository) Find(queryOptions map[string]interface{}) (int64, []*domain.UpChain, error) {
  131 + tx := repository.transactionContext.PgTx
  132 + var upChainModels []*models.UpChain
  133 + upChains := make([]*domain.UpChain, 0)
  134 + query := sqlbuilder.BuildQuery(tx.Model(&upChainModels), queryOptions)
  135 + query.SetOffsetAndLimit(20)
  136 + query.SetOrderDirect("up_chain_id", "DESC")
  137 + if count, err := query.SelectAndCount(); err != nil {
  138 + return 0, upChains, err
  139 + } else {
  140 + for _, upChainModel := range upChainModels {
  141 + if upChain, err := transform.TransformToUpChainDomainModelFromPgModels(upChainModel); err != nil {
  142 + return 0, upChains, err
  143 + } else {
  144 + upChains = append(upChains, upChain)
  145 + }
  146 + }
  147 + return int64(count), upChains, nil
  148 + }
  149 +}
  150 +func NewUpChainRepository(transactionContext *pgTransaction.TransactionContext) (*UpChainRepository, error) {
  151 + if transactionContext == nil {
  152 + return nil, fmt.Errorf("transactionContext参数不能为nil")
  153 + } else {
  154 + return &UpChainRepository{
  155 + transactionContext: transactionContext,
  156 + }, nil
  157 + }
  158 +}
@@ -2,10 +2,20 @@ package goqueue @@ -2,10 +2,20 @@ package goqueue
2 2
3 import ( 3 import (
4 "fmt" 4 "fmt"
  5 + "github.com/linmadan/egglib-go/utils/json"
  6 + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/application/blockChain/command"
  7 + "gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/application/blockChain/service"
5 "gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/log" 8 "gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/log"
6 ) 9 )
7 10
8 func UpToChainHandler(k, v string) error { 11 func UpToChainHandler(k, v string) error {
9 log.Logger.Debug(fmt.Sprintf("%s", v), map[string]interface{}{"handler": "UptoChain"}) 12 log.Logger.Debug(fmt.Sprintf("%s", v), map[string]interface{}{"handler": "UptoChain"})
10 - return nil 13 + blockChainService := service.NewBlockChainService(nil)
  14 + upChainCommand := &command.UpChainCommand{}
  15 + err := json.UnmarshalFromString(v, upChainCommand)
  16 + if err != nil {
  17 + return err
  18 + }
  19 + _, err = blockChainService.UpChain(upChainCommand)
  20 + return err
11 } 21 }