إعداد Checkout

يتمّ استدعاء عملية الدفع عندما ينشئ المستخدِم سلة تسوّق. يتم إرسال محتويات سلة التسوّق الخاصة بالمستخدم وتفاصيل عن الطلب إلى خدمة الويب Ordering End-to-End. تُجري خدمة الويب عملية التحقّق من صحة هذه المعلومات، ويمكنك بعد ذلك إما المتابعة أو إجراء تعديلات على سلة التسوّق حسب الحاجة.

يجب أن يستجيب معالِج الدفع لخدمة الويب لطلبات POST. عندما يختار العميل الدفع، ترسل Google إلى خدمة الويب Ordering End-to-End (الطلب من البداية إلى النهاية) ملف JSON يتضمن CheckoutRequestMessage يتضمّن تفاصيل Cart العميل. بعد ذلك، تستجيب خدمة الويب برمز العميل CheckoutResponseMessage. يوضِّح الرسم البياني التالي هذه العملية.

تعرِض CheckoutResponseMessage سلة التسوق غير المعدَّلة للعميل أو
خطأ.

عند تلقّي طلب دفع، يجب أن تُجري خدمة الويب "الطلب من البداية إلى النهاية" الخطوات التالية:

  • تحقَّق من صلاحية سلة التسوّق استنادًا إلى أسعار السلع الحالية ومدى توفّرها وخدمة مقدّم الخدمة.
  • احتسِب السعر الإجمالي (بما في ذلك أي خصومات وضرائب ورسوم تسليم).
  • إذا كانت الاستجابة ناجحة، يجب الردّ باستخدام سلة تسوّق لم يتم تعديلها.
  • إذا لم تنجح، يمكنك الردّ برسالة خطأ وترتيب جديد مقترَح.

قبل بدء تنفيذ عملية الدفع، ننصحك بمراجعة المعلومات العامة عن عملية التسليم.

رسالة طلب الدفع

للتحقّق من سلة التسوق الخاصة بالعميل، عندما يختار العميل الدفع، تُرسِل Google طلبًا إلى خدمة الويب الخاصة بك يتضمّن نص JSON بتنسيق CheckoutRequestMessage. لا يتم إرسال طلب العميل إلا في وقت لاحق من خطوات عملية الطلب الشاملة.

تشمل البيانات الواردة في ملف 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
}

رسالة الردّ على الدفع

بعد تلقّي طلب من خدمة "الطلب من البداية إلى النهاية"، يجب أن تعالج web service الخاصة بعملية الدفع الطلب وتردّ عليه باستخدام CheckoutResponseMessage. يجب أن يتناول الجدول CheckoutResponseMessage طلبًا ناجحاً أو غير ناجح.

طلب ناجح

إذا تم قبول طلب الفحص، يجب أن يتضمّن CheckoutResponseMessage كلاً من ProposedOrder و PaymentOptions:

  • ProposedOrder

    • cart: عنصر cart مطابق لسلة التسوّق المقدَّمة في CheckoutRequestMessage إذا كان يجب تغيير أيّ من محتوى سلة التسوّق، يجب أن يتضمّن CheckoutResponseMessage بدلاً من ذلك FoodErrorExtension يحتوي على ProposedOrder معدَّل.
    • otherItems: العناصر التي يضيفها مقدّم الخدمة، مثل رسوم التسليم والضرائب وغيرها من الرسوم قد يتضمّن أيضًا إكرامية أضافها المستخدم.
    • totalPrice: إجمالي سعر الطلب
    • extension: FoodOrderExtension لتحديد معلومات التسليم للطلب، مثل وقت التسليم
  • PaymentOptions

    • يتم تناول إعداد معالجة الدفعات لاحقًا في مقالة إعداد Google Pay. يمكنك استخدام العنصر النائب بتنسيق JSON في CheckoutResponseMessage إلى أن تصبح جاهزًا لتنفيذ معالجة الدفعات.
    • لإضافة خيارات الدفع النائبة في CheckoutResponseMessage، يُرجى الرجوع إلى المثال أدناه الذي يستخدم مثالًا لمدخل دفع في PaymentOptions.

مثال على استجابة ناجحة

{
    "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 لحالة خطأ الخدمة الأولى التي تم العثور عليها لا يمكن استرداد هذه الأخطاء، لذا يجب عرض أول خطأ تم رصده. اطّلِع على معالجة الأخطاء للحصول على وصف للأخطاء القابلة للاسترداد.

  1. اطّلِع على سمة FulfillmentOptionInfo في الطلب لتحديد ما إذا كان نوع طريقة توفّر المنتج مخصّصًا لـ delivery أو pickup.
  2. عرض أنواع الأخطاء التالية إذا لزم الأمر:

    نوع الخطأ حالة الاستخدام
    INVALID نوع الإنجاز غير صالح.
    NOT_FOUND لم يتم العثور على نوع الإنجاز.
    مغلقة
    • لا تتوفّر فترات OperationHours للطلب.
    • الطلب هو طلب في أقرب وقت ممكن ولا تتوفّر ServiceHours في أقرب وقت ممكن في الوقت الحالي.
    • تم إغلاق المحطة بسبب حالة طوارئ أو كانت الخدمة isDisabled صحيحة.
    تجدر الإشارة إلى أنّ النوافذ الخاصة لها الأولوية على النوافذ العادية. اطّلِع على الأمثلة في التحقّق من فترة الطلب وإزالة كيانات الخدمة مؤقتًا.
    UNAVAILABLE_SLOT لا يمكن تنفيذ وقت الطلب المُسبَق.
    NO_CAPACITY المطعم مشغول ولا يتلقّى طلبات في الوقت الحالي.
    OUT_OF_SERVICE_AREA لا يمكن تسليم الطلب إلى عنوان المستخدم. اطّلِع على التحقّق من صحة عنوان التسليم للاطّلاع على مثال.
    NO_COURIER_AVAILABLE لا يمكن تسليم الطلب بسبب قلة عدد موظفي التسليم.

التحقّق من سلة التسوّق وتحديد أسعارها

  1. ابحث عن كل سلة تسوّق.lineItems وتحقّق من صحتها باستخدام البيانات الحالية في نظامك أو في نظام التاجر. يتم تضمين قيمة MenuItemOffer.sku من عنصر الخلاصة بصفتها LineItem.offerId. أنشئ عنصر FoodOrderError لكل عنصر في القائمة إذا لزم الأمر. أنشئ خطأً واحدًا كحد أقصى لكل عنصر. عرض أنواع الأخطاء التالية إذا كان ذلك ضروريًا:

    نوع الخطأ حالة الاستخدام يمكن استردادها
    INVALID بيانات السلعة أو أيّ من بيانات الخيارات غير صالحة. لا
    NOT_FOUND تعذّر العثور على العنصر أو أي من الخيارات. لا
    PRICE_CHANGED تغيّر سعر سلعة أو مجموعة إضافات. يمكن التعامل مع هذا الخطأ على أنّه قابل للاسترداد. نعم
    AVAILABILITY_CHANGED المبلغ المطلوب للعناصر أو أيّ من الخيارات غير متوفّر. نعم
    REQUIREMENTS_NOT_MET لم يتم استيفاء الحد الأدنى أو الحد الأقصى للطلب. ويمكن تحديد ذلك من خلال التحقّق مما إذا كان سعر سلة التسوّق أقل من الرسومeligibleTransactionVolumeMin أو أعلى من الرسومeligibleTransactionVolumeMax. اطّلِع على المثال في التحقّق من الحدّ الأدنى لقيمة طلب الشراء. لا
  2. عرض قائمة عناصر سلع تم التحقّق منها باستخدام LineItemType REGULAR مجموع جميع أسعار سلة التسوّق هو سعر سلة التسوّق أو SUBTOTAL.

اطّلِع على الأمثلة في التحقّق من سلع سلة التسوّق.

احتساب رسوم الخدمة

  1. ابحث عن عنصر الرسوم الصحيح للخدمة استنادًا إلى eligibleRegion وvalidFrom وvalidThrough وpriority.
  2. احتسِب مبلغ الرسوم استنادًا إلى ما إذا تم تعريف الكيان باستخدام سمة price أو percentageOfCart أو pricePerMeter.
  3. أعِد عرض رسوم خدمة التوصيل أو خدمة تناول الطعام في الخارج كعنصر LineItem مع LineItemType DELIVERY أو FEE على التوالي. أضِف الرسوم إلى قائمة سلة التسوّق.otherItems

تطبيق العروض الترويجية

  1. ابحث عن عنصر العرض استنادًا إلى مطابقة قيمة العرض الترويجي.coupon مع العرض.dealCode.
  2. تحقّق من الصفقة وأعِد عرض FoodOrderError إذا لزم الأمر. يمكن التعامل مع هذه الأخطاء على أنّها قابلة للاسترداد. عرض أنواع الأخطاء التالية إذا لزم الأمر:

    نوع الخطأ حالة الاستخدام
    PROMO_NOT_RECOGNIZED لم يتم التعرّف على رمز القسيمة.
    PROMO_EXPIRED انتهت صلاحية الصفقة.
    PROMO_ORDER_INELIGIBLE الطلب غير مؤهّل لاستخدام القسيمة.
    PROMO_NOT_APPLICABLE أي سبب آخر
  3. احتسِب مبلغ سعر الصفقة استنادًا إلى Deal.discount أو Deal.discountPercentage.

  4. طبِّق مبلغ سعر الصفقة باستخدام إجمالي سلة التسوّق أو إجمالي الرسوم استنادًا إلى الصفقة.dealType.

  5. ارجع إلى سلة التسوّق.promotions مع العرض الترويجي المُطبَّق.

  6. عرض العرض الترويجي كعنصر LineItem مع LineItemType DISCOUNT أضِف الخصم إلى قائمة سلة التسوّق.otherItems باستخدام سعر سلبي.

عرض الردّ

  1. أنشئ ProposedOrder.cart، تكون سلة التسوّق في الردّ مماثلة لسلة التسوّق في الطلب في حال عدم حدوث أي أخطاء أثناء التحقّق.
  2. عرض قائمة ProposedOrder.otherItems بما في ذلك الضريبة والرسوم والإكرامية والخصم في حال تطبيقه اطّلِع على الإكرامية للحصول على مزيد من التفاصيل حول كيفية ضبط عنصر الإكرامية.
  3. أدرِج ProposedOrder.totalPrice من خلال إضافة سعر سلة التسوّق والرسوم والخصومات والضرائب والإكرامية.
  4. أعِدFoodOrderExtension.availableFulfillmentOptions معFulfillmentOption المعنيّ. عدِّل المدة المُقدَّرة لاستلام الطلب أو تسليمه إلى المدة المتوقّعة.
  5. إذا كانت هناك أخطاء FoodOrderErrors تم إنشاؤها من عمليات التحقّق السابقة من الصحة:
    • أدرِج StructuredResponse.error وقائمة بالأخطاء في FoodErrorExtension.foodOrderErrors.
    • عرض ProposedOrder في الحقل correctedProposedOrder إذا كان بالإمكان استرداد جميع الأخطاء
    • عرض PaymentOptions في الحقل paymentOptions إذا كان بالإمكان استرداد جميع الأخطاء
    • يمكنك اختياريًا تضمين additionalPaymentOptions إذا كانت هناك خيارات دفع أخرى متاحة وكان من الممكن استرداد جميع الأخطاء.
  6. إذا لم تكن هناك أخطاء في التحقّق، أعِد القيمة proposedOrder، paymentOptions في عنصر CheckoutResponse. يمكنك تضمين additionalPaymentOptions اختياريًا إذا كانت هناك خيارات دفع أخرى متوفرة.