Device Token เป็นตัวระบุเฉพาะที่ APNS กําหนดให้กับอุปกรณ์ iOS แต่ละเครื่องสําหรับการกําหนดเส้นทางการแจ้งเตือนแบบพุช โทเค็นถูกสร้างขึ้นโดยระบบเมื่อแอปลงทะเบียนเพื่อรับการแจ้งเตือนและต้องถูกส่งไปยังเซิร์ฟเวอร์เพื่อส่งพุชไปยังอุปกรณ์นี้โดยเฉพาะ ตาม Apple Developer Documentation, 2026 Device Token อาจเปลี่ยนแปลงเมื่อติดตั้งแอปใหม่ กู้คืนอุปกรณ์จากสํารองข้อมูล หรืออัปเดต iOS ดังนั้นเซิร์ฟเวอร์ควรอัปเดตโทเค็นอย่างสม่ําเสมอเพื่อให้แน่ใจว่าส่งได้
ประเด็นสําคัญ
Device Token (โทเค็นอุปกรณ์) เป็นตัวระบุเฉพาะในรูปแบบสตริง hex ที่ APNS (Apple Push Notification Service) สร้างขึ้นสําหรับแต่ละแอปบนอุปกรณ์ iOS โทเค็นเป็นคีย์ที่เซิร์ฟเวอร์ใช้ส่งการแจ้งเตือนแบบพุชไปยังอุปกรณ์เฉพาะ หากไม่มี Device Token ที่ถูกต้อง เซิร์ฟเวอร์จะไม่สามารถส่งการแจ้งเตือนแบบพุชได้ — APNS จะปฏิเสธคําขอด้วยข้อผิดพลาด 400 BadRequest
Device Token ถูกสร้างขึ้นโดยระบบ iOS เมื่อแอปติดต่อ APNS ครั้งแรกหลังการติดตั้ง กระบวนการสร้าง รวมถึงการผูกมัดทางเข้ารหัสกับรหัสบันเดิล (bundle ID) ของแอปและตัวระบุเฉพาะของอุปกรณ์ (UID) หลังจากนั้น APNS จะส่งคืนโทเค็นขนาด 32 ไบต์ในรูปแบบ hex (64 อักขระ) ให้กับแอป โทเค็นไม่ถาวร — ระบบอาจสร้างโทเค็นใหม่ภายใต้เงื่อนไขบางประการ
เมื่อเซิร์ฟเวอร์ส่งการแจ้งเตือนแบบพุช มันจะรวม Device Token ไว้ในคําขอ HTTP/2 ไปยัง APNS APNS ตรวจสอบความถูกต้องของโทเค็น: หากโทเค็นเป็นของสภาพแวดล้อมอื่น (sandbox แทน production) หมดอายุ หรือถูกเพิกถอน เซิร์ฟเวอร์ Apple จะส่งคืนข้อผิดพลาด 410 Gone หรือ 400 BadRequest หลังจากตรวจสอบโทเค็นสําเร็จเท่านั้น APNS จึงเริ่มส่งการแจ้งเตือนไปยังอุปกรณ์
Device Token ไม่ควรสับสนกับ IDFA (Identifier for Advertisers), IDFV (Identifier for Vendor) หรือ UID (Unique Device Identifier) IDFA และ IDFV ใช้สําหรับการโฆษณาและการวิเคราะห์ UID คือหมายเลขซีเรียลของฮาร์ดแวร์ Device Token มีไว้สําหรับการแจ้งเตือนแบบพุชเท่านั้นและไม่เปิดเผยข้อมูลเกี่ยวกับผู้ใช้หรืออุปกรณ์นอก APNS
| ตัวระบุ | วัตถุประสงค์ | ความคงทน |
|---|---|---|
| Device Token | การกําหนดเส้นทางการแจ้งเตือนแบบพุช APNS | อาจเปลี่ยนแปลง |
| IDFA | การโฆษณาและการติดตาม | สามารถรีเซ็ตโดยผู้ใช้ |
| IDFV | การระบุผู้ขาย (การวิเคราะห์) | คงทนสําหรับแอปจากนักพัฒนาคนเดียวกัน |
| Bundle ID | ตัวระบุแอปที่ไม่ซ้ํากัน | คงทน |
กระบวนการรับ Device Token ประกอบด้วยหลายขั้นตอนบังคับ ตั้งแต่การขออนุญาตจากผู้ใช้ไปจนถึงการส่งโทเค็นไปยังเซิร์ฟเวอร์ แต่ละขั้นตอน สําคัญ — การข้ามขั้นตอนใด ๆ จะทําให้ไม่สามารถส่งการแจ้งเตือนแบบพุชไปยังอุปกรณ์ได้
ขั้นตอนแรกคือแอปขออนุญาตจากผู้ใช้ในการส่งการแจ้งเตือนผ่าน UNUserNotificationCenter.current().requestAuthorization ผู้ใช้สามารถ ยอมรับ ปฏิเสธ หรือเลือกตัวเลือกเพิ่มเติม (alert, badge, sound) หากไม่ได้รับความยินยอมอย่างชัดแจ้งจากผู้ใช้ ระบบจะไม่ออก Device Token แม้ว่าแอปจะเรียก registerForRemoteNotifications หลังจากได้รับอนุญาต แอปจะเรียก UIApplication.shared.registerForRemoteNotifications() ซึ่งเริ่มกระบวนการลงทะเบียนกับ APNS
หลังจากการลงทะเบียน APNS จะส่งคืนโทเค็นผ่านตัวแทน AppDelegate: application(_:didRegisterForRemoteNotificationsWithDeviceToken:) การเรียกที่สําเร็จประกอบด้วยออบเจ็กต์ Data พร้อมโทเค็น ซึ่งต้องแปลงเป็นสตริง hex เพื่อส่งไปยังเซิร์ฟเวอร์ ในกรณีที่เกิดข้อผิดพลาด ระบบจะเรียก application(_:didFailToRegisterForRemoteNotificationsWithError:) พร้อมคําอธิบายปัญหา: การกําหนดค่าใบรับรองไม่ถูกต้อง เครือข่ายไม่พร้อมใช้งาน หรือการกําหนดค่าโครงการไม่ถูกต้อง
หลังจากรับโทเค็น แอปควรส่งไปยังเซิร์ฟเวอร์ของตนทันทีเพื่อจัดเก็บในฐานข้อมูล คําขอ API รวมถึงโทเค็น ตัวระบุอุปกรณ์ (สําหรับการจับคู่) สภาพแวดล้อม (sandbox/production) และข้อมูลเพิ่มเติมเสริม: เวอร์ชัน OS รุ่นอุปกรณ์ ภาษา ขอแนะนําให้ส่งโทเค็นซ้ําทุกครั้งที่เปิดแอปเพื่อให้เซิร์ฟเวอร์มีโทเค็นที่อัปเดตอยู่เสมอ
// ขออนุญาตและลงทะเบียนกับ APNS
func registerForPushNotifications() {
UNUserNotificationCenter.current()
.requestAuthorization(options: [.alert, .sound, .badge]) {
[weak self] granted, error in
guard granted else {
print("ไม่ได้รับอนุญาต")
return
}
DispatchQueue.main.async {
UIApplication.shared
.registerForRemoteNotifications()
}
}
}
// รับ Device Token จาก APNS
func application(
_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
) {
let tokenString = deviceToken
.map { String(format: "%02.2hhx", $0) }
.joined()
print("Device Token: \(tokenString)")
// ส่งโทเค็นไปยังเซิร์ฟเวอร์
PushTokenService.shared
.sendTokenToServer(tokenString) { success in
if success {
UserDefaults.standard.set(tokenString,
forKey: "lastDeviceToken")
}
}
}
ฝั่งเซิร์ฟเวอร์ของระบบพุชต้องจัดเก็บ Device Token ในฐานข้อมูล เชื่อมโยงกับผู้ใช้และสภาพแวดล้อม เมื่อส่งการแจ้งเตือน เซิร์ฟเวอร์จะสร้างคําขอไปยัง APNS โดยรวมโทเค็นใน URL และโทเค็น JWT (หรือใบรับรอง) สําหรับการอนุญาต การจัดการโทเค็นที่ถูกต้องส่งผลอย่างสําคัญต่ออัตราการส่งการแจ้งเตือนแบบพุช
ตารางโทเค็นบนเซิร์ฟเวอร์ควรมีอย่างน้อย: Device Token (ไม่ซ้ํากัน), รหัสผู้ใช้, สภาพแวดล้อม (sandbox/production), วันที่อัปเดตล่าสุด และสถานะ (ทํางาน/ไม่ทํางาน) ขอแนะนําให้เพิ่ม ดัชนีบนโทเค็นสําหรับการค้นหาที่รวดเร็วเมื่อส่ง และบนผู้ใช้สําหรับรับรายการอุปกรณ์ทั้งหมดของผู้ใช้ แอปจํานวนมากอนุญาตให้ผู้ใช้หนึ่งคนมีหลายอุปกรณ์ — แต่ละอุปกรณ์มีโทเค็นของตัวเอง
ในการส่งการแจ้งเตือนแบบพุช เซิร์ฟเวอร์ต้องอนุญาตคําขอไปยัง APNS ด้วยสองวิธี แบบใช้ใบรับรอง ใช้ใบรับรอง SSL ที่สร้างใน Apple Developer Console แบบใช้โทเค็นใช้ JWT (JSON Web Token) พร้อมคีย์ .p8 ที่มีอายุสูงสุด 30 วันโดยไม่ต้องต่ออายุใบรับรอง การอนุญาตแบบใช้โทเค็นถือว่าทันสมัยกว่าและ Apple แนะนําสําหรับโครงการใหม่
คําขอไปยัง APNS รวมถึงวิธี HTTP/2 POST, URL พร้อมเส้นทาง /3/device/{device_token}, ส่วนหัวการอนุญาต และส่วนตัว JSON พร้อมเพย์โหลด ส่วนหัว apns-topic ต้องมีรหัสบันเดิลของแอป apns-priority บ่งบอกลําดับความสําคัญในการส่ง (5 — ทันที, 10 — ประหยัดแบตเตอรี่) apns-expiration กําหนดเวลาเป็นวินาทีตั้งแต่ยุคที่ APNS จะพยายามส่งการแจ้งเตือน
// ตัวอย่างการส่ง push บน Node.js ผ่าน APNS HTTP/2
const http2 = require('http2');
const client = http2.connect('https://api.push.apple.com');
const deviceToken = 'abcdef0123456789...';
const payload = JSON.stringify({
"aps": { "alert": "Hello!", "sound": "default" }
});
const req = client.request({
':method': 'POST',
':path': `/3/device/${deviceToken}`,
'apns-topic': 'com.example.app',
'apns-priority': '10',
'apns-expiration': '0',
'authorization': `bearer ${jwtToken}`
});
req.write(payload);
req.end();
req.on('response', (headers) => {
if (headers[':status'] === '200') {
console.log('ส่ง Push สําเร็จ');
}
});
เมื่อส่งการแจ้งเตือนแบบพุชไปยังอุปกรณ์จํานวนมาก ให้ใช้การส่งแบบกลุ่มพร้อมควบคุมอัตรา APNS แนะนํา อย่าเกิน 1500 คําขอต่อวินาทีต่อการเชื่อมต่อ หากเกินขีดจํากัด เซิร์ฟเวอร์ Apple จะส่งคืนข้อผิดพลาด 429 Too Many Requests สําหรับแคมเปญขนาดใหญ่ ให้ใช้หลายการเชื่อมต่อและกระจายโหลดอย่างสม่ําเสมอทั่วอุปกรณ์
Device Token ไม่ถาวรและอาจเปลี่ยนแปลงในหลายสถานการณ์ ซึ่งต้องใช้กลไกการอัปเดตบนเซิร์ฟเวอร์ หากเซิร์ฟเวอร์ยังคงส่งพุชไปยังโทเค็นที่ล้าสมัย APNS จะส่งคืนข้อผิดพลาด 410 Gone ซึ่งบ่งชี้ว่าโทเค็นไม่ถูกต้องสําหรับสภาพแวดล้อมที่กําหนดอีกต่อไป
Apple บันทึกหลายสถานการณ์ที่ Device Token เปลี่ยนแปลง: ผู้ใช้ติดตั้งแอปใหม่ กู้คืนอุปกรณ์จากสํารองข้อมูล iCloud ติดตั้ง iOS เวอร์ชันใหม่ หรือรีเซ็ตการตั้งค่าเครือข่ายหรือความเป็นส่วนตัว ในแต่ละกรณี แอปจะได้รับโทเค็นใหม่จาก APNS เมื่อเปิดครั้งถัดไป เซิร์ฟเวอร์ต้องอัปเดตโทเค็นในฐานข้อมูล โดยลบโทเค็นเก่าและบันทึกโทเค็นใหม่
เมื่อเซิร์ฟเวอร์ส่งพุชไปยังโทเค็นที่ล้าสมัย APNS จะส่งคืน HTTP 410 พร้อมส่วนหัว apns-unless-timestamp ส่วนหัวนี้ บ่งบอกเวลาที่โทเค็นกลายเป็นไม่ถูกต้อง เซิร์ฟเวอร์ต้องลบหรือปิดการใช้งานโทเค็นนี้ในฐานข้อมูลทันทีเพื่อหลีกเลี่ยงการส่งซ้ํา การเพิกเฉยต่อข้อผิดพลาด 410 ทําให้สิ้นเปลืองทรัพยากรและลดอัตราการส่งสําเร็จ
เพื่อให้ฐานข้อมูลโทเค็นเป็นปัจจุบัน ขอแนะนําให้ทําความสะอาดเป็นระยะ สคริปต์ทําความสะอาด วิเคราะห์บันทึก APNS ใน N วันที่ผ่านมา ค้นหาโทเค็นทั้งหมดที่ได้รับข้อผิดพลาด 410 และปิดการใช้งานในฐานข้อมูล นอกจากนี้ โทเค็นที่ไม่มีกิจกรรมผู้ใช้นานกว่า 90 วันสามารถลบออกได้ — เป็นระเบียนที่ไร้ประโยชน์ซึ่งเพิ่มขนาดฐานข้อมูลเท่านั้น
ก่อนส่งการแจ้งเตือนแบบพุชจํานวนมาก (จดหมายข่าว แคมเปญส่งเสริมการขาย) ขอแนะนําให้ตรวจสอบโทเค็นล่วงหน้า APNS ไม่มี API โดยตรงสําหรับการตรวจสอบโทเค็นแบบกลุ่ม ดังนั้นจึงใช้กลยุทธ์การส่งพุชทดสอบที่มีลําดับความสําคัญต่ําและวิเคราะห์ข้อผิดพลาด โทเค็นที่ส่งคืนข้อผิดพลาด 410 จะถูกแยกออกจากการส่งหลัก
มาดูวงจรเต็มของการรับ Device Token ใน Swift รวมถึงการจัดการข้อผิดพลาดและการส่งไปยังเซิร์ฟเวอร์ โค้ดครอบคลุม การขออนุญาต การลงทะเบียนกับ APNS การแปลง Data เป็นสตริง hex การจัดการข้อผิดพลาด และการส่งโทเค็นไปยังเซิร์ฟเวอร์ของคุณเองพร้อมลองใหม่เมื่อล้มเหลว
import UIKit
import UserNotifications
final class PushNotificationManager: NSObject {
static let shared = PushNotificationManager()
private let apiClient = APIClient()
private var currentToken: String?
func register() {
UNUserNotificationCenter.current()
.requestAuthorization(
options: [.alert, .badge, .sound]) {
[weak self] granted, error in
guard granted else {
Analytics.log(
"Push permission denied")
return
}
DispatchQueue.main.async {
UIApplication.shared
.registerForRemoteNotifications()
}
}
}
func handleDeviceToken(_ tokenData: Data) {
let token = tokenData
.map { String(format: "%02.2hhx", $0) }
.joined()
guard token != currentToken else { return }
currentToken = token
sendTokenToServer(token)
}
func handleRegistrationError(_ error: Error) {
Analytics.log(
"Push registration failed: \(error)")
// ลองใหม่หลังจากหน่วงเวลาเมื่อเกิดข้อผิดพลาดเครือข่าย
if let urlError = error as? URLError,
urlError.code == .notConnectedToInternet {
DispatchQueue.main.asyncAfter(
deadline: .now() + 10) { [weak self] in
self?.register()
}
}
}
private func sendTokenToServer(_ token: String) {
let body = PushTokenRequest(
token: token,
environment: Environment.current == .debug
? "sandbox" : "production",
osVersion: UIDevice.current.systemVersion,
locale: Locale.current.identifier
)
apiClient.sendToken(body) { [weak self] result in
if case .success = result {
self?.currentToken = token
}
}
}
}
ข้อผิดพลาดระหว่างการลงทะเบียน APNS อาจเกิดจากสาเหตุต่าง ๆ ที่พบบ่อยที่สุด รวมถึงเครือข่ายไม่พร้อมใช้งาน การกําหนดค่าใบรับรองไม่ถูกต้องใน Xcode (เช่น ความสามารถ Push Notifications ถูกปิด) การใช้เครื่องจําลอง (ไม่รองรับพุช) หรือโปรไฟล์การเตรียมใช้งานไม่ถูกต้อง ในระบบการผลิต สิ่งสําคัญคือต้องบันทึกข้อผิดพลาดและหากเป็นไปได้ ให้ลองลงทะเบียนอีกครั้งเมื่อเปิดแอปครั้งถัดไป
เครื่องจําลอง iOS ไม่รองรับการรับ Device Token จริง สําหรับการทดสอบ การลงทะเบียนบนเครื่องจําลอง ให้ใช้การตรวจสอบสถาปัตยกรรม i386: ในบิลด์ดีบัก คุณสามารถจําลองการรับโทเค็นหรือใช้การทดสอบ UI กับออบเจ็กต์จําลอง การทดสอบการแจ้งเตือนแบบพุจจริงจะดําเนินการบนอุปกรณ์จริงที่เชื่อมต่อกับ Xcode เท่านั้น
คําถามที่พบบ่อย
ได้ Device Token สามารถเปลี่ยนแปลงได้เมื่อติดตั้งแอปใหม่ กู้คืนอุปกรณ์จากสํารองข้อมูล หรืออัปเดต iOS เซิร์ฟเวอร์ต้อง จัดการการอัปเดตโทเค็น: เมื่อรับโทเค็นใหม่จากอุปกรณ์ที่รู้จัก ให้แทนที่โทเค็นเก่า เมื่อเกิดข้อผิดพลาด 410 ให้นําโทเค็นออกจากฐานข้อมูล
Device Token คือ สตริง hex ขนาด 32 ไบต์ 64 อักขระ ในตัวพิมพ์เล็ก (0–9, a–f) ตัวอย่าง: “a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2” โทเค็นถูกส่งเป็น Data จาก APNS และแปลงเป็นสตริงที่ฝั่งแอป
โทเค็น Sandbox ออกให้สําหรับแอปที่สร้างด้วยโปรไฟล์การเตรียมใช้งานสําหรับนักพัฒนาและทํางานกับ api.sandbox.push.apple.com เท่านั้น โทเค็น Production สําหรับ App Store และ TestFlight และทํางานกับ api.push.apple.com เซิร์ฟเวอร์ต้องแยกแยะสภาพแวดล้อมและส่งพุชไปยังปลายทาง APNS ที่เหมาะสม
ข้อผิดพลาด 410 Gone หมายถึง Device Token ไม่ถูกต้อง เซิร์ฟเวอร์ควรลบโทเค็นนี้ออกจากฐานข้อมูลทันทีและหยุดพยายามส่งไปยังโทเค็นนั้น ส่วนหัว apns-unless-timestamp ในการตอบกลับบ่งบอกว่าโทเค็นหยุดทํางานตั้งแต่เมื่อใด
ตรวจสอบเมธอดตัวแทน application(_:didRegisterForRemoteNotificationsWithDeviceToken:) ใน AppDelegate หากเมธอดถูกเรียก แสดงว่าได้รับโทเค็นแล้ว ใช้บันทึกการดีบักหรือ OSLog เพื่อแสดงโทเค็นในคอนโซล Xcode บนอุปกรณ์จริง ให้ตรวจสอบว่าโทเค็นกําลังถูกส่งไปยังเซิร์ฟเวอร์โดยใช้ Network Link Conditioner
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ
อ่านเพิ่มเติม