Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PaymentSheet support for Jetpack Compose #3892

Merged
merged 11 commits into from
Jun 30, 2021
25 changes: 25 additions & 0 deletions payments-core/api/payments-core.api
Original file line number Diff line number Diff line change
Expand Up @@ -4588,6 +4588,31 @@ public final class com/stripe/android/paymentsheet/PaymentSheet$GooglePayConfigu
public static fun values ()[Lcom/stripe/android/paymentsheet/PaymentSheet$GooglePayConfiguration$Environment;
}

public final class com/stripe/android/paymentsheet/PaymentSheetContract : androidx/activity/result/contract/ActivityResultContract {
public fun <init> ()V
public fun createIntent (Landroid/content/Context;Lcom/stripe/android/paymentsheet/PaymentSheetContract$Args;)Landroid/content/Intent;
public synthetic fun createIntent (Landroid/content/Context;Ljava/lang/Object;)Landroid/content/Intent;
public fun parseResult (ILandroid/content/Intent;)Lcom/stripe/android/paymentsheet/PaymentSheetResult;
public synthetic fun parseResult (ILandroid/content/Intent;)Ljava/lang/Object;
}

public final class com/stripe/android/paymentsheet/PaymentSheetContract$Args : com/stripe/android/view/ActivityStarter$Args {
public static final field CREATOR Landroid/os/Parcelable$Creator;
public static final field Companion Lcom/stripe/android/paymentsheet/PaymentSheetContract$Args$Companion;
public fun describeContents ()I
public final fun getGooglePayConfig ()Lcom/stripe/android/paymentsheet/PaymentSheet$GooglePayConfiguration;
public final fun getStatusBarColor ()Ljava/lang/Integer;
public final fun isGooglePayEnabled ()Z
public fun writeToParcel (Landroid/os/Parcel;I)V
}

public final class com/stripe/android/paymentsheet/PaymentSheetContract$Args$Companion {
public final fun createPaymentIntentArgs (Ljava/lang/String;Lcom/stripe/android/paymentsheet/PaymentSheet$Configuration;Ljava/lang/Integer;)Lcom/stripe/android/paymentsheet/PaymentSheetContract$Args;
public static synthetic fun createPaymentIntentArgs$default (Lcom/stripe/android/paymentsheet/PaymentSheetContract$Args$Companion;Ljava/lang/String;Lcom/stripe/android/paymentsheet/PaymentSheet$Configuration;Ljava/lang/Integer;ILjava/lang/Object;)Lcom/stripe/android/paymentsheet/PaymentSheetContract$Args;
public final fun createSetupIntentArgs (Ljava/lang/String;Lcom/stripe/android/paymentsheet/PaymentSheet$Configuration;Ljava/lang/Integer;)Lcom/stripe/android/paymentsheet/PaymentSheetContract$Args;
public static synthetic fun createSetupIntentArgs$default (Lcom/stripe/android/paymentsheet/PaymentSheetContract$Args$Companion;Ljava/lang/String;Lcom/stripe/android/paymentsheet/PaymentSheet$Configuration;Ljava/lang/Integer;ILjava/lang/Object;)Lcom/stripe/android/paymentsheet/PaymentSheetContract$Args;
}

public abstract class com/stripe/android/paymentsheet/PaymentSheetResult : android/os/Parcelable {
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ import androidx.activity.ComponentActivity
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.ActivityResultRegistry
import androidx.fragment.app.Fragment
import com.stripe.android.paymentsheet.model.PaymentIntentClientSecret
import com.stripe.android.paymentsheet.model.SetupIntentClientSecret
import org.jetbrains.annotations.TestOnly

/**
* This is used internally for integrations that don't use Jetpack Compose and are
* able to pass in an activity.
*/
internal class DefaultPaymentSheetLauncher(
private val activityResultLauncher: ActivityResultLauncher<PaymentSheetContract.Args>,
private val statusBarColor: () -> Int?
Expand Down Expand Up @@ -66,21 +68,21 @@ internal class DefaultPaymentSheetLauncher(
paymentIntentClientSecret: String,
configuration: PaymentSheet.Configuration?
) = present(
PaymentSheetContract.Args(
PaymentIntentClientSecret(paymentIntentClientSecret),
PaymentSheetContract.Args.createPaymentIntentArgs(
paymentIntentClientSecret,
configuration,
statusBarColor(),
configuration
)
)

override fun presentWithSetupIntent(
setupIntentClientSecret: String,
configuration: PaymentSheet.Configuration?
) = present(
PaymentSheetContract.Args(
SetupIntentClientSecret(setupIntentClientSecret),
PaymentSheetContract.Args.createSetupIntentArgs(
setupIntentClientSecret,
configuration,
statusBarColor(),
configuration
)
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ import android.content.Intent
import android.os.Bundle
import androidx.activity.result.contract.ActivityResultContract
import androidx.annotation.ColorInt
import androidx.annotation.VisibleForTesting
import androidx.core.os.bundleOf
import com.stripe.android.paymentsheet.model.ClientSecret
import com.stripe.android.paymentsheet.model.PaymentIntentClientSecret
import com.stripe.android.view.ActivityStarter
import kotlinx.parcelize.Parcelize

internal class PaymentSheetContract :
class PaymentSheetContract :
ActivityResultContract<PaymentSheetContract.Args, PaymentSheetResult>() {
override fun createIntent(
context: Context,
Expand All @@ -32,19 +33,39 @@ internal class PaymentSheetContract :
}

@Parcelize
internal data class Args(
val clientSecret: ClientSecret,
@ColorInt val statusBarColor: Int?,
val config: PaymentSheet.Configuration?
class Args @VisibleForTesting internal constructor(
michelleb-stripe marked this conversation as resolved.
Show resolved Hide resolved
internal val clientSecret: ClientSecret,
internal val config: PaymentSheet.Configuration?,
@ColorInt val statusBarColor: Int? = null,
) : ActivityStarter.Args {
val googlePayConfig: PaymentSheet.GooglePayConfiguration? get() = config?.googlePay
val isGooglePayEnabled: Boolean
get() = googlePayConfig != null && clientSecret is PaymentIntentClientSecret

internal companion object {
companion object {
internal fun fromIntent(intent: Intent): Args? {
return intent.getParcelableExtra(EXTRA_ARGS)
}

fun createPaymentIntentArgs(
clientSecret: String,
config: PaymentSheet.Configuration?,
michelleb-stripe marked this conversation as resolved.
Show resolved Hide resolved
statusBarColor: Int? = null,
michelleb-stripe marked this conversation as resolved.
Show resolved Hide resolved
) = Args(
PaymentIntentClientSecret(clientSecret),
config,
statusBarColor
)

fun createSetupIntentArgs(
clientSecret: String,
config: PaymentSheet.Configuration?,
michelleb-stripe marked this conversation as resolved.
Show resolved Hide resolved
statusBarColor: Int? = null,
michelleb-stripe marked this conversation as resolved.
Show resolved Hide resolved
) = Args(
PaymentIntentClientSecret(clientSecret),
config,
statusBarColor
)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ internal class PaymentSheetActivityTest {
context,
PaymentSheetContract.Args(
PaymentIntentClientSecret("client_secret"),
PaymentSheetFixtures.CONFIG_CUSTOMER,
statusBarColor = PaymentSheetFixtures.STATUS_BAR_COLOR,
PaymentSheetFixtures.CONFIG_CUSTOMER
)
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,25 +37,25 @@ internal object PaymentSheetFixtures {

internal val ARGS_CUSTOMER_WITH_GOOGLEPAY_SETUP = PaymentSheetContract.Args(
SetupIntentClientSecret(CLIENT_SECRET),
CONFIG_CUSTOMER_WITH_GOOGLEPAY,
STATUS_BAR_COLOR,
CONFIG_CUSTOMER_WITH_GOOGLEPAY
)

internal val ARGS_CUSTOMER_WITH_GOOGLEPAY = PaymentSheetContract.Args(
PAYMENT_INTENT_CLIENT_SECRET,
CONFIG_CUSTOMER_WITH_GOOGLEPAY,
STATUS_BAR_COLOR,
CONFIG_CUSTOMER_WITH_GOOGLEPAY
)

internal val ARGS_CUSTOMER_WITHOUT_GOOGLEPAY = PaymentSheetContract.Args(
PAYMENT_INTENT_CLIENT_SECRET,
CONFIG_CUSTOMER,
STATUS_BAR_COLOR,
CONFIG_CUSTOMER
)

internal val ARGS_WITHOUT_CUSTOMER = PaymentSheetContract.Args(
PAYMENT_INTENT_CLIENT_SECRET,
config = null,
STATUS_BAR_COLOR,
config = null
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import com.stripe.android.model.PaymentIntentFixtures
import com.stripe.android.model.PaymentMethod
import com.stripe.android.model.PaymentMethodCreateParamsFixtures
import com.stripe.android.model.PaymentMethodFixtures
import com.stripe.android.model.SetupIntentFixtures
import com.stripe.android.model.StripeIntent
import com.stripe.android.networking.AbsFakeStripeRepository
import com.stripe.android.networking.ApiRequest
Expand Down Expand Up @@ -689,7 +688,6 @@ internal class PaymentSheetViewModelTest {

private val PAYMENT_METHODS = listOf(PaymentMethodFixtures.CARD_PAYMENT_METHOD)

val SETUP_INTENT = SetupIntentFixtures.SI_REQUIRES_PAYMENT_METHOD
val PAYMENT_INTENT = PaymentIntentFixtures.PI_REQUIRES_PAYMENT_METHOD
val PAYMENT_INTENT_RESULT = PaymentIntentResult(
intent = PAYMENT_INTENT,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package com.stripe.android.paymentsheet.example.activity

import android.os.Bundle
import android.widget.Toast
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.compose.setContent
import androidx.compose.material.MaterialTheme
import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.ui.platform.LocalContext
import com.stripe.android.paymentsheet.PaymentSheet
import com.stripe.android.paymentsheet.PaymentSheetContract

internal class LaunchPaymentSheetCompleteActivityExposePaymentSheetArgs :
michelleb-stripe marked this conversation as resolved.
Show resolved Hide resolved
BasePaymentSheetActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

setContent {
MaterialTheme {
val stripeLauncher =
rememberLauncherForActivityResult(contract = PaymentSheetContract())
{
onPaymentSheetResult(it)
}

val inProgress by viewModel.inProgress.observeAsState(false)
val status by viewModel.status.observeAsState("")

if (status.isNotBlank()) {
Toast.makeText(LocalContext.current, status, Toast.LENGTH_SHORT).show()
michelleb-stripe marked this conversation as resolved.
Show resolved Hide resolved
viewModel.statusDisplayed()
}

Receipt(inProgress) {
BuyButton(
buyButtonEnabled = !inProgress,
onClick = {
prepareCheckout { customerConfig, clientSecret ->
stripeLauncher.launch(
PaymentSheetContract.Args.createPaymentIntentArgs(
clientSecret,
PaymentSheet.Configuration(
merchantDisplayName = merchantName,
customer = customerConfig,
googlePay = googlePayConfig,
)
)
)
}
}
)
}
}
}
}
}