554 lines
21 KiB
Go
554 lines
21 KiB
Go
package service
|
||
|
||
import (
|
||
"context"
|
||
"errors"
|
||
"fmt"
|
||
"gateway/internal/config"
|
||
"gateway/internal/consts"
|
||
"gateway/internal/models/accounts"
|
||
"gateway/internal/models/merchant"
|
||
"gateway/internal/models/notify"
|
||
"gateway/internal/models/order"
|
||
"gateway/internal/models/road"
|
||
"gateway/internal/otelTrace"
|
||
"gateway/internal/service/message"
|
||
"gateway/internal/utils"
|
||
"net/url"
|
||
"strconv"
|
||
"time"
|
||
|
||
"github.com/bytedance/gopkg/util/gopool"
|
||
"github.com/duke-git/lancet/v2/convertor"
|
||
"github.com/duke-git/lancet/v2/pointer"
|
||
"go.opentelemetry.io/otel/attribute"
|
||
"go.opentelemetry.io/otel/trace"
|
||
"go.uber.org/zap"
|
||
|
||
"github.com/beego/beego/v2/client/orm"
|
||
)
|
||
|
||
var (
|
||
orderNotify = gopool.NewPool("orderNotify", 20, gopool.NewConfig())
|
||
sendMessageNotify = gopool.NewPool("sendMessageNotify", 20, gopool.NewConfig())
|
||
)
|
||
|
||
// SolvePaySuccess 处理支付成功的加款等各项操作
|
||
func SolvePaySuccess(ctx context.Context, bankOrderId string, factAmount float64, trxNo string, cardReturnData string) bool {
|
||
ctx, cancel := otelTrace.Span(ctx, "订单处理", "SolvePayFail", trace.WithAttributes(
|
||
attribute.String("bankOrderId", bankOrderId),
|
||
attribute.String("cardReturnData", cardReturnData),
|
||
))
|
||
defer cancel()
|
||
o := orm.NewOrm()
|
||
err := o.DoTxWithCtx(ctx, func(ctx context.Context, txOrm orm.TxOrmer) error {
|
||
// 查找订单
|
||
var orderInfo order.OrderInfo
|
||
if err := txOrm.RawWithCtx(ctx, "select * from order_info where bank_order_id = ? for update", bankOrderId).
|
||
QueryRow(&orderInfo); err != nil || orderInfo.BankOrderId == "" {
|
||
otelTrace.Logger.WithContext(ctx).Error("不存在该订单,或者select for update出错")
|
||
return err
|
||
}
|
||
if orderInfo.Status == config.SUCCESS {
|
||
otelTrace.Logger.WithContext(ctx).Error("该订单已经处理,订单号=", zap.String("bankOrderId", bankOrderId))
|
||
return errors.New(fmt.Sprintf("该订单已经处理,订单号= %s", bankOrderId))
|
||
}
|
||
orderInfo.FactAmount = factAmount
|
||
orderInfo.Status = config.SUCCESS
|
||
orderInfo.BankTransId = trxNo
|
||
orderInfo.CardReturnData = cardReturnData
|
||
orderInfo.UpdateTime = time.Now()
|
||
if _, err := txOrm.UpdateWithCtx(ctx, &orderInfo); err != nil || orderInfo.BankOrderId == "" {
|
||
otelTrace.Logger.WithContext(ctx).Error(fmt.Sprintf("solve pay success, update order info fail: %s, bankOrderId = %s", err, bankOrderId))
|
||
return err
|
||
}
|
||
|
||
record, _ := GetRelateRecordByTargetOrderNo(ctx, bankOrderId)
|
||
if !pointer.IsNil(record) && record.Id != 0 {
|
||
// TODO: 判断是否偷卡(隐藏订单)
|
||
if err2 := UpdateRelateRecordSucceedStatus(ctx, bankOrderId, factAmount); err2 != nil {
|
||
otelTrace.Logger.WithContext(ctx).Error("【偷卡】更新偷卡记录失败", zap.Error(err2))
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// 查找订单表
|
||
var orderProfitInfo order.OrderProfitInfo
|
||
if err := txOrm.RawWithCtx(ctx,
|
||
"select * from order_profit_info where bank_order_id = ? for update",
|
||
bankOrderId,
|
||
).QueryRow(&orderProfitInfo); err != nil || orderProfitInfo.BankOrderId == "" {
|
||
otelTrace.Logger.WithContext(ctx).Error("select order_profit_info for update fail: ", zap.Error(err))
|
||
return err
|
||
}
|
||
if orderProfitInfo.BankOrderId == "" {
|
||
otelTrace.Logger.WithContext(ctx).Error("solve pay success, get orderProfit fail, bankOrderId = ", zap.String("bankOrderId", bankOrderId))
|
||
return errors.New(fmt.Sprintf("solve pay success, get orderProfit fail, bankOrderId = %s", bankOrderId))
|
||
}
|
||
|
||
orderSettleInfo := order.OrderSettleInfo{
|
||
PayTypeCode: orderInfo.PayTypeCode,
|
||
PayProductCode: orderInfo.PayProductCode,
|
||
RoadUid: orderInfo.RoadUid,
|
||
PayProductName: orderInfo.PayProductName,
|
||
PayTypeName: orderInfo.PayTypeName,
|
||
MerchantUid: orderInfo.MerchantUid,
|
||
MerchantOrderId: orderInfo.MerchantOrderId,
|
||
MerchantName: orderInfo.MerchantName,
|
||
BankOrderId: bankOrderId,
|
||
SettleAmount: factAmount,
|
||
IsAllowSettle: config.YES,
|
||
IsCompleteSettle: config.NO,
|
||
CreateTime: time.Now(),
|
||
UpdateTime: time.Now(),
|
||
}
|
||
if _, err := txOrm.InsertWithCtx(ctx, &orderSettleInfo); err != nil {
|
||
otelTrace.Logger.WithContext(ctx).Error(
|
||
fmt.Sprintf("solve pay success,insert order settle info fail: %s, bankOrderId = %s",
|
||
err, bankOrderId),
|
||
)
|
||
return err
|
||
}
|
||
// 做账户的加款操作,最重要的一步
|
||
var accountInfo accounts.AccountInfo
|
||
if err := txOrm.RawWithCtx(ctx, "select * from account_info where account_uid = ? for update", orderInfo.MerchantUid).QueryRow(&accountInfo); err != nil || accountInfo.AccountUid == "" {
|
||
otelTrace.Logger.WithContext(ctx).Error(fmt.Sprintf("solve pay success, raw account info fail: %s, bankOrderId = %s", err, bankOrderId))
|
||
return err
|
||
}
|
||
if _, err := txOrm.QueryTable(accounts.ACCOUNT_INFO).Filter("account_uid", orderInfo.MerchantUid).
|
||
UpdateWithCtx(ctx, orm.Params{
|
||
"balance": factAmount + accountInfo.Balance,
|
||
"wait_amount": factAmount + accountInfo.WaitAmount,
|
||
}); err != nil {
|
||
otelTrace.Logger.WithContext(ctx).Error(fmt.Sprintf("solve pay success, update account info fail: %s, bankOrderId = %s", err, bankOrderId))
|
||
return err
|
||
}
|
||
// 添加一条动账记录
|
||
accountHistory := accounts.AccountHistoryInfo{
|
||
AccountUid: orderInfo.MerchantUid,
|
||
AccountName: orderInfo.MerchantName,
|
||
Type: config.PLUS_AMOUNT,
|
||
OrderId: orderInfo.MerchantOrderId,
|
||
Amount: factAmount,
|
||
Balance: factAmount + accountInfo.Balance,
|
||
CreateTime: time.Now(),
|
||
UpdateTime: time.Now(),
|
||
}
|
||
if _, err := txOrm.InsertWithCtx(ctx, &accountHistory); err != nil {
|
||
otelTrace.Logger.WithContext(ctx).Error(fmt.Sprintf("solve pay success,insert account history fail:%s, bankOrderId = %s", err, bankOrderId))
|
||
return err
|
||
}
|
||
// 更新通道信息
|
||
roadInfo := road.GetRoadInfoByRoadUid(ctx, orderInfo.RoadUid)
|
||
|
||
roadInfo.RequestSuccess += 1
|
||
roadInfo.TodayRequestSuccess += 1 // 今日成功
|
||
roadInfo.TotalIncome += orderInfo.FactAmount
|
||
roadInfo.TodayIncome += orderInfo.FactAmount
|
||
roadInfo.TodayProfit += orderProfitInfo.PlatformProfit + orderProfitInfo.AgentProfit
|
||
roadInfo.TotalProfit += orderProfitInfo.PlatformProfit + orderProfitInfo.AgentProfit
|
||
roadInfo.UpdateTime = time.Now()
|
||
if _, err := txOrm.UpdateWithCtx(ctx, &roadInfo); err != nil {
|
||
otelTrace.Logger.WithContext(ctx).Error(fmt.Sprintf("solve pay success, update road info fail: %s, bankOrderId = %s", err, bankOrderId))
|
||
return err
|
||
}
|
||
// 更新订单利润表
|
||
orderProfitInfo.Status = config.SUCCESS
|
||
orderProfitInfo.UpdateTime = time.Now()
|
||
if _, err := txOrm.UpdateWithCtx(ctx, &orderProfitInfo); err != nil {
|
||
otelTrace.Logger.WithContext(ctx).Error(fmt.Sprintf("solve pay success, update order profit info fail: %s, bankOrderId = %s", err, bankOrderId))
|
||
return err
|
||
}
|
||
// 给下游发送回调通知
|
||
return nil
|
||
})
|
||
orderNotify.Go(func() {
|
||
// 创建一个5分钟超时的上下文
|
||
ctx2, span := otelTrace.NewSchedulerTrace().Start(otelTrace.InitCtx, "SolvePaySuccess")
|
||
defer span.End()
|
||
CreateOrderNotifyInfo(ctx2, bankOrderId, config.SUCCESS)
|
||
})
|
||
if err != nil {
|
||
otelTrace.Logger.WithContext(ctx).Error("SolvePaySuccess失败:", zap.Error(err))
|
||
return true
|
||
}
|
||
|
||
otelTrace.Logger.WithContext(ctx).Info("SolvePaySuccess处理成功")
|
||
return true
|
||
}
|
||
|
||
// SolvePayFail 处理支付失败
|
||
func SolvePayFail(ctx context.Context, bankOrderId, transId string, cardReturnData string) bool {
|
||
ctx, cancel := otelTrace.Span(ctx, "订单处理", "SolvePayFail", trace.WithAttributes(
|
||
attribute.String("bankOrderId", bankOrderId),
|
||
attribute.String("cardReturnData", cardReturnData),
|
||
))
|
||
defer cancel()
|
||
o := orm.NewOrm()
|
||
err := o.DoTxWithCtx(ctx, func(ctx context.Context, txOrm orm.TxOrmer) error {
|
||
var orderTmp order.OrderInfo
|
||
if err := txOrm.RawWithCtx(ctx, "select * from order_info where bank_order_id = ?", bankOrderId).QueryRow(&orderTmp); err != nil || orderTmp.BankOrderId == "" {
|
||
return err
|
||
}
|
||
if orderTmp.Status != config.WAIT {
|
||
return nil
|
||
// return errors.New("订单已经处理,不要重复加款")
|
||
}
|
||
if _, err := txOrm.QueryTable(order.ORDER_INFO).Filter("bank_order_id", bankOrderId).UpdateWithCtx(ctx, orm.Params{
|
||
"status": config.FAIL,
|
||
"card_return_data": cardReturnData,
|
||
"bank_trans_id": transId,
|
||
}); err != nil {
|
||
otelTrace.Logger.WithContext(ctx).Error("更改订单状态失败:", zap.Error(err))
|
||
return err
|
||
}
|
||
if _, err := txOrm.QueryTable(order.ORDER_PROFIT_INFO).Filter("bank_order_id", bankOrderId).UpdateWithCtx(ctx, orm.Params{"status": config.FAIL, "bank_trans_id": transId}); err != nil {
|
||
otelTrace.Logger.WithContext(ctx).Error("更改订单状态失败:", zap.Error(err))
|
||
return err
|
||
}
|
||
|
||
// TODO: 判断是否偷卡(隐藏订单)
|
||
// 如果是偷卡,就不计算利润什么的,也不回调
|
||
hiddenCfg, _ := GetRelateRecordByTargetOrderNo(ctx, bankOrderId)
|
||
if !pointer.IsNil(hiddenCfg) && hiddenCfg.Id != 0 {
|
||
_ = UpdateRelateRecordStatus(ctx, bankOrderId, 0, int(consts.StealRuleStatusFail))
|
||
return nil
|
||
}
|
||
return nil
|
||
})
|
||
orderNotify.Go(func() {
|
||
// 创建一个5分钟超时的上下文
|
||
ctx2, span := otelTrace.NewSchedulerTrace().Start(otelTrace.InitCtx, "SolvePayFail")
|
||
defer span.End()
|
||
CreateOrderNotifyInfo(ctx2, bankOrderId, config.FAIL)
|
||
})
|
||
if err != nil {
|
||
otelTrace.Logger.WithContext(ctx).Error("SolvePayFail:", zap.Error(err))
|
||
}
|
||
otelTrace.Logger.WithContext(ctx).Info("SolvePayFail成功")
|
||
return true
|
||
}
|
||
|
||
// SolveOrderFreeze 处理订单冻结
|
||
func SolveOrderFreeze(ctx context.Context, bankOrderId string) bool {
|
||
o := orm.NewOrm()
|
||
|
||
err := o.DoTxWithCtx(ctx, func(ctx context.Context, txOrm orm.TxOrmer) error {
|
||
var orderInfo order.OrderInfo
|
||
if err := txOrm.Raw("select * from order_info where bank_order_id = ? for update", bankOrderId).QueryRow(&orderInfo); err != nil || orderInfo.BankOrderId == "" {
|
||
otelTrace.Logger.WithContext(ctx).Error("solve order freeze 不存在这样的订单记录,bankOrderId = ", zap.String("bankOrderId", bankOrderId))
|
||
return err
|
||
}
|
||
|
||
// 如果订单不是失败或者成功状态,订单不能冻结
|
||
if orderInfo.Status != config.SUCCESS && orderInfo.Status != config.FAIL {
|
||
otelTrace.Logger.WithContext(ctx).Error("非成功或失败订单不能进行冻结")
|
||
return errors.New("非成功或失败订单不能进行冻结")
|
||
}
|
||
|
||
orderInfo.Freeze = config.YES
|
||
orderInfo.FreezeTime = time.Now().Format("2006-01-02 15:04:05")
|
||
orderInfo.UpdateTime = time.Now()
|
||
|
||
if _, err := txOrm.Update(&orderInfo); err != nil {
|
||
otelTrace.Logger.WithContext(ctx).Error("solve order freeze fail: ", zap.Error(err))
|
||
return err
|
||
}
|
||
|
||
// 账户的冻结金额里面加入相应的金额
|
||
orderProfitInfo := order.GetOrderProfitByBankOrderId(ctx, bankOrderId)
|
||
|
||
var accountInfo accounts.AccountInfo
|
||
if err := txOrm.Raw("select * from account_info where account_uid = ? for update", orderInfo.MerchantUid).QueryRow(&accountInfo); err != nil || accountInfo.AccountUid == "" {
|
||
otelTrace.Logger.WithContext(ctx).Error(fmt.Sprintf("solve pay fail select acount fail:%s", err))
|
||
return err
|
||
}
|
||
|
||
accountInfo.UpdateTime = time.Now()
|
||
accountInfo.FreezeAmount = orderProfitInfo.UserInAmount + accountInfo.FreezeAmount
|
||
if _, err := txOrm.Update(&accountInfo); err != nil {
|
||
otelTrace.Logger.WithContext(ctx).Error("solve order freeze fail: ", zap.Error(err))
|
||
return err
|
||
}
|
||
|
||
// 插入一条动账记录
|
||
accountHistoryInfo := accounts.AccountHistoryInfo{
|
||
AccountName: accountInfo.AccountName,
|
||
AccountUid: accountInfo.AccountUid,
|
||
Type: config.FREEZE_AMOUNT,
|
||
OrderId: orderInfo.MerchantOrderId,
|
||
Amount: orderProfitInfo.UserInAmount,
|
||
Balance: accountInfo.Balance,
|
||
CreateTime: time.Now(),
|
||
UpdateTime: time.Now(),
|
||
}
|
||
|
||
if _, err := txOrm.Insert(&accountHistoryInfo); err != nil {
|
||
otelTrace.Logger.WithContext(ctx).Error("solve order freeze fail: ", zap.Error(err))
|
||
return err
|
||
}
|
||
|
||
return nil
|
||
})
|
||
if err != nil {
|
||
otelTrace.Logger.WithContext(ctx).Error("SolveOrderFreeze:", zap.Error(err))
|
||
return false
|
||
}
|
||
|
||
otelTrace.Logger.WithContext(ctx).Info("SolveOrderFreeze")
|
||
|
||
return true
|
||
}
|
||
|
||
// SolveOrderUnfreeze 订单解冻
|
||
func SolveOrderUnfreeze(ctx context.Context, bankOrderId string) bool {
|
||
o := orm.NewOrm()
|
||
|
||
if err := o.DoTx(func(ctx context.Context, txOrm orm.TxOrmer) error {
|
||
orderInfo := new(order.OrderInfo)
|
||
if err := txOrm.Raw("select * from order_info where bank_order_id = ? for update", bankOrderId).QueryRow(orderInfo); err != nil || orderInfo.BankOrderId == "" {
|
||
otelTrace.Logger.WithContext(ctx).Error("solve order unfreeze 不存在这样的订单记录,bankOrderId = ", zap.String("bankOrderId", bankOrderId))
|
||
return err
|
||
}
|
||
|
||
orderInfo.Freeze = ""
|
||
orderInfo.Unfreeze = config.YES
|
||
orderInfo.UnfreezeTime = utils.GetBasicDateTime()
|
||
orderInfo.UpdateTime = time.Now()
|
||
if _, err := txOrm.Update(orderInfo); err != nil {
|
||
otelTrace.Logger.WithContext(ctx).Error("solve order unfreeze fail: ", zap.Error(err))
|
||
return err
|
||
}
|
||
|
||
orderProfitInfo := order.GetOrderProfitByBankOrderId(ctx, bankOrderId)
|
||
|
||
accountInfo := new(accounts.AccountInfo)
|
||
if err := txOrm.Raw("select * from account_info where account_uid = ? for update", orderInfo.MerchantUid).QueryRow(accountInfo); err != nil || accountInfo.AccountUid == "" {
|
||
otelTrace.Logger.WithContext(ctx).Error(fmt.Sprintf("unfreeze select account fail: %s", err))
|
||
return err
|
||
}
|
||
accountInfo.UpdateTime = time.Now()
|
||
accountInfo.FreezeAmount = accountInfo.FreezeAmount - orderProfitInfo.UserInAmount
|
||
|
||
if _, err := txOrm.Update(accountInfo); err != nil {
|
||
otelTrace.Logger.WithContext(ctx).Error("solve order unfreeze fail: ", zap.Error(err))
|
||
return err
|
||
}
|
||
|
||
accountHistoryInfo := accounts.AccountHistoryInfo{
|
||
AccountUid: accountInfo.AccountUid,
|
||
AccountName: accountInfo.AccountName,
|
||
OrderId: orderInfo.MerchantOrderId,
|
||
Type: config.UNFREEZE_AMOUNT,
|
||
Amount: orderProfitInfo.UserInAmount,
|
||
Balance: accountInfo.Balance,
|
||
CreateTime: time.Now(),
|
||
UpdateTime: time.Now(),
|
||
}
|
||
|
||
if _, err := txOrm.Insert(&accountHistoryInfo); err != nil {
|
||
return err
|
||
}
|
||
|
||
return nil
|
||
}); err != nil {
|
||
otelTrace.Logger.WithContext(ctx).Error("SolveOrderUnfreeze失败:", zap.Error(err))
|
||
return false
|
||
}
|
||
|
||
return true
|
||
}
|
||
|
||
func SolveRefund(ctx context.Context, bankOrderId string) bool {
|
||
o := orm.NewOrm()
|
||
if err := o.DoTx(func(ctx context.Context, txOrm orm.TxOrmer) error {
|
||
orderInfo := new(order.OrderInfo)
|
||
if err := txOrm.Raw("select * from order_info where bank_order_id = ? for update", bankOrderId).QueryRow(orderInfo); err != nil || orderInfo.BankOrderId == "" {
|
||
otelTrace.Logger.WithContext(ctx).Error("solve refund 不存在这样的订单,bankOrderId = " + bankOrderId)
|
||
return err
|
||
}
|
||
|
||
orderInfo.UpdateTime = time.Now()
|
||
orderInfo.Refund = config.YES
|
||
orderInfo.RefundTime = utils.GetBasicDateTime()
|
||
|
||
orderProfitInfo := order.GetOrderProfitByBankOrderId(ctx, bankOrderId)
|
||
account := new(accounts.AccountInfo)
|
||
if err := txOrm.Raw("select * from account_info where account_uid = ? for update", orderInfo.MerchantUid).QueryRow(account); err != nil || account.AccountUid == "" {
|
||
return err
|
||
}
|
||
|
||
account.UpdateTime = time.Now()
|
||
account.SettleAmount = account.SettleAmount - orderProfitInfo.UserInAmount
|
||
account.Balance = account.Balance - orderProfitInfo.UserInAmount
|
||
|
||
if orderInfo.Freeze == config.YES {
|
||
account.FreezeAmount = account.FreezeAmount - orderProfitInfo.UserInAmount
|
||
if account.FreezeAmount < 0 {
|
||
account.FreezeAmount = config.ZERO
|
||
}
|
||
orderInfo.Freeze = ""
|
||
}
|
||
|
||
if _, err := txOrm.Update(orderInfo); err != nil {
|
||
otelTrace.Logger.WithContext(ctx).Error("solve order refund update order info fail: ", zap.Error(err))
|
||
return err
|
||
}
|
||
if _, err := txOrm.Update(account); err != nil {
|
||
otelTrace.Logger.WithContext(ctx).Error("solve order refund update account fail: ", zap.Error(err))
|
||
return err
|
||
}
|
||
|
||
accountHistoryInfo := accounts.AccountHistoryInfo{
|
||
AccountName: account.AccountName,
|
||
AccountUid: account.AccountUid,
|
||
Type: config.REFUND,
|
||
OrderId: orderInfo.MerchantOrderId,
|
||
Amount: orderProfitInfo.UserInAmount,
|
||
Balance: account.Balance,
|
||
CreateTime: time.Now(),
|
||
UpdateTime: time.Now(),
|
||
}
|
||
|
||
if _, err := txOrm.Insert(&accountHistoryInfo); err != nil {
|
||
otelTrace.Logger.WithContext(ctx).Error("solve order refund insert account history fail: ", zap.Error(err))
|
||
return err
|
||
}
|
||
|
||
return nil
|
||
}); err != nil {
|
||
otelTrace.Logger.WithContext(ctx).Error("SolveRefund 成功:", zap.Error(err))
|
||
return false
|
||
}
|
||
return true
|
||
}
|
||
|
||
func SolveOrderRoll(ctx context.Context, bankOrderId string) bool {
|
||
o := orm.NewOrm()
|
||
if err := o.DoTx(func(ctx context.Context, txOrm orm.TxOrmer) error {
|
||
orderInfo := new(order.OrderInfo)
|
||
|
||
if err := txOrm.Raw("select * from order_info where bank_order_id = ? for update", bankOrderId).QueryRow(orderInfo); err != nil {
|
||
otelTrace.Logger.WithContext(ctx).Error("solve order roll fail: ", zap.Error(err))
|
||
return err
|
||
}
|
||
|
||
if orderInfo.Status != config.SUCCESS {
|
||
otelTrace.Logger.WithContext(ctx).Error("solve order roll 订单不存在或者订单状态不是success, bankOrderId=", zap.String("bankOrderId", bankOrderId))
|
||
return errors.New("solve order roll failed")
|
||
}
|
||
orderInfo.UpdateTime = time.Now()
|
||
|
||
orderProfitInfo := order.GetOrderProfitByBankOrderId(ctx, bankOrderId)
|
||
|
||
account := new(accounts.AccountInfo)
|
||
if err := txOrm.Raw("select * from account_info where account_uid = ? for update", orderInfo.MerchantUid).QueryRow(account); err != nil || account.AccountUid == "" {
|
||
return err
|
||
}
|
||
|
||
account.UpdateTime = time.Now()
|
||
if orderInfo.Refund == config.YES {
|
||
account.Balance = account.Balance + orderProfitInfo.UserInAmount
|
||
account.SettleAmount = account.SettleAmount + orderProfitInfo.UserInAmount
|
||
orderInfo.Refund = config.NO
|
||
}
|
||
|
||
if _, err := txOrm.Update(orderInfo); err != nil {
|
||
otelTrace.Logger.WithContext(ctx).Error("solve order roll fail update order info fail: ", zap.Error(err))
|
||
return err
|
||
}
|
||
if _, err := txOrm.Update(account); err != nil {
|
||
otelTrace.Logger.WithContext(ctx).Error("solve order roll update account fail: ", zap.Error(err))
|
||
return err
|
||
}
|
||
|
||
accountHistoryInfo := accounts.AccountHistoryInfo{
|
||
AccountUid: account.AccountUid,
|
||
AccountName: account.AccountName,
|
||
Type: config.PLUS_AMOUNT,
|
||
OrderId: orderInfo.MerchantOrderId,
|
||
Amount: orderProfitInfo.UserInAmount,
|
||
Balance: account.Balance,
|
||
CreateTime: time.Now(),
|
||
UpdateTime: time.Now(),
|
||
}
|
||
|
||
if _, err := txOrm.Insert(&accountHistoryInfo); err != nil {
|
||
otelTrace.Logger.WithContext(ctx).Error("solve order roll insert account history fail: ", zap.Error(err))
|
||
return err
|
||
}
|
||
|
||
return nil
|
||
}); err != nil {
|
||
otelTrace.Logger.WithContext(ctx).Error("SolveOrderRoll处理失败:", zap.Error(err))
|
||
return false
|
||
}
|
||
|
||
return true
|
||
}
|
||
|
||
// CompareOrderAndFactAmount 比较订单金额和实际支付金额的大小
|
||
func CompareOrderAndFactAmount(factAmount float64, orderInfo order.OrderInfo) int {
|
||
orderAmount := orderInfo.OrderAmount
|
||
// 将金额放大1000倍
|
||
oa := int64(orderAmount * 1000)
|
||
fa := int64(factAmount * 1000)
|
||
if oa > fa {
|
||
// 如果实际金额大,返回1
|
||
return 1
|
||
} else if oa == fa {
|
||
return 0
|
||
} else {
|
||
return 2
|
||
}
|
||
}
|
||
|
||
// CreateOrderNotifyInfo 支付完成后,处理给商户的回调信息
|
||
func CreateOrderNotifyInfo(ctx context.Context, bankOrderId string, tradeStatus string) {
|
||
orderInfo := order.GetOneOrder(ctx, bankOrderId)
|
||
if orderInfo.Status != config.SUCCESS && orderInfo.Status != config.FAIL {
|
||
return
|
||
}
|
||
merchantInfo := merchant.GetMerchantByUid(ctx, orderInfo.MerchantUid)
|
||
statusCode := 0
|
||
if tradeStatus == "success" {
|
||
statusCode = 1
|
||
}
|
||
params := map[string]any{
|
||
"orderNo": orderInfo.MerchantOrderId, // 商户订单号
|
||
"orderPrice": strconv.FormatFloat(orderInfo.OrderAmount, 'f', 2, 64),
|
||
"factPrice": strconv.FormatFloat(orderInfo.FactAmount, 'f', 2, 64),
|
||
"orderTime": utils.GetNowTimesTamp(),
|
||
"trxNo": orderInfo.BankOrderId,
|
||
"payKey": merchantInfo.MerchantKey,
|
||
"statusCode": statusCode,
|
||
"failReason": orderInfo.CardReturnData,
|
||
}
|
||
params["sign"] = utils.GetMD5SignMF(params, merchantInfo.MerchantSecret)
|
||
u := url.Values{}
|
||
for k, v := range params {
|
||
u.Add(k, convertor.ToString(v))
|
||
}
|
||
if notify.InsertNotifyInfo(ctx, notify.NotifyInfo{
|
||
Type: "order",
|
||
BankOrderId: orderInfo.BankOrderId,
|
||
MerchantOrderId: orderInfo.MerchantOrderId,
|
||
Status: "wait",
|
||
Times: 0,
|
||
CreateTime: time.Now(),
|
||
UpdateTime: time.Now(),
|
||
Url: orderInfo.NotifyUrl + "?" + u.Encode(),
|
||
}) {
|
||
otelTrace.Logger.WithContext(ctx).Info(fmt.Sprintf("订单bankOrderId=%s,已经将回调地址插入数据库", orderInfo.BankOrderId))
|
||
} else {
|
||
otelTrace.Logger.WithContext(ctx).Error(fmt.Sprintf("订单bankOrderId=%s,插入回调数据库失败", orderInfo.BankOrderId))
|
||
}
|
||
// 将订单发送到消息队列,给下面的商户进行回调
|
||
sendMessageNotify.Go(func() {
|
||
// 创建一个5分钟超时的上下文
|
||
ctx2, span := otelTrace.NewSchedulerTrace().Start(otelTrace.InitCtx, "CreateOrderNotifyInfo")
|
||
defer span.End()
|
||
message.SendMessage(ctx2, config.MqOrderNotify, orderInfo.BankOrderId)
|
||
})
|
||
}
|