feat(payment): 接入扫呗普通支付2.0

This commit is contained in:
yml
2026-11-11 15:57:30 +08:00
parent 58d9f50bac
commit d403ffc734
30 changed files with 1337 additions and 111 deletions
@@ -25,6 +25,7 @@ var (
ErrSerialNoRequired = errors.New("extra_config.serial_no is required for lakala provider")
ErrTermNoRequired = errors.New("extra_config.term_no is required for lakala provider")
ErrSecretIDRequired = errors.New("extra_config.secret_id is required for shuncheng provider")
ErrTerminalIDRequired = errors.New("extra_config.terminal_id is required for saobei provider")
)
// DTO 数据传输对象
@@ -59,7 +60,7 @@ type ConfigDTO struct {
// CreateRequest 创建支付配置请求
type CreateRequest struct {
Name string `json:"name" binding:"required"`
Provider string `json:"provider" binding:"required,oneof=leshua lakala shuncheng mock"`
Provider string `json:"provider" binding:"required,oneof=leshua lakala shuncheng saobei mock"`
MerchantID string `json:"merchant_id" binding:"required"`
GatewayURL string `json:"gateway_url"`
SignKey string `json:"sign_key"`
@@ -148,7 +148,7 @@ func (h *Handler) ImportBackup(c *gin.Context) {
err == ErrNameRequired || err == ErrMerchantIDRequired || err == ErrGatewayURLRequired ||
err == ErrSignKeyRequired || err == ErrNotifyKeyRequired || err == ErrNotifyURLRequired ||
err == ErrInvalidSignType || err == ErrInvalidStatus || err == ErrInvalidPayWay || err == ErrAppIDRequired ||
err == ErrSerialNoRequired || err == ErrTermNoRequired {
err == ErrSerialNoRequired || err == ErrTermNoRequired || err == ErrTerminalIDRequired {
response.BadRequest(c, err.Error())
return
}
@@ -189,7 +189,7 @@ func (h *Handler) Create(c *gin.Context) {
if err == ErrNameRequired || err == ErrMerchantIDRequired || err == ErrGatewayURLRequired ||
err == ErrSignKeyRequired || err == ErrNotifyKeyRequired || err == ErrInvalidProvider ||
err == ErrNotifyURLRequired || err == ErrInvalidSignType || err == ErrInvalidPayWay || err == ErrAppIDRequired ||
err == ErrInvalidStatus || err == ErrSerialNoRequired || err == ErrTermNoRequired {
err == ErrInvalidStatus || err == ErrSerialNoRequired || err == ErrTermNoRequired || err == ErrTerminalIDRequired {
response.BadRequest(c, err.Error())
return
}
@@ -79,12 +79,26 @@ func (r *Repository) validateCreateRequest(req CreateRequest) error {
return ErrSecretIDRequired
}
}
if req.Provider == "saobei" {
if req.GatewayURL == "" {
return ErrGatewayURLRequired
}
if req.SignKey == "" {
return ErrSignKeyRequired
}
if req.NotifyURL == "" {
return ErrNotifyURLRequired
}
if extraString(req.ExtraConfig, "terminal_id") == "" {
return ErrTerminalIDRequired
}
}
return nil
}
func isValidProvider(value string) bool {
return value == "leshua" || value == "lakala" || value == "shuncheng" || value == "mock"
return value == "leshua" || value == "lakala" || value == "shuncheng" || value == "saobei" || value == "mock"
}
func isValidSignType(value string) bool {
@@ -0,0 +1,28 @@
package paymentconfig
import (
"errors"
"testing"
)
func TestValidateCreateRequestSaobeiRequiresTerminalID(t *testing.T) {
repo := &Repository{}
req := CreateRequest{
Name: "扫呗测试",
Provider: "saobei",
MerchantID: "839305812000286",
GatewayURL: "https://pay.example",
SignKey: "access-token",
NotifyURL: "https://example.com/api/payments/saobei/notify",
ExtraConfig: map[string]any{
"terminal_id": "",
},
}
if err := repo.validateCreateRequest(req); !errors.Is(err, ErrTerminalIDRequired) {
t.Fatalf("validateCreateRequest() error = %v, want %v", err, ErrTerminalIDRequired)
}
req.ExtraConfig["terminal_id"] = "30616969"
if err := repo.validateCreateRequest(req); err != nil {
t.Fatalf("validateCreateRequest() error = %v, want nil", err)
}
}