chore: 清理敏感与开发文档,仅同步代码
- 永久忽略并从仓库移除 开发文档/ - 移除并忽略 .env 与小程序私有配置 - 同步小程序/管理端/API与脚本改动 Made-with: Cursor
This commit is contained in:
56
soul-api/internal/wechat/balance.go
Normal file
56
soul-api/internal/wechat/balance.go
Normal file
@@ -0,0 +1,56 @@
|
||||
package wechat
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"soul-api/internal/config"
|
||||
"soul-api/internal/wechat/transferv3"
|
||||
)
|
||||
|
||||
// MerchantBalance 商户余额(微信返回,单位:分)
|
||||
type MerchantBalance struct {
|
||||
AvailableAmount int64 `json:"available_amount"` // 可用余额(分)
|
||||
PendingAmount int64 `json:"pending_amount"` // 不可用/待结算余额(分)
|
||||
}
|
||||
|
||||
// QueryMerchantBalance 查询商户平台账户实时余额(API: GET /v3/merchant/fund/balance/{account_type})
|
||||
// accountType: BASIC(基本户) | OPERATION(运营账户) | FEES(手续费账户),默认 BASIC
|
||||
// 注意:普通商户可能需向微信申请开通权限,403 NO_AUTH 时表示未开通
|
||||
func QueryMerchantBalance(accountType string) (*MerchantBalance, error) {
|
||||
if accountType == "" {
|
||||
accountType = "BASIC"
|
||||
}
|
||||
cfg := config.Get()
|
||||
if cfg == nil {
|
||||
return nil, fmt.Errorf("配置未加载")
|
||||
}
|
||||
key, err := transferv3.LoadPrivateKeyFromPath(cfg.WechatKeyPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("加载商户私钥失败: %w", err)
|
||||
}
|
||||
client := transferv3.NewClient(cfg.WechatMchID, cfg.WechatAppID, cfg.WechatSerialNo, key)
|
||||
data, status, err := client.GetMerchantBalance(accountType)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("请求微信接口失败: %w", err)
|
||||
}
|
||||
if status != 200 {
|
||||
// 403 NO_AUTH 时返回友好提示,便于管理端展示
|
||||
if status == 403 {
|
||||
var errResp struct {
|
||||
Code string `json:"code"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
_ = json.Unmarshal(data, &errResp)
|
||||
if errResp.Code == "NO_AUTH" {
|
||||
return nil, fmt.Errorf("NO_AUTH: 当前商户号未开通余额查询权限,请登录微信商户平台联系客服申请")
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("微信返回 %d: %s", status, string(data))
|
||||
}
|
||||
var bal MerchantBalance
|
||||
if err := json.Unmarshal(data, &bal); err != nil {
|
||||
return nil, fmt.Errorf("解析余额响应失败: %w", err)
|
||||
}
|
||||
return &bal, nil
|
||||
}
|
||||
@@ -118,3 +118,11 @@ func (c *Client) GetTransferDetail(outBatchNo, outDetailNo string) ([]byte, int,
|
||||
"/details/detail-id/" + url.PathEscape(outDetailNo)
|
||||
return c.do("GET", path, "")
|
||||
}
|
||||
|
||||
// GetMerchantBalance 查询商户平台账户实时余额(文档:GET /v3/merchant/fund/balance/{account_type})
|
||||
// accountType: BASIC(基本户) | OPERATION(运营账户) | FEES(手续费账户)
|
||||
// 注意:普通商户可能需向微信申请开通权限,403 NO_AUTH 表示未开通
|
||||
func (c *Client) GetMerchantBalance(accountType string) ([]byte, int, error) {
|
||||
path := "/v3/merchant/fund/balance/" + url.PathEscape(accountType)
|
||||
return c.do("GET", path, "")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user