Google Pay を使って、Android でスピーディーな購入手続き体験を構築する(Kotlin)

1. はじめに

Google Pay API を使用すると、ユーザーは Google アカウントに保存されている支払い情報を使用して、どこでも支払いを行うことができます。このラボでは、Android 用の Google Pay クライアント ライブラリを使用して、迅速、便利、安全な体験を作り出すことで簡単なサンプル モバイルアプリの購入手続き体験を改善します。それにより、コンバージョンの増加と顧客満足度の向上につなげます。

Auto T-Shirt Shop は、最新の AI 技術を活用した革新的なストアであり、スタイルの好み、天気、季節、ファッションのトレンドといった情報を基に購入すべき最適な商品を提案します。

エンゲージメントに関する指標は膨大にあります。残念ながら、その数字には、購入手続き中に中断されたものも多数含まれます。プロジェクトのオーナーの一人がこの問題に対処しようと決め、ほかの同様のサイトで Google Pay により大きな収益が得られたという結果を示した動画を見たことを思い出しました。そこで、オーナーたちは Google Pay を採用し、その統合をあなたにまかせることにしました。

作成するアプリの概要

この Codelab では、ユーザーが Google Pay でサポートされている支払い方法を使って支払いできるかどうかの判断、支払いボタンの配置と設計、トランザクションの実行など、Google Pay を既存のアプリに統合する方法を説明します。

f5f96f8afc94448c.png

学習内容

  • 既存のアプリに Google Pay を統合する方法
  • 望ましい支払い手段を選ぶ方法
  • ユーザーが Google Pay を使って支払いをする準備ができているかを判断する方法

必要なもの

  • インターネットに接続されているパソコン
  • Android アプリを構築する準備ができている開発環境(Android Studio の使用を推奨します)
  • 最新バージョンの Google Play 開発者サービスがインストールされた Android デバイス

2. 始める

GitHub からリポジトリのクローンを作成する

次のコマンドを使って、パソコン上のフォルダにリポジトリのクローンを作成します。

$ git clone https://github.com/google-pay/android-quickstart

ZIP アーカイブをダウンロードすることもできます。

サンプルアプリの概要を読む

ご覧のとおり、リポジトリはシンプルなファイル構造になっています。この Codelab の主な目標は、使用するプログラミング言語、ライブラリ、ツールに関係なく、この統合を既存および今後のアプリに適用できるようにすることです。

3. Google Pay をアプリ(もしくは自分のアプリ)に統合する

アプリを探索する

アプリを構築したら、エミュレータまたは実機を使って確認できます。Google アカウントと支払い方法がすでに関連付けられているデバイスの使用をおすすめします。

この Codelab で構築するアプリは、非常に高度な機械学習モデルを使い、多くの複雑な特長に基づいて、サイト訪問者に 1 枚の T シャツを提案するデモ モバイル ショップです。では、どのようにしてサイトの読み込みのたびに毎回違う T シャツを提案しているのでしょうか。実を言うと、この非常に高度な機械学習モデルというのは、単なるランダム生成のことです(申し訳ありません)

このデモショップは、既存のアプリや今後構築されるであろうアプリにできるだけ似た方法で構築されていますが、購入するための手段はまだ追加されていません。このデモアプリ上で作業することをおすすめしますが、この Codelab を自由に使って、既存のアプリに Google Pay を統合しても構いません。

上記を行っていない場合は、現状のデモアプリを実行してください。

175215c8c8696ede.png

デモアプリを見れたとしても、特に驚くことはないと思います。画像、価格、商品説明、通常の支払いフォームへと進むボタンといった商品の詳細表示です。

このラボの目標は、基本的に、この煩雑なフローを Google Pay による 2 タップ体験に置き換えることです。

計画を立てる

この統合についてさらに理解を深めるため、プロセスを次の基本的なステップに分割します。

  1. 必要な依存関係を追加する
  2. Google Pay で支払いができるか判断する
  3. Google Pay で支払うボタンを表示する
  4. 支払いリクエストを作成、送信する
  5. 結果を収集する

4. 必要な依存関係を追加する

build.gradle に Google Play 開発者サービスを追加する

Google Pay API を使い始めるためにまず行うことは、必要なパッケージを含む Google Play 開発者サービス内に依存関係を追加することです。これを行うには、アプリ モジュール内の build.gradle ファイル内の dependencies リストに次の implementation アイテムを追加します。このコードラボでは、このモジュールは app と呼ばれます。

implementation "com.google.android.gms:play-services-wallet:18.0.0"

マニフェスト ファイルで API を有効にする

最後に、マニフェスト ファイルの application ノード内に meta-data 要素を追加します。これにより、この API を使用することがシステムに伝わり、API へのアクセスが可能になります。

<meta-data
    android:name="com.google.android.gms.wallet.api.enabled"
    android:value="true" />

5. ユーザー インターフェースと Google Pay ボタンの表示場所を計画する

ビューのレイアウトと全般的な体験は、ユーザーが支払いトランザクションを正常に完了する可能性に影響を与える重要な要素です。Google Pay を使って数回タップするだけで支払い方法を選択できるため、アプリ内でユーザーに支払い方法をいつどこで提供するかについて、より幅広い選択肢を用意できます。たとえば、プロセスの早い段階で、アイテムの詳細ビューなどの領域にクイック決済オプションを追加して、ユーザーが気に入ったアイテムの代金をすぐに支払えるようにできます。

UI とナビゲーションの配置方法を決定したら、次は Google Pay を使って支払いトランザクションをトリガーするボタンを配置します。このボタンのスタイルを指定する際には、ユーザーがアプリ内でこのボタンを見る際の一貫性となじみやすさを保証する一連のガイドラインに沿っていることが期待されます。

a18b3311d84d9dcc.png

この作業を簡単にするために、利用可能なオプションをすべてひとつにまとめ、さまざまな解像度とロケールを用意し、ダウンロードできるようにしました。これには layoutdrawablevalues リソースが含まれ、自身のプロジェクトに直接貼り付けることができます。

ビュー定義に追加する必要があるリソースは、layout ディレクトリ配下の activity_checkout.xml にあります。ビューに追加するには、include 要素を使って適当な位置に配置するだけです。

<include
    android:id="@+id/googlePayButton"
    layout="@layout/buy_with_googlepay_button"
    android:layout_width=<your_width_dimension>
    android:layout_height="@dimen/buy_button_height"
    android:visibility="gone"/>

6. Google Pay API の初期化と構成

API クライアントをインスタンス化する

API の使用を開始するには、Google Pay API の呼び出しに使用するクライアント オブジェクトをインスタンス化する必要があります。アクティビティを作成すれば、すぐにインスタンス化できます。

private lateinit var paymentsClient: PaymentsClient

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_checkout)

    paymentsClient = createPaymentsClient(this)
}

fun createPaymentsClient(activity: Activity): PaymentsClient {
    val walletOptions = Wallet.WalletOptions.Builder()
            .setEnvironment(WalletConstants.ENVIRONMENT_TEST).build()
    return Wallet.getPaymentsClient(activity, walletOptions)
}

支払いクライアントは WalletOptions オブジェクトで初期化されます。環境を ENVIRONMENT_TEST に設定すると、統合全体にわたってダミーの支払い情報を試すことができます。実際のトランザクションをサポートする操作を作成する準備ができたら、環境プロパティを ENVIRONMENT_PRODUCTION に更新できます。

スケルトン

Google Pay API と通信を行うたびに、対象とする API のバージョンなど、リクエストに含める必要がある構成パラメータがいくつもあります。この Codelab の目的に沿うように、オブジェクトにはアプリで受け入れられる支払い方法に関する情報も含まれています。最終的な構造は次のようになります。

{
    apiVersion: number,
    apiVersionMinor: number,
    allowedPaymentMethods: Array
}

allowedPaymentMethods プロパティは支払い方法のリストを受け取ります。すべての支払い方法に対して、次のプロパティを含める必要があります。

{
    type: 'CARD',
    parameters: {
        allowedCardNetworks: Array.<string>,
        allowedAuthMethods: Array.<string>
    }
}

typeparameters に加え、後に tokenizationSpecification プロパティも追加します。このプロパティは対象のユーザーが Google Pay で支払うことができるかどうかの判断には必要ありませんが、PaymentDataRequest 呼び出しで使用され、選択された支払い方法に関連するデータの処理方法を定義するために使用されます。では、ステップごとに見ていきます。

支払い方法の構成

この例では、Mastercard と Visa カードによる決済のみを、トークン化とカード番号(PAN)形式で受け付けます。支払い方法は次のようになります。

private val baseCardPaymentMethod = JSONObject().apply {
    put("type", "CARD")
    put("parameters", JSONObject().apply {
        put("allowedCardNetworks", JSONArray(listOf("VISA", "MASTERCARD")))
        put("allowedAuthMethods", JSONArray(listOf("PAN_ONLY", "CRYPTOGRAM_3DS")))
    })
}

まとめ

要点をまとめましょう。

アプリで受け付ける支払い方法を 1 つ定義し、API バージョン 2.0 で動かそうとしています。完成した構成は次のようになります。

private val baseCardPaymentMethod = JSONObject().apply {
    put("type", "CARD")
    put("parameters", JSONObject().apply {
        put("allowedCardNetworks", JSONArray(listOf("VISA", "MASTERCARD")))
        put("allowedAuthMethods", JSONArray(listOf("PAN_ONLY", "CRYPTOGRAM_3DS")))
    })
}

private val googlePayBaseConfiguration = JSONObject().apply {
    put("apiVersion", 2)
    put("apiVersionMinor", 0)
    put("allowedPaymentMethods",  JSONArray().put(baseCardPaymentMethod))
}

基本構成の準備ができたので、次はファンクションに移りましょう。

7. Google Pay で支払う準備ができているか判断する

ユーザーに迅速で便利な購入手続き体験を提供することが、Google Pay の主な目的の 1 つです。このことは、ユーザーが Google Pay を利用できる状況だけでなく、利用できない状況にも当てはまります。isReadyToPay リクエストを使用すると、Google Pay で支払う準備ができているかどうかを判断でき、それに応じて、サイト内のエクスペリエンスを変更できます。

ユーザーは Google Pay で支払うことができるのか

まず行うことは、アプリ内で支払おうとしているユーザーが Google Pay を使って支払えるかどうかを確認することです。このリクエストでは、Google Pay API のバージョンとサイトで許可している支払い方法を指定する必要があります。これは、前のステップで定義した基本構成オブジェクトに含まれるものとまったく同じです。

val readyToPayRequest =
        IsReadyToPayRequest.fromJson(googlePayBaseConfiguration.toString())

val readyToPayTask = paymentsClient.isReadyToPay(readyToPayRequest)
task.addOnCompleteListener { task ->
    try {
        task.getResult(ApiException::class.java)?.let(::setGooglePayAvailable)
    } catch (exception: ApiException) {
        // Error determining readiness to use Google Pay.
        // Inspect the logs for more details.
    }
}

ご覧のように、呼び出しが失敗のレスポンスを返した場合、Google Pay ではそれ以上のアクションは実行されません。この場合、最も適切な次のステップは、ほかの支払い手段をサポートする追加の UI を表示することです。

一方、レスポンスが成功だった場合は、ユーザーが Google Pay を利用できる準備が整ったことになります。その結果、ユーザーのアクティベーション(例: ボタンのクリック)時に、Google Pay ボタンを表示して決済処理を開始できます。

Google Pay で支払うボタンを表示する

この時点で、Google Pay ボタンを再び表示できます。

private fun setGooglePayAvailable(available: Boolean) {
    if (available) {
        googlePayButton.visibility = View.VISIBLE
        googlePayButton.setOnClickListener { requestPayment() }
    } else {
       // Unable to pay using Google Pay. Update your UI accordingly.
    }
}

private fun requestPayment() {
  // TODO: Perform transaction
}

ボタンのクリック イベントを処理する関数も定義しています。次のセクションでは、この関数を使って支払い方法をリクエストします。

8. 支払い処理

支払いリクエストの準備

この時点で、Google Pay API が読み込まれ、アプリのユーザーが Google Pay を使って支払いを行えることが確認されました。その結果、UI に Google Pay 支払いボタンが表示され、ユーザーがトランザクションを開始する準備が整いました。ログインしているそれぞれのユーザーで利用可能な支払い方法を含んだ支払いシートを読み込みます。

以前、isReadyToPay リクエストの定義で行ったように、この呼び出しは、先に定義した基本構成オブジェクトのプロパティ(apiVersionapiVersionMinorallowedPaymentMethods)に加え、いくつかの新しいプロパティも要求します。今回は、tokenizationSpecification という新しいプロパティと、このリクエストの目的のみに関連する支払い方法の追加 parameters があります。さらに、transactionInfo および merchantInfo も追加する必要があります。

支払い方法に追加の必須情報を含める

まず、以前に使用した基本的なカード支払い方法のコピーを作成します。このカード支払い方法には、選択した支払い方法に関連するデータの処理方法を定義する tokenizationSpecification プロパティとともに、実際のトランザクションに必要なデータ要件も定義する必要があります。この例では、請求先住所と電話番号が必要となります。

tokenizationSpecification プロパティ

トークン化の仕様は、ユーザーが選択した支払い方法がどのように処理され、トランザクションを完了するために使用されるかを決定します。

サポートしている処理手段は 2 種類あります。PCI DSS に準拠したサーバー内から支払いトランザクションを処理している場合は、DIRECT 仕様タイプを使います。この例では、支払いを処理するために支払いゲートウェイを使用するため、PAYMENT_GATEWAY 仕様タイプを設定します。トークン化仕様は次のようになります。

private val tokenizationSpecification = JSONObject().apply {
    put("type", "PAYMENT_GATEWAY")
    put("parameters", JSONObject(mapOf(
            "gateway" to "example",
            "gatewayMerchantId" to "exampleGatewayMerchantId")))
}

parameters セクションでは、Google Pay API でサポートされているプロバイダのリストからゲートウェイを指定し、それぞれのゲートウェイで必要な追加構成を行うことができます。このラボの目的としては、実行されたトランザクションのテスト結果を得られる example ゲートウェイを使用すれば十分です。

追加パラメータ

同様に、トランザクションを正常に実行するためにリクエストする必要がある情報について、詳細を提供できるようになりました。この例では、トランザクションでユーザーの完全な形式の請求先住所と電話番号が必要であることを示すために、billingAddressRequiredbillingAddressParameters のプロパティを追加する必要があります。

private val cardPaymentMethod = JSONObject().apply {
    put("type", "CARD")
    put("tokenizationSpecification", tokenizationSpecification)
    put("parameters", JSONObject().apply {
        put("allowedCardNetworks", JSONArray(listOf("VISA", "MASTERCARD")))
        put("allowedAuthMethods", JSONArray(listOf("PAN_ONLY", "CRYPTOGRAM_3DS")))
        put("billingAddressRequired", true)
        put("billingAddressParameters", JSONObject(mapOf("format" to "FULL")))
    })
}

トランザクションについての情報を追加する

transactionInfo プロパティには、トランザクションに関する金銭的な詳細を示すオブジェクトである価格通貨コードISO 4217 alpha 形式)、価格ステータスが含まれます。価格ステータスは、トランザクションの性質(指定された配送先住所によって価格が変わる場合など)に応じて final または estimated となります。

private val transactionInfo = JSONObject().apply {
    put("totalPrice", "123.45")
    put("totalPriceStatus", "FINAL")
    put("currencyCode", "USD")
}

販売者についての情報を追加する

支払いリクエストには、merchantInfo プロパティに基づいてリクエストを実行する販売者に関する情報が含まれます。このコードラボでは、次の 2 つに焦点を当てます。

  • merchantId に見込まれるのは、Google によりアプリが本番環境で動作することが承認された場合に、アカウントに関連付けられる識別子です。販売者 ID は、Google Pay Business Console で取得できます。TEST 環境の使用中は、評価されないことに注意してください。
  • merchantName はユーザーに表示されるアプリまたは組織の名前です。この名前は、操作をリクエストしている対象に関する詳細情報をユーザーに提供するために、Google Pay 支払いシート内に表示される場合があります。

準備ができたら、販売者に関する情報を paymentDataRequest オブジェクトに追加するだけです。

private val merchantInfo = JSONObject().apply {
    put("merchantName", "Example Merchant")
    put("merchantId", "01234567890123456789")
}

支払い情報をリクエストし、結果を処理する

以前に定義した構成を最終のオブジェクトに統合し、loadPaymentData リクエストに渡します。

private val paymentDataRequestJson = JSONObject(googlePayBaseConfiguration.toString()).apply {
    put("allowedPaymentMethods", JSONArray().put(cardPaymentMethod))
    put("transactionInfo", transactionInfo)
    put("merchantInfo", merchantInfo)
}

この時点で、Google Pay API に有効な支払い方法を要求するために必要なものがすべてそろいました。実行するには、PaymentsClient オブジェクトの loadPaymentData メソッドを使って、定義した構成を渡します。

val paymentDataRequest =
        PaymentDataRequest.fromJson(paymentDataRequestJson.toString())

AutoResolveHelper.resolveTask(
        paymentsClient.loadPaymentData(paymentDataRequest),
        this, LOAD_PAYMENT_DATA_REQUEST_CODE)

このメソッドを呼び出すと、Google Pay 支払いシートが表示されます。構成エラーがない場合は、現在ログインしているアカウントに関連付けられている有効な支払い方法のリストが表示されます。

選択するとシートが閉じ、結果がアクティビティに返され、onActivityResult メソッドによって取得されます。

public override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
    when (requestCode) {
        LOAD_PAYMENT_DATA_REQUEST_CODE -> {
            when (resultCode) {
                Activity.RESULT_OK ->
                    PaymentData.getFromIntent(data)?.let(::handlePaymentSuccess)

                Activity.RESULT_CANCELED -> {
                    // The user cancelled without selecting a payment method.
                }

                AutoResolveHelper.RESULT_ERROR -> {
                    AutoResolveHelper.getStatusFromIntent(data)?.let {
                        handleError(it.statusCode)
                    }
                }
            }
        }
    }
}

選択が成功した場合、選択された支払い方法についての関連情報を含む PaymentData オブジェクトが結果として処理されます。

{
  "apiVersionMinor": 0,
  "apiVersion": 2,
  "paymentMethodData": {
    "description": "Visa •••• 1234",
    "tokenizationData": {
      "type": "PAYMENT_GATEWAY",
      "token": "examplePaymentMethodToken"
    },
    "type": "CARD",
    "info": {
      "cardNetwork": "VISA",
      "cardDetails": "1234",
      "billingAddress": {
        "phoneNumber": ...,
        ...
      }
    }
  }
}

これで、この支払い方法情報を使用して実際のトランザクションを実行できるようになります。

private fun handlePaymentSuccess(paymentData: PaymentData) {
    val paymentMethodToken = paymentData
            .getJSONObject("tokenizationData")
            .getString("token")

    // Sample TODO: Use this token to perform a payment through your payment gateway
}

9. 完了

Google Pay API をアプリに統合することができました。

本番環境に導入する前に、統合チェックリストを確認してください。確認できたら、クライアント構成に追加するための販売者 ID(merchantId)を受け取ります。同様に、サードパーティの決済代行業者またはゲートウェイを使う予定(もしくはすでに使っている)場合、Google Pay 上でサポートされているプロバイダのリストを確認し、構成してください。Google Pay と直接統合する場合は、このトピックに関するドキュメント セクションをご覧ください。

学習した内容

  • アプリに Google API をインポートして構成する。
  • API のサポートを判断し、それに応じて対応する。
  • ユーザーが Google Pay を使って支払えるようにボタンを追加する。
  • 以前に保存されたユーザーの支払い情報を読み込み、処理する。

次のステップ

  • 実際のアプリで Google Pay をテストする(まだテストしていない場合)。
  • Google Pay Business Console で販売者 ID を取得する。
  • 統合チェックリストを確認する。
  • 2 種類の統合(直接統合または支払いゲートウェイやプロセッサの使用)を比較し、どちらが適しているのかを判断する。

詳細

これは役に立ちましたか。

期待以上に役に立った 期待どおりだった あまり役に立たなかった

ほかのタイプの統合(直接統合、非決済カード、passes API)についてのサポートを行うコードラボを見たいですか。

はい、ぜひ見たいです。 いいえ、すでにあるもので十分です。