📚 软件授权充值平台 - 开发文档

API版本 0.1.0 | 适用于万相台地域大师等桌面客户端对接

📋 Swagger UI 📄 OpenAPI JSON(格式化)

一、基础信息

项目值
API Basehttps://softapi.openai2000.cn
接口版本0.1.0
认证方式JWT Bearer Token
签名算法MD5(app级接口必须)
签名时效5分钟

二、签名算法(核心)

算法公式

sign = MD5(app_id + sorted_params + app_key + timestamp)

签名步骤

  1. 获取参数:所有body参数(不含 sign、timestamp)
  2. 排序:按 key 字母升序排列
  3. 拼接:app_id + 排序后的 key1value1key2value2... + app_key + timestamp
  4. MD5:对拼接字符串做 MD5,取32位小写hex
⚠️ 注意事项
  • 签名字段 sign 和 timestamp 都放在 body 中
  • 时间戳为秒级,与服务器时间差不能超过5分钟
  • 签名字符串不要进行URL编码

Python 示例

import hashlib
import time

def make_sign(app_id: str, app_key: str, params: dict) -> dict:
    timestamp = str(int(time.time()))
    # 排序参数(排除sign和timestamp)
    keys = sorted([k for k in params if k not in ('sign', 'timestamp')])
    raw = app_id + ''.join(f"{k}{params[k]}" for k in keys) + app_key + timestamp
    sign = hashlib.md5(raw.encode()).hexdigest()
    return {"sign": sign, "timestamp": timestamp}

# 使用示例
app_id = "APP1756000000123"
app_key = "your_app_key_here"
params = {"app_id": app_id, "username": "test", "password": "12345678"}
result = make_sign(app_id, app_key, params)
# result = {"sign": "abc123...", "timestamp": "1756000000"}

Node.js 示例

const crypto = require('crypto');

function makeSign(appId, appKey, params) {
    const timestamp = Math.floor(Date.now() / 1000).toString();
    // 排序参数(排除sign和timestamp)
    const keys = Object.keys(params)
        .filter(k => k !== 'sign' && k !== 'timestamp')
        .sort();
    const raw = appId + keys.map(k => k + params[k]).join('') + appKey + timestamp;
    const sign = crypto.createHash('md5').update(raw).digest('hex');
    return { sign, timestamp };
}

// 使用示例
const appId = "APP1756000000123";
const appKey = "your_app_key_here";
const params = { app_id: appId, username: "test", password: "12345678" };
const result = makeSign(appId, appKey, params);
// result = { sign: "abc123...", timestamp: "1756000000" }

三、接口文档

1. 用户注册

POST /api/app/user/register

参数类型必填说明
app_idstring✅软件ID
usernamestring✅用户名(3-20字符)
passwordstring✅密码(至少8位)
emailstring❌邮箱(可选,用于找回密码等)
signstring✅签名
timestampstring✅时间戳(秒)

2. 用户登录

POST /api/app/user/login

参数同注册。返回:

{
    "code": 200,
    "msg": "登录成功",
    "data": {
        "token": "jwt_token_xxx",
        "user_id": 123,
        "username": "test",
        "vip_type": 2,  // 0普通 1日卡 2月卡 3年卡 4永久
        "vip_expire_time": "2026-12-31 23:59:59"
    }
}

3. 鉴权校验

GET /api/app/user/auth?app_id=xxx

Header: Authorization: Bearer {token}

4. 充值下单(创建微信支付订单)

POST /api/app/recharge/create

参数类型必填说明
app_idstring✅软件ID
tokenstring✅用户登录token
goods_typeint✅套餐类型:1日卡 / 2月卡 / 3年卡 / 4永久
signstring✅签名
timestampstring✅时间戳(秒)

套餐价格对应表:

goods_type套餐默认价格
1日卡9.9元
2月卡29.9元
3年卡199.9元
4永久520元

返回示例:

{
    "code": 200,
    "msg": "下单成功",
    "data": {
        "order_sn": "SA216947891234abc1",
        "amount": 520,
        "pay_url": "weixin://wxpay/bizpayurl?pr=xxxx"
    }
}
💡 使用说明
  • pay_url 就是微信扫码支付的 code_url,客户端生成二维码让用户扫码即可
  • 用户扫码支付后,需要轮询调用 订单查询 接口获取支付结果

5. 订单查询(轮询检测支付结果)

GET /api/app/recharge/query

参数类型必填说明
app_idstring✅软件ID
tokenstring✅用户token
order_snstring✅下单返回的订单号

返回示例:

{
    "code": 200,
    "msg": "ok",
    "data": {
        "order_sn": "SA2xxxx",
        "amount": 520,
        "goods_type": 4,
        "status": 1,
        "pay_time": "2026-09-15 12:34:56"
    }
}

说明:status 0=未支付,1=已支付

6. 订单列表

GET /api/app/recharge/list

Header: Authorization: Bearer {token}

参数类型必填说明
app_idstring✅软件ID
pageint❌页码,默认1
page_sizeint❌每页数量,默认20

7. 支付成功回调(平台通知你的服务端)

POST 你的软件 notify_url(添加软件时填写)

当用户支付成功后,平台会主动POST通知你的服务端。

参数类型说明
app_idstring软件ID
order_snstring订单号
amountfloat支付金额
goods_typeint套餐类型
user_idint你的软件用户ID
statusint固定为1(支付成功)
timestampstring时间戳
signstring签名,请务必验签确认

验签算法:

sign = MD5(
    app_id + 
    f"amount{amount}" + 
    f"goods_type{goods_type}" + 
    f"order_sn{order_sn}" + 
    f"status1" + 
    f"timestamp{timestamp}" + 
    f"user_id{user_id}" + 
    app_key + 
    timestamp
)
⚠️ 注意事项
  • 请务必验证签名,防止伪造回调
  • 请做好幂等处理,重复回调不要重复开通权限
  • 平台会重试3次(指数退避),如果你的服务端返回错误,平台会持续重试

8. 获取图形验证码

GET /api/captcha

返回:

{
    "code": 200,
    "msg": "获取成功",
    "data": {
        "captcha_id": "a1b2c3d4e5f6g7h8",
        "image": "data:image/png;base64,iVBORw0KGgo..."
    }
};
💡 使用说明
  • captcha_id 用于后续校验,有效期5分钟
  • image 是base64编码的PNG图片,可直接用于 <img src="...">
  • 验证码为4位大写字母+数字(去掉易混淆字符:0/O/1/I/l)

9. 校验图形验证码

POST /api/captcha/verify

参数类型必填说明
captcha_idstring✅验证码ID(从获取接口返回)
captcha_codestring✅用户输入的验证码

返回:

{
    "code": 200,
    "msg": "校验成功",
    "data": { "valid": true }
}

10. 发送邮箱验证码

POST /api/email/captcha/send

参数类型必填说明
emailstring✅用户邮箱地址

返回:

{
    "code": 200,
    "msg": "发送成功,请查收",
}
⚠️ 限制规则
  • 60秒只能发送一次,同一邮箱一天最多发送50次
  • 验证码有效期5分钟,一次性使用

11. 校验邮箱验证码

POST /api/email/captcha/verify

参数类型必填说明
emailstring✅用户邮箱地址
captcha_codestring✅用户输入的验证码

返回:

{
    "code": 200,
    "msg": "校验成功",
    "data": { "valid": true }
}

四、套餐定价

goods_type套餐名称天数默认价格
1日卡1天9.9元
2月卡30天29.9元
3年卡365天199.9元
4永久授权永久520元
💡 定制价格

平台支持为每个软件单独设置价格,你的软件当前定价:

日卡月卡年卡永久
1.9元29.9元199.9元520元

如需修改价格,请联系平台管理员在后台修改。

五、客户端集成流程

┌─────────────────────────────────────────────────────────────┐
│                    客户端启动流程                           │
├─────────────────────────────────────────────────────────────┤
│  1. 检查本地是否保存了 token                                │
│     └─ 无 → 显示登录界面                                    │
│                                                             │
│  2. 调用 /api/app/user/auth 校验 token                     │
│     ├─ 200 → 进入主界面,根据 vip_type 开启功能             │
│     └─ 401/403 → 跳转登录页                                │
│                                                             │
│  3. 登录/注册                                               │
│     ├─ POST /api/app/user/register(带签名)                │
│     └─ POST /api/app/user/login(带签名)                   │
│                                                             │
│  4. 充值                                                    │
│     ├─ POST /api/app/recharge/create(带签名)              │
│     ├─ 展示微信二维码                                       │
│     └─ 轮询 /api/app/recharge/query 等待支付结果           │
└─────────────────────────────────────────────────────────────┘

六、代码示例

import hashlib
import time
import requests

class SoftapiClient:
    def __init__(self, base_url, app_id, app_key):
        self.base_url = base_url
        self.app_id = app_id
        self.app_key = app_key
    
    def _make_sign(self, params):
        timestamp = str(int(time.time()))
        keys = sorted([k for k in params if k not in ('sign', 'timestamp')])
        raw = self.app_id + ''.join(f"{k}{params[k]}" for k in keys) + self.app_key + timestamp
        sign = hashlib.md5(raw.encode()).hexdigest()
        return sign, timestamp
    
    def register(self, username, password):
        params = {"app_id": self.app_id, "username": username, "password": password}
        sign, timestamp = self._make_sign(params)
        params.update({"sign": sign, "timestamp": timestamp})
        return requests.post(f"{self.base_url}/api/app/user/register", json=params).json()
    
    def login(self, username, password):
        params = {"app_id": self.app_id, "username": username, "password": password}
        sign, timestamp = self._make_sign(params)
        params.update({"sign": sign, "timestamp": timestamp})
        return requests.post(f"{self.base_url}/api/app/user/login", json=params).json()
    
    def auth(self, token):
        headers = {"Authorization": f"Bearer {token}"}
        return requests.get(f"{self.base_url}/api/app/user/auth?app_id={self.app_id}", headers=headers).json()
    
    def create_order(self, token, goods_type):
        params = {"app_id": self.app_id, "token": token, "goods_type": str(goods_type)}
        sign, timestamp = self._make_sign(params)
        params.update({"sign": sign, "timestamp": timestamp})
        return requests.post(f"{self.base_url}/api/app/recharge/create", json=params).json()

# 使用
client = SoftapiClient("https://softapi.openai2000.cn", "APPxxx", "your_app_key")
result = client.login("test", "12345678")
print(result)
const crypto = require('crypto');
const axios = require('axios');

class SoftapiClient {
    constructor(baseUrl, appId, appKey) {
        this.baseUrl = baseUrl;
        this.appId = appId;
        this.appKey = appKey;
    }
    
    _makeSign(params) {
        const timestamp = Math.floor(Date.now() / 1000).toString();
        const keys = Object.keys(params)
            .filter(k => k !== 'sign' && k !== 'timestamp')
            .sort();
        const raw = this.appId + keys.map(k => k + params[k]).join('') + this.appKey + timestamp;
        const sign = crypto.createHash('md5').update(raw).digest('hex');
        return { sign, timestamp };
    }
    
    async register(username, password) {
        const params = { app_id: this.appId, username, password };
        const { sign, timestamp } = this._makeSign(params);
        const res = await axios.post(`${this.baseUrl}/api/app/user/register`, {
            ...params, sign, timestamp
        });
        return res.data;
    }
    
    async login(username, password) {
        const params = { app_id: this.appId, username, password };
        const { sign, timestamp } = this._makeSign(params);
        const res = await axios.post(`${this.baseUrl}/api/app/user/login`, {
            ...params, sign, timestamp
        });
        return res.data;
    }
    
    async auth(token) {
        const res = await axios.get(`${this.baseUrl}/api/app/user/auth?app_id=${this.appId}`, {
            headers: { Authorization: `Bearer ${token}` }
        });
        return res.data;
    }
    
    async createOrder(token, goodsType) {
        const params = { app_id: this.appId, token, goods_type: goodsType.toString() };
        const { sign, timestamp } = this._makeSign(params);
        const res = await axios.post(`${this.baseUrl}/api/app/recharge/create`, {
            ...params, sign, timestamp
        });
        return res.data;
    }
}

// 使用
const client = new SoftapiClient("https://softapi.openai2000.cn", "APPxxx", "your_app_key");
client.login("test", "12345678").then(console.log);
// 完整 TypeScript SDK 请下载:
// /opt/software_auth/docs/softapi-client-sdk.ts

import crypto from 'crypto';

interface SoftapiConfig {
    baseUrl: string;
    appId: string;
    appKey: string;
}

export class SoftapiClient {
    private config: SoftapiConfig;
    
    constructor(config: SoftapiConfig) {
        this.config = config;
    }
    
    private makeSign(params: Record) {
        const timestamp = Math.floor(Date.now() / 1000).toString();
        const keys = Object.keys(params)
            .filter(k => k !== 'sign' && k !== 'timestamp')
            .sort();
        const raw = this.config.appId + keys.map(k => k + params[k]).join('') + this.config.appKey + timestamp;
        const sign = crypto.createHash('md5').update(raw).digest('hex');
        return { sign, timestamp };
    }

    // ... 更多方法见 SDK 文件
}

七、联系我们

如有疑问,请联系平台管理员。

查看 Swagger 文档 返回首页

© 2026 软件授权充值平台 | API v0.1.0