תהליך התשלום בקופה מופעל כשמשתמש יוצר עגלת קניות. התוכן של עגלת הקניות של המשתמש והפרטים על ההזמנה נשלחים לשירות האינטרנט שלכם להזמנות מקצה לקצה. שירות האינטרנט שלכם מאמת את המידע הזה, ואז תוכלו להמשיך או לבצע שינויים בעגלת הקניות לפי הצורך.
הטיפול בתשלום בשירות האינטרנט צריך להגיב לבקשות POST. כשלקוח בוחר לבצע תשלום, Google שולחת לשירות האינטרנט של Ordering End-to-End גוף בקשה בפורמט JSON בצורת CheckoutRequestMessage
, שמכיל את הפרטים של Cart
של הלקוח. לאחר מכן, שירות האינטרנט שלכם ישיב עם CheckoutResponseMessage
. התרשים הבא מדגים את התהליך.
כשמקבלים בקשה לתשלום, שירות האינטרנט שלכם להזמנות מקצה לקצה צריך לבצע את הפעולות הבאות:
- בודקים את תקינות עגלת הקניות על סמך המחירים הנוכחיים של הפריטים, הזמינות שלהם ושירות הספק.
- מחשבים את המחיר הכולל (כולל הנחות, מיסים ודמי משלוח).
- אם הפעולה בוצעה ללא שגיאות, יש להשיב עם עגלת קניות ללא שינויים.
- אם הניסיון לא יצליח, יש להשיב עם הודעת שגיאה והצעה חדשה לסדר.
לפני שמתחילים להטמיע תהליך תשלום, מומלץ לעיין במסמך סקירה כללית על תהליך המילוי.
הודעת בקשה לתשלום
כדי לאמת את עגלת הקניות של הלקוח, כשהלקוח בוחר לבצע תשלום, Google שולחת בקשה לשירות האינטרנט שלכם עם גוף JSON בפורמט CheckoutRequestMessage
. ההזמנה של הלקוח לא נשלחת עד שלב מאוחר יותר בתהליך Ordering End-to-End.
הנתונים שמופיעים ב-CheckoutRequestMessage
כוללים את הפרטים הבאים:
- כוונה: השדה
inputs[0].intent
בכל גוף בקשה של תשלום מכיל את ערך המחרוזתactions.foodordering.intent.CHECKOUT
. - עגלת קניות: השדה
inputs[0].arguments[0].extension
בבקשת תשלום מכיל אובייקטCart
שמייצג את עגלת הקניות של הלקוח. - משלוח או איסוף עצמי: שדה התוסף של האובייקט
Cart
מכיל אובייקטFoodCartExtension
שמציין מאפיינים של משלוח או איסוף עצמי:- בהזמנות למשלוח, האובייקט
FoodCartExtension
כולל את הכתובת למשלוח. - בהזמנות לאיסוף או להזמנות ממסעדה, האובייקט
FoodCartExtension
לא מכיל פרטי מיקום.
- בהזמנות למשלוח, האובייקט
- ארגז חול: השדה
isInSandbox
בבקשת תשלום מכיל ערך בוליאני שמציין אם בעסקה נעשה שימוש בתשלומים בארגז חול.
דוגמה לבקשת תשלום
דוגמה ל-CheckoutRequestMessage
:
{
"user": {},
"conversation": {
"conversationId": "CTZbZfUlHCybEdcz_5PB3Ttf"
},
"inputs": [
{
"intent": "actions.foodordering.intent.CHECKOUT",
"arguments": [
{
"extension": {
"@type": "type.googleapis.com/google.actions.v2.orders.Cart",
"merchant": {
"id": "restaurant/Restaurant/QWERTY",
"name": "Tep Tep Chicken Club"
},
"lineItems": [
{
"name": "Spicy Fried Chicken",
"type": "REGULAR",
"id": "299977679",
"quantity": 2,
"price": {
"type": "ESTIMATE",
"amount": {
"currencyCode": "AUD",
"units": "39",
"nanos": 600000000
}
},
"offerId": "MenuItemOffer/QWERTY/scheduleId/496/itemId/143",
"extension": {
"@type": "type.googleapis.com/google.actions.v2.orders.FoodItemExtension"
}
}
],
"extension": {
"@type": "type.googleapis.com/google.actions.v2.orders.FoodCartExtension",
"fulfillmentPreference": {
"fulfillmentInfo": {
"delivery": {
"deliveryTimeIso8601": "P0M"
}
}
},
"location": {
"coordinates": {
"latitude": -33.8376441,
"longitude": 151.0868736
},
"formattedAddress": "Killoola St, 1, Concord West NSW 2138",
"zipCode": "2138",
"city": "Concord West",
"postalAddress": {
"regionCode": "AU",
"postalCode": "2138",
"administrativeArea": "NSW",
"locality": "Concord West",
"addressLines": [
"Killoola St",
"1"
]
}
}
}
}
}
]
}
],
"directActionOnly": true,
"isInSandbox": true
}
הודעת תגובה בקופה
אחרי קבלת בקשה מהשירות של תהליך ההזמנה מקצה לקצה, שירות האינטרנט של תהליך התשלום צריך לעבד אותה ולהשיב עם CheckoutResponseMessage
. השדה CheckoutResponseMessage
צריך לכלול בקשה שהצליחה או בקשה שנכשלה.
בקשה שהושבה בהצלחה
אם בקשת היציאה תאושר, השדה CheckoutResponseMessage
צריך לכלול את הערכים ProposedOrder
ו-PaymentOptions
:
ProposedOrder
cart
: אובייקטcart
זהה לעגלה שצוינה ב-CheckoutRequestMessage
. אם צריך לשנות את אחד מהפריטים בעגלה, ה-CheckoutResponseMessage
צריך לכלול במקום זאתFoodErrorExtension
עםProposedOrder
מתוקן.otherItems
: פריטים שנוספו על ידי הספק, כמו חיובים על משלוח, מיסים ועמלות אחרות. יכול להיות שיכלול גם תשר שהמשתמש הוסיף.totalPrice
: המחיר הכולל של ההזמנה.extension
:FoodOrderExtension
שמגדיר את פרטי האספקה של ההזמנה, כמו זמן האספקה.
PaymentOptions
- בהמשך המאמר, בקטע הגדרת Google Pay, מוסבר איך מגדירים את עיבוד התשלומים.
אפשר להשתמש ב-JSON של placeholder ב-
CheckoutResponseMessage
עד שתהיה לכם אפשרות להטמיע עיבוד תשלומים. - כדי להוסיף אפשרויות תשלום למעקב אחרי
CheckoutResponseMessage
, אפשר להיעזר בדוגמה שבהמשך, שבה נעשה שימוש בשער תשלום לדוגמה ל-PaymentOptions
.
- בהמשך המאמר, בקטע הגדרת Google Pay, מוסבר איך מגדירים את עיבוד התשלומים.
אפשר להשתמש ב-JSON של placeholder ב-
דוגמה לתגובה מוצלחת
{
"finalResponse": {
"richResponse": {
"items": [
{
"structuredResponse": {
"checkoutResponse": {
"proposedOrder": {
"cart": {
"merchant": {
"id": "restaurant/Restaurant/QWERTY",
"name": "Tep Tep Chicken Club"
},
"lineItems": [
{
"name": "Spicy Fried Chicken",
"type": "REGULAR",
"id": "299977679",
"quantity": 2,
"price": {
"type": "ESTIMATE",
"amount": {
"currencyCode": "AUD",
"units": "39",
"nanos": 600000000
}
},
"offerId": "MenuItemOffer/QWERTY/scheduleId/496/itemId/143",
"extension": {
"@type": "type.googleapis.com/google.actions.v2.orders.FoodItemExtension"
}
}
],
"extension": {
"@type": "type.googleapis.com/google.actions.v2.orders.FoodCartExtension",
"fulfillmentPreference": {
"fulfillmentInfo": {
"delivery": {
"deliveryTimeIso8601": "P0M"
}
}
},
"location": {
"coordinates": {
"latitude": -33.8376441,
"longitude": 151.0868736
},
"formattedAddress": "Killoola St, 1, Concord West NSW 2138",
"zipCode": "2138",
"city": "Concord West",
"postalAddress": {
"regionCode": "AU",
"postalCode": "2138",
"administrativeArea": "NSW",
"locality": "Concord West",
"addressLines": [
"Killoola St",
"1"
]
}
}
}
},
"totalPrice": {
"type": "ESTIMATE",
"amount": {
"currencyCode": "AUD",
"units": "43",
"nanos": 100000000
}
},
"extension": {
"@type": "type.googleapis.com/google.actions.v2.orders.FoodOrderExtension",
"availableFulfillmentOptions": [
{
"fulfillmentInfo": {
"delivery": {
"deliveryTimeIso8601": "P0M"
}
}
}
]
},
"otherItems": [
{
"name": "Delivery fee",
"price": {
"type": "ESTIMATE",
"amount": {
"currencyCode": "AUD",
"units": "3",
"nanos": 500000000
}
},
"type": "DELIVERY"
}
]
},
"paymentOptions": {
"googleProvidedOptions": {
"facilitationSpecification": "{\"apiVersion\":2,\"apiVersionMinor\":0,\"merchantInfo\":{\"merchantName\":\"merchantName\"},\"allowedPaymentMethods\":[{\"type\":\"CARD\",\"parameters\":{\"allowedAuthMethods\":[\"PAN_ONLY\"],\"allowedCardNetworks\":[\"VISA\",\"MASTERCARD\"],\"billingAddressRequired\":true,\"cvcRequired\":false},\"tokenizationSpecification\":{\"type\":\"PAYMENT_GATEWAY\",\"parameters\":{\"gatewayMerchantId\":\"YOUR_MERCHANT_ID\",\"gateway\":\"cybersource\"}}}],\"transactionInfo\":{\"currencyCode\":\"AUD\",\"totalPriceStatus\":\"ESTIMATED\",\"totalPrice\":\"43.1\"}} "
}
},
"additionalPaymentOptions": [
{
"actionProvidedOptions": {
"paymentType": "ON_FULFILLMENT",
"displayName": "Pay when you get your food.",
"onFulfillmentPaymentData": {
"supportedPaymentOptions": []
}
}
}
]
}
}
}
]
}
}
}
בקשה שנכשלה
אם בקשת התשלום לא תאושר, השדה CheckoutResponseMessage
צריך לכלול את השדה FoodErrorExtension
, שמכיל רשימה של פריטים מסוג FoodOrderError
שמתארים את השגיאות שהתרחשו. אם יש שגיאות שניתן לתקן בהזמנה, כמו שינוי במחיר של פריט בעגלת הקניות, השדה FoodErrorExtension
חייב לכלול את השדה correctedProposedOrder
.
דוגמה לתגובה לא מוצלחת
{
"expectUserResponse": false,
"finalResponse": {
"richResponse": {
"items": [
{
"structuredResponse": {
"error": {
"@type": "type.googleapis.com/google.actions.v2.orders.FoodErrorExtension",
"foodOrderErrors": [
{
"error": "CLOSED",
"description": "The restaurant is closed."
}
]
}
}
}
]
}
}
}
הטמעת תהליך התשלום
כשמטמיעים את התשלום בקופה, צריך לבצע את השלבים הבאים.
אימות השירות
מחזירים את הערך FoodOrderError לתנאי השגיאה הראשון בשירות שנמצא. אי אפשר לשחזר את השגיאות האלה, ולכן צריך להחזיר את השגיאה הראשונה שנתקלת בה. תיאור של שגיאות שניתן לשחזר מופיע במאמר טיפול בשגיאות.
- קוראים את המאפיין FulfillmentOptionInfo בבקשה כדי לקבוע אם סוג המילוי הוא ל-
delivery
או ל-pickup
. אם צריך, מחזירים את סוגי השגיאות הבאים:
סוג השגיאה תרחיש לדוגמה INVALID סוג המילוי לא חוקי. NOT_FOUND סוג המילוי לא נמצא. סגור - אין חלונות OperationHours להזמנה.
- ההזמנה היא בהקדם האפשרי ואין ServiceHours זמינות בהקדם האפשרי בשלב הזה.
- יש חסימה זמנית מסיבות חירום או שהשירות
isDisabled
נכון.
UNAVAILABLE_SLOT לא ניתן למלא את ההזמנה מראש. NO_CAPACITY המסעדה עמוסה ולא מקבלת כרגע הזמנות. OUT_OF_SERVICE_AREA לא ניתן לשלוח את ההזמנה לכתובת של המשתמש. דוגמה לכך מופיעה במאמר אימות כתובת למשלוח. NO_COURIER_AVAILABLE לא ניתן לבצע את המשלוח כי מספר צוות השליחויות מוגבל.
אימות ועריכת המחיר של עגלת הקניות
מחפשים כל עגלת קניות.
lineItems
ומאמתים עם הנתונים הנוכחיים במערכת שלכם או במערכת של המוכר. הערך MenuItemOffer.sku
מהישות בפיד נכלל בתור LineItem.offerId
. אם צריך, יוצרים אירוע FoodOrderError לכל פריט. אפשר ליצור שגיאה אחת לכל פריט לכל היותר. אם צריך, מחזירים את סוגי השגיאות הבאים:סוג השגיאה תרחיש לדוגמה ניתן לשחזור INVALID נתוני הפריט או נתוני אחת מהאפשרויות לא תקינים. לא NOT_FOUND הפריט או אף אחת מהאפשרויות לא נמצאים. לא PRICE_CHANGED המחיר של פריט או שילוב של תוספים השתנה. אפשר להתייחס לשגיאה הזו כאל שגיאה שניתן לשחזור. כן AVAILABILITY_CHANGED הסכום המבוקש עבור הפריטים או אחת מהאפשרויות לא זמין. כן REQUIREMENTS_NOT_MET לא הגעתם לסכום ההזמנה המינימלי או המקסימלי. אפשר לקבוע זאת על ידי בדיקה אם מחיר עגלת הקניות נמוך מ-Fee. eligibleTransactionVolumeMin
או גבוה מ-Fee.eligibleTransactionVolumeMax
. אפשר לעיין בדוגמה בקטע אימות ערך הזמנה מינימלי.לא החזרת הרשימה המאומתת של הפריטים עם LineItemType
REGULAR
. הסכום של כל המחירים של הפריטים בעגלת הקניות הוא מחיר עגלת הקניות, אוSUBTOTAL
.
דוגמאות מפורטות זמינות במאמר אימות פריטים בעגלת הקניות.
חישוב עמלות השירות
- מחפשים את הישות Fee המתאימה לשירות על סמך הערכים של
eligibleRegion
, validFrom
, validThrough
ו-priority
. - חישוב סכום העמלה על סמך הגדרת הישות באמצעות מאפיין
price
,percentageOfCart
אוpricePerMeter
. - מחזירים את עמלת השירות של המשלוח או של ההזמנה ממסעדה בתור LineItem עם LineItemType
DELIVERY
אוFEE
, בהתאמה. מוסיפים את העמלה לרשימת הכרטיסים.otherItems
החלת מבצעים
- חיפוש הישות Deal על סמך התאמה של הערך Promotion.
coupon
לערך Deal.dealCode
. מאמתים את המבצע ומחזירים FoodOrderError במקרה הצורך. אפשר להתייחס לשגיאות האלה כאל שגיאות שניתן לשחזר. אם צריך, מחזירים את סוגי השגיאות הבאים:
סוג השגיאה תרחיש לדוגמה PROMO_NOT_RECOGNIZED קוד השובר לא זוהה. PROMO_EXPIRED פג התוקף של המבצע. PROMO_ORDER_INELIGIBLE ההזמנה לא עומדת בדרישות של השובר. PROMO_NOT_APPLICABLE סיבה אחרת. מחשבים את סכום מחיר המבצע על סמך Deal.
discount
או Deal.discountPercentage
.מחילים את סכום המבצע על סמך הסכום הכולל בעגלת הקניות או הסכום הכולל של העמלות, בהתאם למבצע.
dealType
.חוזרים אל עגלת הקניות.
promotions
עם המבצע שמומש.מחזירים את קידום המכירות כ-LineItem עם LineItemType
DISCOUNT
. מוסיפים את ההנחה לרשימה Cart.otherItems
עם מחיר שלילי.
החזרת התשובה
- יוצרים את ProposedOrder.
cart
, עגלת התשובה זהה לעגלת הבקשה אם לא נתקלים בשגיאות במהלך האימות. - מחזירים את הרשימה ProposedOrder.
otherItems
, כולל המס, העמלות, התשר וההנחה, אם חלה. במאמר תשריף מוסבר בהרחבה איך מגדירים את הפריט 'תשריף'. - מוסיפים את ProposedOrder.
totalPrice
על ידי הוספת המחיר של עגלת הקניות, העמלות, ההנחות, המיסים והטיפ. - מחזירים את FoodOrderExtension.
availableFulfillmentOptions
עם FulfillmentOption המתאים. מעדכנים את זמן האיסוף או המסירה המשוער לפי הזמן הצפוי. - אם יש שגיאות מסוג FoodOrderErrors שנוצרו מבדיקות האימות הקודמות:
- כוללים את StructuredResponse.
error
ואת רשימת השגיאות ב-FoodErrorExtension.foodOrderErrors
. - מחזירים את ProposedOrder בשדה
correctedProposedOrder
אם ניתן לשחזר את כל השגיאות. - מחזירים את PaymentOptions בשדה
paymentOptions
אם ניתן לשחזר את כל השגיאות. - אפשר לכלול את הערך
additionalPaymentOptions
אם יש אפשרויות תשלום אחרות ואפשר לשחזר את כל השגיאות.
- כוללים את StructuredResponse.
- אם אין שגיאות אימות, מחזירים את הערכים
proposedOrder
,paymentOptions
באובייקט CheckoutResponse. אם יש אפשרויות תשלום אחרות, אפשר לכלול אתadditionalPaymentOptions
.