新增后台微信退款,以及完善退款记录
This commit is contained in:
parent
184d61a5c7
commit
3a324e6656
@ -16,6 +16,13 @@ import (
|
|||||||
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
PaymentPlatformAlipay = "alipay"
|
||||||
|
PaymentPlatformWechat = "wechat"
|
||||||
|
OrderStatusPaid = "paid"
|
||||||
|
RefundNoPrefix = "refund-"
|
||||||
|
)
|
||||||
|
|
||||||
type AdminRefundOrderLogic struct {
|
type AdminRefundOrderLogic struct {
|
||||||
logx.Logger
|
logx.Logger
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
@ -31,37 +38,110 @@ func NewAdminRefundOrderLogic(ctx context.Context, svcCtx *svc.ServiceContext) *
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (l *AdminRefundOrderLogic) AdminRefundOrder(req *types.AdminRefundOrderReq) (resp *types.AdminRefundOrderResp, err error) {
|
func (l *AdminRefundOrderLogic) AdminRefundOrder(req *types.AdminRefundOrderReq) (resp *types.AdminRefundOrderResp, err error) {
|
||||||
// 获取订单信息
|
// 获取并验证订单
|
||||||
order, err := l.svcCtx.OrderModel.FindOne(l.ctx, req.Id)
|
order, err := l.getAndValidateOrder(req.Id, req.RefundAmount)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据支付平台处理退款
|
||||||
|
switch order.PaymentPlatform {
|
||||||
|
case PaymentPlatformAlipay:
|
||||||
|
return l.handleAlipayRefund(order, req)
|
||||||
|
case PaymentPlatformWechat:
|
||||||
|
return l.handleWechatRefund(order, req)
|
||||||
|
default:
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrMsg("不支持的支付平台"), "AdminRefundOrder, 不支持的支付平台: %s", order.PaymentPlatform)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// getAndValidateOrder 获取并验证订单信息
|
||||||
|
func (l *AdminRefundOrderLogic) getAndValidateOrder(orderId int64, refundAmount float64) (*model.Order, error) {
|
||||||
|
order, err := l.svcCtx.OrderModel.FindOne(l.ctx, orderId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "AdminRefundOrder, 查询订单失败 err: %v", err)
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "AdminRefundOrder, 查询订单失败 err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查订单状态
|
// 检查订单状态
|
||||||
if order.Status != "paid" {
|
if order.Status != OrderStatusPaid {
|
||||||
return nil, errors.Wrapf(xerr.NewErrMsg("订单状态不正确,无法退款"), "AdminRefundOrder, 订单状态不正确,无法退款 err: %v", err)
|
return nil, errors.Wrapf(xerr.NewErrMsg("订单状态不正确,无法退款"), "AdminRefundOrder, 订单状态: %s", order.Status)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查退款金额
|
// 检查退款金额
|
||||||
if req.RefundAmount > order.Amount {
|
if refundAmount > order.Amount {
|
||||||
return nil, errors.Wrapf(xerr.NewErrMsg("退款金额不能大于订单金额"), "AdminRefundOrder, 退款金额不能大于订单金额 err: %v", err)
|
return nil, errors.Wrapf(xerr.NewErrMsg("退款金额不能大于订单金额"), "AdminRefundOrder, 退款金额: %f, 订单金额: %f", refundAmount, order.Amount)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return order, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// handleAlipayRefund 处理支付宝退款
|
||||||
|
func (l *AdminRefundOrderLogic) handleAlipayRefund(order *model.Order, req *types.AdminRefundOrderReq) (*types.AdminRefundOrderResp, error) {
|
||||||
|
// 调用支付宝退款接口
|
||||||
refundResp, err := l.svcCtx.AlipayService.AliRefund(l.ctx, order.OrderNo, req.RefundAmount)
|
refundResp, err := l.svcCtx.AlipayService.AliRefund(l.ctx, order.OrderNo, req.RefundAmount)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "AdminRefundOrder, 退款失败 err: %v", err)
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "AdminRefundOrder, 支付宝退款失败 err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
refundNo := l.generateRefundNo(order.OrderNo)
|
||||||
|
|
||||||
if refundResp.IsSuccess() {
|
if refundResp.IsSuccess() {
|
||||||
err = l.svcCtx.OrderModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error {
|
// 支付宝退款成功,创建成功记录
|
||||||
|
err = l.createRefundRecordAndUpdateOrder(order, req, refundNo, refundResp.TradeNo, model.OrderStatusRefunded, model.OrderRefundStatusSuccess)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &types.AdminRefundOrderResp{
|
||||||
|
Status: model.OrderStatusRefunded,
|
||||||
|
RefundNo: refundNo,
|
||||||
|
Amount: req.RefundAmount,
|
||||||
|
}, nil
|
||||||
|
} else {
|
||||||
|
// 支付宝退款失败,创建失败记录但不更新订单状态
|
||||||
|
err = l.createRefundRecordOnly(order, req, refundNo, refundResp.TradeNo, model.OrderRefundStatusFailed)
|
||||||
|
if err != nil {
|
||||||
|
logx.Errorf("创建退款失败记录时出错: %v", err)
|
||||||
|
}
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrMsg(fmt.Sprintf("退款失败: %v", refundResp.Msg)), "AdminRefundOrder, 支付宝退款失败")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// handleWechatRefund 处理微信退款
|
||||||
|
func (l *AdminRefundOrderLogic) handleWechatRefund(order *model.Order, req *types.AdminRefundOrderReq) (*types.AdminRefundOrderResp, error) {
|
||||||
|
// 调用微信退款接口
|
||||||
|
err := l.svcCtx.WechatPayService.WeChatRefund(l.ctx, order.OrderNo, req.RefundAmount, order.Amount)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "AdminRefundOrder, 微信退款失败 err: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 微信退款是异步的,创建pending状态的退款记录
|
||||||
|
refundNo := l.generateRefundNo(order.OrderNo)
|
||||||
|
err = l.createRefundRecordAndUpdateOrder(order, req, refundNo, "", model.OrderStatusRefunding, model.OrderRefundStatusPending)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &types.AdminRefundOrderResp{
|
||||||
|
Status: model.OrderRefundStatusPending,
|
||||||
|
RefundNo: refundNo,
|
||||||
|
Amount: req.RefundAmount,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// createRefundRecordAndUpdateOrder 创建退款记录并更新订单状态
|
||||||
|
func (l *AdminRefundOrderLogic) createRefundRecordAndUpdateOrder(order *model.Order, req *types.AdminRefundOrderReq, refundNo, platformRefundId, orderStatus, refundStatus string) error {
|
||||||
|
return l.svcCtx.OrderModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error {
|
||||||
// 创建退款记录
|
// 创建退款记录
|
||||||
refund := &model.OrderRefund{
|
refund := &model.OrderRefund{
|
||||||
RefundNo: fmt.Sprintf("refund-%s", order.OrderNo),
|
RefundNo: refundNo,
|
||||||
PlatformRefundId: sql.NullString{String: refundResp.TradeNo, Valid: true},
|
PlatformRefundId: l.createNullString(platformRefundId),
|
||||||
OrderId: order.Id,
|
OrderId: order.Id,
|
||||||
UserId: order.UserId,
|
UserId: order.UserId,
|
||||||
ProductId: order.ProductId,
|
ProductId: order.ProductId,
|
||||||
RefundAmount: req.RefundAmount,
|
RefundAmount: req.RefundAmount,
|
||||||
RefundReason: sql.NullString{String: req.RefundReason, Valid: true},
|
RefundReason: l.createNullString(req.RefundReason),
|
||||||
Status: model.OrderRefundStatusPending,
|
Status: refundStatus, // 使用传入的状态,不再硬编码
|
||||||
RefundTime: sql.NullTime{Time: time.Now(), Valid: true},
|
RefundTime: sql.NullTime{Time: time.Now(), Valid: true},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,23 +150,46 @@ func (l *AdminRefundOrderLogic) AdminRefundOrder(req *types.AdminRefundOrderReq)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 更新订单状态
|
// 更新订单状态
|
||||||
order.Status = model.OrderStatusRefunded
|
order.Status = orderStatus
|
||||||
order.RefundTime = sql.NullTime{Time: time.Now(), Valid: true}
|
order.RefundTime = sql.NullTime{Time: time.Now(), Valid: true}
|
||||||
if _, err := l.svcCtx.OrderModel.Update(ctx, session, order); err != nil {
|
if _, err := l.svcCtx.OrderModel.Update(ctx, session, order); err != nil {
|
||||||
return fmt.Errorf("更新订单状态失败: %v", err)
|
return fmt.Errorf("更新订单状态失败: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "AdminRefundOrder, 退款失败 err: %v", err)
|
|
||||||
}
|
|
||||||
return &types.AdminRefundOrderResp{
|
|
||||||
Status: model.OrderStatusRefunded,
|
|
||||||
RefundNo: fmt.Sprintf("refund-%s", order.OrderNo),
|
|
||||||
Amount: req.RefundAmount,
|
|
||||||
}, nil
|
|
||||||
} else {
|
|
||||||
return nil, errors.Wrapf(xerr.NewErrMsg(fmt.Sprintf("退款失败, : %v", refundResp.Msg)), "AdminRefundOrder, 退款失败 err: %v", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// createRefundRecordOnly 仅创建退款记录,不更新订单状态(用于退款失败的情况)
|
||||||
|
func (l *AdminRefundOrderLogic) createRefundRecordOnly(order *model.Order, req *types.AdminRefundOrderReq, refundNo, platformRefundId, refundStatus string) error {
|
||||||
|
refund := &model.OrderRefund{
|
||||||
|
RefundNo: refundNo,
|
||||||
|
PlatformRefundId: l.createNullString(platformRefundId),
|
||||||
|
OrderId: order.Id,
|
||||||
|
UserId: order.UserId,
|
||||||
|
ProductId: order.ProductId,
|
||||||
|
RefundAmount: req.RefundAmount,
|
||||||
|
RefundReason: l.createNullString(req.RefundReason),
|
||||||
|
Status: refundStatus,
|
||||||
|
RefundTime: sql.NullTime{Time: time.Now(), Valid: true},
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := l.svcCtx.OrderRefundModel.Insert(l.ctx, nil, refund)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("创建退款记录失败: %v", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// generateRefundNo 生成退款单号
|
||||||
|
func (l *AdminRefundOrderLogic) generateRefundNo(orderNo string) string {
|
||||||
|
return fmt.Sprintf("%s%s", RefundNoPrefix, orderNo)
|
||||||
|
}
|
||||||
|
|
||||||
|
// createNullString 创建 sql.NullString
|
||||||
|
func (l *AdminRefundOrderLogic) createNullString(value string) sql.NullString {
|
||||||
|
return sql.NullString{
|
||||||
|
String: value,
|
||||||
|
Valid: value != "",
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,12 +5,14 @@ import (
|
|||||||
"database/sql"
|
"database/sql"
|
||||||
"net/http"
|
"net/http"
|
||||||
"qnc-server/app/main/api/internal/svc"
|
"qnc-server/app/main/api/internal/svc"
|
||||||
|
"qnc-server/app/main/model"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/wechatpay-apiv3/wechatpay-go/services/refunddomestic"
|
"github.com/wechatpay-apiv3/wechatpay-go/services/refunddomestic"
|
||||||
"github.com/zeromicro/go-zero/core/logx"
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||||
)
|
)
|
||||||
|
|
||||||
type WechatPayRefundCallbackLogic struct {
|
type WechatPayRefundCallbackLogic struct {
|
||||||
@ -34,21 +36,71 @@ func (l *WechatPayRefundCallbackLogic) handleQueryOrderRefund(orderNo string, st
|
|||||||
return errors.Wrapf(err, "查找查询订单信息失败: %s", orderNo)
|
return errors.Wrapf(err, "查找查询订单信息失败: %s", orderNo)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 只处理成功和失败状态
|
||||||
|
var orderStatus, refundStatus string
|
||||||
|
switch status {
|
||||||
|
case refunddomestic.STATUS_SUCCESS:
|
||||||
|
orderStatus = model.OrderStatusRefunded
|
||||||
|
refundStatus = model.OrderRefundStatusSuccess
|
||||||
|
case refunddomestic.STATUS_CLOSED:
|
||||||
|
// 退款关闭,保持订单原状态,更新退款记录为失败
|
||||||
|
refundStatus = model.OrderRefundStatusFailed
|
||||||
|
case refunddomestic.STATUS_ABNORMAL:
|
||||||
|
// 退款异常,保持订单原状态,更新退款记录为失败
|
||||||
|
refundStatus = model.OrderRefundStatusFailed
|
||||||
|
default:
|
||||||
|
// 其他状态暂不处理
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用事务同时更新订单和退款记录
|
||||||
|
err = l.svcCtx.OrderModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error {
|
||||||
|
// 更新订单状态(仅在退款成功时更新)
|
||||||
if status == refunddomestic.STATUS_SUCCESS {
|
if status == refunddomestic.STATUS_SUCCESS {
|
||||||
order.Status = "refunded"
|
order.Status = orderStatus
|
||||||
order.RefundTime = sql.NullTime{
|
order.RefundTime = sql.NullTime{
|
||||||
Time: time.Now(),
|
Time: time.Now(),
|
||||||
Valid: true,
|
Valid: true,
|
||||||
}
|
}
|
||||||
} else if status == refunddomestic.STATUS_ABNORMAL {
|
if err := l.svcCtx.OrderModel.UpdateWithVersion(ctx, session, order); err != nil {
|
||||||
return nil // 异常状态直接返回
|
|
||||||
} else {
|
|
||||||
return nil // 其他状态直接返回
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := l.svcCtx.OrderModel.UpdateWithVersion(l.ctx, nil, order); err != nil {
|
|
||||||
return errors.Wrapf(err, "更新查询订单状态失败: %s", orderNo)
|
return errors.Wrapf(err, "更新查询订单状态失败: %s", orderNo)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新退款记录状态
|
||||||
|
refund, err := l.svcCtx.OrderRefundModel.FindOneByOrderId(ctx, order.Id)
|
||||||
|
if err != nil {
|
||||||
|
if err == model.ErrNotFound {
|
||||||
|
logx.Errorf("未找到订单对应的退款记录: orderNo=%s, orderId=%d", orderNo, order.Id)
|
||||||
|
return nil // 没有退款记录时不报错,只记录警告
|
||||||
|
}
|
||||||
|
return errors.Wrapf(err, "查找退款记录失败: orderNo=%s", orderNo)
|
||||||
|
}
|
||||||
|
|
||||||
|
refund.Status = refundStatus
|
||||||
|
if status == refunddomestic.STATUS_SUCCESS {
|
||||||
|
refund.RefundTime = sql.NullTime{
|
||||||
|
Time: time.Now(),
|
||||||
|
Valid: true,
|
||||||
|
}
|
||||||
|
} else if status == refunddomestic.STATUS_CLOSED {
|
||||||
|
refund.CloseTime = sql.NullTime{
|
||||||
|
Time: time.Now(),
|
||||||
|
Valid: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := l.svcCtx.OrderRefundModel.Update(ctx, session, refund); err != nil {
|
||||||
|
return errors.Wrapf(err, "更新退款记录状态失败: orderNo=%s", orderNo)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "更新订单和退款记录失败: %s", orderNo)
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@ import (
|
|||||||
"github.com/bytedance/sonic"
|
"github.com/bytedance/sonic"
|
||||||
"github.com/hibiken/asynq"
|
"github.com/hibiken/asynq"
|
||||||
"github.com/zeromicro/go-zero/core/logx"
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||||
)
|
)
|
||||||
|
|
||||||
type PaySuccessNotifyUserHandler struct {
|
type PaySuccessNotifyUserHandler struct {
|
||||||
@ -135,41 +136,132 @@ func (l *PaySuccessNotifyUserHandler) handleError(ctx context.Context, err error
|
|||||||
return asynq.SkipRetry
|
return asynq.SkipRetry
|
||||||
}
|
}
|
||||||
|
|
||||||
// 退款
|
// 发起退款并创建退款记录
|
||||||
|
refundErr := l.processRefund(ctx, order, "业务处理失败,自动退款")
|
||||||
|
if refundErr != nil {
|
||||||
|
logx.Errorf("退款处理失败,订单ID: %d, 错误: %v", order.Id, refundErr)
|
||||||
|
return asynq.SkipRetry
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return asynq.SkipRetry
|
||||||
|
}
|
||||||
|
|
||||||
|
// processRefund 处理退款逻辑
|
||||||
|
func (l *PaySuccessNotifyUserHandler) processRefund(ctx context.Context, order *model.Order, refundReason string) error {
|
||||||
|
refundNo := fmt.Sprintf("refund-%s", order.OrderNo)
|
||||||
|
|
||||||
if order.PaymentPlatform == "wechat" {
|
if order.PaymentPlatform == "wechat" {
|
||||||
|
// 微信退款(异步)
|
||||||
refundErr := l.svcCtx.WechatPayService.WeChatRefund(ctx, order.OrderNo, order.Amount, order.Amount)
|
refundErr := l.svcCtx.WechatPayService.WeChatRefund(ctx, order.OrderNo, order.Amount, order.Amount)
|
||||||
if refundErr != nil {
|
if refundErr != nil {
|
||||||
logx.Error(refundErr)
|
// 微信退款调用失败,创建失败记录
|
||||||
return asynq.SkipRetry
|
createRefundErr := l.createRefundRecord(ctx, order, refundNo, "", model.OrderRefundStatusFailed, refundReason)
|
||||||
|
if createRefundErr != nil {
|
||||||
|
logx.Errorf("创建微信退款失败记录时出错: %v", createRefundErr)
|
||||||
}
|
}
|
||||||
} else {
|
return refundErr
|
||||||
|
}
|
||||||
|
|
||||||
|
// 微信退款调用成功,创建pending记录并更新订单状态
|
||||||
|
return l.svcCtx.OrderModel.Trans(ctx, func(ctx context.Context, session sqlx.Session) error {
|
||||||
|
// 创建pending状态的退款记录
|
||||||
|
if err := l.createRefundRecordWithSession(ctx, session, order, refundNo, "", model.OrderRefundStatusPending, refundReason); err != nil {
|
||||||
|
return fmt.Errorf("创建微信退款记录失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新订单状态为退款中
|
||||||
|
order.Status = model.OrderStatusRefunding
|
||||||
|
order.RefundTime = sql.NullTime{Time: time.Now(), Valid: true}
|
||||||
|
if _, err := l.svcCtx.OrderModel.Update(ctx, session, order); err != nil {
|
||||||
|
return fmt.Errorf("更新订单状态失败: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
} else if order.PaymentPlatform == "alipay" {
|
||||||
|
// 支付宝退款(同步)
|
||||||
refund, refundErr := l.svcCtx.AlipayService.AliRefund(ctx, order.OrderNo, order.Amount)
|
refund, refundErr := l.svcCtx.AlipayService.AliRefund(ctx, order.OrderNo, order.Amount)
|
||||||
if refundErr != nil {
|
if refundErr != nil {
|
||||||
logx.Error(refundErr)
|
// 支付宝退款调用失败,创建失败记录
|
||||||
return asynq.SkipRetry
|
createRefundErr := l.createRefundRecord(ctx, order, refundNo, "", model.OrderRefundStatusFailed, refundReason)
|
||||||
|
if createRefundErr != nil {
|
||||||
|
logx.Errorf("创建支付宝退款失败记录时出错: %v", createRefundErr)
|
||||||
}
|
}
|
||||||
|
return refundErr
|
||||||
|
}
|
||||||
|
|
||||||
if refund.IsSuccess() {
|
if refund.IsSuccess() {
|
||||||
logx.Errorf("支付宝退款成功, orderID: %d", order.Id)
|
// 支付宝退款成功,创建成功记录并更新订单状态
|
||||||
// 更新订单状态为退款
|
return l.svcCtx.OrderModel.Trans(ctx, func(ctx context.Context, session sqlx.Session) error {
|
||||||
order.Status = "refunded"
|
// 创建成功状态的退款记录
|
||||||
order.RefundTime = sql.NullTime{
|
if err := l.createRefundRecordWithSession(ctx, session, order, refundNo, refund.TradeNo, model.OrderRefundStatusSuccess, refundReason); err != nil {
|
||||||
Time: time.Now(),
|
return fmt.Errorf("创建支付宝退款成功记录失败: %v", err)
|
||||||
Valid: true,
|
|
||||||
}
|
}
|
||||||
updateOrderErr := l.svcCtx.OrderModel.UpdateWithVersion(ctx, nil, order)
|
|
||||||
if updateOrderErr != nil {
|
// 更新订单状态为已退款
|
||||||
logx.Errorf("更新订单状态失败,订单ID: %d, 错误: %v", order.Id, updateOrderErr)
|
order.Status = model.OrderStatusRefunded
|
||||||
return fmt.Errorf("更新订单状态失败: %v", updateOrderErr)
|
order.RefundTime = sql.NullTime{Time: time.Now(), Valid: true}
|
||||||
|
if _, err := l.svcCtx.OrderModel.Update(ctx, session, order); err != nil {
|
||||||
|
return fmt.Errorf("更新订单状态失败: %v", err)
|
||||||
}
|
}
|
||||||
return asynq.SkipRetry
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
logx.Errorf("支付宝退款失败:%v", refundErr)
|
// 支付宝退款失败,创建失败记录
|
||||||
return asynq.SkipRetry
|
createRefundErr := l.createRefundRecord(ctx, order, refundNo, refund.TradeNo, model.OrderRefundStatusFailed, refundReason)
|
||||||
|
if createRefundErr != nil {
|
||||||
|
logx.Errorf("创建支付宝退款失败记录时出错: %v", createRefundErr)
|
||||||
|
}
|
||||||
|
return fmt.Errorf("支付宝退款失败: %s", refund.Msg)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return fmt.Errorf("不支持的支付平台: %s", order.PaymentPlatform)
|
||||||
}
|
}
|
||||||
// 直接成功
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// createRefundRecord 创建退款记录(无事务)
|
||||||
|
func (l *PaySuccessNotifyUserHandler) createRefundRecord(ctx context.Context, order *model.Order, refundNo, platformRefundId, status, reason string) error {
|
||||||
|
refund := &model.OrderRefund{
|
||||||
|
RefundNo: refundNo,
|
||||||
|
PlatformRefundId: l.createNullString(platformRefundId),
|
||||||
|
OrderId: order.Id,
|
||||||
|
UserId: order.UserId,
|
||||||
|
ProductId: order.ProductId,
|
||||||
|
RefundAmount: order.Amount,
|
||||||
|
RefundReason: l.createNullString(reason),
|
||||||
|
Status: status,
|
||||||
|
RefundTime: sql.NullTime{Time: time.Now(), Valid: true},
|
||||||
}
|
}
|
||||||
|
|
||||||
return asynq.SkipRetry
|
_, err := l.svcCtx.OrderRefundModel.Insert(ctx, nil, refund)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// createRefundRecordWithSession 创建退款记录(带事务)
|
||||||
|
func (l *PaySuccessNotifyUserHandler) createRefundRecordWithSession(ctx context.Context, session sqlx.Session, order *model.Order, refundNo, platformRefundId, status, reason string) error {
|
||||||
|
refund := &model.OrderRefund{
|
||||||
|
RefundNo: refundNo,
|
||||||
|
PlatformRefundId: l.createNullString(platformRefundId),
|
||||||
|
OrderId: order.Id,
|
||||||
|
UserId: order.UserId,
|
||||||
|
ProductId: order.ProductId,
|
||||||
|
RefundAmount: order.Amount,
|
||||||
|
RefundReason: l.createNullString(reason),
|
||||||
|
Status: status,
|
||||||
|
RefundTime: sql.NullTime{Time: time.Now(), Valid: true},
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := l.svcCtx.OrderRefundModel.Insert(ctx, session, refund)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// createNullString 创建 sql.NullString
|
||||||
|
func (l *PaySuccessNotifyUserHandler) createNullString(value string) sql.NullString {
|
||||||
|
return sql.NullString{
|
||||||
|
String: value,
|
||||||
|
Valid: value != "",
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,6 +45,7 @@ const (
|
|||||||
OrderStatusPaid = "paid"
|
OrderStatusPaid = "paid"
|
||||||
OrderStatusFailed = "failed"
|
OrderStatusFailed = "failed"
|
||||||
OrderStatusRefunded = "refunded"
|
OrderStatusRefunded = "refunded"
|
||||||
|
OrderStatusRefunding = "refunding"
|
||||||
OrderStatusClosed = "closed"
|
OrderStatusClosed = "closed"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user