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

314 lines
8.8 KiB

package pay_service
import (
"errors"
"fmt"
"github.com/xormplus/xorm"
"hudongzhuanjia/logger"
"hudongzhuanjia/models"
im_service "hudongzhuanjia/services/im"
"hudongzhuanjia/utils"
"hudongzhuanjia/utils/define"
"math"
"time"
)
func init() {
go loopOrder()
go utils.HandleTicker(1*time.Hour, HandleReward) // 打赏24小时退款
}
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 HandleSuccess(order *models.UserOrder) error {
if order.GoodType == 4 { // 直播商品
customerOrder := new(models.CustomerOrder)
_, err := customerOrder.UpdateStatusBy(order.OutTradeNo, 0, 1)
if err != nil {
return errors.New("更新状态发送错误")
}
customerOrder.GetByOutTradeNO(order.OutTradeNo)
if customerOrder.Status != 1 {
return errors.New("商品订单状态信息出现异常")
}
subs, err := models.GetCustomerOrderSubsByOrderNos(customerOrder.OrderNo)
if err != nil {
logger.Error("商品子订单查询异常", err)
return err
}
for _, sub := range subs {
err = im_service.SendGroupCustomMessage(customerOrder.BuyerId, order.ActivityId, im_service.NoticeLiveGoodBuy,
map[string]interface{}{
"goods_pic_url": sub["goods_pic_url"],
"goods_num": sub["goods_num"],
"good_name": sub["good_name"],
"good_price": sub["good_price"],
"goods_id": sub["goods_id"],
"timestamp": time.Now().Unix(),
})
if err != nil {
logger.Error("直播商品子订单信息发送异常异常", err)
return err
}
}
activity := new(models.Activity)
exist, err := models.Get(activity, order.ActivityId)
if err != nil || !exist {
return errors.New("互动信息异常")
}
gift := new(models.OrderGift)
exist, err = gift.GetByActivityId(order.ActivityId)
if err != nil {
err = fmt.Errorf("获取订单送礼错误: err-> %v, activity_id-> %v", err, activity.Id)
logger.Error(err)
return err
}
if !exist {
return nil
}
prize := new(models.UserPrize)
prize.UserId = order.UserId
prize.ActivityId = order.ActivityId
prize.RehearsalId = activity.RehearsalId
prize.ActivityName = activity.Name
prize.PrizeName = gift.GiftName
prize.PrizeImg = gift.GiftPicUrl
prize.PrizeType = 4
prize.IsDelete = false
prize.Status = 1
prize.CreatedAt = time.Now()
prize.UpdatedAt = time.Now()
if gift.Num > 0 {
count, err := new(models.CustomerOrder).
Count(activity.Id, activity.RehearsalId, customerOrder.CreatedAt)
if err != nil {
err = fmt.Errorf("订单人数统计失败: err->%v, out_trade_no->%v", err, order.OutTradeNo)
logger.Error(err)
return err
}
if gift.Num <= int(count) { // 人数足够
return nil
}
}
_, err = prize.Add()
if err != nil {
err = fmt.Errorf("奖品添加失败: err->%v, out_trade_no->%v", err, order.OutTradeNo)
logger.Error(err)
return err
}
customerOrder.UserPrizeId = prize.Id
_, err = models.Update(customerOrder.Id, customerOrder, "user_prize_id")
if err != nil {
err = fmt.Errorf("奖品记录添加失败: err-> %v, out_trade_no-> %v, prize_id->%v", err, order.OutTradeNo, prize.Id)
logger.Error(err)
return err
}
} else if order.GoodType == 3 { // 直播红包
info := new(models.LiveRedEnvelopeRule)
_, err := info.UpdateStatusByOutTradeNo(order.OutTradeNo, 1)
if err != nil {
err = fmt.Errorf("状态改变出现错误: err->%v, out_trade_no->%v", err, order.OutTradeNo)
logger.Error(err.Error())
return err
}
exist, err := info.GetByOutTradeNo(order.OutTradeNo)
if err != nil || !exist || info.Status != 1 {
err = fmt.Errorf("直播红包信息异常: err-> %v, exist->%v, status->%v, out_trade_no->%v",
err, exist, info.Status, order.OutTradeNo)
logger.Error(err.Error())
return err
}
err = im_service.SendGroupCustomMessage(info.UserId, order.ActivityId, im_service.NoticeLiveRedPackStart,
map[string]interface{}{
"live_red_envelope_rule_id": info.Id,
"prompt": info.Prompt,
"timestamp": time.Now().Unix(),
})
if err != nil {
err = fmt.Errorf("发送腾讯im信息出现错误: err->%v, info_id->%v, out_trade_no->%v",
err, info.Id, order.OutTradeNo)
logger.Error(err.Error())
return err
}
} else if order.GoodType == 2 { // 打赏
history := new(models.RewardHistory)
exist, err := history.GetByOutTradeNo(order.OutTradeNo)
if err != nil || !exist || history.Status != -1 {
err = fmt.Errorf("打赏历史异常: err->%v, out_trade_no %v", err, order.OutTradeNo)
logger.Error(err.Error())
return err
}
_, err = history.UpdateStatus(history.Id, 0)
if err != nil {
err = fmt.Errorf("打赏状态发送变化: err->%v, out_trade_no %v", err, order.OutTradeNo)
logger.Error(err.Error())
return err
}
} else if order.GoodType == 1 { // 霸屏
history := new(models.BullyScreenHistory)
exist, err := history.GetByOutTradeNo(order.OutTradeNo)
if err != nil || !exist || history.Status != -1 {
err = fmt.Errorf("打赏历史异常: err->%v, out_trade_no %v", err, order.OutTradeNo)
logger.Error(err.Error())
return err
}
_, err = history.UpdateStatus(history.Id, 0)
if err != nil {
err = fmt.Errorf("霸屏状态发送变化: err->%v, out_trade_no %v", err, order.OutTradeNo)
logger.Error(err.Error())
}
}
return nil
}
func HandleTimeout(order *models.UserOrder) error {
// 退还库存
if order.GoodType == 4 {
err := HandleCancelOrder(order.OutTradeNo)
if err != nil {
logger.Error(err)
}
}
return nil
}
// 处理打赏
func HandleReward() error {
result, err := models.GetExpireRewardHistory()
if err != nil {
logger.Error("获取过期打赏错误原因", err)
return err
}
for _, v := range result {
if v.RehearsalId != 0 && v.Type == 0 { // 欧轩互动h5彩排
continue
}
_, err := Refund("欧轩互动-打赏过期退款", v.OutTradeNo)
if err != nil {
logger.Error("欧轩互动打赏过期退款", v.OutTradeNo)
return err
}
v.Status = 4
_, err = models.Update(v.Id, v, "status")
if err != nil {
logger.Error("欧轩互动打赏过期状态改变错误")
}
}
return nil
}
func HandleCancelOrder(outTradeNo string) error {
return models.Commit(func(session *xorm.Session) error {
order := new(models.CustomerOrder)
exist, err := session.Where("is_delete=0 and status=0 and out_trade_no=?",
outTradeNo).Get(order)
if err != nil {
return err
}
if !exist || order.Status != 0 {
return errors.New("客户订单异常")
}
order.Status = 9
order.CancelTime = time.Now()
_, err = session.Where("is_delete=0 and out_trade_no=?",
outTradeNo).Cols("status, cancel_time").Update(order)
if err != nil {
return err
}
subs := make([]*models.CustomerOrderSub, 0)
err = session.Where("is_delete=0 and order_no=?", order.OrderNo).Find(&subs)
if err != nil {
return err
}
for _, sub := range subs {
_, err = session.Where("id=?", sub.GoodsId).
Incr("stock", sub.GoodsNum).Update(&models.CustomerGoods{})
if err != nil {
return err
}
}
return nil
})
}