153 lines
5.7 KiB
Go
153 lines
5.7 KiB
Go
package payment
|
|
|
|
import (
|
|
"crypto/aes"
|
|
"crypto/cipher"
|
|
"encoding/base64"
|
|
"net/url"
|
|
"strings"
|
|
"testing"
|
|
|
|
"kra/internal/biz"
|
|
)
|
|
|
|
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 := &biz.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 := &biz.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 := &biz.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 := &biz.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)
|
|
}
|
|
}
|