互动
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

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,
}
}