239 lines
6.4 KiB
Go
239 lines
6.4 KiB
Go
package ymt_v3_api
|
|
|
|
import (
|
|
"context"
|
|
"crypto/rand"
|
|
"crypto/rsa"
|
|
"crypto/x509"
|
|
"encoding/json"
|
|
"encoding/pem"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
// 生成测试用的 RSA 密钥对和 AES 密钥
|
|
func generateTestKeys() (appID, privateKeyPEM, publicKeyPEM, aesKey string, err error) {
|
|
appID = "test_app_id"
|
|
priv, err := rsa.GenerateKey(rand.Reader, 2048)
|
|
if err != nil {
|
|
return
|
|
}
|
|
privBytes, err := x509.MarshalPKCS8PrivateKey(priv)
|
|
if err != nil {
|
|
return
|
|
}
|
|
privateKeyPEM = string(pem.EncodeToMemory(&pem.Block{Type: "PRIVATE KEY", Bytes: privBytes}))
|
|
|
|
pubBytes, err := x509.MarshalPKIXPublicKey(&priv.PublicKey)
|
|
if err != nil {
|
|
return
|
|
}
|
|
publicKeyPEM = string(pem.EncodeToMemory(&pem.Block{Type: "PUBLIC KEY", Bytes: pubBytes}))
|
|
|
|
aesKey = "1234567890123456" // 16 字节
|
|
return
|
|
}
|
|
|
|
// 启动一个模拟服务器,返回加密的成功响应
|
|
func setupMockServer(t *testing.T, client *Client, bizResp interface{}) *httptest.Server {
|
|
t.Helper()
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
// 验证必要 Header
|
|
if r.Header.Get("Appid") == "" || r.Header.Get("Timestamp") == "" || r.Header.Get("Sign") == "" {
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
json.NewEncoder(w).Encode(apiResponse{Code: 400, Message: "missing header"})
|
|
return
|
|
}
|
|
// 解密请求体,验证 ciphertext 存在
|
|
var reqBody cipherRequest
|
|
if err := json.NewDecoder(r.Body).Decode(&reqBody); err != nil || reqBody.Ciphertext == "" {
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
json.NewEncoder(w).Encode(apiResponse{Code: 400, Message: "invalid body"})
|
|
return
|
|
}
|
|
// 构造加密响应
|
|
ciphertext, err := client.encryptPayload(bizResp)
|
|
if err != nil {
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
return
|
|
}
|
|
resp := apiResponse{
|
|
Code: 200,
|
|
Message: "成功",
|
|
Data: &cipherData{Ciphertext: ciphertext},
|
|
}
|
|
w.Header().Set("Content-Type", "application/json")
|
|
json.NewEncoder(w).Encode(resp)
|
|
}))
|
|
return server
|
|
}
|
|
|
|
func TestOrderKey(t *testing.T) {
|
|
appID, privPEM, pubPEM, aesKey, err := generateTestKeys()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
client, err := NewClient(appID, privPEM, pubPEM, aesKey, WithEncryptType("AES"))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
expectedResp := &OrderKeyResponse{
|
|
OutBizNo: "order_001",
|
|
TradeNo: "7251449503000383488",
|
|
Key: "aZKdU9BymzR6qGRzJM",
|
|
ValidBeginTime: "2026-06-22 15:30:00",
|
|
ValidEndTime: "2026-12-31 23:59:59",
|
|
UsableNum: 1,
|
|
UsageNum: 0,
|
|
Status: 1,
|
|
SettlementPrice: 9.9,
|
|
Account: "18666666666",
|
|
}
|
|
server := setupMockServer(t, client, expectedResp)
|
|
defer server.Close()
|
|
client.baseURL = server.URL
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
|
defer cancel()
|
|
|
|
req := &OrderKeyRequest{
|
|
OutBizNo: "order_001",
|
|
ActivityNo: "ACT20260622001",
|
|
Account: "18666666666",
|
|
NotifyURL: "https://notify.example.com/openapi",
|
|
}
|
|
resp, err := client.OrderKey(ctx, req)
|
|
if err != nil {
|
|
t.Fatalf("OrderKey failed: %v", err)
|
|
}
|
|
if resp.TradeNo != expectedResp.TradeNo {
|
|
t.Errorf("expected trade_no %s, got %s", expectedResp.TradeNo, resp.TradeNo)
|
|
}
|
|
if resp.Key != expectedResp.Key {
|
|
t.Errorf("expected key %s, got %s", expectedResp.Key, resp.Key)
|
|
}
|
|
}
|
|
|
|
func TestQueryKey(t *testing.T) {
|
|
appID, privPEM, pubPEM, aesKey, err := generateTestKeys()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
client, err := NewClient(appID, privPEM, pubPEM, aesKey)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
expectedResp := &QueryKeyResponse{
|
|
OutBizNo: "order_001",
|
|
TradeNo: "7251449503000383488",
|
|
Status: 1,
|
|
}
|
|
server := setupMockServer(t, client, expectedResp)
|
|
defer server.Close()
|
|
client.baseURL = server.URL
|
|
|
|
ctx := context.Background()
|
|
req := &QueryKeyRequest{OutBizNo: "order_001"}
|
|
resp, err := client.QueryKey(ctx, req)
|
|
if err != nil {
|
|
t.Fatalf("QueryKey failed: %v", err)
|
|
}
|
|
if resp.OutBizNo != expectedResp.OutBizNo {
|
|
t.Errorf("expected out_biz_no %s, got %s", expectedResp.OutBizNo, resp.OutBizNo)
|
|
}
|
|
}
|
|
|
|
func TestDiscardKey(t *testing.T) {
|
|
appID, privPEM, pubPEM, aesKey, err := generateTestKeys()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
client, err := NewClient(appID, privPEM, pubPEM, aesKey)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
expectedResp := &DiscardKeyResponse{
|
|
OutBizNo: "order_001",
|
|
TradeNo: "7251449503000383488",
|
|
Status: 3,
|
|
}
|
|
server := setupMockServer(t, client, expectedResp)
|
|
defer server.Close()
|
|
client.baseURL = server.URL
|
|
|
|
ctx := context.Background()
|
|
req := &DiscardKeyRequest{TradeNo: "7251449503000383488"}
|
|
resp, err := client.DiscardKey(ctx, req)
|
|
if err != nil {
|
|
t.Fatalf("DiscardKey failed: %v", err)
|
|
}
|
|
if resp.Status != 3 {
|
|
t.Errorf("expected status 3, got %d", resp.Status)
|
|
}
|
|
}
|
|
|
|
func TestBatchOrderKey(t *testing.T) {
|
|
appID, privPEM, pubPEM, aesKey, err := generateTestKeys()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
client, err := NewClient(appID, privPEM, pubPEM, aesKey)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
expectedResp := &BatchOrderResponse{
|
|
OutBizNo: "batch_001",
|
|
TradeNo: "7251449503000383499",
|
|
Status: "processing",
|
|
}
|
|
server := setupMockServer(t, client, expectedResp)
|
|
defer server.Close()
|
|
client.baseURL = server.URL
|
|
|
|
ctx := context.Background()
|
|
req := &BatchOrderRequest{
|
|
OutBizNo: "batch_001",
|
|
ActivityNo: "ACT20260622001",
|
|
Number: 100,
|
|
}
|
|
resp, err := client.BatchOrderKey(ctx, req)
|
|
if err != nil {
|
|
t.Fatalf("BatchOrderKey failed: %v", err)
|
|
}
|
|
if resp.Status != "processing" {
|
|
t.Errorf("expected status processing, got %s", resp.Status)
|
|
}
|
|
}
|
|
|
|
func TestBatchQueryKey(t *testing.T) {
|
|
appID, privPEM, pubPEM, aesKey, err := generateTestKeys()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
client, err := NewClient(appID, privPEM, pubPEM, aesKey)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
expectedResp := &BatchQueryResponse{
|
|
OutBizNo: "batch_001",
|
|
TradeNo: "7251449503000383499",
|
|
Status: "success",
|
|
DownloadURL: "https://oss.example.com/openapi_7251449503000383499.zip",
|
|
ZipPassword: "123456",
|
|
}
|
|
server := setupMockServer(t, client, expectedResp)
|
|
defer server.Close()
|
|
client.baseURL = server.URL
|
|
|
|
ctx := context.Background()
|
|
req := &BatchQueryRequest{TradeNo: "7251449503000383499"}
|
|
resp, err := client.BatchQueryKey(ctx, req)
|
|
if err != nil {
|
|
t.Fatalf("BatchQueryKey failed: %v", err)
|
|
}
|
|
if resp.DownloadURL != expectedResp.DownloadURL {
|
|
t.Errorf("expected download_url %s, got %s", expectedResp.DownloadURL, resp.DownloadURL)
|
|
}
|
|
} |