This commit is contained in:
2026-03-04 20:07:41 +08:00
parent 6e3c268b82
commit 66d8d660f2
11 changed files with 272 additions and 89 deletions

View File

@@ -82,7 +82,8 @@ func (l *AdminRefundOrderLogic) handleAlipayRefund(order *model.Order, req *type
orderPayTime = &order.PayTime.Time
}
refundNo := l.generateRefundNo(order.OrderNo)
refundResp, err := l.svcCtx.AlipayService.AliRefund(l.ctx, order.OrderNo, req.RefundAmount, orderPayTime, refundNo)
// 按订单记录的商户号 payment_merchant 选择支付宝商户;老订单未写入时由 AliRefund 内部按时间区间兜底。
refundResp, err := l.svcCtx.AlipayService.AliRefund(l.ctx, order.PaymentMerchant, order.OrderNo, req.RefundAmount, orderPayTime, refundNo)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "AdminRefundOrder, 支付宝退款失败 err: %v", err)
}
@@ -146,6 +147,7 @@ func (l *AdminRefundOrderLogic) createRefundRecordAndUpdateOrder(order *model.Or
OrderId: order.Id,
UserId: order.UserId,
ProductId: order.ProductId,
PaymentMerchant: order.PaymentMerchant,
RefundAmount: req.RefundAmount,
RefundReason: l.createNullString(req.RefundReason),
Status: refundStatus, // 使用传入的状态,不再硬编码
@@ -174,6 +176,7 @@ func (l *AdminRefundOrderLogic) createRefundRecordOnly(order *model.Order, req *
OrderId: order.Id,
UserId: order.UserId,
ProductId: order.ProductId,
PaymentMerchant: order.PaymentMerchant,
RefundAmount: req.RefundAmount,
RefundReason: l.createNullString(req.RefundReason),
Status: refundStatus,

View File

@@ -32,22 +32,58 @@ func NewAlipayCallbackLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Al
}
func (l *AlipayCallbackLogic) AlipayCallback(w http.ResponseWriter, r *http.Request) error {
notification, err := l.svcCtx.AlipayService.HandleAliPaymentNotification(r)
if err != nil {
logx.Errorf("支付宝支付回调,%v", err)
// 先解析表单,拿到 out_trade_no 用于查找订单和对应商户号
if err := r.ParseForm(); err != nil {
logx.Errorf("支付宝支付回调,解析请求表单失败: %v", err)
return nil
}
// 根据订单号前缀判断订单类型
orderNo := notification.OutTradeNo
orderNo := r.FormValue("out_trade_no")
if orderNo == "" {
logx.Errorf("支付宝支付回调,缺少 out_trade_no")
return nil
}
// 根据订单号前缀判断订单类型,并查出对应商户标识
var merchant string
if strings.HasPrefix(orderNo, "Q_") {
// 查询订单处理
return l.handleQueryOrderPayment(w, notification)
// 查询订单
order, err := l.svcCtx.OrderModel.FindOneByOrderNo(l.ctx, orderNo)
if err != nil {
logx.Errorf("支付宝支付回调,查询订单失败: %v", err)
return nil
}
merchant = order.PaymentMerchant
} else if strings.HasPrefix(orderNo, "A_") {
// 代理会员订单处理
return l.handleAgentVipOrderPayment(w, notification)
// 代理会员订单
agentOrder, err := l.svcCtx.AgentMembershipRechargeOrderModel.FindOneByOrderNo(l.ctx, orderNo)
if err != nil {
logx.Errorf("支付宝支付回调,查询代理会员订单失败: %v", err)
return nil
}
merchant = agentOrder.PaymentMerchant
} else {
// 兼容旧订单,假设没有前缀的是查询订单
order, err := l.svcCtx.OrderModel.FindOneByOrderNo(l.ctx, orderNo)
if err != nil {
logx.Errorf("支付宝支付回调(旧订单),查询订单失败: %v", err)
return nil
}
merchant = order.PaymentMerchant
}
notification, err := l.svcCtx.AlipayService.HandleAliPaymentNotification(merchant, r.Form)
if err != nil {
logx.Errorf("支付宝支付回调,验签失败: %v", err)
return nil
}
// 再次根据订单号前缀分发到具体处理函数
if strings.HasPrefix(orderNo, "Q_") {
return l.handleQueryOrderPayment(w, notification)
} else if strings.HasPrefix(orderNo, "A_") {
return l.handleAgentVipOrderPayment(w, notification)
} else {
return l.handleQueryOrderPayment(w, notification)
}
}
@@ -218,9 +254,10 @@ func (l *AlipayCallbackLogic) handleRefund(order *model.AgentMembershipRechargeO
return refundErr
}
} else {
// 代理会员订单以创建时间为准,仅 [2026-01-25 16:38:17, 2026-02-02 18:26) 区间内订单走 bak 商户
// 支付宝退款按订单记录的商户号 payment_merchant 走对应商户
// 老订单若未写入商户号,则在 AliRefund 内按时间区间兜底。
orderPayTime := order.CreateTime
refund, refundErr := l.svcCtx.AlipayService.AliRefund(ctx, order.OrderNo, order.Amount, &orderPayTime, "")
refund, refundErr := l.svcCtx.AlipayService.AliRefund(ctx, order.PaymentMerchant, order.OrderNo, order.Amount, &orderPayTime, "")
if refundErr != nil {
return refundErr
}

View File

@@ -28,10 +28,11 @@ type PaymentLogic struct {
svcCtx *svc.ServiceContext
}
type PaymentTypeResp struct {
amount float64
outTradeNo string
description string
orderID int64
amount float64
outTradeNo string
description string
orderID int64
payMerchantID string
}
func NewPaymentLogic(ctx context.Context, svcCtx *svc.ServiceContext) *PaymentLogic {
@@ -79,7 +80,8 @@ func (l *PaymentLogic) Payment(req *types.PaymentReq) (resp *types.PaymentResp,
if req.PayMethod == "wechat" {
prepayData, createOrderErr = l.svcCtx.WechatPayService.CreateWechatOrder(l.ctx, paymentTypeResp.amount, paymentTypeResp.description, paymentTypeResp.outTradeNo)
} else if req.PayMethod == "alipay" {
prepayData, createOrderErr = l.svcCtx.AlipayService.CreateAlipayOrder(l.ctx, paymentTypeResp.amount, paymentTypeResp.description, paymentTypeResp.outTradeNo)
// 支付宝按订单写入的商户标识one/two创建支付订单
prepayData, createOrderErr = l.svcCtx.AlipayService.CreateAlipayOrder(l.ctx, paymentTypeResp.payMerchantID, paymentTypeResp.amount, paymentTypeResp.description, paymentTypeResp.outTradeNo)
} else if req.PayMethod == "appleiap" {
prepayData = l.svcCtx.ApplePayService.GetIappayAppID(paymentTypeResp.outTradeNo)
}
@@ -186,12 +188,24 @@ func (l *PaymentLogic) QueryOrderPayment(req *types.PaymentReq, session sqlx.Ses
amount = 0.01
}
var orderID int64
// 默认支付宝商户号为 one若为代理推广订单存在 AgentIdentifier则使用 two。
paymentMerchant := ""
if req.PayMethod == "alipay" {
if data.AgentIdentifier != "" {
paymentMerchant = "two"
} else {
paymentMerchant = "one"
}
}
order := model.Order{
OrderNo: outTradeNo,
UserId: userID,
ProductId: product.Id,
PaymentPlatform: req.PayMethod,
PaymentScene: "app",
PaymentMerchant: paymentMerchant,
Amount: amount,
Status: "pending",
}
@@ -228,7 +242,13 @@ func (l *PaymentLogic) QueryOrderPayment(req *types.PaymentReq, session sqlx.Ses
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "生成订单, 保存代理订单失败: %+v", agentOrderInsert)
}
}
return &PaymentTypeResp{amount: amount, outTradeNo: outTradeNo, description: product.ProductName, orderID: orderID}, nil
return &PaymentTypeResp{
amount: amount,
outTradeNo: outTradeNo,
description: product.ProductName,
orderID: orderID,
payMerchantID: paymentMerchant,
}, nil
}
func (l *PaymentLogic) AgentVipOrderPayment(req *types.PaymentReq, session sqlx.Session) (resp *PaymentTypeResp, err error) {
userID, getUidErr := ctxdata.GetUidFromCtx(l.ctx)
@@ -274,20 +294,32 @@ func (l *PaymentLogic) AgentVipOrderPayment(req *types.PaymentReq, session sqlx.
if user.Inside == 1 {
amount = 0.01
}
paymentMerchant := ""
if req.PayMethod == "alipay" {
paymentMerchant = "one"
}
agentMembershipRechargeOrder := model.AgentMembershipRechargeOrder{
OrderNo: req.Id,
UserId: userID,
AgentId: agentModel.Id,
Amount: amount,
PaymentMethod: req.PayMethod,
LevelName: agentVipCache.Type,
Status: "pending",
OrderNo: req.Id,
UserId: userID,
AgentId: agentModel.Id,
Amount: amount,
PaymentMethod: req.PayMethod,
PaymentMerchant: paymentMerchant,
LevelName: agentVipCache.Type,
Status: "pending",
}
_, err = l.svcCtx.AgentMembershipRechargeOrderModel.Insert(l.ctx, session, &agentMembershipRechargeOrder)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "生成订单, 保存代理会员充值订单失败: %+v", err)
}
return &PaymentTypeResp{amount: amount, outTradeNo: req.Id, description: fmt.Sprintf("%s代理会员充值", agentMembershipConfig.LevelName)}, nil
return &PaymentTypeResp{
amount: amount,
outTradeNo: req.Id,
description: fmt.Sprintf("%s代理会员充值", agentMembershipConfig.LevelName),
payMerchantID: paymentMerchant,
}, nil
}
func (l *PaymentLogic) agentParsing(agentIdentifier string) (*types.AgentIdentifier, error) {
key, decodeErr := hex.DecodeString("8e3e7a2f60edb49221e953b9c029ed10")

View File

@@ -221,9 +221,10 @@ func (l *WechatPayCallbackLogic) handleRefund(order *model.AgentMembershipRechar
return refundErr
}
} else {
// 代理会员订单以创建时间为准,仅 [2026-01-25 16:38:17, 2026-02-02 18:26) 区间内订单走 bak 商户
// 支付宝退款按订单记录的商户号 payment_merchant 走对应商户
// 老订单若未写入商户号,则在 AliRefund 内按时间区间兜底。
orderPayTime := order.CreateTime
refund, refundErr := l.svcCtx.AlipayService.AliRefund(ctx, order.OrderNo, order.Amount, &orderPayTime, "")
refund, refundErr := l.svcCtx.AlipayService.AliRefund(ctx, order.PaymentMerchant, order.OrderNo, order.Amount, &orderPayTime, "")
if refundErr != nil {
return refundErr
}

View File

@@ -322,12 +322,13 @@ func (l *PaySuccessNotifyUserHandler) handleError(ctx context.Context, err error
logx.Infof("已发起微信退款申请, orderID: %d, amount: %f", order.Id, order.Amount)
return asynq.SkipRetry
} else {
// 支付宝退款为同步结果,仅 [2026-01-25 16:38:17, 2026-02-02 18:26) 区间内订单走 bak 商户
// 支付宝退款为同步结果,优先按订单记录的 payment_merchant 选择商户
// 老订单若未写入商户号,则在 AliRefund 内按时间区间兜底。
orderPayTime := &order.CreateTime
if order.PayTime.Valid {
orderPayTime = &order.PayTime.Time
}
refund, refundErr := l.svcCtx.AlipayService.AliRefund(ctx, order.OrderNo, order.Amount, orderPayTime, "")
refund, refundErr := l.svcCtx.AlipayService.AliRefund(ctx, order.PaymentMerchant, order.OrderNo, order.Amount, orderPayTime, "")
if refundErr != nil {
logx.Error(refundErr)
return asynq.SkipRetry

View File

@@ -5,7 +5,7 @@ import (
"crypto/rand"
"encoding/hex"
"fmt"
"net/http"
"net/url"
"strconv"
"sync/atomic"
"time"
@@ -28,6 +28,28 @@ type AliPayService struct {
AlipayClientBak *alipay.Client // 仅用于 [2026-01-25 16:38:17, 2026-02-02 18:26) 区间内订单的退款
}
// clientForMerchant 根据商户标识与订单时间选择对应的支付宝 client。
// - merchant == "two" 且 Bak 存在:优先返回 Bak
// - merchant == "one" 或空:默认返回主商户;
// - merchant 为空且 orderPayTime 落在备份时间区间:兼容老订单,走 Bak。
func (a *AliPayService) clientForMerchant(merchant string, orderPayTime *time.Time) *alipay.Client {
// 显式指定 two则优先走 Bak
if merchant == "two" && a.AlipayClientBak != nil {
return a.AlipayClientBak
}
// 显式指定 one 或其他未知标识,一律走主商户
if merchant == "one" || merchant == "" {
// 对于老订单未写入 merchant 的情况,继续保留时间区间兜底逻辑
if merchant == "" && orderPayTime != nil && a.AlipayClientBak != nil &&
!orderPayTime.Before(AlipayBakRefundStart) && orderPayTime.Before(AlipayBakRefundEnd) {
return a.AlipayClientBak
}
return a.AlipayClient
}
// 兜底:未知标识时仍走主商户,避免因为配置问题导致整体不可用
return a.AlipayClient
}
// NewAliPayService 是一个构造函数,用于初始化 AliPayService
func NewAliPayService(c config.Config) *AliPayService {
client, err := alipay.New(c.Alipay.AppID, c.Alipay.PrivateKey, c.Alipay.IsProduction)
@@ -77,8 +99,8 @@ func NewAliPayService(c config.Config) *AliPayService {
return svc
}
func (a *AliPayService) CreateAlipayAppOrder(amount float64, subject string, outTradeNo string) (string, error) {
client := a.AlipayClient
func (a *AliPayService) CreateAlipayAppOrder(merchant string, amount float64, subject string, outTradeNo string) (string, error) {
client := a.clientForMerchant(merchant, nil)
totalAmount := lzUtils.ToAlipayAmount(amount)
// 构造移动支付请求
p := alipay.TradeAppPay{
@@ -101,8 +123,8 @@ func (a *AliPayService) CreateAlipayAppOrder(amount float64, subject string, out
}
// CreateAlipayH5Order 创建支付宝H5支付订单
func (a *AliPayService) CreateAlipayH5Order(amount float64, subject string, outTradeNo string) (string, error) {
client := a.AlipayClient
func (a *AliPayService) CreateAlipayH5Order(merchant string, amount float64, subject string, outTradeNo string) (string, error) {
client := a.clientForMerchant(merchant, nil)
totalAmount := lzUtils.ToAlipayAmount(amount)
// 构造H5支付请求
p := alipay.TradeWapPay{
@@ -124,8 +146,9 @@ func (a *AliPayService) CreateAlipayH5Order(amount float64, subject string, outT
return payUrl.String(), nil
}
// CreateAlipayOrder 根据平台类型创建支付宝支付订单
func (a *AliPayService) CreateAlipayOrder(ctx context.Context, amount float64, subject string, outTradeNo string) (string, error) {
// CreateAlipayOrder 根据平台类型和商户标识创建支付宝支付订单
// merchant: 商户标识,目前约定 "one"=主商户, "two"=备商户
func (a *AliPayService) CreateAlipayOrder(ctx context.Context, merchant string, amount float64, subject string, outTradeNo string) (string, error) {
// 根据 ctx 中的 platform 判断平台
platform, platformOk := ctx.Value("platform").(string)
if !platformOk {
@@ -134,23 +157,21 @@ func (a *AliPayService) CreateAlipayOrder(ctx context.Context, amount float64, s
switch platform {
case model.PlatformApp:
// 调用App支付的创建方法
return a.CreateAlipayAppOrder(amount, subject, outTradeNo)
return a.CreateAlipayAppOrder(merchant, amount, subject, outTradeNo)
case model.PlatformH5:
// 调用H5支付的创建方法并传入 returnUrl
return a.CreateAlipayH5Order(amount, subject, outTradeNo)
return a.CreateAlipayH5Order(merchant, amount, subject, outTradeNo)
default:
return "", fmt.Errorf("不支持的支付平台: %s", platform)
}
}
// AliRefund 发起支付宝退款。orderPayTime 为订单支付时间(或创建时间);仅当落在 [2026-01-25 16:38:17, 2026-02-02 18:26) 区间内时使用 bak 商户号,否则使用正式商户号;传 nil 则使用正式商户号。
// AliRefund 发起支付宝退款。
// merchant: 支付商户标识one/two。为空时按老逻辑仅在备份时间区间内使用 Bak。
// orderPayTime 为订单支付时间(或创建时间);用于老订单按时间区间选择商户;传 nil 则忽略时间区间。
// outRequestNo 为商户退款请求号,同一笔退款需唯一;传空则使用 "refund-"+outTradeNo重试时建议传入唯一号避免支付宝报重复。
func (a *AliPayService) AliRefund(ctx context.Context, outTradeNo string, refundAmount float64, orderPayTime *time.Time, outRequestNo string) (*alipay.TradeRefundRsp, error) {
client := a.AlipayClient
if orderPayTime != nil && a.AlipayClientBak != nil &&
!orderPayTime.Before(AlipayBakRefundStart) && orderPayTime.Before(AlipayBakRefundEnd) {
client = a.AlipayClientBak
}
func (a *AliPayService) AliRefund(ctx context.Context, merchant string, outTradeNo string, refundAmount float64, orderPayTime *time.Time, outRequestNo string) (*alipay.TradeRefundRsp, error) {
client := a.clientForMerchant(merchant, orderPayTime)
if outRequestNo == "" {
outRequestNo = fmt.Sprintf("refund-%s", outTradeNo)
@@ -168,27 +189,26 @@ func (a *AliPayService) AliRefund(ctx context.Context, outTradeNo string, refund
return refundResp, nil
}
// HandleAliPaymentNotification 支付宝支付回调
func (a *AliPayService) HandleAliPaymentNotification(r *http.Request) (*alipay.Notification, error) {
// 解析表单
err := r.ParseForm()
if err != nil {
return nil, fmt.Errorf("解析请求表单失败:%v", err)
}
// HandleAliPaymentNotification 支付宝支付回调验签。
// 由上层根据 out_trade_no 查出订单并传入对应商户标识 merchant。
func (a *AliPayService) HandleAliPaymentNotification(merchant string, form url.Values) (*alipay.Notification, error) {
client := a.clientForMerchant(merchant, nil)
// 解析并验证通知DecodeNotification 会自动验证签名
notification, err := a.AlipayClient.DecodeNotification(r.Form)
notification, err := client.DecodeNotification(form)
if err != nil {
return nil, fmt.Errorf("验证签名失败: %v", err)
}
return notification, nil
}
func (a *AliPayService) QueryOrderStatus(ctx context.Context, outTradeNo string) (*alipay.TradeQueryRsp, error) {
// QueryOrderStatus 按商户标识查询支付宝订单状态
func (a *AliPayService) QueryOrderStatus(ctx context.Context, merchant string, outTradeNo string) (*alipay.TradeQueryRsp, error) {
client := a.clientForMerchant(merchant, nil)
queryRequest := alipay.TradeQuery{
OutTradeNo: outTradeNo,
}
// 发起查询请求
resp, err := a.AlipayClient.TradeQuery(ctx, queryRequest)
resp, err := client.TradeQuery(ctx, queryRequest)
if err != nil {
return nil, fmt.Errorf("查询支付宝订单失败: %v", err)
}

View File

@@ -10,8 +10,6 @@ import (
"time"
"tyc-server/common/globalkey"
"github.com/Masterminds/squirrel"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/stores/builder"
@@ -19,6 +17,7 @@ import (
"github.com/zeromicro/go-zero/core/stores/sqlc"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"github.com/zeromicro/go-zero/core/stringx"
"tyc-server/common/globalkey"
)
var (
@@ -65,6 +64,7 @@ type (
LevelName string `db:"level_name"` // 会员级别,如 VIPSVIPnormal
Amount float64 `db:"amount"` // 充值金额
PaymentMethod string `db:"payment_method"` // 支付方式:支付宝,微信,苹果支付,其他
PaymentMerchant string `db:"payment_merchant"` // 支付商户标识,例如 one/two
OrderNo string `db:"order_no"` // 交易号
PlatformOrderId sql.NullString `db:"platform_order_id"` // 支付平台订单号
Status string `db:"status"`
@@ -89,11 +89,11 @@ func (m *defaultAgentMembershipRechargeOrderModel) Insert(ctx context.Context, s
tycAgentMembershipRechargeOrderOrderNoKey := fmt.Sprintf("%s%v", cacheTycAgentMembershipRechargeOrderOrderNoPrefix, data.OrderNo)
tycAgentMembershipRechargeOrderPlatformOrderIdKey := fmt.Sprintf("%s%v", cacheTycAgentMembershipRechargeOrderPlatformOrderIdPrefix, data.PlatformOrderId)
return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", m.table, agentMembershipRechargeOrderRowsExpectAutoSet)
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", m.table, agentMembershipRechargeOrderRowsExpectAutoSet)
if session != nil {
return session.ExecCtx(ctx, query, data.UserId, data.AgentId, data.LevelName, data.Amount, data.PaymentMethod, data.OrderNo, data.PlatformOrderId, data.Status, data.DeleteTime, data.DelState, data.Version)
return session.ExecCtx(ctx, query, data.UserId, data.AgentId, data.LevelName, data.Amount, data.PaymentMethod, data.PaymentMerchant, data.OrderNo, data.PlatformOrderId, data.Status, data.DeleteTime, data.DelState, data.Version)
}
return conn.ExecCtx(ctx, query, data.UserId, data.AgentId, data.LevelName, data.Amount, data.PaymentMethod, data.OrderNo, data.PlatformOrderId, data.Status, data.DeleteTime, data.DelState, data.Version)
return conn.ExecCtx(ctx, query, data.UserId, data.AgentId, data.LevelName, data.Amount, data.PaymentMethod, data.PaymentMerchant, data.OrderNo, data.PlatformOrderId, data.Status, data.DeleteTime, data.DelState, data.Version)
}, tycAgentMembershipRechargeOrderIdKey, tycAgentMembershipRechargeOrderOrderNoKey, tycAgentMembershipRechargeOrderPlatformOrderIdKey)
}
@@ -165,9 +165,9 @@ func (m *defaultAgentMembershipRechargeOrderModel) Update(ctx context.Context, s
return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, agentMembershipRechargeOrderRowsWithPlaceHolder)
if session != nil {
return session.ExecCtx(ctx, query, newData.UserId, newData.AgentId, newData.LevelName, newData.Amount, newData.PaymentMethod, newData.OrderNo, newData.PlatformOrderId, newData.Status, newData.DeleteTime, newData.DelState, newData.Version, newData.Id)
return session.ExecCtx(ctx, query, newData.UserId, newData.AgentId, newData.LevelName, newData.Amount, newData.PaymentMethod, newData.PaymentMerchant, newData.OrderNo, newData.PlatformOrderId, newData.Status, newData.DeleteTime, newData.DelState, newData.Version, newData.Id)
}
return conn.ExecCtx(ctx, query, newData.UserId, newData.AgentId, newData.LevelName, newData.Amount, newData.PaymentMethod, newData.OrderNo, newData.PlatformOrderId, newData.Status, newData.DeleteTime, newData.DelState, newData.Version, newData.Id)
return conn.ExecCtx(ctx, query, newData.UserId, newData.AgentId, newData.LevelName, newData.Amount, newData.PaymentMethod, newData.PaymentMerchant, newData.OrderNo, newData.PlatformOrderId, newData.Status, newData.DeleteTime, newData.DelState, newData.Version, newData.Id)
}, tycAgentMembershipRechargeOrderIdKey, tycAgentMembershipRechargeOrderOrderNoKey, tycAgentMembershipRechargeOrderPlatformOrderIdKey)
}
@@ -189,9 +189,9 @@ func (m *defaultAgentMembershipRechargeOrderModel) UpdateWithVersion(ctx context
sqlResult, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
query := fmt.Sprintf("update %s set %s where `id` = ? and version = ? ", m.table, agentMembershipRechargeOrderRowsWithPlaceHolder)
if session != nil {
return session.ExecCtx(ctx, query, newData.UserId, newData.AgentId, newData.LevelName, newData.Amount, newData.PaymentMethod, newData.OrderNo, newData.PlatformOrderId, newData.Status, newData.DeleteTime, newData.DelState, newData.Version, newData.Id, oldVersion)
return session.ExecCtx(ctx, query, newData.UserId, newData.AgentId, newData.LevelName, newData.Amount, newData.PaymentMethod, newData.PaymentMerchant, newData.OrderNo, newData.PlatformOrderId, newData.Status, newData.DeleteTime, newData.DelState, newData.Version, newData.Id, oldVersion)
}
return conn.ExecCtx(ctx, query, newData.UserId, newData.AgentId, newData.LevelName, newData.Amount, newData.PaymentMethod, newData.OrderNo, newData.PlatformOrderId, newData.Status, newData.DeleteTime, newData.DelState, newData.Version, newData.Id, oldVersion)
return conn.ExecCtx(ctx, query, newData.UserId, newData.AgentId, newData.LevelName, newData.Amount, newData.PaymentMethod, newData.PaymentMerchant, newData.OrderNo, newData.PlatformOrderId, newData.Status, newData.DeleteTime, newData.DelState, newData.Version, newData.Id, oldVersion)
}, tycAgentMembershipRechargeOrderIdKey, tycAgentMembershipRechargeOrderOrderNoKey, tycAgentMembershipRechargeOrderPlatformOrderIdKey)
if err != nil {
return err

View File

@@ -10,8 +10,6 @@ import (
"time"
"tyc-server/common/globalkey"
"github.com/Masterminds/squirrel"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/stores/builder"
@@ -19,6 +17,7 @@ import (
"github.com/zeromicro/go-zero/core/stores/sqlc"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"github.com/zeromicro/go-zero/core/stringx"
"tyc-server/common/globalkey"
)
var (
@@ -63,6 +62,7 @@ type (
ProductId int64 `db:"product_id"` // 产品ID软关联到产品表
PaymentPlatform string `db:"payment_platform"` // 支付平台(支付宝、微信、苹果内购、其他)
PaymentScene string `db:"payment_scene"` // 支付场景App、H5、微信小程序、公众号
PaymentMerchant string `db:"payment_merchant"` // 支付商户标识,例如 one/two
PlatformOrderId sql.NullString `db:"platform_order_id"` // 支付平台订单号
Amount float64 `db:"amount"` // 支付金额
Status string `db:"status"` // 支付状态
@@ -90,11 +90,11 @@ func (m *defaultOrderModel) Insert(ctx context.Context, session sqlx.Session, da
tycOrderIdKey := fmt.Sprintf("%s%v", cacheTycOrderIdPrefix, data.Id)
tycOrderOrderNoKey := fmt.Sprintf("%s%v", cacheTycOrderOrderNoPrefix, data.OrderNo)
return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", m.table, orderRowsExpectAutoSet)
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", m.table, orderRowsExpectAutoSet)
if session != nil {
return session.ExecCtx(ctx, query, data.OrderNo, data.UserId, data.ProductId, data.PaymentPlatform, data.PaymentScene, data.PlatformOrderId, data.Amount, data.Status, data.DelState, data.Version, data.PayTime, data.RefundTime, data.CloseTime, data.DeleteTime, data.SalesCost)
return session.ExecCtx(ctx, query, data.OrderNo, data.UserId, data.ProductId, data.PaymentPlatform, data.PaymentScene, data.PaymentMerchant, data.PlatformOrderId, data.Amount, data.Status, data.DelState, data.Version, data.PayTime, data.RefundTime, data.CloseTime, data.DeleteTime, data.SalesCost)
}
return conn.ExecCtx(ctx, query, data.OrderNo, data.UserId, data.ProductId, data.PaymentPlatform, data.PaymentScene, data.PlatformOrderId, data.Amount, data.Status, data.DelState, data.Version, data.PayTime, data.RefundTime, data.CloseTime, data.DeleteTime, data.SalesCost)
return conn.ExecCtx(ctx, query, data.OrderNo, data.UserId, data.ProductId, data.PaymentPlatform, data.PaymentScene, data.PaymentMerchant, data.PlatformOrderId, data.Amount, data.Status, data.DelState, data.Version, data.PayTime, data.RefundTime, data.CloseTime, data.DeleteTime, data.SalesCost)
}, tycOrderIdKey, tycOrderOrderNoKey)
}
@@ -145,9 +145,9 @@ func (m *defaultOrderModel) Update(ctx context.Context, session sqlx.Session, ne
return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, orderRowsWithPlaceHolder)
if session != nil {
return session.ExecCtx(ctx, query, newData.OrderNo, newData.UserId, newData.ProductId, newData.PaymentPlatform, newData.PaymentScene, newData.PlatformOrderId, newData.Amount, newData.Status, newData.DelState, newData.Version, newData.PayTime, newData.RefundTime, newData.CloseTime, newData.DeleteTime, newData.SalesCost, newData.Id)
return session.ExecCtx(ctx, query, newData.OrderNo, newData.UserId, newData.ProductId, newData.PaymentPlatform, newData.PaymentScene, newData.PaymentMerchant, newData.PlatformOrderId, newData.Amount, newData.Status, newData.DelState, newData.Version, newData.PayTime, newData.RefundTime, newData.CloseTime, newData.DeleteTime, newData.SalesCost, newData.Id)
}
return conn.ExecCtx(ctx, query, newData.OrderNo, newData.UserId, newData.ProductId, newData.PaymentPlatform, newData.PaymentScene, newData.PlatformOrderId, newData.Amount, newData.Status, newData.DelState, newData.Version, newData.PayTime, newData.RefundTime, newData.CloseTime, newData.DeleteTime, newData.SalesCost, newData.Id)
return conn.ExecCtx(ctx, query, newData.OrderNo, newData.UserId, newData.ProductId, newData.PaymentPlatform, newData.PaymentScene, newData.PaymentMerchant, newData.PlatformOrderId, newData.Amount, newData.Status, newData.DelState, newData.Version, newData.PayTime, newData.RefundTime, newData.CloseTime, newData.DeleteTime, newData.SalesCost, newData.Id)
}, tycOrderIdKey, tycOrderOrderNoKey)
}
@@ -168,9 +168,9 @@ func (m *defaultOrderModel) UpdateWithVersion(ctx context.Context, session sqlx.
sqlResult, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
query := fmt.Sprintf("update %s set %s where `id` = ? and version = ? ", m.table, orderRowsWithPlaceHolder)
if session != nil {
return session.ExecCtx(ctx, query, newData.OrderNo, newData.UserId, newData.ProductId, newData.PaymentPlatform, newData.PaymentScene, newData.PlatformOrderId, newData.Amount, newData.Status, newData.DelState, newData.Version, newData.PayTime, newData.RefundTime, newData.CloseTime, newData.DeleteTime, newData.SalesCost, newData.Id, oldVersion)
return session.ExecCtx(ctx, query, newData.OrderNo, newData.UserId, newData.ProductId, newData.PaymentPlatform, newData.PaymentScene, newData.PaymentMerchant, newData.PlatformOrderId, newData.Amount, newData.Status, newData.DelState, newData.Version, newData.PayTime, newData.RefundTime, newData.CloseTime, newData.DeleteTime, newData.SalesCost, newData.Id, oldVersion)
}
return conn.ExecCtx(ctx, query, newData.OrderNo, newData.UserId, newData.ProductId, newData.PaymentPlatform, newData.PaymentScene, newData.PlatformOrderId, newData.Amount, newData.Status, newData.DelState, newData.Version, newData.PayTime, newData.RefundTime, newData.CloseTime, newData.DeleteTime, newData.SalesCost, newData.Id, oldVersion)
return conn.ExecCtx(ctx, query, newData.OrderNo, newData.UserId, newData.ProductId, newData.PaymentPlatform, newData.PaymentScene, newData.PaymentMerchant, newData.PlatformOrderId, newData.Amount, newData.Status, newData.DelState, newData.Version, newData.PayTime, newData.RefundTime, newData.CloseTime, newData.DeleteTime, newData.SalesCost, newData.Id, oldVersion)
}, tycOrderIdKey, tycOrderOrderNoKey)
if err != nil {
return err

View File

@@ -10,8 +10,6 @@ import (
"time"
"tyc-server/common/globalkey"
"github.com/Masterminds/squirrel"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/stores/builder"
@@ -19,6 +17,7 @@ import (
"github.com/zeromicro/go-zero/core/stores/sqlc"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"github.com/zeromicro/go-zero/core/stringx"
"tyc-server/common/globalkey"
)
var (
@@ -64,6 +63,7 @@ type (
OrderId int64 `db:"order_id"` // 关联的订单ID
UserId int64 `db:"user_id"` // 用户ID
ProductId int64 `db:"product_id"` // 产品ID
PaymentMerchant string `db:"payment_merchant"` // 退款对应的支付商户标识,例如 one/two
PlatformRefundId sql.NullString `db:"platform_refund_id"` // 支付平台退款单号
RefundAmount float64 `db:"refund_amount"` // 退款金额
RefundReason sql.NullString `db:"refund_reason"` // 退款原因
@@ -91,11 +91,11 @@ func (m *defaultOrderRefundModel) Insert(ctx context.Context, session sqlx.Sessi
tycOrderRefundPlatformRefundIdKey := fmt.Sprintf("%s%v", cacheTycOrderRefundPlatformRefundIdPrefix, data.PlatformRefundId)
tycOrderRefundRefundNoKey := fmt.Sprintf("%s%v", cacheTycOrderRefundRefundNoPrefix, data.RefundNo)
return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", m.table, orderRefundRowsExpectAutoSet)
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", m.table, orderRefundRowsExpectAutoSet)
if session != nil {
return session.ExecCtx(ctx, query, data.RefundNo, data.OrderId, data.UserId, data.ProductId, data.PlatformRefundId, data.RefundAmount, data.RefundReason, data.Status, data.DelState, data.Version, data.RefundTime, data.CloseTime, data.DeleteTime)
return session.ExecCtx(ctx, query, data.RefundNo, data.OrderId, data.UserId, data.ProductId, data.PaymentMerchant, data.PlatformRefundId, data.RefundAmount, data.RefundReason, data.Status, data.DelState, data.Version, data.RefundTime, data.CloseTime, data.DeleteTime)
}
return conn.ExecCtx(ctx, query, data.RefundNo, data.OrderId, data.UserId, data.ProductId, data.PlatformRefundId, data.RefundAmount, data.RefundReason, data.Status, data.DelState, data.Version, data.RefundTime, data.CloseTime, data.DeleteTime)
return conn.ExecCtx(ctx, query, data.RefundNo, data.OrderId, data.UserId, data.ProductId, data.PaymentMerchant, data.PlatformRefundId, data.RefundAmount, data.RefundReason, data.Status, data.DelState, data.Version, data.RefundTime, data.CloseTime, data.DeleteTime)
}, tycOrderRefundIdKey, tycOrderRefundPlatformRefundIdKey, tycOrderRefundRefundNoKey)
}
@@ -167,9 +167,9 @@ func (m *defaultOrderRefundModel) Update(ctx context.Context, session sqlx.Sessi
return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, orderRefundRowsWithPlaceHolder)
if session != nil {
return session.ExecCtx(ctx, query, newData.RefundNo, newData.OrderId, newData.UserId, newData.ProductId, newData.PlatformRefundId, newData.RefundAmount, newData.RefundReason, newData.Status, newData.DelState, newData.Version, newData.RefundTime, newData.CloseTime, newData.DeleteTime, newData.Id)
return session.ExecCtx(ctx, query, newData.RefundNo, newData.OrderId, newData.UserId, newData.ProductId, newData.PaymentMerchant, newData.PlatformRefundId, newData.RefundAmount, newData.RefundReason, newData.Status, newData.DelState, newData.Version, newData.RefundTime, newData.CloseTime, newData.DeleteTime, newData.Id)
}
return conn.ExecCtx(ctx, query, newData.RefundNo, newData.OrderId, newData.UserId, newData.ProductId, newData.PlatformRefundId, newData.RefundAmount, newData.RefundReason, newData.Status, newData.DelState, newData.Version, newData.RefundTime, newData.CloseTime, newData.DeleteTime, newData.Id)
return conn.ExecCtx(ctx, query, newData.RefundNo, newData.OrderId, newData.UserId, newData.ProductId, newData.PaymentMerchant, newData.PlatformRefundId, newData.RefundAmount, newData.RefundReason, newData.Status, newData.DelState, newData.Version, newData.RefundTime, newData.CloseTime, newData.DeleteTime, newData.Id)
}, tycOrderRefundIdKey, tycOrderRefundPlatformRefundIdKey, tycOrderRefundRefundNoKey)
}
@@ -191,9 +191,9 @@ func (m *defaultOrderRefundModel) UpdateWithVersion(ctx context.Context, session
sqlResult, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
query := fmt.Sprintf("update %s set %s where `id` = ? and version = ? ", m.table, orderRefundRowsWithPlaceHolder)
if session != nil {
return session.ExecCtx(ctx, query, newData.RefundNo, newData.OrderId, newData.UserId, newData.ProductId, newData.PlatformRefundId, newData.RefundAmount, newData.RefundReason, newData.Status, newData.DelState, newData.Version, newData.RefundTime, newData.CloseTime, newData.DeleteTime, newData.Id, oldVersion)
return session.ExecCtx(ctx, query, newData.RefundNo, newData.OrderId, newData.UserId, newData.ProductId, newData.PaymentMerchant, newData.PlatformRefundId, newData.RefundAmount, newData.RefundReason, newData.Status, newData.DelState, newData.Version, newData.RefundTime, newData.CloseTime, newData.DeleteTime, newData.Id, oldVersion)
}
return conn.ExecCtx(ctx, query, newData.RefundNo, newData.OrderId, newData.UserId, newData.ProductId, newData.PlatformRefundId, newData.RefundAmount, newData.RefundReason, newData.Status, newData.DelState, newData.Version, newData.RefundTime, newData.CloseTime, newData.DeleteTime, newData.Id, oldVersion)
return conn.ExecCtx(ctx, query, newData.RefundNo, newData.OrderId, newData.UserId, newData.ProductId, newData.PaymentMerchant, newData.PlatformRefundId, newData.RefundAmount, newData.RefundReason, newData.Status, newData.DelState, newData.Version, newData.RefundTime, newData.CloseTime, newData.DeleteTime, newData.Id, oldVersion)
}, tycOrderRefundIdKey, tycOrderRefundPlatformRefundIdKey, tycOrderRefundRefundNoKey)
if err != nil {
return err

View File

@@ -5,7 +5,7 @@ $DB_URL = "tyc:5vg67b3UNHu8@tcp(127.0.0.1:22001)/tyc"
$OUTPUT_DIR = "./model"
$TEMPLATE_DIR = "../template"
# 表名列表
# 表名列表(按需开启)
$tables = @(
# "agent"
# "agent_active_stat",
@@ -16,7 +16,7 @@ $tables = @(
# "agent_commission_deduction"
# "agent_link",
# "agent_membership_config",
# "agent_membership_recharge_order"
"agent_membership_recharge_order"
# "agent_membership_user_config",
# "agent_order",
# "agent_platform_deduction"
@@ -29,15 +29,15 @@ $tables = @(
# "agent_withdrawal_tax_exemption"
# "feature"
# "global_notifications"
# "order"
# "order_refund"
"order"
"order_refund"
# "product",
# "product_feature"
# "query",
# "query_cleanup_log"
# "query_cleanup_detail"
# "query_cleanup_config"
"user"
# "user"
# "user_auth"
# "user_temp"
# "example"
@@ -55,7 +55,6 @@ $tables = @(
# "admin_promotion_link_stats_history"
# "admin_promotion_order"
# "query_user_record"
)
# 为每个表生成模型

90
deploy/script/m.sql Normal file
View File

@@ -0,0 +1,90 @@
-- =========================
-- 1. 表结构变更:新增 payment_merchant
-- =========================
-- 1.1 order 表:增加支付商户标识
ALTER TABLE `order`
ADD COLUMN `payment_merchant` varchar(64) NOT NULL DEFAULT '' COMMENT '支付商户标识,例如 one/two' AFTER `payment_scene`;
-- 1.2 order_refund 表:增加支付商户标识
ALTER TABLE `order_refund`
ADD COLUMN `payment_merchant` varchar(64) NOT NULL DEFAULT '' COMMENT '退款对应的支付商户标识,例如 one/two' AFTER `product_id`;
-- 1.3 agent_membership_recharge_order 表:增加支付商户标识
ALTER TABLE `agent_membership_recharge_order`
ADD COLUMN `payment_merchant` varchar(64) NOT NULL DEFAULT '' COMMENT '支付商户标识,例如 one/two' AFTER `payment_method`;
-- =========================
-- 2. 历史数据初始化one / two
-- 约定:
-- - one当前主支付宝商户
-- - two当前 bak 支付宝商户
-- 时间区间:
-- [2026-01-25 16:38:17, 2026-02-02 18:26:00)
-- =========================
-- 2.1 order 表:按时间区间映射 one / two
-- 仅处理支付宝订单payment_platform='alipay'
-- 区间内用 two其余用 one
-- 时间优先用 pay_timepay_time 为空则用 create_time
-- 2.1.1 全部支付宝订单默认标记为 one
UPDATE `order`
SET
payment_merchant = 'one'
WHERE
payment_platform = 'alipay'
AND del_state = 0;
-- 2.1.2 区间内的支付宝订单标记为 two
UPDATE `order`
SET
payment_merchant = 'two'
WHERE
payment_platform = 'alipay'
AND del_state = 0
AND (
(
pay_time IS NOT NULL
AND pay_time >= '2026-01-25 16:38:17'
AND pay_time < '2026-02-02 18:26:00'
)
OR (
pay_time IS NULL
AND create_time >= '2026-01-25 16:38:17'
AND create_time < '2026-02-02 18:26:00'
)
);
-- 2.2 agent_membership_recharge_order 表:按创建时间映射 one / two
-- 仅处理支付宝支付payment_method='alipay'
-- 区间内创建的订单标记为 two其余为 one
-- 2.2.1 所有支付宝代理会员充值订单默认标记为 one
UPDATE `agent_membership_recharge_order`
SET
payment_merchant = 'one'
WHERE
payment_method = 'alipay'
AND del_state = 0;
-- 2.2.2 区间内的支付宝代理会员订单标记为 two
UPDATE `agent_membership_recharge_order`
SET
payment_merchant = 'two'
WHERE
payment_method = 'alipay'
AND del_state = 0
AND create_time >= '2026-01-25 16:38:17'
AND create_time < '2026-02-02 18:26:00';
-- 2.3 order_refund 表:跟随对应订单的 payment_merchant
-- 直接复制 order.payment_merchant避免逻辑重复
UPDATE `order_refund` r
JOIN `order` o ON r.order_id = o.id
SET
r.payment_merchant = o.payment_merchant
WHERE
r.del_state = 0
AND o.del_state = 0;