优化表结构,重构模型,重新实现基于白银网关的提取节点流程
This commit is contained in:
@@ -10,11 +10,8 @@ import (
|
||||
"platform/pkg/env"
|
||||
"platform/pkg/u"
|
||||
"platform/web/core"
|
||||
coupon2 "platform/web/domains/coupon"
|
||||
trade2 "platform/web/domains/trade"
|
||||
e "platform/web/events"
|
||||
g "platform/web/globals"
|
||||
"platform/web/globals/orm"
|
||||
m "platform/web/models"
|
||||
q "platform/web/queries"
|
||||
"time"
|
||||
@@ -53,7 +50,7 @@ func (s *tradeService) CreateTrade(uid int32, now time.Time, data *CreateTradeDa
|
||||
coupon, err := q.Coupon.
|
||||
Where(
|
||||
q.Coupon.Code.Eq(*data.CouponCode),
|
||||
q.Coupon.Status.Eq(int32(coupon2.StatusUnused)),
|
||||
q.Coupon.Status.Eq(int(m.CouponStatusUnused)),
|
||||
).
|
||||
Take()
|
||||
if err != nil {
|
||||
@@ -67,7 +64,7 @@ func (s *tradeService) CreateTrade(uid int32, now time.Time, data *CreateTradeDa
|
||||
if !expireAt.IsZero() && expireAt.Before(now) {
|
||||
_, err = q.Coupon.
|
||||
Where(q.Coupon.ID.Eq(coupon.ID)).
|
||||
Update(q.Coupon.Status, coupon2.StatusExpired)
|
||||
Update(q.Coupon.Status, m.CouponStatusExpired)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -86,7 +83,7 @@ func (s *tradeService) CreateTrade(uid int32, now time.Time, data *CreateTradeDa
|
||||
if expireAt.IsZero() {
|
||||
_, err = q.Coupon.
|
||||
Where(q.Coupon.ID.Eq(coupon.ID)).
|
||||
Update(q.Coupon.Status, int32(coupon2.StatusUsed))
|
||||
Update(q.Coupon.Status, int(m.CouponStatusUsed))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -112,7 +109,7 @@ func (s *tradeService) CreateTrade(uid int32, now time.Time, data *CreateTradeDa
|
||||
switch {
|
||||
|
||||
// 支付宝 + 电脑网站
|
||||
case method == trade2.MethodAlipay && platform == trade2.PlatformDesktop:
|
||||
case method == m.TradeMethodAlipay && platform == m.TradePlatformPC:
|
||||
resp, err := g.Alipay.TradePagePay(alipay.TradePagePay{
|
||||
QRPayMode: "4",
|
||||
QRCodeWidth: "196", // 二维码宽度需要-4,支付宝页面布局有问题
|
||||
@@ -130,7 +127,7 @@ func (s *tradeService) CreateTrade(uid int32, now time.Time, data *CreateTradeDa
|
||||
paymentUrl = resp.String()
|
||||
|
||||
// 微信 + 电脑网站
|
||||
case method == trade2.MethodWeChat && platform == trade2.PlatformDesktop:
|
||||
case method == m.TradeMethodWechat && platform == m.TradePlatformPC:
|
||||
resp, _, err := g.WechatPay.Native.Prepay(context.Background(), native.PrepayRequest{
|
||||
Appid: &env.WechatPayAppId,
|
||||
Mchid: &env.WechatPayMchId,
|
||||
@@ -149,14 +146,14 @@ func (s *tradeService) CreateTrade(uid int32, now time.Time, data *CreateTradeDa
|
||||
|
||||
// 商福通 + 电脑网站
|
||||
case
|
||||
method == trade2.MethodSftAlipay && platform == trade2.PlatformDesktop,
|
||||
method == trade2.MethodSftWeChat && platform == trade2.PlatformDesktop:
|
||||
method == m.TradeMethodSftAlipay && platform == m.TradePlatformPC,
|
||||
method == m.TradeMethodSftWechat && platform == m.TradePlatformPC:
|
||||
|
||||
var payType g.SftPayType
|
||||
switch method {
|
||||
case trade2.MethodSftAlipay:
|
||||
case m.TradeMethodSftAlipay:
|
||||
payType = g.SftAlipay
|
||||
case trade2.MethodSftWeChat:
|
||||
case m.TradeMethodSftWechat:
|
||||
payType = g.SftWeChat
|
||||
default:
|
||||
panic("unhandled default case")
|
||||
@@ -178,13 +175,13 @@ func (s *tradeService) CreateTrade(uid int32, now time.Time, data *CreateTradeDa
|
||||
|
||||
// 商福通 + 手机网站
|
||||
case
|
||||
method == trade2.MethodSftAlipay && platform == trade2.PlatformMobile,
|
||||
method == trade2.MethodSftWeChat && platform == trade2.PlatformMobile:
|
||||
method == m.TradeMethodSftAlipay && platform == m.TradePlatformMobile,
|
||||
method == m.TradeMethodSftWechat && platform == m.TradePlatformMobile:
|
||||
var payType g.SftPayType
|
||||
switch method {
|
||||
case trade2.MethodSftAlipay:
|
||||
case m.TradeMethodSftAlipay:
|
||||
payType = g.SftAlipay
|
||||
case trade2.MethodSftWeChat:
|
||||
case m.TradeMethodSftWechat:
|
||||
payType = g.SftWeChat
|
||||
default:
|
||||
panic("unhandled default case")
|
||||
@@ -214,11 +211,11 @@ func (s *tradeService) CreateTrade(uid int32, now time.Time, data *CreateTradeDa
|
||||
err = q.Trade.Create(&m.Trade{
|
||||
UserID: uid,
|
||||
InnerNo: tradeNo,
|
||||
Type: int32(tType),
|
||||
Type: tType,
|
||||
Subject: subject,
|
||||
Amount: amount,
|
||||
Method: int32(method),
|
||||
Platform: int32(platform),
|
||||
Method: method,
|
||||
Platform: platform,
|
||||
PaymentURL: &paymentUrl,
|
||||
})
|
||||
if err != nil {
|
||||
@@ -266,11 +263,11 @@ func (s *tradeService) CompleteTrade(data *ModifyTradeData) error {
|
||||
if err != nil {
|
||||
return core.NewServErr("检查订单状态失败", err)
|
||||
}
|
||||
if result.Status != trade2.StatusSuccess {
|
||||
if result.Status != m.TradeStatusSuccess {
|
||||
switch result.Status {
|
||||
case trade2.StatusPending:
|
||||
case m.TradeStatusPending:
|
||||
return core.NewBizErr("订单未支付")
|
||||
case trade2.StatusCanceled:
|
||||
case m.TradeStatusCanceled:
|
||||
return core.NewBizErr("订单已过期")
|
||||
}
|
||||
}
|
||||
@@ -331,22 +328,22 @@ func completeTrade(data *OnTradeCompletedData) (*m.Trade, error) {
|
||||
}
|
||||
|
||||
// 检查交易状态
|
||||
switch trade2.Status(trade.Status) {
|
||||
case trade2.StatusCanceled:
|
||||
switch trade.Status {
|
||||
case m.TradeStatusCanceled:
|
||||
return core.NewBizErr("交易已取消")
|
||||
case trade2.StatusSuccess:
|
||||
case m.TradeStatusSuccess:
|
||||
return nil // 跳过更新交易信息
|
||||
case trade2.StatusPending:
|
||||
case m.TradeStatusPending:
|
||||
}
|
||||
|
||||
// 更新交易信息
|
||||
trade.Status = int32(trade2.StatusSuccess)
|
||||
trade.Status = m.TradeStatusSuccess
|
||||
trade.OuterNo = &transId
|
||||
trade.Payment = payment
|
||||
trade.Acquirer = u.P(int32(acquirer))
|
||||
trade.CompletedAt = u.P(orm.LocalDateTime(paidAt))
|
||||
trade.Acquirer = u.P(acquirer)
|
||||
trade.CompletedAt = u.P(paidAt)
|
||||
rs, err := q.Trade.
|
||||
Where(q.Trade.InnerNo.Eq(tradeNo), q.Trade.Status.Eq(int32(trade2.StatusPending))).
|
||||
Where(q.Trade.InnerNo.Eq(tradeNo), q.Trade.Status.Eq(int(m.TradeStatusPending))).
|
||||
Updates(trade)
|
||||
if rs.RowsAffected == 0 {
|
||||
return core.NewBizErr("交易状态已发生变化")
|
||||
@@ -372,13 +369,13 @@ func afterTradeComplete(trade *m.Trade) error {
|
||||
}
|
||||
|
||||
// 执行资源创建
|
||||
var ComplementEvents = []trade2.CompleteEvent{
|
||||
var ComplementEvents = []CompleteEvent{
|
||||
ResourceOnTradeComplete{},
|
||||
UserOnTradeComplete{},
|
||||
}
|
||||
|
||||
for _, event := range ComplementEvents {
|
||||
info, ok := event.Check(trade2.Type(trade.Type))
|
||||
info, ok := event.Check(trade.Type)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
@@ -405,7 +402,7 @@ func (s *tradeService) CancelTrade(data *ModifyTradeData, now time.Time) error {
|
||||
return g.Redsync.WithLock(tradeLockKey(tradeNo), func() error {
|
||||
switch method {
|
||||
|
||||
case trade2.MethodAlipay:
|
||||
case m.TradeMethodAlipay:
|
||||
resp, err := g.Alipay.TradeCancel(context.Background(), alipay.TradeCancel{
|
||||
OutTradeNo: tradeNo,
|
||||
})
|
||||
@@ -417,7 +414,7 @@ func (s *tradeService) CancelTrade(data *ModifyTradeData, now time.Time) error {
|
||||
return errors.New("上游取消交易失败")
|
||||
}
|
||||
|
||||
case trade2.MethodWeChat:
|
||||
case m.TradeMethodWechat:
|
||||
resp, err := g.WechatPay.Native.CloseOrder(context.Background(), native.CloseOrderRequest{
|
||||
Mchid: &env.WechatPayMchId,
|
||||
OutTradeNo: &tradeNo,
|
||||
@@ -435,7 +432,7 @@ func (s *tradeService) CancelTrade(data *ModifyTradeData, now time.Time) error {
|
||||
return errors.New("上游取消交易失败")
|
||||
}
|
||||
|
||||
case trade2.MethodSft, trade2.MethodSftAlipay, trade2.MethodSftWeChat:
|
||||
case m.TradeMethodSft, m.TradeMethodSftAlipay, m.TradeMethodSftWechat:
|
||||
_, err := g.SFTPay.OrderClose(&g.OrderCloseReq{
|
||||
MchOrderNo: &tradeNo,
|
||||
})
|
||||
@@ -468,7 +465,7 @@ func (s *tradeService) OnTradeCanceled(tradeNo string, now time.Time) error {
|
||||
func cancelTrade(tradeNo string, now time.Time) error {
|
||||
return q.Q.Transaction(func(q *q.Query) error {
|
||||
// 获取交易信息
|
||||
var status trade2.Status
|
||||
var status m.TradeStatus
|
||||
err := q.Trade.
|
||||
Where(q.Trade.InnerNo.Eq(tradeNo)).
|
||||
Select(q.Trade.Status).
|
||||
@@ -479,19 +476,19 @@ func cancelTrade(tradeNo string, now time.Time) error {
|
||||
|
||||
// 检查交易状态
|
||||
switch status {
|
||||
case trade2.StatusCanceled:
|
||||
case m.TradeStatusCanceled:
|
||||
return core.NewBizErr("交易已取消")
|
||||
case trade2.StatusSuccess:
|
||||
case m.TradeStatusSuccess:
|
||||
return core.NewBizErr("交易已完成")
|
||||
case trade2.StatusPending:
|
||||
case m.TradeStatusPending:
|
||||
}
|
||||
|
||||
// 更新交易状态
|
||||
_, err = q.Trade.
|
||||
Where(q.Trade.InnerNo.Eq(tradeNo)).
|
||||
UpdateSimple(
|
||||
q.Trade.Status.Value(int32(trade2.StatusCanceled)),
|
||||
q.Trade.CanceledAt.Value(orm.LocalDateTime(now)),
|
||||
q.Trade.Status.Value(int(m.TradeStatusCanceled)),
|
||||
q.Trade.CanceledAt.Value(now),
|
||||
)
|
||||
if err != nil {
|
||||
return core.NewServErr("更新交易状态失败", err)
|
||||
@@ -518,7 +515,7 @@ func (s *tradeService) CheckTrade(data *ModifyTradeData) (*CheckTradeResult, err
|
||||
switch method {
|
||||
|
||||
// 支付宝
|
||||
case trade2.MethodAlipay:
|
||||
case m.TradeMethodAlipay:
|
||||
|
||||
// 查询交易状态
|
||||
resp, err := g.Alipay.TradeQuery(context.Background(), alipay.TradeQuery{
|
||||
@@ -537,15 +534,15 @@ func (s *tradeService) CheckTrade(data *ModifyTradeData) (*CheckTradeResult, err
|
||||
switch resp.TradeStatus {
|
||||
|
||||
case alipay.TradeStatusWaitBuyerPay:
|
||||
result.Status = trade2.StatusPending
|
||||
result.Status = m.TradeStatusPending
|
||||
|
||||
case alipay.TradeStatusClosed:
|
||||
result.Status = trade2.StatusCanceled
|
||||
result.Status = m.TradeStatusCanceled
|
||||
|
||||
case alipay.TradeStatusSuccess, alipay.TradeStatusFinished:
|
||||
result.Status = trade2.StatusSuccess
|
||||
result.Status = m.TradeStatusSuccess
|
||||
result.Success = &TradeSuccessResult{}
|
||||
result.Success.Acquirer = trade2.AcquirerAlipay
|
||||
result.Success.Acquirer = m.TradeAcquirerAlipay
|
||||
result.Success.Payment, err = decimal.NewFromString(resp.TotalAmount)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -557,7 +554,7 @@ func (s *tradeService) CheckTrade(data *ModifyTradeData) (*CheckTradeResult, err
|
||||
}
|
||||
|
||||
// 微信
|
||||
case trade2.MethodWeChat:
|
||||
case m.TradeMethodWechat:
|
||||
|
||||
// 查询交易状态
|
||||
resp, _, err := g.WechatPay.Native.QueryOrderByOutTradeNo(context.Background(), native.QueryOrderByOutTradeNoRequest{
|
||||
@@ -583,15 +580,15 @@ func (s *tradeService) CheckTrade(data *ModifyTradeData) (*CheckTradeResult, err
|
||||
switch *resp.TradeState {
|
||||
|
||||
case "NOTPAY":
|
||||
result.Status = trade2.StatusPending
|
||||
result.Status = m.TradeStatusPending
|
||||
|
||||
case "CLOSED":
|
||||
result.Status = trade2.StatusCanceled
|
||||
result.Status = m.TradeStatusCanceled
|
||||
|
||||
case "SUCCESS", "REFUND":
|
||||
result.Status = trade2.StatusSuccess
|
||||
result.Status = m.TradeStatusSuccess
|
||||
result.Success = &TradeSuccessResult{}
|
||||
result.Success.Acquirer = trade2.AcquirerWeChat
|
||||
result.Success.Acquirer = m.TradeAcquirerWechat
|
||||
result.Success.Payment = decimal.NewFromInt(*resp.Amount.PayerTotal).Div(decimal.NewFromInt(100))
|
||||
result.Success.Time, err = time.Parse(time.RFC3339, *resp.SuccessTime)
|
||||
if err != nil {
|
||||
@@ -600,7 +597,7 @@ func (s *tradeService) CheckTrade(data *ModifyTradeData) (*CheckTradeResult, err
|
||||
}
|
||||
|
||||
// 商福通
|
||||
case trade2.MethodSft, trade2.MethodSftAlipay, trade2.MethodSftWeChat:
|
||||
case m.TradeMethodSft, m.TradeMethodSftAlipay, m.TradeMethodSftWechat:
|
||||
|
||||
// 查询交易状态
|
||||
resp, err := g.SFTPay.QueryTrade(&g.QueryTradeReq{
|
||||
@@ -619,21 +616,21 @@ func (s *tradeService) CheckTrade(data *ModifyTradeData) (*CheckTradeResult, err
|
||||
switch resp.State {
|
||||
|
||||
case g.SftInit, g.SftTradeAwait, g.SftTradeFail:
|
||||
result.Status = trade2.StatusPending
|
||||
result.Status = m.TradeStatusPending
|
||||
|
||||
case g.SftTradeClosed, g.SftTradeCancel:
|
||||
result.Status = trade2.StatusCanceled
|
||||
result.Status = m.TradeStatusCanceled
|
||||
|
||||
case g.SftTradeSuccess, g.SftTradeRefund, g.SftRefundIng:
|
||||
result.Status = trade2.StatusSuccess
|
||||
result.Status = m.TradeStatusSuccess
|
||||
result.Success = &TradeSuccessResult{}
|
||||
switch resp.PayType {
|
||||
case "WECHAT":
|
||||
result.Success.Acquirer = trade2.AcquirerWeChat
|
||||
result.Success.Acquirer = m.TradeAcquirerWechat
|
||||
case "ALIPAY":
|
||||
result.Success.Acquirer = trade2.AcquirerAlipay
|
||||
result.Success.Acquirer = m.TradeAcquirerAlipay
|
||||
case "UNIONPAY":
|
||||
result.Success.Acquirer = trade2.AcquirerUnionPay
|
||||
result.Success.Acquirer = m.TradeAcquirerUnionPay
|
||||
}
|
||||
result.Success.Payment = decimal.NewFromInt(resp.Amount).Div(decimal.NewFromInt(100))
|
||||
result.Success.Time, err = time.Parse("2006-01-02 15:04:05", *resp.PayTime)
|
||||
@@ -659,10 +656,10 @@ func tradeLockKey(no string) string {
|
||||
}
|
||||
|
||||
type CreateTradeData struct {
|
||||
Platform trade2.Platform `json:"platform" validate:"required"`
|
||||
Method trade2.Method `json:"method" validate:"required"`
|
||||
Platform m.TradePlatform `json:"platform" validate:"required"`
|
||||
Method m.TradeMethod `json:"method" validate:"required"`
|
||||
CouponCode *string `json:"coupon_code"`
|
||||
Product trade2.ProductInfo
|
||||
Product ProductInfo
|
||||
}
|
||||
|
||||
type CreateTradeResult struct {
|
||||
@@ -672,17 +669,17 @@ type CreateTradeResult struct {
|
||||
|
||||
type ModifyTradeData struct {
|
||||
TradeNo string `json:"trade_no" validate:"required"`
|
||||
Method trade2.Method `json:"method" validate:"required"`
|
||||
Method m.TradeMethod `json:"method" validate:"required"`
|
||||
}
|
||||
|
||||
type CheckTradeResult struct {
|
||||
TransId string
|
||||
Status trade2.Status
|
||||
Status m.TradeStatus
|
||||
Success *TradeSuccessResult
|
||||
}
|
||||
|
||||
type TradeSuccessResult struct {
|
||||
Acquirer trade2.Acquirer
|
||||
Acquirer m.TradeAcquirer
|
||||
Payment decimal.Decimal
|
||||
Time time.Time
|
||||
}
|
||||
@@ -693,6 +690,19 @@ type OnTradeCompletedData struct {
|
||||
*TradeSuccessResult
|
||||
}
|
||||
|
||||
type ProductInfo interface {
|
||||
GetType() m.TradeType
|
||||
GetSubject() string
|
||||
GetAmount() decimal.Decimal
|
||||
Serialize() (string, error)
|
||||
Deserialize(str string) error
|
||||
}
|
||||
|
||||
type CompleteEvent interface {
|
||||
Check(t m.TradeType) (ProductInfo, bool)
|
||||
OnTradeComplete(info ProductInfo, trade *m.Trade) error
|
||||
}
|
||||
|
||||
type TradeErr string
|
||||
|
||||
func (e TradeErr) Error() string {
|
||||
|
||||
Reference in New Issue
Block a user