feat(payment): 接入扫呗普通支付2.0
This commit is contained in:
@@ -9,13 +9,14 @@ import (
|
||||
|
||||
"hfb_jysh/backend/internal/integrations/payment/lakala"
|
||||
"hfb_jysh/backend/internal/integrations/payment/leshua"
|
||||
"hfb_jysh/backend/internal/integrations/payment/saobei"
|
||||
"hfb_jysh/backend/internal/integrations/payment/shuncheng"
|
||||
"hfb_jysh/backend/internal/modules/paymentconfig"
|
||||
)
|
||||
|
||||
type channelClient interface {
|
||||
CreatePayment(ctx context.Context, req channelCreatePaymentRequest) (*channelCreatePaymentResponse, error)
|
||||
QueryPayment(ctx context.Context, thirdOrderID string, providerOrderID string) (*channelQueryPaymentResponse, error)
|
||||
QueryPayment(ctx context.Context, req channelQueryPaymentRequest) (*channelQueryPaymentResponse, error)
|
||||
CreateRefund(ctx context.Context, req channelCreateRefundRequest) (*channelCreateRefundResponse, error)
|
||||
QueryRefund(ctx context.Context, req channelQueryRefundRequest) (*channelQueryRefundResponse, error)
|
||||
VerifyNotify(params map[string]string, rawPayload string, contentType string, authorization string) (channelVerifyNotifyResult, error)
|
||||
@@ -47,6 +48,12 @@ type channelCreatePaymentResponse struct {
|
||||
Raw map[string]string
|
||||
}
|
||||
|
||||
type channelQueryPaymentRequest struct {
|
||||
ThirdOrderID string
|
||||
TraceTime string
|
||||
ProviderOrderID string
|
||||
}
|
||||
|
||||
type channelQueryPaymentResponse struct {
|
||||
OK bool
|
||||
ErrorMessage string
|
||||
@@ -59,14 +66,15 @@ type channelQueryPaymentResponse struct {
|
||||
}
|
||||
|
||||
type channelCreateRefundRequest struct {
|
||||
ThirdOrderID string
|
||||
ProviderOrderID string
|
||||
MerchantRefundID string
|
||||
RefundAmountCent int64
|
||||
NotifyURL string
|
||||
Attach string
|
||||
Remark string
|
||||
ClientIP string
|
||||
ThirdOrderID string
|
||||
OriginalTraceTime string
|
||||
ProviderOrderID string
|
||||
MerchantRefundID string
|
||||
RefundAmountCent int64
|
||||
NotifyURL string
|
||||
Attach string
|
||||
Remark string
|
||||
ClientIP string
|
||||
}
|
||||
|
||||
type channelCreateRefundResponse struct {
|
||||
@@ -80,10 +88,11 @@ type channelCreateRefundResponse struct {
|
||||
}
|
||||
|
||||
type channelQueryRefundRequest struct {
|
||||
ThirdOrderID string
|
||||
ProviderOrderID string
|
||||
MerchantRefundID string
|
||||
ProviderRefundID string
|
||||
ThirdOrderID string
|
||||
ProviderOrderID string
|
||||
MerchantRefundID string
|
||||
MerchantRefundTime string
|
||||
ProviderRefundID string
|
||||
}
|
||||
|
||||
type channelQueryRefundResponse struct {
|
||||
@@ -144,8 +153,8 @@ func (c leshuaChannel) CreatePayment(ctx context.Context, req channelCreatePayme
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c leshuaChannel) QueryPayment(ctx context.Context, thirdOrderID string, providerOrderID string) (*channelQueryPaymentResponse, error) {
|
||||
resp, err := c.client.QueryPayment(ctx, thirdOrderID, providerOrderID)
|
||||
func (c leshuaChannel) QueryPayment(ctx context.Context, req channelQueryPaymentRequest) (*channelQueryPaymentResponse, error) {
|
||||
resp, err := c.client.QueryPayment(ctx, req.ThirdOrderID, req.ProviderOrderID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -264,8 +273,8 @@ func (c lakalaChannel) CreatePayment(ctx context.Context, req channelCreatePayme
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c lakalaChannel) QueryPayment(ctx context.Context, thirdOrderID string, providerOrderID string) (*channelQueryPaymentResponse, error) {
|
||||
resp, err := c.client.QueryPayment(ctx, thirdOrderID, providerOrderID)
|
||||
func (c lakalaChannel) QueryPayment(ctx context.Context, req channelQueryPaymentRequest) (*channelQueryPaymentResponse, error) {
|
||||
resp, err := c.client.QueryPayment(ctx, req.ThirdOrderID, req.ProviderOrderID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -392,8 +401,8 @@ func (c shunchengChannel) CreatePayment(ctx context.Context, req channelCreatePa
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c shunchengChannel) QueryPayment(ctx context.Context, thirdOrderID string, providerOrderID string) (*channelQueryPaymentResponse, error) {
|
||||
resp, err := c.client.QueryPayment(ctx, thirdOrderID, providerOrderID)
|
||||
func (c shunchengChannel) QueryPayment(ctx context.Context, req channelQueryPaymentRequest) (*channelQueryPaymentResponse, error) {
|
||||
resp, err := c.client.QueryPayment(ctx, req.ThirdOrderID, req.ProviderOrderID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -471,6 +480,117 @@ func (c shunchengChannel) VerifyNotify(params map[string]string, rawPayload stri
|
||||
return result, nil
|
||||
}
|
||||
|
||||
type saobeiChannel struct {
|
||||
client *saobei.Client
|
||||
}
|
||||
|
||||
func newSaobeiChannel(cfg saobei.Config) channelClient {
|
||||
return saobeiChannel{client: saobei.NewClient(cfg)}
|
||||
}
|
||||
|
||||
func (c saobeiChannel) CreatePayment(ctx context.Context, req channelCreatePaymentRequest) (*channelCreatePaymentResponse, error) {
|
||||
resp, err := c.client.CreatePayment(ctx, saobei.CreatePaymentRequest{
|
||||
ThirdOrderID: req.ThirdOrderID,
|
||||
AmountCent: req.AmountCent,
|
||||
NotifyURL: req.NotifyURL,
|
||||
Body: req.Body,
|
||||
Attach: req.Attach,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &channelCreatePaymentResponse{
|
||||
OK: resp.OK,
|
||||
ErrorMessage: resp.ErrorMessage,
|
||||
ProviderOrderID: resp.ProviderOrderID,
|
||||
Status: resp.Status,
|
||||
TDCode: resp.QRURL,
|
||||
JSPayURL: resp.QRURL,
|
||||
RawRequest: resp.RawRequest,
|
||||
Raw: resp.Raw,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c saobeiChannel) QueryPayment(ctx context.Context, req channelQueryPaymentRequest) (*channelQueryPaymentResponse, error) {
|
||||
resp, err := c.client.QueryPayment(ctx, saobei.QueryPaymentRequest{
|
||||
ThirdOrderID: req.ThirdOrderID,
|
||||
TerminalTime: req.TraceTime,
|
||||
ProviderOrderID: req.ProviderOrderID,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &channelQueryPaymentResponse{
|
||||
OK: resp.OK,
|
||||
ErrorMessage: resp.ErrorMessage,
|
||||
ProviderOrderID: resp.ProviderOrderID,
|
||||
Status: resp.Status,
|
||||
Amount: resp.Amount,
|
||||
PayTime: resp.PayTime,
|
||||
Raw: resp.Raw,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c saobeiChannel) CreateRefund(ctx context.Context, req channelCreateRefundRequest) (*channelCreateRefundResponse, error) {
|
||||
resp, err := c.client.CreateRefund(ctx, saobei.CreateRefundRequest{
|
||||
ThirdOrderID: req.ThirdOrderID,
|
||||
TerminalTime: req.OriginalTraceTime,
|
||||
ProviderOrderID: req.ProviderOrderID,
|
||||
MerchantRefundID: req.MerchantRefundID,
|
||||
RefundAmountCent: req.RefundAmountCent,
|
||||
Attach: req.Attach,
|
||||
Remark: req.Remark,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &channelCreateRefundResponse{
|
||||
OK: resp.OK,
|
||||
ErrorMessage: resp.ErrorMessage,
|
||||
ProviderRefundID: resp.ProviderRefundID,
|
||||
Status: resp.Status,
|
||||
RefundAmount: resp.RefundAmount,
|
||||
RawRequest: resp.RawRequest,
|
||||
Raw: resp.Raw,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c saobeiChannel) QueryRefund(ctx context.Context, req channelQueryRefundRequest) (*channelQueryRefundResponse, error) {
|
||||
resp, err := c.client.QueryRefund(ctx, saobei.QueryRefundRequest{
|
||||
MerchantRefundID: req.MerchantRefundID,
|
||||
MerchantRefundTime: req.MerchantRefundTime,
|
||||
ProviderRefundID: req.ProviderRefundID,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &channelQueryRefundResponse{
|
||||
OK: resp.OK,
|
||||
ErrorMessage: resp.ErrorMessage,
|
||||
ProviderRefundID: resp.ProviderRefundID,
|
||||
Status: resp.Status,
|
||||
RefundAmount: resp.RefundAmount,
|
||||
RefundTime: resp.RefundTime,
|
||||
Raw: resp.Raw,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c saobeiChannel) VerifyNotify(params map[string]string, rawPayload string, contentType string, authorization string) (channelVerifyNotifyResult, error) {
|
||||
verify := c.client.VerifyNotify(params)
|
||||
result := channelVerifyNotifyResult{
|
||||
OK: verify.OK,
|
||||
MatchedKey: verify.MatchedKey,
|
||||
Got: verify.Got,
|
||||
Expected: verify.Expected,
|
||||
BaseString: verify.BaseString,
|
||||
ParamKeys: verify.ParamKeys,
|
||||
}
|
||||
if !result.OK {
|
||||
return result, ErrPaymentVerifyFailed
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func buildChannelClient(dto *paymentconfig.ConfigDTO) (channelClient, error) {
|
||||
switch strings.ToLower(strings.TrimSpace(dto.Provider)) {
|
||||
case "leshua":
|
||||
@@ -518,6 +638,16 @@ func buildChannelClient(dto *paymentconfig.ConfigDTO) (channelClient, error) {
|
||||
RefundType: extraString(dto.ExtraConfig, "refund_type"),
|
||||
TokenMargin: time.Duration(extraInt(dto.ExtraConfig, "token_refresh_margin_seconds")) * time.Second,
|
||||
})), nil
|
||||
case "saobei":
|
||||
return withChannelBreaker("saobei", newSaobeiChannel(saobei.Config{
|
||||
GatewayURL: dto.GatewayURL,
|
||||
MerchantID: dto.MerchantID,
|
||||
TerminalID: extraString(dto.ExtraConfig, "terminal_id"),
|
||||
AccessToken: dto.SignKey,
|
||||
NotifyURL: dto.NotifyURL,
|
||||
DeviceNo: extraString(dto.ExtraConfig, "device_no"),
|
||||
ExpireSecond: extraInt(dto.ExtraConfig, "expire_seconds"),
|
||||
})), nil
|
||||
case "mock":
|
||||
return nil, nil
|
||||
default:
|
||||
|
||||
@@ -45,9 +45,9 @@ func (c breakerChannel) CreatePayment(ctx context.Context, req channelCreatePaym
|
||||
})
|
||||
}
|
||||
|
||||
func (c breakerChannel) QueryPayment(ctx context.Context, thirdOrderID string, providerOrderID string) (*channelQueryPaymentResponse, error) {
|
||||
func (c breakerChannel) QueryPayment(ctx context.Context, req channelQueryPaymentRequest) (*channelQueryPaymentResponse, error) {
|
||||
return c.queryPayment.Execute(func() (*channelQueryPaymentResponse, error) {
|
||||
return c.next.QueryPayment(ctx, thirdOrderID, providerOrderID)
|
||||
return c.next.QueryPayment(ctx, req)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -61,7 +61,11 @@ func (r *Repository) probeChannelPaid(ctx context.Context, payment *model.Paymen
|
||||
if runtimeConfig.isMockMode() || runtimeConfig.Channel == nil {
|
||||
return nil
|
||||
}
|
||||
resp, err := runtimeConfig.Channel.QueryPayment(ctx, payment.ThirdOrderID, payment.ProviderOrderID)
|
||||
resp, err := runtimeConfig.Channel.QueryPayment(ctx, channelQueryPaymentRequest{
|
||||
ThirdOrderID: payment.ThirdOrderID,
|
||||
TraceTime: paymentTraceTime(payment.RawRequest),
|
||||
ProviderOrderID: payment.ProviderOrderID,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
|
||||
"hfb_jysh/backend/internal/integrations/payment/lakala"
|
||||
"hfb_jysh/backend/internal/integrations/payment/leshua"
|
||||
"hfb_jysh/backend/internal/integrations/payment/saobei"
|
||||
"hfb_jysh/backend/internal/integrations/payment/shuncheng"
|
||||
"hfb_jysh/backend/internal/middleware"
|
||||
"hfb_jysh/backend/internal/modules/order"
|
||||
@@ -263,6 +264,29 @@ func (h *Handler) ShunchengNotify(c *gin.Context) {
|
||||
c.String(http.StatusOK, result.Message)
|
||||
}
|
||||
|
||||
func (h *Handler) SaobeiNotify(c *gin.Context) {
|
||||
body, err := io.ReadAll(io.LimitReader(c.Request.Body, 1<<20))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{"return_code": "02", "return_msg": "读取失败"})
|
||||
return
|
||||
}
|
||||
params, err := saobei.ParsePayload(body)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{"return_code": "02", "return_msg": "解析失败"})
|
||||
return
|
||||
}
|
||||
rawPayload := string(body)
|
||||
contentType := c.GetHeader("Content-Type")
|
||||
result, err := h.service.HandleNotify(c.Request.Context(), "saobei", params, rawPayload, contentType, "")
|
||||
if err != nil || result == nil || !result.OK {
|
||||
h.log().Warn("扫呗支付回调处理失败", notifyLogFields(c.Request.Context(), "saobei", params, contentType, len(body), zap.Error(err))...)
|
||||
c.JSON(http.StatusOK, gin.H{"return_code": "02", "return_msg": "失败"})
|
||||
return
|
||||
}
|
||||
h.log().Info("扫呗支付回调处理完成", notifyLogFields(c.Request.Context(), "saobei", params, contentType, len(body))...)
|
||||
c.JSON(http.StatusOK, gin.H{"return_code": "01", "return_msg": "success"})
|
||||
}
|
||||
|
||||
func currentUserID(c *gin.Context) (uint64, bool) {
|
||||
value, ok := c.Get(middleware.ContextUserID)
|
||||
if !ok {
|
||||
|
||||
@@ -229,7 +229,11 @@ func (r *Repository) QueryMohong(ctx context.Context, userID uint64, orderID uin
|
||||
if runtimeConfig.Channel == nil {
|
||||
return nil, ErrPaymentUnavailable
|
||||
}
|
||||
resp, err := runtimeConfig.Channel.QueryPayment(ctx, payment.ThirdOrderID, payment.ProviderOrderID)
|
||||
resp, err := runtimeConfig.Channel.QueryPayment(ctx, channelQueryPaymentRequest{
|
||||
ThirdOrderID: payment.ThirdOrderID,
|
||||
TraceTime: paymentTraceTime(payment.RawRequest),
|
||||
ProviderOrderID: payment.ProviderOrderID,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"hfb_jysh/backend/internal/integrations/payment/saobei"
|
||||
"hfb_jysh/backend/internal/model"
|
||||
|
||||
"go.uber.org/zap"
|
||||
@@ -22,7 +23,11 @@ func (r *Repository) HandleNotify(ctx context.Context, provider string, params m
|
||||
return r.HandleRefundNotify(ctx, provider, params, rawPayload, contentType, authorization)
|
||||
}
|
||||
|
||||
payment, err := r.findPaymentForNotify(ctx, params)
|
||||
lookupParams := params
|
||||
if provider == "saobei" {
|
||||
lookupParams = saobei.CanonicalizePayload(params)
|
||||
}
|
||||
payment, err := r.findPaymentForNotify(ctx, lookupParams)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -35,7 +40,19 @@ func (r *Repository) HandleNotify(ctx context.Context, provider string, params m
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if amount := parseCent(params["amount"]); amount > 0 && amount != payment.AmountCent {
|
||||
processingParams := params
|
||||
if provider == "saobei" {
|
||||
processingParams = saobei.CanonicalizePayload(params)
|
||||
}
|
||||
if runtimeConfig.Provider == "saobei" {
|
||||
if merchantNo := processingParams["merchant_no"]; merchantNo == "" || merchantNo != payment.MerchantID {
|
||||
return nil, ErrPaymentVerifyFailed
|
||||
}
|
||||
if amount := parseCent(processingParams["amount"]); amount <= 0 || amount != payment.AmountCent {
|
||||
return nil, ErrPaymentVerifyFailed
|
||||
}
|
||||
}
|
||||
if amount := parseCent(processingParams["amount"]); amount > 0 && amount != payment.AmountCent {
|
||||
if err := r.recordNotifyDiagnostic(ctx, payment.ID, params, rawPayload, contentType, verify, "amount_mismatch"); err != nil {
|
||||
r.log().Warn("支付回调诊断保存失败", paymentLogFields(ctx, appendFields(
|
||||
paymentOrderFields(payment),
|
||||
@@ -49,9 +66,9 @@ func (r *Repository) HandleNotify(ctx context.Context, provider string, params m
|
||||
}
|
||||
return nil, ErrPaymentVerifyFailed
|
||||
}
|
||||
raw := withNotifyDiagnostic(params, rawPayload, contentType, verify, "verified")
|
||||
channelStatus := normalizeNotifyPaymentStatus(runtimeConfig.Provider, params["status"])
|
||||
if err := r.applyChannelStatus(ctx, payment, channelStatus, params["pay_time"], raw, channelSourceNotify); err != nil {
|
||||
raw := withNotifyDiagnostic(processingParams, rawPayload, contentType, verify, "verified")
|
||||
channelStatus := normalizeNotifyPaymentStatus(runtimeConfig.Provider, processingParams["status"])
|
||||
if err := r.applyChannelStatus(ctx, payment, channelStatus, processingParams["pay_time"], raw, channelSourceNotify); err != nil {
|
||||
// 入口处的 WARN 只有渠道参数,定位不到是哪个订单哪笔支付单,这里补齐上下文。
|
||||
r.log().Warn("支付回调入账失败", paymentLogFields(ctx, appendFields(
|
||||
paymentOrderFields(payment),
|
||||
@@ -182,10 +199,11 @@ func redactNotifyParams(params map[string]string) map[string]string {
|
||||
allowed := map[string]bool{
|
||||
"service": true, "merchant_id": true, "third_order_id": true,
|
||||
"provider_order_id": true, "leshua_order_id": true, "schc_order_id": true,
|
||||
"terminal_trace": true, "out_trade_no": true,
|
||||
"merchant_refund_id": true, "provider_refund_id": true,
|
||||
"leshua_refund_id": true, "schc_refund_id": true,
|
||||
"status": true, "amount": true, "refund_amount": true,
|
||||
"pay_time": true, "refund_time": true,
|
||||
"status": true, "amount": true, "total_fee": true, "refund_amount": true,
|
||||
"pay_time": true, "end_time": true, "refund_time": true,
|
||||
"code": true, "resp_code": true, "result_code": true, "error_code": true,
|
||||
}
|
||||
redacted := make(map[string]string, len(allowed))
|
||||
|
||||
@@ -102,6 +102,23 @@ func jsonString(value map[string]string) string {
|
||||
}
|
||||
return string(raw)
|
||||
}
|
||||
|
||||
func paymentTraceTime(raw datatypes.JSON) string {
|
||||
if len(raw) == 0 {
|
||||
return ""
|
||||
}
|
||||
var payload map[string]any
|
||||
if err := json.Unmarshal(raw, &payload); err != nil {
|
||||
return ""
|
||||
}
|
||||
for _, key := range []string{"terminal_time", "pay_time"} {
|
||||
if value, ok := payload[key].(string); ok && value != "" {
|
||||
return value
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func newPaymentNo() (string, error) {
|
||||
buf := make([]byte, 4)
|
||||
if _, err := rand.Read(buf); err != nil {
|
||||
|
||||
@@ -29,7 +29,11 @@ func (r *Repository) Query(ctx context.Context, userID uint64, orderID uint64) (
|
||||
if runtimeConfig.Channel == nil {
|
||||
return nil, ErrPaymentUnavailable
|
||||
}
|
||||
resp, err := runtimeConfig.Channel.QueryPayment(ctx, payment.ThirdOrderID, payment.ProviderOrderID)
|
||||
resp, err := runtimeConfig.Channel.QueryPayment(ctx, channelQueryPaymentRequest{
|
||||
ThirdOrderID: payment.ThirdOrderID,
|
||||
TraceTime: paymentTraceTime(payment.RawRequest),
|
||||
ProviderOrderID: payment.ProviderOrderID,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -86,13 +86,14 @@ func (r *Repository) StartRefund(ctx context.Context, orderID uint64, refundAmou
|
||||
return nil, ErrPaymentUnavailable
|
||||
}
|
||||
resp, err := runtimeConfig.Channel.CreateRefund(ctx, channelCreateRefundRequest{
|
||||
ThirdOrderID: originalPayment.ThirdOrderID,
|
||||
ProviderOrderID: refundOriginProviderOrderID(originalPayment),
|
||||
MerchantRefundID: refundOrder.ThirdOrderID,
|
||||
RefundAmountCent: refundAmountCent,
|
||||
NotifyURL: runtimeConfig.NotifyURL,
|
||||
Attach: originalPayment.OrderNo,
|
||||
Remark: remark,
|
||||
ThirdOrderID: originalPayment.ThirdOrderID,
|
||||
OriginalTraceTime: paymentTraceTime(originalPayment.RawRequest),
|
||||
ProviderOrderID: refundOriginProviderOrderID(originalPayment),
|
||||
MerchantRefundID: refundOrder.ThirdOrderID,
|
||||
RefundAmountCent: refundAmountCent,
|
||||
NotifyURL: runtimeConfig.NotifyURL,
|
||||
Attach: originalPayment.OrderNo,
|
||||
Remark: remark,
|
||||
})
|
||||
if err != nil {
|
||||
var rawRequest map[string]string
|
||||
@@ -380,10 +381,11 @@ func isRefundBizType(bizType string) bool {
|
||||
}
|
||||
func refundQueryRequest(payment model.PaymentOrder, originalPayment model.PaymentOrder) channelQueryRefundRequest {
|
||||
return channelQueryRefundRequest{
|
||||
ThirdOrderID: originalPayment.ThirdOrderID,
|
||||
ProviderOrderID: refundOriginProviderOrderID(originalPayment),
|
||||
MerchantRefundID: payment.ThirdOrderID,
|
||||
ProviderRefundID: payment.ProviderOrderID,
|
||||
ThirdOrderID: originalPayment.ThirdOrderID,
|
||||
ProviderOrderID: refundOriginProviderOrderID(originalPayment),
|
||||
MerchantRefundID: payment.ThirdOrderID,
|
||||
MerchantRefundTime: paymentTraceTime(payment.RawRequest),
|
||||
ProviderRefundID: payment.ProviderOrderID,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -73,13 +73,14 @@ func (r *Repository) StartMohongRefund(ctx context.Context, orderID uint64, refu
|
||||
return nil, ErrPaymentUnavailable
|
||||
}
|
||||
resp, err := runtimeConfig.Channel.CreateRefund(ctx, channelCreateRefundRequest{
|
||||
ThirdOrderID: originalPayment.ThirdOrderID,
|
||||
ProviderOrderID: refundOriginProviderOrderID(originalPayment),
|
||||
MerchantRefundID: refundOrder.ThirdOrderID,
|
||||
RefundAmountCent: refundOrder.AmountCent,
|
||||
NotifyURL: runtimeConfig.NotifyURL,
|
||||
Attach: originalPayment.OrderNo,
|
||||
Remark: remark,
|
||||
ThirdOrderID: originalPayment.ThirdOrderID,
|
||||
OriginalTraceTime: paymentTraceTime(originalPayment.RawRequest),
|
||||
ProviderOrderID: refundOriginProviderOrderID(originalPayment),
|
||||
MerchantRefundID: refundOrder.ThirdOrderID,
|
||||
RefundAmountCent: refundOrder.AmountCent,
|
||||
NotifyURL: runtimeConfig.NotifyURL,
|
||||
Attach: originalPayment.OrderNo,
|
||||
Remark: remark,
|
||||
})
|
||||
if err != nil {
|
||||
var rawRequest map[string]string
|
||||
|
||||
@@ -233,7 +233,7 @@ func (r *Repository) runtimeConfigForPayment(ctx context.Context, payment *model
|
||||
MerchantID: merchantID,
|
||||
}, nil
|
||||
}
|
||||
if provider != "leshua" && provider != "lakala" && provider != "shuncheng" {
|
||||
if provider != "leshua" && provider != "lakala" && provider != "shuncheng" && provider != "saobei" {
|
||||
return &runtimePaymentConfig{
|
||||
Provider: provider,
|
||||
MerchantID: merchantID,
|
||||
|
||||
Reference in New Issue
Block a user