1.咪咕钻石会员优化,提交接口返回消息改成异步,此接口不再记录订单数据;

2.回调通知增加失败通知;
This commit is contained in:
chenlin 2025-05-14 18:03:52 +08:00
parent ee6746e9d8
commit eae0fceb11
5 changed files with 223 additions and 133 deletions

View File

@ -7,7 +7,6 @@ import (
"github.com/go-admin-team/go-admin-core/logger"
"go-admin/app/admin/models"
"go-admin/common/apis"
"go-admin/tools"
"go-admin/tools/app"
"net/http"
"time"
@ -201,23 +200,23 @@ func (e MiGuDeployService) SubmitOrder(c *gin.Context) {
}
if resp.Data.LinkId != "" { // 提交订阅成功则记录到订单表
// 记录到订单列表
var orderInfo models.MgOrder
orderInfo.ProductID = models.ProductID
orderInfo.ChannelCode = req.Channel
orderInfo.OrderSerial = logInfo.OutTradeNo
nowTime := time.Now()
orderInfo.SubscribeTime = &nowTime
orderInfo.PhoneNumber = req.Phone
orderInfo.SM4PhoneNumber, _ = tools.SM4Encrypt(models.SM4KEy, req.Phone)
orderInfo.ExternalOrderID = resp.Data.LinkId // 外部平台订单号咪咕返回的linkId)
err = e.Orm.Create(&orderInfo).Error
if err != nil {
logger.Info("Create MgTransactionLog err:", err)
//app.Error(c, http.StatusBadRequest, err, err.Error())
//return
}
//// 记录到订单列表
//var orderInfo models.MgOrder
//orderInfo.ProductID = models.ProductID
//orderInfo.ChannelCode = req.Channel
//orderInfo.OrderSerial = logInfo.OutTradeNo
//nowTime := time.Now()
//orderInfo.SubscribeTime = &nowTime
//orderInfo.PhoneNumber = req.Phone
//orderInfo.SM4PhoneNumber, _ = tools.SM4Encrypt(models.SM4KEy, req.Phone)
//orderInfo.ExternalOrderID = resp.Data.LinkId // 外部平台订单号咪咕返回的linkId)
//
//err = e.Orm.Create(&orderInfo).Error
//if err != nil {
// logger.Info("Create MgTransactionLog err:", err)
// //app.Error(c, http.StatusBadRequest, err, err.Error())
// //return
//}
}
fmt.Println("SubmitOrder-end")

View File

@ -6,7 +6,6 @@ import (
"github.com/gin-gonic/gin"
"github.com/go-admin-team/go-admin-core/logger"
"go-admin/app/admin/models"
"go-admin/tools"
"go-admin/tools/app"
"net/http"
"time"
@ -235,24 +234,24 @@ func (e MiGuDeployService) SubmitOrderEx(c *gin.Context) {
}
if resp.Data.LinkId != "" { // 提交订阅成功则记录到订单表
// 记录到订单列表
var orderInfo models.MgOrder
orderInfo.ProductID = models.ProductID
orderInfo.ChannelCode = req.Channel
orderInfo.OrderSerial = logInfo.OutTradeNo
nowTime := time.Now()
orderInfo.SubscribeTime = &nowTime
orderInfo.PhoneNumber = req.Phone
orderInfo.SM4PhoneNumber, _ = tools.SM4Encrypt(models.SM4KEy, req.Phone)
orderInfo.ExternalOrderID = resp.Data.LinkId // 外部平台订单号咪咕返回的linkId)
orderInfo.ChannelTradeNo = req.OutTradeNo // 渠道订单号
err = e.Orm.Create(&orderInfo).Error
if err != nil {
logger.Info("Create MgTransactionLog err:", err)
app.MiGuError(c, http.StatusBadRequest, err, err.Error())
return
}
//// 记录到订单列表
//var orderInfo models.MgOrder
//orderInfo.ProductID = models.ProductID
//orderInfo.ChannelCode = req.Channel
//orderInfo.OrderSerial = logInfo.OutTradeNo
//nowTime := time.Now()
//orderInfo.SubscribeTime = &nowTime
//orderInfo.PhoneNumber = req.Phone
//orderInfo.SM4PhoneNumber, _ = tools.SM4Encrypt(models.SM4KEy, req.Phone)
//orderInfo.ExternalOrderID = resp.Data.LinkId // 外部平台订单号咪咕返回的linkId)
//orderInfo.ChannelTradeNo = req.OutTradeNo // 渠道订单号
//
//err = e.Orm.Create(&orderInfo).Error
//if err != nil {
// logger.Info("Create MgTransactionLog err:", err)
// app.MiGuError(c, http.StatusBadRequest, err, err.Error())
// return
//}
resp.Data.LinkId = outTradeNo
}

View File

@ -25,13 +25,15 @@ import (
// @Router /api/v1/notice/subscribe [get]
func (e MiGuDeployService) SubscribeNotice(c *gin.Context) {
fmt.Println("SubscribeNotice-start")
logger.Info("订购成功通知-start")
logger.Info("订购通知-start")
fmt.Println("URL:", c.Request.URL.String())
orderId := c.Query("orderId") // 对应linkId
extData := c.Query("extData") // 对应outTradeNo
status := c.Query("status") // status: 1成功 不存在status也认为是订购成功通知
status := c.Query("status") // status: 1成功 -1: 失败
rsCode := c.Query("rsCode") // 失败编码
rsMsg := c.Query("rsMsg") // 失败原因
fmt.Println("orderId:", orderId)
fmt.Println("extData:", extData)
@ -44,7 +46,7 @@ func (e MiGuDeployService) SubscribeNotice(c *gin.Context) {
return
}
if !(status == "1" || status == "") {
if !(status == "1" || status == "-1") {
logger.Error("status is", status)
app.MiGuNoticeOK(c, fmt.Sprintf("failed,status is:%s", status))
return
@ -58,6 +60,9 @@ func (e MiGuDeployService) SubscribeNotice(c *gin.Context) {
return
}
if status == "1" { // 订购成功
fmt.Println("订购成功通知status is 1")
logger.Info("订购成功通知status is 1")
var orderInfo models.MgOrder
for i := 0; i < 3; i++ {
// 查询订单表是否有记录
@ -141,7 +146,8 @@ func (e MiGuDeployService) SubscribeNotice(c *gin.Context) {
if channelInfo.SubscribeURL != "" {
for i := 0; i < 3; i++ {
resp, err := models.NoticeSubChannel(channelInfo.SubscribeURL, orderInfo.OrderSerial,
orderInfo.ChannelTradeNo, "1", channelInfo.MainChannelCode, channelInfo.Remarks)
orderInfo.ChannelTradeNo, "1", channelInfo.MainChannelCode, channelInfo.Remarks,
"", "")
if err != nil {
fmt.Println("NoticeSubChannel err:", err)
fmt.Println("i is:", i)
@ -170,10 +176,75 @@ func (e MiGuDeployService) SubscribeNotice(c *gin.Context) {
logger.Errorf("CheckOrderState MiGuQueryRightsInfo err:", err.Error())
}
fmt.Println("CheckOrderState MiGuQueryRightsInfo resp:", resp)
fmt.Println("订购成功通知-end")
logger.Info("订购成功通知-end")
} else if status == "-1" { // 订购失败
fmt.Println("订购失败通知status is -1")
logger.Info("订购失败通知status is -1")
// 查询交易流水表
var logInfo models.MgTransactionLog
err = e.Orm.Table("mg_transaction_log").
Where("link_id = ?", orderId).First(&logInfo).Error
if err != nil {
logger.Errorf("SubscribeNotice query mg_transaction_log err:", err.Error())
app.MiGuNoticeOK(c, "failed")
return
}
// 解析错误信息
msg, _ := tools.DecodeURL(rsMsg)
// 更新交易流水表
err = e.Orm.Table("mg_transaction_log").Where("link_id = ?", orderId).Updates(map[string]interface{}{
"result": rsCode,
"reason": msg,
"updated_at": time.Now(),
}).Error
if err != nil {
logger.Errorf("SubscribeNotice update mg_transaction_log err:", err.Error())
app.MiGuNoticeOK(c, "failed")
return
}
// 判断是否为子渠道订购,是的话需要通知子渠道
if models.IsValidChannelEx(logInfo.ChannelCode, e.Orm) {
channelInfo, err := models.GetChannelInfoByChannelCode(logInfo.ChannelCode, e.Orm)
if err != nil {
fmt.Println("SubscribeNotice GetChannelInfoByChannelCode err:", err)
fmt.Println("SubscribeNotice sub_channel_code is:", logInfo.ChannelCode)
logger.Errorf("SubscribeNotice GetChannelInfoByChannelCode err, sub_channel_code is:", logInfo.ChannelCode)
}
if channelInfo.SubscribeURL != "" {
for i := 0; i < 3; i++ {
resp, err := models.NoticeSubChannel(channelInfo.SubscribeURL, logInfo.OutTradeNo,
logInfo.ChannelTradeNo, "-1", channelInfo.MainChannelCode, channelInfo.Remarks,
rsCode, rsMsg)
if err != nil {
fmt.Println("NoticeSubChannel err:", err)
fmt.Println("i is:", i)
continue
}
if resp != "success" {
continue
} else {
break
}
}
} else {
fmt.Println("SubscribeNotice SubscribeURL is null, sub_channel_code is:", logInfo.ChannelCode)
logger.Error("SubscribeNotice SubscribeURL is null, sub_channel_code is:", logInfo.ChannelCode)
}
}
fmt.Println("订购失败通知-end")
logger.Info("订购失败通知-end")
}
fmt.Println("SubscribeNotice-end")
logger.Info("订购成功通知-end")
logger.Info("订购通知-end")
app.MiGuNoticeOK(c, "success")
return
}
@ -255,7 +326,8 @@ func (e MiGuDeployService) UnsubscribeNotice(c *gin.Context) {
if channelInfo.SubscribeURL != "" {
for i := 0; i < 3; i++ {
resp, err := models.NoticeSubChannel(channelInfo.SubscribeURL, orderInfo.OrderSerial,
orderInfo.ChannelTradeNo, "2", channelInfo.MainChannelCode, channelInfo.Remarks)
orderInfo.ChannelTradeNo, "2", channelInfo.MainChannelCode, channelInfo.Remarks,
"", "")
if err != nil {
continue
}

View File

@ -707,7 +707,7 @@ func MiGuQueryRightsInfo(r *QueryRightsInfoReq) (QueryRightsInfoResp, error) {
}
// NoticeSubChannel 回调通知接口 (GET 请求返回string类型响应头为text/plain)
func NoticeSubChannel(baseUrl, linkId, extData, status, mainChannelCode, remarks string) (string, error) {
func NoticeSubChannel(baseUrl, linkId, extData, status, mainChannelCode, remarks, rsCode, rsMsg string) (string, error) {
// 构建 GET 请求的 URL
requestUrl, err := url.Parse(baseUrl)
if err != nil {
@ -719,6 +719,8 @@ func NoticeSubChannel(baseUrl, linkId, extData, status, mainChannelCode, remarks
query.Set("orderId", linkId)
query.Set("extData", extData)
query.Set("status", status)
query.Set("rsCode", rsCode)
query.Set("rsMsg", rsMsg)
if strings.Contains(remarks, AddRemark) {
query.Set("channel", mainChannelCode)
@ -912,6 +914,7 @@ func CheckOrderState() {
err := database.Db.Where("is_one_hour_cancel != 1").
Where("created_at >= ?", oneHourAgo).
Where("product_id = 1"). // 只查询产品1的情况
Order("created_at desc").
Find(&orderList).Error

View File

@ -9,6 +9,7 @@ import (
"golang.org/x/crypto/bcrypt"
"gorm.io/gorm"
"log"
"net/url"
"runtime"
"strconv"
)
@ -81,3 +82,19 @@ func GetOrm(c *gin.Context) (*gorm.DB, error) {
return nil, errors.New(fmt.Sprintf("msgID[%s], db connect not exist", msgID))
}
}
// DecodeURL 自动多次 URL 解码,直到结果不再变化
func DecodeURL(input string) (string, error) {
prev := ""
current := input
var err error
for current != prev {
prev = current
current, err = url.QueryUnescape(prev)
if err != nil {
return "", err
}
}
return current, nil
}