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

عندما كان 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 Protocol العادي، ويمكن إثبات هوية المُرسِل من خلال تنفيذ VAPID، ما يعني أنّ تطبيق الويب لم يعُد بحاجة إلى "gcm_sender_id".

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

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

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

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

قبل البدء في استخدام بروتوكول VAPID، علينا التأكّد من أنّ رمز الخادم يعالج بشكلٍ صحيح نقطة نهاية "إشعارات Google لنظام التشغيل Android". في ما يلي مثال على تقديم طلب إلى خدمة دفع في 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 node:

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 من ملف البيان.

.