From 1ee31eea6f06c613971d5026b8c15409816ed85b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E5=AD=90=E9=93=AD?= Date: Wed, 5 Mar 2025 17:00:00 +0800 Subject: [PATCH] cmb --- configs/config.yaml | 8 ++--- go.sum | 1 - internal/conf/conf.pb.go | 49 ++++++++++++++++----------- internal/conf/conf.proto | 7 ++-- internal/pkg/cmb/sm2.go | 1 + internal/pkg/helper/kvsort.go | 62 +++++++++++++++++++++++++++++++++++ internal/service/cmb_mock.go | 24 ++++++++++++++ 7 files changed, 124 insertions(+), 28 deletions(-) create mode 100644 internal/pkg/helper/kvsort.go diff --git a/configs/config.yaml b/configs/config.yaml index d7950f2..d3fb0b5 100644 --- a/configs/config.yaml +++ b/configs/config.yaml @@ -47,10 +47,10 @@ wechat: mchCertificateSerialNumber: "4D081089DEB385316CBDCB55C070287E4920AC76" cmb: - sm2Prk: "" # 私钥 非对称加解密算法SM2 公钥长度为65字节,私钥长度为32字节。非对称密钥是基于国密推荐的椭圆曲线生成的,国密推荐曲线sm2p256v1 - sm2Puk: "" # 公钥,给到招行密钥 - cmbSm2Pik: "" # 招行私钥mock使用,生产不会有该值 - cmbSm2Puk: "" # 招行公钥 + sm2Prk: "8d39ff3d2559258c163f4510f082727f51531e1953ab203d5ab1ea4a6d94fd73" + sm2Puk: "04d827a7dbaaa358ce45b8c7794a7f54819f5c175005a702370e47f135ef6f5f9732758b1474f218419fe9e87f90c28c3b05f08254c651db27df35fae67b77b2e4" # 公钥,给到招行密钥 + cmbSm2Pik: "9450c673cf801164435b9c164ac1404e87997245bc6f323fde22015875a03f6e" # 招行私钥mock使用,生产不会有该值 + cmbSm2Puk: "04a702106cf530dc981e44cd515b394747cfd6bb059247696b188b25281ea4278fe7c6e34a83680110eec71becd31f5db14abc671e5d8e67ce7ca3c6b3adc86674" # 招行公钥 mid: "d6fdd78b6fd13a808818286b9cad9687" aid: "5efaa21263b94f669a1c90ed0279df20" keyAlias: "CO_PUB_KEY_SM2" diff --git a/go.sum b/go.sum index 0f348ac..cf25808 100644 --- a/go.sum +++ b/go.sum @@ -116,7 +116,6 @@ github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/subcommands v1.2.0 h1:vWQspBTo2nEqTUFita5/KeEWlUL8kQObDFbub/EN9oE= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= diff --git a/internal/conf/conf.pb.go b/internal/conf/conf.pb.go index aa5451c..a03845f 100644 --- a/internal/conf/conf.pb.go +++ b/internal/conf/conf.pb.go @@ -422,12 +422,13 @@ type Cmb struct { Mid string `protobuf:"bytes,1,opt,name=mid,proto3" json:"mid,omitempty"` Aid string `protobuf:"bytes,2,opt,name=aid,proto3" json:"aid,omitempty"` - Sm2Prk string `protobuf:"bytes,4,opt,name=sm2Prk,proto3" json:"sm2Prk,omitempty"` - Sm2Puk string `protobuf:"bytes,5,opt,name=sm2Puk,proto3" json:"sm2Puk,omitempty"` + Sm2Prk string `protobuf:"bytes,3,opt,name=sm2Prk,proto3" json:"sm2Prk,omitempty"` + Sm2Puk string `protobuf:"bytes,4,opt,name=sm2Puk,proto3" json:"sm2Puk,omitempty"` + CmbSm2Pik string `protobuf:"bytes,5,opt,name=cmbSm2Pik,proto3" json:"cmbSm2Pik,omitempty"` CmbSm2Puk string `protobuf:"bytes,6,opt,name=cmbSm2Puk,proto3" json:"cmbSm2Puk,omitempty"` KeyAlias string `protobuf:"bytes,7,opt,name=keyAlias,proto3" json:"keyAlias,omitempty"` CmbKeyAlias string `protobuf:"bytes,8,opt,name=cmbKeyAlias,proto3" json:"cmbKeyAlias,omitempty"` - NotifyUrl string `protobuf:"bytes,3,opt,name=notifyUrl,proto3" json:"notifyUrl,omitempty"` + NotifyUrl string `protobuf:"bytes,9,opt,name=notifyUrl,proto3" json:"notifyUrl,omitempty"` } func (x *Cmb) Reset() { @@ -490,6 +491,13 @@ func (x *Cmb) GetSm2Puk() string { return "" } +func (x *Cmb) GetCmbSm2Pik() string { + if x != nil { + return x.CmbSm2Pik + } + return "" +} + func (x *Cmb) GetCmbSm2Puk() string { if x != nil { return x.CmbSm2Puk @@ -964,27 +972,28 @@ var file_conf_conf_proto_rawDesc = []byte{ 0x0a, 0x1a, 0x6d, 0x63, 0x68, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1a, 0x6d, 0x63, 0x68, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, - 0x74, 0x65, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0xd3, + 0x74, 0x65, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0xf1, 0x01, 0x0a, 0x03, 0x43, 0x6d, 0x62, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6d, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x61, 0x69, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x6d, - 0x32, 0x50, 0x72, 0x6b, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x6d, 0x32, 0x50, - 0x72, 0x6b, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x6d, 0x32, 0x50, 0x75, 0x6b, 0x18, 0x05, 0x20, 0x01, + 0x32, 0x50, 0x72, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x6d, 0x32, 0x50, + 0x72, 0x6b, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x6d, 0x32, 0x50, 0x75, 0x6b, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x6d, 0x32, 0x50, 0x75, 0x6b, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6d, - 0x62, 0x53, 0x6d, 0x32, 0x50, 0x75, 0x6b, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, - 0x6d, 0x62, 0x53, 0x6d, 0x32, 0x50, 0x75, 0x6b, 0x12, 0x1a, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x41, - 0x6c, 0x69, 0x61, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6b, 0x65, 0x79, 0x41, - 0x6c, 0x69, 0x61, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x6d, 0x62, 0x4b, 0x65, 0x79, 0x41, 0x6c, - 0x69, 0x61, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6d, 0x62, 0x4b, 0x65, - 0x79, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x79, - 0x55, 0x72, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x6f, 0x74, 0x69, 0x66, - 0x79, 0x55, 0x72, 0x6c, 0x22, 0x3a, 0x0a, 0x04, 0x4c, 0x6f, 0x67, 0x73, 0x12, 0x1a, 0x0a, 0x08, - 0x62, 0x75, 0x73, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, - 0x62, 0x75, 0x73, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x63, 0x63, 0x65, - 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, - 0x42, 0x17, 0x5a, 0x15, 0x76, 0x6f, 0x75, 0x63, 0x68, 0x65, 0x72, 0x2f, 0x63, 0x70, 0x6e, 0x2f, - 0x63, 0x6f, 0x6e, 0x66, 0x3b, 0x63, 0x6f, 0x6e, 0x66, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, + 0x62, 0x53, 0x6d, 0x32, 0x50, 0x69, 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, + 0x6d, 0x62, 0x53, 0x6d, 0x32, 0x50, 0x69, 0x6b, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6d, 0x62, 0x53, + 0x6d, 0x32, 0x50, 0x75, 0x6b, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6d, 0x62, + 0x53, 0x6d, 0x32, 0x50, 0x75, 0x6b, 0x12, 0x1a, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x41, 0x6c, 0x69, + 0x61, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6b, 0x65, 0x79, 0x41, 0x6c, 0x69, + 0x61, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x6d, 0x62, 0x4b, 0x65, 0x79, 0x41, 0x6c, 0x69, 0x61, + 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6d, 0x62, 0x4b, 0x65, 0x79, 0x41, + 0x6c, 0x69, 0x61, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x55, 0x72, + 0x6c, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x55, + 0x72, 0x6c, 0x22, 0x3a, 0x0a, 0x04, 0x4c, 0x6f, 0x67, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x62, 0x75, + 0x73, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x62, 0x75, + 0x73, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x42, 0x17, + 0x5a, 0x15, 0x76, 0x6f, 0x75, 0x63, 0x68, 0x65, 0x72, 0x2f, 0x63, 0x70, 0x6e, 0x2f, 0x63, 0x6f, + 0x6e, 0x66, 0x3b, 0x63, 0x6f, 0x6e, 0x66, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/internal/conf/conf.proto b/internal/conf/conf.proto index e849a43..f478acd 100644 --- a/internal/conf/conf.proto +++ b/internal/conf/conf.proto @@ -73,12 +73,13 @@ message Wechat { message Cmb { string mid = 1; string aid = 2; - string sm2Prk = 4; - string sm2Puk = 5; + string sm2Prk = 3; + string sm2Puk = 4; + string cmbSm2Pik = 5; string cmbSm2Puk = 6; string keyAlias = 7; string cmbKeyAlias = 8; - string notifyUrl = 3; + string notifyUrl = 9; } message Logs { diff --git a/internal/pkg/cmb/sm2.go b/internal/pkg/cmb/sm2.go index 815bc4f..2571fb7 100644 --- a/internal/pkg/cmb/sm2.go +++ b/internal/pkg/cmb/sm2.go @@ -96,6 +96,7 @@ func Decrypt(privateKey, input string) (string, error) { if len(tmpDataArr) != 2 { return "", fmt.Errorf("数据格式错误!") } + plainKey := []byte(kvArr[0]) plainIv := []byte(kvArr[1]) diff --git a/internal/pkg/helper/kvsort.go b/internal/pkg/helper/kvsort.go new file mode 100644 index 0000000..ccad7ac --- /dev/null +++ b/internal/pkg/helper/kvsort.go @@ -0,0 +1,62 @@ +package helper + +import ( + "fmt" + "reflect" + "sort" + "strings" +) + +type KeyValue struct { + Key string + Value string +} + +func LowercaseFirstLetter(s string) string { + if len(s) == 0 { + return s + } + firstLetter := strings.ToLower(s[:1]) + return firstLetter + s[1:] +} + +func SortStruct(data any) []KeyValue { + v := reflect.ValueOf(data).Elem() + t := v.Type() + var kv []KeyValue + for i := 0; i < v.NumField(); i++ { + field := v.Field(i) + key := LowercaseFirstLetter(t.Field(i).Name) + value := fmt.Sprintf("%v", field.Interface()) + kv = append(kv, KeyValue{Key: key, Value: value}) + } + sort.SliceStable(kv, func(i, j int) bool { + return kv[i].Key < kv[j].Key + }) + return kv +} + +func SortStructJsonTag(data any) []KeyValue { + // 获取 data 结构体的类型和值 + dataType := reflect.TypeOf(data).Elem() + dataValue := reflect.ValueOf(data).Elem() + + var kv []KeyValue + for i := 0; i < dataType.NumField(); i++ { + field := dataType.Field(i) + // 获取字段的值 + fieldValue := dataValue.FieldByName(field.Name).Interface() + // 获取 JSON 字段名 + jsonTagName := field.Tag.Get("json") + if jsonTagName != "" { + kv = append(kv, KeyValue{Key: jsonTagName, Value: fmt.Sprintf("%v", fieldValue)}) + } + } + + // 排序 + sort.SliceStable(kv, func(i, j int) bool { + return kv[i].Key < kv[j].Key + }) + + return kv +} diff --git a/internal/service/cmb_mock.go b/internal/service/cmb_mock.go index 643df12..a3a8257 100644 --- a/internal/service/cmb_mock.go +++ b/internal/service/cmb_mock.go @@ -1,10 +1,13 @@ package service import ( + "fmt" "github.com/go-kratos/kratos/v2/transport/http" + "strings" "time" v1 "voucher/api/v1" "voucher/internal/pkg/cmb" + "voucher/internal/pkg/helper" ) func (s *VoucherService) CmbOrderMock(ctx http.Context) error { @@ -36,6 +39,27 @@ func (s *VoucherService) CmbOrderMock(ctx http.Context) error { Sign: "", } + kvRows := helper.SortStructJsonTag(reply) + + var strToBeSigned strings.Builder + for _, kv := range kvRows { + if kv.Key == "sign" { + continue + } + if kv.Value == "" { + continue + } + strToBeSigned.WriteString(fmt.Sprintf("%s=%s&", kv.Key, kv.Value)) + } + + str := fmt.Sprintf("/voucher/cmb/v1/order?%s", strings.TrimRight(strToBeSigned.String(), "&")) + + sing, err := cmb.Sign(s.bc.Cmb.CmbSm2Pik, str) + if err != nil { + return err + } + reply.Sign = sing + return ctx.JSON(200, reply) }