مرات الفوز بإمكانية التشغيل التفاعلي للدفع على الويب

عندما كان Chrome يتيح استخدام واجهة برمجة التطبيقات Web Push API لأول مرة، كان يعتمد على خدمة المراسلة عبر السحابة الإلكترونية Firebase ‏ (FCM)، التي كانت تُعرف سابقًا باسم Google Cloud Messaging ‏ (GCM). هذا الإجراء مطلوب باستخدام واجهة برمجة تطبيقات خاصة بها. سمح ذلك لمتصفّح Chrome بإتاحة Web Push API للمطوّرين في وقت كان لا يزال فيه يتم كتابة مواصفات Web Push Protocol، كما وفّر في وقت لاحق المصادقة (أي أنّ مُرسِل الرسالة هو الشخص الذي يُزعم أنّه هو) في وقت لم يكن فيه Web Push Protocol متوفّرًا. خبر سار: لم يعُد أيّ منهما صحيحًا.

تتيح FCM / GCM وChrome الآن بروتوكول Web Push القياسي، بينما يمكن مصادقة المُرسِل من خلال تنفيذ VAPID، مما يعني أن تطبيق الويب لم يعد بحاجة إلى 'gcm_sender_id'.

في هذه المقالة، سأوضّح أولاً كيفية تحويل رمز السيرفر الحالي لاستخدام Web Push Protocol مع FCM. بعد ذلك، سأوضّح لك كيفية تنفيذ VAPID في كلّ من رمز العميل والخادم.

تتوافق خدمة "إشعارات Google من خادم Firebase" مع بروتوكول Web Push Protocol

لنبدأ ببعض السياق. عندما يسجّل تطبيق الويب اشتراكًا في إعلام فوري، يتم منحه عنوان URL لخدمة الإشعارات الفورية. سيستخدم الخادم نقطة النهاية هذه لإرسال البيانات إلى المستخدم من خلال تطبيق الويب. وفي Chrome، سيتم منحك نقطة نهاية للمراسلة عبر السحابة الإلكترونية من Firebase في حال اشتراك مستخدم بدون VAPID. (سنتناول معيار VAPID لاحقًا). قبل أن يتيح إطار عمل Firebase Cloud Messaging بروتوكول Web Push، كان عليك استخراج رقم تعريف تسجيل FCM من نهاية عنوان URL ووضعه في العنوان قبل إرسال طلب إلى واجهة برمجة التطبيقات في FCM. على سبيل المثال، سيكون لنقطة نهاية FCM لعنوان https://android.googleapis.com/gcm/send/ABCD1234، رقم تعريف التسجيل بـ "ABCD1234".

بما أنّ منصة "إرسال الرسائل إلى الأجهزة الجوّالة من Google" تتيح الآن استخدام Web Push Protocol، يمكنك إبقاء نقطة النهاية سليمة واستخدام عنوان URL كنقطة نهاية لـ Web Push Protocol. (يتوافق ذلك مع Firefox ونأمل أن يكون متوافقًا مع جميع المتصفّحات المستقبلية).

قبل التعمق في VAPID، نحتاج إلى التأكد من أن رمز الخادم يتعامل بشكل صحيح مع نقطة نهاية FCM. في ما يلي مثال على تقديم طلب إلى خدمة دفع في Node. يُرجى العلم أنّنا نضيف مفتاح واجهة برمجة التطبيقات إلى عناوين طلبات المراسلة عبر السحابة الإلكترونية من Firebase. ولن يكون ذلك ضروريًا لنقاط نهاية خدمة الإرسال الفوري الأخرى. بالنسبة إلى الإصدارات الأقدم من Chrome قبل الإصدار 52، وOpera Android ومتصفّح Samsung، عليك أيضًا تضمين "gcm_sender_id" في ملف manifest.json الخاص بتطبيق الويب. يتم استخدام مفتاح واجهة برمجة التطبيقات ومقدِّم الرسالة للتحقق مما إذا كان الخادم الذي يقدّم الطلبات مسموحًا له فعلاً بإرسال الرسائل إلى المستخدم المستلِم.

const headers = new Headers();
// 12-hour notification time to live.
headers.append('TTL', 12 * 60 * 60);
// Assuming no data is going to be sent
headers.append('Content-Length', 0);

// Assuming you're not using VAPID (read on), this
// proprietary header is needed
if(subscription.endpoint
    .indexOf('https://android.googleapis.com/gcm/send/') === 0) {
    headers.append('Authorization', 'GCM_API_KEY');
}

fetch(subscription.endpoint, {
    method: 'POST',
    headers: headers
})
.then(response => {
    if (response.status !== 201) {
    throw new Error('Unable to send push message');
    }
});

تذكَّر أنّ هذا تغيير في واجهة برمجة التطبيقات لـ FCM / GCM، لذا لا تحتاج إلى تعديل الاشتراكات، ما عليك سوى تغيير رمز الخادم لتحديد الرؤوس كما هو موضّح أعلاه.

تقديم بروتوكول VAPID لتحديد الخادم

VAPID هو الاسم المختصر الجديد والرائع لـ "التعريف لخادم التطبيقات التطوعي". تحدِّد هذه المواصفة الجديدة بشكل أساسي عملية بدء الاتصال بين خادم التطبيق وخدمة الدفع العميق، وتسمح لخدمة الدفع العميق بتأكيد الموقع الإلكتروني الذي يرسل الرسائل. باستخدام VAPID، يمكنك تجنُّب الخطوات الخاصة بـ FCM لإرسال رسالة فورية. لن تحتاج بعد الآن إلى مشروع على Firebase أو gcm_sender_id أو عنوان Authorization.

العملية بسيطة جدًا:

  1. ينشئ خادم التطبيقات زوجًا من مفاتيح التشفير العامة/الخاصة. يتم منح المفتاح العام لتطبيق الويب.
  2. عندما يختار المستخدم تلقّي إشعارات فورية، أضِف المفتاح العام إلى عنصر خيارات طلب الاشتراك (subscribe() ).
  3. عندما يُرسِل خادم تطبيقك رسالة دفع، أدرِج رمز JSON مميّزًا للويب موقّعًا مع المفتاح العام.

لنلقِ نظرة على هذه الخطوات بالتفصيل.

إنشاء مفتاحَي تشفير عام/خاص

لا أعرف الكثير عن التشفير، لذا إليك القسم ذي الصلة من المواصفات بشأن تنسيق مفاتيح VAPID العامة/الخاصة:

يجب أن تنشئ خوادم التطبيقات وتحتفظ بزوج مفاتيح توقيع يمكن استخدامه مع التوقيع الرقمي للمنحنى الإهليجي (ECDSA) على منحنى P-256.

يمكنك الاطّلاع على كيفية إجراء ذلك في مكتبة عُقد Web-push:

function generateVAPIDKeys() {
    var curve = crypto.createECDH('prime256v1');
    curve.generateKeys();

    return {
    publicKey: curve.getPublicKey(),
    privateKey: curve.getPrivateKey(),
    };
}

الاشتراك باستخدام المفتاح العام

لاشتراك مستخدم Chrome في خدمة الإرسال الفوري باستخدام المفتاح العام لبروتوكول VAPID، عليك تمرير المفتاح العام كسلسلة Uint8Array باستخدام المَعلمة applicationServerKey في طريقة subscribe()‎.

const publicKey = new Uint8Array([0x4, 0x37, 0x77, 0xfe, . ]);
serviceWorkerRegistration.pushManager.subscribe(
    {
    userVisibleOnly: true,
    applicationServerKey: publicKey
    }
);

يمكنك معرفة ما إذا كان قد تمّت العملية بنجاح من خلال فحص نقطة النهاية في ملف الاشتراك الناتج، وإذا كان المصدر هو fcm.googleapis.com، يعني ذلك أنّه تمّت العملية بنجاح.

https://fcm.googleapis.com/fcm/send/ABCD1234

إرسال رسالة فورية

لإرسال رسالة باستخدام VAPID، عليك إرسال طلب عادي لبروتوكول Web Push Protocol مع رأسَي HTTP إضافيَين: رأس Authorization و رأس Crypto-Key.

عنوان التفويض

يكون عنوان Authorization عبارة عن رمز JSON المميّز للويب (JWT) موقَّع مع "WebPush" أمامه.

رمز JWT هو طريقة لمشاركة عنصر JSON مع طرف ثانٍ بطريقة تسمح للطرف المُرسِل بالتوقيع عليه وللطرف المستلِم بالتحقّق من أنّه من المُرسِل المتوقّع. تتألف بنية JWT من ثلاث سلاسل مشفّرة، يتم ربطها بنقطة واحدة بينها.

<JWTHeader>.<Payload>.<Signature>

عنوان JWT

يحتوي عنوان JWT على اسم الخوارزمية المستخدَمة للتوقيع ونوع الرمز المميّز. بالنسبة إلى VAPID، يجب أن يكون هذا العنوان:

{
    "typ": "JWT",
    "alg": "ES256"
}

بعد ذلك، يتم ترميز عنوان URL باستخدام base64 ويشكّل الجزء الأول من JWT.

الحمولة

"الحمولة" هي عنصر JSON آخر يحتوي على ما يلي:

  • الجمهور ("aud")
    • هذا هو أصل خدمة الإرسال المباشر (ليس أصل موقعك الإلكتروني). في JavaScript، يمكنك تنفيذ ما يلي للحصول على شريحة الجمهور: const audience = new URL(subscription.endpoint).origin
  • وقت انتهاء الصلاحية ("exp")
    • هذا هو عدد الثواني التي يجب أن يُعتبَر فيها الطلب منتهي الصلاحية. يجب أن يتم ذلك في غضون 24 ساعة من تقديم الطلب، بالتوقيت الموحّد العالمي (UTC).
  • الموضوع ("sub")
    • يجب أن يكون الموضوع عنوان URL أو عنوان URL على mailto:. يوفر ذلك نقطة تواصل في حال احتجت خدمة الإرسال الفوري إلى التواصل مع مُرسِل الرسالة.

قد يظهر مثال الحمولة على النحو التالي:

{
    "aud": "http://push-service.example.com",
    "exp": Math.floor((Date.now() / 1000) + (12 * 60 * 60)),
    "sub": "mailto: my-email@some-url.com"
}

يتم ترميز عنصر JSON هذا باستخدام ترميز base64url ويشكّل الجزء الثاني من رمز JWT.

التوقيع

التوقيع هو نتيجة ربط الرأس المرمَّز وحمولة البيانات بنقطة، ثم تشفير النتيجة باستخدام المفتاح الخاص لبروتوكول VAPID الذي أنشأته سابقًا. ويجب إلحاق النتيجة نفسها بالعنوان بنقطة.

لن أعرض نموذج رمز لهذا لأنّ هناك عددًا من المكتبات التي ستأخذ العنوان والحمولة كائنات JSON وستنشئ هذا التوقيع نيابةً عنك.

يتم استخدام رمز JWT الموقَّع كعنوان التفويض مع إضافة "WebPush" في مقدمته، وسيكون على النحو التالي:

WebPush eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJhdWQiOiJodHRwczovL2ZjbS5nb29nbGVhcGlzLmNvbSIsImV4cCI6MTQ2NjY2ODU5NCwic3ViIjoibWFpbHRvOnNpbXBsZS1wdXNoLWRlbW9AZ2F1bnRmYWNlLmNvLnVrIn0.Ec0VR8dtf5qb8Fb5Wk91br-evfho9sZT6jBRuQwxVMFyK5S8bhOjk8kuxvilLqTBmDXJM5l3uVrVOQirSsjq0A

لاحظ بعض الأشياء حول هذا. أولاً، يحتوي عنوان Authorization على الكلمة WebPush، ويجب أن يتبعها مسافة ثم رمز JWT. لاحظ أيضًا النقاط التي تفصل بين عنوان JWT والحمولة والتوقيع.

عنوان مفتاح التشفير

بالإضافة إلى عنوان Authorization، يجب إضافة مفتاحك العام لبروتوكول VAPID إلى عنوان Crypto-Key كسلسلة تم ترميزها باستخدام عنوان URL بترميز Base64 مع إضافة p256ecdsa= قبلها.

p256ecdsa=BDd3_hVL9fZi9Ybo2UUzA284WG5FZR30_95YeZJsiApwXKpNcF1rRPF3foIiBHXRdJI2Qhumhf6_LFTeZaNndIo

عند إرسال إشعار يتضمّن بيانات مشفّرة، سيكون لديك الرأس Crypto-Key، لذا لإضافة مفتاح خادم التطبيقات، ما عليك سوى إضافة فاصلة منقوطة قبل إضافة المحتوى أعلاه، ما يؤدي بدوره إلى الحصول على ما يلي:

dh=BGEw2wsHgLwzerjvnMTkbKrFRxdmwJ5S_k7zi7A1coR_sVjHmGrlvzYpAT1n4NPbioFlQkIrTNL8EH4V3ZZ4vJE;
p256ecdsa=BDd3_hVL9fZi9Ybo2UUzA284WG5FZR30_95YeZJsiApwXKpNcF1rRPF3foIiBHXRdJI2Qhumhf6_LFTeZaN

حقيقة هذه التغييرات

باستخدام VAPID، لم تعُد بحاجة إلى الاشتراك للحصول على حساب على GCM لاستخدام ميزة الإشعارات الفورية في Chrome، ويمكنك استخدام مسار الرمز البرمجي نفسه لإشراك مستخدم وإرسال رسالة إليه في كلّ من Chrome وFirefox. يتوافق كلا التطبيقَين مع المعايير.

تجدر الإشارة إلى أنّه في الإصدار 51 من Chrome والإصدارات الأقدم، ومتصفّح Opera لنظام التشغيل Android ومتصفّح Samsung، سيظل عليك تحديد gcm_sender_id في بيان تطبيق الويب، وستحتاج إلى إضافة عنوان التفويض إلى نقطة نهاية FCM التي سيتم عرضها.

يوفر VAPID منحدرًا خارج النطاق وفقًا لمتطلبات الملكية هذه. في حال تنفيذ VAPID، سيعمل في جميع المتصفحات التي تتيح إرسال إشعارات الدفع على الويب. مع توفّر VAPID في المزيد من المتصفّحات، يمكنك تحديد الوقت المناسب لإلغاء استخدام gcm_sender_id من ملف البيان.

.