SDK
35pay 提供三种官方 SDK:JavaScript / TypeScript、Python、Go。所有 SDK 都是对 REST API 的轻封装,方法名一致。挑你后端用的语言即可。
SDK 仅服务端使用。Secret Key 不要出现在浏览器、移动端、公开仓库。
JavaScript / TypeScript
包名 @35m/sdk,发布在 npm。Node.js 18+,含 TypeScript 类型定义。
安装
npm i @35m/sdk
# 或
pnpm add @35m/sdk用法
import { createPay, Pay, PayError } from '@35m/sdk'
const pay = createPay({
apiKey: process.env.PAY_SECRET_KEY!, // sk_test_xxx 或 sk_live_xxx
// baseUrl: 'https://pay.35team.com', // 自托管时改这里
// timeoutMs: 15000,
})
// 创建支付
const session = await pay.createCheckout({
amount: 9900,
currency: 'CNY',
description: '追思视频套餐',
metadata: { orderId: 'order_123' },
// successUrl 不传:客户付完落到 35pay 收据页(适合 PaymentLink 等简单场景)
// 传了:sync 中转模式 —— 客户落地时 webhook 已处理,本地业务可直接读 paid,零 polling
successUrl: 'https://your.site/orders/123',
})
return Response.redirect(session.url, 303)
// 查询会话
const s = await pay.getSession('sess_01HXYZ...')
if (s.status === 'paid') console.log('paid via', s.record?.provider)
// 验证 webhook 签名(详见 webhooks 文档)
Pay.verifyWebhookSignature(rawBody, sigHeader, secret)错误处理
try {
await pay.createCheckout({ amount: 9900, currency: 'CNY' })
} catch (e) {
if (e instanceof PayError) {
console.error('35pay error', e.status, e.body)
}
throw e
}Python
PyPI 包名 35m-sdk,模块名 pay35,Python 3.9+。 同步版零依赖(仅用 stdlib urllib),异步版可选装 httpx。
安装
# 同步版(FastAPI 同步路由 / Flask / Django sync 视图)
pip install 35m-sdk
# 含异步(FastAPI / Starlette / Litestar / aiohttp)
pip install '35m-sdk[async]'同步用法
import os
from pay35 import Pay, PayError
pay = Pay(api_key=os.environ["PAY_KEY"])
# 创建支付
session = pay.create_checkout(
amount=9900,
currency="CNY",
description="追思视频套餐",
metadata={"order_id": "order_123"},
success_url="https://your.site/orders/123",
)
# session = {"id": ..., "url": ..., "status": "pending", ...}
# 查询会话
s = pay.get_session("sess_01HXYZ...")
# 验证 webhook 签名
ok = Pay.verify_webhook_signature(raw_body, sig_header, secret)异步用法(AsyncPay)
from pay35 import AsyncPay
# 推荐:context manager,自动 aclose
async def create_payment():
async with AsyncPay(api_key=os.environ["PAY_KEY"]) as pay:
return await pay.create_checkout(amount=9900, currency="CNY")
# 或长生命周期,shutdown 时显式 aclose
pay = AsyncPay(api_key=os.environ["PAY_KEY"])
@app.on_event("shutdown")
async def shutdown():
await pay.aclose()AsyncPay 复用一个 httpx.AsyncClient,比每请求新建连接快得多。 长进程(FastAPI / Litestar)建议保留 client,shutdown 时 aclose()。 短脚本用 async with 即可。Go
单文件 pay35.go,零依赖(仅用 stdlib),Go 1.21+。
安装
# 推荐:go get(GitHub release 后可用)
go get github.com/guo2001china/35m-go@v0.1.0
# 或直接 vendor 单文件(零依赖,1 个 .go)
curl -O https://pay.35team.com/sdk/go/pay35.go用法
package main
import (
"log"
"net/http"
"os"
pay35 "github.com/guo2001china/35m-go"
)
func handler(w http.ResponseWriter, r *http.Request) {
pay := pay35.New(pay35.Config{APIKey: os.Getenv("PAY_KEY")})
session, err := pay.CreateCheckout(pay35.CheckoutInput{
Amount: 9900,
Currency: "CNY",
Metadata: map[string]any{"orderId": "order_123"},
SuccessURL: "https://your.site/orders/123",
})
if err != nil {
log.Println(err); http.Error(w, "pay error", 500); return
}
http.Redirect(w, r, session.URL, http.StatusSeeOther)
}
// Webhook
func webhook(w http.ResponseWriter, r *http.Request) {
body, _ := io.ReadAll(r.Body)
sig := r.Header.Get("X-35pay-Signature")
if !pay35.VerifyWebhookSignature(string(body), sig, webhookSecret) {
http.Error(w, "bad signature", 401); return
}
// ...
}方法对照
三种 SDK 方法名风格略有差异(语言习惯),但语义一致:
createCheckout
POST /api/v1/checkout
JS:
pay.createCheckout(input) Python: pay.create_checkout(...) Go: pay.CreateCheckout(input)。返回 session 对象,把 url 给用户跳过去。getSession
GET /api/v1/sessions/:id
查询会话状态。已支付的会话会带
record 字段。refund
POST /api/v1/refunds
JS:
pay.refund(recordId, amount?, reason?) Python: pay.refund(record_id, amount=None, reason=None) Go: pay.Refund(pay35.RefundInput{...})。amount 留空表示全额退款。详见 REST API 退款。verifyWebhookSignature
static / 顶层函数
验签静态方法。详见 Webhooks。
多 ProviderConfig 路由
如果你给同一种 provider 配了多份凭证(如「主号」「个体户副号」),SDK 默认走每种 provider 标了默认的那份。要显式指定,把 providerHints 作为一个额外字段塞进 input:
// JS / TS(类型上是额外字段,as cast 即可)
await pay.createCheckout({
amount: 9900,
currency: 'CNY',
...({ providerHints: { wechat: '个体户副号' } } as object),
})# Python:pay35 字段固定,直接调内部 _request 透传额外字段
pay._request("POST", "/api/v1/checkout", {
"amount": 9900, "currency": "CNY",
"providerHints": {"wechat": "个体户副号"},
})
# AsyncPay 同理:
await pay._request("POST", "/api/v1/checkout", {...})Go SDK 同样可以扩 CheckoutInput 加一个字段,或者直接用 http.Client 发请求。 语义和路由规则见 REST API · providerHints。 三个 SDK 后续会把这个字段加进类型定义。
其他语言
没有官方 SDK 的语言(PHP / Ruby / Java / .NET 等)请直接调 REST API。 签名验证算法是标准 HMAC-SHA256,所有语言都有内置库。