217 lines
6.4 KiB
Go
217 lines
6.4 KiB
Go
package leshua
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestSignUsesASCIISortedNonEmptyParams(t *testing.T) {
|
|
params := map[string]string{
|
|
"service": "get_tdcode",
|
|
"merchant_id": "1234567890",
|
|
"third_order_id": "NO1",
|
|
"amount": "100",
|
|
"nonce_str": "abc",
|
|
"empty": "",
|
|
"sign": "ignored",
|
|
}
|
|
|
|
got := Sign(params, "secret", SignOptions{})
|
|
want := "1E7892034AA77899E8DD609C4FA09E76"
|
|
if got != want {
|
|
t.Fatalf("Sign() = %s, want %s", got, want)
|
|
}
|
|
|
|
baseString := SignBaseString(params, SignOptions{})
|
|
wantBaseString := "amount=100&merchant_id=1234567890&nonce_str=abc&service=get_tdcode&third_order_id=NO1"
|
|
if baseString != wantBaseString {
|
|
t.Fatalf("SignBaseString() = %s, want %s", baseString, wantBaseString)
|
|
}
|
|
}
|
|
|
|
func TestVerifyNotifyIncludesEmptyAndExcludesErrorCode(t *testing.T) {
|
|
client := NewClient(Config{NotifyKey: "notify-secret"})
|
|
params := map[string]string{
|
|
"merchant_id": "1234567890",
|
|
"third_order_id": "NO1",
|
|
"leshua_order_id": "LS1",
|
|
"amount": "100",
|
|
"status": "2",
|
|
"attach": "",
|
|
"leshua": "",
|
|
"error_code": "-20001",
|
|
}
|
|
params["sign"] = Sign(params, "notify-secret", SignOptions{
|
|
IncludeEmpty: true,
|
|
ExcludeKeys: []string{"error_code", "leshua", "sign"},
|
|
})
|
|
|
|
if !client.VerifyNotify(params) {
|
|
t.Fatal("VerifyNotify() = false, want true")
|
|
}
|
|
|
|
params["amount"] = "101"
|
|
if client.VerifyNotify(params) {
|
|
t.Fatal("VerifyNotify() = true after amount changed, want false")
|
|
}
|
|
}
|
|
|
|
func TestVerifyNotifyDoesNotFallBackToSignKey(t *testing.T) {
|
|
client := NewClient(Config{
|
|
NotifyKey: "wrong-notify-secret",
|
|
SignKey: "sign-secret",
|
|
})
|
|
params := map[string]string{
|
|
"merchant_id": "1234567890",
|
|
"third_order_id": "NO1",
|
|
"leshua_order_id": "LS1",
|
|
"amount": "100",
|
|
"status": "2",
|
|
}
|
|
params["sign"] = Sign(params, "sign-secret", SignOptions{
|
|
IncludeEmpty: true,
|
|
ExcludeKeys: []string{"error_code", "sign"},
|
|
})
|
|
|
|
result := client.VerifyNotifyDetail(params)
|
|
if result.OK {
|
|
t.Fatal("VerifyNotifyDetail().OK = true, want false")
|
|
}
|
|
if _, ok := result.Expected["sign_key"]; ok {
|
|
t.Fatal("VerifyNotifyDetail() unexpectedly used sign_key fallback")
|
|
}
|
|
}
|
|
|
|
func TestVerifyNotifyUsesDocumentedNotifySignature(t *testing.T) {
|
|
client := NewClient(Config{NotifyKey: "notify-secret"})
|
|
params := map[string]string{
|
|
"merchant_id": "1234567890",
|
|
"third_order_id": "NO1",
|
|
"leshua_order_id": "LS1",
|
|
"amount": "100",
|
|
"status": "2",
|
|
"sign_type": "MD5",
|
|
}
|
|
params["sign"] = Sign(params, "notify-secret", SignOptions{
|
|
IncludeEmpty: true,
|
|
ExcludeKeys: []string{"error_code", "leshua", "sign"},
|
|
})
|
|
|
|
result := client.VerifyNotifyDetail(params)
|
|
if !result.OK {
|
|
t.Fatal("VerifyNotifyDetail().OK = false, want true")
|
|
}
|
|
if result.MatchedKey != "notify_key" {
|
|
t.Fatalf("MatchedKey = %s, want notify_key", result.MatchedKey)
|
|
}
|
|
}
|
|
|
|
func TestVerifyNotifyKeepsEmptyXMLFieldsInSignature(t *testing.T) {
|
|
client := NewClient(Config{NotifyKey: "notify-secret"})
|
|
params, err := ParsePayload([]byte(`<leshua>
|
|
<amount>100</amount>
|
|
<goods_tag></goods_tag>
|
|
<merchant_id>1234567890</merchant_id>
|
|
<sign_type>MD5</sign_type>
|
|
<status>2</status>
|
|
<third_order_id>NO1</third_order_id>
|
|
</leshua>`))
|
|
if err != nil {
|
|
t.Fatalf("ParsePayload(xml) error = %v", err)
|
|
}
|
|
params["sign"] = Sign(params, "notify-secret", SignOptions{
|
|
IncludeEmpty: true,
|
|
ExcludeKeys: []string{"error_code", "leshua", "sign"},
|
|
})
|
|
|
|
result := client.VerifyNotifyDetail(params)
|
|
if !result.OK {
|
|
t.Fatal("VerifyNotifyDetail().OK = false, want true")
|
|
}
|
|
baseString := result.BaseString[result.MatchedKey]
|
|
if !strings.Contains(baseString, "goods_tag=") {
|
|
t.Fatalf("baseString = %s, want goods_tag included", baseString)
|
|
}
|
|
}
|
|
|
|
func TestParsePayloadSupportsFormAndXML(t *testing.T) {
|
|
form, err := ParsePayload([]byte("third_order_id=NO1&status=2&amount=100"))
|
|
if err != nil {
|
|
t.Fatalf("ParsePayload(form) error = %v", err)
|
|
}
|
|
if form["third_order_id"] != "NO1" || form["status"] != "2" || form["amount"] != "100" {
|
|
t.Fatalf("ParsePayload(form) = %#v", form)
|
|
}
|
|
|
|
xml, err := ParsePayload([]byte("<xml><third_order_id>NO2</third_order_id><status>6</status><goods_tag></goods_tag><coupon/></xml>"))
|
|
if err != nil {
|
|
t.Fatalf("ParsePayload(xml) error = %v", err)
|
|
}
|
|
if xml["third_order_id"] != "NO2" || xml["status"] != "6" {
|
|
t.Fatalf("ParsePayload(xml) = %#v", xml)
|
|
}
|
|
if value, ok := xml["goods_tag"]; !ok || value != "" {
|
|
t.Fatalf("ParsePayload(xml).goods_tag = %q, exists=%v; want empty value", value, ok)
|
|
}
|
|
if value, ok := xml["coupon"]; !ok || value != "" {
|
|
t.Fatalf("ParsePayload(xml).coupon = %q, exists=%v; want empty value", value, ok)
|
|
}
|
|
}
|
|
|
|
func TestSignRefundUsesSameAlgorithm(t *testing.T) {
|
|
params := map[string]string{
|
|
"service": "unified_refund",
|
|
"merchant_id": "1234567890",
|
|
"merchant_refund_id": "REF001",
|
|
"refund_amount": "100",
|
|
"leshua_order_id": "LS1",
|
|
"nonce_str": "abc",
|
|
"sign": "ignored",
|
|
}
|
|
got := Sign(params, "secret", SignOptions{})
|
|
baseString := SignBaseString(params, SignOptions{})
|
|
wantBaseString := "leshua_order_id=LS1&merchant_id=1234567890&merchant_refund_id=REF001&nonce_str=abc&refund_amount=100&service=unified_refund"
|
|
if baseString != wantBaseString {
|
|
t.Fatalf("SignBaseString() = %s, want %s", baseString, wantBaseString)
|
|
}
|
|
want := Sign(map[string]string{
|
|
"service": "unified_refund",
|
|
"merchant_id": "1234567890",
|
|
"merchant_refund_id": "REF001",
|
|
"refund_amount": "100",
|
|
"leshua_order_id": "LS1",
|
|
"nonce_str": "abc",
|
|
}, "secret", SignOptions{})
|
|
if got != want {
|
|
t.Fatalf("Sign() = %s, want %s", got, want)
|
|
}
|
|
}
|
|
|
|
func TestVerifyRefundNotify(t *testing.T) {
|
|
client := NewClient(Config{NotifyKey: "notify-secret"})
|
|
params := map[string]string{
|
|
"merchant_id": "1234567890",
|
|
"third_order_id": "NO1",
|
|
"leshua_order_id": "LS1",
|
|
"merchant_refund_id": "REF001",
|
|
"leshua_refund_id": "LREF001",
|
|
"refund_amount": "100",
|
|
"total_amount": "200",
|
|
"status": "11",
|
|
"attach": "",
|
|
}
|
|
params["sign"] = Sign(params, "notify-secret", SignOptions{
|
|
IncludeEmpty: true,
|
|
ExcludeKeys: []string{"error_code", "leshua", "sign"},
|
|
})
|
|
|
|
if !client.VerifyNotify(params) {
|
|
t.Fatal("VerifyNotify() = false, want true for refund notify")
|
|
}
|
|
|
|
params["status"] = "12"
|
|
if client.VerifyNotify(params) {
|
|
t.Fatal("VerifyNotify() = true after status changed without re-sign, want false")
|
|
}
|
|
}
|