Promotions

Les promotions vous permettent, à vous et à Google, d'inciter les clients à essayer votre service de commande de repas en leur proposant des remises. Google vous permet d'intégrer vos actions de bout en bout de commande à votre système de gestion des promotions.

Les types de remises suivants sont acceptés:

  • Codes promotionnels sponsorisés par Google:codes promotionnels préremplis automatiquement par Google ou saisis par les utilisateurs.
  • Codes promotionnels sponsorisés par des tiers:codes promotionnels que les utilisateurs doivent saisir, fournis par votre service de commande de repas.
  • Remises automatiques sponsorisées par des tiers:remises appliquées automatiquement par votre service de commande de repas sans code promotionnel.

Quel que soit le type de remise, Google appelle le service de traitement des commandes de repas pour vérifier et appliquer la remise.

En tant que développeur d'un service de commande de repas, vous devez apporter quelques modifications à votre implémentation pour calculer les remises pour les codes promotionnels valides ou envoyer des erreurs pour les codes promotionnels non valides, gérer les limites d'utilisation des codes promotionnels et suivre les données comptables pour le remboursement.

Traiter les promotions

Pour implémenter un traitement compatible avec les promotions, procédez comme suit:

  1. Configurez l'intégration des promotions. (Ignorez cette étape si vous n'utilisez pas de codes promotionnels sponsorisés par Google.)
  2. Implémentez le paiement avec des promotions.
  3. Implémentez l'envoi de la commande avec des promotions.

Configurer l'intégration des promotions

Cette section explique comment configurer l'intégration des promotions si vous prévoyez d'utiliser des codes promotionnels sponsorisés par Google. Si vous ne souhaitez accepter que les codes promotionnels ou les remises sponsorisés par un tiers, vous pouvez spécifier votre propre configuration et ignorer cette section.

Google spécifie le type de promotion à sponsoriser et vous contacte pour configurer l'intégration. Nous fournissons les informations suivantes:

  • Montant de la remise.
  • Valeur minimale du panier.
  • Dates de début et de fin de validité des codes promotionnels.
  • Montant maximal en dollars budgété pour la campagne promotionnelle.
  • Nombre de fois que les codes promotionnels peuvent être utilisés.

Exemples de codes promotionnels:

  • FopaNewUser: 10% (pourcentage fixe) avec une remise maximale de 50 $.
  • FopaMoreThan50: 10 $ (remise fixe).

Si Google décide de suspendre l'application du code, vous serez contacté.

Configurer les versements

Contactez votre consultant Google EAP pour configurer le processus de versement. Google ne rembourse les transactions impliquant des codes promotionnels sponsorisés par Google que si l'état final de la commande est l'un des suivants:

  • CONFIRMED
  • IN_TRANSIT
  • READY_FOR_PICKUP
  • IN_PREPARATION
  • FULFILLED

Implémenter le paiement avec des promotions

Cette section décrit l'implémentation du traitement du règlement lorsque vous acceptez les codes promotionnels (sponsorisés par Google ou par un tiers). Pour les remises automatiques sponsorisées par des tiers, il vous suffit de renvoyer l'article de la remise dans CheckoutResponseMessage (aucune vérification du code promotionnel n'est nécessaire).

Lors du traitement d'une commande de repas, Google envoie un seul code promotionnel dans le champ CheckoutRequestMessage à votre prestataire de livraison. Les utilisateurs peuvent modifier leur panier ou leur code promotionnel lors de demandes de paiement répétées.

Pour vérifier si l'utilisateur applique un code promotionnel pour la première fois, procédez comme suit:

  • Codes promotionnels sponsorisés par Google: Google vérifie si un utilisateur revient et tente d'utiliser à nouveau le même code promotionnel. Aucune action de votre part n'est requise.
  • Codes promotionnels sponsorisés par des tiers ou remises automatiques: si vous n'avez pas implémenté l'association de compte et l'acceptation par l'utilisateur, vous ne pourrez pas vérifier les informations de l'utilisateur lors du traitement de la demande de paiement. Vérifiez plutôt cela lors du traitement SubmitOrderRequestMessage, à l'aide des informations Contact (telles que l'adresse e-mail de l'utilisateur) de l'objet FoodCartExtension.

Identifiez les erreurs ou calculez les remises avec votre traitement en fonction de la dernière requête de règlement. Assurez-vous que votre système ne conserve pas d'informations d'état obsolètes.

Vérifier la validité d'un code promotionnel

Votre prestataire de traitement doit vérifier la validité ou l'éligibilité d'un code promotionnel donné par rapport aux conditions stipulées, telles que la date d'expiration, l'utilisation maximale et la remise maximale. Ensuite, répondez de manière appropriée dans CheckoutResponseMessage avec la remise calculée ou avec foodOrderErrors si le code promotionnel ne peut pas être appliqué. Si vous détectez des erreurs avec le code promotionnel, suivez la procédure décrite dans Gérer les erreurs liées aux promotions.

L'extrait de code suivant présente un exemple de foodOrderErrors pour un code promotionnel. Assurez-vous que correctedProposedOrder n'inclut pas le nœud "promotions".

"foodOrderErrors": [
  {
    "error": "PROMO_NOT_APPLICABLE",
    // Copy promotions.coupon string from CheckoutRequest as the ID
    "id": "GoogleNewUser",
    "description": "Promotion could not be applied"
  }
],
"correctedProposedOrder": {// required ...},
"paymentOptions": {// required ...}

Remises sur le calcul

Si le code promotionnel est valide, votre traitement doit calculer la valeur de la remise en dollars et renvoyer un CheckoutResponseMessage avec la valeur de la remise calculée dans le tableau otherItems. Le prix total de la commande ne doit pas être négatif. Si le montant de la remise dépasse le montant du panier, renvoyez le montant maximal en dollars pour que le prix total de la commande soit de 0 $.

L'extrait de code suivant présente un exemple de section CheckoutResponseMessage pour la remise promotionnelle:

"proposedOrder": {
   "otherItems": [
      . . .
      {
        "name": "Discount",
        // copy promotions.coupon field from CheckoutRequest as the id
        "id": "GoogleNewUser",
        "price": {
          "type": "ESTIMATE",
          "amount": {
          "currencyCode": "USD",
          "units": "-3",
          "nanos": -500000000
        }
      },
      "type": "DISCOUNT",
    }
  ]
}

Libérer les promotions inutilisées

Toutes les demandes de paiement ne donnent pas lieu à une demande d'envoi de commande. Si votre service de traitement des commandes bloque une promotion au moment de l'appel de règlement, assurez-vous de mettre en place un mécanisme permettant de lever le blocage si la promotion n'est pas réclamée via l'envoi de la commande au bout d'un certain temps. Cela permet de s'assurer que votre service de commande de repas maintient le quota de campagne approprié.

Gérer les erreurs liées aux promotions

Si votre traitement détermine que le code promotionnel d'un CheckoutRequestMessage n'est pas valide (par exemple, qu'il a expiré, qu'il n'est pas valide ou qu'il n'est pas reconnu), envoyez un CheckoutResponseMessage avec un foodOrderError contenant le code d'erreur et le texte de motif applicables, ainsi que des objets correctedProposedOrder et paymentOptions.

Si votre traitement détecte plusieurs erreurs de code promotionnel pour une même requête, renvoyez les erreurs irrécupérables avant les erreurs récupérables. Priorisez vos vérifications comme suit (de la priorité la plus élevée à la plus faible):

  • PROMO_NOT_RECOGNIZED
  • PROMO_EXPIRED
  • PROMO_USER_INELIGIBLE
  • PROMO_ORDER_INELIGIBLE
  • PROMO_NOT_APPLICABLE

Exemples

Voici un exemple de requête de paiement avec un code promotionnel:

{
    "accessToken": "test_access_token",
    "lastSeen": "2018-06-22T19:25:39Z"
  },
  "conversation": {
    "conversationId": "XYZ"
  },
  "inputs": [
    {
      "intent": "actions.foodordering.intent.CHECKOUT",
      "arguments": [
        {
          "extension": {
            "@type": "type.googleapis.com/google.actions.v2.orders.Cart",
            "merchant": {
              "id": "https://www.exampleprovider.com/merchant/id1",
              "name": "Falafel Bite"
            },
            "lineItems": [
              {
                "name": "Falafel Tray",
                "type": "REGULAR",
                "id": "sample_item_offer_id_1",
                "quantity": 1,
                "price": {
                  "type": "ESTIMATE",
                  "amount": {
                    "currencyCode": "USD",
                    "units": "9",
                    "nanos": 950000000
                  }
                },
                "offerId": "https://www.exampleprovider.com/menu/item/offer/id1",
                "extension": {
                  "@type": "type.googleapis.com/google.actions.v2.orders.FoodItemExtension"
                }
              }
            ],
            "promotions": [
              {
                "coupon": "FOPAACTIVECODE"
              }
            ],
            "extension": {
              "@type": "type.googleapis.com/google.actions.v2.orders.FoodCartExtension",
              "fulfillmentPreference": {
                "fulfillmentInfo": {
                  "pickup": {
                    "pickupTimeIso8601": "P0M"
                  }
                }
              }
            }
          }
        }
      ]
    }
  ],
  "directActionOnly": true,
  "isInSandbox": true
}

Voici la réponse de règlement correspondante du traitement si le code promotionnel est valide:

{
  "expectUserResponse": false,
  "finalResponse": {
    "richResponse": {
      "items": [
        {
          "structuredResponse": {
            "checkoutResponse": {
              "proposedOrder": {
                "otherItems": [
                  {
                    "name": "Delivery Fees",
                    "price": {
                      "type": "ESTIMATE",
                      "amount": {
                        "currencyCode": "USD",
                        "units": "3",
                        "nanos": 500000000
                      }
                    },
                    "type": "DELIVERY"
                  },
                  {
                    "name": "Tax",
                    "price": {
                      "type": "ESTIMATE",
                      "amount": {
                        "currencyCode": "USD",
                        "units": "1",
                        "nanos": 370000000
                      }
                    },
                    "type": "TAX"
                  },
                  {
                    "name": "Promotion",
                    "price": {
                      "type": "ESTIMATE",
                      "amount": {
                        "currencyCode": "USD",
                        "units": "-5",
                        "nanos": 0
                      }
                    },
                    "id": "FOPAACTIVECODE",
                    "type": "DISCOUNT"
                  }
                ],
                "cart": {
                  "merchant": {
                    "id": "https://www.exampleprovider.com/merchant/id1",
                    "name": "Falafel Bite"
                  },
                  "lineItems": [
                    {
                      "name": "Falafel Tray",
                      "type": "REGULAR",
                      "id": "2529103",
                      "quantity": 1,
                      "price": {
                        "type": "ESTIMATE",
                        "amount": {
                          "currencyCode": "USD",
                          "units": "9",
                          "nanos": 950000000
                        }
                      },
                      "offerId": "https://www.exampleprovider.com/menu/item/offer/id1",
                      "extension": {
                        "@type": "type.googleapis.com/google.actions.v2.orders.FoodItemExtension"
                      }
                    }
                  ],
                  "promotions": [
                    {
                      "coupon": "FOPAACTIVECODE"
                    }
                  ],
                  "extension": {
                    "@type": "type.googleapis.com/google.actions.v2.orders.FoodCartExtension",
                    "fulfillmentPreference": {
                      "fulfillmentInfo": {
                        "pickup": {
                          "pickupTimeIso8601": "P0M"
                        }
                      }
                    }
                  }
                },
                "totalPrice": {
                  "type": "ESTIMATE",
                  "amount": {
                    "currencyCode": "USD",
                    "units": "9",
                    "nanos": 820000000
                  }
                },
                "extension": {
                  "@type": "type.googleapis.com/google.actions.v2.orders.FoodOrderExtension",
                  "availableFulfillmentOptions": [
                    {
                      "fulfillmentInfo": {
                        "pickup": {
                          "pickupTimeIso8601": "P0M"
                        }
                      },
                      "expiresAt": "2018-06-22T19:30:52.596Z"
                    }
                  ]
                }
              },
              "orderOptions": {},
              "paymentOptions": {
                "googleProvidedOptions": {
                  "tokenizationParameters": {
                    "tokenizationType": "PAYMENT_GATEWAY",
                    "parameters": {
                      "gateway": "stripe",
                      "stripe:publishableKey": "example_stripe_client_key",
                      "stripe:version": "2017-04-06"
                    }
                  },
                  "supportedCardNetworks": [
                    "AMEX",
                    "DISCOVER",
                    "MASTERCARD",
                    "VISA",
                    "JCB"
                  ],
                  "prepaidCardDisallowed": true
                }
              }
            }
          }
        }
      ],
      "suggestions": []
    }
  }
}

Voici un exemple de réponse de paiement si le code promotionnel n'est pas valide:

{
  "expectUserResponse": false,
  "finalResponse": {
    "richResponse": {
      "items": [
        {
          "structuredResponse": {
            "error": {
              "foodOrderErrors": [
                {
                  "error": "PROMO_NOT_RECOGNIZED",
                  "id": "SOMEPROMO",
                  "description": "Coupon not found"
                }
              ],
              "correctedProposedOrder": {
                "cart": {
                  "merchant": {
                    "id": "https://www.exampleprovider.com/merchant/id1",
                    "name": "Falafel Bite"
                  },
                  "lineItems": [
                    {
                      "id": "sample_item_offer_id_4",
                      "name": "Prawns Biryani",
                      "type": "REGULAR",
                      "quantity": 1,
                      "price": {
                        "type": "ESTIMATE",
                        "amount": {
                          "currencyCode": "USD",
                          "units": "18",
                          "nanos": 750000000
                        }
                      },
                      "offerId": "https://www.exampleprovider.com/menu/item/offer/id4",
                      "extension": {
                        "@type": "type.googleapis.com/google.actions.v2.orders.FoodItemExtension"
                      }
                    }
                  ],
                  "extension": {
                    "fulfillmentPreference": {
                      "fulfillmentInfo": {
                        "pickup": {
                          "pickupTimeIso8601": "P0M"
                        }
                      }
                    },
                    "@type": "type.googleapis.com/google.actions.v2.orders.FoodCartExtension"
                  },
                  "promotions": []
                },
                "otherItems": [
                  {
                    "name": "Tax",
                    "type": "TAX",
                    "price": {
                      "type": "ESTIMATE",
                      "amount": {
                        "currencyCode": "USD",
                        "units": "1",
                        "nanos": 650000000
                      }
                    }
                  }
                ],
                "termsOfServiceUrl": "https://exampleprovider.com/terms",
                "totalPrice": {
                  "type": "ESTIMATE",
                  "amount": {
                    "currencyCode": "USD",
                    "units": "20",
                    "nanos": 400000000
                  }
                },
                "extension": {
                  "availableFulfillmentOptions": [
                    {
                      "fulfillmentInfo": {
                        "pickup": {
                          "pickupTimeIso8601": "PT0M"
                        }
                      }
                    }
                  ],
                  "@type": "type.googleapis.com/google.actions.v2.orders.FoodOrderExtension"
                }
              },
              "paymentOptions": {
                "googleProvidedOptions": {
                  "prepaidCardDisallowed": false,
                  "billingAddressRequired": true,
                  "tokenizationParameters": {
                    "tokenizationType": "PAYMENT_GATEWAY",
                    "parameters": {
                      "gateway": "braintree",
                      "braintree:apiVersion": "v1",
                      "braintree:sdkVersion": "1.4.0",
                      "braintree:merchantId": "example_braintree_merchant_ID",
                      "braintree:clientKey": "example_braintree_client_key",
                      "braintree:authorizationFingerprint": "example_braintree_fingerprint"
                    }
                  }
                }
              },
              "@type": "type.googleapis.com/google.actions.v2.orders.FoodErrorExtension"
            }
          }
        }
      ]
    }
  }
}

Implémenter l'envoi de la commande avec des promotions

Dans votre traitement de la commande, vérifiez si l'utilisateur applique un code promotionnel pour la première fois. Lors du traitement de SubmitOrderRequestMessage, vous pouvez vérifier cela à l'aide des informations Contact (telles que l'adresse e-mail de l'utilisateur) de l'objet FoodCartExtension.

Vous devez également vérifier à nouveau l'éligibilité du code promotionnel:

  • Si le code est applicable, confirmez la commande et indiquez que le bon de réduction a été utilisé.
  • Si le code n'est plus applicable:refusez la commande avec l'erreur PROMO_NOT_APPLICABLE. Vous pouvez fournir une raison de refus spécifique à l'aide du même mécanisme que pour FoodOrderUpdateExtension.

Exemples

Voici un exemple de requête d'envoi de commande avec des promotions:

{
  "conversation": {
    "conversationId": "example_conversation_ID"
  },
  "inputs": [
    {
      "intent": "actions.intent.TRANSACTION_DECISION",
      "arguments": [
        {
          "transactionDecisionValue": {
            "order": {
              "finalOrder": {
                "cart": {
                  "merchant": {
                    "id": "https://www.exampleprovider.com/merchant/id1",
                    "name": "Falafel Bite"
                  },
                  "lineItems": [
                    {
                      "name": "Falafel Tray",
                      "type": "REGULAR",
                      "id": "sample_item_offer_id_1",
                      "quantity": 1,
                      "price": {
                        "type": "ESTIMATE",
                        "amount": {
                          "currencyCode": "USD",
                          "units": "9",
                          "nanos": 950000000
                        }
                      },
                      "offerId": "https://www.exampleprovider.com/menu/item/addon/offer/id1",
                      "extension": {
                        "@type": "type.googleapis.com/google.actions.v2.orders.FoodItemExtension"
                      }
                    }
                  ],
                  "promotions": [
                    {
                      "coupon": "FOPAACTIVECODE"
                    }
                  ],
                  "extension": {
                    "@type": "type.googleapis.com/google.actions.v2.orders.FoodCartExtension",
                    "fulfillmentPreference": {
                      "fulfillmentInfo": {
                        "pickup": {
                          "pickupTimeIso8601": "P0M"
                        }
                      }
                    },
                    "contact": {
                      "displayName": "Food Ordering",
                      "email": "example.provider@gmail.com",
                      "phoneNumber": "+19993334444",
                      "firstName": "Food",
                      "lastName": "Ordering"
                    }
                  }
                },
                "otherItems": [
                  {
                    "name": "Delivery Fees",
                    "type": "DELIVERY",
                    "price": {
                      "type": "ESTIMATE",
                      "amount": {
                        "currencyCode": "USD",
                        "units": "3",
                        "nanos": 500000000
                      }
                    }
                  },
                  {
                    "name": "Tax",
                    "type": "TAX",
                    "price": {
                      "type": "ESTIMATE",
                      "amount": {
                        "currencyCode": "USD",
                        "units": "1",
                        "nanos": 370000000
                      }
                    }
                  },
                  {
                    "name": "Promotion",
                    "type": "DISCOUNT",
                    "price": {
                      "type": "ESTIMATE",
                      "amount": {
                        "currencyCode": "USD",
                        "units": "-5"
                      }
                    },
                    "id": "FOPAACTIVECODE"
                  },
                  {
                    "name": "Subtotal",
                    "type": "SUBTOTAL",
                    "price": {
                      "type": "ESTIMATE",
                      "amount": {
                        "currencyCode": "USD",
                        "units": "9",
                        "nanos": 950000000
                      }
                    }
                  },
                  {
                    "name": "Tip",
                    "type": "GRATUITY",
                    "price": {
                      "type": "ESTIMATE",
                      "amount": {
                        "currencyCode": "USD"
                      }
                    }
                  }
                ],
                "totalPrice": {
                  "type": "ESTIMATE",
                  "amount": {
                    "currencyCode": "USD",
                    "units": "9",
                    "nanos": 820000000
                  }
                },
                "extension": {
                  "@type": "type.googleapis.com/google.actions.v2.orders.FoodOrderExtension"
                }
              },
              "googleOrderId": "example_google_order_ID",
              "orderDate": "2018-06-22T19:30:59.502Z",
              "paymentInfo": {
                "displayName": "example_display_name",
                "googleProvidedPaymentInstrument": {
                  "instrumentToken": "example_instrument_token"
                },
                "paymentType": "PAYMENT_CARD"
              },
              "locale": "en"
            }
          }
        }
      ]
    }
  ],
  "directActionOnly": true,
  "isInSandbox": true
}

Voici un exemple de réponse d'envoi de commande correspondante d'un traitement si le code promotionnel est valide:

{
  "expectUserResponse": false,
  "finalResponse": {
    "richResponse": {
      "items": [
        {
          "structuredResponse": {
            "orderUpdate": {
              "actionOrderId": "example_action_order_ID",
              "orderState": {
                "state": "CREATED",
                "label": "Order is created with partner."
              },
              "updateTime": "2018-06-22T19:31:01.556Z",
              "orderManagementActions": [
                {
                  "type": "CALL_RESTAURANT",
                  "button": {
                    "title": "Call Us",
                    "openUrlAction": {
                      "url": "tel:+1-111-111-1111"
                    }
                  }
                },
                {
                  "type": "EMAIL",
                  "button": {
                    "title": "Email Us",
                    "openUrlAction": {
                      "url": "mailto:example.provider@gmail.com"
                    }
                  }
                },
                {
                  "type": "CUSTOMER_SERVICE",
                  "button": {
                    "title": "Customer Service",
                    "openUrlAction": {
                      "url": "http://www.google.com"
                    }
                  }
                }
              ]
            }
          }
        }
      ],
      "suggestions": []
    }
  }
}

Voici un exemple de réponse à l'envoi de la commande si le code promotionnel n'est pas valide:

"orderUpdate": {
  "actionOrderId": "sample_action_order_id",
  "orderState": {
    "state": "REJECTED",
    "label": "Order rejected."
  },
  "updateTime": "2017-05-10T02:30:00.000Z",
  "rejectionInfo": {
    "type": "PROMO_NOT_APPLICABLE",
    "reason": "Sorry, there's something wrong. Try another code?"
  },
  "orderManagementActions": [
    {
      "type": "CUSTOMER_SERVICE",
      "button": {
        "title": "Contact customer service",
        "openUrlAction": {
          "url": "mailto:support@example.com"
        }
      }
    },
    {
      "type": "EMAIL",
      "button": {
        "title": "Email restaurant",
        "openUrlAction": {
          "url": "mailto:example.provider@example.com"
        }
      }
    },
    {
      "type": "CALL_RESTAURANT",
      "button": {
        "title": "Call restaurant",
        "openUrlAction": {
          "url": "tel:+19993334444"
        }
      }
    }
  ],
  "infoExtension": {
    "@type": "type.googleapis.com/google.actions.v2.orders.FoodOrderUpdateExtension",
    "foodOrderErrors": [
      {
        "error": "PROMO_USER_INELIGIBLE",
        "description": "Sorry, you can only use this promotion once."
      }
    ]
  }
}