Files
soul-yongping/soul-api/internal/wechat/balance.go
卡若 76965adb23 chore: 清理敏感与开发文档,仅同步代码
- 永久忽略并从仓库移除 开发文档/
- 移除并忽略 .env 与小程序私有配置
- 同步小程序/管理端/API与脚本改动

Made-with: Cursor
2026-03-17 17:50:12 +08:00

57 lines
1.9 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 (
"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
}