dongfeng-pay/gateway/pay_for/payfor_service.go

371 lines
11 KiB
Go
Raw Normal View History

/***************************************************
** @Desc : 代付处理
** @Time : 2019/11/28 18:52
** @Author : yuebin
** @File : payfor_service
** @Last Modified by : yuebin
** @Last Modified time: 2019/11/28 18:52
** @Software: GoLand
****************************************************/
package pay_for
import (
"context"
"encoding/json"
"fmt"
"gateway/conf"
"gateway/message"
"gateway/models/accounts"
"gateway/models/merchant"
"gateway/models/payfor"
"gateway/models/road"
"gateway/response"
"gateway/supplier/third_party"
"gateway/utils"
"github.com/beego/beego/v2/client/orm"
"github.com/beego/beego/v2/core/logs"
"github.com/rs/xid"
"strconv"
"strings"
)
/**
** 程序自动代付
*/
func AutoPayFor(params map[string]string, giveType string) *response.PayForResponse {
payForResponse := new(response.PayForResponse)
merchantInfo := merchant.GetMerchantByPaykey(params["merchantKey"])
if !utils.Md5Verify(params, merchantInfo.MerchantSecret) {
logs.Error(fmt.Sprintf("下游商户代付请求,签名失败,商户信息: %+v", merchantInfo))
payForResponse.ResultCode = "01"
payForResponse.ResultMsg = "下游商户代付请求,签名失败。"
return payForResponse
} else {
res, msg := checkSettAmount(params["amount"])
if !res {
payForResponse.ResultCode = "01"
payForResponse.ResultMsg = msg
return payForResponse
}
exist := payfor.IsExistPayForByMerchantOrderId(params["merchantOrderId"])
if exist {
logs.Error(fmt.Sprintf("代付订单号重复merchantOrderId = %s", params["merchantOrderId"]))
payForResponse.ResultMsg = "商户订单号重复"
payForResponse.ResultCode = "01"
return payForResponse
}
settAmount, err := strconv.ParseFloat(params["amount"], 64)
if err != nil {
logs.Error("代付的金额错误:", err)
payForResponse.ResultMsg = "代付金额错误"
payForResponse.ResultCode = "01"
return payForResponse
}
p := payfor.PayforInfo{
PayforUid: "pppp" + xid.New().String(),
MerchantUid: merchantInfo.MerchantUid,
MerchantName: merchantInfo.MerchantName,
MerchantOrderId: params["merchantOrderId"],
BankOrderId: "4444" + xid.New().String(),
PayforAmount: settAmount,
Status: conf.PAYFOR_COMFRIM,
BankAccountName: params["realname"],
BankAccountNo: params["cardNo"],
BankAccountType: params["accType"],
City: params["city"],
Ares: params["province"] + params["city"],
PhoneNo: params["mobileNo"],
GiveType: giveType,
UpdateTime: utils.GetBasicDateTime(),
CreateTime: utils.GetBasicDateTime(),
RequestTime: utils.GetBasicDateTime(),
}
// 获取银行编码和银行名称
p.BankCode = utils.GetBankCodeByBankCardNo(p.BankAccountNo)
p.BankName = utils.GetBankNameByCode(p.BankCode)
if !payfor.InsertPayfor(p) {
payForResponse.ResultCode = "01"
payForResponse.ResultMsg = "代付记录插入失败"
} else {
payForResponse.ResultMsg = "代付订单已生成"
payForResponse.ResultCode = "00"
payForResponse.SettAmount = params["amount"]
payForResponse.MerchantOrderId = params["MerchantOrderId"]
p = payfor.GetPayForByBankOrderId(p.BankOrderId)
if findPayForRoad(p) {
payForResponse.ResultCode = "00"
payForResponse.ResultMsg = "银行处理中"
} else {
payForResponse.ResultCode = "01"
payForResponse.ResultMsg = "系统处理失败"
}
}
return payForResponse
}
}
/**
* 返回1表示需要手动打款返回0表示银行已经受理-1表示系统处理失败
*/
func findPayForRoad(p payfor.PayforInfo) bool {
m := merchant.GetMerchantByUid(p.MerchantUid)
// 检查商户是否设置了自动代付
if m.AutoPayFor == conf.NO || m.AutoPayFor == "" {
logs.Notice(fmt.Sprintf("该商户uid=%s 没有开通自动代付功能", p.MerchantUid))
p.Type = conf.PAYFOR_HAND
payfor.UpdatePayFor(p)
} else {
if m.SinglePayForRoadUid != "" {
p.RoadUid = m.SinglePayForRoadUid
p.RoadName = m.SinglePayForRoadName
} else {
roadPoolInfo := road.GetRoadPoolByRoadPoolCode(m.RollPayForRoadCode)
roadUids := strings.Split(roadPoolInfo.RoadUidPool, "||")
roadInfoList := road.GetRoadInfosByRoadUids(roadUids)
if len(roadUids) == 0 || len(roadInfoList) == 0 {
logs.Error(fmt.Sprintf("通道轮询池=%s, 没有配置通道", m.RollPayForRoadCode))
} else {
p.RoadUid = roadInfoList[0].RoadUid
p.RoadName = roadInfoList[0].RoadName
}
}
if !payfor.UpdatePayFor(p) {
return false
}
if len(p.RoadUid) > 0 {
roadInfo := road.GetRoadInfoByRoadUid(p.RoadUid)
p.PayforFee = roadInfo.SettleFee
p.PayforTotalAmount = p.PayforFee + p.PayforAmount
if m.PayforFee > conf.ZERO {
logs.Info(fmt.Sprintf("商户uid=%s有单独的代付手续费。", m.MerchantUid))
p.PayforFee = m.PayforFee
p.PayforTotalAmount = p.PayforFee + p.PayforAmount
}
if !payfor.UpdatePayFor(p) {
return false
}
if p.GiveType == conf.SELF_HELP {
if !MerchantSelf(p) {
return false
}
} else {
if !SendPayFor(p) {
return false
}
}
} else {
p.Status = conf.PAYFOR_FAIL
if !payfor.UpdatePayFor(p) {
return false
}
p.ResponseContent = "没有设置代付通道"
}
}
return true
}
/**
** 商户自己体现
*/
func MerchantSelf(p payfor.PayforInfo) bool {
o := orm.NewOrm()
if err := o.DoTx(func(ctx context.Context, txOrm orm.TxOrmer) error {
p.UpdateTime = utils.GetBasicDateTime()
p.Status = conf.PAYFOR_BANKING
p.RequestTime = utils.GetBasicDateTime()
p.IsSend = conf.YES
if _, err := txOrm.Update(&p); err != nil {
return err
}
RequestPayFor(p)
return nil
}); err != nil {
return false
}
return true
}
func SendPayFor(p payfor.PayforInfo) bool {
o := orm.NewOrm()
if err := o.DoTx(func(ctx context.Context, txOrm orm.TxOrmer) error {
var account accounts.AccountInfo
if err := txOrm.Raw("select * from account_info where account_uid = ? for update", p.MerchantUid).QueryRow(&account); err != nil || account.AccountUid == "" {
logs.Error("send payfor select account fail", err)
return err
}
//支付金额不足,将直接判定为失败,不往下面邹逻辑了
if account.SettleAmount-account.PayforAmount < p.PayforAmount+p.PayforFee {
p.Status = conf.PAYFOR_FAIL
p.UpdateTime = utils.GetBasicDateTime()
if _, err := txOrm.Update(&p); err != nil {
return err
} else {
return nil
}
}
account.UpdateTime = utils.GetBasicDateTime()
account.PayforAmount = account.PayforAmount + p.PayforAmount + p.PayforFee
if _, err := txOrm.Update(&account); err != nil {
logs.Error(fmt.Sprintf("商户uid=%s在发送代付给上游的处理中更新账户表出错, err: %s", p.MerchantUid, err))
return err
}
p.IsSend = conf.YES
p.Status = conf.PAYFOR_BANKING //变为银行处理中
p.GiveType = conf.PAYFOR_ROAD
p.RequestTime = utils.GetBasicDateTime()
p.UpdateTime = utils.GetBasicDateTime()
if _, err := txOrm.Update(&p); err != nil {
logs.Error(fmt.Sprintf("商户uid=%s在发送代付给上游的处理中更代付列表出错 err%s", p.MerchantUid, err))
return err
}
RequestPayFor(p)
return nil
}); err != nil {
return false
}
return true
}
func RequestPayFor(p payfor.PayforInfo) {
if p.RoadUid == "" {
return
}
p.Type = conf.PAYFOR_ROAD
roadInfo := road.GetRoadInfoByRoadUid(p.RoadUid)
supplierCode := roadInfo.ProductUid
supplier := third_party.GetPaySupplierByCode(supplierCode)
res := supplier.PayFor(p)
logs.Info(fmt.Sprintf("代付uid=%s上游处理结果为%s", p.PayforUid, res))
//将代付订单号发送到消息队列
message.SendMessage(conf.MQ_PAYFOR_QUERY, p.BankOrderId)
}
/**
* 代付结果查询
*/
func PayForResultQuery(params map[string]string) string {
query := make(map[string]string)
query["merchantOrderId"] = params["merchantOrderId"]
merchantInfo := merchant.GetMerchantByPaykey(params["merchantKey"])
if !utils.Md5Verify(params, merchantInfo.MerchantSecret) {
query["resultMsg"] = "签名错误"
query["settStatus"] = "03"
query["sign"] = utils.GetMD5Sign(params, utils.SortMap(params), merchantInfo.MerchantSecret)
} else {
payForInfo := payfor.GetPayForByMerchantOrderId(params["merchantOrderId"])
if payForInfo.BankOrderId == "" {
query["resultMsg"] = "不存在这样的代付订单"
query["settStatus"] = "03"
query["sign"] = utils.GetMD5Sign(params, utils.SortMap(params), merchantInfo.MerchantSecret)
} else {
switch payForInfo.Status {
case conf.PAYFOR_BANKING:
query["resultMsg"] = "打款中"
query["settStatus"] = "02"
case conf.PAYFOR_SOLVING:
query["resultMsg"] = "打款中"
query["settStatus"] = "02"
case conf.PAYFOR_COMFRIM:
query["resultMsg"] = "打款中"
query["settStatus"] = "02"
case conf.PAYFOR_SUCCESS:
query["resultMsg"] = "打款成功"
query["settStatus"] = "00"
query["settAmount"] = strconv.FormatFloat(payForInfo.PayforAmount, 'f', 2, 64)
query["settFee"] = strconv.FormatFloat(payForInfo.PayforFee, 'f', 2, 64)
case conf.PAYFOR_FAIL:
query["resultMsg"] = "打款失败"
query["settStatus"] = "01"
}
query["sign"] = utils.GetMD5Sign(query, utils.SortMap(query), merchantInfo.MerchantSecret)
}
}
mJson, err := json.Marshal(query)
if err != nil {
logs.Error("PayForQuery json marshal fail", err)
return fmt.Sprintf("PayForQuery json marshal fail%s", err.Error())
} else {
return string(mJson)
}
}
/**
* 商户查询余额
*/
func BalanceQuery(params map[string]string) string {
balanceResponse := new(response.BalanceResponse)
str := ""
merchantInfo := merchant.GetMerchantByPaykey(params["merchantKey"])
if !utils.Md5Verify(params, merchantInfo.MerchantSecret) {
balanceResponse.ResultCode = "-1"
balanceResponse.ResultMsg = "签名错误"
mJson, _ := json.Marshal(balanceResponse)
str = string(mJson)
} else {
accountInfo := accounts.GetAccountByUid(merchantInfo.MerchantUid)
tmp := make(map[string]string)
tmp["resultCode"] = "00"
tmp["balance"] = strconv.FormatFloat(accountInfo.Balance, 'f', 2, 64)
tmp["availableAmount"] = strconv.FormatFloat(accountInfo.SettleAmount, 'f', 2, 64)
tmp["freezeAmount"] = strconv.FormatFloat(accountInfo.FreezeAmount, 'f', 2, 64)
tmp["waitAmount"] = strconv.FormatFloat(accountInfo.WaitAmount, 'f', 2, 64)
tmp["loanAmount"] = strconv.FormatFloat(accountInfo.LoanAmount, 'f', 2, 64)
tmp["payforAmount"] = strconv.FormatFloat(accountInfo.PayforAmount, 'f', 2, 64)
tmp["resultMsg"] = "查询成功"
tmp["sign"] = utils.GetMD5Sign(tmp, utils.SortMap(tmp), merchantInfo.MerchantSecret)
mJson, _ := json.Marshal(tmp)
str = string(mJson)
}
return str
}
func checkSettAmount(settAmount string) (bool, string) {
_, err := strconv.ParseFloat(settAmount, 64)
if err != nil {
logs.Error(fmt.Sprintf("代付金额有误settAmount = %s", settAmount))
return false, "代付金额有误"
}
return true, ""
}