提交新项目

This commit is contained in:
kongyuebin
2019-12-19 14:47:58 +08:00
parent 7ba20ac1b9
commit f29066a984
609 changed files with 238892 additions and 0 deletions

5
jhmicro/conf/app.conf Normal file
View File

@@ -0,0 +1,5 @@
appname = jhmicro
httpport = 8010
runmode = dev
mysql = dljjj

22
jhmicro/main.go Normal file
View 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()
}

View 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("消息应答失败!")
}
}
}
}
}

View 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

View 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
View 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分钟没有执行了.........")
}
}
}

View 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("消息应答失败!")
}
}
}
}
}

View 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("消息应答失败!")
}
}
}
}
}