diff --git a/CHANGELOG.md b/CHANGELOG.md
index f3891930189..5c0a53b9d12 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,12 @@
## XX.XX.XX - 2023-XX-XX
+### PaymentSheet
+* [ADDED][7337](https://github.com/stripe/stripe-android/pull/7337) PaymentSheet now supports Swish for PaymentIntents in private beta.
+
+### Payments
+* [ADDED][7337](https://github.com/stripe/stripe-android/pull/7337) Added support for Swish for PaymentIntents in private beta.
+
### Financial Connections
* [FIXED][7331](https://github.com/stripe/stripe-android/pull/7331) When cancelling out of a auth session, going back to the consent screen required two back taps.
diff --git a/example/AndroidManifest.xml b/example/AndroidManifest.xml
index 3a1937cccab..e5ae8f1b57c 100644
--- a/example/AndroidManifest.xml
+++ b/example/AndroidManifest.xml
@@ -79,6 +79,7 @@
+
diff --git a/example/res/values/strings.xml b/example/res/values/strings.xml
index e2aa681d861..fca41e7aad9 100644
--- a/example/res/values/strings.xml
+++ b/example/res/values/strings.xml
@@ -34,6 +34,7 @@
"Manual US Bank Account Example"
Cash App Pay
Revolut Pay
+ Swish
Card Brands
Card number
Possible Card Brands
diff --git a/example/src/main/java/com/stripe/example/activity/LauncherActivity.kt b/example/src/main/java/com/stripe/example/activity/LauncherActivity.kt
index 81f430f9822..756ead19d62 100644
--- a/example/src/main/java/com/stripe/example/activity/LauncherActivity.kt
+++ b/example/src/main/java/com/stripe/example/activity/LauncherActivity.kt
@@ -177,6 +177,10 @@ class LauncherActivity : AppCompatActivity() {
activity.getString(R.string.revolut_pay_example),
RevolutPayActivity::class.java
),
+ Item(
+ activity.getString(R.string.swish_example),
+ SwishExampleActivity::class.java
+ ),
// This is for internal use so as not to confuse the user.
Item(
"StripeImage Example",
diff --git a/example/src/main/java/com/stripe/example/activity/SwishExampleActivity.kt b/example/src/main/java/com/stripe/example/activity/SwishExampleActivity.kt
new file mode 100644
index 00000000000..4ab402f140e
--- /dev/null
+++ b/example/src/main/java/com/stripe/example/activity/SwishExampleActivity.kt
@@ -0,0 +1,91 @@
+package com.stripe.example.activity
+
+import android.os.Bundle
+import androidx.activity.compose.setContent
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.material.Button
+import androidx.compose.material.CircularProgressIndicator
+import androidx.compose.material.Divider
+import androidx.compose.material.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.livedata.observeAsState
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.unit.dp
+import com.google.accompanist.themeadapter.material.MdcTheme
+import com.stripe.android.model.PaymentMethodCreateParams
+
+class SwishExampleActivity : StripeIntentActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ setContent {
+ val isProcessing by viewModel.inProgress.observeAsState(initial = false)
+ val status by viewModel.status.observeAsState(initial = "")
+
+ SwishScreen(
+ isProcessing = isProcessing,
+ status = status,
+ onButtonPressed = { payWithSwish() },
+ )
+ }
+ }
+
+ private fun payWithSwish() {
+ val params = PaymentMethodCreateParams.createSwish()
+
+ createAndConfirmPaymentIntent(
+ country = "FR",
+ currency = "SEK",
+ paymentMethodCreateParams = params,
+ supportedPaymentMethods = "swish",
+ )
+ }
+}
+
+@Composable
+private fun SwishScreen(
+ isProcessing: Boolean,
+ status: String,
+ onButtonPressed: () -> Unit,
+) {
+ MdcTheme {
+ Column(modifier = Modifier.fillMaxSize()) {
+ Row(verticalAlignment = Alignment.CenterVertically) {
+ Button(
+ onClick = onButtonPressed,
+ enabled = !isProcessing,
+ modifier = Modifier.padding(16.dp),
+ ) {
+ Text("Pay with Swish")
+ }
+
+ if (isProcessing) {
+ CircularProgressIndicator(modifier = Modifier.size(24.dp))
+ }
+ }
+
+ if (status.isNotBlank()) {
+ Divider(
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(horizontal = 16.dp),
+ )
+
+ Text(
+ text = status,
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(16.dp),
+ )
+ }
+ }
+ }
+}
diff --git a/payments-core/api/payments-core.api b/payments-core/api/payments-core.api
index ac53190e0a4..fd90ba7e10c 100644
--- a/payments-core/api/payments-core.api
+++ b/payments-core/api/payments-core.api
@@ -3799,6 +3799,7 @@ public final class com/stripe/android/model/PaymentMethod$Type : java/lang/Enum,
public static final field RevolutPay Lcom/stripe/android/model/PaymentMethod$Type;
public static final field SepaDebit Lcom/stripe/android/model/PaymentMethod$Type;
public static final field Sofort Lcom/stripe/android/model/PaymentMethod$Type;
+ public static final field Swish Lcom/stripe/android/model/PaymentMethod$Type;
public static final field USBankAccount Lcom/stripe/android/model/PaymentMethod$Type;
public static final field Upi Lcom/stripe/android/model/PaymentMethod$Type;
public static final field WeChatPay Lcom/stripe/android/model/PaymentMethod$Type;
@@ -3968,12 +3969,13 @@ public final class com/stripe/android/model/PaymentMethodCreateParams : android/
public synthetic fun (Lcom/stripe/android/model/PaymentMethodCreateParams$Netbanking;Lcom/stripe/android/model/PaymentMethod$BillingDetails;Ljava/util/Map;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun (Lcom/stripe/android/model/PaymentMethodCreateParams$SepaDebit;Lcom/stripe/android/model/PaymentMethod$BillingDetails;Ljava/util/Map;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun (Lcom/stripe/android/model/PaymentMethodCreateParams$Sofort;Lcom/stripe/android/model/PaymentMethod$BillingDetails;Ljava/util/Map;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
+ public synthetic fun (Lcom/stripe/android/model/PaymentMethodCreateParams$Swish;Lcom/stripe/android/model/PaymentMethod$BillingDetails;Ljava/util/Map;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun (Lcom/stripe/android/model/PaymentMethodCreateParams$USBankAccount;Lcom/stripe/android/model/PaymentMethod$BillingDetails;Ljava/util/Map;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun (Lcom/stripe/android/model/PaymentMethodCreateParams$Upi;Lcom/stripe/android/model/PaymentMethod$BillingDetails;Ljava/util/Map;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
- public final fun component15 ()Lcom/stripe/android/model/PaymentMethod$BillingDetails;
+ public final fun component16 ()Lcom/stripe/android/model/PaymentMethod$BillingDetails;
public final fun component3 ()Lcom/stripe/android/model/PaymentMethodCreateParams$Card;
- public final fun copy (Ljava/lang/String;ZLcom/stripe/android/model/PaymentMethodCreateParams$Card;Lcom/stripe/android/model/PaymentMethodCreateParams$Ideal;Lcom/stripe/android/model/PaymentMethodCreateParams$Fpx;Lcom/stripe/android/model/PaymentMethodCreateParams$SepaDebit;Lcom/stripe/android/model/PaymentMethodCreateParams$AuBecsDebit;Lcom/stripe/android/model/PaymentMethodCreateParams$BacsDebit;Lcom/stripe/android/model/PaymentMethodCreateParams$Sofort;Lcom/stripe/android/model/PaymentMethodCreateParams$Upi;Lcom/stripe/android/model/PaymentMethodCreateParams$Netbanking;Lcom/stripe/android/model/PaymentMethodCreateParams$USBankAccount;Lcom/stripe/android/model/PaymentMethodCreateParams$Link;Lcom/stripe/android/model/PaymentMethodCreateParams$CashAppPay;Lcom/stripe/android/model/PaymentMethod$BillingDetails;Ljava/util/Map;Ljava/util/Set;Ljava/util/Map;)Lcom/stripe/android/model/PaymentMethodCreateParams;
- public static synthetic fun copy$default (Lcom/stripe/android/model/PaymentMethodCreateParams;Ljava/lang/String;ZLcom/stripe/android/model/PaymentMethodCreateParams$Card;Lcom/stripe/android/model/PaymentMethodCreateParams$Ideal;Lcom/stripe/android/model/PaymentMethodCreateParams$Fpx;Lcom/stripe/android/model/PaymentMethodCreateParams$SepaDebit;Lcom/stripe/android/model/PaymentMethodCreateParams$AuBecsDebit;Lcom/stripe/android/model/PaymentMethodCreateParams$BacsDebit;Lcom/stripe/android/model/PaymentMethodCreateParams$Sofort;Lcom/stripe/android/model/PaymentMethodCreateParams$Upi;Lcom/stripe/android/model/PaymentMethodCreateParams$Netbanking;Lcom/stripe/android/model/PaymentMethodCreateParams$USBankAccount;Lcom/stripe/android/model/PaymentMethodCreateParams$Link;Lcom/stripe/android/model/PaymentMethodCreateParams$CashAppPay;Lcom/stripe/android/model/PaymentMethod$BillingDetails;Ljava/util/Map;Ljava/util/Set;Ljava/util/Map;ILjava/lang/Object;)Lcom/stripe/android/model/PaymentMethodCreateParams;
+ public final fun copy (Ljava/lang/String;ZLcom/stripe/android/model/PaymentMethodCreateParams$Card;Lcom/stripe/android/model/PaymentMethodCreateParams$Ideal;Lcom/stripe/android/model/PaymentMethodCreateParams$Fpx;Lcom/stripe/android/model/PaymentMethodCreateParams$SepaDebit;Lcom/stripe/android/model/PaymentMethodCreateParams$AuBecsDebit;Lcom/stripe/android/model/PaymentMethodCreateParams$BacsDebit;Lcom/stripe/android/model/PaymentMethodCreateParams$Sofort;Lcom/stripe/android/model/PaymentMethodCreateParams$Upi;Lcom/stripe/android/model/PaymentMethodCreateParams$Netbanking;Lcom/stripe/android/model/PaymentMethodCreateParams$USBankAccount;Lcom/stripe/android/model/PaymentMethodCreateParams$Link;Lcom/stripe/android/model/PaymentMethodCreateParams$CashAppPay;Lcom/stripe/android/model/PaymentMethodCreateParams$Swish;Lcom/stripe/android/model/PaymentMethod$BillingDetails;Ljava/util/Map;Ljava/util/Set;Ljava/util/Map;)Lcom/stripe/android/model/PaymentMethodCreateParams;
+ public static synthetic fun copy$default (Lcom/stripe/android/model/PaymentMethodCreateParams;Ljava/lang/String;ZLcom/stripe/android/model/PaymentMethodCreateParams$Card;Lcom/stripe/android/model/PaymentMethodCreateParams$Ideal;Lcom/stripe/android/model/PaymentMethodCreateParams$Fpx;Lcom/stripe/android/model/PaymentMethodCreateParams$SepaDebit;Lcom/stripe/android/model/PaymentMethodCreateParams$AuBecsDebit;Lcom/stripe/android/model/PaymentMethodCreateParams$BacsDebit;Lcom/stripe/android/model/PaymentMethodCreateParams$Sofort;Lcom/stripe/android/model/PaymentMethodCreateParams$Upi;Lcom/stripe/android/model/PaymentMethodCreateParams$Netbanking;Lcom/stripe/android/model/PaymentMethodCreateParams$USBankAccount;Lcom/stripe/android/model/PaymentMethodCreateParams$Link;Lcom/stripe/android/model/PaymentMethodCreateParams$CashAppPay;Lcom/stripe/android/model/PaymentMethodCreateParams$Swish;Lcom/stripe/android/model/PaymentMethod$BillingDetails;Ljava/util/Map;Ljava/util/Set;Ljava/util/Map;ILjava/lang/Object;)Lcom/stripe/android/model/PaymentMethodCreateParams;
public static final fun create (Lcom/stripe/android/model/PaymentMethodCreateParams$AuBecsDebit;Lcom/stripe/android/model/PaymentMethod$BillingDetails;)Lcom/stripe/android/model/PaymentMethodCreateParams;
public static final fun create (Lcom/stripe/android/model/PaymentMethodCreateParams$AuBecsDebit;Lcom/stripe/android/model/PaymentMethod$BillingDetails;Ljava/util/Map;)Lcom/stripe/android/model/PaymentMethodCreateParams;
public static final fun create (Lcom/stripe/android/model/PaymentMethodCreateParams$BacsDebit;Lcom/stripe/android/model/PaymentMethod$BillingDetails;)Lcom/stripe/android/model/PaymentMethodCreateParams;
@@ -4038,6 +4040,9 @@ public final class com/stripe/android/model/PaymentMethodCreateParams : android/
public static final fun createRevolutPay ()Lcom/stripe/android/model/PaymentMethodCreateParams;
public static final fun createRevolutPay (Lcom/stripe/android/model/PaymentMethod$BillingDetails;)Lcom/stripe/android/model/PaymentMethodCreateParams;
public static final fun createRevolutPay (Lcom/stripe/android/model/PaymentMethod$BillingDetails;Ljava/util/Map;)Lcom/stripe/android/model/PaymentMethodCreateParams;
+ public static final fun createSwish ()Lcom/stripe/android/model/PaymentMethodCreateParams;
+ public static final fun createSwish (Lcom/stripe/android/model/PaymentMethod$BillingDetails;)Lcom/stripe/android/model/PaymentMethodCreateParams;
+ public static final fun createSwish (Lcom/stripe/android/model/PaymentMethod$BillingDetails;Ljava/util/Map;)Lcom/stripe/android/model/PaymentMethodCreateParams;
public static final fun createUSBankAccount ()Lcom/stripe/android/model/PaymentMethodCreateParams;
public static final fun createUSBankAccount (Lcom/stripe/android/model/PaymentMethod$BillingDetails;)Lcom/stripe/android/model/PaymentMethodCreateParams;
public static final fun createUSBankAccount (Lcom/stripe/android/model/PaymentMethod$BillingDetails;Ljava/util/Map;)Lcom/stripe/android/model/PaymentMethodCreateParams;
@@ -4254,6 +4259,10 @@ public final class com/stripe/android/model/PaymentMethodCreateParams$Companion
public final fun createRevolutPay (Lcom/stripe/android/model/PaymentMethod$BillingDetails;)Lcom/stripe/android/model/PaymentMethodCreateParams;
public final fun createRevolutPay (Lcom/stripe/android/model/PaymentMethod$BillingDetails;Ljava/util/Map;)Lcom/stripe/android/model/PaymentMethodCreateParams;
public static synthetic fun createRevolutPay$default (Lcom/stripe/android/model/PaymentMethodCreateParams$Companion;Lcom/stripe/android/model/PaymentMethod$BillingDetails;Ljava/util/Map;ILjava/lang/Object;)Lcom/stripe/android/model/PaymentMethodCreateParams;
+ public final fun createSwish ()Lcom/stripe/android/model/PaymentMethodCreateParams;
+ public final fun createSwish (Lcom/stripe/android/model/PaymentMethod$BillingDetails;)Lcom/stripe/android/model/PaymentMethodCreateParams;
+ public final fun createSwish (Lcom/stripe/android/model/PaymentMethod$BillingDetails;Ljava/util/Map;)Lcom/stripe/android/model/PaymentMethodCreateParams;
+ public static synthetic fun createSwish$default (Lcom/stripe/android/model/PaymentMethodCreateParams$Companion;Lcom/stripe/android/model/PaymentMethod$BillingDetails;Ljava/util/Map;ILjava/lang/Object;)Lcom/stripe/android/model/PaymentMethodCreateParams;
public final fun createUSBankAccount ()Lcom/stripe/android/model/PaymentMethodCreateParams;
public final fun createUSBankAccount (Lcom/stripe/android/model/PaymentMethod$BillingDetails;)Lcom/stripe/android/model/PaymentMethodCreateParams;
public final fun createUSBankAccount (Lcom/stripe/android/model/PaymentMethod$BillingDetails;Ljava/util/Map;)Lcom/stripe/android/model/PaymentMethodCreateParams;
@@ -4414,6 +4423,23 @@ public final class com/stripe/android/model/PaymentMethodCreateParams$Sofort$Cre
public synthetic fun newArray (I)[Ljava/lang/Object;
}
+public final class com/stripe/android/model/PaymentMethodCreateParams$Swish : android/os/Parcelable, com/stripe/android/model/StripeParamsModel {
+ public static final field $stable I
+ public static final field CREATOR Landroid/os/Parcelable$Creator;
+ public fun ()V
+ public fun describeContents ()I
+ public fun toParamMap ()Ljava/util/Map;
+ public fun writeToParcel (Landroid/os/Parcel;I)V
+}
+
+public final class com/stripe/android/model/PaymentMethodCreateParams$Swish$Creator : android/os/Parcelable$Creator {
+ public fun ()V
+ public final fun createFromParcel (Landroid/os/Parcel;)Lcom/stripe/android/model/PaymentMethodCreateParams$Swish;
+ public synthetic fun createFromParcel (Landroid/os/Parcel;)Ljava/lang/Object;
+ public final fun newArray (I)[Lcom/stripe/android/model/PaymentMethodCreateParams$Swish;
+ public synthetic fun newArray (I)[Ljava/lang/Object;
+}
+
public final class com/stripe/android/model/PaymentMethodCreateParams$USBankAccount : android/os/Parcelable, com/stripe/android/model/StripeParamsModel {
public static final field $stable I
public static final field CREATOR Landroid/os/Parcelable$Creator;
@@ -6210,6 +6236,29 @@ public final class com/stripe/android/model/StripeIntent$NextActionData$SdkData$
public synthetic fun newArray (I)[Ljava/lang/Object;
}
+public final class com/stripe/android/model/StripeIntent$NextActionData$SwishRedirect : com/stripe/android/model/StripeIntent$NextActionData {
+ public static final field $stable I
+ public static final field CREATOR Landroid/os/Parcelable$Creator;
+ public fun (Ljava/lang/String;)V
+ public final fun component1 ()Ljava/lang/String;
+ public final fun copy (Ljava/lang/String;)Lcom/stripe/android/model/StripeIntent$NextActionData$SwishRedirect;
+ public static synthetic fun copy$default (Lcom/stripe/android/model/StripeIntent$NextActionData$SwishRedirect;Ljava/lang/String;ILjava/lang/Object;)Lcom/stripe/android/model/StripeIntent$NextActionData$SwishRedirect;
+ public fun describeContents ()I
+ public fun equals (Ljava/lang/Object;)Z
+ public final fun getMobileAuthUrl ()Ljava/lang/String;
+ public fun hashCode ()I
+ public fun toString ()Ljava/lang/String;
+ public fun writeToParcel (Landroid/os/Parcel;I)V
+}
+
+public final class com/stripe/android/model/StripeIntent$NextActionData$SwishRedirect$Creator : android/os/Parcelable$Creator {
+ public fun ()V
+ public final fun createFromParcel (Landroid/os/Parcel;)Lcom/stripe/android/model/StripeIntent$NextActionData$SwishRedirect;
+ public synthetic fun createFromParcel (Landroid/os/Parcel;)Ljava/lang/Object;
+ public final fun newArray (I)[Lcom/stripe/android/model/StripeIntent$NextActionData$SwishRedirect;
+ public synthetic fun newArray (I)[Ljava/lang/Object;
+}
+
public final class com/stripe/android/model/StripeIntent$NextActionData$UpiAwaitNotification : com/stripe/android/model/StripeIntent$NextActionData {
public static final field $stable I
public static final field CREATOR Landroid/os/Parcelable$Creator;
@@ -6271,6 +6320,7 @@ public final class com/stripe/android/model/StripeIntent$NextActionType : java/l
public static final field DisplayKonbiniDetails Lcom/stripe/android/model/StripeIntent$NextActionType;
public static final field DisplayOxxoDetails Lcom/stripe/android/model/StripeIntent$NextActionType;
public static final field RedirectToUrl Lcom/stripe/android/model/StripeIntent$NextActionType;
+ public static final field SwishRedirect Lcom/stripe/android/model/StripeIntent$NextActionType;
public static final field UpiAwaitNotification Lcom/stripe/android/model/StripeIntent$NextActionType;
public static final field UseStripeSdk Lcom/stripe/android/model/StripeIntent$NextActionType;
public static final field VerifyWithMicrodeposits Lcom/stripe/android/model/StripeIntent$NextActionType;
diff --git a/payments-core/detekt-baseline.xml b/payments-core/detekt-baseline.xml
index 43a950f62f3..15046f32954 100644
--- a/payments-core/detekt-baseline.xml
+++ b/payments-core/detekt-baseline.xml
@@ -7,6 +7,7 @@
ComplexCondition:ExpiryDateEditText.kt$ExpiryDateEditText.<no name provided>$expirationDate.month.length == 2 && latestInsertionSize > 0 && !inErrorState || rawNumericInput.length > 2
ConstructorParameterNaming:Source.kt$Source$private val _klarna: Klarna? = null
ConstructorParameterNaming:Source.kt$Source$private val _weChat: WeChat? = null
+ CyclomaticComplexMethod:NextActionDataParser.kt$NextActionDataParser$override fun parse( json: JSONObject ): StripeIntent.NextActionData?
CyclomaticComplexMethod:PaymentMethodJsonParser.kt$PaymentMethodJsonParser$override fun parse(json: JSONObject): PaymentMethod
CyclomaticComplexMethod:Source.kt$Source.Companion$@SourceType @JvmStatic fun asSourceType(sourceType: String?): String
CyclomaticComplexMethod:SourceJsonParser.kt$SourceJsonParser.Companion$@Source.SourceType private fun asSourceType(sourceType: String?): String
diff --git a/payments-core/src/main/java/com/stripe/android/StripeIntentResult.kt b/payments-core/src/main/java/com/stripe/android/StripeIntentResult.kt
index 95261a09200..a906c3073bb 100644
--- a/payments-core/src/main/java/com/stripe/android/StripeIntentResult.kt
+++ b/payments-core/src/main/java/com/stripe/android/StripeIntentResult.kt
@@ -91,6 +91,7 @@ abstract class StripeIntentResult internal constructor(
StripeIntent.NextActionType.AlipayRedirect,
StripeIntent.NextActionType.WeChatPayRedirect,
StripeIntent.NextActionType.CashAppRedirect,
+ StripeIntent.NextActionType.SwishRedirect,
null -> {
false
}
diff --git a/payments-core/src/main/java/com/stripe/android/model/PaymentIntent.kt b/payments-core/src/main/java/com/stripe/android/model/PaymentIntent.kt
index 7ac2c506a1d..ed629148d70 100644
--- a/payments-core/src/main/java/com/stripe/android/model/PaymentIntent.kt
+++ b/payments-core/src/main/java/com/stripe/android/model/PaymentIntent.kt
@@ -189,6 +189,9 @@ constructor(
is StripeIntent.NextActionData.BlikAuthorize -> {
StripeIntent.NextActionType.BlikAuthorize
}
+ is StripeIntent.NextActionData.SwishRedirect -> {
+ StripeIntent.NextActionType.SwishRedirect
+ }
is StripeIntent.NextActionData.AlipayRedirect,
is StripeIntent.NextActionData.WeChatPayRedirect,
null -> {
diff --git a/payments-core/src/main/java/com/stripe/android/model/PaymentMethod.kt b/payments-core/src/main/java/com/stripe/android/model/PaymentMethod.kt
index 2eda92216a4..23ab1543eb3 100644
--- a/payments-core/src/main/java/com/stripe/android/model/PaymentMethod.kt
+++ b/payments-core/src/main/java/com/stripe/android/model/PaymentMethod.kt
@@ -397,6 +397,13 @@ constructor(
isVoucher = true,
requiresMandate = false,
hasDelayedSettlement = true,
+ ),
+ Swish(
+ code = "swish",
+ isReusable = false,
+ isVoucher = false,
+ requiresMandate = false,
+ hasDelayedSettlement = false,
);
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) // For paymentsheet
diff --git a/payments-core/src/main/java/com/stripe/android/model/PaymentMethodCreateParams.kt b/payments-core/src/main/java/com/stripe/android/model/PaymentMethodCreateParams.kt
index b7d11394db5..26e7e174de8 100644
--- a/payments-core/src/main/java/com/stripe/android/model/PaymentMethodCreateParams.kt
+++ b/payments-core/src/main/java/com/stripe/android/model/PaymentMethodCreateParams.kt
@@ -34,6 +34,7 @@ data class PaymentMethodCreateParams internal constructor(
private val usBankAccount: USBankAccount? = null,
private val link: Link? = null,
private val cashAppPay: CashAppPay? = null,
+ private val swish: Swish? = null,
val billingDetails: PaymentMethod.BillingDetails? = null,
private val metadata: Map? = null,
private val productUsage: Set = emptySet(),
@@ -65,6 +66,7 @@ data class PaymentMethodCreateParams internal constructor(
usBankAccount: USBankAccount? = null,
link: Link? = null,
cashAppPay: CashAppPay? = null,
+ swish: Swish? = null,
billingDetails: PaymentMethod.BillingDetails? = null,
metadata: Map? = null,
productUsage: Set = emptySet(),
@@ -84,6 +86,7 @@ data class PaymentMethodCreateParams internal constructor(
usBankAccount,
link,
cashAppPay,
+ swish,
billingDetails,
metadata,
productUsage,
@@ -224,6 +227,17 @@ data class PaymentMethodCreateParams internal constructor(
metadata = metadata,
)
+ private constructor(
+ swish: Swish,
+ billingDetails: PaymentMethod.BillingDetails?,
+ metadata: Map?,
+ ) : this(
+ type = PaymentMethod.Type.Swish,
+ swish = swish,
+ billingDetails = billingDetails,
+ metadata = metadata,
+ )
+
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
fun requiresMandate(): Boolean {
return requiresMandate
@@ -493,6 +507,14 @@ data class PaymentMethodCreateParams internal constructor(
override fun toParamMap(): Map = emptyMap()
}
+ /**
+ * Encapsulates parameters used to create [PaymentMethodCreateParams] when using Swish.
+ */
+ @Parcelize
+ class Swish : StripeParamsModel, Parcelable {
+ override fun toParamMap(): Map = emptyMap()
+ }
+
@Parcelize
@Suppress("DataClassPrivateConstructor")
data class USBankAccount private constructor(
@@ -958,6 +980,19 @@ data class PaymentMethodCreateParams internal constructor(
return PaymentMethodCreateParams(CashAppPay(), billingDetails, metadata)
}
+ /**
+ * Helper method to create [PaymentMethodCreateParams] with [Swish] as the payment
+ * method type.
+ */
+ @JvmStatic
+ @JvmOverloads
+ fun createSwish(
+ billingDetails: PaymentMethod.BillingDetails? = null,
+ metadata: Map? = null
+ ): PaymentMethodCreateParams {
+ return PaymentMethodCreateParams(Swish(), billingDetails, metadata)
+ }
+
@JvmStatic
@JvmOverloads
fun createRevolutPay(
diff --git a/payments-core/src/main/java/com/stripe/android/model/SetupIntent.kt b/payments-core/src/main/java/com/stripe/android/model/SetupIntent.kt
index e56039d803a..dd9131737d6 100644
--- a/payments-core/src/main/java/com/stripe/android/model/SetupIntent.kt
+++ b/payments-core/src/main/java/com/stripe/android/model/SetupIntent.kt
@@ -141,6 +141,7 @@ data class SetupIntent internal constructor(
is StripeIntent.NextActionData.BlikAuthorize,
is StripeIntent.NextActionData.WeChatPayRedirect,
is StripeIntent.NextActionData.UpiAwaitNotification,
+ is StripeIntent.NextActionData.SwishRedirect,
null -> {
null
}
diff --git a/payments-core/src/main/java/com/stripe/android/model/StripeIntent.kt b/payments-core/src/main/java/com/stripe/android/model/StripeIntent.kt
index c74ea449fb8..0b3898b3c0f 100644
--- a/payments-core/src/main/java/com/stripe/android/model/StripeIntent.kt
+++ b/payments-core/src/main/java/com/stripe/android/model/StripeIntent.kt
@@ -97,7 +97,8 @@ sealed interface StripeIntent : StripeModel {
UpiAwaitNotification("upi_await_notification"),
CashAppRedirect("cashapp_handle_redirect_or_display_qr_code"),
DisplayBoletoDetails("boleto_display_details"),
- DisplayKonbiniDetails("konbini_display_details");
+ DisplayKonbiniDetails("konbini_display_details"),
+ SwishRedirect("swish_handle_redirect_or_display_qr_code");
@Keep
override fun toString(): String {
@@ -333,5 +334,13 @@ sealed interface StripeIntent : StripeModel {
data class CashAppRedirect(
val mobileAuthUrl: String,
) : NextActionData()
+
+ /**
+ * Contains the authentication URL for redirecting your customer to Swish.
+ */
+ @Parcelize
+ data class SwishRedirect(
+ val mobileAuthUrl: String,
+ ) : NextActionData()
}
}
diff --git a/payments-core/src/main/java/com/stripe/android/model/parsers/NextActionDataParser.kt b/payments-core/src/main/java/com/stripe/android/model/parsers/NextActionDataParser.kt
index e591773e621..f0762966c71 100644
--- a/payments-core/src/main/java/com/stripe/android/model/parsers/NextActionDataParser.kt
+++ b/payments-core/src/main/java/com/stripe/android/model/parsers/NextActionDataParser.kt
@@ -28,6 +28,7 @@ internal class NextActionDataParser : ModelJsonParser VerifyWithMicrodepositsParser()
StripeIntent.NextActionType.UpiAwaitNotification -> UpiAwaitNotificationParser()
StripeIntent.NextActionType.CashAppRedirect -> CashAppRedirectParser()
+ StripeIntent.NextActionType.SwishRedirect -> SwishRedirectParser()
null -> return null
}
return parser.parse(json.optJSONObject(nextActionType.code) ?: JSONObject())
@@ -265,6 +266,16 @@ internal class NextActionDataParser : ModelJsonParser {
+
+ override fun parse(json: JSONObject): StripeIntent.NextActionData.SwishRedirect {
+ return StripeIntent.NextActionData.SwishRedirect(
+ mobileAuthUrl = json.optString("mobile_auth_url"),
+ )
+ }
+ }
+
private companion object {
private const val FIELD_NEXT_ACTION_TYPE = "type"
}
diff --git a/payments-core/src/main/java/com/stripe/android/payments/PaymentFlowResultProcessor.kt b/payments-core/src/main/java/com/stripe/android/payments/PaymentFlowResultProcessor.kt
index bd9114865fc..eb8008edc0a 100644
--- a/payments-core/src/main/java/com/stripe/android/payments/PaymentFlowResultProcessor.kt
+++ b/payments-core/src/main/java/com/stripe/android/payments/PaymentFlowResultProcessor.kt
@@ -155,8 +155,13 @@ internal sealed class PaymentFlowResultProcessor
+ is StripeIntent.NextActionData.SwishRedirect -> {
+ authUrl = nextActionData.mobileAuthUrl
+ returnUrl = defaultReturnUrl.value
+ shouldCancelIntentOnUserNavigation = false
+ }
+ else -> {
throw IllegalArgumentException("WebAuthenticator can't process nextActionData: $nextActionData")
+ }
}
beginWebAuth(
diff --git a/payments-core/src/main/java/com/stripe/android/payments/core/injection/AuthenticationModule.kt b/payments-core/src/main/java/com/stripe/android/payments/core/injection/AuthenticationModule.kt
index ea06d7dc49e..8fa7870b1d5 100644
--- a/payments-core/src/main/java/com/stripe/android/payments/core/injection/AuthenticationModule.kt
+++ b/payments-core/src/main/java/com/stripe/android/payments/core/injection/AuthenticationModule.kt
@@ -82,6 +82,14 @@ internal abstract class AuthenticationModule {
webIntentAuthenticator: WebIntentAuthenticator
): PaymentAuthenticator
+ @IntentAuthenticatorMap
+ @Binds
+ @IntoMap
+ @IntentAuthenticatorKey(NextActionData.SwishRedirect::class)
+ abstract fun bindsSwishRedirectAuthenticator(
+ webIntentAuthenticator: WebIntentAuthenticator
+ ): PaymentAuthenticator
+
companion object {
@Provides
@Singleton
diff --git a/payments-core/src/test/java/com/stripe/android/ApiKeyFixtures.kt b/payments-core/src/test/java/com/stripe/android/ApiKeyFixtures.kt
index 95a8ae13342..c67f0fbe300 100644
--- a/payments-core/src/test/java/com/stripe/android/ApiKeyFixtures.kt
+++ b/payments-core/src/test/java/com/stripe/android/ApiKeyFixtures.kt
@@ -30,4 +30,6 @@ internal object ApiKeyFixtures {
const val CASH_APP_PAY_PUBLISHABLE_KEY = "pk_test_ErsyMEOTudSjQR8hh0VrQr5X008sBXGOu6"
const val REVOLUT_PAY_PUBLISHABLE_KEY =
"pk_test_51KmkHbGoesj9fw9QAZJlz1qY4dns8nFmLKc7rXiWKAIj8QU7NPFPwSY1h8mqRaFRKQ9njs9pVJoo2jhN6ZKSDA4h00mjcbGF7b"
+ const val SWISH_PUBLISHABLE_KEY =
+ "pk_test_51JtgfQKG6vc7r7YCU0qQNOkDaaHrEgeHgGKrJMNfuWwaKgXMLzPUA1f8ZlCNPonIROLOnzpUnJK1C1xFH3M3Mz8X00Q6O4GfUt"
}
diff --git a/payments-core/src/test/java/com/stripe/android/PaymentMethodEndToEndTest.kt b/payments-core/src/test/java/com/stripe/android/PaymentMethodEndToEndTest.kt
index 39c2ba456e0..1bd0a49ec7e 100644
--- a/payments-core/src/test/java/com/stripe/android/PaymentMethodEndToEndTest.kt
+++ b/payments-core/src/test/java/com/stripe/android/PaymentMethodEndToEndTest.kt
@@ -456,4 +456,13 @@ internal class PaymentMethodEndToEndTest {
val paymentMethod = stripe.createPaymentMethodSynchronous(params)
assertThat(paymentMethod.type).isEqualTo(PaymentMethod.Type.RevolutPay)
}
+
+ @Test
+ fun createPaymentMethod_withSwish_shouldCreateObject() {
+ val params = PaymentMethodCreateParamsFixtures.SWISH
+ val stripe = Stripe(context, ApiKeyFixtures.SWISH_PUBLISHABLE_KEY)
+
+ val paymentMethod = stripe.createPaymentMethodSynchronous(params)
+ assertThat(paymentMethod.type).isEqualTo(PaymentMethod.Type.Swish)
+ }
}
diff --git a/payments-core/src/test/java/com/stripe/android/model/PaymentMethodCreateParamsFixtures.kt b/payments-core/src/test/java/com/stripe/android/model/PaymentMethodCreateParamsFixtures.kt
index 280ea38302f..fd8159c71ec 100644
--- a/payments-core/src/test/java/com/stripe/android/model/PaymentMethodCreateParamsFixtures.kt
+++ b/payments-core/src/test/java/com/stripe/android/model/PaymentMethodCreateParamsFixtures.kt
@@ -121,6 +121,10 @@ internal object PaymentMethodCreateParamsFixtures {
billingDetails = BILLING_DETAILS,
)
+ internal val SWISH = PaymentMethodCreateParams.createSwish(
+ billingDetails = BILLING_DETAILS,
+ )
+
@JvmStatic
fun createWith(metadata: Map): PaymentMethodCreateParams {
return PaymentMethodCreateParams.create(
diff --git a/payments-ui-core/res/drawable/stripe_ic_paymentsheet_pm_swish.xml b/payments-ui-core/res/drawable/stripe_ic_paymentsheet_pm_swish.xml
new file mode 100644
index 00000000000..d0915928339
--- /dev/null
+++ b/payments-ui-core/res/drawable/stripe_ic_paymentsheet_pm_swish.xml
@@ -0,0 +1,76 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/payments-ui-core/res/values/donottranslate.xml b/payments-ui-core/res/values/donottranslate.xml
index 1a25a2a43d4..dbb3f1b7b67 100644
--- a/payments-ui-core/res/values/donottranslate.xml
+++ b/payments-ui-core/res/values/donottranslate.xml
@@ -17,7 +17,7 @@
GrabPay
FPX Bank
Boleto
-
+ Swish
Affirm
Revolut Pay
Amazon Pay
diff --git a/payments-ui-core/src/main/assets/lpms.json b/payments-ui-core/src/main/assets/lpms.json
index d0476a29f34..c077fe53adc 100644
--- a/payments-ui-core/src/main/assets/lpms.json
+++ b/payments-ui-core/src/main/assets/lpms.json
@@ -1086,5 +1086,10 @@
"type": "konbini_confirmation_number"
}
]
+ },
+ {
+ "type": "swish",
+ "async": false,
+ "fields": []
}
]
diff --git a/payments-ui-core/src/main/java/com/stripe/android/paymentsheet/forms/PaymentMethodRequirements.kt b/payments-ui-core/src/main/java/com/stripe/android/paymentsheet/forms/PaymentMethodRequirements.kt
index 15c94da1540..cb8e5e6193c 100644
--- a/payments-ui-core/src/main/java/com/stripe/android/paymentsheet/forms/PaymentMethodRequirements.kt
+++ b/payments-ui-core/src/main/java/com/stripe/android/paymentsheet/forms/PaymentMethodRequirements.kt
@@ -295,3 +295,9 @@ internal val KonbiniRequirement = PaymentMethodRequirements(
siRequirements = null,
confirmPMFromCustomer = null,
)
+
+internal val SwishRequirement = PaymentMethodRequirements(
+ piRequirements = emptySet(),
+ siRequirements = null,
+ confirmPMFromCustomer = false,
+)
diff --git a/payments-ui-core/src/main/java/com/stripe/android/ui/core/forms/resources/LpmRepository.kt b/payments-ui-core/src/main/java/com/stripe/android/ui/core/forms/resources/LpmRepository.kt
index a72537174bc..b2ab5ec6aba 100644
--- a/payments-ui-core/src/main/java/com/stripe/android/ui/core/forms/resources/LpmRepository.kt
+++ b/payments-ui-core/src/main/java/com/stripe/android/ui/core/forms/resources/LpmRepository.kt
@@ -40,6 +40,7 @@ import com.stripe.android.paymentsheet.forms.PaypalRequirement
import com.stripe.android.paymentsheet.forms.RevolutPayRequirement
import com.stripe.android.paymentsheet.forms.SepaDebitRequirement
import com.stripe.android.paymentsheet.forms.SofortRequirement
+import com.stripe.android.paymentsheet.forms.SwishRequirement
import com.stripe.android.paymentsheet.forms.USBankAccountRequirement
import com.stripe.android.paymentsheet.forms.UpiRequirement
import com.stripe.android.paymentsheet.forms.ZipRequirement
@@ -600,6 +601,17 @@ class LpmRepository constructor(
requirement = KonbiniRequirement,
formSpec = LayoutSpec(sharedDataSpec.fields),
)
+ PaymentMethod.Type.Swish.code -> SupportedPaymentMethod(
+ code = "swish",
+ requiresMandate = false,
+ displayNameResource = R.string.stripe_paymentsheet_payment_method_swish,
+ iconResource = R.drawable.stripe_ic_paymentsheet_pm_swish,
+ lightThemeIconUrl = sharedDataSpec.selectorIcon?.lightThemePng,
+ darkThemeIconUrl = sharedDataSpec.selectorIcon?.darkThemePng,
+ tintIconOnSelection = false,
+ requirement = SwishRequirement,
+ formSpec = LayoutSpec(sharedDataSpec.fields),
+ )
else -> null
}
diff --git a/paymentsheet-example/src/androidTest/java/com/stripe/android/lpm/TestSwish.kt b/paymentsheet-example/src/androidTest/java/com/stripe/android/lpm/TestSwish.kt
new file mode 100644
index 00000000000..09c4af401b0
--- /dev/null
+++ b/paymentsheet-example/src/androidTest/java/com/stripe/android/lpm/TestSwish.kt
@@ -0,0 +1,35 @@
+package com.stripe.android.lpm
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.stripe.android.BaseLpmTest
+import com.stripe.android.test.core.Currency
+import com.stripe.android.test.core.DelayedPMs
+import com.stripe.android.test.core.GooglePayState
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+internal class TestSwish : BaseLpmTest() {
+
+ private val swishUser = newUser.copy(
+ paymentMethod = lpmRepository.fromCode("swish")!!,
+ currency = Currency.SEK,
+ merchantCountryCode = "FR",
+ delayed = DelayedPMs.On,
+ googlePayState = GooglePayState.Off,
+ )
+
+ @Test
+ fun testSwish() {
+ testDriver.confirmNewOrGuestComplete(
+ testParameters = swishUser,
+ )
+ }
+
+ @Test
+ fun testSwishInCustomFlow() {
+ testDriver.confirmCustom(
+ testParameters = swishUser,
+ )
+ }
+}
diff --git a/paymentsheet-example/src/androidTest/java/com/stripe/android/test/core/TestParameters.kt b/paymentsheet-example/src/androidTest/java/com/stripe/android/test/core/TestParameters.kt
index 3ad8d20856d..639875daafa 100644
--- a/paymentsheet-example/src/androidTest/java/com/stripe/android/test/core/TestParameters.kt
+++ b/paymentsheet-example/src/androidTest/java/com/stripe/android/test/core/TestParameters.kt
@@ -147,6 +147,7 @@ enum class Currency {
BRL,
MXN,
JPY,
+ SEK,
}
/**
diff --git a/paymentsheet-example/src/main/java/com/stripe/android/paymentsheet/example/playground/activity/PaymentSheetPlaygroundActivity.kt b/paymentsheet-example/src/main/java/com/stripe/android/paymentsheet/example/playground/activity/PaymentSheetPlaygroundActivity.kt
index b6a5d999714..7ec2617cd35 100644
--- a/paymentsheet-example/src/main/java/com/stripe/android/paymentsheet/example/playground/activity/PaymentSheetPlaygroundActivity.kt
+++ b/paymentsheet-example/src/main/java/com/stripe/android/paymentsheet/example/playground/activity/PaymentSheetPlaygroundActivity.kt
@@ -936,7 +936,8 @@ class PaymentSheetPlaygroundActivity : AppCompatActivity() {
"MYR",
"MXN",
"BRL",
- "JPY"
+ "JPY",
+ "SEK",
)
}
}
diff --git a/paymentsheet-example/src/main/java/com/stripe/android/paymentsheet/example/playground/model/PlaygroundCheckoutModel.kt b/paymentsheet-example/src/main/java/com/stripe/android/paymentsheet/example/playground/model/PlaygroundCheckoutModel.kt
index ca1dcb3cc0c..028864e4e7a 100644
--- a/paymentsheet-example/src/main/java/com/stripe/android/paymentsheet/example/playground/model/PlaygroundCheckoutModel.kt
+++ b/paymentsheet-example/src/main/java/com/stripe/android/paymentsheet/example/playground/model/PlaygroundCheckoutModel.kt
@@ -52,6 +52,7 @@ data class CheckoutCurrency(val value: String) {
val AUD = CheckoutCurrency("aud")
val GBP = CheckoutCurrency("gbp")
val PLN = CheckoutCurrency("pln")
+ val SEK = CheckoutCurrency("sek")
}
}
diff --git a/paymentsheet/src/test/resources/swish-support.csv b/paymentsheet/src/test/resources/swish-support.csv
new file mode 100644
index 00000000000..b72d3555109
--- /dev/null
+++ b/paymentsheet/src/test/resources/swish-support.csv
@@ -0,0 +1,49 @@
+lpm, hasCustomer, allowsDelayedPayment, intentSetupFutureUsage, intentHasShipping, intentLpms, supportCustomerSavedCard, formExists, formType, supportsAdding
+swish, true, true, off_session, false, card/swish, false, false, not available, false
+swish, true, true, off_session, false, card/eps/swish, false, false, not available, false
+swish, true, false, off_session, false, card/swish, false, false, not available, false
+swish, true, false, off_session, false, card/eps/swish, false, false, not available, false
+swish, true, true, on_session, false, card/swish, false, false, not available, false
+swish, true, true, on_session, false, card/eps/swish, false, false, not available, false
+swish, true, false, on_session, false, card/swish, false, false, not available, false
+swish, true, false, on_session, false, card/eps/swish, false, false, not available, false
+swish, true, true, null, false, card/swish, false, true, oneTime, true
+swish, true, true, null, false, card/eps/swish, false, true, oneTime, true
+swish, true, false, null, false, card/swish, false, true, oneTime, true
+swish, true, false, null, false, card/eps/swish, false, true, oneTime, true
+swish, false, true, off_session, false, card/swish, false, false, not available, false
+swish, false, true, off_session, false, card/eps/swish, false, false, not available, false
+swish, false, false, off_session, false, card/swish, false, false, not available, false
+swish, false, false, off_session, false, card/eps/swish, false, false, not available, false
+swish, false, true, on_session, false, card/swish, false, false, not available, false
+swish, false, true, on_session, false, card/eps/swish, false, false, not available, false
+swish, false, false, on_session, false, card/swish, false, false, not available, false
+swish, false, false, on_session, false, card/eps/swish, false, false, not available, false
+swish, false, true, null, false, card/swish, false, true, oneTime, true
+swish, false, true, null, false, card/eps/swish, false, true, oneTime, true
+swish, false, false, null, false, card/swish, false, true, oneTime, true
+swish, false, false, null, false, card/eps/swish, false, true, oneTime, true
+swish, true, true, off_session, true, card/swish, false, false, not available, false
+swish, true, true, off_session, true, card/eps/swish, false, false, not available, false
+swish, true, false, off_session, true, card/swish, false, false, not available, false
+swish, true, false, off_session, true, card/eps/swish, false, false, not available, false
+swish, true, true, on_session, true, card/swish, false, false, not available, false
+swish, true, true, on_session, true, card/eps/swish, false, false, not available, false
+swish, true, false, on_session, true, card/swish, false, false, not available, false
+swish, true, false, on_session, true, card/eps/swish, false, false, not available, false
+swish, true, true, null, true, card/swish, false, true, oneTime, true
+swish, true, true, null, true, card/eps/swish, false, true, oneTime, true
+swish, true, false, null, true, card/swish, false, true, oneTime, true
+swish, true, false, null, true, card/eps/swish, false, true, oneTime, true
+swish, false, true, off_session, true, card/swish, false, false, not available, false
+swish, false, true, off_session, true, card/eps/swish, false, false, not available, false
+swish, false, false, off_session, true, card/swish, false, false, not available, false
+swish, false, false, off_session, true, card/eps/swish, false, false, not available, false
+swish, false, true, on_session, true, card/swish, false, false, not available, false
+swish, false, true, on_session, true, card/eps/swish, false, false, not available, false
+swish, false, false, on_session, true, card/swish, false, false, not available, false
+swish, false, false, on_session, true, card/eps/swish, false, false, not available, false
+swish, false, true, null, true, card/swish, false, true, oneTime, true
+swish, false, true, null, true, card/eps/swish, false, true, oneTime, true
+swish, false, false, null, true, card/swish, false, true, oneTime, true
+swish, false, false, null, true, card/eps/swish, false, true, oneTime, true