修改网关代码的结构,调整了逻辑,删除了许多无用的代码

This commit is contained in:
kongyuebin 2021-09-16 14:57:23 +08:00
parent 706a95317d
commit 2a98cbd9ac
58 changed files with 6137 additions and 744 deletions

View File

@ -1,6 +1,6 @@
appname = jhgateway appname = jhgateway
httpport = 12309 httpport = 12309
runmode = dev runmode = pro
sessionon = true sessionon = true

View File

@ -16,3 +16,97 @@ const (
DB_PASSWORD = "Kyb^15273031604" DB_PASSWORD = "Kyb^15273031604"
DB_BASE = "juhe_pay" DB_BASE = "juhe_pay"
) )
const (
ACTIVE = "active"
UNACTIVE = "unactive"
DELETE = "delete"
REFUND = "refund"
ORDERROLL = "order_roll"
WAIT = "wait"
SUCCESS = "success"
FAIL = "fail"
YES = "yes"
NO = "no"
ZERO = 0.0 //0元手续费
VERIFY_CODE_LEN = 4 //验证码的长度
PAYFOR_FEE = 2.00 //代付手续费
PAYFOR_INTERVAL = 5 //每过5分钟执行一次代付
PLUS_AMOUNT = "plus_amount" //加款操作
SUB_AMOUNT = "sub_amount" //减款操作
FREEZE_AMOUNT = "freeze_amount" //冻结操作
UNFREEZE_AMOUNT = "unfreeze_amount" //解冻操作
PAYFOR_COMFRIM = "payfor_confirm" //下发带审核
PAYFOR_SOLVING = "payfor_solving" //发下处理中
PAYFOR_HANDING = "payfor_handing" //手动打款中
PAYFOR_BANKING = "payfor_banking" //银行处理中
PAYFOR_FAIL = "payfor_fail" //代付失败
PAYFOR_SUCCESS = "payfor_success" //代付成功
PAYFOR_ROAD = "payfor_road" //通道打款
PAYFOR_HAND = "payfor_hand" //手动打款
PAYFOR_REFUSE = "payfor_refuse" // 拒绝打款
SELF_API = "self_api" //自助api系统下发
SELF_MERCHANT = "self_merchant" //管理手动处理商户下发
SELF_HELP = "self_help" //管理自己提现
PUBLIC = "public" //对公卡
PRIVATE = "private" //对私卡
)
const (
ICBC = "ICBC"
ABC = "ABC"
BOC = "BOC"
CCB = "CCB"
BOCOM = "BOCOM"
CNCB = "CNCB"
CEB = "CEB"
HXB = "HXB"
CMBC = "CMBC"
GDB = "GDB"
CMB = "CMB"
CIB = "CIB"
SPDB = "SPDB"
PSBC = "PSBC"
PAB = "PAB"
NJCB = "NJCB"
NBCB = "NBCB"
WZCB = "WZCB"
CSCB = "CSCB"
CZCB = "CZCB"
CCQTGB = "CCQTGB"
SHRCB = "SHRCB"
BJRCB = "BJRCB"
SDB = "SDB"
)
var bankInfo = map[string]string{
ICBC: "中国工商银行",
ABC: "中国农业银行",
BOC: "中国银行",
CCB: "中国建设银行",
BOCOM: "交通银行",
CNCB: "中信银行",
CEB: "中国光大银行",
HXB: "华夏银行",
CMBC: "中国民生银行",
GDB: "广发银行",
CMB: "招商银行",
CIB: "兴业银行",
SPDB: "浦发银行",
PSBC: "中国邮政储蓄银行",
PAB: "平安银行",
NJCB: "南京银行",
NBCB: "宁波银行",
WZCB: "温州市商业银行",
CSCB: "长沙银行",
CZCB: "浙江稠州商业银行",
CCQTGB: "重庆三峡银行",
SHRCB: "上海农村商业银行",
BJRCB: "北京农商行",
SDB: "深圳发展银行",
}

25
gateway/conf/mq_config.go Normal file
View File

@ -0,0 +1,25 @@
/***************************************************
** @Desc : This file for ...
** @Time : 2019/11/6 11:37
** @Author : yuebin
** @File : mq_config
** @Last Modified by : yuebin
** @Last Modified time: 2019/11/6 11:37
** @Software: GoLand
****************************************************/
package conf
import "net"
const (
mqHost = "127.0.0.1"
mqPort = "61613"
MqOrderQuery = "order_query"
MQ_PAYFOR_QUERY = "payfor_query"
MqOrderNotify = "order_notify"
)
func GetMQAddress() string {
return net.JoinHostPort(mqHost, mqPort)
}

View File

@ -0,0 +1,99 @@
/***************************************************
** @Desc : This file for ...
** @Time : 2019/10/29 15:01
** @Author : yuebin
** @File : pay_way_code
** @Last Modified by : yuebin
** @Last Modified time: 2019/10/29 15:01
** @Software: GoLand
****************************************************/
package conf
var ScanPayWayCodes = []string{
"WEIXIN_SCAN",
"UNION_SCAN",
"ALI_SCAN",
"BAIDU_SCAN",
"JD_SCAN",
"QQ_SCAN",
}
var H5PayWayCodes = []string{
"WEIXIN_H5",
"ALI_H5",
"QQ_H5",
"UNION_H5",
"BAIDU_H5",
"JD_H5",
}
var SytPayWayCodes = []string{
"WEIXIN_SYT",
"ALI_SYT",
"QQ_SYT",
"UNION_SYT",
"BAIDU_SYT",
"JD_SYT",
}
var FastPayWayCodes = []string{
"UNION-FAST",
}
var WebPayWayCode = []string{
"UNION-WAP",
}
func GetScanPayWayCodes() []string {
return ScanPayWayCodes
}
func GetNameByPayWayCode(code string) string {
switch code {
case "WEIXIN_SCAN":
return "微信扫码"
case "UNION_SCAN":
return "银联扫码"
case "ALI_SCAN":
return "支付宝扫码"
case "BAIDU_SCAN":
return "百度扫码"
case "JD_SCAN":
return "京东扫码"
case "QQ_SCAN":
return "QQ扫码"
case "WEIXIN_H5":
return "微信H5"
case "UNION_H5":
return "银联H5"
case "ALI_H5":
return "支付宝H5"
case "BAIDU_H5":
return "百度H5"
case "JD_H5":
return "京东H5"
case "QQ_H5":
return "QQ-H5"
case "WEIXIN_SYT":
return "微信收银台"
case "UNION_SYT":
return "银联收银台"
case "ALI_SYT":
return "支付宝收银台"
case "BAIDU_SYT":
return "百度收银台"
case "JD_SYT":
return "京东收银台"
case "QQ_SYT":
return "QQ-收银台"
case "UNION_FAST":
return "银联快捷"
case "UNION_WAP":
return "银联web"
default:
return "未知"
}
}

View File

@ -0,0 +1,48 @@
/***************************************************
** @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 (
"gateway/response"
"gateway/service"
"github.com/beego/beego/v2/server/web"
"strings"
)
type BaseGateway struct {
web.Controller
}
//获取商户请求过来的基本参数参数
func (c *BaseGateway) PayPrepare() *response.PayBaseResp {
params := make(map[string]string)
//获取客户端的ip
clientIp := c.Ctx.Input.IP()
params["orderNo"] = strings.TrimSpace(c.GetString("orderNo"))
params["productName"] = strings.TrimSpace(c.GetString("productName"))
params["orderPeriod"] = strings.TrimSpace(c.GetString("orderPeriod"))
params["orderPrice"] = strings.TrimSpace(c.GetString("orderPrice"))
params["payWayCode"] = strings.TrimSpace(c.GetString("payWayCode"))
params["osType"] = strings.TrimSpace(c.GetString("osType"))
params["notifyUrl"] = strings.TrimSpace(c.GetString("notifyUrl"))
//c.Params["returnUrl"] = strings.TrimSpace(c.GetString("returnUrl"))
params["payKey"] = strings.TrimSpace(c.GetString("payKey"))
params["sign"] = strings.TrimSpace(c.GetString("sign"))
p := service.GetMerchantInfo(params)
p.ClientIp = clientIp
p = service.JudgeParams(p)
if p.Code != -1 {
p.Code = 200
}
return p
}

View File

@ -1,367 +0,0 @@
/***************************************************
** @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
}

View File

@ -10,14 +10,14 @@
package gateway package gateway
import ( import (
beego "github.com/beego/beego/v2/server/web" "github.com/beego/beego/v2/server/web"
) )
type ErrorGatewayController struct { type ErrorGatewayController struct {
beego.Controller web.Controller
} }
func (c *ErrorGatewayController) ErrorParams() { func (c *ErrorGatewayController) ErrorParams() {
beego.ReadFromRequest(&c.Controller) web.ReadFromRequest(&c.Controller)
c.TplName = "err/params.html" c.TplName = "err/params.html"
} }

View File

@ -0,0 +1,100 @@
/***************************************************
** @Desc : 代付下发金额处理逻辑
** @Time : 2019/12/5 14:05
** @Author : yuebin
** @File : payfor_gateway
** @Last Modified by : yuebin
** @Last Modified time: 2019/12/5 14:05
** @Software: GoLand
****************************************************/
package gateway
import (
"fmt"
"gateway/conf"
"gateway/pay_for"
"gateway/response"
"github.com/beego/beego/v2/server/web"
"strings"
)
type PayForGateway struct {
web.Controller
}
/*
* 接受下游商户的代付请求
*/
func (c *PayForGateway) PayFor() {
params := make(map[string]string)
params["merchantKey"] = strings.TrimSpace(c.GetString("merchantKey"))
params["realname"] = strings.TrimSpace(c.GetString("realname"))
params["cardNo"] = strings.TrimSpace(c.GetString("cardNo"))
//params["bankCode"] = strings.TrimSpace(c.GetString("bankCode"))
params["accType"] = strings.TrimSpace(c.GetString("accType"))
//params["province"] = strings.TrimSpace(c.GetString("province"))
//params["city"] = strings.TrimSpace(c.GetString("city"))
//params["bankAccountAddress"] = strings.TrimSpace(c.GetString("bankAccountAddress"))
params["amount"] = strings.TrimSpace(c.GetString("amount"))
//params["mobileNo"] = strings.TrimSpace(c.GetString("mobileNo"))
params["merchantOrderId"] = strings.TrimSpace(c.GetString("merchantOrderId"))
params["sign"] = strings.TrimSpace(c.GetString("sign"))
payForResponse := new(response.PayForResponse)
res, msg := checkParams(params)
if !res {
payForResponse.ResultCode = "01"
payForResponse.ResultMsg = msg
} else {
payForResponse = pay_for.AutoPayFor(params, conf.SELF_API)
}
c.Data["json"] = payForResponse
_ = c.ServeJSON()
}
/*
* 代付结果查询
*/
func (c *PayForGateway) PayForQuery() {
params := make(map[string]string)
params["merchantKey"] = strings.TrimSpace(c.GetString("merchantKey"))
params["timestamp"] = strings.TrimSpace(c.GetString("timestamp"))
params["merchantOrderId"] = strings.TrimSpace(c.GetString("merchantOrderId"))
params["sign"] = strings.TrimSpace(c.GetString("sign"))
c.Data["json"] = pay_for.PayForResultQuery(params)
_ = c.ServeJSON()
}
/*
* 商户查找余额
*/
func (c *PayForGateway) Balance() {
params := make(map[string]string)
params["merchantKey"] = strings.TrimSpace(c.GetString("merchantKey"))
params["timestamp"] = strings.TrimSpace(c.GetString("timestamp"))
params["sign"] = strings.TrimSpace(c.GetString("sign"))
balanceResponse := new(response.BalanceResponse)
res, msg := checkParams(params)
if !res {
balanceResponse.ResultCode = "-1"
balanceResponse.ResultMsg = msg
c.Data["json"] = balanceResponse
} else {
c.Data["json"] = pay_for.BalanceQuery(params)
}
_ = c.ServeJSON()
}
func checkParams(params map[string]string) (bool, string) {
for k, v := range params {
if v == "" || len(v) == 0 {
return false, fmt.Sprintf("字段: %s 为必填!", k)
}
}
return true, ""
}

View File

@ -1,256 +0,0 @@
/***************************************************
** @Desc : This file for ...
** @Time : 2019/12/5 14:05
** @Author : yuebin
** @File : payfor_gateway
** @Last Modified by : yuebin
** @Last Modified time: 2019/12/5 14:05
** @Software: GoLand
****************************************************/
package gateway
import (
"encoding/json"
"fmt"
"gateway/common"
"gateway/models"
"gateway/utils"
"github.com/beego/beego/v2/core/logs"
beego "github.com/beego/beego/v2/server/web"
"github.com/rs/xid"
"strconv"
"strings"
)
type PayForGateway struct {
beego.Controller
}
type PayForResponse struct {
ResultCode string `json:"resultCode,omitempty"`
ResultMsg string `json:"resultMsg,omitempty"`
MerchantOrderId string `json:"merchantOrderId,omitempty"`
SettAmount string `json:"settAmount,omitempty"`
SettFee string `json:"settFee,omitempty"`
Sign string `json:"sign,omitempty"`
}
type PayForQueryResponse struct {
ResultMsg string `json:"resultMsg,omitempty"`
MerchantOrderId string `json:"merchantOrderId,omitempty"`
SettAmount string `json:"settAmount,omitempty"`
SettFee string `json:"settFee,omitempty"`
SettStatus string `json:"settStatus,omitempty"`
Sign string `json:"sign,omitempty"`
}
type BalanceResponse struct {
resultCode string `json:"resultCode,omitempty"`
balance string `json:"balance,omitempty"`
availableAmount string `json:"availableAmount,omitempty"`
freezeAmount string `json:"freezeAmount,omitempty"`
waitAmount string `json:"waitAmount,omitempty"`
loanAmount string `json:"loanAmount,omitempty"`
payforAmount string `json:"payforAmount,omitempty"`
resultMsg string `json:"resultMsg,omitempty"`
sign string `json:"sign,omitempty"`
}
/*
* 接受下游商户的代付请求
*/
func (c *PayForGateway) PayFor() {
params := make(map[string]string)
params["merchantKey"] = strings.TrimSpace(c.GetString("merchantKey"))
params["realname"] = strings.TrimSpace(c.GetString("realname"))
params["cardNo"] = strings.TrimSpace(c.GetString("cardNo"))
params["bankCode"] = strings.TrimSpace(c.GetString("bankCode"))
params["accType"] = strings.TrimSpace(c.GetString("accType"))
params["province"] = strings.TrimSpace(c.GetString("province"))
params["city"] = strings.TrimSpace(c.GetString("city"))
params["bankAccountAddress"] = strings.TrimSpace(c.GetString("bankAccountAddress"))
params["amount"] = strings.TrimSpace(c.GetString("amount"))
params["moblieNo"] = strings.TrimSpace(c.GetString("moblieNo"))
params["merchantOrderId"] = strings.TrimSpace(c.GetString("merchantOrderId"))
params["sign"] = strings.TrimSpace(c.GetString("sign"))
payForResponse := new(PayForResponse)
res, msg := c.checkParams(params)
if !res {
payForResponse.ResultCode = "01"
payForResponse.ResultMsg = msg
c.Data["json"] = payForResponse
c.ServeJSON()
return
}
merchantInfo := models.GetMerchantByPaykey(params["merchantKey"])
if !utils.Md5Verify(params, merchantInfo.MerchantSecret) {
logs.Error(fmt.Sprintf("下游商户代付请求,签名失败,商户信息: %+v", merchantInfo))
payForResponse.ResultCode = "01"
payForResponse.ResultMsg = "下游商户代付请求,签名失败。"
} else {
res, msg = c.checkSettAmount(params["amount"])
if !res {
payForResponse.ResultCode = "01"
payForResponse.ResultMsg = msg
c.Data["json"] = payForResponse
c.ServeJSON()
return
}
exist := models.IsExistPayForByMerchantOrderId(params["merchantOrderId"])
if exist {
logs.Error(fmt.Sprintf("代付订单号重复merchantOrderId = %s", params["merchantOrderId"]))
payForResponse.ResultMsg = "商户订单号重复"
payForResponse.ResultCode = "01"
c.Data["json"] = payForResponse
c.ServeJSON()
return
}
settAmount, _ := strconv.ParseFloat(params["amount"], 64)
payFor := models.PayforInfo{PayforUid: "pppp" + xid.New().String(), MerchantUid: merchantInfo.MerchantUid, MerchantName: merchantInfo.MerchantName,
MerchantOrderId: params["merchantOrderId"], BankOrderId: "4444" + xid.New().String(), PayforAmount: settAmount, Status: common.PAYFOR_COMFRIM,
BankCode: params["bankCode"], BankName: params["bankAccountAddress"], BankAccountName: params["realname"], BankAccountNo: params["cardNo"],
BankAccountType: params["accType"], City: params["city"], Ares: params["province"] + params["city"], PhoneNo: params["mobileNo"], Type: common.SELF_API,
UpdateTime: utils.GetBasicDateTime(), CreateTime: utils.GetBasicDateTime(),
}
if !models.InsertPayfor(payFor) {
payForResponse.ResultCode = "01"
payForResponse.ResultMsg = "代付记录插入失败"
} else {
payForResponse.ResultMsg = "代付订单已生成"
payForResponse.ResultCode = "00"
payForResponse.SettAmount = params["amount"]
payForResponse.MerchantOrderId = params["MerchantOrderId"]
tmp := make(map[string]string)
tmp["resultCode"] = payForResponse.ResultCode
tmp["resultMsg"] = payForResponse.ResultMsg
tmp["merchantOrderId"] = payForResponse.MerchantOrderId
tmp["settAmount"] = payForResponse.SettAmount
keys := utils.SortMap(tmp)
sign := utils.GetMD5Sign(params, keys, merchantInfo.MerchantSecret)
tmp["sign"] = sign
c.Data["json"] = payForResponse
c.ServeJSON()
}
}
}
func (c *PayForGateway) checkSettAmount(settAmount string) (bool, string) {
_, err := strconv.ParseFloat(settAmount, 64)
if err != nil {
logs.Error(fmt.Sprintf("代付金额有误settAmount = %s", settAmount))
return false, "代付金额有误"
}
return true, ""
}
func (c *PayForGateway) checkParams(params map[string]string) (bool, string) {
for k, v := range params {
if v == "" || len(v) == 0 {
return false, fmt.Sprintf("字段: %s 为必填!", k)
}
}
return true, ""
}
/*
* 代付结果查询
*/
func (c *PayForGateway) PayForQuery() {
params := make(map[string]string)
params["merchantKey"] = strings.TrimSpace(c.GetString("merchantKey"))
params["timestamp"] = strings.TrimSpace(c.GetString("timestamp"))
params["merchantOrderId"] = strings.TrimSpace(c.GetString("merchantOrderId"))
params["sign"] = strings.TrimSpace(c.GetString("sign"))
query := make(map[string]string)
query["merchantOrderId"] = params["merchantOrderId"]
merchantInfo := models.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 := models.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 common.PAYFOR_BANKING:
query["resultMsg"] = "打款中"
query["settStatus"] = "02"
case common.PAYFOR_SOLVING:
query["resultMsg"] = "打款中"
query["settStatus"] = "02"
case common.PAYFOR_COMFRIM:
query["resultMsg"] = "打款中"
query["settStatus"] = "02"
case common.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 common.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)
}
c.Data["json"] = string(mJson)
c.ServeJSON()
}
/*
* 商户查找余额
*/
func (c *PayForGateway) Balance() {
params := make(map[string]string)
params["merchantKey"] = strings.TrimSpace(c.GetString("merchantKey"))
params["timestamp"] = strings.TrimSpace(c.GetString("timestamp"))
params["sign"] = strings.TrimSpace(c.GetString("sign"))
balanceResponse := new(BalanceResponse)
res, msg := c.checkParams(params)
if !res {
balanceResponse.resultCode = "-1"
balanceResponse.resultMsg = msg
c.Data["json"] = balanceResponse
} else {
merchantInfo := models.GetMerchantByPaykey(params["merchantKey"])
if !utils.Md5Verify(params, merchantInfo.MerchantSecret) {
balanceResponse.resultCode = "-1"
balanceResponse.resultMsg = "签名错误"
c.Data["json"] = balanceResponse
} else {
accountInfo := models.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)
c.Data["json"] = string(mJson)
}
}
c.ServeJSON()
}

View File

@ -0,0 +1,73 @@
/***************************************************
** @Desc : 下游请求扫码支付的处理逻辑
** @Time : 2019/10/24 11:15
** @Author : yuebin
** @File : gateway
** @Last Modified by : yuebin
** @Last Modified time: 2019/10/24 11:15
** @Software: GoLand
****************************************************/
package gateway
import (
"gateway/response"
"gateway/service"
"gateway/supplier/third_party"
"gateway/utils"
"strings"
)
type ScanController struct {
BaseGateway
}
//处理错误的返回
func (c *ScanController) SolveFailJSON(p *response.PayBaseResp) {
scanFailJSON := new(response.ScanFailData)
scanFailJSON.StatusCode = "01"
scanFailJSON.PayKey = p.Params["payKey"]
scanFailJSON.Msg = p.Msg
c.Data["json"] = scanFailJSON
_ = c.ServeJSON()
c.StopRun()
}
//处理扫码的请求
func (c *ScanController) Scan() {
p := c.PayPrepare()
if p.Code == -1 {
c.SolveFailJSON(p)
}
//签名验证
p.Params["returnUrl"] = strings.TrimSpace(c.GetString("returnUrl"))
paySecret := p.MerchantInfo.MerchantSecret
if !utils.Md5Verify(p.Params, paySecret) {
p.Code = -1
p.Msg = "签名异常"
c.SolveFailJSON(p)
}
//选择通道
p = service.ChooseRoad(p)
if p.Code == -1 {
c.SolveFailJSON(p)
}
//生成订单记录
orderInfo, _ := service.GenerateRecord(p)
if p.Code == -1 {
c.SolveFailJSON(p)
}
//获取到对应的上游
supplierCode := p.RoadInfo.ProductUid
supplier := third_party.GetPaySupplierByCode(supplierCode)
scanData := supplier.Scan(orderInfo, p.RoadInfo, p.MerchantInfo)
if scanData.Status == "00" {
scanSuccessData := service.GenerateSuccessData(scanData, p)
c.Data["json"] = scanSuccessData
_ = c.ServeJSON()
} else {
p.Msg = scanData.Msg
c.SolveFailJSON(p)
}
}

View File

@ -1,86 +0,0 @@
/***************************************************
** @Desc : 下游请求扫码支付的处理逻辑
** @Time : 2019/10/24 11:15
** @Author : yuebin
** @File : gateway
** @Last Modified by : yuebin
** @Last Modified time: 2019/10/24 11:15
** @Software: GoLand
****************************************************/
package gateway
import (
controller "gateway/supplier"
"gateway/utils"
"strings"
)
type ScanController struct {
BaseGateway
}
type ScanSuccessData struct {
OrderNo string `json:"orderNo"`
Sign string `json:"sign"`
OrderPrice string `json:"orderPrice"`
PayKey string `json:"payKey"`
PayUrl string `json:"payURL"`
StatusCode string `json:"statusCode"`
Msg string `json:"msg"`
}
type ScanFailData struct {
PayKey string `json:"payKey"`
StatusCode string `json:"statusCode"`
Msg string `json:"msg"`
}
//处理错误的返回
func (c *ScanController) SolveFailJSON() {
scanFailJSON := new(ScanFailData)
scanFailJSON.StatusCode = "01"
scanFailJSON.PayKey = c.Params["payKey"]
scanFailJSON.Msg = c.Msg
c.Data["json"] = scanFailJSON
c.ServeJSON()
c.StopRun()
}
//处理扫码的请求
func (c *ScanController) Scan() {
c.PayPrepare()
if c.Code == -1 {
c.SolveFailJSON()
}
//签名验证
c.Params["returnUrl"] = strings.TrimSpace(c.GetString("returnUrl"))
paySecret := c.MerchantInfo.MerchantSecret
if !utils.Md5Verify(c.Params, paySecret) {
c.Code = -1
c.Msg = "签名异常"
c.SolveFailJSON()
}
//选择通道
c.ChooseRoad()
if c.Code == -1 {
c.SolveFailJSON()
}
//升级订单记录
orderInfo, _ := c.GenerateRecord()
if c.Code == -1 {
c.SolveFailJSON()
}
//获取到对应的上游
supplierCode := c.RoadInfo.ProductUid
supplier := controller.GetPaySupplierByCode(supplierCode)
scanData := supplier.Scan(orderInfo, c.RoadInfo, c.MerchantInfo)
if scanData.Status == "00" {
scanSuccessData := c.GenerateSuccessData(scanData)
c.Data["json"] = scanSuccessData
c.ServeJSON()
} else {
c.SolveFailJSON()
}
}

43
gateway/message/init.go Normal file
View File

@ -0,0 +1,43 @@
/***************************************************
** @Desc : This file for ...
** @Time : 2019/11/6 11:43
** @Author : yuebin
** @File : active_mq
** @Last Modified by : yuebin
** @Last Modified time: 2019/11/6 11:43
** @Software: GoLand
****************************************************/
package message
import (
"gateway/conf"
"github.com/beego/beego/v2/core/logs"
"github.com/go-stomp/stomp"
"os"
"time"
)
//解决第一个问题的代码
var activeConn *stomp.Conn
var options = []func(*stomp.Conn) error{
//设置读写超时超时时间为1个小时
stomp.ConnOpt.HeartBeat(7200*time.Second, 7200*time.Second),
stomp.ConnOpt.HeartBeatError(360 * time.Second),
}
func init() {
address := conf.GetMQAddress()
conn, err := stomp.Dial("tcp", address, options...)
if err != nil {
logs.Error("链接active mq 失败:", err.Error())
os.Exit(1)
}
activeConn = conn
}
func GetActiveMQConn() *stomp.Conn {
return activeConn
}

View File

@ -0,0 +1,33 @@
/***************************************************
** @Desc : This file for ...
** @Time : 2019/11/21 15:53
** @Author : yuebin
** @File : send_message
** @Last Modified by : yuebin
** @Last Modified time: 2019/11/21 15:53
** @Software: GoLand
****************************************************/
package message
import (
"github.com/beego/beego/v2/core/logs"
"os"
)
func SendMessage(topic, message string) {
conn := GetActiveMQConn()
if conn == nil {
logs.Error("send message get Active mq fail")
os.Exit(1)
}
err := conn.Send(topic, "text/plain", []byte(message))
if err != nil {
logs.Error("发送消息给activeMQ失败, message=", message)
} else {
logs.Info("发送消息给activeMQ成功message=", message)
}
}

View File

@ -0,0 +1,119 @@
/***************************************************
** @Desc : This file for ...
** @Time : 2019/10/16 11:11
** @Author : yuebin
** @File : account
** @Last Modified by : yuebin
** @Last Modified time: 2019/10/16 11:11
** @Software: GoLand
****************************************************/
package accounts
import (
"github.com/beego/beego/v2/client/orm"
"github.com/beego/beego/v2/core/logs"
)
type AccountInfo struct {
Id int
Status string
AccountUid string
AccountName string
Balance float64 //账户总余额
SettleAmount float64 //已经结算的金额
LoanAmount float64 //账户押款金额
FreezeAmount float64 //账户冻结金额
WaitAmount float64 //待结算资金
PayforAmount float64 //代付在途金额
//AbleBalance float64 //账户可用金额
UpdateTime string
CreateTime string
}
const ACCOUNT_INFO = "account_info"
func InsetAcount(account AccountInfo) bool {
o := orm.NewOrm()
_, err := o.Insert(&account)
if err != nil {
logs.Error("insert account fail: ", err)
return false
}
return true
}
func GetAccountByUid(accountUid string) AccountInfo {
o := orm.NewOrm()
var account AccountInfo
_, err := o.QueryTable(ACCOUNT_INFO).Filter("account_uid", accountUid).Limit(1).All(&account)
if err != nil {
logs.Error("get account by uid fail: ", err)
}
return account
}
func GetAccountLenByMap(params map[string]string) int {
o := orm.NewOrm()
qs := o.QueryTable(ACCOUNT_INFO)
for k, v := range params {
if len(v) > 0 {
qs = qs.Filter(k, v)
}
}
cnt, err := qs.Limit(-1).OrderBy("-update_time").Count()
if err != nil {
logs.Error("get account len by map fail: ", err)
}
return int(cnt)
}
func GetAccountByMap(params map[string]string, displayCount, offset int) []AccountInfo {
o := orm.NewOrm()
var accountList []AccountInfo
qs := o.QueryTable(ACCOUNT_INFO)
for k, v := range params {
if len(v) > 0 {
qs = qs.Filter(k, v)
}
}
_, err := qs.Limit(displayCount, offset).OrderBy("-update_time").All(&accountList)
if err != nil {
logs.Error("get account by map fail: ", err)
}
return accountList
}
func GetAllAccount() []AccountInfo {
o := orm.NewOrm()
var accountList []AccountInfo
_, err := o.QueryTable(ACCOUNT_INFO).Limit(-1).All(&accountList)
if err != nil {
logs.Error("get all account fail: ", err)
}
return accountList
}
func UpdateAccount(account AccountInfo) bool {
o := orm.NewOrm()
_, err := o.Update(&account)
if err != nil {
logs.Error("update account fail: ", err)
return false
}
return true
}
func DeleteAccountByUid(accountUid string) bool {
o := orm.NewOrm()
_, err := o.QueryTable(ACCOUNT_INFO).Filter("account_uid", accountUid).Delete()
if err != nil {
logs.Error("delete account fail: ", err)
return false
}
return true
}

View File

@ -0,0 +1,69 @@
/***************************************************
** @Desc : This file for ...
** @Time : 2019/10/19 14:56
** @Author : yuebin
** @File : account_history_info
** @Last Modified by : yuebin
** @Last Modified time: 2019/10/19 14:56
** @Software: GoLand
****************************************************/
package accounts
import (
"github.com/beego/beego/v2/client/orm"
"github.com/beego/beego/v2/core/logs"
)
type AccountHistoryInfo struct {
Id int
AccountUid string
AccountName string
Type string
Amount float64
Balance float64
UpdateTime string
CreateTime string
}
const ACCOUNT_HISTORY_INFO = "account_history_info"
func InsertAccountHistory(accountHistory AccountHistoryInfo) bool {
o := orm.NewOrm()
_, err := o.Insert(accountHistory)
if err != nil {
logs.Error("insert account history fail: ", err)
return false
}
return true
}
func GetAccountHistoryLenByMap(params map[string]string) int {
o := orm.NewOrm()
qs := o.QueryTable(ACCOUNT_HISTORY_INFO)
for k, v := range params {
if len(v) > 0 {
qs = qs.Filter(k, v)
}
}
cnt, err := qs.Limit(-1).Count()
if err != nil {
logs.Error("get account history len by map fail: ", err)
}
return int(cnt)
}
func GetAccountHistoryByMap(params map[string]string, displayCount, offset int) []AccountHistoryInfo {
o := orm.NewOrm()
qs := o.QueryTable(ACCOUNT_HISTORY_INFO)
var accountHistoryList []AccountHistoryInfo
for k, v := range params {
if len(v) > 0 {
qs = qs.Filter(k, v)
}
}
_, err := qs.Limit(displayCount, offset).OrderBy("-update_time").All(&accountHistoryList)
if err != nil {
logs.Error("get account history by map fail: ", err)
}
return accountHistoryList
}

View File

@ -0,0 +1,162 @@
/***************************************************
** @Desc : This file for ...
** @Time : 2019/9/19 14:41
** @Author : yuebin
** @File : agent_info
** @Last Modified by : yuebin
** @Last Modified time: 2019/9/19 14:41
** @Software: GoLand
****************************************************/
package agent
import (
"github.com/beego/beego/v2/client/orm"
"github.com/beego/beego/v2/core/logs"
)
type AgentInfo struct {
Id int
Status string
AgentName string
AgentPassword string
PayPassword string
AgentRemark string
AgentUid string
AgentPhone string
UpdateTime string
CreateTime string
}
const AGENT_INFO = "agent_info"
func IsEixstByAgentName(agentName string) bool {
o := orm.NewOrm()
exist := o.QueryTable(AGENT_INFO).Filter("agent_name", agentName).Exist()
return exist
}
func IsExistByAgentUid(uid string) bool {
o := orm.NewOrm()
exist := o.QueryTable(AGENT_INFO).Filter("agent_uid", uid).Exist()
return exist
}
func IsEixstByAgentPhone(agentPhone string) bool {
o := orm.NewOrm()
exist := o.QueryTable(AGENT_INFO).Filter("agent_phone", agentPhone).Exist()
return exist
}
func InsertAgentInfo(agentInfo AgentInfo) bool {
o := orm.NewOrm()
_, err := o.Insert(&agentInfo)
if err != nil {
logs.Error("insert agent info fail: ", err)
return false
}
return true
}
func GetAgentInfoByAgentUid(agentUid string) AgentInfo {
o := orm.NewOrm()
var agentInfo AgentInfo
_, err := o.QueryTable(AGENT_INFO).Filter("agent_uid", agentUid).Limit(1).All(&agentInfo)
if err != nil {
logs.Error("get agent info by agentUid fail: ", err)
}
return agentInfo
}
func GetAgentInfoByPhone(phone string) AgentInfo {
o := orm.NewOrm()
var agentInfo AgentInfo
_, err := o.QueryTable(AGENT_INFO).Filter("agent_phone", phone).Limit(1).All(&agentInfo)
if err != nil {
logs.Error("get agent info by phone fail: ", err)
}
return agentInfo
}
func GetAgentInfoLenByMap(params map[string]string) int {
o := orm.NewOrm()
qs := o.QueryTable(AGENT_INFO)
for k, v := range params {
if len(v) > 0 {
qs = qs.Filter(k, v)
}
}
cnt, err := qs.Limit(-1).Count()
if err != nil {
logs.Error("get agentinfo len by map fail: ", err)
}
return int(cnt)
}
func GetAgentInfoByMap(params map[string]string, displayCount, offset int) []AgentInfo {
o := orm.NewOrm()
var agentInfoList []AgentInfo
qs := o.QueryTable(AGENT_INFO)
for k, v := range params {
if len(v) > 0 {
qs = qs.Filter(k, v)
}
}
_, err := qs.Limit(displayCount, offset).OrderBy("-update_time").All(&agentInfoList)
if err != nil {
logs.Error("get agentInfo by map fail: ", err)
}
return agentInfoList
}
func GetAllAgentByMap(parmas map[string]string) []AgentInfo {
o := orm.NewOrm()
var agentList []AgentInfo
qs := o.QueryTable(AGENT_INFO)
for k, v := range parmas {
if len(v) > 0 {
qs = qs.Filter(k, v)
}
}
_, err := qs.Limit(-1).All(&agentList)
if err != nil {
logs.Error("get all agent by map fail: ", err)
}
return agentList
}
func UpdateAgentInfo(agentInfo AgentInfo) bool {
o := orm.NewOrm()
_, err := o.Update(&agentInfo)
if err != nil {
logs.Error("update agentinfo fail: ", err)
return false
}
return true
}
func DeleteAgentByAgentUid(agentUid string) bool {
o := orm.NewOrm()
_, err := o.QueryTable(AGENT_INFO).Filter("agent_uid", agentUid).Delete()
if err != nil {
logs.Error("delete agent by agent uid fail: ", err)
return false
}
return true
}

View File

@ -1,10 +1,13 @@
/*************************************************** /***************************************************
** @Desc : 接受上游通道商的订单结果异步回调 ** @Desc : This file for ...
** @Time : 2019/11/22 23:27 ** @Time : 2019/12/17 17:50
** @Author : yuebin ** @Author : yuebin
** @File : supplier_notify ** @File : agent_profit
** @Last Modified by : yuebin ** @Last Modified by : yuebin
** @Last Modified time: 2019/11/22 23:27 ** @Last Modified time: 2019/12/17 17:50
** @Software: GoLand ** @Software: GoLand
****************************************************/ ****************************************************/
package gateway package agent
type AgentProfit struct {
}

View File

@ -12,6 +12,15 @@ package models
import ( import (
"fmt" "fmt"
"gateway/conf" "gateway/conf"
"gateway/models/accounts"
"gateway/models/agent"
"gateway/models/merchant"
"gateway/models/notify"
"gateway/models/order"
"gateway/models/payfor"
"gateway/models/road"
"gateway/models/system"
"gateway/models/user"
"github.com/beego/beego/v2/client/orm" "github.com/beego/beego/v2/client/orm"
"github.com/beego/beego/v2/core/logs" "github.com/beego/beego/v2/core/logs"
_ "github.com/go-sql-driver/mysql" _ "github.com/go-sql-driver/mysql"
@ -30,10 +39,23 @@ func init() {
orm.RegisterDriver("mysql", orm.DRMySQL) orm.RegisterDriver("mysql", orm.DRMySQL)
orm.RegisterDataBase("default", "mysql", link) orm.RegisterDataBase("default", "mysql", link)
orm.RegisterModel(new(UserInfo), new(MenuInfo), new(SecondMenuInfo), orm.RegisterModel(new(user.UserInfo),
new(PowerInfo), new(RoleInfo), new(BankCardInfo), new(RoadInfo), new(system.MenuInfo),
new(RoadPoolInfo), new(AgentInfo), new(MerchantInfo), new(MerchantDeployInfo), new(system.SecondMenuInfo),
new(AccountInfo), new(AccountHistoryInfo), new(OrderInfo), new(OrderProfitInfo), new(system.PowerInfo),
new(OrderSettleInfo), new(NotifyInfo), new(MerchantLoadInfo), new(system.RoleInfo),
new(PayforInfo)) new(system.BankCardInfo),
new(road.RoadInfo),
new(road.RoadPoolInfo),
new(agent.AgentInfo),
new(merchant.MerchantInfo),
new(merchant.MerchantDeployInfo),
new(accounts.AccountInfo),
new(accounts.AccountHistoryInfo),
new(order.OrderInfo),
new(order.OrderProfitInfo),
new(order.OrderSettleInfo),
new(notify.NotifyInfo),
new(merchant.MerchantLoadInfo),
new(payfor.PayforInfo))
} }

View File

@ -0,0 +1,135 @@
/***************************************************
** @Desc : This file for ...
** @Time : 2019/10/7 11:52
** @Author : yuebin
** @File : merchant_deploy_info
** @Last Modified by : yuebin
** @Last Modified time: 2019/10/7 11:52
** @Software: GoLand
****************************************************/
package merchant
import (
"github.com/beego/beego/v2/client/orm"
"github.com/beego/beego/v2/core/logs"
)
type MerchantDeployInfo struct {
Id int
Status string
MerchantUid string
PayType string
SingleRoadUid string
SingleRoadName string
SingleRoadPlatformRate float64
SingleRoadAgentRate float64
RollRoadCode string
RollRoadName string
RollRoadPlatformRate float64
RollRoadAgentRate float64
IsLoan string
LoanRate float64
LoanDays int
UnfreezeHour int
WaitUnfreezeAmount float64
LoanAmount float64
UpdateTime string
CreateTime string
}
const MERCHANT_DEPLOY_INFO = "merchant_deploy_info"
func InsertMerchantDeployInfo(merchantDeployInfo MerchantDeployInfo) bool {
o := orm.NewOrm()
_, err := o.Insert(&merchantDeployInfo)
if err != nil {
logs.Error("insert merchant deploy info fail: ", err)
return false
}
return true
}
func IsExistByUidAndPayType(uid, payType string) bool {
o := orm.NewOrm()
isEixst := o.QueryTable(MERCHANT_DEPLOY_INFO).Filter("merchant_uid", uid).Filter("pay_type", payType).Exist()
return isEixst
}
func GetMerchantDeployByUidAndPayType(uid, payType string) MerchantDeployInfo {
o := orm.NewOrm()
var merchantDeployInfo MerchantDeployInfo
_, err := o.QueryTable(MERCHANT_DEPLOY_INFO).Filter("merchant_uid", uid).Filter("pay_type", payType).Limit(1).All(&merchantDeployInfo)
if err != nil {
logs.Error("get merchant deploy by uid and paytype fail:", err)
}
return merchantDeployInfo
}
func GetMerchantDeployByUid(uid string) (ms []MerchantDeployInfo) {
o := orm.NewOrm()
_, err := o.QueryTable(MERCHANT_DEPLOY_INFO).Filter("merchant_uid", uid).All(&ms)
if err != nil {
logs.Error("get merchant deploy by uid fail:", err)
}
return ms
}
func GetMerchantDeployByHour(hour int) []MerchantDeployInfo {
o := orm.NewOrm()
var merchantDeployList []MerchantDeployInfo
_, err := o.QueryTable(MERCHANT_DEPLOY_INFO).Filter("unfreeze_hour", hour).Filter("status", "active").Limit(-1).All(&merchantDeployList)
if err != nil {
logs.Error("get merchant deploy list fail: ", err)
}
return merchantDeployList
}
func DeleteMerchantDeployByUidAndPayType(uid, payType string) bool {
o := orm.NewOrm()
_, err := o.QueryTable(MERCHANT_DEPLOY_INFO).Filter("merchant_uid", uid).Filter("pay_type", payType).Delete()
if err != nil {
logs.Error("delete merchant deploy by uid and payType fail: ", err)
return false
}
return true
}
func UpdateMerchantDeploy(merchantDeploy MerchantDeployInfo) bool {
o := orm.NewOrm()
_, err := o.Update(&merchantDeploy)
if err != nil {
logs.Error("update merchant deploy fail: ", err)
return false
}
return true
}
func GetMerchantDeployLenByMap(params map[string]string) int {
o := orm.NewOrm()
qs := o.QueryTable(MERCHANT_DEPLOY_INFO)
for k, v := range params {
if len(v) > 0 {
qs = qs.Filter(k, v)
}
}
cnt, err := qs.Count()
if err != nil {
logs.Error("get merchant deploy len by map fail: ", err)
}
return int(cnt)
}
func GetMerchantDeployListByMap(params map[string]string, displayCount, offset int) (md []MerchantDeployInfo) {
o := orm.NewOrm()
qs := o.QueryTable(MERCHANT_DEPLOY_INFO)
for k, v := range params {
if len(v) > 0 {
qs = qs.Filter(k, v)
}
}
_, err := qs.Limit(displayCount, offset).OrderBy("-update_time").All(&md)
if err != nil {
logs.Error("get merchant deploy list by map fail: ", err)
}
return md
}

View File

@ -0,0 +1,205 @@
/***************************************************
** @Desc : This file for ...
** @Time : 2019/9/28 16:47
** @Author : yuebin
** @File : merchant_info
** @Last Modified by : yuebin
** @Last Modified time: 2019/9/28 16:47
** @Software: GoLand
****************************************************/
package merchant
import (
"github.com/beego/beego/v2/client/orm"
"github.com/beego/beego/v2/core/logs"
)
type MerchantInfo struct {
Id int
Status string
BelongAgentUid string
BelongAgentName string
MerchantName string
MerchantUid string
MerchantKey string
MerchantSecret string
LoginPassword string
LoginAccount string
AutoSettle string
AutoPayFor string
WhiteIps string
Remark string
SinglePayForRoadUid string
SinglePayForRoadName string
RollPayForRoadCode string
RollPayForRoadName string
PayforFee float64
UpdateTime string
CreateTime string
}
const MERCHANT_INFO = "merchant_info"
func IsExistByMerchantName(merchantName string) bool {
o := orm.NewOrm()
exist := o.QueryTable(MERCHANT_INFO).Filter("merchant_name", merchantName).Exist()
return exist
}
func IsExistByMerchantUid(uid string) bool {
o := orm.NewOrm()
exist := o.QueryTable(MERCHANT_INFO).Filter("merchant_uid", uid).Exist()
return exist
}
func IsExistMerchantByAgentUid(uid string) bool {
o := orm.NewOrm()
exist := o.QueryTable(MERCHANT_INFO).Filter("belong_agent_uid", uid).Exist()
return exist
}
func IsExistByMerchantPhone(phone string) bool {
o := orm.NewOrm()
exist := o.QueryTable(MERCHANT_INFO).Filter("LoginAccount", phone).Exist()
return exist
}
func GetMerchantByPhone(phone string) (m MerchantInfo) {
o := orm.NewOrm()
_, e := o.QueryTable(MERCHANT_INFO).Filter("LoginAccount", phone).Limit(1).All(&m)
if e != nil {
logs.Error("GetMerchantByPhone merchant fail: ", e)
}
return m
}
func InsertMerchantInfo(merchantInfo MerchantInfo) bool {
o := orm.NewOrm()
_, err := o.Insert(&merchantInfo)
if err != nil {
logs.Error("insert merchant fail: ", err)
return false
}
return true
}
func GetMerchantLenByMap(params map[string]string) int {
o := orm.NewOrm()
qs := o.QueryTable(MERCHANT_INFO)
for k, v := range params {
if len(v) > 0 {
qs = qs.Filter(k, v)
}
}
cnt, err := qs.Count()
if err != nil {
logs.Error("get merchant len by map fail: ", err)
}
return int(cnt)
}
func GetMerchantListByMap(params map[string]string, displayCount, offset int) []MerchantInfo {
o := orm.NewOrm()
qs := o.QueryTable(MERCHANT_INFO)
for k, v := range params {
if len(v) > 0 {
qs = qs.Filter(k, v)
}
}
var merchantList []MerchantInfo
_, err := qs.Limit(displayCount, offset).OrderBy("-update_time").All(&merchantList)
if err != nil {
logs.Error("get merchant list by map fail: ", err)
}
return merchantList
}
func GetAllMerchant() []MerchantInfo {
o := orm.NewOrm()
var merchantList []MerchantInfo
_, err := o.QueryTable(MERCHANT_INFO).Limit(-1).All(&merchantList)
if err != nil {
logs.Error("get all merchant fail", err)
}
return merchantList
}
func GetMerchantByParams(params map[string]string, displayCount, offset int) []MerchantInfo {
o := orm.NewOrm()
var merchantList []MerchantInfo
qs := o.QueryTable(MERCHANT_INFO)
for k, v := range params {
if len(v) > 0 {
qs = qs.Filter(k, v)
}
}
qs.Limit(displayCount, offset).All(&merchantList)
return merchantList
}
func GetMerchantLenByParams(params map[string]string) int {
o := orm.NewOrm()
qs := o.QueryTable(MERCHANT_INFO)
for k, v := range params {
if len(v) > 0 {
qs = qs.Filter(k, v)
}
}
cnt, err := qs.Limit(-1).Count()
if err != nil {
logs.Error("get merchant len by params fail: ", err)
}
return int(cnt)
}
func GetMerchantByUid(merchantUid string) MerchantInfo {
o := orm.NewOrm()
var merchantInfo MerchantInfo
_, err := o.QueryTable(MERCHANT_INFO).Filter("merchant_uid", merchantUid).Limit(1).All(&merchantInfo)
if err != nil {
logs.Error("get merchant info fail: ", err)
}
return merchantInfo
}
func GetMerchantByPaykey(payKey string) MerchantInfo {
o := orm.NewOrm()
var merchantInfo MerchantInfo
_, err := o.QueryTable(MERCHANT_INFO).Filter("merchant_key", payKey).Limit(1).All(&merchantInfo)
if err != nil {
logs.Error("get merchant by merchantKey fail: ", err)
}
return merchantInfo
}
func UpdateMerchant(merchantInfo MerchantInfo) bool {
o := orm.NewOrm()
_, err := o.Update(&merchantInfo)
if err != nil {
logs.Error("update merchant fail: ", err)
return false
}
return true
}
func DeleteMerchantByUid(merchantUid string) bool {
o := orm.NewOrm()
_, err := o.QueryTable(MERCHANT_INFO).Filter("merchant_uid", merchantUid).Delete()
if err != nil {
logs.Error("delete merchant fail: ", err)
return false
}
return true
}

View File

@ -0,0 +1,56 @@
/***************************************************
** @Desc : This file for ...
** @Time : 2019/11/22 13:07
** @Author : yuebin
** @File : merchant_load_info
** @Last Modified by : yuebin
** @Last Modified time: 2019/11/22 13:07
** @Software: GoLand
****************************************************/
package merchant
import (
"github.com/beego/beego/v2/client/orm"
"github.com/beego/beego/v2/core/logs"
)
type MerchantLoadInfo struct {
Id int
Status string
MerchantUid string
RoadUid string
LoadDate string
LoadAmount float64
UpdateTime string
CreateTime string
}
const MERCHANT_LOAD_INFO = "merchant_load_info"
func GetMerchantLoadInfoByMap(params map[string]string) []MerchantLoadInfo {
o := orm.NewOrm()
qs := o.QueryTable(MERCHANT_LOAD_INFO)
for k, v := range params {
if len(v) > 0 {
qs = qs.Filter(k, v)
}
}
var merchantLoadList []MerchantLoadInfo
_, err := qs.Limit(-11).All(&merchantLoadList)
if err != nil {
logs.Error("get merchant load info fail: ", err)
}
return merchantLoadList
}
func IsExistMerchantLoadByParams(params map[string]string) bool {
o := orm.NewOrm()
qs := o.QueryTable(MERCHANT_LOAD_INFO)
for k, v := range params {
if len(v) > 0 {
qs = qs.Filter(k, v)
}
}
return qs.Exist()
}

View File

@ -0,0 +1,84 @@
/***************************************************
** @Desc : This file for ...
** @Time : 2019/11/20 13:13
** @Author : yuebin
** @File : notify_info
** @Last Modified by : yuebin
** @Last Modified time: 2019/11/20 13:13
** @Software: GoLand
****************************************************/
package notify
import (
"github.com/beego/beego/v2/client/orm"
"github.com/beego/beego/v2/core/logs"
)
type NotifyInfo struct {
Id int
Type string //订单-order代付-payfor
BankOrderId string
MerchantOrderId string
Status string
Times int
Url string
Response string
UpdateTime string
CreateTime string
}
const NOTIFYINFO = "notify_info"
func InsertNotifyInfo(notifyInfo NotifyInfo) bool {
o := orm.NewOrm()
_, err := o.Insert(&notifyInfo)
if err != nil {
logs.Error("insert notify fail", err)
return false
}
return true
}
func NotifyInfoExistByBankOrderId(bankOrderId string) bool {
o := orm.NewOrm()
exist := o.QueryTable(NOTIFYINFO).Filter("bank_order_id", bankOrderId).Exist()
return exist
}
func GetNotifyInfoByBankOrderId(bankOrderId string) NotifyInfo {
o := orm.NewOrm()
var notifyInfo NotifyInfo
_, err := o.QueryTable(NOTIFYINFO).Filter("bank_order_id", bankOrderId).All(&notifyInfo)
if err != nil {
logs.Error("get notify info by bankOrderId fail: ", err)
}
return notifyInfo
}
func GetNotifyInfosNotSuccess(params map[string]interface{}) []NotifyInfo {
o := orm.NewOrm()
var notifyInfoList []NotifyInfo
qs := o.QueryTable(NOTIFYINFO)
for k, v := range params {
qs = qs.Filter(k, v)
}
qs = qs.Exclude("status", "success")
_, err := qs.Limit(-1).All(&notifyInfoList)
if err != nil {
logs.Error("get notifyinfos fail: ", err)
}
return notifyInfoList
}
func UpdateNotifyInfo(notifyInfo NotifyInfo) bool {
o := orm.NewOrm()
_, err := o.Update(&notifyInfo)
if err != nil {
logs.Error("update notify info fail: ", err)
return false
}
return true
}

View File

@ -0,0 +1,222 @@
/***************************************************
** @Desc : This file for ...
** @Time : 2019/10/28 10:15
** @Author : yuebin
** @File : order_info
** @Last Modified by : yuebin
** @Last Modified time: 2019/10/28 10:15
** @Software: GoLand
****************************************************/
package order
import (
"fmt"
"github.com/beego/beego/v2/client/orm"
"github.com/beego/beego/v2/core/logs"
"strconv"
)
type OrderInfo struct {
Id int
ShopName string //商品名称
OrderPeriod string //订单有效时间
MerchantOrderId string //商户订单id
BankOrderId string //本系统订单id
BankTransId string //上游流水id
OrderAmount float64 //订单提交的金额
ShowAmount float64 //待支付的金额
FactAmount float64 //用户实际支付金额
RollPoolCode string //轮询池编码
RollPoolName string //轮询池名臣
RoadUid string //通道标识
RoadName string //通道名称
PayProductName string //上游支付公司的名称
PayProductCode string //上游支付公司的编码代号
PayTypeCode string //支付产品编码
PayTypeName string //支付产品名称
OsType string //操作系统类型
Status string //订单支付状态
Refund string //退款状态
RefundTime string //退款操作时间
Freeze string //冻结状态
FreezeTime string //冻结时间
Unfreeze string //是否已经解冻
UnfreezeTime string //解冻时间
ReturnUrl string //支付完跳转地址
NotifyUrl string //下游回调地址
MerchantUid string //商户id
MerchantName string //商户名称
AgentUid string //该商户所属代理
AgentName string //该商户所属代理名称
UpdateTime string
CreateTime string
}
const ORDER_INFO = "order_info"
func InsertOrder(orderInfo OrderInfo) bool {
o := orm.NewOrm()
_, err := o.Insert(&orderInfo)
if err != nil {
logs.Error("insert order info fail: ", err)
return false
}
return true
}
func OrderNoIsEixst(orderId string) bool {
o := orm.NewOrm()
exits := o.QueryTable(ORDER_INFO).Filter("merchant_order_id", orderId).Exist()
return exits
}
func BankOrderIdIsEixst(bankOrderId string) bool {
o := orm.NewOrm()
exists := o.QueryTable(ORDER_INFO).Filter("bank_order_id", bankOrderId).Exist()
return exists
}
func GetOrderLenByMap(params map[string]string) int {
o := orm.NewOrm()
qs := o.QueryTable(ORDER_INFO)
for k, v := range params {
if len(v) > 0 {
qs = qs.Filter(k, v)
}
}
cnt, _ := qs.Limit(-1).Count()
return int(cnt)
}
func GetOrderByMap(params map[string]string, display, offset int) []OrderInfo {
o := orm.NewOrm()
var orderInfoList []OrderInfo
qs := o.QueryTable(ORDER_INFO)
for k, v := range params {
if len(v) > 0 {
qs = qs.Filter(k, v)
}
}
_, err := qs.Limit(display, offset).OrderBy("-update_time").All(&orderInfoList)
if err != nil {
logs.Error("get order by map fail: ", err)
}
return orderInfoList
}
func GetSuccessRateByMap(params map[string]string) string {
o := orm.NewOrm()
qs := o.QueryTable(ORDER_INFO)
for k, v := range params {
if len(v) > 0 {
qs = qs.Filter(k, v)
}
}
successRate := "0%"
allCount, _ := qs.Limit(-1).Count()
successCount, _ := qs.Filter("status", "success").Limit(-1).Count()
if allCount == 0 {
return successRate
}
tmp := float64(successCount) / float64(allCount) * 100
successRate = fmt.Sprintf("%.1f", tmp)
return successRate + "%"
}
func GetAllAmountByMap(params map[string]string) float64 {
o := orm.NewOrm()
condition := "select sum(order_amount) as allAmount from order_info "
for _, v := range params {
if len(v) > 0 {
condition = condition + "where "
break
}
}
flag := false
if params["create_time__gte"] != "" {
flag = true
condition = condition + " create_time >= '" + params["create_time__gte"] + "'"
}
if params["create_time__lte"] != "" {
if flag {
condition = condition + " and "
}
condition = condition + " create_time <= '" + params["create_time__lte"] + "'"
}
if params["merchant_name__icontains"] != "" {
if flag {
condition = condition + " and "
}
condition = condition + "merchant_name like %'" + params["merchant_name__icontains"] + "'% "
}
if params["merchant_order_id"] != "" {
if flag {
condition = condition + " and "
}
condition = condition + " merchant_order_id = '" + params["merchant_order_id"] + "'"
}
if params["bank_order_id"] != "" {
if flag {
condition = condition + " and "
}
condition = condition + " bank_order_id = '" + params["bank_order_id"] + "'"
}
if params["status"] != "" {
if flag {
condition = condition + " and "
}
condition = condition + "status = '" + params["status"] + "'"
}
if params["pay_product_code"] != "" {
if flag {
condition = condition + " and "
}
condition = condition + "pay_product_code = " + params["pay_product_code"] + "'"
}
if params["pay_type_code"] != "" {
if flag {
condition = condition + " and "
}
condition = condition + "pay_type_code = " + params["pay_type_code"]
}
logs.Info("get order amount str = ", condition)
var maps []orm.Params
allAmount := 0.00
num, err := o.Raw(condition).Values(&maps)
if err == nil && num > 0 {
allAmount, _ = strconv.ParseFloat(maps[0]["allAmount"].(string), 64)
}
return allAmount
}
func GetOrderByBankOrderId(bankOrderId string) OrderInfo {
o := orm.NewOrm()
var orderInfo OrderInfo
_, err := o.QueryTable(ORDER_INFO).Filter("bank_order_id", bankOrderId).Limit(1).All(&orderInfo)
if err != nil {
logs.Error("get order info by bankOrderId fail: ", err)
}
return orderInfo
}
func GetOrderByMerchantOrderId(merchantOrderId string) OrderInfo {
o := orm.NewOrm()
var orderInfo OrderInfo
_, err := o.QueryTable(ORDER_INFO).Filter("merchant_order_id", merchantOrderId).Limit(1).All(&orderInfo)
if err != nil {
logs.Error("get order by merchant_order_id: ", err.Error())
}
return orderInfo
}
func GetOneOrder(bankOrderId string) OrderInfo {
o := orm.NewOrm()
var orderInfo OrderInfo
_, err := o.QueryTable(ORDER_INFO).Filter("bank_order_id", bankOrderId).Limit(1).All(&orderInfo)
if err != nil {
logs.Error("get one order fail: ", err)
}
return orderInfo
}

View File

@ -0,0 +1,120 @@
/***************************************************
** @Desc : This file for ...
** @Time : 2019/10/30 11:44
** @Author : yuebin
** @File : order_profit_info
** @Last Modified by : yuebin
** @Last Modified time: 2019/10/30 11:44
** @Software: GoLand
****************************************************/
package order
import (
"github.com/beego/beego/v2/client/orm"
"github.com/beego/beego/v2/core/logs"
)
type OrderProfitInfo struct {
Id int
MerchantName string
MerchantUid string
AgentName string
AgentUid string
PayProductCode string
PayProductName string
PayTypeCode string
PayTypeName string
Status string
MerchantOrderId string
BankOrderId string
BankTransId string
OrderAmount float64
ShowAmount float64
FactAmount float64
UserInAmount float64
SupplierRate float64
PlatformRate float64
AgentRate float64
AllProfit float64
SupplierProfit float64
PlatformProfit float64
AgentProfit float64
UpdateTime string
CreateTime string
}
const ORDER_PROFIT_INFO = "order_profit_info"
func GetOrderProfitByBankOrderId(bankOrderId string) OrderProfitInfo {
o := orm.NewOrm()
var orderProfit OrderProfitInfo
_, err := o.QueryTable(ORDER_PROFIT_INFO).Filter("bank_order_id", bankOrderId).Limit(1).All(&orderProfit)
if err != nil {
logs.Error("GetOrderProfitByBankOrderId fail", err)
}
return orderProfit
}
func GetOrderProfitLenByMap(params map[string]string) int {
o := orm.NewOrm()
qs := o.QueryTable(ORDER_PROFIT_INFO)
for k, v := range params {
if len(v) > 0 {
qs = qs.Filter(k, v)
}
}
cnt, _ := qs.Limit(-1).Count()
return int(cnt)
}
func GetOrderProfitByMap(params map[string]string, display, offset int) []OrderProfitInfo {
o := orm.NewOrm()
var orderProfitInfoList []OrderProfitInfo
qs := o.QueryTable(ORDER_PROFIT_INFO)
for k, v := range params {
if len(v) > 0 {
qs = qs.Filter(k, v)
}
}
_, err := qs.Limit(display, offset).OrderBy("-update_time").All(&orderProfitInfoList)
if err != nil {
logs.Error("get order by map fail: ", err)
}
return orderProfitInfoList
}
/*
func GetPlatformProfitByMap(params map[string]string) []models.PlatformProfit {
o := orm.NewOrm()
cond := "select merchant_name, agent_name, pay_product_name as supplier_name, pay_type_name, sum(fact_amount) as order_amount, count(1) as order_count, " +
"sum(platform_profit) as platform_profit, sum(agent_profit) as agent_profit from " + ORDER_PROFIT_INFO + " where status='success' "
flag := false
for k, v := range params {
if len(v) > 0 {
if flag {
cond += " and"
}
if strings.Contains(k, "create_time__gte") {
cond = cond + " create_time>='" + v + "'"
} else if strings.Contains(k, "create_time__lte") {
cond = cond + " create_time<='" + v + "'"
} else {
cond = cond + " " + k + "='" + v + "'"
}
flag = true
}
}
cond += " group by merchant_uid, agent_uid, pay_product_code, pay_type_code"
var platformProfitList []models.PlatformProfit
_, err := o.Raw(cond).QueryRows(&platformProfitList)
if err != nil {
logs.Error("get platform profit by map fail:", err)
}
return platformProfitList
}
*/

View File

@ -0,0 +1,51 @@
/***************************************************
** @Desc : This file for ...
** @Time : 2019/10/30 11:41
** @Author : yuebin
** @File : order_settle_info
** @Last Modified by : yuebin
** @Last Modified time: 2019/10/30 11:41
** @Software: GoLand
****************************************************/
package order
import (
"github.com/beego/beego/v2/client/orm"
"github.com/beego/beego/v2/core/logs"
)
type OrderSettleInfo struct {
Id int
PayProductCode string
PayProductName string
PayTypeCode string
RoadUid string
PayTypeName string
MerchantUid string
MerchantName string
MerchantOrderId string
BankOrderId string
SettleAmount float64
IsAllowSettle string
IsCompleteSettle string
UpdateTime string
CreateTime string
}
const ORDER_SETTLE_INFO = "order_settle_info"
func GetOrderSettleListByParams(params map[string]string) []OrderSettleInfo {
o := orm.NewOrm()
qs := o.QueryTable(ORDER_SETTLE_INFO)
for k, v := range params {
if len(v) > 0 {
qs = qs.Filter(k, v)
}
}
var orderSettleList []OrderSettleInfo
if _, err := qs.Limit(-1).All(&orderSettleList); err != nil {
logs.Error("get order settle list fail: ", err)
}
return orderSettleList
}

View File

@ -0,0 +1,21 @@
/***************************************************
** @Desc : This file for ...
** @Time : 2019/12/17 17:50
** @Author : yuebin
** @File : platform_profit
** @Last Modified by : yuebin
** @Last Modified time: 2019/12/17 17:50
** @Software: GoLand
****************************************************/
package order
type PlatformProfit struct {
MerchantName string
AgentName string
SupplierName string
PayTypeName string
OrderAmount float64
OrderCount int
PlatformProfit float64
AgentProfit float64
}

View File

@ -0,0 +1,116 @@
/***************************************************
** @Desc : This file for ...
** @Time : 2019/11/25 14:32
** @Author : yuebin
** @File : payfor_info
** @Last Modified by : yuebin
** @Last Modified time: 2019/11/25 14:32
** @Software: GoLand
****************************************************/
package payfor
import (
"github.com/beego/beego/v2/client/orm"
"github.com/beego/beego/v2/core/logs"
)
type PayforInfo struct {
Id int
PayforUid string
MerchantUid string
MerchantName string
MerchantOrderId string
BankOrderId string
BankTransId string
RoadUid string
RoadName string
RollPoolCode string
RollPoolName string
PayforFee float64
PayforAmount float64
PayforTotalAmount float64
BankCode string
BankName string
BankAccountName string
BankAccountNo string
BankAccountType string
Country string
City string
Ares string
BankAccountAddress string
PhoneNo string
GiveType string
Type string
NotifyUrl string
Status string
IsSend string
RequestTime string
ResponseTime string
ResponseContent string
Remark string
CreateTime string
UpdateTime string
}
const PAYFORINFO = "payfor_info"
func InsertPayfor(payFor PayforInfo) bool {
o := orm.NewOrm()
_, err := o.Insert(&payFor)
if err != nil {
logs.Error("insert payfor fail: ", err)
return false
}
return true
}
func IsExistPayForByBankOrderId(bankOrderId string) bool {
o := orm.NewOrm()
exist := o.QueryTable(PAYFORINFO).Filter("bank_order_id", bankOrderId).Exist()
return exist
}
func IsExistPayForByMerchantOrderId(merchantOrderId string) bool {
o := orm.NewOrm()
exist := o.QueryTable(PAYFORINFO).Filter("merchant_order_id", merchantOrderId).Exist()
return exist
}
func GetPayForByBankOrderId(bankOrderId string) PayforInfo {
o := orm.NewOrm()
var payFor PayforInfo
_, err := o.QueryTable(PAYFORINFO).Filter("bank_order_id", bankOrderId).Limit(1).All(&payFor)
if err != nil {
logs.Error("get pay for by bank_order_id fail: ", err)
}
return payFor
}
func GetPayForByMerchantOrderId(merchantOrderId string) PayforInfo {
o := orm.NewOrm()
var payFor PayforInfo
_, err := o.QueryTable(PAYFORINFO).Filter("merchant_order_id", merchantOrderId).Limit(1).All(&payFor)
if err != nil {
logs.Error("fail: ", err)
}
return payFor
}
func UpdatePayFor(payFor PayforInfo) bool {
o := orm.NewOrm()
_, err := o.Update(&payFor)
if err != nil {
logs.Error("update pay for fail", err)
return false
}
return true
}

View File

@ -0,0 +1,162 @@
/***************************************************
** @Desc : This file for ...
** @Time : 2019/9/8 12:09
** @Author : yuebin
** @File : road_info
** @Last Modified by : yuebin
** @Last Modified time: 2019/9/8 12:09
** @Software: GoLand
****************************************************/
package road
import (
"github.com/beego/beego/v2/client/orm"
"github.com/beego/beego/v2/core/logs"
)
type RoadInfo struct {
Id int
Status string
RoadName string
RoadUid string
Remark string
ProductName string
ProductUid string
PayType string
BasicFee float64
SettleFee float64
TotalLimit float64
TodayLimit float64
SingleMinLimit float64
SingleMaxLimit float64
StarHour int
EndHour int
Params string
TodayIncome float64
TotalIncome float64
TodayProfit float64
TotalProfit float64
Balance float64
RequestAll int
RequestSuccess int
UpdateTime string
CreateTime string
}
const ROAD_INFO = "road_info"
func GetRoadInfoByRoadUid(roadUid string) RoadInfo {
o := orm.NewOrm()
var roadInfo RoadInfo
_, err := o.QueryTable(ROAD_INFO).Exclude("status", "delete").Filter("road_uid", roadUid).Limit(1).All(&roadInfo)
if err != nil {
logs.Error("get road info by road uid fail: ", err)
}
return roadInfo
}
func GetRoadInfosByRoadUids(roadUids []string) []RoadInfo {
o := orm.NewOrm()
var roadInfoList []RoadInfo
_, err := o.QueryTable(ROAD_INFO).Filter("road_uid__in", roadUids).OrderBy("update_time").All(&roadInfoList)
if err != nil {
logs.Error("get roadInfos by roadUids fail: ", err)
}
return roadInfoList
}
func GetRoadInfoByName(roadName string) RoadInfo {
o := orm.NewOrm()
var roadInfo RoadInfo
_, err := o.QueryTable(ROAD_INFO).Exclude("status", "delete").Filter("road_name", roadName).Limit(1).All(&roadInfo)
if err != nil {
logs.Error("get road info by name fail: ", err)
}
return roadInfo
}
func GetRoadLenByMap(params map[string]string) int {
o := orm.NewOrm()
qs := o.QueryTable(ROAD_INFO)
for k, v := range params {
if len(v) > 0 {
qs = qs.Filter(k, v)
}
}
cnt, err := qs.Exclude("status", "delete").Limit(-1).Count()
if err != nil {
logs.Error("get road len by map fail: ", err)
}
return int(cnt)
}
func GetRoadInfoByMap(params map[string]string, displayCount, offset int) []RoadInfo {
o := orm.NewOrm()
var roadInfoList []RoadInfo
qs := o.QueryTable(ROAD_INFO)
for k, v := range params {
if len(v) > 0 {
qs = qs.Filter(k, v)
}
}
_, err := qs.Exclude("status", "delete").Limit(displayCount, offset).OrderBy("-update_time").All(&roadInfoList)
if err != nil {
logs.Error("get road info by map fail: ", err)
}
return roadInfoList
}
func GetAllRoad(params map[string]string) []RoadInfo {
o := orm.NewOrm()
var roadInfoList []RoadInfo
qs := o.QueryTable(ROAD_INFO)
for k, v := range params {
if len(v) > 0 {
qs = qs.Filter(k, v)
}
}
_, err := qs.Limit(-1).All(&roadInfoList)
if err != nil {
logs.Error("get all road fail: ", err)
}
return roadInfoList
}
func InsertRoadInfo(roadInfo RoadInfo) bool {
o := orm.NewOrm()
_, err := o.Insert(&roadInfo)
if err != nil {
logs.Error("insert road info fail: ", err)
return false
}
return true
}
func RoadInfoExistByRoadUid(roadUid string) bool {
o := orm.NewOrm()
exist := o.QueryTable(ROAD_INFO).Filter("status", "active").Filter("road_uid", roadUid).Exist()
return exist
}
func UpdateRoadInfo(roadInfo RoadInfo) bool {
o := orm.NewOrm()
_, err := o.Update(&roadInfo)
if err != nil {
logs.Error("update road info fail: ", err)
return false
}
return true
}
func DeleteRoadByRoadUid(roadUid string) bool {
o := orm.NewOrm()
_, err := o.QueryTable(ROAD_INFO).Filter("road_uid", roadUid).Delete()
if err != nil {
logs.Error("delete road by road uid fail: ", err)
return false
}
return true
}

View File

@ -0,0 +1,127 @@
/***************************************************
** @Desc : This file for ...
** @Time : 2019/9/9 16:35
** @Author : yuebin
** @File : road_pool_info
** @Last Modified by : yuebin
** @Last Modified time: 2019/9/9 16:35
** @Software: GoLand
****************************************************/
package road
import (
"github.com/beego/beego/v2/client/orm"
"github.com/beego/beego/v2/core/logs"
)
type RoadPoolInfo struct {
Id int
Status string
RoadPoolName string
RoadPoolCode string
RoadUidPool string
UpdateTime string
CreateTime string
}
const ROAD_POOL_INFO = "road_pool_info"
func InsertRoadPool(roadPool RoadPoolInfo) bool {
o := orm.NewOrm()
_, err := o.Insert(&roadPool)
if err != nil {
logs.Error("insert road pool fail: ", err)
return false
}
return true
}
func GetRoadPoolLenByMap(params map[string]string) int {
o := orm.NewOrm()
qs := o.QueryTable(ROAD_POOL_INFO)
for k, v := range params {
if len(v) > 0 {
qs = qs.Filter(k, v)
}
}
cnt, err := qs.Limit(-1).Count()
if err != nil {
logs.Error("get road pool len by map fail: ", err)
}
return int(cnt)
}
func GetRoadPoolByMap(params map[string]string, displayCount, offset int) []RoadPoolInfo {
o := orm.NewOrm()
var roadPoolList []RoadPoolInfo
qs := o.QueryTable(ROAD_POOL_INFO)
for k, v := range params {
if len(v) > 0 {
qs.Filter(k, v)
}
}
_, err := qs.Limit(displayCount, offset).OrderBy("-update_time").All(&roadPoolList)
if err != nil {
logs.Error("get road pool by map fail: ", err)
}
return roadPoolList
}
func GetRoadPoolByRoadPoolCode(roadPoolCode string) RoadPoolInfo {
o := orm.NewOrm()
var roadPoolInfo RoadPoolInfo
_, err := o.QueryTable(ROAD_POOL_INFO).Filter("road_pool_code", roadPoolCode).Limit(1).All(&roadPoolInfo)
if err != nil {
logs.Error("get road pool info by road pool code fail: ", err)
}
return roadPoolInfo
}
func GetAllRollPool(params map[string]string) []RoadPoolInfo {
o := orm.NewOrm()
var roadPoolList []RoadPoolInfo
qs := o.QueryTable(ROAD_POOL_INFO)
for k, v := range params {
if len(v) > 0 {
qs = qs.Filter(k, v)
}
}
_, err := qs.Limit(-1).All(&roadPoolList)
if err != nil {
logs.Error("get all roll pool fail: ", err)
}
return roadPoolList
}
func GetRoadPoolByName(roadPoolName string) RoadPoolInfo {
o := orm.NewOrm()
var roadPoolInfo RoadPoolInfo
_, err := o.QueryTable(ROAD_POOL_INFO).Filter("road_pool_name", roadPoolName).Limit(1).All(&roadPoolInfo)
if err != nil {
logs.Error("get road pool by name fail: ", err)
}
return roadPoolInfo
}
func DeleteRoadPoolByCode(roadPoolCode string) bool {
o := orm.NewOrm()
_, err := o.QueryTable(ROAD_POOL_INFO).Filter("road_pool_code", roadPoolCode).Delete()
if err != nil {
logs.Error("delete road pool by code fail: ", err)
return false
}
return true
}
func UpdateRoadPool(roadPool RoadPoolInfo) bool {
o := orm.NewOrm()
_, err := o.Update(&roadPool)
if err != nil {
logs.Error("update road pool fail: ", err)
return false
}
return true
}

View File

@ -0,0 +1,106 @@
/***************************************************
** @Desc : This file for ...
** @Time : 2019/9/6 10:19
** @Author : yuebin
** @File : bank_card_info
** @Last Modified by : yuebin
** @Last Modified time: 2019/9/6 10:19
** @Software: GoLand
****************************************************/
package system
import (
"github.com/beego/beego/v2/client/orm"
"github.com/beego/beego/v2/core/logs"
)
type BankCardInfo struct {
Id int
Uid string
UserName string
BankName string
BankCode string
BankAccountType string
AccountName string
BankNo string
IdentifyCard string
CertificateNo string
PhoneNo string
BankAddress string
UpdateTime string
CreateTime string
}
const BANK_CARD_INFO = "bank_card_info"
func InsertBankCardInfo(bankCardInfo BankCardInfo) bool {
o := orm.NewOrm()
_, err := o.Insert(&bankCardInfo)
if err != nil {
logs.Error("insert bank card info fail: ", err)
return false
}
return true
}
func GetBankCardLenByMap(params map[string]string) int {
o := orm.NewOrm()
qs := o.QueryTable(BANK_CARD_INFO)
for k, v := range params {
qs = qs.Filter(k, v)
}
cnt, err := qs.Limit(-1).Count()
if err != nil {
logs.Error("get bank card len by map fail: ", err)
}
return int(cnt)
}
func GetBankCardByMap(params map[string]string, displayCount, offset int) []BankCardInfo {
o := orm.NewOrm()
var bankCardList []BankCardInfo
qs := o.QueryTable(BANK_CARD_INFO)
for k, v := range params {
if len(v) > 0 {
qs = qs.Filter(k, v)
}
}
_, err := qs.Limit(displayCount, offset).OrderBy("-update_time").All(&bankCardList)
if err != nil {
logs.Error("get bank card by map fail: ", err)
}
return bankCardList
}
func GetBankCardByUid(uid string) BankCardInfo {
o := orm.NewOrm()
var bankCardInfo BankCardInfo
_, err := o.QueryTable(bankCardInfo).Filter("uid", uid).Limit(1).All(&bankCardInfo)
if err != nil {
logs.Error("get bank card by uid fail: ", err)
}
return bankCardInfo
}
func DeleteBankCardByUid(uid string) bool {
o := orm.NewOrm()
_, err := o.QueryTable(BANK_CARD_INFO).Filter("uid", uid).Delete()
if err != nil {
logs.Error("delete bank card by uid fail: ", err)
return false
}
return true
}
func UpdateBankCard(bankCard BankCardInfo) bool {
o := orm.NewOrm()
_, err := o.Update(&bankCard)
if err != nil {
logs.Error("update bank card fail: ", err)
return false
}
return true
}

View File

@ -0,0 +1,179 @@
/***************************************************
** @Desc : This file for ...
** @Time : 2019/8/21 9:33
** @Author : yuebin
** @File : menu_info
** @Last Modified by : yuebin
** @Last Modified time: 2019/8/21 9:33
** @Software: GoLand
****************************************************/
package system
import (
"github.com/beego/beego/v2/client/orm"
"github.com/beego/beego/v2/core/logs"
)
type MenuInfo struct {
Id int
MenuOrder int
MenuUid string
FirstMenu string
SecondMenu string
Creater string
Status string
CreateTime string
UpdateTime string
}
//实现排序的三个接口函数
type MenuInfoSlice []MenuInfo
func (m MenuInfoSlice) Len() int {
return len(m)
}
func (m MenuInfoSlice) Swap(i, j int) {
m[i], m[j] = m[j], m[i]
}
func (m MenuInfoSlice) Less(i, j int) bool {
return m[i].MenuOrder < m[j].MenuOrder //从小到大排序
}
const MENUINFO = "menu_info"
func InsertMenu(menuInfo MenuInfo) bool {
o := orm.NewOrm()
_, err := o.Insert(&menuInfo)
if err != nil {
logs.Error("insert new menu info fail", err)
return false
}
return true
}
func FirstMenuIsExists(firstMenu string) bool {
o := orm.NewOrm()
exist := o.QueryTable(MENUINFO).Filter("first_menu", firstMenu).Exist()
return exist
}
func FirstMenuUidIsExists(firstMenUid string) bool {
o := orm.NewOrm()
exist := o.QueryTable(MENUINFO).Filter("menu_uid", firstMenUid).Exist()
return exist
}
func MenuOrderIsExists(menuOrder int) bool {
o := orm.NewOrm()
exist := o.QueryTable(MENUINFO).Filter("menu_order", menuOrder).Exist()
return exist
}
func GetMenuLen() int {
o := orm.NewOrm()
cnt, err := o.QueryTable(MENUINFO).Count()
if err != nil {
logs.Error("get menu info len length fail: ", err)
}
return int(cnt)
}
func GetMenuInfoByMenuUid(menuUid string) MenuInfo {
o := orm.NewOrm()
var menuInfo MenuInfo
_, err := o.QueryTable(MENUINFO).Filter("menu_uid", menuUid).Limit(1).All(&menuInfo)
if err != nil {
logs.Error("get menu info by menuUid fail: ", err)
}
return menuInfo
}
func GetMenuInfosByMenuUids(menuUids []string) []MenuInfo {
menuInfoList := make([]MenuInfo, 0)
for _, v := range menuUids {
m := GetMenuInfoByMenuUid(v)
menuInfoList = append(menuInfoList, m)
}
return menuInfoList
}
func GetMenuInfoByMenuOrder(menuOrder int) MenuInfo {
o := orm.NewOrm()
var menuInfo MenuInfo
_, err := o.QueryTable(MENUINFO).Filter("menu_order", menuOrder).Limit(1).All(&menuInfo)
if err != nil {
logs.Error("get menu info by menu order fail: ", err)
}
return menuInfo
}
func GetMenuAll() []MenuInfo {
o := orm.NewOrm()
var menuInfoList []MenuInfo
_, err := o.QueryTable(MENUINFO).OrderBy("-update_time").All(&menuInfoList)
if err != nil {
logs.Error("get all menu list fail", err)
}
return menuInfoList
}
func GetMenuOffset(displayCount, offset int) []MenuInfo {
o := orm.NewOrm()
var menuInfoList []MenuInfo
_, err := o.QueryTable(MENUINFO).Limit(displayCount, offset).All(&menuInfoList)
if err != nil {
logs.Error("get menu offset fail: ", err)
}
return menuInfoList
}
func GetMenuOffsetByMap(params map[string]string, displayCount, offset int) []MenuInfo {
o := orm.NewOrm()
var menuInfoList []MenuInfo
qs := o.QueryTable(MENUINFO)
for k, v := range params {
if len(v) > 0 {
qs = qs.Filter(k, v)
}
}
_, err := qs.Limit(displayCount, offset).OrderBy("-update_time").All(&menuInfoList)
if err != nil {
logs.Error("get menu offset by map fail: ", err)
}
return menuInfoList
}
func GetMenuLenByMap(params map[string]string) int {
o := orm.NewOrm()
qs := o.QueryTable(MENUINFO)
for k, v := range params {
if len(v) > 0 {
qs = qs.Filter(k, v)
}
}
cnt, err := qs.Count()
if err != nil {
logs.Error("get menu len by map fail: ", err)
}
return int(cnt)
}
func UpdateMenuInfo(menuInfo MenuInfo) {
o := orm.NewOrm()
cnt, err := o.Update(&menuInfo)
if err != nil {
logs.Error("update menu info fail: ", err)
}
logs.Info("update menu info success, num: ", cnt)
}
func DeleteMenuInfo(menuUid string) {
o := orm.NewOrm()
cnt, err := o.QueryTable(MENUINFO).Filter("menu_uid", menuUid).Delete()
if err != nil {
logs.Error("delete menu info fail: ", err)
}
logs.Info("delete menu info num: ", cnt)
}

View File

@ -0,0 +1,143 @@
/***************************************************
** @Desc : This file for ...
** @Time : 2019/8/28 17:59
** @Author : yuebin
** @File : power_info
** @Last Modified by : yuebin
** @Last Modified time: 2019/8/28 17:59
** @Software: GoLand
****************************************************/
package system
import (
"github.com/beego/beego/v2/client/orm"
"github.com/beego/beego/v2/core/logs"
)
type PowerInfo struct {
Id int
FirstMenuUid string
SecondMenuUid string
SecondMenu string
PowerId string
PowerItem string
Creater string
Status string
CreateTime string
UpdateTime string
}
const POWER_INFO = "power_info"
type PowerInfoSlice []PowerInfo
func (sm PowerInfoSlice) Len() int {
return len(sm)
}
func (sm PowerInfoSlice) Swap(i, j int) {
sm[i], sm[j] = sm[j], sm[i]
}
func (sm PowerInfoSlice) Less(i, j int) bool {
return sm[i].SecondMenuUid < sm[j].SecondMenuUid
}
func PowerUidExists(powerUid string) bool {
o := orm.NewOrm()
exists := o.QueryTable(POWER_INFO).Filter("power_id", powerUid).Exist()
return exists
}
func InsertPowerInfo(powerInfo PowerInfo) bool {
o := orm.NewOrm()
_, err := o.Insert(&powerInfo)
if err != nil {
logs.Error("insert power info fail: ", err)
return false
}
return true
}
func GetPower() []PowerInfo {
o := orm.NewOrm()
var powerInfo []PowerInfo
_, err := o.QueryTable(POWER_INFO).Limit(-1).All(&powerInfo)
if err != nil {
logs.Error("get power fail: ", err)
}
return powerInfo
}
func GetPowerById(powerId string) PowerInfo {
o := orm.NewOrm()
var powerInfo PowerInfo
_, err := o.QueryTable(POWER_INFO).Filter("power_id", powerId).Limit(1).All(&powerInfo)
if err != nil {
logs.Error("get power by id fail: ", err)
}
return powerInfo
}
func GetPowerByIds(powerIds []string) []PowerInfo {
var powerInfoList []PowerInfo
for _, v := range powerIds {
m := GetPowerById(v)
powerInfoList = append(powerInfoList, m)
}
return powerInfoList
}
func GetPowerItemLenByMap(params map[string]string) int {
o := orm.NewOrm()
qs := o.QueryTable(POWER_INFO)
for k, v := range params {
if len(v) > 0 {
qs = qs.Filter(k, v)
}
}
cnt, err := qs.Limit(-1).Count()
if err != nil {
logs.Error("get power item len by map fail: ", err)
}
return int(cnt)
}
func GetPowerItemByMap(params map[string]string, displpay, offset int) []PowerInfo {
o := orm.NewOrm()
var powerItemList []PowerInfo
qs := o.QueryTable(POWER_INFO)
for k, v := range params {
if len(v) > 0 {
qs = qs.Filter(k, v)
}
}
_, err := qs.Limit(displpay, offset).OrderBy("-update_time").All(&powerItemList)
if err != nil {
logs.Error("get power item by map fail: ", err)
}
return powerItemList
}
func DeletePowerItemByPowerID(powerID string) bool {
o := orm.NewOrm()
_, err := o.QueryTable(POWER_INFO).Filter("power_id", powerID).Delete()
if err != nil {
logs.Error("delete power item by powerID fail: ", err)
return false
}
return true
}
func DeletePowerBySecondUid(secondUid string) bool {
o := orm.NewOrm()
_, err := o.QueryTable(POWER_INFO).Filter("second_menu_uid", secondUid).Delete()
if err != nil {
logs.Error("delete power by second menu uid fail: ", err)
return false
}
return true
}

View File

@ -0,0 +1,123 @@
/***************************************************
** @Desc : This file for ...
** @Time : 2019/8/29 14:43
** @Author : yuebin
** @File : role_info
** @Last Modified by : yuebin
** @Last Modified time: 2019/8/29 14:43
** @Software: GoLand
****************************************************/
package system
import (
"github.com/beego/beego/v2/client/orm"
"github.com/beego/beego/v2/core/logs"
)
type RoleInfo struct {
Id int
RoleName string
RoleUid string
ShowFirstMenu string
ShowFirstUid string
ShowSecondMenu string
ShowSecondUid string
ShowPower string
ShowPowerUid string
Creater string
Status string
Remark string
CreateTime string
UpdateTime string
}
const ROLE_INFO = "role_info"
func GetRoleLenByMap(params map[string]string) int {
o := orm.NewOrm()
qs := o.QueryTable(ROLE_INFO)
for k, v := range params {
if len(v) > 0 {
qs = qs.Filter(k, v)
}
}
cnt, err := qs.Count()
if err != nil {
logs.Error("get role len by map fail: ", err)
}
return int(cnt)
}
func GetRole() []RoleInfo {
o := orm.NewOrm()
var roleInfo []RoleInfo
_, err := o.QueryTable(ROLE_INFO).Limit(-1).OrderBy("-update_time").All(&roleInfo)
if err != nil {
logs.Error("get all role fail: ", err)
}
return roleInfo
}
func GetRoleByMap(params map[string]string, display, offset int) []RoleInfo {
o := orm.NewOrm()
var roleInfo []RoleInfo
qs := o.QueryTable(ROLE_INFO)
for k, v := range params {
if len(v) > 0 {
qs = qs.Filter(k, v)
}
}
_, err := qs.Limit(display, offset).OrderBy("-update_time").All(&roleInfo)
if err != nil {
logs.Error("get role by map fail: ", err)
}
return roleInfo
}
func GetRoleByRoleUid(roleUid string) RoleInfo {
o := orm.NewOrm()
var roleInfo RoleInfo
_, err := o.QueryTable(ROLE_INFO).Filter("role_uid", roleUid).Limit(1).All(&roleInfo)
if err != nil {
logs.Error("get role by role uid fail: ", err)
}
return roleInfo
}
func RoleNameExists(roleName string) bool {
o := orm.NewOrm()
exists := o.QueryTable(ROLE_INFO).Filter("role_name", roleName).Exist()
return exists
}
func InsertRole(roleInfo RoleInfo) bool {
o := orm.NewOrm()
_, err := o.Insert(&roleInfo)
if err != nil {
logs.Error("insert role fail: ", err)
return false
}
return true
}
func DeleteRoleByRoleUid(roleUid string) bool {
o := orm.NewOrm()
_, err := o.QueryTable(ROLE_INFO).Filter("role_uid", roleUid).Delete()
if err != nil {
logs.Error("delete role by role uid fail: ", err)
return false
}
return true
}
func UpdateRoleInfo(roleInfo RoleInfo) bool {
o := orm.NewOrm()
_, err := o.Update(&roleInfo)
if err != nil {
logs.Error("update role info fail: ", err)
return false
}
return true
}

View File

@ -0,0 +1,216 @@
/***************************************************
** @Desc : This file for ...
** @Time : 2019/8/26 9:33
** @Author : yuebin
** @File : second_menu_info
** @Last Modified by : yuebin
** @Last Modified time: 2019/8/26 9:33
** @Software: GoLand
****************************************************/
package system
import (
"github.com/beego/beego/v2/client/orm"
"github.com/beego/beego/v2/core/logs"
)
const SECOND_MENU_INFO = "second_menu_info"
type SecondMenuInfo struct {
Id int
FirstMenuOrder int
FirstMenuUid string
FirstMenu string
MenuOrder int
SecondMenuUid string
SecondMenu string
SecondRouter string
Creater string
Status string
CreateTime string
UpdateTime string
}
type SecondMenuSlice []SecondMenuInfo
func (sm SecondMenuSlice) Len() int {
return len(sm)
}
func (sm SecondMenuSlice) Swap(i, j int) {
sm[i], sm[j] = sm[j], sm[i]
}
func (sm SecondMenuSlice) Less(i, j int) bool {
if sm[i].FirstMenuOrder == sm[j].FirstMenuOrder {
return sm[i].MenuOrder < sm[j].MenuOrder
}
return sm[i].FirstMenuOrder < sm[j].FirstMenuOrder
}
func GetSecondMenuLen() int {
o := orm.NewOrm()
cnt, err := o.QueryTable(SECOND_MENU_INFO).Count()
if err != nil {
logs.Error("get second meun len fail: ", err)
}
return int(cnt)
}
func GetSecondMenuInfoByMenuOrder(menuOrder int, firstMenuUid string) SecondMenuInfo {
o := orm.NewOrm()
var secondMenuInfo SecondMenuInfo
_, err := o.QueryTable(SECOND_MENU_INFO).Filter("first_menu_uid", firstMenuUid).Filter("menu_order", menuOrder).Limit(1).All(&secondMenuInfo)
if err != nil {
logs.Error("get second menu info by menu order fail: ", err)
}
return secondMenuInfo
}
func GetSecondMenuLenByFirstMenuUid(firstMenuUid string) int {
o := orm.NewOrm()
cnt, err := o.QueryTable(SECOND_MENU_INFO).Filter("first_menu_uid", firstMenuUid).Count()
if err != nil {
logs.Error("get second menu len by first menu uid fail: ", err)
}
return int(cnt)
}
func GetSecondMenuList() []SecondMenuInfo {
o := orm.NewOrm()
var secondMenuList []SecondMenuInfo
_, err := o.QueryTable(SECOND_MENU_INFO).Limit(-1).OrderBy("-update_time").All(&secondMenuList)
if err != nil {
logs.Error("get second menu list fail: ", err)
}
return secondMenuList
}
func GetSecondMenuInfoBySecondMenuUid(secondMenuUid string) SecondMenuInfo {
o := orm.NewOrm()
var secondMenuInfo SecondMenuInfo
_, err := o.QueryTable(SECOND_MENU_INFO).Filter("second_menu_uid", secondMenuUid).Limit(1).All(&secondMenuInfo)
if err != nil {
logs.Error("get scond menu info by second menu uid fail: ", err)
}
return secondMenuInfo
}
func GetSecondMenuInfoBySecondMenuUids(secondMenuUids []string) []SecondMenuInfo {
secondMenuInfoList := make([]SecondMenuInfo, 0)
for _, v := range secondMenuUids {
sm := GetSecondMenuInfoBySecondMenuUid(v)
secondMenuInfoList = append(secondMenuInfoList, sm)
}
return secondMenuInfoList
}
func GetSecondMenuListByFirstMenuUid(firstMenuUid string) []SecondMenuInfo {
o := orm.NewOrm()
var secondMenuList []SecondMenuInfo
_, err := o.QueryTable(SECOND_MENU_INFO).Filter("first_menu_uid", firstMenuUid).Limit(-1).OrderBy("-update_time").All(&secondMenuList)
if err != nil {
logs.Error("get second menu list by first menu uid fail: ", err)
}
return secondMenuList
}
func GetSecondMenuLenByMap(params map[string]string) int {
o := orm.NewOrm()
qs := o.QueryTable(SECOND_MENU_INFO)
for k, v := range params {
qs = qs.Filter(k, v)
}
cnt, err := qs.Limit(-1).Count()
if err != nil {
logs.Error("get second menu len by map fail: ", err)
}
return int(cnt)
}
func GetSecondMenuByMap(params map[string]string, displayCount, offset int) []SecondMenuInfo {
o := orm.NewOrm()
var secondMenuList []SecondMenuInfo
qs := o.QueryTable(SECOND_MENU_INFO)
for k, v := range params {
if len(v) > 0 {
qs = qs.Filter(k, v)
}
}
_, err := qs.Limit(displayCount, offset).OrderBy("-update_time").All(&secondMenuList)
if err != nil {
logs.Error("get second menu by map fail: ", err)
}
return secondMenuList
}
func InsertSecondMenu(secondMenuInfo SecondMenuInfo) bool {
o := orm.NewOrm()
_, err := o.Insert(&secondMenuInfo)
if err != nil {
logs.Error("insert second menu fail: ", err)
return false
}
return true
}
func SecondMenuIsExists(seconfMenu string) bool {
o := orm.NewOrm()
exist := o.QueryTable(SECOND_MENU_INFO).Filter("second_menu", seconfMenu).Exist()
return exist
}
func SecondMenuUidIsExists(secondMenuUid string) bool {
o := orm.NewOrm()
exist := o.QueryTable(SECOND_MENU_INFO).Filter("second_menu_uid", secondMenuUid).Exist()
return exist
}
func SecondRouterExists(secondRouter string) bool {
o := orm.NewOrm()
exist := o.QueryTable(SECOND_MENU_INFO).Filter("second_router", secondRouter).Exist()
return exist
}
func DeleteSecondMenuByFirstMenuUid(firstMenuUid string) bool {
o := orm.NewOrm()
num, err := o.QueryTable(SECOND_MENU_INFO).Filter("first_menu_uid", firstMenuUid).Delete()
if err != nil {
logs.Error("delete second menu by first menu uid fail: ", err)
return false
}
logs.Info("delete second menu by first menu uid success, num: ", num)
return true
}
func DeleteSecondMenuBySecondMenuUid(secondMenuUid string) bool {
o := orm.NewOrm()
num, err := o.QueryTable(SECOND_MENU_INFO).Filter("second_menu_uid", secondMenuUid).Delete()
if err != nil {
logs.Error("delete second menu by second menu uid fail: ", err)
return false
}
logs.Info("delete second menu by second menu uid success, num: ", num)
return true
}
func UpdateSecondMenuOrderBySecondUid(secondUid string, order int) {
o := orm.NewOrm()
_, err := o.QueryTable(SECOND_MENU_INFO).Filter("second_menu_uid", secondUid).Update(orm.Params{"menu_order": order})
if err != nil {
logs.Error("update second menu order by second menu uid fail: ", err)
}
}
func UpdateSecondMenu(secondMenu SecondMenuInfo) {
o := orm.NewOrm()
_, err := o.Update(&secondMenu)
if err != nil {
logs.Error("update second menu for first order fail: ", err)
}
}
func SecondMenuExistByMenuOrder(menuOrder int) bool {
o := orm.NewOrm()
exist := o.QueryTable(SECOND_MENU_INFO).Filter("menu_order", menuOrder).Exist()
return exist
}

View File

@ -0,0 +1,146 @@
/***************************************************
** @Desc : This file for ...
** @Time : 2019/8/9 14:02
** @Author : yuebin
** @File : user_info
** @Last Modified by : yuebin
** @Last Modified time: 2019/8/9 14:02
** @Software: GoLand
****************************************************/
package user
import (
"github.com/beego/beego/v2/client/orm"
"github.com/beego/beego/v2/core/logs"
)
const (
USERINFO = "user_info"
)
type UserInfo struct {
Id int
UserId string
Passwd string
Nick string
Remark string
Ip string
Status string
Role string
RoleName string
CreateTime string
UpdateTime string
}
func GetUserInfoByUserID(userID string) UserInfo {
o := orm.NewOrm()
var userInfo UserInfo
err := o.QueryTable(USERINFO).Exclude("status", "delete").Filter("user_id", userID).One(&userInfo)
if err != nil {
logs.Error("get user info fail: ", err)
}
return userInfo
}
func GetOperatorByMap(params map[string]string, displayCount, offset int) []UserInfo {
o := orm.NewOrm()
var userInfo []UserInfo
qs := o.QueryTable(USERINFO)
for k, v := range params {
if len(v) > 0 {
qs = qs.Filter(k, v)
}
}
_, err := qs.Exclude("status", "delete").Limit(displayCount, offset).OrderBy("-update_time").All(&userInfo)
if err != nil {
logs.Error("get operator by map fail: ", err)
}
return userInfo
}
func GetOperatorLenByMap(params map[string]string) int {
o := orm.NewOrm()
qs := o.QueryTable(USERINFO)
for k, v := range params {
qs = qs.Filter(k, v)
}
cnt, err := qs.Exclude("status", "delete").Count()
if err != nil {
logs.Error("get operator len by map fail: ", err)
}
return int(cnt)
}
func UpdateUserInfoIP(userInfo UserInfo) {
o := orm.NewOrm()
num, err := o.QueryTable(USERINFO).Exclude("status", "delete").Filter("user_id", userInfo.UserId).Update(orm.Params{"ip": userInfo.Ip})
if err != nil {
logs.Error("%s update user info ip fail: %v", userInfo.UserId, err)
} else {
logs.Info("%s update user info ip success, num: %d", userInfo.UserId, num)
}
}
func UpdateUserInfoPassword(userInfo UserInfo) {
o := orm.NewOrm()
num, err := o.QueryTable(USERINFO).Exclude("status", "delete").Filter("user_id", userInfo.UserId).Update(orm.Params{"passwd": userInfo.Passwd})
if err != nil {
logs.Error("%s update user info password fail: %v", userInfo.UserId, err)
} else {
logs.Info("%s update user info password success, update num: %d", userInfo.UserId, num)
}
}
func UpdateUserInfo(userInfo UserInfo) {
o := orm.NewOrm()
if num, err := o.Update(&userInfo); err != nil {
logs.Error("update user info fail: ", err)
} else {
logs.Info("update user info success, num: ", num)
}
}
func UpdateStauts(status, userId string) bool {
o := orm.NewOrm()
_, err := o.QueryTable(USERINFO).Filter("user_id", userId).Update(orm.Params{"status": status})
if err != nil {
logs.Error("update status fail: ", err)
return false
}
return true
}
func UserInfoExistByUserId(userId string) bool {
o := orm.NewOrm()
exist := o.QueryTable(USERINFO).Exclude("status", "delete").Filter("user_id", userId).Exist()
return exist
}
func NickIsExist(nick string) bool {
o := orm.NewOrm()
exist := o.QueryTable(USERINFO).Exclude("status", "delete").Filter("nick", nick).Exist()
return exist
}
func InsertUser(userInfo UserInfo) bool {
o := orm.NewOrm()
_, err := o.Insert(&userInfo)
if err != nil {
logs.Error("insert user fail: ", err)
return false
}
return true
}
func DeleteUserByUserId(userId string) bool {
o := orm.NewOrm()
_, err := o.QueryTable(USERINFO).Exclude("status", "delete").Filter("user_id", userId).Update(orm.Params{"status": "delete"})
if err != nil {
logs.Error("delete user by userId fail: ", err)
return false
}
return true
}

View File

@ -0,0 +1,173 @@
/***************************************************
** @Desc : 向下游返回支付结果
** @Time : 2019/11/20 1:35
** @Author : yuebin
** @File : order_notify
** @Last Modified by : yuebin
** @Last Modified time: 2019/11/20 1:35
** @Software: GoLand
****************************************************/
package notify
import (
"fmt"
"gateway/conf"
"gateway/message"
"gateway/models/notify"
"gateway/utils"
"github.com/beego/beego/v2/client/httplib"
"github.com/beego/beego/v2/core/logs"
"github.com/go-stomp/stomp"
"os"
"strings"
"time"
)
type OrderNotifyTask struct {
Delay *time.Timer
MerchantOrderId string
BankOrderId string
FirstNotifyTime string
NotifyTimes int
LimitTimes int
Status string //success-通知成功,其余的为待通知或者通知未完成
}
const (
LimitTimes = 5 //最多通知5次
)
//给商户发送订单结果
func SendOrderNotify(bankOrderId string) {
if !notify.NotifyInfoExistByBankOrderId(bankOrderId) {
logs.Error("该订单不存在回调内容bankOrderId= " + bankOrderId)
return
}
notifyInfo := notify.GetNotifyInfoByBankOrderId(bankOrderId)
if notifyInfo.Status == "success" {
logs.Info(fmt.Sprintf("该订单= %s,已经回调", bankOrderId))
return
}
notifyInfo.Times += 1
notifyInfo.UpdateTime = utils.GetBasicDateTime()
req := httplib.Post(notifyInfo.Url)
response, err := req.String()
if err == nil && ("success" == response || "SUCCESS" == response) {
if strings.Contains(strings.ToLower(response), "success") {
notifyInfo.Status = "success"
if notify.UpdateNotifyInfo(notifyInfo) {
logs.Info("订单回调成功, bankOrderId=", bankOrderId)
} else {
logs.Error("订单回调成功,但是更新数据库失败, bankOrderId=", bankOrderId)
}
} else {
logs.Notice("订单已经回调,商户已经收到了回调通知,但是返回值错误: ", response)
}
} else {
if notifyInfo.Times > LimitTimes {
logs.Notice(fmt.Sprintf("该订单= %s已经超过了回调次数", bankOrderId))
} else {
minute := GetOrderNotifyMinute(notifyInfo.Times)
logs.Info(fmt.Sprintf("bankOrderId = %s, 进行第 %d 次回调,本次延时时间为:%d", notifyInfo.BankOrderId, notifyInfo.Times, minute))
task := OrderNotifyTask{Delay: time.NewTimer(time.Duration(minute) * time.Minute),
MerchantOrderId: notifyInfo.MerchantOrderId, BankOrderId: notifyInfo.BankOrderId, FirstNotifyTime: notifyInfo.CreateTime,
NotifyTimes: notifyInfo.Times, LimitTimes: LimitTimes, Status: notifyInfo.Status}
go OrderNotifyTimer(task)
if !notify.UpdateNotifyInfo(notifyInfo) {
logs.Error("订单回调失败,数据库更新失败:" + bankOrderId)
}
}
}
}
func GetOrderNotifyMinute(times int) int {
cur := 0
switch times {
case 0:
cur = 0
break
case 1:
cur = 1
break
case 2:
cur = 2
break
case 3:
cur = 5
break
case 4:
cur = 15
break
case 5:
cur = 30
break
default:
cur = 45
break
}
return cur
}
func OrderNotifyTimer(task OrderNotifyTask) {
for {
select {
case <-task.Delay.C:
SendOrderNotify(task.BankOrderId)
return
//70分钟没有执行该协程那么退出协程
case <-time.After(time.Minute * 70):
logs.Notice("订单回调延时执行70分钟没有执行")
return
}
}
}
//读取一小时之内,未发送成功,并且还没有到达回调限制次数的记录读取,存入延迟队列
func CreateOrderDelayQueue() {
params := make(map[string]interface{})
params["times__lte"] = LimitTimes
params["create_time__gte"] = utils.GetDateTimeBeforeHours(48)
notifyList := notify.GetNotifyInfosNotSuccess(params)
for _, nf := range notifyList {
minute := GetOrderNotifyMinute(nf.Times)
task := OrderNotifyTask{Delay: time.NewTimer(time.Duration(minute) * time.Minute),
MerchantOrderId: nf.MerchantOrderId, BankOrderId: nf.BankOrderId, FirstNotifyTime: nf.CreateTime,
NotifyTimes: nf.Times, LimitTimes: LimitTimes, Status: nf.Status}
go OrderNotifyTimer(task)
}
}
//创建订单回调消费者
func CreateOrderNotifyConsumer() {
CreateOrderDelayQueue()
//启动定时任务
conn := message.GetActiveMQConn()
if conn == nil {
logs.Error("启动消息队列消费者失败....")
os.Exit(1)
}
logs.Notice("订单回调消息队列启动成功......")
orderNotify, err := conn.Subscribe(conf.MqOrderNotify, stomp.AckClient)
if err != nil {
logs.Error("订阅订单回调失败......")
os.Exit(1)
}
for {
select {
case v := <-orderNotify.C:
if v != nil {
bankOrderId := string(v.Body)
go SendOrderNotify(bankOrderId)
//应答,重要
err := conn.Ack(v)
if err != nil {
logs.Error("消息应答失败!")
}
}
}
}
}

View File

@ -0,0 +1,10 @@
/***************************************************
** @Desc : 将代付结果返回给请求方
** @Time : 2019/11/20 1:35
** @Author : yuebin
** @File : payfor_notify
** @Last Modified by : yuebin
** @Last Modified time: 2019/11/20 1:35
** @Software: GoLand
****************************************************/
package notify

View File

@ -0,0 +1,370 @@
/***************************************************
** @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, ""
}

View File

@ -0,0 +1,135 @@
package pay_for
import (
"context"
"errors"
"fmt"
"gateway/conf"
"gateway/models/accounts"
"gateway/models/payfor"
"gateway/utils"
"github.com/beego/beego/v2/client/orm"
"github.com/beego/beego/v2/core/logs"
)
func PayForFail(p payfor.PayforInfo) bool {
o := orm.NewOrm()
if err := o.DoTx(func(ctx context.Context, txOrm orm.TxOrmer) error {
var tmpForPay payfor.PayforInfo
if err := txOrm.Raw("select * from payfor_info where bank_order_id = ? for update", p.BankOrderId).QueryRow(&tmpForPay); err != nil || tmpForPay.PayforUid == "" {
logs.Error("solve pay fail select fail", err)
return err
}
if tmpForPay.Status == conf.PAYFOR_FAIL || tmpForPay.Status == conf.PAYFOR_SUCCESS {
logs.Error(fmt.Sprintf("该代付订单uid=%s状态已经是最终结果", tmpForPay.PayforUid))
return errors.New("状态已经是最终结果")
}
//更新payfor记录的状态
tmpForPay.Status = conf.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 accounts.AccountInfo
if err := txOrm.Raw("select * from account_info where account_uid = ? for update", tmpForPay.MerchantUid).QueryRow(&account); err != nil || account.AccountUid == "" {
logs.Error("payfor select account fail", err)
return err
}
account.UpdateTime = utils.GetBasicDateTime()
if account.PayforAmount < tmpForPay.PayforTotalAmount {
logs.Error(fmt.Sprintf("商户uid=%s账户中待代付金额小于代付记录的金额", tmpForPay.MerchantUid))
return errors.New("账户中待代付金额小于代付记录的金额")
}
//将正在打款中的金额减去
account.PayforAmount = account.PayforAmount - tmpForPay.PayforTotalAmount
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(p payfor.PayforInfo) bool {
o := orm.NewOrm()
if err := o.DoTx(func(ctx context.Context, txOrm orm.TxOrmer) error {
var tmpPayFor payfor.PayforInfo
if err := txOrm.Raw("select * from payfor_info where bank_order_id = ? for update", p.BankOrderId).QueryRow(&tmpPayFor); err != nil || tmpPayFor.PayforUid == "" {
logs.Error("payfor success select payfor fail", err)
return err
}
if tmpPayFor.Status == conf.PAYFOR_FAIL || tmpPayFor.Status == conf.PAYFOR_SUCCESS {
logs.Error(fmt.Sprintf("该代付订单uid=#{payFor.PayforUid},已经是最终结果,不需要处理"))
return errors.New("已经是最终结果,不需要处理")
}
tmpPayFor.UpdateTime = utils.GetBasicDateTime()
tmpPayFor.Status = conf.PAYFOR_SUCCESS
_, err := txOrm.Update(&tmpPayFor)
if err != nil {
logs.Error("PayForSuccess update payfor fail: ", err)
return err
}
var account accounts.AccountInfo
if err := txOrm.Raw("select * from account_info where account_uid = ? for update", tmpPayFor.MerchantUid).QueryRow(&account); err != nil || account.AccountUid == "" {
logs.Error("payfor success select account fail", err)
return err
}
account.UpdateTime = utils.GetBasicDateTime()
if account.PayforAmount < tmpPayFor.PayforTotalAmount {
logs.Error(fmt.Sprintf("商户uid=#{payFor.MerchantUid},账户中待代付金额小于代付记录的金额"))
return errors.New("账户中待代付金额小于代付记录的金额")
}
//代付打款中的金额减去
account.PayforAmount = account.PayforAmount - tmpPayFor.PayforTotalAmount
//减去余额,减去可用金额
account.Balance = account.Balance - tmpPayFor.PayforTotalAmount
//已结算金额减去
account.SettleAmount = account.SettleAmount - tmpPayFor.PayforTotalAmount
if _, err := txOrm.Update(&account); err != nil {
logs.Error("PayForSuccess update account fail", err)
return err
}
//添加一条动账记录
accountHistory := accounts.AccountHistoryInfo{
AccountUid: tmpPayFor.MerchantUid,
AccountName: tmpPayFor.MerchantName,
Type: conf.SUB_AMOUNT,
Amount: tmpPayFor.PayforTotalAmount,
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
}

View File

@ -7,20 +7,21 @@
** @Last Modified time: 2019/11/6 13:59 ** @Last Modified time: 2019/11/6 13:59
** @Software: GoLand ** @Software: GoLand
****************************************************/ ****************************************************/
package gateway package query
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"gateway/models" "gateway/models/merchant"
"gateway/models/order"
"gateway/utils" "gateway/utils"
"github.com/beego/beego/v2/core/logs" "github.com/beego/beego/v2/core/logs"
beego "github.com/beego/beego/v2/server/web" "github.com/beego/beego/v2/server/web"
"strings" "strings"
) )
type QueryController struct { type MerchantQueryController struct {
beego.Controller web.Controller
} }
type OrderQueryFailData struct { type OrderQueryFailData struct {
@ -32,7 +33,7 @@ type OrderQueryFailData struct {
/* /*
** 改接口是为下游商户提供订单查询 ** 改接口是为下游商户提供订单查询
*/ */
func (c *QueryController) OrderQuery() { func (c *MerchantQueryController) OrderQuery() {
orderNo := strings.TrimSpace(c.GetString("orderNo")) orderNo := strings.TrimSpace(c.GetString("orderNo"))
payKey := strings.TrimSpace(c.GetString("payKey")) payKey := strings.TrimSpace(c.GetString("payKey"))
sign := strings.TrimSpace(c.GetString("sign")) sign := strings.TrimSpace(c.GetString("sign"))
@ -44,11 +45,11 @@ func (c *QueryController) OrderQuery() {
failData.StatusCode = "01" failData.StatusCode = "01"
failData.PayKey = payKey failData.PayKey = payKey
merchantInfo := models.GetMerchantByPaykey(payKey) merchantInfo := merchant.GetMerchantByPaykey(payKey)
if merchantInfo.MerchantUid == "" || len(merchantInfo.MerchantUid) == 0 { if merchantInfo.MerchantUid == "" || len(merchantInfo.MerchantUid) == 0 {
failData.Msg = "商户不存在请核对payKey字段" failData.Msg = "商户不存在请核对payKey字段"
} }
orderInfo := models.GetOrderByMerchantOrderId(orderNo) orderInfo := order.GetOrderByMerchantOrderId(orderNo)
if orderInfo.BankOrderId == "" || len(orderInfo.BankOrderId) == 0 { if orderInfo.BankOrderId == "" || len(orderInfo.BankOrderId) == 0 {
failData.Msg = "不存在这样的订单请核对orderNo字段" failData.Msg = "不存在这样的订单请核对orderNo字段"
} }
@ -60,7 +61,7 @@ func (c *QueryController) OrderQuery() {
} }
if failData.Msg != "" { if failData.Msg != "" {
c.Data["json"] = failData c.Data["json"] = failData
c.ServeJSON() _ = c.ServeJSON()
return return
} }
p := make(map[string]string) p := make(map[string]string)

View File

@ -0,0 +1,137 @@
/***************************************************
** @Desc : 处理代付查询功能
** @Time : 2019/12/3 15:07
** @Author : yuebin
** @File : pay_for_query
** @Last Modified by : yuebin
** @Last Modified time: 2019/12/3 15:07
** @Software: GoLand
****************************************************/
package query
import (
"fmt"
"gateway/conf"
"gateway/message"
"gateway/models/payfor"
"gateway/models/road"
"gateway/pay_for"
"gateway/supplier/third_party"
"gateway/utils"
"github.com/beego/beego/v2/core/logs"
"github.com/go-stomp/stomp"
"os"
"time"
)
type PayForQueryTask struct {
Delay *time.Timer
MerchantOrderId string
BankOrderId string
FirstNotifyTime string
QueryTimes int
LimitTimes int
Status string
}
const (
PayForLimitTimes = 12 //最多查询次数
PayForQueryInterval = 5 //时间间隔为5分钟
)
func PayForQueryTimer(task PayForQueryTask) {
for {
select {
case <-task.Delay.C:
PayForSupplier(task)
task.Delay.Stop()
return
//70分钟没有执行该协程那么退出协程
case <-time.After(time.Minute * 70):
return
}
}
}
func PayForSupplier(task PayForQueryTask) {
logs.Info(fmt.Sprintf("执行代付查询任务:%+v", task))
payFor := payfor.GetPayForByBankOrderId(task.BankOrderId)
roadInfo := road.GetRoadInfoByRoadUid(payFor.RoadUid)
supplier := third_party.GetPaySupplierByCode(roadInfo.ProductUid)
if supplier == nil {
logs.Error("代付查询返回supplier为空")
return
}
res, _ := supplier.PayForQuery(payFor)
if res == conf.PAYFOR_SUCCESS {
//代付成功了
pay_for.PayForSuccess(payFor)
} else if res == conf.PAYFOR_FAIL {
//代付失败
pay_for.PayForFail(payFor)
} else if res == conf.PAYFOR_BANKING {
//银行处理中,那么就继续执行查询,直到次数超过最大次数
if task.QueryTimes <= task.LimitTimes {
task.QueryTimes += 1
task.Delay = time.NewTimer(time.Duration(PayForQueryInterval) * time.Minute)
go PayForQueryTimer(task)
} else {
logs.Info(fmt.Sprintf("该代付订单已经超过最大查询次数bankOrderId = %s", task.BankOrderId))
}
}
}
func payForQueryConsumer(bankOrderId string) {
exist := payfor.IsExistPayForByBankOrderId(bankOrderId)
if !exist {
logs.Error(fmt.Sprintf("代付记录不存在bankOrderId = %s", bankOrderId))
return
}
payFor := payfor.GetPayForByBankOrderId(bankOrderId)
if payFor.Status != conf.PAYFOR_BANKING {
logs.Info(fmt.Sprintf("代付状态不是银行处理中不需要去查询bankOrderId = %s", bankOrderId))
return
}
payForQueryTask := PayForQueryTask{Delay: time.NewTimer(time.Duration(PayForQueryInterval) * time.Minute), MerchantOrderId: payFor.MerchantOrderId,
BankOrderId: payFor.BankOrderId, FirstNotifyTime: utils.GetBasicDateTime(), QueryTimes: 1, LimitTimes: PayForLimitTimes, Status: payFor.Status}
go PayForQueryTimer(payForQueryTask)
}
/*
* 创建代付查询的消费者
*/
func CreatePayForQueryConsumer() {
//启动定时任务
conn := message.GetActiveMQConn()
if conn == nil {
logs.Error("启动消息队列消费者失败....")
os.Exit(1)
}
logs.Notice("代付查询消费启动成功......")
payForQuery, err := conn.Subscribe(conf.MQ_PAYFOR_QUERY, stomp.AckClient)
if err != nil {
logs.Error("订阅代付查询失败......")
os.Exit(1)
}
for {
select {
case v := <-payForQuery.C:
if v != nil {
bankOrderId := string(v.Body)
go payForQueryConsumer(bankOrderId)
//应答,重要
err := conn.Ack(v)
if err != nil {
logs.Error("消息应答失败!")
}
}
}
}
}

View File

@ -0,0 +1,109 @@
/***************************************************
** @Desc : 自动查询上游的支付结果
** @Time : 2019/11/22 23:02
** @Author : yuebin
** @File : order_query
** @Last Modified by : yuebin
** @Last Modified time: 2019/11/22 23:02
** @Software: GoLand
****************************************************/
package query
import (
"fmt"
"gateway/conf"
"gateway/message"
"gateway/models/order"
"gateway/supplier/third_party"
"github.com/beego/beego/v2/core/logs"
"github.com/go-stomp/stomp"
"os"
"time"
)
type OrderQueryTask struct {
BankOrderId string
OrderQueryTimer *time.Timer
Times int
}
const (
DelayTime = 5 //延时时间为5分钟查询一次
LimitTimes = 5 //最多查询5次
)
/*
** 该接口是查询上游的订单
*/
func solveSupplierOrderQuery(task OrderQueryTask) {
bankOrderId := task.BankOrderId
orderInfo := order.GetOrderByBankOrderId(bankOrderId)
if orderInfo.BankOrderId == "" || len(orderInfo.BankOrderId) == 0 {
logs.Error("不存在这样的订单,订单查询结束")
return
}
if orderInfo.Status != "" && orderInfo.Status != "wait" {
logs.Error(fmt.Sprintf("该订单=%s已经处理完毕", bankOrderId))
return
}
supplierCode := orderInfo.PayProductCode
supplier := third_party.GetPaySupplierByCode(supplierCode)
flag := supplier.PayQuery(orderInfo)
if flag {
logs.Info("订单查询成功, bankOrderId", bankOrderId)
} else {
if task.Times <= LimitTimes {
task.Times += 1
task.OrderQueryTimer = time.NewTimer(time.Duration(5) * time.Minute)
DelayOrderQueryQueue(task)
} else {
logs.Notice(fmt.Sprintf("订单id=%s, 已经查询超过次数"))
}
}
}
/*
* 延时队列
*/
func DelayOrderQueryQueue(task OrderQueryTask) {
for {
select {
case <-task.OrderQueryTimer.C:
logs.Info(fmt.Sprintf("订单id=%s,执行第:%d 次查询", task.BankOrderId, task.Times))
solveSupplierOrderQuery(task)
return
case <-time.After(time.Duration(2*DelayTime) * time.Minute):
return
}
}
}
/*
** 启动消息订单查询的消息队列消费者
*/
func CreateSupplierOrderQueryCuConsumer() {
conn := message.GetActiveMQConn()
if conn == nil {
logs.Error("supplier order query consumer fail")
os.Exit(1)
}
logs.Notice("启动订单查询的消费者成功.....")
orderQuerySub, _ := conn.Subscribe(conf.MqOrderQuery, stomp.AckClient)
for {
select {
case v := <-orderQuerySub.C:
if v != nil {
bankOrderId := string(v.Body)
logs.Info("消费者正在处理订单查询: " + bankOrderId)
task := OrderQueryTask{BankOrderId: bankOrderId, OrderQueryTimer: time.NewTimer(time.Second * 1), Times: 1}
DelayOrderQueryQueue(task)
//应答,重要
err := conn.Ack(v)
if err != nil {
logs.Error("消息应答失败!")
}
}
}
}
}

View File

@ -0,0 +1,36 @@
package response
import (
"gateway/models/merchant"
"gateway/models/road"
)
type PayBaseResp struct {
Params map[string]string //请求的基本参数
ClientIp string //商户ip
MerchantInfo merchant.MerchantInfo //商户信息
Msg string //信息
Code int //状态码 200正常
RoadInfo road.RoadInfo
RoadPoolInfo road.RoadPoolInfo
OrderAmount float64
PayWayCode string
PlatformRate float64
AgentRate float64
}
type ScanSuccessData struct {
OrderNo string `json:"orderNo"`
Sign string `json:"sign"`
OrderPrice string `json:"orderPrice"`
PayKey string `json:"payKey"`
PayUrl string `json:"payURL"`
StatusCode string `json:"statusCode"`
Msg string `json:"msg"`
}
type ScanFailData struct {
PayKey string `json:"payKey"`
StatusCode string `json:"statusCode"`
Msg string `json:"msg"`
}

View File

@ -0,0 +1,40 @@
package response
/**
* 返回自动代付结果
*/
type PayForResponse struct {
ResultCode string `json:"resultCode,omitempty"`
ResultMsg string `json:"resultMsg,omitempty"`
MerchantOrderId string `json:"merchantOrderId,omitempty"`
SettAmount string `json:"settAmount,omitempty"`
SettFee string `json:"settFee,omitempty"`
Sign string `json:"sign,omitempty"`
}
/**
* 返回商户代付结果查询结果
*/
type PayForQueryResponse struct {
ResultMsg string `json:"resultMsg,omitempty"`
MerchantOrderId string `json:"merchantOrderId,omitempty"`
SettAmount string `json:"settAmount,omitempty"`
SettFee string `json:"settFee,omitempty"`
SettStatus string `json:"settStatus,omitempty"`
Sign string `json:"sign,omitempty"`
}
/**
* 返回商户查询余额结果
*/
type BalanceResponse struct {
ResultCode string `json:"resultCode,omitempty"`
Balance string `json:"balance,omitempty"`
AvailableAmount string `json:"availableAmount,omitempty"`
FreezeAmount string `json:"freezeAmount,omitempty"`
WaitAmount string `json:"waitAmount,omitempty"`
LoanAmount string `json:"loanAmount,omitempty"`
PayforAmount string `json:"payforAmount,omitempty"`
ResultMsg string `json:"resultMsg,omitempty"`
Sign string `json:"sign,omitempty"`
}

View File

@ -0,0 +1,193 @@
package service
import (
"context"
"gateway/conf"
"gateway/models/merchant"
"gateway/models/order"
"gateway/response"
"github.com/beego/beego/v2/client/orm"
"github.com/beego/beego/v2/core/logs"
"strconv"
"strings"
)
//获取商户信息
func GetMerchantInfo(params map[string]string) *response.PayBaseResp {
c := new(response.PayBaseResp)
c.Params = make(map[string]string)
c.Params = params
merchantInfo := merchant.GetMerchantByPaykey(params["payKey"])
if merchantInfo.MerchantUid == "" || len(merchantInfo.MerchantUid) == 0 {
c.Code = -1
c.Msg = "商户不存在或者paykey有误请联系管理员"
} else if merchantInfo.Status != conf.ACTIVE {
c.Code = -1
c.Msg = "商户状态已经被冻结或者被删除,请联系管理员!"
} else {
c.MerchantInfo = merchantInfo
}
return c
}
func JudgeParams(c *response.PayBaseResp) *response.PayBaseResp {
//c.ReturnUrlIsValid()
c = OrderIsValid(c)
c = NotifyUrlIsValid(c)
c = OsTypeIsValid(c)
c = PayWayCodeIsValid(c)
c = ProductIsValid(c)
c = OrderPeriodIsValid(c)
//c = IpIsWhite()
c = OrderPriceIsValid(c)
return c
}
/*
* 插入支付订单记录和订单利润记录保证一致性
*/
func InsertOrderAndOrderProfit(orderInfo order.OrderInfo, orderProfitInfo order.OrderProfitInfo) bool {
o := orm.NewOrm()
if err := o.DoTx(func(ctx context.Context, txOrm orm.TxOrmer) error {
if _, err := txOrm.Insert(&orderInfo); err != nil {
logs.Error("insert orderInfo fail: ", err)
return err
}
if _, err := txOrm.Insert(&orderProfitInfo); err != nil {
logs.Error("insert orderProfit fail: ", err)
return err
}
return nil
}); err != nil {
return false
}
return true
}
/**
** 判断跳转地址是否符合规则
*/
func ReturnUrlIsValid(c *response.PayBaseResp) *response.PayBaseResp {
if c.Params["returnUrl"] == "" || len(c.Params["returnUrl"]) == 0 {
c.Code = -1
c.Msg = "支付成功后跳转地址不能为空"
}
return c
}
/**
** 判断回调地址是否符合规则
*/
func NotifyUrlIsValid(c *response.PayBaseResp) *response.PayBaseResp {
if c.Params["notifyUrl"] == "" || len(c.Params["notifyUrl"]) == 0 {
c.Code = -1
c.Msg = "支付成功订单回调地址不能空位"
}
return c
}
/**
** 判断设备类型是否符合规则
*/
func OsTypeIsValid(c *response.PayBaseResp) *response.PayBaseResp {
if c.Params["osType"] == "" || len(c.Params["osType"]) == 0 {
c.Code = -1
c.Msg = "支付设备系统类型不能为空,默认填写\"1\"即可"
}
return c
}
/**
** 判断支付类型字段是否符合规则
*/
func PayWayCodeIsValid(c *response.PayBaseResp) *response.PayBaseResp {
if c.Params["payWayCode"] == "" || len(c.Params["payWayCode"]) == 0 {
c.Code = -1
c.Msg = "支付类型字段不能为空"
return c
}
if !strings.Contains(c.Params["payWayCode"], "SCAN") {
c.Code = -1
c.Msg = "扫码支付不支持这种支付类型"
} else {
scanPayWayCodes := conf.GetScanPayWayCodes()
for _, v := range scanPayWayCodes {
if c.Params["payWayCode"] == v {
c.PayWayCode = strings.Replace(c.Params["payWayCode"], "-", "_", -1)
return c
}
}
c.Code = -1
c.Msg = "不存在这种支付类型,请仔细阅读对接文档"
}
return c
}
func ProductIsValid(c *response.PayBaseResp) *response.PayBaseResp {
if c.Params["productName"] == "" || len(c.Params["productName"]) == 0 {
c.Code = -1
c.Msg = "商品描述信息字段不能为空"
}
return c
}
func OrderPeriodIsValid(c *response.PayBaseResp) *response.PayBaseResp {
if c.Params["orderPeriod"] == "" || len(c.Params["orderPeriod"]) == 0 {
c.Code = -1
c.Msg = "订单过期时间不能为空,默认填写\"1\"即可"
}
return c
}
//判断订单金额
func OrderPriceIsValid(c *response.PayBaseResp) *response.PayBaseResp {
if c.Params["orderPrice"] == "" || len(c.Params["orderPrice"]) == 0 {
c.Code = -1
c.Msg = "订单金额不能为空"
return c
}
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
return c
}
//判断金额订单号是否为空或者有重复
func OrderIsValid(c *response.PayBaseResp) *response.PayBaseResp {
if c.Params["orderNo"] == "" || len(c.Params["orderNo"]) == 0 {
c.Code = -1
c.Msg = "商户订单号不能为空"
return c
}
if order.OrderNoIsEixst(c.Params["orderNo"]) {
c.Code = -1
c.Msg = "商户订单号重复"
}
return c
}
//判断ip是否在白名单中
func IpIsWhite() bool {
//TODO
return true
}

View File

@ -0,0 +1,249 @@
/***************************************************
** @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 service
import (
"fmt"
"gateway/conf"
"gateway/models/merchant"
"gateway/models/order"
"gateway/models/road"
"gateway/response"
"gateway/supplier"
"gateway/utils"
"github.com/beego/beego/v2/core/logs"
"github.com/rs/xid"
"strings"
"time"
)
//选择通道
func ChooseRoad(c *response.PayBaseResp) *response.PayBaseResp {
payWayCode := c.Params["payWayCode"]
merchantUid := c.MerchantInfo.MerchantUid
//通道配置信息
deployInfo := merchant.GetMerchantDeployByUidAndPayType(merchantUid, payWayCode)
if deployInfo.MerchantUid == "" {
c.Code = -1
c.Msg = "该商户没有配置通道信息"
return c
}
singleRoad := road.GetRoadInfoByRoadUid(deployInfo.SingleRoadUid)
c.RoadPoolInfo = road.GetRoadPoolByRoadPoolCode(deployInfo.RollRoadCode)
if RoadIsValid(singleRoad, c) {
c.RoadInfo = singleRoad
c.PlatformRate = deployInfo.SingleRoadPlatformRate
c.AgentRate = deployInfo.SingleRoadAgentRate
return c
}
//如果单通道没有有效的,那么寻找通道池里面的通道
if c.RoadPoolInfo.RoadPoolCode == "" {
c.Code = -1
c.Msg = "该商户没有配置通道"
return c
}
roadUids := strings.Split(c.RoadPoolInfo.RoadUidPool, "||")
roadInfos := road.GetRoadInfosByRoadUids(roadUids)
for _, roadInfo := range roadInfos {
if RoadIsValid(roadInfo, c) {
c.RoadInfo = roadInfo
c.PlatformRate = deployInfo.RollRoadPlatformRate
c.AgentRate = deployInfo.RollRoadAgentRate
return c
}
}
if c.RoadInfo.RoadUid == "" {
c.Code = -1
c.Msg = "该商户没有配置通道或者通道不可用"
}
return c
}
//判断通道是否是合法的
func RoadIsValid(roadInfo road.RoadInfo, c *response.PayBaseResp) 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()
road.UpdateRoadInfo(roadInfo)
return true
}
//获取基本订单记录
func GenerateOrderInfo(c *response.PayBaseResp) order.OrderInfo {
//6666是自己系统订单号
bankOrderNo := "6666" + xid.New().String()
//获取支付类型的名称,例如支付宝扫码等
payTypeName := conf.GetNameByPayWayCode(c.Params["payWayCode"])
orderInfo := order.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: conf.NO,
Refund: conf.NO,
Unfreeze: conf.NO,
PayProductCode: c.RoadInfo.ProductUid,
PayTypeCode: c.PayWayCode,
PayTypeName: payTypeName,
OsType: c.Params["osType"],
Status: conf.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 > conf.ZERO {
orderInfo.AgentUid = c.MerchantInfo.BelongAgentUid
orderInfo.AgentName = c.MerchantInfo.BelongAgentName
}
return orderInfo
}
//计算收益,平台利润,代理利润
func GenerateOrderProfit(orderInfo order.OrderInfo, c *response.PayBaseResp) order.OrderProfitInfo {
//因为所有的手续费率都是百分率所以需要除以100
payTypeName := conf.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 = conf.ZERO
}
allProfit := supplierProfit + platformProfit + agentProfit
if allProfit >= c.OrderAmount {
logs.Error("手续费已经超过订单金额bankOrderId = %s", orderInfo.BankOrderId)
c.Msg = "手续费已经超过了订单金额"
c.Code = -1
}
orderProfit := order.OrderProfitInfo{
PayProductCode: c.RoadInfo.ProductUid,
PayProductName: c.RoadInfo.ProductName,
PayTypeCode: c.PayWayCode,
PayTypeName: payTypeName,
Status: conf.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 > conf.ZERO {
orderProfit.AgentUid = c.MerchantInfo.BelongAgentUid
orderProfit.AgentName = c.MerchantInfo.BelongAgentName
}
return orderProfit
}
/*
* 生成订单一系列的记录
*/
func GenerateRecord(c *response.PayBaseResp) (order.OrderInfo, order.OrderProfitInfo) {
//生成订单记录,订单利润利润
orderInfo := GenerateOrderInfo(c)
orderProfit := GenerateOrderProfit(orderInfo, c)
if c.Code == -1 {
return orderInfo, orderProfit
}
if !InsertOrderAndOrderProfit(orderInfo, orderProfit) {
c.Code = -1
return orderInfo, orderProfit
}
logs.Info("插入支付订单记录和支付利润记录成功")
return orderInfo, orderProfit
}
func GenerateSuccessData(scanData supplier.ScanData, c *response.PayBaseResp) *response.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(response.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
}

View File

@ -0,0 +1,503 @@
package service
import (
"context"
"errors"
"fmt"
"gateway/conf"
"gateway/message"
"gateway/models/accounts"
"gateway/models/merchant"
"gateway/models/notify"
"gateway/models/order"
"gateway/models/road"
"gateway/utils"
"github.com/beego/beego/v2/client/orm"
"github.com/beego/beego/v2/core/logs"
"net/url"
"strconv"
)
//处理支付成功的加款等各项操作
func SolvePaySuccess(bankOrderId string, factAmount float64, trxNo string) bool {
o := orm.NewOrm()
err := o.DoTx(func(ctx context.Context, txOrm orm.TxOrmer) error {
var orderInfo order.OrderInfo
if err := txOrm.Raw("select * from order_info where bank_order_id = ? for update", bankOrderId).QueryRow(&orderInfo); err != nil || orderInfo.BankOrderId == "" {
logs.Error("不存在该订单或者select for update出错")
return err
}
if orderInfo.Status != "wait" {
logs.Error("该订单已经处理,订单号=", bankOrderId)
return errors.New(fmt.Sprintf("该订单已经处理,订单号= %s", bankOrderId))
}
if factAmount <= conf.ZERO {
factAmount = orderInfo.OrderAmount
}
var orderProfitInfo order.OrderProfitInfo
if err := txOrm.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)
return err
}
if orderProfitInfo.BankOrderId == "" {
logs.Error("solve pay success, get orderProfit fail, bankOrderId = ", bankOrderId)
return errors.New(fmt.Sprintf("solve pay success, get orderProfit fail, bankOrderId = %s", bankOrderId))
}
orderInfo.Status = conf.SUCCESS
orderInfo.BankTransId = trxNo
orderInfo.UpdateTime = utils.GetBasicDateTime()
if _, err := txOrm.Update(&orderInfo); err != nil || orderInfo.BankOrderId == "" {
logs.Error(fmt.Sprintf("solve pay success, update order info fail: %s, bankOrderId = %s", err, bankOrderId))
return err
}
orderSettleInfo := order.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: orderProfitInfo.UserInAmount,
IsAllowSettle: conf.YES,
IsCompleteSettle: conf.NO,
UpdateTime: utils.GetBasicDateTime(),
CreateTime: utils.GetBasicDateTime(),
}
if _, err := txOrm.Insert(&orderSettleInfo); err != nil {
logs.Error(fmt.Sprintf("solve pay successinsert order settle info fail: %s, bankOrderId = %s", err, bankOrderId))
return err
}
//做账户的加款操作,最重要的一部
var accountInfo accounts.AccountInfo
if err := txOrm.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))
return err
}
if _, err := txOrm.QueryTable(accounts.ACCOUNT_INFO).Filter("account_uid", orderInfo.MerchantUid).
Update((orm.Params{"balance": accountInfo.Balance + orderProfitInfo.UserInAmount, "wait_amount": accountInfo.WaitAmount + orderProfitInfo.UserInAmount})); err != nil {
logs.Error(fmt.Sprintf("solve pay success, update account info fail: %s, bankOrderId = %s", err, bankOrderId))
return err
}
//添加一条动账记录
accountHistory := accounts.AccountHistoryInfo{
AccountUid: orderInfo.MerchantUid,
AccountName: orderInfo.MerchantName,
Type: conf.PLUS_AMOUNT,
Amount: orderProfitInfo.UserInAmount,
Balance: accountInfo.Balance + orderProfitInfo.UserInAmount,
UpdateTime: utils.GetBasicDateTime(),
CreateTime: utils.GetBasicDateTime(),
}
if _, err := txOrm.Insert(&accountHistory); err != nil {
logs.Error(fmt.Sprintf("solve pay successinsert account history fail%s, bankOrderId = %s", err, bankOrderId))
return err
}
//更新通道信息
roadInfo := road.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 := txOrm.Update(&roadInfo); err != nil {
logs.Error(fmt.Sprintf("solve pay success, update road info fail: %s, bankOrderId = %s", err, bankOrderId))
return err
}
//更新订单利润表
orderProfitInfo.Status = conf.SUCCESS
orderProfitInfo.UpdateTime = utils.GetBasicDateTime()
if _, err := txOrm.Update(&orderProfitInfo); err != nil {
logs.Error(fmt.Sprintf("solve pay success, update order profit info fail: %s, bankOrderId = %s", err, bankOrderId))
return err
}
// 给下游发送回调通知
go CreateOrderNotifyInfo(orderInfo, conf.SUCCESS)
return nil
})
if err != nil {
logs.Error("SolvePaySuccess失败", err)
return false
}
logs.Info("SolvePaySuccess处理成功")
return true
}
//处理支付失败
func SolvePayFail(bankOrderId, transId string) bool {
o := orm.NewOrm()
err := o.DoTx(func(ctx context.Context, txOrm orm.TxOrmer) error {
var orderTmp order.OrderInfo
//bankOrderId := orderInfo.BankOrderId
if err := txOrm.Raw("select * from order_info where bank_order_id = ?", bankOrderId).QueryRow(&orderTmp); err != nil || orderTmp.BankOrderId == "" {
return err
}
if orderTmp.Status != "wait" {
return errors.New("订单已经处理,不要重复加款")
}
if _, err := txOrm.QueryTable(order.ORDER_INFO).Filter("bank_order_id", bankOrderId).Update(orm.Params{"status": conf.FAIL, "bank_trans_id": transId}); err != nil {
logs.Error("更改订单状态失败:", err)
return err
}
if _, err := txOrm.QueryTable(order.ORDER_PROFIT_INFO).Filter("bank_order_id", bankOrderId).Update(orm.Params{"status": conf.FAIL, "bank_trans_id": transId}); err != nil {
logs.Error("更改订单状态失败:", err)
return err
}
go CreateOrderNotifyInfo(orderTmp, conf.FAIL)
return nil
})
if err != nil {
logs.Error("SolvePayFail", err)
return false
}
logs.Info("SolvePayFail成功")
return true
}
//处理订单冻结
func SolveOrderFreeze(bankOrderId string) bool {
o := orm.NewOrm()
err := o.DoTx(func(ctx context.Context, txOrm orm.TxOrmer) error {
var orderInfo order.OrderInfo
if err := txOrm.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)
return err
}
if orderInfo.Status != conf.SUCCESS {
logs.Error("非成功订单不能进行冻结")
return errors.New("非成功订单不能进行冻结")
}
orderInfo.Freeze = conf.YES
orderInfo.FreezeTime = utils.GetBasicDateTime()
orderInfo.UpdateTime = utils.GetBasicDateTime()
if _, err := txOrm.Update(&orderInfo); err != nil {
logs.Error("solve order freeze fail: ", err)
return err
}
//账户的冻结金额里面加入相应的金额
orderProfitInfo := order.GetOrderProfitByBankOrderId(bankOrderId)
var accountInfo accounts.AccountInfo
if err := txOrm.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))
return err
}
accountInfo.UpdateTime = utils.GetBasicDateTime()
accountInfo.FreezeAmount = accountInfo.FreezeAmount + orderProfitInfo.UserInAmount
if _, err := txOrm.Update(&accountInfo); err != nil {
logs.Error("solve order freeze fail: ", err)
return err
}
//插入一条动账记录
accountHistoryInfo := accounts.AccountHistoryInfo{
AccountName: accountInfo.AccountName,
AccountUid: accountInfo.AccountUid,
Type: conf.FREEZE_AMOUNT,
Amount: orderProfitInfo.UserInAmount,
Balance: accountInfo.Balance,
UpdateTime: utils.GetBasicDateTime(),
CreateTime: utils.GetBasicDateTime(),
}
if _, err := txOrm.Insert(&accountHistoryInfo); err != nil {
logs.Error("solve order freeze fail: ", err)
return err
}
return nil
})
if err != nil {
logs.Error("SolveOrderFreeze", err)
return false
}
logs.Info("SolveOrderFreeze")
return true
}
//订单解冻
func SolveOrderUnfreeze(bankOrderId string) bool {
o := orm.NewOrm()
if err := o.DoTx(func(ctx context.Context, txOrm orm.TxOrmer) error {
orderInfo := new(order.OrderInfo)
if err := txOrm.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 err
}
orderInfo.Freeze = ""
orderInfo.Unfreeze = conf.YES
orderInfo.UnfreezeTime = utils.GetBasicDateTime()
orderInfo.UpdateTime = utils.GetBasicDateTime()
if _, err := txOrm.Update(orderInfo); err != nil {
logs.Error("solve order unfreeze fail: ", err)
return err
}
orderProfitInfo := order.GetOrderProfitByBankOrderId(bankOrderId)
accountInfo := new(accounts.AccountInfo)
if err := txOrm.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))
return err
}
accountInfo.UpdateTime = utils.GetBasicDateTime()
accountInfo.FreezeAmount = accountInfo.FreezeAmount - orderProfitInfo.UserInAmount
if _, err := txOrm.Update(accountInfo); err != nil {
logs.Error("solve order unfreeze fail: ", err)
return err
}
accountHistoryInfo := accounts.AccountHistoryInfo{
AccountUid: accountInfo.AccountUid,
AccountName: accountInfo.AccountName,
Type: conf.UNFREEZE_AMOUNT,
Amount: orderProfitInfo.UserInAmount,
Balance: accountInfo.Balance,
UpdateTime: utils.GetBasicDateTime(),
CreateTime: utils.GetBasicDateTime(),
}
if _, err := txOrm.Insert(&accountHistoryInfo); err != nil {
return err
}
return nil
}); err != nil {
logs.Error("SolveOrderUnfreeze失败", err)
return false
}
return true
}
func SolveRefund(bankOrderId string) bool {
o := orm.NewOrm()
if err := o.DoTx(func(ctx context.Context, txOrm orm.TxOrmer) error {
orderInfo := new(order.OrderInfo)
if err := txOrm.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 err
}
orderInfo.UpdateTime = utils.GetBasicDateTime()
orderInfo.Refund = conf.YES
orderInfo.RefundTime = utils.GetBasicDateTime()
orderProfitInfo := order.GetOrderProfitByBankOrderId(bankOrderId)
account := new(accounts.AccountInfo)
if err := txOrm.Raw("select * from account_info where account_uid = ? for update", orderInfo.MerchantUid).QueryRow(account); err != nil || account.AccountUid == "" {
return err
}
account.UpdateTime = utils.GetBasicDateTime()
account.SettleAmount = account.SettleAmount - orderProfitInfo.UserInAmount
account.Balance = account.Balance - orderProfitInfo.UserInAmount
if orderInfo.Freeze == conf.YES {
account.FreezeAmount = account.FreezeAmount - orderProfitInfo.UserInAmount
if account.FreezeAmount < 0 {
account.FreezeAmount = conf.ZERO
}
orderInfo.Freeze = ""
}
if _, err := txOrm.Update(orderInfo); err != nil {
logs.Error("solve order refund update order info fail: ", err)
return err
}
if _, err := txOrm.Update(account); err != nil {
logs.Error("solve order refund update account fail: ", err)
return err
}
accountHistoryInfo := accounts.AccountHistoryInfo{
AccountName: account.AccountName,
AccountUid: account.AccountUid,
Type: conf.REFUND,
Amount: orderProfitInfo.UserInAmount,
Balance: account.Balance,
UpdateTime: utils.GetBasicDateTime(),
CreateTime: utils.GetBasicDateTime(),
}
if _, err := txOrm.Insert(&accountHistoryInfo); err != nil {
logs.Error("solve order refund insert account history fail: ", err)
return err
}
return nil
}); err != nil {
logs.Error("SolveRefund 成功:", err)
return false
}
return true
}
func SolveOrderRoll(bankOrderId string) bool {
o := orm.NewOrm()
if err := o.DoTx(func(ctx context.Context, txOrm orm.TxOrmer) error {
orderInfo := new(order.OrderInfo)
if err := txOrm.Raw("select * from order_info where bank_order_id = ? for update", bankOrderId).QueryRow(orderInfo); err != nil {
logs.Error("solve order roll fail ", err)
return err
}
if orderInfo.Status != conf.SUCCESS {
logs.Error("solve order roll 订单不存在或者订单状态不是success, bankOrderId=", bankOrderId)
return errors.New("solve order roll failed")
}
orderInfo.UpdateTime = utils.GetBasicDateTime()
orderProfitInfo := order.GetOrderProfitByBankOrderId(bankOrderId)
account := new(accounts.AccountInfo)
if err := txOrm.Raw("select * from account_info where account_uid = ? for update", orderInfo.MerchantUid).QueryRow(account); err != nil || account.AccountUid == "" {
return err
}
account.UpdateTime = utils.GetBasicDateTime()
if orderInfo.Refund == conf.YES {
account.Balance = account.Balance + orderProfitInfo.UserInAmount
account.SettleAmount = account.SettleAmount + orderProfitInfo.UserInAmount
orderInfo.Refund = conf.NO
}
if _, err := txOrm.Update(orderInfo); err != nil {
logs.Error("solve order roll fail update order info fail: ", err)
return err
}
if _, err := txOrm.Update(account); err != nil {
logs.Error("solve order roll update account fail: ", err)
return err
}
accountHistoryInfo := accounts.AccountHistoryInfo{
AccountUid: account.AccountUid,
AccountName: account.AccountName,
Type: conf.PLUS_AMOUNT,
Amount: orderProfitInfo.UserInAmount,
Balance: account.Balance,
UpdateTime: utils.GetBasicDateTime(),
CreateTime: utils.GetBasicDateTime(),
}
if _, err := txOrm.Insert(&accountHistoryInfo); err != nil {
logs.Error("solve order roll insert account history fail: ", err)
return err
}
return nil
}); err != nil {
logs.Error("SolveOrderRoll处理失败", err)
return false
}
return true
}
//比较订单金额和实际支付金额的大小
func CompareOrderAndFactAmount(factAmount float64, orderInfo order.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 CreateOrderNotifyInfo(orderInfo order.OrderInfo, tradeStatus string) {
notifyInfo := new(notify.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 := merchant.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)
u := url.Values{}
for k, v := range params {
u.Add(k, v)
}
notifyInfo.Url = orderInfo.NotifyUrl + "?" + u.Encode()
if notify.InsertNotifyInfo(*notifyInfo) {
logs.Info(fmt.Sprintf("订单bankOrderId=%s已经将回调地址插入数据库", orderInfo.BankOrderId))
} else {
logs.Error(fmt.Sprintf("订单bankOrderId=%s插入回调数据库失败", orderInfo.BankOrderId))
}
//将订单发送到消息队列,给下面的商户进行回调
go message.SendMessage(conf.MqOrderNotify, orderInfo.BankOrderId)
}

View File

@ -0,0 +1,234 @@
/***************************************************
** @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 service
import (
"context"
"errors"
"fmt"
"gateway/conf"
"gateway/models/accounts"
"gateway/models/merchant"
"gateway/models/order"
"gateway/utils"
"github.com/beego/beego/v2/client/orm"
"github.com/beego/beego/v2/core/logs"
"time"
)
const (
Interval = 2 //隔多少分钟进行结算
Minutes = 1 //每隔15分钟进行扫码看有没有隔天押款金额
)
/**
* 订单结算将那些支付成功的订单金额加入到商户账户的结算金额中
*/
func OrderSettle() {
params := make(map[string]string)
params["is_allow_settle"] = conf.YES
params["is_complete_settle"] = conf.NO
orderSettleList := order.GetOrderSettleListByParams(params)
for _, orderSettle := range orderSettleList {
orderProfitInfo := order.GetOrderProfitByBankOrderId(orderSettle.BankOrderId)
if !settle(orderSettle, orderProfitInfo) {
logs.Error(fmt.Sprintf("结算订单bankOrderId = #{orderSettle.BankOrderId} 执行失败"))
} else {
logs.Info(fmt.Sprintf("结算订单bankOrderId= #{orderSettle.BankOrderId},执行成功"))
}
}
}
func settle(orderSettle order.OrderSettleInfo, orderProfit order.OrderProfitInfo) bool {
o := orm.NewOrm()
if err := o.DoTx(func(ctx context.Context, txOrm orm.TxOrmer) error {
tmpSettle := new(order.OrderSettleInfo)
if err := txOrm.Raw("select * from order_settle_info where bank_order_id=? for update", orderSettle.BankOrderId).QueryRow(tmpSettle); err != nil || tmpSettle.BankOrderId == "" {
logs.Error("获取tmpSettle失败bankOrderId=%s", orderSettle.BankOrderId)
return err
}
tmpSettle.UpdateTime = utils.GetBasicDateTime()
tmpSettle.IsCompleteSettle = conf.YES
if _, err := txOrm.Update(tmpSettle); err != nil {
logs.Error("更新tmpSettle失败错误", err)
return err
}
accountInfo := new(accounts.AccountInfo)
if err := txOrm.Raw("select * from account_info where account_uid=? for update", orderSettle.MerchantUid).QueryRow(accountInfo); err != nil || accountInfo.UpdateTime == "" {
logs.Error("结算select account info失败错误信息", err)
return err
}
accountInfo.UpdateTime = utils.GetBasicDateTime()
// 商户有押款操作
loadAmount := 0.0
merchantDeployInfo := merchant.GetMerchantDeployByUidAndPayType(accountInfo.AccountUid, orderSettle.PayTypeCode)
if merchantDeployInfo.IsLoan == conf.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 !merchant.IsExistMerchantLoadByParams(params) {
tmp := merchant.MerchantLoadInfo{Status: conf.NO, MerchantUid: orderSettle.MerchantUid, RoadUid: orderSettle.RoadUid,
LoadDate: utils.GetDateAfterDays(merchantDeployInfo.LoanDays), LoadAmount: loadAmount,
UpdateTime: utils.GetBasicDateTime(), CreateTime: utils.GetBasicDateTime()}
if _, err := txOrm.Insert(&tmp); err != nil {
logs.Error("結算插入merchantLoad失敗失败信息", err)
return err
} else {
logs.Info("结算插入新的merchantLoad信息成功")
}
} else {
merchantLoad := new(merchant.MerchantLoadInfo)
if err := txOrm.Raw("select * from merchant_load_info where merchant_uid=? and road_uid=? and load_date=? for update").
QueryRow(merchantLoad); err != nil || merchantLoad.UpdateTime == "" {
logs.Error(fmt.Sprintf("结算过程select merchant load info失败错误信息#{err}"))
return err
} else {
merchantLoad.UpdateTime = utils.GetBasicDateTime()
merchantLoad.LoadAmount += loadAmount
if _, err := txOrm.Update(merchantLoad); err != nil {
logs.Error(fmt.Sprintf("结算过程update merchant load info失败失败信息#{err}"))
return err
}
}
}
} else {
logs.Info(fmt.Sprintf("结算过程中,该商户不需要押款,全款结算"))
}
if accountInfo.WaitAmount < orderProfit.UserInAmount {
logs.Error("系统出现严重故障,账户的带结算金额小于订单结算金额")
return errors.New("系统出现严重故障,账户的带结算金额小于订单结算金额, 账户 = " + accountInfo.AccountName + "订单id = " + orderProfit.BankOrderId)
}
needAmount := orderProfit.UserInAmount - loadAmount
accountInfo.SettleAmount = accountInfo.SettleAmount + needAmount
accountInfo.WaitAmount = accountInfo.WaitAmount - orderProfit.UserInAmount
accountInfo.LoanAmount = accountInfo.LoanAmount + loadAmount
if _, err := txOrm.Update(accountInfo); err != nil {
logs.Error("结算update account 失败,错误信息:", err)
return err
}
return nil
}); err != nil {
return false
}
return true
}
/*
* 商户的押款释放处理根据商户的押款时间进行处理
*/
func MerchantLoadSolve() {
hour := time.Now().Hour()
merchantDeployList := merchant.GetMerchantDeployByHour(hour)
for _, merchantDeploy := range merchantDeployList {
logs.Info(fmt.Sprintf("开始执行商户uid= #{merchantDeploy.MerchantUid},进行解款操作"))
loadDate := utils.GetDateBeforeDays(merchantDeploy.LoanDays)
params := make(map[string]string)
params["status"] = conf.NO
params["merchant_uid"] = merchantDeploy.MerchantUid
params["load_date"] = loadDate
merchantLoadList := merchant.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 merchant.MerchantLoadInfo) bool {
o := orm.NewOrm()
if err := o.DoTx(func(ctx context.Context, txOrm orm.TxOrmer) error {
tmpLoad := new(merchant.MerchantLoadInfo)
if err := txOrm.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.MerchantUid == "" {
logs.Error(fmt.Sprintf("解款操作获取商户押款信息失败fail %s", err))
return err
}
if tmpLoad.Status != conf.NO {
logs.Error(fmt.Sprintf("押款信息merchantuid=%s通道uid=%s 押款日期=%s,已经解款过,不需要再进行处理了", tmpLoad.MerchantUid, tmpLoad.RoadUid, tmpLoad.LoadDate))
return errors.New("已经解款过,不需要再进行处理了")
}
tmpLoad.UpdateTime = utils.GetBasicDateTime()
tmpLoad.Status = conf.YES
if _, err := txOrm.Update(tmpLoad); err != nil {
logs.Error(fmt.Sprintf("解款操作更新merchant load info 失败:%s", err))
return err
}
accountInfo := new(accounts.AccountInfo)
if err := txOrm.Raw("select * from account_info where account_uid = ? for update", merchantLoad.MerchantUid).QueryRow(accountInfo); err != nil || accountInfo.AccountUid == "" {
logs.Error("结款操作获取账户信息失败:", err)
return err
}
accountInfo.UpdateTime = utils.GetBasicDateTime()
if accountInfo.LoanAmount >= tmpLoad.LoadAmount {
accountInfo.LoanAmount = accountInfo.LoanAmount - tmpLoad.LoadAmount
accountInfo.SettleAmount = accountInfo.SettleAmount + tmpLoad.LoadAmount
} else {
accountInfo.LoanAmount = conf.ZERO
}
if _, err := txOrm.Update(accountInfo); err != nil {
logs.Error(fmt.Sprintf("解款操作更新account info 失败:%s账户uid=%s", err, accountInfo.AccountUid))
return err
}
return nil
}); err != nil {
return false
}
return true
}
func OrderSettleInit() {
//每隔5分钟巡查有没有可以进行结算的订单
go func() {
settleTimer := time.NewTimer(time.Duration(Interval) * time.Minute)
oneMinuteTimer := time.NewTimer(time.Duration(Minutes) * time.Minute)
for {
select {
case <-settleTimer.C:
settleTimer = time.NewTimer(time.Duration(Interval) * time.Minute)
logs.Info("开始对商户进行支付订单结算>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>")
OrderSettle()
case <-oneMinuteTimer.C:
oneMinuteTimer = time.NewTimer(time.Duration(Minutes) * time.Minute)
logs.Info("开始执行商户的解款操作>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>")
MerchantLoadSolve()
}
}
}()
}

View File

@ -7,10 +7,13 @@
** @Last Modified time: 2019/10/28 9:39 ** @Last Modified time: 2019/10/28 9:39
** @Software: GoLand ** @Software: GoLand
****************************************************/ ****************************************************/
package controller package supplier
import ( import (
"gateway/models" "gateway/models/merchant"
"gateway/models/order"
"gateway/models/payfor"
"gateway/models/road"
) )
//定义扫码支付的返回值 //定义扫码支付的返回值
@ -27,15 +30,15 @@ type ScanData struct {
} }
type PayInterface interface { type PayInterface interface {
Scan(models.OrderInfo, models.RoadInfo, models.MerchantInfo) ScanData Scan(order.OrderInfo, road.RoadInfo, merchant.MerchantInfo) ScanData
H5(models.OrderInfo, models.RoadInfo, models.MerchantInfo) ScanData H5(order.OrderInfo, road.RoadInfo, merchant.MerchantInfo) ScanData
Fast(models.OrderInfo, models.RoadInfo, models.MerchantInfo) bool Fast(order.OrderInfo, road.RoadInfo, merchant.MerchantInfo) bool
Syt(models.OrderInfo, models.RoadInfo, models.MerchantInfo) ScanData Syt(order.OrderInfo, road.RoadInfo, merchant.MerchantInfo) ScanData
Web(models.OrderInfo, models.RoadInfo, models.MerchantInfo) bool Web(order.OrderInfo, road.RoadInfo, merchant.MerchantInfo) bool
PayNotify() PayNotify()
PayQuery(models.OrderInfo) bool PayQuery(order.OrderInfo) bool
PayFor(models.PayforInfo) string PayFor(payfor.PayforInfo) string
PayForNotify() string PayForNotify() string
PayForQuery(models.PayforInfo) (string, string) PayForQuery(payfor.PayforInfo) (string, string)
BalanceQuery(models.RoadInfo) float64 BalanceQuery(road.RoadInfo) float64
} }

190
gateway/supplier/third_party/daili.go vendored Normal file
View File

@ -0,0 +1,190 @@
/***************************************************
** @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 third_party
import (
"gateway/models/merchant"
"gateway/models/order"
"gateway/models/payfor"
"gateway/models/road"
"gateway/service"
"gateway/supplier"
"gateway/utils"
"github.com/astaxie/beego/httplib"
"github.com/astaxie/beego/logs"
"github.com/beego/beego/v2/server/web"
"github.com/rs/xid"
"github.com/widuu/gojson"
"strconv"
"strings"
)
type DaiLiImpl struct {
web.Controller
}
const NOTITY_URL = "http://localhost:12306/accept/notify"
const URL = "http://zhaoyin.lfwin.com/payapi/pay/jspay3"
func (c *DaiLiImpl) Scan(orderInfo order.OrderInfo, roadInfo road.RoadInfo, merchantInfo merchant.MerchantInfo) supplier.ScanData {
// 从boss后台获取数据
service := gojson.Json(roadInfo.Params).Get("service").Tostring()
apiKey := gojson.Json(roadInfo.Params).Get("apikey").Tostring()
signKey := gojson.Json(roadInfo.Params).Get("signkey").Tostring()
params := make(map[string]string)
params["service"] = service
params["apikey"] = apiKey
params["money"] = strconv.FormatFloat(orderInfo.OrderAmount, 'f', 2, 32)
params["nonce_str"] = xid.New().String()
params["mch_orderid"] = orderInfo.BankOrderId
params["notify_url"] = NOTITY_URL
waitStr := utils.MapToString(utils.SortMapByKeys(params))
waitStr = waitStr + "&signkey=" + signKey
sign := utils.GetMD5LOWER(waitStr)
params["sign"] = sign
request := URL + "?" + utils.MapToString(params)
logs.Info("代丽请求字符串 = " + request)
var scanData supplier.ScanData
scanData.Status = "00"
response, err := httplib.Post(request).String()
if err != nil {
logs.Error("代丽支付请求失败:" + err.Error())
scanData.Status = "-1"
scanData.Msg = "请求失败:" + err.Error()
} else {
/*logs.Info("代丽支付返回 = " + response)
status := gojson.Json(response).Get("status").Tostring()
message := gojson.Json(response).Get("message").Tostring()
if "10000" != status {
scanData.Status = "-1"
scanData.Msg = message
} else {*/
codeUrl := gojson.Json(response).Get("url").Tostring()
codeUrl = "http://www.baidu.com"
scanData.PayUrl = codeUrl
scanData.OrderNo = orderInfo.BankOrderId
scanData.OrderPrice = strconv.FormatFloat(orderInfo.OrderAmount, 'f', 2, 64)
//}
}
return scanData
}
func (c *DaiLiImpl) H5(orderInfo order.OrderInfo, roadInfo road.RoadInfo, merchantInfo merchant.MerchantInfo) supplier.ScanData {
var scanData supplier.ScanData
scanData.Status = "01"
return scanData
}
func (c *DaiLiImpl) Syt(orderInfo order.OrderInfo, roadInfo road.RoadInfo, merchantInfo merchant.MerchantInfo) supplier.ScanData {
var scanData supplier.ScanData
scanData.Status = "01"
return scanData
}
func (c *DaiLiImpl) Fast(orderInfo order.OrderInfo, roadInfo road.RoadInfo, merchantInfo merchant.MerchantInfo) bool {
var scanData supplier.ScanData
scanData.Status = "01"
return true
}
func (c *DaiLiImpl) Web(orderInfo order.OrderInfo, roadInfo road.RoadInfo, merchantInfo merchant.MerchantInfo) bool {
var scanData supplier.ScanData
scanData.Status = "01"
return true
}
func (c *DaiLiImpl) PayNotify() {
params := make(map[string]string)
orderNo := strings.TrimSpace(c.GetString("orderNo"))
orderInfo := order.GetOrderByBankOrderId(orderNo)
if orderInfo.BankOrderId == "" || len(orderInfo.BankOrderId) == 0 {
logs.Error("快付回调的订单号不存在,订单号=", orderNo)
c.StopRun()
}
roadInfo := road.GetRoadInfoByRoadUid(orderInfo.RoadUid)
if roadInfo.RoadUid == "" || len(roadInfo.RoadUid) == 0 {
logs.Error("支付通道已经关系或者删除,不进行回调")
c.StopRun()
}
merchantUid := orderInfo.MerchantUid
merchantInfo := merchant.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 {
orderInfo.FactAmount = 0
}
orderInfo.FactAmount = factAmount
orderInfo.BankTransId = params["trxNo"]
tradeStatus := params["tradeStatus"]
//paySolveController := new(service.PaySolveController)
if tradeStatus == "FAILED" {
if !service.SolvePayFail(orderInfo.BankOrderId, "") {
logs.Error("solve order fail fail")
}
} else if tradeStatus == "CANCELED" {
if !service.SolvePayFail(orderInfo.BankOrderId, "") {
logs.Error("solve order cancel fail")
}
} else if tradeStatus == "WAITING_PAYMENT" {
logs.Notice("快付回调该订单还处于等待支付订单id=", orderNo)
} else if tradeStatus == "SUCCESS" {
//订单支付成功,需要搞很多事情 TODO
service.SolvePaySuccess(orderInfo.BankOrderId, orderInfo.FactAmount, c.GetString("trxNo"))
}
c.Ctx.WriteString("success")
}
func (c *DaiLiImpl) PayQuery(orderInfo order.OrderInfo) bool {
return true
}
func (c *DaiLiImpl) PayFor(info payfor.PayforInfo) string {
return ""
}
func (c *DaiLiImpl) PayForNotify() string {
return ""
}
func (c *DaiLiImpl) PayForQuery(payFor payfor.PayforInfo) (string, string) {
return "", ""
}
func (c *DaiLiImpl) BalanceQuery(roadInfo road.RoadInfo) float64 {
return 0.00
}

48
gateway/supplier/third_party/init.go vendored Normal file
View File

@ -0,0 +1,48 @@
/***************************************************
** @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 third_party
import (
"gateway/supplier"
"github.com/beego/beego/v2/core/logs"
)
//添加新的上游通道时,需要添加这里
var supplierCode2Name = map[string]string{
"KF": "快付支付",
"WEIXIN": "官方微信",
"ALIPAY": "官方支付宝",
"DAILI": "代丽支付",
}
var registerSupplier = make(map[string]supplier.PayInterface)
//注册各种上游的支付接口
func init() {
registerSupplier["KF"] = new(KuaiFuImpl)
logs.Notice(CheckSupplierByCode("KF"))
registerSupplier["DAILI"] = new(DaiLiImpl)
logs.Notice(CheckSupplierByCode("DAILI"))
}
func GetPaySupplierByCode(code string) supplier.PayInterface {
return registerSupplier[code]
}
func CheckSupplierByCode(code string) string {
for k, v := range supplierCode2Name {
if k == code {
return v + ",注册完毕"
}
}
return "未找到上游名称,注册有问题。"
}

384
gateway/supplier/third_party/kuaifu.go vendored Normal file
View File

@ -0,0 +1,384 @@
/***************************************************
** @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 third_party
import (
"fmt"
"gateway/conf"
"gateway/models/merchant"
"gateway/models/order"
"gateway/models/payfor"
"gateway/models/road"
"gateway/service"
"gateway/supplier"
"gateway/utils"
"github.com/beego/beego/v2/client/httplib"
"github.com/beego/beego/v2/core/logs"
beego "github.com/beego/beego/v2/server/web"
"github.com/rs/xid"
"github.com/widuu/gojson"
"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 order.OrderInfo, roadInfo road.RoadInfo, merchantInfo merchant.MerchantInfo) supplier.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"] = "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 supplier.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 order.OrderInfo, roadInfo road.RoadInfo, merchantInfo merchant.MerchantInfo) supplier.ScanData {
var scanData supplier.ScanData
scanData.Status = "01"
return scanData
}
func (c *KuaiFuImpl) Syt(orderInfo order.OrderInfo, roadInfo road.RoadInfo, merchantInfo merchant.MerchantInfo) supplier.ScanData {
var scanData supplier.ScanData
scanData.Status = "01"
return scanData
}
func (c *KuaiFuImpl) Fast(orderInfo order.OrderInfo, roadInfo road.RoadInfo, merchantInfo merchant.MerchantInfo) bool {
var scanData supplier.ScanData
scanData.Status = "01"
return true
}
func (c *KuaiFuImpl) Web(orderInfo order.OrderInfo, roadInfo road.RoadInfo, merchantInfo merchant.MerchantInfo) bool {
var scanData supplier.ScanData
scanData.Status = "01"
return true
}
//支付回调
func (c *KuaiFuImpl) PayNotify() {
params := make(map[string]string)
orderNo := strings.TrimSpace(c.GetString("orderNo"))
orderInfo := order.GetOrderByBankOrderId(orderNo)
if orderInfo.BankOrderId == "" || len(orderInfo.BankOrderId) == 0 {
logs.Error("快付回调的订单号不存在,订单号=", orderNo)
c.StopRun()
}
roadInfo := road.GetRoadInfoByRoadUid(orderInfo.RoadUid)
if roadInfo.RoadUid == "" || len(roadInfo.RoadUid) == 0 {
logs.Error("支付通道已经关系或者删除,不进行回调")
c.StopRun()
}
merchantUid := orderInfo.MerchantUid
merchantInfo := merchant.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"]
if tradeStatus == "FAILED" {
if !service.SolvePayFail(orderInfo.BankOrderId, "") {
logs.Error("solve order fail fail")
}
} else if tradeStatus == "CANCELED" {
if !service.SolvePayFail(orderInfo.BankOrderId, "") {
logs.Error("solve order cancel fail")
}
} else if tradeStatus == "WAITING_PAYMENT" {
logs.Notice("快付回调该订单还处于等待支付订单id=", orderNo)
} else if tradeStatus == "SUCCESS" {
//订单支付成功,需要搞很多事情 TODO
service.SolvePaySuccess(orderInfo.BankOrderId, orderInfo.FactAmount, c.GetString("trxNo"))
}
c.Ctx.WriteString("success")
}
func (c *KuaiFuImpl) PayQuery(orderInfo order.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()
trxNo := gojson.Json(response).Get("trxNo").Tostring()
if tradeStatus == "SUCCESS" {
//调用支付成功的接口,做加款更新操作,需要把实际支付金额传入
if !service.SolvePaySuccess(orderInfo.BankOrderId, factAmount, trxNo) {
return false
}
} else if tradeStatus == "FAILED" {
if !service.SolvePayFail(orderInfo.BankOrderId, "") {
return false
}
} else {
logs.Info("订单状态处于:" + tradeStatus + "bankOrderId" + orderInfo.BankOrderId)
}
return true
}
func (c *KuaiFuImpl) PayFor(payFor payfor.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 == conf.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 payfor.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 conf.PAYFOR_SOLVING, "查询失败"
}
payFor.ResponseContent = response
payFor.ResponseTime = utils.GetBasicDateTime()
payFor.UpdateTime = utils.GetBasicDateTime()
if !payfor.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 conf.PAYFOR_SOLVING, resultMsg
}
logs.Info("快付代付查询返回结果:", resultMsg)
merchantOrderId := gojson.Json(response).Get("merchantOrderId").Tostring()
if merchantOrderId != payFor.BankOrderId {
logs.Error("快付代付返回结果订单id不一致: ", merchantOrderId)
return conf.PAYFOR_SOLVING, "快付代付返回结果订单id不一致"
}
settStatus := gojson.Json(response).Get("settStatus").Tostring()
if settStatus == "00" {
return conf.PAYFOR_SUCCESS, "代付成功"
} else if settStatus == "01" {
return conf.PAYFOR_FAIL, "代付失败"
} else {
return conf.PAYFOR_BANKING, "银行处理中"
}
}
func (c *KuaiFuImpl) BalanceQuery(roadInfo road.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,43 @@
package test
import (
"gateway/conf"
_ "gateway/message"
_ "gateway/models"
"gateway/models/payfor"
"gateway/pay_for"
"gateway/utils"
"github.com/beego/beego/v2/core/logs"
"github.com/rs/xid"
"testing"
)
func TestAutoPayFor(t *testing.T) {
params := make(map[string]string)
params["merchantKey"] = "kkkkc254gk8isf001cqrj6p0"
params["realname"] = "孔跃彬"
params["cardNo"] = "6214830200383973"
params["accType"] = "0"
params["amount"] = "100"
paySecret := "ssssc254gk8isf001cqrj6pg"
params["merchantOrderId"] = xid.New().String()
keys := utils.SortMap(params)
params["sign"] = utils.GetMD5Sign(params, keys, paySecret)
payFor := pay_for.AutoPayFor(params, conf.SELF_API)
logs.Info(payFor)
}
func TestPayForFail(t *testing.T) {
p := new(payfor.PayforInfo)
p.BankOrderId = "4444c4vlk3u7mathho2o8md0"
res := pay_for.PayForFail(*p)
logs.Info(res)
}
func TestPayForSuccess(t *testing.T) {
p := new(payfor.PayforInfo)
p.BankOrderId = "4444c4vlk3u7mathho2o8md0"
res := pay_for.PayForSuccess(*p)
logs.Info(res)
}

63
gateway/tests/pay_test.go Normal file
View File

@ -0,0 +1,63 @@
package test
import (
_ "gateway/message"
_ "gateway/models"
"gateway/service"
"gateway/utils"
"github.com/astaxie/beego/httplib"
"github.com/astaxie/beego/logs"
"github.com/rs/xid"
"net/url"
"testing"
)
import _ "gateway/routers"
/*
** 充值测试
*/
func TestPay(t *testing.T) {
params := make(map[string]string)
params["orderNo"] = xid.New().String()
params["productName"] = "kongyuhebin"
params["orderPeriod"] = "1"
params["orderPrice"] = "100.00"
params["payWayCode"] = "WEIXIN_SCAN"
params["osType"] = "1"
params["notifyUrl"] = "http://localhost:12309/shop/notify"
params["payKey"] = "kkkkc254gk8isf001cqrj6p0"
keys := utils.SortMap(params)
params["sign"] = utils.GetMD5Sign(params, keys, "ssssc254gk8isf001cqrj6pg")
u := url.Values{}
for k, v := range params {
u.Add(k, v)
}
l := "http://localhost:12309/gateway/scan?" + u.Encode()
logs.Info("请求url" + l)
resp := httplib.Get(l)
s, err := resp.String()
if err != nil {
logs.Error("请求错误:" + err.Error())
}
logs.Info("微信扫码返回结果:" + s)
}
/**
** 充值失败回调
*/
func TestPayFail(t *testing.T) {
service.SolvePayFail("6666c50bd567matj5v6g30dg", "")
}
/**
** 充值成功
*/
func TestPaySuccess(t *testing.T) {
service.SolvePaySuccess("6666c50mhcu7matjtv0a4330", 0, "")
}

47
gateway/utils/bank.go Normal file

File diff suppressed because one or more lines are too long

View File

@ -38,3 +38,7 @@ func GetDateBeforeDays(days int) string {
func GetDateTimeBeforeDays(days int) string { func GetDateTimeBeforeDays(days int) string {
return time.Now().Add(-time.Hour * time.Duration(days) * 24).Format("2006-01-02 15:04:05") return time.Now().Add(-time.Hour * time.Duration(days) * 24).Format("2006-01-02 15:04:05")
} }
func GetDateAfterDays(days int) string {
return time.Now().Add(time.Hour * time.Duration(days) * 24).Format("2006-01-02")
}

View File

@ -30,3 +30,18 @@ func GetMD5LOWER(s string) string {
func GetMD5Upper(s string) string { func GetMD5Upper(s string) string {
return strings.ToUpper(GetMD5LOWER(s)) return strings.ToUpper(GetMD5LOWER(s))
} }
/**
** 将map数据变成key=value形式的字符串
*/
func MapToString(m map[string]string) string {
res := ""
for k, v := range m {
res = res + k + "=" + v + "&"
}
suffix := strings.TrimSuffix(res, "&")
return suffix
}

View File

@ -24,3 +24,16 @@ func SortMap(m map[string]string) []string {
sort.Strings(arr) sort.Strings(arr)
return arr return arr
} }
/**
** 按照key的ascii值从小到大给map排序
*/
func SortMapByKeys(m map[string]string) map[string]string {
keys := SortMap(m)
tmp := make(map[string]string)
for _, key := range keys {
tmp[key] = m[key]
}
return tmp
}