| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200 |
- package services
- import (
- "app/commons/constant"
- "app/commons/core"
- "app/commons/core/exchange"
- "app/commons/model/entity"
- "fmt"
- "github.com/shopspring/decimal"
- )
- func (s *CommonService) RwCallback(req *exchange.TransferCallbackReq) error {
- var count int64
- if err := s.DB().Model(&entity.AssetRwCallbackLog{}).
- Where("order_id", req.OrderId).
- Count(&count).Error; err != nil {
- return err
- }
- if count > 0 {
- return nil
- }
- newLog := entity.AssetRwCallbackLog{
- Currency: req.Currency,
- Amount: req.Amount,
- OrderId: req.OrderId,
- OpenId: req.OpenId,
- CreateTime: req.CreateTime,
- Type: req.Type,
- AppId: req.AppId,
- CustomParam: req.CustomParam,
- Sign: req.Sign,
- Status: req.Status, // 交易所返回状态码 0 1 成功 2 失败
- State: constant.RwCallbackStateWaiting, // 0 待处理 1 处理成功 2 处理失败
- }
- err := s.DB().Create(&newLog).Error
- if err != nil {
- return err
- }
- // 触发订单处理
- go s.callbackHandlerCheck()
- return nil
- }
- // 回调处理失败检查
- var callbackHandler bool = false
- func (s *CommonService) callbackHandlerCheck() {
- if callbackHandler {
- core.Log.Infof("回调任务处理中")
- return
- }
- callbackHandler = true
- defer func() {
- callbackHandler = false
- }()
- db := s.DB().Where("state", constant.RwCallbackStateWaiting)
- var count int64
- if err := db.Model(&entity.AssetRwCallbackLog{}).Count(&count).Error; err != nil {
- core.Log.Error(err.Error())
- return
- }
- if count == 0 {
- return
- }
- items, err := s.BatchAssetRwCallbackLog(db)
- if err != nil {
- core.Log.Error(err.Error())
- }
- for _, item := range items {
- switch item.Type {
- case exchange.TransferUserToApp:
- s.handleRecharge(item)
- break
- case exchange.TransferAppToUser:
- s.handleWithdraw(item)
- break
- }
- }
- return
- }
- // 转出回调处理逻辑
- // 收到转出成功回调
- // 1 修改回调记录状态 2 扣除用户冻结资产 3 产出流水信息
- // status 1 成功 2 失败
- func (s *CommonService) handleWithdraw(callbackLog *entity.AssetRwCallbackLog) {
- if callbackLog.State != constant.RwCallbackStateWaiting {
- return
- }
- var err error
- defer func() {
- callbackLog.State = constant.RwCallbackStateFinish
- callbackLog.ErrDesc = "success"
- if err != nil {
- callbackLog.State = constant.RwCallbackStateFail
- callbackLog.ErrDesc = err.Error()
- }
- if err = s.DB().Model(&entity.AssetRwCallbackLog{}).
- Where("id", callbackLog.Id).Updates(map[string]interface{}{
- "state": callbackLog.State,
- "err_desc": callbackLog.ErrDesc,
- }).Error; err != nil {
- core.Log.Error(err.Error())
- }
- }()
- order, err := s.FirstAssetRwRecord(s.DB().Where("order_id", callbackLog.OrderId))
- if err != nil {
- return
- }
- // 查找订单信息
- amount, err := decimal.NewFromString(callbackLog.Amount)
- if err != nil {
- return
- }
- // 订单状态检查 提现状态检查
- if order.Status != constant.RwStatePass && order.WithdrawState != constant.WithdrawStateFinish {
- err = fmt.Errorf("order.Status:%d WithdrawState:%d", order.Status, order.WithdrawState)
- return
- }
- // 金额检查 -- 这里是否改为大于则不处理?
- if !order.RealAmount.Equal(amount) {
- err = fmt.Errorf("order amount :%s app to user amount :%s", order.Amount, amount)
- return
- }
- // 提现状态 非1 即失败
- if callbackLog.Status == exchange.ExchangeRwStatusWithdrawSuccess {
- err = s.withdrawSuccessHandler(order)
- return
- }
- err = s.DB().Model(&entity.AssetRwRecord{}).Where("id", order.Id).
- Update("status", constant.RwStateSystemFail).Error
- return
- }
- // 提现成功扣除冻结处理
- func (s *CommonService) withdrawSuccessHandler(order *entity.AssetRwRecord) error {
- var err error
- if order.Status != constant.RwStatePass && order.WithdrawState != constant.WithdrawStateFinish {
- return nil
- }
- // order.Amount
- // 订单状态等于1 表示这个订单是审核后发起提现
- // 扣除冻结金额 并产生资产流水
- // 重新获取资产信息 -- 这个方法已经加了分布式锁 理论上是不需要再重新获取
- userAsset, err := s.GetAssetBySymbol(order.UserId, order.Symbol)
- if err != nil {
- return fmt.Errorf("not found asset")
- }
- dbTx := s.DB().Begin()
- bs := constant.BsById(constant.BsAssetWithdrawSuccess)
- bs.ContextName = order.TableName()
- bs.ContextValue = order.OrderId
- err = s.GenBillAndActionAsset(dbTx,
- userAsset.UserId,
- userAsset.Symbol,
- decimal.Zero,
- decimal.Zero.Sub(order.Amount),
- bs)
- if err != nil {
- dbTx.Rollback()
- return err
- }
- err = dbTx.Model(&entity.AssetRwRecord{}).
- Where("id", order.Id).
- Update("status", constant.RwStateFinish).Error
- if err != nil {
- dbTx.Rollback()
- return err
- }
- dbTx.Commit()
- return nil
- }
- // 构建充提记录
- // feeRatio,
- // feeAmount,
- // fee,
- // realAmount,
- func (s *CommonService) buildRwRecord(symbol string, userId int64, openId, orderId string, rwDirection int, amount, feeRatio, feeBaseAmount, fee, realAmount decimal.Decimal) *entity.AssetRwRecord {
- describe := fmt.Sprintf("用户%s 数量%s", constant.GetRwDirectionName(rwDirection), amount.String())
- return &entity.AssetRwRecord{
- OrderId: orderId,
- OpenId: openId,
- UserId: userId,
- Symbol: symbol,
- Amount: amount,
- Ratio: feeRatio,
- BaseFee: feeBaseAmount,
- Fee: fee,
- RealAmount: realAmount,
- Status: constant.RwStateWaiting,
- Direction: rwDirection,
- DirectionName: constant.GetRwDirectionName(rwDirection),
- Describe: describe,
- }
- }
|