package pay import ( "encoding/json" "io" "net/http" "qnc-server/app/main/api/internal/service" "qnc-server/app/main/api/internal/svc" "github.com/zeromicro/go-zero/core/logx" ) type XpayPushLogic struct { logx.Logger svcCtx *svc.ServiceContext } func NewXpayPushLogic(svcCtx *svc.ServiceContext) *XpayPushLogic { return &XpayPushLogic{svcCtx: svcCtx} } // HandleGET mp 后台配置消息推送时的验签 func (l *XpayPushLogic) HandleGET(w http.ResponseWriter, r *http.Request) { q := r.URL.Query() signature := q.Get("signature") timestamp := q.Get("timestamp") nonce := q.Get("nonce") echostr := q.Get("echostr") if l.svcCtx.XpayService.VerifyPushSignature(signature, timestamp, nonce) { w.WriteHeader(http.StatusOK) _, _ = w.Write([]byte(echostr)) return } w.WriteHeader(http.StatusForbidden) } // HandlePOST 接收 xpay_goods_deliver_notify func (l *XpayPushLogic) HandlePOST(w http.ResponseWriter, r *http.Request) { body, err := io.ReadAll(r.Body) if err != nil { l.writePushResp(w, 1, "read body failed") return } var notify service.XpayDeliverNotify if err := json.Unmarshal(body, ¬ify); err != nil { l.writePushResp(w, 1, "parse failed") return } if notify.Event != "" && notify.Event != "xpay_goods_deliver_notify" { l.writePushResp(w, 0, "ignored") return } orderNo := notify.OutTradeNo if orderNo == "" { l.writePushResp(w, 1, "missing OutTradeNo") return } ctx := r.Context() logx.WithContext(ctx).Infof("[xpay:push] recv event=%s order_no=%s openid=%s env=%d body=%s", notify.Event, orderNo, notify.OpenId, notify.Env, string(body)) already, _ := l.svcCtx.XpayService.AlreadyNotified(ctx, orderNo) if already { l.writePushResp(w, 0, "already notified") return } order, findErr := l.svcCtx.OrderModel.FindOneByOrderNo(ctx, orderNo) if findErr != nil { logx.WithContext(ctx).Errorf("[xpay push] 订单不存在 order_no=%s err=%v", orderNo, findErr) l.writePushResp(w, 1, "order not found") return } wxOrderID := notify.WeChatPayInfo.TransactionId credited, fulfillErr := fulfillQueryOrderPaid(ctx, l.svcCtx, order, wxOrderID, notify.GoodsInfo.ActualPrice) if fulfillErr != nil { logx.WithContext(ctx).Errorf("[xpay push] 到账失败 order_no=%s err=%v", orderNo, fulfillErr) l.writePushResp(w, 1, fulfillErr.Error()) return } _ = l.svcCtx.XpayService.MarkNotified(ctx, orderNo) logx.WithContext(ctx).Infof("[xpay push] event=xpay_goods_deliver_notify order_no=%s credited=%v", orderNo, credited) l.writePushResp(w, 0, "success") } func (l *XpayPushLogic) writePushResp(w http.ResponseWriter, errCode int, errMsg string) { w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) _ = json.NewEncoder(w).Encode(map[string]interface{}{ "ErrCode": errCode, "ErrMsg": errMsg, }) }