package front import ( "PaymentCenter/app/constants/common" "PaymentCenter/app/constants/errorcode" "PaymentCenter/app/models/paychannelmodel" "PaymentCenter/app/services" "PaymentCenter/app/third/paymentService" "bytes" "encoding/json" "fmt" "github.com/gin-gonic/gin" "github.com/go-pay/gopay" "github.com/go-pay/gopay/alipay" "github.com/go-pay/gopay/wechat/v3" "github.com/qit-team/snow-core/log/logger" "io" "strconv" "net/http" ) // WxCallback 微信支付回调 func WxCallback(c *gin.Context) { saveLogger(c, "wx") payChannelId := c.Param("payChannelId") logger.Info(c, "WxCallback-回调数据payChannelId", payChannelId) if payChannelId == "" { c.String(http.StatusBadRequest, "%s", "fail") return } // 查询应用下的支付配置 var payChannelModel paychannelmodel.PayChannel payChannelIdInt, _ := strconv.Atoi(payChannelId) payChannelModel.Id = int64(payChannelIdInt) code := services.PayChannelGet(&payChannelModel) if code == errorcode.PayChannelNotFound { logger.Error(c, "AliCallback-回调数据未获取到支付配置,404") c.String(http.StatusBadRequest, "%s", "fail") return } if payChannelModel.ChannelType != common.PAY_CHANNEL_WECHAT_H5 { logger.Error(c, "WxCallback-回调数据解析支付配置错误,查询的数据不是当前渠道") c.String(http.StatusBadRequest, "%s", "fail") return } var wxConfig paymentService.WxPay err := json.Unmarshal([]byte(payChannelModel.ExtJson), &wxConfig) if err != nil { logger.Error(c, "WxCallback-回调数据解析支付配置错误", fmt.Sprintf("错误原因:%s", err.Error())) c.String(http.StatusBadRequest, "%s", "fail") return } if wxConfig.ApiV3Key == "" || wxConfig.MchId == "" || wxConfig.PrivateKey == "" || wxConfig.SerialNo == "" { logger.Error(c, "WxCallback-回调数据解析支付配置错误,解析出来的信息为空") c.String(http.StatusBadRequest, "%s", "fail") return } wxConfig.AppId = payChannelModel.AppId notifyReq, err := wechat.V3ParseNotify(c.Request) if err != nil { logger.Error(c, "WxCallback-回调数据验签失败", err.Error()) c.String(http.StatusBadRequest, "%s", "fail") return } notifyReqJson, _ := json.Marshal(notifyReq) logger.Info(c, "WxCallback-解析微信回调请求的参数到 V3NotifyReq 结构体", string(notifyReqJson)) err = paymentService.WxPayCallBack(notifyReq, wxConfig) if err != nil { logger.Error(c, "WxCallback-回调执行失败,失败原因:", err.Error()) c.String(http.StatusBadRequest, "%s", "fail") return } c.JSON(http.StatusOK, &wechat.V3NotifyRsp{Code: gopay.SUCCESS, Message: "成功"}) return } // AliCallback 支付宝支付回调 func AliCallback(c *gin.Context) { saveLogger(c, "ALI") payChannelId := c.Param("payChannelId") logger.Info(c, "AliCallback-回调数据APPID", payChannelId) if payChannelId == "" { c.String(http.StatusBadRequest, "%s", "fail") return } // 查询应用下的支付配置 var payChannelModel paychannelmodel.PayChannel payChannelIdInt, _ := strconv.Atoi(payChannelId) payChannelModel.Id = int64(payChannelIdInt) code := services.PayChannelGet(&payChannelModel) if code == errorcode.PayChannelNotFound { logger.Error(c, "AliCallback-回调数据未获取到支付配置,404") c.String(http.StatusBadRequest, "%s", "fail") return } if payChannelModel.ChannelType != common.PAY_CHANNEL_ALIPAY_WEB { logger.Error(c, "AliCallback-回调数据解析支付配置错误,查询的数据不是当前渠道") c.String(http.StatusBadRequest, "%s", "fail") return } var aliConfig paymentService.AliPay err := json.Unmarshal([]byte(payChannelModel.ExtJson), &aliConfig) if err != nil { logger.Error(c, "AliCallback-回调数据解析支付配置错误", fmt.Sprintf("错误原因:%s", err.Error())) c.String(http.StatusBadRequest, "%s", "fail") return } if aliConfig.AlipayPublicCert == "" || aliConfig.PrivateKey == "" || aliConfig.AppPublicCert == "" || aliConfig.AlipayRootCert == "" { logger.Error(c, "AliCallback-回调数据解析支付配置错误,解析出来的信息为空") c.String(http.StatusBadRequest, "%s", "fail") return } aliConfig.AppId = payChannelModel.AppId notifyReq, err := alipay.ParseNotifyToBodyMap(c.Request) // c.Request 是 gin 框架的写法 if err != nil { c.String(http.StatusBadRequest, "%s", "fail") return } notifyReqJson, _ := json.Marshal(notifyReq) logger.Info(c, "AliCallback-解析支付宝支付异步通知的参数到BodyMap", string(notifyReqJson)) err = paymentService.ALiCallBack(notifyReq, aliConfig) if err != nil { logger.Error(c, "AliCallback-回调执行失败,失败原因:", err.Error()) c.String(http.StatusBadRequest, "%s", "fail") return } c.String(http.StatusOK, "%s", "success") return } func saveLogger(c *gin.Context, payType string) { // 保存请求的方法和URL method := c.Request.Method url := c.Request.URL.String() // 保存请求头 headers := make(map[string]string) for k, v := range c.Request.Header { headers[k] = v[0] } // 保存请求体 var bodyBytes []byte if c.Request.Body != nil { bodyBytes, _ = io.ReadAll(c.Request.Body) } // 由于 io.ReadAll 会将 body 读完,所以需要重新赋值 c.Request.Body = io.NopCloser(bytes.NewBuffer(bodyBytes)) // 使用 logger 记录请求信息 logger.Info(c, "支付回调"+payType, fmt.Sprintf("接受的参数:method: %s , url: %s , headers: %s , body: %s", method, url, headers, string(bodyBytes))) c.Next() }