黄梓健 5 years ago
parent
commit
6f9945ae01
  1. 4
      models/customer_goods.go
  2. 9
      models/customer_order_sub.go
  3. 7
      models/user_order.go
  4. 2
      services/pay/const.go
  5. 82
      services/pay/handle.go
  6. 161
      services/pay/order.go

4
models/customer_goods.go

@ -43,3 +43,7 @@ func GetGoodsByActivityId(activityId, areaId int64) ([]*CustomerGoods, error) {
Asc("created_at").Find(&goods)
return goods, err
}
func (t *CustomerGoods) IncrStockById(id interface{}, num int) (int64, error) {
return core.GetXormAuto().ID(id).Incr("stock", num).Cols("stock").Update(t)
}

9
models/customer_order_sub.go

@ -40,12 +40,3 @@ func GetCustomerOrderSubsByOrderNos(orderNos ...string) (subs []*CustomerOrderSu
Desc("s.created_at").Find(&subs)
return
}
//func GetCustomerOrderSubsByOutTradeNo(outTradeNo string) (subs []*CustomerOrderSub, err error) {
// err = core.GetXormAuto().Table(new(CustomerOrderSub)).Alias("s").
// Select("s.order_no, s.goods_id, s.goods_num, s.good_name, s.good_price, g.goods_pic_url").
// Join("left", new(CustomerGoods).Alias("g"), "g.id=s.goods_id").
// Where("s.is_delete=0 and out_trade_no=?", outTradeNo).
// Desc("s.created_at").Find(&subs)
// return
//}

7
models/user_order.go

@ -27,7 +27,7 @@ type UserOrder struct {
TransactionId string `json:"transaction_id" xorm:"not null default('') comment('微信支付订单号') VARCHAR(32)"`
ExpireAt int64 `json:"time_expire" xorm:"not null default('0') comment('交易过期') INT(20)"`
PrepayId string `json:"prepay_id" xorm:"not null default('') comment('预支付交易会话标识') VARCHAR(64)"`
Status int `json:"status" xorm:"not null default(0) comment('0尚未支付/支付中1支付成功2已销3转入退款4退款成功5支付失败6订单关闭7订单超时') TINYINT(1)"`
Status int `json:"status" xorm:"not null default(0) comment('0尚未支付/支付中1支付成功2已销3转入退款4退款成功5支付失败6订单关闭7订单超时') TINYINT(1)"`
// 退款
RefundRecvAccount string `json:"refund_recv_account" xorm:"not null default '' comment('入账账号') VARCHAR(64)"`
@ -61,9 +61,8 @@ func (t *UserOrder) UpdateRefundByOutTradeNo(outTradeNo interface{}) (int64, err
Cols("status", "refund_recv_account", "refund_account").Update(t)
}
func GetUserOrdersByStatus(expire string, status ...int) ([]*UserOrder, error) {
func GetUserOrdersByStatus(status ...int) ([]*UserOrder, error) {
orders := make([]*UserOrder, 0)
err := core.GetXormAuto().Where("is_delete=0 and expire_at <= ?", expire).
In("status", status).Desc("created_at").Find(&orders)
err := core.GetXormAuto().Where("is_delete=0").In("status", status).Find(&orders)
return orders, err
}

2
services/pay/const.go

@ -71,7 +71,7 @@ const (
CODE_TRADE_USERPAYING = "USERPAYING" // 用户支付中
CODE_TRADE_PAYERROR = "PAYERROR" // 支付失败
CODE_TRANSFER_PROCESSING = "PROCESSING" // 转账处理中
CODE_TRANSFER_NOT_FOUND = "NOT_FOUND" // 账单消息
CODE_TRANSFER_NOT_FOUND = "NOT_FOUND" // 账单不见了
)
type CommonReturn struct {

82
services/pay/handle.go

@ -3,7 +3,6 @@ package pay_service
import (
"errors"
"fmt"
"github.com/ouxuanserver/osmanthuswine/src/core"
"hudongzhuanjia/logger"
"hudongzhuanjia/models"
im_service "hudongzhuanjia/services/im"
@ -13,14 +12,14 @@ import (
//处理支付成功之后的回调问题
// 直播红包
func HandleSuccess(param *OrderDelayQueueParam) error {
if param.Order.GoodType == 4 { // 直播商品
func HandleSuccess(order *models.UserOrder) error {
if order.GoodType == 4 { // 直播商品
customerOrder := new(models.CustomerOrder)
_, err := customerOrder.UpdateStatusBy(param.Order.OutTradeNo, 0, 1)
_, err := customerOrder.UpdateStatusBy(order.OutTradeNo, 0, 1)
if err != nil {
return errors.New("更新状态发送错误")
}
customerOrder.GetByOutTradeNO(param.Order.OutTradeNo)
customerOrder.GetByOutTradeNO(order.OutTradeNo)
if customerOrder.Status != 1 {
return errors.New("商品订单状态信息出现异常")
}
@ -30,7 +29,7 @@ func HandleSuccess(param *OrderDelayQueueParam) error {
return err
}
for _, sub := range subs {
err = im_service.SendGroupCustomMessage(customerOrder.BuyerId, param.Order.ActivityId, im_service.NoticeLiveGoodBuy,
err = im_service.SendGroupCustomMessage(customerOrder.BuyerId, order.ActivityId, im_service.NoticeLiveGoodBuy,
map[string]interface{}{
"goods_pic_url": sub.GoodsPicUrl,
"goods_num": sub.GoodsNum,
@ -46,13 +45,13 @@ func HandleSuccess(param *OrderDelayQueueParam) error {
}
activity := new(models.Activity)
exist, err := models.Get(activity, param.Order.ActivityId)
exist, err := models.Get(activity, order.ActivityId)
if err != nil || !exist {
return errors.New("互动信息异常")
}
gift := new(models.OrderGift)
exist, err = gift.GetByActivityId(param.Order.ActivityId)
exist, err = gift.GetByActivityId(order.ActivityId)
if err != nil {
err = fmt.Errorf("获取订单送礼错误: err-> %v, activity_id-> %v", err, activity.Id)
logger.Error(err)
@ -64,8 +63,8 @@ func HandleSuccess(param *OrderDelayQueueParam) error {
}
prize := new(models.UserPrize)
prize.UserId = param.Order.UserId
prize.ActivityId = param.Order.ActivityId
prize.UserId = order.UserId
prize.ActivityId = order.ActivityId
prize.RehearsalId = activity.RehearsalId
prize.ActivityName = activity.Name
prize.PrizeName = gift.GiftName
@ -79,7 +78,7 @@ func HandleSuccess(param *OrderDelayQueueParam) error {
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, param.Order.OutTradeNo)
err = fmt.Errorf("订单人数统计失败: err->%v, out_trade_no->%v", err, order.OutTradeNo)
logger.Error(err)
return err
}
@ -90,7 +89,7 @@ func HandleSuccess(param *OrderDelayQueueParam) error {
}
_, err = prize.Add()
if err != nil {
err = fmt.Errorf("奖品添加失败: err->%v, out_trade_no->%v", err, param.Order.OutTradeNo)
err = fmt.Errorf("奖品添加失败: err->%v, out_trade_no->%v", err, order.OutTradeNo)
logger.Error(err)
return err
}
@ -98,27 +97,27 @@ func HandleSuccess(param *OrderDelayQueueParam) error {
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, param.Order.OutTradeNo, prize.Id)
err = fmt.Errorf("奖品记录添加失败: err-> %v, out_trade_no-> %v, prize_id->%v", err, order.OutTradeNo, prize.Id)
logger.Error(err)
return err
}
} else if param.Order.GoodType == 3 { // 直播红包
} else if order.GoodType == 3 { // 直播红包
info := new(models.LiveRedEnvelopeRule)
_, err := info.UpdateStatusByOutTradeNo(param.Order.OutTradeNo, 1)
_, err := info.UpdateStatusByOutTradeNo(order.OutTradeNo, 1)
if err != nil {
err = fmt.Errorf("状态改变出现错误: err->%v, out_trade_no->%v", err, param.Order.OutTradeNo)
err = fmt.Errorf("状态改变出现错误: err->%v, out_trade_no->%v", err, order.OutTradeNo)
logger.Error(err.Error())
return err
}
exist, err := info.GetByOutTradeNo(param.Order.OutTradeNo)
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, param.Order.OutTradeNo)
err, exist, info.Status, order.OutTradeNo)
logger.Error(err.Error())
return err
}
err = im_service.SendGroupCustomMessage(info.UserId, param.Order.ActivityId, im_service.NoticeLiveRedPackStart,
err = im_service.SendGroupCustomMessage(info.UserId, order.ActivityId, im_service.NoticeLiveRedPackStart,
map[string]interface{}{
"live_red_envelope_rule_id": info.Id,
"prompt": info.Prompt,
@ -126,65 +125,64 @@ func HandleSuccess(param *OrderDelayQueueParam) error {
})
if err != nil {
err = fmt.Errorf("发送腾讯im信息出现错误: err->%v, info_id->%v, out_trade_no->%v",
err, info.Id, param.Order.OutTradeNo)
err, info.Id, order.OutTradeNo)
logger.Error(err.Error())
return err
}
} else if param.Order.GoodType == 2 { // 打赏
} else if order.GoodType == 2 { // 打赏
history := new(models.RewardHistory)
exist, err := history.GetByOutTradeNo(param.Order.OutTradeNo)
exist, err := history.GetByOutTradeNo(order.OutTradeNo)
if err != nil || !exist || history.Status != -1 {
err = fmt.Errorf("打赏历史异常: err->%v, out_trade_no %v", err, param.Order.OutTradeNo)
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, param.Order.OutTradeNo)
err = fmt.Errorf("打赏状态发送变化: err->%v, out_trade_no %v", err, order.OutTradeNo)
logger.Error(err.Error())
return err
}
} else if param.Order.GoodType == 1 { // 霸屏
} else if order.GoodType == 1 { // 霸屏
history := new(models.BullyScreenHistory)
exist, err := history.GetByOutTradeNo(param.Order.OutTradeNo)
exist, err := history.GetByOutTradeNo(order.OutTradeNo)
if err != nil || !exist || history.Status != -1 {
err = fmt.Errorf("打赏历史异常: err->%v, out_trade_no %v", err, param.Order.OutTradeNo)
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, param.Order.OutTradeNo)
err = fmt.Errorf("霸屏状态发送变化: err->%v, out_trade_no %v", err, order.OutTradeNo)
logger.Error(err.Error())
}
}
return nil
}
func HandleFailed(param *OrderDelayQueueParam) (err error) {
var exist bool
func HandleFailed(order *models.UserOrder) error {
// 退还库存
if param.Order.GoodType == 4 {
order := new(models.CustomerOrder)
exist, err = order.GetByOutTradeNO(param.Order.OutTradeNo)
if order.GoodType == 4 {
customerOrder := new(models.CustomerOrder)
exist, err := customerOrder.GetByOutTradeNO(order.OutTradeNo)
if err != nil || !exist {
err = fmt.Errorf("不存在客户订单: err-> %v, out_trade_no->%v", err, param.Order.OutTradeNo)
err = fmt.Errorf("不存在客户订单: err-> %v, out_trade_no->%v", err, order.OutTradeNo)
logger.Error(err.Error())
return
return err
}
subs := make([]*models.CustomerOrderSub, 0)
err = core.GetXormAuto().Where("is_delete=0 and order_no=?", order.OrderNo).Find(&subs)
subs, err := models.GetCustomerOrderSubsByOrderNos(customerOrder.OrderNo)
if err != nil {
err = fmt.Errorf("不存在客户子订单: err-> %v, out_trade_no->%v", err, param.Order.OutTradeNo)
err = fmt.Errorf("不存在客户子订单: err-> %v, out_trade_no->%v", err, order.OutTradeNo)
return err
}
for _, sub := range subs {
_, err = core.GetXormAuto().Where("id=?", sub.GoodsId).
Incr("stock", sub.GoodsNum).Update(&models.CustomerGoods{})
_, err = new(models.CustomerGoods).IncrStockById(sub.GoodsId, sub.GoodsNum)
if err != nil {
err = fmt.Errorf("库存返回失败: err->%v, out_trade_no->%v, sub_id->%v", err, param.Order.OutTradeNo, sub.Id)
err = fmt.Errorf("库存返回失败: err->%v, out_trade_no->%v, sub_id->%v", err, order.OutTradeNo, sub.Id)
return err
}
}
}
return
return nil
}

161
services/pay/order.go

@ -3,10 +3,8 @@ package pay_service
import (
"encoding/xml"
"fmt"
core2 "github.com/chanxuehong/wechat/mch/core"
pay_core "github.com/chanxuehong/wechat/mch/core"
"github.com/chanxuehong/wechat/mch/pay"
"github.com/pkg/errors"
"go.uber.org/zap"
"hudongzhuanjia/logger"
"hudongzhuanjia/models"
"hudongzhuanjia/utils"
@ -21,39 +19,25 @@ func init() {
go loopUnifiedOrder()
}
var orderDelayQueue = make(chan *OrderDelayQueueParam, math.MaxInt8)
var orderDelayQueue = make(chan *models.UserOrder, math.MaxInt8)
type OrderDelayQueueParam struct {
Order *models.UserOrder
First bool `json:"first"`
Delay int `json:"delay"`
}
func PutOrderDelayQueue(order *models.UserOrder, delay int) {
if delay == 0 {
delay = 0
}
orderDelayQueue <- &OrderDelayQueueParam{
First: true,
Delay: delay,
Order: order,
}
func PutOrderDelayQueue(order *models.UserOrder) {
orderDelayQueue <- order
}
func loopUnifiedOrder() {
orders, err := models.GetUserOrdersByStatus(core2.FormatTime(time.Now().Add(12*time.Hour)), 0, 3)
orders, err := models.GetUserOrdersByStatus(0, 3)
if err != nil {
panic(err)
}
for _, order := range orders {
PutOrderDelayQueue(order, 0)
PutOrderDelayQueue(order)
}
defer func() {
if err := recover(); err != nil {
logger.Error("订单轮询查询", zap.Any("panic 恢复错误", err))
logger.Error("订单轮询查询: panic 恢复错误", err)
}
// 重启
time.Sleep(5 * time.Second)
@ -61,53 +45,43 @@ func loopUnifiedOrder() {
}()
for {
select {
case param, ok := <-orderDelayQueue:
case order, ok := <-orderDelayQueue:
if !ok {
panic("通道异常关闭")
}
if param.Order.ExpireAt <= time.Now().Unix() {
if param.Order.Status == 0 {
order := new(models.UserOrder)
_, err = order.UpdateStatusByOutTradeNo(param.Order.OutTradeNo, 7)
Close(param.Order.OutTradeNo) // 超时关闭订单
go HandleFailed(param)
if order.ExpireAt <= time.Now().Unix() {
if order.Status == 0 {
err = Close(order.OutTradeNo) // 超时关闭订单
order.Status = 7
_, err = models.Update(order.Id, order, "status")
go HandleFailed(order)
}
continue // 超时
}
// 首次进入不延迟
if !param.First {
time.Sleep(time.Duration(param.Delay) * time.Millisecond)
continue
}
param.First = false
if param.Order.Status == 0 {
res, err := OrderQuery(param.Order.OutTradeNo)
if order.Status == 0 {
res, err := OrderQuery(order.OutTradeNo)
// 出现错误
if err != nil {
logger.Error("查询订单出现错误", zap.String("错误原因", err.Error()),
zap.String("交易订单号", param.Order.OutTradeNo))
orderDelayQueue <- param // 重新进入队列
logger.Error("查询订单出现错误: 错误原因-->", err.Error(), "交易订单号-->", order.OutTradeNo)
orderDelayQueue <- order // 重新进入队列
continue
}
if res.Query.TradeState == CODE_TRADE_SUCCESS {
param.Order = res.Order
go HandleSuccess(param)
} else if res.Query.TradeState == CODE_TRADE_REFUND {
param.Order.Status = 3
orderDelayQueue <- param
if res["trade_state"] == CODE_TRADE_SUCCESS {
go HandleSuccess(order)
} else if res["trade_state"] == CODE_TRADE_REFUND {
order.Status = 3
orderDelayQueue <- order
continue
} else if res.Query.TradeState == CODE_TRADE_NOTPAY || res.Query.TradeState == CODE_TRADE_USERPAYING {
orderDelayQueue <- param
} else {
orderDelayQueue <- order
continue
}
} else if param.Order.Status == 3 {
_, err = QueryRefund(param.Order.OutTradeNo)
} else if order.Status == 3 {
_, err = QueryRefund(order.OutTradeNo)
if err != nil {
logger.Error("退款订单查询错误", zap.String("错误原因", err.Error()),
zap.String("交易订单号", param.Order.OutTradeNo))
logger.Error("退款订单查询错误: 错误原因-->", err.Error(), "交易订单号-->", order.OutTradeNo)
continue
}
} else {
@ -135,7 +109,7 @@ func UnifiedOrder(content, openId string, fee, goodType, userId, activityId, exp
body["trade_type"] = "JSAPI"
body["device_info"] = "WEB"
body["nonce_str"] = nonceStr
body["sign_type"] = core2.SignType_MD5
body["sign_type"] = pay_core.SignType_MD5
body["open_id"] = openId
resp, err := pay.UnifiedOrder(client, body)
@ -165,15 +139,15 @@ func UnifiedOrder(content, openId string, fee, goodType, userId, activityId, exp
//获取H5支付需要的paySign
timestamp := strconv.FormatInt(time.Now().Unix(), 10)
pac := "prepay_id=" + resp["prepay_id"]
paySign := core2.JsapiSign(client.AppId(), timestamp, nonceStr, pac, core2.SignType_MD5, ApiKey)
paySign := pay_core.JsapiSign(client.AppId(), timestamp, nonceStr, pac, pay_core.SignType_MD5, ApiKey)
go PutOrderDelayQueue(userOrder, 0)
go PutOrderDelayQueue(userOrder)
return map[string]interface{}{
"appid": Appid,
"timestamp": timestamp,
"nonce_str": nonceStr,
"package": pac,
"sign_type": core2.SignType_MD5,
"sign_type": pay_core.SignType_MD5,
"pay_sign": paySign,
"out_trade_no": outTradeNo,
"user_order_id": userOrder.Id,
@ -187,21 +161,21 @@ func ReOrder(outTradeNo string) (map[string]interface{}, error) {
return nil, err
}
if !exist {
return nil, errors.New("订单不存在")
return nil, fmt.Errorf("订单不存在")
}
timestamp := strconv.FormatInt(time.Now().Unix(), 10)
nonceStr := utils.RandomStr(32)
//获取H5支付需要的paySign
pac := "prepay_id=" + userOrder.PrepayId
paySign := core2.JsapiSign(Appid, timestamp, nonceStr, pac, core2.SignType_MD5, ApiKey)
go PutOrderDelayQueue(userOrder, 0)
paySign := pay_core.JsapiSign(Appid, timestamp, nonceStr, pac, pay_core.SignType_MD5, ApiKey)
go PutOrderDelayQueue(userOrder)
return map[string]interface{}{
"appid": Appid,
"timestamp": timestamp,
"nonce_str": nonceStr,
"package": pac,
"sign_type": core2.SignType_MD5,
"sign_type": pay_core.SignType_MD5,
"pay_sign": paySign,
"out_trade_no": outTradeNo,
"user_order_id": userOrder.Id,
@ -277,9 +251,7 @@ func NotifyOrder(w io.Reader) (order *models.UserOrder, err error) {
return
}
err = HandleSuccess(&OrderDelayQueueParam{
Order: userOrder,
})
err = HandleSuccess(userOrder)
if err != nil {
logger.Error(fmt.Sprintf("handle success: %v", err))
return
@ -296,54 +268,23 @@ type OrderQueryResult struct {
Query *pay.OrderQueryResponse
}
func OrderQuery(outTradeNo string) (*OrderQueryResult, error) {
func OrderQuery(outTradeNo string) (map[string]string, error) {
client, err := Client()
if err != nil {
return nil, err
}
// 请求订单查询,成功后得到结果
userOrder := new(models.UserOrder)
exist, err := userOrder.GetByOutTradeNo(outTradeNo)
if err != nil {
return nil, err
}
if !exist {
return nil, errors.New("订单不存在")
}
res, err := pay.OrderQuery2(client, &pay.OrderQueryRequest{
OutTradeNo: outTradeNo,
NonceStr: utils.RandomStr(32),
SignType: core2.SignType_MD5,
})
body := make(map[string]string)
body["out_trade_no"] = outTradeNo
body["nonce_str"] = utils.RandomStr(32)
body["sign_type"] = pay_core.SignType_MD5
res, err := pay.OrderQuery(client, body)
if err != nil {
return nil, err
}
userOrder.TransactionId = res.TransactionId
switch res.TradeState {
case CODE_TRADE_SUCCESS:
userOrder.Status = 1
case CODE_TRADE_REVOKED:
userOrder.Status = 2
case CODE_TRADE_REFUND:
userOrder.Status = 3
case CODE_TRADE_PAYERROR:
userOrder.Status = 5
case CODE_TRADE_CLOSED:
userOrder.Status = 6
case CODE_TRADE_NOTPAY: // 超过期限,就关闭
userOrder.Status = 0
}
if _, err = userOrder.UpdateStatusByOutTradeNo(outTradeNo, userOrder.Status); err != nil {
return nil, err
}
return &OrderQueryResult{
Order: userOrder,
Query: res,
}, nil
return res, nil
}
func Close(outTradeNo string) error {
@ -354,7 +295,7 @@ func Close(outTradeNo string) error {
err = pay.CloseOrder2(client, &pay.CloseOrderRequest{
OutTradeNo: outTradeNo,
NonceStr: utils.RandomStr(32),
SignType: core2.SignType_MD5,
SignType: pay_core.SignType_MD5,
})
// 请求关闭订单,成功后得到结果
if err != nil {
@ -372,7 +313,7 @@ func Refund(reason, outTradeNo string) (*pay.RefundResponse, error) {
return nil, err
}
if !exist {
return nil, errors.New("订单不存在")
return nil, fmt.Errorf("订单不存在")
}
client, err := Client()
@ -385,7 +326,7 @@ func Refund(reason, outTradeNo string) (*pay.RefundResponse, error) {
TotalFee: userOrder.TotalFee,
RefundFee: userOrder.TotalFee,
NonceStr: nonceStr,
SignType: core2.SignType_MD5,
SignType: pay_core.SignType_MD5,
RefundFeeType: "CNY",
RefundDesc: reason,
})
@ -399,7 +340,7 @@ func Refund(reason, outTradeNo string) (*pay.RefundResponse, error) {
return nil, err
}
PutOrderDelayQueue(userOrder, 0) // 退款查询
PutOrderDelayQueue(userOrder) // 退款查询
return res, nil
}
@ -415,14 +356,14 @@ func QueryRefund(outTradeNo string) (*QueryRefundResult, error) {
return nil, err
}
if !exist {
return nil, errors.New("不存在改笔退款")
return nil, fmt.Errorf("不存在改笔退款")
}
client, err := Client()
res, err := pay.RefundQuery2(client, &pay.RefundQueryRequest{
OutTradeNo: outTradeNo,
NonceStr: utils.RandomStr(32),
SignType: core2.SignType_MD5,
SignType: pay_core.SignType_MD5,
})
//请求申请退款
if err != nil {

Loading…
Cancel
Save