go-zero之App支付服務

charliecen發表於2021-12-15

APP微信支付

參考文件:gopay程式碼庫 官網文件

由於go-zero 會生成很多程式碼,這裡我就簡單寫一下主要的程式碼,想看完整的話參考web支付服務

例項化客戶端


func NewWxAppPayClient(mchId, serialNo, apiV3Key, cPath string) *wechat.ClientV3 {
    // NewClientV3 初始化微信客戶端 v3
    //    mchid:商戶ID 或者服務商模式的 sp_mchid
    //     serialNo:商戶證照的證照序列號
    //    apiV3Key:apiV3Key,商戶平臺獲取
    //    privateKey:私鑰 apiclient_key.pem 讀取後的內容
    privateKeyPath := GetFilePath(cPath)
    privateKey, _ := ioutil.ReadFile(privateKeyPath)
    client, err := wechat.NewClientV3(mchId, serialNo, apiV3Key, string(privateKey))
    if err != nil {
        logx.Error("微信初始化失敗", err)
        return nil
    }
    // 啟用自動同步返回驗籤,並定時更新微信平臺API證照
    err = client.AutoVerifySign()
    if err != nil {
        logx.Error("自動同步返回驗籤失敗", err)
        return nil
    }
    return client
}

生成預支付

//  APP 微信生成預付單
func (l *WxPrePayLogic) WxPrePay(in *order.WxPrePayRequest) (*order.Response, error) {
    data := make(map[string]string, 0)
    appId := l.svcCtx.Config.WxAppPay.AppId
    mchId := l.svcCtx.Config.WxAppPay.MchId
    serialNo := l.svcCtx.Config.WxAppPay.MCSNum
    apiV3Key := l.svcCtx.Config.WxAppPay.ApiV3Secret
    cPath := l.svcCtx.Config.WxAppPay.CPath
    notifyUrl := l.svcCtx.Config.WxAppPay.NotifyUrl
    bm := make(gopay.BodyMap)
    bm.Set("appid", appId).
        Set("mchid", mchId).
        Set("description", in.Desc).
        Set("out_trade_no", in.OrderId).
        Set("notify_url", notifyUrl).
        SetBodyMap("amount", func(bm gopay.BodyMap) {
            bm.Set("total", in.Total).
                Set("currency", "CNY")
        })

    // 呼叫微信客戶端
    wxResp, err := tool.NewWxAppPayClient(mchId, serialNo, apiV3Key, cPath).V3TransactionApp(context.TODO(), bm)
    if err != nil {
        logx.Error("微信APP下單失敗", err)
        return &order.Response{
            Code: 201,
            Msg:  "下單失敗",
            Data: data,
        }, nil
    }
    data["prepay_id"] = wxResp.Response.PrepayId
    return &order.Response{
        Code: 200,
        Msg:  "success",
        Data: data,
    }, nil
}

微信支付

//  APP 微信支付,
func (l *WxPayLogic) WxPay(in *order.WxPayRequest) (*order.Response, error) {
    data := make(map[string]string, 0)
    appId := l.svcCtx.Config.WxAppPay.AppId
    mchId := l.svcCtx.Config.WxAppPay.MchId
    serialNo := l.svcCtx.Config.WxAppPay.MCSNum
    apiV3Key := l.svcCtx.Config.WxAppPay.ApiV3Secret
    cPath := l.svcCtx.Config.WxAppPay.CPath
    // 調起支付,獲取引數和簽名,下發給前端APP
    app, err := tool.NewWxAppPayClient(mchId, serialNo, apiV3Key, cPath).PaySignOfApp(appId, in.PrePayId)
    if err != nil {
        logx.Error("支付失敗")
        return &order.Response{
            Code: 201,
            Msg:  "支付失敗",
            Data: data,
        }, nil
    }
    data["appid"] = app.Appid
    data["partnerid"] = app.Partnerid
    data["prepayid"] = in.PrePayId
    data["package"] = app.Package
    data["noncestr"] = app.Noncestr
    data["timestamp"] = app.Timestamp
    data["sign"] = app.Sign
    return &order.Response{
        Code: 200,
        Msg:  "success",
        Data: data,
    }, nil
}

介面

這裡把微信和支付寶合併了,根據前端傳遞的型別來判斷是哪種支付方式。

// APP 支付
func (l *AppPayLogic) AppPay(req types.GenerateOrderReq) (*types.OrderResponse, error) {
    data := make(map[string]interface{}, 0)
    userId, _ := l.ctx.Value("userId").(json.Number).Int64()

    // 商品詳情
    goodsInfo, err := l.svcCtx.Lookclient.GoodsDetail(l.ctx, &lookclient.FindGoodsByIdRequest{Id: req.GoodsId})
    if err != nil || goodsInfo.Code != 200 {
        return &types.OrderResponse{
            Code: 201,
            Msg:  goodsInfo.Msg,
            Data: data,
        }, nil
    }
    // 商品表價格字串轉int64
    price, _ := strconv.ParseFloat(goodsInfo.Data.Price, 10)
    goodsPrice := int64(price * 100)
    // 生成訂單詳情
    goodsInfoData, _ := json.Marshal(goodsInfo.Data)
    // rpc 生成訂單
    orderInfo, err := l.svcCtx.OrderClient.GenerateOrder(l.ctx, &orderclient.GenerateOrderRequest{
        UserId:  userId,
        GoodsId: goodsInfo.Data.Id,
        PayType: req.PayType,
        Amount:  goodsPrice,
        Desc:    goodsInfo.Data.Desc,
        Data:    string(goodsInfoData),
    })
    if err != nil || orderInfo.Code != 200 {
        return &types.OrderResponse{
            Code: 201,
            Msg:  orderInfo.Msg,
            Data: data,
        }, nil
    }
    // 判斷支付方式
    if req.PayType == config.WxPay {
        // 生成預支付
        wxPrePayResp, err := l.svcCtx.OrderClient.WxPrePay(l.ctx, &orderclient.WxPrePayRequest{
            OrderId: orderInfo.Data["order_id"],
            Desc:    goodsInfo.Data.Desc,
            Total:   goodsPrice,
        })

        if err != nil || wxPrePayResp.Code != 200 {
            return &types.OrderResponse{
                Code: 201,
                Msg:  wxPrePayResp.Msg,
                Data: data,
            }, nil
        }

        // 生成支付資訊
        wxPayResp, err := l.svcCtx.OrderClient.WxPay(l.ctx, &orderclient.WxPayRequest{
            PrePayId: wxPrePayResp.Data["prepay_id"],
        })
        if err != nil || wxPayResp.Code != 200 {
            return &types.OrderResponse{
                Code: 201,
                Msg:  wxPayResp.Msg,
                Data: data,
            }, nil
        }
        data["info"] = wxPayResp.Data
    } else if req.PayType == config.AliPay {
        // 支付寶支付
        aliPayResp, err := l.svcCtx.OrderClient.AliAppPay(l.ctx, &orderclient.AliPrePayRequest{
            OrderId: orderInfo.Data["order_id"],
            Desc:    goodsInfo.Data.Desc,
            Total:   goodsPrice,
        })
        if err != nil || aliPayResp.Code != 200 {
            return &types.OrderResponse{
                Code: 201,
                Msg:  aliPayResp.Msg,
                Data: data,
            }, nil
        }
        data["info"] = aliPayResp.Data
    }
    return &types.OrderResponse{
        Code: 200,
        Msg:  "success",
        Data: data,
    }, nil
}

測試下

goods_id 表示商品id,pay_type表示支付方式,1:微信,2:支付寶

curl --location --request POST 'https://localhost/order/app_pay' \
--header 'User-Agent: Apipost client Runtime/+https://www.apipost.cn/' \
--form 'goods_id=2' \
--form 'pay_type=1'


{
    "code": 200,
    "msg": "success",
    "data": {
        "info": {
            "appid": "wxfafadfadfafd1",
            "noncestr": "auwyL7PvDhdfadfadfaf",
            "package": "Sign=WXPay",
            "partnerid": "12312313131231",
            "prepayid": "fadfaefeafae124123ef23234234243",
            "sign": "f7q9A7VIP/D62/AG5QKxr2hQ==",
            "timestamp": "2342342342424"
        }
    }
}

這裡只寫了微信的,下次有時間再寫下支付寶APP支付

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章