优化结构
This commit is contained in:
@@ -19,6 +19,22 @@ func paymentDefinition(provider, name, description string, defaults map[string]a
|
||||
common := []IntegrationConfigField{
|
||||
integrationField("notify_url", "支付回调地址", false, false, "url"),
|
||||
integrationField("return_url", "同步跳转地址", false, false, "url"),
|
||||
integrationField("test_amount", "测试金额(最小货币单位)", false, false, "number"),
|
||||
integrationField("test_currency", "测试币种", false, false, "text"),
|
||||
integrationField("test_extra", "测试下单扩展参数(JSON)", false, false, "textarea"),
|
||||
integrationField("test_mode", "允许执行渠道测试", false, false, "switch"),
|
||||
}
|
||||
if _, exists := defaults["test_amount"]; !exists {
|
||||
defaults["test_amount"] = 1
|
||||
}
|
||||
if _, exists := defaults["test_currency"]; !exists {
|
||||
defaults["test_currency"] = "CNY"
|
||||
}
|
||||
if _, exists := defaults["test_extra"]; !exists {
|
||||
defaults["test_extra"] = "{}"
|
||||
}
|
||||
if _, exists := defaults["test_mode"]; !exists {
|
||||
defaults["test_mode"] = false
|
||||
}
|
||||
fields = append(fields, common...)
|
||||
for _, field := range fields {
|
||||
@@ -85,8 +101,8 @@ var integrationDefinitions = map[string][]IntegrationConfigDefinition{
|
||||
integrationField("app_id", "应用 ID", true, false, "text"), integrationField("merchant_id", "商户号", true, false, "text"), integrationField("mch_key", "API 密钥", true, true, "password"), integrationSelect("sign_type", "签名算法", false, "MD5", "HMAC-SHA256"), integrationSelect("trade_type", "默认交易类型", false, "JSAPI", "APP", "NATIVE", "MWEB", "MICROPAY"), integrationField("client_cert", "商户证书", false, true, "textarea"), integrationField("client_key", "证书私钥", false, true, "textarea")),
|
||||
paymentDefinition(PaymentWechatV3, "微信支付 V3", "微信支付 API v3", map[string]any{"app_id": "", "merchant_id": "", "serial_no": "", "private_key": "", "api_v3_key": "", "platform_cert": "", "platform_serial_no": "", "trade_type": "jsapi"},
|
||||
integrationField("app_id", "应用 ID", true, false, "text"), integrationField("merchant_id", "商户号", true, false, "text"), integrationField("serial_no", "商户证书序列号", true, false, "text"), integrationField("private_key", "商户私钥", true, true, "textarea"), integrationField("api_v3_key", "API v3 密钥", true, true, "password"), integrationField("platform_cert", "平台证书", true, true, "textarea"), integrationField("platform_serial_no", "平台证书序列号", false, false, "text"), integrationSelect("trade_type", "默认交易类型", false, "jsapi", "app", "native", "h5", "codepay")),
|
||||
paymentDefinition(PaymentApple, "Apple IAP", "Apple App Store Server API", map[string]any{"issuer_id": "", "key_id": "", "bundle_id": "", "private_key": "", "price_divisor": 10, "environment": "production"},
|
||||
integrationField("issuer_id", "Issuer ID", true, false, "text"), integrationField("key_id", "Key ID", true, false, "text"), integrationField("bundle_id", "Bundle ID", true, false, "text"), integrationField("private_key", "P8 私钥", true, true, "textarea"), integrationField("price_divisor", "价格除数", false, false, "number"), integrationSelect("environment", "环境", false, "production", "sandbox")),
|
||||
paymentDefinition(PaymentApple, "Apple IAP", "Apple App Store Server API", map[string]any{"issuer_id": "", "key_id": "", "bundle_id": "", "private_key": "", "price_divisor": 10, "environment": "production", "test_product_id": "", "test_transaction_id": ""},
|
||||
integrationField("issuer_id", "Issuer ID", true, false, "text"), integrationField("key_id", "Key ID", true, false, "text"), integrationField("bundle_id", "Bundle ID", true, false, "text"), integrationField("private_key", "P8 私钥", true, true, "textarea"), integrationField("price_divisor", "价格除数", false, false, "number"), integrationSelect("environment", "环境", false, "production", "sandbox"), integrationField("test_product_id", "测试商品 ID", false, false, "text"), integrationField("test_transaction_id", "沙箱交易 ID", false, false, "text")),
|
||||
paymentDefinition(PaymentDouyin, "抖音支付", "抖音开放平台支付", map[string]any{"app_id": "", "merchant_id": "", "serial_no": "", "api_key": "", "private_key": "", "platform_cert": "", "platform_serial_no": "", "trade_type": "jsapi", "environment": "production"},
|
||||
integrationField("app_id", "应用 ID", true, false, "text"), integrationField("merchant_id", "商户号", true, false, "text"), integrationField("serial_no", "商户证书序列号", true, false, "text"), integrationField("api_key", "API 密钥", true, true, "password"), integrationField("private_key", "商户私钥", true, true, "textarea"), integrationField("platform_cert", "平台证书", true, true, "textarea"), integrationField("platform_serial_no", "平台证书序列号", false, false, "text"), integrationSelect("trade_type", "默认交易类型", false, "app", "jsapi", "h5", "native"), integrationSelect("environment", "环境", false, "production")),
|
||||
paymentDefinition(PaymentQQ, "QQ 钱包", "QQ 钱包支付", map[string]any{"mch_id": "", "api_key": "", "sign_type": "MD5", "trade_type": "NATIVE", "cert_file": "", "key_file": "", "environment": "production"},
|
||||
@@ -95,7 +111,7 @@ var integrationDefinitions = map[string][]IntegrationConfigDefinition{
|
||||
integrationField("cus_id", "商户号", true, false, "text"), integrationField("app_id", "应用 ID", true, false, "text"), integrationField("private_key", "商户私钥", true, true, "textarea"), integrationField("public_key", "平台公钥", true, true, "textarea"), integrationField("org_id", "机构号", false, false, "text"), integrationField("pay_type", "支付类型", false, false, "text"), integrationSelect("query_order_type", "查单标识", false, "reqsn", "trxid"), integrationField("currency", "币种", false, false, "text"), integrationSelect("environment", "环境", false, "production", "sandbox")),
|
||||
paymentDefinition(PaymentLakala, "拉卡拉", "拉卡拉聚合支付", map[string]any{"partner_code": "", "credential_code": "", "channel": "Wechat", "method": "jsapi", "currency": "CNY", "environment": "production"},
|
||||
integrationField("partner_code", "合作方编号", true, false, "text"), integrationField("credential_code", "凭证码", true, true, "password"), integrationSelect("channel", "支付渠道", false, "Wechat", "Alipay", "UnionPay"), integrationSelect("method", "默认支付方式", false, "jsapi", "h5", "mini", "native", "qrcode", "native_jsapi", "sdk", "web", "retail", "retail_qrcode"), integrationField("currency", "币种", false, false, "text"), integrationSelect("environment", "环境", false, "production")),
|
||||
paymentDefinition(PaymentPayPal, "PayPal", "PayPal Checkout", map[string]any{"client_id": "", "client_secret": "", "webhook_id": "", "environment": "sandbox", "return_url": "", "cancel_url": "", "auto_capture": true},
|
||||
paymentDefinition(PaymentPayPal, "PayPal", "PayPal Checkout", map[string]any{"client_id": "", "client_secret": "", "webhook_id": "", "environment": "sandbox", "return_url": "", "cancel_url": "", "auto_capture": true, "test_currency": "USD"},
|
||||
integrationField("client_id", "Client ID", true, false, "text"), integrationField("client_secret", "Client Secret", true, true, "password"), integrationField("webhook_id", "Webhook ID", true, false, "text"), integrationSelect("environment", "环境", false, "sandbox", "production"), integrationField("cancel_url", "取消跳转地址", false, false, "url"), integrationField("auto_capture", "自动捕获", false, false, "switch")),
|
||||
paymentDefinition(PaymentSaobei, "扫呗", "扫呗聚合支付", map[string]any{"inst_no": "", "key": "", "merchant_no": "", "terminal_id": "", "access_token": "", "pay_type": "010", "currency": "CNY", "environment": "production"},
|
||||
integrationField("inst_no", "机构号", true, false, "text"), integrationField("key", "机构密钥", true, true, "password"), integrationField("merchant_no", "商户号", true, false, "text"), integrationField("terminal_id", "终端号", true, false, "text"), integrationField("access_token", "访问令牌", true, true, "password"), integrationField("pay_type", "支付类型", false, false, "text"), integrationField("currency", "币种", false, false, "text"), integrationSelect("environment", "环境", false, "production", "sandbox")),
|
||||
|
||||
@@ -182,6 +182,27 @@ type PaymentResult struct {
|
||||
FailureAck PaymentCallbackAck `json:"-"`
|
||||
}
|
||||
|
||||
// PaymentTestStage is one step of a provider connectivity test. A skipped
|
||||
// query/refund is reported explicitly because a prepay flow cannot be marked
|
||||
// paid without a sandbox payer interaction.
|
||||
type PaymentTestStage struct {
|
||||
Name string `json:"name"`
|
||||
Status string `json:"status"`
|
||||
Message string `json:"message,omitempty"`
|
||||
TradeNo string `json:"tradeNo,omitempty"`
|
||||
Duration int64 `json:"durationMs,omitempty"`
|
||||
}
|
||||
|
||||
type PaymentTestResult struct {
|
||||
Provider string `json:"provider"`
|
||||
TradeNo string `json:"tradeNo"`
|
||||
Passed bool `json:"passed"`
|
||||
FullFlow bool `json:"fullFlow"`
|
||||
Mode string `json:"mode,omitempty"`
|
||||
Stages []PaymentTestStage `json:"stages"`
|
||||
Result *PaymentResult `json:"result,omitempty"`
|
||||
}
|
||||
|
||||
type PaymentCallbackAck = paymentutil.CallbackAck
|
||||
type PaymentCallbackError = paymentutil.CallbackError
|
||||
|
||||
@@ -207,6 +228,10 @@ type PaymentRepo interface {
|
||||
HandleCallback(context.Context, *PaymentCallback) (*PaymentResult, error)
|
||||
}
|
||||
|
||||
type PaymentProviderTester interface {
|
||||
TestProvider(context.Context, string) (*PaymentTestResult, error)
|
||||
}
|
||||
|
||||
type PaymentHooks interface {
|
||||
BeforeCreate(context.Context, *PaymentRequest) error
|
||||
}
|
||||
@@ -477,6 +502,21 @@ func (uc *PaymentUsecase) Refund(ctx context.Context, provider, tradeNo string,
|
||||
return uc.refundWithOrder(ctx, provider, tradeNo, amount)
|
||||
}
|
||||
|
||||
// TestProvider exercises the configured provider without requiring a business
|
||||
// module or a real customer order. Provider adapters use their configured
|
||||
// sandbox/test endpoint when one is selected in integration settings.
|
||||
func (uc *PaymentUsecase) TestProvider(ctx context.Context, provider string) (*PaymentTestResult, error) {
|
||||
provider = strings.TrimSpace(provider)
|
||||
if !supportedPaymentProvider(provider) {
|
||||
return nil, errors.New("不支持的支付渠道")
|
||||
}
|
||||
tester, ok := uc.repo.(PaymentProviderTester)
|
||||
if !ok {
|
||||
return nil, errors.New("支付渠道仓储未接入")
|
||||
}
|
||||
return tester.TestProvider(ctx, provider)
|
||||
}
|
||||
|
||||
// Fulfill retries delivery for an already-paid order. It is intentionally
|
||||
// idempotent: the repository lease prevents concurrent attempts and a
|
||||
// succeeded order is returned as a duplicate without invoking the handler.
|
||||
|
||||
Reference in New Issue
Block a user