接入你的 App
Xsolla 订阅
适合通过 Xsolla 卖订阅、自己没有服务端的 App。App 用一个 API 密钥把 Xsolla 用户 ID 发给网关;网关用你的 Xsolla API 密钥去问 Xsolla,回答该用户有没有生效中的订阅。验证免费。
#开始之前
- 一个 Xsolla Publisher Account,其中有卖订阅的项目(Subscriptions → Subscription plans)。
- App 写进支付令牌的用户 ID(user.id)。同一个用户每次都要一样,比如 App 首次生成后保存下来的 ID。
#1. 拿到 ID 和 API 密钥
- 1
打开 Publisher Account
publisher.xsolla.com用有权限管理 API 密钥的账号登录。
- 2
记下商户 ID 和项目 ID
打开项目,地址是 publisher.xsolla.com/<商户 ID>/projects/<项目 ID>,例如 746076 和 273204。
- 3
创建 API 密钥
Company settings → API keys → Create API key,或项目的 Settings → API keys马上复制:Xsolla 只显示一次。拿到它的人能读取你的订阅,所以不要放进 App。
#2. 填到 API 密钥上
- 1
打开 App 用的那个密钥
控制台 → API 密钥 → 编辑给 App 单独建一个密钥,只开放它用到的模型,并设置额度上限。
- 2
填写 Xsolla 订阅验证
设置 Xsolla 验证填写商户 ID、项目 ID 和 API 密钥后保存。网关会先用这个密钥问一次 Xsolla 再保存;密钥加密保存,之后不再显示。
#3. 在 App 里验证
付款窗口关闭后查一次,App 打开时再查一次。传 App 写进支付令牌的同一个用户 ID。不要等结果才启动 App:先显示上次保存的结果,查完再更新。每个密钥默认每分钟可查 120 次。
xsolla.dart
import 'dart:convert';
import 'package:http/http.dart' as http;
const apiKey = 'sk-YOUR_KEY';
Future<Map<String, dynamic>?> checkXsolla(String userId) async {
final res = await http.post(
Uri.parse('https://www.aisplice.store/v1/xsolla/verify'),
headers: {
'Authorization': 'Bearer $apiKey',
'Content-Type': 'application/json',
// Request signing on for this key? Then this call must be signed too:
// ...signedHeaders('POST', '/v1/xsolla/verify'),
},
body: jsonEncode({'user_id': userId}),
);
if (res.statusCode != 200) return null; // keep the last saved answer
return jsonDecode(res.body) as Map<String, dynamic>;
}
Future<void> refreshEntitlement(String userId) async {
final status = await checkXsolla(userId);
if (status == null) return;
await saveEntitlement(status); // your local storage
if (status['active'] == true) unlockPaidFeatures();
}#4. 决定解锁什么
| 验证结果 | App 怎么做 | 常见原因 |
|---|---|---|
| active: true, in_trial: true | 解锁,并按 expiry_time 显示“试用到期时间”。 | 免费试用,还没扣款 |
| active: true | 解锁,有效到 expiry_time。 | 已付费,包括关闭了自动续费但还没到期的订阅 |
| subscribed: true, active: false | 不解锁,显示续订页面。 | 已取消或已冻结 |
| subscribed: false | 不解锁,显示订阅页面。 | 该用户还没有订阅,或付款还没完成 |
| HTTP 502 / 503 | 沿用上次保存的结果,稍后重试。 | Xsolla 或 API 密钥没有回应 |
把 expiry_time 和结果一起保存。两次验证之间,到这个时间之前都当作可用,这样手机离线也能正常用。
#5. 保护 App 里的密钥
放在 App 里的 key 抓包就能看到。给这个 key 开启请求签名,这样别人复制走 key 也单独用不了;打包时做混淆,并给 key 设额度上限。
#6. 查看发生了什么
每次验证(包括缓存结果和失败)都会列在控制台 → 请求日志里,是密钥上的一条免费 xsolla-verify 记录。
- 保存时提示 Xsolla 不接受密钥:密钥没复制全、已被删除,或属于别的公司。请新建一个。
- xsolla_credentials_invalid:保存后密钥在 Publisher Account 里被删了。请新建密钥并填到 API 密钥上。
- 每次都返回 subscribed: false:用户 ID 和支付令牌里的不一致,或密钥上的项目 ID 是另一个项目。
还是没解决?
把请求 ID 或报错信息发给我们,我们来查。