正在显示
13 个修改的文件
包含
521 行增加
和
21 行删除
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 | +} |
pkg/domain/up_chain.go
0 → 100644
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{} |
@@ -108,12 +126,14 @@ func TestBSNBlockChain_UpToChain(t *testing.T) { | @@ -108,12 +126,14 @@ func TestBSNBlockChain_UpToChain(t *testing.T) { | ||
108 | PublicPem: []byte(pubPem), | 126 | PublicPem: []byte(pubPem), |
109 | Host: host, | 127 | Host: host, |
110 | PublicKey: pubKey, | 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) { |
@@ -121,13 +141,16 @@ func TestBSNBlockChain_GetToken(t *testing.T) { | @@ -121,13 +141,16 @@ func TestBSNBlockChain_GetToken(t *testing.T) { | ||
121 | PublicPem: []byte(pubPem), | 141 | PublicPem: []byte(pubPem), |
122 | Host: host, | 142 | Host: host, |
123 | PublicKey: pubKey, | 143 | PublicKey: pubKey, |
144 | + PrivatePem: priK, | ||
124 | } | 145 | } |
125 | options := &GetTokenRequest{ | 146 | options := &GetTokenRequest{ |
126 | Type: 1, | 147 | Type: 1, |
127 | - TsTxId: "", | 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)) |
pkg/infrastructure/pg/models/up_chain.go
0 → 100644
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 | +} |
pkg/infrastructure/pg/transform/up_chain.go
0 → 100644
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 | } |
-
请 注册 或 登录 后发表评论