refactor: reorganize modules and add Linux build tooling
This commit is contained in:
23
module/finance/wallet/internal/logic/wechat/app_pre_order.go
Normal file
23
module/finance/wallet/internal/logic/wechat/app_pre_order.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package wechat
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
pb "bsm/full/module/finance/wallet/pb"
|
||||
"git.apinb.com/bsm-sdk/core/service"
|
||||
)
|
||||
|
||||
// 微信APP支付下单
|
||||
func AppPreOrder(ctx context.Context, in *pb.WxpayAppPreOrderRequest) (reply *pb.WxpayAppPreOrderReply, err error) {
|
||||
// parse authorization meta.
|
||||
_, err = service.ParseMetaCtx(ctx, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// TODO: valid code
|
||||
|
||||
// TODO: add your logic code & delete this line.
|
||||
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package wechat
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
pb "bsm/full/module/finance/wallet/pb"
|
||||
)
|
||||
|
||||
// 微信JSAPI下单
|
||||
func JsapiPreOrder(ctx context.Context, in *pb.WxpayJSAPIPreOrderRequest) (reply *pb.WxpayJSAPIPreOrderReply, err error) {
|
||||
if err := CheckParam(in.Amount, in.AuthCode, in.UserIdentification, in.OrderNo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var (
|
||||
attach = in.AuthCode // 授权码
|
||||
orderNo = in.OrderNo // 订单唯一码
|
||||
desc = in.Description // 商品描述
|
||||
openid = in.UserIdentification // 用户微信唯一标识
|
||||
amount = in.Amount // 订单金额
|
||||
)
|
||||
wx, _ := NewWechat()
|
||||
res, err := wx.GetResponse(attach, orderNo, desc, openid, amount)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &pb.WxpayJSAPIPreOrderReply{PrepayId: res.PrepayId}, nil
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package wechat
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
pb "bsm/full/module/finance/wallet/pb"
|
||||
"git.apinb.com/bsm-sdk/core/service"
|
||||
)
|
||||
|
||||
// 微信native二维码支付下单
|
||||
func NativePreOrder(ctx context.Context, in *pb.WxpayNativePreOrderRequest) (reply *pb.WxpayNativePreOrderReply, err error) {
|
||||
// parse authorization meta.
|
||||
_, err = service.ParseMetaCtx(ctx, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// TODO: valid code
|
||||
|
||||
// TODO: add your logic code & delete this line.
|
||||
|
||||
return
|
||||
}
|
||||
23
module/finance/wallet/internal/logic/wechat/transfer.go
Normal file
23
module/finance/wallet/internal/logic/wechat/transfer.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package wechat
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
pb "bsm/full/module/finance/wallet/pb"
|
||||
"git.apinb.com/bsm-sdk/core/service"
|
||||
)
|
||||
|
||||
// 微信转账到零钱
|
||||
func Transfer(ctx context.Context, in *pb.WxpayTransferRequest) (reply *pb.WxpayTransferReply, err error) {
|
||||
// parse authorization meta.
|
||||
_, err = service.ParseMetaCtx(ctx, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// TODO: valid code
|
||||
|
||||
// TODO: add your logic code & delete this line.
|
||||
|
||||
return
|
||||
}
|
||||
196
module/finance/wallet/internal/logic/wechat/wechat.go
Normal file
196
module/finance/wallet/internal/logic/wechat/wechat.go
Normal file
@@ -0,0 +1,196 @@
|
||||
package wechat
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"bsm/full/module/finance/wallet/internal/config"
|
||||
"bsm/full/module/finance/wallet/internal/excode"
|
||||
"github.com/go-pay/gopay"
|
||||
"github.com/go-pay/gopay/wechat/v3"
|
||||
)
|
||||
|
||||
type WeChatPay struct {
|
||||
ctx context.Context
|
||||
Client *wechat.ClientV3
|
||||
Body *gopay.BodyMap
|
||||
}
|
||||
|
||||
var (
|
||||
mchID string
|
||||
SerialNumber string
|
||||
mchAPIv3Key string
|
||||
ApiClientKey string
|
||||
AppId string
|
||||
Currency string
|
||||
NotifyUrl string
|
||||
)
|
||||
|
||||
func new() {
|
||||
mchID = config.Spec.WeChat.MchID // 商户号
|
||||
SerialNumber = config.Spec.WeChat.SerialNo // 商户证书序列号
|
||||
mchAPIv3Key = config.Spec.WeChat.APIV3Key // 商户APIv3密钥
|
||||
ApiClientKey = config.Spec.WeChat.PrivateKey // 私钥
|
||||
AppId = config.Spec.WeChat.AppID // Appid
|
||||
Currency = config.Spec.WeChat.Currency // 货币类型 CNY:人民币,境内商户号仅支持人民币。
|
||||
NotifyUrl = config.Spec.WeChat.NotifyURL // 通知URL必须为直接可访问的URL,不允许携带查询串,要求必须为https地址。
|
||||
}
|
||||
|
||||
func NewWechat() (*WeChatPay, error) {
|
||||
new()
|
||||
// NewClientV3 初始化微信客户端 v3
|
||||
// mchid:商户ID 或者服务商模式的 sp_mchid
|
||||
// serialNo:商户证书的证书序列号
|
||||
// apiV3Key:apiV3Key,商户平台获取
|
||||
// privateKey:私钥 apiclient_key.pem 读取后的内容
|
||||
privateKey, err := os.ReadFile(ApiClientKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
client, err := wechat.NewClientV3(mchID, SerialNumber, mchAPIv3Key, string(privateKey))
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 设置微信平台API证书和序列号(如开启自动验签,请忽略此步骤)
|
||||
//client.SetPlatformCert([]byte(""), "")
|
||||
|
||||
// 启用自动同步返回验签,并定时更新微信平台API证书(开启自动验签时,无需单独设置微信平台API证书和序列号)
|
||||
err = client.AutoVerifySign()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 打开Debug开关,输出日志,默认是关闭的
|
||||
client.DebugSwitch = gopay.DebugOn
|
||||
|
||||
return &WeChatPay{
|
||||
ctx: context.Background(),
|
||||
Client: client,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetResponse tradeNo:finance_payment表的identity
|
||||
func (srv *WeChatPay) GetResponse(Attach, OrderNo, desc, openid string, amount int64) (*wechat.Prepay, error) {
|
||||
expire := time.Now().Add(60 * time.Minute).Format(time.RFC3339)
|
||||
// 初始化 BodyMap
|
||||
bm := make(gopay.BodyMap)
|
||||
bm.Set("appid", AppId).
|
||||
Set("mchid", mchID).
|
||||
Set("description", desc).
|
||||
Set("attach", Attach). //finance_payment表的identity 附加数据,在查询API和支付通知中原样返回,可作为自定义参数使用,实际情况下只有支付完成状态才会返回该字段
|
||||
Set("out_trade_no", OrderNo).
|
||||
Set("time_expire", expire).
|
||||
Set("notify_url", NotifyUrl).
|
||||
SetBodyMap("amount", func(bm gopay.BodyMap) {
|
||||
bm.Set("total", amount).
|
||||
Set("currency", Currency)
|
||||
}).
|
||||
SetBodyMap("payer", func(bm gopay.BodyMap) {
|
||||
bm.Set("openid", openid)
|
||||
})
|
||||
|
||||
wxRsp, err := srv.Client.V3TransactionJsapi(srv.ctx, bm)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return wxRsp.Response, nil
|
||||
}
|
||||
|
||||
func (srv *WeChatPay) MiniPaySign(prepayid string) (map[string]string, error) {
|
||||
applet, err := srv.Client.PaySignOfApplet(AppId, prepayid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
reply, err := struct2map(applet)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return reply, nil
|
||||
}
|
||||
|
||||
func (srv *WeChatPay) AppPaySign(prepayid string) (map[string]string, error) {
|
||||
app, err := srv.Client.PaySignOfApp(AppId, prepayid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
reply, err := struct2map(app)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return reply, nil
|
||||
}
|
||||
|
||||
func (srv *WeChatPay) JsapiPaySign(prepayid string) (map[string]string, error) {
|
||||
jsapi, err := srv.Client.PaySignOfJSAPI(AppId, prepayid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
reply, err := struct2map(jsapi)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return reply, nil
|
||||
}
|
||||
|
||||
func (srv *WeChatPay) NativePaySign(Attach, OrderNo, description, expire, openid string, amount int64) (map[string]string, error) {
|
||||
// 初始化 BodyMap
|
||||
body := make(gopay.BodyMap)
|
||||
body.Set("appid", AppId).
|
||||
Set("mchid", mchID).
|
||||
Set("description", description).
|
||||
Set("attach", Attach). //finance_payment表的identity 附加数据,在查询API和支付通知中原样返回,可作为自定义参数使用,实际情况下只有支付完成状态才会返回该字段
|
||||
Set("out_trade_no", OrderNo).
|
||||
Set("time_expire", expire).
|
||||
Set("notify_url", NotifyUrl).
|
||||
SetBodyMap("amount", func(bm gopay.BodyMap) {
|
||||
bm.Set("total", amount).
|
||||
Set("currency", Currency)
|
||||
}).
|
||||
SetBodyMap("payer", func(bm gopay.BodyMap) {
|
||||
bm.Set("openid", openid)
|
||||
})
|
||||
|
||||
native, err := srv.Client.V3TransactionNative(srv.ctx, body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
reply, err := struct2map(native)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return reply, nil
|
||||
}
|
||||
|
||||
func struct2map(in any) (map[string]string, error) {
|
||||
b, err := json.Marshal(in)
|
||||
var m map[string]string
|
||||
err = json.Unmarshal(b, &m)
|
||||
return m, err
|
||||
}
|
||||
|
||||
func CheckParam(amount int64, auth_code string, identity string, order_no string) (err error) {
|
||||
if amount == 0 {
|
||||
return excode.ErrAmount
|
||||
}
|
||||
if auth_code == "" {
|
||||
return excode.ErrAuthCode
|
||||
}
|
||||
if identity == "" {
|
||||
return excode.ErrPassportId
|
||||
}
|
||||
if order_no == "" {
|
||||
return excode.ErrOrderNo
|
||||
}
|
||||
return nil
|
||||
}
|
||||
41
module/finance/wallet/internal/logic/wechat/wx_callback.go
Normal file
41
module/finance/wallet/internal/logic/wechat/wx_callback.go
Normal file
@@ -0,0 +1,41 @@
|
||||
package wechat
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
|
||||
"bsm/full/module/finance/wallet/internal/config"
|
||||
pb "bsm/full/module/finance/wallet/pb"
|
||||
"git.apinb.com/bsm-sdk/core/errcode"
|
||||
"git.apinb.com/bsm-sdk/core/printer"
|
||||
"github.com/go-pay/gopay/wechat/v3"
|
||||
)
|
||||
|
||||
// 微信支付回调
|
||||
func WxCallback(ctx context.Context, in *pb.WxCallBackRequest) (reply *pb.CallBackReply, err error) {
|
||||
var notifyReq = &wechat.V3NotifyReq{}
|
||||
data, err := json.Marshal(in)
|
||||
if err != nil {
|
||||
return nil, errcode.ErrJsonMarshal
|
||||
}
|
||||
err = json.Unmarshal(data, ¬ifyReq)
|
||||
if err != nil {
|
||||
return nil, errcode.ErrJsonUnmarshal
|
||||
}
|
||||
|
||||
wx, _ := NewWechat()
|
||||
pubKey := wx.Client.WxPublicKeyMap()
|
||||
err = notifyReq.VerifySignByPKMap(pubKey)
|
||||
if err != nil {
|
||||
printer.Error(err.Error())
|
||||
return &pb.CallBackReply{Code: "FAIL", Message: "验签失败"}, nil
|
||||
}
|
||||
res, err := notifyReq.DecryptPayCipherText(config.Spec.WeChat.APIV3Key)
|
||||
if err != nil {
|
||||
printer.Error(err.Error())
|
||||
return &pb.CallBackReply{Code: "FAIL", Message: "验签失败"}, err
|
||||
}
|
||||
// Todo: 业务逻辑
|
||||
payResult, _ := json.Marshal(res)
|
||||
return &pb.CallBackReply{Code: "SUCCESS", Message: string(payResult)}, nil
|
||||
}
|
||||
Reference in New Issue
Block a user