feat:邮储支付fix

This commit is contained in:
wolter 2026-08-10 11:31:00 +08:00
parent 7f2aceb5a7
commit 2543a0fd4d
11 changed files with 244 additions and 200 deletions

View File

@ -46,7 +46,7 @@ func PayUrl(c *gin.Context) {
res.Order = thirdpay.NewOrdersResp(pay.Order)
res.Url = pay.Url
res.ThirdMsg = pay.ThirdMsg
res.PayInfo = pay.PayInfo
res.JsInfo = pay.JsApiInfo
controllers.ApiRes(c, res, pay.PayCode)
return

View File

@ -62,10 +62,10 @@ type CloseReqs struct {
// api 接口返回数据, 统一返回结构, order数据会进行加密
type ApiResponse struct {
Order interface{} `json:"order,omitempty"`
Url string `json:"url,omitempty"`
ThirdMsg string `json:"third_msg,omitempty"`
JsInfo *WxMiniPayResponse `json:"js_info,omitempty"`
Order interface{} `json:"order,omitempty"`
Url string `json:"url,omitempty"`
JsInfo *WxMiniPayResponse `json:"js_info,omitempty"`
PayInfo string `json:"pay_info,omitempty"` // 支付参数邮储app支付参数
}
type PayChannelListRequest struct {

View File

@ -44,6 +44,7 @@ type Pay struct {
Url string // 支付链接
ThirdMsg string // 第三方错误信息
JsApiInfo *front.WxMiniPayResponse // jsapi支付参数
PayInfo string // 支付参数邮储app支付参数
}
func NewPayWithPayCheck(paycheck *PayCheck) *Pay {
@ -217,7 +218,7 @@ func (w *Pay) PayUrl() (url string) {
}
} else if w.PayParam.Channel.ChannelType == common.PAY_CHANNEL_PSBC {
// 邮储支付返回 handCodePay 参数
w.ThirdMsg = res.Result
w.PayInfo = res.Result
} else {
w.Url = res.Result
}

View File

@ -46,9 +46,8 @@ func (c *Client) BillQuery(date time.Time) (*BillQueryResponse, error) {
encryptedBytes, _ := json.Marshal(encryptedReq)
url := c.cfg.FileHost + c.cfg.MerchantId + ".htm?partnerTxSriNo=" + BusiMainId
// head 同时作为 HTTP Header 明文传输
head := requestBody["head"].(map[string]string)
body, err := c.doPost(url, head, encryptedBytes)
// head 同时作为 HTTP Header 明文传输(对齐 YouChuKoffee 的 doPost 方式)
body, err := c.doPost(url, BusiMainId, "ufile.query.commonQuery", encryptedBytes)
if err != nil {
return nil, err
}
@ -103,9 +102,8 @@ func (c *Client) BillDownload(fileId string, date time.Time) ([]byte, error) {
encryptedBytes, _ := json.Marshal(encryptedReq)
url := c.cfg.FileHost + c.cfg.MerchantId + ".htm?partnerTxSriNo=" + BusiMainId
// head 同时作为 HTTP Header 明文传输
head := requestBody["head"].(map[string]string)
body, err := c.doPost(url, head, encryptedBytes)
// head 同时作为 HTTP Header 明文传输(对齐 YouChuKoffee 的 doPost 方式)
body, err := c.doPost(url, BusiMainId, "ufile.download.commonDownload", encryptedBytes)
if err != nil {
return nil, err
}

View File

@ -8,6 +8,7 @@ import (
"encoding/base64"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"math/big"
@ -16,9 +17,9 @@ import (
"strings"
"time"
"PaymentCenter/app/third/paymentService/psbc/internal/sm2"
psbcutil "PaymentCenter/app/third/paymentService/psbc/internal/util"
"github.com/ZZMarquis/gm/sm4"
"github.com/tjfoc/gmsm/sm2"
"github.com/tjfoc/gmsm/x509"
)
// Client 支付客户端
@ -33,17 +34,23 @@ func NewClient(cfg Config) *Client {
// doPost 发送 POST 请求到邮储银行
// head 信息通过 HTTP Header 明文传输encryptedBody 作为 HTTP POST Body
// 对齐 YouChuKoffee 的 postbank.doPost 流程
func (c *Client) doPost(url string, head map[string]string, encryptedBody []byte) ([]byte, error) {
// 对齐 YouChuKoffee 的 postbank.doPost 流程youchu_api.go/config.go
func (c *Client) doPost(url string, partnerTxSriNo string, method string, encryptedBody []byte) ([]byte, error) {
req, err := http.NewRequest("POST", url, bytes.NewReader(encryptedBody))
if err != nil {
return nil, fmt.Errorf("创建请求失败: %v", err)
}
// 构建 HTTP Header对齐 YouChuKoffee 的 doPost 方式
req.Header.Set("partnerTxSriNo", partnerTxSriNo)
req.Header.Set("reqTime", time.Now().Format("20060102150405"))
req.Header.Set("method", method)
req.Header.Set("version", "1")
req.Header.Set("merchantId", c.cfg.MerchantId)
req.Header.Set("appID", c.cfg.AppID)
req.Header.Set("accessType", "API")
req.Header.Set("reserve", "")
req.Header.Set("Content-Type", "application/json;charset=UTF-8")
for k, v := range head {
req.Header.Set(k, v)
}
client := &http.Client{Timeout: 60 * time.Second}
resp, err := client.Do(req)
@ -106,6 +113,7 @@ func RandomNumber(n int) string {
// EncryptMobile 手机银行支付参数加密
// 返回: tysdPayParams(base64), tysdEncryptKey(base64)
// 使用 YouChuKoffee 加密包psbc/internal/sm2 + psbc/internal/util
func (c *Client) EncryptMobile(inputJson string, signStr string) (string, string, error) {
defer func() {
if err := recover(); err != nil {
@ -113,14 +121,14 @@ func (c *Client) EncryptMobile(inputJson string, signStr string) (string, string
}
}()
sm4Key := generateSM4Key()
sm4Key := psbcutil.GenerateSM4Key()
// SM2 加密 SM4 密钥(使用银行公钥
bankPubKey, err := x509.ReadPublicKeyFromHex(c.cfg.BankKey)
// SM2 加密 SM4 密钥(使用银行公钥,使用 YouChuKoffee 的 Sm2Encrypt
bankPubKey, err := sm2.ReadPublicKeyFromHex(c.cfg.BankKey)
if err != nil {
return "", "", fmt.Errorf("读取银行公钥失败: %v", err)
}
encryptKeyBytes, err := sm2.Encrypt(bankPubKey, sm4Key, nil, sm2.C1C3C2)
encryptKeyBytes, err := psbcutil.Sm2Encrypt(bankPubKey, sm4Key)
if err != nil {
return "", "", fmt.Errorf("sm2加密失败: %v", err)
}
@ -129,8 +137,8 @@ func (c *Client) EncryptMobile(inputJson string, signStr string) (string, string
encryptKeyBytes = encryptKeyBytes[1:]
}
// SM2 签名(与 YouChuKoffee 对齐:UserID 传 nil默认值 1234567812345678
merchantPrivKey, err := x509.ReadPrivateKeyFromHex(c.cfg.PrivateKey)
// SM2 签名(使用 YouChuKoffee 的 Sm2SignUserID 传 nil默认值 1234567812345678
merchantPrivKey, err := sm2.ReadPrivateKeyFromHex(c.cfg.PrivateKey)
if err != nil {
return "", "", fmt.Errorf("读取商户私钥失败: %v", err)
}
@ -141,8 +149,10 @@ func (c *Client) EncryptMobile(inputJson string, signStr string) (string, string
sig := encodeBase64(rsToBytes(r, s))
// 拼接参数并 SM4 ECB 加密
// 对齐 YouChuKoffee: sm43.ECBEncrypt(sm4Key, sm43.PKCS5Padding([]byte(param), 16))
// sm4ECBEncrypt 内部已处理 padding调用方不需要再 pad
param := fmt.Sprintf("%s&sign=%s", inputJson, sig)
tmp, err := sm4ECBEncrypt(sm4Key, pkcs5Padding([]byte(param), 16))
tmp, err := sm4ECBEncrypt(sm4Key, []byte(param))
if err != nil {
return "", "", fmt.Errorf("sm4加密失败: %v", err)
}
@ -151,91 +161,113 @@ func (c *Client) EncryptMobile(inputJson string, signStr string) (string, string
}
// DecryptResponse 解密银行响应
func (c *Client) DecryptResponse(respJson string, isRequest bool) (string, error) {
var reqData map[string]string
if err := json.Unmarshal([]byte(respJson), &reqData); err != nil {
return "", fmt.Errorf("解析响应JSON失败: %v响应内容: %s", err, respJson)
}
dataKey := "response"
func (c *Client) DecryptResponse(response string, isRequest bool) (Rsponse string, err error) {
var MerchantId, PrivateKey, PublicKey string
if isRequest {
dataKey = "request"
MerchantId = c.cfg.MerchantId
PrivateKey = c.cfg.PrivateKeyCallback
PublicKey = c.cfg.SopPublicKey
} else {
MerchantId = c.cfg.MerchantId
PrivateKey = c.cfg.PrivateKeyCallback
PublicKey = c.cfg.SopPublicKey
}
_, hasData := reqData[dataKey]
_, hasSignature := reqData["signature"]
_, hasEncryptKey := reqData["encryptKey"]
if !hasData || !hasSignature || !hasEncryptKey {
if code, ok := reqData["code"]; ok {
msg := reqData["msg"]
if msg == "" {
msg = reqData["message"]
}
return "", fmt.Errorf("银行返回错误,错误码: %s错误信息: %s", code, msg)
}
if respCode, ok := reqData["respCode"]; ok {
respMsg := reqData["respMsg"]
return "", fmt.Errorf("银行返回错误,错误码: %s错误信息: %s", respCode, respMsg)
}
missingFields := []string{}
if !hasData {
missingFields = append(missingFields, dataKey)
}
if !hasSignature {
missingFields = append(missingFields, "signature")
}
if !hasEncryptKey {
missingFields = append(missingFields, "encryptKey")
}
return "", fmt.Errorf("响应格式不正确,缺少字段: %v响应内容: %s", missingFields, respJson)
}
reqData["accessToken"] = ""
inData := reqData[dataKey]
inSignature := reqData["signature"]
inEncryptKey := reqData["encryptKey"]
// 验签
checked := c.verify(fmt.Sprintf("%s%s%s", inData, inEncryptKey, ""), inSignature)
if !checked {
return "", fmt.Errorf("签名验证失败")
}
// 解密 SM4 密钥
privKey, err := x509.ReadPrivateKeyFromHex(c.cfg.PrivateKey)
encrypt, err := Decrypt(MerchantId, PrivateKey, PublicKey, response, isRequest)
if err != nil {
return "", fmt.Errorf("读取私钥失败: %v", err)
return
}
var RsponseData map[string]interface{}
err = json.Unmarshal([]byte(encrypt), &RsponseData)
if err != nil {
return
} else {
if RsponseData["body"] != nil {
if body, ok := RsponseData["body"].(string); ok {
Rsponse = body
} else {
notify, _ := json.Marshal(RsponseData["body"].(map[string]interface{}))
Rsponse = string(notify)
}
}
}
return
}
func Decrypt(merchantId, privateKey, sopPublicKey, respJson string, isRequest bool) (string, error) {
var reqData map[string]string
err := json.Unmarshal([]byte(respJson), &reqData)
if err != nil {
return "", err
}
reqData["accessToken"] = ""
keys := [4]string{}
if isRequest {
keys = [4]string{"request", "signature", "encryptKey", "accessToken"}
} else {
keys = [4]string{"response", "signature", "encryptKey", "accessToken"}
}
var inEncryptKey, inAccessToken, inData, inSignature string
for i := 0; i < 4; i++ {
data, err := checkInData(reqData, keys[i])
if err != nil {
return "", err
}
switch keys[i] {
case "request", "response":
inData = data
case "signature":
inSignature = data
case "encryptKey":
inEncryptKey = data
case "accessToken":
inAccessToken = data
}
}
checked := verify(fmt.Sprintf("%s%s%s", inData, inEncryptKey, inAccessToken), inSignature, sopPublicKey, merchantId)
if !checked {
return "", errors.New("签名验证失败")
}
priKey, err := sm2.ReadPrivateKeyFromHex(privateKey)
if err != nil {
return "", errors.New("读取私钥失败")
}
hexEncryptKey, err := hex.DecodeString(inEncryptKey)
if err != nil {
return "", fmt.Errorf("解密sm4key失败: %v", err)
return "", errors.New("解密sm4key失败")
}
sm4Key, err := sm2.Decrypt(privKey, hexEncryptKey, sm2.C1C3C2)
sm4Key, err := psbcutil.Sm2Decrypt(priKey, hexEncryptKey)
if err != nil {
return "", fmt.Errorf("解密sm2key失败: %v", err)
return "", errors.New("解密sm2key失败")
}
// 解密数据
request, _ := base64.StdEncoding.DecodeString(inData)
encryptedSm4Key, err := sm4.CBCDecrypt(sm4Key, getSM4IV(), request)
decryptedStr := string(pkcs5UnPadding(encryptedSm4Key))
// 提取 body 字段(银行解密后的结构为 {head, body},业务数据在 body 中)
var decryptedMap map[string]interface{}
if jsonErr := json.Unmarshal([]byte(decryptedStr), &decryptedMap); jsonErr == nil {
if bodyVal, bodyOk := decryptedMap["body"]; bodyOk && bodyVal != nil {
if bodyStr, isStr := bodyVal.(string); isStr {
return bodyStr, nil
}
bodyBytes, marshalErr := json.Marshal(bodyVal)
if marshalErr == nil {
return string(bodyBytes), nil
}
}
encryptedSm4Key, err := sm4.CBCDecrypt(sm4Key, psbcutil.GetSM4IV(), request)
return string(psbcutil.Padding(encryptedSm4Key, 0)), nil
}
func checkInData(reqData map[string]string, key string) (string, error) {
data, ok := reqData[key]
if !ok {
return "", errors.New("请求数据中不存在" + key)
}
return data, nil
}
return decryptedStr, nil
func verify(content string, signature string, publicKeyStr string, merchantId string) bool {
pubKey, err := sm2.ReadPublicKeyFromHex(publicKeyStr)
//content = ""
if err != nil {
panic(fmt.Sprintf("pubKeyBytes sm2 ReadPublicKeyFromHex err: %v", err))
}
r, s := signToRS(signature)
return sm2.Sm2Verify(pubKey, []byte(content), []byte(merchantId), r, s)
}
// VerifySignature 验签
@ -244,7 +276,7 @@ func (c *Client) VerifySignature(content, signature string) bool {
}
func (c *Client) verify(content, signature string) bool {
pubKey, err := x509.ReadPublicKeyFromHex(c.cfg.SopPublicKey)
pubKey, err := sm2.ReadPublicKeyFromHex(c.cfg.SopPublicKey)
if err != nil {
panic(fmt.Sprintf("pubKeyBytes sm2 ReadPublicKeyFromHex err: %v", err))
}

View File

@ -6,11 +6,12 @@ import (
"encoding/hex"
"encoding/json"
"fmt"
"math/big"
"strings"
"PaymentCenter/app/third/paymentService/psbc/internal/sm2"
psbcutil "PaymentCenter/app/third/paymentService/psbc/internal/util"
"github.com/ZZMarquis/gm/sm4"
"github.com/tjfoc/gmsm/sm2"
"github.com/tjfoc/gmsm/x509"
)
// EncryptRequest 加密请求
@ -30,11 +31,11 @@ func EncryptRequest(request interface{}, cfg Config) (map[string]string, error)
return nil, fmt.Errorf("序列化请求失败: %v", err)
}
inputJson := string(inputBytes)
// Step 2: SM4 CBC 加密
sm4Key := generateSM4Key()
iv := getSM4IV()
paddedData := pkcs5Padding([]byte(inputJson), sm4.BlockSize)
sm4Key := psbcutil.GenerateSM4Key()
iv := psbcutil.GetSM4IV() // UISwD9fW6cFh9SNS
paddedData := psbcutil.Padding([]byte(inputJson), 1)
tmp, err := sm4.CBCEncrypt(sm4Key, iv, paddedData)
if err != nil {
return nil, fmt.Errorf("SM4加密失败: %v", err)
@ -42,12 +43,12 @@ func EncryptRequest(request interface{}, cfg Config) (map[string]string, error)
responseMsg := base64.StdEncoding.EncodeToString(tmp)
responseMsg = addNewline(responseMsg) // 对齐 YouChuKoffee每76字符加 \r\n
// Step 3: SM2 加密 SM4 密钥
sopPubKey, err := x509.ReadPublicKeyFromHex(cfg.SopPublicKey)
// Step 3: SM2 加密 SM4 密钥(使用 copied sm2 包,对齐 YouChuKoffee 的 Sm2Encrypt
sopPubKey, err := sm2.ReadPublicKeyFromHex(cfg.SopPublicKey)
if err != nil {
return nil, fmt.Errorf("读取SOP公钥失败: %v", err)
}
encryptKeyBytes, err := sm2.Encrypt(sopPubKey, sm4Key, rand.Reader, sm2.C1C3C2)
encryptKeyBytes, err := psbcutil.Sm2Encrypt(sopPubKey, sm4Key)
if err != nil {
return nil, fmt.Errorf("SM2加密SM4密钥失败: %v", err)
}
@ -55,7 +56,8 @@ func EncryptRequest(request interface{}, cfg Config) (map[string]string, error)
// Step 4: 签名(对齐 YouChuKoffee sign()UserID = MerchantId
signContent := fmt.Sprintf("%s%s%s", responseMsg, encryptKey, accessToken)
signature, err := client.signWithUserID(signContent, []byte(cfg.MerchantId))
signature, err := sign(cfg.MerchantId, client.cfg.PrivateKeyCallback, signContent)
if err != nil {
return nil, fmt.Errorf("生成签名失败: %v", err)
}
@ -71,16 +73,23 @@ func EncryptRequest(request interface{}, cfg Config) (map[string]string, error)
// signWithUserID 使用指定 UserID 对内容进行 SM2 签名
// 对齐 YouChuKoffee 的 sign() + rSToSign():直接返回 r.Text(16) + "#" + s.Text(16),不做 base64 编码
func (c *Client) signWithUserID(content string, userId []byte) (string, error) {
privKey, err := x509.ReadPrivateKeyFromHex(c.cfg.PrivateKey)
func sign(merchantId string, privateKeyHex string, signContent string) (string, error) {
privateKey, err := sm2.ReadPrivateKeyFromHex(privateKeyHex)
if err != nil {
return "", fmt.Errorf("读取私钥失败: %v", err)
return "", err
}
r, s, err := sm2.Sm2Sign(privKey, []byte(content), userId, rand.Reader)
r, s, err := sm2.Sm2Sign(privateKey, []byte(signContent), []byte(merchantId), rand.Reader)
if err != nil {
return "", fmt.Errorf("SM2签名失败: %v", err)
return "", err
}
return r.Text(16) + "#" + s.Text(16), nil
return rSToSign(r, s), nil
}
func rSToSign(r *big.Int, s *big.Int) string {
rStr := r.Text(16)
sStr := s.Text(16)
return fmt.Sprintf("%s#%s", rStr, sStr)
}
// addNewline 每76个字符添加 \r\n对齐 YouChuKoffee 的 postbank.addNewline

View File

@ -34,8 +34,8 @@ func (c *Client) OrderQuery(orderNo string) (*OrderQueryResponse, error) {
"txnCode": "1004",
"sourceId": "16",
"reqTraceId": now + RandomNumber(10),
"reqDate": now, // 14 位 YYYYMMDDHHmmss
"txnDt": now,
"reqDate": now, // 14 位 YYYYMMDDHHmmss
"txnDt": time.Now().Format("20060102"), // 8 位 YYYYMMDD对齐 YouChuKoffee
"mchtNo": c.cfg.MchtNo,
"oldSeqNo": orderNo,
},
@ -48,12 +48,13 @@ func (c *Client) OrderQuery(orderNo string) (*OrderQueryResponse, error) {
return nil, fmt.Errorf("加密请求失败: %v", err)
}
BusiMainId = "202607301754241710448735"
encryptedBytes, _ := json.Marshal(encryptedReq)
url := c.cfg.OrderHost + c.cfg.MerchantId + ".htm?partnerTxSriNo=" + BusiMainId
// head 同时作为 HTTP Header 明文传输
head := requestBody["head"].(map[string]string)
body, err := c.doPost(url, head, encryptedBytes)
// head 同时作为 HTTP Header 明文传输(对齐 YouChuKoffee 的 doPost 方式)
body, err := c.doPost(url, BusiMainId, "b2c.gatewaypay.orderQuery", encryptedBytes)
if err != nil {
return nil, err
}

View File

@ -53,9 +53,8 @@ func (c *Client) Refund(req RefundRequest) (*RefundResponse, error) {
encryptedBytes, _ := json.Marshal(encryptedReq)
url := c.cfg.OrderHost + c.cfg.MerchantId + ".htm?partnerTxSriNo=" + BusiMainId
// head 同时作为 HTTP Header 明文传输
head := requestBody["head"].(map[string]string)
body, err := c.doPost(url, head, encryptedBytes)
// head 同时作为 HTTP Header 明文传输(对齐 YouChuKoffee 的 doPost 方式)
body, err := c.doPost(url, BusiMainId, "b2c.gatewaypay.orderRefund", encryptedBytes)
if err != nil {
return nil, err
}

View File

@ -6,23 +6,24 @@ import (
// Config 支付配置
type Config struct {
MerchantId string
MchtNo string
AppID string
SopPublicKey string
PrivateKey string
Pubkey string
BankKey string
Sha string
ReturnUrl string
SuccessUrl string
NotifyUrl string
ShowTitleBar string
LoginHost string
OrderHost string
FileHost string
ShopId string
Psbcmcc string // 三方服务商标识,如 LSXD、JBZ
MerchantId string
MchtNo string
AppID string
SopPublicKey string
PrivateKey string
Pubkey string
BankKey string
Sha string
ReturnUrl string
SuccessUrl string
NotifyUrl string
ShowTitleBar string
LoginHost string
OrderHost string
FileHost string
ShopId string
Psbcmcc string // 三方服务商标识,如 LSXD、JBZ
PrivateKeyCallback string // 邮储响应解密的私钥
}
// PaymentLinkRequest 生成支付链接请求

View File

@ -12,44 +12,46 @@ import (
)
type PsbcPay struct {
MerchantId string `json:"merchant_id"` // 商户ID
MchtNo string `json:"mcht_no"` // 商户号
AppID string `json:"app_id"` // 应用ID
SopPublicKey string `json:"sop_public_key"` // SOP公钥
PrivateKey string `json:"private_key"` // 商户私钥
Pubkey string `json:"pubkey"` // 商户公钥
BankKey string `json:"bank_key"` // 银行公钥
Sha string `json:"sha"` // SHA密钥
ReturnUrl string `json:"return_url"` // 支付返回地址
SuccessUrl string `json:"success_url"` // 支付成功地址
NotifyUrl string `json:"notify_url"` // 回调通知地址
ShowTitleBar string `json:"show_title_bar"` // 是否显示标题栏
LoginHost string `json:"login_host"` // 登录服务地址
OrderHost string `json:"order_host"` // 订单服务地址
FileHost string `json:"file_host"` // 文件服务地址
ShopId string `json:"shop_id"` // 店铺ID
Psbcmcc string `json:"psbcmcc"` // 三方服务商标识
MerchantId string `json:"merchant_id"` // 商户ID
MchtNo string `json:"mcht_no"` // 商户号
AppID string `json:"app_id"` // 应用ID
SopPublicKey string `json:"sop_public_key"` // SOP公钥
PrivateKey string `json:"private_key"` // 商户私钥
PrivateKeyCallback string `json:"private_key_callback"` // 邮储响应解密的私钥
Pubkey string `json:"pubkey"` // 商户公钥
BankKey string `json:"bank_key"` // 银行公钥
Sha string `json:"sha"` // SHA密钥
ReturnUrl string `json:"return_url"` // 支付返回地址
SuccessUrl string `json:"success_url"` // 支付成功地址
NotifyUrl string `json:"notify_url"` // 回调通知地址
ShowTitleBar string `json:"show_title_bar"` // 是否显示标题栏
LoginHost string `json:"login_host"` // 登录服务地址
OrderHost string `json:"order_host"` // 订单服务地址
FileHost string `json:"file_host"` // 文件服务地址
ShopId string `json:"shop_id"` // 店铺ID
Psbcmcc string `json:"psbcmcc"` // 三方服务商标识
}
func PsbcInitClient(psbcConfig PsbcPay) *psbc.Client {
cfg := psbc.Config{
MerchantId: psbcConfig.MerchantId,
MchtNo: psbcConfig.MchtNo,
AppID: psbcConfig.AppID,
SopPublicKey: psbcConfig.SopPublicKey,
PrivateKey: psbcConfig.PrivateKey,
Pubkey: psbcConfig.Pubkey,
BankKey: psbcConfig.BankKey,
Sha: psbcConfig.Sha,
ReturnUrl: psbcConfig.ReturnUrl,
SuccessUrl: psbcConfig.SuccessUrl,
NotifyUrl: psbcConfig.NotifyUrl,
ShowTitleBar: psbcConfig.ShowTitleBar,
LoginHost: psbcConfig.LoginHost,
OrderHost: psbcConfig.OrderHost,
FileHost: psbcConfig.FileHost,
ShopId: psbcConfig.ShopId,
Psbcmcc: psbcConfig.Psbcmcc,
MerchantId: psbcConfig.MerchantId,
MchtNo: psbcConfig.MchtNo,
AppID: psbcConfig.AppID,
SopPublicKey: psbcConfig.SopPublicKey,
PrivateKey: psbcConfig.PrivateKey,
Pubkey: psbcConfig.Pubkey,
BankKey: psbcConfig.BankKey,
Sha: psbcConfig.Sha,
ReturnUrl: psbcConfig.ReturnUrl,
SuccessUrl: psbcConfig.SuccessUrl,
NotifyUrl: psbcConfig.NotifyUrl,
ShowTitleBar: psbcConfig.ShowTitleBar,
LoginHost: psbcConfig.LoginHost,
OrderHost: psbcConfig.OrderHost,
FileHost: psbcConfig.FileHost,
ShopId: psbcConfig.ShopId,
Psbcmcc: psbcConfig.Psbcmcc,
PrivateKeyCallback: psbcConfig.PrivateKeyCallback,
}
return psbc.NewClient(cfg)
}

View File

@ -35,22 +35,23 @@ func TestPsbcPay(t *testing.T) {
//data := `{"merchant_id": "your_merchant_id", "mcht_no": "your_mcht_no", "app_id": "your_app_id", "sop_public_key": "your_sop_public_key", "private_key": "your_private_key", "pubkey": "your_pubkey", "bank_key": "your_bank_key", "sha": "your_sha_key", "return_url": "https://example.com/return", "success_url": "https://example.com/success", "notify_url": "https://example.com/notify", "show_title_bar": "1", "login_host": "https://login.example.com", "order_host": "https://order.example.com", "file_host": "https://file.example.com", "shop_id": "your_shop_id"}`
psbc := PsbcPay{
MerchantId: "testMerchant001",
MchtNo: "100610100019042",
AppID: "961925472724332544001",
SopPublicKey: "04CABE03249C94BDC8A6A4440DA1B2ADFACF73F4340E5F1B9A76463694B44C2E5600A9BEAA035739383C292CF9F1C4695FAAC7963CD5033D5D647A6B1EBE78EC6A",
PrivateKey: "140c5c68da1829b79d8e4629a8b9548bd694ccc7061fbacb1079aed0e5ac33fa",
Pubkey: "0447fe9ed13aac6200c92b893ad1289a98437c8404e64b1d2f7c755698a8b8e8acb35c1db2bedc5213c930bdfc10efb0e12269cf6a06877679f114fe5ae9dd4469",
BankKey: "04E0E2E37F11901483CDFBC47F489D87D5D78C55DD7F919B73DEA83007748668B7871A1BA9608F156E25B7D64C7821379BAC1E2C591D5A50FF311D1AAE026C1DAE",
Sha: "636879vrt96t57w6f59",
ReturnUrl: "http://milk.h5.test.86698.cn/#/pages/ycnc/order",
SuccessUrl: "http://milk.h5.test.86698.cn/#/pages/ycnc/orderDetail?isPayBack=true&order_no=",
NotifyUrl: "http://milk.test.api.cdlsxd.cn/api/v1/order/notify",
ShowTitleBar: "true",
LoginHost: "http://wap.dev.psbc.com/sop-h5/biz/crecard/",
OrderHost: "http://wap.dev.psbc.com/sop-h5/biz/unionpay/",
FileHost: "",
ShopId: "LSXD0001",
MerchantId: "testMerchant001",
MchtNo: "100610100019042",
AppID: "961925472724332544001",
SopPublicKey: "04CABE03249C94BDC8A6A4440DA1B2ADFACF73F4340E5F1B9A76463694B44C2E5600A9BEAA035739383C292CF9F1C4695FAAC7963CD5033D5D647A6B1EBE78EC6A",
PrivateKey: "140c5c68da1829b79d8e4629a8b9548bd694ccc7061fbacb1079aed0e5ac33fa",
PrivateKeyCallback: "1F0E2F085955461A9B87820AFBD513712CAEA89687BE657DE4EC91613BE62D32",
Pubkey: "0447fe9ed13aac6200c92b893ad1289a98437c8404e64b1d2f7c755698a8b8e8acb35c1db2bedc5213c930bdfc10efb0e12269cf6a06877679f114fe5ae9dd4469",
BankKey: "04E0E2E37F11901483CDFBC47F489D87D5D78C55DD7F919B73DEA83007748668B7871A1BA9608F156E25B7D64C7821379BAC1E2C591D5A50FF311D1AAE026C1DAE",
Sha: "636879vrt96t57w6f59",
ReturnUrl: "http://milk.h5.test.86698.cn/#/pages/ycnc/order",
SuccessUrl: "http://milk.h5.test.86698.cn/#/pages/ycnc/orderDetail?isPayBack=true&order_no=",
NotifyUrl: "http://milk.test.api.cdlsxd.cn/api/v1/order/notify",
ShowTitleBar: "true",
LoginHost: "http://wap.dev.psbc.com/sop-h5/biz/crecard/",
OrderHost: "http://wap.dev.psbc.com/sop-h5/biz/unionpay/",
FileHost: "",
ShopId: "LSXD0001",
}
data, _ := json.Marshal(psbc)
fmt.Println(string(data))
@ -69,18 +70,18 @@ func TestPsbcPay(t *testing.T) {
PayerClientIp: "192.168.110.235",
Psbc: psbc,
}
//支付
orderResult := PaymentService(c, request)
t.Log(orderResult)
////支付
//orderResult := PaymentService(c, request)
//t.Log(orderResult)
//// 查询订单
//qreq := PayOrderQueryRequest{
// OrderId: request.OrderId,
// PayChannel: 3,
// Psbc: request.Psbc,
//}
//queryResult := PayOrderQuery(c, qreq)
//t.Log(queryResult)
// 查询订单
qreq := PayOrderQueryRequest{
OrderId: request.OrderId,
PayChannel: 3,
Psbc: request.Psbc,
}
queryResult := PayOrderQuery(c, qreq)
t.Log(queryResult)
//// 退款
//refund := OrderRefundRequest{