dongfeng-pay/boss/supplier/payfor_solve.go

351 lines
12 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/***************************************************
** @Desc : 代付处理
** @Time : 2019/11/28 18:52
** @Author : yuebin
** @File : payfor_solve
** @Last Modified by : yuebin
** @Last Modified time: 2019/11/28 18:52
** @Software: GoLand
****************************************************/
package controller
import (
"boss/common"
"boss/message_queue"
"boss/models"
"boss/utils"
"context"
"errors"
"fmt"
"github.com/beego/beego/v2/client/orm"
"github.com/beego/beego/v2/core/logs"
"strings"
)
func PayForFail(payFor models.PayforInfo) bool {
o := orm.NewOrm()
if err := o.DoTx(func(ctx context.Context, txOrm orm.TxOrmer) error {
var tmpForPay models.PayforInfo
if err := txOrm.Raw("select * from payfor_info where bank_order_id = ? for update", payFor.BankOrderId).QueryRow(&tmpForPay); err != nil || tmpForPay.PayforUid == "" {
logs.Error("solve pay fail select fail", err)
return err
}
if tmpForPay.Status == common.PAYFOR_FAIL || tmpForPay.Status == common.PAYFOR_SUCCESS {
logs.Error(fmt.Sprintf("该代付订单uid=%s状态已经是最终结果", payFor.PayforUid))
return errors.New("状态已经是最终结果")
}
//更新payfor记录的状态
tmpForPay.Status = common.PAYFOR_FAIL
tmpForPay.UpdateTime = utils.GetBasicDateTime()
if _, err := txOrm.Update(&tmpForPay); err != nil {
logs.Error("PayForFail update payfor_info fail: ", err)
return err
}
var account models.AccountInfo
if err := txOrm.Raw("select * from account_info where account_uid = ? for update", payFor.MerchantUid).QueryRow(&account); err != nil || account.AccountUid == "" {
logs.Error("payfor select account fail", err)
return err
}
account.UpdateTime = utils.GetBasicDateTime()
if account.PayforAmount < (payFor.PayforAmount + payFor.PayforFee) {
logs.Error(fmt.Sprintf("商户uid=%s账户中待代付金额小于代付记录的金额", payFor.MerchantUid))
return errors.New("账户中待代付金额小于代付记录的金额")
}
//将正在打款中的金额减去
account.PayforAmount = account.PayforAmount - payFor.PayforAmount - payFor.PayforFee
if _, err := txOrm.Update(&account); err != nil {
logs.Error("PayForFail update account fail: ", err)
return err
}
return nil
}); err != nil {
return false
}
return true
}
func PayForSuccess(payFor models.PayforInfo) bool {
o := orm.NewOrm()
if err := o.DoTx(func(ctx context.Context, txOrm orm.TxOrmer) error {
var tmpPayFor models.PayforInfo
if err := txOrm.Raw("select * from payfor_info where bank_order_id = ? for update", payFor.BankOrderId).QueryRow(&tmpPayFor); err != nil || tmpPayFor.PayforUid == "" {
logs.Error("payfor success select payfor fail", err)
return err
}
if tmpPayFor.Status == common.PAYFOR_FAIL || tmpPayFor.Status == common.PAYFOR_SUCCESS {
logs.Error(fmt.Sprintf("该代付订单uid=%s已经是最终结果不需要处理", payFor.PayforUid))
return errors.New("已经是最终结果,不需要处理")
}
tmpPayFor.UpdateTime = utils.GetBasicDateTime()
tmpPayFor.Status = common.PAYFOR_SUCCESS
_, err := txOrm.Update(&tmpPayFor)
if err != nil {
logs.Error("PayForSuccess update payfor fail: ", err)
return err
}
var account models.AccountInfo
if err := txOrm.Raw("select * from account_info where account_uid = ? for update", payFor.MerchantUid).QueryRow(&account); err != nil || account.AccountUid == "" {
logs.Error("payfor success select account fail", err)
return err
}
account.UpdateTime = utils.GetBasicDateTime()
if account.PayforAmount < (payFor.PayforAmount + payFor.PayforFee) {
logs.Error(fmt.Sprintf("商户uid=%s账户中待代付金额小于代付记录的金额", payFor.MerchantUid))
return errors.New("账户中待代付金额小于代付记录的金额")
}
//代付打款中的金额减去
account.PayforAmount = account.PayforAmount - payFor.PayforAmount - payFor.PayforFee
//减去余额,减去可用金额
account.Balance = account.Balance - payFor.PayforAmount - payFor.PayforFee
//已结算金额减去
account.SettleAmount = account.SettleAmount - payFor.PayforAmount - payFor.PayforFee
if _, err := txOrm.Update(&account); err != nil {
logs.Error("PayForSuccess udpate account fail", err)
return err
}
//添加一条动账记录
accountHistory := models.AccountHistoryInfo{AccountUid: payFor.MerchantUid, AccountName: payFor.MerchantName,
Type: common.SUB_AMOUNT, Amount: payFor.PayforAmount + payFor.PayforFee, Balance: account.Balance,
UpdateTime: utils.GetBasicDateTime(), CreateTime: utils.GetBasicDateTime()}
if _, err := txOrm.Insert(&accountHistory); err != nil {
logs.Error("PayForSuccess insert account history fail: ", err)
return err
}
return nil
}); err != nil {
return false
}
return true
}
/*
* 自动审核代付订单
*/
func SolvePayForConfirm() {
params := make(map[string]string)
beforeOneDay := utils.GetDateTimeBeforeDays(1)
nowDate := utils.GetBasicDateTime()
params["create_time__lte"] = beforeOneDay
params["create_time__gte"] = nowDate
params["status"] = common.PAYFOR_COMFRIM
payForList := models.GetPayForListByParams(params)
for _, p := range payForList {
if p.Type == common.SELF_HELP || p.Type == common.SELF_MERCHANT {
//系统后台提交的,人工审核
continue
}
//判断商户是否开通了自动代付功能
merchant := models.GetMerchantByUid(p.MerchantUid)
//判断商户是否开通了自动代付
if merchant.AutoPayFor == common.NO || merchant.AutoPayFor == "" {
logs.Notice(fmt.Sprintf("该商户uid=%s 没有开通自动代付功能", p.MerchantUid))
continue
}
//找自动代付通道
findPayForRoad(p, merchant)
}
}
func findPayForRoad(payFor models.PayforInfo, merchant models.MerchantInfo) bool {
//检查是否单独填写了每笔代付的手续费
if merchant.PayforFee > common.ZERO {
logs.Info(fmt.Sprintf("商户uid=%s有单独的代付手续费。", merchant.MerchantUid))
payFor.PayforFee = merchant.PayforFee
payFor.PayforTotalAmount = payFor.PayforFee + payFor.PayforAmount
}
if merchant.SinglePayForRoadUid != "" {
payFor.RoadUid = merchant.SinglePayForRoadUid
payFor.RoadName = merchant.SinglePayForRoadName
} else {
//到轮询里面寻找代付通道
if merchant.RollPayForRoadCode == "" {
logs.Notice(fmt.Sprintf("该商户没有配置代付通道"))
return false
}
roadPoolInfo := models.GetRoadPoolByRoadPoolCode(merchant.RollPayForRoadCode)
roadUids := strings.Split(roadPoolInfo.RoadUidPool, "||")
roadInfoList := models.GetRoadInfosByRoadUids(roadUids)
if len(roadUids) == 0 || len(roadInfoList) == 0 {
logs.Error(fmt.Sprintf("通道轮询池=%s, 没有配置通道", merchant.RollPayForRoadCode))
return false
}
payFor.RoadUid = roadInfoList[0].RoadUid
payFor.RoadName = roadInfoList[0].RoadName
}
o := orm.NewOrm()
// 开启事务
if err := o.DoTx(func(ctx context.Context, txOrm orm.TxOrmer) error {
var tmpPayFor models.PayforInfo
if err := txOrm.Raw("select * from payfor_info where payfor_uid = ? for update", payFor.PayforUid).QueryRow(&tmpPayFor); err != nil || tmpPayFor.PayforUid == "" {
logs.Error("find payfor road select payfor fail", err)
return err
}
if tmpPayFor.Status != common.PAYFOR_COMFRIM {
logs.Notice(fmt.Sprintf("该代付记录uid=%s已经被审核", payFor.PayforUid))
return errors.New("已经被审核")
}
tmpPayFor.UpdateTime = utils.GetBasicDateTime()
tmpPayFor.Status = common.PAYFOR_SOLVING
tmpPayFor.GiveType = common.PAYFOR_ROAD
if _, err := txOrm.Update(&tmpPayFor); err != nil {
logs.Error(fmt.Sprintf("该代付记录uid=%s从审核更新为正在处理出错: %s", payFor.PayforUid, err))
return err
}
return nil
}); err != nil {
return false
}
return true
}
/*
* 执行逻辑
*/
func SolvePayFor() {
//取出一天之内的没有做处理并且不是手动打款的代付记录
params := make(map[string]string)
beforeOneDay := utils.GetDateTimeBeforeDays(1)
nowDate := utils.GetBasicDateTime()
params["create_time__lte"] = nowDate
params["create_time__gte"] = beforeOneDay
params["is_send"] = "no"
params["status"] = common.PAYFOR_SOLVING
params["give_type"] = common.PAYFOR_ROAD
payForList := models.GetPayForListByParams(params)
for _, p := range payForList {
if p.Type == common.SELF_HELP {
//如果后台管理人员,通过任意下发,不涉及到商户减款操作,直接发送代付请求
solveSelf(p)
} else {
SendPayFor(p)
}
}
}
func solveSelf(payFor models.PayforInfo) bool {
o := orm.NewOrm()
if err := o.DoTx(func(ctx context.Context, txOrm orm.TxOrmer) error {
var tmpPayFor models.PayforInfo
if err := txOrm.Raw("select * from payfor_info where payfor_uid = ? for update", payFor.PayforUid).QueryRow(&tmpPayFor); err != nil || tmpPayFor.PayforUid == "" {
logs.Error("solve self payfor fail", err)
return errors.New("solve self payfor fail")
}
if tmpPayFor.IsSend == common.YES {
return errors.New("代付已经发送")
}
tmpPayFor.UpdateTime = utils.GetBasicDateTime()
if payFor.RoadUid == "" {
tmpPayFor.Status = common.PAYFOR_FAIL
} else {
tmpPayFor.Status = common.PAYFOR_BANKING
tmpPayFor.RequestTime = utils.GetBasicDateTime()
tmpPayFor.IsSend = common.YES
}
if _, err := txOrm.Update(&tmpPayFor); err != nil {
return err
}
RequestPayFor(payFor)
return nil
}); err != nil {
return false
}
return true
}
func SendPayFor(payFor models.PayforInfo) bool {
o := orm.NewOrm()
if err := o.DoTx(func(ctx context.Context, txOrm orm.TxOrmer) error {
var tmpPayFor models.PayforInfo
if err := txOrm.Raw("select * from payfor_info where payfor_uid = ? for update", payFor.PayforUid).QueryRow(&tmpPayFor); err != nil || tmpPayFor.PayforUid == "" {
logs.Error("send payfor select payfor fail: ", err)
return err
}
var account models.AccountInfo
if err := txOrm.Raw("select * from account_info where account_uid = ? for update", payFor.MerchantUid).QueryRow(&account); err != nil || account.AccountUid == "" {
logs.Error("send payfor select account fail", err)
return err
}
//支付金额不足,将直接判定为失败,不往下面邹逻辑了
if account.SettleAmount-account.PayforAmount < tmpPayFor.PayforAmount+tmpPayFor.PayforFee {
tmpPayFor.Status = common.PAYFOR_FAIL
tmpPayFor.UpdateTime = utils.GetBasicDateTime()
if _, err := txOrm.Update(&tmpPayFor); err != nil {
return err
} else {
return nil
}
}
account.UpdateTime = utils.GetBasicDateTime()
account.PayforAmount = account.PayforAmount + payFor.PayforAmount + payFor.PayforFee
if _, err := txOrm.Update(&account); err != nil {
logs.Error(fmt.Sprintf("商户uid=%s在发送代付给上游的处理中更新账户表出错, err: %s", payFor.MerchantUid, err))
return err
}
tmpPayFor.IsSend = common.YES
tmpPayFor.Status = common.PAYFOR_BANKING //变为银行处理中
tmpPayFor.RequestTime = utils.GetBasicDateTime()
tmpPayFor.UpdateTime = utils.GetBasicDateTime()
if _, err := txOrm.Update(&tmpPayFor); err != nil {
logs.Error(fmt.Sprintf("商户uid=%s在发送代付给上游的处理中更代付列表出错 err%s", payFor.MerchantUid, err))
return err
}
RequestPayFor(payFor)
return nil
}); err != nil {
return false
}
return true
}
func RequestPayFor(payFor models.PayforInfo) {
if payFor.RoadUid == "" {
return
}
roadInfo := models.GetRoadInfoByRoadUid(payFor.RoadUid)
supplierCode := roadInfo.ProductUid
supplier := GetPaySupplierByCode(supplierCode)
res := supplier.PayFor(payFor)
logs.Info(fmt.Sprintf("代付uid=%s上游处理结果为%s", payFor.PayforUid, res))
//将代付订单号发送到消息队列
message_queue.SendMessage(common.MQ_PAYFOR_QUERY, payFor.BankOrderId)
}