ymt_v3_generate-20260721-10.../ymt_v3_generate/example_test.go

272 lines
6.8 KiB
Go

package ymt_v3_generate_test
import (
"context"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/base64"
"encoding/json"
"encoding/pem"
"fmt"
"net/http"
"net/http/httptest"
"strings"
"testing"
"time"
sdk "ymt_v3_generate"
)
// 生成测试用的 RSA 密钥对和 AES key
func generateTestKeys() (privateKeyPEM, publicKeyPEM string, aesKey []byte, err error) {
// RSA 密钥
priv, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
return "", "", nil, err
}
privBytes := x509.MarshalPKCS1PrivateKey(priv)
privPEM := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: privBytes})
publicKey := &priv.PublicKey
pubBytes, err := x509.MarshalPKIXPublicKey(publicKey)
if err != nil {
return "", "", nil, err
}
pubPEM := pem.EncodeToMemory(&pem.Block{Type: "PUBLIC KEY", Bytes: pubBytes})
// AES key (16字节)
aesKey = make([]byte, 16)
_, err = rand.Read(aesKey)
if err != nil {
return "", "", nil, err
}
return string(privPEM), string(pubPEM), aesKey, nil
}
// 模拟服务器,返回加密的响应
func mockServer(t *testing.T, aesKey []byte, responseBody interface{}) *httptest.Server {
return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// 验证请求头
appID := r.Header.Get("Appid")
timestamp := r.Header.Get("Timestamp")
sign := r.Header.Get("Sign")
if appID == "" || timestamp == "" || sign == "" {
http.Error(w, "missing headers", http.StatusBadRequest)
return
}
// 读取请求体
var reqBody map[string]string
if err := json.NewDecoder(r.Body).Decode(&reqBody); err != nil {
http.Error(w, "invalid body", http.StatusBadRequest)
return
}
ciphertext := reqBody["ciphertext"]
if ciphertext == "" {
http.Error(w, "missing ciphertext", http.StatusBadRequest)
return
}
// 这里不验证签名,仅测试流程
// 构造响应
respPlaintext, _ := json.Marshal(responseBody)
// 加密
encrypted, err := sdk.EncryptPlaintext(string(respPlaintext), aesKey)
if err != nil {
http.Error(w, "encrypt error", http.StatusInternalServerError)
return
}
apiResp := map[string]interface{}{
"code": 200,
"message": "成功",
"data": map[string]string{
"ciphertext": encrypted,
},
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(apiResp)
}))
}
func TestCreateKeyOrder(t *testing.T) {
privPEM, pubPEM, aesKey, err := generateTestKeys()
if err != nil {
t.Fatal(err)
}
server := mockServer(t, aesKey, sdk.KeyOrderResponse{
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",
})
defer server.Close()
client := sdk.NewClient(
sdk.WithAppID("test_app"),
sdk.WithPrivateKey(privPEM),
sdk.WithPublicKey(pubPEM),
sdk.WithKey(base64.StdEncoding.EncodeToString(aesKey)),
sdk.WithBaseURL(server.URL),
)
req := &sdk.KeyOrderRequest{
OutBizNo: "order_001",
ActivityNo: "ACT20260622001",
Account: "18666666666",
NotifyURL: "https://notify.example.com/openapi",
}
resp, err := client.CreateKeyOrder(context.Background(), req)
if err != nil {
t.Fatal(err)
}
if resp.TradeNo != "7251449503000383488" {
t.Errorf("expected trade_no 7251449503000383488, got %s", resp.TradeNo)
}
}
func TestQueryKey(t *testing.T) {
privPEM, pubPEM, aesKey, err := generateTestKeys()
if err != nil {
t.Fatal(err)
}
server := mockServer(t, aesKey, sdk.KeyQueryResponse{
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",
})
defer server.Close()
client := sdk.NewClient(
sdk.WithAppID("test_app"),
sdk.WithPrivateKey(privPEM),
sdk.WithPublicKey(pubPEM),
sdk.WithKey(base64.StdEncoding.EncodeToString(aesKey)),
sdk.WithBaseURL(server.URL),
)
req := &sdk.KeyQueryRequest{
OutBizNo: "order_001",
}
resp, err := client.QueryKey(context.Background(), req)
if err != nil {
t.Fatal(err)
}
if resp.TradeNo != "7251449503000383488" {
t.Errorf("expected trade_no 7251449503000383488, got %s", resp.TradeNo)
}
}
func TestDiscardKey(t *testing.T) {
privPEM, pubPEM, aesKey, err := generateTestKeys()
if err != nil {
t.Fatal(err)
}
server := mockServer(t, aesKey, sdk.KeyDiscardResponse{
OutBizNo: "order_001",
TradeNo: "7251449503000383488",
Status: 3,
})
defer server.Close()
client := sdk.NewClient(
sdk.WithAppID("test_app"),
sdk.WithPrivateKey(privPEM),
sdk.WithPublicKey(pubPEM),
sdk.WithKey(base64.StdEncoding.EncodeToString(aesKey)),
sdk.WithBaseURL(server.URL),
)
req := &sdk.KeyDiscardRequest{
TradeNo: "7251449503000383488",
}
resp, err := client.DiscardKey(context.Background(), req)
if err != nil {
t.Fatal(err)
}
if resp.Status != 3 {
t.Errorf("expected status 3, got %d", resp.Status)
}
}
func TestBatchOrder(t *testing.T) {
privPEM, pubPEM, aesKey, err := generateTestKeys()
if err != nil {
t.Fatal(err)
}
server := mockServer(t, aesKey, sdk.BatchOrderResponse{
OutBizNo: "batch_001",
TradeNo: "7251449503000383499",
Status: "processing",
})
defer server.Close()
client := sdk.NewClient(
sdk.WithAppID("test_app"),
sdk.WithPrivateKey(privPEM),
sdk.WithPublicKey(pubPEM),
sdk.WithKey(base64.StdEncoding.EncodeToString(aesKey)),
sdk.WithBaseURL(server.URL),
)
req := &sdk.BatchOrderRequest{
OutBizNo: "batch_001",
ActivityNo: "ACT20260622001",
Number: 100,
}
resp, err := client.BatchOrder(context.Background(), req)
if err != nil {
t.Fatal(err)
}
if resp.Status != "processing" {
t.Errorf("expected status processing, got %s", resp.Status)
}
}
func TestBatchQuery(t *testing.T) {
privPEM, pubPEM, aesKey, err := generateTestKeys()
if err != nil {
t.Fatal(err)
}
server := mockServer(t, aesKey, sdk.BatchQueryResponse{
OutBizNo: "batch_001",
TradeNo: "7251449503000383499",
Status: "success",
DownloadURL: "https://oss.example.com/openapi_7251449503000383499.zip",
ZipPassword: "123456",
})
defer server.Close()
client := sdk.NewClient(
sdk.WithAppID("test_app"),
sdk.WithPrivateKey(privPEM),
sdk.WithPublicKey(pubPEM),
sdk.WithKey(base64.StdEncoding.EncodeToString(aesKey)),
sdk.WithBaseURL(server.URL),
)
req := &sdk.BatchQueryRequest{
TradeNo: "7251449503000383499",
}
resp, err := client.BatchQuery(context.Background(), req)
if err != nil {
t.Fatal(err)
}
if resp.Status != "success" {
t.Errorf("expected status success, got %s", resp.Status)
}
if resp.DownloadURL == "" {
t.Error("expected download_url not empty")
}
}