This commit is contained in:
李子铭 2025-03-05 17:00:00 +08:00
parent f362b6b573
commit 1ee31eea6f
7 changed files with 124 additions and 28 deletions

View File

@ -47,10 +47,10 @@ wechat:
mchCertificateSerialNumber: "4D081089DEB385316CBDCB55C070287E4920AC76" mchCertificateSerialNumber: "4D081089DEB385316CBDCB55C070287E4920AC76"
cmb: cmb:
sm2Prk: "" # 私钥 非对称加解密算法SM2 公钥长度为65字节私钥长度为32字节。非对称密钥是基于国密推荐的椭圆曲线生成的国密推荐曲线sm2p256v1 sm2Prk: "8d39ff3d2559258c163f4510f082727f51531e1953ab203d5ab1ea4a6d94fd73"
sm2Puk: "" # 公钥,给到招行密钥 sm2Puk: "04d827a7dbaaa358ce45b8c7794a7f54819f5c175005a702370e47f135ef6f5f9732758b1474f218419fe9e87f90c28c3b05f08254c651db27df35fae67b77b2e4" # 公钥,给到招行密钥
cmbSm2Pik: "" # 招行私钥mock使用生产不会有该值 cmbSm2Pik: "9450c673cf801164435b9c164ac1404e87997245bc6f323fde22015875a03f6e" # 招行私钥mock使用生产不会有该值
cmbSm2Puk: "" # 招行公钥 cmbSm2Puk: "04a702106cf530dc981e44cd515b394747cfd6bb059247696b188b25281ea4278fe7c6e34a83680110eec71becd31f5db14abc671e5d8e67ce7ca3c6b3adc86674" # 招行公钥
mid: "d6fdd78b6fd13a808818286b9cad9687" mid: "d6fdd78b6fd13a808818286b9cad9687"
aid: "5efaa21263b94f669a1c90ed0279df20" aid: "5efaa21263b94f669a1c90ed0279df20"
keyAlias: "CO_PUB_KEY_SM2" keyAlias: "CO_PUB_KEY_SM2"

1
go.sum
View File

@ -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/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/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= 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/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.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=

View File

@ -422,12 +422,13 @@ type Cmb struct {
Mid string `protobuf:"bytes,1,opt,name=mid,proto3" json:"mid,omitempty"` Mid string `protobuf:"bytes,1,opt,name=mid,proto3" json:"mid,omitempty"`
Aid string `protobuf:"bytes,2,opt,name=aid,proto3" json:"aid,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"` Sm2Prk string `protobuf:"bytes,3,opt,name=sm2Prk,proto3" json:"sm2Prk,omitempty"`
Sm2Puk string `protobuf:"bytes,5,opt,name=sm2Puk,proto3" json:"sm2Puk,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"` CmbSm2Puk string `protobuf:"bytes,6,opt,name=cmbSm2Puk,proto3" json:"cmbSm2Puk,omitempty"`
KeyAlias string `protobuf:"bytes,7,opt,name=keyAlias,proto3" json:"keyAlias,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"` 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() { func (x *Cmb) Reset() {
@ -490,6 +491,13 @@ func (x *Cmb) GetSm2Puk() string {
return "" return ""
} }
func (x *Cmb) GetCmbSm2Pik() string {
if x != nil {
return x.CmbSm2Pik
}
return ""
}
func (x *Cmb) GetCmbSm2Puk() string { func (x *Cmb) GetCmbSm2Puk() string {
if x != nil { if x != nil {
return x.CmbSm2Puk 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, 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, 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, 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, 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, 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, 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, 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, 0x05, 0x20, 0x01, 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, 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, 0x62, 0x53, 0x6d, 0x32, 0x50, 0x69, 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63,
0x6d, 0x62, 0x53, 0x6d, 0x32, 0x50, 0x75, 0x6b, 0x12, 0x1a, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x41, 0x6d, 0x62, 0x53, 0x6d, 0x32, 0x50, 0x69, 0x6b, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6d, 0x62, 0x53,
0x6c, 0x69, 0x61, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6b, 0x65, 0x79, 0x41, 0x6d, 0x32, 0x50, 0x75, 0x6b, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x6d, 0x62,
0x6c, 0x69, 0x61, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x6d, 0x62, 0x4b, 0x65, 0x79, 0x41, 0x6c, 0x53, 0x6d, 0x32, 0x50, 0x75, 0x6b, 0x12, 0x1a, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x41, 0x6c, 0x69,
0x69, 0x61, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6d, 0x62, 0x4b, 0x65, 0x61, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6b, 0x65, 0x79, 0x41, 0x6c, 0x69,
0x79, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x61, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x6d, 0x62, 0x4b, 0x65, 0x79, 0x41, 0x6c, 0x69, 0x61,
0x55, 0x72, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6d, 0x62, 0x4b, 0x65, 0x79, 0x41,
0x79, 0x55, 0x72, 0x6c, 0x22, 0x3a, 0x0a, 0x04, 0x4c, 0x6f, 0x67, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x55, 0x72,
0x62, 0x75, 0x73, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6c, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x55,
0x62, 0x75, 0x73, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x63, 0x63, 0x65, 0x72, 0x6c, 0x22, 0x3a, 0x0a, 0x04, 0x4c, 0x6f, 0x67, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x62, 0x75,
0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x73, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x62, 0x75,
0x42, 0x17, 0x5a, 0x15, 0x76, 0x6f, 0x75, 0x63, 0x68, 0x65, 0x72, 0x2f, 0x63, 0x70, 0x6e, 0x2f, 0x73, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73,
0x63, 0x6f, 0x6e, 0x66, 0x3b, 0x63, 0x6f, 0x6e, 0x66, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x42, 0x17,
0x33, 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 ( var (

View File

@ -73,12 +73,13 @@ message Wechat {
message Cmb { message Cmb {
string mid = 1; string mid = 1;
string aid = 2; string aid = 2;
string sm2Prk = 4; string sm2Prk = 3;
string sm2Puk = 5; string sm2Puk = 4;
string cmbSm2Pik = 5;
string cmbSm2Puk = 6; string cmbSm2Puk = 6;
string keyAlias = 7; string keyAlias = 7;
string cmbKeyAlias = 8; string cmbKeyAlias = 8;
string notifyUrl = 3; string notifyUrl = 9;
} }
message Logs { message Logs {

View File

@ -96,6 +96,7 @@ func Decrypt(privateKey, input string) (string, error) {
if len(tmpDataArr) != 2 { if len(tmpDataArr) != 2 {
return "", fmt.Errorf("数据格式错误!") return "", fmt.Errorf("数据格式错误!")
} }
plainKey := []byte(kvArr[0]) plainKey := []byte(kvArr[0])
plainIv := []byte(kvArr[1]) plainIv := []byte(kvArr[1])

View File

@ -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
}

View File

@ -1,10 +1,13 @@
package service package service
import ( import (
"fmt"
"github.com/go-kratos/kratos/v2/transport/http" "github.com/go-kratos/kratos/v2/transport/http"
"strings"
"time" "time"
v1 "voucher/api/v1" v1 "voucher/api/v1"
"voucher/internal/pkg/cmb" "voucher/internal/pkg/cmb"
"voucher/internal/pkg/helper"
) )
func (s *VoucherService) CmbOrderMock(ctx http.Context) error { func (s *VoucherService) CmbOrderMock(ctx http.Context) error {
@ -36,6 +39,27 @@ func (s *VoucherService) CmbOrderMock(ctx http.Context) error {
Sign: "", 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) return ctx.JSON(200, reply)
} }