1. はじめに
作成するアプリの概要
この Codelab を完了すると、Android 向けに Google Pay 統合が機能する最小限の Jetpack Compose アプリが完成します。このプロジェクトは、処理のために決済サービス プロバイダに送信される決済トークンを取得します。
学習内容
- Google Pay Jetpack Compose ライブラリのインストールと構成方法
- Google Pay ボタンを表示してクリックを処理する方法
- Google Pay から支払いトークンをリクエストする方法
必要なもの
- Android Studio(最新の安定版)がインストールされている。
- Android Studio でセットアップされた Android SDK とエミュレータまたはデバイス。
- 本番環境では、Google Pay
merchantIdが必要になります。Google Pay & Wallet Console での登録は 1 分で完了します。今すぐ登録しましょう。
2. Jetpack Compose プロジェクトを作成する
プロジェクト ファイルを作成する
- Android Studio で
gpay-composeという名前の新しい Jetpack Compose プロジェクトを作成します。- Android Studio を開き、
New Projectを選択します。 Empty Activity (Jetpack Compose)テンプレートを選択します。- 名前:
gpay-compose、パッケージ名:com.example.gpay。 - 言語: Kotlin、最小 SDK: API 21 以降。
- [完了] をクリックしてプロジェクトを生成します。
- Android Studio を開き、
- Google Pay Compose ボタンの依存関係を追加します。
app/build.gradle(.kts)ファイルに次を追加します。 Groovy DSL:dependencies { implementation("com.google.pay.button:compose-pay-button:1.0.0") }dependencies { implementation 'com.google.pay.button:compose-pay-button:1.0.0' } - Google Play 開発者サービス ウォレットの依存関係を追加する(Google Pay シートを開くため):
app/build.gradle(.kts)ファイルに次の依存関係を追加します。 プロジェクトで Groovy DSL を使用している場合は、次のようにします。dependencies { implementation("com.google.android.gms:play-services-wallet:19.3.0") }dependencies { implementation 'com.google.android.gms:play-services-wallet:19.3.0' } - Android Studio で
MainActivity.ktを開き、内容を次の最小限の Compose アプリ スキャフォールドに置き換えます(ボタンの接続は後で行います)。package com.example.gpay import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background) { Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { // Google Pay button added in the next section } } } } }
3. Google Pay を設定する
Google Pay の支払いリクエストにはリクエスト オブジェクトが必要です。ここで baseGooglePayRequest として定義されたオブジェクトには、すべてのリクエストに共通する最小限の設定が含まれています。リクエストに応じて追加の設定が追加されます。この Codelab で確認します。
Google Pay の構成定数を MainActivity.kt に追加します(次のステップで再利用します)。
private const val merchantId = "12345678901234567890"
// This is the base configuration for all Google Pay payment data requests.
private val baseGooglePayRequest = """
{
"apiVersion": 2,
"apiVersionMinor": 0,
"allowedPaymentMethods": [
{
"type": "CARD",
"parameters": {
"allowedAuthMethods": [
"PAN_ONLY", "CRYPTOGRAM_3DS"
],
"allowedCardNetworks": [
"AMEX", "DISCOVER", "INTERAC", "JCB", "MASTERCARD", "VISA"
]
},
"tokenizationSpecification": {
"type": "PAYMENT_GATEWAY",
"parameters": {
"gateway": "example",
"gatewayMerchantId": "exampleGatewayMerchantId"
}
}
}
],
"merchantInfo": {
"merchantId": "$merchantId"
}
}
""".trimIndent()
リソース
- API リファレンス: Google Pay API のリクエスト オブジェクトのドキュメント
- API リファレンス: 許可される認証方法、許可されるカード ネットワーク、適切なゲートウェイ値を含むトークン化の仕様について詳しくは、
PaymentMethodをご覧ください。
4. Google Pay ボタンを追加する
Compose Pay Button を使用してネイティブの Google Pay ボタンをレンダリングし、Wallet API を使用して Google Pay シートを開きます。
MainActivity.kt の内容全体を次の完全な例(構成、ボタン、支払いフローを含む)に置き換えます。
package com.example.gpay
import android.os.Bundle
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import com.google.android.gms.common.api.CommonStatusCodes
import com.google.android.gms.tasks.Task
import com.google.android.gms.wallet.contract.TaskResultContracts.GetPaymentDataResult
import com.google.android.gms.wallet.*
import com.google.pay.button.ButtonTheme
import com.google.pay.button.ButtonType
import com.google.pay.button.PayButton
import org.json.JSONObject
private const val merchantId = "12345678901234567890"
// Base Google Pay request used for both the button and the Wallet request
private val baseGooglePayRequest = """
{
"apiVersion": 2,
"apiVersionMinor": 0,
"allowedPaymentMethods": [
{
"type": "CARD",
"parameters": {
"allowedAuthMethods": [
"PAN_ONLY", "CRYPTOGRAM_3DS"
],
"allowedCardNetworks": [
"AMEX", "DISCOVER", "INTERAC", "JCB", "MASTERCARD", "VISA"
]
},
"tokenizationSpecification": {
"type": "PAYMENT_GATEWAY",
"parameters": {
"gateway": "example",
"gatewayMerchantId": "exampleGatewayMerchantId"
}
}
}
],
"merchantInfo": {
"merchantId": "$merchantId"
}
}
""".trimIndent()
class MainActivity : ComponentActivity() {
private val paymentDataLauncher = registerForActivityResult(GetPaymentDataResult()) { taskResult ->
when (taskResult.status.statusCode) {
CommonStatusCodes.SUCCESS -> {
handlePaymentData(taskResult.result!!)
}
//CommonStatusCodes.CANCELED -> The user canceled
//CommonStatusCodes.DEVELOPER_ERROR -> The API returned an error (it.status: Status)
//else -> Handle internal and other unexpected errors
}
}
private lateinit var paymentsClient: PaymentsClient
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Create the PaymentsClient
paymentsClient = Wallet.getPaymentsClient(
this,
Wallet.WalletOptions.Builder()
.setEnvironment(WalletConstants.ENVIRONMENT_TEST) // Switch to PRODUCTION when ready
.build()
)
// Derive allowedPaymentMethods for the button from baseGooglePayRequest
val allowedPaymentMethods = JSONObject(baseGooglePayRequest)
.getJSONArray("allowedPaymentMethods")
.toString()
setContent {
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
PayButton(
onClick = { requestPayment(paymentDataLauncher) },
allowedPaymentMethods = allowedPaymentMethods,
type = ButtonType.Pay,
theme = ButtonTheme.Light
)
}
}
}
private fun requestPayment(launcher: ActivityResultLauncher<Task<PaymentData>>) {
// Build a PaymentDataRequest from the base request by adding transaction info
val requestJson = JSONObject(baseGooglePayRequest).apply {
put("transactionInfo", JSONObject().apply {
put("totalPrice", "14.95")
put("totalPriceStatus", "FINAL")
put("countryCode", "US")
put("currencyCode", "USD")
})
}
val request = PaymentDataRequest.fromJson(requestJson.toString())
val task = paymentsClient.loadPaymentData(request)
task.addOnCompleteListener(paymentDataLauncher::launch)
}
private fun handlePaymentData(paymentData: PaymentData?) {
val json = paymentData?.toJson() ?: return
val paymentMethodData = JSONObject(json).getJSONObject("paymentMethodData")
val tokenizationData = paymentMethodData.getJSONObject("tokenizationData")
val token = tokenizationData.getString("token")
// Send 'token' to your payment service provider (PSP)
println("Payment token: $token")
}
}
5. 支払いリクエストを作成する
Google Pay ボタンが押されると、requestPayment(...) は baseGooglePayRequest に transactionInfo を追加して PaymentDataRequest をビルドし、Google Pay シートを開いて、支払いトークンを返します。
要点
- ボタン:
PayButtonはネイティブの Google Pay ボタンをレンダリングします。 - クライアント:
PaymentsClientが TEST または PRODUCTION で構成されています。 - リリース: 必要に応じて
loadPaymentDataを使用し、IntentSenderで解決します。 - トークン:
PaymentData.toJson()を解析してpaymentMethodData.tokenizationData.tokenを抽出し、PSP に送信します。
6. まとめ
これでこの Codelab は終了です。Android 向け Jetpack Compose アプリに Google Pay API を統合する方法を学びました。
プロジェクトを実行する
Android Studio(Run > Run 'app')からプロジェクトを実行して、アプリを起動します。
次のステップ
参考情報
- Discord の #payments チャンネルで会話に参加する
- X で @GooglePayDevs をフォローする
- YouTube で Google Pay 関連の動画を見る