diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0f579ad69aa..7682499eebd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,9 @@
## XX.XX.XX - 2023-XX-XX
+### PaymentSheet
+* [ADDED][7302](https://github.com/stripe/stripe-android/pull/7302) PaymentSheet now supports Alma for PaymentIntents in private beta.
+
## 20.30.2 - 2023-09-13
### PaymentSheet
diff --git a/payments-core/api/payments-core.api b/payments-core/api/payments-core.api
index c70ad2b8c7f..09c31c32588 100644
--- a/payments-core/api/payments-core.api
+++ b/payments-core/api/payments-core.api
@@ -3760,6 +3760,7 @@ public final class com/stripe/android/model/PaymentMethod$Type : java/lang/Enum,
public static final field Affirm Lcom/stripe/android/model/PaymentMethod$Type;
public static final field AfterpayClearpay Lcom/stripe/android/model/PaymentMethod$Type;
public static final field Alipay Lcom/stripe/android/model/PaymentMethod$Type;
+ public static final field Alma Lcom/stripe/android/model/PaymentMethod$Type;
public static final field AmazonPay Lcom/stripe/android/model/PaymentMethod$Type;
public static final field AuBecsDebit Lcom/stripe/android/model/PaymentMethod$Type;
public static final field BacsDebit Lcom/stripe/android/model/PaymentMethod$Type;
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 f6fab92d0cd..3043829ccfe 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
@@ -349,6 +349,13 @@ constructor(
requiresMandate = false,
hasDelayedSettlement = false
),
+ Alma(
+ "alma",
+ isReusable = false,
+ isVoucher = false,
+ requiresMandate = false,
+ hasDelayedSettlement = false
+ ),
MobilePay(
"mobilepay",
isReusable = false,
diff --git a/payments-ui-core/res/drawable-night/stripe_ic_paymentsheet_pm_alma.xml b/payments-ui-core/res/drawable-night/stripe_ic_paymentsheet_pm_alma.xml
new file mode 100644
index 00000000000..e19ccd53aa0
--- /dev/null
+++ b/payments-ui-core/res/drawable-night/stripe_ic_paymentsheet_pm_alma.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/payments-ui-core/res/drawable/stripe_ic_paymentsheet_pm_alma.xml b/payments-ui-core/res/drawable/stripe_ic_paymentsheet_pm_alma.xml
new file mode 100644
index 00000000000..95d87d568fd
--- /dev/null
+++ b/payments-ui-core/res/drawable/stripe_ic_paymentsheet_pm_alma.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/payments-ui-core/res/values/donottranslate.xml b/payments-ui-core/res/values/donottranslate.xml
index fc58cfade4f..1a25a2a43d4 100644
--- a/payments-ui-core/res/values/donottranslate.xml
+++ b/payments-ui-core/res/values/donottranslate.xml
@@ -21,6 +21,7 @@
Affirm
Revolut Pay
Amazon Pay
+ Alma
MobilePay
Zip
BLIK
diff --git a/payments-ui-core/src/main/assets/lpms.json b/payments-ui-core/src/main/assets/lpms.json
index b4c99e5636b..fa12bd3b030 100644
--- a/payments-ui-core/src/main/assets/lpms.json
+++ b/payments-ui-core/src/main/assets/lpms.json
@@ -791,6 +791,32 @@
}
}
},
+ {
+ "type": "alma",
+ "async": false,
+ "selector_icon": {
+ "light_theme_png": "https://js.stripe.com/v3/fingerprinted/img/payment-methods/icon-pm-alma_dark-9adee7a095478e23c76054e7fcb4c275.png",
+ "dark_theme_png": "https://js.stripe.com/v3/fingerprinted/img/payment-methods/icon-pm-alma_light-41fe66ba84194788e98548aa6e749c79.png"
+ },
+ "fields": [
+ ],
+ "next_action_spec": {
+ "confirm_response_status_specs": {
+ "requires_action": {
+ "type": "redirect_to_url"
+ }
+ },
+ "post_confirm_handling_pi_status_specs": {
+ "succeeded": {
+ "type": "finished"
+ },
+ "requires_action": {
+ "type": "canceled"
+ }
+ }
+ }
+ },
+
{
"type": "mobilepay",
"async": false,
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 1a13af55c2e..afb3ffa24fd 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
@@ -206,6 +206,12 @@ internal val AmazonPayRequirement = PaymentMethodRequirements(
confirmPMFromCustomer = null
)
+internal val AlmaRequirement = PaymentMethodRequirements(
+ piRequirements = emptySet(),
+ siRequirements = null,
+ confirmPMFromCustomer = null
+)
+
internal val MobilePayRequirement = PaymentMethodRequirements(
piRequirements = emptySet(),
siRequirements = null,
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 d17acc302eb..026b0a098c5 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
@@ -17,6 +17,7 @@ import com.stripe.android.payments.financialconnections.IsFinancialConnectionsAv
import com.stripe.android.paymentsheet.forms.AffirmRequirement
import com.stripe.android.paymentsheet.forms.AfterpayClearpayRequirement
import com.stripe.android.paymentsheet.forms.AlipayRequirement
+import com.stripe.android.paymentsheet.forms.AlmaRequirement
import com.stripe.android.paymentsheet.forms.AmazonPayRequirement
import com.stripe.android.paymentsheet.forms.AuBecsDebitRequirement
import com.stripe.android.paymentsheet.forms.BancontactRequirement
@@ -401,6 +402,17 @@ class LpmRepository constructor(
requirement = AmazonPayRequirement,
formSpec = LayoutSpec(sharedDataSpec.fields)
)
+ PaymentMethod.Type.Alma.code -> SupportedPaymentMethod(
+ code = "alma",
+ requiresMandate = false,
+ displayNameResource = R.string.stripe_paymentsheet_payment_method_alma,
+ iconResource = R.drawable.stripe_ic_paymentsheet_pm_alma,
+ lightThemeIconUrl = sharedDataSpec.selectorIcon?.lightThemePng,
+ darkThemeIconUrl = sharedDataSpec.selectorIcon?.darkThemePng,
+ tintIconOnSelection = false,
+ requirement = AlmaRequirement,
+ formSpec = LayoutSpec(sharedDataSpec.fields)
+ )
PaymentMethod.Type.MobilePay.code -> SupportedPaymentMethod(
code = "mobilepay",
requiresMandate = false,
diff --git a/paymentsheet-example/src/androidTest/java/com/stripe/android/lpm/TestAlma.kt b/paymentsheet-example/src/androidTest/java/com/stripe/android/lpm/TestAlma.kt
new file mode 100644
index 00000000000..a42bdbd35f9
--- /dev/null
+++ b/paymentsheet-example/src/androidTest/java/com/stripe/android/lpm/TestAlma.kt
@@ -0,0 +1,32 @@
+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 org.junit.Ignore
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+internal class TestAlma : BaseLpmTest() {
+ private val alma = newUser.copy(
+ paymentMethod = lpmRepository.fromCode("alma")!!,
+ currency = Currency.EUR,
+ merchantCountryCode = "FR",
+ )
+
+ @Ignore("Complex authorization handling required")
+ @Test
+ fun testAlma() {
+ testDriver.confirmNewOrGuestComplete(
+ testParameters = alma,
+ )
+ }
+
+ @Test
+ fun testAlmaInCustomFlow() {
+ testDriver.confirmCustom(
+ testParameters = alma,
+ )
+ }
+}
diff --git a/paymentsheet/src/test/resources/alma-support.csv b/paymentsheet/src/test/resources/alma-support.csv
new file mode 100644
index 00000000000..3347da82c18
--- /dev/null
+++ b/paymentsheet/src/test/resources/alma-support.csv
@@ -0,0 +1,49 @@
+lpm, hasCustomer, allowsDelayedPayment, intentSetupFutureUsage, intentHasShipping, intentLpms, supportCustomerSavedCard, formExists, formType, supportsAdding
+alma, true, true, off_session, false, card/alma, false, false, not available, false
+alma, true, true, off_session, false, card/eps/alma, false, false, not available, false
+alma, true, false, off_session, false, card/alma, false, false, not available, false
+alma, true, false, off_session, false, card/eps/alma, false, false, not available, false
+alma, true, true, on_session, false, card/alma, false, false, not available, false
+alma, true, true, on_session, false, card/eps/alma, false, false, not available, false
+alma, true, false, on_session, false, card/alma, false, false, not available, false
+alma, true, false, on_session, false, card/eps/alma, false, false, not available, false
+alma, true, true, null, false, card/alma, false, true, oneTime, true
+alma, true, true, null, false, card/eps/alma, false, true, oneTime, true
+alma, true, false, null, false, card/alma, false, true, oneTime, true
+alma, true, false, null, false, card/eps/alma, false, true, oneTime, true
+alma, false, true, off_session, false, card/alma, false, false, not available, false
+alma, false, true, off_session, false, card/eps/alma, false, false, not available, false
+alma, false, false, off_session, false, card/alma, false, false, not available, false
+alma, false, false, off_session, false, card/eps/alma, false, false, not available, false
+alma, false, true, on_session, false, card/alma, false, false, not available, false
+alma, false, true, on_session, false, card/eps/alma, false, false, not available, false
+alma, false, false, on_session, false, card/alma, false, false, not available, false
+alma, false, false, on_session, false, card/eps/alma, false, false, not available, false
+alma, false, true, null, false, card/alma, false, true, oneTime, true
+alma, false, true, null, false, card/eps/alma, false, true, oneTime, true
+alma, false, false, null, false, card/alma, false, true, oneTime, true
+alma, false, false, null, false, card/eps/alma, false, true, oneTime, true
+alma, true, true, off_session, true, card/alma, false, false, not available, false
+alma, true, true, off_session, true, card/eps/alma, false, false, not available, false
+alma, true, false, off_session, true, card/alma, false, false, not available, false
+alma, true, false, off_session, true, card/eps/alma, false, false, not available, false
+alma, true, true, on_session, true, card/alma, false, false, not available, false
+alma, true, true, on_session, true, card/eps/alma, false, false, not available, false
+alma, true, false, on_session, true, card/alma, false, false, not available, false
+alma, true, false, on_session, true, card/eps/alma, false, false, not available, false
+alma, true, true, null, true, card/alma, false, true, oneTime, true
+alma, true, true, null, true, card/eps/alma, false, true, oneTime, true
+alma, true, false, null, true, card/alma, false, true, oneTime, true
+alma, true, false, null, true, card/eps/alma, false, true, oneTime, true
+alma, false, true, off_session, true, card/alma, false, false, not available, false
+alma, false, true, off_session, true, card/eps/alma, false, false, not available, false
+alma, false, false, off_session, true, card/alma, false, false, not available, false
+alma, false, false, off_session, true, card/eps/alma, false, false, not available, false
+alma, false, true, on_session, true, card/alma, false, false, not available, false
+alma, false, true, on_session, true, card/eps/alma, false, false, not available, false
+alma, false, false, on_session, true, card/alma, false, false, not available, false
+alma, false, false, on_session, true, card/eps/alma, false, false, not available, false
+alma, false, true, null, true, card/alma, false, true, oneTime, true
+alma, false, true, null, true, card/eps/alma, false, true, oneTime, true
+alma, false, false, null, true, card/alma, false, true, oneTime, true
+alma, false, false, null, true, card/eps/alma, false, true, oneTime, true