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
提供了一個body
轉json
的方法,所以比微信操作還要簡單
// 支付寶回撥
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 協議》,轉載必須註明作者和本文連結