dongfeng-pay/microservice/supplier/payfor_solve.go

351 lines
12 KiB
Go
Raw Normal View History

2021-04-27 15:33:49 +08:00
/***************************************************
** @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 (
"context"
"errors"
"fmt"
"github.com/beego/beego/v2/client/orm"
"github.com/beego/beego/v2/core/logs"
"microservice/common"
"microservice/message_queue"
"microservice/models"
"microservice/utils"
"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)
}