微信与支付宝支付之前写的支付回调的逻辑在网关层处理,网关一般是接收参数,响应数据。所以有些不合理。下面做了些处理
微信支付回调
这里用的是官方的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
提供了一个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来处理业务逻辑。实现网关层与业务层分离。