Customer Sheet を導入する
顧客がアプリの設定で保存済みの決済手段を管理できるようにします。
注
Customer Sheet は、アプリの設定ページでの使用を目的としています。決済フローと支払いには、Mobile Payment Element を使用します。Mobile Payment Element には、決済手段の保存と表示のサポートも組み込まれており、Customer Sheet よりも多くの決済手段に対応しています。
Customer Sheet は、顧客が保存済みの決済手段を管理するための構築済み UI コンポーネントです。Customer Sheet UI は決済フロー以外で使用することができ、外観やスタイルは自社のアプリに合わせてカスタマイズ可能です。顧客は、Customer オブジェクトに保存される決済手段を追加および削除し、デバイスのローカル上に保存されるデフォルトの決済手段を設定できます。Mobile Payment Element と Customer Sheet の両方を使用して、保存された決済手段に対して一貫性のあるエンドツーエンドのソリューションを顧客に提供します。

Stripe を設定する
まず、Stripe アカウントが必要です。今すぐ登録してください。
SDK をインストールするには、app/build.gradle ファイルの dependencies
ブロックに stripe-android
を追加します。
注
SDK の最新リリースおよび過去バージョンの詳細については、GitHub の Releases ページをご覧ください。新しいリリースの公開時に通知を受け取るには、リポジトリのリリースを確認してください。
Stripe の公開可能キーを使用して SDK を設定し、 Application
サブクラスなどで、Stripe API へのリクエストを実行できるようにします。
決済手段を有効にする
支払い方法の設定を表示して、サポートする支払い方法を有効にします。SetupIntent を作成するには、少なくとも 1 つは支払い方法を有効にする必要があります。
多くの顧客から決済を受け付けられるよう、Stripe では、カードやその他一般的な決済手段がデフォルトで有効になっていますが、ビジネスや顧客に適した追加の決済手段を有効にすることをお勧めします。プロダクトと決済手段のサポートについては決済手段のサポートを、手数料については料金体系ページをご覧ください。
注
現時点では、CustomerSheet はカードとアメリカの銀行口座のみに対応しています。
Customer エンドポイントを追加するサーバー側
サーバー側で、Customer の一時キーを取得するエンドポイントと、新しい決済手段を Customer に保存する SetupIntent を作成するエンドポイントの 2 つのエンドポイントを作成します。
- Customer ID を指定して設定された SetupIntent を返すエンドポイントを作成します。
今後の支払いで、顧客が決済フローでオンセッション時にのみ決済手段を使用する場合、usage パラメーターを on_session に設定して、オーソリ率を改善します。
Customer アダプターを作成するクライアント側
CustomerSheet
は StripeCustomerAdapter
を使用することで Stripe と通信できます。クライアント側で、CustomerAdapter
を設定して、サーバー上のこれらのエンドポイントに対するリクエストを行います。
import android.app.Application import androidx.lifecycle.AndroidViewModel import com.stripe.android.customersheet.CustomerAdapter import com.stripe.android.customersheet.ExperimentalCustomerSheetApi @OptIn(ExperimentalCustomerSheetApi::class) class CheckoutViewModel( application: Application ) : AndroidViewModel(application) { val customerAdapter = CustomerAdapter.create( context = getApplication(), customerEphemeralKeyProvider = { myBackend.getEphemeralKey().fold( onSuccess = { response -> CustomerAdapter.Result.success( CustomerEphemeralKey.create( customerId = response.customerId, ephemeralKey = response.ephemeralKeySecret, ) ) }, onFailure = { exception -> CustomerAdapter.Result.failure( cause = exception, displayMessage = "We couldn't retrieve your information, please try again.", ) } ) }, setupIntentClientSecretProvider = { customerId -> myBackend.createSetupIntent(customerId).fold( onSuccess = { response -> CustomerAdapter.Result.success( response.setupIntentClientSecret, ) }, onFailure = { exception -> CustomerAdapter.Result.failure( cause = exception, displayMessage = "We couldn't retrieve your information, please try again.", ) } ) } ) }
画面を設定する
次に、CustomerAdapter
で Customer Sheet を初期化してから、CustomerSheet.Configuration を指定して configure
を呼び出します。present
と retrievePaymentOptionSelection
を呼び出す前に、必ず configure
を呼び出すようにしてください。
import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.activity.viewModels import com.stripe.android.customersheet.CustomerSheet import com.stripe.android.customersheet.ExperimentalCustomerSheetApi import com.stripe.android.customersheet.rememberCustomerSheet @OptIn(ExperimentalCustomerSheetApi::class) class CheckoutActivity : ComponentActivity() { private val viewModel by viewModels<CheckoutViewModel>() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val configuration = CustomerSheet.Configuration.builder(merchantDisplayName = "{{YOUR BUSINESS NAME}}") .build() setContent { val customerSheet = rememberCustomerSheet( customerAdapter = viewModel.customerAdapter, callback = viewModel::handleResult // Implemented in next step ) LaunchedEffect(customerSheet) { customerSheet.configure(configuration = configuration) } } } }
画面を表示する
Customer Sheet を表示します。顧客が画面を閉じると、Customer Sheet は、CustomerSheetResult
を指定して完了ブロックを呼び出します。
import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.activity.viewModels import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.material.Text import androidx.compose.material.TextButton import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import com.stripe.android.customersheet.CustomerSheet import com.stripe.android.customersheet.ExperimentalCustomerSheetApi import com.stripe.android.customersheet.rememberCustomerSheet import com.stripe.android.uicore.image.rememberDrawablePainter @OptIn(ExperimentalCustomerSheetApi::class) class CheckoutActivity : ComponentActivity() { private val viewModel by viewModels<CheckoutViewModel>() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val configuration = CustomerSheet.Configuration.builder(merchantDisplayName = "{{YOUR BUSINESS NAME}}") .headerTextForSelectionScreen("Manage your payment method") .build() setContent { val customerSheet = rememberCustomerSheet( customerAdapter = viewModel.customerAdapter, callback = viewModel::handleResult ) LaunchedEffect(customerSheet) { customerSheet.configure(configuration = configuration) viewModel.handleResult(customerSheet.retrievePaymentOptionSelection()) } val paymentOption by viewModel.paymentOption.collectAsState() Row( modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween, ) { val icon = paymentOption?.icon() if (icon != null) { Image( painter = rememberDrawablePainter( drawable = icon ), contentDescription = "Payment Method Icon", modifier = Modifier.height(32.dp) ) } TextButton( onClick = { customerSheet.present() } ) { Text( text = paymentOption?.label ?: "Select" ) } } } } }
import android.app.Application import androidx.lifecycle.AndroidViewModel import com.stripe.android.customersheet.CustomerAdapter import com.stripe.android.customersheet.CustomerEphemeralKey import com.stripe.android.customersheet.CustomerSheetResult import com.stripe.android.customersheet.ExperimentalCustomerSheetApi import com.stripe.android.paymentsheet.model.PaymentOption import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.update @OptIn(ExperimentalCustomerSheetApi::class) class CheckoutViewModel( application: Application ) : AndroidViewModel(application) { val customerAdapter = // ... private val _paymentOption = MutableStateFlow<PaymentOption?>(null) val paymentOption: StateFlow<PaymentOption?> = _paymentOption fun handleResult(result: CustomerSheetResult) { when (result) { is CustomerSheetResult.Selected -> { // Configure your UI based on the payment option _paymentOption.update { result.selection?.paymentOption } } is CustomerSheetResult.Canceled -> { // Configure your UI based on the payment option _paymentOption.update { result.selection?.paymentOption } } is CustomerSheetResult.Failed -> { // Show the error in your UI } } } }
- 顧客が支払い方法を選択する場合、その結果は、
CustomerSheetResult.
になります。関連付けられる値は、選択されたSelected PaymentOptionSelection
になるか、ユーザーが過去に選択した支払い方法を削除した場合は null になります。支払い方法の詳細は、PaymentOptionSelection
のpaymentMethod
値で確認できます。 - 顧客が画面をキャンセルした場合、その結果は
CustomerSheetResult.
になります。関連付けられる値は、顧客の元のCanceled PaymentOptionSelection
であるか、顧客が以前に決済手段を選択していない場合や、最初に選択した決済手段を削除している場合は null になります。 - エラーが発生した場合、その結果は
CustomerSheetResult.
になります。Failed