客户系统集成
本文说明如何把客户系统(协会/商城/外贸)接入授权站。
一、集成流程
客户系统启动
↓
读取 .env 的 LICENSE_CODE
↓
缓存 24 小时内有验证结果? → 有 → 放行
↓ 没有
请求授权站 /api/license/verify
↓
用内置公钥验签 token
↓ 通过 → 缓存结果(24h),重置失败计数
↓ 失败 → 失败计数 +1
↓
连续失败 7 天 → 后台红条提示(不锁功能)
二、配置项
.env:
LICENSE_CODE=XH-2026-XXXX-XXXX
LICENSE_SERVER=https://cy.yunfenxiang.net
LICENSE_PUBLIC_KEY=-----BEGIN PUBLIC KEY-----...
或在后台「授权状态」里配(推荐,不用改 .env)。
三、中间件实现(参考)
class LicenseMiddleware
{
public function handle($request, Closure $next)
{
$cacheKey = 'license_check';
$cached = Cache::get($cacheKey);
if ($cached && $cached['valid']) {
return $next($request);
}
try {
$resp = Http::timeout(5)->post(config('license.server') . '/api/license/verify', [
'license' => config('license.code'),
'domain' => $request->getHost(),
'product' => config('license.product'),
]);
$data = $resp->json('data') ?? [];
$ok = ! empty($data['token'])
&& openssl_verify(
$data['token'],
base64_decode($data['signature']),
config('license.public_key'),
OPENSSL_ALGO_SHA256
) === 1;
if ($ok && ! empty($data['valid'])) {
Cache::put($cacheKey, ['valid' => true, 'expire' => $data['expire_at']], 86400);
Cache::forget('license_fail_days');
return $next($request);
}
} catch (\Throwable $e) {
Log::warning('[License] 验证失败', ['error' => $e->getMessage()]);
}
// 失败:计数(不锁功能,只在后台提示)
$days = (int) Cache::get('license_fail_days', 0);
Cache::put('license_fail_days', $days + 1, 86400 * 30);
return $next($request);
}
}
关键:验证失败也不锁功能,只在后台顶部提示。避免网络抖动导致客户无法使用。
四、离线模式
内网客户(无外网):
- 在授权站生成
license.dat - 放到
storage/license/license.dat - 客户系统启动读取 → 公钥验签 → 校验到期
- 有效则无需联网
五、公钥轮换
客户系统内置主备两把公钥:
const LICENSE_KEYS = [
'primary' => '-----BEGIN PUBLIC KEY-----(当前主钥)',
'secondary' => '-----BEGIN PUBLIC KEY-----(备用钥)',
];
验签时先主后备,保证换密钥时老客户不受影响。
六、后台授权状态页
授权码:XH-2026-XXXX-XXXX
状态: ✅ 已授权(专业版)
到期: 2027-11-06(剩 365 天)
最近验证:2026-11-06 08:00
[重新验证]
未授权/过期时,后台顶部显示红色提示条。
七、常见问题
| 问题 | 排查 | |---|---| | 一直提示未授权 | 授权码/域名/服务器地址 | | 验证成功但解不了 | 公钥不匹配(换过密钥?) | | 离线证书无效 | 指纹不符/已过期 |
下一篇:常见报错