requestAutocomplete

أخذ أموالي، وليس وقتي

جيك أرشيبالد
جيك أرشيبالد

مقدمة

أحبّ الويب. بشكل عام، أعتقد أنها فكرة جيدة جدًا. وبالتالي، أشارك في الكثير من النقاشات حول الويب مقارنةً باللغة الأصلية. لن يحتاج الشخص الآخر إلى وقت طويل لبدء الحديث عن سهولة الدفع من خلال الأنظمة الأصلية. استجابتي المعتادة هي إسقاط قنبلة دخان والهروب من الغرفة وأضحك بجنون، لأنّ هذه ليست حجة يمكنني الفوز بها. يمكن أن يصل معدّل التخلّي عن سلة التسوّق على الويب على الأجهزة الجوّالة إلى%97. تخيل ذلك في العالم الحقيقي. تخيل أنّ 97% من الأشخاص في سوبر ماركت ومعهم عربة مليئة بالأشياء التي يريدونها، يقلبون عربة التسوق ويخرجون. والآن، يكلّف بعض هؤلاء المستخدِمين مبالغ باهظة الثمن ولم يكن لديهم نية الشراء مطلقًا، ولكن تجربة المستخدم المروّعة في الشراء على الويب تساهم بشكل كبير. نحن نفرض ضريبة على المستخدمين في حال السلامة. فكّر في تجربة دفع ممتعة مررت بها على الويب، وخاصةً على الأجهزة الجوّالة. إنه متجر تطبيقات، أليس كذلك؟ أو على الأقل نظام مغلق مشابه يحتوي حاليًا على معلومات الدفع الخاصة بك. هذه مشكلة. وتتطلّب هذه السياسة من المواقع الإلكترونية الالتزام بمقدّم خدمات دفع معيّن يجب أن يكون لدى المستخدم حساب عليه وأن يكون مسجّلاً الدخول إليه، أو الالتزام بمنصة تتطلب تسجيل دخول المستخدمين إلى مقدّم خدمات دفع معيّن، مثل متاجر التطبيقات التي تتطلّب منك إنشاء ترميز لهذه المنصة فقط. وإذا لم تقم بأحد هذه الإجراءات، فمن المألوف أن يضغط المستخدم على الشاشة أو لوحة المفاتيح حتى يختفي كل أصابعه أو يستسلم. نحن بحاجة إلى إصلاح ذلك.

requestAutocomplete

في عالم WebGL و WebRTC وواجهات برمجة تطبيقات الويب الرائعة الأخرى التي تبدأ بكلمة "الويب"، يتميز requestAutocomplete بمظهر غير جذاب. ومع ذلك، فهو بطل خارق في الملابس البيج. واجهة برمجة تطبيقات صغيرة مملة يمكنها أن تتخطى ذاكرتك في قلب مصاصة الوقت في عمليات الدفع على الويب.

وبدلاً من الاعتماد على مقدّم خدمات دفع معيّن، يطلب الموقع الإلكتروني تفاصيل الدفع من المتصفّح الذي يخزّن هذه البيانات نيابةً عن المستخدم. يمكن أيضًا دمج إصدار requestAutocomplete() من Chrome مع "محفظة Google" للمستخدمين في الولايات المتحدة فقط (حاليًا). يمكنك تجربته على موقعنا الإلكتروني التجريبي.

form.requestAutocomplete

تتضمن عناصر النموذج طريقة واحدة جديدة، وهي requestAutocomplete، والتي تطلب من المتصفح ملء النموذج. سيعرض المتصفح مربع حوار للمستخدم الذي يطلب الإذن ويسمح للمستخدم بتحديد التفاصيل التي يريد تقديمها. لا يمكنك طلب هذا الحدث في أي وقت، بل يجب استدعاؤه أثناء تنفيذ أحداث تفاعل معيّنة، مثل الماوس للأعلى أو للأسفل أو النقر أو النقر أو المفاتيح أو اللمس. هذا تقييد أمني متعمد.

button.addEventListener('click', function(event) {
  form.requestAutocomplete();
  event.preventDefault();
});

// TODO: listen for autocomplete events on the form

قبل الاطّلاع على الأحداث، نحتاج إلى التأكّد من أنّ المتصفِّح يفهم حقول النماذج...

متطلبات النموذج

عندما كان اتصال الإنترنت باللونين الأبيض والأسود، اعتمد برنامج Internet Explorer 5 سمة جديدة، autocomplete، في عناصر إدخال النموذج. ويمكن ضبطه على "إيقاف" لإيقاف عرض الاقتراحات في المتصفِّح، وهذا كل ما في الأمر. تم توسيع واجهة برمجة التطبيقات هذه حتى تتمكن من تحديد المحتوى المتوقع للحقل بدون تعديل سمة "الاسم"، وهذا ما يستخدمه requestAutocomplete لربط حقول النموذج ببيانات المستخدمين.

<input name="fullname" autocomplete="name">

من مواصفات المواصفات، لا يقتصر استخدام requestAutocomplete على الدفع، ولكن طريقة التنفيذ الحالية في Chrome هي نفسها. في المستقبل، توقَّع أن تتمكن المتصفحات من التعامل مع أنواع أخرى من البيانات، ونأمل أن تكون تفاصيل تسجيل الدخول، ومنشئ كلمات المرور، ومعلومات جواز السفر، وحتى تحميل صورة رمزية.

تتعرّف ميزة requestAutocomplete في متصفّح Chrome حاليًا على ما يلي:

الدفع

  • بريد إلكتروني
  • cc-name - الاسم على البطاقة
  • رقم cc-number - رقم البطاقة
  • cc-exp-month - شهر انتهاء صلاحية البطاقة كرقمين
  • cc-exp-year - سنة انتهاء صلاحية البطاقة كأربعة أرقام
  • cc-csc - رمز أمان البطاقة المؤلّف من 3 إلى 4 أرقام
<input type="email" autocomplete="email" name="email">
<input type="text" autocomplete="cc-name" name="card-name">
<input type="text" autocomplete="cc-number" name="card-num">
<input type="text" autocomplete="cc-exp-month" name="card-exp-month">
<input type="text" autocomplete="cc-exp-year" name="card-exp-year">
<input type="text" autocomplete="cc-csc" name="card-csc">

سمات "name" التي استخدمتها أعلاه هي أمثلة فقط، وليس هناك حاجة لاستخدام قيم معينة. إذا كنت تريد إعادة استخدام هذا النموذج للمستخدمين الذين ليس لديهم requestAutocomplete، وهو مثال مثالي، ستحتاج إلى إضافة تصنيفات وتخطيط والتحقق الأساسي من HTML5.

غير مقيد على عناصر الإدخال أيضًا، يمكنك استخدام أي نوع من أنواع إدخال النموذج. على سبيل المثال، يمكنك استخدام <select> لحقول انتهاء صلاحية البطاقة.

رسالة مفصّلة من وحدة التحكّم.
رسالة تفصيلية حول وحدة التحكّم

العنوان

  • الاسم - الاسم الكامل. إن أخذ اسم كامل كحقل واحد أفضل بكثير من استخدام حقول متعددة. تُظهر الحقول المتعددة، مثل الاسم الأول واسم العائلة انحيازًا غربيًا، وقد لا تكون منطقية بالنسبة إلى الثقافات الأخرى، كما أنّه من الأسهل كتابتها في حقل واحد.

  • رقم الهاتف - رقم الهاتف الكامل بما في ذلك رمز البلد، يمكن تقسيمه بدلاً من ذلك إلى

    • رمز tel-country - على سبيل المثال، 44+
    • tel-national - الباقي
  • عنوان الشارع - العنوان الكامل مع الفصل بين المكونات بفواصل، ويمكن تقسيمه إلى

    • سطر العنوان1
    • سطر العنوان 2 - قد يكون فارغًا
  • المنطقة المحلية - المدينة/البلدة

  • المنطقة - رمز الولاية أو المقاطعة أو الكانتون

  • الرمز البريدي - الرمز البريدي والرمز البريدي والرمز البريدي

  • بلد

يجب استخدام ما سبق مع: - الفوترة - الشحن

<input type="text" autocomplete="billing name" required name="billing-name">
<input type="tel" autocomplete="billing tel" required name="billling-tel">
<input type="text" autocomplete="billing address-line1" required name="billing-address1">
<input type="text" autocomplete="billing address-line2" required name="billing-address2">
<input type="text" autocomplete="billing locality" required name="billing-locality">
<input type="text" autocomplete="billing region" required name="billing-region">
<input type="text" autocomplete="billing postal-code" required name="billing-postal-code">
<select autocomplete="billing country" required name="billing-country">
  <option value="US">United States</option>
  …
</select>

<input type="text" autocomplete="shipping name" name="shipping-name">
…

مرة أخرى، سمات الاسم هي أمثلة، ويمكنك استخدام ما تريد. بالطبع، لا يجب أن تطلب جميع النماذج عنوان شحن، على سبيل المثال: لا تسألني عن المكان الذي أريد توصيل غرفة الفندق به، فموقعك الجغرافي الحالي غالبًا ما يكون نقطة البيع. حسنًا، لقد حصلنا على النموذج، ونعرف كيفية طلب autocompletion. لكن...

متى يجب طلب ميزة requestAutocomplete؟

من المفترض أن تريد عرض مربّع الحوار requestAutocomplete بدلاً من تحميل الصفحة التي تعرض نموذج الدفع. إذا سارت الأمور على ما يرام، من المفترض ألا يرى المستخدم النموذج على الإطلاق.

مسار الدفعات

أحد الأنماط الشائعة هو أن يكون لديك صفحة سلة تسوق مع زر "الدفع" الذي ينقلك إلى نموذج تفاصيل الدفع. في هذه الحالة، تريد تحميل نموذج الفوترة في صفحة سلة التسوق، مع إخفائه عن المستخدم واستدعاء requestAutocomplete عليه عندما يضغط المستخدم على زر "الدفع". تذكر أنك ستحتاج إلى عرض صفحة سلة التسوق عبر طبقة المقابس الآمنة لتجنب تحذير الهيكل العظمي. للبدء، يجب أن نخفي زر الدفع حتى لا يتمكن المستخدم من النقر عليه إلى أن نصبح جاهزين، ولكنّنا نريد إجراء ذلك فقط للمستخدمين الذين لديهم JavaScript. لذلك، في رأس الصفحة:

<script>document.documentElement.className += ' js';</script>

وفي خدمة مقارنة الأسعار (CSS):

.js #checkout-button,
#checkout-form.for-autocomplete {
  display: none;
}

علينا تضمين نموذج الفوترة في صفحة سلة التسوق. وقد يظهر هذا التصنيف في أي مكان، ولكن يتم التأكّد من أنّ خدمة CSS الواردة أعلاه لا تظهر للمستخدم.

<form id="checkout-form" class="for-autocomplete" action="/checkout" method="post">
  …fields for payment, billing address &amp; shipping if relevant…
</form>

يمكن الآن للغة JavaScript بدء إعداد كل شيء:

function enhanceForm() {
  var button = document.getElementById('checkout-button');
  var form = document.getElementById('checkout-form');

  // show the checkout button
  button.style.display = 'block';

  // exit early if there's no requestAutocomplete support
  if (!form.requestAutocomplete) {
    // be sure to show the checkout button so users can
    // access the basic payment form!
    return;
  }

  button.addEventListener('click', function(event) {
    form.requestAutocomplete();
    event.preventDefault();
  });

  // TODO: listen for autocomplete events on the form
}

يمكنك الاتصال بـ "enhanceForm" على صفحة سلة التسوق، بعد وقت قصير من ظهور نموذج الدفع والزر الخاص بك. ستحصل المتصفحات التي تتوافق مع requestAutocomplete على التجربة السريعة الجديدة والرائعة، وستعود المتصفّحات الأخرى إلى استخدام طريقة الدفع العادية. وللحصول على نقاط إضافية، قد تحتاج إلى تحميل تنسيق HTML للنموذج من خلال XHR كجزء من enhanceForm. وهذا يعني أنّه لا يمكنك تحميل النموذج إلا من خلال المتصفّحات المتوافقة مع requestAutocomplete، وأنّك لست بحاجة إلى إضافة النموذج إلى كل صفحة يمكنك الاتصال بـ enhanceForm منها. هذه هي الطريقة التي يعمل بها الموقع الإلكتروني التجريبي.

لقد اتصلت بـ requestAutocomplete، فماذا بعد؟

عملية الإكمال التلقائي غير متزامنة، ويتم الرجوع إلى requestAutocomplete على الفور. لمعرفة كيف سارت الأمور، نستمع إلى حدثين جديدين:

form.addEventListener('autocomplete', function() {
  // hurrah! You got all the data you needed
});

form.addEventListener('autocompleteerror', function(event) {
  if (event.reason == 'invalid') {
    // the form was populated, but it failed html5 validation
    // eg, the data didn't match one of your pattern attributes
  }
  else if (event.reason == 'cancel') {
    // the user aborted the process
  }
  else if (event.reason == 'disabled') {
    // the browser supports requestAutocomplete, but it's not
    // available at this time. Eg, it wasn't called from an
    // interaction event or the page is insecure
  }
});

إذا نجحت جميع الخطوات، يمكنك إجراء أي شيء تريده باستخدام البيانات، وأبسط ما يمكنك فعله هو إرسال النموذج. يمكن للخادم حينئذٍ التحقق من صحة البيانات ومنح المستخدم صفحة تأكيد تتضمن تكلفة التسليم. إذا كانت البيانات غير صالحة، يمكنك عرض النموذج وتمييز الحقول التي يحتاج المستخدم إلى تعديلها. وبدلاً من ذلك، يمكنك إرسال النموذج والسماح لعملية التحقق العادية من جهة الخادم بالمسؤولية. إذا ألغى المستخدم العملية، فلن تحتاج إلى اتخاذ أي إجراء. إذا تم إيقاف الميزة، يمكنك إرسال المستخدم إلى النموذج العادي. لذلك في معظم الحالات، سيبدو المستمعون مثل...

form.addEventListener('autocomplete', function() {
  form.submit();
});

form.addEventListener('autocompleteerror', function(event) {
  if (event.reason == 'invalid') {
    form.submit();
  }
  else if (event.reason != 'cancel') {
    window.location = '/checkout-page/';
  }
});

أين يخزِّن المتصفح بياناتي؟

لا تحدد المواصفات مكان تخزين البيانات، مما يسمح للمتصفحات بالابتكار. إذا كنت مسجّلاً الدخول إلى متصفِّح Chrome، يمكنك تخزين التفاصيل في "محفظة Google" مع إتاحة الوصول إليها على الأجهزة الأخرى التي سجّلت الدخول إليها. في حال حفظ التفاصيل في "محفظة Google"، لن يتم التعامل مع رقم بطاقتك الحقيقي بحلول "requestAutocomplete"، ما يعزّز مستوى الأمان. إذا لم تكن مسجّلاً الدخول إلى Chrome أو اخترت عدم استخدام "محفظة Google"، سيتم تخزين بياناتك اختياريًا في المتصفّح لإعادة استخدامها. هذا هو الوضع الحالي، ولكن قد يعتمد Chrome والمتصفّحات الأخرى في المستقبل مقدّمي خدمات دفع إضافيين.

تسهيل عمليات الدفع

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

جولة إضافية: التعامل مع النماذج المتعددة الصفحات

من الأفضل الاتصال برقم requestAutocomplete مرة واحدة وجمع كل البيانات التي تحتاج إليها. إذا لم يكن بإمكانك تعديل خادمك لتلقّي جميع هذه البيانات في آنٍ واحد، لا بأس في إخراج البيانات من النموذج المكتمل وإرسالها، على الرغم من ذلك الأنسب لك. يمكنك استخدام هذه الدالة الصغيرة والرائعة لالتقاط جميع البيانات المتوافقة حاليًا ككائن بسيط، بدون الحاجة إلى إنشاء نموذج بنفسك. بعد حصولك على البيانات، يمكنك التحويل إلى التنسيق الذي يحتاجه الخادم، ونشره في خطوات متعددة.

checkoutButton.addEventListener('click', function() {
  requestUserData({
    billing: true,
    shipping: true
  }, function(response) {
    if (response.err == 'cancel') {
      // exit silently
      return;
    }
    if (response.err) {
      // fall back to normal form
      window.location.href = '/normal-checkout-form/';
      return;
    }

    // the rest is just made-up pseudo code as an example
    postToServer(data.shipping).then(function() {
      return postToServer(data.billing);
    }).then(function() {
      return postToServer(data.cc);
    }).catch(function() {
      // handle error
    });
  });
});