kra-new/internal/integration/payment/native_test.go

152 lines
5.7 KiB
Go

package payment
import (
"crypto/aes"
"crypto/cipher"
"encoding/base64"
bizpayment "kra/internal/biz/payment"
"net/url"
"strings"
"testing"
)
func TestWechatV2SignOfficialStyle(t *testing.T) {
values := map[string]string{
"appid": "wxd930ea5d5a258f4f", "mch_id": "10000100", "device_info": "1000",
"body": "test", "nonce_str": "ibuaiVcKdpRxkhJA",
}
got := wechatV2Sign(values, "192006250b4c09247ec02edce69f6a2d", "MD5")
if got != strings.ToUpper(got) || len(got) != 32 {
t.Fatalf("invalid WeChat v2 MD5 signature %q", got)
}
values["sign"] = got
if err := verifyWechatV2(values, "192006250b4c09247ec02edce69f6a2d"); err != nil {
t.Fatal(err)
}
}
func TestApplePaymentResultSeparatesMerchantAndProviderTradeNumbers(t *testing.T) {
result, err := applePaymentResult("1000000000001", map[string]any{
"transactionId": "1000000000001",
"appAccountToken": "123e4567-e89b-12d3-a456-426614174000",
"currency": "CNY",
"price": "1000",
}, nil, map[string]any{"price_divisor": "10"})
if err != nil {
t.Fatal(err)
}
if result.TradeNo != "123e4567-e89b-12d3-a456-426614174000" || result.ProviderTradeNo != "1000000000001" || result.QueryID != "1000000000001" {
t.Fatalf("unexpected Apple order identifiers: %+v", result)
}
}
func TestApplePaymentResultTreatsZeroRevocationDateAsNotRevoked(t *testing.T) {
result, err := applePaymentResult("1000000000001", map[string]any{
"transactionId": "1000000000001",
"appAccountToken": "123e4567-e89b-12d3-a456-426614174000",
"currency": "CNY",
"price": "1000",
"revocationDate": float64(0),
}, nil, map[string]any{"price_divisor": "10"})
if err != nil || result.Status != "success" || result.Amount != 100 {
t.Fatalf("zero revocationDate result = %+v, err = %v", result, err)
}
result, err = applePaymentResult("1000000000001", map[string]any{
"transactionId": "1000000000001",
"appAccountToken": "123e4567-e89b-12d3-a456-426614174000",
"currency": "CNY",
"price": "1000",
"revocationDate": float64(1700000000000),
}, nil, map[string]any{"price_divisor": "10"})
if err != nil || result.Status != "failed" {
t.Fatalf("positive revocationDate result = %+v, err = %v", result, err)
}
}
func TestWechatV3Decrypt(t *testing.T) {
key := "01234567890123456789012345678901"
nonce := "0123456789ab"
aad := "transaction"
plain := []byte(`{"out_trade_no":"T1","trade_state":"SUCCESS"}`)
block, err := aes.NewCipher([]byte(key))
if err != nil {
t.Fatal(err)
}
gcm, err := cipher.NewGCM(block)
if err != nil {
t.Fatal(err)
}
ciphertext := base64.StdEncoding.EncodeToString(gcm.Seal(nil, []byte(nonce), plain, []byte(aad)))
got, err := decryptWechatV3(ciphertext, nonce, aad, key)
if err != nil {
t.Fatal(err)
}
if string(got) != string(plain) {
t.Fatalf("plaintext = %q", got)
}
}
func TestAlipaySignContentSortedAndExcludesSign(t *testing.T) {
values := url.Values{"method": {"alipay.trade.query"}, "app_id": {"123"}, "sign": {"ignored"}, "empty": {""}}
if got := alipaySignContent(values); got != "app_id=123&method=alipay.trade.query" {
t.Fatalf("sign content = %q", got)
}
}
func TestAlipayBreakdownWithPointPayment(t *testing.T) {
result := &bizpayment.PaymentResult{Status: "success", Amount: 1000}
err := populateAlipayBreakdown(result, map[string]any{
"total_amount": "10.00", "buyer_pay_amount": "8.00", "point_amount": "2.00", "receipt_amount": "8.00",
})
if err != nil {
t.Fatal(err)
}
if !result.AmountBreakdownKnown || result.PayerPaidAmount != 800 || result.CashPaidAmount != 600 || result.PointPaidAmount != 200 || result.DiscountAmount != 200 || result.SettlementAmount != 800 {
t.Fatalf("unexpected Alipay breakdown: %+v", result)
}
}
func TestWechatV2BreakdownWithCoupon(t *testing.T) {
result := &bizpayment.PaymentResult{Status: "success", Amount: 1000}
err := populateWechatV2Breakdown(result, map[string]string{"cash_fee": "900", "coupon_fee": "100", "settlement_total_fee": "950"})
if err != nil {
t.Fatal(err)
}
if !result.AmountBreakdownKnown || result.PayerPaidAmount != 900 || result.DiscountAmount != 100 || result.SettlementAmount != 950 {
t.Fatalf("unexpected WeChat v2 breakdown: %+v", result)
}
}
func TestWechatV3BreakdownWithPromotion(t *testing.T) {
result := &bizpayment.PaymentResult{Status: "success", Amount: 1000}
err := populateWechatV3Breakdown(result, map[string]any{
"amount": map[string]any{"payer_total": float64(800), "settlement_amount": float64(780)},
"promotion_detail": []any{map[string]any{"amount": float64(200)}},
})
if err != nil {
t.Fatal(err)
}
if !result.AmountBreakdownKnown || result.PayerPaidAmount != 800 || result.CashPaidAmount != 800 || result.DiscountAmount != 200 || result.SettlementAmount != 780 {
t.Fatalf("unexpected WeChat v3 breakdown: %+v", result)
}
}
func TestVendorBreakdownUsesConfiguredUnits(t *testing.T) {
result := &bizpayment.PaymentResult{Status: "success", Amount: 1000, Currency: "CNY"}
object := map[string]any{"data": map[string]any{
"payer": "8.00", "cash": "6.00", "points": "2.00", "discount": "2.00", "settlement": "7.80",
}}
config := map[string]any{
"query_amount_scale": "100", "query_payer_paid_amount_field": "data.payer", "query_cash_paid_amount_field": "data.cash",
"query_point_paid_amount_field": "data.points", "query_discount_amount_field": "data.discount",
"query_settlement_amount_field": "data.settlement", "query_payer_currency_field": "data.currency",
}
err := populateVendorBreakdown(result, object, config)
if err != nil {
t.Fatal(err)
}
if !result.AmountBreakdownKnown || result.PayerPaidAmount != 800 || result.CashPaidAmount != 600 || result.PointPaidAmount != 200 || result.DiscountAmount != 200 || result.SettlementAmount != 780 {
t.Fatalf("unexpected vendor breakdown: %+v", result)
}
}