Help Needed with Amazon Pay Integration for Alexa

amazon-alexa

#1

Hi Jan/Alex/everyone,

This is Simon from Smixon Ltd. I’m new to the community, currently building a cross-platform voice app for one of our clients.

Made some good progress so far. Have set up AWS Developer account, AWS Lambda function / Jovo webhook as endpoints, and also have an Amazon Merchant Account with Access ID and Secret Access Key. ASK-CLI, Jovo-CLI have been fantastic tools so far, as well as the Jovo debugger. We’ve built up the basic logic/functionality of our app directly with the Jovo language model. This involves giving some information/instructions to our users, followed by asking if they would like us to add a certain product to their Amazon basket.

Today, using the alexaSkill manifest in our project.js file, we have enabled read/write permissions to user household lists, and also enabled the Display Interface for when we want to display images or get permission from our users.

Now we’ve hit a bit of a brick wall in terms of progress, and we’re hoping to get it fixed ASAP with some help.

Here’s what we want to do:

  1. Ask user if they would like to add a product to their basket.
  2. Use a followUpState(‘AddItemToBasketState’) to process the user YesIntent() or NoIntent().
  3. If yes we need to check for permission to use Amazon Pay, if denied, we need to send a List Permissions card to them to enable permission.
  4. Add item to their basket.

Initially, we want to get this working with just voice (Echo Dot), but we can add in the images/animations later for Echo Show etc. Reading through the Jovo docs today, we can see that the Jovo helper methods described on the Amazon Pay page [https://www.jovo.tech/docs/amazon-alexa/pay] could be useful to us. But the documentation here is limited, and going to the Alexa Skill Kit reference [https://developer.amazon.com/docs/amazon-pay/amazon-pay-overview.html] has left us unsure what to do. :thinking:

We know that we have to gain permission from the user, then send a setupDirective… Honestly, we don’t know where to start with the next stage!

There’s also the issue of whether we need to use the Amazon Presentation Language. Or can we just use card templates? So confusing!

Here’s a snippet of our code, described above. Unfortunately we can’t give the entire sample of code as the project details are private to us and our client. Hopefully this snippet will be enough for now:

.addText(
            "Would you like me to add a bottle of " + productType + " to your basket?"
        );

    this.followUpState('AddItemToBasketState').ask(speech);
},

AddItemToBasketState: {

    // This is where we would like to start adding items to our user's basket, instead of just using the
    // this.tell() method. The only reason that is there is because we we're testing everything was working
    // with the followUpState.

    YesIntent() {
        this.tell('Okay, item added to basket.');
    },

    NoIntent() {
        this.tell('No problem.');
    },
}

Any help would be greatly appreciated as we are short on time with a deadline coming up soon. If we can demonstrate that we can add products to a user’s basket, I think our client will be satisfied that we have got this part to work.

Many thanks in advance,

Simon Revill
Smixon Ltd


#2

Hi Simon,

First off, welcome to the Jovo Community Forum :tada:

Just to make sure there is no misunderstanding. The household lists are ToDo or Shopping Lists inside the Amazon Alexa account of a user, they’re not the user’s Amazon shopping cart/basket. Adding something to a shopping list shouldn’t be a problem, but for adding something to the cart, I believe the only way is to use Amazon Pay, although II haven’t personally implemented something like this yet.

Have you added the necessary permissions for Amazon Pay in your project.js?

{
     name: 'payments:autopay_consent'
}

Adding these permissions to your Alexa Skill should work the same way as adding the list permissions that you mentioned.

The official Amazon Pay features and docs are pretty complex, this is why we only added the Jovo-specific helpe methods to our Jovo Docs.

Have you done all the steps that are described here, like registering as an Amazon Payments merchant?

The code examples there are with the Alexa Skills Kit SDK, but if you follow the content of the handle functions together with the helper methods in Jovo (addDirective) this should give you an initial idea of how it works.

If there is anything critical that’s missing in the docs, please let us know,
Jan


#3

Hi Jan,

Thanks for the quick response! To answer your questions:

  1. Have you added the necessary permissions for Amazon Pay in your project.js ?
    {
    name: ‘payments:autopay_consent’
    }

Yes, this has already been added to our project.js file.

  1. Have you done all the steps that are described here, like registering as an Amazon Payments merchant?

I have been reading these docs all day and yes, I agree, they are very complex. Here’s what we have done so far:

Before you begin :white_check_mark:
Register as an Amazon Payments merchant :white_check_mark:
Register as an Amazon Web Services developer :white_check_mark:
Create your skill :white_check_mark:
Link your skill with your Amazon Payments account in Seller Central :white_check_mark:

This is where I’m stuck / lost:

Set up your payment workflow
Check for Amazon Pay permissions and Voice Purchasing settings
Payment workflow 1: Charge now
Payment workflow 2: Charge later
Set up your backend server

Request customer contact information
Set up error and decline handling
Test your integration

The Amazon docs are complex. However, I don’t think complexity is the real issue here. When I started this I had no experience of developing voice apps and our team had built a rudimentary version of it without Jovo - just using Node.js. When I came into the team, they had decided that we should use Jovo so we could develop cross-platform. So I’ve been using just JavaScript as usual, with the Jovo framework.

I’ll try to use the addDirective() helper method. Problem is I’m not sure where it’s going, and I don’t when or how I’m going to implement the actual product into this…

Again, thanks for the quick response - especially since you helped me earlier today on Slack!


#4

Have you tried adding something like this:

YesIntent() {
    if (this.$alexaSkill.isAmazonPayPermissionGranted()) {
        const setupDirective = {
            "type": "Connections.SendRequest",
            "name": "Setup",
            "payload": {
                "@type": "SetupAmazonPayRequest",
                "@version": "2",
                "sellerId": "AEMGQXXXKD154",
                "countryOfEstablishment": "US",
                "ledgerCurrency": "USD",
                "checkoutLanguage": "en_US",
                "billingAgreementAttributes": {
                    "@type": "BillingAgreementAttributes ",
                    "@version": "2",
                    "sellerNote": "Billing Agreement Seller Note",
                    "sellerBillingAgreementAttributes": {
                        "@type": "SellerBillingAgreementAttributes ",
                        "@version": "2",
                        "sellerBillingAgreementId": "BA12345",
                        "storeName": "Test store name",
                        "customInformation": "Test custom information"
                    }
                },
                "needAmazonShippingAddress": false
            },
            "token": "correlationToken"
        };

        this.$alexaSkill.addDirective(setupDirective);
        this.tell('Okay, item added to basket.');
    } else {
        this.$alexaSkill.showAskForAmazonPayPermissionCard();
        this.tell('I sent you a card to your Alexa app. Please provide the permission');
    }
    
 },

Edit: As of @Kaan_Kilic’s suggestion, I added speech output to the permission card part.


#5

I was literally just about to try that. Will let you know what happens. Thanks


#6

Okay, I tried that. I edited the sellerID, ledgerCurrency and checkoutLanguage to reflect our own account settings.

Naturally, I was expecting this.$alexaSkill.showAskForAmazonPayPermissionCard(); to be triggered, but nothing shows up on the Alexable Developer Console in the ‘Medium Hub’ window.


#7

I think it should be sent as a card in your Alexa app, not on a device with screen


#8

Right. I’ll test it by making a simple card (from the Jovo docs):

this.$alexaSkill.showStandardCard('Hello World', 'This is a standard card');

this.tell('I added a card to the response!');

and insert this into the if/else block. I’ll let you know if that works, and then we can go from there.


#9

But this.$alexaSkill.showAskForAmazonPayPermissionCard(); didn’t send a card? There is no simple card needed. What does the JSON response look like in your logs? Does it have the card content included?


#10

Sorry I misunderstood. In the Alexa Developer console, the JSON output disappears when answer with ‘yes’. The message I get is ‘Skill I/O is available only for speech requests to skills you have created’. Am I looking in the wrong place?


#11

Usually, the command line is better to see real-time logs


#12

I see. I just ran another test. Here’s the output in the command line. I will remember that for future reference!

Would you like me to add a bottle of One Thousand and One Troubleshooter to your basket?</speak>"
                        }
                }
        },
        "sessionAttributes": {
                "_JOVO_STATE_": "AddItemToBasketState"
        }
}
{
        "version": "1.0",
        "session": {
                "new": false,
                "sessionId": "amzn1.echo-api.session.0000000-0000-0000-0000-00000000000",
                "application": {
                        "applicationId": "amzn1.echo-sdk-ams.app.000000-d0ed-0000-ad00-000000d00ebe"
                },
                "attributes": {
                        "_JOVO_STATE_": "AddItemToBasketState"
                },
                "user": {
                        "userId": "jovo-debugger-user"
                }
        },
        "context": {
                "System": {
                        "application": {
                                "applicationId": "amzn1.echo-sdk-ams.app.000000-d0ed-0000-ad00-000000d00ebe"
                        },
                        "user": {
                                "userId": "jovo-debugger-user"
                        },
                        "device": {
                                "deviceId": "amzn1.ask.device.XXXXXA6LX6BOBJF6XNWQM2ZO4NVVGZRFFEL6PMXKWLOHI36IY3B4XCSZKZPR42RAWCBSQEDNGS746OCC2PKR5KDIVAUY6F2DX5GV2SQAXPD7GMKQRWLG4LFKXFPVLVTXHFGLCQKHB7ZNBKLHQU4SJG6NNGA",
                                "supportedInterfaces": {
                                        "AudioPlayer": {},
                                        "Display": {
                                                "templateVersion": "1.0",
                                                "markupVersion": "1.0"
                                        },
                                        "VideoApp": {},
                                        "Alexa.Presentation.APL": {
                                                "runtime": {
                                                        "maxVersion": "1.0"
                                                }
                                        }
                                }
                        }
                },
                "AudioPlayer": {
                        "offsetInMilliseconds": 0,
                        "playerActivity": "IDLE"
                }
        },
        "request": {
                "type": "IntentRequest",
                "requestId": "amzn1.echo-api.request.0000000-0000-0000-0000-00000000000",
                "timestamp": "2019-03-25T22:57:44.002Z",
                "dialogState": "COMPLETED",
                "locale": "en-GB",
                "intent": {
                        "name": "AMAZON.YesIntent",
                        "confirmationStatus": "NONE",
                        "slots": {}
                }
        }
}
{
        "version": "1.0",
        "response": {
                "shouldEndSession": true,
                "card": {
                        "type": "AskForPermissionsConsent",
                        "permissions": [
                                "payments:autopay_consent"
                        ]
                }
        },
        "sessionAttributes": {}
}

#13
"card": {
                        "type": "AskForPermissionsConsent",
                        "permissions": [
                                "payments:autopay_consent"
                        ]
                }

Seems like the card should be sent to the Alexa app. Only if you’ve been testing on a device or the Amazon Developer console though, not with the Jovo Debugger (which the logs suggest you’re using)


#14

Yes I saw that. I did use jovo run to watch the command line output. I’ve run the test in the Amazon Developer Console and basically, nothing happens. I respond with a ‘yes’ and the app just stops. What am I missing? Lol.

I don’t want to take up much more of your time today, you’ve been really helpful so far. Perhaps we can carry on tomorrow. If you can suggest any documents I should read until then, that would be great.


#15

Is the Interaction Model deployed to the Skill project and does it include AMAZON.YesIntent? The Jovo Debugger only simulates requests (by just creating dummy JSON responses).


#16


#17

I’m not sure if this is relevant but just in case:

I use jovo build, then jovo deploy. I’m having an issue with permissions as it tries to upload to lambda so at the moment I just upload the bundle.zip directly inside lambda, which then updates the Alexa project in the developer console. The interaction model is updated automatically.


#18

Hi Simon,

the app might stop because you’re missing the speech output. Try:

this.$alexaSkill.showAskForAmazonPayPermissionCard();
this.tell('I sent you a card to your Alexa app. Please provide the permission');

#19

Thanks Kaan, I will try that and update you. :+1:


#20

Okay I’ve got some good news. I’ve sorted out permissions, sending a card to the Alexa app. I’ve also managed to send the directive, which I’ve updated with the additional parameters sandboxMode: true and also sandboxCustomerEmailId which I’ve already set up in Sandbox mode on Amazon Seller Central.

My next question is how can I use Jovo to handle the response? In the docs, the only thing mentioned is the built-in ON_PURCHASE intent:

ON_PURCHASE() {
    const request = this.$request.toJSON(); // access the request object
}

Am I right in thinking that once this function turns the request into JSON format, I can then send the ‘Charge’ request back from within the ON_PURCHASE() intent?

Thanks guys.

By the way - I will be documenting this entire process for my own future reference. If you can help me implement this, we can all use this as a way to enhance the future Jovo documentation.