dootask/app/Module/AppPush/DeviceRegistry.php
kuaifan a49ee608a5 feat(push): 新增 DooPush 推送通道,与友盟并存
- 新增 app_push_devices 表与 api/push/device 接口(新版 App 上报/删除 DooPush 设备)
- app/Module/AppPush 统一分发友盟与 DooPush,业务字段经 payload.data 下发
- 系统设置「App 推送」新增 DooPush 配置;点击通知打开对应会话
- 更新 Expo 壳子模块(接入 DooPush)、语言包与 ai-kb
2026-10-19 10:33:19 +00:00

52 lines
2.0 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace App\Module\AppPush;
use App\Exceptions\ApiException;
use App\Models\AppPushDevice;
use App\Models\UmengAlias;
use App\Models\UserDevice;
class DeviceRegistry
{
/**
* 绑定当前登录设备,并在同一事务中清理旧壳别名。
*/
public static function update(int $userid, array $attributes, string $uniqueId = ''): void
{
$hash = UserDevice::check();
if (!$hash) {
throw new ApiException('身份已失效,请重新登录', [], -1);
}
AppPushDevice::transaction(function () use ($userid, $attributes, $uniqueId, $hash) {
$device = AppPushDevice::createInstance(array_merge($attributes, [
'userid' => $userid,
'channel' => 'doopush',
'device_hash' => $hash,
]));
// 唯一键原子 upsert,设备切换帐号或并发上报时保留一条绑定。
AppPushDevice::upsert([$device->getAttributes()], ['channel', 'device_id'], [
'userid', 'vendor', 'platform', 'device_hash', 'device', 'version', 'ua', 'is_notified', 'updated_at',
]);
UmengAlias::whereDeviceHash($hash)->delete();
if (mb_strlen($uniqueId) >= 5) {
// 显式使用 ! 转义,避免 %、_ 或反斜杠扩大别名匹配范围。
$suffix = strtr($uniqueId, ['!' => '!!', '%' => '!%', '_' => '!_']);
UmengAlias::whereRaw("alias LIKE ? ESCAPE '!'", ['%-' . $suffix])->delete();
}
});
}
/**
* 退出时 token 可以已失效,但必须与绑定时的 token 相同。
*/
public static function remove(string $deviceId, string $token): void
{
if ($token === '') {
return;
}
// 与 UserDevice::check()/forget() 共用 TOKEN MD5 算法,不依赖 token 解码。
AppPushDevice::whereChannel('doopush')->whereDeviceId($deviceId)->whereDeviceHash(md5($token))->delete();
}
}