Payment Intents API を使用して、購入から支払い詳細を保存します。以下のようなユースケースがあります。
- 顧客に EC ストアの注文の請求を行い、以降の購入に備えて情報を保存します。
- 継続支払いの初回の支払いを開始します。
- 頭金を請求し、情報を保存して後から全額を請求できるようにします。
カード提示取引
Stripe Terminal を介した支払いなどのカード提示取引では、別のプロセスを使用して決済手段を保存します。詳細については、Terminal のドキュメントをご覧ください。
法令遵守
顧客の支払いの詳細を保存する際、適用されるすべての法律、規制、ネットワークの規則に準拠する責任はお客様にあります。これらの要件は通常、以降の購入時の決済フローでの顧客の支払い方法を提示する、顧客がお客様のウェブサイトやアプリを使用していないときに請求するなど、将来に備えて顧客の支払い方法を保存する場合に適用されます。支払い方法の保存をどのように計画しているかを示す規約をウェブサイトやアプリに追加し、顧客が許可できるようにします。
支払い方法を保存する場合、規約に記載された特定の用途にのみ使用できます。顧客がオフラインであるときに支払い方法に請求して、以降の購入に備えたオプションとして保存する場合は、この特定の用途について顧客から明示的に同意を収集する必要があります。たとえば、同意を収集するために「今後の使用に備えて支払い方法を保存する」チェックボックスを使用します。
顧客がオフラインのときに請求するには、規約に以下の内容を含める必要があります。
- 指定された取引で顧客の代理として単独の支払いまたは一連の支払いを開始することをお客様に許可するという、顧客からお客様への同意
- 予期される支払い時期と支払い頻度 (たとえば、請求が予定されている分割払いなのか、サブスクリプションの決済なのか、あるいは予定されていないトップアップなのか)。
- 支払い金額の決定方法
- 支払い方法をサブスクリプションサービスに使用する場合は、キャンセルに関するポリシー
これらの規約に関する顧客の書面による同意の記録を必ず保管してください。
まず、Stripe アカウントが必要です。今すぐ登録してください。
サーバー側
この実装では、Stripe API と通信するエンドポイントがサーバー上に必要です。サーバーから Stripe API にアクセスするには、Stripe の公式ライブラリを使用してください。
クライアント側
Stripe Android SDK はオープンソースであり、詳細なドキュメントが提供されています。
SDK をインストールするには、app/build.gradle ファイルの dependencies
ブロックに stripe-android
を追加します。
plugins {
id("com.android.application")
}
android { ... }
dependencies {
implementation("com.stripe:stripe-android:21.19.0")
implementation("com.stripe:financial-connections:21.19.0")
}
カード支払いはデフォルトで有効になっています。決済手段の設定を表示して、対応する予定の決済手段を有効にします。
この接続方法では、以下の 3 つの Stripe API オブジェクトを使用します。
PaymentIntent (支払いインテント): Stripe はこれを使用して、顧客から支払いを回収する意図を示し、プロセス全体を通して支払いの試行と支払い状態の変化を追跡します。
Customer (顧客): 今後の支払いに備えて決済手段を設定するには、決済手段をCustomer に関連付ける必要があります。Customer オブジェクトは、顧客がビジネスでアカウントを作成するときに作成します。顧客がゲストとして支払いを行う場合は、支払いの前に Customer オブジェクトを作成し、後でこのオブジェクトを顧客のアカウントを表す内部表現に関連付けることができます。
Customer Ephemeral Key (顧客の一時キー): Customer オブジェクトの情報は機密情報であるため、アプリから直接取得することはできません。Ephemeral Key により、SDK に Customer への一時的なアクセス権が付与されます。
セキュリティ上の理由により、アプリでこれらのオブジェクトを作成することはできません。代わりに、サーバー側で以下を行うエンドポイントを追加します。
- Customer を取得するか、新規作成する。
- Customer の一時キーを作成する。
- amount、currency、customer、setup_future_usage を指定して PaymentIntent を作成します。オプションで、
automatic_payment_methods
パラメーターを含めることもできます。Stripe は、最新バージョンの API ではこの機能をデフォルトで有効にしています。 - PaymentIntent の client secret、一時キーの
secret
、顧客の id、および貴社の公開可能キーをアプリに返します。
注
モバイル Payment Element は、クレジットカードとアメリカの銀行口座を使用する setup_future_usage
のみに対応しています。
決済プロセス中に顧客に表示される支払い方法は、PaymentIntent にも含まれています。Stripe にダッシュボードの設定から支払い方法を取得するよう指定することも、手動でリストに表示することもできます。選択したオプションにかかわらず、顧客に表示される支払い方法は、PaymentIntent で渡す通貨によって絞り込まれることにご注意ください。たとえば、PaymentIntent で eur
を渡し、ダッシュボードで OXXO が有効になっている場合、OXXO は eur
による決済に対応していないため、顧客に表示されません。
構築済みのシステムで、支払い方法を提供するためにコードベースのオプションが必要になる場合を除き、自動化されたオプションを使用することをお勧めします。これは、Stripe が通貨、支払い方法の制約、その他のパラメーターを評価して、対応可能な支払い方法を決定するためです。自動化されたオプションでは、購入完了率の向上につながり、使用通貨と顧客の所在地に最適な支払い方法が優先的に表示されます。
注
このエンドポイントの実行可能な実装内容を Glitch でテストします。
支払い方法はダッシュボードで管理できます。Stripe は取引額、通貨、決済フローなどの要素に基づいて、適切な支払い方法が返されるように処理します。PaymentIntent は、ダッシュボードで設定された支払い方法を使用して作成されます。ダッシュボードを使用しない場合や、支払い方法を手動で指定する場合は、payment_method_types
属性を使用して支払い方法を一覧表示することができます。
curl https://api.stripe.com/v1/customers \
-u sk_test_BQokikJOvBiI2HlWgH4olfQ2
: \
-X "POST"
curl https://api.stripe.com/v1/ephemeral_keys \
-u sk_test_BQokikJOvBiI2HlWgH4olfQ2
: \
-H "Stripe-Version: 2025-05-28.basil" \
-X "POST" \
-d "customer"="{{CUSTOMER_ID}}" \
curl https://api.stripe.com/v1/payment_intents \
-u sk_test_BQokikJOvBiI2HlWgH4olfQ2
: \
-X "POST" \
-d "customer"="{{CUSTOMER_ID}}" \
-d "amount"=1099 \
-d "currency"="eur" \
-d "setup_future_usage"="off_session" \
-d "automatic_payment_methods[enabled]"=true \
決済ページでは、Mobile Payment Element を表示する前に以下を実行する必要があります。
決済アクティビティーの onCreate
内で PaymentSheet
インスタンスを初期化して、結果を処理するメソッドを渡します。
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import com.stripe.android.paymentsheet.PaymentSheet
import com.stripe.android.paymentsheet.PaymentSheetResult
@Composable
fun App() {
val paymentSheet = remember { PaymentSheet.Builder(::onPaymentSheetResult) }.build()
}
private fun onPaymentSheetResult(paymentSheetResult: PaymentSheetResult) {
}
次に、前のステップで作成したエンドポイントから、PaymentIntent の client secret、一時キーの secret、Customer ID、公開可能キーを取得します。公開可能キーは PaymentConfiguration
を使用して設定し、その他は保存して、PaymentSheet を表示するときに使用します。
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.ui.platform.LocalContext
import com.github.kittinunf.fuel.httpPost
import com.github.kittinunf.fuel.json.responseJson
import com.stripe.android.PaymentConfiguration
import com.stripe.android.paymentsheet.PaymentSheet
import com.stripe.android.paymentsheet.PaymentSheetResult
import com.github.kittinunf.result.Result
@Composable
fun App() {
val paymentSheet = remember { PaymentSheet.Builder(::onPaymentSheetResult) }.build()
val context = LocalContext.current
var customerConfig by remember { mutableStateOf<PaymentSheet.CustomerConfiguration?>(null) }
var paymentIntentClientSecret by remember { mutableStateOf<String?>(null) }
LaunchedEffect(context) {
"Your backend endpoint/payment-sheet".httpPost().responseJson { _, _, result ->
if (result is Result.Success) {
val responseJson = result.get().obj()
paymentIntentClientSecret = responseJson.getString("paymentIntent")
customerConfig = PaymentSheet.CustomerConfiguration(
id = responseJson.getString("customer"),
ephemeralKeySecret = responseJson.getString("ephemeralKey")
)
val publishableKey = responseJson.getString("publishableKey")
PaymentConfiguration.init(context, publishableKey)
}
}
}
}
private fun onPaymentSheetResult(paymentSheetResult: PaymentSheetResult) {
}
顧客が決済ボタンをタップしたら、presentWithPaymentIntent を呼び出して支払い画面を表示します。顧客が決済を完了すると、画面が閉じ、PaymentSheetResult とともに PaymentSheetResultCallback が呼び出されます。
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.platform.LocalContext
import com.github.kittinunf.fuel.httpPost
import com.github.kittinunf.fuel.json.responseJson
import com.stripe.android.PaymentConfiguration
import com.stripe.android.paymentsheet.PaymentSheet
import com.stripe.android.paymentsheet.PaymentSheetResult
import com.github.kittinunf.result.Result
@OptIn(ExperimentalCustomerSessionApi::class)
@Composable
fun App() {
val paymentSheet = remember { PaymentSheet.Builder(::onPaymentSheetResult) }.build()
val context = LocalContext.current
var customerConfig by remember { mutableStateOf<PaymentSheet.CustomerConfiguration?>(null) }
var paymentIntentClientSecret by remember { mutableStateOf<String?>(null) }
LaunchedEffect(context) {
"Your backend endpoint/payment-sheet".httpPost().responseJson { _, _, result ->
if (result is Result.Success) {
val responseJson = result.get().obj()
paymentIntentClientSecret = responseJson.getString("paymentIntent")
customerConfig = PaymentSheet.CustomerConfiguration(
id = responseJson.getString("customer"),
ephemeralKeySecret = responseJson.getString("ephemeralKey")
)
val publishableKey = responseJson.getString("publishableKey")
PaymentConfiguration.init(context, publishableKey)
}
}
}
Button(
onClick = {
val currentConfig = customerConfig
val currentClientSecret = paymentIntentClientSecret
if (currentConfig != null && currentClientSecret != null) {
presentPaymentSheet(paymentSheet, currentConfig, currentClientSecret)
}
}
) {
Text("Checkout")
}
}
private fun presentPaymentSheet(
paymentSheet: PaymentSheet,
customerConfig: PaymentSheet.CustomerConfiguration,
paymentIntentClientSecret: String
) {
paymentSheet.presentWithPaymentIntent(
paymentIntentClientSecret,
PaymentSheet.Configuration.Builder(merchantDisplayName = "My merchant name")
.customer(customerConfig)
.allowsDelayedPaymentMethods(true)
.build()
)
}
private fun onPaymentSheetResult(paymentSheetResult: PaymentSheetResult) {
when(paymentSheetResult) {
is PaymentSheetResult.Canceled -> {
print("Canceled")
}
is PaymentSheetResult.Failed -> {
print("Error: ${paymentSheetResult.error}")
}
is PaymentSheetResult.Completed -> {
print("Completed")
}
}
}
allowsDelayedPaymentMethods
を true に設定すると、アメリカの銀行口座などの 遅延通知型の支払い方法を使用できます。これらの支払い方法では、PaymentSheet
が完了した時点では最終的な支払いステータスが判明せず、後になって成功または失敗が確定します。このようなタイプの支払い方法に対応する場合は、注文が確定済みであることを顧客に通知し、支払いが成功した場合にのみ注文のフルフィルメント (商品の発送など) を実行するようにします。
支払いが完了すると、Stripe は payment_intent.succeeded イベントを送信します。ダッシュボードの Webhook ツールを使用するか Webhook のガイドに従ってこれらのイベントを受信し、顧客への注文確認メールの送信、データベースでの売上の記録、配送ワークフローの開始などのアクションを実行します。
クライアントからのコールバックを待つのではなく、これらのイベントをリッスンします。クライアントでは、コールバックが実行される前に顧客がブラウザーのウィンドウを閉じたり、アプリを終了する場合、また悪意を持つクライアントがレスポンスを不正操作する場合もあります。非同期型のイベントをリッスンするよう組み込みを設定すると、単一の組み込みで複数の異なるタイプの支払い方法を受け付けることができます。
Payment Element を使用して支払いを回収する場合は、payment_intent.succeeded
イベントのほかにこれらのイベントを処理することをお勧めします。
イベント | 説明 | アクション |
---|
payment_intent.succeeded | 顧客が正常に支払いを完了したときに送信されます。 | 顧客に注文の確定を送信し、顧客の注文のフルフィルメントを実行します。 |
payment_intent.processing | 顧客が正常に支払いを開始したが、支払いがまだ完了していない場合に送信されます。このイベントは、多くの場合、顧客が口座引き落としを開始するときに送信されます。その後、payment_intent.succeeded イベント、また、失敗の場合は payment_intent.payment_failed イベントが送信されます。 | 顧客に注文確認メールを送信し、支払いが保留中であることを示します。デジタル商品では、支払いの完了を待たずに注文のフルフィルメントを行うことが必要になる場合があります。 |
payment_intent.payment_failed | 顧客が支払いを試みたが、支払いに失敗する場合に送信されます。 | 支払いが processing から payment_failed に変わった場合は、顧客に再度支払いを試すように促します。 |
法令遵守
顧客の支払いの詳細を保存する際、お客様は適用されるすべての法律、規制、ネットワークの規則に準拠する責任があります。将来の購入に備えて顧客に過去の決済手段を提供する際は、必ず、特定の将来の使用に備えて決済手段の詳細を保存することについての同意を顧客から収集した決済手段をリストアップします。顧客に関連付けられた決済手段のうち、将来の購入用の保存済みの決済手段として顧客に提示できるものと提示できないものを区別するには、allow_redisplay パラメーターを使用します。
購入者にオフセッションで請求する準備ができたら、Customer ID と PaymentMethod ID を使用して、PaymentIntent を作成します。請求する決済手段を見つけるには、顧客に関連付けられた決済手段を一覧表示します。この例ではカードが一覧表示されますが、サポートされているすべてのタイプを一覧表示できます。
curl -G https://api.stripe.com/v1/payment_methods \
-u "sk_test_BQokikJOvBiI2HlWgH4olfQ2
:" \
-d customer= \
-d type=card
Customer ID と PaymentMethod ID を取得したら、支払いの金額と通貨を使用して PaymentIntent を作成します。その他のいくつかのパラメーターを設定して、オフセッションの支払いを行います。
- off_session を
true
に設定して、支払いの試行時に購入者が決済フローを実行中でないことと、カード発行会社、銀行、その他の決済機関などのパートナーからの認証リクエストに対応できないことを示します。決済フローの実行時にパートナーが認証をリクエストした場合、Stripe は前回のオンセッション取引の顧客情報を使用して免除をリクエストします。免除の条件を満していない場合は PaymentIntent からエラーが返されることがあります。 - PaymentIntent の confirm プロパティの値を
true
に設定します。これにより、PaymentIntent が作成されると直ちに確定されます。 - payment_method を PaymentMethod の ID に設定し、customer を Customer の ID に設定します。
curl https://api.stripe.com/v1/payment_intents \
-u sk_test_BQokikJOvBiI2HlWgH4olfQ2
: \
-d amount=1099 \
-d currency=usd \
-d "automatic_payment_methods[enabled]"=true \
-d customer="{{CUSTOMER_ID}}" \
-d payment_method="{{PAYMENT_METHOD_ID}}" \
-d return_url="https://example.com/order/123/complete" \
-d off_session=true \
-d confirm=true
決済手段 | シナリオ | テスト方法 |
---|
クレジットカード | カードの設定は成功し、認証は必要ありません。 | クレジットカード番号 4242 4242 4242 4242 と、任意の有効期限、セキュリティーコード、郵便番号を使用してクレジットカードフォームに入力します。 |
クレジットカード | このカードは初期設定時に認証が必要であり、それ以降は支払いに成功します。 | クレジットカード番号 4000 0025 0000 3155 と、任意の有効期限、セキュリティーコード、郵便番号を使用してクレジットカードフォームに入力します。 |
クレジットカード | このカードは、初期設定時も、以降の支払いでも認証が必要です。 | クレジットカード番号 4000 0027 6000 3184 と、任意の有効期限、セキュリティーコード、郵便番号を使用してクレジットカードフォームに入力します。 |
クレジットカード | 設定中にカードは拒否されます。 | クレジットカード番号 4000 0000 0000 9995 と、任意の有効期限、セキュリティーコード、郵便番号を使用してクレジットカードフォームに入力します。 |