go-zero之支付回撥問題

charliecen發表於2021-11-03

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 協議》,轉載必須註明作者和本文連結

相關文章