chore: 清理敏感与开发文档,仅同步代码

- 永久忽略并从仓库移除 开发文档/
- 移除并忽略 .env 与小程序私有配置
- 同步小程序/管理端/API与脚本改动

Made-with: Cursor
This commit is contained in:
卡若
2026-03-17 17:50:12 +08:00
parent 868b0a10d9
commit 76965adb23
443 changed files with 24175 additions and 64154 deletions

View 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
}

View File

@@ -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, "")
}