diff --git a/gateway/conf/app.conf b/gateway/conf/app.conf index 27c0850..1d20f9e 100644 --- a/gateway/conf/app.conf +++ b/gateway/conf/app.conf @@ -1,6 +1,6 @@ appname = jhgateway httpport = 12309 -runmode = dev +runmode = pro sessionon = true diff --git a/gateway/conf/config.go b/gateway/conf/config.go index 8e330d3..ea42055 100644 --- a/gateway/conf/config.go +++ b/gateway/conf/config.go @@ -16,3 +16,97 @@ const ( DB_PASSWORD = "Kyb^15273031604" 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: "深圳发展银行", +} diff --git a/gateway/conf/mq_config.go b/gateway/conf/mq_config.go new file mode 100644 index 0000000..89d6da3 --- /dev/null +++ b/gateway/conf/mq_config.go @@ -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) +} diff --git a/gateway/conf/pay_way_code.go b/gateway/conf/pay_way_code.go new file mode 100644 index 0000000..553a5a9 --- /dev/null +++ b/gateway/conf/pay_way_code.go @@ -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 "未知" + } +} diff --git a/gateway/controllers/gateway/base_controller.go b/gateway/controllers/gateway/base_controller.go new file mode 100644 index 0000000..43f0215 --- /dev/null +++ b/gateway/controllers/gateway/base_controller.go @@ -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 +} diff --git a/gateway/controllers/gateway/base_gateway.go b/gateway/controllers/gateway/base_gateway.go deleted file mode 100644 index b3c6f94..0000000 --- a/gateway/controllers/gateway/base_gateway.go +++ /dev/null @@ -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 -} diff --git a/gateway/controllers/gateway/error_gateway.go b/gateway/controllers/gateway/error_controller.go similarity index 81% rename from gateway/controllers/gateway/error_gateway.go rename to gateway/controllers/gateway/error_controller.go index e540609..60e9cd4 100644 --- a/gateway/controllers/gateway/error_gateway.go +++ b/gateway/controllers/gateway/error_controller.go @@ -10,14 +10,14 @@ package gateway import ( - beego "github.com/beego/beego/v2/server/web" + "github.com/beego/beego/v2/server/web" ) type ErrorGatewayController struct { - beego.Controller + web.Controller } func (c *ErrorGatewayController) ErrorParams() { - beego.ReadFromRequest(&c.Controller) + web.ReadFromRequest(&c.Controller) c.TplName = "err/params.html" } diff --git a/gateway/controllers/gateway/payfor_controller.go b/gateway/controllers/gateway/payfor_controller.go new file mode 100644 index 0000000..670765c --- /dev/null +++ b/gateway/controllers/gateway/payfor_controller.go @@ -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, "" +} diff --git a/gateway/controllers/gateway/payfor_gateway.go b/gateway/controllers/gateway/payfor_gateway.go deleted file mode 100644 index 52cd10c..0000000 --- a/gateway/controllers/gateway/payfor_gateway.go +++ /dev/null @@ -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() -} diff --git a/gateway/controllers/gateway/scan_controller.go b/gateway/controllers/gateway/scan_controller.go new file mode 100644 index 0000000..25f7103 --- /dev/null +++ b/gateway/controllers/gateway/scan_controller.go @@ -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) + } +} diff --git a/gateway/controllers/gateway/scan_gateway.go b/gateway/controllers/gateway/scan_gateway.go deleted file mode 100644 index d75b173..0000000 --- a/gateway/controllers/gateway/scan_gateway.go +++ /dev/null @@ -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() - } -} diff --git a/gateway/message/init.go b/gateway/message/init.go new file mode 100644 index 0000000..8711cd9 --- /dev/null +++ b/gateway/message/init.go @@ -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 +} diff --git a/gateway/message/send_message.go b/gateway/message/send_message.go new file mode 100644 index 0000000..244fc44 --- /dev/null +++ b/gateway/message/send_message.go @@ -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) + } +} diff --git a/gateway/models/accounts/account.go b/gateway/models/accounts/account.go new file mode 100644 index 0000000..0351f2d --- /dev/null +++ b/gateway/models/accounts/account.go @@ -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 +} diff --git a/gateway/models/accounts/account_history_info.go b/gateway/models/accounts/account_history_info.go new file mode 100644 index 0000000..864d432 --- /dev/null +++ b/gateway/models/accounts/account_history_info.go @@ -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 +} diff --git a/gateway/models/agent/agent_info.go b/gateway/models/agent/agent_info.go new file mode 100644 index 0000000..d37873b --- /dev/null +++ b/gateway/models/agent/agent_info.go @@ -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 +} diff --git a/gateway/controllers/gateway/supplier_notify.go b/gateway/models/agent/agent_profit.go similarity index 50% rename from gateway/controllers/gateway/supplier_notify.go rename to gateway/models/agent/agent_profit.go index 75c7ae7..f217152 100644 --- a/gateway/controllers/gateway/supplier_notify.go +++ b/gateway/models/agent/agent_profit.go @@ -1,10 +1,13 @@ /*************************************************** - ** @Desc : 接受上游通道商的订单结果异步回调 - ** @Time : 2019/11/22 23:27 + ** @Desc : This file for ... + ** @Time : 2019/12/17 17:50 ** @Author : yuebin - ** @File : supplier_notify + ** @File : agent_profit ** @Last Modified by : yuebin - ** @Last Modified time: 2019/11/22 23:27 + ** @Last Modified time: 2019/12/17 17:50 ** @Software: GoLand ****************************************************/ -package gateway +package agent + +type AgentProfit struct { +} diff --git a/gateway/models/init.go b/gateway/models/init.go index a5372a2..47e0247 100644 --- a/gateway/models/init.go +++ b/gateway/models/init.go @@ -12,6 +12,15 @@ package models import ( "fmt" "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/core/logs" _ "github.com/go-sql-driver/mysql" @@ -30,10 +39,23 @@ func init() { orm.RegisterDriver("mysql", orm.DRMySQL) orm.RegisterDataBase("default", "mysql", link) - orm.RegisterModel(new(UserInfo), new(MenuInfo), new(SecondMenuInfo), - new(PowerInfo), new(RoleInfo), new(BankCardInfo), new(RoadInfo), - new(RoadPoolInfo), new(AgentInfo), new(MerchantInfo), new(MerchantDeployInfo), - new(AccountInfo), new(AccountHistoryInfo), new(OrderInfo), new(OrderProfitInfo), - new(OrderSettleInfo), new(NotifyInfo), new(MerchantLoadInfo), - new(PayforInfo)) + orm.RegisterModel(new(user.UserInfo), + new(system.MenuInfo), + new(system.SecondMenuInfo), + new(system.PowerInfo), + new(system.RoleInfo), + 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)) } diff --git a/gateway/models/merchant/merchant_deploy_info.go b/gateway/models/merchant/merchant_deploy_info.go new file mode 100644 index 0000000..28f2d22 --- /dev/null +++ b/gateway/models/merchant/merchant_deploy_info.go @@ -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 +} diff --git a/gateway/models/merchant/merchant_info.go b/gateway/models/merchant/merchant_info.go new file mode 100644 index 0000000..3cd924d --- /dev/null +++ b/gateway/models/merchant/merchant_info.go @@ -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 +} diff --git a/gateway/models/merchant/merchant_load_info.go b/gateway/models/merchant/merchant_load_info.go new file mode 100644 index 0000000..6da7b41 --- /dev/null +++ b/gateway/models/merchant/merchant_load_info.go @@ -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() +} diff --git a/gateway/models/notify/notify_info.go b/gateway/models/notify/notify_info.go new file mode 100644 index 0000000..7c9a430 --- /dev/null +++ b/gateway/models/notify/notify_info.go @@ -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(¬ifyInfo) + 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(¬ifyInfo) + 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(¬ifyInfoList) + + if err != nil { + logs.Error("get notifyinfos fail: ", err) + } + + return notifyInfoList +} + +func UpdateNotifyInfo(notifyInfo NotifyInfo) bool { + o := orm.NewOrm() + _, err := o.Update(¬ifyInfo) + if err != nil { + logs.Error("update notify info fail: ", err) + return false + } + return true +} diff --git a/gateway/models/order/order_info.go b/gateway/models/order/order_info.go new file mode 100644 index 0000000..5696251 --- /dev/null +++ b/gateway/models/order/order_info.go @@ -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 +} diff --git a/gateway/models/order/order_profit_info.go b/gateway/models/order/order_profit_info.go new file mode 100644 index 0000000..6c8abae --- /dev/null +++ b/gateway/models/order/order_profit_info.go @@ -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 +} +*/ diff --git a/gateway/models/order/order_settle_info.go b/gateway/models/order/order_settle_info.go new file mode 100644 index 0000000..a4bbc1f --- /dev/null +++ b/gateway/models/order/order_settle_info.go @@ -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 +} diff --git a/gateway/models/order/platform_profit.go b/gateway/models/order/platform_profit.go new file mode 100644 index 0000000..08e8e87 --- /dev/null +++ b/gateway/models/order/platform_profit.go @@ -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 +} diff --git a/gateway/models/payfor/payfor_info.go b/gateway/models/payfor/payfor_info.go new file mode 100644 index 0000000..a6a9e22 --- /dev/null +++ b/gateway/models/payfor/payfor_info.go @@ -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 +} diff --git a/gateway/models/road/road_info.go b/gateway/models/road/road_info.go new file mode 100644 index 0000000..73f1700 --- /dev/null +++ b/gateway/models/road/road_info.go @@ -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 +} diff --git a/gateway/models/road/road_pool_info.go b/gateway/models/road/road_pool_info.go new file mode 100644 index 0000000..42e959a --- /dev/null +++ b/gateway/models/road/road_pool_info.go @@ -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 +} diff --git a/gateway/models/system/bank_card_info.go b/gateway/models/system/bank_card_info.go new file mode 100644 index 0000000..bfa0e82 --- /dev/null +++ b/gateway/models/system/bank_card_info.go @@ -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 +} diff --git a/gateway/models/system/menu_info.go b/gateway/models/system/menu_info.go new file mode 100644 index 0000000..395e7a3 --- /dev/null +++ b/gateway/models/system/menu_info.go @@ -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) +} diff --git a/gateway/models/system/power_info.go b/gateway/models/system/power_info.go new file mode 100644 index 0000000..1dbb63e --- /dev/null +++ b/gateway/models/system/power_info.go @@ -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 +} diff --git a/gateway/models/system/role_info.go b/gateway/models/system/role_info.go new file mode 100644 index 0000000..84a6a41 --- /dev/null +++ b/gateway/models/system/role_info.go @@ -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 +} diff --git a/gateway/models/system/second_menu_info.go b/gateway/models/system/second_menu_info.go new file mode 100644 index 0000000..da9a070 --- /dev/null +++ b/gateway/models/system/second_menu_info.go @@ -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 +} diff --git a/gateway/models/user/user_info.go b/gateway/models/user/user_info.go new file mode 100644 index 0000000..70d3f2c --- /dev/null +++ b/gateway/models/user/user_info.go @@ -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 +} diff --git a/gateway/notify/order_notify.go b/gateway/notify/order_notify.go new file mode 100644 index 0000000..6b255d2 --- /dev/null +++ b/gateway/notify/order_notify.go @@ -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("消息应答失败!") + } + } + } + } +} diff --git a/gateway/notify/payfor_notify.go b/gateway/notify/payfor_notify.go new file mode 100644 index 0000000..4ad7dc2 --- /dev/null +++ b/gateway/notify/payfor_notify.go @@ -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 diff --git a/gateway/pay_for/payfor_service.go b/gateway/pay_for/payfor_service.go new file mode 100644 index 0000000..2b9a5de --- /dev/null +++ b/gateway/pay_for/payfor_service.go @@ -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, "" +} diff --git a/gateway/pay_for/payfor_solve.go b/gateway/pay_for/payfor_solve.go new file mode 100644 index 0000000..0f1460e --- /dev/null +++ b/gateway/pay_for/payfor_solve.go @@ -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 +} diff --git a/gateway/controllers/gateway/merchant_query.go b/gateway/query/merchant_query.go similarity index 86% rename from gateway/controllers/gateway/merchant_query.go rename to gateway/query/merchant_query.go index b2b985b..6f36171 100644 --- a/gateway/controllers/gateway/merchant_query.go +++ b/gateway/query/merchant_query.go @@ -7,20 +7,21 @@ ** @Last Modified time: 2019/11/6 13:59 ** @Software: GoLand ****************************************************/ -package gateway +package query import ( "encoding/json" "fmt" - "gateway/models" + "gateway/models/merchant" + "gateway/models/order" "gateway/utils" "github.com/beego/beego/v2/core/logs" - beego "github.com/beego/beego/v2/server/web" + "github.com/beego/beego/v2/server/web" "strings" ) -type QueryController struct { - beego.Controller +type MerchantQueryController struct { + web.Controller } type OrderQueryFailData struct { @@ -32,7 +33,7 @@ type OrderQueryFailData struct { /* ** 改接口是为下游商户提供订单查询 */ -func (c *QueryController) OrderQuery() { +func (c *MerchantQueryController) OrderQuery() { orderNo := strings.TrimSpace(c.GetString("orderNo")) payKey := strings.TrimSpace(c.GetString("payKey")) sign := strings.TrimSpace(c.GetString("sign")) @@ -44,11 +45,11 @@ func (c *QueryController) OrderQuery() { failData.StatusCode = "01" failData.PayKey = payKey - merchantInfo := models.GetMerchantByPaykey(payKey) + merchantInfo := merchant.GetMerchantByPaykey(payKey) if merchantInfo.MerchantUid == "" || len(merchantInfo.MerchantUid) == 0 { failData.Msg = "商户不存在,请核对payKey字段" } - orderInfo := models.GetOrderByMerchantOrderId(orderNo) + orderInfo := order.GetOrderByMerchantOrderId(orderNo) if orderInfo.BankOrderId == "" || len(orderInfo.BankOrderId) == 0 { failData.Msg = "不存在这样的订单,请核对orderNo字段" } @@ -60,7 +61,7 @@ func (c *QueryController) OrderQuery() { } if failData.Msg != "" { c.Data["json"] = failData - c.ServeJSON() + _ = c.ServeJSON() return } p := make(map[string]string) diff --git a/gateway/query/payfor_query.go b/gateway/query/payfor_query.go new file mode 100644 index 0000000..4c376d4 --- /dev/null +++ b/gateway/query/payfor_query.go @@ -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("消息应答失败!") + } + } + } + } +} diff --git a/gateway/query/supplier_query.go b/gateway/query/supplier_query.go new file mode 100644 index 0000000..07f731b --- /dev/null +++ b/gateway/query/supplier_query.go @@ -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("消息应答失败!") + } + } + } + } +} diff --git a/gateway/response/pay_resp.go b/gateway/response/pay_resp.go new file mode 100644 index 0000000..725a95d --- /dev/null +++ b/gateway/response/pay_resp.go @@ -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"` +} diff --git a/gateway/response/payfor_resp.go b/gateway/response/payfor_resp.go new file mode 100644 index 0000000..4835e70 --- /dev/null +++ b/gateway/response/payfor_resp.go @@ -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"` +} diff --git a/gateway/service/base_service.go b/gateway/service/base_service.go new file mode 100644 index 0000000..59ad07d --- /dev/null +++ b/gateway/service/base_service.go @@ -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 +} diff --git a/gateway/service/pay_service.go b/gateway/service/pay_service.go new file mode 100644 index 0000000..e10e283 --- /dev/null +++ b/gateway/service/pay_service.go @@ -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 +} diff --git a/gateway/service/pay_solve.go b/gateway/service/pay_solve.go new file mode 100644 index 0000000..0c795ce --- /dev/null +++ b/gateway/service/pay_solve.go @@ -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 success,insert 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 success,insert 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) +} diff --git a/gateway/service/settle_service.go b/gateway/service/settle_service.go new file mode 100644 index 0000000..8843e11 --- /dev/null +++ b/gateway/service/settle_service.go @@ -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() + } + } + }() +} diff --git a/gateway/supplier/supplier_interface.go b/gateway/supplier/supplier_interface.go index 13ebfcc..5c29a91 100644 --- a/gateway/supplier/supplier_interface.go +++ b/gateway/supplier/supplier_interface.go @@ -7,10 +7,13 @@ ** @Last Modified time: 2019/10/28 9:39 ** @Software: GoLand ****************************************************/ -package controller +package supplier 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 { - Scan(models.OrderInfo, models.RoadInfo, models.MerchantInfo) ScanData - H5(models.OrderInfo, models.RoadInfo, models.MerchantInfo) ScanData - Fast(models.OrderInfo, models.RoadInfo, models.MerchantInfo) bool - Syt(models.OrderInfo, models.RoadInfo, models.MerchantInfo) ScanData - Web(models.OrderInfo, models.RoadInfo, models.MerchantInfo) bool + Scan(order.OrderInfo, road.RoadInfo, merchant.MerchantInfo) ScanData + H5(order.OrderInfo, road.RoadInfo, merchant.MerchantInfo) ScanData + Fast(order.OrderInfo, road.RoadInfo, merchant.MerchantInfo) bool + Syt(order.OrderInfo, road.RoadInfo, merchant.MerchantInfo) ScanData + Web(order.OrderInfo, road.RoadInfo, merchant.MerchantInfo) bool PayNotify() - PayQuery(models.OrderInfo) bool - PayFor(models.PayforInfo) string + PayQuery(order.OrderInfo) bool + PayFor(payfor.PayforInfo) string PayForNotify() string - PayForQuery(models.PayforInfo) (string, string) - BalanceQuery(models.RoadInfo) float64 + PayForQuery(payfor.PayforInfo) (string, string) + BalanceQuery(road.RoadInfo) float64 } diff --git a/gateway/supplier/third_party/daili.go b/gateway/supplier/third_party/daili.go new file mode 100644 index 0000000..be3a6d9 --- /dev/null +++ b/gateway/supplier/third_party/daili.go @@ -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 +} diff --git a/gateway/supplier/third_party/init.go b/gateway/supplier/third_party/init.go new file mode 100644 index 0000000..7d6d6bb --- /dev/null +++ b/gateway/supplier/third_party/init.go @@ -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 "未找到上游名称,注册有问题。" +} diff --git a/gateway/supplier/third_party/kuaifu.go b/gateway/supplier/third_party/kuaifu.go new file mode 100644 index 0000000..b8e5cf8 --- /dev/null +++ b/gateway/supplier/third_party/kuaifu.go @@ -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 +} diff --git a/gateway/tests/pay_for_test.go b/gateway/tests/pay_for_test.go new file mode 100644 index 0000000..364bad4 --- /dev/null +++ b/gateway/tests/pay_for_test.go @@ -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) +} diff --git a/gateway/tests/pay_test.go b/gateway/tests/pay_test.go new file mode 100644 index 0000000..2f6b4aa --- /dev/null +++ b/gateway/tests/pay_test.go @@ -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, "") +} diff --git a/gateway/utils/bank.go b/gateway/utils/bank.go new file mode 100644 index 0000000..1b72c9c --- /dev/null +++ b/gateway/utils/bank.go @@ -0,0 +1,47 @@ +package utils + +import ( + "github.com/astaxie/beego/httplib" + "github.com/astaxie/beego/logs" + "github.com/widuu/gojson" +) + +const bankUrl = "https://ccdcapi.alipay.com/validateAndCacheCardInfo.json?_input_charset=utf-8&cardBinCheck=true&cardNo=" +const CodeToName = "{\n \"SRCB\": \"深圳农村商业银行\", \n \"BGB\": \"广西北部湾银行\", \n \"SHRCB\": \"上海农村商业银行\", \n \"BJBANK\": \"北京银行\", \n \"WHCCB\": \"威海市商业银行\", \n \"BOZK\": \"周口银行\", \n \"KORLABANK\": \"库尔勒市商业银行\", \n \"SPABANK\": \"平安银行\", \n \"SDEB\": \"顺德农商银行\", \n \"HURCB\": \"湖北省农村信用社\", \n \"WRCB\": \"无锡农村商业银行\", \n \"BOCY\": \"朝阳银行\", \n \"CZBANK\": \"浙商银行\", \n \"HDBANK\": \"邯郸银行\", \n \"BOC\": \"中国银行\", \n \"BOD\": \"东莞银行\", \n \"CCB\": \"中国建设银行\", \n \"ZYCBANK\": \"遵义市商业银行\", \n \"SXCB\": \"绍兴银行\", \n \"GZRCU\": \"贵州省农村信用社\", \n \"ZJKCCB\": \"张家口市商业银行\", \n \"BOJZ\": \"锦州银行\", \n \"BOP\": \"平顶山银行\", \n \"HKB\": \"汉口银行\", \n \"SPDB\": \"上海浦东发展银行\", \n \"NXRCU\": \"宁夏黄河农村商业银行\", \n \"NYNB\": \"广东南粤银行\", \n \"GRCB\": \"广州农商银行\", \n \"BOSZ\": \"苏州银行\", \n \"HZCB\": \"杭州银行\", \n \"HSBK\": \"衡水银行\", \n \"HBC\": \"湖北银行\", \n \"JXBANK\": \"嘉兴银行\", \n \"HRXJB\": \"华融湘江银行\", \n \"BODD\": \"丹东银行\", \n \"AYCB\": \"安阳银行\", \n \"EGBANK\": \"恒丰银行\", \n \"CDB\": \"国家开发银行\", \n \"TCRCB\": \"江苏太仓农村商业银行\", \n \"NJCB\": \"南京银行\", \n \"ZZBANK\": \"郑州银行\", \n \"DYCB\": \"德阳商业银行\", \n \"YBCCB\": \"宜宾市商业银行\", \n \"SCRCU\": \"四川省农村信用\", \n \"KLB\": \"昆仑银行\", \n \"LSBANK\": \"莱商银行\", \n \"YDRCB\": \"尧都农商行\", \n \"CCQTGB\": \"重庆三峡银行\", \n \"FDB\": \"富滇银行\", \n \"JSRCU\": \"江苏省农村信用联合社\", \n \"JNBANK\": \"济宁银行\", \n \"CMB\": \"招商银行\", \n \"JINCHB\": \"晋城银行JCBANK\", \n \"FXCB\": \"阜新银行\", \n \"WHRCB\": \"武汉农村商业银行\", \n \"HBYCBANK\": \"湖北银行宜昌分行\", \n \"TZCB\": \"台州银行\", \n \"TACCB\": \"泰安市商业银行\", \n \"XCYH\": \"许昌银行\", \n \"CEB\": \"中国光大银行\", \n \"NXBANK\": \"宁夏银行\", \n \"HSBANK\": \"徽商银行\", \n \"JJBANK\": \"九江银行\", \n \"NHQS\": \"农信银清算中心\", \n \"MTBANK\": \"浙江民泰商业银行\", \n \"LANGFB\": \"廊坊银行\", \n \"ASCB\": \"鞍山银行\", \n \"KSRB\": \"昆山农村商业银行\", \n \"YXCCB\": \"玉溪市商业银行\", \n \"DLB\": \"大连银行\", \n \"DRCBCL\": \"东莞农村商业银行\", \n \"GCB\": \"广州银行\", \n \"NBBANK\": \"宁波银行\", \n \"BOYK\": \"营口银行\", \n \"SXRCCU\": \"陕西信合\", \n \"GLBANK\": \"桂林银行\", \n \"BOQH\": \"青海银行\", \n \"CDRCB\": \"成都农商银行\", \n \"QDCCB\": \"青岛银行\", \n \"HKBEA\": \"东亚银行\", \n \"HBHSBANK\": \"湖北银行黄石分行\", \n \"WZCB\": \"温州银行\", \n \"TRCB\": \"天津农商银行\", \n \"QLBANK\": \"齐鲁银行\", \n \"GDRCC\": \"广东省农村信用社联合社\", \n \"ZJTLCB\": \"浙江泰隆商业银行\", \n \"GZB\": \"赣州银行\", \n \"GYCB\": \"贵阳市商业银行\", \n \"CQBANK\": \"重庆银行\", \n \"DAQINGB\": \"龙江银行\", \n \"CGNB\": \"南充市商业银行\", \n \"SCCB\": \"三门峡银行\", \n \"CSRCB\": \"常熟农村商业银行\", \n \"SHBANK\": \"上海银行\", \n \"JLBANK\": \"吉林银行\", \n \"CZRCB\": \"常州农村信用联社\", \n \"BANKWF\": \"潍坊银行\", \n \"ZRCBANK\": \"张家港农村商业银行\", \n \"FJHXBC\": \"福建海峡银行\", \n \"ZJNX\": \"浙江省农村信用社联合社\", \n \"LZYH\": \"兰州银行\", \n \"JSB\": \"晋商银行\", \n \"BOHAIB\": \"渤海银行\", \n \"CZCB\": \"浙江稠州商业银行\", \n \"YQCCB\": \"阳泉银行\", \n \"SJBANK\": \"盛京银行\", \n \"XABANK\": \"西安银行\", \n \"BSB\": \"包商银行\", \n \"JSBANK\": \"江苏银行\", \n \"FSCB\": \"抚顺银行\", \n \"HNRCU\": \"河南省农村信用\", \n \"COMM\": \"交通银行\", \n \"XTB\": \"邢台银行\", \n \"CITIC\": \"中信银行\", \n \"HXBANK\": \"华夏银行\", \n \"HNRCC\": \"湖南省农村信用社\", \n \"DYCCB\": \"东营市商业银行\", \n \"ORBANK\": \"鄂尔多斯银行\", \n \"BJRCB\": \"北京农村商业银行\", \n \"XYBANK\": \"信阳银行\", \n \"ZGCCB\": \"自贡市商业银行\", \n \"CDCB\": \"成都银行\", \n \"HANABANK\": \"韩亚银行\", \n \"CMBC\": \"中国民生银行\", \n \"LYBANK\": \"洛阳银行\", \n \"GDB\": \"广东发展银行\", \n \"ZBCB\": \"齐商银行\", \n \"CBKF\": \"开封市商业银行\", \n \"H3CB\": \"内蒙古银行\", \n \"CIB\": \"兴业银行\", \n \"CRCBANK\": \"重庆农村商业银行\", \n \"SZSBK\": \"石嘴山银行\", \n \"DZBANK\": \"德州银行\", \n \"SRBANK\": \"上饶银行\", \n \"LSCCB\": \"乐山市商业银行\", \n \"JXRCU\": \"江西省农村信用\", \n \"ICBC\": \"中国工商银行\", \n \"JZBANK\": \"晋中市商业银行\", \n \"HZCCB\": \"湖州市商业银行\", \n \"NHB\": \"南海农村信用联社\", \n \"XXBANK\": \"新乡银行\", \n \"JRCB\": \"江苏江阴农村商业银行\", \n \"YNRCC\": \"云南省农村信用社\", \n \"ABC\": \"中国农业银行\", \n \"GXRCU\": \"广西省农村信用\", \n \"PSBC\": \"中国邮政储蓄银行\", \n \"BZMD\": \"驻马店银行\", \n \"ARCU\": \"安徽省农村信用社\", \n \"GSRCU\": \"甘肃省农村信用\", \n \"LYCB\": \"辽阳市商业银行\", \n \"JLRCU\": \"吉林农信\", \n \"URMQCCB\": \"乌鲁木齐市商业银行\", \n \"XLBANK\": \"中山小榄村镇银行\", \n \"CSCB\": \"长沙银行\", \n \"JHBANK\": \"金华银行\", \n \"BHB\": \"河北银行\", \n \"NBYZ\": \"鄞州银行\", \n \"LSBC\": \"临商银行\", \n \"BOCD\": \"承德银行\", \n \"SDRCU\": \"山东农信\", \n \"NCB\": \"南昌银行\", \n \"TCCB\": \"天津银行\", \n \"WJRCB\": \"吴江农商银行\", \n \"CBBQS\": \"城市商业银行资金清算中心\", \n \"HBRCU\": \"河北省农村信用社\"\n}" + +/** +** 根据银行卡号获取银行信息 + */ +func GetBankCodeByBankCardNo(bankCardNo string) string { + bUrl := bankUrl + bankCardNo + request := httplib.Get(bUrl) + s, err := request.String() + if err != nil { + logs.Error("获取银行信息失败:" + err.Error()) + return "" + } + + logs.Info("获取到银行信息为:" + s) + code := gojson.Json(s).Get("bank").Tostring() + return code + +} + +/** +** 根据银行卡号获取银行名称 + */ +func GetBankNameByCardNo(cardNo string) string { + code := GetBankCodeByBankCardNo(cardNo) + if code == "" { + return code + } + + return GetBankNameByCode(code) +} + +/** +** 根据银行编码获取银行名称 + */ +func GetBankNameByCode(code string) string { + return gojson.Json(CodeToName).Get(code).Tostring() +} diff --git a/gateway/utils/date_time.go b/gateway/utils/date_time.go index 919b998..0ff64d6 100644 --- a/gateway/utils/date_time.go +++ b/gateway/utils/date_time.go @@ -38,3 +38,7 @@ func GetDateBeforeDays(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") } + +func GetDateAfterDays(days int) string { + return time.Now().Add(time.Hour * time.Duration(days) * 24).Format("2006-01-02") +} diff --git a/gateway/utils/md5.go b/gateway/utils/md5.go index 3532a3a..76f629d 100644 --- a/gateway/utils/md5.go +++ b/gateway/utils/md5.go @@ -30,3 +30,18 @@ func GetMD5LOWER(s string) string { func GetMD5Upper(s string) string { 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 +} diff --git a/gateway/utils/sort_go.go b/gateway/utils/sort_go.go index a6989ef..05c5776 100644 --- a/gateway/utils/sort_go.go +++ b/gateway/utils/sort_go.go @@ -24,3 +24,16 @@ func SortMap(m map[string]string) []string { sort.Strings(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 +}