bindDevice($pushToken); } $device = AppPushDevice::createInstance(array_merge($attributes, [ 'userid' => $userid, 'channel' => $channel, 'device_hash' => $hash, ])); // 唯一键原子 upsert,设备切换帐号或并发上报时保留一条绑定。 AppPushDevice::upsert([$device->getAttributes()], ['channel', 'device_id'], [ 'userid', 'vendor', 'platform', 'device_hash', 'device', 'version', 'ua', 'is_notified', 'updated_at', ]); } /** * 退出时 token 可以已失效,但必须与绑定时的 token 相同。 */ public static function remove(string $deviceId, string $token): void { if ($token === '') { return; } // 与 UserDevice::check()/forget() 共用 TOKEN MD5 算法,不依赖 token 解码。 $channels = AppPushDevice::whereIn('channel', [AppPush::CHANNEL_SYSTEM, AppPush::CHANNEL_CUSTOM]) ->whereDeviceId($deviceId)->whereDeviceHash(md5($token))->pluck('channel')->all(); if (!$channels) { return; } AppPushDevice::whereIn('channel', $channels)->whereDeviceId($deviceId)->whereDeviceHash(md5($token))->delete(); if (in_array(AppPush::CHANNEL_SYSTEM, $channels, true)) { app(DooPushClient::class)->unbindDevice($deviceId); } } }