mirror of
https://github.com/kongyuebin1/dongfeng-pay.git
synced 2025-10-24 01:58:00 +08:00
提交新项目
This commit is contained in:
5
jhmicro/conf/app.conf
Normal file
5
jhmicro/conf/app.conf
Normal file
@@ -0,0 +1,5 @@
|
||||
appname = jhmicro
|
||||
httpport = 8010
|
||||
runmode = dev
|
||||
|
||||
mysql = dljjj
|
22
jhmicro/main.go
Normal file
22
jhmicro/main.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/astaxie/beego"
|
||||
"github.com/astaxie/beego/logs"
|
||||
"juhe/jhmicro/notify"
|
||||
"juhe/jhmicro/order_settle"
|
||||
"juhe/jhmicro/pay_for"
|
||||
"juhe/jhmicro/query"
|
||||
"juhe/service/service_init"
|
||||
)
|
||||
|
||||
func main() {
|
||||
logs.SetLogger(logs.AdapterFile, `{"level": 7, "color":true, "filename":"jhmicro.log"}`)
|
||||
service_init.InitAll()
|
||||
go notify.CreateOrderNotifyConsumer()
|
||||
go query.CreateSupplierOrderQueryCuConsumer()
|
||||
go pay_for.PayForInit()
|
||||
go query.CreatePayForQueryConsumer()
|
||||
go order_settle.OrderSettleInit()
|
||||
beego.Run()
|
||||
}
|
163
jhmicro/notify/order_notify.go
Normal file
163
jhmicro/notify/order_notify.go
Normal file
@@ -0,0 +1,163 @@
|
||||
/***************************************************
|
||||
** @Desc : This file for ...
|
||||
** @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"
|
||||
"github.com/astaxie/beego/httplib"
|
||||
"github.com/astaxie/beego/logs"
|
||||
"github.com/go-stomp/stomp"
|
||||
"juhe/service/common"
|
||||
"juhe/service/message_queue"
|
||||
"juhe/service/models"
|
||||
"juhe/service/utils"
|
||||
"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 !models.NotifyInfoExistByBankOrderId(bankOrderId) {
|
||||
logs.Error("该订单不存在回调内容,bankOrderId=", bankOrderId)
|
||||
return
|
||||
}
|
||||
|
||||
notifyInfo := models.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 {
|
||||
if strings.Contains(strings.ToLower(response), "success") {
|
||||
notifyInfo.Status = "success"
|
||||
if models.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)
|
||||
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}
|
||||
logs.Info(fmt.Sprintf("订单bankOrderId=%s,已经是第:%d,回调", bankOrderId, notifyInfo.Times))
|
||||
go OrderNotifyTimer(task)
|
||||
if !models.UpdateNotifyInfo(notifyInfo) {
|
||||
logs.Error("订单回调失败,数据库更新失败:", bankOrderId)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func GetOrderNotifyMinute(times int) int {
|
||||
cur := 1
|
||||
switch times {
|
||||
case 0:
|
||||
cur = 1
|
||||
case 2:
|
||||
cur = 2
|
||||
case 3:
|
||||
cur = 5
|
||||
case 4:
|
||||
cur = 15
|
||||
case 5:
|
||||
cur = 30
|
||||
}
|
||||
return cur
|
||||
}
|
||||
|
||||
func OrderNotifyTimer(task OrderNotifyTask) {
|
||||
for {
|
||||
select {
|
||||
case <-task.Delay.C:
|
||||
SendOrderNotify(task.BankOrderId)
|
||||
task.Delay.Stop()
|
||||
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(1)
|
||||
notifyList := models.GetNotifyInfosNotSuccess(params)
|
||||
for _, notify := range notifyList {
|
||||
minute := GetOrderNotifyMinute(notify.Times)
|
||||
task := OrderNotifyTask{Delay: time.NewTimer(time.Duration(minute) * time.Minute),
|
||||
MerchantOrderId: notify.MerchantOrderId, BankOrderId: notify.BankOrderId, FirstNotifyTime: notify.CreateTime,
|
||||
NotifyTimes: notify.Times, LimitTimes: LimitTimes, Status: notify.Status}
|
||||
go OrderNotifyTimer(task)
|
||||
}
|
||||
}
|
||||
|
||||
//创建订单回调消费者
|
||||
func CreateOrderNotifyConsumer() {
|
||||
CreateOrderDelayQueue()
|
||||
//启动定时任务
|
||||
conn := message_queue.GetActiveMQConn()
|
||||
if conn == nil {
|
||||
logs.Error("启动消息队列消费者失败....")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
logs.Notice("订单回调消息队列启动成功......")
|
||||
orderNotify, err := conn.Subscribe(common.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("消息应答失败!")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
10
jhmicro/notify/payfor_notify.go
Normal file
10
jhmicro/notify/payfor_notify.go
Normal file
@@ -0,0 +1,10 @@
|
||||
/***************************************************
|
||||
** @Desc : This file for ...
|
||||
** @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
|
41
jhmicro/order_settle/settle.go
Normal file
41
jhmicro/order_settle/settle.go
Normal file
@@ -0,0 +1,41 @@
|
||||
/***************************************************
|
||||
** @Desc : 将待结算的订单金额,加入账户可用金额中
|
||||
** @Time : 2019/11/21 23:43
|
||||
** @Author : yuebin
|
||||
** @File : settle
|
||||
** @Last Modified by : yuebin
|
||||
** @Last Modified time: 2019/11/21 23:43
|
||||
** @Software: GoLand
|
||||
****************************************************/
|
||||
package order_settle
|
||||
|
||||
import (
|
||||
"github.com/astaxie/beego/logs"
|
||||
"juhe/service/controller"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
SettleInterval = 5 //隔多少分钟进行结算
|
||||
OneMinute = 15 //每隔15分钟,进行扫码,看有没有隔天押款金额
|
||||
)
|
||||
|
||||
func OrderSettleInit() {
|
||||
//每隔5分钟,巡查有没有可以进行结算的订单
|
||||
go func() {
|
||||
settleTimer := time.NewTimer(time.Duration(SettleInterval) * time.Minute)
|
||||
oneMinuteTimer := time.NewTimer(time.Duration(OneMinute) * time.Minute)
|
||||
for {
|
||||
select {
|
||||
case <-settleTimer.C:
|
||||
settleTimer = time.NewTimer(time.Duration(SettleInterval) * time.Minute)
|
||||
logs.Info("开始对商户进行支付订单结算>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>")
|
||||
controller.OrderSettle()
|
||||
case <-oneMinuteTimer.C:
|
||||
oneMinuteTimer = time.NewTimer(time.Duration(OneMinute) * time.Minute)
|
||||
logs.Info("开始执行商户的解款操作>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>")
|
||||
controller.MerchantLoadSolve()
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
32
jhmicro/pay_for/payfor.go
Normal file
32
jhmicro/pay_for/payfor.go
Normal file
@@ -0,0 +1,32 @@
|
||||
/***************************************************
|
||||
** @Desc : 处理代付问题
|
||||
** @Time : 2019/11/29 14:07
|
||||
** @Author : yuebin
|
||||
** @File : payfor
|
||||
** @Last Modified by : yuebin
|
||||
** @Last Modified time: 2019/11/29 14:07
|
||||
** @Software: GoLand
|
||||
****************************************************/
|
||||
package pay_for
|
||||
|
||||
import (
|
||||
"github.com/astaxie/beego/logs"
|
||||
"juhe/service/common"
|
||||
"juhe/service/controller"
|
||||
"time"
|
||||
)
|
||||
|
||||
func PayForInit() {
|
||||
payForIntervalTimer := time.NewTimer(time.Duration(common.PAYFOR_INTERVAL * time.Second))
|
||||
for {
|
||||
select {
|
||||
case <-payForIntervalTimer.C:
|
||||
logs.Info("代付小程序开始执行任务......")
|
||||
payForIntervalTimer = time.NewTimer(time.Duration(common.PAYFOR_INTERVAL * time.Minute))
|
||||
controller.SolvePayForConfirm()
|
||||
controller.SolvePayFor()
|
||||
case <-time.After(time.Duration(10 * time.Minute)):
|
||||
logs.Notice("代付小程序已经10分钟没有执行了.........")
|
||||
}
|
||||
}
|
||||
}
|
109
jhmicro/query/order_query.go
Normal file
109
jhmicro/query/order_query.go
Normal file
@@ -0,0 +1,109 @@
|
||||
/***************************************************
|
||||
** @Desc : This file for ...
|
||||
** @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"
|
||||
"github.com/astaxie/beego/logs"
|
||||
"github.com/go-stomp/stomp"
|
||||
"juhe/service/common"
|
||||
"juhe/service/controller"
|
||||
"juhe/service/message_queue"
|
||||
"juhe/service/models"
|
||||
"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 := models.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 := controller.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_queue.GetActiveMQConn()
|
||||
if conn == nil {
|
||||
logs.Error("supplier order query consumer fail")
|
||||
os.Exit(1)
|
||||
}
|
||||
logs.Notice("启动订单查询的消费者成功.....")
|
||||
orderQuerySub, _ := conn.Subscribe(common.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("消息应答失败!")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
135
jhmicro/query/pay_for_query.go
Normal file
135
jhmicro/query/pay_for_query.go
Normal file
@@ -0,0 +1,135 @@
|
||||
/***************************************************
|
||||
** @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"
|
||||
"github.com/astaxie/beego/logs"
|
||||
"github.com/go-stomp/stomp"
|
||||
"juhe/service/common"
|
||||
"juhe/service/controller"
|
||||
"juhe/service/message_queue"
|
||||
"juhe/service/models"
|
||||
"juhe/service/utils"
|
||||
"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 := models.GetPayForByBankOrderId(task.BankOrderId)
|
||||
roadInfo := models.GetRoadInfoByRoadUid(payFor.RoadUid)
|
||||
supplier := controller.GetPaySupplierByCode(roadInfo.ProductUid)
|
||||
if supplier == nil {
|
||||
logs.Error("代付查询返回supplier为空")
|
||||
return
|
||||
}
|
||||
res, _ := supplier.PayForQuery(payFor)
|
||||
if res == common.PAYFOR_SUCCESS {
|
||||
//代付成功了
|
||||
controller.PayForSuccess(payFor)
|
||||
} else if res == common.PAYFOR_FAIL {
|
||||
//代付失败
|
||||
controller.PayForFail(payFor)
|
||||
} else if res == common.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 := models.IsExistPayForByBankOrderId(bankOrderId)
|
||||
if !exist {
|
||||
logs.Error(fmt.Sprintf("代付记录不存在,bankOrderId = %s", bankOrderId))
|
||||
return
|
||||
}
|
||||
|
||||
payFor := models.GetPayForByBankOrderId(bankOrderId)
|
||||
|
||||
if payFor.Status != common.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_queue.GetActiveMQConn()
|
||||
if conn == nil {
|
||||
logs.Error("启动消息队列消费者失败....")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
logs.Notice("代付查询消费启动成功......")
|
||||
|
||||
payForQuery, err := conn.Subscribe(common.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("消息应答失败!")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user