requestAutocomplete

ใช้เงินของฉัน ไม่ใช่เวลาของฉัน

เจค อาร์ชิบาลด์
เจค อาร์ชิบาลด์

เกริ่นนำ

ฉันชอบเว็บ โดยรวมแล้ว ผมคิดว่าเป็นแนวคิดที่ดีทีเดียว ด้วยเหตุนี้ ฉันจึงมักจะโต้เถียงกันบนเว็บเมื่อเทียบกับคนพื้นเมือง อีกฝ่ายเริ่มพูดเกี่ยวกับความง่ายในการชำระเงินผ่านระบบของระบบในไม่ช้า คำตอบปกติของฉันคือทิ้งระเบิดควันแล้ววิ่งหนีออกจากห้อง แล้วหัวเราะอย่างบ้าคลั่ง เพราะฉันสู้ไม่ได้หรอก การละทิ้งรถเข็นช็อปปิ้งกลางคันในเว็บบนอุปกรณ์เคลื่อนที่อาจสูงถึง 97% ลองนึกภาพในโลกแห่งความเป็นจริง ลองจินตนาการว่า 97% ของผู้ใช้ในซูเปอร์มาร์เก็ตมีรถเข็นที่เต็มไปด้วยสินค้าที่ต้องการ ซึ่งพลิกรถเข็นแล้วเดินออกมา ในตอนนี้ ผู้ใช้บางรายอาจเพียงแค่ตั้งราคาสินค้าและไม่เคยมีความตั้งใจที่จะซื้อ แต่ประสบการณ์ของผู้ใช้ในการซื้อบนเว็บที่เลวร้ายก็ถือเป็นปัจจัยที่สำคัญอย่างยิ่ง เรากำลังคิดภาษีของผู้ใช้ในแง่ความปลอดภัย ลองนึกถึงประสบการณ์การชำระเงินที่น่าพึงพอใจบนเว็บ โดยเฉพาะบนอุปกรณ์เคลื่อนที่ นั่นคือร้านแอปใช่ไหม หรืออย่างน้อยระบบปิดที่คล้ายกันซึ่งมีข้อมูลการชำระเงินของคุณอยู่แล้ว ซึ่งถือเป็นปัญหา เว็บไซต์กำหนดให้เว็บไซต์มีสัญญาผูกมัดกับผู้ให้บริการชำระเงินรายใดรายหนึ่งซึ่งผู้ใช้ต้องมีบัญชีและเข้าสู่ระบบอยู่แล้ว หรือผูกมัดในแพลตฟอร์มที่กำหนดให้ผู้ใช้ต้องเข้าสู่ระบบผู้ให้บริการชำระเงินรายใดรายหนึ่ง เช่น App Storex ที่กำหนดให้คุณต้องเขียนโค้ดสำหรับแพลตฟอร์มนั้นเพียงอย่างเดียว หากคุณไม่ทำอย่างใดอย่างหนึ่ง ผู้ใช้จะถูกบังคับให้แตะหน้าจอหรือแป้นพิมพ์จนกว่าหนังนิ้วจะหมดไป หรือพวกเขายอมแพ้ เราต้องแก้ปัญหานี้

requestAutocomplete

ในโลกของ WebGL นั้น WebRTC และ API ของเว็บที่ซับซ้อนอื่นๆ ที่เริ่มต้นด้วย “Web” requestAutocomplete เป็นเบราว์เซอร์ที่แทบไม่มีประโยชน์ แต่เป็นซูเปอร์ฮีโร่ในชุดสีเบจ API ตัวจิ๋วที่น่าเบื่อซึ่งสามารถปักเดิมพันเป็นหัวใจสำคัญของแวมไพร์ในการชำระเงินบนเว็บได้

แทนที่เว็บไซต์จะต้องพึ่งพาผู้ให้บริการชำระเงินรายใดรายหนึ่ง เว็บไซต์จะขอรายละเอียดการชำระเงินจากเบราว์เซอร์ ซึ่งจัดเก็บไว้ในนามของผู้ใช้ requestAutocomplete() เวอร์ชัน Chrome ยังผสานรวมกับ Google Wallet สำหรับผู้ใช้ในสหรัฐอเมริกาเท่านั้น (ปัจจุบัน) ด้วย ลองใช้เว็บไซต์ทดสอบของเรา

form.requestAutocomplete

องค์ประกอบแบบฟอร์มมีวิธีการใหม่วิธีเดียว ซึ่งก็คือ requestAutocomplete ซึ่งขอให้เบราว์เซอร์เติมข้อมูลในแบบฟอร์ม โดยเบราว์เซอร์จะแสดงกล่องโต้ตอบให้ผู้ใช้ขอสิทธิ์และอนุญาตให้ผู้ใช้เลือกรายละเอียดที่ต้องการระบุ คุณไม่สามารถเรียกใช้ได้ทุกเมื่อที่คุณต้องการ จะต้องมีการเรียกระหว่างการดำเนินการเหตุการณ์การโต้ตอบบางอย่าง เช่น เหตุการณ์การขึ้น/ลงของเมาส์ การคลิก การใช้แป้น และการแตะ นี่เป็นข้อจำกัดด้านความปลอดภัยโดยเฉพาะ

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

// TODO: listen for autocomplete events on the form

ก่อนที่จะดูเหตุการณ์ เราต้องตรวจสอบให้แน่ใจว่าเบราว์เซอร์เข้าใจช่องของแบบฟอร์ม...

ข้อกำหนดของแบบฟอร์ม

ย้อนกลับไปตอนที่อินเทอร์เน็ตเป็นภาพขาวดำ Internet Explorer 5 ได้ใช้แอตทริบิวต์ใหม่ "autocomplete" ในองค์ประกอบอินพุตแบบฟอร์ม ซึ่งอาจตั้งค่าเป็น "ปิด" เพื่อหยุดการเสนอคำแนะนำในเบราว์เซอร์ แค่นี้ก็เรียบร้อย API นี้ได้รับการขยาย เพื่อให้คุณระบุเนื้อหาที่ต้องการของช่องได้โดยไม่ต้องแก้ไขแอตทริบิวต์ “name” และนี่คือสิ่งที่ requestAutocomplete ใช้เพื่อลิงก์ช่องในแบบฟอร์มกับข้อมูลผู้ใช้

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

ตามข้อกำหนด requestAutocomplete ไม่ได้มีไว้สำหรับการชำระเงินโดยเฉพาะ แต่การใช้งานในปัจจุบันของ Chrome ค่อนข้างมาก ในอนาคตคาดหวังว่าเบราว์เซอร์จะสามารถจัดการข้อมูลประเภทอื่นๆ ได้ โดยหวังว่าสิ่งต่างๆ อย่างเช่นรายละเอียดการเข้าสู่ระบบและการสร้างรหัสผ่าน ข้อมูลหนังสือเดินทาง หรือแม้แต่การอัปโหลดรูปโปรไฟล์

ปัจจุบันใน Chrome นั้น requestAutocomplete จะจดจำสิ่งต่อไปนี้:

การชำระเงิน

  • อีเมล
  • ชื่อสำเนา - ชื่อบนบัตร
  • หมายเลข cc - หมายเลขบัตร
  • cc-exp-month - เดือนที่บัตรหมดอายุเป็นตัวเลข 2 หลัก
  • cc-exp-year - ปีที่บัตรหมดอายุเป็นตัวเลข 4 หลัก
  • 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-code - เช่น +44
    • tel-national - ที่เหลือ
  • ที่อยู่ถนน - ที่อยู่แบบเต็มซึ่งมีองค์ประกอบที่คั่นด้วยคอมมา สามารถแยกออกเป็น

    • ที่อยู่บรรทัดที่ 1
    • บรรทัดที่อยู่2 - อาจว่างเปล่า
  • ย่าน - เมือง

  • ภูมิภาค - รหัสรัฐ เขต หรือมณฑล

  • รหัสไปรษณีย์ - รหัสไปรษณีย์ รหัสไปรษณีย์

  • 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 เพื่อหลีกเลี่ยงคำเตือน Skeletor ในตอนเริ่มต้น เราควรซ่อนปุ่มชำระเงินเพื่อไม่ให้ผู้ใช้คลิกได้จนกว่าเราจะพร้อม แต่เราต้องการใช้วิธีนี้สำหรับผู้ใช้ที่มี 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 จะส่งคืนทันที ซึ่งเราได้ฟังเหตุการณ์ใหม่ 2 - 3 เหตุการณ์ต่อไปนี้ เพื่อดูว่าผลที่ได้เป็นอย่างไร

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
    });
  });
});