查询钱包余额/授信
本文说明如何通过 MagikCloud Open API,查询租户当前钱包余额与授信额度。
前置条件
请先完成 接入流程 中的 AK/SK 获取;请求须按 构建请求 完成 AK/SK 签名。
查询钱包余额与授信
接口说明
| 项 | 值 |
|---|---|
| Base URL | https://openapi.magikcloud.cn |
| 路径 | /api/v1/wallets/balance |
| 方法 | GET |
查询参数
无。租户由 AK/SK 自动识别,无需传 tenant_id。
请求 URL 示例
响应示例
{
"code": 0,
"reason": "OK",
"message": "success",
"data": {
"tenantId": "tn-xxx",
"balance": "1200.00",
"giftBalance": "50.00",
"unpaidAmount": "0.00",
"creditLimit": "5000.00",
"usedCredit": "0.00",
"availableCredit": "5000.00",
"updatedAt": "2026-05-27T08:00:00Z"
}
}
响应字段说明
| 字段 | 类型 | 说明 |
|---|---|---|
tenantId |
string | 租户 ID |
balance |
string | 现金余额,已扣减预付在途消费 |
giftBalance |
string | 代金券余额:所有有效代金券剩余金额之和 |
unpaidAmount |
string | 账单欠费(后付),只有这部分消费占用授信 |
creditLimit |
string | 运营授予的授信额度,"0" 表示无授信(纯预付租户) |
usedCredit |
string | 已用授信,等于 unpaidAmount(仅账单欠费)。预付在途消费不计入授信,因其已从 balance 中扣减 |
availableCredit |
string | 可用授信,等于 creditLimit - usedCredit。超额时可能为负数,服务端不做截断处理 |
updatedAt |
string(时间) | 钱包更新时间,RFC 3339 |
金额字段均为字符串,与控制台余额页面一致。
数据时效性:balance 已扣减预付在途消费(分钟级更新),与实时消费存在至多几分钟的滞后;usedCredit 和 availableCredit 由账单欠费驱动,按出账节奏更新。请勿将这些数值当作秒级准确值使用。
Go 示例
package main
import (
"bytes"
"crypto/hmac"
"crypto/rand"
"crypto/sha256"
"encoding/base64"
"fmt"
"io"
"net/http"
"os"
"strings"
"time"
)
const (
baseURL = "https://openapi.magikcloud.cn"
path = "/api/v1/wallets/balance"
)
func main() {
accessKeyID := os.Getenv("ACCESS_KEY_ID")
secretKey := []byte(os.Getenv("SECRET_ACCESS_KEY"))
if accessKeyID == "" || len(secretKey) == 0 {
panic("请设置 ACCESS_KEY_ID 和 SECRET_ACCESS_KEY")
}
req, err := http.NewRequest(http.MethodGet, baseURL+path, nil)
if err != nil {
panic(err)
}
if err := signRequest(req, accessKeyID, secretKey); err != nil {
panic(err)
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(resp.Status)
fmt.Println(string(body))
}
func signRequest(req *http.Request, accessKeyID string, secretKey []byte) error {
if req.Body != nil {
bodyBytes, err := io.ReadAll(req.Body)
if err != nil {
return err
}
_ = req.Body.Close()
sum := sha256.Sum256(bodyBytes)
digest := base64.URLEncoding.EncodeToString(sum[:])
req.Header.Set("Content-Digest", "sha-256="+digest)
req.Body = io.NopCloser(bytes.NewReader(bodyBytes))
} else {
sum := sha256.Sum256(nil)
req.Header.Set("Content-Digest", "sha-256="+base64.URLEncoding.EncodeToString(sum[:]))
}
nonceBytes := make([]byte, 32)
if _, err := rand.Read(nonceBytes); err != nil {
return err
}
nonce := base64.RawURLEncoding.EncodeToString(nonceBytes)
created := time.Now().Unix()
query := "?"
if req.URL.RawQuery != "" {
query += req.URL.RawQuery
}
cd := req.Header.Get("Content-Digest")
reqPath := req.URL.Path
if reqPath == "" {
reqPath = "/"
}
escape := func(s string) string {
s = strings.ReplaceAll(s, `\`, `\\`)
s = strings.ReplaceAll(s, `"`, `\"`)
return s
}
sigParams := `("@method" "@query" "@path" "content-digest")` + ";" + strings.Join([]string{
fmt.Sprintf("created=%d", created),
fmt.Sprintf(`nonce="%s"`, escape(nonce)),
fmt.Sprintf(`keyid="%s"`, escape(accessKeyID)),
`alg="hmac-sha256"`,
}, ";")
signatureBase := strings.Join([]string{
fmt.Sprintf(`"@method": %s`, req.Method),
fmt.Sprintf(`"@query": %s`, query),
fmt.Sprintf(`"@path": %s`, reqPath),
fmt.Sprintf(`"content-digest": %s`, cd),
fmt.Sprintf(`"@signature-params": %s`, sigParams),
}, "\n")
mac := hmac.New(sha256.New, secretKey)
mac.Write([]byte(signatureBase))
sig := base64.RawURLEncoding.EncodeToString(mac.Sum(nil))
req.Header.Set("Signature-Input", "magik="+sigParams)
req.Header.Set("Signature", "magik=:"+sig+":")
return nil
}
Postman 调试
使用与 日账单/用量查询 相同的 postman_pre_request_script.js 脚本,在每次发送前自动计算 Content-Digest、Signature-Input、Signature。
1. 环境变量(Environment)
在 Postman 里新建 Environment,配置:
| 变量 | 示例 | 说明 |
|---|---|---|
access_key_id |
AK... |
控制台 Access Key ID |
secret_access_key |
SK... |
Secret(勿提交到 Git) |
2. 配置请求
- Method:
GET - URL:
- Body:无(GET)
- 右上角选中上一步创建的 Environment