首先,你可以在github上查看stripe compose示例stripe-android (ComposeExampleActivity.kt).
添加条带依赖
implementation "com.stripe:stripe-android:20.17.0"
初始化条带PaymentConfiguration
在应用程序类中
@HiltAndroidApp
class BookstoreApplication : Application() {
override fun onCreate() {
super.onCreate()
PaymentConfiguration.init(applicationContext, BuildConfig.STRIPE_PUBLISHABLE_KEY)
}
}
Stripe 提供了多种在应用程序中实现支付的方式。让我们考虑使用付款确认PaymentSheetContract
and PaymentLauncher
.
示例#1:使用确认付款PaymentSheetContract
In this case, we should use
rememberLauncherForActivityResult()
with
PaymentSheetContract()
to launch stripe payment form.
PaymentScreen.kt (Compose)
@Composable
fun PaymentScreen(
viewModel: PaymentViewModel = hiltViewModel()
) {
val stripeLauncher = rememberLauncherForActivityResult(
contract = PaymentSheetContract(),
onResult = {
viewModel.handlePaymentResult(it)
}
)
val clientSecret by viewModel.clientSecret.collectAsStateWithLifecycle()
clientSecret?.let {
val args = PaymentSheetContract.Args.createPaymentIntentArgs(it)
stripeLauncher.launch(args)
viewModel.onPaymentLaunched()
}
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center
) {
Button(
onClick = {
viewModel.makePayment()
}
) {
Text(text = "Confirm payment")
}
}
}
PaymentViewModel.kt
@HiltViewModel
class PaymentViewModel @Inject constructor(
private val repository: PaymentRepository
) : ViewModel() {
private val _clientSecret = MutableStateFlow<String?>(null)
val clientSecret = _clientSecret.asStateFlow()
fun makePayment() {
val paymentIntent = repository.createPaymentIntent()
_clientSecret.update { paymentIntent.clientSecret }
}
fun onPaymentLaunched() {
_clientSecret.update { null }
}
fun handlePaymentResult(result: PaymentSheetResult) {
when(result) {
PaymentSheetResult.Canceled -> TODO()
PaymentSheetResult.Completed -> TODO()
is PaymentSheetResult.Failed -> TODO()
}
}
}
示例#2:使用确认付款PaymentLauncher
In this case, we should use
rememberLauncherForActivityResult()
with
PaymentSheetContract()
to launch stripe payment form.
PaymentScreen.kt (Compose)
@Composable
fun PaymentScreen(
viewModel: PaymentViewModel = hiltViewModel()
) {
val paymentLauncher = rememberPaymentLauncher(viewModel::handlePaymentResult)
val confirmPaymentParams by viewModel.confirmPaymentParams.collectAsStateWithLifecycle()
confirmPaymentParams?.let { payment ->
paymentLauncher.confirm(payment)
viewModel.onPaymentLaunched()
}
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center
) {
Button(
onClick = {
viewModel.makePayment()
}
) {
Text(text = "Confirm payment")
}
}
}
@Composable
fun rememberPaymentLauncher(
callback: PaymentLauncher.PaymentResultCallback
): PaymentLauncher {
val config = PaymentConfiguration.getInstance(LocalContext.current)
return PaymentLauncher.rememberLauncher(
publishableKey = config.publishableKey,
stripeAccountId = config.stripeAccountId,
callback = callback
)
}
PaymentViewModel.kt
@HiltViewModel
class PaymentViewModel @Inject constructor(
private val repository: PaymentRepository
) : ViewModel() {
private val _confirmPaymentParams = MutableStateFlow<ConfirmPaymentIntentParams?>(null)
val confirmPaymentParams = _confirmPaymentParams.asStateFlow()
fun makePayment() {
val paymentIntent = repository.createPaymentIntent()
// For example, pay with hardcoded test card
val configuration = ConfirmPaymentIntentParams.createWithPaymentMethodCreateParams(
paymentMethodCreateParams = PaymentMethodCreateParams.create(
card = PaymentMethodCreateParams.Card(
number = "4242424242424242",
expiryMonth = 1,
expiryYear = 24,
cvc = "111"
)
),
clientSecret = paymentIntent.clientSecret
)
_confirmPaymentParams.update { configuration }
}
fun onPaymentLaunched() {
_confirmPaymentParams.update { null }
}
fun handlePaymentResult(result: PaymentResult) {
when(result) {
PaymentResult.Canceled -> TODO()
PaymentResult.Completed -> TODO()
is PaymentResult.Failed -> TODO()
}
}
}
数据层
The functions described below should be implemented somewhere on the server side. So, the client should only request some data from
payment intent (
client_secret
for example).
请阅读条纹接受付款文档以更好地理解。
您还可以观看 YouTube 视频:如何在 Android Studio 2022 中集成 Stripe.
PaymentRepository.kt
class PaymentRepository @Inject constructor(
private val stripeApiService: StripeApiService,
private val paymentDao: PaymentDao
) {
/*
Create customer before payment (attach to app user)
*/
suspend fun createCustomer() = withContext(Dispatchers.IO) {
val customer = stripeApiService.createCustomer()
// save customer in the database or preferences
// customerId required to confirm payment
paymentDao.insertCustomer(customer)
}
suspend fun refreshCustomerEphemeralKey() = withContext(Dispatchers.IO) {
val customer = paymentDao.getCustomer()
val key = stripeApiService.createEphemeralKey(customer.customerId)
paymentDao.insertEphemeralKey(key)
}
suspend fun createPaymentIntent() = withContext(Dispatchers.IO) {
val customer = paymentDao.getCustomer()
refreshCustomerEphemeralKey()
val paymentIntent = stripeApiService.createPaymentIntent(
customerId = customer.customerId,
amount = 1000,
currency = "usd", // or your currency
autoPaymentMethodsEnable = true
)
return@withContext paymentIntent
}
}
StripeApiService.kt
private const val SECRET = BuildConfig.STRIPE_SECRET_KEY
interface StripeApiService {
@Headers(
"Authorization: Bearer $SECRET",
"Stripe-Version: 2022-08-01"
)
@POST("v1/customers")
suspend fun createCustomer() : CustomerApiModel
@Headers(
"Authorization: Bearer $SECRET",
"Stripe-Version: 2022-08-01"
)
@POST("v1/ephemeral_keys")
suspend fun createEphemeralKey(
@Query("customer") customerId: String
): EphemeralKeyApiModel
@Headers(
"Authorization: Bearer $SECRET"
)
@POST("v1/payment_intents")
suspend fun createPaymentIntent(
@Query("customer") customerId: String,
@Query("amount") amount: Int,
@Query("currency") currency: String,
@Query("automatic_payment_methods[enabled]") autoPaymentMethodsEnable: Boolean,
): PaymentIntentApiModel
}