refactor: reorganize modules and add Linux build tooling
This commit is contained in:
89
module/finance/wallet/internal/config/config.go
Normal file
89
module/finance/wallet/internal/config/config.go
Normal file
@@ -0,0 +1,89 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
||||
"git.apinb.com/bsm-sdk/core/conf"
|
||||
"git.apinb.com/bsm-sdk/core/crypto/encipher"
|
||||
"git.apinb.com/bsm-sdk/core/env"
|
||||
)
|
||||
|
||||
var (
|
||||
Spec SrvConfig // 全局配置实例
|
||||
)
|
||||
|
||||
// SrvConfig 服务配置结构体
|
||||
type SrvConfig struct {
|
||||
conf.Base `yaml:",inline"` // 基础配置
|
||||
Databases *conf.DBConf `yaml:"Databases"` // 数据库配置
|
||||
MicroService *conf.MicroServiceConf `yaml:"MicroService"` // 微服务配置
|
||||
Rpc map[string]conf.RpcConf `yaml:"Rpc"` // RPC配置
|
||||
Gateway *conf.GatewayConf `yaml:"Gateway"` // 网关配置
|
||||
Apm *conf.ApmConf `yaml:"APM"` // APM监控配置
|
||||
Etcd *conf.EtcdConf `yaml:"Etcd"` // Etcd配置
|
||||
|
||||
WeChat *WeChatConf `yaml:"WeChat"` // 微信支付配置
|
||||
Alipay *AlipayConf `yaml:"Alipay"` // 支付宝配置
|
||||
Wallet *WalletConfig `yaml:"Wallet"` // 钱包配置
|
||||
QrCodeSavePath string `yaml:"QrCodeSavePath"` // 二维码保存路径
|
||||
}
|
||||
|
||||
// WeChatConf 微信支付配置
|
||||
type WeChatConf struct {
|
||||
AppID string `yaml:"AppID"` // 微信应用ID
|
||||
AppSecret string `yaml:"AppSecret"` // 微信应用密钥
|
||||
SerialNo string `yaml:"SerialNo"` // 证书序列号
|
||||
APIV3Key string `yaml:"APIV3Key"` // APIv3密钥
|
||||
PrivateKey string `yaml:"PrivateKey"` // 私钥
|
||||
NotifyURL string `yaml:"NotifyURL"` // 回调通知地址
|
||||
Currency string `yaml:"Currency"` // 货币类型
|
||||
MchID string `yaml:"MchID"` // 商户号
|
||||
SubMchID string `yaml:"SubMchID"` // 子商户号
|
||||
OpenID string `yaml:"OpenID"` // 用户OpenID
|
||||
}
|
||||
|
||||
// AlipayConf 支付宝配置
|
||||
type AlipayConf struct {
|
||||
AppID string `yaml:"AppID"` // 支付宝应用ID
|
||||
AppSecret string `yaml:"AppSecret"` // 应用密钥
|
||||
PrivateKey string `yaml:"PrivateKey"` // 应用私钥
|
||||
IsProd bool `yaml:"IsProd"` // 是否生产环境
|
||||
NotifyURL string `yaml:"NotifyURL"` // 异步通知地址
|
||||
ReturnURL string `yaml:"ReturnURL"` // 同步跳转地址
|
||||
QuitURL string `yaml:"QuitURL"` // 退出地址
|
||||
PublicKeyRsa2Byte string `yaml:"PublicKeyRsa2Byte"` // 支付宝公钥
|
||||
CertPublicKey string `yaml:"CertPublicKey"` // 应用公钥证书
|
||||
CertRoot string `yaml:"CertRoot"` // 根证书
|
||||
CertPublicKeyRsa2 string `yaml:"CertPublicKeyRsa2"` // 应用公钥证书RSA2
|
||||
}
|
||||
|
||||
// WalletConfig 钱包配置
|
||||
type WalletConfig struct {
|
||||
Name string `yaml:"Name"` // 钱包名称
|
||||
URL string `yaml:"URL"` // 钱包URL
|
||||
PublicKey string `yaml:"PublicKey"` // 公钥
|
||||
YMDHMS string `yaml:"YMDHMS"` // 时间格式
|
||||
YMD string `yaml:"YMD"` // 日期格式
|
||||
AlipyIsOpen bool `yaml:"AlipyIsOpen"` // 支付宝是否开启
|
||||
WalletIsOpen bool `yaml:"WalletIsOpen"` // 钱包是否开启
|
||||
WechatpayIsOpen bool `yaml:"WechatpayIsOpen"` // 微信支付是否开启
|
||||
}
|
||||
|
||||
// New 初始化配置
|
||||
func New(srvKey string) {
|
||||
// 初始化配置,创建一个新的配置实例
|
||||
conf.New(srvKey, &Spec)
|
||||
|
||||
// 配置校验:服务IP和端口
|
||||
Spec.Port = conf.CheckPort(Spec.Port)
|
||||
Spec.BindIP = conf.CheckIP(Spec.BindIP)
|
||||
Spec.Addr = net.JoinHostPort(Spec.BindIP, Spec.Port)
|
||||
|
||||
// 配置校验 服务名称地址及监听地址不能为空
|
||||
conf.NotNil(Spec.Service, Spec.Cache)
|
||||
|
||||
// 初始化加密SecretKey
|
||||
encipher.New(env.Runtime.JwtSecretKey)
|
||||
|
||||
conf.PrintInfo(Spec.Addr)
|
||||
}
|
||||
29
module/finance/wallet/internal/excode/ex.go
Normal file
29
module/finance/wallet/internal/excode/ex.go
Normal file
@@ -0,0 +1,29 @@
|
||||
// Package excode 定义钱包服务的错误码
|
||||
package excode
|
||||
|
||||
import (
|
||||
"git.apinb.com/bsm-sdk/core/errcode"
|
||||
)
|
||||
|
||||
var (
|
||||
// 用户相关错误
|
||||
ErrPassportId = errcode.NewError(3801, "passport id not found") // 用户ID未找到
|
||||
ErrAuthCode = errcode.NewError(3802, "auth_code Not Found") // 授权码未找到
|
||||
ErrOrderNo = errcode.NewError(3803, "order_no Not Found") // 订单号未找到
|
||||
ErrAmount = errcode.NewError(3805, "amount Not Found") // 金额参数未找到
|
||||
ErrIdentityArgument = errcode.NewError(3807, "Invalid parameter:identity") // 身份参数无效
|
||||
ErrPasswordArgument = errcode.NewError(3808, "Invalid parameter:password") // 密码参数无效
|
||||
ErrVerifySign = errcode.NewError(3809, "Verify Sign Failed") // 签名验证失败
|
||||
|
||||
// 钱包相关错误
|
||||
ErrBalanceNotEnough = errcode.NewError(3812, "Err Balance not enough") // 余额不足
|
||||
ErrPay = errcode.NewError(3813, "Pay Error") // 支付失败
|
||||
ErrPayType = errcode.NewError(3816, "Err PayType") // 支付类型错误
|
||||
ErrPayChannel = errcode.NewError(3821, "Channel Error") // 支付渠道错误
|
||||
|
||||
// 第三方支付相关错误
|
||||
ErrWechatInit = errcode.NewError(3817, "Internal Error") // 微信支付初始化失败
|
||||
ErrWechatGetResp = errcode.NewError(3818, "Internal Error") // 微信支付响应获取失败
|
||||
ErrAlipayInit = errcode.NewError(3819, "Internal Error") // 支付宝初始化失败
|
||||
ErrAlipayGetResp = errcode.NewError(3820, "Internal Error") // 支付宝响应获取失败
|
||||
)
|
||||
26
module/finance/wallet/internal/impl/impl.go
Normal file
26
module/finance/wallet/internal/impl/impl.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package impl
|
||||
|
||||
import (
|
||||
"bsm/full/module/finance/wallet/internal/config"
|
||||
"git.apinb.com/bsm-sdk/core/cache/redis"
|
||||
"git.apinb.com/bsm-sdk/core/with"
|
||||
cache "github.com/patrickmn/go-cache"
|
||||
clientv3 "go.etcd.io/etcd/client/v3"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
var (
|
||||
RedisService *redis.RedisClient // Redis 客户端服务
|
||||
EtcdService *clientv3.Client // Etcd 客户端服务
|
||||
DBService *gorm.DB // 数据库服务
|
||||
MemorySerice *cache.Cache // 内存缓存服务
|
||||
)
|
||||
|
||||
// NewImpl 初始化各类服务实例
|
||||
func NewImpl() {
|
||||
// 初始化内存缓存
|
||||
MemorySerice = with.Memory(nil)
|
||||
RedisService = with.RedisCache(config.Spec.Cache) // redis cache
|
||||
DBService = with.Databases(config.Spec.Databases, nil) // model
|
||||
EtcdService = with.Etcd(config.Spec.Etcd) // etcd
|
||||
}
|
||||
70
module/finance/wallet/internal/logic/alipay/alipay.go
Normal file
70
module/finance/wallet/internal/logic/alipay/alipay.go
Normal file
@@ -0,0 +1,70 @@
|
||||
package alipay
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"bsm/full/module/finance/wallet/internal/config"
|
||||
"github.com/go-pay/gopay"
|
||||
"github.com/go-pay/gopay/alipay"
|
||||
)
|
||||
|
||||
type AliPay struct {
|
||||
ctx context.Context
|
||||
Client *alipay.Client
|
||||
Body *gopay.BodyMap
|
||||
}
|
||||
|
||||
func NewAlipay() (*AliPay, error) {
|
||||
// 初始化支付宝客户端
|
||||
// appid:应用ID
|
||||
// privateKey:应用私钥,支持PKCS1和PKCS8
|
||||
// isProd:是否是正式环境
|
||||
client, err := alipay.NewClient(config.Spec.Alipay.AppID, config.Spec.Alipay.PrivateKey, config.Spec.Alipay.IsProd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// 打开Debug开关,输出日志,默认关闭
|
||||
client.DebugSwitch = gopay.DebugOn
|
||||
|
||||
// 设置支付宝请求 公共参数
|
||||
client.SetLocation(alipay.LocationShanghai) // 设置时区,不设置或出错均为默认服务器时间
|
||||
client.SetCharset(alipay.UTF8) // 设置字符编码,不设置默认 utf-8
|
||||
client.SetSignType(alipay.RSA2) // 设置签名类型,不设置默认 RSA2
|
||||
client.SetReturnUrl(config.Spec.Alipay.ReturnURL) // 设置返回URL
|
||||
client.SetNotifyUrl(config.Spec.Alipay.NotifyURL) // 设置异步通知URL
|
||||
|
||||
// 自动同步验签(只支持证书模式)
|
||||
// 传入 alipayCertPublicKey_RSA2.crt 内容
|
||||
client.AutoVerifySign([]byte(config.Spec.Alipay.PublicKeyRsa2Byte))
|
||||
|
||||
// 公钥证书模式
|
||||
err = client.SetCertSnByPath(config.Spec.Alipay.CertPublicKey, config.Spec.Alipay.CertRoot, config.Spec.Alipay.CertPublicKeyRsa2)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &AliPay{
|
||||
Client: client,
|
||||
// ctx: context.Background(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (srv *AliPay) SetBody(body, orderNo string, amount int64) {
|
||||
srv.Body.Set("subject", config.Spec.Wallet.Name).
|
||||
Set("body", body). //finance_payment表的identity
|
||||
Set("product_code", "QUICK_WAP_WAY").
|
||||
Set("out_trade_no", orderNo).
|
||||
Set("total_amount", amount/100).
|
||||
Set("timeout_express", "60m").
|
||||
Set("quit_url", config.Spec.Alipay.QuitURL)
|
||||
}
|
||||
|
||||
func (srv *AliPay) TradeWapPay() (string, error) {
|
||||
result, err := srv.Client.TradeWapPay(srv.ctx, *srv.Body)
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (srv *AliPay) TradeAppPay() (string, error) {
|
||||
result, err := srv.Client.TradeAppPay(srv.ctx, *srv.Body)
|
||||
return result, err
|
||||
}
|
||||
23
module/finance/wallet/internal/logic/alipay/app_pay.go
Normal file
23
module/finance/wallet/internal/logic/alipay/app_pay.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package alipay
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
pb "bsm/full/module/finance/wallet/pb"
|
||||
"git.apinb.com/bsm-sdk/core/service"
|
||||
)
|
||||
|
||||
// 支付宝APP支付
|
||||
func AppPay(ctx context.Context, in *pb.AlipayTradeAppPayRequest) (reply *pb.AlipayTradeAppPayReply, 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/alipay/page_pay.go
Normal file
23
module/finance/wallet/internal/logic/alipay/page_pay.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package alipay
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
pb "bsm/full/module/finance/wallet/pb"
|
||||
"git.apinb.com/bsm-sdk/core/service"
|
||||
)
|
||||
|
||||
// 支付宝电脑网站支付
|
||||
func PagePay(ctx context.Context, in *pb.AlipayTradePagePayRequest) (reply *pb.AlipayTradePagePayReply, 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/alipay/transfer.go
Normal file
23
module/finance/wallet/internal/logic/alipay/transfer.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package alipay
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
pb "bsm/full/module/finance/wallet/pb"
|
||||
"git.apinb.com/bsm-sdk/core/service"
|
||||
)
|
||||
|
||||
// 支付宝转账到个人支付宝账户
|
||||
func Transfer(ctx context.Context, in *pb.AlipayUniTransferRequest) (reply *pb.AlipayUniTransferReply, 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/alipay/wap_pay.go
Normal file
23
module/finance/wallet/internal/logic/alipay/wap_pay.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package alipay
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
pb "bsm/full/module/finance/wallet/pb"
|
||||
"git.apinb.com/bsm-sdk/core/service"
|
||||
)
|
||||
|
||||
// 支付宝wap支付
|
||||
func WapPay(ctx context.Context, in *pb.AlipayTradeWapPayRequest) (reply *pb.AlipayTradeWapPayReply, 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
|
||||
}
|
||||
62
module/finance/wallet/internal/logic/basic/add_bank_card.go
Normal file
62
module/finance/wallet/internal/logic/basic/add_bank_card.go
Normal file
@@ -0,0 +1,62 @@
|
||||
package basic
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"bsm/full/module/finance/wallet/internal/impl"
|
||||
"bsm/full/module/finance/wallet/internal/models"
|
||||
pb "bsm/full/module/finance/wallet/pb"
|
||||
"git.apinb.com/bsm-sdk/core/errcode"
|
||||
"git.apinb.com/bsm-sdk/core/printer"
|
||||
"git.apinb.com/bsm-sdk/core/service"
|
||||
"git.apinb.com/bsm-sdk/core/utils"
|
||||
"git.apinb.com/bsm-sdk/core/vars"
|
||||
)
|
||||
|
||||
// 添加银行卡
|
||||
func AddBankCard(ctx context.Context, in *pb.AddBankCardRequest) (reply *pb.StatusReply, err error) {
|
||||
auth, ok := service.ParseMetaCtx(ctx, nil)
|
||||
if ok != nil {
|
||||
return nil, ok
|
||||
}
|
||||
|
||||
if in.Phone == "" || in.IdCard == "" || in.CardNo == "" || in.CardOwner == "" {
|
||||
return nil, errcode.ErrInvalidArgument
|
||||
}
|
||||
|
||||
myWallet, err := models.GetWalletByPassportIdentity(auth.ID, auth.Identity)
|
||||
if err != nil {
|
||||
printer.Error(err.Error())
|
||||
return nil, errcode.ErrDB
|
||||
}
|
||||
|
||||
// Try to enrich bank meta if exists locally; ignore not found.
|
||||
var cardInfo models.WalletBank
|
||||
_ = impl.DBService.Where("card_no = ?", in.CardNo).First(&cardInfo).Error
|
||||
|
||||
data := &models.WalletBank{
|
||||
WalletIdentity: myWallet.Identity,
|
||||
CardNo: in.CardNo,
|
||||
BankName: cardInfo.BankName,
|
||||
Bank: cardInfo.Bank,
|
||||
BankType: cardInfo.BankType,
|
||||
CardOwner: in.CardOwner,
|
||||
IDCard: in.IdCard,
|
||||
Phone: in.Phone,
|
||||
}
|
||||
|
||||
data.Identity = utils.UUID()
|
||||
data.PassportID = auth.ID
|
||||
data.PassportIdentity = auth.Identity
|
||||
|
||||
err = impl.DBService.Create(&data).Error
|
||||
if err != nil {
|
||||
printer.Error(err.Error())
|
||||
return nil, errcode.ErrDB
|
||||
}
|
||||
return &pb.StatusReply{
|
||||
Message: vars.OK,
|
||||
Timeseq: time.Now().UnixMilli(),
|
||||
}, nil
|
||||
}
|
||||
60
module/finance/wallet/internal/logic/basic/apply_cash.go
Normal file
60
module/finance/wallet/internal/logic/basic/apply_cash.go
Normal file
@@ -0,0 +1,60 @@
|
||||
package basic
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"bsm/full/module/finance/wallet/internal/excode"
|
||||
"bsm/full/module/finance/wallet/internal/impl"
|
||||
"bsm/full/module/finance/wallet/internal/models"
|
||||
pb "bsm/full/module/finance/wallet/pb"
|
||||
"git.apinb.com/bsm-sdk/core/errcode"
|
||||
"git.apinb.com/bsm-sdk/core/printer"
|
||||
"git.apinb.com/bsm-sdk/core/service"
|
||||
"git.apinb.com/bsm-sdk/core/utils"
|
||||
"git.apinb.com/bsm-sdk/core/vars"
|
||||
)
|
||||
|
||||
// 申请提现
|
||||
func ApplyCash(ctx context.Context, in *pb.ApplyCashRequest) (reply *pb.StatusReply, err error) {
|
||||
auth, ok := service.ParseMetaCtx(ctx, nil)
|
||||
if ok != nil {
|
||||
return nil, ok
|
||||
}
|
||||
|
||||
if in.Amount == 0 || in.Channel == 0 {
|
||||
return nil, errcode.ErrInvalidArgument
|
||||
}
|
||||
|
||||
myWallet, err := models.GetWalletByPassportIdentity(auth.ID, auth.Identity)
|
||||
if err != nil {
|
||||
printer.Error(err.Error())
|
||||
return nil, errcode.ErrDB
|
||||
}
|
||||
|
||||
if in.Amount > myWallet.Balance {
|
||||
return nil, excode.ErrBalanceNotEnough
|
||||
}
|
||||
|
||||
data := &models.WalletApplyCash{
|
||||
WalletIdentity: myWallet.Identity,
|
||||
Amount: in.Amount,
|
||||
Channel: int8(in.Channel),
|
||||
Remark: in.Remark,
|
||||
}
|
||||
data.Identity = utils.UUID()
|
||||
data.PassportID = auth.ID
|
||||
data.PassportIdentity = auth.Identity
|
||||
|
||||
err = impl.DBService.Create(&data).Error
|
||||
if err != nil {
|
||||
printer.Error(err.Error())
|
||||
return nil, errcode.ErrDB
|
||||
}
|
||||
|
||||
//生成提现单
|
||||
return &pb.StatusReply{
|
||||
Message: vars.OK,
|
||||
Timeseq: time.Now().UnixMilli(),
|
||||
}, nil
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package basic
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"bsm/full/module/finance/wallet/internal/impl"
|
||||
"bsm/full/module/finance/wallet/internal/models"
|
||||
pb "bsm/full/module/finance/wallet/pb"
|
||||
"git.apinb.com/bsm-sdk/core/errcode"
|
||||
"git.apinb.com/bsm-sdk/core/printer"
|
||||
"git.apinb.com/bsm-sdk/core/service"
|
||||
"git.apinb.com/bsm-sdk/core/vars"
|
||||
)
|
||||
|
||||
// 绑定微信或支付宝账户
|
||||
func BindPaymentId(ctx context.Context, in *pb.BindPaymentIDRequest) (reply *pb.StatusReply, err error) {
|
||||
auth, ok := service.ParseMetaCtx(ctx, nil)
|
||||
if ok != nil {
|
||||
return nil, ok
|
||||
}
|
||||
|
||||
if in.PayType == 0 || in.AuthCode == "" {
|
||||
return nil, errcode.ErrInvalidArgument
|
||||
}
|
||||
|
||||
var filed string
|
||||
//通过code获取微信或者支付宝的openid
|
||||
if in.PayType == 1 {
|
||||
filed = "wxpay_id"
|
||||
}
|
||||
if in.PayType == 2 {
|
||||
filed = "alipay_id"
|
||||
}
|
||||
|
||||
err = impl.DBService.Model(&models.WalletBasic{}).Where("passport_identity=?", auth.Identity).Update(filed, in.AuthCode).Error
|
||||
if err != nil {
|
||||
printer.Error(err.Error())
|
||||
return nil, errcode.ErrDB
|
||||
}
|
||||
|
||||
return &pb.StatusReply{
|
||||
Message: vars.OK,
|
||||
Timeseq: time.Now().UnixMilli(),
|
||||
}, nil
|
||||
}
|
||||
54
module/finance/wallet/internal/logic/basic/get_bank_card.go
Normal file
54
module/finance/wallet/internal/logic/basic/get_bank_card.go
Normal file
@@ -0,0 +1,54 @@
|
||||
package basic
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"bsm/full/module/finance/wallet/internal/impl"
|
||||
"bsm/full/module/finance/wallet/internal/models"
|
||||
pb "bsm/full/module/finance/wallet/pb"
|
||||
"git.apinb.com/bsm-sdk/core/errcode"
|
||||
"git.apinb.com/bsm-sdk/core/printer"
|
||||
"git.apinb.com/bsm-sdk/core/service"
|
||||
"git.apinb.com/bsm-sdk/core/vars"
|
||||
)
|
||||
|
||||
// 获取用户银行卡列表
|
||||
func GetBankCard(ctx context.Context, in *pb.FinanceEmpty) (reply *pb.GetBankCardReply, err error) {
|
||||
auth, ok := service.ParseMetaCtx(ctx, nil)
|
||||
if ok != nil {
|
||||
return nil, ok
|
||||
}
|
||||
|
||||
myWallet, err := models.GetWalletByPassportIdentity(auth.ID, auth.Identity)
|
||||
if err != nil {
|
||||
printer.Error(err.Error())
|
||||
return nil, errcode.ErrDB
|
||||
}
|
||||
|
||||
result := make([]*models.WalletBank, 0)
|
||||
err = impl.DBService.Where("wallet_identity=?", myWallet.Identity).Find(&result).Error
|
||||
if err != nil {
|
||||
printer.Error(err.Error())
|
||||
return nil, errcode.ErrDB
|
||||
}
|
||||
|
||||
data := make([]*pb.BankCardInfo, 0)
|
||||
for _, card := range result {
|
||||
data = append(data, &pb.BankCardInfo{
|
||||
Id: int64(card.ID),
|
||||
Bank: card.Bank,
|
||||
BankName: card.BankName,
|
||||
BankType: card.BankType,
|
||||
BankNumber: card.CardNo,
|
||||
BindId: card.BindID,
|
||||
Phone: card.Phone,
|
||||
CardOwner: card.CardOwner,
|
||||
IdCard: card.IDCard,
|
||||
Created: card.CreatedAt.Format(vars.YYYY_MM_DD),
|
||||
})
|
||||
}
|
||||
|
||||
return &pb.GetBankCardReply{
|
||||
Data: data,
|
||||
}, nil
|
||||
}
|
||||
86
module/finance/wallet/internal/logic/basic/get_wallet.go
Normal file
86
module/finance/wallet/internal/logic/basic/get_wallet.go
Normal file
@@ -0,0 +1,86 @@
|
||||
package basic
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"bsm/full/module/finance/wallet/internal/impl"
|
||||
"bsm/full/module/finance/wallet/internal/models"
|
||||
pb "bsm/full/module/finance/wallet/pb"
|
||||
"git.apinb.com/bsm-sdk/core/errcode"
|
||||
"git.apinb.com/bsm-sdk/core/printer"
|
||||
"git.apinb.com/bsm-sdk/core/service"
|
||||
"git.apinb.com/bsm-sdk/core/vars"
|
||||
)
|
||||
|
||||
// 获取钱包信息
|
||||
func GetWallet(ctx context.Context, in *pb.GetWalletRequest) (reply *pb.GetWalletReply, err error) {
|
||||
auth, ok := service.ParseMetaCtx(ctx, nil)
|
||||
if ok != nil {
|
||||
return nil, ok
|
||||
}
|
||||
|
||||
myWallet, err := models.GetWalletByPassportIdentity(auth.ID, auth.Identity)
|
||||
if err != nil {
|
||||
printer.Error(err.Error())
|
||||
return nil, errcode.ErrDB
|
||||
}
|
||||
|
||||
var transIn int8 = 1 // 收入
|
||||
var transOut int8 = -1 // 支出
|
||||
|
||||
ymd, _ := strconv.Atoi(time.Now().Format(vars.YYYYMMDD))
|
||||
ym := time.Now().Year()*100 + int(time.Now().Month())
|
||||
|
||||
var totalMoney int64
|
||||
total := make(map[string]int64)
|
||||
|
||||
// 统计当日收入
|
||||
if in.IsTotalTodayIn {
|
||||
impl.DBService.Model(&models.WalletRecord{}).Select("sum(money)").Where("passport_id=? AND trans_type=? AND ymd=?", auth.ID, transIn, ymd).Scan(&totalMoney)
|
||||
total["TodayIn"] = totalMoney
|
||||
}
|
||||
|
||||
// 统计当日支出
|
||||
if in.IsTotalTodayOut {
|
||||
impl.DBService.Model(&models.WalletRecord{}).Select("sum(money)").Where("passport_id=? AND trans_type=? AND ymd=?", auth.ID, transOut, ymd).Scan(&totalMoney)
|
||||
total["TodayOut"] = totalMoney
|
||||
}
|
||||
|
||||
// 统计本月收入
|
||||
if in.IsTotalMonthIn {
|
||||
impl.DBService.Model(&models.WalletRecord{}).Select("sum(money)").Where("passport_id=? AND trans_type=? AND ym=?", auth.ID, transIn, ym).Scan(&totalMoney)
|
||||
total["MonthIn"] = totalMoney
|
||||
}
|
||||
|
||||
// 统计本月支出
|
||||
if in.IsTotalMonthOut {
|
||||
impl.DBService.Model(&models.WalletRecord{}).Select("sum(money)").Where("passport_id=? AND trans_type=? AND ym=?", auth.ID, transOut, ym).Scan(&totalMoney)
|
||||
total["MonthOut"] = totalMoney
|
||||
}
|
||||
|
||||
// 统计全部收入
|
||||
if in.IsTotalAllIn {
|
||||
impl.DBService.Model(&models.WalletRecord{}).Select("sum(money)").Where("passport_id=? AND trans_type=? ", auth.ID, transIn).Scan(&totalMoney)
|
||||
total["AllIn"] = totalMoney
|
||||
}
|
||||
|
||||
// 统计全部支出
|
||||
if in.IsTotalAllOut {
|
||||
impl.DBService.Model(&models.WalletRecord{}).Select("sum(money)").Where("passport_id=? AND trans_type=? ", auth.ID, transOut).Scan(&totalMoney)
|
||||
total["AllOut"] = totalMoney
|
||||
}
|
||||
// remove useless fmt.Sprint side-effect-free call
|
||||
return &pb.GetWalletReply{
|
||||
PassportIdentity: myWallet.PassportIdentity,
|
||||
WalletIdentity: myWallet.Identity,
|
||||
Balance: myWallet.Balance,
|
||||
WithdrawalBalance: myWallet.WithdrawalBalance,
|
||||
Total: total,
|
||||
Status: int32(myWallet.Status),
|
||||
AlipayId: myWallet.AlipayID,
|
||||
WxpayId: myWallet.WxpayID,
|
||||
Created: myWallet.CreatedAt.Format(vars.YYYY_MM_DD_HH_MM_SS),
|
||||
}, nil
|
||||
}
|
||||
37
module/finance/wallet/internal/logic/basic/rm_bank_card.go
Normal file
37
module/finance/wallet/internal/logic/basic/rm_bank_card.go
Normal file
@@ -0,0 +1,37 @@
|
||||
package basic
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"bsm/full/module/finance/wallet/internal/impl"
|
||||
"bsm/full/module/finance/wallet/internal/models"
|
||||
pb "bsm/full/module/finance/wallet/pb"
|
||||
"git.apinb.com/bsm-sdk/core/errcode"
|
||||
"git.apinb.com/bsm-sdk/core/printer"
|
||||
"git.apinb.com/bsm-sdk/core/service"
|
||||
"git.apinb.com/bsm-sdk/core/vars"
|
||||
)
|
||||
|
||||
// 删除银行卡
|
||||
func RmBankCard(ctx context.Context, in *pb.RmBankCardRequest) (reply *pb.StatusReply, err error) {
|
||||
auth, ok := service.ParseMetaCtx(ctx, nil)
|
||||
if ok != nil {
|
||||
return nil, ok
|
||||
}
|
||||
|
||||
if in.Identity == "" {
|
||||
return nil, errcode.ErrInvalidArgument
|
||||
}
|
||||
|
||||
err = impl.DBService.Where("passport_identity=? and identity=?", auth.Identity, in.Identity).Delete(&models.WalletBank{}).Error
|
||||
if err != nil {
|
||||
printer.Error(err.Error())
|
||||
return nil, errcode.ErrDB
|
||||
}
|
||||
|
||||
return &pb.StatusReply{
|
||||
Message: vars.OK,
|
||||
Timeseq: time.Now().UnixMilli(),
|
||||
}, nil
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package basic
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"bsm/full/module/finance/wallet/internal/impl"
|
||||
"bsm/full/module/finance/wallet/internal/models"
|
||||
pb "bsm/full/module/finance/wallet/pb"
|
||||
"git.apinb.com/bsm-sdk/core/errcode"
|
||||
"git.apinb.com/bsm-sdk/core/printer"
|
||||
"git.apinb.com/bsm-sdk/core/service"
|
||||
"git.apinb.com/bsm-sdk/core/vars"
|
||||
)
|
||||
|
||||
// 设置支付密码
|
||||
func SetPayPassword(ctx context.Context, in *pb.SetPayPasswordRequest) (reply *pb.StatusReply, err error) {
|
||||
auth, ok := service.ParseMetaCtx(ctx, nil)
|
||||
if ok != nil {
|
||||
return nil, ok
|
||||
}
|
||||
|
||||
if in.Password == "" {
|
||||
return nil, errcode.ErrPassword
|
||||
}
|
||||
|
||||
encPassword := EncodePassword(in.Password, auth.Identity)
|
||||
|
||||
err = impl.DBService.Model(&models.WalletBasic{}).Where("passport_identity", auth.Identity).Update("pay_password", encPassword).Error
|
||||
if err != nil {
|
||||
printer.Error(err.Error())
|
||||
return nil, errcode.ErrDB
|
||||
}
|
||||
|
||||
return &pb.StatusReply{
|
||||
Message: vars.OK,
|
||||
Timeseq: time.Now().UnixMilli(),
|
||||
}, nil
|
||||
}
|
||||
54
module/finance/wallet/internal/logic/basic/transactions.go
Normal file
54
module/finance/wallet/internal/logic/basic/transactions.go
Normal file
@@ -0,0 +1,54 @@
|
||||
package basic
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"bsm/full/module/finance/wallet/internal/models"
|
||||
pb "bsm/full/module/finance/wallet/pb"
|
||||
"git.apinb.com/bsm-sdk/core/errcode"
|
||||
"git.apinb.com/bsm-sdk/core/printer"
|
||||
"git.apinb.com/bsm-sdk/core/service"
|
||||
"git.apinb.com/bsm-sdk/core/vars"
|
||||
)
|
||||
|
||||
// 查询交易记录
|
||||
func Transactions(ctx context.Context, in *pb.TransactionsRequest) (reply *pb.TransactionsReply, err error) {
|
||||
auth, err := service.ParseMetaCtx(ctx, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if in.Page <= 1 {
|
||||
in.Page = 1
|
||||
}
|
||||
if in.PageSize <= 1 {
|
||||
in.PageSize = 20
|
||||
}
|
||||
list, total, err := models.FindWalletRecords(auth.Identity, in.Start, in.End, in.TransType, in.TradeType, in.Page, in.PageSize)
|
||||
if err != nil {
|
||||
printer.Error(err.Error())
|
||||
return nil, errcode.ErrDB
|
||||
}
|
||||
res := &pb.TransactionsReply{
|
||||
Total: total,
|
||||
}
|
||||
data := make([]*pb.Transaction, 0)
|
||||
if len(list) > 0 {
|
||||
for _, item := range list {
|
||||
data = append(data, &pb.Transaction{
|
||||
TransType: int32(item.TransType),
|
||||
TradeType: int32(item.TradeType),
|
||||
InTradeNo: item.InTradeNo,
|
||||
OutTradeNo: item.OutTradeNo,
|
||||
Money: item.Money,
|
||||
Fee: item.Fee,
|
||||
PayChannel: int32(item.PayChannel),
|
||||
PayType: item.PayType,
|
||||
Remark: item.Remark,
|
||||
Created: item.CreatedAt.Format(vars.YYYY_MM_DD_HH_MM_SS),
|
||||
})
|
||||
}
|
||||
}
|
||||
res.Records = data
|
||||
return res, nil
|
||||
}
|
||||
69
module/finance/wallet/internal/logic/basic/wallet.go
Normal file
69
module/finance/wallet/internal/logic/basic/wallet.go
Normal file
@@ -0,0 +1,69 @@
|
||||
// Package basic 钱包基础业务逻辑
|
||||
package basic
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"bsm/full/module/finance/wallet/internal/config"
|
||||
"bsm/full/module/finance/wallet/internal/excode"
|
||||
"bsm/full/module/finance/wallet/internal/impl"
|
||||
"bsm/full/module/finance/wallet/internal/models"
|
||||
"git.apinb.com/bsm-sdk/core/errcode"
|
||||
"git.apinb.com/bsm-sdk/core/utils"
|
||||
)
|
||||
|
||||
// WalletPay 钱包支付结构体
|
||||
type WalletPay struct {
|
||||
ctx context.Context
|
||||
Body *models.WalletBasic
|
||||
}
|
||||
|
||||
// NewWallet 创建钱包支付实例
|
||||
// 验证用户身份、钱包状态、支付密码和余额
|
||||
func NewWallet(passportIdentity, pwd string, amount int64) (*WalletPay, error) {
|
||||
// 检查钱包是否存在
|
||||
wallet := models.WalletExists(passportIdentity)
|
||||
if wallet == nil {
|
||||
return nil, errcode.ErrNotFound(404, "wallet")
|
||||
}
|
||||
|
||||
// 检查钱包状态
|
||||
if wallet.Status == -1 {
|
||||
return nil, errcode.ErrPermissionDenied
|
||||
}
|
||||
|
||||
// 验证支付密码
|
||||
encPassword := EncodePassword(pwd, passportIdentity)
|
||||
if encPassword != wallet.PayPassword {
|
||||
return nil, errcode.ErrPassword
|
||||
}
|
||||
|
||||
// 检查余额是否足够
|
||||
if amount > wallet.Balance {
|
||||
return nil, excode.ErrBalanceNotEnough
|
||||
}
|
||||
|
||||
return &WalletPay{
|
||||
Body: wallet,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// TradeConsum 执行交易消费
|
||||
// 扣除钱包余额和可提现余额
|
||||
func (srv *WalletPay) TradeConsum(amount int64) error {
|
||||
data := map[string]interface{}{
|
||||
"balance": srv.Body.Balance - amount,
|
||||
"withdrawal_balance": srv.Body.WithdrawalBalance - amount,
|
||||
}
|
||||
err := impl.DBService.Model(&models.WalletBasic{}).Where("identity=?", srv.Body.Identity).UpdateColumns(data).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// EncodePassword 加密支付密码
|
||||
// 使用SHA256算法对密码进行加密
|
||||
func EncodePassword(pwd, passportIdentity string) string {
|
||||
return utils.Sha256(pwd, passportIdentity+config.Spec.Wallet.PublicKey)
|
||||
}
|
||||
138
module/finance/wallet/internal/logic/payment/by_charge.go
Normal file
138
module/finance/wallet/internal/logic/payment/by_charge.go
Normal file
@@ -0,0 +1,138 @@
|
||||
package payment
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"bsm/full/module/finance/wallet/internal/excode"
|
||||
"bsm/full/module/finance/wallet/internal/logic/alipay"
|
||||
"bsm/full/module/finance/wallet/internal/logic/wechat"
|
||||
"bsm/full/module/finance/wallet/internal/models"
|
||||
pb "bsm/full/module/finance/wallet/pb"
|
||||
"git.apinb.com/bsm-sdk/core/env"
|
||||
"git.apinb.com/bsm-sdk/core/errcode"
|
||||
"git.apinb.com/bsm-sdk/core/printer"
|
||||
"git.apinb.com/bsm-sdk/core/service"
|
||||
"git.apinb.com/bsm-sdk/core/utils"
|
||||
)
|
||||
|
||||
// 支付-充值
|
||||
func ByCharge(ctx context.Context, in *pb.ChargeRequest) (reply *pb.PaymentReply, err error) {
|
||||
auth, ok := service.ParseMetaCtx(ctx, nil)
|
||||
if ok != nil {
|
||||
return nil, ok
|
||||
}
|
||||
|
||||
if in.Amount == 0 || in.Desc == "" {
|
||||
return nil, errcode.ErrInvalidArgument
|
||||
}
|
||||
|
||||
var (
|
||||
myWallet, wErr = models.GetWalletByPassportIdentity(auth.ID, auth.Identity)
|
||||
orderNo = utils.RandomString(32)
|
||||
paymentRecrod = models.WalletPayment{
|
||||
WalletIdentity: myWallet.Identity,
|
||||
Type: 1, //1充值,2为订单
|
||||
OrderNo: orderNo,
|
||||
PayChannel: int8(in.PayChannel),
|
||||
PayType: in.PayType,
|
||||
Amount: in.Amount,
|
||||
}
|
||||
)
|
||||
if wErr != nil || myWallet.Identity == "" {
|
||||
return nil, errcode.ErrNotFound(404, "wallet")
|
||||
}
|
||||
|
||||
paymentRecrod.Identity = utils.UUID()
|
||||
paymentRecrod.PassportID = auth.ID
|
||||
paymentRecrod.PassportIdentity = auth.Identity
|
||||
|
||||
var payBodyAttach strings.Builder
|
||||
payBodyAttach.WriteString(env.Runtime.Workspace)
|
||||
payBodyAttach.WriteString(",")
|
||||
payBodyAttach.WriteString(paymentRecrod.Identity)
|
||||
|
||||
replyResult := map[string]string{}
|
||||
switch in.PayChannel {
|
||||
case 1:
|
||||
if in.OpenId == "" {
|
||||
return nil, errcode.ErrInvalidArgument
|
||||
}
|
||||
wechat, err := wechat.NewWechat()
|
||||
if err != nil {
|
||||
printer.Error(err.Error())
|
||||
return nil, excode.ErrWechatInit
|
||||
}
|
||||
res, err := wechat.GetResponse(payBodyAttach.String(), orderNo, in.Desc, in.OpenId, in.Amount)
|
||||
if err != nil {
|
||||
printer.Error(err.Error())
|
||||
return nil, excode.ErrWechatGetResp
|
||||
}
|
||||
|
||||
switch in.PayType {
|
||||
case "JSAPI":
|
||||
replyResult, err = wechat.JsapiPaySign(res.PrepayId)
|
||||
if err != nil {
|
||||
printer.Error(err.Error())
|
||||
return nil, excode.ErrWechatGetResp
|
||||
}
|
||||
case "APP":
|
||||
replyResult, err = wechat.AppPaySign(res.PrepayId)
|
||||
if err != nil {
|
||||
printer.Error(err.Error())
|
||||
return nil, excode.ErrWechatGetResp
|
||||
}
|
||||
case "MINI":
|
||||
replyResult, err = wechat.MiniPaySign(res.PrepayId)
|
||||
if err != nil {
|
||||
printer.Error(err.Error())
|
||||
return nil, excode.ErrWechatGetResp
|
||||
}
|
||||
default:
|
||||
return nil, excode.ErrPayType
|
||||
}
|
||||
|
||||
case 2:
|
||||
var result string
|
||||
alipay, err := alipay.NewAlipay()
|
||||
if err != nil {
|
||||
printer.Error(err.Error())
|
||||
return nil, excode.ErrAlipayInit
|
||||
}
|
||||
alipay.SetBody(payBodyAttach.String(), orderNo, in.Amount)
|
||||
|
||||
switch in.PayType {
|
||||
case "WAP":
|
||||
result, err = alipay.TradeWapPay()
|
||||
if err != nil {
|
||||
printer.Error(err.Error())
|
||||
return nil, excode.ErrAlipayGetResp
|
||||
}
|
||||
|
||||
case "APP":
|
||||
result, err = alipay.TradeAppPay()
|
||||
if err != nil {
|
||||
printer.Error(err.Error())
|
||||
return nil, excode.ErrAlipayGetResp
|
||||
}
|
||||
default:
|
||||
return nil, excode.ErrPayType
|
||||
}
|
||||
|
||||
replyResult["payUrl"] = result
|
||||
|
||||
default:
|
||||
return nil, excode.ErrPayChannel
|
||||
}
|
||||
|
||||
//写入支付记录表(不可忽略错误)
|
||||
if err := models.CreatePaymentRecord(&paymentRecrod); err != nil {
|
||||
printer.Error("CreatePaymentRecord failed: ", err.Error())
|
||||
return nil, errcode.ErrDB
|
||||
}
|
||||
|
||||
return &pb.PaymentReply{
|
||||
Code: 200,
|
||||
Result: replyResult,
|
||||
}, nil
|
||||
}
|
||||
162
module/finance/wallet/internal/logic/payment/by_order.go
Normal file
162
module/finance/wallet/internal/logic/payment/by_order.go
Normal file
@@ -0,0 +1,162 @@
|
||||
package payment
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"bsm/full/module/finance/wallet/internal/excode"
|
||||
"bsm/full/module/finance/wallet/internal/logic/alipay"
|
||||
"bsm/full/module/finance/wallet/internal/logic/basic"
|
||||
"bsm/full/module/finance/wallet/internal/logic/wechat"
|
||||
"bsm/full/module/finance/wallet/internal/models"
|
||||
pb "bsm/full/module/finance/wallet/pb"
|
||||
"git.apinb.com/bsm-sdk/core/env"
|
||||
"git.apinb.com/bsm-sdk/core/errcode"
|
||||
"git.apinb.com/bsm-sdk/core/printer"
|
||||
"git.apinb.com/bsm-sdk/core/service"
|
||||
"git.apinb.com/bsm-sdk/core/utils"
|
||||
)
|
||||
|
||||
// 支付-电商订单
|
||||
func ByOrder(ctx context.Context, in *pb.OrderRequest) (reply *pb.PaymentReply, err error) {
|
||||
auth, ok := service.ParseMetaCtx(ctx, nil)
|
||||
if ok != nil {
|
||||
return nil, ok
|
||||
}
|
||||
|
||||
if in.OrderNo == "" || in.Desc == "" {
|
||||
return nil, errcode.ErrInvalidArgument
|
||||
}
|
||||
|
||||
amount, err := models.GetTransPriceByOrderNo(in.OrderNo)
|
||||
if err != nil {
|
||||
return nil, errcode.ErrNotFound(404, "order")
|
||||
}
|
||||
|
||||
var (
|
||||
myWallet, wErr = models.GetWalletByPassportIdentity(auth.ID, auth.Identity)
|
||||
paymentRecrod = models.WalletPayment{
|
||||
WalletIdentity: myWallet.Identity,
|
||||
Type: 2, //1充值,2为订单
|
||||
OrderNo: in.OrderNo,
|
||||
PayChannel: int8(in.PayChannel),
|
||||
PayType: in.PayType,
|
||||
Amount: amount,
|
||||
}
|
||||
)
|
||||
if wErr != nil || myWallet.Identity == "" {
|
||||
return nil, errcode.ErrNotFound(404, "wallet")
|
||||
}
|
||||
|
||||
paymentRecrod.Identity = utils.UUID()
|
||||
paymentRecrod.PassportID = auth.ID
|
||||
paymentRecrod.PassportIdentity = auth.Identity
|
||||
|
||||
var payBodyAttach strings.Builder
|
||||
payBodyAttach.WriteString(env.Runtime.Workspace)
|
||||
payBodyAttach.WriteString(",")
|
||||
payBodyAttach.WriteString(paymentRecrod.Identity)
|
||||
|
||||
replyResult := make(map[string]string)
|
||||
switch in.PayChannel {
|
||||
case 1:
|
||||
wechat, err := wechat.NewWechat()
|
||||
if err != nil {
|
||||
printer.Error(err.Error())
|
||||
return nil, excode.ErrWechatInit
|
||||
}
|
||||
|
||||
res, err := wechat.GetResponse(payBodyAttach.String(), in.OrderNo, in.Desc, in.OpenId, amount)
|
||||
if err != nil {
|
||||
printer.Error(err.Error())
|
||||
return nil, excode.ErrWechatGetResp
|
||||
}
|
||||
|
||||
switch in.PayType {
|
||||
case "JSAPI":
|
||||
replyResult, err = wechat.JsapiPaySign(res.PrepayId)
|
||||
if err != nil {
|
||||
printer.Error(err.Error())
|
||||
return nil, excode.ErrWechatGetResp
|
||||
}
|
||||
case "APP":
|
||||
replyResult, err = wechat.AppPaySign(res.PrepayId)
|
||||
if err != nil {
|
||||
printer.Error(err.Error())
|
||||
return nil, excode.ErrWechatGetResp
|
||||
}
|
||||
case "MINI":
|
||||
replyResult, err = wechat.MiniPaySign(res.PrepayId)
|
||||
if err != nil {
|
||||
printer.Error(err.Error())
|
||||
return nil, excode.ErrWechatGetResp
|
||||
}
|
||||
case "NATIVE":
|
||||
replyResult, err = wechat.NativePaySign(payBodyAttach.String(), in.OrderNo, in.Desc, "", in.OpenId, amount)
|
||||
if err == nil {
|
||||
if v, ok := replyResult["code_url"]; ok {
|
||||
replyResult["qr_code"] = v
|
||||
}
|
||||
} else {
|
||||
printer.Error(err.Error())
|
||||
return nil, excode.ErrWechatGetResp
|
||||
}
|
||||
|
||||
default:
|
||||
return nil, excode.ErrPayType
|
||||
}
|
||||
|
||||
replyResult["prepay_id"] = res.PrepayId
|
||||
|
||||
case 2:
|
||||
var result string
|
||||
alipay, err := alipay.NewAlipay()
|
||||
if err != nil {
|
||||
printer.Error(err.Error())
|
||||
return nil, excode.ErrAlipayInit
|
||||
}
|
||||
alipay.SetBody(payBodyAttach.String(), in.OrderNo, amount)
|
||||
switch in.PayType {
|
||||
case "WAP":
|
||||
result, err = alipay.TradeWapPay()
|
||||
if err != nil {
|
||||
printer.Error(err.Error())
|
||||
return nil, excode.ErrAlipayGetResp
|
||||
}
|
||||
case "APP":
|
||||
result, err = alipay.TradeAppPay()
|
||||
if err != nil {
|
||||
printer.Error(err.Error())
|
||||
return nil, excode.ErrAlipayGetResp
|
||||
}
|
||||
default:
|
||||
return nil, excode.ErrPayType
|
||||
}
|
||||
|
||||
replyResult["payUrl"] = result
|
||||
|
||||
case 3:
|
||||
walletSrv, err := basic.NewWallet(auth.Identity, in.Password, amount)
|
||||
if err != nil {
|
||||
return nil, errcode.ErrDB
|
||||
}
|
||||
err = walletSrv.TradeConsum(amount)
|
||||
if err != nil {
|
||||
return nil, excode.ErrBalanceNotEnough
|
||||
}
|
||||
default:
|
||||
return nil, excode.ErrPayChannel
|
||||
}
|
||||
|
||||
// 写入支付记录表(不可忽略错误)
|
||||
if err := models.CreatePaymentRecord(&paymentRecrod); err != nil {
|
||||
printer.Error("CreatePaymentRecord failed: ", err.Error())
|
||||
return nil, errcode.ErrDB
|
||||
}
|
||||
|
||||
//return
|
||||
return &pb.PaymentReply{
|
||||
Code: 200,
|
||||
Result: replyResult,
|
||||
}, nil
|
||||
}
|
||||
40
module/finance/wallet/internal/logic/payment/callback.go
Normal file
40
module/finance/wallet/internal/logic/payment/callback.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package payment
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"bsm/full/module/finance/wallet/internal/models"
|
||||
pb "bsm/full/module/finance/wallet/pb"
|
||||
"git.apinb.com/bsm-sdk/core/errcode"
|
||||
"git.apinb.com/bsm-sdk/core/service"
|
||||
"git.apinb.com/bsm-sdk/core/vars"
|
||||
)
|
||||
|
||||
// 回调更新支付的结果和状态
|
||||
func Callback(ctx context.Context, in *pb.CallbackRequest) (reply *pb.StatusReply, err error) {
|
||||
auth, ok := service.ParseMetaCtx(ctx, nil)
|
||||
if ok != nil {
|
||||
return nil, ok
|
||||
}
|
||||
|
||||
if in.Identity == "" {
|
||||
return nil, errcode.ErrInvalidArgument
|
||||
}
|
||||
|
||||
var status int8 = 0
|
||||
if in.CallbackStatus {
|
||||
status = 2
|
||||
} else {
|
||||
status = -1
|
||||
}
|
||||
err = models.UpsetWalletPaymentByIdentity(auth.Identity, in.Identity, status, in.CallbackMsg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &pb.StatusReply{
|
||||
Message: vars.OK,
|
||||
Timeseq: time.Now().UnixMilli(),
|
||||
}, nil
|
||||
|
||||
}
|
||||
37
module/finance/wallet/internal/logic/payment/get.go
Normal file
37
module/finance/wallet/internal/logic/payment/get.go
Normal file
@@ -0,0 +1,37 @@
|
||||
package payment
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"bsm/full/module/finance/wallet/internal/models"
|
||||
pb "bsm/full/module/finance/wallet/pb"
|
||||
"git.apinb.com/bsm-sdk/core/errcode"
|
||||
"git.apinb.com/bsm-sdk/core/service"
|
||||
)
|
||||
|
||||
// 获取支付的详情
|
||||
func Get(ctx context.Context, in *pb.IdentRequest) (reply *pb.PaymentItem, err error) {
|
||||
auth, ok := service.ParseMetaCtx(ctx, nil)
|
||||
if ok != nil {
|
||||
return nil, ok
|
||||
}
|
||||
|
||||
if in.Identity == "" {
|
||||
return nil, errcode.ErrInvalidArgument
|
||||
}
|
||||
paymentRecord, err := models.GetWalletPaymentByIdentity(auth.Identity, in.Identity)
|
||||
if err != nil {
|
||||
return nil, errcode.ErrNotFound(404, "payment")
|
||||
}
|
||||
|
||||
return &pb.PaymentItem{
|
||||
OrderNo: paymentRecord.OrderNo,
|
||||
TradeNo: paymentRecord.TradeNo,
|
||||
Type: int32(paymentRecord.Type),
|
||||
PayChannel: int32(paymentRecord.PayChannel),
|
||||
PayType: paymentRecord.PayType,
|
||||
Amount: paymentRecord.Amount,
|
||||
Args: paymentRecord.Args,
|
||||
Status: int32(paymentRecord.Status),
|
||||
}, nil
|
||||
}
|
||||
27
module/finance/wallet/internal/logic/payment/hello.go
Normal file
27
module/finance/wallet/internal/logic/payment/hello.go
Normal file
@@ -0,0 +1,27 @@
|
||||
// Package payment 支付相关业务逻辑
|
||||
package payment
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
pb "bsm/full/module/finance/wallet/pb"
|
||||
"git.apinb.com/bsm-sdk/core/service"
|
||||
)
|
||||
|
||||
// Hello 支付服务健康检查接口
|
||||
// 用于验证支付服务是否正常运行
|
||||
func Hello(ctx context.Context, in *pb.Empty) (reply *pb.PaymentReply, err error) {
|
||||
// 解析授权元数据
|
||||
_, err = service.ParseMetaCtx(ctx, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 返回服务状态信息
|
||||
return &pb.PaymentReply{
|
||||
Result: map[string]string{
|
||||
"message": "Payment service is running",
|
||||
"status": "healthy",
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
48
module/finance/wallet/internal/logic/payment/way.go
Normal file
48
module/finance/wallet/internal/logic/payment/way.go
Normal file
@@ -0,0 +1,48 @@
|
||||
package payment
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"bsm/full/module/finance/wallet/internal/config"
|
||||
"bsm/full/module/finance/wallet/internal/models"
|
||||
pb "bsm/full/module/finance/wallet/pb"
|
||||
"git.apinb.com/bsm-sdk/core/service"
|
||||
)
|
||||
|
||||
// 获取平台支持的支付网关
|
||||
func Way(ctx context.Context, in *pb.WayRequest) (reply *pb.WayReply, err error) {
|
||||
auth, ok := service.ParseMetaCtx(ctx, nil)
|
||||
if ok != nil {
|
||||
return nil, ok
|
||||
}
|
||||
|
||||
items := make([]*pb.WayItem, 0)
|
||||
|
||||
if config.Spec.Wallet.AlipyIsOpen {
|
||||
items = append(items, &pb.WayItem{
|
||||
Ident: "ALIPAY",
|
||||
Title: "支付宝",
|
||||
})
|
||||
}
|
||||
|
||||
if config.Spec.Wallet.WechatpayIsOpen {
|
||||
items = append(items, &pb.WayItem{
|
||||
Ident: "WECHATPAY",
|
||||
Title: "微信支付",
|
||||
})
|
||||
}
|
||||
|
||||
if config.Spec.Wallet.WalletIsOpen {
|
||||
balance := fmt.Sprintf("%.2f", models.GetWalletBalanceByPassportIdentity(auth.Identity))
|
||||
items = append(items, &pb.WayItem{
|
||||
Ident: "WALLET",
|
||||
Title: "钱包余额",
|
||||
Intro: "余额:" + balance + " 元",
|
||||
})
|
||||
}
|
||||
|
||||
return &pb.WayReply{
|
||||
Way: items,
|
||||
}, nil
|
||||
}
|
||||
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
|
||||
}
|
||||
197
module/finance/wallet/internal/models/query.go
Normal file
197
module/finance/wallet/internal/models/query.go
Normal file
@@ -0,0 +1,197 @@
|
||||
// Package models 定义钱包相关的数据模型和数据库操作
|
||||
package models
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"bsm/full/module/finance/wallet/internal/impl"
|
||||
"git.apinb.com/bsm-sdk/core/types"
|
||||
"git.apinb.com/bsm-sdk/core/utils"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// InitData 初始化默认钱包数据
|
||||
func InitData() error {
|
||||
var (
|
||||
cnt int64
|
||||
err error
|
||||
userIdentity string
|
||||
)
|
||||
|
||||
// 获取默认用户唯一标识
|
||||
err = impl.DBService.Table("passport_account").Select("identity").Where("account=?", "demo").Find(&userIdentity).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if userIdentity == "" {
|
||||
return errors.New("默认用户未找到")
|
||||
}
|
||||
|
||||
// 检查是否已经创建了钱包信息
|
||||
err = impl.DBService.Model(&WalletBasic{}).Where("passport_identity=?", userIdentity).Count(&cnt).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 如果钱包不存在,则创建默认钱包
|
||||
if cnt == 0 {
|
||||
pa := WalletBasic{
|
||||
Balance: 0,
|
||||
WithdrawalBalance: 0,
|
||||
Std_Identity: types.Std_Identity{Identity: utils.ULID()},
|
||||
Std_Passport: types.Std_Passport{PassportIdentity: userIdentity},
|
||||
}
|
||||
err = impl.DBService.Create(&pa).Error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetWalletBalanceByPassportIdentity 根据用户身份获取钱包余额
|
||||
func GetWalletBalanceByPassportIdentity(passport_identity string) float64 {
|
||||
wallet := new(WalletBasic)
|
||||
err := impl.DBService.Where("passport_identity = ?", passport_identity).First(wallet).Error
|
||||
if err != nil {
|
||||
return 0.00
|
||||
}
|
||||
return float64(wallet.Balance / 100)
|
||||
}
|
||||
|
||||
// WalletExists 检查钱包是否存在
|
||||
func WalletExists(passportIdentity string) *WalletBasic {
|
||||
wallet := new(WalletBasic)
|
||||
err := impl.DBService.Where("passport_identity = ?", passportIdentity).First(wallet).Error
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return wallet
|
||||
}
|
||||
|
||||
// GetWalletByPassportIdentity 根据用户身份获取钱包,如果不存在则创建
|
||||
func GetWalletByPassportIdentity(passport_id uint, passport_identity string) (*WalletBasic, error) {
|
||||
wallet := new(WalletBasic)
|
||||
err := impl.DBService.Where("passport_identity = ?", passport_identity).First(wallet).Error
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
// 钱包不存在,创建新钱包
|
||||
wallet.Identity = utils.UUID()
|
||||
wallet.PassportID = passport_id
|
||||
wallet.PassportIdentity = passport_identity
|
||||
impl.DBService.Create(wallet)
|
||||
return wallet, nil
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return wallet, nil
|
||||
}
|
||||
|
||||
// GetWalletByPassportIdentityT 根据用户身份获取钱包(不创建)
|
||||
func GetWalletByPassportIdentityT(passport_id int64, passport_identity string) (*WalletBasic, error) {
|
||||
wallet := &WalletBasic{}
|
||||
err := impl.DBService.Where("passport_identity = ?", passport_identity).First(wallet).Error
|
||||
return wallet, err
|
||||
}
|
||||
|
||||
// GetTransPriceByOrderNo 根据订单号获取交易价格
|
||||
func GetTransPriceByOrderNo(no string) (int64, error) {
|
||||
var amount int64
|
||||
impl.DBService.Select("trans_price").Table("order_summary").Where("order_no=? and status=1", no).Scan(&amount)
|
||||
if amount == 0 {
|
||||
return 0, status.Error(codes.Internal, "Order is close.")
|
||||
}
|
||||
return amount, nil
|
||||
}
|
||||
|
||||
// GetWalletPaymentByIdentity 根据身份和支付ID获取钱包支付记录
|
||||
func GetWalletPaymentByIdentity(passport_identity, identity string) (*WalletPayment, error) {
|
||||
fp := new(WalletPayment)
|
||||
err := impl.DBService.Where("passport_identity=? and identity=?", passport_identity, identity).First(&fp).Error
|
||||
return fp, err
|
||||
}
|
||||
|
||||
// UpsetWalletPaymentByIdentity 更新钱包支付记录状态
|
||||
func UpsetWalletPaymentByIdentity(passport_identity, identity string, CallbackStatus int8, CallbackMsg string) error {
|
||||
err := impl.DBService.Model(&WalletPayment{}).Where("passport_identity=? and identity=?", passport_identity, identity).Updates(map[string]interface{}{"status": CallbackStatus, "call_back_msg": CallbackMsg}).Error
|
||||
return err
|
||||
}
|
||||
|
||||
// CreatePaymentRecord 创建支付记录
|
||||
func CreatePaymentRecord(fp *WalletPayment) error {
|
||||
return impl.DBService.Create(&fp).Error
|
||||
}
|
||||
|
||||
// CreateTradeRecord 创建交易记录
|
||||
func CreateTradeRecord(fr *WalletRecord) error {
|
||||
return impl.DBService.Create(&fr).Error
|
||||
}
|
||||
|
||||
// ChargeWallet 为钱包充值
|
||||
func ChargeWallet(passport_id uint, passport_identity, order_no string, paySource int32, amount int64) error {
|
||||
wallet, err := GetWalletByPassportIdentity(passport_id, passport_identity)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 更新钱包余额
|
||||
data := map[string]interface{}{
|
||||
"balance": wallet.Balance + amount,
|
||||
"withdrawal_balance": wallet.WithdrawalBalance + amount,
|
||||
}
|
||||
err = impl.DBService.Model(&WalletBasic{}).Where("identity=?", wallet.Identity).UpdateColumns(data).Error
|
||||
if err != nil {
|
||||
return err
|
||||
} else {
|
||||
// 创建交易记录
|
||||
record := &WalletRecord{
|
||||
WalletIdentity: wallet.Identity,
|
||||
TransType: 1, // 充值类型
|
||||
InTradeNo: order_no,
|
||||
Money: amount,
|
||||
TradeType: 1, // 收入类型
|
||||
PayChannel: int8(paySource),
|
||||
}
|
||||
record.PassportID = passport_id
|
||||
record.PassportIdentity = passport_identity
|
||||
CreateTradeRecord(record)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// FindWalletRecords 查询钱包交易记录
|
||||
func FindWalletRecords(passportIdentity, start, end string, transType, tradeType, page, pageSize int64) ([]*WalletRecord, int64, error) {
|
||||
list := make([]*WalletRecord, 0)
|
||||
tx := impl.DBService.Where("passport_identity = ?", passportIdentity)
|
||||
|
||||
// 添加时间范围过滤
|
||||
if start != "" {
|
||||
tx.Where("created_at >= ?", start)
|
||||
}
|
||||
if end != "" {
|
||||
tx.Where("created_at <= ?", end)
|
||||
}
|
||||
|
||||
// 添加交易类型过滤
|
||||
if transType != 0 {
|
||||
tx.Where("trans_type = ?", transType)
|
||||
}
|
||||
if tradeType != 0 {
|
||||
tx.Where("trade_type = ?", tradeType)
|
||||
}
|
||||
|
||||
// 分页查询
|
||||
res := tx.Order("created_at desc").Limit(int(pageSize)).Offset(int((page - 1) * pageSize)).Find(&list)
|
||||
if res.Error != nil {
|
||||
if !errors.Is(res.Error, gorm.ErrRecordNotFound) {
|
||||
return nil, 0, res.Error
|
||||
}
|
||||
return nil, 0, nil
|
||||
}
|
||||
return list, res.RowsAffected, nil
|
||||
}
|
||||
37
module/finance/wallet/internal/models/wallet_apply_cash.go
Normal file
37
module/finance/wallet/internal/models/wallet_apply_cash.go
Normal file
@@ -0,0 +1,37 @@
|
||||
// Models generated by mesh dev cli,@Author: David Yan(david.yan@qq.com).
|
||||
package models
|
||||
|
||||
import (
|
||||
"git.apinb.com/bsm-sdk/core/database"
|
||||
"git.apinb.com/bsm-sdk/core/types"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
/*
|
||||
* WalletApplyCash
|
||||
* Comment: 提现信息表
|
||||
* Version: 10
|
||||
* Created: 2022-04-14 22:18:44 , Updated:0001-01-01 00:00:00
|
||||
*/
|
||||
type WalletApplyCash struct {
|
||||
gorm.Model
|
||||
types.Std_Identity
|
||||
types.Std_Passport
|
||||
WalletIdentity string `gorm:"column:wallet_identity;type:varchar(36);not null;" json:"wallet_identity"` // 钱包唯一码
|
||||
CashNo string `gorm:"column:cash_no;type:varchar(255);default:'';" json:"cash_no"` // 钱包内部交易流水号
|
||||
TradeNo string `gorm:"column:trade_no;type:varchar(255);default:'';" json:"trade_no"` // 第三方交易流水号
|
||||
Remark string `gorm:"column:remark;type:varchar(255);default:'';" json:"remark"` // 备注
|
||||
Amount int64 `gorm:"column:amount;default:0;" json:"amount"` // 提现金额,单位:分
|
||||
Channel int8 `gorm:"column:channel;default:0;" json:"channel"` // 提现方式 1:微信 2:支付宝 3:银行卡
|
||||
Status int8 `gorm:"column:status;default:0;" json:"status"` // 提现状态 -1:提现失败 0:待处理 1:提现成功
|
||||
CallBackMsg string `gorm:"column:call_back_msg;type:varchar(255);default:'';" json:"call_back_msg"` // 提现回调信息
|
||||
}
|
||||
|
||||
func init() {
|
||||
database.AppendMigrate(&WalletApplyCash{})
|
||||
}
|
||||
|
||||
// TableName .
|
||||
func (table *WalletApplyCash) TableName() string {
|
||||
return "wallet_apply_cash" //对应数据库表名
|
||||
}
|
||||
38
module/finance/wallet/internal/models/wallet_bank.go
Normal file
38
module/finance/wallet/internal/models/wallet_bank.go
Normal file
@@ -0,0 +1,38 @@
|
||||
// Models generated by mesh dev cli,@Author: David Yan(david.yan@qq.com).
|
||||
package models
|
||||
|
||||
import (
|
||||
"git.apinb.com/bsm-sdk/core/database"
|
||||
"git.apinb.com/bsm-sdk/core/types"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
/*
|
||||
* WalletBank
|
||||
* Comment: 银行卡信息表
|
||||
* Version: 10
|
||||
* Created: 2022-04-14 22:17:01 , Updated:0001-01-01 00:00:00
|
||||
*/
|
||||
type WalletBank struct {
|
||||
gorm.Model
|
||||
types.Std_Identity
|
||||
types.Std_Passport
|
||||
WalletIdentity string `gorm:"column:wallet_identity;type:varchar(36);not null;" json:"wallet_identity"` // 钱包唯一码
|
||||
CardNo string `gorm:"column:card_no;type:varchar(255);not null;" json:"card_no"` // 银行卡号
|
||||
BankName string `gorm:"column:bank_name;type:varchar(255);not null;" json:"bank_name"` // 银行名
|
||||
CardOwner string `gorm:"column:card_owner;type:varchar(255);not null;" json:"card_owner"` // 持卡人姓名
|
||||
IDCard string `gorm:"column:id_card;type:varchar(255);not null;" json:"id_card"` // 持卡人身份证号
|
||||
Phone string `gorm:"column:phone;type:varchar(20);not null;" json:"phone"` // 银行预留的手机号
|
||||
BindID string `gorm:"column:bind_id;type:varchar(20);default:'';" json:"bind_id"` // 绑定银行卡返回的绑定id
|
||||
BankType string `gorm:"column:bank_type;type:varchar(20);default:'';" json:"bank_type"` // 银行卡类型 DC为储蓄卡,CC为信用卡
|
||||
Bank string `gorm:"column:bank;type:varchar(64);not null;" json:"bank"` // 银行卡所属行
|
||||
}
|
||||
|
||||
func init() {
|
||||
database.AppendMigrate(&WalletBank{})
|
||||
}
|
||||
|
||||
// TableName .
|
||||
func (table *WalletBank) TableName() string {
|
||||
return "wallet_bank" //对应数据库表名
|
||||
}
|
||||
33
module/finance/wallet/internal/models/wallet_basic.go
Normal file
33
module/finance/wallet/internal/models/wallet_basic.go
Normal file
@@ -0,0 +1,33 @@
|
||||
// Package models 定义钱包相关的数据模型
|
||||
// @Author: David Yan(david.yan@qq.com)
|
||||
// @Created: 2022-04-14 22:12:48
|
||||
package models
|
||||
|
||||
import (
|
||||
"git.apinb.com/bsm-sdk/core/database"
|
||||
"git.apinb.com/bsm-sdk/core/types"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// WalletBasic 钱包基础信息表
|
||||
// 存储用户钱包的基本信息,包括余额、支付密码、绑定的第三方支付账号等
|
||||
type WalletBasic struct {
|
||||
gorm.Model
|
||||
types.Std_Identity
|
||||
types.Std_Passport
|
||||
AlipayID string `gorm:"column:alipay_id;type:varchar(64);default:'';comment:绑定的支付宝ID;" json:"alipay_id"` // 绑定的支付宝ID
|
||||
WxpayID string `gorm:"column:wxpay_id;type:varchar(64);default:'';comment:绑定的微信支付ID;" json:"wxpay_id"` // 绑定的微信支付ID
|
||||
PayPassword string `gorm:"column:pay_password;type:varchar(255);default:'';comment:支付密码;" json:"pay_password"` // 支付密码
|
||||
Balance int64 `gorm:"column:balance;default:0;comment:余额;" json:"balance"` // 余额,单位:分
|
||||
WithdrawalBalance int64 `gorm:"column:withdrawal_balance;default:0;comment:可提现余额;" json:"withdrawal_balance"` // 可提现余额,单位:分
|
||||
types.Std_Status
|
||||
}
|
||||
|
||||
func init() {
|
||||
database.AppendMigrate(&WalletBasic{})
|
||||
}
|
||||
|
||||
// TableName 返回数据库表名
|
||||
func (table *WalletBasic) TableName() string {
|
||||
return "wallet_basic"
|
||||
}
|
||||
40
module/finance/wallet/internal/models/wallet_payment.go
Normal file
40
module/finance/wallet/internal/models/wallet_payment.go
Normal file
@@ -0,0 +1,40 @@
|
||||
// Models generated by mesh dev cli,@Author: David Yan(david.yan@qq.com).
|
||||
package models
|
||||
|
||||
import (
|
||||
"git.apinb.com/bsm-sdk/core/database"
|
||||
"git.apinb.com/bsm-sdk/core/types"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
/*
|
||||
* WalletPayment
|
||||
* Comment: 支付记录表
|
||||
* Version: 10
|
||||
* Created: 2022-04-14 22:19:57 , Updated:0001-01-01 00:00:00
|
||||
*/
|
||||
type WalletPayment struct {
|
||||
gorm.Model
|
||||
types.Std_Identity
|
||||
types.Std_Passport
|
||||
WalletIdentity string `gorm:"column:wallet_identity;type:varchar(36);not null;" json:"wallet_identity"` // 钱包唯一码
|
||||
OrderNo string `gorm:"column:order_no;type:varchar(255);not null;" json:"order_no"` // 订单号
|
||||
TradeNo string `gorm:"column:trade_no;type:varchar(255);default:'';" json:"trade_no"` // 第三方交易流水号(创建时可为空,回调后更新)
|
||||
Type int8 `gorm:"column:type;default:0;" json:"type"` // 类型:1充值;2支付电商订单
|
||||
PayChannel int8 `gorm:"column:pay_channel;default:0;" json:"pay_channel"` // 方式 1:微信 2:支付宝 3:银行卡
|
||||
PayType string `gorm:"column:pay_type;type:varchar(255);not null;" json:"pay_type"` // 支付类型 JSAPI:微信浏览器内支付 APP:app支付 MINI:小程序 NATIVE:Native支付,pc端生成二维码供用户扫码支付,QUICK_MSECURITY_PAY:app支付 QUICK_WAP_WAY:手机网站支付 FAST_INSTANT_TRADE_PAY:pc网站支付
|
||||
Amount int64 `gorm:"column:amount;default:0;" json:"amount"` // 金额,单位分
|
||||
Args string `gorm:"column:args;type:varchar(255);default:'';" json:"args"` // 相关参数
|
||||
Remark string `gorm:"column:remark;type:varchar(255);default:'';" json:"remark"` // 备注
|
||||
CallBackMsg string `gorm:"column:callback_msg;type:varchar(255);default:'';" json:"callback_msg"` // 支付回调信息
|
||||
types.Std_Status // 支付状态:-3:手动取消,-2:超时自动取消,-1:支付失败,0:创建,1:支付中,2:支付成功
|
||||
}
|
||||
|
||||
func init() {
|
||||
database.AppendMigrate(&WalletPayment{})
|
||||
}
|
||||
|
||||
// TableName .
|
||||
func (table *WalletPayment) TableName() string {
|
||||
return "wallet_payment" //对应数据库表名
|
||||
}
|
||||
41
module/finance/wallet/internal/models/wallet_record.go
Normal file
41
module/finance/wallet/internal/models/wallet_record.go
Normal file
@@ -0,0 +1,41 @@
|
||||
// Models generated by mesh dev cli,@Author: David Yan(david.yan@qq.com).
|
||||
package models
|
||||
|
||||
import (
|
||||
"git.apinb.com/bsm-sdk/core/database"
|
||||
"git.apinb.com/bsm-sdk/core/types"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
/*
|
||||
* WalletRecord
|
||||
* Comment:
|
||||
* Version: 10
|
||||
* Created: 2022-04-14 22:20:44 , Updated:0001-01-01 00:00:00
|
||||
*/
|
||||
type WalletRecord struct {
|
||||
gorm.Model
|
||||
types.Std_Identity
|
||||
types.Std_Passport
|
||||
WalletIdentity string `gorm:"column:wallet_identity;type:varchar(36);not null;" json:"wallet_identity"` // 钱包唯一标识串
|
||||
TransType int8 `gorm:"column:trans_type;default:0;Index;" json:"trans_type"` // 收支类型,-1:支出,1:收入
|
||||
InTradeNo string `gorm:"column:in_trade_no;type:varchar(50);not null;" json:"in_trade_no"` // 内部交易流水号
|
||||
OutTradeNo string `gorm:"column:out_trade_no;type:varchar(50);default:'';" json:"out_trade_no"` // 外部交易流水号,示例:微信、支付宝、银行卡等
|
||||
Money int64 `gorm:"column:money; unsigned;default:0;" json:"money"` // 交易金额,单位:分
|
||||
Fee int64 `gorm:"column:fee; unsigned;default:0;" json:"fee"` // 交易手续费,单位:分
|
||||
PayChannel int8 `gorm:"column:pay_channel;default:0;" json:"pay_channel"` // 方式 1:微信 2:支付宝 3:银行卡
|
||||
PayType string `gorm:"column:pay_type;type:varchar(255);not null;" json:"pay_type"` // 支付类型 JSAPI:微信浏览器内支付 APP:app支付 MINI:小程序 NATIVE:Native支付,pc端生成二维码供用户扫码支付,QUICK_MSECURITY_PAY:app支付 QUICK_WAP_WAY:手机网站支付 FAST_INSTANT_TRADE_PAY:pc网站支付
|
||||
TradeType int8 `gorm:"column:trade_type;default:0;" json:"trade_type"` // 交易类型,1:充值,2:提现,3:消费,4:退款,5:收益
|
||||
Ymd int32 `gorm:"column:ymd;Index;not null;" json:"ymd"` // 索引:年月日
|
||||
Ym int32 `gorm:"column:ym;Index;not null;" json:"ym"` // 索引:年月
|
||||
Remark string `gorm:"column:remark;type:varchar(255);default:'';" json:"remark"` // 交易备注
|
||||
}
|
||||
|
||||
func init() {
|
||||
database.AppendMigrate(&WalletRecord{})
|
||||
}
|
||||
|
||||
// TableName .
|
||||
func (table *WalletRecord) TableName() string {
|
||||
return "wallet_record" //对应数据库表名
|
||||
}
|
||||
34
module/finance/wallet/internal/models/wallet_refund.go
Normal file
34
module/finance/wallet/internal/models/wallet_refund.go
Normal file
@@ -0,0 +1,34 @@
|
||||
// Models generated by mesh dev cli,@Author: David Yan(david.yan@qq.com).
|
||||
package models
|
||||
|
||||
import (
|
||||
"git.apinb.com/bsm-sdk/core/database"
|
||||
"git.apinb.com/bsm-sdk/core/types"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
/*
|
||||
* WalletRefund
|
||||
* Comment: 退款记录表
|
||||
* Version: 10
|
||||
* Created: 2022-04-14 22:24:38 , Updated:0001-01-01 00:00:00
|
||||
*/
|
||||
type WalletRefund struct {
|
||||
gorm.Model
|
||||
types.Std_Identity
|
||||
types.Std_Passport
|
||||
WalletIdentity string `gorm:"column:wallet_identity;type:varchar(36);not null;" json:"wallet_identity"` // 钱包唯一码
|
||||
OrderIdentity string `gorm:"column:order_identity;type:varchar(64);not null;" json:"order_identity"` // 订单唯一码
|
||||
Reason string `gorm:"column:reason;type:text;default:'';" json:"reason"` // 退款理由
|
||||
OrderInfo string `gorm:"column:order_info;type:text;default:'';" json:"order_info"` // 订单信息
|
||||
Result string `gorm:"column:result;type:text;default:'';" json:"result"` // 处理结果
|
||||
}
|
||||
|
||||
func init() {
|
||||
database.AppendMigrate(&WalletRefund{})
|
||||
}
|
||||
|
||||
// TableName .
|
||||
func (table *WalletRefund) TableName() string {
|
||||
return "wallet_refund" //对应数据库表名
|
||||
}
|
||||
36
module/finance/wallet/internal/server/alipay_server.go
Normal file
36
module/finance/wallet/internal/server/alipay_server.go
Normal file
@@ -0,0 +1,36 @@
|
||||
// Code generated by protoc-gen-slc. DO NOT EDIT.
|
||||
package server
|
||||
|
||||
import (
|
||||
"context"
|
||||
"bsm/full/module/finance/wallet/internal/logic/alipay"
|
||||
pb "bsm/full/module/finance/wallet/pb"
|
||||
)
|
||||
|
||||
type AlipayServer struct {
|
||||
pb.UnimplementedAlipayServer
|
||||
}
|
||||
|
||||
func NewAlipayServer() *AlipayServer {
|
||||
return &AlipayServer{}
|
||||
}
|
||||
|
||||
// 支付宝wap支付
|
||||
func (s *AlipayServer) WapPay(ctx context.Context, in *pb.AlipayTradeWapPayRequest) (*pb.AlipayTradeWapPayReply, error) {
|
||||
return alipay.WapPay(ctx, in)
|
||||
}
|
||||
|
||||
// 支付宝电脑网站支付
|
||||
func (s *AlipayServer) PagePay(ctx context.Context, in *pb.AlipayTradePagePayRequest) (*pb.AlipayTradePagePayReply, error) {
|
||||
return alipay.PagePay(ctx, in)
|
||||
}
|
||||
|
||||
// 支付宝APP支付
|
||||
func (s *AlipayServer) AppPay(ctx context.Context, in *pb.AlipayTradeAppPayRequest) (*pb.AlipayTradeAppPayReply, error) {
|
||||
return alipay.AppPay(ctx, in)
|
||||
}
|
||||
|
||||
// 支付宝转账到个人支付宝账户
|
||||
func (s *AlipayServer) Transfer(ctx context.Context, in *pb.AlipayUniTransferRequest) (*pb.AlipayUniTransferReply, error) {
|
||||
return alipay.Transfer(ctx, in)
|
||||
}
|
||||
56
module/finance/wallet/internal/server/basic_server.go
Normal file
56
module/finance/wallet/internal/server/basic_server.go
Normal file
@@ -0,0 +1,56 @@
|
||||
// Code generated by protoc-gen-slc. DO NOT EDIT.
|
||||
package server
|
||||
|
||||
import (
|
||||
"context"
|
||||
"bsm/full/module/finance/wallet/internal/logic/basic"
|
||||
pb "bsm/full/module/finance/wallet/pb"
|
||||
)
|
||||
|
||||
type BasicServer struct {
|
||||
pb.UnimplementedBasicServer
|
||||
}
|
||||
|
||||
func NewBasicServer() *BasicServer {
|
||||
return &BasicServer{}
|
||||
}
|
||||
|
||||
// 获取钱包信息
|
||||
func (s *BasicServer) GetWallet(ctx context.Context, in *pb.GetWalletRequest) (*pb.GetWalletReply, error) {
|
||||
return basic.GetWallet(ctx, in)
|
||||
}
|
||||
|
||||
// 设置支付密码
|
||||
func (s *BasicServer) SetPayPassword(ctx context.Context, in *pb.SetPayPasswordRequest) (*pb.StatusReply, error) {
|
||||
return basic.SetPayPassword(ctx, in)
|
||||
}
|
||||
|
||||
// 绑定微信或支付宝账户
|
||||
func (s *BasicServer) BindPaymentId(ctx context.Context, in *pb.BindPaymentIDRequest) (*pb.StatusReply, error) {
|
||||
return basic.BindPaymentId(ctx, in)
|
||||
}
|
||||
|
||||
// 查询交易记录
|
||||
func (s *BasicServer) Transactions(ctx context.Context, in *pb.TransactionsRequest) (*pb.TransactionsReply, error) {
|
||||
return basic.Transactions(ctx, in)
|
||||
}
|
||||
|
||||
// 添加银行卡
|
||||
func (s *BasicServer) AddBankCard(ctx context.Context, in *pb.AddBankCardRequest) (*pb.StatusReply, error) {
|
||||
return basic.AddBankCard(ctx, in)
|
||||
}
|
||||
|
||||
// 获取用户银行卡列表
|
||||
func (s *BasicServer) GetBankCard(ctx context.Context, in *pb.FinanceEmpty) (*pb.GetBankCardReply, error) {
|
||||
return basic.GetBankCard(ctx, in)
|
||||
}
|
||||
|
||||
// 删除银行卡
|
||||
func (s *BasicServer) RmBankCard(ctx context.Context, in *pb.RmBankCardRequest) (*pb.StatusReply, error) {
|
||||
return basic.RmBankCard(ctx, in)
|
||||
}
|
||||
|
||||
// 申请提现
|
||||
func (s *BasicServer) ApplyCash(ctx context.Context, in *pb.ApplyCashRequest) (*pb.StatusReply, error) {
|
||||
return basic.ApplyCash(ctx, in)
|
||||
}
|
||||
106
module/finance/wallet/internal/server/new.go
Normal file
106
module/finance/wallet/internal/server/new.go
Normal file
@@ -0,0 +1,106 @@
|
||||
// Code generated by protoc-gen-slc. DO NOT EDIT.
|
||||
package server
|
||||
|
||||
import (
|
||||
"context"
|
||||
pb "bsm/full/module/finance/wallet/pb"
|
||||
"git.apinb.com/bsm-sdk/core/vars"
|
||||
gwRuntime "github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
"google.golang.org/grpc/reflection"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Server struct {
|
||||
Grpc *grpc.Server
|
||||
Ctx context.Context
|
||||
Mux *gwRuntime.ServeMux
|
||||
grpcConns map[string]*grpc.ClientConn // 连接池
|
||||
}
|
||||
|
||||
func New(addr string) *Server {
|
||||
srv := &Server{
|
||||
Ctx: context.Background(),
|
||||
Grpc: grpc.NewServer(),
|
||||
Mux: gwRuntime.NewServeMux(gwRuntime.WithForwardResponseRewriter(responseEnvelope)),
|
||||
grpcConns: make(map[string]*grpc.ClientConn),
|
||||
}
|
||||
|
||||
// register service to grpc.Server
|
||||
pb.RegisterAlipayServer(srv.Grpc, NewAlipayServer())
|
||||
pb.RegisterPaymentServer(srv.Grpc, NewPaymentServer())
|
||||
pb.RegisterBasicServer(srv.Grpc, NewBasicServer())
|
||||
pb.RegisterWechatServer(srv.Grpc, NewWechatServer())
|
||||
|
||||
reflection.Register(srv.Grpc)
|
||||
|
||||
// 连接池: 只创建一次连接并复用
|
||||
conn, ok := srv.grpcConns[addr]
|
||||
if !ok {
|
||||
var err error
|
||||
conn, err = grpc.NewClient(addr, grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||
if err != nil {
|
||||
panic("failed to dial grpc server: " + err.Error())
|
||||
}
|
||||
srv.grpcConns[addr] = conn
|
||||
}
|
||||
|
||||
// 将服务注册到Gateway
|
||||
|
||||
if err := pb.RegisterAlipayHandler(srv.Ctx, srv.Mux, conn); err != nil {
|
||||
panic("Failed to register Alipay handler: " + err.Error())
|
||||
}
|
||||
|
||||
if err := pb.RegisterPaymentHandler(srv.Ctx, srv.Mux, conn); err != nil {
|
||||
panic("Failed to register Payment handler: " + err.Error())
|
||||
}
|
||||
|
||||
if err := pb.RegisterBasicHandler(srv.Ctx, srv.Mux, conn); err != nil {
|
||||
panic("Failed to register Basic handler: " + err.Error())
|
||||
}
|
||||
|
||||
if err := pb.RegisterWechatHandler(srv.Ctx, srv.Mux, conn); err != nil {
|
||||
panic("Failed to register Wechat handler: " + err.Error())
|
||||
}
|
||||
|
||||
// Register services swagger
|
||||
srv.RegisterSwagger()
|
||||
|
||||
return srv
|
||||
}
|
||||
|
||||
// RegisterSwagger 注册swagger
|
||||
func (s *Server) RegisterSwagger() {
|
||||
srvKey := strings.ToLower(vars.ServiceKey)
|
||||
s.Mux.HandlePath("GET", "/"+srvKey+".swagger.json", func(w http.ResponseWriter, r *http.Request, pathParams map[string]string) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
bytes, err := os.ReadFile("./swagger/" + srvKey + ".swagger.json")
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
w.Write([]byte(err.Error()))
|
||||
return
|
||||
}
|
||||
w.Write(bytes)
|
||||
return
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
// response envelope
|
||||
func responseEnvelope(_ context.Context, response proto.Message) (interface{}, error) {
|
||||
name := string(response.ProtoReflect().Descriptor().Name())
|
||||
if name == "Status" || name == "Error" || name == "StatusReply" {
|
||||
return response, nil
|
||||
}
|
||||
return map[string]any{
|
||||
"code": 0,
|
||||
"message": vars.OK,
|
||||
"details": response,
|
||||
"timeseq": time.Now().Unix(),
|
||||
}, nil
|
||||
}
|
||||
45
module/finance/wallet/internal/server/payment_server.go
Normal file
45
module/finance/wallet/internal/server/payment_server.go
Normal file
@@ -0,0 +1,45 @@
|
||||
// Code generated by protoc-gen-slc. DO NOT EDIT.
|
||||
package server
|
||||
|
||||
import (
|
||||
"context"
|
||||
"bsm/full/module/finance/wallet/internal/logic/payment"
|
||||
pb "bsm/full/module/finance/wallet/pb"
|
||||
)
|
||||
|
||||
type PaymentServer struct {
|
||||
pb.UnimplementedPaymentServer
|
||||
}
|
||||
|
||||
func NewPaymentServer() *PaymentServer {
|
||||
return &PaymentServer{}
|
||||
}
|
||||
|
||||
func (s *PaymentServer) Hello(ctx context.Context, in *pb.Empty) (*pb.PaymentReply, error) {
|
||||
return payment.Hello(ctx, in)
|
||||
}
|
||||
|
||||
// 获取平台支持的支付网关
|
||||
func (s *PaymentServer) Way(ctx context.Context, in *pb.WayRequest) (*pb.WayReply, error) {
|
||||
return payment.Way(ctx, in)
|
||||
}
|
||||
|
||||
// 获取支付的详情
|
||||
func (s *PaymentServer) Get(ctx context.Context, in *pb.IdentRequest) (*pb.PaymentItem, error) {
|
||||
return payment.Get(ctx, in)
|
||||
}
|
||||
|
||||
// 支付-电商订单
|
||||
func (s *PaymentServer) ByOrder(ctx context.Context, in *pb.OrderRequest) (*pb.PaymentReply, error) {
|
||||
return payment.ByOrder(ctx, in)
|
||||
}
|
||||
|
||||
// 支付-充值
|
||||
func (s *PaymentServer) ByCharge(ctx context.Context, in *pb.ChargeRequest) (*pb.PaymentReply, error) {
|
||||
return payment.ByCharge(ctx, in)
|
||||
}
|
||||
|
||||
// 回调更新支付的结果和状态
|
||||
func (s *PaymentServer) Callback(ctx context.Context, in *pb.CallbackRequest) (*pb.StatusReply, error) {
|
||||
return payment.Callback(ctx, in)
|
||||
}
|
||||
41
module/finance/wallet/internal/server/wechat_server.go
Normal file
41
module/finance/wallet/internal/server/wechat_server.go
Normal file
@@ -0,0 +1,41 @@
|
||||
// Code generated by protoc-gen-slc. DO NOT EDIT.
|
||||
package server
|
||||
|
||||
import (
|
||||
"context"
|
||||
"bsm/full/module/finance/wallet/internal/logic/wechat"
|
||||
pb "bsm/full/module/finance/wallet/pb"
|
||||
)
|
||||
|
||||
type WechatServer struct {
|
||||
pb.UnimplementedWechatServer
|
||||
}
|
||||
|
||||
func NewWechatServer() *WechatServer {
|
||||
return &WechatServer{}
|
||||
}
|
||||
|
||||
// 微信JSAPI下单
|
||||
func (s *WechatServer) JsapiPreOrder(ctx context.Context, in *pb.WxpayJSAPIPreOrderRequest) (*pb.WxpayJSAPIPreOrderReply, error) {
|
||||
return wechat.JsapiPreOrder(ctx, in)
|
||||
}
|
||||
|
||||
// 微信APP支付下单
|
||||
func (s *WechatServer) AppPreOrder(ctx context.Context, in *pb.WxpayAppPreOrderRequest) (*pb.WxpayAppPreOrderReply, error) {
|
||||
return wechat.AppPreOrder(ctx, in)
|
||||
}
|
||||
|
||||
// 微信native二维码支付下单
|
||||
func (s *WechatServer) NativePreOrder(ctx context.Context, in *pb.WxpayNativePreOrderRequest) (*pb.WxpayNativePreOrderReply, error) {
|
||||
return wechat.NativePreOrder(ctx, in)
|
||||
}
|
||||
|
||||
// 微信转账到零钱
|
||||
func (s *WechatServer) Transfer(ctx context.Context, in *pb.WxpayTransferRequest) (*pb.WxpayTransferReply, error) {
|
||||
return wechat.Transfer(ctx, in)
|
||||
}
|
||||
|
||||
// 微信支付回调
|
||||
func (s *WechatServer) WxCallback(ctx context.Context, in *pb.WxCallBackRequest) (*pb.CallBackReply, error) {
|
||||
return wechat.WxCallback(ctx, in)
|
||||
}
|
||||
Reference in New Issue
Block a user