Anyone know of a KMM wrapper lib around the Stripe...
# multiplatform
c
Anyone know of a KMM wrapper lib around the Stripe API's? Trying to avoid writing my own lol
👀 2
c
Did not know about klibs thats cool
m
what you end up doing @chrisjenx ?
I’m not sure about that open source Stripe sdk. Particularly since it doesn’t seem to have the Stripe UI baked in.
I’m thinking of building a wrapper around the two native SDK’s myself too!
c
Yeah basically did that, for WasmJs, iOS and Android
For the WasmJs you need to make sure the js lib gets attached to the root dom, not the compose one, as stripe stupidly doesn't support shadow doms (not like basically every spa uses those.. but hey)
THen you can use LocalViewController and LocalContext for the iOS and Android libraries respectively. Using Franks SPM is hugely helpful
👍 1
m
Do you mean François?
c
yes
m
Ah not so concerned with WasmJs. I’m surprised someone hasn’t already put together a module which imports both platform dependency - with ios using spm4kmp
Anyway only need something relatively simple for my use case to begin with. So will have a go next week
c
Yeah, I only use the PaymentLauncher, which unless you're doing something odd handles pretty much adding payment methods and paying
🙌 1
m
Great!
Hey! Struggled a bit here, I thought I may be able to instantiate the Android sourceset
PaymentSheet
from within my definition, but the initialiser requires Activity For now I’ve ended up creating a
StripeCheckout
composable which owns the paymentSheet and is responsible for presenting: https://github.com/markst/stripe-kmp/blob/main/shared/src/androidMain/kotlin/com/fouroneone/stripe/StripePayments.android.kt
I thought I was going to be able to build the
PaymentSheet
simply like this:
Copy code
private class AndroidStripePayments(private val context: Context) : StripePayments {

    var paymentSheet: PaymentSheet?

    @Composable
    override fun Initialize(publishableKey: String) {
        PaymentConfiguration.init(context = context, publishableKey = publishableKey)
        paymentSheet = PaymentSheet.Builder { result -> onResult(result.toCommonResult()) }.build()
    }

    @Composable
    override fun presentWithPaymentIntent(
        clientSecret: String,
        onResult: (PaymentSheetResult) -> Unit
    ) {
        paymentSheet.presentWithPaymentIntent(
            paymentIntentClientSecret = clientSecret,
            configuration = null
        )
    }
}
Think I’ve settled on the fact I have to use
Composable
for my PaymentSheet.
Copy code
@Composable
actual fun rememberPaymentSheet(
    stripePayments: StripePayments,
    onResult: (PaymentSheetResult) -> Unit
): PaymentSheetWrapper {
    val paymentSheet = remember(onResult) {
        PaymentSheet.Builder(resultCallback = { result: StripePaymentSheetResult ->
            onResult(result.toCommonResult())
        })
    }.build()

    return remember(paymentSheet) {
        AndroidPaymentSheetWrapper(paymentSheet)
    }
}
But am curious how you went about this @chrisjenx
c
I'm traveling right now ping me next week and I'll copy paste my implementations
👍 1
thank you color 1
m
Ping
Would be hugely grateful @chrisjenx
c
Ahh yes
Lemme get Junie to create a .md for you
❤️ 1
Haven't forgotten, was finishing another task
m
no stress at all!
it’s the middle of the night for you
c
I noticed I forgot to finish payment Intent for wasm so glad I check this!
👀 1
Lemme know if there's anything else you want to elaborate on
m
Awesome! Thanks so much for taking the time to do that
Interesting so you’re passing the the activity to
AndroidPaymentsLauncher()
I had trouble with that:
Copy code
IllegalStateException: LifecycleOwners must call register before they are STARTED
c
Copy code
override fun onCreate(savedInstanceState: Bundle?) {
        enableEdgeToEdge(statusBarStyle = SystemBarStyle.light(Color.TRANSPARENT, Color.BLACK))
        super.onCreate(savedInstanceState)
        // Always create the root component outside Compose on the main thread
        val defaultComponentContext = defaultComponentContext()
        val root = DefaultAppComponent(
            componentContext = defaultComponentContext,
            navigationHandler = AndroidNavigationHandler(this),
            paymentsLauncher = AndroidPaymentsLauncher(this),
        )
👍 1
I think I remember that being an issue, I was using
LocalContext
and used to init from the
@Composable
, but paymentsheet needed to be registered in onCreate because the activity result they use needs to be able to listen to ActivityResults from there started activity. Just annoying API design on Stripe side (Also would be nice if google result handler would just send you the result after registering so you can register post onCreate)
👀 1
FYI Stripe SPM is buggy and somtimes misses assets (probably an SPM bug, but Stripe refuses to fix it), I had to resort to Stripe being imported manually, created a gist incase you need to do the same: https://gist.github.com/chrisjenx/79fe87fc45a3821afe2715832e3770be
👀 1
👍 1
m
Yeah had noticed. Strange one that it only seems to occur sometimes, I assumed it was because I was using spm4kmp
c
Nope, I used SPM directly in Xcode, same issue. As far as I can tell it's cause SPM is non-derministic so it runs in different orders every time it imports and seems Stripes modules might overwrite each other, very strange. There's a bunch of tickets on their iOS repo they close without a fix. Guess Pod's is still better at some stuff...
m
right. thanks for letting me know!
105 Views