diff --git a/CHANGELOG.md b/CHANGELOG.md
index d80ffb03cf6..7ecbcc6e7f4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,11 @@
## XX.XX.XX - 2023-XX-XX
+### PaymentSheet
+
+* [ADDED] PaymentSheet now supports the following payment methods for PaymentIntents:
+ * [7281](https://github.com/stripe/stripe-android/pull/7281) OXXO
+
## 20.30.1 - 2023-09-11
### Financial Connections
diff --git a/payments-ui-core/res/drawable/stripe_ic_paymentsheet_pm_oxxo.xml b/payments-ui-core/res/drawable/stripe_ic_paymentsheet_pm_oxxo.xml
new file mode 100644
index 00000000000..b3bfb31362b
--- /dev/null
+++ b/payments-ui-core/res/drawable/stripe_ic_paymentsheet_pm_oxxo.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
diff --git a/payments-ui-core/res/values/donottranslate.xml b/payments-ui-core/res/values/donottranslate.xml
index 9b3ded3fd3d..b479f95ae16 100644
--- a/payments-ui-core/res/values/donottranslate.xml
+++ b/payments-ui-core/res/values/donottranslate.xml
@@ -24,6 +24,7 @@
Zip
BLIK
Alipay
+ OXXO
diff --git a/payments-ui-core/src/main/assets/lpms.json b/payments-ui-core/src/main/assets/lpms.json
index cae7a87bfbc..b2d011b0c24 100644
--- a/payments-ui-core/src/main/assets/lpms.json
+++ b/payments-ui-core/src/main/assets/lpms.json
@@ -993,5 +993,23 @@
"light_theme_png": "https://js.stripe.com/v3/fingerprinted/img/payment-methods/icon-pm-alipay@3x-d216a94882c3c5422274faaec75a3c81.png"
},
"fields": []
+ },
+ {
+ "type": "oxxo",
+ "async": true,
+ "fields": [
+ {
+ "type": "name",
+ "api_path": {
+ "v1": "billing_details[name]"
+ }
+ },
+ {
+ "type": "email",
+ "api_path": {
+ "v1": "billing_details[email]"
+ }
+ }
+ ]
}
]
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 13578b7a7ac..4bbe8f38cde 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
@@ -271,3 +271,9 @@ internal val AlipayRequirement = PaymentMethodRequirements(
siRequirements = null,
confirmPMFromCustomer = false,
)
+
+internal val OxxoRequirement = PaymentMethodRequirements(
+ piRequirements = setOf(Delayed),
+ 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 380d5c70912..f428076c19e 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
@@ -30,6 +30,7 @@ import com.stripe.android.paymentsheet.forms.GrabPayRequirement
import com.stripe.android.paymentsheet.forms.IdealRequirement
import com.stripe.android.paymentsheet.forms.KlarnaRequirement
import com.stripe.android.paymentsheet.forms.MobilePayRequirement
+import com.stripe.android.paymentsheet.forms.OxxoRequirement
import com.stripe.android.paymentsheet.forms.P24Requirement
import com.stripe.android.paymentsheet.forms.PaymentMethodRequirements
import com.stripe.android.paymentsheet.forms.PaypalRequirement
@@ -72,7 +73,6 @@ class LpmRepository constructor(
private val lpmInitialFormData: LpmInitialFormData = LpmInitialFormData.Instance,
private val lpmPostConfirmData: LuxePostConfirmActionRepository = LuxePostConfirmActionRepository.Instance
) {
-
fun fromCode(code: PaymentMethodCode?) = lpmInitialFormData.fromCode(code)
fun values(): List = lpmInitialFormData.values()
@@ -543,6 +543,17 @@ class LpmRepository constructor(
requirement = AlipayRequirement,
formSpec = LayoutSpec(sharedDataSpec.fields),
)
+ PaymentMethod.Type.Oxxo.code -> SupportedPaymentMethod(
+ code = "oxxo",
+ requiresMandate = false,
+ displayNameResource = R.string.stripe_paymentsheet_payment_method_oxxo,
+ iconResource = R.drawable.stripe_ic_paymentsheet_pm_oxxo,
+ lightThemeIconUrl = null,
+ darkThemeIconUrl = null,
+ tintIconOnSelection = false,
+ requirement = OxxoRequirement,
+ formSpec = LayoutSpec(sharedDataSpec.fields),
+ )
else -> null
}
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 71bdd33a2ce..01b26de4a1f 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
@@ -882,7 +882,7 @@ class PaymentSheetPlaygroundActivity : AppCompatActivity() {
/**
* Modify this list if you want to change the countries displayed in the playground.
*/
- country.code.value in setOf("US", "GB", "AU", "FR", "IN", "SG", "MY")
+ country.code.value in setOf("US", "GB", "AU", "FR", "IN", "SG", "MY", "MX")
}.map { country ->
/**
* Modify this statement to change the default currency associated with each
@@ -910,6 +910,9 @@ class PaymentSheetPlaygroundActivity : AppCompatActivity() {
"MY" -> {
country to "MYR"
}
+ "MX" -> {
+ country to "MXN"
+ }
else -> {
country to "USD"
}
@@ -918,6 +921,6 @@ class PaymentSheetPlaygroundActivity : AppCompatActivity() {
// List was created from: https://stripe.com/docs/currencies
/** Modify this list if you want to change the currencies displayed in the playground **/
- private val stripeSupportedCurrencies = listOf("AUD", "EUR", "GBP", "USD", "INR", "PLN", "SGD", "MYR")
+ private val stripeSupportedCurrencies = listOf("AUD", "EUR", "GBP", "USD", "INR", "PLN", "SGD", "MYR", "MXN")
}
}
diff --git a/paymentsheet/src/androidTest/java/com/stripe/android/paymentsheet/PaymentSheetPage.kt b/paymentsheet/src/androidTest/java/com/stripe/android/paymentsheet/PaymentSheetPage.kt
index aa15fd4fa6c..0599a8ee563 100644
--- a/paymentsheet/src/androidTest/java/com/stripe/android/paymentsheet/PaymentSheetPage.kt
+++ b/paymentsheet/src/androidTest/java/com/stripe/android/paymentsheet/PaymentSheetPage.kt
@@ -33,6 +33,12 @@ internal class PaymentSheetPage(
.performClick()
}
+ fun clickViewWithText(text: String) {
+ composeTestRule.onNode(hasText(text))
+ .performScrollTo()
+ .performClick()
+ }
+
fun waitForText(text: String, substring: Boolean = false) {
composeTestRule.waitUntil(timeoutMillis = 5_000) {
composeTestRule
diff --git a/paymentsheet/src/test/resources/oxxo-support.csv b/paymentsheet/src/test/resources/oxxo-support.csv
new file mode 100644
index 00000000000..6332f325fab
--- /dev/null
+++ b/paymentsheet/src/test/resources/oxxo-support.csv
@@ -0,0 +1,49 @@
+lpm, hasCustomer, allowsDelayedPayment, intentSetupFutureUsage, intentHasShipping, intentLpms, supportCustomerSavedCard, formExists, formType, supportsAdding
+oxxo, true, true, off_session, false, card/oxxo, false, false, not available, false
+oxxo, true, true, off_session, false, card/eps/oxxo, false, false, not available, false
+oxxo, true, false, off_session, false, card/oxxo, false, false, not available, false
+oxxo, true, false, off_session, false, card/eps/oxxo, false, false, not available, false
+oxxo, true, true, on_session, false, card/oxxo, false, false, not available, false
+oxxo, true, true, on_session, false, card/eps/oxxo, false, false, not available, false
+oxxo, true, false, on_session, false, card/oxxo, false, false, not available, false
+oxxo, true, false, on_session, false, card/eps/oxxo, false, false, not available, false
+oxxo, true, true, null, false, card/oxxo, false, true, oneTime, true
+oxxo, true, true, null, false, card/eps/oxxo, false, true, oneTime, true
+oxxo, true, false, null, false, card/oxxo, false, false, not available, false
+oxxo, true, false, null, false, card/eps/oxxo, false, false, not available, false
+oxxo, false, true, off_session, false, card/oxxo, false, false, not available, false
+oxxo, false, true, off_session, false, card/eps/oxxo, false, false, not available, false
+oxxo, false, false, off_session, false, card/oxxo, false, false, not available, false
+oxxo, false, false, off_session, false, card/eps/oxxo, false, false, not available, false
+oxxo, false, true, on_session, false, card/oxxo, false, false, not available, false
+oxxo, false, true, on_session, false, card/eps/oxxo, false, false, not available, false
+oxxo, false, false, on_session, false, card/oxxo, false, false, not available, false
+oxxo, false, false, on_session, false, card/eps/oxxo, false, false, not available, false
+oxxo, false, true, null, false, card/oxxo, false, true, oneTime, true
+oxxo, false, true, null, false, card/eps/oxxo, false, true, oneTime, true
+oxxo, false, false, null, false, card/oxxo, false, false, not available, false
+oxxo, false, false, null, false, card/eps/oxxo, false, false, not available, false
+oxxo, true, true, off_session, true, card/oxxo, false, false, not available, false
+oxxo, true, true, off_session, true, card/eps/oxxo, false, false, not available, false
+oxxo, true, false, off_session, true, card/oxxo, false, false, not available, false
+oxxo, true, false, off_session, true, card/eps/oxxo, false, false, not available, false
+oxxo, true, true, on_session, true, card/oxxo, false, false, not available, false
+oxxo, true, true, on_session, true, card/eps/oxxo, false, false, not available, false
+oxxo, true, false, on_session, true, card/oxxo, false, false, not available, false
+oxxo, true, false, on_session, true, card/eps/oxxo, false, false, not available, false
+oxxo, true, true, null, true, card/oxxo, false, true, oneTime, true
+oxxo, true, true, null, true, card/eps/oxxo, false, true, oneTime, true
+oxxo, true, false, null, true, card/oxxo, false, false, not available, false
+oxxo, true, false, null, true, card/eps/oxxo, false, false, not available, false
+oxxo, false, true, off_session, true, card/oxxo, false, false, not available, false
+oxxo, false, true, off_session, true, card/eps/oxxo, false, false, not available, false
+oxxo, false, false, off_session, true, card/oxxo, false, false, not available, false
+oxxo, false, false, off_session, true, card/eps/oxxo, false, false, not available, false
+oxxo, false, true, on_session, true, card/oxxo, false, false, not available, false
+oxxo, false, true, on_session, true, card/eps/oxxo, false, false, not available, false
+oxxo, false, false, on_session, true, card/oxxo, false, false, not available, false
+oxxo, false, false, on_session, true, card/eps/oxxo, false, false, not available, false
+oxxo, false, true, null, true, card/oxxo, false, true, oneTime, true
+oxxo, false, true, null, true, card/eps/oxxo, false, true, oneTime, true
+oxxo, false, false, null, true, card/oxxo, false, false, not available, false
+oxxo, false, false, null, true, card/eps/oxxo, false, false, not available, false