Dialogflow Tutorial: Setup Transaction API on Google Assistant using NodeJS

Chatbot based e-commerce is gradually expanding. It is now possible to publish chatbots on Google Assistant where user can buy your products, book your service, make reservation and make payment in Google Assistant itself. This makes the buying process seamless for users with payment from their linked credit/debit card in Google Pay Account. But enabling payment in Google Assistant is not a straight forward process. We have to integrate Google Transaction API. In this Dialogflow Tutorial, we are going to discuss how to integrate Transaction API in your Dialogflow based chatbot for Google Assistant.

Why do you need to implement Transaction API

Transactions in Actions/Chatbots on Google enables your action/chatbot to handle order purchases and reservations from user in the chatbot using Google Pay. Transaction API is a set of API that you can use to implement the transaction in your action. Also, Google will not publish your action into production if you are performing any transaction without using Transaction API. So, if you are planning to offer payment or reservation functionality in your chatbot then you will have to use Transaction API.

How to implement Transaction API

Actions on Google has provided some documentation where you can find how to implement the transaction API in your chatbot. Few things are straight forward but some of it could confuse you.

To implement transaction API, you need to pick a transaction type from four types available. The four available types are:

  • Physical transactions with Google Pay (Google-managed payments): Using this method you can enable users to pay via their Google Pay account. Also, google has provided some gateways which it supports, so if you want to use any of those gateways then you will be able to do that.
  • Physical transactions with merchant-managed payments: This option will be useful if you have your own store already setup and you want users to make payment with their saved payment method on your website. By integrating Account Linking, you can setup the actions.intent.SIGN_IN intent to have the user log in to your own store and invoke your own API to use their saved payment method on your website.
  • Reservations: If you want your users to make reservations on your chatbot then this option will be useful.
  • Digital transactions: you can allow access to premium content if the user purchases a subscription using this option. Select this option if you want to let users purchase digital goods you own in the Google Play store, such as digital subscriptions or other in-app purchases right from your chatbot.

You can select any one from the above based on your requirements. For the demonstration purpose, we will use the first one “Physical transaction with Google Pay”.

To integrate the “Physical transaction with Google Pay”, Actions on Google has provided documentation which you can find here. And also they have provided some sample code on their github repo. In their example they use firebase while in our example, you won’t need to worry about firebase. You can set it up locally and test it using ngrok.

Download the agent and code files:

Fill up the form below to download your Transaction API Integration Agent for Dialogflow.

* indicates required

You will receive zipped file containing transaction API integration agent.

You will need to import the TransactionAPITesting.zip in your Dialogflow agent to populate the agent.

Also, you need to setup a new NodeJS project, copy the index.js and package.json in that folder and run “npm install” in same directory so that it will install required node modules.

Let’s understand the setup step by step.

The Flow of Transaction

Below is the general flow of transaction that we’ll be implementing. Some of those steps are optional so it’s up to you whether you want to use them or not.

  • Gather information (optional)
    • Validate transaction requirements – Check the user’s payment information is properly configured or not
    • Get delivery address – user’s delivery address (optional)
  • Build the order
    • Create your order cart
  • Propose the order
    • Propose the order summary to the user
  • Finalize the order and send the receipt
    • Confirm the order and send a confirmation receipt to the user
  • Send order updates
    • Send updates to the user, if the order status changes

Enabling transactions in your Action

Before performing transactions, you need to specify it from Actions on Google console. To do that Go to your actions on Google console. Then the “Deploy” tab and then “Directory Information”. Scroll all the way to the bottom, you will find a “Transactions” option. Check the first box below this option “Do your Actions use the Transactions API to perform transactions of physical goods?”. See the below screenshot for reference.

That’s it from configuration side, now we can implement the transactions in our chatbot.

1. Check if the user is able to perform transactions

When the user starts the transaction you can just trigger the actions.intent.TRANSACTION_REQUIREMENTS_CHECK system intent using the following JSON payload in Dialogflow.

{
  "payload": {
    "google": {
      "expectUserResponse": true,
      "systemIntent": {
        "intent": "actions.intent.TRANSACTION_REQUIREMENTS_CHECK",
        "data": {
          "@type": "type.googleapis.com/google.actions.transactions.v3.TransactionRequirementsCheckSpec"
        }
      }
    }
  }
}

To get the result from the intent add the #actions_intent_TRANSACTION_REQUIREMENTS_CHECK in the event section of the intent where you want to handle the response. Then create a new parameter and add its value as #actions_intent_TRANSACTION_REQUIREMENTS_CHECK.TRANSACTION_REQUIREMENTS_CHECK_RESULT.resultType. Here the parameter “resultType” is the result of the transaction requirements check intent. If the resultType is “CAN_TRANSACT” allow the user to do transaction else give them an error.

2. Get User Delivery Address

To ask user about the delivery address, just use the below system intent. You can change the reason message to whatever you want. It will be displayed with the default message.

{
   "payload": {
     "google": {
       "expectUserResponse": true,
       "systemIntent": {
         "intent": "actions.intent.DELIVERY_ADDRESS",
         "data": {
           "@type": "type.googleapis.com/google.actions.v2.DeliveryAddressValueSpec",
           "addressOptions": {
             "reason": "To know where to send the order"
           }
         }
       }
     }
   }
 }

To get the delivery address and user response for delivery address intent. Add the actions_intent_DELIVERY_ADDRESS event to the event section of the intent where you want to handle the delivery address response.
To get the responses such as address and user decision just add new parameters with the following value #actions_intent_DELIVERY_ADDRESS.DELIVERY_ADDRESS_VALUE.location.postalAddress.addressLines[0] for address and #actions_intent_DELIVERY_ADDRESS.DELIVERY_ADDRESS_VALUE.userDecision for decision.

3. Build and propose the order

Now the next step is to tell users about the order details. So, just use the below payload with your cart details and it will display users an order summary card in Assistant.

{
   "payload": {
     "google": {
       "expectUserResponse": true,
       "systemIntent": {
         "intent": "actions.intent.TRANSACTION_DECISION",
         "data": {
           "@type": "type.googleapis.com/google.actions.transactions.v3.TransactionDecisionValueSpec",
           "order": {
             "createTime": "2019-08-01T17:12:13.761Z",
             "lastUpdateTime": "2019-08-01T17:12:13.761Z",
             "merchantOrderId": "UNIQUE_ORDER_ID",
             "userVisibleOrderId": "USER_VISIBLE_ORDER_ID",
             "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": "Line Item Price",
                       "state": "ACTUAL",
                       "amount": {
                         "currencyCode": "USD",
                         "amountInMicros": 8990000
                       },
                       "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
                           }
                         ],
                         "note": "Extra pepperoni",
                         "quantity": 1,
                         "subOptions": []
                       }
                     ]
                   }
                 }
               ]
             },
             "buyerInfo": {
               "email": "janedoe@gmail.com",
               "firstName": "Jane",
               "lastName": "Doe",
               "displayName": "Jane Doe"
             },
             "priceAttributes": [
               {
                 "type": "TOTAL",
                 "name": "Total Price",
                 "state": "ESTIMATE",
                 "amount": {
                   "currencyCode": "USD",
                   "amountInMicros": 15770000
                 },
                 "taxIncluded": true
               },
               {
                 "type": "TAX",
                 "name": "Tax",
                 "state": "ESTIMATE",
                 "amount": {
                   "currencyCode": "USD",
                   "amountInMicros": 3780000
                 },
                 "taxIncluded": true
               },
               {
                 "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
               }
             ],
             "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": "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": "2017-01-16T01:30:15.01Z"
                 },
                 "location": {
                   "zipCode": "94086",
                   "city": "Sunnyvale",
                   "postalAddress": {
                     "regionCode": "US",
                     "postalCode": "94086",
                     "administrativeArea": "CA",
                     "locality": "Sunnyvale",
                     "addressLines": [
                       "222, Some other Street"
                     ]
                   }
                 },
                 "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"
             }
           },
           "orderOptions": {
             "requestDeliveryAddress": false,
             "userInfoOptions": {
               "userInfoProperties": [
                 "EMAIL"
               ]
             }
           },
           "paymentParameters": {
             "googlePaymentOption": {
               "facilitationSpec": "{\"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\":\"10.00\",\"currencyCode\":\"USD\"}}"
             }
           },
           "presentationOptions": {
             "actionDisplayName": "PLACE_ORDER"
           }
         }
       }
     }
   }
 }

Above JSON should display result as below in Google Assistant:

4. Handling user decision in Dialogflow

To handle the decision of the proposed order card just add the actions_intent_TRANSACTION_DECISION event in the event section of the intent where you want to handle the user response. When the user performs any action on the proposed order card the following intent will be triggered.

To get the use decision value add a new parameter with value as #actions_intent_TRANSACTION_DECISION.TRANSACTION_DECISION_VALUE.transactionDecision.

The transactionDecision value can be any one of the followning ORDER_ACCEPTED, ORDER_REJECTED, DELIVERY_ADDRESS_UPDATED, CART_CHANGE_REQUESTED, and USER_CANNOT_TRANSACT.

If the transactionDecision is ORDER_ACCEPTED then you can process further with the order confirmation.

If the user chooses to change the delivery address during the proposed order card. Then the value of transactionDecision will be DELIVERY_ADDRESS_UPDATED.

You can decide what to do further with the value of the transactionDecision parameter. You can display “Transaction successful” message for ORDER_ACCEPTED or you can display an error message on ORDER_REJECTED. Remember to always handle the intent response to prevent agent from crashing.


So, that’s how Transaction API can be integrated and tested in Dialogflow for Google Assistant chatbot. If you still face any difficulty then feel free to post your question in the comments.

If you are looking for Chatbot Development services or to integrate Transaction API in your action then do contact us or send your requirement at letstalk@pragnakalp.com. We would be happy to offer our expert services.

Categories: Chatbots Development Dialogflow Dialogflow Tutorial How To

Leave a Reply

Your email address will not be published.

You may use these <abbr title="HyperText Markup Language">HTML</abbr> tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*