requestAutocomplete

קחו את הכסף שלי, לא את הזמן שלי

ג'ייק ארצ'יבלד
ג'ייק ארצ'יבלד

מבוא

אני אוהב את האינטרנט. בסך הכול, לדעתי זה רעיון די טוב. לכן אני מעורב בהרבה דיונים באינטרנט לעומת דיונים מקומיים. תוך זמן קצר, האדם הזה מתחיל לדבר על קלות ביצוע התשלומים באמצעות מערכות מקומיות. התגובה הרגילה שלי היא להשליך פצצת עשן ולברוח מהחדר בצחוק מטורף, כי זה לא טיעון שאני יכול לנצח. שיעור הנטישה של עגלת קניות באינטרנט לנייד יכול להגיע עד ל-97%. נסו לדמיין את זה בעולם האמיתי. נניח ש-97% מהאנשים בסופרמרקט, עם עגלה מלאה בדברים שהם רוצים, הופכים את העגלה ויוצאים לטבע. נכון לעכשיו, חלק מהאנשים האלה רק מתמחרים דברים ואף פעם לא הייתה להם כוונה לקנות, אבל חוויית המשתמש האיומה של הקנייה באינטרנט תורמת באופן משמעותי. אנחנו מערערים למשתמשים ומטילים עליהם מס על שפיותם. חשוב על חוויית תשלום נעימה שהייתה לך באינטרנט, במיוחד בנייד. זו חנות אפליקציות, נכון? או לפחות מערכת סגורה דומה שכבר כוללת את פרטי התשלום שלכם. זוהי בעיה. המדיניות דורשת מאתרים להתחייב לספק תשלום מסוים שלמשתמש צריך להיות כבר חשבון ולהיות מחובר אליו, או להתחייב לפלטפורמה שדורשת מהמשתמשים להיות מחוברים לספק תשלום מסוים. אם לא תעשו אחד מהדברים האלה, המטרה של המשתמש היא פשוט להקיש על המסך או על המקלדת שלו עד שכל עור האצבע שלו ייעלם, או עד שיוותר. אנחנו צריכים לפתור את הבעיה.

requestAutocomplete

בעולם של WebGL, WebRTC וממשקי API מיוחדים אחרים לאינטרנט, שמתחילים ב-"אינטרנט", requestAutocomplete נראה לא זוהר. אבל הוא גיבור-על בבגדי בז'. API קטנטן ומשעמם שיכול להיצמד לליבו של ערפד התשלומים באינטרנט.

במקום להסתמך על ספק תשלום מסוים, הוא מבקש את פרטי התשלום מהדפדפן, ששומר אותם בשם המשתמש. גרסת Chrome של requestcomplete() משתלבת גם עם Google Wallet עבור משתמשים בארה"ב בלבד (נכון לעכשיו). נסו את זה באתר הבדיקה שלנו.

form.requestAutocomplete

לרכיבי טופס יש שיטה חדשה אחת - 'השלמה אוטומטית', שמבקשת מהדפדפן למלא את הטופס. הדפדפן יציג למשתמש תיבת דו-שיח שמבקשת הרשאה, ומאפשר לו לבחור אילו פרטים הוא רוצה למסור. לא ניתן להפעיל אותה בכל עת. צריך להפעיל אותה במהלך הביצוע של אירועי אינטראקציה מסוימים, כמו העברת העכבר כלפי מעלה/מטה, לחיצה, מקש ואירועי מגע. זוהי הגבלת אבטחה מכוונת.

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

// TODO: listen for autocomplete events on the form

לפני שנבחן את האירועים, אנחנו צריכים לוודא שהדפדפן מבין את שדות הטופס...

דרישות לגבי טופס

כשהאינטרנט היה בצבעי שחור-לבן, השתמשנו ב-Internet Explorer 5 במאפיין חדש, autocomplete, ברכיבי קלט של טפסים. אפשר להעביר למצב 'מושבת' כדי שהדפדפן לא יציע הצעות, וזה הכול. ה-API הזה הורחב כך שאפשר יהיה לציין את התוכן הצפוי של השדה בלי לשנות את המאפיין 'שם', ובעזרתו requestAutocomplete משתמש כדי לקשר שדות טופס לנתוני משתמשים.

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

לפי המפרט, אין ל-requestAutocomplete אפשרות ספציפית לתשלומים, אבל ההטמעה הנוכחית של Chrome כן היא כמעט.

כרגע ב-Chrome, requestAutocomplete מזהה את הדברים הבאים:

תשלום

  • אימייל
  • cc-name - השם שמופיע בכרטיס
  • מספר עותק – מספר הכרטיס
  • 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> כדי לציין את שדות התפוגה של הכרטיס.

הודעה מפורטת במסוף.
הודעה מפורטת במסוף

כתובת

  • name - שם מלא. הגדרת שם מלא כשדה יחיד עדיפה בהרבה שדות. שדות מרובים, כמו שם פרטי ושם משפחה, מראים הטיה מערבית ועשויה להיות לא הגיונית לתרבויות אחרות. בנוסף, קל יותר להקליד בשדה אחד

  • טלפון - מספר טלפון מלא כולל קידומת מדינה, ניתן גם לפרט

    • tel-country-code - למשל +44
    • tel-national – כל השאר
  • רחוב - כתובת מלאה עם רכיבים מופרדים בפסיקים,

    • שורת כתובת1
    • address-line2 – הכתובת עשויה להיות ריקה
  • רשות מוניציפאלית - עיר/יישוב

  • אזור – קוד מדינה (State), מחוז או קנטון

  • מיקוד - מיקוד

  • country

צריך להשתמש בפרטים שלמעלה בשילוב עם: - חיוב - משלוח

<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 כשהמשתמש לוחץ על לחצן התשלום. חשוב לזכור: כדי להימנע מהאזהרה 'שלד', עליכם להציג את דף עגלת הקניות באמצעות SSL. כדי להתחיל, עלינו להסתיר את לחצן התשלום כדי שהמשתמש לא יוכל ללחוץ עליו עד שנרצה, אבל אנחנו רוצים לעשות זאת רק עבור משתמשים עם 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 חוזר מיד. כדי לבדוק איך זה עובד, אנחנו מקשיבים לכמה אירועים חדשים:

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 Wallet, כך שיהיו נגישים במכשירים אחרים שבהם תתחברו לחשבון. אם תאחסן את הפרטים ב-Wallet, מספר הכרטיס האמיתי שלך לא יטופל על ידי requestAutocomplete, דבר שישפר את האבטחה. אם לא התחברת ל-Chrome או שבחרת לא להשתמש בGoogle Wallet, הפרטים שלך מאוחסנים באופן מקומי בדפדפן לצורך שימוש חוזר. זהו המצב כרגע, אבל בעתיד 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
    });
  });
});