הגדרת שליחת ההזמנה

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

בקטע הזה מוסבר על הפורמט של הודעת הבקשה להזמנה שנשלחת על ידי Google, שנקראת SubmitOrderRequestMessage, ועל הפורמט של הודעת התגובה שאתם צריכים לספק, שנקראת SubmitOrderResponseMessage. מידע נוסף על מחזור החיים של מילוי ההזמנות זמין בסקירה הכללית על מילוי ההזמנות.

הטמעת שירותי מילוי הזמנות

שירות האינטרנט של Ordering End-to-End שאתם יוצרים כדי לעבוד עם Ordering End-to-End חייב לכלול נקודת קצה של כתובת URL לקבלת הודעות על הזמנות מ-Google. לצורך עיבוד ההזמנה, שירות האינטרנט שלכם מקבל מ-Google את הערך SubmitOrderRequestMessage בפורמט JSON כבקשת POST. הבקשה הזו מכילה הזמנה של לקוח, כולל מיסים, עמלות ופרטי תשלום. כשמקבלים בקשה לשליחת הזמנה, שירות האינטרנט צריך לבצע את הפעולות הבאות:

  • בדיקת הזכאות לביצוע עסקה, כמו אימות כרטיס או זיהוי הונאות.
  • יוצרים הזמנה במערכת.
  • מאשרים את אמצעי התשלום ומפעילים את Charge API של ספק שירותי התשלומים, במקרים הרלוונטיים.
  • יש להשיב עם סטטוס ההזמנה המתאים: CREATED, CONFIRMED או REJECTED.

אחרי עיבוד ההזמנה, קוד המילוי צריך לספק תשובה ל-Google בצורת הודעת JSON מסוג SubmitOrderResponseMessage.

מידע נוסף על דרישות ההטמעה של שירות האינטרנט של מילוי ההזמנות מקצה לקצה זמין במאמר סקירה כללית על מילוי הזמנות.

הודעת הבקשה להזמנה

כשלקוח בוחר לבצע הזמנה במהלך התהליך מתחילתו ועד סופו, Google שולחת בקשה לשירות האינטרנט שלכם עם הודעת JSON שנקראת SubmitOrderRequestMessage, שמכילה את הנתונים הבאים:

  1. כוונה: השדה inputs[0].intent בכל גוף בקשה לשליחת הזמנה מכיל את ערך המחרוזת actions.intent.TRANSACTION_DECISION.
  2. הזמנה: השדה inputs[0].arguments[0].transactionDecisionValue בבקשה לשליחת הזמנה מכיל אובייקט Order שמייצג את ההזמנה של הלקוח שרוצים להעביר, יחד עם פרטי התשלום.
  3. דגל ארגז חול: השדה isInSandbox בבקשה לשליחת הזמנה מציין אם בעסקה נעשה שימוש בתשלומים בארגז חול.

דוגמה לבקשת הזמנה

דוגמה ל-SubmitOrderRequestMessage:

JSON
{
    "user": {},
    "conversation": {
        "conversationId": "CTKbKfUlHCyDEdcz_5PBJTtf"
    },
    "inputs": [
        {
            "intent": "actions.intent.TRANSACTION_DECISION",
            "arguments": [
                {
                    "transactionDecisionValue": {
                        "order": {
                            "finalOrder": {
                                "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"
                                                ]
                                            }
                                        },
                                        "contact": {
                                            "displayName": "Hab Sy",
                                            "email": "hab9878.sy@gmail.com",
                                            "phoneNumber": "+61000000000",
                                            "firstName": "Hab",
                                            "lastName": "Sy"
                                        }
                                    }
                                },
                                "otherItems": [
                                    {
                                        "name": "Delivery fee",
                                        "type": "DELIVERY",
                                        "price": {
                                            "type": "ESTIMATE",
                                            "amount": {
                                                "currencyCode": "AUD",
                                                "units": "3",
                                                "nanos": 500000000
                                            }
                                        }
                                    },
                                    {
                                        "name": "Subtotal",
                                        "type": "SUBTOTAL",
                                        "price": {
                                            "type": "ESTIMATE",
                                            "amount": {
                                                "currencyCode": "AUD",
                                                "units": "39",
                                                "nanos": 600000000
                                            }
                                        }
                                    }
                                ],
                                "totalPrice": {
                                    "type": "ESTIMATE",
                                    "amount": {
                                        "currencyCode": "AUD",
                                        "units": "43",
                                        "nanos": 100000000
                                    }
                                },
                                "extension": {
                                    "@type": "type.googleapis.com/google.actions.v2.orders.FoodOrderExtension"
                                }
                            },
                            "googleOrderId": "01412971004192156198",
                            "orderDate": "2020-10-22T09:02:06.173Z",
                            "paymentInfo": {
                                "displayName": "Pay when you get your food",
                                "paymentType": "ON_FULFILLMENT"
                            }
                        }
                    }
                }
            ]
        }
    ],
    "directActionOnly": true,
    "isInSandbox": true
}
    

הודעת תגובה להזמנה

אחרי קבלת בקשה, שירות האינטרנט של תהליך ההזמנה מקצה אותה לטיפול ומחזיר SubmitOrderResponseMessage שכולל את הנתונים הבאים:

  • OrderUpdate: אובייקט שמכיל את סטטוס ההזמנה ואת כל הפעולות שזמינות למשתמש לאחר ההזמנה, כמו יצירת קשר עם התמיכה וצפייה בפרטי ההזמנה. אתם מגדירים את הפעולות האלה בשדה finalResponse.richResponse.items[0].structuredResponse.orderUpdate בתגובה.

שדה עדכון ההזמנה

כששירות האינטרנט שולח SubmitOrderResponseMessage, הוא מכיל את השדה OrderUpdate שכולל את השדות הבאים:

  • actionOrderId: המזהה הייחודי של ההזמנה, שמשמשים לזיהוי ההזמנה באופן ייחודי במערכת ולהפניה אליה כששולחים עדכונים נוספים לגבי ההזמנה.
  • orderState: אובייקט OrderState שמייצג את מצב ההזמנה.
  • orderManagementActions: פעולות שזמינות למשתמש אחרי ביצוע ההזמנה, כמו יצירת קשר עם תמיכת הלקוחות וצפייה בפרטי ההזמנה.
  • totalPrice: המחיר הכולל של ההזמנה. הפעולה הזאת אופציונלית. שולחים רק אם המחיר הכולל של ההזמנה השתנה אחרי שליחת ההזמנה.

ההזמנה יכולה להיות באחד מהמצבים הבאים:

  • CREATED: נקודת הקצה לטיפול בהזמנות עיבדתה את ההזמנה בהצלחה, אבל הספק עדיין לא אישר אותה.
  • CONFIRMED: ההזמנה טופלה בהצלחה בנקודת הקצה לטיפול בהזמנות, והספק אישר אותה.
  • REJECTED: הייתה בעיה ונקודת הקצה לטיפול בהזמנות לא הצליחה ליצור או לאשר את ההזמנה. הבעיה יכולה להיות בעיה בתשלום.

אם מגדירים הזמנה למצב REJECTED, צריך לציין את הסיבה בשדה rejectionInfo של OrderUpdate. משתמשים בערכי FoodOrderUpdateExtension.FoodOrderErrors בשילוב עם rejectionInfo מסוג UNKNOWN ומספקים תיאור.

דוגמה לתגובה להזמנה

דוגמה ל-SubmitOrderResponseMessage:

JSON
{
  "finalResponse": {
    "richResponse": {
      "items": [
        {
          "structuredResponse": {
            "orderUpdate": {
              "actionOrderId": "1603357328160",
              "orderState": {
                "state": "CONFIRMED",
                "label": "Pending"
              },
              "updateTime": "2020-10-22T02:02:08-07:00",
              "orderManagementActions": [
                {
                  "type": "CUSTOMER_SERVICE",
                  "button": {
                    "title": "Call customer service",
                    "openUrlAction": {
                      "url": "tel:+61234561000"
                    }
                  }
                },
                {
                  "type": "VIEW_DETAILS",
                  "button": {
                    "title": "View order details",
                    "openUrlAction": {
                      "url": "https://partner.com/view/orderstatus"
                    }
                  }
                }
              ],
              "receipt": {
                "userVisibleOrderId": "BXZ-1603357328"
              }
            }
          }
        }
      ]
    }
  }
}

בקשה שנכשלה

אם שליחת בקשה נכשלת, SubmitOrderResponseMessage צריך להגדיר את OrderState.state ל-REJECTED. התשובה חייבת לכלול גם את RejectionInfo, שמכיל אובייקט RejectionType שמתאר את סוג השגיאה.

דוגמה לתגובה לא מוצלחת

JSON
{
  "expectUserResponse": false,
  "finalResponse": {
    "richResponse": {
      "items": [
        {
          "structuredResponse": {
            "orderUpdate": {
              "actionOrderId": "sample_action_order_id",
              "orderState": {
                "state": "REJECTED",
                "label": "Order rejected"
              },
              "updateTime": "2017-05-10T02:30:00.000Z",
              "rejectionInfo": {
                "type": "PAYMENT_DECLINED",
                "reason": "Insufficient funds"
              },
              "orderManagementActions": [
                {
                  "type": "CUSTOMER_SERVICE",
                  "button": {
                    "title": "Contact customer service",
                    "openUrlAction": {
                      "url": "mailto:support@example.com"
                    }
                  }
                },
                {
                  "type": "EMAIL",
                  "button": {
                    "title": "Email restaurant",
                    "openUrlAction": {
                      "url": "mailto:person@example.com"
                    }
                  }
                },
                {
                  "type": "CALL",
                  "button": {
                    "title": "Call restaurant",
                    "openUrlAction": {
                      "url": "tel:+16505554679"
                    }
                  }
                },
                {
                  "type": "VIEW_DETAILS",
                  "button": {
                    "title": "View order",
                    "openUrlAction": {
                      "url": "https://orderview.partner.com?orderid=sample_action_order_id"
                    }
                  }
                }
              ]
            }
          }
        }
      ]
    }
  }
}
    

שליחת בקשה להטמעת ההזמנה

כך מטמיעים את ה-API לשליחת הזמנות:

אימות

  1. מבצעים אימותים של שירותים, עגלות קניות וקידומי מכירות, כפי שמתואר בקטע הגדרת תהליך התשלום.
  2. אם צריך, מחזירים את RejectionInfo עם אחד מהסוגים הבאים:
RejectionInfoType תרחיש לדוגמה
UNAVAILABLE_SLOT זמן האספקה כבר לא תקף.
PROMO_USER_INELIGIBLE כדי לאמת את הזכאות של המשתמש למבצע, משתמשים בכתובת האימייל באובייקט Contact בבקשה. אפשר לעיין בדוגמה בקטע הטמעת שליחת הזמנה עם מבצעים.
INELIGIBLE
  • פרטי המשתמש, כמו מספר טלפון או כתובת אימייל, לא תקינים.
  • מנוע הסיכונים מזהה הונאה.
PAYMENT_DECLINED לא ניתן לעבד את התשלום. לדוגמה, יכול להיות שהסיבה לכך היא יתרה לא מספיקה בחשבון.
UNKNOWN בכל שגיאת אימות אחרת.

אם נתקלתם בשגיאות אימות, מגדירים את OrderState.state לערך REJECTED. לחלופין, אפשר לציין סיבה ספציפית לדחייה באמצעות התוסף FoodOrderUpdateExtension.foodOrderErrors. דוגמאות מפורטות במאמר אימות של שליחת הזמנה.

עיבוד התשלום

  1. מחושבים את totalPrice על ידי הוספת המחיר של עגלת הקניות, העמלות, ההנחות, המיסים והטיפ. הערך של totalPrice צריך להיות זהה לערך של totalPrice שהוחזר ב-CheckoutResponseMessage, בתוספת השינוי בסכום התשר אם המשתמש יכול לשנות את התשר. פרטים נוספים זמינים במאמר שינויים במחיר במהלך שליחת ההזמנה.
  2. מעבדים את ההזמנה ואת התשלום אם מחזירים תשובה עם סטטוס ההזמנה CREATED או CONFIRMED.
  3. כדי לוודא שהתגובה שתוחזר תהיה בפורמט תקין, צריך להשתמש בסוגי נתונים שנוצרו מהסכימה, כפי שמתואר במאמר יצירת ספריות לקוח.
  4. כדי לעבד את התשלום, משתמשים ב-GoogleProvidedPaymentInstrument.instrumentToken. אם לא ניתן לעבד את התשלום, מחזירים את הערך RejectionInfo עם הערך PAYMENT_DECLINED. פרטים נוספים זמינים במאמר עיבוד תשלומים.
  5. הודעה למשתמש מיד אחרי עיבוד ההזמנה באימייל או ב-SMS.

החזרת התשובה

  1. אם אין שגיאות, מגדירים את OrderState.state לערך CREATED או CONFIRMED.
  2. אם נתקלת בשגיאות, צריך להגדיר את OrderState.state לערך REJECTED ולכלול את האובייקט RejectionInfo עם הערך המתאים של RejectionInfoType.
  3. מגדירים את OrderUpdate.orderManagementActions.