اشتراک‌های وب‌قلاب

Google Health API به برنامه شما اجازه می‌دهد وقتی داده‌های سلامتی کاربر تغییر می‌کند، اعلان‌های هم‌زمان دریافت کند. به‌جای نظرسنجی برای تغییرات، سرور شما به‌محض دردسترس قرار گرفتن داده‌ها در Google Health API، درخواست HTTPS POST وب‌قلاب را دریافت می‌کند.

انواع داده‌های پشتیبانی‌شده

اعلان‌های Webhook برای انواع داده‌های زیر پشتیبانی می‌شود:

جدول: انواع داده‌های Google Health API با پشتیبانی وب‌قلاب
نوع داده عملیات
دردسترس
حوزه
دقیقه‌های فعال
dataType: active-minutes
filter parameter: active_minutes
نوع گزارش: فاصله زمانی
وضوح ذخیره‌سازی: ۱ دقیقه

دستگاه‌های سازگار

  • Fitbit Air
  • Fitbit Alta
  • Fitbit Alta HR
  • Fitbit Blaze
  • Fitbit Charge 2
  • Fitbit Charge 3
  • Fitbit Flex 2
  • Fitbit Inspire
  • Fitbit Inspire HR
  • Pixel Watch 4
list, reconcile, rollup, dailyRollup .activity_and_fitness.readonly
.activity_and_fitness.writeonly
دقایق محدوده فعالیت
dataType: active-zone-minutes
filter parameter: active_zone_minutes
نوع گزارش: فاصله زمانی
وضوح ذخیره‌سازی: ۱ دقیقه

دستگاه‌های سازگار

list, reconcile, rollup, dailyRollup .activity_and_fitness.readonly
.activity_and_fitness.writeonly
سطح فعالیت
dataType: activity-level
filter parameter: activity_level
نوع گزارش: فاصله زمانی
فهرست، تطبیق دادن .activity_and_fitness.readonly
.activity_and_fitness.writeonly
ارتفاع
dataType: altitude
filter parameter: altitude
نوع گزارش: فاصله زمانی
وضوح ذخیره‌سازی: ۱ دقیقه
list, reconcile, rollup, dailyRollup .activity_and_fitness.readonly
.activity_and_fitness.writeonly
قند خون
dataType: blood-glucose
filter parameter: blood_glucose
نوع گزارش: نمونه
list, get, reconcile, rollup, dailyRollup .health_metrics_and_measurements.readonly
.health_metrics_and_measurements.writeonly
چربی بدن
dataType: body-fat
filter 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-zone
filter parameter: calories_in_heart_rate_zone
نوع گزارش: فاصله زمانی
وضوح ذخیره‌سازی: ۱ دقیقه
rollup, dailyRollup .activity_and_fitness.readonly
.activity_and_fitness.writeonly
تغییرپذیری ضربان قلب روزانه
dataType: daily-heart-rate-variability
filter parameter: daily_heart_rate_variability
نوع ضبط: روزانه

دستگاه‌های سازگار

فهرست، تطبیق دادن .health_metrics_and_measurements.readonly
.health_metrics_and_measurements.writeonly
محدوده‌های ضربان قلب روزانه
dataType: daily-heart-rate-zones
filter parameter: daily_heart_rate_zones
نوع ضبط: روزانه
فهرست، تطبیق دادن .health_metrics_and_measurements.readonly
.health_metrics_and_measurements.writeonly
اشباع اکسیژن روزانه
dataType: daily-oxygen-saturation
filter parameter: daily_oxygen_saturation
نوع ضبط: روزانه

دستگاه‌های سازگار

فهرست، تطبیق دادن .health_metrics_and_measurements.readonly
.health_metrics_and_measurements.writeonly
سرعت تنفس روزانه
dataType: daily-respiratory-rate
filter parameter: daily_respiratory_rate
نوع ضبط: روزانه

دستگاه‌های سازگار

فهرست، تطبیق دادن .health_metrics_and_measurements.readonly
.health_metrics_and_measurements.writeonly
ضربان قلب روزانه در حالت استراحت
dataType: daily-resting-heart-rate
filter parameter: daily_resting_heart_rate
نوع ضبط: روزانه

دستگاه‌های سازگار

فهرست، تطبیق دادن .health_metrics_and_measurements.readonly
.health_metrics_and_measurements.writeonly
انحرافات دمای خواب روزانه
dataType: daily-sleep-temperature-derivations
filter parameter: daily_sleep_temperature_derivations
نوع ضبط: روزانه

دستگاه‌های سازگار

فهرست، تطبیق دادن .health_metrics_and_measurements.readonly
.health_metrics_and_measurements.writeonly
مسافت
dataType: distance
filter parameter: distance
نوع گزارش: فاصله زمانی
وضوح ذخیره‌سازی: ۱ دقیقه

دستگاه‌های سازگار

list, reconcile, rollup, dailyRollup .activity_and_fitness.readonly
.activity_and_fitness.writeonly
ورزش
dataType: exercise
filter parameter: exercise
نوع ضبط: جلسه

دستگاه‌های سازگار

list, get, reconcile, create, update, batchDelete .activity_and_fitness.readonly
.activity_and_fitness.writeonly
طبقات
dataType: floors
filter parameter: floors
نوع گزارش: فاصله زمانی
وضوح ذخیره‌سازی: ۱ دقیقه
reconcile, rollup, dailyRollup .activity_and_fitness.readonly
.activity_and_fitness.writeonly
ضربان قلب
dataType: heart-rate
filter parameter: heart_rate
نوع گزارش: نمونه
وضوح فضای ذخیره‌سازی: ۱ ثانیه

دستگاه‌های سازگار

list, reconcile, rollup, dailyRollup .health_metrics_and_measurements.readonly
.health_metrics_and_measurements.writeonly
تغییرپذیری ضربان قلب
dataType: heart-rate-variability
filter parameter: heart_rate_variability
نوع گزارش: نمونه

دستگاه‌های سازگار

فهرست، تطبیق دادن .health_metrics_and_measurements.readonly
.health_metrics_and_measurements.writeonly
قد
dataType: height
filter parameter: height
نوع گزارش: نمونه
list, get, reconcile, create, update, batchDelete .health_metrics_and_measurements.readonly
.health_metrics_and_measurements.writeonly
گزارش آب‌رسانی
dataType: hydration-log
filter parameter: hydration_log
نوع ضبط: جلسه
list, get, reconcile, rollup, dailyRollup, create, update, batchDelete .nutrition.readonly
.nutrition.writeonly
گزارش تغذیه
dataType: nutrition-log
filter parameter: nutrition_log
نوع ضبط: جلسه

دستگاه‌های سازگار

list, get, reconcile, rollup, dailyRollup, create, update, batchDelete .nutrition.readonly
.nutrition.writeonly
خلاصه اطلاعات خواب سرعت تنفس
dataType: respiratory-rate-sleep-summary
filter parameter: respiratory_rate_sleep_summary
نوع گزارش: نمونه

دستگاه‌های سازگار

فهرست، تطبیق دادن .health_metrics_and_measurements.readonly
.health_metrics_and_measurements.writeonly
اجرای حداکثر اکسیژن مصرفی
dataType: run-vo2-max
filter parameter: run_vo2_max
نوع گزارش: نمونه

دستگاه‌های سازگار

list, reconcile, rollup, dailyRollup .activity_and_fitness.readonly
.activity_and_fitness.writeonly
دوره بی‌تحرکی
dataType: sedentary-period
filter parameter: sedentary_period
نوع گزارش: فاصله زمانی

دستگاه‌های سازگار

list, reconcile, rollup, dailyRollup .activity_and_fitness.readonly
.activity_and_fitness.writeonly
خواب
dataType: sleep
filter parameter: sleep
نوع ضبط: جلسه

دستگاه‌های سازگار

list, get, reconcile, create, update, batchDelete .sleep.readonly
.sleep.writeonly
مراحل
dataType: steps
filter parameter: steps
نوع گزارش: فاصله زمانی
وضوح ذخیره‌سازی: ۱ دقیقه

دستگاه‌های سازگار

list, reconcile, rollup, dailyRollup .activity_and_fitness.readonly
.activity_and_fitness.writeonly
زمان در محدوده ضربان قلب
dataType: time-in-heart-rate-zone
filter parameter: time_in_heart_rate_zone
نوع گزارش: فاصله زمانی
وضوح ذخیره‌سازی: ۱ دقیقه
list, reconcile, rollup, dailyRollup .activity_and_fitness.readonly
.activity_and_fitness.writeonly
وزن
dataType: weight
filter 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.readonly
    • https://www.googleapis.com/auth/googlehealth.activity_and_fitness.writeonly
  • سنجه‌های سلامتی که نوع داده وزن را پوشش می‌دهد:
    • https://www.googleapis.com/auth/googlehealth.health_metrics_and_measurements.readonly
    • https://www.googleapis.com/auth/googlehealth.health_metrics_and_measurements.writeonly
  • خواب، که نوع داده خواب را پوشش می‌دهد:
    • https://www.googleapis.com/auth/googlehealth.sleep.readonly
    • https://www.googleapis.com/auth/googlehealth.sleep.writeonly

حساب‌های سرویس IAM

هرچند الزامی نیست، توصیه می‌کنیم هنگام پیکربندی مشترکین برای Google Health API از حساب سرویس IAM استفاده کنید. حساب‌های خدمات ازطریق ویژگی‌های زیر، امنیت بهتری برای حجم کاری برنامه‌ها درمقایسه با حساب‌های کاربری استاندارد فراهم می‌کنند:

  • اعتبارنامه‌های کوتاه‌مدت خودکارسازی‌شده: وقتی به محیط اجرای Google Cloud (مانند Compute Engine،‏ Cloud Run، یا Google Kubernetes Engine) متصل می‌شوند، حساب‌های سرویس به‌طور خودکار اعتبارنامه‌های امن و کوتاه‌مدت را دریافت و تعویض می‌کنند. این کار خطرات مدیریت و ذخیره کردن کلیدهای ثابت دائمی را ازبین می‌برد.
  • اصل حداقل امتیاز: حساب‌های سرویس هویت‌های اختصاصی برای حجم‌های کاری ارائه می‌دهند. می‌توانید فقط اجازه‌های خاصی را که برای مدیریت نقاط پایانی مشترک لازم است به آن‌ها اعطا کنید و از دسترسی گسترده‌تر به منابع Google Cloud خود جلوگیری کنید.
  • استقلال چرخه حیات: حساب‌های خدماتی مستقل از حساب هر کاربر حقیقی عمل می‌کنند، که این امر تضمین می‌کند تغییرات پرسنل بر پایداری اصالت‌سنجی بلندمدت تأثیر نمی‌گذارد.

راه‌اندازی حساب سرویس

برای پیکربندی برنامه مشترک خود برای اصالت‌سنجی بااستفاده از حساب سرویس:

  1. ایجاد حساب سرویس: در کنسول Google Cloud، به صفحه IAM و «سرپرست» پروژه بروید تا حساب سرویس جدیدی با مدیریت کاربر ایجاد کنید.
  2. اعطای نقش‌های IAM لازم: نقش‌های مناسب را به حساب سرویس اختصاص دهید که برای مدیریت مشترکین در پروژه Google Cloud شما لازم است.
  3. حساب خدمات را به حجم کاری‌تان پیوست کنید: محیط میزبان منطق مشترک را پیکربندی کنید تا به‌عنوان حساب خدمات جدید اجرا شود. این کار به کد برنامه شما (مانند کتابخانه‌های کارخواه Google API) اجازه می‌دهد هنگام فراخوانی projects.subscribers REST API، به‌طور خودکار اعتبارنامه‌های کوتاه‌مدت حساب سرویس را شناسایی و استفاده کند.

نقش‌های CPE

برای مدیریت «مشترکین» یا «اشتراک‌های» Google Health API، باید نقش مناسب را به «حساب سرویس» جعل‌شده که تماس‌های API را برقرار می‌کند اعطا کنید. بسته به سطح دسترسی موردنیاز، یکی از نقش‌های زیر را اختصاص دهید:

  • Google Health API Read
  • ویرایشگر Google Health API
  • Google Health API Admin

درباره اجازه‌ها و نقش‌های IAM در Google Health API بیشتر بدانید.

مدیریت مشترکان

قبل‌از اینکه بتوانید اعلان دریافت کنید، باید «مشترک» ثبت کنید که نشان‌دهنده نقطه پایانی اعلان برنامه شما است. می‌توانید مشترکین را بااستفاده از REST API موجود در projects.subscribers مدیریت کنید.

نقطه پایانی مشترک شما باید از HTTPS (TLSv1.2+) استفاده کند و به‌طور عمومی دردسترس باشد. درطول ایجاد و به‌روزرسانی مشترک، Google Health API یک چالش درستی‌سنجی انجام می‌دهد تا مطمئن شود شما مالک URI نقطه پایانی هستید. اگر درستی‌سنجی ناموفق باشد، عملیات ایجاد و به‌روزرسانی مشترک با FailedPreconditionException ناموفق خواهد بود.

ایجاد مشترک

برای ثبت مشترک جدید برای پروژه‌تان، از نقطه پایانی create استفاده کنید. باید موارد زیر را ارائه کنید:

  • ‫project-id: شماره پروژه‌ای که حساب سرویس وب‌قلاب در آن ایجاد شده است.
  • subscriberId: شناسه یکتایی که برای مشترک ارائه می‌دهید. این شناسه باید بین ۴ تا ۳۶ نویسه باشد و با عبارت باقاعده ([a-z]([a-z0-9-]{2,34}[a-z0-9])) مطابقت داشته باشد.
  • ‫endpointUri: نشانی وب مقصد برای اعلان‌های وب‌قلاب.
  • subscriberConfigs: انواع داده‌هایی که می‌خواهید برای آن‌ها اعلان دریافت کنید، و خط‌مشی اشتراک برای هرکدام.
  • endpointAuthorization: سازوکار مجوز برای نقطه پایانی شما. این باید حاوی secret باشد که شما ارائه می‌دهید. مقدار secret در سرصفحه Authorization با هر پیام اعلان ارسال می‌شود. می‌توانید از این کد برای تأیید اینکه درخواست‌های ورودی از Google Health API هستند استفاده کنید. برای مثال، می‌توانید secret را روی Bearer R4nd0m5tr1ng123 برای اصالت‌سنجی Bearer، یا Basic dXNlcjpwYXNzd29yZA== برای اصالت‌سنجی Basic تنظیم کنید.

در 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 باید حاوی فهرست جداشده با کاما از نام فیلدهایی باشد که می‌خواهید به‌روز کنید، و برای نام فیلدها از نگارش شتری استفاده کنید (برای مثال، endpointUri). بدنه درخواست باید حاوی شیء «مشترک» جزئی با مقادیر جدید برای فیلدهایی باشد که می‌خواهید به‌روز کنید. فقط فیلدهای مشخص‌شده در 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 هرگاه مشترکی ایجاد کنید یا پیکربندی نقطه پایانی آن را به‌روز کنید (endpointUri یا endpointAuthorization)، یک دست‌دهی درستی‌سنجی دومرحله‌ای اجباری انجام می‌دهد. این فرایند به‌صورت هم‌زمان درطول فراخوانی API انجام می‌شود. این سرویس دو درخواست POST خودکار به URI نقطه پایانی شما ارسال می‌کند، از User-Agent Google-Health-API-Webhooks استفاده می‌کند، و بدنه JSON آن {"type": "verification"} است.

  • دست‌دهی مجاز: اولین درخواست با سرصفحه Authorization پیکربندی‌شده شما ارسال می‌شود. سرور شما باید با وضعیت 200 OK یا 201 Created پاسخ دهد.
  • Unauthorized Challenge: درخواست دوم بدون اطلاعات کاربری ارسال شده است. سرور شما باید با وضعیت 401 Unauthorized یا 403 Forbidden پاسخ دهد.

این دست‌دهی تأیید می‌کند که نقطه پایانی شما فعال است و به‌درستی امنیت را اعمال می‌کند. اگر هرکدام از مراحل ناموفق باشد، درخواست API با خطای FAILED_PRECONDITION ناموفق می‌شود. فقط پس‌از موفقیت‌آمیز بودن این دست‌دهی، مشترک شما ذخیره و فعال می‌شود تا اعلان‌های داده‌های سلامتی را دریافت کند.

چرخش کلید

اگر لازم است کلیدهای endpointAuthorization را بچرخانید، این مراحل را دنبال کنید:

  1. نقطه پایانی‌تان را پیکربندی کنید تا هم مقادیر قدیمی و هم مقادیر جدید endpointAuthorization را بپذیرد.
  2. پیکربندی مشترک را با مقدار endpointAuthorization جدید بااستفاده از درخواست patch با ?updateMask=endpointAuthorization به‌روز کنید.
  3. پس‌از تأیید موفقیت‌آمیز بودن مرحله ۲، نقطه پایانی‌تان را برای پذیرش فقط مقدار جدید endpointAuthorization پیکربندی کنید.

اشتراک‌های کاربر

‫Google Health API به شما کمک می‌کند اشتراک‌های کاربر را به‌طور مؤثر مدیریت کنید و نیاز به ثبت دستی درطول آماده‌سازی کاربر را کاهش دهید.

اشتراک‌های خودکار

توصیه می‌کنیم از اشتراک‌های خودکار استفاده کنید. برای فعال کردن این ویژگی، subscriptionCreatePolicy را روی AUTOMATIC در subscriberConfigs برای انواع داده خاص تنظیم کنید. dataTypes که با خط‌مشی AUTOMATIC مشخص می‌کنید همان نوع داده‌هایی هستند که Google Health API برای آن‌ها اعلان ارسال می‌کند، به‌شرطی که رضایت کاربر نیز برای آن نوع داده‌ها اعطا شده باشد.

وقتی کاربر برای گستره‌هایی که با انواع داده‌های دارای خط‌مشی AUTOMATIC مطابقت دارند رضایت برنامه را اعطا می‌کند، Google Health API به‌طور خودکار انواع داده‌های حاصل از تقاطع بین انواع داده‌های رضایت‌داده‌شده کاربر و انواع داده‌های پیکربندی مشترک خودکار برای آن کاربر را ردیابی می‌کند و برای آن‌ها اعلان ارسال می‌کند. سپس هرگاه آن کاربر داده‌های جدیدی برای آن نوع‌ها تولید کند، اعلان‌ها به نقطه پایانی شما ارسال می‌شود. این روش برای کاربرانی کار می‌کند که قبل یا بعداز ایجاد مشترک، رضایت خود را اعلام می‌کنند. اعلان‌ها برای داده‌های تولیدشده قبل‌از ایجاد مشترک، تکمیل نمی‌شوند.

اگر کاربری رضایتش را لغو کند، اعلان‌های مربوط به انواع داده‌های مربوطه متوقف خواهد شد. اشتراک‌های خودکار توسط Google مدیریت می‌شوند و نمی‌توان آن‌ها را به‌صورت جداگانه فهرست یا حذف کرد؛ این اشتراک‌ها فقط زمانی برداشته می‌شوند که مشترک اصلی حذف شود.

اشتراک‌های دستی

اگر مشترک شما با MANUAL subscription_create_policy برای انواع داده‌های خاص پیکربندی شده است، باید به‌طور صریح اشتراک‌ها را برای هر کاربر ایجاد و مدیریت کنید. «اشتراک» کاربر خاصی را برای مجموعه مشخصی از انواع داده به نقطه پایانی مشترک شما پیوند می‌دهد. توسعه‌دهندگان می‌توانند از میاناهای برنامه‌سازی کاربردی خاصی برای موارد زیر استفاده کنند:

  • ایجاد اشتراک (دستی) برای هر healthUserId - اشتراک جدیدی برای کاربر خاصی ایجاد می‌کند. این روش مستلزم آن است که مشترک SubscriptionCreatePolicy را برای انواع داده‌های درخواست‌شده روی MANUAL تنظیم کرده باشد.
  • به‌روزرسانی اشتراک (دستی) - انواع داده را برای اشتراک کاربر موجود به‌روز می‌کند.
  • حذف اشتراک (دستی) - اشتراک کاربر خاصی را حذف می‌کند. پس‌از حذف، نقطه پایانی مشترک شما دیگر برای این کاربر برای انواع داده‌های مرتبط اعلان دریافت نخواهد کرد.
  • فهرست کردن اشتراک‌ها (غیرخودکار) - همه اشتراک‌های فعال را برای مشترک موردنظر فهرست می‌کند. می‌توانید نتایج را براساس کاربر یا نوع داده فیلتر کنید.

اعلان‌ها

وقتی داده‌های کاربر برای نوع داده مشترک‌شده تغییر می‌کند، Google Health API درخواست HTTPS POST را به نشانی وب نقطه پایانی مشترک ارسال می‌کند.

قالب اعلان

بار داده اعلان حاوی جزئیاتی درباره تغییر داده است، ازجمله شناسه کاربر، نوع داده، و بازه‌های زمانی که می‌توانید از آن‌ها برای جستجوی داده‌های به‌روزشده استفاده کنید. وقتی چند به‌روزرسانی انجام می‌شود یا به‌روزرسانی‌ها تجمیع می‌شوند، اعلان‌ها باهم دسته‌بندی می‌شوند و به‌صورت آرایه 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 یا انجام حذف دسته‌ای بااستفاده از میانای برنامه‌سازی کاربردی). اعلان‌های Webhook برای رویدادهای حذف در سطح سیستم، مانند لغو اجازه‌های برنامه توسط کاربر یا حذف حساب Fitbit، ارسال نمی‌شوند.

توصیه می‌کنیم منطق مدیریت اعلان خود را یکسان‌ساز کنید، به‌ویژه برای عملیات UPSERT، زیرا تلاش‌های مجدد می‌تواند باعث ارسال اعلان‌های تکراری شود.

فیلد clientProvidedSubscriptionName شناسه یکتا است:

  • برای اشتراک‌های دارای خط‌مشی MANUAL، این فیلد حاوی نام اشتراک دائمی ارائه‌شده توسط توسعه‌دهنده است که هنگام ایجاد اشتراک مشخص شده است. این شناسه پایداری برای مدیریت اشتراک‌های دستی ارائه می‌دهد.
  • برای اشتراک‌های ایجادشده با خط‌مشی AUTOMATIC،‏ Google 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 حاوی یک یا چند شیء است که نشان‌دهنده فواصل زمانی برای داده‌های اصلاح‌شده است:

فیلد نوع الزامی شرح
physicalTimeInterval object نه بازه زمانی فیزیکی UTC داده‌های اصلاح‌شده (قالب YYYY-MM-DDTHH:MM:SSZ). برای سنجه‌های درون‌روز پر می‌شود؛ برای خلاصه‌های روزانه و فعالیت‌های کل روز حذف می‌شود.
civilDateTimeInterval object بله تاریخ تقویم مدنی (محلی) و فاصله زمانی داده‌های اصلاح‌شده، بدون ساعت هماهنگ جهانی یا انحراف منطقه زمانی.
civilIso8601TimeInterval object بله بازه زمانی مدنی (محلی) که به‌صورت رشته ISO 8601 (قالب YYYY-MM-DDTHH:MM:SS) بدون ساعت هماهنگ جهانی یا انحراف منطقه زمانی نشان داده می‌شود.

برای فعالیت‌های تمام‌روز و مجموع‌های روزانه، فیلد 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 پیام‌ها را به‌صورت دسته‌ای ارسال می‌کند. سیستم به‌گونه‌ای پیکربندی شده است که حداکثر ۹۹ پیام در هر دسته ارسال کند، که به‌محض دردسترس قرار گرفتن به‌طور خودکار ارسال می‌شوند.

وقتی پیام‌ها دسته‌بندی می‌شوند، بار مفید به‌عنوان آرایه JSON حاوی چند شیء اعلان ارسال می‌شود. یک دسته واحد می‌تواند شامل به‌روزرسانی‌های چند کاربر در چندین نوع داده مشترک‌شده باشد. برای مشاهده نمونه بار داده، به مثال دسته‌ای (چند کاربر و نوع داده) در بخش «قالب اعلان» مراجعه کنید.

پاسخ دادن به اعلان

سرور شما باید سرصفحه 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 را با فیلتر برای محدوده زمانی بازه فراخوانی کنید. این به‌طور خودکار فاصله‌های هم‌پوشان را از دستگاه‌های متصل‌شده حذف می‌کند. برای جزئیات و مثال‌ها، دریافت نمای تطبیق‌داده‌شده از داده‌های بازه را ببینید.

سه راهبرد رایج برای به‌روزرسانی پایگاه داده پس‌از دریافت اعلان تغییر داده وجود دارد:

  • صف‌بندی (توصیه‌شده): اعلان‌های ورودی را در صف پیام قرار دهید و آن‌ها را براساس منابع سیستم خارج از صف پردازش کنید.
  • بازیابی فوری: به باطن خود دستور دهید تا فوراً با Google Health API تماس بگیرد تا داده‌های به‌روزشده را واکشی کند و آن را به پایگاه داده شما ارسال کند.
  • به‌روزرسانی‌های تنبل: سوابق پایگاه داده محلی کاربر را به‌عنوان کثیف علامت‌گذاری کنید و فقط هنگامی که کاربر دفعه بعد از برنامه شما بازدید می‌کند، داده‌های به‌روزشده را از Google Health API واکشی کنید.

راهبرد صف‌بندی به شما امکان می‌دهد داده‌ها را تقریباً به‌طور هم‌زمان پردازش کنید و درعین‌حال دربرابر سیل اعلان‌ها مقاوم بمانید (برای مثال، اگر قطعی سرویس باعث شود که انبوهی از اعلان‌ها به‌طور هم‌زمان ارسال شوند). درحالی‌که می‌توانید برای صرفه‌جویی در منابع، این صف‌ها را در یک برنامه دسته‌ای با فاصله زمانی طولانی (برای مثال، هر ۳ ساعت) پردازش کنید، اشکال این است که کاربران معمولاً انتظار دارند داده‌هایشان را به‌صورت تقریباً هم‌زمان به‌روز ببینند.

روال‌های مطلوب

برای اطمینان از مدیریت قابل‌اعتماد و کارآمد به‌روزرسانی‌های داده، این روال‌های مطلوب را دنبال کنید:

  • استفاده از Subscription API: از Subscription API استفاده کنید تا وقتی کاربر داده‌های جدیدی برای بارگیری دارد، به‌جای نظرسنجی از نقاط پایانی، به شما اطلاع داده شود.
  • اعلان‌ها را به‌طور جداگانه صف‌بندی و پردازش کنید: هنگام دریافت اعلان‌های اشتراک، آن‌ها را در صف قرار دهید و براساس منابع سیستم خود به‌طور جداگانه پردازش کنید. با تأیید فوری درخواست، نقطه پایانی وب‌قلاب را سبک نگه دارید.

درستی‌سنجی امضا

برای اطمینان از اصالت اعلان‌های Webhooks، بار داده JSON خام هر اعلان وب‌قلاب خروجی بااستفاده از PublicKeySign Tink با کلید خصوصی امضا می‌شود و امضای کدگذاری‌شده Base64 را در سرایند HTTP GOOGLE-HEALTH-API-SIGNATURE در درخواست ارائه می‌دهد. این کلیدهای امضا هر ۳۰ روز یک‌بار به‌طور خودکار چرخانده می‌شوند و مجموعه کلیدهای عمومی رسمی مربوطه به‌صورت فایل JSON در نشانی وب دائمی https://www.gstatic.com/googlehealthapi/webhooks/webhooks_public_keyset.json توزیع می‌شود.

نحوه درستی‌سنجی کردن امضا

استفاده از Tink (توصیه‌شده): توسعه‌دهندگان می‌توانند امضا را بااستفاده از PublicKeyVerify اولیه Tink درستی‌سنجی کنند. مجموعه کلید عمومی را از نشانی وب دائمی واکشی کنید، PublicKeyVerify اولیه را با مجموعه کلید نمونه‌سازی کنید، و سرصفحه GOOGLE-HEALTH-API-SIGNATURE رمزگشایی‌شده را دربرابر بار خالص JSON وب‌قلاب خام درستی‌سنجی کنید.

درستی‌سنجی دستی (بدون Tink): اگر توسعه‌دهندگان انتخاب کنند که از Tink استفاده نکنند، می‌توانند با دنبال کردن این مراحل، امضا را به‌صورت دستی درستی‌سنجی کنند:

  1. سرصفحه GOOGLE-HEALTH-API-SIGNATURE را با ۶۴پایه‌ای رمزگشایی می‌کند تا پیشوند ۵ بایتی Tink (که حاوی پیشوند نسخه ۱ بایتی و keyId ۴ بایتی است) را از امضای واقعی کدبندی‌شده با DER جدا کند.
  2. مجموعه کلید JSON را از https://www.gstatic.com/googlehealthapi/webhooks/webhooks_public_keyset.json واکشی کنید.
  3. کلید منطبق با keyId تجزیه‌شده را پیدا کنید و فیلد مقدار آن را که حاوی میان‌گیر پروتکل EcdsaPublicKey سریالی‌شده است، با Base64 رمزگشایی کنید.
  4. مختصات x و y با ترتیب بایت‌های باارزش‌تر (برچسب‌های Protobuf‏ ۳ و ۴) را از این بارداده دودویی استخراج کن.
  5. بااستفاده از مختصات x و y استخراج‌شده، یک کلید عمومی استاندارد ECDSA P-256 را در کتابخانه رمزنگاری داخلی نمونه‌سازی کنید.
  6. پایه‌بار JSON وب‌قلاب خام را بااستفاده از الگوریتم SHA-256 دربرابر امضای DER استخراج‌شده درستی‌سنجی کنید.

وضعیت مشترک و بازیابی

اگر نقطه پایانی مشترک شما دردسترس نباشد یا کد وضعیت خطا برگرداند (هر چیزی غیراز 204)، Google Health API اعلان‌های معلقه را تا ۷ روز ذخیره می‌کند و تحویل را با عقب‌نشینی نمایی دوباره امتحان می‌کند.

وقتی نقطه پایانی‌تان دوباره آنلاین شد و با 204 پاسخ داد، API به‌طور خودکار پیام‌های ذخیره‌شده در صف انتظار را تحویل می‌دهد. اعلان‌های قدیمی‌تر از ۷ روز دور انداخته می‌شوند و قابل‌بازیابی نیستند.

خطاهای رایج

کد خطا پیام شرح توصیه
خطای ۴۰۰ - درخواست نامناسب شماره پروژه در نام منبع نامعتبر است هنگام حذف یا به‌روزرسانی مشترک بااستفاده از شناسه پروژه Google Cloud در نشانی وب درخواست به‌جای شماره پروژه. این مورد برای اشتراک‌های وب‌قلاب که از نقطه پایانی projects.subscribers استفاده می‌کنند اعمال می‌شود. از شماره پروژه Google Cloud در نشانی وب درخواست استفاده کنید، نه شناسه پروژه.
خطای ۴۰۳ - ممنوع است تماس‌گیرنده اجازه ندارد هنگام ایجاد یا فهرست کردن مشترکین بااستفاده از شناسه پروژه Google Cloud در نشانی وب درخواست به‌جای شماره پروژه. این مورد برای اشتراک‌های وب‌قلاب که از نقطه پایانی projects.subscribers استفاده می‌کنند اعمال می‌شود. از شماره پروژه Google Cloud در نشانی وب درخواست استفاده کنید، نه شناسه پروژه.