hb-20260724155322/hb/example_test.go

200 lines
7.7 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package hb
import (
"context"
"fmt"
"log"
"testing"
)
// ExampleClient_Refund_MD5 使用MD5签名的退款示例
func ExampleClient_Refund_MD5() {
// 创建客户端使用MD5签名
client, err := NewClient(
"888009941110054",
WithSignKey("your-64-digit-sign-key-here"),
WithBaseURL("https://uatipos.10086.cn"), // 测试环境
)
if err != nil {
log.Fatalf("创建客户端失败: %v", err)
}
// 构建退款请求
req := &RefundRequest{
RequestId: "20211105053044",
SignType: SignTypeMD5,
OrderId: "20211105045315",
Amount: "1",
}
// 发送退款请求
resp, err := client.Refund(context.Background(), req)
if err != nil {
log.Fatalf("退款请求失败: %v", err)
}
fmt.Printf("返回码: %s\n", resp.ReturnCode)
fmt.Printf("退款结果: %s\n", resp.Status)
fmt.Printf("流水号: %s\n", resp.PayNo)
// 判断退款请求是否成功
if IsRefundRequestSuccess(resp.ReturnCode) {
fmt.Println("退款请求提交成功")
}
// 判断退款最终结果
if IsRefundSuccess(resp.Status) {
fmt.Println("退款最终成功")
}
// Output:
// 返回码: 000000
// 退款结果: SUCCESS
// 流水号: 205206151912517707
// 退款请求提交成功
// 退款最终成功
}
// ExampleClient_Refund_RSA 使用RSA签名的退款示例
func ExampleClient_Refund_RSA() {
// 商户RSA私钥PEM格式
privateKey := `-----BEGIN PRIVATE KEY-----
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAJ...(你的私钥)
-----END PRIVATE KEY-----`
// 创建客户端使用RSA签名
client, err := NewClient(
"888009941110054",
WithPrivateKey(privateKey),
WithBaseURL("https://ipos.10086.cn"), // 生产环境
)
if err != nil {
log.Fatalf("创建客户端失败: %v", err)
}
// 构建退款请求
req := &RefundRequest{
RequestId: "20211105053044",
SignType: SignTypeRSA,
OrderId: "20211105045315",
Amount: "1",
}
// 发送退款请求
resp, err := client.Refund(context.Background(), req)
if err != nil {
log.Fatalf("退款请求失败: %v", err)
}
fmt.Printf("返回码: %s\n", resp.ReturnCode)
fmt.Printf("退款结果: %s\n", resp.Status)
// Output:
// 返回码: 000000
// 退款结果: SUCCESS
}
// TestSignMD5 测试MD5签名
func TestSignMD5(t *testing.T) {
signStr := "merchantId=888009941110054&requestId=20211105053044&signType=MD5&type=OrderRefund&version=2.0.0&orderId=20211105045315&amount=1"
signKey := "test-sign-key-64-chars-length-string-for-testing"
hmac := SignMD5(signStr, signKey)
if hmac == "" {
t.Error("MD5签名结果为空")
}
t.Logf("MD5签名结果: %s", hmac)
// 验证签名
if !VerifyMD5(signStr, signKey, hmac) {
t.Error("MD5签名验证失败")
}
}
// TestBuildSignString 测试签名串构建
func TestBuildSignString(t *testing.T) {
params := map[string]string{
"merchantId": "888009941110054",
"requestId": "20211105053044",
"signType": "MD5",
"type": "OrderRefund",
"version": "2.0.0",
"orderId": "20211105045315",
"amount": "1",
}
keys := getRequestSignKeys()
signStr := buildSignString(params, keys)
expected := "merchantId=888009941110054&requestId=20211105053044&signType=MD5&type=OrderRefund&version=2.0.0&orderId=20211105045315&amount=1"
if signStr != expected {
t.Errorf("签名串不匹配\n期望: %s\n实际: %s", expected, signStr)
}
}
// TestParseResponse 测试响应解析
func TestParseResponse(t *testing.T) {
rawResponse := `merchantId=888009941110054&payNo=205206151912517707&returnCode=000000&message=SUCCESS&signType=RSA&type=OrderRefund&version=2.0.0&amount=1&orderId=20211105045315&status=SUCCESS&serverCert=3082042030820308A003020102020420B82E72300D06092A864886F70D0101050500302F310B300906035504061302434E3120301E06035504030C17434D434120456E74657270726973652043415F32303438301E170D3230303830363031343834395A170D3232303830363031343834395A3076310B300906035504061302434E310F300D06035504080C06E6B996E58D97310F300D06035504070C06E995BFE6B2993145304306035504030C3CE4B8ADE59BBDE7A7BBE58AA8E9809AE4BFA1E99B86E59BA2E6B996E58D97E69C89E99990E585ACE58FB8E794B5E5AD90E59586E58AA1E4B8ADE5BF8330820122300D06092A864886F70D01010105000382010F003082010A028201010092FCBC26F1107D35B966C0C098B1F31F8313103A29DC5C78A8056D1AFAC1E5BAA89F5AEE6D3E737D3554AE815040AD5A5D9BAF5BB5B4B45AA5622335E3B9F48D9C05DF29248DF944544D414513F37DFE7F618D0C62B24E1E90CFD1790791861E20FDEFC4288EA4BF906EE1A6B576D9FDE6108CF5A1ED01D1931F2C72AED5393AE9CB668BBF629B25A239E09C54D45B565FBA040963B011C7B80F7C93D4695F4568F6358D591FBCB1073C2583630EC858B7C21F5B7CBB8CC05431D93F4AC358F78A06D6E40D1C033083F403697C12A0A99FF6363D792F624B66FCA655E7057686BA5093A8F68597DB8F40865081A3EB43C1C52E91D35F83F9FF3BF40C9901D08B0203010001A381FC3081F930370603551D250101FF042D302B06082B0601050507030206082B0601050507030106096086480186F8420401060A2B0601040182370A0303301F0603551D23041830168014972A89BEE6A2AA3FA666133AE36A3FBA5D86697130710603551D1F046A30683066A02FA02D862B687474703A2F2F7777772E636D63612E6E65742F646F776E6C6F61642F63726C2F43524C3134322E63726CA233A431302F3120301E06035504030C17434D434120456E74657270726973652043415F32303438310B300906035504061302434E300B0603551D0F0404030200B1301D0603551D0E04160414F713DA66CF8A1F30440D83455C2AFC6560B040B6300D06092A864886F70D010105050003820101002AD8B85ABEEAE53C6002381120F7D6B23620464197FBBDB093D4BB98AF256E335F55A67E32BFDF165BB1E2DDA997A0727086D26F8427FE6B77F6F00C6168CE715E8D298D5EB47B7227CDB8094CB1047CBDEA3D911903DCAA57131DEE1CD0069BBF8C7940A3E68438CCCA1949FF045F7349AA865F7FAC7170B7D7339DEBC46930FF9B241200440EAFD280F868C13364D13ECEB04EA702D0479862F9590813AB94BE38DC84E366B884174731464111A1AFEB199E1D7D518651BB5F430926286CA2B5619CD54689F5851A231C1605146D4ACD6CCC54DB79CC49F992083D5DEACAFDDC2B8777B13B7D63FF7E35D1098BEFD6B550EC3328ECE0224F5AAD6C2B83FB85&hmac=00AAA308D1AA66B2E534D9177B408B55A0CC14F8B27ACE59F08150E66E51858F18070A0DD629FCBD47BB1A98A632DB3F492213A92F14885043EC68BD8180E58ED742D748B708B281693226A7D3BF326B812BA45E7E7D13B4D52498B3C6C83380827CD741A9EF0D99B1C96588C2BE56C79BDFC3813CA4E627142BA7717FFFB43BE53F9B3F2A6D3112D83A90C3D3859A8456BC892E6E960FE56F36F829FAFA7CAEF19D01D10C0BD2F2538827CFF4C642BBAA6423AED0CB8E0D980D7D0BDEB4B1A04B9DAC8867B724527423038D953603A07018BEC1980AD31EDD3E88977F72795DCFB0B3B674FA91A6443F9F0DB67B485B3F3AD5E48AA26F3641E44B64FC7B0920`
resp, err := parseResponse(rawResponse)
if err != nil {
t.Fatalf("解析响应失败: %v", err)
}
if resp.MerchantId != "888009941110054" {
t.Errorf("MerchantId不匹配: %s", resp.MerchantId)
}
if resp.PayNo != "205206151912517707" {
t.Errorf("PayNo不匹配: %s", resp.PayNo)
}
if resp.ReturnCode != "000000" {
t.Errorf("ReturnCode不匹配: %s", resp.ReturnCode)
}
if resp.Status != "SUCCESS" {
t.Errorf("Status不匹配: %s", resp.Status)
}
if resp.SignType != "RSA" {
t.Errorf("SignType不匹配: %s", resp.SignType)
}
}
// TestErrorCode 测试错误码映射
func TestErrorCode(t *testing.T) {
tests := []struct {
code string
expected string
}{
{"000000", "未知错误码"},
{"C01088", "退货金额域非法"},
{"D22201", "订单不存在"},
{"IPS0008", "签名不符,一般都是由于中文编码引起"},
{"UNKNOWN", "未知错误码"},
}
for _, tt := range tests {
desc := GetErrorDescription(tt.code)
if desc != tt.expected {
t.Errorf("错误码 %s: 期望 %s, 实际 %s", tt.code, tt.expected, desc)
}
}
}
// TestIsRefundSuccess 测试退款成功判断
func TestIsRefundSuccess(t *testing.T) {
if !IsRefundRequestSuccess("000000") {
t.Error("000000 应该表示退款请求成功")
}
if !IsRefundRequestSuccess("MCG00000") {
t.Error("MCG00000 应该表示退款请求成功")
}
if IsRefundRequestSuccess("C01088") {
t.Error("C01088 不应该表示退款请求成功")
}
if !IsRefundSuccess("SUCCESS") {
t.Error("SUCCESS 应该表示退款最终成功")
}
if IsRefundSuccess("FAILED") {
t.Error("FAILED 不应该表示退款最终成功")
}
}