dongfeng-pay/gateway/controllers/gateway/base_gateway.go

368 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/10/28 18:09
** @Author : yuebin
** @File : base_gateway
** @Last Modified by : yuebin
** @Last Modified time: 2019/10/28 18:09
** @Software: GoLand
****************************************************/
package gateway
import (
"fmt"
"gateway/common"
"gateway/models"
controller "gateway/supplier"
"gateway/utils"
"github.com/beego/beego/v2/core/logs"
beego "github.com/beego/beego/v2/server/web"
"github.com/rs/xid"
"strconv"
"strings"
"time"
)
type BaseGateway struct {
beego.Controller
Params map[string]string //请求的基本参数
ClientIp string //商户ip
MerchantInfo models.MerchantInfo //商户信息
Msg string //信息
Code int //状态码 200正常
RoadInfo models.RoadInfo
RoadPoolInfo models.RoadPoolInfo
OrderAmount float64
PayWayCode string
PlatformRate float64
AgentRate float64
}
//获取商户请求过来的基本参数参数
func (c *BaseGateway) PayPrepare() {
c.Params = make(map[string]string)
//获取客户端的ip
c.ClientIp = c.Ctx.Input.IP()
c.Params["orderNo"] = strings.TrimSpace(c.GetString("orderNo"))
c.Params["productName"] = strings.TrimSpace(c.GetString("productName"))
c.Params["orderPeriod"] = strings.TrimSpace(c.GetString("orderPeriod"))
c.Params["orderPrice"] = strings.TrimSpace(c.GetString("orderPrice"))
c.Params["payWayCode"] = strings.TrimSpace(c.GetString("payWayCode"))
c.Params["osType"] = strings.TrimSpace(c.GetString("osType"))
c.Params["notifyUrl"] = strings.TrimSpace(c.GetString("notifyUrl"))
//c.Params["returnUrl"] = strings.TrimSpace(c.GetString("returnUrl"))
c.Params["payKey"] = strings.TrimSpace(c.GetString("payKey"))
c.Params["sign"] = strings.TrimSpace(c.GetString("sign"))
c.GetMerchantInfo()
c.JudgeParams()
if c.Code != -1 {
c.Code = 200
}
}
//判断参数的
func (c *BaseGateway) JudgeParams() {
//c.ReturnUrlIsValid()
c.OrderIsValid()
c.NotifyUrlIsValid()
c.OsTypeIsValid()
c.PayWayCodeIsValid()
c.ProductIsValid()
c.OrderPeriodIsValid()
c.IpIsWhite()
c.OrderPriceIsValid()
}
func (c *BaseGateway) ReturnUrlIsValid() {
if c.Params["returnUrl"] == "" || len(c.Params["returnUrl"]) == 0 {
c.Code = -1
c.Msg = "支付成功后跳转地址不能为空"
}
}
func (c *BaseGateway) NotifyUrlIsValid() {
if c.Params["notifyUrl"] == "" || len(c.Params["notifyUrl"]) == 0 {
c.Code = -1
c.Msg = "支付成功订单回调地址不能空位"
}
}
func (c *BaseGateway) OsTypeIsValid() {
if c.Params["osType"] == "" || len(c.Params["osType"]) == 0 {
c.Code = -1
c.Msg = "支付设备系统类型不能为空,默认填写\"1\"即可"
}
}
func (c *BaseGateway) PayWayCodeIsValid() {
if c.Params["payWayCode"] == "" || len(c.Params["payWayCode"]) == 0 {
c.Code = -1
c.Msg = "支付类型字段不能为空"
return
}
if !strings.Contains(c.Params["payWayCode"], "SCAN") {
c.Code = -1
c.Msg = "扫码支付不支持这种支付类型"
} else {
scanPayWayCodes := common.GetScanPayWayCodes()
for _, v := range scanPayWayCodes {
if c.Params["payWayCode"] == v {
c.PayWayCode = strings.Replace(c.Params["payWayCode"], "-", "_", -1)
return
}
}
c.Code = -1
c.Msg = "不存在这种支付类型,请仔细阅读对接文档"
}
}
func (c *BaseGateway) ProductIsValid() {
if c.Params["productName"] == "" || len(c.Params["productName"]) == 0 {
c.Code = -1
c.Msg = "商品描述信息字段不能为空"
}
}
func (c *BaseGateway) OrderPeriodIsValid() {
if c.Params["orderPeriod"] == "" || len(c.Params["orderPeriod"]) == 0 {
c.Code = -1
c.Msg = "订单过期时间不能为空,默认填写\"1\"即可"
}
}
//获取商户信息
func (c *BaseGateway) GetMerchantInfo() {
merchantInfo := models.GetMerchantByPaykey(c.Params["payKey"])
if merchantInfo.MerchantUid == "" || len(merchantInfo.MerchantUid) == 0 {
c.Code = -1
c.Msg = "商户不存在或者paykey有误请联系管理员"
} else if merchantInfo.Status != common.ACTIVE {
c.Code = -1
c.Msg = "商户状态已经被冻结或者被删除,请联系管理员!"
} else {
c.MerchantInfo = merchantInfo
}
}
//判断订单金额
func (c *BaseGateway) OrderPriceIsValid() {
if c.Params["orderPrice"] == "" || len(c.Params["orderPrice"]) == 0 {
c.Code = -1
c.Msg = "订单金额不能为空"
return
}
a, err := strconv.ParseFloat(c.Params["orderPrice"], 64)
if err != nil {
logs.Error("order price is invalid ", c.Params["orderPrice"])
c.Code = -1
c.Msg = "订单金额非法"
}
c.OrderAmount = a
}
//判断金额订单号是否为空或者有重复
func (c *BaseGateway) OrderIsValid() {
if c.Params["orderNo"] == "" || len(c.Params["orderNo"]) == 0 {
c.Code = -1
c.Msg = "商户订单号不能为空"
return
}
if models.OrderNoIsEixst(c.Params["orderNo"]) {
c.Code = -1
c.Msg = "商户订单号重复"
}
}
//判断ip是否在白名单中
func (c *BaseGateway) IpIsWhite() bool {
//TODO
return true
}
//选择通道
func (c *BaseGateway) ChooseRoad() {
payWayCode := c.Params["payWayCode"]
merchantUid := c.MerchantInfo.MerchantUid
//通道配置信息
deployInfo := models.GetMerchantDeployByUidAndPayType(merchantUid, payWayCode)
if deployInfo.MerchantUid == "" {
c.Code = -1
c.Msg = "该商户没有配置"
return
}
singleRoad := models.GetRoadInfoByRoadUid(deployInfo.SingleRoadUid)
c.RoadPoolInfo = models.GetRoadPoolByRoadPoolCode(deployInfo.RollRoadCode)
if c.RoadIsValid(singleRoad) {
c.RoadInfo = singleRoad
c.PlatformRate = deployInfo.SingleRoadPlatformRate
c.AgentRate = deployInfo.SingleRoadAgentRate
return
}
//如果单通道没有有效的,那么寻找通道池里面的通道
if c.RoadPoolInfo.RoadPoolCode == "" {
c.Code = -1
c.Msg = "该商户没有配置通道"
return
}
roadUids := strings.Split(c.RoadPoolInfo.RoadUidPool, "||")
roadInfos := models.GetRoadInfosByRoadUids(roadUids)
for _, roadInfo := range roadInfos {
if c.RoadIsValid(roadInfo) {
c.RoadInfo = roadInfo
c.PlatformRate = deployInfo.RollRoadPlatformRate
c.AgentRate = deployInfo.RollRoadAgentRate
return
}
}
if c.RoadInfo.RoadUid == "" {
c.Code = -1
c.Msg = "该商户没有配置通道或者通道不可用"
}
}
//判断通道是否是合法的
func (c *BaseGateway) RoadIsValid(roadInfo models.RoadInfo) bool {
if roadInfo.RoadUid == "" || len(roadInfo.RoadUid) == 0 {
return false
}
FORMAT := fmt.Sprintf("该通道:%s;", roadInfo.RoadName)
if roadInfo.Status != "active" {
logs.Notice(FORMAT + "不是激活状态")
return false
}
hour := time.Now().Hour()
s := roadInfo.StarHour
e := roadInfo.EndHour
if hour < s || hour > e {
logs.Notice(FORMAT)
return false
}
minAmount := roadInfo.SingleMinLimit
maxAmount := roadInfo.SingleMaxLimit
if minAmount > c.OrderAmount || maxAmount < c.OrderAmount {
logs.Error(FORMAT + "订单金额超限制")
return false
}
todayLimit := roadInfo.TodayLimit
totalLimit := roadInfo.TotalLimit
todayIncome := roadInfo.TodayIncome
totalIncome := roadInfo.TotalIncome
if (todayIncome + c.OrderAmount) > todayLimit {
logs.Error(FORMAT + "达到了每天金额上限")
return false
}
if (totalIncome + c.OrderAmount) > totalLimit {
logs.Error(FORMAT + "达到了总量限制")
return false
}
//如果通道被选中,那么总请求数+1
roadInfo.RequestAll = roadInfo.RequestAll + 1
roadInfo.UpdateTime = utils.GetBasicDateTime()
models.UpdateRoadInfo(roadInfo)
return true
}
//获取基本订单记录
func (c *BaseGateway) GetOrderInfo() models.OrderInfo {
//6666是自己系统订单号
bankOrderNo := "6666" + xid.New().String()
//获取支付类型的名称,例如支付宝扫码等
payTypeName := common.GetNameByPayWayCode(c.Params["payWayCode"])
orderInfo := models.OrderInfo{
MerchantUid: c.MerchantInfo.MerchantUid, MerchantName: c.MerchantInfo.MerchantName, MerchantOrderId: c.Params["orderNo"],
BankOrderId: bankOrderNo, OrderAmount: c.OrderAmount, FactAmount: c.OrderAmount, ShowAmount: c.OrderAmount,
RollPoolCode: c.RoadPoolInfo.RoadPoolCode, RollPoolName: c.RoadPoolInfo.RoadPoolName, RoadUid: c.RoadInfo.RoadUid,
RoadName: c.RoadInfo.RoadName, PayProductName: c.RoadInfo.ProductName, ShopName: c.Params["productName"], Freeze: common.NO,
Refund: common.NO, Unfreeze: common.NO, PayProductCode: c.RoadInfo.ProductUid, PayTypeCode: c.PayWayCode, PayTypeName: payTypeName,
OsType: c.Params["osType"], Status: common.WAIT, NotifyUrl: c.Params["notifyUrl"], ReturnUrl: c.Params["returnUrl"],
OrderPeriod: c.Params["orderPeriod"], UpdateTime: utils.GetBasicDateTime(), CreateTime: utils.GetBasicDateTime(),
}
if c.MerchantInfo.BelongAgentUid != "" || c.AgentRate > common.ZERO {
orderInfo.AgentUid = c.MerchantInfo.BelongAgentUid
orderInfo.AgentName = c.MerchantInfo.BelongAgentName
}
return orderInfo
}
//计算收益,平台利润,代理利润
func (c *BaseGateway) GetOrderProfit(orderInfo models.OrderInfo) models.OrderProfitInfo {
//因为所有的手续费率都是百分率所以需要除以100
payTypeName := common.GetNameByPayWayCode(c.PayWayCode)
supplierProfit := c.OrderAmount / 100 * c.RoadInfo.BasicFee
platformProfit := c.OrderAmount / 100 * c.PlatformRate
agentProfit := c.OrderAmount / 100 * c.AgentRate
//如果用户没有设置代理那么代理利润为0.000
if c.MerchantInfo.BelongAgentUid == "" || len(c.MerchantInfo.BelongAgentUid) == 0 {
agentProfit = common.ZERO
}
allProfit := supplierProfit + platformProfit + agentProfit
if allProfit >= c.OrderAmount {
logs.Error("手续费已经超过订单金额bankOrderId = %s", orderInfo.BankOrderId)
c.Msg = "手续费已经超过了订单金额"
c.Code = -1
}
orderProfit := models.OrderProfitInfo{
PayProductCode: c.RoadInfo.ProductUid, PayProductName: c.RoadInfo.ProductName, PayTypeCode: c.PayWayCode, PayTypeName: payTypeName,
Status: common.WAIT, MerchantOrderId: c.Params["orderNo"], BankOrderId: orderInfo.BankOrderId, OrderAmount: c.OrderAmount,
FactAmount: c.OrderAmount, ShowAmount: c.OrderAmount, AllProfit: allProfit, UserInAmount: c.OrderAmount - allProfit,
SupplierProfit: supplierProfit, PlatformProfit: platformProfit, AgentProfit: agentProfit, UpdateTime: utils.GetBasicDateTime(),
CreateTime: utils.GetBasicDateTime(), MerchantUid: c.MerchantInfo.MerchantUid, MerchantName: orderInfo.MerchantName,
SupplierRate: c.RoadInfo.BasicFee, PlatformRate: c.PlatformRate, AgentRate: c.AgentRate, AgentName: orderInfo.AgentName, AgentUid: orderInfo.AgentUid,
}
//如果该条订单设置了代理利率,并且设置了代理
if c.MerchantInfo.BelongAgentUid != "" || c.AgentRate > common.ZERO {
orderProfit.AgentUid = c.MerchantInfo.BelongAgentUid
orderProfit.AgentName = c.MerchantInfo.BelongAgentName
}
return orderProfit
}
/*
* 生成订单一系列的记录
*/
func (c *BaseGateway) GenerateRecord() (models.OrderInfo, models.OrderProfitInfo) {
//生成订单记录,订单利润利润
orderInfo := c.GetOrderInfo()
orderProfit := c.GetOrderProfit(orderInfo)
if c.Code == -1 {
return orderInfo, orderProfit
}
if !controller.InsertOrderAndOrderProfit(orderInfo, orderProfit) {
c.Code = -1
return orderInfo, orderProfit
}
logs.Info("插入支付订单记录和支付利润记录成功")
return orderInfo, orderProfit
}
func (c *BaseGateway) GenerateSuccessData(scanData controller.ScanData) *ScanSuccessData {
params := make(map[string]string)
params["orderNo"] = scanData.OrderNo
params["orderPrice"] = scanData.OrderPrice
params["payKey"] = c.MerchantInfo.MerchantKey
params["payURL"] = scanData.PayUrl
params["statusCode"] = "00"
keys := utils.SortMap(params)
sign := utils.GetMD5Sign(params, keys, c.MerchantInfo.MerchantSecret)
scanSuccessData := new(ScanSuccessData)
scanSuccessData.StatusCode = "00"
scanSuccessData.PayKey = c.MerchantInfo.MerchantKey
scanSuccessData.OrderNo = scanData.OrderNo
scanSuccessData.OrderPrice = scanData.OrderPrice
scanSuccessData.PayUrl = scanData.PayUrl
scanSuccessData.PayKey = c.MerchantInfo.MerchantKey
scanSuccessData.Msg = "请求成功"
scanSuccessData.Sign = sign
return scanSuccessData
}