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

جو ميدلي
جو ميدلي

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

تتوافق ميزة "المراسلة عبر السحابة الإلكترونية من Firebase" أو "بروتوكول رسائل السحابة الإلكترونية من Firebase" مع Chrome الآن مع بروتوكول Web Push القياسي، بينما يمكن مصادقة المُرسِل من خلال تنفيذ VAPID، أي أنّ تطبيق الويب لم يعُد بحاجة إلى "gcm_sender_id".

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

توافق "المراسلة عبر السحابة الإلكترونية من Firebase" مع بروتوكول Web Push

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

الآن وبعد أن تتوافق خدمة FCM مع بروتوكول Web Push، يمكنك ترك نقطة النهاية كما هي واستخدام عنوان URL كنقطة نهاية لبروتوكول Web Push. (وبالتالي، يتماشى هذا الأمر مع Firefox، ونأمل أن يساعد كل متصفّح آخر في المستقبل.)

قبل أن نتعمق في VAPID، نحتاج إلى التأكد من أن رمز الخادم يعالج بشكل صحيح نقطة نهاية FCM. فيما يلي مثال على تقديم طلب إلى خدمة Push في Node. تجدر الإشارة إلى أنّه بالنسبة إلى خدمة FCM، نضيف مفتاح واجهة برمجة التطبيقات إلى عناوين الطلبات. وبالنسبة إلى نقاط نهاية الخدمة الفورية الأخرى، لن تحتاج إلى إجراء ذلك. بالنسبة إلى متصفّح Chrome الذي يسبق الإصدار 52، وهو Opera Android ومتصفّح Samsung، لا يزال يتعين عليك أيضًا تضمين 'gcm_sender_id' في ملف البيان.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، يمكنك تجنُّب الخطوات الخاصة بالمراسلة عبر السحابة الإلكترونية من Firebase لإرسال رسالة فورية. لم تعُد بحاجة إلى مشروع Firebase أو عنوان gcm_sender_id أو عنوان Authorization.

العملية بسيطة للغاية:

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

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

إنشاء زوج من المفاتيح العامة/الخاصة

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

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

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

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

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

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

للاشتراك في دفع مستخدم Chrome باستخدام مفتاح VAPID العام، عليك ضبط المفتاح العام على أنّه Uint8Array باستخدام المَعلمة applicationServerKey لطريقة subscription().

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 عادي باستخدام عنوانَي HTTP إضافيين: رأس التفويض ورأس مفتاح التشفير.

رأس التفويض

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

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

<JWTHeader>.<Payload>.<Signature>

عنوان JWT

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

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

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

المحتوى

حمولة البيانات هي كائن JSON آخر يحتوي على ما يلي:

  • الجمهور ("aud")
    • هذا هو أصل خدمة Push (ليس مصدر موقعك). في JavaScript، يمكنك تنفيذ ما يلي لجذب الجمهور: const audience = new URL(subscription.endpoint).origin
  • وقت انتهاء الصلاحية ("exp")
    • هذا هو عدد الثواني المتبقية حتى يتم اعتبار الطلب منتهي الصلاحية. يجب أن يحدث ذلك في غضون 24 ساعة من تقديم الطلب، بالتوقيت العالمي المُنسّق.
  • الموضوع ("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 هذا بعنوان URL base64 ويتشكّل الجزء الثاني من JWT.

التوقيع

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

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

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

WebPush eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJhdWQiOiJodHRwczovL2ZjbS5nb29nbGVhcGlzLmNvbSIsImV4cCI6MTQ2NjY2ODU5NCwic3ViIjoibWFpbHRvOnNpbXBsZS1wdXNoLWRlbW9AZ2F1bnRmYWNlLmNvLnVrIn0.Ec0VR8dtf5qb8Fb5Wk91br-evfho9sZT6jBRuQwxVMFyK5S8bhOjk8kuxvilLqTBmDXJM5l3uVrVOQirSsjq0A

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

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

بالإضافة إلى عنوان "التفويض"، يجب إضافة مفتاح 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 في بيان تطبيق الويب، وستحتاج إلى إضافة عنوان "التفويض" إلى نقطة نهاية "المراسلة عبر السحابة الإلكترونية من Firebase" التي سيتم عرضها.

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