由gopath形式改为module

This commit is contained in:
kongyuebin
2021-04-27 15:33:49 +08:00
parent aef4dbb33c
commit 77d895e83a
1117 changed files with 332447 additions and 20 deletions

View File

@@ -0,0 +1,70 @@
/***************************************************
** @Desc : This file for ...
** @Time : 2019/10/28 16:38
** @Author : yuebin
** @File : alipay
** @Last Modified by : yuebin
** @Last Modified time: 2019/10/28 16:38
** @Software: GoLand
****************************************************/
package controller
import (
"dongfeng/service/models"
)
type AlipayImpl struct {
}
func (c *AlipayImpl) Scan(orderInfo models.OrderInfo, roadInfo models.RoadInfo, merchantInfo models.MerchantInfo) ScanData {
var scanData ScanData
scanData.Status = "01"
return scanData
}
func (c *AlipayImpl) H5(orderInfo models.OrderInfo, roadInfo models.RoadInfo, merchantInfo models.MerchantInfo) ScanData {
var scanData ScanData
scanData.Status = "01"
return scanData
}
func (c *AlipayImpl) Syt(orderInfo models.OrderInfo, roadInfo models.RoadInfo, merchantInfo models.MerchantInfo) ScanData {
var scanData ScanData
scanData.Status = "01"
return scanData
}
func (c *AlipayImpl) Fast(orderInfo models.OrderInfo, roadInfo models.RoadInfo, merchantInfo models.MerchantInfo) bool {
var scanData ScanData
scanData.Status = "01"
return true
}
func (c *AlipayImpl) Web(orderInfo models.OrderInfo, roadInfo models.RoadInfo, merchantInfo models.MerchantInfo) bool {
var scanData ScanData
scanData.Status = "01"
return true
}
func (c *AlipayImpl) PayNotify() {
}
func (c *AlipayImpl) PayQuery(orderInfo models.OrderInfo) bool {
return true
}
func (c *AlipayImpl) PayFor(info models.PayforInfo) string {
return ""
}
func (c *AlipayImpl) PayForNotify() string {
return ""
}
func (c *AlipayImpl) PayForQuery(payFor models.PayforInfo) (string, string) {
return "", ""
}
func (c *AlipayImpl) BalanceQuery(roadInfo models.RoadInfo) float64 {
return 0.00
}

View File

@@ -0,0 +1,14 @@
/***************************************************
** @Desc : This file for ...
** @Time : 2019/11/19 18:12
** @Author : yuebin
** @File : consts.go
** @Last Modified by : yuebin
** @Last Modified time: 2019/11/19 18:12
** @Software: GoLand
****************************************************/
package controller
const (
PayNotify = ""
)

View File

@@ -0,0 +1,48 @@
/***************************************************
** @Desc : 处理网关模块的一些需要操作数据库的功能
** @Time : 2019/12/7 16:40
** @Author : yuebin
** @File : gateway_solve
** @Last Modified by : yuebin
** @Last Modified time: 2019/12/7 16:40
** @Software: GoLand
****************************************************/
package controller
import (
"github.com/astaxie/beego/logs"
"github.com/astaxie/beego/orm"
"dongfeng/service/models"
)
/*
* 插入支付订单记录和订单利润记录,保证一致性
*/
func InsertOrderAndOrderProfit(orderInfo models.OrderInfo, orderProfitInfo models.OrderProfitInfo) bool {
o := orm.NewOrm()
o.Begin()
defer func(interface{}) {
if err := recover(); err != nil {
o.Rollback()
}
}(o)
if _, err := o.Insert(&orderInfo); err != nil {
logs.Error("insert orderInfo fail: ", err)
o.Rollback()
return false
}
if _, err := o.Insert(&orderProfitInfo); err != nil {
logs.Error("insert orderProfit fail: ", err)
o.Rollback()
return false
}
if err := o.Commit(); err != nil {
logs.Error("insert order and orderProfit fail", err)
} else {
logs.Info("插入order和orderProfit记录成功")
}
return true
}

View File

@@ -0,0 +1,32 @@
/***************************************************
** @Desc : 注册上游支付接口
** @Time : 2019/10/28 14:48
** @Author : yuebin
** @File : init
** @Last Modified by : yuebin
** @Last Modified time: 2019/10/28 14:48
** @Software: GoLand
****************************************************/
package controller
import (
"dongfeng/service/common"
"github.com/astaxie/beego/logs"
)
var registerSupplier = make(map[string]PayInterface)
//注册各种上游的支付接口
func Init() {
registerSupplier["KF"] = new(KuaiFuImpl)
logs.Notice(common.CheckSupplierByCode("KF"))
registerSupplier["WEIXIN"] = new(WeiXinImpl)
logs.Notice(common.CheckSupplierByCode("WEIXIN"))
registerSupplier["ALIPAY"] = new(AlipayImpl)
logs.Notice(common.CheckSupplierByCode("ALIPAY"))
}
func GetPaySupplierByCode(code string) PayInterface {
return registerSupplier[code]
}

View File

@@ -0,0 +1,381 @@
/***************************************************
** @Desc : 快付支付的实现逻辑
** @Time : 2019/10/28 14:12
** @Author : yuebin
** @File : kuaifu
** @Last Modified by : yuebin
** @Last Modified time: 2019/10/28 14:12
** @Software: GoLand
****************************************************/
package controller
import (
"fmt"
"github.com/astaxie/beego"
"github.com/astaxie/beego/httplib"
"github.com/astaxie/beego/logs"
"github.com/rs/xid"
"github.com/widuu/gojson"
"dongfeng/service/common"
"dongfeng/service/models"
"dongfeng/service/utils"
"strconv"
"strings"
)
type KuaiFuImpl struct {
beego.Controller
}
const (
HOST = "localhost"
KF_SCAN_HOST = "http://" + HOST + "/gateway/scanPay/payService"
KF_PAYFOR_HOST = "http://" + HOST + "/gateway/remittance/pay"
KF_BALANCE_QUERY = "http://" + HOST + "/gateway/remittance/getBalance"
KF_ORDER_QUERY = "http://" + HOST + "/gateway/scanPay/orderQuery"
KF_PAYFOR_QUERY = "http://" + HOST + "/gateway/remittance/query"
KF_PAY_KEY = "xxxxxxx"
KF_PAY_SECRET = "xxxxxx"
)
func (c *KuaiFuImpl) Scan(orderInfo models.OrderInfo, roadInfo models.RoadInfo, merchantInfo models.MerchantInfo) ScanData {
payWayCode := ""
switch orderInfo.PayTypeCode {
case "ALI_SCAN":
payWayCode = "SCAN_ALIPAY"
case "WEIXIN_SCAN":
payWayCode = "SCAN_WEIXIN"
case "QQ_SCAN":
payWayCode = "SCAN_QQ"
case "UNION_SCAN":
payWayCode = "SCAN_YL"
case "BAIDU_SCAN":
case "JD_SCAN":
}
//将金额转为带有2位小数点的float
order := fmt.Sprintf("%0.2f", orderInfo.OrderAmount)
params := make(map[string]string)
params["orderNo"] = orderInfo.BankOrderId
params["productName"] = orderInfo.ShopName
params["orderPeriod"] = orderInfo.OrderPeriod
params["orderPrice"] = order
params["payWayCode"] = payWayCode
params["osType"] = orderInfo.OsType
params["notifyUrl"] = PayNotify + "KF"
params["payKey"] = KF_PAY_KEY
//params["field1"] = "field1"
keys := utils.SortMap(params)
sign := utils.GetMD5Sign(params, keys, KF_PAY_SECRET)
params["sign"] = sign
req := httplib.Post(KF_SCAN_HOST)
for k, v := range params {
req.Param(k, v)
}
var scanData ScanData
scanData.Supplier = orderInfo.PayProductCode
scanData.PayType = orderInfo.PayTypeCode
scanData.OrderNo = orderInfo.MerchantOrderId
scanData.BankNo = orderInfo.BankOrderId
scanData.OrderPrice = params["orderPrice"]
response, err := req.String()
if err != nil {
logs.Error("KF 请求失败:", err)
scanData.Status = "01"
scanData.Msg = gojson.Json(response).Get("statusMsg").Tostring()
return scanData
}
statusCode := gojson.Json(response).Get("statusCode").Tostring()
if statusCode != "00" {
logs.Error("KF生成扫码地址失败")
scanData.Status = "01"
scanData.Msg = "生成扫码地址失败"
return scanData
}
payUrl := gojson.Json(response).Get("payURL").Tostring()
scanData.Status = "00"
scanData.PayUrl = payUrl
scanData.Msg = "请求成功"
return scanData
}
func (c *KuaiFuImpl) H5(orderInfo models.OrderInfo, roadInfo models.RoadInfo, merchantInfo models.MerchantInfo) ScanData {
var scanData ScanData
scanData.Status = "01"
return scanData
}
func (c *KuaiFuImpl) Syt(orderInfo models.OrderInfo, roadInfo models.RoadInfo, merchantInfo models.MerchantInfo) ScanData {
var scanData ScanData
scanData.Status = "01"
return scanData
}
func (c *KuaiFuImpl) Fast(orderInfo models.OrderInfo, roadInfo models.RoadInfo, merchantInfo models.MerchantInfo) bool {
var scanData ScanData
scanData.Status = "01"
return true
}
func (c *KuaiFuImpl) Web(orderInfo models.OrderInfo, roadInfo models.RoadInfo, merchantInfo models.MerchantInfo) bool {
var scanData ScanData
scanData.Status = "01"
return true
}
//支付回调
func (c *KuaiFuImpl) PayNotify() {
params := make(map[string]string)
orderNo := strings.TrimSpace(c.GetString("orderNo"))
orderInfo := models.GetOrderByBankOrderId(orderNo)
if orderInfo.BankOrderId == "" || len(orderInfo.BankOrderId) == 0 {
logs.Error("快付回调的订单号不存在,订单号=", orderNo)
c.StopRun()
}
roadInfo := models.GetRoadInfoByRoadUid(orderInfo.RoadUid)
if roadInfo.RoadUid == "" || len(roadInfo.RoadUid) == 0 {
logs.Error("支付通道已经关系或者删除,不进行回调")
c.StopRun()
}
merchantUid := orderInfo.MerchantUid
merchantInfo := models.GetMerchantByUid(merchantUid)
if merchantInfo.MerchantUid == "" || len(merchantInfo.MerchantUid) == 0 {
logs.Error("快付回调失败该商户不存在或者已经删除商户uid=", merchantUid)
c.StopRun()
}
paySecret := merchantInfo.MerchantSecret
params["orderNo"] = orderNo
params["orderPrice"] = strings.TrimSpace(c.GetString("orderPrice"))
params["orderTime"] = strings.TrimSpace(c.GetString("orderTime"))
params["trxNo"] = strings.TrimSpace(c.GetString("trxNo"))
params["statusCode"] = strings.TrimSpace(c.GetString("statusCode"))
params["tradeStatus"] = strings.TrimSpace(c.GetString("tradeStatus"))
params["field1"] = strings.TrimSpace(c.GetString("field1"))
params["payKey"] = strings.TrimSpace(c.GetString("payKey"))
//对参数进行验签
keys := utils.SortMap(params)
tmpSign := utils.GetMD5Sign(params, keys, paySecret)
sign := strings.TrimSpace(c.GetString("sign"))
if tmpSign != sign {
logs.Error("快付回调签名异常,回调失败")
c.StopRun()
}
//实际支付金额
factAmount, err := strconv.ParseFloat(params["orderPrice"], 64)
if err != nil {
logs.Error("快付回调实际金额有误, factAmount=", params["orderPrice"])
c.StopRun()
}
orderInfo.FactAmount = factAmount
orderInfo.BankTransId = params["trxNo"]
tradeStatus := params["tradeStatus"]
paySolveController := new(PaySolveController)
if tradeStatus == "FAILED" {
if !paySolveController.SolvePayFail(orderInfo, "fail") {
logs.Error("solve order fail fail")
}
} else if tradeStatus == "CANCELED" {
if !paySolveController.SolvePayFail(orderInfo, "cancel") {
logs.Error("solve order cancel fail")
}
} else if tradeStatus == "WAITING_PAYMENT" {
logs.Notice("快付回调该订单还处于等待支付订单id=", orderNo)
} else if tradeStatus == "SUCCESS" {
//订单支付成功,需要搞很多事情 TODO
paySolveController.SolvePaySuccess(orderInfo.BankOrderId, orderInfo.FactAmount, c.GetString("trxNo"))
}
c.Ctx.WriteString("success")
}
func (c *KuaiFuImpl) PayQuery(orderInfo models.OrderInfo) bool {
if orderInfo.Status != "wait" && orderInfo.Status != "" {
logs.Error("订单已经被处理不需要查询bankOrderId", orderInfo.BankOrderId)
return false
}
params := make(map[string]string)
params["orderNo"] = orderInfo.BankOrderId
params["payKey"] = KF_PAY_KEY
paySecret := KF_PAY_SECRET
keys := utils.SortMap(params)
params["sign"] = utils.GetMD5Sign(params, keys, paySecret)
req := httplib.Get(KF_ORDER_QUERY)
for k, v := range params {
req.Param(k, v)
}
response, err := req.String()
if err != nil {
logs.Error("快付订单查询失败,bankOrderId: ", orderInfo.BankOrderId)
logs.Error("err: ", err)
return false
}
statusCode := gojson.Json(response).Get("statusCode").Tostring()
if statusCode != "00" {
logs.Error("快付订单查询返回失败bankOrderId", orderInfo.BankOrderId)
logs.Error("err: ", response)
return false
}
//获取用户的实际支付金额
orderPrice := gojson.Json(response).Get("orderPrice").Tostring()
factAmount, err := strconv.ParseFloat(orderPrice, 64)
if err != nil {
logs.Error("快速查询得到的实际金额错误, orderPrice=", orderPrice)
}
//orderInfo.FactAmount = orderInfo.OrderAmount
tradeStatus := gojson.Json(response).Get("tradeStatus").Tostring()
paySolveController := new(PaySolveController)
trxNo := gojson.Json(response).Get("trxNo").Tostring()
if tradeStatus == "SUCCESS" {
//调用支付成功的接口,做加款更新操作,需要把实际支付金额传入
if !paySolveController.SolvePaySuccess(orderInfo.BankOrderId, factAmount, trxNo) {
return false
}
} else if tradeStatus == "FAILED" {
if !paySolveController.SolvePayFail(orderInfo, "fail") {
return false
}
} else {
logs.Info("订单状态处于:" + tradeStatus + "bankOrderId" + orderInfo.BankOrderId)
}
return true
}
func (c *KuaiFuImpl) PayFor(payFor models.PayforInfo) string {
params := make(map[string]string)
params["merchantKey"] = KF_PAY_KEY
params["realname"] = payFor.BankAccountName
params["cardNo"] = payFor.BankAccountNo
params["bankCode"] = payFor.BankCode
if payFor.BankAccountType == common.PRIVATE {
params["accType"] = "01"
} else {
params["accType"] = "02"
}
params["province"] = payFor.BankAccountAddress
params["city"] = payFor.BankAccountAddress
params["bankAccountAddress"] = payFor.BankAccountAddress
//将float64转为字符串
params["amount"] = strconv.FormatFloat(payFor.PayforAmount, 'f', 2, 64)
params["moblieNo"] = payFor.PhoneNo
params["merchantOrderId"] = payFor.BankOrderId
keys := utils.SortMap(params)
sign := utils.GetMD5Sign(params, keys, KF_PAY_SECRET)
params["sign"] = sign
req := httplib.Post(KF_PAYFOR_HOST)
for k, v := range params {
req.Param(k, v)
}
response, err := req.String()
if err != nil {
logs.Error("快付代付返回错误结果: ", response)
} else {
json := gojson.Json(response)
resultCode := json.Get("resultCode").Tostring()
resultMsg := json.Get("resultMsg").Tostring()
if resultCode != "00" {
logs.Error("快付代付返回错误信息:", resultMsg)
return "fail"
}
settStatus := json.Get("settStatus").Tostring()
if settStatus == "00" {
logs.Info(fmt.Sprintf("代付uid=%s已经成功发送给了上游处理", payFor.PayforUid))
} else if settStatus == "01" {
logs.Info(fmt.Sprintf("代付uid=%s发送失败", payFor.PayforUid))
}
}
return "success"
}
func (c *KuaiFuImpl) PayForNotify() string {
return ""
}
func (c *KuaiFuImpl) PayForQuery(payFor models.PayforInfo) (string, string) {
params := make(map[string]string)
params["merchantKey"] = KF_PAY_KEY
params["timestamp"] = utils.GetNowTimesTamp()
params["merchantOrderId"] = payFor.BankOrderId
keys := utils.SortMap(params)
sign := utils.GetMD5Sign(params, keys, KF_PAY_SECRET)
params["sign"] = sign
req := httplib.Get(KF_PAYFOR_QUERY)
for k, v := range params {
req.Param(k, v)
}
response, err := req.String()
if err != nil {
logs.Error("快付代付查询失败:", err)
return common.PAYFOR_SOLVING, "查询失败"
}
payFor.ResponseContext = response
payFor.ResponseTime = utils.GetBasicDateTime()
payFor.UpdateTime = utils.GetBasicDateTime()
if !models.UpdatePayFor(payFor) {
logs.Error("更新快付代付订单状态失败")
}
resultCode := gojson.Json(response).Get("resultCode").Tostring()
resultMsg := gojson.Json(response).Get("resultMsg").Tostring()
if resultCode != "00" {
logs.Error("快付代付查询返回错误:", resultMsg)
return common.PAYFOR_SOLVING, resultMsg
}
logs.Info("快付代付查询返回结果:", resultMsg)
merchantOrderId := gojson.Json(response).Get("merchantOrderId").Tostring()
if merchantOrderId != payFor.BankOrderId {
logs.Error("快付代付返回结果订单id不一致: ", merchantOrderId)
return common.PAYFOR_SOLVING, "快付代付返回结果订单id不一致"
}
settStatus := gojson.Json(response).Get("settStatus").Tostring()
if settStatus == "00" {
return common.PAYFOR_SUCCESS, "代付成功"
} else if settStatus == "01" {
return common.PAYFOR_FAIL, "代付失败"
} else {
return common.PAYFOR_BANKING, "银行处理中"
}
}
func (c *KuaiFuImpl) BalanceQuery(roadInfo models.RoadInfo) float64 {
params := make(map[string]string)
params["merchantKey"] = KF_PAY_KEY
params["timestamp"] = utils.GetNowTimesTamp()
params["merchantOrderId"] = xid.New().String()
keys := utils.SortMap(params)
sign := utils.GetMD5Sign(params, keys, KF_PAY_SECRET)
params["sign"] = sign
req := httplib.Get(KF_BALANCE_QUERY)
for k, v := range params {
req.Param(k, v)
}
response, err := req.String()
if err != nil {
logs.Error("快付余额查询失败,err: ", err)
return 0.00
}
logs.Debug("快付余额查询返回:", response)
resultCode := gojson.Json(response).Get("resultCode").Tostring()
resultMsg := gojson.Json(response).Get("resultMsg").Tostring()
logs.Notice("快付返回信息:", resultMsg)
if resultCode != "00" {
return 0.00
}
balance := gojson.Json(response).Get("balance").Tostring()
availableAmount := gojson.Json(response).Get("availableAmount").Tostring()
logs.Info(fmt.Sprintf("快付余额=%s可用金额=%s", balance, availableAmount))
f, err := strconv.ParseFloat(availableAmount, 64)
return f
}

View File

@@ -0,0 +1,203 @@
/***************************************************
** @Desc : 订单结算,将订单上面的钱加入到账户余额中
** @Time : 2019/11/22 11:34
** @Author : yuebin
** @File : order_settle
** @Last Modified by : yuebin
** @Last Modified time: 2019/11/22 11:34
** @Software: GoLand
****************************************************/
package controller
import (
"fmt"
"github.com/astaxie/beego/logs"
"github.com/astaxie/beego/orm"
"dongfeng/service/common"
"dongfeng/service/models"
"dongfeng/service/utils"
"time"
)
//订单结算,将那些支付成功的订单金额加入到商户账户的结算金额中
func OrderSettle() {
params := make(map[string]string)
params["is_allow_settle"] = common.YES
params["is_complete_settle"] = common.NO
orderSettleList := models.GetOrderSettleListByParams(params)
for _, orderSettle := range orderSettleList {
orderProfitInfo := models.GetOrderProfitByBankOrderId(orderSettle.BankOrderId)
if !settle(orderSettle, orderProfitInfo) {
logs.Error(fmt.Sprintf("结算订单bankOrderId=%s 执行失败", orderSettle.BankOrderId))
} else {
logs.Info(fmt.Sprintf("结算订单bankOrderId=%s执行成功", orderSettle.BankOrderId))
}
}
}
func settle(orderSettle models.OrderSettleInfo, orderProfit models.OrderProfitInfo) bool {
o := orm.NewOrm()
o.Begin()
defer func(interface{}) {
if err := recover(); err != nil {
logs.Error(fmt.Sprintf("结算信息出了panic错误信息%s", err))
o.Rollback()
return
}
}(o)
tmpSettle := new(models.OrderSettleInfo)
if err := o.Raw("select * from order_settle_info where bank_order_id=? for update", orderSettle.BankOrderId).QueryRow(tmpSettle); err != nil || tmpSettle == nil {
logs.Error("获取tmpSettle失败bankOrderId=%s", orderSettle.BankOrderId)
o.Rollback()
return false
}
tmpSettle.UpdateTime = utils.GetBasicDateTime()
tmpSettle.IsCompleteSettle = common.YES
if _, err := o.Update(tmpSettle); err != nil {
logs.Error("更新tmpSettle失败错误", err)
o.Rollback()
return false
}
accountInfo := new(models.AccountInfo)
if err := o.Raw("select * from account_info where account_uid=? for update", orderSettle.MerchantUid).QueryRow(accountInfo); err != nil || accountInfo == nil {
logs.Error("结算select account info失败错误信息", err)
o.Rollback()
return false
}
accountInfo.UpdateTime = utils.GetBasicDateTime()
accountInfo.SettleAmount += orderProfit.FactAmount
if _, err := o.Update(accountInfo); err != nil {
logs.Error("结算update account 失败,错误信息:", err)
o.Rollback()
return false
}
merchantDeployInfo := models.GetMerchantDeployByUidAndPayType(accountInfo.AccountUid, orderSettle.PayTypeCode)
if merchantDeployInfo.IsLoan == common.YES {
loadAmount := merchantDeployInfo.LoanRate * 0.01 * orderProfit.FactAmount
date := utils.GetDate()
params := make(map[string]string)
params["merchant_uid"] = tmpSettle.MerchantUid
params["road_uid"] = tmpSettle.RoadUid
params["load_date"] = date
if !models.IsExistMerchantLoadByParams(params) {
tmp := models.MerchantLoadInfo{Status: common.NO, MerchantUid: orderSettle.MerchantUid, RoadUid: orderSettle.RoadUid,
LoadDate: date, LoadAmount: loadAmount, UpdateTime: utils.GetBasicDateTime(), CreateTime: utils.GetBasicDateTime()}
if _, err := o.Insert(tmp); err != nil {
logs.Error("結算插入merchantLoad失敗失败信息", err)
o.Rollback()
return false
} else {
logs.Info("结算插入新的merchantLoad信息成功")
}
} else {
merchantLoad := new(models.MerchantLoadInfo)
if err := o.Raw("select * from merchant_load_info where merchant_uid=? and road_uid=? and load_date=? for update").
QueryRow(merchantLoad); err != nil || merchantLoad == nil {
logs.Error(fmt.Sprintf("结算过程select merchant load info失败错误信息%s", err))
o.Rollback()
return false
} else {
merchantLoad.UpdateTime = utils.GetBasicDateTime()
merchantLoad.LoadAmount += loadAmount
if _, err := o.Update(merchantLoad); err != nil {
logs.Error(fmt.Sprintf("结算过程update merchant load info失败失败信息%s", err))
o.Rollback()
return false
}
}
}
} else {
logs.Info(fmt.Sprintf("结算过程中,该商户不需要押款,全款结算"))
}
return true
}
/*
* 商户的押款释放处理,根据商户的押款时间进行处理
*/
func MerchantLoadSolve() {
hour := time.Now().Hour()
merchantDeployList := models.GetMerchantDeployByHour(hour)
for _, merchantDeploy := range merchantDeployList {
logs.Info(fmt.Sprintf("开始执行商户uid=%s进行解款操作", merchantDeploy.MerchantUid))
loadDate := utils.GetDateBeforeDays(merchantDeploy.LoanDays)
params := make(map[string]string)
params["status"] = common.NO
params["merchant_uid"] = merchantDeploy.MerchantUid
params["load_date"] = loadDate
merchantLoadList := models.GetMerchantLoadInfoByMap(params)
for _, merchantLoad := range merchantLoadList {
if MerchantAbleAmount(merchantLoad) {
logs.Info(fmt.Sprintf("商户uid=%s押款金额=%f押款通道=%s, 解款成功", merchantLoad.MerchantUid, merchantLoad.LoadAmount, merchantLoad.RoadUid))
} else {
logs.Error(fmt.Sprintf("商户uid=%s押款金额=%f押款通道=%s, 解款失败", merchantLoad.MerchantUid, merchantLoad.LoadAmount, merchantLoad.RoadUid))
}
}
}
}
/*
* 对应的商户的账户可用金额进行调整操作
*/
func MerchantAbleAmount(merchantLoad models.MerchantLoadInfo) bool {
o := orm.NewOrm()
o.Begin()
defer func(interface{}) {
if err := recover(); err != nil {
logs.Error(fmt.Sprintf("解款操作出现了painc错误信息%s", err))
o.Rollback()
return
}
}(o)
tmpLoad := new(models.MerchantLoadInfo)
if err := o.Raw("select * from merchant_load_info where merchant_uid=? and road_uid=? and load_date=? for update",
merchantLoad.MerchantUid, merchantLoad.RoadUid, merchantLoad.LoadDate).QueryRow(tmpLoad); err != nil || tmpLoad == nil {
logs.Error(fmt.Sprintf("解款操作获取商户押款信息失败fail %s", err))
o.Rollback()
return false
}
if tmpLoad.Status != common.NO {
logs.Error(fmt.Sprintf("押款信息merchantuid=%s通道uid=%s 押款日期=%s,已经解款过,不需要再进行处理了", tmpLoad.MerchantUid, tmpLoad.RoadUid, tmpLoad.LoadDate))
o.Rollback()
return false
}
tmpLoad.UpdateTime = utils.GetBasicDateTime()
tmpLoad.Status = common.YES
if _, err := o.Update(tmpLoad); err != nil {
logs.Error(fmt.Sprintf("解款操作更新merchant load info 失败:%s", err))
o.Rollback()
return false
}
accountInfo := new(models.AccountInfo)
accountInfo.UpdateTime = utils.GetBasicDateTime()
if accountInfo.LoanAmount >= tmpLoad.LoadAmount {
accountInfo.LoanAmount -= tmpLoad.LoadAmount
} else {
accountInfo.LoanAmount = common.ZERO
}
if _, err := o.Update(accountInfo); err != nil {
logs.Error(fmt.Sprintf("解款操作更新account info 失败:%s账户uid=%s", err, accountInfo.AccountUid))
o.Rollback()
return false
}
if err := o.Commit(); err != nil {
logs.Error(fmt.Sprintf("解款操作commint事务失败账号uid=%s错误信息=%s", accountInfo.AccountUid, err))
} else {
logs.Info(fmt.Sprintf("账户uid=%s通道uid=%s押款日期=%s解款操作成功", accountInfo.AccountUid, tmpLoad.RoadUid, tmpLoad.LoadDate))
}
return true
}

View File

@@ -0,0 +1,539 @@
/***************************************************
** @Desc : 处理订单状态,用户加款等核心业务
** @Time : 2019/10/31 11:44
** @Author : yuebin
** @File : pay_solve
** @Last Modified by : yuebin
** @Last Modified time: 2019/10/31 11:44
** @Software: GoLand
****************************************************/
package controller
import (
"fmt"
"github.com/astaxie/beego/logs"
"github.com/astaxie/beego/orm"
"dongfeng/service/common"
"dongfeng/service/message_queue"
"dongfeng/service/models"
"dongfeng/service/utils"
url2 "net/url"
"strconv"
)
type PaySolveController struct {
}
//处理支付成功的加款等各项操作
func (c *PaySolveController) SolvePaySuccess(bankOrderId string, factAmount float64, trxNo string) bool {
o := orm.NewOrm()
o.Begin()
defer func(interface{}) {
if r := recover(); r != nil {
o.Rollback()
logs.Error("SolvePaySuccess fail call rollback")
}
}(o)
var orderInfo models.OrderInfo
if err := o.Raw("select * from order_info where bank_order_id = ? for update", bankOrderId).QueryRow(&orderInfo); err != nil || orderInfo.BankOrderId == "" {
o.Rollback()
logs.Error("不存在该订单或者select for update出错")
return false
}
if orderInfo.Status != "wait" {
o.Rollback()
logs.Error("该订单已经处理,订单号=", bankOrderId)
return false
}
if factAmount <= common.ZERO {
factAmount = orderInfo.OrderAmount
}
var orderProfitInfo models.OrderProfitInfo
if err := o.Raw("select * from order_profit_info where bank_order_id = ? for update", bankOrderId).QueryRow(&orderProfitInfo); err != nil || orderProfitInfo.BankOrderId == "" {
logs.Error("select order_profit_info for update fail: ", err)
o.Rollback()
return false
}
if orderProfitInfo.BankOrderId == "" {
logs.Error("solve pay success, get orderProfit fail, bankOrderId = ", bankOrderId)
o.Rollback()
return false
}
comp := c.CompareOrderAndFactAmount(factAmount, orderInfo)
//如果实际支付金额比订单金额大或者小,那么重新按照实际金额金额利润计算
if comp != 0 {
orderProfitInfo.FactAmount = factAmount
orderProfitInfo.SupplierProfit = orderInfo.FactAmount * orderProfitInfo.SupplierRate
orderProfitInfo.PlatformProfit = orderInfo.FactAmount * orderProfitInfo.PlatformRate
orderProfitInfo.AgentProfit = orderInfo.FactAmount * orderProfitInfo.AgentRate
orderProfitInfo.AllProfit = orderProfitInfo.SupplierProfit + orderProfitInfo.PlatformProfit + orderProfitInfo.AgentProfit
orderProfitInfo.UserInAmount = orderProfitInfo.FactAmount - orderProfitInfo.AllProfit
orderProfitInfo.UpdateTime = utils.GetBasicDateTime()
orderInfo.FactAmount = factAmount
//如果实际支付金额跟订单金额有出入,那么需要重新更新利润记录
if _, err := o.Update(orderProfitInfo); err != nil {
logs.Info("solve pay success fail", err)
}
}
orderInfo.Status = common.SUCCESS
orderInfo.BankTransId = trxNo
orderInfo.UpdateTime = utils.GetBasicDateTime()
if _, err := o.Update(&orderInfo); err != nil || orderInfo.BankOrderId == "" {
logs.Error(fmt.Sprintf("solve pay success, update order info fail: %s, bankOrderId = %s", err, bankOrderId))
o.Rollback()
return false
}
//插入一条待结算记录
settAmount := orderProfitInfo.FactAmount - orderProfitInfo.SupplierProfit - orderProfitInfo.PlatformProfit - orderProfitInfo.AgentProfit
if settAmount <= 0.00 {
logs.Error(fmt.Sprintf("订单id=%s计算利润存在异常", bankOrderId))
o.Rollback()
return false
}
orderSettleInfo := models.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: settAmount, IsAllowSettle: common.YES,
IsCompleteSettle: common.NO, UpdateTime: utils.GetBasicDateTime(), CreateTime: utils.GetBasicDateTime()}
if _, err := o.Insert(&orderSettleInfo); err != nil {
logs.Error(fmt.Sprintf("solve pay successinsert order settle info fail: %s, bankOrderId = %s", err, bankOrderId))
o.Rollback()
return false
}
//做账户的加款操作,最重要的一部
var accountInfo models.AccountInfo
if err := o.Raw("select * from account_info where account_uid = ? for update", orderInfo.MerchantUid).QueryRow(&accountInfo); err != nil || accountInfo.AccountUid == "" {
logs.Error(fmt.Sprintf("solve pay success, raw account info fail: %s, bankOrderId = %s", err, bankOrderId))
o.Rollback()
return false
}
if _, err := o.QueryTable(models.ACCOUNT_INFO).Filter("account_uid", orderInfo.MerchantUid).
Update(orm.Params{"balance": accountInfo.Balance + settAmount, "wait_amount": accountInfo.WaitAmount + settAmount}); err != nil {
logs.Error(fmt.Sprintf("solve pay success, update account info fail: %s, bankOrderId = %s", err, bankOrderId))
o.Rollback()
return false
}
//添加一条动账记录
accountHistory := models.AccountHistoryInfo{AccountUid: orderInfo.MerchantUid, AccountName: orderInfo.MerchantName,
Type: common.PLUS_AMOUNT, Amount: settAmount, Balance: accountInfo.Balance + settAmount,
UpdateTime: utils.GetBasicDateTime(), CreateTime: utils.GetBasicDateTime()}
if _, err := o.Insert(&accountHistory); err != nil {
logs.Error(fmt.Sprintf("solve pay successinsert account history fail%s, bankOrderId = %s", err, bankOrderId))
o.Rollback()
return false
}
//更新通道信息
roadInfo := models.GetRoadInfoByRoadUid(orderInfo.RoadUid)
roadInfo.UpdateTime = utils.GetBasicDateTime()
roadInfo.RequestSuccess += 1
roadInfo.TotalIncome += orderInfo.FactAmount
roadInfo.TodayIncome += orderInfo.FactAmount
roadInfo.TodayProfit += orderProfitInfo.PlatformProfit + orderProfitInfo.AgentProfit
roadInfo.TotalProfit += orderProfitInfo.PlatformProfit + orderProfitInfo.AgentProfit
roadInfo.UpdateTime = utils.GetBasicDateTime()
if _, err := o.Update(&roadInfo); err != nil {
logs.Error(fmt.Sprintf("solve pay success, update road info fail: %s, bankOrderId = %s", err, bankOrderId))
o.Rollback()
return false
}
//更新订单利润表
orderProfitInfo.Status = common.SUCCESS
orderProfitInfo.UpdateTime = utils.GetBasicDateTime()
if _, err := o.Update(&orderProfitInfo); err != nil {
logs.Error(fmt.Sprintf("solve pay success, update order profit info fail: %s, bankOrderId = %s", err, bankOrderId))
o.Rollback()
return false
}
if err := o.Commit(); err != nil {
logs.Error(fmt.Sprintf("订单bankOrderId = %s加款失败", bankOrderId))
logs.Error("失败原因:", err)
return false
} else {
logs.Info("账户加款成功,并记录了账户历史!")
//如果处理成功,发送到消息队列,进行商户的回调操作
go c.CreateOrderNotifyInfo(orderInfo, common.SUCCESS)
}
return true
}
//处理支付失败
func (c *PaySolveController) SolvePayFail(orderInfo models.OrderInfo, str string) bool {
o := orm.NewOrm()
o.Begin()
defer func(interface{}) {
if r := recover(); r != nil {
o.Rollback()
logs.Error("SolvePaySuccess fail call rollback")
}
}(o)
var orderTmp models.OrderInfo
bankOrderId := orderInfo.BankOrderId
if err := o.Raw("select * from order_info where bank_order_id = ?", bankOrderId).QueryRow(&orderTmp); err != nil || orderTmp.BankOrderId == "" {
o.Rollback()
return false
}
if orderTmp.Status != "wait" {
o.Rollback()
return false
}
_, err1 := o.QueryTable(models.ORDER_INFO).Filter("bank_order_id", bankOrderId).Update(orm.Params{"status": str, "bank_trans_id": orderInfo.BankTransId})
_, err2 := o.QueryTable(models.ORDER_PROFIT_INFO).Filter("bank_order_id", bankOrderId).Update(orm.Params{"status": str, "bank_trans_id": orderInfo.BankTransId})
if err1 != nil || err2 != nil {
logs.Error("SolvePayFail fail: ", err1, err2)
o.Rollback()
return false
} else {
o.Commit()
go c.CreateOrderNotifyInfo(orderInfo, common.FAIL)
return true
}
}
//处理订单冻结
func (c *PaySolveController) SolveOrderFreeze(bankOrderId string) bool {
o := orm.NewOrm()
o.Begin()
defer func(interface{}) {
if err := recover(); err != nil {
o.Rollback()
return
}
}(o)
var orderInfo models.OrderInfo
if err := o.Raw("select * from order_info where bank_order_id = ? for update", bankOrderId).QueryRow(&orderInfo); err != nil || orderInfo.BankOrderId == "" {
logs.Error("solve order freeze 不存在这样的订单记录bankOrderId = ", bankOrderId)
o.Rollback()
return false
}
if orderInfo.Status != common.SUCCESS {
o.Rollback()
return false
}
orderInfo.Freeze = common.YES
orderInfo.FreezeTime = utils.GetBasicDateTime()
orderInfo.UpdateTime = utils.GetBasicDateTime()
if _, err := o.Update(&orderInfo); err != nil {
logs.Error("solve order freeze fail: ", err)
o.Rollback()
return false
}
//账户的冻结金额里面加入相应的金额
orderProfitInfo := models.GetOrderProfitByBankOrderId(bankOrderId)
var accountInfo models.AccountInfo
if err := o.Raw("select * from account_info where account_uid = ? for update", orderInfo.MerchantUid).QueryRow(&accountInfo); err != nil || accountInfo.AccountUid == "" {
logs.Error(fmt.Sprintf("solve pay fail select acount fail%s", err))
o.Rollback()
return false
}
accountInfo.UpdateTime = utils.GetBasicDateTime()
accountInfo.FreezeAmount = accountInfo.FreezeAmount + orderProfitInfo.UserInAmount
if _, err := o.Update(&accountInfo); err != nil {
logs.Error("solve order freeze fail: ", err)
o.Rollback()
return false
}
//插入一条动账记录
accountHistoryInfo := models.AccountHistoryInfo{AccountName: accountInfo.AccountName, AccountUid: accountInfo.AccountUid,
Type: common.FREEZE_AMOUNT, Amount: orderProfitInfo.UserInAmount, Balance: accountInfo.Balance, UpdateTime: utils.GetBasicDateTime(), CreateTime: utils.GetBasicDateTime()}
if _, err := o.Insert(&accountHistoryInfo); err != nil {
logs.Error("solve order freeze fail: ", err)
o.Rollback()
return false
}
if err := o.Commit(); err != nil {
logs.Error("SolveOrderFreeze fail")
} else {
logs.Info("冻结处理成功")
}
return true
}
//订单解冻
func (c *PaySolveController) SolveOrderUnfreeze(bankOrderId string) bool {
o := orm.NewOrm()
o.Begin()
defer func(interface{}) {
if err := recover(); err != nil {
o.Rollback()
return
}
}(o)
orderInfo := new(models.OrderInfo)
if err := o.Raw("select * from order_info where bank_order_id = ? for update", bankOrderId).QueryRow(orderInfo); err != nil || orderInfo.BankOrderId == "" {
logs.Error("solve order unfreeze 不存在这样的订单记录bankOrderId = ", bankOrderId)
return false
}
orderInfo.Freeze = ""
orderInfo.Unfreeze = common.YES
orderInfo.UnfreezeTime = utils.GetBasicDateTime()
orderInfo.UpdateTime = utils.GetBasicDateTime()
if _, err := o.Update(orderInfo); err != nil {
logs.Error("solve order unfreeze fail: ", err)
o.Rollback()
return false
}
orderProfitInfo := models.GetOrderProfitByBankOrderId(bankOrderId)
accountInfo := new(models.AccountInfo)
if err := o.Raw("select * from account_info where account_uid = ? for update", orderInfo.MerchantUid).QueryRow(accountInfo); err != nil || accountInfo.AccountUid == "" {
logs.Error(fmt.Sprintf("unfreeze select account fail: %s", err))
o.Rollback()
return false
}
accountInfo.UpdateTime = utils.GetBasicDateTime()
accountInfo.FreezeAmount = accountInfo.FreezeAmount - orderProfitInfo.UserInAmount
if _, err := o.Update(accountInfo); err != nil {
logs.Error("solve order unfreeze fail: ", err)
o.Rollback()
return false
}
accountHistoryInfo := models.AccountHistoryInfo{AccountUid: accountInfo.AccountUid, AccountName: accountInfo.AccountName, Type: common.UNFREEZE_AMOUNT,
Amount: orderProfitInfo.UserInAmount, Balance: accountInfo.Balance, UpdateTime: utils.GetBasicDateTime(), CreateTime: utils.GetBasicDateTime()}
if _, err := o.Insert(&accountHistoryInfo); err != nil {
logs.Error("solve order unfreeze fail: ", err)
o.Rollback()
return false
}
if err := o.Commit(); err != nil {
logs.Error(fmt.Sprintf("unfreeze commit fail: %s", err))
return false
} else {
logs.Info("解冻成功")
}
return true
}
func (c *PaySolveController) SolveRefund(bankOrderId string) bool {
o := orm.NewOrm()
o.Begin()
defer func(interface{}) {
if err := recover(); err != nil {
o.Rollback()
return
}
}(o)
orderInfo := new(models.OrderInfo)
if err := o.Raw("select * from order_info where bank_order_id = ? for update", bankOrderId).QueryRow(orderInfo); err != nil || orderInfo.BankOrderId == "" {
logs.Error("solve refund 不存在这样的订单bankOrderId = " + bankOrderId)
return false
}
orderInfo.UpdateTime = utils.GetBasicDateTime()
orderInfo.Refund = common.YES
orderInfo.RefundTime = utils.GetBasicDateTime()
orderProfitInfo := models.GetOrderProfitByBankOrderId(bankOrderId)
account := new(models.AccountInfo)
if err := o.Raw("select * from account_info where account_uid = ? for update", orderInfo.MerchantUid).QueryRow(account); err != nil || account.AccountUid == "" {
o.Rollback()
return false
}
account.UpdateTime = utils.GetBasicDateTime()
account.SettleAmount = account.SettleAmount - orderProfitInfo.UserInAmount
account.Balance = account.Balance - orderProfitInfo.UserInAmount
if orderInfo.Freeze == common.YES {
account.FreezeAmount = account.FreezeAmount - orderProfitInfo.UserInAmount
if account.FreezeAmount < 0 {
account.FreezeAmount = common.ZERO
}
orderInfo.Freeze = ""
}
if _, err := o.Update(orderInfo); err != nil {
logs.Error("solve order refund update order info fail: ", err)
o.Rollback()
return false
}
if _, err := o.Update(account); err != nil {
logs.Error("solve order refund update account fail: ", err)
o.Rollback()
return false
}
accountHistoryInfo := models.AccountHistoryInfo{AccountName: account.AccountName, AccountUid: account.AccountUid,
Type: common.REFUND, Amount: orderProfitInfo.UserInAmount, Balance: account.Balance,
UpdateTime: utils.GetBasicDateTime(), CreateTime: utils.GetBasicDateTime()}
if _, err := o.Insert(&accountHistoryInfo); err != nil {
logs.Error("solve order refund insert account history fail: ", err)
o.Rollback()
return false
}
if err := o.Commit(); err != nil {
logs.Error("退款处理失败fail ", err)
} else {
logs.Info("退款处理成功")
}
return true
}
func (c *PaySolveController) SolveOrderRoll(bankOrderId string) bool {
o := orm.NewOrm()
o.Begin()
defer func(interface{}) {
if err := recover(); err != nil {
o.Rollback()
return
}
}(o)
orderInfo := new(models.OrderInfo)
if err := o.Raw("select * from order_info where bank_order_id = ? for update", bankOrderId).QueryRow(orderInfo); err != nil {
logs.Error("solve order roll fail ", err)
o.Rollback()
return false
}
if orderInfo.Status != common.SUCCESS {
logs.Error("solve order roll 订单不存在或者订单状态不是success, bankOrderId=", bankOrderId)
o.Rollback()
return false
}
orderInfo.UpdateTime = utils.GetBasicDateTime()
orderProfitInfo := models.GetOrderProfitByBankOrderId(bankOrderId)
account := new(models.AccountInfo)
if err := o.Raw("select * from account_info where account_uid = ? for update", orderInfo.MerchantUid).QueryRow(account); err != nil || account.AccountUid == "" {
logs.Error("solve order roll get account is nil, accountUid = ", orderInfo.MerchantUid)
o.Rollback()
return false
}
account.UpdateTime = utils.GetBasicDateTime()
if orderInfo.Refund == common.YES {
account.Balance = account.Balance + orderProfitInfo.UserInAmount
account.SettleAmount = account.SettleAmount + orderProfitInfo.UserInAmount
orderInfo.Refund = common.NO
}
if _, err := o.Update(orderInfo); err != nil {
logs.Error("solve order roll fail update order info fail: ", err)
o.Rollback()
return false
}
if _, err := o.Update(account); err != nil {
logs.Error("solve order roll update account fail: ", err)
o.Rollback()
return false
}
accountHistoryInfo := models.AccountHistoryInfo{AccountUid: account.AccountUid, AccountName: account.AccountName,
Type: common.PLUS_AMOUNT, Amount: orderProfitInfo.UserInAmount, Balance: account.Balance,
UpdateTime: utils.GetBasicDateTime(), CreateTime: utils.GetBasicDateTime()}
if _, err := o.Insert(&accountHistoryInfo); err != nil {
logs.Error("solve order roll insert account history fail: ", err)
o.Rollback()
return false
}
if err := o.Commit(); err != nil {
logs.Error("处理订单回滚失败,fail: ", err)
} else {
logs.Info("处理订单回滚成功")
}
return true
}
//比较订单金额和实际支付金额的大小
func (c *PaySolveController) CompareOrderAndFactAmount(factAmount float64, orderInfo models.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
}
}
//支付完成后,处理给商户的回调信息
func (c *PaySolveController) CreateOrderNotifyInfo(orderInfo models.OrderInfo, tradeStatus string) {
notifyInfo := new(models.NotifyInfo)
notifyInfo.Type = "order"
notifyInfo.BankOrderId = orderInfo.BankOrderId
notifyInfo.MerchantOrderId = orderInfo.MerchantOrderId
notifyInfo.Status = "wait"
notifyInfo.Times = 0
notifyInfo.UpdateTime = utils.GetBasicDateTime()
notifyInfo.CreateTime = utils.GetBasicDateTime()
merchantInfo := models.GetMerchantByUid(orderInfo.MerchantUid)
params := make(map[string]string)
params["orderNo"] = orderInfo.MerchantOrderId
params["orderPrice"] = strconv.FormatFloat(orderInfo.OrderAmount, 'f', 2, 64)
params["factPrice"] = strconv.FormatFloat(orderInfo.FactAmount, 'f', 2, 64)
params["orderTime"] = utils.GetDateTimeNot()
if orderInfo.BankTransId != "" {
params["trxNo"] = orderInfo.BankTransId
} else {
params["trxNo"] = orderInfo.BankOrderId
}
params["statusCode"] = "00"
params["tradeStatus"] = tradeStatus
params["payKey"] = merchantInfo.MerchantKey
params["sign"] = utils.GetMD5Sign(params, utils.SortMap(params), merchantInfo.MerchantSecret)
url := url2.Values{}
for k, v := range params {
url.Add(k, v)
}
notifyInfo.Url = orderInfo.NotifyUrl + "?" + url.Encode()
if models.InsertNotifyInfo(*notifyInfo) {
logs.Info(fmt.Sprintf("订单bankOrderId=%s已经将回调地址插入数据库", orderInfo.BankOrderId))
} else {
logs.Error(fmt.Sprintf("订单bankOrderId=%s插入回调数据库失败", orderInfo.BankOrderId))
}
//将订单发送到消息队列,给下面的商户进行回调
message_queue.SendMessage(common.MqOrderNotify, orderInfo.BankOrderId)
}

View File

@@ -0,0 +1,393 @@
/***************************************************
** @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 (
"fmt"
"github.com/astaxie/beego/logs"
"github.com/astaxie/beego/orm"
"dongfeng/service/common"
"dongfeng/service/message_queue"
"dongfeng/service/models"
"dongfeng/service/utils"
"strings"
)
func PayForFail(payFor models.PayforInfo) bool {
o := orm.NewOrm()
o.Begin()
defer func(interface{}) {
if err := recover(); err != nil {
logs.Error("pay for fail,rollback....")
o.Rollback()
}
return
}(o)
var tmpForPay models.PayforInfo
if err := o.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)
o.Rollback()
return false
}
if tmpForPay.Status == common.PAYFOR_FAIL || tmpForPay.Status == common.PAYFOR_SUCCESS {
logs.Error(fmt.Sprintf("该代付订单uid=%s状态已经是最终结果", payFor.PayforUid))
o.Rollback()
return false
}
//更新payfor记录的状态
tmpForPay.Status = common.PAYFOR_FAIL
tmpForPay.UpdateTime = utils.GetBasicDateTime()
if _, err := o.Update(&tmpForPay); err != nil {
logs.Error("PayForFail update payfor_info fail: ", err)
o.Rollback()
return false
}
var account models.AccountInfo
if err := o.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)
o.Rollback()
return false
}
account.UpdateTime = utils.GetBasicDateTime()
if account.PayforAmount < (payFor.PayforAmount + payFor.PayforFee) {
logs.Error(fmt.Sprintf("商户uid=%s账户中待代付金额小于代付记录的金额", payFor.MerchantUid))
o.Rollback()
return false
}
//将正在打款中的金额减去
account.PayforAmount = account.PayforAmount - payFor.PayforAmount - payFor.PayforFee
if _, err := o.Update(&account); err != nil {
logs.Error("PayForFail update account fail: ", err)
o.Rollback()
return false
}
if err := o.Commit(); err != nil {
logs.Error("代付失败处理出错fail", err)
} else {
logs.Info("代付处理成功")
}
return true
}
func PayForSuccess(payFor models.PayforInfo) bool {
o := orm.NewOrm()
o.Begin()
defer func(interface{}) {
if err := recover(); err != nil {
logs.Error("pay for success,rollback....")
o.Rollback()
}
return
}(o)
var tmpPayFor models.PayforInfo
if err := o.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)
o.Rollback()
return false
}
if tmpPayFor.Status == common.PAYFOR_FAIL || tmpPayFor.Status == common.PAYFOR_SUCCESS {
logs.Error(fmt.Sprintf("该代付订单uid=%s已经是最终结果不需要处理", payFor.PayforUid))
o.Rollback()
return false
}
tmpPayFor.UpdateTime = utils.GetBasicDateTime()
tmpPayFor.Status = common.PAYFOR_SUCCESS
_, err := o.Update(&tmpPayFor)
if err != nil {
logs.Error("PayForSuccess update payfor fail: ", err)
o.Rollback()
return false
}
var account models.AccountInfo
if err := o.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)
o.Rollback()
return false
}
account.UpdateTime = utils.GetBasicDateTime()
if account.PayforAmount < (payFor.PayforAmount + payFor.PayforFee) {
logs.Error(fmt.Sprintf("商户uid=%s账户中待代付金额小于代付记录的金额", payFor.MerchantUid))
o.Rollback()
return false
}
//代付打款中的金额减去
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 := o.Update(&account); err != nil {
logs.Error("PayForSuccess udpate account fail", err)
return false
}
//添加一条动账记录
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 := o.Insert(&accountHistory); err != nil {
logs.Error("PayForSuccess insert account history fail: ", err)
o.Rollback()
return false
}
if err := o.Commit(); err != nil {
logs.Error("代付成功处理失败fail", err)
} else {
logs.Info("代付处理成功")
}
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 {
o := orm.NewOrm()
//检查是否单独填写了每笔代付的手续费
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.Begin()
defer func(interface{}) {
if err := recover(); err != nil {
o.Rollback()
return
}
}(o)
var tmpPayFor models.PayforInfo
if err := o.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)
o.Rollback()
return false
}
if tmpPayFor.Status != common.PAYFOR_COMFRIM {
logs.Notice(fmt.Sprintf("该代付记录uid=%s已经被审核", payFor.PayforUid))
return false
}
tmpPayFor.UpdateTime = utils.GetBasicDateTime()
tmpPayFor.Status = common.PAYFOR_SOLVING
tmpPayFor.GiveType = common.PAYFOR_ROAD
if _, err := o.Update(&tmpPayFor); err != nil {
logs.Error(fmt.Sprintf("该代付记录uid=%s从审核更新为正在处理出错: %s", payFor.PayforUid, err))
o.Rollback()
return false
}
if err := o.Commit(); err != nil {
logs.Error("挑选代付通道失败fail", err)
} else {
logs.Info("挑选代付通道成功")
}
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) {
o := orm.NewOrm()
o.Begin()
defer func(interface{}) {
if err := recover(); err != nil {
o.Rollback()
}
}(o)
var tmpPayFor models.PayforInfo
if err := o.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)
o.Rollback()
return
}
if tmpPayFor.IsSend == common.YES {
o.Rollback()
return
}
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
}
_, err := o.Update(&tmpPayFor)
if err != nil {
o.Rollback()
} else {
o.Commit()
RequestPayFor(payFor)
}
}
func SendPayFor(payFor models.PayforInfo) bool {
o := orm.NewOrm()
o.Begin()
defer func(interface{}) {
if err := recover(); err != nil {
o.Rollback()
return
}
}(o)
var tmpPayFor models.PayforInfo
if err := o.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)
o.Rollback()
return false
}
var account models.AccountInfo
if err := o.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)
o.Rollback()
return false
}
//支付金额不足,将直接判定为失败,不往下面邹逻辑了
if account.SettleAmount-account.PayforAmount < tmpPayFor.PayforAmount+tmpPayFor.PayforFee {
tmpPayFor.Status = common.PAYFOR_FAIL
tmpPayFor.UpdateTime = utils.GetBasicDateTime()
o.Update(&tmpPayFor)
o.Commit()
return false
}
account.UpdateTime = utils.GetBasicDateTime()
account.PayforAmount = account.PayforAmount + payFor.PayforAmount + payFor.PayforFee
_, err := o.Update(&account)
if err != nil {
logs.Error(fmt.Sprintf("商户uid=%s在发送代付给上游的处理中更新账户表出错, err: %s", payFor.MerchantUid, err))
o.Rollback()
return false
}
tmpPayFor.IsSend = common.YES
tmpPayFor.Status = common.PAYFOR_BANKING //变为银行处理中
tmpPayFor.RequestTime = utils.GetBasicDateTime()
tmpPayFor.UpdateTime = utils.GetBasicDateTime()
_, err = o.Update(&tmpPayFor)
if err != nil {
logs.Error(fmt.Sprintf("商户uid=%s在发送代付给上游的处理中更代付列表出错 err%s", payFor.MerchantUid, err))
o.Rollback()
return false
} else {
o.Commit()
RequestPayFor(payFor)
}
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)
}

View File

@@ -0,0 +1,41 @@
/***************************************************
** @Desc : This file for ...
** @Time : 2019/10/28 9:39
** @Author : yuebin
** @File : supplier_interface
** @Last Modified by : yuebin
** @Last Modified time: 2019/10/28 9:39
** @Software: GoLand
****************************************************/
package controller
import (
"dongfeng/service/models"
)
//定义扫码支付的返回值
type ScanData struct {
Supplier string //上游的通道供应商
PayType string //支付类型
OrderNo string //下游商户请求订单号
BankNo string //本系统的请求订单号
OrderPrice string //订单金额
FactPrice string //实际的展示在客户面前的金额
Status string //状态码 '00' 成功
PayUrl string //支付二维码链接地址
Msg string //附加的信息
}
type PayInterface interface {
Scan(models.OrderInfo, models.RoadInfo, models.MerchantInfo) ScanData
H5(models.OrderInfo, models.RoadInfo, models.MerchantInfo) ScanData
Fast(models.OrderInfo, models.RoadInfo, models.MerchantInfo) bool
Syt(models.OrderInfo, models.RoadInfo, models.MerchantInfo) ScanData
Web(models.OrderInfo, models.RoadInfo, models.MerchantInfo) bool
PayNotify()
PayQuery(models.OrderInfo) bool
PayFor(models.PayforInfo) string
PayForNotify() string
PayForQuery(models.PayforInfo) (string, string)
BalanceQuery(models.RoadInfo) float64
}

View File

@@ -0,0 +1,70 @@
/***************************************************
** @Desc : This file for ...
** @Time : 2019/10/28 16:38
** @Author : yuebin
** @File : weixin
** @Last Modified by : yuebin
** @Last Modified time: 2019/10/28 16:38
** @Software: GoLand
****************************************************/
package controller
import (
"dongfeng/service/models"
)
type WeiXinImpl struct {
}
func (c *WeiXinImpl) Scan(orderInfo models.OrderInfo, roadInfo models.RoadInfo, merchantInfo models.MerchantInfo) ScanData {
var scanData ScanData
scanData.Status = "01"
return scanData
}
func (c *WeiXinImpl) H5(orderInfo models.OrderInfo, roadInfo models.RoadInfo, merchantInfo models.MerchantInfo) ScanData {
var scanData ScanData
scanData.Status = "01"
return scanData
}
func (c *WeiXinImpl) Syt(orderInfo models.OrderInfo, roadInfo models.RoadInfo, merchantInfo models.MerchantInfo) ScanData {
var scanData ScanData
scanData.Status = "01"
return scanData
}
func (c *WeiXinImpl) Fast(orderInfo models.OrderInfo, roadInfo models.RoadInfo, merchantInfo models.MerchantInfo) bool {
var scanData ScanData
scanData.Status = "01"
return true
}
func (c *WeiXinImpl) Web(orderInfo models.OrderInfo, roadInfo models.RoadInfo, merchantInfo models.MerchantInfo) bool {
var scanData ScanData
scanData.Status = "01"
return true
}
func (c *WeiXinImpl) PayNotify() {
}
func (c *WeiXinImpl) PayQuery(orderInfo models.OrderInfo) bool {
return true
}
func (c *WeiXinImpl) PayFor(payFor models.PayforInfo) string {
return ""
}
func (c *WeiXinImpl) PayForNotify() string {
return ""
}
func (c *WeiXinImpl) PayForQuery(payFor models.PayforInfo) (string, string) {
return "", ""
}
func (c *WeiXinImpl) BalanceQuery(roadInfo models.RoadInfo) float64 {
return 0.00
}