คู่มือนี้จะอธิบายขั้นตอนการพัฒนาโครงการการดำเนินการที่รวมธุรกรรมสำหรับสินค้าที่จับต้องได้โดยใช้วิธีการชำระเงินที่จัดการโดยเว็บไซต์ของคุณ
ขั้นตอนการทำธุรกรรม
เมื่อโปรเจ็กต์การดำเนินการของคุณจัดการธุรกรรมทางกายภาพโดยใช้การชำระเงินที่จัดการโดยผู้ขาย โปรเจ็กต์จะใช้ขั้นตอนต่อไปนี้
- ลิงก์บัญชีของผู้ใช้ - เพื่อให้ผู้ใช้สามารถใช้วิธีการชำระเงิน ที่บันทึกไว้กับบริการของคุณ ให้ใช้การลิงก์บัญชีเพื่อเชื่อมโยงบัญชี Google กับบัญชีของผู้ใช้ในบริการ
- รวบรวมข้อมูล (ไม่บังคับ) - คุณควรรวบรวมข้อมูลต่อไปนี้จากผู้ใช้ตั้งแต่เนิ่นๆ ของการสนทนา ทั้งนี้ขึ้นอยู่กับลักษณะธุรกรรมของคุณ
- ตรวจสอบข้อกำหนดธุรกรรม - ในตอนต้นของส่วนธุรกรรมของการสนทนา ให้ตรวจสอบว่าผู้ใช้มีคุณสมบัติตรงตามข้อกำหนดในการทำธุรกรรม เช่น มีการกำหนดค่าข้อมูลการชำระเงินอย่างถูกต้องและพร้อมใช้งานก่อนที่จะสร้างรถเข็น
- ขอที่อยู่สำหรับจัดส่ง - หากธุรกรรมต้องใช้ที่อยู่สำหรับนำส่ง ให้รวบรวมที่อยู่จากผู้ใช้
- สร้างคำสั่งซื้อ - พาผู้ใช้ไปดู "ชุดประกอบรถเข็น" ซึ่งจะเลือกสินค้าที่ต้องการซื้อ
- เสนอคำสั่งซื้อ - เมื่อรถเข็นเสร็จสมบูรณ์แล้ว ให้เสนอคำสั่งซื้อแก่ผู้ใช้เพื่อยืนยันว่าถูกต้อง หากคำสั่งซื้อได้รับการยืนยัน คุณจะได้รับการตอบกลับพร้อมรายละเอียดคำสั่งซื้อและโทเค็นการชำระเงิน
- สรุปคำสั่งซื้อและส่งใบเสร็จ - เมื่อยืนยันคำสั่งซื้อแล้ว ให้อัปเดตการติดตามสินค้าคงคลังหรือบริการดำเนินการตามคำสั่งซื้ออื่นๆ จากนั้นส่งใบเสร็จให้ผู้ใช้
- ส่งการอัปเดตคำสั่งซื้อ - ให้การอัปเดตคำสั่งซื้อแก่ผู้ใช้ตลอดระยะเวลาอายุการใช้งานของการดำเนินการตามคำสั่งซื้อโดยส่งคำขอ Patch ไปยัง Orders API
ข้อจำกัดและหลักเกณฑ์การตรวจสอบ
โปรดทราบว่านโยบายเพิ่มเติมมีผลกับการดำเนินการที่มีธุรกรรม เราอาจใช้เวลาถึง 6 สัปดาห์ในการตรวจสอบการดำเนินการที่มีธุรกรรม ดังนั้นโปรดคำนึงถึงเวลาดังกล่าวเมื่อวางแผนกำหนดการเผยแพร่ เพื่อช่วยให้กระบวนการตรวจสอบง่ายขึ้น โปรดตรวจสอบว่าคุณปฏิบัติตามนโยบายและหลักเกณฑ์สำหรับธุรกรรมก่อนส่งการดำเนินการเข้ารับการตรวจสอบ
คุณใช้การดำเนินการที่ขายสินค้าที่จับต้องได้ในประเทศต่อไปนี้เท่านั้น
ออสเตรเลีย บราซิล แคนาดา อินโดนีเซีย |
ญี่ปุ่น เม็กซิโก กาตาร์ รัสเซีย |
สิงคโปร์ สวิตเซอร์แลนด์ ไทย ตุรกี สหราชอาณาจักร สหรัฐอเมริกา |
สร้างโปรเจ็กต์
โปรดดูตัวอย่างการสนทนาเกี่ยวกับธุรกรรมในตัวอย่างธุรกรรมของ Node.js
ตั้งค่าโครงการ
เมื่อสร้างการดำเนินการ คุณต้องระบุว่าคุณต้องการทำธุรกรรมในคอนโซลการดำเนินการ
หากต้องการตั้งค่าโปรเจ็กต์และการดำเนินการตามคำสั่งซื้อ ให้ทำตามขั้นตอนต่อไปนี้
- สร้างโปรเจ็กต์ใหม่หรือนำเข้าโปรเจ็กต์ที่มีอยู่
- ไปที่ทำให้ใช้งานได้ > ข้อมูลไดเรกทอรี
ในส่วนข้อมูลเพิ่มเติม > ธุรกรรม > เลือกช่องที่ระบุว่า "การดำเนินการของคุณใช้ Transaction API ในการทำธุรกรรมสินค้าที่จับต้องได้ไหม"
ลิงก์บัญชีของผู้ใช้ (ไม่บังคับ)
เมื่อใช้วิธีการชำระเงินของคุณเองเพื่อเรียกเก็บเงินจากผู้ใช้ เราขอแนะนำให้ลิงก์บัญชี Google ของผู้ใช้กับบัญชีที่ผู้ใช้มีกับบริการของคุณเอง เพื่อดึงข้อมูล แสดง และเรียกเก็บเงินตามวิธีการชำระเงินที่จัดเก็บไว้
ออกแบบอินเทอร์เฟซผู้ใช้แบบเสียงสำหรับขั้นตอนการตรวจสอบสิทธิ์
ตรวจสอบว่าผู้ใช้ได้รับการยืนยันหรือไม่ และเริ่มขั้นตอนการลิงก์บัญชี
- เปิดโปรเจ็กต์ Actions Builder ในคอนโซล Actions
- สร้างฉากใหม่เพื่อเริ่มลิงก์บัญชีใน Action ของคุณ
- คลิกฉาก
- คลิกไอคอนเพิ่ม (+) เพื่อเพิ่มฉากใหม่
- ในโหมดที่สร้างขึ้นใหม่ ให้คลิกไอคอนเพิ่ม add สำหรับเงื่อนไข
- เพิ่มเงื่อนไขที่ตรวจสอบว่าผู้ใช้ที่เชื่อมโยงกับการสนทนาเป็นผู้ใช้ที่ได้รับการยืนยันหรือไม่ หากการตรวจสอบไม่สำเร็จ การดำเนินการของคุณจะไม่สามารถลิงก์บัญชีในระหว่างการสนทนา และควรกลับไปให้สิทธิ์เข้าถึงฟังก์ชันการทำงานที่ไม่จำเป็นต้องมีการลิงก์บัญชี
- ในช่อง
Enter new expression
ในส่วนเงื่อนไข ให้ป้อนตรรกะต่อไปนี้user.verificationStatus != "VERIFIED"
- ในส่วนการเปลี่ยน ให้เลือกฉากที่ไม่ต้องมีการลิงก์บัญชีหรือฉากที่เป็นจุดเข้าถึงฟังก์ชันการทำงานสำหรับผู้มาเยือนเท่านั้น
- ในช่อง
- คลิกไอคอนเพิ่ม add สำหรับเงื่อนไข
- เพิ่มเงื่อนไขเพื่อทริกเกอร์โฟลว์การลิงก์บัญชีหากผู้ใช้ไม่มีข้อมูลระบุตัวตนที่เชื่อมโยง
- ในช่อง
Enter new expression
ในส่วนเงื่อนไข ให้ป้อนตรรกะต่อไปนี้user.verificationStatus == "VERIFIED"
- ในส่วนการเปลี่ยน ให้เลือกโหมดระบบการลิงก์บัญชี
- คลิกบันทึก
- ในช่อง
เมื่อบันทึกแล้ว ระบบจะเพิ่มโหมดระบบการลิงก์บัญชีใหม่ที่ชื่อว่า <SceneName>_AccountLinking
ลงในโปรเจ็กต์
ปรับแต่งฉากการลิงก์บัญชี
- เลือกโหมดระบบการลิงก์บัญชีในส่วนฉาก
- คลิกส่งพรอมต์ แล้วเพิ่มประโยคสั้นๆ เพื่ออธิบายให้ผู้ใช้ทราบว่าทำไมการดำเนินการจึงจำเป็นต้องเข้าถึงข้อมูลประจำตัว (เช่น "เพื่อบันทึกค่ากำหนดของคุณ")
- คลิกบันทึก
- ในส่วนเงื่อนไข ให้คลิกหากผู้ใช้ลิงก์บัญชีสำเร็จแล้ว
- กำหนดค่าว่าขั้นตอนควรดำเนินการอย่างไรหากผู้ใช้ตกลงที่จะลิงก์บัญชี เช่น เรียกใช้เว็บฮุคเพื่อประมวลผลตรรกะทางธุรกิจที่กำหนดเองที่จำเป็น แล้วเปลี่ยนกลับไปยังฉากที่สร้างขึ้น
- คลิกบันทึก
- คลิกหากผู้ใช้ยกเลิกหรือปิดการลิงก์บัญชีในส่วนเงื่อนไข
- กำหนดค่าว่าขั้นตอนควรดำเนินการอย่างไรหากผู้ใช้ไม่ตกลงที่จะลิงก์บัญชี เช่น ส่งข้อความตอบรับและเปลี่ยนเส้นทางไปยังฉากที่มีฟังก์ชันการทำงานที่ไม่ต้องใช้การลิงก์บัญชี
- คลิกบันทึก
- ในส่วนเงื่อนไข ให้คลิกหากระบบหรือเครือข่ายเกิดข้อผิดพลาด
- กำหนดค่าว่าขั้นตอนควรดำเนินการอย่างไรหากดำเนินการลิงก์บัญชีไม่สำเร็จเนื่องจากข้อผิดพลาดของระบบหรือเครือข่าย เช่น ส่งข้อความตอบรับและเปลี่ยนเส้นทางไปยังฉากที่มีฟังก์ชันการทำงานที่ไม่ต้องใช้การลิงก์บัญชี
- คลิกบันทึก
รวบรวมข้อมูล (ไม่บังคับ)
ตรวจสอบข้อกำหนดของธุรกรรม (ไม่บังคับ)
ทันทีที่ผู้ใช้ระบุว่าต้องการซื้อสินค้า คุณควรตรวจสอบว่าผู้ใช้จะทำธุรกรรมได้ เช่น เมื่อเรียกใช้ การดำเนินการอาจถามว่า "คุณต้องการสั่งซื้อรองเท้าหรือตรวจสอบเงินคงเหลือ" หากผู้ใช้พูดว่า "สั่งซื้อรองเท้า" คุณควรตรวจสอบว่าผู้ใช้ดำเนินการต่อได้และเปิดโอกาสให้ผู้ใช้แก้ไขการตั้งค่าที่ป้องกันไม่ให้ทำธุรกรรมต่อ ในการดำเนินการดังกล่าว คุณควรเปลี่ยนไปใช้โหมดที่ดำเนินการตรวจสอบข้อกำหนดของธุรกรรม
สร้างฉากการตรวจสอบข้อกำหนดในการทำธุรกรรม
- จากแท็บโหมด ให้เพิ่มฉากใหม่ชื่อ
TransactionRequirementsCheck
- ในส่วนการเติมช่องโฆษณา ให้คลิก + เพื่อเพิ่มช่องใหม่
- ในส่วนเลือกประเภท ให้เลือก
actions.type.TransactionRequirementsCheckResult
เป็นประเภทช่องโฆษณา - ในช่องชื่อช่อง ให้ตั้งชื่อช่องโฆษณาเป็น
TransactionRequirementsCheck
- เปิดใช้ช่องทำเครื่องหมายปรับแต่งการเขียนค่าช่องเอง (เปิดใช้อยู่โดยค่าเริ่มต้น)
คลิกบันทึก
การตรวจสอบข้อกําหนดของธุรกรรมจะทําให้เกิดผลลัพธ์อย่างใดอย่างหนึ่งต่อไปนี้
- หากตรงตามข้อกำหนดแล้ว ระบบจะตั้งค่าพารามิเตอร์เซสชันโดยมีเงื่อนไขความสำเร็จ และคุณจะสร้างลำดับของผู้ใช้ต่อไปได้
- หากไม่สามารถปฏิบัติตามข้อกำหนดอย่างน้อย 1 ข้อ ระบบจะตั้งค่าพารามิเตอร์เซสชันโดยมีเงื่อนไขความล้มเหลว ในกรณีนี้ คุณควรเปลี่ยนการสนทนาออกจาก
ประสบการณ์การทำธุรกรรม หรือควรจบการสนทนา
- หากผู้ใช้สามารถแก้ไขข้อผิดพลาดที่ทำให้สถานะไม่สำเร็จได้ ระบบจะแจ้งให้ผู้ใช้แก้ไขปัญหาดังกล่าวในอุปกรณ์ หากการสนทนาเกิดขึ้นในพื้นที่ที่ใช้เสียงอย่างเดียว ระบบจะเริ่มต้นแฮนด์ออฟไปยังโทรศัพท์ของผู้ใช้
ผลการตรวจสอบข้อกำหนดธุรกรรม
- จากแท็บฉาก ให้เลือกฉาก
TransactionRequirementsCheck
ที่สร้างขึ้นใหม่ - ในส่วนเงื่อนไข ให้คลิก + เพื่อเพิ่มเงื่อนไขใหม่
ในช่องข้อความ ให้ป้อนไวยากรณ์เงื่อนไขต่อไปนี้เพื่อตรวจสอบเงื่อนไขความสำเร็จ
scene.slots.status == "FINAL" && session.params.TransactionRequirementsCheck.resultType == "CAN_TRANSACT"
วางเคอร์เซอร์เหนือเงื่อนไขที่เพิ่งเพิ่ม แล้วคลิกลูกศรขึ้นเพื่อวางไว้หน้า
if scene.slots.status == "FINAL"
เปิดใช้ส่งพรอมต์และใช้ข้อความแจ้งง่ายๆ เพื่อแจ้งให้ผู้ใช้ทราบว่าพร้อมทำธุรกรรมแล้ว ดังนี้
candidates: - first_simple: variants: - speech: >- You are ready to purchase physical goods.
ในส่วนการเปลี่ยน ให้เลือกฉากอื่น เพื่อให้ผู้ใช้สนทนาต่อและทำธุรกรรมต่อได้
เลือกเงื่อนไข
else if scene.slots.status == "FINAL"
เปิดใช้ส่งพรอมต์และใช้ข้อความแจ้งง่ายๆ เพื่อแจ้งให้ผู้ใช้ทราบว่าทำธุรกรรมไม่ได้
candidates: - first_simple: variants: - speech: Transaction requirements check failed.
ในส่วนการเปลี่ยน ให้เลือกสิ้นสุดการสนทนาเพื่อสิ้นสุดการสนทนาหากผู้ใช้ทำธุรกรรมไม่ได้
ขอที่อยู่สำหรับจัดส่ง (ไม่บังคับ)
หากธุรกรรมของคุณต้องใช้ที่อยู่สำหรับจัดส่งของผู้ใช้ คุณควรส่งคำขอจากผู้ใช้ ซึ่งอาจเป็นประโยชน์ในการระบุราคารวม สถานที่นำส่ง/รับสินค้า หรือเพื่อตรวจสอบว่าผู้ใช้อยู่ในภูมิภาคที่ให้บริการของคุณ ในการดำเนินการดังกล่าว คุณควรเปลี่ยนไปใช้ฉากที่แจ้งให้ผู้ใช้ทราบถึงที่อยู่สำหรับจัดส่ง
สร้างโหมดที่อยู่สำหรับการนำส่ง
- จากแท็บฉาก ให้เพิ่มฉากใหม่ชื่อ
DeliveryAddress
- ในส่วนการเติมช่องโฆษณา ให้คลิก + เพื่อเพิ่มช่องใหม่
- ในส่วนเลือกประเภท ให้เลือก
actions.type.DeliveryAddressValue
เป็นประเภทช่องโฆษณา - ในช่องชื่อช่อง ให้ตั้งชื่อช่องโฆษณาเป็น
TransactionDeliveryAddress
- เปิดใช้ช่องทำเครื่องหมายปรับแต่งการเขียนค่าช่องเอง (เปิดใช้อยู่โดยค่าเริ่มต้น)
- คลิกบันทึก
เมื่อกำหนดค่าสล็อต คุณจะระบุ reason
ที่ช่วยให้คุณเกริ่นนำคำขอของ Assistant เพื่อรับที่อยู่ที่มีสตริงได้ โดยสตริงเหตุผลเริ่มต้นคือ "เพื่อให้ทราบว่าจะส่งคำสั่งซื้อไปที่ใด" ดังนั้น Assistant อาจถามผู้ใช้ว่า "ฉันต้องขอที่อยู่สำหรับจัดส่งของคุณก่อน คุณรู้ว่าต้องส่งคำสั่งซื้อไปที่ไหน"
- บนแพลตฟอร์มที่มีหน้าจอ ผู้ใช้จะเลือกที่อยู่ที่ต้องการใช้สำหรับธุรกรรม หากผู้ใช้ไม่เคยให้ที่อยู่มาก่อน ก็สามารถป้อนที่อยู่ใหม่ได้
- บนแพลตฟอร์มแบบเสียงเท่านั้น Assistant จะขอสิทธิ์ในการแชร์ที่อยู่เริ่มต้นสำหรับธุรกรรมจากผู้ใช้ หากบุคคลนั้นไม่เคยให้ที่อยู่ไว้ ระบบจะส่งการสนทนาไปที่โทรศัพท์เพื่อเข้า
ในการจัดการผลลัพธ์ของที่อยู่สำหรับนำส่ง ให้ทำตามขั้นตอนต่อไปนี้
- จากแท็บฉาก ให้เลือกฉาก
DeliveryAddress
ที่สร้างขึ้นใหม่ - ในส่วนเงื่อนไข ให้คลิก + เพื่อเพิ่มเงื่อนไขใหม่
ในช่องข้อความ ให้ป้อนไวยากรณ์เงื่อนไขต่อไปนี้เพื่อตรวจสอบเงื่อนไขความสำเร็จ
scene.slots.status == "FINAL" && session.params.TransactionDeliveryAddress.userDecision == "ACCEPTED"
วางเคอร์เซอร์เหนือเงื่อนไขที่เพิ่งเพิ่ม แล้วคลิกลูกศรขึ้นเพื่อวางไว้หน้า
if scene.slots.status == "FINAL"
เปิดใช้ส่งข้อความแจ้งและระบุข้อความแจ้งง่ายๆ ที่แจ้งให้ผู้ใช้ทราบว่าคุณได้รับที่อยู่แล้ว
candidates: - first_simple: variants: - speech: >- Great! Your order will be delivered to $session.params.TransactionDeliveryAddress.location.postalAddress.locality $session.params.TransactionDeliveryAddress.location.postalAddress.administrativeArea $session.params.TransactionDeliveryAddress.location.postalAddress.regionCode $session.params.TransactionDeliveryAddress.location.postalAddress.postalCode
ในส่วนการเปลี่ยน ให้เลือกฉากอื่นเพื่อให้ผู้ใช้สนทนาต่อได้
เลือกเงื่อนไข
else if scene.slots.status == "FINAL"
เปิดใช้ส่งพรอมต์และใช้ข้อความแจ้งง่ายๆ เพื่อแจ้งให้ผู้ใช้ทราบว่าทำธุรกรรมไม่ได้
candidates: - first_simple: variants: - speech: I failed to get your delivery address.
ในส่วนการเปลี่ยน ให้เลือกสิ้นสุดการสนทนาเพื่อสิ้นสุดการสนทนา หากผู้ใช้ทำธุรกรรมไม่ได้
สร้างคำสั่งซื้อ
เมื่อมีข้อมูลผู้ใช้ที่ต้องการแล้ว คุณจะสร้างประสบการณ์การใช้งาน "การประกอบรถเข็น" ที่แนะนำให้ผู้ใช้สร้างคำสั่งซื้อ การดำเนินการทุกครั้งจะมีขั้นตอนการประกอบรถเข็นที่แตกต่างกันเล็กน้อยตามที่เหมาะสมสำหรับผลิตภัณฑ์หรือบริการนั้นๆ
การประกอบรถเข็นขั้นพื้นฐานที่สุดคือการให้ผู้ใช้เลือกสินค้าจากรายการเพื่อเพิ่มลงในคำสั่งซื้อ แต่คุณออกแบบการสนทนาเพื่อลดความซับซ้อนของประสบการณ์ผู้ใช้ได้ คุณสามารถสร้างประสบการณ์การประกอบรถเข็นที่ช่วยให้ผู้ใช้สั่งซื้อสินค้าล่าสุดอีกครั้งได้ด้วยคำถามง่ายๆ แบบใช่หรือไม่ คุณยังนำเสนอภาพหมุนหรือการ์ดลิสต์รายการ "แนะนำ" หรือ "แนะนำ" ยอดนิยมแก่ผู้ใช้ได้ด้วย
เราขอแนะนำให้ใช้การตอบกลับที่สมบูรณ์เพื่อนำเสนอตัวเลือกของผู้ใช้ให้เห็นเป็นภาพ แต่ในขณะเดียวกันก็ออกแบบการสนทนาเพื่อให้ผู้ใช้สร้างรถเข็นได้โดยใช้เพียงเสียงเท่านั้น ดูแนวทางปฏิบัติแนะนำและตัวอย่างประสบการณ์การประกอบรถเข็นที่มีคุณภาพสูงได้ในหลักเกณฑ์การออกแบบธุรกรรม
สร้างคำสั่งซื้อ
ตลอดการสนทนา คุณจะต้องรวบรวมรายการที่ผู้ใช้ต้องการซื้อ จากนั้นจึงสร้างออบเจ็กต์ Order
อย่างน้อย Order
ของคุณต้องมีสิ่งต่อไปนี้
buyerInfo
- ข้อมูลเกี่ยวกับผู้ใช้ที่ทำการซื้อtransactionMerchant
- ข้อมูลเกี่ยวกับผู้ขายที่อำนวยความสะดวกในการสั่งซื้อcontents
- เนื้อหาจริงของคำสั่งซื้อที่แสดงเป็นlineItems
priceAttributes
- รายละเอียดราคาเกี่ยวกับคำสั่งซื้อ รวมถึงค่าใช้จ่ายรวมของคำสั่งซื้อพร้อมส่วนลดและภาษี
โปรดดูเอกสารการตอบกลับของ Order
เพื่อสร้างรถเข็น โปรดทราบว่าคุณอาจต้องใส่ช่อง
ต่างๆ โดยขึ้นอยู่กับลำดับ
โค้ดตัวอย่างด้านล่างแสดงคำสั่งซื้อที่สมบูรณ์ รวมถึงช่องที่ไม่บังคับ
const order = {
createTime: '2019-09-24T18:00:00.877Z',
lastUpdateTime: '2019-09-24T18:00:00.877Z',
merchantOrderId: orderId, // A unique ID String for the order
userVisibleOrderId: orderId,
transactionMerchant: {
id: 'http://www.example.com',
name: 'Example Merchant',
},
contents: {
lineItems: [
{
id: 'LINE_ITEM_ID',
name: 'Pizza',
description: 'A four cheese pizza.',
priceAttributes: [
{
type: 'REGULAR',
name: 'Item Price',
state: 'ACTUAL',
amount: {
currencyCode: 'USD',
amountInMicros: 8990000,
},
taxIncluded: true,
},
{
type: 'TOTAL',
name: 'Total Price',
state: 'ACTUAL',
amount: {
currencyCode: 'USD',
amountInMicros: 9990000,
},
taxIncluded: true,
},
],
notes: [
'Extra cheese.',
],
purchase: {
quantity: 1,
unitMeasure: {
measure: 1,
unit: 'POUND',
},
itemOptions: [
{
id: 'ITEM_OPTION_ID',
name: 'Pepperoni',
prices: [
{
type: 'REGULAR',
state: 'ACTUAL',
name: 'Item Price',
amount: {
currencyCode: 'USD',
amountInMicros: 1000000,
},
taxIncluded: true,
},
{
type: 'TOTAL',
name: 'Total Price',
state: 'ACTUAL',
amount: {
currencyCode: 'USD',
amountInMicros: 1000000,
},
taxIncluded: true,
},
],
note: 'Extra pepperoni',
quantity: 1,
subOptions: [],
},
],
},
},
],
},
buyerInfo: {
email: 'janedoe@gmail.com',
firstName: 'Jane',
lastName: 'Doe',
displayName: 'Jane Doe',
},
priceAttributes: [
{
type: 'SUBTOTAL',
name: 'Subtotal',
state: 'ESTIMATE',
amount: {
currencyCode: 'USD',
amountInMicros: 9990000,
},
taxIncluded: true,
},
{
type: 'DELIVERY',
name: 'Delivery',
state: 'ACTUAL',
amount: {
currencyCode: 'USD',
amountInMicros: 2000000,
},
taxIncluded: true,
},
{
type: 'TAX',
name: 'Tax',
state: 'ESTIMATE',
amount: {
currencyCode: 'USD',
amountInMicros: 3780000,
},
taxIncluded: true,
},
{
type: 'TOTAL',
name: 'Total Price',
state: 'ESTIMATE',
amount: {
currencyCode: 'USD',
amountInMicros: 15770000,
},
taxIncluded: true,
},
],
followUpActions: [
{
type: 'VIEW_DETAILS',
title: 'View details',
openUrlAction: {
url: 'http://example.com',
},
},
{
type: 'CALL',
title: 'Call us',
openUrlAction: {
url: 'tel:+16501112222',
},
},
{
type: 'EMAIL',
title: 'Email us',
openUrlAction: {
url: 'mailto:person@example.com',
},
},
],
termsOfServiceUrl: 'http://www.example.com',
note: 'Sale event',
promotions: [
{
coupon: 'COUPON_CODE',
},
],
purchase: {
status: 'CREATED',
userVisibleStatusLabel: 'CREATED',
type: 'FOOD',
returnsInfo: {
isReturnable: false,
daysToReturn: 1,
policyUrl: 'http://www.example.com',
},
fulfillmentInfo: {
id: 'FULFILLMENT_SERVICE_ID',
fulfillmentType: 'DELIVERY',
expectedFulfillmentTime: {
timeIso8601: '2019-09-25T18:00:00.877Z',
},
location: location,
price: {
type: 'REGULAR',
name: 'Delivery Price',
state: 'ACTUAL',
amount: {
currencyCode: 'USD',
amountInMicros: 2000000,
},
taxIncluded: true,
},
fulfillmentContact: {
email: 'johnjohnson@gmail.com',
firstName: 'John',
lastName: 'Johnson',
displayName: 'John Johnson',
},
},
purchaseLocationType: 'ONLINE_PURCHASE',
},
};
สร้างตัวเลือกลำดับและงานนำเสนอ
ก่อนที่ผู้ใช้จะยืนยันคำสั่งซื้อ ระบบจะแสดงการ์ดคำสั่งซื้อที่เสนอมา คุณปรับแต่งวิธีแสดงการ์ดนี้แก่ผู้ใช้ได้โดยการตั้งค่าตัวเลือกลำดับและการนำเสนอต่างๆ
ด้านล่างนี้คือตัวเลือกคำสั่งซื้อและการนำเสนอสำหรับการสั่งซื้อที่ต้องใช้ที่อยู่สำหรับจัดส่ง รวมถึงอีเมลของผู้ใช้ในการ์ดยืนยันคำสั่งซื้อ
const orderOptions = {
'requestDeliveryAddress': true,
'userInfoOptions': {
'userInfoProperties': ['EMAIL']
}
};
const presentationOptions = {
'actionDisplayName': 'PLACE_ORDER'
};
สร้างพารามิเตอร์การชำระเงิน
ออบเจ็กต์ paymentParameters
ของคุณมี merchantPaymentOption
ที่มีช่องซึ่งอธิบายวิธีการชำระเงินของผู้ใช้สำหรับคำสั่งซื้อ ต่อไปนี้เป็นตัวอย่างสำหรับพารามิเตอร์การชำระเงินที่ใช้บัตรเครดิต Visa
const paymentParamenters = {
'merchantPaymentOption': {
'defaultMerchantPaymentMethodId': '12345678',
'managePaymentMethodUrl': 'https://example.com/managePayment',
'merchantPaymentMethod': [{
'paymentMethodDisplayInfo': {
'paymentMethodDisplayName': 'VISA **** 1234',
'paymentType': 'PAYMENT_CARD'
},
'paymentMethodGroup': 'Payment method group',
'paymentMethodId': '12345678',
'paymentMethodStatus': {
'status': 'STATUS_OK',
'statusMessage': 'Status message'
}
}]
}
};
บันทึกข้อมูลคำสั่งซื้อในพารามิเตอร์เซสชัน
บันทึกข้อมูลคำสั่งซื้อลงในพารามิเตอร์ session
จาก Fulfillment
ระบบจะใช้ออบเจ็กต์ลำดับข้ามฉากในเซสชันเดียวกัน
conv.session.params.order = {
'@type': 'type.googleapis.com/google.actions.transactions.v3.TransactionDecisionValueSpec',
order: order,
orderOptions: orderOptions,
presentationOptions: presentationOptions,
paymentParameters: paymentParameters
};
เสนอคำสั่งซื้อ
เมื่อคุณสร้างคำสั่งซื้อแล้ว คุณต้องนำเสนอคำสั่งซื้อนั้นต่อผู้ใช้เพื่อยืนยันหรือปฏิเสธ ในการดำเนินการดังกล่าว คุณควรเปลี่ยนไปใช้ฉากที่ทำการตัดสินใจเกี่ยวกับธุรกรรม
สร้างโหมดการตัดสินใจเกี่ยวกับธุรกรรม
- จากแท็บฉาก ให้เพิ่มฉากใหม่ชื่อ
TransactionDecision
- ในส่วนการเติมช่องโฆษณา ให้คลิก + เพื่อเพิ่มช่องใหม่
- ในส่วนเลือกประเภท ให้เลือก
actions.type.TransactionDecisionValue
เป็นประเภทช่อง - ในช่องชื่อช่อง ให้ตั้งชื่อช่องโฆษณาเป็น
TransactionDecision
- เปิดใช้ช่องทำเครื่องหมายปรับแต่งการเขียนค่าช่องเอง (เปิดใช้อยู่โดยค่าเริ่มต้น)
- ในส่วนกำหนดค่าสล็อต ให้เลือกใช้พารามิเตอร์เซสชันจากเมนูแบบเลื่อนลง
- ในส่วนกำหนดค่าสล็อต ให้ป้อนชื่อพารามิเตอร์เซสชันที่ใช้จัดเก็บลำดับลงในช่องข้อความ (เช่น
$session.params.order
) - คลิกบันทึก
เพื่อพยายามเติมช่อง TransactionDecisionValue
Assistant จะเริ่มประสบการณ์การใช้งานในตัวซึ่งระบบจะแสดงผล Order
ที่คุณส่งไปยัง "การ์ดตัวอย่างรถเข็น" โดยตรง ผู้ใช้สามารถพูดว่า "สั่งซื้อ" ปฏิเสธธุรกรรม เปลี่ยนตัวเลือกการชำระเงิน เช่น บัตรเครดิตหรือที่อยู่ หรือขอเปลี่ยนเนื้อหาในคำสั่งซื้อ
ผู้ใช้ยังอาจขอเปลี่ยนแปลงคำสั่งซื้อในขั้นตอนนี้ ในกรณีนี้ คุณควรตรวจสอบว่าการดำเนินการตามคำสั่งซื้อสามารถจัดการคำขอเปลี่ยนแปลงคำสั่งซื้อได้หลังจากที่ดำเนินการประกอบรถเข็นเสร็จแล้ว
จัดการผลการตัดสินธุรกรรม
เมื่อมีการเติมช่องโฆษณา TransactionDecisionValue
ระบบจะจัดเก็บคำตอบของผู้ใช้เกี่ยวกับการตัดสินใจเรื่องธุรกรรมไว้ในพารามิเตอร์เซสชัน โดยค่านี้ประกอบด้วยข้อมูลต่อไปนี้
ORDER_ACCEPTED
,ORDER_REJECTED
,DELIVERY_ADDRESS_UPDATED
,CART_CHANGE_REQUESTED
USER_CANNOT_TRANSACT
.
วิธีจัดการผลการตัดสินธุรกรรม
- จากแท็บฉาก ให้เลือกฉาก
TransactionDecision
ที่สร้างขึ้นใหม่ - ในส่วนเงื่อนไข ให้คลิก + เพื่อเพิ่มเงื่อนไขใหม่
ในช่องข้อความ ให้ป้อนไวยากรณ์เงื่อนไขต่อไปนี้เพื่อตรวจสอบเงื่อนไขสำเร็จ
scene.slots.status == "FINAL" && session.params.TransactionDecision.transactionDecision == "ORDER_ACCEPTED"
วางเคอร์เซอร์เหนือเงื่อนไขที่เพิ่งเพิ่ม แล้วคลิกลูกศรขึ้นเพื่อวางไว้หน้า
if scene.slots.status == "FINAL"
เปิดใช้ส่งพรอมต์และใช้ข้อความแจ้งง่ายๆ เพื่อแจ้งให้ผู้ใช้ทราบว่าคำสั่งซื้อเสร็จสมบูรณ์แล้ว
candidates: - first_simple: variants: - speech: >- Transaction completed! Your order $session.params.TransactionDecision.order.merchantOrderId is all set!
ในส่วนการเปลี่ยน ให้เลือกสิ้นสุดการสนทนาเพื่อสิ้นสุดการสนทนา
ในส่วนเงื่อนไข ให้คลิก + เพื่อเพิ่มเงื่อนไขใหม่
ในช่องข้อความ ให้ป้อนไวยากรณ์เงื่อนไขต่อไปนี้เพื่อตรวจสอบเงื่อนไขที่ล้มเหลว
scene.slots.status == "FINAL" && session.params.TransactionDecision.transactionDecision == "ORDER_REJECTED"
วางเคอร์เซอร์เหนือเงื่อนไขที่เพิ่งเพิ่ม แล้วคลิกลูกศรขึ้นเพื่อวางไว้หน้า
if scene.slots.status == "FINAL"
เปิดใช้ส่งพรอมต์และใช้ข้อความแจ้งง่ายๆ เพื่อแจ้งให้ผู้ใช้ทราบว่าคำสั่งซื้อถูกปฏิเสธแล้วดังนี้
candidates: - first_simple: variants: - speech: Look like you don't want to order anything. Goodbye.
เลือกสิ้นสุดการสนทนาเพื่อสิ้นสุดการสนทนาในส่วนการเปลี่ยน
เลือกเงื่อนไข
else if scene.slots.status == "FINAL"
เปิดใช้ส่งพรอมต์และใช้ข้อความแจ้งง่ายๆ ที่แจ้งให้ผู้ใช้ทราบว่าตนทำธุรกรรมไม่ได้ ดังนี้
candidates: - first_simple: variants: - speech: >- Transaction failed with status $session.params.TransactionDecision.transactionDecision
ในส่วนการเปลี่ยน ให้เลือกสิ้นสุดการสนทนาเพื่อสิ้นสุดการสนทนา หากผู้ใช้ทำธุรกรรมไม่ได้
สั่งซื้อให้เสร็จสิ้นและส่งใบเสร็จ
เมื่อสล็อต TransactionDecisionValue
แสดงผลเป็น ORDER_ACCEPTED
คุณต้องดำเนินการตามที่จำเป็นทันทีเพื่อ "ยืนยัน" คำสั่งซื้อ (เช่น คงไว้ในฐานข้อมูลของคุณเองและเรียกเก็บเงินผู้ใช้)
คุณจบการสนทนาด้วยคำตอบนี้ได้ แต่ต้องใส่คำตอบง่ายๆ เพื่อให้การสนทนาดำเนินต่อไป เมื่อคุณระบุ orderUpdate
เบื้องต้นนี้ ผู้ใช้จะเห็น "การ์ดใบเสร็จที่ยุบแล้ว" พร้อมกับคำตอบที่เหลือของคุณ บัตรนี้จะแสดงใบเสร็จที่ผู้ใช้พบในประวัติการสั่งซื้อ
ในระหว่างการยืนยันคำสั่งซื้อ ออบเจ็กต์คำสั่งซื้ออาจมี userVisibleOrderId
ซึ่งเป็นรหัสที่ผู้ใช้เห็นสำหรับคำสั่งซื้อนั้นๆ คุณใช้ merchantOrderId
กับช่องนี้ซ้ำได้
ส่วนหนึ่งของออบเจ็กต์ OrderUpdate
จะต้องมีออบเจ็กต์การดำเนินการติดตามผล ซึ่งจะไฟล์ Manifest เป็นปุ่ม URL ที่ด้านล่างของรายละเอียดคำสั่งซื้อที่ผู้ใช้ดูได้ในประวัติการสั่งซื้อใน Assistant
- คุณต้องระบุการดำเนินการติดตามผล
VIEW_DETAILS
สำหรับคำสั่งซื้อแต่ละรายการเป็นอย่างน้อย ซึ่งควรมีลิงก์ในรายละเอียดที่อ้างอิงถึงคำสั่งซื้อในแอปหรือเว็บไซต์บนอุปกรณ์เคลื่อนที่ - นอกจากนี้ คุณต้องส่งใบเสร็จอย่างเป็นทางการทางอีเมลที่ตรงตามข้อกำหนดทางกฎหมายทั้งหมดสำหรับการทำธุรกรรม นอกเหนือจากบัตรใบเสร็จในการสนทนาของการดำเนินการของคุณ
วิธีส่งการอัปเดตคำสั่งซื้อเริ่มต้น
- จากแท็บฉาก ให้เลือกฉาก
TransactionDecision
ของคุณ ในส่วนเงื่อนไข ให้เลือกเงื่อนไขที่ตรวจสอบผลลัพธ์สำเร็จ
ORDER_ACCEPTED
:scene.slots.status == "FINAL" && session.params.TransactionDecision.transactionDecision == "ORDER_ACCEPTED"
สําหรับเงื่อนไขนี้ ให้เปิดใช้โทรหาเว็บฮุค และระบุชื่อแฮนเดิล Intent เช่น
update_order
ในโค้ดเว็บฮุค ให้เพิ่มเครื่องจัดการ Intent เพื่อส่งการอัปเดตคำสั่งซื้อเริ่มต้น ดังนี้
app.handle('update_order', conv => { const currentTime = new Date().toISOString(); let order = conv.session.params.TransactionDecision.order; conv.add(new OrderUpdate({ 'updateMask': { 'paths': [ 'purchase.status', 'purchase.user_visible_status_label' ] }, 'order': { 'merchantOrderId': order.merchantOrderId, 'lastUpdateTime': currentTime, 'purchase': { 'status': 'CONFIRMED', 'userVisibleStatusLabel': 'Order confirmed' }, }, 'reason': 'Reason string })); });
ส่งข้อมูลอัปเดตการสั่งซื้อ
คุณจะต้องแจ้งให้ผู้ใช้ทราบถึงสถานะของคำสั่งซื้อตลอดอายุของคำสั่งซื้อ ส่งการอัปเดตคำสั่งซื้อของผู้ใช้โดยส่งคำขอ HTTP PATCH ไปยัง Orders API พร้อมสถานะและรายละเอียดของคำสั่งซื้อ
ตั้งค่าคำขอแบบไม่พร้อมกันไปยัง Orders API
คำขออัปเดตคำสั่งซื้อไปยัง Orders API จะได้รับอนุญาตจากโทเค็นเพื่อการเข้าถึง หากต้องการแพตช์การอัปเดตคำสั่งซื้อไปยัง Orders API ให้ดาวน์โหลดคีย์บัญชีบริการ JSON ที่เชื่อมโยงกับโปรเจ็กต์คอนโซล Actions ของคุณ จากนั้นแลกเปลี่ยนคีย์บัญชีบริการกับโทเค็นสำหรับผู้ถือซึ่งส่งผ่านไปยังส่วนหัว Authorization
ของคำขอ HTTP ได้
หากต้องการเรียกข้อมูลคีย์บัญชีบริการ ให้ทำตามขั้นตอนต่อไปนี้
- ในคอนโซล Google Cloud ให้ไปที่เมนู ☰ > API และบริการ > ข้อมูลเข้าสู่ระบบ > สร้างข้อมูลเข้าสู่ระบบ > คีย์บัญชีบริการ
- ภายใต้บัญชีบริการ เลือกบัญชีบริการใหม่
- ตั้งค่าบัญชีบริการเป็น
service-account
- ตั้งค่าบทบาทเป็นโปรเจ็กต์ > เจ้าของ
- ตั้งค่าประเภทคีย์เป็น JSON
- เลือกสร้าง
- ระบบจะดาวน์โหลดคีย์บัญชีบริการ JSON ส่วนตัวไปยังเครื่องภายใน
ในโค้ดอัปเดตคำสั่งซื้อ คุณจะแลกเปลี่ยนคีย์บริการสำหรับโทเค็นสำหรับผู้ถือได้ โดยใช้ไลบรารีของไคลเอ็นต์ Google APIs และขอบเขต "https://www.googleapis.com/auth/actions.order.developer" คุณดูขั้นตอนการติดตั้งและตัวอย่างได้ที่หน้า GitHub ของไคลเอ็นต์ API
นอกจากนี้ คุณยังอ้างอิง order-update.js
ในตัวอย่าง Node.js เป็นตัวอย่างการแลกเปลี่ยนคีย์ได้ด้วย
ส่งข้อมูลอัปเดตการสั่งซื้อ
เมื่อแลกเปลี่ยนคีย์บัญชีบริการกับโทเค็นสำหรับผู้ถือ OAuth แล้ว คุณจะส่งการอัปเดตคำสั่งซื้อเป็นคำขอ Patch ที่ได้รับอนุญาตไปยัง Orders API ได้
URL ของ API คำสั่งซื้อ:
PATCH https://actions.googleapis.com/v3/orders/${orderId}
ระบุส่วนหัวต่อไปนี้ในคำขอของคุณ
"Authorization: Bearer token"
ด้วยโทเค็นสำหรับผู้ถือ OAuth ที่คุณแลกเปลี่ยนคีย์บัญชีบริการให้"Content-Type: application/json"
.
คำขอ Patch ควรมีเนื้อหา JSON ในรูปแบบต่อไปนี้
{ "orderUpdate": OrderUpdate }
ออบเจ็กต์ OrderUpdate
ประกอบด้วยช่องระดับบนสุดต่อไปนี้
updateMask
- ช่องของคำสั่งซื้อที่คุณกำลังอัปเดต หากต้องการอัปเดตสถานะการสั่งซื้อ ให้ตั้งค่าเป็นpurchase.status, purchase.userVisibleStatusLabel
order
- เนื้อหาของอัปเดต หากกำลังอัปเดตเนื้อหาของคำสั่งซื้อ ให้ตั้งค่าเป็นออบเจ็กต์Order
ที่อัปเดต หากคุณกำลังอัปเดตสถานะของคำสั่งซื้อ (เช่น จาก"CONFIRMED"
เป็น"SHIPPED"
) ออบเจ็กต์จะมีช่องต่อไปนี้merchantOrderId
- รหัสเดียวกับที่ตั้งค่าไว้ในออบเจ็กต์Order
lastUpdateTime
- การประทับเวลาของการอัปเดตนี้purchase
- ออบเจ็กต์ที่มีสิ่งต่อไปนี้status
- สถานะของคำสั่งซื้อเป็นPurchaseStatus
เช่น "SHIPPED
" หรือ "DELIVERED
"userVisibleStatusLabel
- ป้ายกำกับที่ผู้ใช้เห็นซึ่งมีรายละเอียดเกี่ยวกับสถานะการสั่งซื้อ เช่น "คำสั่งซื้อได้รับการจัดส่งแล้วและอยู่ระหว่างการจัดส่ง"
userNotification
ที่แสดงในอุปกรณ์ของผู้ใช้ได้เมื่อส่งการอัปเดตนี้ โปรดทราบว่าการรวมออบเจ็กต์นี้ไม่ได้รับประกันว่าการแจ้งเตือนจะปรากฏในอุปกรณ์ของผู้ใช้
โค้ดตัวอย่างต่อไปนี้แสดงตัวอย่าง OrderUpdate
ที่อัปเดตสถานะของคำสั่งซื้อเป็น DELIVERED
// Import the 'googleapis' module for authorizing the request.
const {google} = require('googleapis');
// Import the 'request-promise' module for sending an HTTP POST request.
const request = require('request-promise');
// Import the OrderUpdate class from the client library.
const {OrderUpdate} = require('@assistant/conversation');
// Import the service account key used to authorize the request.
// Replacing the string path with a path to your service account key.
// i.e. const serviceAccountKey = require('./service-account.json')
// Create a new JWT client for the Actions API using credentials
// from the service account key.
let jwtClient = new google.auth.JWT(
serviceAccountKey.client_email,
null,
serviceAccountKey.private_key,
['https://www.googleapis.com/auth/actions.order.developer'],
null,
);
// Authorize the client
let tokens = await jwtClient.authorize();
// Declare order update
const orderUpdate = new OrderUpdate({
updateMask: {
paths: [
'purchase.status',
'purchase.user_visible_status_label'
]
},
order: {
merchantOrderId: orderId, // Specify the ID of the order to update
lastUpdateTime: new Date().toISOString(),
purchase: {
status: 'DELIVERED',
userVisibleStatusLabel: 'Order delivered',
},
},
reason: 'Order status updated to delivered.',
});
// Set up the PATCH request header and body,
// including the authorized token and order update.
let options = {
method: 'PATCH',
uri: `https://actions.googleapis.com/v3/orders/${orderId}`,
auth: {
bearer: tokens.access_token,
},
body: {
header: {
isInSandbox: true,
},
orderUpdate,
},
json: true,
};
// Send the PATCH request to the Orders API.
try {
await request(options);
} catch (e) {
console.log(`Error: ${e}`);
}
ตั้งค่าสถานะการซื้อ
status
ของการอัปเดตคำสั่งซื้อต้องอธิบายสถานะปัจจุบันของคำสั่งซื้อ ในช่อง order.purchase.status
ของการอัปเดต ให้ใช้ค่าใดค่าหนึ่งต่อไปนี้
CREATED
- ผู้ใช้ยอมรับคำสั่งซื้อและ "สร้าง" จากมุมมองของการดำเนินการของคุณ แต่ต้องประมวลผลด้วยตนเองในเบื้องหลังCONFIRMED
- คำสั่งซื้อทำงานอยู่และกำลังประมวลผลสำหรับการดำเนินการตามคำสั่งซื้อIN_PREPARATION
- อยู่ระหว่างการเตรียมสินค้าเพื่อจัดส่ง/จัดส่ง เช่น อาหารกำลังปรุงสุกหรือสิ่งของที่บรรจุหีบห่อREADY_FOR_PICKUP
- ผู้รับสามารถมารับสินค้าได้DELIVERED
- คำสั่งซื้อส่งถึงผู้รับแล้วOUT_OF_STOCK
- สินค้าอย่างน้อย 1 รายการในคำสั่งซื้อนี้หมดสต็อกCHANGE_REQUESTED
- ผู้ใช้ขอเปลี่ยนแปลงคำสั่งซื้อ ระบบกำลังประมวลผลการเปลี่ยนแปลงRETURNED
- ผู้ใช้ส่งคืนสินค้าหลังจากการนำส่งREJECTED
- หากคุณไม่สามารถดำเนินการ เรียกเก็บเงิน หรือ "เปิดใช้งาน" คำสั่งซื้อCANCELLED
- ผู้ใช้ยกเลิกคำสั่งซื้อ
คุณควรส่งการอัปเดตคำสั่งซื้อสำหรับแต่ละสถานะที่เกี่ยวข้องกับธุรกรรมของคุณ ตัวอย่างเช่น หากธุรกรรมของคุณต้องมีการดำเนินการด้วยตนเองเพื่อบันทึกคำสั่งซื้อหลังจากทำการสั่งซื้อแล้ว ให้ส่งการอัปเดตคำสั่งซื้อด้วย CREATED
จนกว่าระบบจะประมวลผลเพิ่มเติมเสร็จสิ้น บางคำสั่งซื้อไม่ได้กำหนดให้มีค่าสถานะทุกค่า
ทดสอบโปรเจ็กต์
เมื่อทดสอบโปรเจ็กต์ คุณเปิดใช้โหมดแซนด์บ็อกซ์ในคอนโซลการดำเนินการเพื่อทดสอบการดำเนินการของคุณได้โดยไม่ต้องเรียกเก็บเงินจากวิธีการชำระเงิน หากต้องการเปิดใช้โหมดแซนด์บ็อกซ์ ให้ทำตามขั้นตอนต่อไปนี้
- ในคอนโซล Actions ให้คลิกทดสอบในการนําทาง
- คลิกการตั้งค่า
- เปิดใช้ตัวเลือกแซนด์บ็อกซ์สำหรับการพัฒนา
สำหรับธุรกรรมที่จับต้องได้ คุณยังตั้งค่าช่อง isInSandbox
เป็น true
ในตัวอย่างได้ด้วย การดำเนินการนี้เทียบเท่ากับการเปิดใช้การตั้งค่าโหมดแซนด์บ็อกซ์ในคอนโซลการดำเนินการ หากต้องการดูข้อมูลโค้ดที่ใช้ isInSandbox
โปรดดูส่วนส่งการอัปเดตคำสั่งซื้อ
การแก้ปัญหา
หากพบปัญหาระหว่างการทดสอบ คุณควรอ่านขั้นตอนการแก้ปัญหาสำหรับธุรกรรม