修复 Context 改造后的编译问题

This commit is contained in:
yml2213
2026-06-10 09:43:49 +08:00
parent b377f8350b
commit 334436f381
13 changed files with 193 additions and 189 deletions
+8 -8
View File
@@ -37,7 +37,7 @@ func (h *Handler) Start(c *gin.Context) {
}
var req StartPaymentRequest
_ = c.ShouldBindJSON(&req)
item, err := h.service.Start(userID, orderID, req, c.ClientIP())
item, err := h.service.Start(c.Request.Context(), userID, orderID, req, c.ClientIP())
if err != nil {
writePaymentError(c, err)
return
@@ -55,7 +55,7 @@ func (h *Handler) Query(c *gin.Context) {
if !ok {
return
}
item, err := h.service.Query(userID, orderID)
item, err := h.service.Query(c.Request.Context(), userID, orderID)
if err != nil {
writePaymentError(c, err)
return
@@ -74,7 +74,7 @@ func (h *Handler) WalletRecharge(c *gin.Context) {
response.BadRequest(c, "充值金额不正确")
return
}
item, err := h.service.StartWalletRecharge(userID, req, c.ClientIP())
item, err := h.service.StartWalletRecharge(c.Request.Context(), userID, req, c.ClientIP())
if err != nil {
writePaymentError(c, err)
return
@@ -92,7 +92,7 @@ func (h *Handler) WalletRechargeQuery(c *gin.Context) {
if !ok {
return
}
item, err := h.service.QueryWalletRecharge(userID, paymentID)
item, err := h.service.QueryWalletRecharge(c.Request.Context(), userID, paymentID)
if err != nil {
writePaymentError(c, err)
return
@@ -105,7 +105,7 @@ func (h *Handler) QueryRefundStatus(c *gin.Context) {
if !ok {
return
}
item, err := h.service.QueryRefundStatus(orderID)
item, err := h.service.QueryRefundStatus(c.Request.Context(), orderID)
if err != nil {
writePaymentError(c, err)
return
@@ -118,7 +118,7 @@ func (h *Handler) AdminList(c *gin.Context) {
if !ok {
return
}
result, err := h.service.AdminList(query)
result, err := h.service.AdminList(c.Request.Context(), query)
if err != nil {
writePaymentError(c, err)
return
@@ -148,7 +148,7 @@ func (h *Handler) LeshuaNotify(c *gin.Context) {
contentType,
rawPayload,
)
result, err := h.service.HandleLeshuaNotify(params, rawPayload, contentType)
result, err := h.service.HandleLeshuaNotify(c.Request.Context(), params, rawPayload, contentType)
if err != nil || result == nil || !result.OK {
log.Printf("[payment] leshua notify failed third_order_id=%s err=%v", params["third_order_id"], err)
c.String(http.StatusOK, "FAIL")
@@ -181,7 +181,7 @@ func (h *Handler) LakalaNotify(c *gin.Context) {
contentType,
rawPayload,
)
result, err := h.service.HandleNotify("lakala", params, rawPayload, contentType, authorization)
result, err := h.service.HandleNotify(c.Request.Context(), "lakala", params, rawPayload, contentType, authorization)
if err != nil || result == nil || !result.OK {
log.Printf("[payment] lakala notify failed third_order_id=%s err=%v", params["third_order_id"], err)
c.JSON(http.StatusOK, gin.H{"code": "FAIL", "message": "失败"})
+107 -107
View File
@@ -135,12 +135,12 @@ func runtimeConfigFromDTO(dto *paymentconfig.ConfigDTO) *runtimePaymentConfig {
}
}
func (r *Repository) Start(userID uint64, orderID uint64, req StartPaymentRequest, clientIP string) (*PaymentDTO, error) {
func (r *Repository) Start(ctx context.Context, userID uint64, orderID uint64, req StartPaymentRequest, clientIP string) (*PaymentDTO, error) {
defaultConfig, err := r.defaultRuntimeConfig()
if err != nil {
return nil, ErrPaymentUnavailable
}
payment, orderRow, err := r.preparePayment(userID, orderID, req, *defaultConfig)
payment, orderRow, err := r.preparePayment(ctx, userID, orderID, req, *defaultConfig)
if err != nil {
return nil, err
}
@@ -154,7 +154,7 @@ func (r *Repository) Start(userID uint64, orderID uint64, req StartPaymentReques
return &dto, nil
}
if runtimeConfig.isMockMode() {
if err := r.confirmPaid(payment, "2", time.Now(), map[string]string{
if err := r.confirmPaid(ctx, payment, "2", time.Now(), map[string]string{
"mock": "true",
"third_order_id": payment.ThirdOrderID,
"leshua_order_id": payment.ProviderOrderID,
@@ -162,7 +162,7 @@ func (r *Repository) Start(userID uint64, orderID uint64, req StartPaymentReques
}, channelSourceMock); err != nil {
return nil, err
}
latest, err := r.findPaymentByID(payment.ID)
latest, err := r.findPaymentByID(ctx, payment.ID)
if err != nil {
return nil, err
}
@@ -176,13 +176,13 @@ func (r *Repository) Start(userID uint64, orderID uint64, req StartPaymentReques
return &dto, nil
}
if runtimeConfig.Channel == nil {
_ = r.markPaymentFailed(payment.ID, nil, "payment channel unavailable")
_ = r.markPaymentFailed(ctx, payment.ID, nil, "payment channel unavailable")
return nil, ErrPaymentUnavailable
}
log.Printf("[payment] payment start order_id=%d order_no=%s payment_id=%d provider=%s amount_cent=%d third_order_id=%s",
orderID, orderRow.OrderNo, payment.ID, runtimeConfig.Provider, payment.AmountCent, payment.ThirdOrderID)
resp, err := runtimeConfig.Channel.CreatePayment(context.Background(), channelCreatePaymentRequest{
resp, err := runtimeConfig.Channel.CreatePayment(ctx, channelCreatePaymentRequest{
ThirdOrderID: payment.ThirdOrderID,
AmountCent: payment.AmountCent,
PayWay: payment.PayWay,
@@ -194,18 +194,18 @@ func (r *Repository) Start(userID uint64, orderID uint64, req StartPaymentReques
Attach: orderRow.OrderNo,
})
if err != nil {
_ = r.markPaymentFailed(payment.ID, nil, err.Error())
_ = r.markPaymentFailed(ctx, payment.ID, nil, err.Error())
log.Printf("[payment] payment request failed order_id=%d payment_id=%d provider=%s amount_cent=%d err=%v",
orderID, payment.ID, runtimeConfig.Provider, payment.AmountCent, err)
return nil, err
}
if !resp.OK {
_ = r.markPaymentFailed(payment.ID, resp.Raw, resp.ErrorMessage)
_ = r.markPaymentFailed(ctx, payment.ID, resp.Raw, resp.ErrorMessage)
log.Printf("[payment] payment rejected order_id=%d payment_id=%d provider=%s amount_cent=%d code=%s message=%s",
orderID, payment.ID, runtimeConfig.Provider, payment.AmountCent, firstNonEmpty(resp.Raw["code"], resp.Raw["resp_code"], resp.Raw["result_code"]), resp.ErrorMessage)
return nil, ErrPaymentUnavailable
}
if err := r.db.Model(&model.PaymentOrder{}).Where("id = ?", payment.ID).Updates(map[string]any{
if err := r.db.WithContext(ctx).Model(&model.PaymentOrder{}).Where("id = ?", payment.ID).Updates(map[string]any{
"status": "paying",
"provider_order_id": resp.ProviderOrderID,
"pay_way": firstNonEmpty(resp.PayWay, payment.PayWay),
@@ -217,7 +217,7 @@ func (r *Repository) Start(userID uint64, orderID uint64, req StartPaymentReques
}).Error; err != nil {
return nil, err
}
latest, err := r.findPaymentByID(payment.ID)
latest, err := r.findPaymentByID(ctx, payment.ID)
if err != nil {
return nil, err
}
@@ -228,7 +228,7 @@ func (r *Repository) Start(userID uint64, orderID uint64, req StartPaymentReques
return &dto, nil
}
func (r *Repository) StartWalletRecharge(userID uint64, req WalletRechargePaymentRequest, clientIP string) (*PaymentDTO, error) {
func (r *Repository) StartWalletRecharge(ctx context.Context, userID uint64, req WalletRechargePaymentRequest, clientIP string) (*PaymentDTO, error) {
amountCent := req.AmountCent
if userID == 0 || amountCent < moneyCent(MinWalletRechargeAmount) {
return nil, ErrPaymentCannotStart
@@ -237,12 +237,12 @@ func (r *Repository) StartWalletRecharge(userID uint64, req WalletRechargePaymen
if err != nil {
return nil, ErrPaymentUnavailable
}
payment, err := r.createWalletRechargePayment(userID, amountCent, req, *runtimeConfig)
payment, err := r.createWalletRechargePayment(ctx, userID, amountCent, req, *runtimeConfig)
if err != nil {
return nil, err
}
if runtimeConfig.isMockMode() {
if err := r.confirmPaid(payment, "2", time.Now(), map[string]string{
if err := r.confirmPaid(ctx, payment, "2", time.Now(), map[string]string{
"mock": "true",
"third_order_id": payment.ThirdOrderID,
"leshua_order_id": payment.ProviderOrderID,
@@ -250,7 +250,7 @@ func (r *Repository) StartWalletRecharge(userID uint64, req WalletRechargePaymen
}, channelSourceMock); err != nil {
return nil, err
}
latest, err := r.findPaymentByID(payment.ID)
latest, err := r.findPaymentByID(ctx, payment.ID)
if err != nil {
return nil, err
}
@@ -259,12 +259,12 @@ func (r *Repository) StartWalletRecharge(userID uint64, req WalletRechargePaymen
return &dto, nil
}
if runtimeConfig.Channel == nil {
_ = r.markPaymentFailed(payment.ID, nil, "payment channel unavailable")
_ = r.markPaymentFailed(ctx, payment.ID, nil, "payment channel unavailable")
return nil, ErrPaymentUnavailable
}
log.Printf("[payment] wallet recharge start user_id=%d payment_id=%d provider=%s amount_cent=%d third_order_id=%s",
userID, payment.ID, runtimeConfig.Provider, payment.AmountCent, payment.ThirdOrderID)
resp, err := runtimeConfig.Channel.CreatePayment(context.Background(), channelCreatePaymentRequest{
resp, err := runtimeConfig.Channel.CreatePayment(ctx, channelCreatePaymentRequest{
ThirdOrderID: payment.ThirdOrderID,
AmountCent: payment.AmountCent,
PayWay: payment.PayWay,
@@ -276,18 +276,18 @@ func (r *Repository) StartWalletRecharge(userID uint64, req WalletRechargePaymen
Attach: payment.PaymentNo,
})
if err != nil {
_ = r.markPaymentFailed(payment.ID, nil, err.Error())
_ = r.markPaymentFailed(ctx, payment.ID, nil, err.Error())
log.Printf("[payment] wallet recharge request failed user_id=%d payment_id=%d provider=%s amount_cent=%d err=%v",
userID, payment.ID, runtimeConfig.Provider, payment.AmountCent, err)
return nil, err
}
if !resp.OK {
_ = r.markPaymentFailed(payment.ID, resp.Raw, resp.ErrorMessage)
_ = r.markPaymentFailed(ctx, payment.ID, resp.Raw, resp.ErrorMessage)
log.Printf("[payment] wallet recharge rejected user_id=%d payment_id=%d provider=%s amount_cent=%d code=%s message=%s",
userID, payment.ID, runtimeConfig.Provider, payment.AmountCent, firstNonEmpty(resp.Raw["code"], resp.Raw["resp_code"], resp.Raw["result_code"]), resp.ErrorMessage)
return nil, ErrPaymentUnavailable
}
if err := r.db.Model(&model.PaymentOrder{}).Where("id = ?", payment.ID).Updates(map[string]any{
if err := r.db.WithContext(ctx).Model(&model.PaymentOrder{}).Where("id = ?", payment.ID).Updates(map[string]any{
"status": "paying",
"provider_order_id": resp.ProviderOrderID,
"pay_way": firstNonEmpty(resp.PayWay, payment.PayWay),
@@ -299,7 +299,7 @@ func (r *Repository) StartWalletRecharge(userID uint64, req WalletRechargePaymen
}).Error; err != nil {
return nil, err
}
latest, err := r.findPaymentByID(payment.ID)
latest, err := r.findPaymentByID(ctx, payment.ID)
if err != nil {
return nil, err
}
@@ -310,9 +310,9 @@ func (r *Repository) StartWalletRecharge(userID uint64, req WalletRechargePaymen
return &dto, nil
}
func (r *Repository) QueryWalletRecharge(userID uint64, paymentID uint64) (*PaymentDTO, error) {
func (r *Repository) QueryWalletRecharge(ctx context.Context, userID uint64, paymentID uint64) (*PaymentDTO, error) {
var payment model.PaymentOrder
if err := r.db.Where("id = ? AND user_id = ? AND order_id = 0", paymentID, userID).First(&payment).Error; err != nil {
if err := r.db.WithContext(ctx).Where("id = ? AND user_id = ? AND order_id = 0", paymentID, userID).First(&payment).Error; err != nil {
if err == gorm.ErrRecordNotFound {
return nil, ErrPaymentNotFound
}
@@ -329,14 +329,14 @@ func (r *Repository) QueryWalletRecharge(userID uint64, paymentID uint64) (*Paym
if runtimeConfig.Channel == nil {
return nil, ErrPaymentUnavailable
}
resp, err := runtimeConfig.Channel.QueryPayment(context.Background(), payment.ThirdOrderID, payment.ProviderOrderID)
resp, err := runtimeConfig.Channel.QueryPayment(ctx, payment.ThirdOrderID, payment.ProviderOrderID)
if err != nil {
return nil, err
}
if err := r.applyChannelStatus(&payment, resp.Status, resp.PayTime, resp.Raw, channelSourceQuery); err != nil {
if err := r.applyChannelStatus(ctx, &payment, resp.Status, resp.PayTime, resp.Raw, channelSourceQuery); err != nil {
return nil, err
}
latest, err := r.findPaymentByID(payment.ID)
latest, err := r.findPaymentByID(ctx, payment.ID)
if err != nil {
return nil, err
}
@@ -344,9 +344,9 @@ func (r *Repository) QueryWalletRecharge(userID uint64, paymentID uint64) (*Paym
return &dto, nil
}
func (r *Repository) Query(userID uint64, orderID uint64) (*PaymentDTO, error) {
func (r *Repository) Query(ctx context.Context, userID uint64, orderID uint64) (*PaymentDTO, error) {
var payment model.PaymentOrder
if err := r.db.Where("order_id = ? AND user_id = ? AND biz_type = ?", orderID, userID, "order_pay").Order("id DESC").First(&payment).Error; err != nil {
if err := r.db.WithContext(ctx).Where("order_id = ? AND user_id = ? AND biz_type = ?", orderID, userID, "order_pay").Order("id DESC").First(&payment).Error; err != nil {
if err == gorm.ErrRecordNotFound {
return nil, ErrPaymentNotFound
}
@@ -363,14 +363,14 @@ func (r *Repository) Query(userID uint64, orderID uint64) (*PaymentDTO, error) {
if runtimeConfig.Channel == nil {
return nil, ErrPaymentUnavailable
}
resp, err := runtimeConfig.Channel.QueryPayment(context.Background(), payment.ThirdOrderID, payment.ProviderOrderID)
resp, err := runtimeConfig.Channel.QueryPayment(ctx, payment.ThirdOrderID, payment.ProviderOrderID)
if err != nil {
return nil, err
}
if err := r.applyChannelStatus(&payment, resp.Status, resp.PayTime, resp.Raw, channelSourceQuery); err != nil {
if err := r.applyChannelStatus(ctx, &payment, resp.Status, resp.PayTime, resp.Raw, channelSourceQuery); err != nil {
return nil, err
}
latest, err := r.findPaymentByID(payment.ID)
latest, err := r.findPaymentByID(ctx, payment.ID)
if err != nil {
return nil, err
}
@@ -378,17 +378,17 @@ func (r *Repository) Query(userID uint64, orderID uint64) (*PaymentDTO, error) {
return &dto, nil
}
func (r *Repository) HandleLeshuaNotify(params map[string]string, rawPayload string, contentType string) (*NotifyResult, error) {
return r.HandleNotify("leshua", params, rawPayload, contentType, "")
func (r *Repository) HandleLeshuaNotify(ctx context.Context, params map[string]string, rawPayload string, contentType string) (*NotifyResult, error) {
return r.HandleNotify(ctx, "leshua", params, rawPayload, contentType, "")
}
func (r *Repository) HandleNotify(provider string, params map[string]string, rawPayload string, contentType string, authorization string) (*NotifyResult, error) {
func (r *Repository) HandleNotify(ctx context.Context, provider string, params map[string]string, rawPayload string, contentType string, authorization string) (*NotifyResult, error) {
// 退款通知会携带 merchant_refund_id 或 leshua_refund_id。
if params["merchant_refund_id"] != "" || params["leshua_refund_id"] != "" || params["provider_refund_id"] != "" {
return r.HandleRefundNotify(provider, params, rawPayload, contentType, authorization)
return r.HandleRefundNotify(ctx, provider, params, rawPayload, contentType, authorization)
}
payment, err := r.findPaymentForNotify(params)
payment, err := r.findPaymentForNotify(ctx, params)
if err != nil {
return nil, err
}
@@ -396,28 +396,28 @@ func (r *Repository) HandleNotify(provider string, params map[string]string, raw
if err != nil {
return nil, ErrPaymentUnavailable
}
verify, err := r.verifyNotify(payment, runtimeConfig, params, rawPayload, contentType, authorization)
verify, err := r.verifyNotify(ctx, payment, runtimeConfig, params, rawPayload, contentType, authorization)
if err != nil {
return nil, err
}
if amount := parseCent(params["amount"]); amount > 0 && amount != payment.AmountCent {
if err := r.recordNotifyDiagnostic(payment.ID, params, rawPayload, contentType, verify, "amount_mismatch"); err != nil {
if err := r.recordNotifyDiagnostic(ctx, payment.ID, params, rawPayload, contentType, verify, "amount_mismatch"); err != nil {
log.Printf("[payment] %s notify diagnostic save failed third_order_id=%s err=%v", runtimeConfig.Provider, params["third_order_id"], err)
}
return nil, ErrPaymentVerifyFailed
}
raw := withNotifyDiagnostic(params, rawPayload, contentType, verify, "verified")
if err := r.applyChannelStatus(payment, normalizeNotifyPaymentStatus(runtimeConfig.Provider, params["status"]), params["pay_time"], raw, channelSourceNotify); err != nil {
if err := r.applyChannelStatus(ctx, payment, normalizeNotifyPaymentStatus(runtimeConfig.Provider, params["status"]), params["pay_time"], raw, channelSourceNotify); err != nil {
return nil, err
}
return &NotifyResult{OK: true, Message: "000000"}, nil
}
// StartRefund 创建退款单,并在本地落库后调用乐刷退款接口。
func (r *Repository) StartRefund(orderID uint64, refundAmountCent int64, bizType string, remark string) (*RefundDTO, error) {
func (r *Repository) StartRefund(ctx context.Context, orderID uint64, refundAmountCent int64, bizType string, remark string) (*RefundDTO, error) {
var originalPayment model.PaymentOrder
if err := r.db.Where("order_id = ? AND status = 'paid' AND biz_type = 'order_pay'", orderID).Order("id DESC").First(&originalPayment).Error; err != nil {
if err := r.db.WithContext(ctx).Where("order_id = ? AND status = 'paid' AND biz_type = 'order_pay'", orderID).Order("id DESC").First(&originalPayment).Error; err != nil {
if err == gorm.ErrRecordNotFound {
return nil, ErrPaymentNotFound
}
@@ -429,7 +429,7 @@ func (r *Repository) StartRefund(orderID uint64, refundAmountCent int64, bizType
}
var existingRefund model.PaymentOrder
err = r.db.Where("order_id = ? AND biz_type = ? AND status NOT IN ('failed')", orderID, bizType).Order("id DESC").First(&existingRefund).Error
err = r.db.WithContext(ctx).Where("order_id = ? AND biz_type = ? AND status NOT IN ('failed')", orderID, bizType).Order("id DESC").First(&existingRefund).Error
if err == nil {
dto := toRefundDTO(existingRefund)
return &dto, nil
@@ -468,32 +468,32 @@ func (r *Repository) StartRefund(orderID uint64, refundAmountCent int64, bizType
if remark != "" {
refundOrder.RawResponse = datatypes.JSON([]byte(fmt.Sprintf(`{"mock":"true","remark":"%s"}`, remark)))
}
if err := r.db.Create(&refundOrder).Error; err != nil {
if err := r.db.WithContext(ctx).Create(&refundOrder).Error; err != nil {
return nil, err
}
r.recordConfigUsage(runtimeConfig, &refundOrder)
if err := r.updateOrderRefundStatus(orderID, refundAmountCent); err != nil {
if err := r.updateOrderRefundStatus(ctx, orderID, refundAmountCent); err != nil {
log.Printf("[payment] mock update order refund status failed order_id=%d err=%v", orderID, err)
}
dto := toRefundDTO(refundOrder)
return &dto, nil
}
if err := r.db.Create(&refundOrder).Error; err != nil {
if err := r.db.WithContext(ctx).Create(&refundOrder).Error; err != nil {
return nil, err
}
log.Printf("[payment] refund start order_id=%d order_no=%s payment_id=%d biz_type=%s provider=%s amount_cent=%d merchant_refund_id=%s origin_third_order_id=%s origin_provider_order_id=%s",
orderID, originalPayment.OrderNo, refundOrder.ID, bizType, runtimeConfig.Provider, refundAmountCent, merchantRefundID, originalPayment.ThirdOrderID, refundOriginProviderOrderID(originalPayment))
r.recordConfigUsage(runtimeConfig, &refundOrder)
if err := r.markOrderRefunding(orderID, refundAmountCent); err != nil {
if err := r.markOrderRefunding(ctx, orderID, refundAmountCent); err != nil {
log.Printf("[payment] mark order refunding failed order_id=%d err=%v", orderID, err)
}
if runtimeConfig.Channel == nil {
_ = r.markRefundFailed(refundOrder.ID, orderID, refundAmountCent, map[string]string{"error": "payment channel unavailable"})
_ = r.markRefundFailed(ctx, refundOrder.ID, orderID, refundAmountCent, map[string]string{"error": "payment channel unavailable"})
return nil, ErrPaymentUnavailable
}
resp, err := runtimeConfig.Channel.CreateRefund(context.Background(), channelCreateRefundRequest{
resp, err := runtimeConfig.Channel.CreateRefund(ctx, channelCreateRefundRequest{
ThirdOrderID: originalPayment.ThirdOrderID,
ProviderOrderID: refundOriginProviderOrderID(originalPayment),
MerchantRefundID: merchantRefundID,
@@ -503,13 +503,13 @@ func (r *Repository) StartRefund(orderID uint64, refundAmountCent int64, bizType
Remark: remark,
})
if err != nil {
_ = r.markRefundFailed(refundOrder.ID, orderID, refundAmountCent, map[string]string{"error": err.Error()})
_ = r.markRefundFailed(ctx, refundOrder.ID, orderID, refundAmountCent, map[string]string{"error": err.Error()})
log.Printf("[payment] refund request failed order_id=%d payment_id=%d biz_type=%s provider=%s amount_cent=%d err=%v",
orderID, refundOrder.ID, bizType, runtimeConfig.Provider, refundAmountCent, err)
return nil, err
}
if !resp.OK {
_ = r.markRefundFailed(refundOrder.ID, orderID, refundAmountCent, resp.Raw)
_ = r.markRefundFailed(ctx, refundOrder.ID, orderID, refundAmountCent, resp.Raw)
log.Printf("[payment] refund rejected order_id=%d payment_id=%d biz_type=%s provider=%s amount_cent=%d code=%s message=%s",
orderID, refundOrder.ID, bizType, runtimeConfig.Provider, refundAmountCent, firstNonEmpty(resp.Raw["code"], resp.Raw["resp_code"], resp.Raw["result_code"]), resp.ErrorMessage)
return nil, ErrPaymentUnavailable
@@ -524,7 +524,7 @@ func (r *Repository) StartRefund(orderID uint64, refundAmountCent int64, bizType
} else if resp.Status == "failed" {
refundStatus = "failed"
}
if err := r.db.Model(&model.PaymentOrder{}).Where("id = ?", refundOrder.ID).Updates(map[string]any{
if err := r.db.WithContext(ctx).Model(&model.PaymentOrder{}).Where("id = ?", refundOrder.ID).Updates(map[string]any{
"status": refundStatus,
"provider_order_id": resp.ProviderRefundID,
"raw_request": jsonMap(resp.RawRequest),
@@ -535,12 +535,12 @@ func (r *Repository) StartRefund(orderID uint64, refundAmountCent int64, bizType
}
if refundStatus == "refunded" {
_ = r.updateOrderRefundStatus(orderID, refundAmountCent)
_ = r.updateOrderRefundStatus(ctx, orderID, refundAmountCent)
refundOrder.PaidAt = paidAt
} else if refundStatus == "failed" {
_ = r.markOrderRefundFailed(orderID, refundAmountCent)
_ = r.markOrderRefundFailed(ctx, orderID, refundAmountCent)
} else {
_ = r.markOrderRefunding(orderID, refundAmountCent)
_ = r.markOrderRefunding(ctx, orderID, refundAmountCent)
}
refundOrder.Status = refundStatus
refundOrder.ProviderOrderID = resp.ProviderRefundID
@@ -552,9 +552,9 @@ func (r *Repository) StartRefund(orderID uint64, refundAmountCent int64, bizType
}
// QueryRefundStatus 查询订单最近一笔退款状态。
func (r *Repository) QueryRefundStatus(orderID uint64) (*RefundDTO, error) {
func (r *Repository) QueryRefundStatus(ctx context.Context, orderID uint64) (*RefundDTO, error) {
var payment model.PaymentOrder
if err := r.db.Where("order_id = ? AND biz_type IN ?", orderID, refundBizTypes).Order("id DESC").First(&payment).Error; err != nil {
if err := r.db.WithContext(ctx).Where("order_id = ? AND biz_type IN ?", orderID, refundBizTypes).Order("id DESC").First(&payment).Error; err != nil {
if err == gorm.ErrRecordNotFound {
return nil, ErrPaymentNotFound
}
@@ -571,7 +571,7 @@ func (r *Repository) QueryRefundStatus(orderID uint64) (*RefundDTO, error) {
if runtimeConfig.Channel == nil {
return nil, ErrPaymentUnavailable
}
resp, err := runtimeConfig.Channel.QueryRefund(context.Background(), channelQueryRefundRequest{
resp, err := runtimeConfig.Channel.QueryRefund(ctx, channelQueryRefundRequest{
ThirdOrderID: payment.ThirdOrderID,
MerchantRefundID: payment.ThirdOrderID,
ProviderRefundID: payment.ProviderOrderID,
@@ -581,7 +581,7 @@ func (r *Repository) QueryRefundStatus(orderID uint64) (*RefundDTO, error) {
}
if resp.Status == "refunded" {
now := time.Now()
if err := r.db.Model(&model.PaymentOrder{}).Where("id = ?", payment.ID).Updates(map[string]any{
if err := r.db.WithContext(ctx).Model(&model.PaymentOrder{}).Where("id = ?", payment.ID).Updates(map[string]any{
"status": "refunded",
"paid_at": now,
"raw_response": jsonMap(withRawSource(resp.Raw, channelSourceQuery)),
@@ -590,26 +590,26 @@ func (r *Repository) QueryRefundStatus(orderID uint64) (*RefundDTO, error) {
}
payment.Status = "refunded"
payment.PaidAt = &now
_ = r.updateOrderRefundStatus(orderID, payment.AmountCent)
_ = r.updateOrderRefundStatus(ctx, orderID, payment.AmountCent)
} else if resp.Status == "failed" {
if err := r.db.Model(&model.PaymentOrder{}).Where("id = ?", payment.ID).Updates(map[string]any{
if err := r.db.WithContext(ctx).Model(&model.PaymentOrder{}).Where("id = ?", payment.ID).Updates(map[string]any{
"status": "failed",
"raw_response": jsonMap(withRawSource(resp.Raw, channelSourceQuery)),
}).Error; err != nil {
return nil, err
}
payment.Status = "failed"
_ = r.markOrderRefundFailed(orderID, payment.AmountCent)
_ = r.markOrderRefundFailed(ctx, orderID, payment.AmountCent)
}
dto := toRefundDTO(payment)
return &dto, nil
}
func (r *Repository) AdminList(query AdminPaymentQuery) (*PaginatedResult, error) {
db := r.db.Table("payment_orders AS p").
func (r *Repository) AdminList(ctx context.Context, query AdminPaymentQuery) (*PaginatedResult, error) {
db := r.db.WithContext(ctx).Table("payment_orders AS p").
Select("p.*, COALESCE(u.phone, '') AS user_phone").
Joins("LEFT JOIN users AS u ON u.id = p.user_id")
countDB := r.db.Model(&model.PaymentOrder{})
countDB := r.db.WithContext(ctx).Model(&model.PaymentOrder{})
if query.UserID > 0 {
db = db.Where("p.user_id = ?", query.UserID)
countDB = countDB.Where("user_id = ?", query.UserID)
@@ -651,8 +651,8 @@ func (r *Repository) AdminList(query AdminPaymentQuery) (*PaginatedResult, error
}
// HandleRefundNotify 处理渠道退款通知。
func (r *Repository) HandleRefundNotify(provider string, params map[string]string, rawPayload string, contentType string, authorization string) (*NotifyResult, error) {
payment, err := r.findRefundPaymentForNotify(params)
func (r *Repository) HandleRefundNotify(ctx context.Context, provider string, params map[string]string, rawPayload string, contentType string, authorization string) (*NotifyResult, error) {
payment, err := r.findRefundPaymentForNotify(ctx, params)
if err != nil {
return nil, err
}
@@ -660,7 +660,7 @@ func (r *Repository) HandleRefundNotify(provider string, params map[string]strin
if err != nil {
return nil, ErrPaymentUnavailable
}
verify, err := r.verifyNotify(payment, runtimeConfig, params, rawPayload, contentType, authorization)
verify, err := r.verifyNotify(ctx, payment, runtimeConfig, params, rawPayload, contentType, authorization)
if err != nil {
return nil, err
}
@@ -670,7 +670,7 @@ func (r *Repository) HandleRefundNotify(provider string, params map[string]strin
switch status {
case "refunded":
now := time.Now()
if err := r.db.Model(&model.PaymentOrder{}).Where("id = ?", payment.ID).Updates(map[string]any{
if err := r.db.WithContext(ctx).Model(&model.PaymentOrder{}).Where("id = ?", payment.ID).Updates(map[string]any{
"status": "refunded",
"paid_at": now,
"notified_at": now,
@@ -678,16 +678,16 @@ func (r *Repository) HandleRefundNotify(provider string, params map[string]strin
}).Error; err != nil {
return nil, err
}
_ = r.updateOrderRefundStatus(payment.OrderID, payment.AmountCent)
_ = r.updateOrderRefundStatus(ctx, payment.OrderID, payment.AmountCent)
case "failed":
r.db.Model(&model.PaymentOrder{}).Where("id = ?", payment.ID).Updates(map[string]any{
r.db.WithContext(ctx).Model(&model.PaymentOrder{}).Where("id = ?", payment.ID).Updates(map[string]any{
"status": "failed",
"notified_at": time.Now(),
"raw_response": jsonMap(raw),
})
_ = r.markOrderRefundFailed(payment.OrderID, payment.AmountCent)
_ = r.markOrderRefundFailed(ctx, payment.OrderID, payment.AmountCent)
default:
r.db.Model(&model.PaymentOrder{}).Where("id = ?", payment.ID).Updates(map[string]any{
r.db.WithContext(ctx).Model(&model.PaymentOrder{}).Where("id = ?", payment.ID).Updates(map[string]any{
"status": "refunding",
"raw_response": jsonMap(raw),
})
@@ -696,42 +696,42 @@ func (r *Repository) HandleRefundNotify(provider string, params map[string]strin
}
// updateOrderRefundStatus 更新订单退款成功状态。
func (r *Repository) updateOrderRefundStatus(orderID uint64, refundAmountCent int64) error {
func (r *Repository) updateOrderRefundStatus(ctx context.Context, orderID uint64, refundAmountCent int64) error {
now := time.Now()
return r.db.Model(&model.RentalOrder{}).Where("id = ?", orderID).Updates(map[string]any{
return r.db.WithContext(ctx).Model(&model.RentalOrder{}).Where("id = ?", orderID).Updates(map[string]any{
"refund_status": "refunded",
"refund_amount_cent": refundAmountCent,
"refunded_at": now,
}).Error
}
func (r *Repository) markOrderRefunding(orderID uint64, refundAmountCent int64) error {
return r.db.Model(&model.RentalOrder{}).Where("id = ?", orderID).Updates(map[string]any{
func (r *Repository) markOrderRefunding(ctx context.Context, orderID uint64, refundAmountCent int64) error {
return r.db.WithContext(ctx).Model(&model.RentalOrder{}).Where("id = ?", orderID).Updates(map[string]any{
"refund_status": "refunding",
"refund_amount_cent": refundAmountCent,
"refunded_at": nil,
}).Error
}
func (r *Repository) markOrderRefundFailed(orderID uint64, refundAmountCent int64) error {
return r.db.Model(&model.RentalOrder{}).Where("id = ?", orderID).Updates(map[string]any{
func (r *Repository) markOrderRefundFailed(ctx context.Context, orderID uint64, refundAmountCent int64) error {
return r.db.WithContext(ctx).Model(&model.RentalOrder{}).Where("id = ?", orderID).Updates(map[string]any{
"refund_status": "failed",
"refund_amount_cent": refundAmountCent,
"refunded_at": nil,
}).Error
}
func (r *Repository) markRefundFailed(paymentID uint64, orderID uint64, refundAmountCent int64, raw map[string]string) error {
func (r *Repository) markRefundFailed(ctx context.Context, paymentID uint64, orderID uint64, refundAmountCent int64, raw map[string]string) error {
if raw == nil {
raw = map[string]string{"error": "refund failed"}
}
if err := r.db.Model(&model.PaymentOrder{}).Where("id = ?", paymentID).Updates(map[string]any{
if err := r.db.WithContext(ctx).Model(&model.PaymentOrder{}).Where("id = ?", paymentID).Updates(map[string]any{
"status": "failed",
"raw_response": jsonMap(raw),
}).Error; err != nil {
return err
}
return r.markOrderRefundFailed(orderID, refundAmountCent)
return r.markOrderRefundFailed(ctx, orderID, refundAmountCent)
}
// toRefundDTO 将支付表里的退款单转换为接口 DTO。
@@ -751,10 +751,10 @@ func toRefundDTO(payment model.PaymentOrder) RefundDTO {
}
}
func (r *Repository) preparePayment(userID uint64, orderID uint64, req StartPaymentRequest, runtimeConfig runtimePaymentConfig) (*model.PaymentOrder, *model.RentalOrder, error) {
func (r *Repository) preparePayment(ctx context.Context, userID uint64, orderID uint64, req StartPaymentRequest, runtimeConfig runtimePaymentConfig) (*model.PaymentOrder, *model.RentalOrder, error) {
var paymentID uint64
var orderRow model.RentalOrder
err := r.db.Transaction(func(tx *gorm.DB) error {
err := r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
var row model.RentalOrder
if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).
Where("id = ? AND renter_id = ?", orderID, userID).
@@ -807,7 +807,7 @@ func (r *Repository) preparePayment(userID uint64, orderID uint64, req StartPaym
if err != nil {
return nil, nil, err
}
payment, err := r.findPaymentByID(paymentID)
payment, err := r.findPaymentByID(ctx, paymentID)
if err != nil {
return nil, nil, err
}
@@ -875,7 +875,7 @@ func newOrderPayment(row model.RentalOrder, amountCent int64, req StartPaymentRe
return payment, nil
}
func (r *Repository) createWalletRechargePayment(userID uint64, amountCent int64, req WalletRechargePaymentRequest, runtimeConfig runtimePaymentConfig) (*model.PaymentOrder, error) {
func (r *Repository) createWalletRechargePayment(ctx context.Context, userID uint64, amountCent int64, req WalletRechargePaymentRequest, runtimeConfig runtimePaymentConfig) (*model.PaymentOrder, error) {
paymentNo, err := newPaymentNo()
if err != nil {
return nil, err
@@ -899,13 +899,13 @@ func (r *Repository) createWalletRechargePayment(userID uint64, amountCent int64
payment.ProviderOrderID = "MOCK" + paymentNo
payment.TDCode = "mock://payment/recharge/" + paymentNo
}
if err := r.db.Create(&payment).Error; err != nil {
if err := r.db.WithContext(ctx).Create(&payment).Error; err != nil {
return nil, err
}
return &payment, nil
}
func (r *Repository) applyChannelStatus(payment *model.PaymentOrder, status string, payTime string, raw map[string]string, source string) error {
func (r *Repository) applyChannelStatus(ctx context.Context, payment *model.PaymentOrder, status string, payTime string, raw map[string]string, source string) error {
switch status {
case "paid":
paidAt := parseChannelTime(payTime)
@@ -913,17 +913,17 @@ func (r *Repository) applyChannelStatus(payment *model.PaymentOrder, status stri
now := time.Now()
paidAt = &now
}
return r.confirmPaid(payment, status, *paidAt, raw, source)
return r.confirmPaid(ctx, payment, status, *paidAt, raw, source)
case "closed":
return r.updateChannelStatus(payment.ID, "closed", raw, source)
return r.updateChannelStatus(ctx, payment.ID, "closed", raw, source)
case "failed":
return r.updateChannelStatus(payment.ID, "failed", raw, source)
return r.updateChannelStatus(ctx, payment.ID, "failed", raw, source)
default:
return r.updateChannelStatus(payment.ID, "paying", raw, source)
return r.updateChannelStatus(ctx, payment.ID, "paying", raw, source)
}
}
func (r *Repository) updateChannelStatus(paymentID uint64, status string, raw map[string]string, source string) error {
func (r *Repository) updateChannelStatus(ctx context.Context, paymentID uint64, status string, raw map[string]string, source string) error {
updates := map[string]any{
"status": status,
"raw_response": jsonMap(withRawSource(raw, source)),
@@ -931,16 +931,16 @@ func (r *Repository) updateChannelStatus(paymentID uint64, status string, raw ma
if source == channelSourceNotify {
updates["notified_at"] = time.Now()
}
return r.db.Model(&model.PaymentOrder{}).Where("id = ?", paymentID).Updates(updates).Error
return r.db.WithContext(ctx).Model(&model.PaymentOrder{}).Where("id = ?", paymentID).Updates(updates).Error
}
func (r *Repository) confirmPaid(payment *model.PaymentOrder, status string, paidAt time.Time, raw map[string]string, source string) error {
func (r *Repository) confirmPaid(ctx context.Context, payment *model.PaymentOrder, status string, paidAt time.Time, raw map[string]string, source string) error {
if payment.Status != "paid" {
if payment.OrderID == 0 {
if r.walletRepo == nil {
return ErrDependencyUnavailable
}
if err := r.walletRepo.ConfirmRechargeFromChannel(context.Background(), payment.UserID, firstNonEmpty(payment.ProviderOrderID, payment.PaymentNo), payment.AmountCent); err != nil {
if err := r.walletRepo.ConfirmRechargeFromChannel(ctx, payment.UserID, firstNonEmpty(payment.ProviderOrderID, payment.PaymentNo), payment.AmountCent); err != nil {
return err
}
} else {
@@ -961,34 +961,34 @@ func (r *Repository) confirmPaid(payment *model.PaymentOrder, status string, pai
if source == channelSourceNotify {
updates["notified_at"] = time.Now()
}
return r.db.Model(&model.PaymentOrder{}).Where("id = ?", payment.ID).Updates(updates).Error
return r.db.WithContext(ctx).Model(&model.PaymentOrder{}).Where("id = ?", payment.ID).Updates(updates).Error
}
func (r *Repository) markPaymentFailed(paymentID uint64, raw map[string]string, message string) error {
func (r *Repository) markPaymentFailed(ctx context.Context, paymentID uint64, raw map[string]string, message string) error {
if raw == nil {
raw = map[string]string{"error": message}
}
return r.db.Model(&model.PaymentOrder{}).Where("id = ?", paymentID).Updates(map[string]any{
return r.db.WithContext(ctx).Model(&model.PaymentOrder{}).Where("id = ?", paymentID).Updates(map[string]any{
"status": "failed",
"raw_response": jsonMap(raw),
}).Error
}
func (r *Repository) findPaymentByID(paymentID uint64) (*model.PaymentOrder, error) {
func (r *Repository) findPaymentByID(ctx context.Context, paymentID uint64) (*model.PaymentOrder, error) {
var payment model.PaymentOrder
if err := r.db.First(&payment, paymentID).Error; err != nil {
if err := r.db.WithContext(ctx).First(&payment, paymentID).Error; err != nil {
return nil, err
}
return &payment, nil
}
func (r *Repository) findPaymentForNotify(params map[string]string) (*model.PaymentOrder, error) {
func (r *Repository) findPaymentForNotify(ctx context.Context, params map[string]string) (*model.PaymentOrder, error) {
thirdOrderID := params["third_order_id"]
if thirdOrderID == "" {
return nil, ErrPaymentNotFound
}
var payment model.PaymentOrder
if err := r.db.Where("third_order_id = ?", thirdOrderID).First(&payment).Error; err != nil {
if err := r.db.WithContext(ctx).Where("third_order_id = ?", thirdOrderID).First(&payment).Error; err != nil {
if err == gorm.ErrRecordNotFound {
return nil, ErrPaymentNotFound
}
@@ -997,13 +997,13 @@ func (r *Repository) findPaymentForNotify(params map[string]string) (*model.Paym
return &payment, nil
}
func (r *Repository) findRefundPaymentForNotify(params map[string]string) (*model.PaymentOrder, error) {
func (r *Repository) findRefundPaymentForNotify(ctx context.Context, params map[string]string) (*model.PaymentOrder, error) {
merchantRefundID := params["merchant_refund_id"]
if merchantRefundID == "" {
return nil, ErrPaymentNotFound
}
var payment model.PaymentOrder
if err := r.db.Where("third_order_id = ?", merchantRefundID).First(&payment).Error; err != nil {
if err := r.db.WithContext(ctx).Where("third_order_id = ?", merchantRefundID).First(&payment).Error; err != nil {
if err == gorm.ErrRecordNotFound {
return nil, ErrPaymentNotFound
}
@@ -1012,7 +1012,7 @@ func (r *Repository) findRefundPaymentForNotify(params map[string]string) (*mode
return &payment, nil
}
func (r *Repository) verifyNotify(payment *model.PaymentOrder, runtimeConfig *runtimePaymentConfig, params map[string]string, rawPayload string, contentType string, authorization string) (channelVerifyNotifyResult, error) {
func (r *Repository) verifyNotify(ctx context.Context, payment *model.PaymentOrder, runtimeConfig *runtimePaymentConfig, params map[string]string, rawPayload string, contentType string, authorization string) (channelVerifyNotifyResult, error) {
var verify channelVerifyNotifyResult
if runtimeConfig.isMockMode() {
return verify, nil
@@ -1032,7 +1032,7 @@ func (r *Repository) verifyNotify(payment *model.PaymentOrder, runtimeConfig *ru
verify.ParamKeys,
firstNonEmpty(verify.BaseString["notify_key"], verify.BaseString["notify_cert"]),
)
if err := r.recordNotifyDiagnostic(payment.ID, params, rawPayload, contentType, verify, "verify_failed"); err != nil {
if err := r.recordNotifyDiagnostic(ctx, payment.ID, params, rawPayload, contentType, verify, "verify_failed"); err != nil {
log.Printf("[payment] %s notify diagnostic save failed payment_id=%d err=%v", runtimeConfig.Provider, payment.ID, err)
}
return verify, ErrPaymentVerifyFailed
@@ -1231,12 +1231,12 @@ func withRawSource(raw map[string]string, source string) map[string]string {
return out
}
func (r *Repository) recordNotifyDiagnostic(paymentID uint64, params map[string]string, rawPayload string, contentType string, verify channelVerifyNotifyResult, status string) error {
func (r *Repository) recordNotifyDiagnostic(ctx context.Context, paymentID uint64, params map[string]string, rawPayload string, contentType string, verify channelVerifyNotifyResult, status string) error {
if paymentID == 0 {
return nil
}
raw := withNotifyDiagnostic(params, rawPayload, contentType, verify, status)
return r.db.Model(&model.PaymentOrder{}).
return r.db.WithContext(ctx).Model(&model.PaymentOrder{}).
Where("id = ?", paymentID).
Update("raw_response", jsonMap(raw)).Error
}
@@ -246,7 +246,7 @@ func TestRuntimePaymentConfigRequiredFields(t *testing.T) {
func TestServiceStartRequiresNonZeroOrderID(t *testing.T) {
svc := &Service{repo: &Repository{}}
_, err := svc.Start(1, 0, StartPaymentRequest{}, "127.0.0.1")
_, err := svc.Start(t.Context(), 1, 0, StartPaymentRequest{}, "127.0.0.1")
if !errors.Is(err, ErrPaymentCannotStart) {
t.Fatalf("error = %v, want ErrPaymentCannotStart", err)
}
@@ -255,7 +255,7 @@ func TestServiceStartRequiresNonZeroOrderID(t *testing.T) {
func TestServiceStartRequiresNonZeroUserID(t *testing.T) {
svc := &Service{repo: &Repository{}}
_, err := svc.Start(0, 100, StartPaymentRequest{}, "127.0.0.1")
_, err := svc.Start(t.Context(), 0, 100, StartPaymentRequest{}, "127.0.0.1")
if !errors.Is(err, ErrPaymentCannotStart) {
t.Fatalf("error = %v, want ErrPaymentCannotStart", err)
}
@@ -264,12 +264,12 @@ func TestServiceStartRequiresNonZeroUserID(t *testing.T) {
func TestServiceStartRefundRequiresPositiveAmount(t *testing.T) {
svc := &Service{repo: &Repository{}}
_, err := svc.StartRefund(100, 0, "cancel_refund", "test")
_, err := svc.StartRefund(t.Context(), 100, 0, "cancel_refund", "test")
if !errors.Is(err, ErrRefundCannotStart) {
t.Fatalf("error = %v, want ErrRefundCannotStart", err)
}
_, err = svc.StartRefund(100, -1000, "cancel_refund", "test")
_, err = svc.StartRefund(t.Context(), 100, -1000, "cancel_refund", "test")
if !errors.Is(err, ErrRefundCannotStart) {
t.Fatalf("error = %v, want ErrRefundCannotStart", err)
}
@@ -278,7 +278,7 @@ func TestServiceStartRefundRequiresPositiveAmount(t *testing.T) {
func TestServiceStartRefundRequiresNonZeroOrderID(t *testing.T) {
svc := &Service{repo: &Repository{}}
_, err := svc.StartRefund(0, 1000, "cancel_refund", "test")
_, err := svc.StartRefund(t.Context(), 0, 1000, "cancel_refund", "test")
if !errors.Is(err, ErrRefundCannotStart) {
t.Fatalf("error = %v, want ErrRefundCannotStart", err)
}
+19 -18
View File
@@ -1,6 +1,7 @@
package payment
import (
"context"
"errors"
"strings"
)
@@ -33,81 +34,81 @@ func NewService(repo *Repository, appEnv ...string) *Service {
}
}
func (s *Service) Start(userID uint64, orderID uint64, req StartPaymentRequest, clientIP string) (*PaymentDTO, error) {
func (s *Service) Start(ctx context.Context, userID uint64, orderID uint64, req StartPaymentRequest, clientIP string) (*PaymentDTO, error) {
if s.repo == nil {
return nil, ErrDependencyUnavailable
}
if userID == 0 || orderID == 0 {
return nil, ErrPaymentCannotStart
}
return s.repo.Start(userID, orderID, req, clientIP)
return s.repo.Start(ctx, userID, orderID, req, clientIP)
}
func (s *Service) Query(userID uint64, orderID uint64) (*PaymentDTO, error) {
func (s *Service) Query(ctx context.Context, userID uint64, orderID uint64) (*PaymentDTO, error) {
if s.repo == nil {
return nil, ErrDependencyUnavailable
}
if userID == 0 || orderID == 0 {
return nil, ErrPaymentNotFound
}
return s.repo.Query(userID, orderID)
return s.repo.Query(ctx, userID, orderID)
}
func (s *Service) StartWalletRecharge(userID uint64, req WalletRechargePaymentRequest, clientIP string) (*PaymentDTO, error) {
func (s *Service) StartWalletRecharge(ctx context.Context, userID uint64, req WalletRechargePaymentRequest, clientIP string) (*PaymentDTO, error) {
if s.repo == nil {
return nil, ErrDependencyUnavailable
}
if !s.walletRechargeEnabled {
return nil, ErrWalletRechargeDisabled
}
return s.repo.StartWalletRecharge(userID, req, clientIP)
return s.repo.StartWalletRecharge(ctx, userID, req, clientIP)
}
func (s *Service) QueryWalletRecharge(userID uint64, paymentID uint64) (*PaymentDTO, error) {
func (s *Service) QueryWalletRecharge(ctx context.Context, userID uint64, paymentID uint64) (*PaymentDTO, error) {
if s.repo == nil {
return nil, ErrDependencyUnavailable
}
if userID == 0 || paymentID == 0 {
return nil, ErrPaymentNotFound
}
return s.repo.QueryWalletRecharge(userID, paymentID)
return s.repo.QueryWalletRecharge(ctx, userID, paymentID)
}
func (s *Service) HandleLeshuaNotify(params map[string]string, rawPayload string, contentType string) (*NotifyResult, error) {
func (s *Service) HandleLeshuaNotify(ctx context.Context, params map[string]string, rawPayload string, contentType string) (*NotifyResult, error) {
if s.repo == nil {
return nil, ErrDependencyUnavailable
}
return s.repo.HandleLeshuaNotify(params, rawPayload, contentType)
return s.repo.HandleLeshuaNotify(ctx, params, rawPayload, contentType)
}
func (s *Service) HandleNotify(provider string, params map[string]string, rawPayload string, contentType string, authorization string) (*NotifyResult, error) {
func (s *Service) HandleNotify(ctx context.Context, provider string, params map[string]string, rawPayload string, contentType string, authorization string) (*NotifyResult, error) {
if s.repo == nil {
return nil, ErrDependencyUnavailable
}
return s.repo.HandleNotify(provider, params, rawPayload, contentType, authorization)
return s.repo.HandleNotify(ctx, provider, params, rawPayload, contentType, authorization)
}
func (s *Service) StartRefund(orderID uint64, refundAmountCent int64, bizType string, remark string) (*RefundDTO, error) {
func (s *Service) StartRefund(ctx context.Context, orderID uint64, refundAmountCent int64, bizType string, remark string) (*RefundDTO, error) {
if s.repo == nil {
return nil, ErrDependencyUnavailable
}
if orderID == 0 || refundAmountCent <= 0 {
return nil, ErrRefundCannotStart
}
return s.repo.StartRefund(orderID, refundAmountCent, bizType, remark)
return s.repo.StartRefund(ctx, orderID, refundAmountCent, bizType, remark)
}
func (s *Service) QueryRefundStatus(orderID uint64) (*RefundDTO, error) {
func (s *Service) QueryRefundStatus(ctx context.Context, orderID uint64) (*RefundDTO, error) {
if s.repo == nil {
return nil, ErrDependencyUnavailable
}
if orderID == 0 {
return nil, ErrPaymentNotFound
}
return s.repo.QueryRefundStatus(orderID)
return s.repo.QueryRefundStatus(ctx, orderID)
}
func (s *Service) AdminList(query AdminPaymentQuery) (*PaginatedResult, error) {
func (s *Service) AdminList(ctx context.Context, query AdminPaymentQuery) (*PaginatedResult, error) {
if s.repo == nil {
return nil, ErrDependencyUnavailable
}
@@ -120,5 +121,5 @@ func (s *Service) AdminList(query AdminPaymentQuery) (*PaginatedResult, error) {
if query.PageSize > 100 {
query.PageSize = 100
}
return s.repo.AdminList(query)
return s.repo.AdminList(ctx, query)
}
@@ -8,7 +8,7 @@ import (
// TestServiceDependencyChecks 测试 Service 依赖检查
func TestServiceStartWithNilRepo(t *testing.T) {
svc := &Service{repo: nil}
_, err := svc.Start(1, 100, StartPaymentRequest{}, "127.0.0.1")
_, err := svc.Start(t.Context(), 1, 100, StartPaymentRequest{}, "127.0.0.1")
if !errors.Is(err, ErrDependencyUnavailable) {
t.Fatalf("Start() error = %v, want ErrDependencyUnavailable", err)
}
@@ -18,13 +18,13 @@ func TestServiceStartWithInvalidParams(t *testing.T) {
svc := &Service{repo: &Repository{}}
// 测试 userID 为 0
_, err := svc.Start(0, 100, StartPaymentRequest{}, "127.0.0.1")
_, err := svc.Start(t.Context(), 0, 100, StartPaymentRequest{}, "127.0.0.1")
if !errors.Is(err, ErrPaymentCannotStart) {
t.Fatalf("Start() error = %v, want ErrPaymentCannotStart", err)
}
// 测试 orderID 为 0
_, err = svc.Start(1, 0, StartPaymentRequest{}, "127.0.0.1")
_, err = svc.Start(t.Context(), 1, 0, StartPaymentRequest{}, "127.0.0.1")
if !errors.Is(err, ErrPaymentCannotStart) {
t.Fatalf("Start() error = %v, want ErrPaymentCannotStart", err)
}
@@ -32,7 +32,7 @@ func TestServiceStartWithInvalidParams(t *testing.T) {
func TestServiceQueryWithNilRepo(t *testing.T) {
svc := &Service{repo: nil}
_, err := svc.Query(1, 100)
_, err := svc.Query(t.Context(), 1, 100)
if !errors.Is(err, ErrDependencyUnavailable) {
t.Fatalf("Query() error = %v, want ErrDependencyUnavailable", err)
}
@@ -41,7 +41,7 @@ func TestServiceQueryWithNilRepo(t *testing.T) {
func TestServiceQueryWithInvalidParams(t *testing.T) {
svc := &Service{repo: &Repository{}}
_, err := svc.Query(0, 100)
_, err := svc.Query(t.Context(), 0, 100)
if !errors.Is(err, ErrPaymentNotFound) {
t.Fatalf("Query() error = %v, want ErrPaymentNotFound", err)
}
@@ -49,7 +49,7 @@ func TestServiceQueryWithInvalidParams(t *testing.T) {
func TestServiceStartRefundWithNilRepo(t *testing.T) {
svc := &Service{repo: nil}
_, err := svc.StartRefund(100, 1000, "cancel_refund", "test")
_, err := svc.StartRefund(t.Context(), 100, 1000, "cancel_refund", "test")
if !errors.Is(err, ErrDependencyUnavailable) {
t.Fatalf("StartRefund() error = %v, want ErrDependencyUnavailable", err)
}
@@ -59,13 +59,13 @@ func TestServiceStartRefundWithInvalidParams(t *testing.T) {
svc := &Service{repo: &Repository{}}
// 测试 orderID 为 0
_, err := svc.StartRefund(0, 1000, "cancel_refund", "test")
_, err := svc.StartRefund(t.Context(), 0, 1000, "cancel_refund", "test")
if !errors.Is(err, ErrRefundCannotStart) {
t.Fatalf("StartRefund() error = %v, want ErrRefundCannotStart", err)
}
// 测试金额为 0
_, err = svc.StartRefund(100, 0, "cancel_refund", "test")
_, err = svc.StartRefund(t.Context(), 100, 0, "cancel_refund", "test")
if !errors.Is(err, ErrRefundCannotStart) {
t.Fatalf("StartRefund() error = %v, want ErrRefundCannotStart", err)
}
@@ -73,7 +73,7 @@ func TestServiceStartRefundWithInvalidParams(t *testing.T) {
func TestServiceWalletRechargeDisabledInProduction(t *testing.T) {
svc := NewService(&Repository{}, "production")
_, err := svc.StartWalletRecharge(1, WalletRechargePaymentRequest{AmountCent: 1000}, "127.0.0.1")
_, err := svc.StartWalletRecharge(t.Context(), 1, WalletRechargePaymentRequest{AmountCent: 1000}, "127.0.0.1")
if !errors.Is(err, ErrWalletRechargeDisabled) {
t.Fatalf("StartWalletRecharge() error = %v, want ErrWalletRechargeDisabled", err)
}