package wechat import ( "context" "encoding/json" "bsm/full/module/finance/wallet/internal/config" "bsm/full/module/finance/wallet/internal/models" pb "bsm/full/module/finance/wallet/pb" "git.apinb.com/bsm-sdk/core/errcode" "git.apinb.com/bsm-sdk/core/printer" "github.com/go-pay/gopay/wechat/v3" ) // 微信支付回调 // 完成验签与解密后,按商户订单号反查本地支付单、核对金额, // 条件更新为支付成功并在同一事务内入账写流水。 func WxCallback(ctx context.Context, in *pb.WxCallBackRequest) (reply *pb.CallBackReply, err error) { var notifyReq = &wechat.V3NotifyReq{} data, err := json.Marshal(in) if err != nil { return nil, errcode.ErrJsonMarshal } err = json.Unmarshal(data, ¬ifyReq) if err != nil { return nil, errcode.ErrJsonUnmarshal } wx, err := NewWechat() if err != nil { printer.Error(err.Error()) return &pb.CallBackReply{Code: "FAIL", Message: "支付客户端初始化失败"}, nil } pubKey := wx.Client.WxPublicKeyMap() err = notifyReq.VerifySignByPKMap(pubKey) if err != nil { printer.Error(err.Error()) return &pb.CallBackReply{Code: "FAIL", Message: "验签失败"}, nil } res, err := notifyReq.DecryptPayCipherText(config.Spec.WeChat.APIV3Key) if err != nil { printer.Error(err.Error()) return &pb.CallBackReply{Code: "FAIL", Message: "解密失败"}, err } // 仅处理支付成功通知,其余状态直接应答,避免渠道重复推送 if res.TradeState != "SUCCESS" { return &pb.CallBackReply{Code: "SUCCESS", Message: res.TradeState}, nil } if res.Amount == nil { return &pb.CallBackReply{Code: "FAIL", Message: "金额缺失"}, nil } // 结算:金额核对 + 条件更新为成功 + 事务内入账写流水(幂等) if err := models.SettlePaymentSuccess(res.OutTradeNo, res.TransactionId, int64(res.Amount.Total)); err != nil { printer.Error(err.Error()) return &pb.CallBackReply{Code: "FAIL", Message: "结算失败"}, nil } return &pb.CallBackReply{Code: "SUCCESS", Message: "SUCCESS"}, nil }