AlexaでのAmazon Pay連携実装が大変そうだったのでSDK作った話

Alexa Advent Calendar 2018およびAlexa Skills Kit SDK Advent Calendar 2018 19日目の記事です。 Alexa Dev Summit Tokyo 2018お […]

広告ここから
広告ここまで

目次

    Alexa Advent Calendar 2018およびAlexa Skills Kit SDK Advent Calendar 2018 19日目の記事です。

    Alexa Dev Summit Tokyo 2018お疲れ様でした。Amazon PayのワークショップでついにAmazon PayとAlexaの連携を体験できることができ、すごくテンションが上がっています。ただ、ワークショップ中にも「各APIへのパラメーターについてはとりあえずなところが一部あるので、本番利用は注意していください(意訳)」というコメントがあり、自前でいろいろ作るのは大変そうだなという感想もありました。実際ワークショップの運営もかなり駆け足でしたので・・・

    {
      "@type": "ChargeAmazonPayRequest",
      "@version": "2",
      "sellerId": "my-seller-id",
      "billingAgreementId": "agreement-id",
      "paymentAction": "AuthorizeAndCapture",
      "authorizeAttributes": {
        "@type": "AuthorizeAttributes",
        "@version": "2",
        "authorizationReferenceId": "MyReference ID",
        "authorizationAmount": {
          "@type": "Price",
          "@version": "2",
          "amount": "500",
          "currencyCode": "USD"
        }
      },
      "sellerOrderAttributes": {
        "@type": "SellerOrderAttributes",
        "@version": "2",
        "sellerOrderId": "my seller id",
        "storeName": "Example store"
      }
    }

    こういうのをコツコツ作っていかないといけない感じですね。

    で、ask-utilsを出している身としては、「使いにくそうならいい感じにするやつだせばいいやん」という気持ちになりました。

    と、いうことでベータ版ですがask-utils-for-amazon-payリリースしました。

    使い方

    現時点では、addDirectiveのpayloadにいれるオブジェクトを作るビルダーのみ提供しています。npm i -S ask-utils-for-amazon-payにてインストール後、以下のような形で組み込めます。

    const AmazonSetupHandler = {
      canHandle (handlerInput) {
        return canHandle(handlerInput, 'IntentRequest', 'SetupIntent')
      },
      handle(handlerInput) {
        const SellerOrderAttributes= AMAZONPay.Setup.BillingAgreementBuilder
          .setPlatFormId('My id')
          .setSellerNote('my note')
          .setSellerBillingAgreementId('agreement id')
          .setSellerNote('My store')
          .setCustomInformation('custom info')
        const setupPayload = AMAZONPay.Setup.PayloadBuilder
          .setSellerId('my seller id')
          .setCountryOfEstablishment('country')
          .setLedgerCurrency('ledger currency')
          .setCheckoutLanguage('checkout lang')
          .withAmazonShippingAddress(true)
          .isSandboxMode(true)
          .setSandboxCustomerEmailId('email')
          .updateBillingAgreement(SellerOrderAttributes)
    
        return handlerInput.responseBuilder
          .addDirective({
            "type": "Connections.SendRequest",
            "name": "Setup",
            "payload": setupPayload.getPayload(),
            "token": 'token'
          })
          .withShouldEndSession(true)
          .getResponse();
      },
    }

    メソッドチェーンがちょっと長くなるので冗長感はありますが、自前でオブジェクトを作り上げるよりはましかなということでご了承ください。

    TypeScriptでも使えます

    TypeScriptの勉強も兼ねてだったので、TypeScriptでも動くようにしました。動いているはず。

    import AmazonPay from 'ask-utils-for-amazon-pay'
    
    const authorizeAttributes = AmazonPay.Charge.AuthorizeAttributesBuilder
        .setReferenceId('MyReference ID')
        .setCurrencyCode('USD')
        .setAmount('500')
    const sellerOrderAttribtes = AmazonPay.Charge.SellerOrderAttributesBuilder
        .setSellerOrderId('my seller id')
        .setStoreName('Example store')
    const payload = AmazonPay.Charge.PayloadBuilder
        .setSellerId('my-seller-id')
        .setBillingAgreementId('agreement-id')
        .updateAuthorizeAttributes(authorizeAttributes)
        .updateSellerOrderAttributes(sellerOrderAttribtes)
        .getPayload()
    console.log(payload)

    exampleに単体で動かすもの・handlerに組み込んだもの・TypeScriptでビルドして動かすものの3つを用意しています。

    きつかったところ

    ビルダー作る部分より、TypeScriptでimportできるようにする部分がきつかったです。default exportしないとTypeScriptでimportした時に型エラーがでて、default exportすると今度はESでrequireした時に.defaultをつけないといけなくなって・・・

    もっといい方法ある気はしますが、今はこんな感じでなんとかどっちでもいけるようにしています。

    
    export interface AmazonPay {
        Charge: {
            AuthorizeAttributesBuilder: ChargeAuthorizeAttributesBuilder;
            SellerOrderAttributesBuilder: ChargeSellerOrderAttributesBuilder;
            PayloadBuilder: ChargePayloadBuilder;
        }
        Setup: {
            PayloadBuilder: SetupPayloadBuilder;
            BillingAgreementBuilder: SetupBillingAgreementBuilder;
        }
    }
    const AmazonPay: AmazonPay = {
        Charge: {
            AuthorizeAttributesBuilder: ChargeAuthorizeAttributesFactory.init(),
            SellerOrderAttributesBuilder: ChargeSellerOrderAttributesFactory.init(),
            PayloadBuilder: ChargePayloadFactory.init()
        },
        Setup: {
            PayloadBuilder: SetupPayloadFactory.init(),
            BillingAgreementBuilder: SetupBillingAgreementFactory.init()
        }
    }
    // For TypeScript
    export default AmazonPay
    // For ES / JavaScript
    module.exports = AmazonPay

    今後について

    この要領でDirective系でオブジェクト組み立てるやつはだいたいビルダーにできるかなという気がしています。APLとかいい感じに動的生成できたらいいなぁとか、VS CodeやJetBrain系のサポート受けながら楽にコード書きたいなぁという気持ちです。

    一通り作るところで満足しちゃった感あるので、「これ欲しい!」とかあればプルリクくださいませ。

    広告ここから
    広告ここまで
    Home
    Search
    Bookmark