Files
soul-yongping/soul-api/internal/wechat/transfer.go

139 lines
4.0 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package wechat
import (
"context"
"fmt"
"time"
"soul-api/internal/config"
"github.com/ArtisanCloud/PowerLibs/v3/object"
"github.com/ArtisanCloud/PowerWeChat/v3/src/payment/transfer/request"
)
// TransferParams 转账参数
type TransferParams struct {
OutBatchNo string // 商家批次单号(唯一)
OutDetailNo string // 商家明细单号(唯一)
OpenID string // 收款用户 openid
Amount int // 转账金额(分)
UserName string // 收款用户姓名(可选,用于实名校验)
Remark string // 转账备注
BatchName string // 批次名称(如"提现"
BatchRemark string // 批次备注
}
// TransferResult 转账结果
type TransferResult struct {
BatchID string // 微信批次单号
OutBatchNo string // 商家批次单号
CreateTime time.Time // 批次创建时间
BatchStatus string // 批次状态ACCEPTED-已受理 等
}
// InitTransfer 保留兼容:转账已由 Init() 中 PowerWeChat Payment 统一初始化,调用无副作用
func InitTransfer(_ *config.Config) error {
return nil
}
// InitiateTransfer 发起商家转账到零钱PowerWeChat TransferBatch
func InitiateTransfer(params TransferParams) (*TransferResult, error) {
if paymentApp == nil {
return nil, fmt.Errorf("支付/转账未初始化,请先调用 wechat.Init")
}
detail := &request.TransferDetail{
OutDetailNO: params.OutDetailNo,
TransferAmount: params.Amount,
TransferRemark: params.Remark,
OpenID: params.OpenID,
}
if params.UserName != "" {
detail.UserName = object.NewNullString(params.UserName, true)
}
req := &request.RequestTransferBatch{
AppID: cfg.WechatAppID,
OutBatchNO: params.OutBatchNo,
BatchName: params.BatchName,
BatchRemark: params.BatchRemark,
TotalAmount: params.Amount,
TotalNum: 1,
TransferDetailList: []*request.TransferDetail{detail},
}
if cfg.WechatTransferURL != "" {
req.SetNotifyUrl(cfg.WechatTransferURL)
}
resp, err := paymentApp.TransferBatch.Batch(context.Background(), req)
if err != nil {
return nil, fmt.Errorf("发起转账失败: %w", err)
}
if resp == nil {
return nil, fmt.Errorf("转账返回为空")
}
result := &TransferResult{
OutBatchNo: resp.OutBatchNo,
BatchStatus: "ACCEPTED",
}
if resp.BatchId != "" {
result.BatchID = resp.BatchId
}
if !resp.CreateTime.IsZero() {
result.CreateTime = resp.CreateTime
}
return result, nil
}
// QueryTransfer 查询转账结果(可选,转账状态也可通过回调获取)
func QueryTransfer(outBatchNo, outDetailNo string) (map[string]interface{}, error) {
if paymentApp == nil {
return map[string]interface{}{
"out_batch_no": outBatchNo,
"out_detail_no": outDetailNo,
"status": "unknown",
"message": "转账未初始化",
}, nil
}
detail, err := paymentApp.TransferBatch.QueryOutBatchNoDetail(context.Background(), outBatchNo, outDetailNo)
if err != nil {
return map[string]interface{}{
"out_batch_no": outBatchNo,
"out_detail_no": outDetailNo,
"status": "processing",
"message": err.Error(),
}, nil
}
if detail == nil {
return map[string]interface{}{
"out_batch_no": outBatchNo,
"out_detail_no": outDetailNo,
"status": "processing",
"message": "转账处理中",
}, nil
}
return map[string]interface{}{
"out_batch_no": outBatchNo,
"out_detail_no": outDetailNo,
"detail_status": detail.DetailStatus,
"fail_reason": detail.FailReason,
"transfer_amount": detail.TransferAmount,
}, nil
}
// GenerateTransferBatchNo 生成转账批次单号
func GenerateTransferBatchNo() string {
now := time.Now()
timestamp := now.Format("20060102150405")
random := now.UnixNano() % 1000000
return fmt.Sprintf("WD%s%06d", timestamp, random)
}
// GenerateTransferDetailNo 生成转账明细单号
func GenerateTransferDetailNo() string {
now := time.Now()
timestamp := now.Format("20060102150405")
random := now.UnixNano() % 1000000
return fmt.Sprintf("WDD%s%06d", timestamp, random)
}