kun432's blog

Alexaなどスマートスピーカーの話題中心に、Voiceflowの日本語情報を発信してます。たまにAWSやkubernetesなど。

〜スマートスピーカーやVoiceflowの記事は右メニューのカテゴリからどうぞ。〜

VoiceflowでAmazon Payをやってみる③ ChargeAPIの処理の流れ

f:id:kun432:20210313005910p:plain

VoiceflowでAmazon Payの第2回です。前回はSetup APIで支払準備を行い、Charge APIでの支払いの直前までを解説しました。今回はCharge APIでいよいよ実際の支払いです。

第1回はこちら。

第2回はこちら。

目次

解説

Step 6

Step 6ではCharge APIを使って実際の請求を行います。ここもDirective StepでConnections.SendRequestディレクティブを使います。

f:id:kun432:20210626235047p:plain

ディレクティブはこんな感じです。

{
            "type": "Connections.SendRequest",
            "name": "Charge",
            "payload": {
                "@type": "ChargeAmazonPayRequest",
                "@version": "2",
                "sellerId": "{sellerId}",
                "billingAgreementId": "{billingId}",
                "paymentAction": "AuthorizeAndCapture",
                "authorizeAttributes": {
                    "@type": "AuthorizeAttributes",
                    "@version": "2",
                    "authorizationReferenceId": "{authorizationRef}",
                    "authorizationAmount": {
                        "@type": "Price",
                        "@version": "2",
                        "amount": "1000",
                        "currencyCode": "JPY"
                    },
                    "transactionTimeout": 0,
                    "sellerAuthorizationNote": "購入者へのメモです。"
                },
                "sellerOrderAttributes": {
                    "@type": "SellerOrderAttributes",
                    "@version": "2",
                    "sellerOrderId": "{orderRefId}",
                    "storeName": "デモブックストア",
                    "customInformation": "Test custom information",
                    "sellerNote": "Test seller note"
                }
        },
        "token": "{tokenId}"
}

Setup APIで使用したbillingAgreementIdを使って、今度は"name":"Charge"を指定します。authorizeAttributesの中で金額や通貨が指定してありますね。これが決済金額になります。これらをCharge APIに送信することで請求を行います。

それ以外にも、店舗名(sellerOrderAttributes.storeName)や備考(sellerAuthorizationNote)など購入者へ通知されるメールに表示されるようなものや、販売者側の注文番号(sellerOrderAttributes.sellerOrderId)など販売管理に使うようなものまで色々パラメータがあります。各パラメータの詳細については公式のドキュメントをご覧ください。

Step 7/8

Step 7は、Setup APIのレスポンスを受けるのにも使っていましたが、Charge APIのレスポンスも同じEvent Stepで受けて、イベント名でそれぞれの処理を分岐させています。

f:id:kun432:20210627001344p:plain

Charge APIからのレスポンスはこんな感じです。

{
    "type": "Connections.Response",
    "requestId": "amzn1.echo-api.request.XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
    "timestamp": "2021-06-25T14:16:22Z",
    "locale": "ja-JP",
    "status": {
        "code": "200",
        "message": "OK"
    },
    "name": "Charge",
    "payload": {
        "authorizationDetails": {
            "authorizationAmount": {
                "amount": "1000.00",
                "currencyCode": "JPY"
            },
            "capturedAmount": {
                "amount": "1000.00",
                "currencyCode": "JPY"
            },
            "softDescriptor": "AMZ*XXXXXXXX",
            "expirationTimestamp": "2021-07-25T14:16:22.198Z",
            "idList": [
                "S03-XXXXXXX-XXXXXXX-XXXXXXX"
            ],
            "softDecline": false,
            "authorizationStatus": {
                "lastUpdateTimestamp": "2021-06-25T14:16:22.198Z",
                "reasonCode": "MaxCapturesProcessed",
                "state": "Closed"
            },
            "authorizationFee": {
                "amount": "0.00",
                "currencyCode": "JPY"
            },
            "captureNow": true,
            "sellerAuthorizationNote": "購入者へのメモです。",
            "creationTimestamp": "2021-06-25T14:16:22.198Z",
            "amazonAuthorizationId": "S03-XXXXXXX-XXXXXXX-XXXXXXX",
            "authorizationReferenceId": "XXXXXXXX-XXXX"
        },
        "amazonOrderReferenceId": "S03-XXXXXXX-XXXXXXX"
    },
    "token": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
}

そして、Condition Stepで結果を判定します。で、ここはデモを作ったあとで調べていて気づいたのですが、status.codeだけではなく、authorizationStatus.stateもチェックしないといけないようです。status.codeが200でも、ここが"Declined"になっている場合は何かしら支払いができない状態を表しています。少し修正しましょう。

authorizationRetという変数を用意します。

f:id:kun432:20210627003826p:plain

Custom Code StepでCharge APIの結果から、authorizationStatus.stateを取り出して、変数authorizationRetに入れます。コードは以下。

authorizationRet = data.payload.authorizationStatus.state

f:id:kun432:20210627003918p:plain

次のCondition Stepで条件を追加します。Setup APIの結果チェックと同様に、最初にauthorizationStatus.stateが"Declined"だったらエラーにしてしまいましょう。判定の順番を入れて変えてますので注意してください。

f:id:kun432:20210627004117p:plain

で最後にStep8でその結果に応じて発話を変えていますが、ここも線をつなぎ直しました。

f:id:kun432:20210627004245p:plain

これでOKですね。

完成後の全体フロー

スキル起動からSetup API、Charge APIの処理を含めた、全体フローの流れはこうなります。

f:id:kun432:20210626203811p:plain

Skill Connectionsの仕組みでは、Directive StepからEvent Stepにジャンプしてフローが継続するかんじになるのがわかりますでしょうか?

Skill Connectionsを使うメリット

単にAPIにリクエストを送るだけなら、Directive/Event Stepを使ったSkill Connectionsのようなわかりにくい仕組みよりも、API Stepを使ってその中でリクエスト・レスポンスを処理すればいいじゃないか、と思うかもしれません。Skill Connectionsのメリットは実際の利用中の会話を見てもらうとわかりやすいと思います。

f:id:kun432:20210627004830p:plain

プロジェクトの中で指定していないような発話がいくつかあるのがわかるでしょうか?赤枠で囲ったところがそうですね。

f:id:kun432:20210627005027p:plain

Skill Connectionsの仕組みは、カスタムスキルからは単にリクエストを送るだけで、その結果を得るために必要なやりとり、例えば今回のAmazon Payだと、

  • 送付先が必要な場合は、初回のみ、スキルに住所情報を共有するかの確認
  • Amazon Payで支払いを行う場合に必要なパーミッションの確認(Amazon Payおよび1クリック注文が有効かどうか)

などをAlexaとユーザ間で解決してくれて、カスタムスキルは結果を受け取るだけ、になることです。これを全部スキルで実装するのはなかなか骨が折れる作業なので、とても楽ですね。

ただし、API Stepのようにリクエストして即レスポンスを受けるというわけにはいかなくなるので、Event Stepでレスポンスを待ち受ける口を作るというわけです。

まとめ

3回に分けてVoiceflowでAmazon Payの実装について説明してきました。スキルでマネタイズを行う場合、これまでのVoiceflowだとスキル内課金のみでしたが、Amazon Payでリアルな商品の販売もできると、よりビジネス的な利用ができそうですね!

Amazon PayのAPIの話や、Directive/Event Stepを使ったSkill Connections的なやりとりなど、今回は少し技術的な要素が多かったかもですね。ただ、Directive/Event Stepはとても強力な機能で、過去のVoiceflowではできなかった以下のような機能が実現できるのではないかと思います。

  • Directive Step
    • プログレッシブ応答
    • Web API for Games
  • Event Step
    • 発話以外のインテントリクエストを受け付けることができる
      • Skill Connections
      • APLのタッチイベント
      • Web API for Games

これらについても引き続き実装できるかトライしてみたいと思います。