拉卡拉增加不限制支付方式
This commit is contained in:
@@ -169,7 +169,7 @@ func (c *Client) CreatePayment(ctx context.Context, req CreatePaymentRequest) (*
|
||||
return nil, err
|
||||
}
|
||||
payWay := firstNonEmpty(req.PayWay, c.cfg.PayWay, "ZFBZF")
|
||||
payMode := firstNonEmpty(c.cfg.PayMode, payModeFromPayWay(payWay), "ALIPAY")
|
||||
payMode := normalizeCounterPayMode(c.cfg.PayMode)
|
||||
expireMinutes := c.cfg.OrderExpireMinutes
|
||||
if expireMinutes <= 0 {
|
||||
expireMinutes = 15
|
||||
@@ -183,9 +183,11 @@ func (c *Client) CreatePayment(ctx context.Context, req CreatePaymentRequest) (*
|
||||
"support_refund": 1,
|
||||
"support_repeat_pay": 1,
|
||||
"support_cancel": 0,
|
||||
"counter_param": fmt.Sprintf(`{"pay_mode":"%s"}`, payMode),
|
||||
"order_info": sanitizeText(req.Body, 128),
|
||||
}
|
||||
if payMode != "" {
|
||||
reqData["counter_param"] = fmt.Sprintf(`{"pay_mode":"%s"}`, payMode)
|
||||
}
|
||||
if c.cfg.TermNo != "" {
|
||||
reqData["term_no"] = c.cfg.TermNo
|
||||
}
|
||||
@@ -710,6 +712,15 @@ func payModeFromPayWay(payWay string) string {
|
||||
}
|
||||
}
|
||||
|
||||
func normalizeCounterPayMode(value string) string {
|
||||
switch strings.ToUpper(strings.TrimSpace(value)) {
|
||||
case "", "AUTO", "ALL", "NONE", "UNLIMITED":
|
||||
return ""
|
||||
default:
|
||||
return strings.ToUpper(strings.TrimSpace(value))
|
||||
}
|
||||
}
|
||||
|
||||
func sanitizeText(value string, maxRunes int) string {
|
||||
value = strings.TrimSpace(value)
|
||||
if value == "" || maxRunes <= 0 {
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
package lakala
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"encoding/json"
|
||||
"encoding/pem"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
@@ -70,6 +74,22 @@ func TestParsePayloadNormalizesAliases(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreatePaymentOmitsCounterParamWhenPayModeBlank(t *testing.T) {
|
||||
body := captureCreatePaymentBody(t, "")
|
||||
reqData := body["req_data"].(map[string]any)
|
||||
if _, ok := reqData["counter_param"]; ok {
|
||||
t.Fatalf("counter_param exists when pay_mode is blank: %#v", reqData["counter_param"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreatePaymentSetsCounterParamWhenPayModeConfigured(t *testing.T) {
|
||||
body := captureCreatePaymentBody(t, "WECHAT")
|
||||
reqData := body["req_data"].(map[string]any)
|
||||
if reqData["counter_param"] != `{"pay_mode":"WECHAT"}` {
|
||||
t.Fatalf("counter_param = %#v, want WECHAT", reqData["counter_param"])
|
||||
}
|
||||
}
|
||||
|
||||
func testKeyPairPEM(t *testing.T, key *rsa.PrivateKey) (string, string) {
|
||||
t.Helper()
|
||||
privateDER := x509.MarshalPKCS1PrivateKey(key)
|
||||
@@ -88,3 +108,44 @@ func testKeyPairPEM(t *testing.T, key *rsa.PrivateKey) (string, string) {
|
||||
}))
|
||||
return privatePEM, certPEM
|
||||
}
|
||||
|
||||
func captureCreatePaymentBody(t *testing.T, payMode string) map[string]any {
|
||||
t.Helper()
|
||||
var captured map[string]any
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Path != endpointCounterCreate {
|
||||
t.Fatalf("path = %s, want %s", r.URL.Path, endpointCounterCreate)
|
||||
}
|
||||
if err := json.NewDecoder(r.Body).Decode(&captured); err != nil {
|
||||
t.Fatalf("decode request: %v", err)
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_, _ = w.Write([]byte(`{"resp_code":"0","result_code":"0","pay_order_no":"LK1"}`))
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
key, err := rsa.GenerateKey(rand.Reader, 2048)
|
||||
if err != nil {
|
||||
t.Fatalf("generate key: %v", err)
|
||||
}
|
||||
privatePEM, certPEM := testKeyPairPEM(t, key)
|
||||
client := NewClient(Config{
|
||||
GatewayURL: server.URL,
|
||||
AppID: "app-1",
|
||||
SerialNo: "serial-1",
|
||||
MerchantID: "merchant-1",
|
||||
PrivateKey: privatePEM,
|
||||
NotifyCert: certPEM,
|
||||
PayMode: payMode,
|
||||
})
|
||||
_, err = client.CreatePayment(context.Background(), CreatePaymentRequest{
|
||||
ThirdOrderID: "ORDER1",
|
||||
AmountCent: 100,
|
||||
NotifyURL: "https://example.com/notify",
|
||||
Body: "测试订单",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("CreatePayment error = %v", err)
|
||||
}
|
||||
return captured
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ function defaultExtraConfig(provider: string) {
|
||||
serial_no: '',
|
||||
term_no: '',
|
||||
lakala_cert: '',
|
||||
pay_mode: 'ALIPAY',
|
||||
pay_mode: 'AUTO',
|
||||
order_expire_minutes: 15,
|
||||
}
|
||||
}
|
||||
@@ -93,6 +93,17 @@ const extraConfig = computed<Record<string, any>>(() => {
|
||||
return formData.value.extra_config
|
||||
})
|
||||
|
||||
function normalizeExtraConfig(provider: string, extraConfig?: Record<string, any> | null) {
|
||||
const extra = {
|
||||
...defaultExtraConfig(provider),
|
||||
...(extraConfig || {}),
|
||||
}
|
||||
if (provider === 'lakala' && !extra.pay_mode) {
|
||||
extra.pay_mode = 'AUTO'
|
||||
}
|
||||
return extra
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(val) => {
|
||||
@@ -107,7 +118,7 @@ watch(
|
||||
pay_way: props.config.pay_way,
|
||||
jspay_flag: props.config.jspay_flag,
|
||||
sign_type: props.config.sign_type,
|
||||
extra_config: props.config.extra_config || defaultExtraConfig(props.config.provider),
|
||||
extra_config: normalizeExtraConfig(props.config.provider, props.config.extra_config),
|
||||
is_default: props.config.is_default,
|
||||
status: props.config.status,
|
||||
environment: props.config.environment,
|
||||
@@ -313,6 +324,7 @@ function handleClose() {
|
||||
|
||||
<el-form-item v-if="isLakala" label="拉卡拉模式">
|
||||
<el-select v-model="extraConfig.pay_mode" :disabled="isReadonly">
|
||||
<el-option label="不限制,由收银台选择" value="AUTO" />
|
||||
<el-option label="支付宝" value="ALIPAY" />
|
||||
<el-option label="微信" value="WECHAT" />
|
||||
<el-option label="银联" value="UQRCODEPAY" />
|
||||
|
||||
Reference in New Issue
Block a user