go-zero之支付回调问题

go-zero之支付回调问题

微信与支付宝支付

之前写的支付回调的逻辑在网关层处理,网关一般是接收参数,响应数据。所以有些不合理。下面做了些处理

微信支付回调

这里用的是官方的SDK, V3版本

下面是微信支付API接口,需要在handler传入 *http.Request

func WxNotifyHandleHandler(ctx *svc.ServiceContext) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        l := order.NewWxNotifyHandleLogic(r.Context(), ctx)
        resp, err := l.WxNotifyHandle(r)    // 这里需要传入http.Request
        if err != nil {
            httpx.Error(w, err)
        } else {
            httpx.OkJson(w, resp)
        }
    }
}

api请求rpc之前,封装下请求参数类型,需要rpc能接受的类型

// 微信支付回调
func (l *WxNotifyHandleLogic) WxNotifyHandle(req *http.Request) (*types.WxNotifyResp, error) {
    // header 转成byte类型,方便rpc定义的pb语法类型
    header,_ := json.Marshal(req.Header)
    // body 也是一样
    body, err := getRequestBody(req)
    ....
}

func getRequestBody(request *http.Request) ([]byte, error) {
    body, err := ioutil.ReadAll(request.Body)
    if err != nil {
        return nil, errors.New("读取body错误:%s")
    }

    _ = request.Body.Close()
    request.Body = ioutil.NopCloser(bytes.NewBuffer(body))

    return body, nil
}

下面是rpc来解封参数,转成*http.Request类型,来验证密钥或证书等


//  RPC微信回调
func (l *WxPayNotifyLogic) WxPayNotify(in *order.WxPayNotifyRequest) (*order.Response, error) {
    notifyUrl := l.svcCtx.Config.WxPay.NotifyUrl

    // 从api拿到req body, 然后再转成 *http.Request
    req, _ := http.NewRequest(http.MethodPost, notifyUrl, strings.NewReader(string(in.Body)))
    var mapHeader http.Header
    _ = json.Unmarshal(in.Header, &mapHeader)
    for k, v := range mapHeader {
        req.Header.Add(k, v[0])
    }

    ...
}

支付宝回调

sdk github

由于sdk提供了一个bodyjson的方法,所以比微信操作还要简单

// 支付宝回调
func (l *AliPayNotifyHandleLogic) AliPayNotifyHandle(req *http.Request, resp http.ResponseWriter) {
    // 把req 解析成map
    notifyReq, err := alipay.ParseNotifyToBodyMap(req)
    if err != nil {
        logx.Error("支付宝回调解析req错误:", err)
        return
    }
    // body转成json
    notifyBody := notifyReq.JsonBody()

    // 传入rpc
    result, err := l.svcCtx.OrderClient.AliPayNotify(l.ctx, &orderclient.AliPayNotifyRequest{
        Body:   notifyBody,
    })

    ...
}

rpc这里把json转成map

// 支付宝回调
func (l *AliPayNotifyLogic) AliPayNotify(in *order.AliPayNotifyRequest) (*order.Response, error) {

    // json 转 map
    var bodyMap gopay.BodyMap
    _ = json.Unmarshal([]byte(in.Body), &bodyMap)

    // 传入map来公钥证书内容,验证签名
    ok, err := alipay.VerifySignWithCert(aliPayCertPublicKeyContent, bodyMap)
    ...

}

至此,网关只负责处理参数,返回数据,rpc来处理业务逻辑。实现网关层与业务层分离。

本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 2

完全可以把参数encoder为字符串,传递到具体的rpc中去处理

2年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!
未填写
文章
39
粉丝
9
喜欢
71
收藏
102
排名:461
访问:1.9 万
私信
所有博文
社区赞助商