应用接入协议
在当前网站访问
/help/login查看用户字段映射,/help/integration-api查看完整登录/授权接口参数与响应;机器契约为 OpenAPI。
OAuth2 / OIDC
管理员在「应用接入」、开发者在「我的应用」创建应用,配置精确回调URL、scope与public_client,保存首次显示的secret和API Key。公共客户端不能打包secret;机密客户端仅在服务端保存。
发现文档:GET /.well-known/openid-configuration;公钥:GET /.well-known/jwks.json。issuer为APP_ORIGIN,生产必须HTTPS。
- 生成随机state、nonce和43–128位URL安全code_verifier,challenge为SHA256(verifier)的无填充Base64URL。
- 浏览器跳转
/oauth/authorize,参数response_type=code、client_id、redirect_uri、scope、state、nonce、code_challenge、code_challenge_method=S256。 - 登录同意后回调携带code和state,客户端必须核对state。
- POST表单至
/oauth/token:grant_type=authorization_code、code、client_id、redirect_uri、code_verifier。机密客户端还需client_secret_basic或client_secret_post认证。授权码60秒有效、一次使用。 - ID Token使用JWKS校验RS256、kid、iss、aud、exp、nonce,不能仅解码。访问令牌放入Authorization: Bearer调用
/oauth/userinfo。 - 申请offline_access才能刷新。刷新后原子替换旧令牌,重放会撤销令牌族。退出调用
/oauth/revoke;用户可在控制台撤销应用同意。
升级到包含在线传统客户端兼容选项的版本时,先运行数据库迁移(015_application_legacy_oauth.sql),再启动新版服务和前端。
对于已开启 PKCE 但不发送 nonce 的机密客户端,可在管理员“应用接入 → 编辑”或开发者“我的应用 → 编辑配置”中开启“兼容不发送 nonce 的 OIDC 应用”。仅对该应用生效,保存后新的授权请求立即生效,无需修改环境变量或重启。默认关闭,公开客户端不能开启;非空 nonce 仍须为16–512字符,PKCE要求不变。
对于 Cloudreve、Gitea 等无法发送 PKCE 和 nonce、但能安全保存 Client Secret 的服务端应用,可开启“传统 OIDC 客户端兼容(不发送 PKCE / nonce)”。该设置同样按应用保存并立即生效。缺少 PKCE 只在 challenge 与 method 均未提供时兼容;一旦提供就必须是 S256 且在换取令牌时匹配 verifier。公开客户端不能开启此选项。
支持prompt=consent/login/none。建议使用成熟OIDC客户端库;本项目未取得第三方符合性认证。
授权查询与扣减
POST /api/v1/auth/check,JSON含authorization_id、binding_value。POST /api/v1/auth/consume,另含quantity与idempotency_key(8–128字符)。同一业务重试使用同一幂等键,不能在客户端自行扣余额。
服务端使用X-API-Key,仅访问对应应用授权;不能将API Key公开分发。用户客户端使用获准license:read/consume scope的OAuth访问令牌。域名/设备绑定要求binding_value已验证,且受数量和解绑冷却约束。
激活码、设备与域名授权
管理员按授权商品批量生成激活码,只需设置数量、可选的兑换截止时间和批次备注。系统在生成时自动锁定商品当时的授权规则,包括授权类型、时长、额度以及设备或域名绑定上限;之后修改商品不会改变已经发出的激活码权益。激活码按批次管理,可再次查看、复制或导出尚未使用的激活码,并可追踪兑换用户、兑换时间和对应授权的使用情况。新激活码以哈希用于兑换核验,同时加密保存用于有权限的管理员再次查看;升级前生成且只保存哈希的旧激活码无法恢复原文,但仍按原兼容规则兑换。
用户可以在认证中心工作台提交 POST /authorizations/activate,也可以让接入应用使用当前用户的 OAuth Access Token 调用同一路径。应用内兑换必须申请 license:activate scope,请求只提交 {"code":"AC-..."};认证中心从令牌确定用户和应用,并只允许兑换属于该应用的激活码。应用 API Key 只能证明应用身份,不能单独代表用户兑换。成功响应同时返回值相同的 license_key 与 authorization_id,并返回 application_id、auth_type、绑定上限和额度。接入方保存 license_key 用于后续授权校验;激活码只用于一次兑换。
同一个 license:activate 用户 Access Token 也可以调用下述绑定、兼容确认和解绑路径。认证中心同时按令牌中的用户 ID 与应用 ID 限制目标授权,不能管理该用户在其他应用中的授权:
POST /authorizations/:id/bindingsPOST /authorizations/:id/bindings/:binding/verifyDELETE /authorizations/:id/bindings/:binding
设备型授权通过 POST /authorizations/:id/bindings 激活设备,binding_type为device、binding_value为应用生成的稳定设备标识。达到上限后拒绝新设备。用户在授权详情中可查看设备并调用 DELETE /authorizations/:id/bindings/:binding 取消激活。旧绑定协议中,解绑成功释放绑定名额,仍遵守所属应用配置的冷却时间;绑定名额不代表运行期并发许可。采用严格在线租约的客户端中,解绑会撤销旧租约的续期能力,但不缩短旧客户端已经收到的截止时间;新设备须等旧实例停止并 release,或等原租约实际到期,再成功 acquire 后才能运行。参见永久授权恢复与单设备在线租约。旧绑定策略迁移为 010_activation_code_policy.sql,租约协议另需 027_authorization_leases.sql;此说明不表示生产迁移已经执行。
域名型授权提交根域名后立即生效,不需要配置 DNS TXT 记录。提交完整子域名时携带 parent_binding_id 指向根域名,子域名必须严格位于该根域名之下。授权检查只接受根域名和用户明确配置的子域名;未配置的其他子域名不会自动获得授权。移除根域名会级联移除它下面的子域名。旧客户端的验证路径继续保留,但只确认旧绑定并立即生效,不再查询 DNS。升级时迁移 026_domain_binding_immediate.sql 会把已有待验证域名直接设为有效。
浏览器与交易
浏览器接口前缀 /api/v1,返回 {code,message,data}。用户写请求使用同源Cookie、Origin和X-CSRF-Token,先GET /api/v1/auth/csrf。机器授权、OAuth表单和支付通知使用各自认证。
创建订单POST /orders,含items(product_id/quantity,可选renewal_authorization_id)、coupon_ids、points、idempotency_key;同一键更换内容返回409。金额一律最小货币单位整数。
POST /orders/:id/pay 指定channel,返回跳转、二维码或银行资料。浏览器返回页不代表到账。正式通知地址 /api/v1/payments/:channel/callback,各适配器校验签名、商户、金额、币种后事务发放权益。
银行需工作人员录入真实流水和金额,跨订单复用流水被拒绝。取消后晚到账进入独立退款,不正常开通权益。退款须按类型区分:管理员售后金额退款(after_sales)支持部分或全部剩余现金/积分退款,保留订单及已履约权益;取消未履约纯服务订单(cancel_order)仅退还全部剩余额度;用户原有退货退款会回收软件权益,续期退款按原规则回滚续期增量,原单存在未处理续期时先处理续期。金额退款不等于撤销权益,提交或审核通过也不等于渠道已经退回资金。详情见浏览器与订单退款接口。普通软件授权订阅由用户主动续期;开发者会员可另行开启仅使用预付余额的自动续费,免费开发者订阅续期金额为 0,均不会直接向支付渠道周期扣款。详情见开发者会员与应用管理。
发票适配
配置HTTPS endpoint与Bearer token。系统POST JSON,Idempotency-Key和request_id均为申请编号:issue或申请编号:void。适配器须幂等,返回匹配request_id、amount_minor与currency。
请求含operation、invoice_no、title快照、amount_minor、currency、invoice_type、invoice_format、email、shipping_address、order_id。响应status=processing表示等待;issued需真实invoice_no,电子票需pdf_base64,纸票可含tracking_no;作废成功返回voided。详细字段见invoice_adapter.go。
退款可能早于异步开票完成,适配器应能按申请编号取消或查找已开票再红冲。不能仅删除本地PDF代表税务作废。未配置自动服务时使用人工开票与真实文件上传。
外部配置
支付、第三方登录、生产SMTP和税务开票都需要实际服务账号、回调域名与沙箱验收。密钥加密存储,读取时屏蔽;不要写入源码或日志。软件版本/S3客户端协议见 版本管理。