go-zero之App微信支付服务
APP微信支付
由于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 协议》,转载必须注明作者和本文链接