Créer des transactions physiques avec Google Pay

Ce guide vous explique comment développer un projet Actions qui intègre les transactions liées à des biens physiques et utilise Google Pay pour les paiements.

Flux de transactions

Lorsque votre projet Actions gère des transactions physiques à l'aide des paiements gérés par le marchand, il suit le flux suivant:

  1. Collecter des informations (facultatif) : selon la nature de votre transaction, vous pouvez recueillir les informations suivantes auprès de l'utilisateur au début de la conversation :
    1. Valider les exigences de transaction : au début de la conversation, vérifiez que l'utilisateur répond aux exigences pour effectuer une transaction, par exemple que les informations de paiement soient correctement configurées et disponibles avant de créer son panier.
    2. Demander une adresse de livraison : si la transaction nécessite une adresse de livraison, rassemblez-en une auprès de l'utilisateur.
  2. Création de la commande : guidez l'utilisateur à travers un "assemblage du panier" dans lequel il peut choisir les articles qu'il souhaite acheter.
  3. Proposez la commande : une fois le panier terminé, proposez la commande à l'utilisateur pour qu'il puisse confirmer qu'elle est correcte. Si la commande est confirmée, vous recevrez une réponse contenant les détails de la commande et un jeton de paiement.
  4. Finaliser la commande et envoyer un reçu : une fois la commande confirmée, mettez à jour le suivi de l'inventaire ou d'autres services de traitement, puis envoyez un reçu à l'utilisateur.
  5. Envoyer des mises à jour de commande : au cours de la durée de traitement de la commande, informez l'utilisateur des mises à jour de la commande en envoyant des requêtes PATCH à l'API Orders.

Restrictions et consignes relatives aux avis

N'oubliez pas que des règles supplémentaires s'appliquent aux actions avec transactions. L'examen des actions avec transactions peut prendre jusqu'à six semaines. Tenez-en compte lorsque vous planifiez votre calendrier de lancement. Pour faciliter le processus d'examen, assurez-vous de respecter les Règles et consignes concernant les transactions avant d'envoyer votre action pour examen.

Vous ne pouvez déployer des actions que dans les pays suivants:

Australie
Brésil
Canada
Indonésie
Japon
Mexique
Russie
Singapour
Thaïlande
États-Unis
Royaume-Uni
Turquie

Compiler votre projet

Pour obtenir des exemples complets de conversations transactionnelles, consultez l'exemple de transaction Node.js.

Prérequis

Lors de la création de votre action, vous devez indiquer que vous souhaitez effectuer des transactions dans la console Actions.

Pour configurer votre projet et votre traitement, procédez comme suit:

  1. Créez un projet ou importez un projet existant.
  2. Accédez à Déployer > Informations sur le répertoire.
  3. Sous Informations supplémentaires > Transactions, cochez la case "Vos actions utilisent-ils l'API Transactions pour effectuer des transactions de biens physiques ?".

1. Recueillir des informations (facultatif)

1a. Valider les exigences de transaction (facultatif)

Dès que l'utilisateur a indiqué vouloir effectuer un achat, vous devez vous assurer qu'il pourra effectuer une transaction. Par exemple, lorsqu'elle est appelée, votre action peut demander "Voulez-vous commander des chaussures ou vérifier le solde de votre compte ?". Si l'utilisateur dit "commander des chaussures", vous devez vous assurer qu'il peut continuer et lui donner la possibilité de corriger tous les paramètres qui l'empêchent de poursuivre la transaction. Pour ce faire, vous devez passer à une scène qui effectue une vérification des exigences de la transaction.

Créer une scène de vérification des exigences de transaction
  1. Dans l'onglet "Scènes", ajoutez une scène nommée TransactionRequirementsCheck.
  2. Sous Remplissage de cases, cliquez sur + pour ajouter un emplacement.
  3. Sous Sélectionner un type, sélectionnez actions.type.TransactionRequirementsCheckResult comme type d'emplacement.
  4. Dans le champ du nom de l'emplacement, nommez l'emplacement TransactionRequirementsCheck.
  5. Cochez la case Customizeslot value writeback (Personnaliser l'écriture des valeurs d'emplacement) (activée par défaut).
  6. Cliquez sur Enregistrer.

Une vérification des exigences de transaction entraîne l'un des résultats suivants:

  • Si les conditions sont remplies, le paramètre de session est défini avec une condition de réussite, et vous pouvez continuer à créer la commande de l'utilisateur.
  • Si une ou plusieurs des conditions ne peuvent pas être remplies, le paramètre de session est défini avec une condition d'échec. Dans ce cas, vous devez détourner la conversation de l'expérience transactionnelle ou mettre fin à la conversation.
    • Si l'utilisateur peut corriger les erreurs entraînant l'état d'échec, il sera invité à le faire sur son appareil. Si la conversation se déroule sur une surface vocale uniquement, le transfert est déclenché vers le téléphone de l'utilisateur.

Gérer le résultat de la vérification des exigences de transaction

  1. Dans l'onglet Scenes (Scènes), sélectionnez la scène TransactionRequirementsCheck que vous venez de créer.
  2. Sous Condition, cliquez sur + pour ajouter une condition.
  3. Dans le champ de texte, saisissez la syntaxe de condition suivante pour vérifier la condition de réussite:

    scene.slots.status == "FINAL" && session.params.TransactionRequirementsCheck.resultType == "CAN_TRANSACT"
    
  4. Pointez sur la condition que vous venez d'ajouter, puis cliquez sur la flèche vers le haut pour la placer avant if scene.slots.status == "FINAL".

  5. Activez Envoyer des invites et fournissez une invite simple informant l'utilisateur qu'il est prêt à effectuer une transaction:

    candidates:
      - first_simple:
          variants:
            - speech: >-
                You are ready to purchase physical goods.
    
  6. Sous Transition, sélectionnez une autre scène, ce qui permet à l'utilisateur de poursuivre la conversation et d'effectuer une transaction.

  7. Sélectionnez la condition else if scene.slots.status == "FINAL".

  8. Activez Envoyer des invites et fournissez une invite simple informant l'utilisateur qu'il ne peut pas effectuer de transaction:

    candidates:
      - first_simple:
          variants:
            - speech: Transaction requirements check failed.
    
  9. Sous Transition, sélectionnez End conversation (Terminer la conversation) pour mettre fin à la conversation si un utilisateur ne parvient pas à effectuer de transactions.

Demander une adresse de livraison

Si votre transaction nécessite l'adresse de livraison d'un utilisateur, vous devez en faire la demande à l'utilisateur. Cela peut être utile pour déterminer le prix total, le lieu de livraison ou de retrait, ou pour s'assurer que l'utilisateur se trouve dans la région desservie. Pour ce faire, vous devez passer à une scène qui invite l'utilisateur à fournir son adresse de livraison.

Créer une scène d'adresse de livraison

  1. Dans l'onglet Scenes (Scènes), ajoutez une scène nommée DeliveryAddress.
  2. Sous Remplissage de cases, cliquez sur + pour ajouter un emplacement.
  3. Sous Sélectionner un type, choisissez actions.type.DeliveryAddressValue comme type d'emplacement.
  4. Dans le champ du nom de l'emplacement, nommez l'emplacement TransactionDeliveryAddress.
  5. Cochez la case Personnaliser l'écriture des valeurs d'emplacement (option activée par défaut).
  6. Cliquez sur Save (Enregistrer).

Lors de la configuration de l'emplacement, vous pouvez fournir un reason qui vous permet de faire précéder la requête de l'Assistant d'obtenir une adresse avec une chaîne.La chaîne de raison par défaut est "pour savoir où envoyer la commande". Par conséquent, l'Assistant peut demander à l'utilisateur: "Pour savoir où envoyer la commande, je dois obtenir votre adresse de livraison".

  • Sur les surfaces avec un écran, l'utilisateur choisira l'adresse qu'il souhaite utiliser pour la transaction. S'ils n'ont pas encore fourni d'adresse, ils peuvent en saisir une.
  • Sur les surfaces vocales uniquement, l'Assistant demande à l'utilisateur l'autorisation de partager son adresse par défaut pour la transaction. S'ils n'ont pas encore communiqué d'adresse, la conversation est transmise sur un téléphone.

Pour gérer le résultat de l'adresse de livraison, procédez comme suit:

  1. Dans l'onglet Scenes (Scènes), sélectionnez la scène DeliveryAddress que vous venez de créer.
  2. Sous Condition, cliquez sur + pour ajouter une condition.
  3. Dans le champ de texte, saisissez la syntaxe de condition suivante pour vérifier la condition de réussite:

    scene.slots.status == "FINAL" && session.params.TransactionDeliveryAddress.userDecision == "ACCEPTED"
    
  4. Pointez sur la condition que vous venez d'ajouter, puis cliquez sur la flèche vers le haut pour la placer avant if scene.slots.status == "FINAL".

  5. Activez Envoyer des invites et fournissez une invite simple informant l'utilisateur que vous avez reçu son adresse:

    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
    
  6. Sous Transition, sélectionnez une autre scène pour permettre à l'utilisateur de poursuivre la conversation.

  7. Sélectionnez la condition else if scene.slots.status == "FINAL".

  8. Activez Envoyer des invites et fournissez une invite simple informant l'utilisateur qu'il ne peut pas effectuer de transaction:

    candidates:
      - first_simple:
          variants:
            - speech: I failed to get your delivery address.
    
  9. Sous Transition, sélectionnez End conversation (Terminer la conversation) pour mettre fin à la conversation si un utilisateur ne parvient pas à effectuer de transactions.

Créer la commande

Une fois que vous disposez des informations utilisateur dont vous avez besoin, vous allez créer une expérience d'"assemblage du panier" qui guidera l'utilisateur dans la création d'une commande. Chaque action aura un flux d'assemblage du panier légèrement différent en fonction de son produit ou service.

L'expérience d'assemblage de panier la plus basique consiste à permettre à l'utilisateur de choisir des articles dans une liste à ajouter à sa commande, mais vous pouvez concevoir la conversation pour simplifier l'expérience utilisateur. Vous pouvez créer une expérience d'assemblage du panier qui permet à l'utilisateur de commander à nouveau son dernier achat via une simple question "Oui" ou "Non". Vous pouvez également présenter à l'utilisateur une fiche de type carrousel ou liste des principaux éléments "sélectionnés" ou "recommandés".

Nous vous recommandons d'utiliser des réponses enrichies pour présenter visuellement les options de l'utilisateur, mais également de concevoir la conversation de sorte que l'utilisateur puisse construire son panier en utilisant uniquement sa voix. Pour découvrir des bonnes pratiques et des exemples d'expériences d'assemblage de paniers de haute qualité, consultez les consignes de conception.

Créer une commande

Tout au long de votre conversation, vous devez rassembler les articles qu'un utilisateur souhaite acheter, puis créer un objet Order.

Votre fichier Order doit au minimum contenir les éléments suivants:

  • buyerInfo : informations sur l'utilisateur effectuant l'achat.
  • transactionMerchant : informations sur le marchand qui a géré la commande.
  • contents : contenu réel de la commande indiquée sous la forme lineItems.
  • priceAttributes : indique le détail du prix de la commande, y compris son coût total avec les remises et les taxes.

Consultez la documentation concernant la réponse Order pour créer votre panier. Notez que vous devrez peut-être inclure différents champs en fonction de la commande.

L'exemple de code ci-dessous présente une commande complète, y compris les champs facultatifs:

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',
  },
};

Créer des options de commande et de présentation

Avant que l'utilisateur ne confirme sa commande, une fiche de commande proposée s'affiche. Vous pouvez personnaliser la façon dont cette fiche est présentée à l'utilisateur en définissant différentes options d'ordre et de présentation.

Vous trouverez ci-dessous les options de commande et de présentation permettant de passer une commande nécessitant une adresse de livraison, y compris l'adresse e-mail de l'utilisateur sur la carte de confirmation de commande:

const orderOptions = {
      'requestDeliveryAddress': true,
      'userInfoOptions': {
        'userInfoProperties': ['EMAIL']
      }
    };

const presentationOptions = {
      'actionDisplayName': 'PLACE_ORDER'
    };

Créer des paramètres de paiement

Votre objet paymentParameters inclura des paramètres de tokenisation qui changent en fonction de la société de traitement Google Pay que vous prévoyez d'utiliser (comme Stripe, Braintree, ACI, etc.).

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',
          },
        }),
      },
    };

Le contenu de l'objet tokenizationSpecification sera différent pour chaque passerelle de paiement. Le tableau suivant indique les paramètres utilisés par chaque passerelle:

EXEMPLE
"parameters": {
  "gateway": "example",
  "gatewayMerchantId": "exampleGatewayMerchantId"
}
CAI
"parameters": {
  "gateway": "aciworldwide",
  "gatewayMerchantId": "YOUR_ENTITY_ID"
}
ADYEN
"parameters": {
  "gateway": "adyen",
  "gatewayMerchantId": "YOUR_MERCHANT_ACCOUNT_NAME"
}
ALFA-BANK
"parameters": {
  "gateway": "alfabank",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
BLUE_MEDIA
"parameters": {
  "gateway": "bluemedia",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
BLUESNAP
"parameters": {
  "gateway": "bluesnap",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
BRAINTREE
"parameters": {
  "gateway": "braintree",
  "braintree:apiVersion": "v1",
  "braintree:sdkVersion": braintree.client.VERSION,
  "braintree:merchantId": "YOUR_BRAINTREE_MERCHANT_ID",
  "braintree:clientKey": "YOUR_BRAINTREE_TOKENIZATION_KEY"
}
CHASE_PAYMENTECH
"parameters": {
  "gateway": "chase",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ACCOUNT_NUMBER"
}
RÈGLEMENT
"parameters": {
  "gateway": "checkoutltd",
  "gatewayMerchantId": "YOUR_PUBLIC_KEY"
}
CLOUDPAYMENTS
"parameters": {
  "gateway": "cloudpayments",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
CYBERSOURCE
"parameters": {
  "gateway": "cybersource",
  "gatewayMerchantId": "YOUR_MERCHANT_ID"
}
DATATRANS
"parameters": {
  "gateway": "datatrans",
  "gatewayMerchantId": "YOUR_MERCHANT_ID"
}
EBANX
"parameters": {
  "gateway": "ebanx",
  "gatewayMerchantId": "YOUR_PUBLIC_INTEGRATION_KEY"
}
FIRST_DATA
"parameters": {
  "gateway": "firstdata",
  "gatewayMerchantId": "YOUR_MERCHANT_ID"
}
GLOBAL_PAYMENTS
"parameters": {
  "gateway": "globalpayments",
  "gatewayMerchantId": "YOUR_MERCHANT_ID"
}
GOPAY
"parameters": {
  "gateway": "gopay",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
HITRUST
"parameters": {
  "gateway": "hitrustpay",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
IMSOLUTIONS
"parameters": {
  "gateway": "imsolutions",
  "gatewayMerchantId": "YOUR_MERCHANT_ID"
}
LYRA
"parameters": {
  "gateway": "lyra",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
MPGS
"parameters": {
  "gateway": "mpgs",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
money_MAIL_RU
"parameters": {
  "gateway": "moneymailru",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
NEWEBPAY
"parameters": {
  "gateway": "newebpay",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
NEXI
"parameters": {
  "gateway": "nexi",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
NMI
"parameters": {
  "gateway": "creditcall",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
PAYSAFE
"parameters": {
  "gateway": "paysafe",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
PAYTURE
"parameters": {
  "gateway": "payture",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
PAYU
"parameters": {
  "gateway": "payu",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
PRZELEWY24
"parameters": {
  "gateway": "przelewy24",
  "gatewayMerchantId": "YOUR_MERCHANT_ID"
}
RBK consiste à
"parameters": {
  "gateway": "rbkmoney",
  "gatewayMerchantId": "YOUR_MERCHANT_ID"
}
SBERBANK
"parameters": {
  "gateway": "sberbank",
  "gatewayMerchantId": "YOUR_ORGANIZATION_NAME"
}
CARRE
"parameters": {
  "gateway": "square",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
RAYURE
"parameters": {
  "gateway": "stripe",
  "stripe:version": "2018-10-31",
  "stripe:publishableKey": "YOUR_PUBLIC_STRIPE_KEY"
}
TAPPAY
"parameters": {
  "gateway": "tappay",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
TINKOFF
"parameters": {
  "gateway": "tinkoff",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
UNITELLER
"parameters": {
  "gateway": "uniteller",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
VANTIV
"parameters": {
  "gateway": "vantiv",
  "vantiv:merchantPayPageId": "YOUR_PAY_PAGE_ID",
  "vantiv:merchantOrderId": "YOUR_ORDER_ID",
  "vantiv:merchantTransactionId": "YOUR_TRANSACTION_ID",
  "vantiv:merchantReportGroup": "*web"
}
WORLDPAY
"parameters": {
  "gateway": "worldpay",
  "gatewayMerchantId": "YOUR_WORLDPAY_MERCHANT_ID"
}
YANDEX
"parameters": {
  "gateway": "yandexcheckout",
  "gatewayMerchantId": "YOUR_SHOP_ID"
}

Enregistrer les données de commande dans le paramètre de session

À partir du traitement, enregistrez les données de la commande dans un paramètre de session. L'objet order sera utilisé dans toutes les scènes de la même session.

conv.session.params.order = {
    '@type': 'type.googleapis.com/google.actions.transactions.v3.TransactionDecisionValueSpec',
    order: order,
    orderOptions: orderOptions,
    presentationOptions: presentationOptions,
    paymentParameters: paymentParameters
};

Proposer la commande

Une fois la commande créée, vous devez la présenter à l'utilisateur pour qu'il la confirme ou la refuse. Pour ce faire, vous devez passer à une scène qui effectue une décision de transaction.

Créer une scène de décision de transaction

  1. Dans l'onglet Scenes (Scènes), ajoutez une scène nommée TransactionDecision.
  2. Sous Remplissage de cases, cliquez sur + pour ajouter un emplacement.
  3. Sous Select type (Sélectionner un type), sélectionnez actions.type.TransactionDecisionValue comme type d'emplacement.
  4. Dans le champ du nom de l'emplacement, nommez l'emplacement TransactionDecision.
  5. Cochez la case Personnaliser l'écriture des valeurs d'emplacement (option activée par défaut).
  6. Sous Configurer l'emplacement, sélectionnez Utiliser le paramètre de session dans le menu déroulant.
  7. Sous Configurer l'emplacement, saisissez le nom du paramètre de session utilisé pour stocker la commande dans le champ de texte (par exemple, $session.params.order).
  8. Cliquez sur Save (Enregistrer).

Pour tenter de remplir un emplacement TransactionDecisionValue, l'Assistant lance une expérience intégrée dans laquelle le Order que vous avez transmis s'affiche directement sur une "carte d'aperçu du panier". L'utilisateur peut dire "passer la commande", refuser la transaction, modifier une option de paiement (comme la carte de crédit ou l'adresse) ou demander à modifier le contenu de la commande.

L'utilisateur peut également demander à modifier la commande. Dans ce cas, vous devez vous assurer que votre traitement peut traiter les demandes de modification de commande une fois l'expérience d'assemblage du panier terminée.

Gérer le résultat de la décision de transaction

Lorsqu'un emplacement TransactionDecisionValue est rempli, la réponse de l'utilisateur à la décision concernant la transaction est stockée dans un paramètre de session. Cette valeur contient les éléments suivants:

  • ORDER_ACCEPTED,
  • ORDER_REJECTED,
  • DELIVERY_ADDRESS_UPDATED,
  • CART_CHANGE_REQUESTED
  • USER_CANNOT_TRANSACT.

Pour gérer le résultat d'une décision de transaction:

  1. Dans l'onglet Scenes (Scènes), sélectionnez la scène TransactionDecision que vous venez de créer.
  2. Sous Condition, cliquez sur + pour ajouter une condition.
  3. Dans le champ de texte, saisissez la syntaxe suivante pour la condition de réussite:

    scene.slots.status == "FINAL" && session.params.TransactionDecision.transactionDecision == "ORDER_ACCEPTED"
    
  4. Pointez sur la condition que vous venez d'ajouter, puis cliquez sur la flèche vers le haut pour la placer avant if scene.slots.status == "FINAL".

  5. Activez Envoyer des invites et fournissez une invite simple informant l'utilisateur que sa commande est terminée:

    candidates:
      - first_simple:
          variants:
            - speech: >-
                Transaction completed! Your order
                $session.params.TransactionDecision.order.merchantOrderId is all
                set!
    
  6. Sous Transition, sélectionnez Terminer la conversation pour mettre fin à la conversation.

  7. Sous Condition, cliquez sur + pour ajouter une condition.

  8. Dans le champ de texte, saisissez la syntaxe de condition suivante pour vérifier les conditions d'échec:

      scene.slots.status == "FINAL" && session.params.TransactionDecision.transactionDecision == "ORDER_REJECTED"
    
  9. Pointez sur la condition que vous venez d'ajouter, puis cliquez sur la flèche vers le haut pour la placer avant if scene.slots.status == "FINAL".

  10. Activez Envoyer des invites et fournissez une invite simple informant l'utilisateur que la commande a été refusée:

    candidates:
      - first_simple:
          variants:
            - speech: Look like you don't want to order anything. Goodbye.
    
  11. Sous Transition, sélectionnez Terminer la conversation pour mettre fin à la conversation.

  12. Sélectionnez la condition else if scene.slots.status == "FINAL".

  13. Activez Envoyer des invites et fournissez une invite simple informant l'utilisateur qu'il ne peut pas effectuer de transaction:

    candidates:
      - first_simple:
          variants:
            - speech: >-
                Transaction failed with status
                $session.params.TransactionDecision.transactionDecision
    
  14. Sous Transition, sélectionnez End conversation (Terminer la conversation) pour mettre fin à la conversation si un utilisateur ne peut pas effectuer de transactions.

Finaliser la commande et envoyer un reçu

Lorsque l'emplacement TransactionDecisionValue renvoie un résultat de ORDER_ACCEPTED, vous devez immédiatement effectuer le traitement nécessaire pour "confirmer" la commande (comme la conserver dans votre propre base de données et facturer l'utilisateur).

Vous pouvez mettre fin à la conversation par cette réponse, mais vous devez inclure une réponse simple pour que la conversation continue. Lorsque vous fournissez ce orderUpdate initial, l'utilisateur voit une "fiche de reçu réduit" avec le reste de votre réponse. Cette carte reflète le reçu que l'utilisateur trouve dans son historique des commandes.

Lors de la confirmation de commande, votre objet de commande peut inclure un userVisibleOrderId, qui correspond à l'ID que l'utilisateur voit pour la commande. Vous pouvez réutiliser merchantOrderId pour ce champ.

Une partie de l'objet OrderUpdate doit contenir un objet d'action de suivi, qui se manifeste sous la forme de boutons URL en bas des détails de la commande que l'utilisateur peut trouver dans l'historique des commandes de l'Assistant.

  • Vous devez fournir au moins une action de suivi VIEW_DETAILS pour chaque commande. Il doit contenir un lien profond vers la représentation de la commande sur votre application mobile ou votre site Web.
  • En plus de la fiche de reçu figurant dans la conversation de votre action, vous devez également envoyer un reçu officiel par e-mail qui répond à toutes les exigences légales pour effectuer une transaction.

Pour envoyer une première mise à jour de la commande:

  1. Dans l'onglet Scenes (Scènes), sélectionnez votre scène TransactionDecision.
  2. Sous Condition, sélectionnez la condition qui vérifie le résultat de réussite, ORDER_ACCEPTED:

      scene.slots.status == "FINAL" && session.params.TransactionDecision.transactionDecision == "ORDER_ACCEPTED"
    
  3. Pour cette condition, activez Appeler votre webhook et indiquez un nom de gestionnaire d'intent, tel que update_order.

  4. Dans le code de webhook, ajoutez un gestionnaire d'intent pour envoyer une première mise à jour de la commande:

    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
      }));
    });
    

Envoyer des mises à jour de commande

Vous devez tenir l'utilisateur informé de l'état de la commande tout au long de sa durée de vie. Envoyez des mises à jour de commande à l'utilisateur en envoyant des requêtes HTTP PATCH à l'API Orders avec l'état et les détails de la commande.

Configurer des requêtes asynchrones vers Orders API

Les requêtes de mise à jour de commande adressées à Orders API sont autorisées par un jeton d'accès. Pour PATCH une mise à jour de commande dans l'API Orders, téléchargez une clé de compte de service JSON associée à votre projet dans la console Actions, puis échangez-la contre un jeton de support qui peut être transmis dans l'en-tête Authorization de la requête HTTP.

Pour récupérer la clé de votre compte de service, procédez comme suit:

  1. Dans la console Google Cloud, accédez à Menu Dataproc > API et services > Identifiants > Créer des identifiants > Clé de compte de service.
  2. Sous Compte de service, sélectionnez Nouveau compte de service.
  3. Définissez le compte de service sur service-account.
  4. Définissez Rôle sur Projet > Propriétaire.
  5. Définissez le type de clé sur JSON.
  6. Sélectionnez Créer.
  7. Une clé de compte de service JSON privée sera téléchargée sur votre ordinateur local.

Dans votre code de mise à jour de commande, vous pouvez échanger votre clé de service contre un jeton de support en utilisant la bibliothèque cliente des API Google et le champ d'application "https://www.googleapis.com/auth/actions.order.developer". Vous trouverez la procédure d'installation et des exemples sur la page GitHub de la bibliothèque cliente de l'API.

Vous pouvez également référencer order-update.js dans notre exemple Node.js pour un exemple d'échange de clés.

Envoyer des mises à jour de commande

Une fois que vous avez échangé votre clé de compte de service contre un jeton de support OAuth, vous pouvez envoyer des mises à jour de commande en tant que requêtes PATCH autorisées à Orders API.

URL de l'API Orders: PATCH https://actions.googleapis.com/v3/orders/${orderId}

Fournissez les en-têtes suivants dans votre requête:

  • "Authorization: Bearer token" par le jeton de support OAuth pour lequel vous avez échangé votre clé de compte de service.
  • "Content-Type: application/json".

La requête PATCH doit prendre un corps JSON au format suivant:

{ "orderUpdate": OrderUpdate }

L'objet OrderUpdate comprend les champs de niveau supérieur suivants:

  • updateMask : champs de la commande que vous mettez à jour. Pour mettre à jour l'état de la commande, définissez la valeur sur purchase.status, purchase.userVisibleStatusLabel.
  • order : contenu de la mise à jour. Si vous mettez à jour le contenu de la commande, définissez la valeur sur l'objet Order mis à jour. Si vous mettez à jour l'état de la commande (par exemple, de "CONFIRMED" à "SHIPPED"), l'objet contient les champs suivants:

    • merchantOrderId : le même ID que celui défini dans l'objet Order.
    • lastUpdateTime : date et heure de cette mise à jour.
    • purchase : objet contenant les éléments suivants :
      • status : état de la commande sous la forme d'une PurchaseStatus (par exemple, SHIPPED ou DELIVERED).
      • userVisibleStatusLabel : étiquette visible par l'utilisateur qui fournit des détails sur l'état de la commande, par exemple "Votre commande a été expédiée et est en cours de livraison".
  • userNotification qui peut s'afficher sur l'appareil de l'utilisateur lorsque cette mise à jour est envoyée. Notez que l'inclusion de cet objet ne garantit pas l'affichage d'une notification sur l'appareil de l'utilisateur.

L'exemple de code suivant montre un exemple de OrderUpdate qui met à jour l'état de la commande sur 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}`);
}
Définir l'état de l'achat

Le status de la mise à jour d'une commande doit décrire l'état actuel de la commande. Dans le champ order.purchase.status de votre mise à jour, utilisez l'une des valeurs suivantes:

  • CREATED : la commande est acceptée par l'utilisateur et "créée" du point de vue de votre action, mais nécessite un traitement manuel sur votre backend.
  • CONFIRMED : la commande est active et en cours de traitement.
  • IN_PREPARATION : la commande est en cours de préparation pour l'expédition ou la livraison, par exemple un plat cuisiné ou un article en cours d'emballage.
  • READY_FOR_PICKUP : la commande peut être retirée par le destinataire.
  • DELIVERED : la commande a été livrée au destinataire.
  • OUT_OF_STOCK : un ou plusieurs articles de la commande ne sont pas disponibles.
  • CHANGE_REQUESTED : l'utilisateur a demandé à modifier la commande, et la modification est en cours de traitement.
  • RETURNED : l'utilisateur a retourné la commande après la livraison.
  • REJECTED si vous n'avez pas été en mesure de traiter, facturer ou "activer" la commande.
  • CANCELLED : la commande a été annulée par l'utilisateur.

Vous devez envoyer des mises à jour de commande pour chaque état pertinent pour votre transaction. Par exemple, si votre transaction nécessite un traitement manuel pour consigner la commande après qu'elle a été passée, envoyez une mise à jour CREATED jusqu'à ce que ce traitement supplémentaire soit terminé. Toutes les valeurs d'état ne sont pas requises pour toutes les commandes.

Tester votre projet

Lorsque vous testez votre projet, vous pouvez activer le mode bac à sable dans la console Actions pour tester votre action sans facturer de mode de paiement. Pour activer le mode bac à sable, procédez comme suit:

  1. Dans la console Actions, cliquez sur Tester dans le menu de navigation.
  2. Cliquez sur Paramètres.
  3. Activez l'option Bac à sable de développement.

Pour les transactions physiques, vous pouvez également définir le champ isInSandbox sur true dans votre exemple. Cette action équivaut à activer le paramètre du mode bac à sable dans la console Actions. Pour voir un extrait de code utilisant isInSandbox, consultez la section Envoyer des informations sur la commande.

Dépannage

Si vous rencontrez des problèmes pendant les tests, vous devez consulter nos étapes de dépannage pour les transactions.