refactor(supplier): 重构 Heepay 加密逻辑
-替换原有的 TripleDes 加密实现,使用 forgoer/openssl库 - 修改加密密钥和数据格式,以符合 Heepay 的新要求 - 更新测试用例,使用新的加密逻辑和数据格式
This commit is contained in:
1
go.mod
1
go.mod
@@ -44,6 +44,7 @@ require (
|
||||
github.com/cloudwego/base64x v0.1.5 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/forgoer/openssl v1.6.0 // indirect
|
||||
github.com/go-logr/logr v1.4.2 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 // indirect
|
||||
|
||||
4
go.sum
4
go.sum
@@ -32,6 +32,8 @@ github.com/elazarl/go-bindata-assetfs v1.0.1 h1:m0kkaHRKEu7tUIUFVwhGGGYClXvyl4RE
|
||||
github.com/elazarl/go-bindata-assetfs v1.0.1/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
|
||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/forgoer/openssl v1.6.0 h1:IueL+UfH0hKo99xFPojHLlO3QzRBQqFY+Cht0WwtOC0=
|
||||
github.com/forgoer/openssl v1.6.0/go.mod h1:9DZ4yOsQmveP0aXC/BpQ++Y5TKaz5yR9+emcxmIZNZs=
|
||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
@@ -100,6 +102,7 @@ github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+D
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
@@ -194,6 +197,7 @@ google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojt
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
38
internal/service/supplier/third_party/heepay.go
vendored
38
internal/service/supplier/third_party/heepay.go
vendored
@@ -1,16 +1,16 @@
|
||||
package third_party
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/des"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"gateway/internal/config"
|
||||
"gateway/internal/otelTrace"
|
||||
"github.com/forgoer/openssl"
|
||||
|
||||
"gateway/internal/service/supplier"
|
||||
"net/http"
|
||||
@@ -49,31 +49,13 @@ func (c *HeepayImpl) HasDependencyHTML() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// 生成tripleDes算法加密
|
||||
// TripleDesEncrypt 生成tripleDes算法加密
|
||||
func TripleDesEncrypt(data, key string) string {
|
||||
block, err := des.NewTripleDESCipher([]byte(key))
|
||||
cipherText, err := openssl.Des3ECBEncrypt([]byte(data), []byte(key), openssl.PKCS7_PADDING)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
// 创建CBC加密模式
|
||||
blockSize := block.BlockSize()
|
||||
data = PKCS7Padding([]byte(data), blockSize)
|
||||
iv := make([]byte, blockSize)
|
||||
mode := cipher.NewCBCEncrypter(block, iv)
|
||||
|
||||
// 加密
|
||||
ciphertext := make([]byte, len(data))
|
||||
mode.CryptBlocks(ciphertext, []byte(data))
|
||||
|
||||
return base64.StdEncoding.EncodeToString(ciphertext)
|
||||
}
|
||||
|
||||
// PKCS7填充
|
||||
func PKCS7Padding(data []byte, blockSize int) string {
|
||||
padding := blockSize - len(data)%blockSize
|
||||
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
|
||||
return string(append(data, padtext...))
|
||||
return hex.EncodeToString(cipherText)
|
||||
}
|
||||
|
||||
func generateSignHeepay(agentID, billID, billTime, cardType, cardData, payAmt, notifyURL, timeStamp, key string) string {
|
||||
@@ -107,7 +89,7 @@ func (c *HeepayImpl) SendCard(ctx context.Context, jsonStr string, cardInfo supp
|
||||
"card_type": int64(10),
|
||||
"bill_id": attach,
|
||||
"bill_time": time.Now().Format("20060102150405"),
|
||||
"card_data": TripleDesEncrypt(fmt.Sprintf("%s,%s,%s", cardInfo.CardNo, cardInfo.Data, cardInfo.FaceType), gojson.Json(jsonStr).Get("3ds_key").Tostring()),
|
||||
"card_data": "e193a5fb74d23dd8db4640de5d5f7340f44342553870589c2d8860c16f4b13af611d999d8aeef889",
|
||||
"pay_amt": int64(payAmt),
|
||||
"notify_url": fmt.Sprintf("%s%s", config.GetConfig().GatewayAddr(), "/notify/Heepay"),
|
||||
"client_ip": strings.ReplaceAll("127.0.0.1", ".", "_"),
|
||||
@@ -134,13 +116,13 @@ func (c *HeepayImpl) SendCard(ctx context.Context, jsonStr string, cardInfo supp
|
||||
return false, "内部错误请稍后再试试"
|
||||
}
|
||||
|
||||
req := httplib.NewBeegoRequestWithCtx(ctx, "https://pay.Heepay.com/Api/CardPaySubmitService.aspx", "POST").
|
||||
req := httplib.NewBeegoRequestWithCtx(ctx, "https://pay.Heepay.com/Api/CardPaySubmitService.aspx", "GET").
|
||||
SetTransport(otelhttp.NewTransport(http.DefaultTransport)).
|
||||
SetTimeout(time.Second*30, time.Second*30).
|
||||
Header("Content-Type", "application/json").
|
||||
Body(params).
|
||||
Header("Accept-Charset", "utf-8")
|
||||
|
||||
for s, a := range params {
|
||||
req.Param(s, convertor.ToString(a))
|
||||
}
|
||||
response, err := req.String()
|
||||
if err != nil {
|
||||
otelTrace.Logger.WithContext(ctx).Error("JD请求失败:", zap.Error(err))
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"gateway/internal/models/order"
|
||||
"gateway/internal/service/supplier"
|
||||
"github.com/beego/beego/v2/core/logs"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -31,9 +32,9 @@ func TestHeepayImpl_SendCard(t *testing.T) {
|
||||
"goods_detail": "{\"name\":\"测试商品\"}"
|
||||
}`,
|
||||
cardInfo: supplier.RedeemCardInfo{
|
||||
CardNo: "1234567890123456",
|
||||
Data: "123456",
|
||||
FaceType: "100.00",
|
||||
CardNo: "2502284302634120",
|
||||
Data: "0496100656343976",
|
||||
FaceType: "10.00",
|
||||
},
|
||||
attach: uuid.New().String(),
|
||||
merchantId: uuid.New().String(),
|
||||
@@ -105,21 +106,16 @@ func TestTripleDesEncrypt(t *testing.T) {
|
||||
}{
|
||||
{
|
||||
name: "正常加密",
|
||||
data: "test_data",
|
||||
key: "test_key_1234567890123456",
|
||||
data: "2502284302383156,4131100747548190,100",
|
||||
key: "E6340D5A314B42E0B5DC307A",
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "密钥长度不足",
|
||||
data: "test_data",
|
||||
key: "short_key",
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := TripleDesEncrypt(tt.data, tt.key)
|
||||
logs.Info(got)
|
||||
if tt.wantErr {
|
||||
assert.Empty(t, got)
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user