diff --git a/app/http/controllers/front/api.go b/app/http/controllers/front/api.go index 04a3c9b..9fe6338 100644 --- a/app/http/controllers/front/api.go +++ b/app/http/controllers/front/api.go @@ -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 diff --git a/app/http/entities/front/pay.go b/app/http/entities/front/pay.go index 53e23c5..cc71f8c 100644 --- a/app/http/entities/front/pay.go +++ b/app/http/entities/front/pay.go @@ -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 { diff --git a/app/services/thirdpay/do/pay.go b/app/services/thirdpay/do/pay.go index 7225991..ce4fb25 100644 --- a/app/services/thirdpay/do/pay.go +++ b/app/services/thirdpay/do/pay.go @@ -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 } diff --git a/app/third/paymentService/psbc/bill.go b/app/third/paymentService/psbc/bill.go index cd34dbc..7e84acf 100644 --- a/app/third/paymentService/psbc/bill.go +++ b/app/third/paymentService/psbc/bill.go @@ -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 } diff --git a/app/third/paymentService/psbc/client.go b/app/third/paymentService/psbc/client.go index 90a7ee9..6a664f0 100644 --- a/app/third/paymentService/psbc/client.go +++ b/app/third/paymentService/psbc/client.go @@ -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 的 Sm2Sign,UserID 传 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)) } diff --git a/app/third/paymentService/psbc/encrypt.go b/app/third/paymentService/psbc/encrypt.go index 7c4b20e..e88f131 100644 --- a/app/third/paymentService/psbc/encrypt.go +++ b/app/third/paymentService/psbc/encrypt.go @@ -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 diff --git a/app/third/paymentService/psbc/order.go b/app/third/paymentService/psbc/order.go index 193c872..73a1112 100644 --- a/app/third/paymentService/psbc/order.go +++ b/app/third/paymentService/psbc/order.go @@ -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 } diff --git a/app/third/paymentService/psbc/refund.go b/app/third/paymentService/psbc/refund.go index c6df14c..f8589bd 100644 --- a/app/third/paymentService/psbc/refund.go +++ b/app/third/paymentService/psbc/refund.go @@ -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 } diff --git a/app/third/paymentService/psbc/types.go b/app/third/paymentService/psbc/types.go index 7102ca0..5eb1ecd 100644 --- a/app/third/paymentService/psbc/types.go +++ b/app/third/paymentService/psbc/types.go @@ -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 生成支付链接请求 diff --git a/app/third/paymentService/psbc_service.go b/app/third/paymentService/psbc_service.go index 82cfc68..4dd929b 100644 --- a/app/third/paymentService/psbc_service.go +++ b/app/third/paymentService/psbc_service.go @@ -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) } diff --git a/app/third/paymentService/psbc_test.go b/app/third/paymentService/psbc_test.go index 210a943..668030f 100644 --- a/app/third/paymentService/psbc_test.go +++ b/app/third/paymentService/psbc_test.go @@ -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{