stripe / stripe-android

Stripe Android SDK
https://stripe.com/docs/mobile/android
MIT License
1.28k stars 644 forks source link

[Question] [Information] PaymentResult is not giving payment details like iOS #6199

Closed aadityapaliwal94 closed 1 year ago

aadityapaliwal94 commented 1 year ago

Summary

I am using Stripe's paymentLauncher.confirm(confirmParams) method to confirm a payment. On the callback, I am getting PaymentResult but it doesn't have any extra data (Like id, secret key, status, etc...). iOS SDK is giving all the parameters. How can I get it?

Code to reproduce

class MyFragment : BaseFragment() {

lateinit var cardDetailsParam: CreditCardReplenishmentParam
private lateinit var paymentIntentClientSecret: String
private lateinit var paymentLauncher: PaymentLauncher
override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val paymentConfiguration = PaymentConfiguration.getInstance(requireContext())
        paymentLauncher = PaymentLauncher.Companion.create(
            this,
            paymentConfiguration.publishableKey,
            paymentConfiguration.stripeAccountId,
            ::onPaymentResult
        )
    }

private fun payWith3DSStripe() {

    val userCardDetails = PaymentMethodCreateParams.Card(
        number = cardDetailsParam.card,
        cvc = cardDetailsParam.code,
        expiryMonth = cardDetailsParam.expMonth.toInt(),
        expiryYear = cardDetailsParam.expYear.toInt()
    )

    val userAddress = PaymentMethod.BillingDetails(
        address = Address(
            postalCode = cardDetailsParam.zipCode
        )
    )

    val confirmParams = ConfirmPaymentIntentParams
        .createWithPaymentMethodCreateParams(PaymentMethodCreateParams.create(userCardDetails, userAddress), paymentIntentClientSecret)

    lifecycleScope.launch {
        paymentLauncher.confirm(confirmParams)
    }
}
private fun onPaymentResult(paymentResult: PaymentResult) {

        val message = when (paymentResult) {
            is PaymentResult.Completed -> {
                "Completed!"
            }
            is PaymentResult.Canceled -> {
                "Canceled!"
            }
            is PaymentResult.Failed -> {
                "Failed: " + paymentResult.throwable.message
            }
        }
    }

Android version

8.1.0

Impacted devices

Android devices

Installation method

gradle dependency

kotlin: stripe-android: 20.19.1 Android Gradle Plugin:'1.7.10' Gradle:'7.0.4'

SDK classes

PaymentResult

https://stripe.com/docs/payments/accept-a-payment?platform=android&ui=custom

jameswoo-stripe commented 1 year ago

Hi @aadityapaliwal94 can you please provide more detail about which parameters you want to see in the response? Could you also describe your use case? For example, why do you need the secret key in the response, when you have access to the secret key before you call confirm?

aadityapaliwal94 commented 1 year ago

Hi @jameswoo-stripe

Yes, we have the secret key but iOS has more parameters in its data. Like our, BE needs id (stripeID) also from the response. So, iOS is able to fetch it but Android doesn't have anything there. See below -

<StripePayments.STPPaymentIntent:; stripeId = pi_3M6pEzhTGoxPTJ; amount = 5; canceledAt = nil; captureMethod = Optional("automatic"); confirmationMethod = Optional("automatic"); countryCode = nil; created = 2023-02-10 04:21:15 +0000; currency = usd; description = nil; lastPaymentError = nil; linkSettings = nil; livemode = false; nextAction = nil; paymentMethodId = Optional("pm_1MEzhTGoxPTJ"); paymentMethod = Optional(<StripePayments.STPPaymentMethod:; stripeId = pm_16sEzhTGoxPTJgt; alipay = nil; auBECSDebit = nil; bacsDebit = nil; bancontact = nil; billingDetails = Optional(<StripePayments.STPPaymentMethodBillingDetails: 0x600001221bd0; name = ; phone = ; email = ; address = Optional(<StripePayments.STPPaymentMethodAddress: 0x600001f2c080; line1 = ; line2 = ; city = ; state = ; postalCode = ; country = >)>); card = Optional(<StripePayments.STPPaymentMethodCard: 0x6000003503f0; brand = Visa; checks = <StripePayments.STPPaymentMethodCardChecks:; addressLine1Check: ; addressPostalCodeCheck: ; cvcCheck: >; country = US; expMonth = 3; expYear = 2025; funding = credit; last4 = 4242; fingerprint = ; networks = <StripePayments.STPPaymentMethodCardNetworks: 0x600003efac40; available: ["visa"]; preferred: >; threeDSecureUsage = <StripePayments.STPPaymentMethodThreeDSecureUsage: 0x60000303d280; supported: YES>; wallet = >); cardPresent = nil; created = Optional(2023-02-10 04:21:18 +0000); customerId = ; ideal = nil; eps = nil; fpx = nil; giropay = nil; netBanking = nil; oxxo = nil; grabPay = nil; payPal = nil; przelewy24 = nil; sepaDebit = nil; sofort = nil; upi = nil; afterpay_clearpay = nil; blik = nil; weChatPay = nil; boleto = nil; link = nil; klarna = nil; affirm = nil; usBankAccount = nil; cashapp = nil; liveMode = NO; type = card>); paymentMethodOptions = nil; paymentMethodTypes = Optional(["card"]); receiptEmail = nil; setupFutureUsage = nil; shipping = nil; sourceId = nil; status = Optional("succeeded"); unactivatedPaymentMethodTypes = []>

jameswoo-stripe commented 1 year ago

Hi @aadityapaliwal94, you have a few ways you can get the stripeId.

  1. When you create a payment intent on the server and pass it to the mobile client, you should be able to pass the stripeId along with the client secret (see payment intent API) back to your mobile client. I think this is your safest option.

  2. Another way you can get the stripeId is from the client_secret it self. The payment intent client_secret is structured as follows, pi_abc_secret_123, the ID will be everything before the secret, so from the example, it will be pi_abc. I would not rely on this as always being true.

  3. Another way you can get the stripeId is by fetching the payment intent client side or server side. If you want to do it from the client side, you can call stripe (see Stripe.kt, retrievePaymentIntent). On the server side, you can create an endpoint to fetch the payment intent using the client secret, get the stripe id, and return the result back to your client. This requires an additional network call, so this is up to you.

I hope this helps!

aadityapaliwal94 commented 1 year ago

Thanks @jameswoo-stripe

it would definitely help.