62 lines
2.0 KiB
Go
62 lines
2.0 KiB
Go
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
|
|
}
|