From eae0fceb11a2ecf55751343755fca24b7259e69c Mon Sep 17 00:00:00 2001 From: chenlin Date: Wed, 14 May 2025 18:03:52 +0800 Subject: [PATCH] =?UTF-8?q?1.=E5=92=AA=E5=92=95=E9=92=BB=E7=9F=B3=E4=BC=9A?= =?UTF-8?q?=E5=91=98=E4=BC=98=E5=8C=96=EF=BC=8C=E6=8F=90=E4=BA=A4=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E8=BF=94=E5=9B=9E=E6=B6=88=E6=81=AF=E6=94=B9=E6=88=90?= =?UTF-8?q?=E5=BC=82=E6=AD=A5=EF=BC=8C=E6=AD=A4=E6=8E=A5=E5=8F=A3=E4=B8=8D?= =?UTF-8?q?=E5=86=8D=E8=AE=B0=E5=BD=95=E8=AE=A2=E5=8D=95=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=EF=BC=9B=202.=E5=9B=9E=E8=B0=83=E9=80=9A=E7=9F=A5=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E5=A4=B1=E8=B4=A5=E9=80=9A=E7=9F=A5=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/admin/apis/migumanage/migu.go | 35 ++- app/admin/apis/migumanage/migu_external.go | 37 ++- app/admin/apis/migumanage/migu_notice.go | 262 +++++++++++++-------- app/admin/models/migu.go | 5 +- tools/utils.go | 17 ++ 5 files changed, 223 insertions(+), 133 deletions(-) diff --git a/app/admin/apis/migumanage/migu.go b/app/admin/apis/migumanage/migu.go index ed8cb54..d6cb111 100644 --- a/app/admin/apis/migumanage/migu.go +++ b/app/admin/apis/migumanage/migu.go @@ -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") diff --git a/app/admin/apis/migumanage/migu_external.go b/app/admin/apis/migumanage/migu_external.go index 1ea1857..8fbad42 100644 --- a/app/admin/apis/migumanage/migu_external.go +++ b/app/admin/apis/migumanage/migu_external.go @@ -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 } diff --git a/app/admin/apis/migumanage/migu_notice.go b/app/admin/apis/migumanage/migu_notice.go index 82f15e8..a5afc60 100644 --- a/app/admin/apis/migumanage/migu_notice.go +++ b/app/admin/apis/migumanage/migu_notice.go @@ -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,25 +60,128 @@ func (e MiGuDeployService) SubscribeNotice(c *gin.Context) { return } - var orderInfo models.MgOrder - for i := 0; i < 3; i++ { - // 查询订单表是否有记录 - err = e.Orm.Table("mg_order").Where("external_order_id = ?", orderId).First(&orderInfo).Error - if err != nil && err.Error() != "record not found" { - logger.Errorf("SubscribeNotice query mg_order err:", err.Error()) - app.MiGuNoticeOK(c, "failed") - return + if status == "1" { // 订购成功 + fmt.Println("订购成功通知:status is 1") + logger.Info("订购成功通知:status is 1") + var orderInfo models.MgOrder + for i := 0; i < 3; i++ { + // 查询订单表是否有记录 + err = e.Orm.Table("mg_order").Where("external_order_id = ?", orderId).First(&orderInfo).Error + if err != nil && err.Error() != "record not found" { + logger.Errorf("SubscribeNotice query mg_order err:", err.Error()) + app.MiGuNoticeOK(c, "failed") + return + } + + if errors.Is(err, gorm.ErrRecordNotFound) { // 没有查询到记录,循环查询3次 + time.Sleep(800 * time.Millisecond) + } else if err == nil { // 查询到记录,则跳出循环 + break + } } - if errors.Is(err, gorm.ErrRecordNotFound) { // 没有查询到记录,循环查询3次 - time.Sleep(800 * time.Millisecond) - } else if err == nil { // 查询到记录,则跳出循环 - break - } - } + var checkPhoneNum string + if errors.Is(err, gorm.ErrRecordNotFound) { // 订单表没有记录 + // 查询交易流水表 + 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 + } + + checkPhoneNum = logInfo.PhoneNumber + + // 插入订单表 + var inOrder models.MgOrder + inOrder.CreatedAt = logInfo.CreatedAt + inOrder.UpdatedAt = logInfo.UpdatedAt + inOrder.ProductID = logInfo.ProductID + inOrder.ChannelCode = logInfo.ChannelCode + inOrder.OrderSerial = logInfo.OutTradeNo + strTime := time.Now() + inOrder.SubscribeTime = &strTime + inOrder.PhoneNumber = logInfo.PhoneNumber + inOrder.SM4PhoneNumber, _ = tools.SM4Encrypt(models.SM4KEy, logInfo.PhoneNumber) + inOrder.ExternalOrderID = logInfo.LinkId + inOrder.ChannelTradeNo = logInfo.ChannelTradeNo + inOrder.State = models.SubscribeOK + + err = e.Orm.Create(&inOrder).Error + if err != nil { + logger.Info("Create MgOrder err:", err) + app.MiGuError(c, http.StatusBadRequest, err, err.Error()) + return + } + orderInfo.ChannelCode = inOrder.ChannelCode + orderInfo.OrderSerial = inOrder.OrderSerial + orderInfo.ChannelTradeNo = inOrder.ChannelTradeNo + } else { // 订单表有记录 + checkPhoneNum = orderInfo.PhoneNumber + if orderInfo.State != 1 { + err = e.Orm.Table("mg_order").Where("external_order_id = ?", orderId).Updates(map[string]interface{}{ + "state": models.SubscribeOK, + "subscribe_time": time.Now(), + "updated_at": time.Now(), + }).Error + if err != nil { + logger.Errorf("SubscribeNotice update mg_order err:", err.Error()) + app.MiGuNoticeOK(c, "failed") + return + } + } + } + + // 判断是否为子渠道订购,是的话需要通知子渠道 + if models.IsValidChannelEx(orderInfo.ChannelCode, e.Orm) { + channelInfo, err := models.GetChannelInfoByChannelCode(orderInfo.ChannelCode, e.Orm) + if err != nil { + fmt.Println("SubscribeNotice GetChannelInfoByChannelCode err:", err) + fmt.Println("SubscribeNotice sub_channel_code is:", orderInfo.ChannelCode) + logger.Errorf("SubscribeNotice GetChannelInfoByChannelCode err, sub_channel_code is:", orderInfo.ChannelCode) + } + + if channelInfo.SubscribeURL != "" { + for i := 0; i < 3; i++ { + resp, err := models.NoticeSubChannel(channelInfo.SubscribeURL, orderInfo.OrderSerial, + orderInfo.ChannelTradeNo, "1", channelInfo.MainChannelCode, channelInfo.Remarks, + "", "") + 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:", orderInfo.ChannelCode) + logger.Error("SubscribeNotice SubscribeURL is null, sub_channel_code is:", orderInfo.ChannelCode) + } + } + + var req models.QueryRightsInfoReq + req.AppChannelList = append(req.AppChannelList, models.ChannelCode) + req.Mobile = checkPhoneNum + + resp, err := models.MiGuQueryRightsInfo(&req) + if err != nil { + fmt.Println("CheckOrderState MiGuQueryRightsInfo err:", err.Error()) + 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 checkPhoneNum string - if errors.Is(err, gorm.ErrRecordNotFound) { // 订单表没有记录 // 查询交易流水表 var logInfo models.MgTransactionLog err = e.Orm.Table("mg_transaction_log"). @@ -87,93 +192,59 @@ func (e MiGuDeployService) SubscribeNotice(c *gin.Context) { return } - checkPhoneNum = logInfo.PhoneNumber + // 解析错误信息 + msg, _ := tools.DecodeURL(rsMsg) - // 插入订单表 - var inOrder models.MgOrder - inOrder.CreatedAt = logInfo.CreatedAt - inOrder.UpdatedAt = logInfo.UpdatedAt - inOrder.ProductID = logInfo.ProductID - inOrder.ChannelCode = logInfo.ChannelCode - inOrder.OrderSerial = logInfo.OutTradeNo - strTime := time.Now() - inOrder.SubscribeTime = &strTime - inOrder.PhoneNumber = logInfo.PhoneNumber - inOrder.SM4PhoneNumber, _ = tools.SM4Encrypt(models.SM4KEy, logInfo.PhoneNumber) - inOrder.ExternalOrderID = logInfo.LinkId - inOrder.ChannelTradeNo = logInfo.ChannelTradeNo - inOrder.State = models.SubscribeOK - - err = e.Orm.Create(&inOrder).Error + // 更新交易流水表 + 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.Info("Create MgOrder err:", err) - app.MiGuError(c, http.StatusBadRequest, err, err.Error()) + logger.Errorf("SubscribeNotice update mg_transaction_log err:", err.Error()) + app.MiGuNoticeOK(c, "failed") return } - orderInfo.ChannelCode = inOrder.ChannelCode - orderInfo.OrderSerial = inOrder.OrderSerial - orderInfo.ChannelTradeNo = inOrder.ChannelTradeNo - } else { // 订单表有记录 - checkPhoneNum = orderInfo.PhoneNumber - if orderInfo.State != 1 { - err = e.Orm.Table("mg_order").Where("external_order_id = ?", orderId).Updates(map[string]interface{}{ - "state": models.SubscribeOK, - "subscribe_time": time.Now(), - "updated_at": time.Now(), - }).Error + + // 判断是否为子渠道订购,是的话需要通知子渠道 + if models.IsValidChannelEx(logInfo.ChannelCode, e.Orm) { + channelInfo, err := models.GetChannelInfoByChannelCode(logInfo.ChannelCode, e.Orm) if err != nil { - logger.Errorf("SubscribeNotice update mg_order err:", err.Error()) - app.MiGuNoticeOK(c, "failed") - return - } - } - } - - // 判断是否为子渠道订购,是的话需要通知子渠道 - if models.IsValidChannelEx(orderInfo.ChannelCode, e.Orm) { - channelInfo, err := models.GetChannelInfoByChannelCode(orderInfo.ChannelCode, e.Orm) - if err != nil { - fmt.Println("SubscribeNotice GetChannelInfoByChannelCode err:", err) - fmt.Println("SubscribeNotice sub_channel_code is:", orderInfo.ChannelCode) - logger.Errorf("SubscribeNotice GetChannelInfoByChannelCode err, sub_channel_code is:", orderInfo.ChannelCode) - } - - if channelInfo.SubscribeURL != "" { - for i := 0; i < 3; i++ { - resp, err := models.NoticeSubChannel(channelInfo.SubscribeURL, orderInfo.OrderSerial, - orderInfo.ChannelTradeNo, "1", channelInfo.MainChannelCode, channelInfo.Remarks) - if err != nil { - fmt.Println("NoticeSubChannel err:", err) - fmt.Println("i is:", i) - continue - } - if resp != "success" { - continue - } else { - break - } + 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) } - } else { - fmt.Println("SubscribeNotice SubscribeURL is null, sub_channel_code is:", orderInfo.ChannelCode) - logger.Error("SubscribeNotice SubscribeURL is null, sub_channel_code is:", orderInfo.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) + } } - } - var req models.QueryRightsInfoReq - req.AppChannelList = append(req.AppChannelList, models.ChannelCode) - req.Mobile = checkPhoneNum - - resp, err := models.MiGuQueryRightsInfo(&req) - if err != nil { - fmt.Println("CheckOrderState MiGuQueryRightsInfo err:", err.Error()) - logger.Errorf("CheckOrderState MiGuQueryRightsInfo err:", err.Error()) + fmt.Println("订购失败通知-end") + logger.Info("订购失败通知-end") } - fmt.Println("CheckOrderState MiGuQueryRightsInfo resp:", resp) 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 } diff --git a/app/admin/models/migu.go b/app/admin/models/migu.go index b1de017..36172be 100644 --- a/app/admin/models/migu.go +++ b/app/admin/models/migu.go @@ -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 diff --git a/tools/utils.go b/tools/utils.go index e053ec7..a500cc6 100644 --- a/tools/utils.go +++ b/tools/utils.go @@ -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 +}