คู่มือนี้จะอธิบายขั้นตอนการพัฒนาโปรเจ็กต์ Actions ที่รวมธุรกรรมสำหรับสินค้าที่จับต้องได้และใช้ Google Pay สำหรับการชำระเงิน
ขั้นตอนการทำธุรกรรม
เมื่อโปรเจ็กต์การดำเนินการของคุณจัดการธุรกรรมทางกายภาพโดยใช้การชำระเงินที่จัดการโดยผู้ขาย โปรเจ็กต์จะใช้ขั้นตอนต่อไปนี้
- รวบรวมข้อมูล (ไม่บังคับ) - คุณควรรวบรวมข้อมูลต่อไปนี้จากผู้ใช้เมื่อเริ่มต้นการสนทนา ทั้งนี้ขึ้นอยู่กับลักษณะธุรกรรมของคุณ
- ตรวจสอบข้อกำหนดเกี่ยวกับธุรกรรม - เมื่อเริ่มต้นการสนทนา ให้ตรวจสอบว่าผู้ใช้มีคุณสมบัติตรงตามข้อกำหนดในการทำธุรกรรม เช่น มีการกำหนดค่าข้อมูลการชำระเงินอย่างเหมาะสมและพร้อมใช้งานก่อนที่จะสร้างรถเข็น
- ขอที่อยู่สำหรับจัดส่ง - หากธุรกรรมต้องใช้ที่อยู่สำหรับนำส่ง ให้รวบรวมที่อยู่จากผู้ใช้
- สร้างคำสั่งซื้อ - พาผู้ใช้ไปดู "ชุดประกอบรถเข็น" ซึ่งจะเลือกสินค้าที่ต้องการซื้อ
- เสนอคำสั่งซื้อ - เมื่อรถเข็นเสร็จสมบูรณ์แล้ว ให้เสนอคำสั่งซื้อแก่ผู้ใช้เพื่อยืนยันว่าถูกต้อง หากคำสั่งซื้อได้รับการยืนยัน คุณจะได้รับการตอบกลับพร้อมรายละเอียดคำสั่งซื้อและโทเค็นการชำระเงิน
- สรุปคำสั่งซื้อและส่งใบเสร็จ - เมื่อยืนยันคำสั่งซื้อแล้ว ให้อัปเดตการติดตามสินค้าคงคลังหรือบริการดำเนินการตามคำสั่งซื้ออื่นๆ จากนั้นส่งใบเสร็จให้ผู้ใช้
- ส่งการอัปเดตคำสั่งซื้อ - ให้การอัปเดตคำสั่งซื้อแก่ผู้ใช้ตลอดระยะเวลาอายุการใช้งานของการดำเนินการตามคำสั่งซื้อโดยส่งคำขอ Patch ไปยัง Orders API
ข้อจำกัดและหลักเกณฑ์การตรวจสอบ
โปรดทราบว่านโยบายเพิ่มเติมมีผลกับการดำเนินการที่มีธุรกรรม เราอาจใช้เวลาถึง 6 สัปดาห์ในการตรวจสอบการดำเนินการที่มีธุรกรรม ดังนั้นโปรดคำนึงถึงเวลาดังกล่าวเมื่อวางแผนกำหนดการเผยแพร่ เพื่อช่วยให้กระบวนการตรวจสอบง่ายขึ้น โปรดตรวจสอบว่าคุณปฏิบัติตามนโยบายและหลักเกณฑ์สำหรับธุรกรรมก่อนส่งการดำเนินการเข้ารับการตรวจสอบ
คุณใช้การดำเนินการที่ขายสินค้าที่จับต้องได้ในประเทศต่อไปนี้เท่านั้น
ออสเตรเลีย บราซิล แคนาดา อินโดนีเซีย |
ญี่ปุ่น เม็กซิโก รัสเซีย |
สิงคโปร์ ไทย ตุรกี สหราชอาณาจักร สหรัฐอเมริกา |
สร้างโปรเจ็กต์
ดูตัวอย่างการสนทนาด้านธุรกรรมได้ที่ตัวอย่างธุรกรรมของ Node.js
ตั้งค่า
เมื่อสร้างการดำเนินการ คุณต้องระบุว่าคุณต้องการทำธุรกรรมในคอนโซลการดำเนินการ
หากต้องการตั้งค่าโปรเจ็กต์และการดำเนินการตามคำสั่งซื้อ ให้ทำตามขั้นตอนต่อไปนี้
- สร้างโปรเจ็กต์ใหม่หรือนำเข้าโปรเจ็กต์ที่มีอยู่
- ไปที่ทำให้ใช้งานได้ > ข้อมูลไดเรกทอรี
ในส่วนข้อมูลเพิ่มเติม > ธุรกรรม > เลือกช่องที่ระบุว่า "การดำเนินการของคุณใช้ Transaction API ในการทำธุรกรรมสินค้าที่จับต้องได้ไหม"
1. รวบรวมข้อมูล (ไม่บังคับ)
1a. ตรวจสอบข้อกำหนดของธุรกรรม (ไม่บังคับ)
ทันทีที่ผู้ใช้ระบุว่าต้องการซื้อสินค้า คุณควรตรวจสอบว่าผู้ใช้จะทำธุรกรรมได้ เช่น เมื่อเรียกใช้ การดำเนินการอาจถามว่า "คุณต้องการสั่งซื้อรองเท้าหรือตรวจสอบเงินคงเหลือ" หากผู้ใช้พูดว่า "สั่งซื้อรองเท้า" คุณควรตรวจสอบว่าผู้ใช้ดำเนินการต่อได้และเปิดโอกาสให้ผู้ใช้แก้ไขการตั้งค่าที่ป้องกันไม่ให้ทำธุรกรรมต่อ ในการดำเนินการดังกล่าว คุณควรเปลี่ยนไปใช้โหมดที่ดำเนินการตรวจสอบข้อกำหนดของธุรกรรม
สร้างฉากการตรวจสอบข้อกำหนดในการทำธุรกรรม
- จากแท็บโหมด ให้เพิ่มฉากใหม่ชื่อ
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
จะมีพารามิเตอร์การแปลงข้อมูลเป็นโทเค็นที่เปลี่ยนแปลงตามผู้ประมวลผล Google Pay ที่วางแผนจะใช้ (เช่น Stripe, Braintree, ACI ฯลฯ)
const paymentParamenters = {
'googlePaymentOption': {
// facilitationSpec is expected to be a serialized JSON string
'facilitationSpec': JSON.stringify({
'apiVersion': 2,
'apiVersionMinor': 0,
'merchantInfo': {
'merchantName': 'Example Merchant',
},
'allowedPaymentMethods': [
{
'type': 'CARD',
'parameters': {
'allowedAuthMethods': ['PAN_ONLY', 'CRYPTOGRAM_3DS'],
'allowedCardNetworks': [
'AMEX', 'DISCOVER', 'JCB', 'MASTERCARD', 'VISA'],
},
'tokenizationSpecification': {
'type': 'PAYMENT_GATEWAY',
'parameters': {
'gateway': 'example',
'gatewayMerchantId': 'exampleGatewayMerchantId',
},
},
},
],
'transactionInfo': {
'totalPriceStatus': 'FINAL',
'totalPrice': '15.77',
'currencyCode': 'USD',
},
}),
},
};
เนื้อหาของออบเจ็กต์ tokenizationSpecification
จะแตกต่างกันไปสำหรับเกตเวย์การชำระเงินแต่ละรายการ ตารางต่อไปนี้แสดงพารามิเตอร์ที่เกตเวย์แต่ละรายการใช้
"parameters": { "gateway": "example", "gatewayMerchantId": "exampleGatewayMerchantId" }
"parameters": { "gateway": "aciworldwide", "gatewayMerchantId": "YOUR_ENTITY_ID" }
"parameters": { "gateway": "adyen", "gatewayMerchantId": "YOUR_MERCHANT_ACCOUNT_NAME" }
"parameters": { "gateway": "alfabank", "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" }
"parameters": { "gateway": "bluemedia", "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" }
"parameters": { "gateway": "bluesnap", "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" }
"parameters": { "gateway": "braintree", "braintree:apiVersion": "v1", "braintree:sdkVersion": braintree.client.VERSION, "braintree:merchantId": "YOUR_BRAINTREE_MERCHANT_ID", "braintree:clientKey": "YOUR_BRAINTREE_TOKENIZATION_KEY" }
"parameters": { "gateway": "chase", "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ACCOUNT_NUMBER" }
"parameters": { "gateway": "checkoutltd", "gatewayMerchantId": "YOUR_PUBLIC_KEY" }
"parameters": { "gateway": "cloudpayments", "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" }
"parameters": { "gateway": "cybersource", "gatewayMerchantId": "YOUR_MERCHANT_ID" }
"parameters": { "gateway": "datatrans", "gatewayMerchantId": "YOUR_MERCHANT_ID" }
"parameters": { "gateway": "ebanx", "gatewayMerchantId": "YOUR_PUBLIC_INTEGRATION_KEY" }
"parameters": { "gateway": "firstdata", "gatewayMerchantId": "YOUR_MERCHANT_ID" }
"parameters": { "gateway": "globalpayments", "gatewayMerchantId": "YOUR_MERCHANT_ID" }
"parameters": { "gateway": "gopay", "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" }
"parameters": { "gateway": "hitrustpay", "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" }
"parameters": { "gateway": "imsolutions", "gatewayMerchantId": "YOUR_MERCHANT_ID" }
"parameters": { "gateway": "lyra", "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" }
"parameters": { "gateway": "mpgs", "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" }
"parameters": { "gateway": "moneymailru", "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" }
"parameters": { "gateway": "newebpay", "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" }
"parameters": { "gateway": "nexi", "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" }
"parameters": { "gateway": "creditcall", "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" }
"parameters": { "gateway": "paysafe", "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" }
"parameters": { "gateway": "payture", "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" }
"parameters": { "gateway": "payu", "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" }
"parameters": { "gateway": "przelewy24", "gatewayMerchantId": "YOUR_MERCHANT_ID" }
"parameters": { "gateway": "rbkmoney", "gatewayMerchantId": "YOUR_MERCHANT_ID" }
"parameters": { "gateway": "sberbank", "gatewayMerchantId": "YOUR_ORGANIZATION_NAME" }
"parameters": { "gateway": "square", "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" }
"parameters": { "gateway": "stripe", "stripe:version": "2018-10-31", "stripe:publishableKey": "YOUR_PUBLIC_STRIPE_KEY" }
"parameters": { "gateway": "tappay", "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" }
"parameters": { "gateway": "tinkoff", "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" }
"parameters": { "gateway": "uniteller", "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID" }
"parameters": { "gateway": "vantiv", "vantiv:merchantPayPageId": "YOUR_PAY_PAGE_ID", "vantiv:merchantOrderId": "YOUR_ORDER_ID", "vantiv:merchantTransactionId": "YOUR_TRANSACTION_ID", "vantiv:merchantReportGroup": "*web" }
"parameters": { "gateway": "worldpay", "gatewayMerchantId": "YOUR_WORLDPAY_MERCHANT_ID" }
"parameters": { "gateway": "yandexcheckout", "gatewayMerchantId": "YOUR_SHOP_ID" }
บันทึกข้อมูลคำสั่งซื้อในพารามิเตอร์เซสชัน
บันทึกข้อมูลคำสั่งซื้อลงในพารามิเตอร์เซสชันจาก 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
โปรดดูส่วนส่งการอัปเดตคำสั่งซื้อ
การแก้ปัญหา
หากพบปัญหาระหว่างการทดสอบ คุณควรอ่านขั้นตอนการแก้ปัญหาสำหรับธุรกรรม