nexcore

package module
v0.0.0-...-6958252 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 14, 2026 License: MIT Imports: 21 Imported by: 0

README

Tovanix Go SDK

Tovanix(原 NexCore)平台全能 Go 客户端,覆盖 Payment / Exchange / Energy / SMTP / Withdraw / Account / VCard 7 大命名空间全部 44 个 v1 公开 endpoint.

零依赖(仅标准库 net/http / crypto/hmac / encoding/json).

环境

  • Go 1.21+

安装

go get github.com/DoBestone/nexcore-sdk/go

文件结构

go.mod                 (module: github.com/DoBestone/nexcore-sdk/go)
doc.go                 package 文档
client.go              主客户端 Client + Config + NewClient()
http.go                底层 HTTP 传输
errors.go              统一异常 Error + AsError()
payment.go             多链收款(7 endpoints)
payment_test.go        签名语义测试(amount 归一 / timeout 恒入签 / get-address 签名串)
exchange.go            汇率(5 endpoints)
energy.go              TRON 能量租赁(8 endpoints)
smtp.go                SMTP 聚合 API(6 endpoints)
withdraw.go            提币(4 endpoints,RSA 签名)
account.go             账户(2 endpoints)
vcard.go               虚拟信用卡(12 endpoints)
examples/
├── create_order/main.go
└── webhook/main.go

用法

package main

import (
    "encoding/json"
    "fmt"
    "log"
    "time"

    nexcore "github.com/DoBestone/nexcore-sdk/go"
)

func main() {
    c := nexcore.NewClient(nexcore.Config{
        BaseURL:         "https://your-domain.com",
        PaymentAppID:    "APP20260412XXXX",
        PaymentAppKey:   "your_app_key_here",
        EnergyAPIKey:    "energy_api_key_here",
        EnergySecretKey: "energy_secret_key_here",
        SMTPAPIKey:      "smk_xxx",
    })

    // 创建支付订单
    raw, err := c.Payment.CreateOrder(map[string]any{
        "out_order_id": fmt.Sprintf("ORDER_%d", time.Now().Unix()),
        "amount":       "100.00",
        "currency":     "CNY",
        "trade_type":   "usdt.trc20",
        "call_type":    "rotation",
        "timeout":      1800,
    })
    if err != nil {
        if ne := nexcore.AsError(err); ne != nil {
            log.Fatalf("Error #%d: %s (trace=%s)", ne.Code, ne.Message, ne.RequestID)
        }
        log.Fatal(err)
    }
    var order struct {
        PayAddress string `json:"pay_address"`
    }
    _ = json.Unmarshal(raw, &order)
    fmt.Println("支付地址:", order.PayAddress)

    // 查询汇率
    raw, _ = c.Exchange.GetRate("USDT", "CNY")
    var rate struct { Rate float64 `json:"rate"` }
    _ = json.Unmarshal(raw, &rate)
    fmt.Printf("USDT/CNY: %.4f\n", rate.Rate)

    // 估算能量
    raw, _ = c.Energy.EstimateEnergy("TXxxxxxxxxxxxxxxxxxxxxx")
    var est struct { SuggestedEnergy int `json:"suggested_energy"` }
    _ = json.Unmarshal(raw, &est)
    fmt.Println("建议能量:", est.SuggestedEnergy)

    // 发送邮件
    raw, _ = c.SMTP.Send(map[string]any{
        "to":      "user@example.com",
        "subject": "验证码",
        "body":    "<h1>123456</h1>",
        "is_html": true,
    })
    var mail struct { MessageID string `json:"message_id"` }
    _ = json.Unmarshal(raw, &mail)
    fmt.Println("消息 ID:", mail.MessageID)
}

API 列表

client.Payment — 多链收款(7 endpoint)
方法 HTTP endpoint
CreateOrder(params) POST /api/v1/pay/create
QueryOrder(outOrderID) GET /api/v1/pay/query
CloseOrder(outOrderID) POST /api/v1/pay/close
GetAppConfig() GET /api/v1/pay/app-config
BindAddress(userID, tradeType) POST /api/v1/pay/bind-address
GetUserAddress(userID) POST /api/v1/pay/get-address
UnbindAddress(userID) POST /api/v1/pay/unbind-address
Sign(params) (工具) HMAC-SHA256 签名
VerifyNotifySign(payload) (工具) webhook 校验(常量时间)
client.Exchange — 汇率(5 endpoint)
方法 HTTP endpoint
GetRate(from, to) GET /api/v1/rate
Convert(from, to, amount) POST /api/v1/convert
GetRates(symbols, base) GET /api/v1/rates
GetFiatRates(base) GET /api/v1/rates/fiat
GetAllRates(base) GET /api/v1/rates/all

注:GetRatesbase 传空字符串时由后端取默认(USDT).

client.Energy — TRON 能量租赁(8 endpoint)
方法 HTTP endpoint
GetInfo() GET /api/v1/energy/info
GetPrice(energyAmount, period) GET /api/v1/energy/price?energy_amount=&period=
EstimateEnergy(toAddress) GET /api/v1/energy/estimate-energy?to_address=
CreateOrder(params) POST /api/v1/energy/order
CreateOnetimeOrder(params) POST /api/v1/energy/order/onetime
QueryOrder(serial) GET /api/v1/energy/order/:serial
ListOrders(filter) GET /api/v1/energy/orders
ReclaimOrder(serial) POST /api/v1/energy/order/reclaim

注:租期 period 枚举 1H / 1D / 3D / 7D / 30D;CreateOrder 必填 receive_address / energy_amount / period,可选 out_trade_no / remark.

client.SMTP — SMTP 聚合(6 endpoint)
方法 HTTP endpoint
Send(params, opts...) POST /api/v1/smtp/send
SendBatch(params, opts...) POST /api/v1/smtp/send/batch
SendTemplate(params) POST /api/v1/smtp/send/template
GetQuota() GET /api/v1/smtp/quota
GetStatus(messageID) GET /api/v1/smtp/status/:message_id
ReportInbound(params) POST /api/v1/smtp/inbound
  • Send 可选字段:from_name / reply_to / text_body / headers / cc / bcc / attachments / account_id / send_at(定时,RFC3339);opts(SMTPSendOptions)可带 IdempotencyKey 写入 Idempotency-Key 幂等头
  • SendBatch 必填 recipients 数组(元素 {to, variables?, from_name?}),静态 subject+bodytemplate_code 二选一;同样支持幂等 opts
  • SendTemplate 必填 to + template_code,可选 variables / from_name
  • GetQuota 返回 daily_limit/daily_used/daily_remaining / monthly_* / expire_at
  • ReportInbound 上报退信/投诉(emailmessage_id 至少其一,type = bounce | complaint)
client.Withdraw — 提币(4 endpoint,RSA-PKCS1v15-SHA256 签名)
方法 HTTP endpoint
CreateWithdraw(params) POST /api/v1/withdraw
GetWithdraw(id) GET /api/v1/withdraw/:id
GetWithdrawableBalance() GET /api/v1/balance/withdrawable
QuoteFee(chain, symbol, amount) GET /api/v1/fee/quote(amount 必填)
Sign(...) / VerifyCallback(...) (工具) RSA 签名 / 平台回调验签
client.Account — 账户(2 endpoint)
方法 HTTP endpoint
GetBalance() GET /api/v1/account/balance
GetDepositAddress() GET /api/v1/account/deposit-address
client.VCard — 虚拟信用卡(12 endpoint)
方法 HTTP endpoint
GetInfo() / ListBins() / ListCards() GET /api/v1/vcard/*(读,X-API-Key)
GetCardTransactions(cardID) / ListOrders(query) / GetOrder(orderID) GET 同上
UpdateCardRemark(cardID, remark) POST 同上
GetCardDetails(cardID) / GetCardCode(cardID) GET 敏感读(HMAC 头签名)
OpenCard(params) / RechargeCard(cardID, params) / CancelCard(cardID) POST 资金操作(HMAC 头签名)

Webhook 签名校验

http.HandleFunc("/payment/notify", func(w http.ResponseWriter, r *http.Request) {
    var payload map[string]any
    if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
        http.Error(w, "bad request", 400)
        return
    }
    if !c.Payment.VerifyNotifySign(payload) {
        http.Error(w, "invalid sign", 400)
        return
    }
    // 处理回调... 务必幂等
    w.Write([]byte("OK"))
})

VerifyNotifySign 内部用 hmac.Equal,常量时间比较防时序攻击.

异常

所有方法返回错误用 *nexcore.Error,字段:

  • Code — 平台错误码(0=成功)
  • Message — 错误描述
  • RequestID — 服务端追踪 ID(响应头 X-Trace-Id)
  • HTTPStatus — HTTP 状态码

nexcore.AsError(err) 把通用 error 转成 *nexcore.Error.

返回值约定

所有方法返回 json.RawMessage — 业务方自行 json.Unmarshal 到具体 struct.

这样设计的好处:后端 API 加字段不需要升级 SDK,业务方按需取字段即可.

示例

examples/:

  • create_order/main.go — 完整下单(go run ./examples/create_order)
  • webhook/main.go — HTTP webhook 接收(go run ./examples/webhook)

Documentation

Overview

Package nexcore is the official Go SDK for the Tovanix platform (formerly NexCore).

一次配置覆盖 Tovanix 平台全部 v1 公开接口,业务按 namespace 划分:

  • client.Payment — 多链收款(HMAC-SHA256 签名)
  • client.Withdraw — 多链收款 · 提币(RSA-2048 签名)
  • client.Exchange — 汇率(X-App-Key + X-App-Secret header)
  • client.Energy — TRON 能量租赁(X-API-Key + X-Secret-Key)
  • client.SMTP — SMTP 聚合(Bearer Token)
  • client.Account — 账户余额 / 充值地址(X-API-Key + X-Secret-Key)
  • client.VCard — 虚拟信用卡(读用双密钥;开卡/充值/注销/敏感信息用 HMAC 签名)

使用:

import nexcore "github.com/DoBestone/nexcore-sdk/go"

c := nexcore.NewClient(nexcore.Config{
    BaseURL:               "https://your-domain.com",
    PaymentAppID:          "APP20260412XXXX",
    PaymentAppKey:         "your_app_key_here",
    EnergyAPIKey:          "energy_key",
    EnergySecretKey:       "energy_secret",
    SMTPAPIKey:            "smk_xxx",
    WithdrawAPIKey:        "MPK_xxx",
    WithdrawPrivateKeyPEM: os.Getenv("WITHDRAW_RSA_PRIV"),
})

raw, err := c.Payment.CreateOrder(map[string]any{
    "out_order_id": fmt.Sprintf("ORDER_%d", time.Now().Unix()),
    "amount":       "100.00",
    "currency":     "CNY",
    "trade_type":   "usdt.trc20",
    "call_type":    "rotation",
})

所有方法返回 json.RawMessage,业务方自行 json.Unmarshal 到具体 struct, 这样后端 API 加字段不需要升级 SDK.

所有错误统一返回 *nexcore.Error(含 Code / Message / RequestID / HTTPStatus). 使用 nexcore.AsError(err) 把通用 error 转换成 *Error.

Index

Constants

View Source
const Version = "3.3.0"

Version is the SDK version, kept in sync with the public repository tags.

Variables

This section is empty.

Functions

func VerifyWebhook

func VerifyWebhook(params map[string]string, secret string) bool

VerifyWebhook 校验平台推送的 webhook 签名(给对接方验证平台主动推送的真实性).

复刻后端 pkg.GenerateSign 的算法:

  • 取 params 中所有「非空、且 key != "sign"」的字段
  • 按 key 升序拼成 "k1=v1&k2=v2&..."
  • sign = hex_lower( HMAC_SHA256(secret, 拼接串) )
  • 与 params["sign"] 用 hmac.Equal 做常量时间比较

防重放:平台推送一般同时带 sign_ts(签名时刻,unix 秒,±300s 窗口)与 nonce(随机串). 本函数只校验签名;时间窗(now-sign_ts 在 ±300s 内)与 nonce 去重需由调用方自行实现, 二者配合才能完整防重放.

用法:

params := map[string]string{
    "event":   "card.transaction",
    "card_id": "123",
    "sign_ts": "1718000000",
    "nonce":   "abc123...",
    "sign":    req.Header...或 body 里的 sign 字段,
}
if !nexcore.VerifyWebhook(params, webhookSecret) {
    // 验签失败,拒绝处理
}

Types

type AccountNamespace

type AccountNamespace struct {
	// contains filtered or unexported fields
}

AccountNamespace implements the v1 账户 read endpoints.

对应 NexCore 账户模块的公开只读接口:

GET /api/v1/account/balance          GetBalance        查询账户余额
GET /api/v1/account/deposit-address  GetDepositAddress 查询/获取充值地址

鉴权:X-API-Key + X-Secret-Key 双 header(用 cfg.APIKey / cfg.APISecret). account 与 vcard 命名空间共用同一对 MPK 商户密钥.

func (*AccountNamespace) GetBalance

func (n *AccountNamespace) GetBalance() (json.RawMessage, error)

GetBalance returns the account balance.

GET /api/v1/account/balance

func (*AccountNamespace) GetDepositAddress

func (n *AccountNamespace) GetDepositAddress() (json.RawMessage, error)

GetDepositAddress returns the account deposit address(es).

GET /api/v1/account/deposit-address

type Client

type Client struct {

	// Payment 多链收款命名空间
	Payment *PaymentNamespace
	// Exchange 汇率命名空间
	Exchange *ExchangeNamespace
	// Energy TRON 能量租赁命名空间
	Energy *EnergyNamespace
	// SMTP SMTP 聚合命名空间
	SMTP *SMTPNamespace
	// Withdraw 提币命名空间(多链收款业务的资金出库端,RSA-2048 签名)
	Withdraw *WithdrawNamespace
	// Account 账户命名空间(余额 / 充值地址,双密钥读)
	Account *AccountNamespace
	// VCard 虚拟信用卡命名空间(读用双密钥,开卡/充值/注销/敏感信息用 HMAC 签名)
	VCard *VCardNamespace
	// contains filtered or unexported fields
}

Client NexCore 全能客户端.

业务 namespace 通过字段访问:

c.Payment   - 多链收款
c.Exchange  - 汇率
c.Energy    - TRON 能量租赁
c.SMTP      - SMTP 聚合
c.Account   - 账户(余额 / 充值地址)
c.VCard     - 虚拟信用卡

所有方法返回 json.RawMessage,业务方自行 json.Unmarshal 到具体 struct.

func NewClient

func NewClient(cfg Config) *Client

NewClient creates a new NexCore client.

c := nexcore.NewClient(nexcore.Config{
    BaseURL: "https://your-domain.com",
    PaymentAppID: "APP20260412XXXX",
    PaymentAppKey: "your_app_key_here",
})

type Config

type Config struct {
	// BaseURL NexCore 平台基础 URL,例如 "https://your-domain.com"(必填).
	BaseURL string

	// PaymentAppID 多链收款 / 汇率 应用 ID.
	PaymentAppID string
	// PaymentAppKey 多链收款 / 汇率 应用密钥(HMAC 签名 + X-App-Secret 同用).
	PaymentAppKey string

	// EnergyAPIKey TRON 能量租赁 X-API-Key.
	EnergyAPIKey string
	// EnergySecretKey TRON 能量租赁 X-Secret-Key.
	EnergySecretKey string

	// SMTPAPIKey SMTP 聚合 API 的 smk_ 前缀 Token.
	SMTPAPIKey string

	// WithdrawAPIKey 提币 API 的 X-API-Key(账户级 API Key).
	WithdrawAPIKey string
	// WithdrawPrivateKeyPEM 对接方 RSA 私钥 PEM 字符串(用于请求签名).
	// 推荐运行时从环境变量或密钥管理服务读出,不要硬编码.
	WithdrawPrivateKeyPEM string
	// WithdrawPlatformPublicKeyPEM 平台 RSA 公钥 PEM(用于回调验签,可选).
	WithdrawPlatformPublicKeyPEM string

	// APIKey 商户 API Key(MPK 商户密钥的 key 部分);account 与 vcard 命名空间共用.
	// 双密钥读场景作为 X-API-Key,HMAC 签名写场景作为 X-Key-ID.
	APIKey string
	// APISecret 商户 API Secret(MPK 商户密钥的 secret 部分);account 与 vcard 命名空间共用.
	// 双密钥读场景作为 X-Secret-Key,HMAC 签名写场景作为 HMAC-SHA256 的密钥.
	APISecret string

	// Timeout HTTP 超时,默认 30s.
	Timeout time.Duration

	// UserAgent 自定义 User-Agent(可选).
	UserAgent string
}

Config 客户端配置.

type EnergyNamespace

type EnergyNamespace struct {
	// contains filtered or unexported fields
}

EnergyNamespace implements all 8 TRON energy lease v1 endpoints.

对应 /docs 文档 "能量租赁" 模块的全部 v1 公开接口 (对照 internal/handler/trxx_api.go):

GET  /api/v1/energy/info             GetInfo             平台公开信息
GET  /api/v1/energy/price            GetPrice            指定能量+周期的报价
GET  /api/v1/energy/estimate-energy  EstimateEnergy      根据地址估算 TRC20 转账所需能量
POST /api/v1/energy/order            CreateOrder         创建常规租赁订单
POST /api/v1/energy/order/onetime    CreateOnetimeOrder  创建一次性订单
GET  /api/v1/energy/order/:serial    QueryOrder          查询订单(serial 字符串)
GET  /api/v1/energy/orders           ListOrders          列出所有订单
POST /api/v1/energy/order/reclaim    ReclaimOrder        主动回收订单

鉴权:X-API-Key + X-Secret-Key 双 header.

func (*EnergyNamespace) CreateOnetimeOrder

func (n *EnergyNamespace) CreateOnetimeOrder(params map[string]any) (json.RawMessage, error)

CreateOnetimeOrder creates a one-time order (energy is reclaimed after one use).

POST /api/v1/energy/order/onetime

适用场景:用户只做一笔 TRC20 转账,转完即丢能量.

必填:

receive_address (string) — 收能量的目标 TRON 地址
period          (string) — 1H / 1D / 3D / 7D / 30D

可选:

out_trade_no    (string) — 商户侧订单号(幂等/对账用)
remark          (string) — 备注

注意:本接口没有 energy_amount 参数,能量数由平台按目标地址估算.

返回 {serial, price_trx, deducted_usd}. 计费按预估上界先扣款,再按上游实际金额结算 —— 多退少不补.

func (*EnergyNamespace) CreateOrder

func (n *EnergyNamespace) CreateOrder(params map[string]any) (json.RawMessage, error)

CreateOrder creates a regular lease order.

POST /api/v1/energy/order

必填:

receive_address (string) — 收能量的目标 TRON 地址
energy_amount   (int)    — 能量数(>= minimum_order_energy)
period          (string) — 1H / 1D / 3D / 7D / 30D

可选:

out_trade_no    (string) — 商户侧订单号(幂等/对账用)
remark          (string) — 备注

返回 {serial, price_trx, deducted_usd}.

func (*EnergyNamespace) EstimateEnergy

func (n *EnergyNamespace) EstimateEnergy(toAddress string) (json.RawMessage, error)

EstimateEnergy estimates the energy needed for a TRC20 transfer to the given address.

GET /api/v1/energy/estimate-energy?to_address=TXxxxxxxxx

to_address 必须是合法 TRON 主网地址(T 开头 34 字符).

返回 {to_address, initialized, suggested_energy}. initialized=false 表示目标地址无 USDT 余额(首笔转账需更多能量).

func (*EnergyNamespace) GetInfo

func (n *EnergyNamespace) GetInfo() (json.RawMessage, error)

GetInfo returns platform public info (available energy, pricing tiers, etc).

GET /api/v1/energy/info

返回 {platform_avail_energy, minimum_order_energy, maximum_order_energy, tiered_pricing, ...}.

func (*EnergyNamespace) GetPrice

func (n *EnergyNamespace) GetPrice(energy int, period string) (json.RawMessage, error)

GetPrice quotes the price for a given energy amount and period.

GET /api/v1/energy/price?energy_amount=65000&period=1D

period: "1H" / "1D" / "3D" / "7D" / "30D",空字符串视为 "1D".

返回 {period, energy_amount, price_trx}.

func (*EnergyNamespace) ListOrders

func (n *EnergyNamespace) ListOrders(filter map[string]any) (json.RawMessage, error)

ListOrders lists all orders, optionally filtered.

GET /api/v1/energy/orders

filter 可包含:

status    (int) — -1 全部(默认) / 0 待处理 / 40 成功 / 41 失败
page      (int) — 页码,默认 1
page_size (int) — 每页条数,默认 20,最大 100

返回 {list, total, page, page_size},list 元素字段同 QueryOrder.

func (*EnergyNamespace) QueryOrder

func (n *EnergyNamespace) QueryOrder(serial string) (json.RawMessage, error)

QueryOrder queries an order by serial string.

GET /api/v1/energy/order/:serial

注意:serial 是字符串序列号,**不是**数字 id.

返回订单视图 {serial, receive_address, energy_amount, period, price_trx, status, status_msg, out_trade_no, order_type, created_at}.

func (*EnergyNamespace) ReclaimOrder

func (n *EnergyNamespace) ReclaimOrder(serial string) (json.RawMessage, error)

ReclaimOrder actively reclaims an order (returns energy to the platform).

POST /api/v1/energy/order/reclaim

返回 {errno, message},errno=0 表示回收成功.

type Error

type Error struct {
	// Message 人类可读错误描述
	Message string
	// Code 平台错误码(0=成功;-1=客户端层错误;其他参见错误码表)
	Code int
	// RequestID 服务端日志追踪 ID,通过响应头 X-Trace-Id 透传.排查问题时给后端工单提供本值.
	RequestID string
	// HTTPStatus 实际 HTTP 状态码;客户端层错误时为 0.
	HTTPStatus int
}

Error is the unified SDK error type.

所有 SDK 调用失败(网络错误 / HTTP 4xx-5xx / 业务 code != 0)统一返回 *Error. 业务方用 errors.As 或 nexcore.AsError 提取详细字段.

func AsError

func AsError(err error) *Error

AsError 把通用 error 转成 *Error,方便业务层拿 Code / RequestID 等字段. 不是 SDK 抛出的错误返回 nil.

if err := client.Payment.CreateOrder(...); err != nil {
    if ne := nexcore.AsError(err); ne != nil {
        log.Printf("Code=%d, Trace=%s", ne.Code, ne.RequestID)
    }
}

func (*Error) Error

func (e *Error) Error() string

Error implements the error interface.

type ExchangeNamespace

type ExchangeNamespace struct {
	// contains filtered or unexported fields
}

ExchangeNamespace implements all 5 exchange-related v1 endpoints.

对应 /docs 文档 "多链收款 → 汇率服务" 5 个 endpoint (对照 internal/handler/exchange_api.go):

GET  /api/v1/rate          GetRate         单对币种汇率
POST /api/v1/convert       Convert         金额换算
GET  /api/v1/rates         GetRates        批量获取多币种汇率
GET  /api/v1/rates/fiat    GetFiatRates    主流法币汇率
GET  /api/v1/rates/all     GetAllRates     所有支持币种快照

鉴权:走 APIAuth 中间件,用 X-App-Key + X-App-Secret(应用密钥)header.

func (*ExchangeNamespace) Convert

func (n *ExchangeNamespace) Convert(from, to string, amount any) (json.RawMessage, error)

Convert performs an amount conversion between two currencies.

POST /api/v1/convert

参数 amount 可以是 string 或 number,推荐 string 避免浮点误差. 返回 {from, to, amount, result, rate, updated_at}.

func (*ExchangeNamespace) GetAllRates

func (n *ExchangeNamespace) GetAllRates(base string) (json.RawMessage, error)

GetAllRates returns a snapshot of all supported currencies (crypto + fiat).

GET /api/v1/rates/all?base=USDT

func (*ExchangeNamespace) GetFiatRates

func (n *ExchangeNamespace) GetFiatRates(base string) (json.RawMessage, error)

GetFiatRates returns rates of major fiat currencies against a base fiat.

GET /api/v1/rates/fiat?base=USD

func (*ExchangeNamespace) GetRate

func (n *ExchangeNamespace) GetRate(from, to string) (json.RawMessage, error)

GetRate queries a single rate pair.

GET /api/v1/rate?from=USDT&to=CNY

返回 {from, to, rate, inverse, updated_at},inverse = 1/rate.

func (*ExchangeNamespace) GetRates

func (n *ExchangeNamespace) GetRates(symbols []string, base string) (json.RawMessage, error)

GetRates batch-queries multiple symbols against a base currency.

GET /api/v1/rates?symbols=USDT,TRX,ETH&base=CNY

base 传空字符串时不携带该参数,由后端取默认值 USDT.

返回 {base, rates: {USDT: 7.23, TRX: 0.85, ...}, updated_at}.

type PaymentNamespace

type PaymentNamespace struct {
	// contains filtered or unexported fields
}

PaymentNamespace implements all v1 endpoints under "/api/v1/pay/".

对应 /docs 文档 "多链收款" 模块的全部 7 个 v1 公开接口 (对照 internal/handler/order.go + one_to_one.go):

POST /api/v1/pay/create          CreateOrder       创建收款订单
GET  /api/v1/pay/query           QueryOrder        查询订单状态
POST /api/v1/pay/close           CloseOrder        关闭订单
GET  /api/v1/pay/app-config      GetAppConfig      查询应用配置
POST /api/v1/pay/bind-address    BindAddress       一对一 — 绑定地址
POST /api/v1/pay/get-address     GetUserAddress    一对一 — 查询用户已绑地址
POST /api/v1/pay/unbind-address  UnbindAddress     一对一 — 解绑

另提供 VerifyNotifySign() 校验 webhook 回调签名(常量时间比较).

鉴权:HMAC-SHA256 签名 — 所有请求自动追加 app_id + sign 字段.

func (*PaymentNamespace) BindAddress

func (n *PaymentNamespace) BindAddress(userID, tradeType string) (json.RawMessage, error)

BindAddress binds a user to a fixed receiving address (one-to-one mode).

POST /api/v1/pay/bind-address

func (*PaymentNamespace) CloseOrder

func (n *PaymentNamespace) CloseOrder(outOrderID string) (json.RawMessage, error)

CloseOrder closes an open order.

POST /api/v1/pay/close

func (*PaymentNamespace) CreateOrder

func (n *PaymentNamespace) CreateOrder(params map[string]any) (json.RawMessage, error)

CreateOrder creates a payment order.

POST /api/v1/pay/create

必填字段:

out_order_id (string) — 商户侧订单号,必须唯一
amount       (string) — 法币金额,推荐两位小数 string 避免浮点误差
currency     (string) — 法币代码 CNY/USD/EUR/JPY/KRW/HKD
trade_type   (string) — 加密币种.链,如 "usdt.trc20"
call_type    (string) — 必填;本接口只支持 "rotation"(轮播),
                        一对一模式请改用 BindAddress 绑定地址接口

可选字段:

out_user_id  (string) — 商户侧用户标识
timeout      (int)    — 订单过期秒数,默认 1800
subject      (string) — 订单描述
notify_url   (string) — webhook 回调 URL
return_url   (string) — 支付成功跳转 URL

签名口径(与后端一致,SDK 自动处理,body 保持原值):

  • amount 归一为两位小数字符串参与签名(后端按 decimal StringFixed(2) 校验)
  • timeout 恒参与签名,未传按 "0"

返回 {order_id, out_order_id, amount, currency, crypto_amount, crypto_currency, crypto_symbol, pay_address, pay_url, qrcode_url, payment_page_url, status, created_at, expired_at}.

func (*PaymentNamespace) GetAppConfig

func (n *PaymentNamespace) GetAppConfig() (json.RawMessage, error)

GetAppConfig returns current application configuration.

GET /api/v1/pay/app-config

func (*PaymentNamespace) GetUserAddress

func (n *PaymentNamespace) GetUserAddress(userID string) (json.RawMessage, error)

GetUserAddress queries the address bound to a user (one-to-one mode).

POST /api/v1/pay/get-address (注意:后端是 POST,不是 GET)

与 BindAddress 的差异:绑定需要 trade_type 指定币种/链, 查询只需要 user_id —— 后端只校验 {app_id, user_id} 两个字段的签名, 不接收 trade_type.

func (*PaymentNamespace) QueryOrder

func (n *PaymentNamespace) QueryOrder(outOrderID string) (json.RawMessage, error)

QueryOrder queries an order by merchant out_order_id.

GET /api/v1/pay/query

func (*PaymentNamespace) Sign

func (n *PaymentNamespace) Sign(params map[string]any) (string, error)

Sign computes HMAC-SHA256 signature for the given params.

业务方一般不需要直接调,SDK 内部自动调用.公开出来便于:

  • 自行测试签名是否正确(对照 /docs 文档输出)
  • 校验回调签名(VerifyNotifySign 内部也用)

签名算法:把所有非空、非 sign 的参数按 key 升序拼接成 k1=v1&k2=v2, 然后用 PaymentAppKey 做 HMAC-SHA256,返回 64 字符小写 hex.

func (*PaymentNamespace) UnbindAddress

func (n *PaymentNamespace) UnbindAddress(userID string) (json.RawMessage, error)

UnbindAddress unbinds a user's address (one-to-one mode).

POST /api/v1/pay/unbind-address

func (*PaymentNamespace) VerifyNotifySign

func (n *PaymentNamespace) VerifyNotifySign(payload map[string]any) bool

VerifyNotifySign verifies a webhook notification signature with constant-time comparison.

NexCore 平台通过 notify_url 推送 JSON 通知时会带 sign 字段. 本方法用 hmac.Equal 常量时间比较防止时序攻击.

返回 true=签名正确,可信
    false=签名错误/缺失,应拒绝该回调

type SMTPNamespace

type SMTPNamespace struct {
	// contains filtered or unexported fields
}

SMTPNamespace implements all 6 SMTP aggregation v1 endpoints.

对应 /docs 文档 "SMTP API" 模块的全部 v1 公开接口 (对照 internal/handler/smtp_api.go + smtp_api_ext.go):

POST /api/v1/smtp/send                 Send           发送单封邮件
POST /api/v1/smtp/send/batch           SendBatch      批量发送(每收件人一封独立邮件)
POST /api/v1/smtp/send/template        SendTemplate   按模板渲染发送
GET  /api/v1/smtp/quota                GetQuota       查询本期配额与用量
GET  /api/v1/smtp/status/:message_id   GetStatus      查询邮件投递状态
POST /api/v1/smtp/inbound              ReportInbound  上报退信/投诉(自动入黑名单)

鉴权:Bearer Token — "Authorization: Bearer smk_xxx".

func (*SMTPNamespace) GetQuota

func (n *SMTPNamespace) GetQuota() (json.RawMessage, error)

GetQuota returns the current subscription period quota and usage.

GET /api/v1/smtp/quota

返回 {daily_limit, daily_used, daily_remaining, monthly_limit, monthly_used, monthly_remaining, expire_at}.

func (*SMTPNamespace) GetStatus

func (n *SMTPNamespace) GetStatus(messageID string) (json.RawMessage, error)

GetStatus queries delivery status of a sent message.

GET /api/v1/smtp/status/:message_id

返回发送日志记录,主要字段:

message_id       (string) — 消息 ID
status           (string) — pending / sending / success / failed
error_message    (string) — 失败原因
smtp_response    (string) — SMTP 服务器响应
send_duration_ms (int)    — 发送耗时(毫秒)
opened_at / open_count / clicked_at / click_count — 打开/点击追踪(启用追踪时)
created_at       (string) — 创建时间

func (*SMTPNamespace) ReportInbound

func (n *SMTPNamespace) ReportInbound(params map[string]any) (json.RawMessage, error)

ReportInbound reports a bounce/complaint event (auto-adds to suppression list).

POST /api/v1/smtp/inbound

params:

email      (string) — 退信/投诉的收件人邮箱
message_id (string) — 关联的消息 ID
type       (string) — "bounce"(退信)或 "complaint"(投诉)

email / message_id 至少传其一.

返回 {ok: true}.

func (*SMTPNamespace) Send

func (n *SMTPNamespace) Send(params map[string]any, opts ...SMTPSendOptions) (json.RawMessage, error)

Send sends a single email.

POST /api/v1/smtp/send

params 必填:

to       (string) — 收件人邮箱
subject  (string) — 邮件主题
body     (string) — 正文(纯文本或 HTML)

可选:

is_html     (bool)     — body 是否为 HTML,默认 false
from_name   (string)   — 发件人显示名
reply_to    (string)   — 回信地址(Reply-To 头)
text_body   (string)   — 纯文本版本;HTML 邮件带此值时输出 multipart/alternative 提升送达率
headers     (map)      — 自定义邮件头(核心头不可覆盖)
cc          ([]string) — 抄送(写 Cc 头 + 投递)
bcc         ([]string) — 密送(只投递不写头)
attachments ([]object) — 附件列表,元素 {filename, content_base64, content_type}
account_id  (int)      — 指定发信账户 ID(默认自动选最优)
send_at     (string)   — 定时发送(RFC3339,如 2026-07-01T10:00:00Z);> now+30s 则排期到点发

opts 可传 SMTPSendOptions{IdempotencyKey: "..."} 启用幂等(向后兼容,可不传).

返回 {message_id, status, account_name, used_smtp, account_id, send_duration_ms}; 定时分支(send_at 命中排期)返回 {scheduled: true, scheduled_id, send_at}.

func (*SMTPNamespace) SendBatch

func (n *SMTPNamespace) SendBatch(params map[string]any, opts ...SMTPSendOptions) (json.RawMessage, error)

SendBatch sends one independent mail per recipient.

POST /api/v1/smtp/send/batch

params 必填:

recipients ([]object) — 收件人列表,元素 {to(必填), variables?(map), from_name?}

内容二选一(必须指定其一):

静态模式 — subject + body 直接传,每人复用同样内容(仍支持 {{var}} 用 variables 逐人替换)
模板模式 — template_code 传已保存的模板编码,subject/body 留空,每人 variables 渲染

其余可选:is_html / reply_to / cc / bcc / attachments / account_id / headers (message 级字段,对每个收件人邮件相同;cc/bcc/附件会随每封重复).

限制:单次 recipients 数量受订阅 max_batch_size 上限(默认 10);逐封扣配额.

opts 可传 SMTPSendOptions{IdempotencyKey: "..."} 启用幂等(向后兼容,可不传).

返回 {total, success, failed, results: [{to, status, message_id?, error?}]}.

func (*SMTPNamespace) SendTemplate

func (n *SMTPNamespace) SendTemplate(params map[string]any) (json.RawMessage, error)

SendTemplate sends mail rendered from a saved template.

POST /api/v1/smtp/send/template

模板需要先在用户后台 "SMTP API → 模板管理" 创建.

params 必填:

to            (string) — 收件人邮箱
template_code (string) — 模板编码(注意是字符串 code,不是数字 id)

可选:

variables (map)    — 渲染变量(对应模板中 {{var_name}} 占位符)
from_name (string) — 发件人显示名

返回 {message_id, status, used_smtp}.

type SMTPSendOptions

type SMTPSendOptions struct {
	// IdempotencyKey 幂等键:同 key 重试直接返回首次成功结果,
	// 防网络超时重试导致重复发送 + 双扣配额.通过 Idempotency-Key 请求头传递.
	IdempotencyKey string
}

SMTPSendOptions Send / SendBatch 的可选项.

type VCardNamespace

type VCardNamespace struct {
	// contains filtered or unexported fields
}

VCardNamespace implements the v1 虚拟信用卡 endpoints.

对应 NexCore 虚拟信用卡模块(对照 internal/handler/virtual_card_api.go):

只读 / 普通写(X-API-Key + X-Secret-Key 双 header):

GET  /api/v1/vcard/info                       GetInfo              平台公开信息
GET  /api/v1/vcard/bins                        ListBins             可开卡 BIN 列表
GET  /api/v1/vcard/cards                       ListCards            我的卡片列表
GET  /api/v1/vcard/cards/{id}/transactions     GetCardTransactions  卡片消费流水
GET  /api/v1/vcard/orders                      ListOrders           订单列表
GET  /api/v1/vcard/orders/{id}                 GetOrder             单笔订单
PUT  /api/v1/vcard/cards/{id}/remark           UpdateCardRemark     修改卡备注

资金 / 敏感(HMAC-SHA256 签名 + X-Key-ID/X-Timestamp/X-Nonce/X-Signature):

GET  /api/v1/vcard/cards/{id}/details          GetCardDetails       卡敏感信息(卡号等)
GET  /api/v1/vcard/cards/{id}/code             GetCardCode          CVV / 安全码
POST /api/v1/vcard/cards                        OpenCard             开卡
POST /api/v1/vcard/cards/{id}/recharge          RechargeCard         充值
POST /api/v1/vcard/cards/{id}/cancel            CancelCard           注销

鉴权密钥来自 cfg.APIKey / cfg.APISecret(MPK 商户密钥),与 account 命名空间共用.

func (*VCardNamespace) CancelCard

func (n *VCardNamespace) CancelCard(cardID string) (json.RawMessage, error)

CancelCard cancels (closes) a card.

POST /api/v1/vcard/cards/{id}/cancel — HMAC 签名鉴权,无 body.

func (*VCardNamespace) GetCardCode

func (n *VCardNamespace) GetCardCode(cardID string) (json.RawMessage, error)

GetCardCode returns the card's security code (CVV/CVC).

GET /api/v1/vcard/cards/{id}/code — HMAC 签名鉴权.

func (*VCardNamespace) GetCardDetails

func (n *VCardNamespace) GetCardDetails(cardID string) (json.RawMessage, error)

GetCardDetails returns the card's sensitive details (full PAN, expiry, etc).

GET /api/v1/vcard/cards/{id}/details — HMAC 签名鉴权.

func (*VCardNamespace) GetCardTransactions

func (n *VCardNamespace) GetCardTransactions(cardID string) (json.RawMessage, error)

GetCardTransactions returns the consumption transactions of a card.

GET /api/v1/vcard/cards/{id}/transactions

func (*VCardNamespace) GetInfo

func (n *VCardNamespace) GetInfo() (json.RawMessage, error)

GetInfo returns vcard platform public info.

GET /api/v1/vcard/info

func (*VCardNamespace) GetOrder

func (n *VCardNamespace) GetOrder(orderID string) (json.RawMessage, error)

GetOrder returns a single vcard order.

GET /api/v1/vcard/orders/{id}

func (*VCardNamespace) ListBins

func (n *VCardNamespace) ListBins() (json.RawMessage, error)

ListBins lists open-card BINs (card platforms / tiers).

GET /api/v1/vcard/bins

func (*VCardNamespace) ListCards

func (n *VCardNamespace) ListCards() (json.RawMessage, error)

ListCards lists the merchant's cards.

GET /api/v1/vcard/cards

func (*VCardNamespace) ListOrders

func (n *VCardNamespace) ListOrders(query map[string]any) (json.RawMessage, error)

ListOrders lists vcard orders.

GET /api/v1/vcard/orders

query 支持 page / page_size / status / order_type.

func (*VCardNamespace) OpenCard

func (n *VCardNamespace) OpenCard(params map[string]any) (json.RawMessage, error)

OpenCard opens a new virtual card.

POST /api/v1/vcard/cards — HMAC 签名鉴权.

params := map[string]any{
    "bin_platform_id": 1,
    "amount":          "20.00",
}

func (*VCardNamespace) RechargeCard

func (n *VCardNamespace) RechargeCard(cardID string, params map[string]any) (json.RawMessage, error)

RechargeCard recharges an existing card.

POST /api/v1/vcard/cards/{id}/recharge — HMAC 签名鉴权.

params := map[string]any{"amount": "10.00"}

func (*VCardNamespace) UpdateCardRemark

func (n *VCardNamespace) UpdateCardRemark(cardID, remark string) (json.RawMessage, error)

UpdateCardRemark updates a card's remark.

PUT /api/v1/vcard/cards/{id}/remark body {"remark": remark}

非资金敏感,使用双密钥写(X-API-Key + X-Secret-Key).

type WithdrawNamespace

type WithdrawNamespace struct {
	// contains filtered or unexported fields
}

WithdrawNamespace implements the v1 提币 API — 多链收款业务的资金出库端.

鉴权:RSA-PKCS1v15-SHA256 签名 + 4 个请求头

X-API-Key            账户级 API Key(控制台「账号 → API 密钥」)
X-Timestamp          unix ms,与服务器时差 ≤ 60s
X-Nonce              一次性 nonce(uuid v4),5 分钟内不可重复
X-Withdraw-Signature RSA-PKCS1v15-SHA256(caller_private_key, signString),Base64

signString = METHOD + "\n" + PATH + "\n" + TIMESTAMP + "\n" + NONCE + "\n" + BODY 其中 BODY 为 HTTP body 原文(JSON 字符串原样,GET 请求为空字符串).

对应 /docs 文档 "提币 API" 章节的 4 个 endpoint(internal/handler/api_withdraw_v1.go):

POST /api/v1/withdraw                 CreateWithdraw       发起提币
GET  /api/v1/withdraw/:id             GetWithdraw          查询单笔状态
GET  /api/v1/balance/withdrawable     GetWithdrawableBalance 查询可提余额
GET  /api/v1/fee/quote                QuoteFee             费用预估

另提供 VerifyCallback() 校验平台回调签名(用平台公钥).

func (*WithdrawNamespace) CreateWithdraw

func (n *WithdrawNamespace) CreateWithdraw(params map[string]any) (json.RawMessage, error)

CreateWithdraw 发起提币 — POST /api/v1/withdraw

下单后状态为 pending,等延迟到期由 worker 自动广播.期间可在控制台暂停 / 加速 / 取消.

params := map[string]any{
    "chain":        "tron",
    "symbol":       "USDT",
    "amount":       "100.5",
    "to_address":   "TXxxxxxxxx",
    "memo":         "withdraw to user #1024",  // 可选
    "callback_url": "https://your-domain.com/cb", // 可选
    "request_id":   "your-idempotency-uuid",   // 可选,推荐传
}
raw, err := client.Withdraw.CreateWithdraw(params)

func (*WithdrawNamespace) GetWithdraw

func (n *WithdrawNamespace) GetWithdraw(id string) (json.RawMessage, error)

GetWithdraw 查询单笔提币状态 — GET /api/v1/withdraw/:id

返回订单详情(可用来轮询状态,也建议优先用回调).

func (*WithdrawNamespace) GetWithdrawableBalance

func (n *WithdrawNamespace) GetWithdrawableBalance() (json.RawMessage, error)

GetWithdrawableBalance 查询可提余额 — GET /api/v1/balance/withdrawable

返回该账户在每条链 × 每种资产下的「已归集待提现」余额. 只有这部分可用于 API 提币.

func (*WithdrawNamespace) QuoteFee

func (n *WithdrawNamespace) QuoteFee(chain, symbol, amount string) (json.RawMessage, error)

QuoteFee 费用预估 — GET /api/v1/fee/quote?chain=&symbol=&amount=

返回管理端为该 chain × symbol 配置的预扣费(OKX 式固定值).

raw, err := client.Withdraw.QuoteFee("tron", "USDT", "100")

func (*WithdrawNamespace) Sign

func (n *WithdrawNamespace) Sign(method, path, timestamp, nonce, body string) (string, error)

Sign computes the RSA-PKCS1v15-SHA256 signature for a withdraw request.

业务方一般不需要直接调,SDK 内部 do 时自动调用.公开出来便于:

  • 测试签名正确性
  • 自行实现非标场景(比如 curl 调试)

func (*WithdrawNamespace) VerifyCallback

func (n *WithdrawNamespace) VerifyCallback(method, path, timestamp, nonce string, body []byte, base64Sig string) error

VerifyCallback 验证平台回调签名.

用法(对接方收到回调时):

sig := req.Header.Get("X-Platform-Signature")
body, _ := io.ReadAll(req.Body)
ts := req.Header.Get("X-Timestamp")
nonce := req.Header.Get("X-Nonce")
if err := client.Withdraw.VerifyCallback(req.Method, req.URL.Path, ts, nonce, body, sig); err != nil {
    // 验签失败,拒绝处理
}

验签算法与请求方向一致:RSA-PKCS1v15-SHA256(platform_public_key, signString).

Directories

Path Synopsis
examples
create_order command
Tovanix Go SDK — 创建支付订单(轮播模式)
Tovanix Go SDK — 创建支付订单(轮播模式)
webhook command
Tovanix Go SDK — Webhook 回调签名校验
Tovanix Go SDK — Webhook 回调签名校验

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL