You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
208 lines
5.4 KiB
208 lines
5.4 KiB
package pay_service
|
|
|
|
import (
|
|
"go.uber.org/zap"
|
|
"hudongzhuanjia/logger"
|
|
"hudongzhuanjia/models"
|
|
"hudongzhuanjia/utils/define"
|
|
"math"
|
|
"time"
|
|
)
|
|
|
|
var orderDelayQueue = make(chan *models.UserOrder, math.MaxInt8)
|
|
|
|
func PutOrderDelayQueue(order *models.UserOrder) {
|
|
orderDelayQueue <- order
|
|
}
|
|
|
|
func loopOrder() {
|
|
orders, err := models.GetUserOrdersByStatus(0, 3)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
for _, order := range orders {
|
|
PutOrderDelayQueue(order)
|
|
}
|
|
|
|
defer func() {
|
|
if err := recover(); err != nil {
|
|
logger.Error("订单轮询查询: panic 恢复错误", err)
|
|
}
|
|
// 重启
|
|
time.Sleep(5 * time.Second)
|
|
loopOrder()
|
|
}()
|
|
for {
|
|
select {
|
|
case order, ok := <-orderDelayQueue:
|
|
if !ok {
|
|
panic("通道异常关闭")
|
|
}
|
|
if order.ExpireAt <= time.Now().Unix() { // 订单超时
|
|
if order.Status == 0 {
|
|
go HandleTimeout(order)
|
|
}
|
|
continue
|
|
}
|
|
|
|
if order.Status == 0 {
|
|
res, err := OrderQuery(order.OutTradeNo)
|
|
if err != nil {
|
|
logger.Error("查询订单出现错误: 错误原因-->", err.Error(), "交易订单号-->", order.OutTradeNo)
|
|
orderDelayQueue <- order // 重新进入队列
|
|
continue
|
|
}
|
|
|
|
if res["trade_state"] == define.CODE_TRADE_SUCCESS {
|
|
go HandleSuccess(order)
|
|
} else if res["trade_state"] == define.CODE_TRADE_REFUND {
|
|
order.Status = 3
|
|
orderDelayQueue <- order
|
|
continue
|
|
} else {
|
|
orderDelayQueue <- order
|
|
continue
|
|
}
|
|
} else if order.Status == 3 {
|
|
res, err := QueryRefund(order.OutTradeNo)
|
|
if err != nil {
|
|
logger.Error("退款订单查询错误: 错误原因-->", err.Error(), "交易订单号-->", order.OutTradeNo)
|
|
continue
|
|
}
|
|
order.RefundAccount = res.RefundList[0].RefundAccount
|
|
order.RefundRecvAccount = res.RefundList[0].RefundRecvAccout
|
|
order.Status = 4
|
|
_, err = models.Update(order.Id, order, "refund_account", "refund_recv_account", "status")
|
|
if err != nil {
|
|
logger.Error("退款状态改变错误: 错误原因-->", err, "交易订单号-->", order.OutTradeNo)
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func HandleTimeout(order *models.UserOrder) error {
|
|
// 退还库存
|
|
if order.GoodType == 4 {
|
|
err := HandleCancelOrder(order.OutTradeNo)
|
|
if err != nil {
|
|
logger.Error(err)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func init() {
|
|
//go loopTransfer()
|
|
}
|
|
|
|
var transferDelayQueue = make(chan *transferDelayQueueParam, math.MaxInt8)
|
|
|
|
type transferDelayQueueParam struct {
|
|
first bool // 首次跳过
|
|
Retries int `json:"retries"` // 尝试次数
|
|
Delay int `json:"delay"` // 延迟时间, 单位second
|
|
Amount int `json:"amount"` // 转账金额
|
|
Desc string `json:"desc"` // 转账描述
|
|
OpenId string `json:"open_id"` // 被转账人
|
|
PartnerTradeNo string `json:"partner_trade_no"` // 转账账单单号
|
|
}
|
|
|
|
func loopTransfer() {
|
|
//初始化
|
|
transfers, err := models.GetUserTransferByStatus(0, 1, 3)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
transferDelayQueue = make(chan *transferDelayQueueParam, math.MaxInt8)
|
|
for _, transfer := range transfers {
|
|
transferDelayQueue <- &transferDelayQueueParam{
|
|
first: true,
|
|
Retries: 5,
|
|
Delay: 2 * 60,
|
|
Amount: transfer.PaymentAmount,
|
|
Desc: transfer.Desc,
|
|
OpenId: transfer.OpenId,
|
|
PartnerTradeNo: transfer.PartnerTradeNo,
|
|
}
|
|
}
|
|
|
|
defer func() {
|
|
if errRec := recover(); errRec != nil {
|
|
logger.Error("转账轮询 loop transfer panic", zap.Any("错误原因", errRec))
|
|
}
|
|
loopTransfer()
|
|
}()
|
|
for {
|
|
select {
|
|
case param, ok := <-transferDelayQueue:
|
|
if !ok {
|
|
panic("转账延迟通道异常关闭")
|
|
}
|
|
|
|
// 尝试次数
|
|
if param.Retries <= 0 {
|
|
logger.Info("微信转账尝试3次失败", zap.String("转账账单单号", param.PartnerTradeNo))
|
|
userTransfer := new(models.UserTransfer)
|
|
userTransfer.Status = 4
|
|
_, err = userTransfer.UpdateByPartnerTradeNo(param.PartnerTradeNo)
|
|
if err != nil {
|
|
logger.Info("微信转账更新状态失败", zap.String("失败原因", err.Error()),
|
|
zap.String("转账账单单号", param.PartnerTradeNo))
|
|
}
|
|
continue
|
|
} else {
|
|
param.Retries--
|
|
}
|
|
|
|
if !param.first {
|
|
time.Sleep(time.Duration(param.Delay) * time.Second)
|
|
}
|
|
param.first = false
|
|
res, err := TransferInfo(param.PartnerTradeNo)
|
|
if err != nil {
|
|
logger.Error("微信转账查询出现的错误", zap.String("错误原因", err.Error()),
|
|
zap.String("转账账单", param.PartnerTradeNo))
|
|
transferDelayQueue <- param
|
|
continue
|
|
}
|
|
|
|
if res.Status == define.CODE_SUCCESS {
|
|
continue
|
|
} else if res.Status == define.CODE_TRANSFER_PROCESSING {
|
|
transferDelayQueue <- param
|
|
continue
|
|
} else {
|
|
//失败 --> 重新转账
|
|
_, err = Transfer(param.Desc, param.OpenId, param.PartnerTradeNo, param.Amount)
|
|
if err != nil {
|
|
logger.Error("微信转账出现的错误", zap.String("错误原因", err.Error()),
|
|
zap.String("转账账单", param.PartnerTradeNo))
|
|
}
|
|
transferDelayQueue <- param // 重新确认
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func PutTransferDelayQueue(desc, openId, partnerTradeNo string, amount, retries, delay int) {
|
|
if retries <= 0 {
|
|
retries = 3
|
|
}
|
|
if delay == 0 {
|
|
delay = 30
|
|
}
|
|
transferDelayQueue <- &transferDelayQueueParam{
|
|
first: true,
|
|
Retries: retries,
|
|
Delay: delay,
|
|
Amount: amount,
|
|
Desc: desc,
|
|
OpenId: openId,
|
|
PartnerTradeNo: partnerTradeNo,
|
|
}
|
|
}
|