Google Health API ช่วยให้แอปพลิเคชันของคุณได้รับการแจ้งเตือนแบบเรียลไทม์เมื่อข้อมูลสุขภาพของผู้ใช้มีการเปลี่ยนแปลง เซิร์ฟเวอร์ของคุณจะได้รับเว็บฮุคคำขอ HTTPS POST ทันทีที่ข้อมูลพร้อมใช้งานใน Google Health API แทนที่จะทำการสำรวจการเปลี่ยนแปลง
ประเภทข้อมูลที่รองรับ
ระบบรองรับการแจ้งเตือน Webhook สำหรับข้อมูลประเภทต่อไปนี้
| ประเภทข้อมูล | การดำเนินการ ที่ใช้ได้ |
ขอบเขต |
|---|---|---|
|
นาทีที่แอ็กทีฟ
dataType:
active-minutesfilter parameter: active_minutes
ประเภทระเบียน: Interval
ความละเอียดของพื้นที่เก็บข้อมูล: 1 นาที
อุปกรณ์ที่เข้ากันได้
|
list, reconcile, rollup, dailyRollup | .activity_and_fitness.readonly.activity_and_fitness.writeonly |
|
นาทีในโซนแอ็กทีฟ
dataType:
active-zone-minutesfilter parameter: active_zone_minutes
ประเภทระเบียน: Interval
ความละเอียดของพื้นที่เก็บข้อมูล: 1 นาที
อุปกรณ์ที่เข้ากันได้
|
list, reconcile, rollup, dailyRollup | .activity_and_fitness.readonly.activity_and_fitness.writeonly |
|
ระดับกิจกรรม
|
รายการ, ตรวจสอบยอดคงเหลือ | .activity_and_fitness.readonly.activity_and_fitness.writeonly |
|
Altitude
dataType:
altitudefilter parameter: altitude
ประเภทระเบียน: Interval
ความละเอียดของพื้นที่เก็บข้อมูล: 1 นาที
|
list, reconcile, rollup, dailyRollup | .activity_and_fitness.readonly.activity_and_fitness.writeonly |
|
น้ำตาลกลูโคสในเลือด
dataType:
blood-glucosefilter parameter: blood_glucose
ประเภทระเบียน: ตัวอย่าง
|
list, get, reconcile, rollup, dailyRollup | .health_metrics_and_measurements.readonly.health_metrics_and_measurements.writeonly |
|
ไขมันร่างกาย
dataType:
body-fatfilter parameter: body_fat
ประเภทระเบียน: ตัวอย่าง
อุปกรณ์ที่เข้ากันได้
|
list, get, reconcile, rollup, dailyRollup, create, update, batchDelete | .health_metrics_and_measurements.readonly.health_metrics_and_measurements.writeonly |
|
แคลอรีในโซนอัตราการเต้นของหัวใจ
dataType:
calories-in-heart-rate-zonefilter parameter: calories_in_heart_rate_zone
ประเภทระเบียน: Interval
ความละเอียดของพื้นที่เก็บข้อมูล: 1 นาที
|
rollup, dailyRollup | .activity_and_fitness.readonly.activity_and_fitness.writeonly |
|
ความผันแปรของอัตราการเต้นของหัวใจประจำวัน
dataType:
daily-heart-rate-variabilityfilter parameter: daily_heart_rate_variability
ประเภทการบันทึก: รายวัน
อุปกรณ์ที่เข้ากันได้
|
รายการ, ตรวจสอบยอดคงเหลือ | .health_metrics_and_measurements.readonly.health_metrics_and_measurements.writeonly |
|
โซนอัตราการเต้นของหัวใจประจำวัน
dataType:
daily-heart-rate-zonesfilter parameter: daily_heart_rate_zones
ประเภทการบันทึก: รายวัน
|
รายการ, ตรวจสอบยอดคงเหลือ | .health_metrics_and_measurements.readonly.health_metrics_and_measurements.writeonly |
|
ความอิ่มตัวของออกซิเจนรายวัน
dataType:
daily-oxygen-saturationfilter parameter: daily_oxygen_saturation
ประเภทการบันทึก: รายวัน
อุปกรณ์ที่เข้ากันได้
|
รายการ, ตรวจสอบยอดคงเหลือ | .health_metrics_and_measurements.readonly.health_metrics_and_measurements.writeonly |
|
อัตราการหายใจรายวัน
dataType:
daily-respiratory-ratefilter parameter: daily_respiratory_rate
ประเภทการบันทึก: รายวัน
อุปกรณ์ที่เข้ากันได้
|
รายการ, ตรวจสอบยอดคงเหลือ | .health_metrics_and_measurements.readonly.health_metrics_and_measurements.writeonly |
|
อัตราการเต้นของหัวใจขณะพักรายวัน
dataType:
daily-resting-heart-ratefilter parameter: daily_resting_heart_rate
ประเภทการบันทึก: รายวัน
อุปกรณ์ที่เข้ากันได้
|
รายการ, ตรวจสอบยอดคงเหลือ | .health_metrics_and_measurements.readonly.health_metrics_and_measurements.writeonly |
|
ค่าเบี่ยงเบนของอุณหภูมิขณะนอนหลับรายวัน
dataType:
daily-sleep-temperature-derivationsfilter parameter: daily_sleep_temperature_derivations
ประเภทการบันทึก: รายวัน
อุปกรณ์ที่เข้ากันได้
|
รายการ, ตรวจสอบยอดคงเหลือ | .health_metrics_and_measurements.readonly.health_metrics_and_measurements.writeonly |
|
ระยะทาง
dataType:
distancefilter parameter: distance
ประเภทระเบียน: Interval
ความละเอียดของพื้นที่เก็บข้อมูล: 1 นาที
อุปกรณ์ที่เข้ากันได้
|
list, reconcile, rollup, dailyRollup | .activity_and_fitness.readonly.activity_and_fitness.writeonly |
|
การออกกำลังกาย
dataType:
exercisefilter parameter: exercise
ประเภทระเบียน: เซสชัน
อุปกรณ์ที่เข้ากันได้
|
list, get, reconcile, create, update, batchDelete | .activity_and_fitness.readonly.activity_and_fitness.writeonly |
|
ชั้น
dataType:
floorsfilter parameter: floors
ประเภทระเบียน: Interval
ความละเอียดของพื้นที่เก็บข้อมูล: 1 นาที
|
reconcile, rollup, dailyRollup | .activity_and_fitness.readonly.activity_and_fitness.writeonly |
|
อัตราการเต้นของหัวใจ
dataType:
heart-ratefilter parameter: heart_rate
ประเภทระเบียน: ตัวอย่าง
ความละเอียดของพื้นที่เก็บข้อมูล: 1 วินาที
อุปกรณ์ที่เข้ากันได้
|
list, reconcile, rollup, dailyRollup | .health_metrics_and_measurements.readonly.health_metrics_and_measurements.writeonly |
|
ความผันแปรของอัตราการเต้นของหัวใจ
dataType:
heart-rate-variabilityfilter parameter: heart_rate_variability
ประเภทระเบียน: ตัวอย่าง
อุปกรณ์ที่เข้ากันได้
|
รายการ, ตรวจสอบยอดคงเหลือ | .health_metrics_and_measurements.readonly.health_metrics_and_measurements.writeonly |
|
ส่วนสูง
|
list, get, reconcile, create, update, batchDelete | .health_metrics_and_measurements.readonly.health_metrics_and_measurements.writeonly |
|
บันทึกปริมาณน้ำที่ดื่ม
|
list, get, reconcile, rollup, dailyRollup, create, update, batchDelete | .nutrition.readonly.nutrition.writeonly |
|
บันทึกโภชนาการ
dataType:
nutrition-logfilter parameter: nutrition_log
ประเภทระเบียน: เซสชัน
อุปกรณ์ที่เข้ากันได้
|
list, get, reconcile, rollup, dailyRollup, create, update, batchDelete | .nutrition.readonly.nutrition.writeonly |
|
สรุปอัตราการหายใจขณะนอนหลับ
dataType:
respiratory-rate-sleep-summaryfilter parameter: respiratory_rate_sleep_summary
ประเภทระเบียน: ตัวอย่าง
อุปกรณ์ที่เข้ากันได้
|
รายการ, ตรวจสอบยอดคงเหลือ | .health_metrics_and_measurements.readonly.health_metrics_and_measurements.writeonly |
|
ปริมาณการใช้ออกซิเจนสูงสุด (VO2 Max) ขณะวิ่ง
dataType:
run-vo2-maxfilter parameter: run_vo2_max
ประเภทระเบียน: ตัวอย่าง
อุปกรณ์ที่เข้ากันได้
|
list, reconcile, rollup, dailyRollup | .activity_and_fitness.readonly.activity_and_fitness.writeonly |
|
ระยะเวลาที่ไม่มีการเคลื่อนไหว
dataType:
sedentary-periodfilter parameter: sedentary_period
ประเภทระเบียน: Interval
อุปกรณ์ที่เข้ากันได้
|
list, reconcile, rollup, dailyRollup | .activity_and_fitness.readonly.activity_and_fitness.writeonly |
|
การนอนหลับ
dataType:
sleepfilter parameter: sleep
ประเภทระเบียน: เซสชัน
อุปกรณ์ที่เข้ากันได้
|
list, get, reconcile, create, update, batchDelete | .sleep.readonly.sleep.writeonly |
|
ขั้นตอน
dataType:
stepsfilter parameter: steps
ประเภทระเบียน: Interval
ความละเอียดของพื้นที่เก็บข้อมูล: 1 นาที
อุปกรณ์ที่เข้ากันได้
|
list, reconcile, rollup, dailyRollup | .activity_and_fitness.readonly.activity_and_fitness.writeonly |
|
เวลาในโซนอัตราการเต้นของหัวใจ
dataType:
time-in-heart-rate-zonefilter parameter: time_in_heart_rate_zone
ประเภทระเบียน: Interval
ความละเอียดของพื้นที่เก็บข้อมูล: 1 นาที
|
list, reconcile, rollup, dailyRollup | .activity_and_fitness.readonly.activity_and_fitness.writeonly |
|
น้ำหนัก
dataType:
weightfilter parameter: weight
ประเภทระเบียน: ตัวอย่าง
อุปกรณ์ที่เข้ากันได้
|
list, get, reconcile, rollup, dailyRollup, create, update, batchDelete | .health_metrics_and_measurements.readonly.health_metrics_and_measurements.writeonly |
ขอบเขตการแจ้งเตือน
ระบบจะส่งการแจ้งเตือนสำหรับข้อมูลประเภทเหล่านี้ก็ต่อเมื่อผู้ใช้ให้ความยินยอมสำหรับขอบเขตที่เกี่ยวข้องอย่างใดอย่างหนึ่งต่อไปนี้
- กิจกรรม ซึ่งครอบคลุมประเภทข้อมูลนาทีที่แอ็กทีฟ จำนวนก้าว ระดับความสูง ระยะทาง และจำนวนชั้น ดังนี้
https://www.googleapis.com/auth/googlehealth.activity_and_fitness.readonlyhttps://www.googleapis.com/auth/googlehealth.activity_and_fitness.writeonly
- ตัวชี้วัดสุขภาพ ซึ่งครอบคลุมประเภทข้อมูลน้ำหนัก
https://www.googleapis.com/auth/googlehealth.health_metrics_and_measurements.readonlyhttps://www.googleapis.com/auth/googlehealth.health_metrics_and_measurements.writeonly
- การนอนหลับ ซึ่งครอบคลุมประเภทข้อมูลการนอนหลับ ดังนี้
https://www.googleapis.com/auth/googlehealth.sleep.readonlyhttps://www.googleapis.com/auth/googlehealth.sleep.writeonly
บัญชีบริการ IAM
แม้ว่าจะไม่จำเป็น แต่เราขอแนะนำให้ใช้บัญชีบริการ IAM เมื่อกำหนดค่าผู้สมัครใช้บริการสำหรับ Google Health API บัญชีบริการช่วยให้ภาระงานของแอปพลิเคชันมีความปลอดภัยมากกว่าบัญชีผู้ใช้มาตรฐานผ่านฟีเจอร์ต่อไปนี้
- ข้อมูลเข้าสู่ระบบแบบอายุสั้นอัตโนมัติ: เมื่อเชื่อมต่อกับสภาพแวดล้อมการดำเนินการของ Google Cloud (เช่น Compute Engine, Cloud Run หรือ Google Kubernetes Engine) บัญชีบริการจะได้รับและหมุนเวียนข้อมูลเข้าสู่ระบบแบบอายุสั้นที่ปลอดภัยโดยอัตโนมัติ ซึ่งจะช่วยลดความเสี่ยงในการจัดการและจัดเก็บคีย์แบบคงที่ถาวร
- หลักการให้สิทธิ์ขั้นต่ำที่สุด: บัญชีบริการจะให้ข้อมูลประจำตัวเฉพาะสำหรับเวิร์กโหลด คุณสามารถให้สิทธิ์เฉพาะที่จำเป็นในการจัดการปลายทางของผู้สมัครใช้บริการเท่านั้น เพื่อหลีกเลี่ยงการเข้าถึงทรัพยากร Google Cloud ในวงกว้าง
- ความเป็นอิสระของวงจร: บัญชีบริการทำงานแยกต่างหากจากบัญชีของผู้ใช้แต่ละราย เพื่อให้มั่นใจว่าการเปลี่ยนแปลงบุคลากรจะไม่ส่งผลต่อความเสถียรของการตรวจสอบสิทธิ์ในระยะยาว
ตั้งค่าบัญชีบริการ
วิธีกำหนดค่าแอปพลิเคชันผู้สมัครใช้บริการเพื่อตรวจสอบสิทธิ์โดยใช้บัญชีบริการมีดังนี้
- สร้างบัญชีบริการ: ในคอนโซล Google Cloud ให้ไปที่หน้า IAM และผู้ดูแลระบบของโปรเจ็กต์เพื่อสร้างบัญชีบริการใหม่ที่จัดการโดยผู้ใช้
- มอบบทบาท IAM ที่จำเป็น: มอบหมายบทบาทที่เหมาะสมให้กับบัญชีบริการที่จำเป็นในการจัดการผู้สมัครใช้บริการในโปรเจ็กต์ที่อยู่ในระบบคลาวด์ Google Cloud
- แนบบัญชีบริการกับภาระงาน: กำหนดค่าสภาพแวดล้อมที่โฮสต์ตรรกะของผู้สมัครใช้บริการให้ทำงานเป็นบัญชีบริการใหม่
ซึ่งจะช่วยให้โค้ดของแอปพลิเคชัน (เช่น ไลบรารีของไคลเอ็นต์ Google API) ตรวจหาและใช้ข้อมูลเข้าสู่ระบบที่มีอายุสั้นของบัญชีบริการโดยอัตโนมัติเมื่อเรียกใช้
projects.subscribersREST API
บทบาท CPE
หากต้องการจัดการผู้สมัครใช้บริการหรือการสมัครใช้บริการ Google Health API คุณต้องให้สิทธิ์บทบาทที่เหมาะสมแก่บัญชีบริการที่แอบอ้างเป็นบุคคลอื่นซึ่งทำการเรียก API มอบหมายบทบาทใดบทบาทหนึ่งต่อไปนี้ โดยขึ้นอยู่กับระดับการเข้าถึงที่ต้องการ
- Google Health API Read
- ผู้แก้ไข Google Health API
- ผู้ดูแลระบบ Google Health API
ดูข้อมูลเพิ่มเติมเกี่ยวกับบทบาทและสิทธิ์ IAM ของ Google Health API
จัดการผู้ติดตาม
ก่อนที่จะรับการแจ้งเตือนได้ คุณต้องลงทะเบียน Subscriber ซึ่งแสดงถึงปลายทางการแจ้งเตือนของแอปพลิเคชัน คุณจัดการผู้สมัครใช้บริการได้โดยใช้ REST API ที่พร้อมใช้งานที่ projects.subscribers
ปลายทางของผู้สมัครใช้บริการต้องใช้ HTTPS (TLSv1.2+) และเข้าถึงได้แบบสาธารณะ
ในระหว่างการสร้างและอัปเดตผู้สมัครใช้บริการ Google Health API จะทำการตรวจสอบเพื่อยืนยันว่าคุณเป็นเจ้าของ URI ปลายทาง หากการยืนยันไม่สำเร็จ การดำเนินการสร้างและอัปเดตผู้สมัครใช้บริการจะล้มเหลวพร้อมกับข้อผิดพลาด FailedPreconditionException
สร้างผู้สมัครใช้บริการ
หากต้องการลงทะเบียนผู้สมัครใช้บริการใหม่สำหรับโปรเจ็กต์ ให้ใช้ปลายทาง create คุณต้องระบุข้อมูลต่อไปนี้
project-id: หมายเลขโปรเจ็กต์ที่สร้างบัญชีบริการเว็บฮุคsubscriberId: ตัวระบุที่ไม่ซ้ำกันซึ่งคุณระบุสำหรับผู้สมัครใช้บริการ รหัสนี้ต้องมีอักขระระหว่าง 4 ถึง 36 ตัว และตรงกับนิพจน์ทั่วไป ([a-z]([a-z0-9-]{2,34}[a-z0-9]))endpointUri: URL ปลายทางสำหรับการแจ้งเตือนเว็บฮุคsubscriberConfigs: ประเภทข้อมูลที่คุณต้องการรับการแจ้งเตือน และนโยบายการสมัครใช้บริการสำหรับแต่ละประเภทendpointAuthorization: กลไกการให้สิทธิ์สำหรับปลายทาง ซึ่งต้องมีsecretที่คุณระบุ ระบบจะส่งค่าของsecretในส่วนหัวAuthorizationพร้อมกับข้อความแจ้งเตือนแต่ละรายการ คุณสามารถใช้โทเค็นนี้เพื่อยืนยันว่าคำขอที่เข้ามามาจาก Google Health API เช่น คุณสามารถตั้งค่าsecretเป็นBearer R4nd0m5tr1ng123สำหรับการตรวจสอบสิทธิ์แบบ Bearer หรือBasic dXNlcjpwYXNzd29yZA==สำหรับการตรวจสอบสิทธิ์พื้นฐาน
ใน subscriberConfigs คุณต้องตั้งค่า subscriptionCreatePolicy สำหรับข้อมูลแต่ละประเภท ตั้งค่าเป็น AUTOMATIC เพื่อใช้การสมัครใช้บริการอัตโนมัติ หรือ MANUAL หากคุณต้องการจัดการการสมัครใช้บริการของผู้ใช้ด้วยตนเอง ดูรายละเอียดเพิ่มเติมเกี่ยวกับแต่ละตัวเลือกได้ที่การสมัครใช้บริการอัตโนมัติและการสมัครใช้บริการด้วยตนเอง
ส่งคำขอ
POST https://health.googleapis.com/v4/projects/project-id/subscribers?subscriberId=subscriber-id
{
"endpointUri": "https://myapp.com/webhooks/health",
"subscriberConfigs": [
{
"dataTypes": ["steps", "altitude", "distance", "floors", "weight"],
"subscriptionCreatePolicy": "AUTOMATIC"
},
{
"dataTypes": ["sleep"],
"subscriptionCreatePolicy": "MANUAL"
}
],
"endpointAuthorization": {
"secret": "Bearer example-secret-token"
}
}คำตอบ
{
"name": "projects/project-id/subscribers/subscriber-id",
"endpointUri": "https://myapp.com/webhooks/health",
"subscriberConfigs": [
{
"dataTypes": ["steps", "altitude", "distance", "floors", "weight"],
"subscriptionCreatePolicy": "AUTOMATIC"
},
{
"dataTypes": ["sleep"],
"subscriptionCreatePolicy": "MANUAL"
}
]
}ผู้ติดตามจากรายการ
ใช้ปลายทาง list เพื่อดึงข้อมูลผู้สมัครใช้บริการทั้งหมดที่ลงทะเบียนไว้สำหรับโปรเจ็กต์ของคุณ
ส่งคำขอ
GET https://health.googleapis.com/v4/projects/project-id/subscribers
คำตอบ
{
"subscribers": [
{
"name": "projects/project-id/subscribers/subscriber-id",
"endpointUri": "https://myapp.com/webhooks/health",
"subscriberConfigs": [
{
"dataTypes": ["steps", "altitude", "distance", "floors", "weight"],
"subscriptionCreatePolicy": "AUTOMATIC"
},
{
"dataTypes": ["sleep"],
"subscriptionCreatePolicy": "MANUAL"
}
],
"endpointAuthorization": {
"authorizationTokenSet": true
}
}
],
"totalSize": 1
}อัปเดตสมาชิก
ใช้ปลายทาง patch เพื่ออัปเดตผู้สมัครใช้บริการในโปรเจ็กต์ ช่องที่อัปเดตได้คือ endpointUri, subscriberConfigs และ endpointAuthorization
คุณอัปเดตช่องได้โดยระบุพารามิเตอร์การค้นหา updateMask และเนื้อหาคำขอ updateMask ต้องมีรายการชื่อช่องที่คั่นด้วยคอมมาซึ่งคุณต้องการอัปเดต โดยใช้การเขียนแบบ Camel Case สำหรับชื่อช่อง (เช่น endpointUri) เนื้อหาคำขอต้องมีออบเจ็กต์ Subscriber บางส่วนที่มีค่าใหม่สำหรับช่องที่ต้องการอัปเดต ระบบจะอัปเดตเฉพาะช่องที่ระบุใน updateMask เท่านั้น หากคุณระบุฟิลด์ในเนื้อหาคำขอที่ไม่ได้อยู่ใน updateMask ระบบจะไม่สนใจฟิลด์ดังกล่าว
หากคุณอัปเดต endpointUri หรือ endpointAuthorization ระบบจะดำเนินการยืนยันปลายทาง โปรดดูรายละเอียดที่หัวข้อการยืนยันปลายทาง
เมื่ออัปเดต subscriberConfigs โปรดทราบว่าจะเป็นการแทนที่ทั้งหมด ไม่ใช่การผสานรวม หาก subscriberConfigs รวมอยู่ใน updateMask การกำหนดค่าที่จัดเก็บไว้ทั้งหมดสำหรับผู้สมัครใช้บริการรายนั้นจะถูกเขียนทับด้วยรายการที่ระบุไว้ในเนื้อหาคำขอ หากต้องการเพิ่มหรือนำการกำหนดค่าออก คุณต้องระบุชุดการกำหนดค่าที่สมบูรณ์ หากคุณกำลังอัปเดตช่องอื่นๆ และต้องการคงการกำหนดค่าปัจจุบันไว้ ให้ละเว้น subscriberConfigs จาก updateMask
ส่งคำขอ
PATCH https://health.googleapis.com/v4/projects/project-id/subscribers/subscriber-id?updateMask=endpointUri
{
"endpointUri": "https://myapp.com/new-webhooks/health"
}คำตอบ
{
"name": "projects/project-id/subscribers/subscriber-id",
"endpointUri": "https://myapp.com/new-webhooks/health",
"subscriberConfigs": [
{
"dataTypes": ["steps", "altitude", "distance", "floors", "weight"],
"subscriptionCreatePolicy": "AUTOMATIC"
},
{
"dataTypes": ["sleep"],
"subscriptionCreatePolicy": "MANUAL"
}
]
}ลบผู้ติดตาม
ใช้ปลายทาง delete เพื่อนำผู้สมัครใช้ออกจากโปรเจ็กต์ เมื่อลบแล้ว ผู้ติดตามจะไม่ได้รับ
การแจ้งเตือนอีกต่อไป
ส่งคำขอ
DELETE https://health.googleapis.com/v4/projects/project-id/subscribers/subscriber-id
คำตอบ
ระบบจะแสดงเนื้อหาการตอบกลับที่ว่างเปล่าพร้อมสถานะ HTTP `200 OK` หากการลบสำเร็จ{}การยืนยันปลายทาง
เพื่อให้มั่นใจว่าการนำส่งการแจ้งเตือนมีความปลอดภัยและเชื่อถือได้ Google Health API จะทำการแฮนด์เชคเพื่อการยืนยันแบบ 2 ขั้นตอนที่จำเป็นทุกครั้งที่คุณสร้างผู้สมัครใช้บริการหรืออัปเดตการกำหนดค่าปลายทาง (endpointUri หรือ endpointAuthorization) กระบวนการนี้จะดำเนินการพร้อมกันระหว่างการเรียก API บริการจะส่งคำขอ POST อัตโนมัติ 2 รายการไปยัง URI ปลายทางของคุณโดยใช้ User Agent Google-Health-API-Webhooks พร้อมเนื้อหา JSON {"type": "verification"}
- Authorized Handshake: ระบบจะส่งคำขอแรกพร้อมส่วนหัว
Authorizationที่คุณกำหนดค่าไว้ เซิร์ฟเวอร์ต้องตอบกลับด้วยสถานะ200 OKหรือ201 Created - การตรวจสอบสิทธิ์ที่ไม่ได้รับอนุญาต: ระบบจะส่งคำขอที่ 2 โดยไม่มีข้อมูลเข้าสู่ระบบ
เซิร์ฟเวอร์ต้องตอบสนองด้วยสถานะ
401 Unauthorizedหรือ403 Forbidden
การแฮนด์เชคนี้เป็นการยืนยันว่าปลายทางของคุณทำงานอยู่และบังคับใช้การรักษาความปลอดภัยอย่างถูกต้อง หากขั้นตอนใดขั้นตอนหนึ่งไม่สำเร็จ คำขอ API จะไม่สำเร็จพร้อมข้อผิดพลาด FAILED_PRECONDITION ระบบจะบันทึกและเปิดใช้งานผู้สมัครใช้บริการเพื่อรับการแจ้งเตือนข้อมูลสุขภาพหลังจากที่การแฮนด์เชคนี้สำเร็จเท่านั้น
การหมุนเวียนคีย์
หากต้องการหมุนเวียนคีย์สำหรับ endpointAuthorization ให้ทำตามขั้นตอนต่อไปนี้
- กำหนดค่าปลายทางให้ยอมรับทั้งค่า
endpointAuthorizationเก่าและใหม่ - อัปเดตการกำหนดค่าผู้ติดตามด้วยค่า
endpointAuthorizationใหม่โดยใช้คำขอpatchที่มี?updateMask=endpointAuthorization - กำหนดค่าปลายทางให้ยอมรับเฉพาะค่า
endpointAuthorizationใหม่หลังจากยืนยันว่าขั้นตอนที่ 2 สำเร็จแล้ว
การสมัครใช้บริการของผู้ใช้
Google Health API ช่วยให้คุณจัดการการสมัครใช้บริการของผู้ใช้ได้อย่างมีประสิทธิภาพ ซึ่งช่วยลดความจำเป็นในการลงทะเบียนด้วยตนเองระหว่างการเตรียมความพร้อมผู้ใช้งานใหม่
การสมัครใช้บริการอัตโนมัติ
เราขอแนะนำให้ใช้การสมัครใช้บริการอัตโนมัติ หากต้องการเปิดใช้ฟีเจอร์นี้ ให้ตั้งค่า subscriptionCreatePolicy เป็น AUTOMATIC ใน subscriberConfigs สำหรับประเภทข้อมูลที่เฉพาะเจาะจง dataTypes ที่คุณระบุด้วยนโยบาย AUTOMATIC เป็นข้อมูลประเภทเดียวกับที่ Google Health API ส่งการแจ้งเตือน โดยต้องได้รับความยินยอมจากผู้ใช้สำหรับข้อมูลประเภทดังกล่าวด้วย
เมื่อผู้ใช้ให้ความยินยอมแก่แอปพลิเคชันสำหรับขอบเขตที่สอดคล้องกับประเภทข้อมูลที่มีนโยบาย AUTOMATIC Google Health API จะติดตามและส่งการแจ้งเตือนสำหรับประเภทข้อมูลที่เกิดจากการตัดกันระหว่างประเภทข้อมูลที่ผู้ใช้ให้ความยินยอมและประเภทข้อมูลการกำหนดค่าผู้สมัครใช้บริการอัตโนมัติสำหรับผู้ใช้รายนั้นโดยอัตโนมัติ จากนั้นระบบจะส่งการแจ้งเตือนไปยังปลายทางของคุณเมื่อใดก็ตามที่ผู้ใช้สร้างข้อมูลใหม่สำหรับประเภทเหล่านั้น ซึ่งจะใช้ได้กับผู้ใช้ที่ให้ความยินยอมก่อนหรือหลังจากที่คุณสร้างผู้สมัครใช้บริการ ระบบจะไม่ทดแทนข้อมูลการแจ้งเตือนที่สร้างขึ้นก่อนที่จะสร้างผู้สมัครใช้บริการ
หากผู้ใช้เพิกถอนความยินยอม การแจ้งเตือนสำหรับประเภทข้อมูลที่เกี่ยวข้องจะหยุดลง การสมัครใช้บริการอัตโนมัติจะจัดการโดย Google และไม่สามารถแสดงหรือลบทีละรายการได้ โดยจะนำออกเมื่อมีการลบผู้สมัครใช้บริการหลักเท่านั้น
การสมัครใช้บริการด้วยตนเอง
หากผู้สมัครใช้บริการของคุณได้รับการกำหนดค่าด้วย subscription_create_policy แบบ MANUAL
สำหรับประเภทข้อมูลที่เฉพาะเจาะจง คุณต้องสร้างและจัดการการสมัครใช้บริการ
สำหรับผู้ใช้แต่ละรายอย่างชัดเจน การสมัครใช้บริการจะลิงก์ผู้ใช้ที่เฉพาะเจาะจงกับปลายทางของผู้สมัครใช้บริการสำหรับชุดประเภทข้อมูลที่กำหนด นักพัฒนาแอปสามารถใช้ API ที่เฉพาะเจาะจงเพื่อดำเนินการต่อไปนี้
- สร้างการสมัครใช้บริการ (ด้วยตนเอง) ต่อ
healthUserId- สร้างการสมัครใช้บริการใหม่สำหรับผู้ใช้ที่ระบุ วิธีนี้กำหนดให้ผู้สมัครใช้บริการต้องตั้งค่าSubscriptionCreatePolicyเป็นMANUALสำหรับประเภทข้อมูลที่ขอ - อัปเดตการสมัครใช้บริการ (ด้วยตนเอง) - อัปเดตประเภทข้อมูลสำหรับการสมัครใช้บริการของผู้ใช้ที่มีอยู่
- ลบการสมัครใช้บริการ (ด้วยตนเอง) - ลบการสมัครใช้บริการของผู้ใช้ที่ระบุ เมื่อลบแล้ว ปลายทางของผู้สมัครใช้บริการจะไม่ได้รับการแจ้งเตือนสำหรับผู้ใช้รายนี้สำหรับประเภทข้อมูลที่เกี่ยวข้องอีกต่อไป
- แสดงรายการการสมัครใช้บริการ (ด้วยตนเอง) - แสดงรายการการสมัครใช้บริการที่ใช้งานอยู่ทั้งหมดสำหรับผู้สมัครใช้บริการที่ระบุ คุณสามารถกรองผลลัพธ์ตามผู้ใช้หรือประเภทข้อมูลได้
การแจ้งเตือน
เมื่อข้อมูลของผู้ใช้มีการเปลี่ยนแปลงสำหรับประเภทข้อมูลที่สมัครใช้บริการ Google Health API จะส่งคำขอ HTTPS POST ไปยัง URL ปลายทางของผู้สมัครใช้บริการ
รูปแบบการแจ้งเตือน
เพย์โหลดการแจ้งเตือนมีรายละเอียดเกี่ยวกับการเปลี่ยนแปลงข้อมูล ซึ่งรวมถึงรหัสผู้ใช้ ประเภทข้อมูล และช่วงเวลา ซึ่งคุณสามารถใช้เพื่อค้นหาข้อมูลที่อัปเดตได้ เมื่อมีการอัปเดตหลายรายการหรือมีการรวมการอัปเดต ระบบจะรวมการแจ้งเตือนเข้าด้วยกันและส่งเป็นอาร์เรย์ JSON ของออบเจ็กต์การแจ้งเตือน
เมื่อมีการเรียกใช้การแจ้งเตือนเว็บฮุค Google Health API จะส่งคำขอ HTTPS POST ไปยังปลายทางของผู้สมัครใช้บริการในรูปแบบต่อไปนี้
Upsert (ข้อมูลอนุกรมเวลา)
POST https://your-endpoint-uri
Authorization: Bearer example-secret-token
GOOGLE-HEALTH-API-SIGNATURE: signature-value
Content-Type: application/json
{
"data": {
"version": "1",
"clientProvidedSubscriptionName": "subscription-name",
"healthUserId": "health-user-id",
"operation": "UPSERT",
"dataType": "steps",
"intervals": [
{
"physicalTimeInterval": {
"startTime": "2026-03-08T01:29:00Z",
"endTime": "2026-03-08T01:34:00Z"
},
"civilDateTimeInterval": {
"startDateTime": {
"date": {
"year": 2026,
"month": 3,
"day": 7
},
"time": {
"hours": 17,
"minutes": 29
}
},
"endDateTime": {
"date": {
"year": 2026,
"month": 3,
"day": 7
},
"time": {
"hours": 17,
"minutes": 34
}
}
},
"civilIso8601TimeInterval": {
"startTime": "2026-03-07T17:29:00",
"endTime": "2026-03-07T17:34:00"
}
}
]
}
}ลบ (ข้อมูลอนุกรมเวลา)
POST https://your-endpoint-uri
Authorization: Bearer example-secret-token
GOOGLE-HEALTH-API-SIGNATURE: signature-value
Content-Type: application/json
[
{
"data": {
"version": "1",
"clientProvidedSubscriptionName": "subscription-name",
"healthUserId": "health-user-id",
"operation": "DELETE",
"dataType": "steps",
"intervals": [
{
"physicalTimeInterval": {
"startTime": "2026-08-12T12:00:00Z",
"endTime": "2026-08-12T12:30:00Z"
},
"civilIso8601TimeInterval": {
"startTime": "2026-08-12T12:00:00",
"endTime": "2026-08-12T12:30:00"
}
}
]
}
}
]ลบ (ข้อมูลที่ระบุตัวบุคคลได้)
POST https://your-endpoint-uri
Authorization: Bearer example-secret-token
GOOGLE-HEALTH-API-SIGNATURE: signature-value
Content-Type: application/json
{
"data": {
"version": "1",
"clientProvidedSubscriptionName": "subscription-name",
"healthUserId": "health-user-id",
"operation": "DELETE",
"dataType": "sleep",
"intervals": [
{
"physicalTimeInterval": {
"startTime": "2026-08-12T22:00:00Z",
"endTime": "2026-08-13T06:00:00Z"
},
"civilIso8601TimeInterval": {
"startTime": "2026-08-12T22:00:00",
"endTime": "2026-08-13T06:00:00"
}
}
],
"recordId": "9875412"
}
}เป็นกลุ่ม (ผู้ใช้หลายคนและประเภทข้อมูลหลายรายการ)
POST https://your-endpoint-uri
Authorization: Bearer example-secret-token
GOOGLE-HEALTH-API-SIGNATURE: signature-value
Content-Type: application/json
[
{
"data": {
"version": "1",
"clientProvidedSubscriptionName": "auto-project-number-subscriber-id-WEBHOOK_DATA_TYPE_STEPS",
"healthUserId": "health-user-id-1",
"operation": "UPSERT",
"dataType": "steps",
"intervals": [
{
"physicalTimeInterval": {
"startTime": "2026-03-08T01:29:00Z",
"endTime": "2026-03-08T01:34:00Z"
},
"civilDateTimeInterval": {
"startDateTime": {
"date": {
"year": 2026,
"month": 3,
"day": 7
},
"time": {
"hours": 17,
"minutes": 29
}
},
"endDateTime": {
"date": {
"year": 2026,
"month": 3,
"day": 7
},
"time": {
"hours": 17,
"minutes": 34
}
}
},
"civilIso8601TimeInterval": {
"startTime": "2026-03-07T17:29:00",
"endTime": "2026-03-07T17:34:00"
}
}
]
}
},
{
"data": {
"version": "1",
"clientProvidedSubscriptionName": "auto-project-number-subscriber-id-WEBHOOK_DATA_TYPE_WEIGHT",
"healthUserId": "health-user-id-1",
"operation": "UPSERT",
"dataType": "weight",
"intervals": [
{
"physicalTimeInterval": {
"startTime": "2026-03-07T15:14:00Z",
"endTime": "2026-03-07T15:16:00Z"
},
"civilDateTimeInterval": {
"startDateTime": {
"date": {
"year": 2026,
"month": 3,
"day": 7
},
"time": {
"hours": 7,
"minutes": 14
}
},
"endDateTime": {
"date": {
"year": 2026,
"month": 3,
"day": 7
},
"time": {
"hours": 7,
"minutes": 16
}
}
},
"civilIso8601TimeInterval": {
"startTime": "2026-03-07T07:14:00",
"endTime": "2026-03-07T07:16:00"
}
}
]
}
},
{
"data": {
"version": "1",
"clientProvidedSubscriptionName": "auto-project-number-subscriber-id-WEBHOOK_DATA_TYPE_STEPS",
"healthUserId": "health-user-id-2",
"operation": "UPSERT",
"dataType": "steps",
"intervals": [
{
"civilDateTimeInterval": {
"startDateTime": {
"date": {
"year": 2026,
"month": 8,
"day": 20
},
"time": {
"hours": 0,
"minutes": 0
}
},
"endDateTime": {
"date": {
"year": 2026,
"month": 8,
"day": 21
},
"time": {
"hours": 0,
"minutes": 0
}
}
},
"civilIso8601TimeInterval": {
"startTime": "2026-08-20T00:00:00",
"endTime": "2026-08-21T00:00:00"
}
}
]
}
},
{
"data": {
"version": "1",
"clientProvidedSubscriptionName": "subscription-name",
"healthUserId": "health-user-id-2",
"operation": "UPSERT",
"dataType": "sleep",
"intervals": [
{
"physicalTimeInterval": {
"startTime": "2026-08-12T22:00:00Z",
"endTime": "2026-08-13T06:00:00Z"
},
"civilDateTimeInterval": {
"startDateTime": {
"date": {
"year": 2026,
"month": 8,
"day": 12
},
"time": {
"hours": 22,
"minutes": 0
}
},
"endDateTime": {
"date": {
"year": 2026,
"month": 8,
"day": 13
},
"time": {
"hours": 6,
"minutes": 0
}
}
},
"civilIso8601TimeInterval": {
"startTime": "2026-08-12T22:00:00",
"endTime": "2026-08-13T06:00:00"
}
}
],
"recordId": "9875412"
}
}
]ช่อง operation จะระบุประเภทการเปลี่ยนแปลงที่ทริกเกอร์การแจ้งเตือน ดังนี้
UPSERT: ส่งเมื่อมีการเพิ่มหรือแก้ไขข้อมูลDELETE: ส่งเมื่อผู้ใช้ลบข้อมูลอย่างชัดแจ้ง (เช่น การลบdataPointsโดยใช้แอป Fitbit หรือการลบแบบกลุ่มโดยใช้ API) ระบบจะไม่ส่งการแจ้งเตือน Webhook สำหรับเหตุการณ์การลบระดับระบบ เช่น ผู้ใช้เพิกถอนสิทธิ์ของแอปพลิเคชันหรือลบบัญชี Fitbit
เราขอแนะนำให้ทำให้ตรรกะการจัดการการแจ้งเตือนเป็นแบบ Idempotent โดยเฉพาะสำหรับการดำเนินการ UPSERT เนื่องจากการลองใหม่อาจทำให้ระบบส่งการแจ้งเตือนซ้ำ
ช่อง clientProvidedSubscriptionName เป็นตัวระบุที่ไม่ซ้ำกัน ดังนี้
- สำหรับการสมัครใช้บริการที่มีนโยบาย
MANUALช่องนี้จะมีชื่อการสมัครใช้บริการแบบถาวรที่นักพัฒนาแอปเป็นผู้ระบุเมื่อสร้างการสมัครใช้บริการ ซึ่งจะให้รหัสที่เสถียรสำหรับการจัดการการสมัครใช้บริการด้วยตนเอง - สำหรับการสมัครใช้บริการที่สร้างขึ้นด้วยนโยบาย
AUTOMATICGoogle Health API จะสร้างและกำหนดตัวระบุในรูปแบบauto-<project-number>-<subscriber-id>-<WEBHOOK_DATA_TYPE_TOKEN>โดยอัตโนมัติ โดยมีรายละเอียดดังนี้<project-number>คือหมายเลขโปรเจ็กต์ Google Cloud ของนักพัฒนาแอป (เช่น362978535920)<subscriber-id>คือรหัสการลงทะเบียนของผู้สมัครใช้บริการ / ชื่อผู้สมัครใช้บริการ (เช่นgoogle-health-sync)<WEBHOOK_DATA_TYPE_TOKEN>คือโทเค็นที่แสดงถึงประเภทข้อมูลที่เฉพาะเจาะจง ดูโทเค็นที่เป็นไปได้ทั้งหมดในคำศัพท์ของโทเค็นประเภทข้อมูลเว็บฮุค
การรวม clientProvidedSubscriptionName สำหรับทั้งนโยบายแบบแมนนวลและแบบอัตโนมัติจะช่วยให้มั่นใจได้ว่ารูปแบบเพย์โหลดการแจ้งเตือนจะสอดคล้องกันในทุกประเภทการสมัครใช้บริการ
การแมปรหัสผู้ใช้
healthUserId คือตัวระบุ Google Health API สำหรับผู้ใช้ที่มีการเปลี่ยนแปลงข้อมูล หากแอปพลิเคชันรองรับผู้ใช้หลายคน คุณจะได้รับการแจ้งเตือนสำหรับผู้ใช้ที่ให้ความยินยอมแก่แอปพลิเคชันของคุณ เมื่อได้รับการแจ้งเตือน ให้ใช้ healthUserId เพื่อระบุว่าข้อมูลของผู้ใช้รายใดมีการเปลี่ยนแปลง เพื่อให้คุณใช้ข้อมูลเข้าสู่ระบบ OAuth ของผู้ใช้รายนั้นเพื่อค้นหาข้อมูลได้
หากต้องการจับคู่ข้อมูลเข้าสู่ระบบ OAuth ของผู้ใช้กับ healthUserId ให้ใช้ปลายทาง getIdentity เรียกปลายทางนี้ด้วยข้อมูลเข้าสู่ระบบของผู้ใช้ในระหว่างการเตรียมความพร้อมผู้ใช้งานใหม่เพื่อดึงข้อมูล healthUserId และจัดเก็บการแมปนี้ การแมปนี้จะไม่เปลี่ยนแปลงเมื่อเวลาผ่านไป จึงแคชได้โดยไม่มีกำหนด ดูตัวอย่างได้ที่รับรหัสผู้ใช้ ซึ่งจะช่วยให้คุณเลือกข้อมูลเข้าสู่ระบบของผู้ใช้ที่ถูกต้องเมื่อค้นหาข้อมูลตาม healthUserId ในการแจ้งเตือน
ช่วงเวลา
อาร์เรย์ intervals มีออบเจ็กต์อย่างน้อย 1 รายการที่แสดงช่วงเวลาสำหรับข้อมูลที่แก้ไข
| ช่อง | ประเภท | ต้องระบุ | คำอธิบาย |
|---|---|---|---|
physicalTimeInterval |
object |
ไม่ใช่ | ช่วงเวลาจริงตามเวลา UTC ของข้อมูลที่แก้ไข (รูปแบบ YYYY-MM-DDTHH:MM:SSZ) ป้อนข้อมูลสำหรับเมตริกระหว่างวัน ละเว้นสำหรับข้อมูลสรุปรายวันและกิจกรรมตลอดทั้งวัน |
civilDateTimeInterval |
object |
ใช่ | วันที่และช่วงเวลาตามปฏิทินพลเรือน (ท้องถิ่น) ของข้อมูลที่แก้ไข โดยไม่มีการชดเชยเวลา UTC หรือเขตเวลา |
civilIso8601TimeInterval |
object |
ใช่ | ช่วงเวลาตามเวลาพลเรือน (ท้องถิ่น) ที่แสดงเป็นสตริง ISO 8601 (รูปแบบ YYYY-MM-DDTHH:MM:SS) โดยไม่มีการชดเชยเวลา UTC หรือเขตเวลา |
สำหรับกิจกรรมตลอดทั้งวันและข้อมูลรวมรายวัน ระบบจะละเว้นช่อง physicalTimeInterval ออกจากเพย์โหลดการแจ้งเตือนโดยเจตนา เนื่องจากกิจกรรมตลอดวันจะจัดกลุ่มตามวันที่ตามปฏิทิน และระยะเวลาจริงอาจไม่ถูกต้องเมื่อข้ามเขตเวลา เมื่อประมวลผลกิจกรรมที่จัดขึ้นตลอดทั้งวัน คุณควรใช้ช่อง civilDateTimeInterval หรือ civilIso8601TimeInterval เป็นแนวทางปฏิบัติแนะนำ ดูรายละเอียดเกี่ยวกับวิธีค้นหาจุดข้อมูลเหล่านี้โดยใช้ตัวกรองเวลาพลเรือนได้ที่กรองข้อมูลตามเวลาเริ่มต้นพลเรือนของช่วงเวลา
ต่อไปนี้คือตัวอย่างเพย์โหลดการแจ้งเตือนสำหรับกิจกรรมตลอดทั้งวันซึ่งไม่มีช่อง physicalTimeInterval
{
"data": {
"version": "1",
"clientProvidedSubscriptionName": "auto-503461148219-lindasubscriber-WEBHOOK_DATA_TYPE_STEPS",
"healthUserId": "343864966078399341",
"operation": "UPSERT",
"dataType": "steps",
"intervals": [
{
"civilDateTimeInterval": {
"startDateTime": {
"date": {
"year": 2026,
"month": 7,
"day": 14
},
"time": {}
},
"endDateTime": {
"date": {
"year": 2026,
"month": 7,
"day": 15
},
"time": {}
}
},
"civilIso8601TimeInterval": {
"startTime": "2026-07-14T00:00:00",
"endTime": "2026-07-15T00:00:00"
}
}
]
}
}คำศัพท์ของโทเค็นประเภทข้อมูลเว็บฮุค
เมื่อใช้นโยบาย AUTOMATIC clientProvidedSubscriptionName ที่สร้างขึ้นจะมีโทเค็นส่วนต่อท้าย WEBHOOK_DATA_TYPE_* ที่เป็นตัวพิมพ์ใหญ่รายการใดรายการหนึ่งต่อไปนี้ โดยขึ้นอยู่กับประเภทข้อมูล
| โทเค็นประเภทข้อมูลของเว็บฮุค | ประเภทข้อมูลที่เกี่ยวข้อง |
|---|---|
WEBHOOK_DATA_TYPE_ACTIVE_MINUTES |
active-minutes |
WEBHOOK_DATA_TYPE_ACTIVE_ZONE_MINUTES |
active-zone-minutes |
WEBHOOK_DATA_TYPE_ACTIVITY_LEVEL |
activity-level |
WEBHOOK_DATA_TYPE_ALTITUDE |
altitude |
WEBHOOK_DATA_TYPE_BLOOD_GLUCOSE |
blood-glucose |
WEBHOOK_DATA_TYPE_BODY_FAT |
body-fat |
WEBHOOK_DATA_TYPE_CALORIES_IN_HEART_RATE_ZONE |
calories-in-heart-rate-zone |
WEBHOOK_DATA_TYPE_DAILY_HEART_RATE_VARIABILITY |
daily-heart-rate-variability |
WEBHOOK_DATA_TYPE_DAILY_HEART_RATE_ZONES |
daily-heart-rate-zones |
WEBHOOK_DATA_TYPE_DAILY_OXYGEN_SATURATION |
daily-oxygen-saturation |
WEBHOOK_DATA_TYPE_DAILY_RESPIRATORY_RATE |
daily-respiratory-rate |
WEBHOOK_DATA_TYPE_DAILY_RESTING_HEART_RATE |
daily-resting-heart-rate |
WEBHOOK_DATA_TYPE_DAILY_SLEEP_TEMPERATURE_DERIVATIONS |
daily-sleep-temperature-derivations |
WEBHOOK_DATA_TYPE_DISTANCE |
distance |
WEBHOOK_DATA_TYPE_EXERCISE |
exercise |
WEBHOOK_DATA_TYPE_FLOORS |
floors |
WEBHOOK_DATA_TYPE_HEART_RATE |
heart-rate |
WEBHOOK_DATA_TYPE_HEART_RATE_VARIABILITY |
heart-rate-variability |
WEBHOOK_DATA_TYPE_HEIGHT |
height |
WEBHOOK_DATA_TYPE_HYDRATION_LOG |
hydration-log |
WEBHOOK_DATA_TYPE_NUTRITION_LOG |
nutrition-log |
WEBHOOK_DATA_TYPE_RESPIRATORY_RATE_SLEEP_SUMMARY |
respiratory-rate-sleep-summary |
WEBHOOK_DATA_TYPE_RUN_VO2_MAX |
run-vo2-max |
WEBHOOK_DATA_TYPE_SEDENTARY_PERIOD |
sedentary-period |
WEBHOOK_DATA_TYPE_SLEEP |
sleep |
WEBHOOK_DATA_TYPE_STEPS |
steps |
WEBHOOK_DATA_TYPE_TIME_IN_HEART_RATE_ZONE |
time-in-heart-rate-zone |
WEBHOOK_DATA_TYPE_WEIGHT |
weight |
WEBHOOK_DATA_TYPE_USER_DELETED |
user-deleted (เหตุการณ์ของระบบ) |
WEBHOOK_DATA_TYPE_USER_REVOKED_ACCESS |
user-revoked-access (เหตุการณ์ของระบบ) |
การรวบรวมข้อมูลอัปเดต
Google Health API จะรวมข้อความเข้าด้วยกันเพื่อลดการจราจรของข้อมูลในเครือข่าย ระบบได้รับการกำหนดค่าให้ส่งข้อความสูงสุด 99 ข้อความต่อกลุ่ม ซึ่งจะพุชโดยอัตโนมัติเมื่อพร้อมใช้งาน
เมื่อมีการรวมข้อความเป็นกลุ่ม ระบบจะส่งเพย์โหลดเป็นอาร์เรย์ JSON ที่มีออบเจ็กต์การแจ้งเตือนหลายรายการ โดยกลุ่มเดียวสามารถรวมการอัปเดตสำหรับผู้ใช้หลายรายในข้อมูลที่สมัครใช้บริการหลายประเภท ดูตัวอย่างเพย์โหลดได้ที่ตัวอย่างBatch (ผู้ใช้หลายคนและประเภทข้อมูลหลายรายการ) ในส่วนรูปแบบการแจ้งเตือน
ตอบกลับการแจ้งเตือน
เซิร์ฟเวอร์ของคุณต้องตรวจสอบส่วนหัว Authorization, จัดการแฮนด์เชคการยืนยันปลายทางแบบซิงโครนัส และตอบสนองต่อการแจ้งเตือนการเปลี่ยนแปลงข้อมูลด้วยรหัสสถานะ HTTP 204 No Content ทันที เพื่อหลีกเลี่ยงการหมดเวลา ให้ประมวลผลเพย์โหลดการแจ้งเตือนแบบอะซิงโครนัสหลังจากส่งการตอบกลับ หาก Google Health API ได้รับรหัสสถานะอื่นๆ หรือคำขอหมดเวลา ระบบจะลองส่งการแจ้งเตือนอีกครั้งในภายหลัง
ตัวอย่าง Node.js (Express)
app.post('/webhook-receiver', (req, res) => {
if (req.headers.authorization !== EXPECTED_SECRET) {
return res.status(401).send();
}
if (req.body && !Array.isArray(req.body) && req.body.type === 'verification') {
return res.status(200).send();
}
// 1. Immediately acknowledge the notification batch
res.status(204).send();
// 2. Normalize single-object or batched array notifications and reconcile asynchronously
const notifications = Array.isArray(req.body) ? req.body : [req.body];
setImmediate(async () => {
for (const notification of notifications) {
const { healthUserId, dataType, intervals = [] } = notification.data || {};
console.log(`Update for user ${healthUserId} of type ${dataType}`);
// Query /v4/users/${healthUserId}/dataTypes/${dataType}/dataPoints:reconcile?filter=...
// for each interval in `intervals` (using >= and < comparators; for sleep, filter on
// sleep.interval.end_time or sleep.interval.civil_end_time).
}
});
});
หากต้องการดึงข้อมูลที่อัปเดตสำหรับแต่ละช่วงเวลาที่ได้รับแจ้ง ให้เรียกใช้ปลายทาง reconcile พร้อมกับ filter สำหรับช่วงเวลาของช่วงเวลาดังกล่าว ซึ่งจะกรองช่วงเวลาที่ทับซ้อนกันจากอุปกรณ์ที่เชื่อมต่อออกโดยอัตโนมัติ ดูรายละเอียดและตัวอย่างได้ที่ดูมุมมองที่ปรับยอดแล้วของข้อมูลช่วงเวลา
กลยุทธ์ที่ใช้กันทั่วไปในการอัปเดตฐานข้อมูลหลังจากได้รับการแจ้งเตือนการเปลี่ยนแปลงข้อมูลมี 3 กลยุทธ์ดังนี้
- การจัดคิว (แนะนำ): วางการแจ้งเตือนขาเข้าไว้ในคิวข้อความและประมวลผลการแจ้งเตือนเหล่านั้นนอกคิวตามทรัพยากรระบบ
- การดึงข้อมูลทันที: สั่งให้แบ็กเอนด์เรียกใช้ Google Health API ทันทีเพื่อดึงข้อมูลที่อัปเดตและบันทึกลงในฐานข้อมูล
- การอัปเดตแบบ Lazy: ทำเครื่องหมายระเบียนฐานข้อมูลในเครื่องของผู้ใช้ว่าไม่ถูกต้อง และดึงข้อมูลที่อัปเดตจาก Google Health API เมื่อผู้ใช้เข้าชมแอปพลิเคชันของคุณในครั้งถัดไปเท่านั้น
กลยุทธ์การจัดคิวช่วยให้คุณประมวลผลข้อมูลได้แบบเกือบเรียลไทม์ ขณะเดียวกันก็ยังคงยืดหยุ่นต่อการแจ้งเตือนจำนวนมาก (เช่น หากการหยุดทำงานของบริการทำให้การแจ้งเตือนที่ค้างอยู่ถูกส่งพร้อมกันทั้งหมด) แม้ว่าคุณจะเลือกประมวลผลคิวเหล่านี้ตามกำหนดการแบบกลุ่มที่มีช่วงเวลายาวนาน (เช่น ทุก 3 ชั่วโมง) เพื่อประหยัดทรัพยากรได้ แต่ข้อเสียคือโดยปกติแล้วผู้ใช้คาดหวังว่าจะเห็นข้อมูลอัปเดตแบบเกือบเรียลไทม์
แนวทางปฏิบัติแนะนำ
ทำตามแนวทางปฏิบัติแนะนำต่อไปนี้เพื่อให้มั่นใจว่าการจัดการการอัปเดตข้อมูลเป็นไปอย่างน่าเชื่อถือและมีประสิทธิภาพ
- ใช้ Subscription API: ใช้ Subscription API เพื่อรับการแจ้งเตือนเมื่อผู้ใช้มีข้อมูลใหม่ให้ดาวน์โหลด แทนที่จะใช้ปลายทางแบบโพลลิ่ง
- จัดคิวและประมวลผลการแจ้งเตือนแยกกัน: เมื่อได้รับการแจ้งเตือนการสมัครใช้บริการ ให้จัดคิวและประมวลผลการแจ้งเตือนแยกกันตามทรัพยากรของระบบ ทำให้ปลายทางเว็บฮุคมีขนาดเล็กโดยการรับทราบคำขอทันที
การยืนยันลายเซ็น
เพื่อให้มั่นใจว่าการแจ้งเตือน Webhook เป็นของแท้ เพย์โหลด JSON ดิบของการแจ้งเตือน Webhook ขาออกทุกรายการจะได้รับการลงนามด้วยคีย์ส่วนตัวโดยใช้ PublicKeySign ของ Tink ซึ่งจะให้ลายเซ็นที่เข้ารหัส Base64 ในส่วนหัว HTTP GOOGLE-HEALTH-API-SIGNATURE ในคำขอ คีย์การรับรองเหล่านี้จะหมุนเวียนโดยอัตโนมัติทุก 30 วัน และคีย์เซ็ตสาธารณะอย่างเป็นทางการที่เกี่ยวข้องจะเผยแพร่เป็นไฟล์ JSON ที่ URL ถาวร https://www.gstatic.com/googlehealthapi/webhooks/webhooks_public_keyset.json
วิธียืนยันลายเซ็น
การใช้ Tink (แนะนำ): นักพัฒนาแอปสามารถยืนยันลายเซ็นโดยใช้พริมิทีฟ PublicKeyVerify ของ Tink ดึงข้อมูลชุดคีย์สาธารณะจาก URL ถาวร สร้างอินสแตนซ์ของพรีมิติฟ PublicKeyVerify ด้วยชุดคีย์ และยืนยันส่วนหัว GOOGLE-HEALTH-API-SIGNATURE ที่ถอดรหัสแล้วกับเพย์โหลด JSON ของเว็บฮุคแบบดิบ
การยืนยันด้วยตนเอง (โดยไม่ใช้ Tink): หากนักพัฒนาแอปเลือกที่จะไม่ใช้ Tink นักพัฒนาแอปจะยืนยันลายเซ็นด้วยตนเองได้โดยทำตามขั้นตอนต่อไปนี้
- ถอดรหัส Base64 ส่วนหัว
GOOGLE-HEALTH-API-SIGNATUREเพื่อแยกคำนำหน้า Tink ขนาด 5 ไบต์ (ซึ่งมีคำนำหน้าเวอร์ชันขนาด 1 ไบต์และ keyId ขนาด 4 ไบต์) ออกจากลายเซ็นที่เข้ารหัส DER จริง - ดึงข้อมูลชุดคีย์ JSON จาก https://www.gstatic.com/googlehealthapi/webhooks/webhooks_public_keyset.json
- ค้นหาคีย์ที่ตรงกับ keyId ที่แยกวิเคราะห์แล้ว และถอดรหัส Base64 ในช่องค่า ซึ่งมีบัฟเฟอร์โปรโตคอล EcdsaPublicKey ที่เรียงลำดับแล้ว
- ดึงข้อมูลพิกัด x และ y แบบ Big-Endian (แท็ก Protobuf 3 และ 4) จากเพย์โหลดไบนารีนี้
- สร้างอินสแตนซ์คีย์สาธารณะ ECDSA P-256 มาตรฐานในไลบรารีวิทยาการเข้ารหัสในตัวโดยใช้พิกัด x และ y ที่ดึงมา
- ยืนยันเพย์โหลด JSON ของเว็บฮุกดิบกับลายเซ็น DER ที่ดึงมาโดยใช้อัลกอริทึม SHA-256
สถานะผู้ติดตามและการกู้คืน
หากปลายทางของผู้สมัครใช้บริการไม่พร้อมใช้งานหรือแสดงรหัสสถานะข้อผิดพลาด (รหัสอื่นที่ไม่ใช่ 204) Google Health API จะจัดเก็บการแจ้งเตือนที่รอดำเนินการไว้เป็นเวลาสูงสุด 7 วัน และลองนำส่งอีกครั้งด้วย Exponential Backoff
เมื่อปลายทางกลับมาออนไลน์และตอบกลับด้วย 204 แล้ว API จะส่งข้อความที่ค้างอยู่ซึ่งจัดเก็บไว้โดยอัตโนมัติ ระบบจะทิ้งการแจ้งเตือนที่เก่ากว่า 7 วันและกู้คืนไม่ได้
ข้อผิดพลาดที่พบบ่อย
| รหัสข้อผิดพลาด | ข้อความ | คำอธิบาย | คำแนะนำ |
|---|---|---|---|
| 400 คำขอไม่ถูกต้อง | หมายเลขโปรเจ็กต์ในชื่อทรัพยากรไม่ถูกต้อง | เมื่อลบหรืออัปเดตผู้สมัครใช้บริการโดยใช้รหัสโปรเจ็กต์ที่อยู่ในระบบคลาวด์ของ Google ใน URL คำขอแทนหมายเลขโปรเจ็กต์ ซึ่งจะมีผลกับการสมัครใช้บริการเว็บฮุคที่ใช้ปลายทาง projects.subscribers |
ใช้หมายเลขโปรเจ็กต์ Google Cloud ใน URL คำขอ ไม่ใช่รหัสโปรเจ็กต์ |
| 403 ต้องห้าม | ผู้โทรไม่มีสิทธิ์ | เมื่อสร้างหรือแสดงรายชื่อผู้สมัครใช้บริการโดยใช้รหัสโปรเจ็กต์ Google Cloud ใน URL คำขอแทนหมายเลขโปรเจ็กต์ ซึ่งจะมีผลกับการสมัครใช้บริการเว็บฮุคที่ใช้ปลายทาง projects.subscribers |
ใช้หมายเลขโปรเจ็กต์ Google Cloud ใน URL คำขอ ไม่ใช่รหัสโปรเจ็กต์ |