From 43e7aee9c2f022e557c23269b3651e7c54269f2c Mon Sep 17 00:00:00 2001 From: wucongxing8150 <815046773@qq.com> Date: Fri, 9 Aug 2024 18:24:32 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BA=86=E9=80=80=E6=AC=BE?= =?UTF-8?q?=E7=9B=B8=E5=85=B3=E6=8E=A5=E5=8F=A3=EF=BC=8C=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E4=BA=86=E9=80=80=E6=AC=BE=E5=9B=9E=E8=B0=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/controller/CallBack.go | 308 +++++++++++++++++++++++++++++------ api/router/router.go | 18 +- api/service/OrderMember.go | 20 ++- api/service/OrderSingle.go | 26 ++- config.yaml | 6 +- extend/weChat/base.go | 86 +++++----- extend/weChat/parseNotify.go | 39 ++++- utils/intToString.go | 48 ++++++ 8 files changed, 433 insertions(+), 118 deletions(-) diff --git a/api/controller/CallBack.go b/api/controller/CallBack.go index 17329b0..dc947fc 100644 --- a/api/controller/CallBack.go +++ b/api/controller/CallBack.go @@ -17,7 +17,7 @@ type CallBack struct{} // WxPaySingle 微信支付回调-单项 func (r *CallBack) WxPaySingle(c *gin.Context) { - notifyReq, transaction, err := weChat.ParseNotify(c) + notifyReq, transaction, err := weChat.PayParseNotify(c) if err != nil { responses.FailWithMessage(err.Error(), c) return @@ -60,8 +60,8 @@ func (r *CallBack) WxPaySingle(c *gin.Context) { return } - // 处理支付状态 - wxPayResult, err := weChat.HandlePayStatus(transaction) + // 处理回调支付状态 + wxResult, err := weChat.HandlePayStatus(transaction) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"code": "ERROR", "message": err}) return @@ -77,18 +77,15 @@ func (r *CallBack) WxPaySingle(c *gin.Context) { // 修改订单 orderSingleData := make(map[string]interface{}) - if wxPayResult.OrderStatus != nil { - orderSingleData["order_status"] = &wxPayResult.OrderStatus - } - orderSingleData["pay_status"] = &wxPayResult.PayStatus - if wxPayResult.PayTime != nil { - orderSingleData["pay_time"] = &wxPayResult.PayTime + orderSingleData["order_status"] = wxResult.OrderStatus + orderSingleData["pay_status"] = wxResult.PayStatus + if wxResult.PayTime != nil { + orderSingleData["pay_time"] = *wxResult.PayTime } orderSingleData["escrow_trade_no"] = transaction.TransactionId - orderSingleData["updated_at"] = time.Now().Format("2006-01-02 15:04:05") // 处理单项有效时间 - if *wxPayResult.PayStatus == 2 { + if wxResult.PayStatus == 2 { systemSingleDao := dao.SystemSingleDao{} maps := make(map[string]interface{}) @@ -109,22 +106,24 @@ func (r *CallBack) WxPaySingle(c *gin.Context) { return } - // 增加单项支付次数 - questionService := service.QuestionService{} - res, err := questionService.AddQuestionPayCount(tx, orderSingle.QuestionId) - if err != nil || res == false { - tx.Rollback() - responses.FailWithMessage("内部错误", c) - return - } + if wxResult.PayStatus == 2 { + // 增加单项支付次数 + questionService := service.QuestionService{} + res, err := questionService.AddQuestionPayCount(tx, orderSingle.QuestionId) + if err != nil || res == false { + tx.Rollback() + responses.FailWithMessage("内部错误", c) + return + } - // 增加用户单项支付次数 - userService := service.UserService{} - res, err = userService.AddUserSingleSubmitCount(tx, orderSingle.UserId) - if err != nil || res == false { - tx.Rollback() - responses.FailWithMessage("内部错误", c) - return + // 增加用户单项支付次数 + userService := service.UserService{} + res, err = userService.AddUserSingleSubmitCount(tx, orderSingle.UserId) + if err != nil || res == false { + tx.Rollback() + responses.FailWithMessage("内部错误", c) + return + } } tx.Commit() @@ -133,7 +132,7 @@ func (r *CallBack) WxPaySingle(c *gin.Context) { // WxPayMember 微信支付回调-会员 func (r *CallBack) WxPayMember(c *gin.Context) { - notifyReq, transaction, err := weChat.ParseNotify(c) + notifyReq, transaction, err := weChat.PayParseNotify(c) if err != nil { responses.FailWithMessage(err.Error(), c) return @@ -176,8 +175,8 @@ func (r *CallBack) WxPayMember(c *gin.Context) { return } - // 处理支付状态 - wxPayResult, err := weChat.HandlePayStatus(transaction) + // 处理回调支付状态 + wxResult, err := weChat.HandlePayStatus(transaction) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"code": "ERROR", "message": err}) return @@ -201,15 +200,12 @@ func (r *CallBack) WxPayMember(c *gin.Context) { // 修改订单 orderSingleData := make(map[string]interface{}) - if wxPayResult.OrderStatus != nil { - orderSingleData["order_status"] = &wxPayResult.OrderStatus - } - orderSingleData["pay_status"] = &wxPayResult.PayStatus - if wxPayResult.PayTime != nil { - orderSingleData["pay_time"] = &wxPayResult.PayTime + orderSingleData["order_status"] = wxResult.OrderStatus + orderSingleData["pay_status"] = wxResult.PayStatus + if wxResult.PayTime != nil { + orderSingleData["pay_time"] = *wxResult.PayTime } orderSingleData["escrow_trade_no"] = transaction.TransactionId - orderSingleData["updated_at"] = time.Now().Format("2006-01-02 15:04:05") err = orderMemberDao.EditOrderMemberById(tx, orderMember.OrderId, orderSingleData) if err != nil { tx.Rollback() @@ -217,8 +213,9 @@ func (r *CallBack) WxPayMember(c *gin.Context) { return } - // 处理未支付单项订单 - if *wxPayResult.OrderStatus == 2 { + // 处理支付成功情况 + if wxResult.OrderStatus == 2 { + // 完成未支付单项订单 orderSingleService := service.OrderSingleService{} res, err := orderSingleService.CompleteUnPayOrderSingle(tx, orderMember.UserId) if err != nil || res == false { @@ -226,10 +223,8 @@ func (r *CallBack) WxPayMember(c *gin.Context) { c.JSON(http.StatusInternalServerError, gin.H{"code": "ERROR", "message": err}) return } - } - // 处理用户会员过期时间 - if *wxPayResult.OrderStatus == 2 { + // 处理用户会员过期时间 // 获取订单配置 systemMemberDao := dao.SystemMemberDao{} systemMember, err := systemMemberDao.GetSystemMemberById(orderMember.SystemMemberId) @@ -240,23 +235,240 @@ func (r *CallBack) WxPayMember(c *gin.Context) { } userService := service.UserService{} - res := userService.AddUserMemberValidDate(tx, user, int(systemMember.MemberDays)) + res = userService.AddUserMemberValidDate(tx, user, int(systemMember.MemberDays)) if res == false { tx.Rollback() c.JSON(http.StatusInternalServerError, gin.H{"code": "ERROR", "message": "增加用户会员到期时间失败"}) return } + + // 增加用户会员购买次数 + res, err = userService.AddUserMemberBuyCount(tx, user.UserId) + if err != nil || res == false { + tx.Rollback() + c.JSON(http.StatusInternalServerError, gin.H{"code": "ERROR", "message": "增加用户会员到期时间失败"}) + return + } } - // 增加用户单项提交次数 - userService := service.UserService{} - res, err := userService.AddUserMemberBuyCount(tx, user.UserId) - if err != nil || res == false { - tx.Rollback() - c.JSON(http.StatusInternalServerError, gin.H{"code": "ERROR", "message": "增加用户会员到期时间失败"}) + tx.Commit() + c.JSON(http.StatusOK, gin.H{"code": "SUCCESS", "message": "OK"}) +} + +// WxPaySingleRefund 微信退款回调-单项 +func (r *CallBack) WxPaySingleRefund(c *gin.Context) { + notifyReq, refund, err := weChat.RefundParseNotify(c) + if err != nil { + responses.FailWithMessage(err.Error(), c) return } + // 记录日志 + utils.LogJsonErr("微信退款回调-单项", notifyReq) + utils.LogJsonErr("微信退款回调-单项", refund) + + if refund == nil { + c.JSON(http.StatusBadRequest, gin.H{"code": "ERROR", "message": "缺少订单数据"}) + return + } + + if refund.OutTradeNo == nil { + c.JSON(http.StatusBadRequest, gin.H{"code": "ERROR", "message": "缺少外部订单号"}) + return + } + + // 查询订单 + orderSingleDao := dao.OrderSingleDao{} + maps := make(map[string]interface{}) + maps["order_no"] = refund.OutTradeNo + orderSingle, err := orderSingleDao.GetOrderSingle(maps) + if err != nil || orderSingle == nil { + c.JSON(http.StatusBadRequest, gin.H{"code": "ERROR", "message": "无订单数据"}) + return + } + + // 验证订单状态-订单状态(1:待支付 2:已完成 3:已取消) + if orderSingle.OrderStatus == 1 { + message := "订单状态:" + utils.OrderSingleStatusToString(orderSingle.OrderStatus) + " 无需处理" + c.JSON(http.StatusOK, gin.H{"code": "SUCCESS", "message": message}) + return + } + + // 验证订单退款状态(0:无退款 1:申请退款 2:退款中 3:退款成功 4:拒绝退款 5:退款关闭 6:退款异常 7:部分退款) + if orderSingle.RefundStatus == 3 { + message := "订单状态:" + utils.OrderSingleRefundStatusToString(orderSingle.RefundStatus) + " 无需处理" + c.JSON(http.StatusOK, gin.H{"code": "SUCCESS", "message": message}) + return + } + + // 验证订单支付状态(1:未支付 2:已支付 3:支付中 4:支付失败 5:支付超时 6:支付关闭 7:已撤销 8:转入退款) + if orderSingle.PayStatus != 2 && orderSingle.PayStatus != 8 { + message := "订单状态:" + utils.OrderSinglePayStatusToString(orderSingle.RefundStatus) + " 无需处理" + c.JSON(http.StatusOK, gin.H{"code": "SUCCESS", "message": message}) + return + } + + // 处理回调支付状态 + wxResult, err := weChat.HandlePayRefundStatus(refund) + if err != nil { + c.JSON(http.StatusBadRequest, gin.H{"code": "ERROR", "message": err}) + return + } + + // 开始事务 + tx := global.Db.Begin() + defer func() { + if r := recover(); r != nil { + tx.Rollback() + } + }() + + // 修改订单 + orderSingleData := make(map[string]interface{}) + orderSingleData["refund_status"] = wxResult.RefundStatus + err = orderSingleDao.EditOrderSingleById(tx, orderSingle.OrderId, orderSingleData) + if err != nil { + tx.Rollback() + c.JSON(http.StatusBadRequest, gin.H{"code": "ERROR", "message": err}) + return + } + + // 修改订单退款 + orderSingleRefundDao := dao.OrderSingleRefundDao{} + + orderSingleRefundData := make(map[string]interface{}) + orderSingleRefundData["refund_status"] = wxResult.RefundStatus + if wxResult.SuccessTime != nil { + orderSingleRefundData["success_time"] = *wxResult.SuccessTime + } + err = orderSingleRefundDao.EditOrderSingleRefundById(tx, orderSingle.OrderId, orderSingleRefundData) + if err != nil { + tx.Rollback() + c.JSON(http.StatusBadRequest, gin.H{"code": "ERROR", "message": err}) + return + } + + // 处理退款成功情况 + if wxResult.RefundStatus == 3 { + // 退还订单优惠卷 + orderSingleService := service.OrderSingleService{} + err = orderSingleService.OrderCouponRefund(tx, orderSingle) + if err != nil { + tx.Rollback() + c.JSON(http.StatusBadRequest, gin.H{"code": "ERROR", "message": err}) + return + } + } + + tx.Commit() + c.JSON(http.StatusOK, gin.H{"code": "SUCCESS", "message": "OK"}) +} + +// WxPayMemberRefund 微信退款回调-会员 +func (r *CallBack) WxPayMemberRefund(c *gin.Context) { + notifyReq, refund, err := weChat.RefundParseNotify(c) + if err != nil { + responses.FailWithMessage(err.Error(), c) + return + } + + // 记录日志 + utils.LogJsonErr("微信退款回调-会员", notifyReq) + utils.LogJsonErr("微信退款回调-会员", refund) + + if refund == nil { + c.JSON(http.StatusBadRequest, gin.H{"code": "ERROR", "message": "缺少订单数据"}) + return + } + + if refund.OutTradeNo == nil { + c.JSON(http.StatusBadRequest, gin.H{"code": "ERROR", "message": "缺少外部订单号"}) + return + } + + // 查询订单 + orderMemberDao := dao.OrderMemberDao{} + maps := make(map[string]interface{}) + maps["order_no"] = refund.OutTradeNo + orderMember, err := orderMemberDao.GetOrderMember(maps) + if err != nil || orderMember == nil { + c.JSON(http.StatusBadRequest, gin.H{"code": "ERROR", "message": "无订单数据"}) + return + } + + // 验证订单状态-订单状态(1:待支付 2:已完成 3:已取消) + if orderMember.OrderStatus == 1 { + message := "订单状态:" + utils.OrderSingleStatusToString(orderMember.OrderStatus) + " 无需处理" + c.JSON(http.StatusOK, gin.H{"code": "SUCCESS", "message": message}) + return + } + + // 验证订单退款状态(0:无退款 1:申请退款 2:退款中 3:退款成功 4:拒绝退款 5:退款关闭 6:退款异常 7:部分退款) + if orderMember.RefundStatus == 3 { + message := "订单状态:" + utils.OrderSingleRefundStatusToString(orderMember.RefundStatus) + " 无需处理" + c.JSON(http.StatusOK, gin.H{"code": "SUCCESS", "message": message}) + return + } + + // 验证订单支付状态(1:未支付 2:已支付 3:支付中 4:支付失败 5:支付超时 6:支付关闭 7:已撤销 8:转入退款) + if orderMember.PayStatus != 2 && orderMember.PayStatus != 8 { + message := "订单状态:" + utils.OrderSinglePayStatusToString(orderMember.RefundStatus) + " 无需处理" + c.JSON(http.StatusOK, gin.H{"code": "SUCCESS", "message": message}) + return + } + + // 处理回调支付状态 + wxResult, err := weChat.HandlePayRefundStatus(refund) + if err != nil { + c.JSON(http.StatusBadRequest, gin.H{"code": "ERROR", "message": err}) + return + } + + // 开始事务 + tx := global.Db.Begin() + defer func() { + if r := recover(); r != nil { + tx.Rollback() + } + }() + + // 修改订单 + orderMemberData := make(map[string]interface{}) + orderMemberData["refund_status"] = wxResult.RefundStatus + err = orderMemberDao.EditOrderMemberById(tx, orderMember.OrderId, orderMemberData) + if err != nil { + tx.Rollback() + c.JSON(http.StatusBadRequest, gin.H{"code": "ERROR", "message": err}) + return + } + + // 修改订单退款 + orderMemberRefundDao := dao.OrderMemberRefundDao{} + + orderMemberRefundData := make(map[string]interface{}) + orderMemberRefundData["refund_status"] = wxResult.RefundStatus + if wxResult.SuccessTime != nil { + orderMemberRefundData["success_time"] = *wxResult.SuccessTime + } + err = orderMemberRefundDao.EditOrderMemberRefundById(tx, orderMember.OrderId, orderMemberRefundData) + if err != nil { + tx.Rollback() + c.JSON(http.StatusBadRequest, gin.H{"code": "ERROR", "message": err}) + return + } + + // 处理退款成功情况 + if wxResult.RefundStatus == 3 { + // 退还订单优惠卷 + orderMemberService := service.OrderMemberService{} + err = orderMemberService.OrderCouponRefund(tx, orderMember) + if err != nil { + tx.Rollback() + c.JSON(http.StatusBadRequest, gin.H{"code": "ERROR", "message": err}) + return + } + } + tx.Commit() c.JSON(http.StatusOK, gin.H{"code": "SUCCESS", "message": "OK"}) } diff --git a/api/router/router.go b/api/router/router.go index 8547ba1..f2e510b 100644 --- a/api/router/router.go +++ b/api/router/router.go @@ -99,10 +99,24 @@ func publicRouter(r *gin.Engine, api controller.Api) { wxpayGroup := callbackGroup.Group("/wxpay") { // 单项 - wxpayGroup.POST("/single", api.CallBack.WxPaySingle) + singleGroup := wxpayGroup.Group("/single") + { + // 支付成功 + singleGroup.POST("", api.CallBack.WxPaySingle) + + // 退款 + singleGroup.POST("/refund", api.CallBack.WxPaySingleRefund) + } // 会员 - wxpayGroup.POST("/member", api.CallBack.WxPayMember) + memberGroup := wxpayGroup.Group("/member") + { + // 支付成功 + memberGroup.POST("/", api.CallBack.WxPayMember) + + // 退款 + memberGroup.POST("/refund", api.CallBack.WxPayMemberRefund) + } } } } diff --git a/api/service/OrderMember.go b/api/service/OrderMember.go index 23afba3..b136d2c 100644 --- a/api/service/OrderMember.go +++ b/api/service/OrderMember.go @@ -62,7 +62,7 @@ func (r *OrderMemberService) AddOrderMember(tx *gorm.DB, UserId, SystemMemberId diffDays := int(diff.Hours() / 24) totalDays := diffDays + int(systemMember.MemberDays) if totalDays > 180 { - return nil, errors.New("超出会员有效期") + return nil, errors.New("超出会员最大购买天数") } } @@ -241,6 +241,8 @@ func (r *OrderMemberService) CancelOrderSingle(tx *gorm.DB, orderMember *model.O } // 修改订单为取消 + orderMemberDao := dao.OrderMemberDao{} + orderMemberData := make(map[string]interface{}) orderMemberData["order_status"] = 3 if cancelReason == 3 { @@ -250,19 +252,19 @@ func (r *OrderMemberService) CancelOrderSingle(tx *gorm.DB, orderMember *model.O orderMemberData["cancel_status"] = 1 orderMemberData["cancel_time"] = time.Now().Format("2006-01-02 15:04:05") orderMemberData["cancel_remarks"] = utils.OrderCancelReasonToString(cancelReason) - orderMemberData["updated_at"] = time.Now().Format("2006-01-02 15:04:05") - - orderMemberDao := dao.OrderMemberDao{} err = orderMemberDao.EditOrderMemberById(tx, orderMember.OrderId, orderMemberData) if err != nil { return false, errors.New("订单取消失败") } - // 退还订单优惠卷 - err = r.OrderCouponRefund(tx, orderMember) - if err != nil { - tx.Rollback() - return false, err + // 处理支付金额为0时退还优惠卷问题 + if orderMember.PaymentAmountTotal == 0 { + // 退还订单优惠卷 + err = r.OrderCouponRefund(tx, orderMember) + if err != nil { + tx.Rollback() + return false, err + } } return true, nil diff --git a/api/service/OrderSingle.go b/api/service/OrderSingle.go index 503d3f5..ccd89b5 100644 --- a/api/service/OrderSingle.go +++ b/api/service/OrderSingle.go @@ -274,6 +274,8 @@ func (r *OrderSingleService) CancelOrderSingle(tx *gorm.DB, orderSingle *model.O } // 修改订单为取消 + orderSingleDao := dao.OrderSingleDao{} + orderSingleData := make(map[string]interface{}) orderSingleData["order_status"] = 3 if cancelReason == 3 { @@ -283,19 +285,19 @@ func (r *OrderSingleService) CancelOrderSingle(tx *gorm.DB, orderSingle *model.O orderSingleData["cancel_status"] = 1 orderSingleData["cancel_time"] = time.Now().Format("2006-01-02 15:04:05") orderSingleData["cancel_remarks"] = utils.OrderCancelReasonToString(cancelReason) - orderSingleData["updated_at"] = time.Now().Format("2006-01-02 15:04:05") - - orderSingleDao := dao.OrderSingleDao{} err = orderSingleDao.EditOrderSingleById(tx, orderSingle.OrderId, orderSingleData) if err != nil { return false, errors.New("订单取消失败") } - // 退还订单优惠卷 - err = r.OrderCouponRefund(tx, orderSingle) - if err != nil { - tx.Rollback() - return false, err + // 处理支付金额为0时退还优惠卷问题 + if orderSingle.PaymentAmountTotal == 0 { + // 退还订单优惠卷 + err = r.OrderCouponRefund(tx, orderSingle) + if err != nil { + tx.Rollback() + return false, err + } } return true, nil @@ -385,6 +387,13 @@ func (r *OrderSingleService) CompleteUnPayOrderSingle(tx *gorm.DB, userId int64) return false, err } + systemSingleDao := dao.SystemSingleDao{} + maps = make(map[string]interface{}) + systemSingle, err := systemSingleDao.GetSystemSingle(maps) + if err != nil { + return false, err + } + for _, single := range orderSingles { // 生成第三方支付流水号 escrowTradeNo := "GD" + global.Snowflake.Generate().String() @@ -395,6 +404,7 @@ func (r *OrderSingleService) CompleteUnPayOrderSingle(tx *gorm.DB, userId int64) orderSingleData["pay_time"] = time.Now().Format("2006-01-02 15:04:05") orderSingleData["escrow_trade_no"] = escrowTradeNo orderSingleData["updated_at"] = time.Now().Format("2006-01-02 15:04:05") + orderSingleData["valid_date"] = time.Now().Add(time.Duration(systemSingle.ValidDays) * 24 * time.Hour) //有效时间 err = orderSingleDao.EditOrderSingleById(tx, single.OrderId, orderSingleData) if err != nil { return false, err diff --git a/config.yaml b/config.yaml index 6817e71..44fa59d 100644 --- a/config.yaml +++ b/config.yaml @@ -50,9 +50,9 @@ wechat: app-id: wx68affaa9d23528f8 app-secret: 2963c90242ddb2421c939591ad9e903d single-pay-notify-url: callback/wxpay/single # 单项支付回调地址 - single-refund-notify-url: callback/wxpay/inquiry/refund # 单项退款回调地址 - member-pay-notify-url: callback/wxpay/single # 会员支付回调地址 - member-refund-notify-url: callback/wxpay/inquiry/refund # 会员退款回调地址 + single-refund-notify-url: callback/wxpay/single/refund # 单项退款回调地址 + member-pay-notify-url: callback/wxpay/member # 会员支付回调地址 + member-refund-notify-url: callback/wxpay/member/refund # 会员退款回调地址 refund-notify-domain: https://dev-hepa.igandan.com/api/ pay-1281030301: mch-id: 1281030301 diff --git a/extend/weChat/base.go b/extend/weChat/base.go index 98a4b9d..089dd0e 100644 --- a/extend/weChat/base.go +++ b/extend/weChat/base.go @@ -6,9 +6,9 @@ import ( "github.com/wechatpay-apiv3/wechatpay-go/core" "github.com/wechatpay-apiv3/wechatpay-go/core/option" "github.com/wechatpay-apiv3/wechatpay-go/services/payments" + "github.com/wechatpay-apiv3/wechatpay-go/services/refunddomestic" "github.com/wechatpay-apiv3/wechatpay-go/utils" "hepa-calc-api/config" - "time" ) // 创建客户端 @@ -41,65 +41,59 @@ func createClient() (*core.Client, error) { return client, nil } +// WxPayResult 支付结果 type WxPayResult struct { - OrderStatus *int `json:"order_status"` // 订单状态(1:待支付 2:已完成 3:已取消) - PayStatus *int `json:"pay_status"` // 支付状态(1:未支付 2:已支付 3:支付中 4:支付失败 5:支付超时 6:支付关闭 7:已撤销 8:转入退款) - PayTime *time.Time `json:"pay_time"` // 支付时间 + OrderStatus int `json:"order_status"` // 订单状态(1:待支付 2:已完成 3:已取消) + PayStatus int `json:"pay_status"` // 支付状态(1:未支付 2:已支付 3:支付中 4:支付失败 5:支付超时 6:支付关闭 7:已撤销 8:转入退款) + PayTime *string `json:"pay_time"` // 支付时间 +} + +// WxPayRefundResult 退款结果 +type WxPayRefundResult struct { + RefundStatus int `json:"refundStatus"` // 订单退款状态(0:无退款 1:申请退款 2:退款中 3:退款成功 4:拒绝退款 5:退款关闭 6:退款异常 7:部分退款) + SuccessTime *string `json:"successTime"` // 退款成功时间 } // HandlePayStatus 处理支付状态 func HandlePayStatus(t *payments.Transaction) (w *WxPayResult, err error) { - // 支付成功 - if *t.TradeState == "SUCCESS" { - orderStatus := 2 - w.OrderStatus = &orderStatus - - payStatus := 2 - w.PayStatus = &payStatus - - parse, err := time.Parse("2006-01-02T15:04:05+07:00", *t.SuccessTime) - if err != nil { - return nil, errors.New("支付时间处理错误") - } - - w.PayTime = &parse - if err != nil { - return nil, errors.New("支付时间错误") - } - } - switch *t.TradeState { case "SUCCESS": // 支付成功 - orderStatus := 2 - w.OrderStatus = &orderStatus - - payStatus := 2 - w.PayStatus = &payStatus - - parse, err := time.Parse("2006-01-02T15:04:05+07:00", *t.SuccessTime) - if err != nil { - return nil, errors.New("支付时间处理错误") - } - - w.PayTime = &parse - if err != nil { - return nil, errors.New("支付时间错误") - } + w.OrderStatus = 2 + w.PayStatus = 2 + w.PayTime = t.SuccessTime case "CLOSED": // 已关闭 - payStatus := 6 - w.PayStatus = &payStatus + w.PayStatus = 6 case "REVOKED": // 已撤销(付款码支付) - payStatus := 7 - w.PayStatus = &payStatus + w.PayStatus = 7 case "USERPAYING": // 用户支付中(付款码支付) - payStatus := 3 - w.PayStatus = &payStatus + w.PayStatus = 3 case "PAYERROR": // 支付失败(其他原因,如银行返回失败) - payStatus := 4 - w.PayStatus = &payStatus + w.PayStatus = 4 default: return nil, errors.New("未知支付状态") } return w, nil } + +// HandlePayRefundStatus 处理退款状态 +func HandlePayRefundStatus(r *refunddomestic.Refund) (w *WxPayRefundResult, err error) { + switch *r.Status { + case "SUCCESS": // 退款成功 + w.RefundStatus = 3 + if r.SuccessTime != nil { + successTime := r.SuccessTime.Format("2006-01-02 15:04:05") + w.SuccessTime = &successTime + } + case "CLOSED": // 退款关闭 + w.RefundStatus = 5 + case "PROCESSING": // 退款处理中 + w.RefundStatus = 2 + case "ABNORMAL": // 退款异常 + return nil, errors.New("退款状态错误") + default: + return nil, errors.New("退款状态错误") + } + + return w, nil +} diff --git a/extend/weChat/parseNotify.go b/extend/weChat/parseNotify.go index 9152cbc..11d09d8 100644 --- a/extend/weChat/parseNotify.go +++ b/extend/weChat/parseNotify.go @@ -8,12 +8,13 @@ import ( "github.com/wechatpay-apiv3/wechatpay-go/core/downloader" "github.com/wechatpay-apiv3/wechatpay-go/core/notify" "github.com/wechatpay-apiv3/wechatpay-go/services/payments" + "github.com/wechatpay-apiv3/wechatpay-go/services/refunddomestic" "github.com/wechatpay-apiv3/wechatpay-go/utils" "hepa-calc-api/config" ) -// ParseNotify 回调通知的验签与解密 -func ParseNotify(c *gin.Context) (notifyReq *notify.Request, t *payments.Transaction, err error) { +// PayParseNotify 支付回调通知的验签与解密 +func PayParseNotify(c *gin.Context) (notifyReq *notify.Request, t *payments.Transaction, err error) { mchId := config.C.Wechat.Pay1281030301.MchId // 商户号 mchCertificateSerialNumber := config.C.Wechat.Pay1281030301.MchCertificateSerialNumber // 商户证书序列号 v3ApiSecret := config.C.Wechat.Pay1281030301.V3ApiSecret // 商户APIv3密钥 @@ -45,3 +46,37 @@ func ParseNotify(c *gin.Context) (notifyReq *notify.Request, t *payments.Transac return notifyReq, transaction, nil } + +// RefundParseNotify 退款回调通知的验签与解密 +func RefundParseNotify(c *gin.Context) (notifyReq *notify.Request, t *refunddomestic.Refund, err error) { + mchId := config.C.Wechat.Pay1281030301.MchId // 商户号 + mchCertificateSerialNumber := config.C.Wechat.Pay1281030301.MchCertificateSerialNumber // 商户证书序列号 + v3ApiSecret := config.C.Wechat.Pay1281030301.V3ApiSecret // 商户APIv3密钥 + privateKeyPath := "extend/weChat/certs/" + config.C.Wechat.Pay1281030301.MchId + "/apiclient_key.pem" // 商户私钥文件地址 + + // 使用 utils 提供的函数从本地文件中加载商户私钥,商户私钥会用来生成请求的签名 + mchPrivateKey, err := utils.LoadPrivateKeyWithPath(privateKeyPath) + if err != nil { + return nil, nil, errors.New("微信支付生成失败") + } + + // 1. 使用 `RegisterDownloaderWithPrivateKey` 注册下载器 + err = downloader.MgrInstance().RegisterDownloaderWithPrivateKey(c, mchPrivateKey, mchCertificateSerialNumber, mchId, v3ApiSecret) + if err != nil { + return nil, nil, err + } + + // 2. 获取商户号对应的微信支付平台证书访问器 + certificateVisitor := downloader.MgrInstance().GetCertificateVisitor(mchId) + // 3. 使用证书访问器初始化 `notify.Handler` + handler, err := notify.NewRSANotifyHandler(v3ApiSecret, verifiers.NewSHA256WithRSAVerifier(certificateVisitor)) + + refund := new(refunddomestic.Refund) + notifyReq, err = handler.ParseNotifyRequest(context.Background(), c.Request, refund) + // 如果验签未通过,或者解密失败 + if err != nil { + return nil, nil, err + } + + return notifyReq, refund, nil +} diff --git a/utils/intToString.go b/utils/intToString.go index c760f47..e730d41 100644 --- a/utils/intToString.go +++ b/utils/intToString.go @@ -27,3 +27,51 @@ func OrderSingleStatusToString(i int) string { return "未知" } } + +// OrderSingleRefundStatusToString 订单退款状态(0:无退款 1:申请退款 2:退款中 3:退款成功 4:拒绝退款 5:退款关闭 6:退款异常 7:部分退款) +func OrderSingleRefundStatusToString(i int) string { + switch i { + case 0: + return "无退款" + case 1: + return "申请退款" + case 2: + return "退款中" + case 3: + return "退款成功" + case 4: + return "拒绝退款" + case 5: + return "退款关闭" + case 6: + return "退款异常" + case 7: + return "部分退款" + default: + return "未知" + } +} + +// OrderSinglePayStatusToString 订单支付状态(1:未支付 2:已支付 3:支付中 4:支付失败 5:支付超时 6:支付关闭 7:已撤销 8:转入退款) +func OrderSinglePayStatusToString(i int) string { + switch i { + case 1: + return "未支付" + case 2: + return "已支付" + case 3: + return "支付中" + case 4: + return "支付失败" + case 5: + return "支付超时" + case 6: + return "支付关闭" + case 7: + return "已撤销" + case 8: + return "转入退款" + default: + return "未知" + } +}