admin管理员组文章数量:1026989
I have the following problem, processing payment with 3ds card. My app uses Jetpack compose I have a payment screen. So I create a payment intent with new or saved card. Then I check if I need 3ds and start 3ds processing the following way:
@Composable
fun ThreeDSScreen(
publishableKey: String,
secret: String,
onSuccess: () -> Unit,
onCancel: () -> Unit,
onFail: () -> Unit
) {
val paymentLauncher = rememberPaymentLauncher(
publishableKey = publishableKey,
stripeAccountId = null,
callback = PaymentResultCallback(
onSuccess = onSuccess,
onCancel = onCancel,
onFail = onFail
)
)
val needLaunch = remember { mutableStateOf(true) }
LaunchedEffect(secret) {
if (needLaunch.value) {
needLaunch.value = false
delay(200)
paymentLauncher.confirm(
ConfirmPaymentIntentParams.create(
clientSecret = secret,
paymentMethodType = PaymentMethod.Type.CardPresent
)
)
}
}
}
class PaymentResultCallback(
private val onSuccess: () -> Unit,
private val onCancel: () -> Unit,
private val onFail: () -> Unit
) : PaymentLauncher.PaymentResultCallback {
override fun onPaymentResult(paymentResult: PaymentResult) {
when (paymentResult) {
is PaymentResult.Completed -> { onSuccess() }
is PaymentResult.Canceled -> { onCancel() }
is PaymentResult.Failed -> { onFail() }
}
}
}
I also save client secret in encrypted shared prefs. And it works fine whether a user fails it or cancel or confirm it. But let's imagine I stopped app. And I want in my app on start to check if pending intent exists. So I check it. And if I see a pending intent I try to confirm it the same way. Passing client secret to this composable. I use Stripe test VISA card with 3ds in order to check. So I start this function and see the Stripe 3ds test screen is starting and just after that Stripe behaves as if a user pressed fail. What am I doing wrong? I checked that my secret key is ok.
UPD: After running Stripe confirm I get Fail. So I'm trying to cancel pending payment intent. If I didn't succeed, I try to confirm again and from the second time it runs successfully. It seems that there's some problem with running this confirmation.
I have the following problem, processing payment with 3ds card. My app uses Jetpack compose I have a payment screen. So I create a payment intent with new or saved card. Then I check if I need 3ds and start 3ds processing the following way:
@Composable
fun ThreeDSScreen(
publishableKey: String,
secret: String,
onSuccess: () -> Unit,
onCancel: () -> Unit,
onFail: () -> Unit
) {
val paymentLauncher = rememberPaymentLauncher(
publishableKey = publishableKey,
stripeAccountId = null,
callback = PaymentResultCallback(
onSuccess = onSuccess,
onCancel = onCancel,
onFail = onFail
)
)
val needLaunch = remember { mutableStateOf(true) }
LaunchedEffect(secret) {
if (needLaunch.value) {
needLaunch.value = false
delay(200)
paymentLauncher.confirm(
ConfirmPaymentIntentParams.create(
clientSecret = secret,
paymentMethodType = PaymentMethod.Type.CardPresent
)
)
}
}
}
class PaymentResultCallback(
private val onSuccess: () -> Unit,
private val onCancel: () -> Unit,
private val onFail: () -> Unit
) : PaymentLauncher.PaymentResultCallback {
override fun onPaymentResult(paymentResult: PaymentResult) {
when (paymentResult) {
is PaymentResult.Completed -> { onSuccess() }
is PaymentResult.Canceled -> { onCancel() }
is PaymentResult.Failed -> { onFail() }
}
}
}
I also save client secret in encrypted shared prefs. And it works fine whether a user fails it or cancel or confirm it. But let's imagine I stopped app. And I want in my app on start to check if pending intent exists. So I check it. And if I see a pending intent I try to confirm it the same way. Passing client secret to this composable. I use Stripe test VISA card with 3ds in order to check. So I start this function and see the Stripe 3ds test screen is starting and just after that Stripe behaves as if a user pressed fail. What am I doing wrong? I checked that my secret key is ok.
UPD: After running Stripe confirm I get Fail. So I'm trying to cancel pending payment intent. If I didn't succeed, I try to confirm again and from the second time it runs successfully. It seems that there's some problem with running this confirmation.
Share Improve this question edited Nov 18, 2024 at 23:04 Al Sh asked Nov 18, 2024 at 15:42 Al ShAl Sh 511 silver badge4 bronze badges2 Answers
Reset to default 0It sounds like you're running into an issue where the 3D Secure (3DS) flow is prematurely failing when you try to confirm the payment intent after the app is restarted, even though the clientSecret and setup seem correct. The issue could be related to how the payment confirmation process is triggered after the app restarts, as well as how the payment state is handled in your app during the reinitialization.
Here's the code : first pic of the code : [1]: https://i.sstatic/nzkDItPN.png
It appears you are mistakenly indicating CardPresent
(which is for use with Stripe Terminal and reading cards in person), instead of Card
for online cards.
I would recommend you revise this line and retest everything:
- paymentMethodType = PaymentMethod.Type.CardPresent
+ paymentMethodType = PaymentMethod.Type.Card
I have the following problem, processing payment with 3ds card. My app uses Jetpack compose I have a payment screen. So I create a payment intent with new or saved card. Then I check if I need 3ds and start 3ds processing the following way:
@Composable
fun ThreeDSScreen(
publishableKey: String,
secret: String,
onSuccess: () -> Unit,
onCancel: () -> Unit,
onFail: () -> Unit
) {
val paymentLauncher = rememberPaymentLauncher(
publishableKey = publishableKey,
stripeAccountId = null,
callback = PaymentResultCallback(
onSuccess = onSuccess,
onCancel = onCancel,
onFail = onFail
)
)
val needLaunch = remember { mutableStateOf(true) }
LaunchedEffect(secret) {
if (needLaunch.value) {
needLaunch.value = false
delay(200)
paymentLauncher.confirm(
ConfirmPaymentIntentParams.create(
clientSecret = secret,
paymentMethodType = PaymentMethod.Type.CardPresent
)
)
}
}
}
class PaymentResultCallback(
private val onSuccess: () -> Unit,
private val onCancel: () -> Unit,
private val onFail: () -> Unit
) : PaymentLauncher.PaymentResultCallback {
override fun onPaymentResult(paymentResult: PaymentResult) {
when (paymentResult) {
is PaymentResult.Completed -> { onSuccess() }
is PaymentResult.Canceled -> { onCancel() }
is PaymentResult.Failed -> { onFail() }
}
}
}
I also save client secret in encrypted shared prefs. And it works fine whether a user fails it or cancel or confirm it. But let's imagine I stopped app. And I want in my app on start to check if pending intent exists. So I check it. And if I see a pending intent I try to confirm it the same way. Passing client secret to this composable. I use Stripe test VISA card with 3ds in order to check. So I start this function and see the Stripe 3ds test screen is starting and just after that Stripe behaves as if a user pressed fail. What am I doing wrong? I checked that my secret key is ok.
UPD: After running Stripe confirm I get Fail. So I'm trying to cancel pending payment intent. If I didn't succeed, I try to confirm again and from the second time it runs successfully. It seems that there's some problem with running this confirmation.
I have the following problem, processing payment with 3ds card. My app uses Jetpack compose I have a payment screen. So I create a payment intent with new or saved card. Then I check if I need 3ds and start 3ds processing the following way:
@Composable
fun ThreeDSScreen(
publishableKey: String,
secret: String,
onSuccess: () -> Unit,
onCancel: () -> Unit,
onFail: () -> Unit
) {
val paymentLauncher = rememberPaymentLauncher(
publishableKey = publishableKey,
stripeAccountId = null,
callback = PaymentResultCallback(
onSuccess = onSuccess,
onCancel = onCancel,
onFail = onFail
)
)
val needLaunch = remember { mutableStateOf(true) }
LaunchedEffect(secret) {
if (needLaunch.value) {
needLaunch.value = false
delay(200)
paymentLauncher.confirm(
ConfirmPaymentIntentParams.create(
clientSecret = secret,
paymentMethodType = PaymentMethod.Type.CardPresent
)
)
}
}
}
class PaymentResultCallback(
private val onSuccess: () -> Unit,
private val onCancel: () -> Unit,
private val onFail: () -> Unit
) : PaymentLauncher.PaymentResultCallback {
override fun onPaymentResult(paymentResult: PaymentResult) {
when (paymentResult) {
is PaymentResult.Completed -> { onSuccess() }
is PaymentResult.Canceled -> { onCancel() }
is PaymentResult.Failed -> { onFail() }
}
}
}
I also save client secret in encrypted shared prefs. And it works fine whether a user fails it or cancel or confirm it. But let's imagine I stopped app. And I want in my app on start to check if pending intent exists. So I check it. And if I see a pending intent I try to confirm it the same way. Passing client secret to this composable. I use Stripe test VISA card with 3ds in order to check. So I start this function and see the Stripe 3ds test screen is starting and just after that Stripe behaves as if a user pressed fail. What am I doing wrong? I checked that my secret key is ok.
UPD: After running Stripe confirm I get Fail. So I'm trying to cancel pending payment intent. If I didn't succeed, I try to confirm again and from the second time it runs successfully. It seems that there's some problem with running this confirmation.
Share Improve this question edited Nov 18, 2024 at 23:04 Al Sh asked Nov 18, 2024 at 15:42 Al ShAl Sh 511 silver badge4 bronze badges2 Answers
Reset to default 0It sounds like you're running into an issue where the 3D Secure (3DS) flow is prematurely failing when you try to confirm the payment intent after the app is restarted, even though the clientSecret and setup seem correct. The issue could be related to how the payment confirmation process is triggered after the app restarts, as well as how the payment state is handled in your app during the reinitialization.
Here's the code : first pic of the code : [1]: https://i.sstatic/nzkDItPN.png
It appears you are mistakenly indicating CardPresent
(which is for use with Stripe Terminal and reading cards in person), instead of Card
for online cards.
I would recommend you revise this line and retest everything:
- paymentMethodType = PaymentMethod.Type.CardPresent
+ paymentMethodType = PaymentMethod.Type.Card
本文标签: kotlinStripe processing 3ds payment on AndroidStack Overflow
版权声明:本文标题:kotlin - Stripe processing 3ds payment on Android - Stack Overflow 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://it.en369.cn/questions/1745610697a2158985.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论