Skip to content

Commit f2dd745

Browse files
Merge pull request #6 from afterpay/maintenance/update-from-upstream-4.0.0
Maintenance: update from upstream v4.0.0
2 parents 83fcf6e + f4fa7f6 commit f2dd745

File tree

67 files changed

+1857
-271
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

67 files changed

+1857
-271
lines changed

Diff for: README.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ Add `afterpay-android-button` to your `build.gradle` dependencies.
3838

3939
```gradle
4040
dependencies {
41-
implementation 'com.afterpay:afterpay-android-button:3.3.1'
41+
implementation 'com.afterpay:afterpay-android-button:4.0.0'
4242
}
4343
```
4444

@@ -121,6 +121,8 @@ class ExampleActivity: Activity {
121121

122122
### Launching the Checkout (v2)
123123

124+
**Note:** Checkout v2 is not available at this time for the following regions: France, Italy, Spain.
125+
124126
Launch the Afterpay checkout v2 flow by starting the intent provided by the SDK for the given options.
125127

126128
> When creating a checkout token, `popupOriginUrl` must be set to `https://static.afterpay.com`. The SDK’s example merchant server sets the parameter [here](https://github.com/afterpay/sdk-example-server/blob/master/src/routes/checkout.ts#L28). See the [API reference][express-checkout] for more details! Failing to do so will cause undefined behavior.

Diff for: afterpay/src/main/kotlin/com/afterpay/android/Afterpay.kt

+21-4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package com.afterpay.android
22

33
import android.content.Context
44
import android.content.Intent
5+
import com.afterpay.android.internal.AfterpayDrawable
6+
import com.afterpay.android.internal.AfterpayString
57
import com.afterpay.android.internal.ApiV3
68
import com.afterpay.android.internal.Brand
79
import com.afterpay.android.internal.CheckoutV3
@@ -11,6 +13,7 @@ import com.afterpay.android.internal.getCancellationStatusExtra
1113
import com.afterpay.android.internal.getCancellationStatusExtraErrorV3
1214
import com.afterpay.android.internal.getCancellationStatusExtraV3
1315
import com.afterpay.android.internal.getOrderTokenExtra
16+
import com.afterpay.android.internal.getRegionLanguage
1417
import com.afterpay.android.internal.getResultDataExtra
1518
import com.afterpay.android.internal.putCheckoutUrlExtra
1619
import com.afterpay.android.internal.putCheckoutV2OptionsExtra
@@ -46,11 +49,23 @@ object Afterpay {
4649
private set
4750

4851
internal val locale: Locale
49-
get() = configuration?.locale ?: Locales.US
52+
get() = configuration?.locale ?: Locales.EN_US
5053

5154
internal val brand: Brand
5255
get() = Brand.forLocale(locale)
5356

57+
internal val language: Locale?
58+
get() = getRegionLanguage(locale, Locale.getDefault())
59+
60+
internal val enabled: Boolean
61+
get() = language != null
62+
63+
internal val strings: AfterpayString
64+
get() = AfterpayString.forLocale()
65+
66+
internal val drawables: AfterpayDrawable
67+
get() = AfterpayDrawable.forLocale()
68+
5469
internal var checkoutV2Handler: AfterpayCheckoutV2Handler? = null
5570
private set
5671

@@ -60,9 +75,11 @@ object Afterpay {
6075
* Afterpay checkout.
6176
*/
6277
@JvmStatic
63-
fun createCheckoutIntent(context: Context, checkoutUrl: String): Intent =
64-
Intent(context, AfterpayCheckoutActivity::class.java)
65-
.putCheckoutUrlExtra(checkoutUrl)
78+
fun createCheckoutIntent(context: Context, checkoutUrl: String): Intent {
79+
val url = if (enabled) { checkoutUrl } else { "LANGUAGE_NOT_SUPPORTED" }
80+
return Intent(context, AfterpayCheckoutActivity::class.java)
81+
.putCheckoutUrlExtra(url)
82+
}
6683

6784
/**
6885
* Returns an [Intent] for the given [context] and [options] that can be passed to

Diff for: afterpay/src/main/kotlin/com/afterpay/android/CancellationStatus.kt

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ enum class CancellationStatus {
55
NO_CHECKOUT_URL,
66
INVALID_CHECKOUT_URL,
77
NO_CHECKOUT_HANDLER,
8-
NO_CONFIGURATION
8+
NO_CONFIGURATION,
9+
LANGUAGE_NOT_SUPPORTED,
910
}
1011

1112
enum class CancellationStatusV3 {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package com.afterpay.android.internal
2+
3+
import androidx.annotation.DrawableRes
4+
import com.afterpay.android.Afterpay
5+
import com.afterpay.android.R
6+
import com.afterpay.android.internal.Locales.EN_AU
7+
import com.afterpay.android.internal.Locales.EN_CA
8+
import com.afterpay.android.internal.Locales.EN_GB
9+
import com.afterpay.android.internal.Locales.EN_NZ
10+
import com.afterpay.android.internal.Locales.EN_US
11+
import com.afterpay.android.internal.Locales.ES_ES
12+
import com.afterpay.android.internal.Locales.FR_CA
13+
import com.afterpay.android.internal.Locales.FR_FR
14+
import com.afterpay.android.internal.Locales.IT_IT
15+
16+
private val localeLanguages = mapOf(
17+
EN_AU to AfterpayDrawable.EN_AFTERPAY,
18+
EN_GB to AfterpayDrawable.EN_CLEARPAY,
19+
EN_NZ to AfterpayDrawable.EN_AFTERPAY,
20+
EN_US to AfterpayDrawable.EN_AFTERPAY,
21+
EN_CA to AfterpayDrawable.EN_AFTERPAY,
22+
FR_CA to AfterpayDrawable.FR_CA,
23+
FR_FR to AfterpayDrawable.FR,
24+
IT_IT to AfterpayDrawable.IT,
25+
ES_ES to AfterpayDrawable.ES,
26+
)
27+
28+
internal enum class AfterpayDrawable(
29+
@DrawableRes val buttonBuyNowForeground: Int,
30+
@DrawableRes val buttonCheckoutForeground: Int,
31+
@DrawableRes val buttonPayNowForeground: Int,
32+
@DrawableRes val buttonPlaceOrderForeground: Int,
33+
) {
34+
EN_AFTERPAY(
35+
buttonBuyNowForeground = R.drawable.afterpay_button_buy_now_fg_en,
36+
buttonCheckoutForeground = R.drawable.afterpay_button_checkout_fg_en,
37+
buttonPayNowForeground = R.drawable.afterpay_button_pay_now_fg_en,
38+
buttonPlaceOrderForeground = R.drawable.afterpay_button_place_order_fg_en,
39+
),
40+
EN_CLEARPAY(
41+
buttonBuyNowForeground = R.drawable.clearpay_button_buy_now_fg_en,
42+
buttonCheckoutForeground = R.drawable.clearpay_button_checkout_fg_en,
43+
buttonPayNowForeground = R.drawable.clearpay_button_pay_now_fg_en,
44+
buttonPlaceOrderForeground = R.drawable.clearpay_button_place_order_fg_en,
45+
),
46+
FR_CA(
47+
buttonBuyNowForeground = R.drawable.afterpay_button_buy_now_fg_fr_ca,
48+
buttonCheckoutForeground = R.drawable.afterpay_button_checkout_fg_fr_ca,
49+
buttonPayNowForeground = R.drawable.afterpay_button_pay_now_fg_fr_ca,
50+
buttonPlaceOrderForeground = R.drawable.afterpay_button_place_order_fg_fr_ca,
51+
),
52+
FR(
53+
buttonBuyNowForeground = R.drawable.clearpay_button_buy_now_fg_fr,
54+
buttonCheckoutForeground = R.drawable.clearpay_button_checkout_fg_fr,
55+
buttonPayNowForeground = R.drawable.clearpay_button_pay_now_fg_fr,
56+
buttonPlaceOrderForeground = R.drawable.clearpay_button_place_order_fg_fr,
57+
),
58+
IT(
59+
buttonBuyNowForeground = R.drawable.clearpay_button_buy_now_fg_it,
60+
buttonCheckoutForeground = R.drawable.clearpay_button_checkout_fg_it,
61+
buttonPayNowForeground = R.drawable.clearpay_button_pay_now_fg_it,
62+
buttonPlaceOrderForeground = R.drawable.clearpay_button_place_order_fg_it,
63+
),
64+
ES(
65+
buttonBuyNowForeground = R.drawable.clearpay_button_buy_now_fg_es,
66+
buttonCheckoutForeground = R.drawable.clearpay_button_checkout_fg_es,
67+
buttonPayNowForeground = R.drawable.clearpay_button_pay_now_fg_es,
68+
buttonPlaceOrderForeground = R.drawable.clearpay_button_place_order_fg_es,
69+
);
70+
71+
companion object {
72+
fun forLocale(): AfterpayDrawable {
73+
return localeLanguages[Afterpay.language] ?: EN_AFTERPAY
74+
}
75+
}
76+
}

Diff for: afterpay/src/main/kotlin/com/afterpay/android/internal/AfterpayInstalment.kt

+45-12
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import java.math.RoundingMode
66
import java.text.DecimalFormat
77
import java.text.NumberFormat
88
import java.util.Currency
9+
import java.util.Locale
910

1011
internal sealed class AfterpayInstalment {
1112
data class Available(
@@ -20,34 +21,59 @@ internal sealed class AfterpayInstalment {
2021
object NoConfiguration : AfterpayInstalment()
2122

2223
companion object {
23-
fun of(totalCost: BigDecimal, configuration: Configuration?): AfterpayInstalment {
24+
fun of(totalCost: BigDecimal, configuration: Configuration?, clientLocale: Locale): AfterpayInstalment {
2425
if (configuration == null) {
2526
return NoConfiguration
2627
}
2728

28-
val currencyLocale = Locales.validSet.first { Currency.getInstance(it) == configuration.currency }
29+
val currencyLocales = Locales.validSet.filterTo(HashSet()) {
30+
Currency.getInstance(it) == configuration.currency
31+
}
32+
33+
val currencyLocale: Locale = when {
34+
currencyLocales.count() == 1 -> currencyLocales.first()
35+
currencyLocales.contains(configuration.locale) -> configuration.locale
36+
else -> Locales.validSet.first { Currency.getInstance(it) == configuration.currency }
37+
}
38+
39+
val localCurrency = Currency.getInstance(clientLocale)
2940
val currencySymbol = configuration.currency.getSymbol(currencyLocale)
30-
val usCurrencySymbol = Currency.getInstance(Locales.US).getSymbol(Locales.US)
31-
val localCurrency = Currency.getInstance(configuration.locale)
3241

33-
val currencyFormatter = (NumberFormat.getCurrencyInstance(currencyLocale) as DecimalFormat).apply {
42+
val usCurrencySymbol = Currency.getInstance(Locales.EN_US).getSymbol(Locales.EN_US)
43+
val gbCurrencySymbol = Currency.getInstance(Locales.EN_GB).getSymbol(Locales.EN_GB)
44+
val euCurrencySymbol = Currency.getInstance(Locales.FR_FR).getSymbol(Locales.FR_FR)
45+
46+
val currencyFormatter = (NumberFormat.getCurrencyInstance(clientLocale) as DecimalFormat).apply {
3447
this.currency = configuration.currency
3548
}
3649

37-
if (configuration.locale == Locales.US) {
50+
if (clientLocale == Locales.EN_US) {
3851
currencyFormatter.apply {
52+
when (currencySymbol) {
53+
euCurrencySymbol -> this.applyPattern("#,##0.00¤")
54+
}
55+
3956
decimalFormatSymbols = decimalFormatSymbols.apply {
4057
this.currencySymbol = when (configuration.currency) {
41-
Currency.getInstance(Locales.AUSTRALIA) -> "A$"
42-
Currency.getInstance(Locales.NEW_ZEALAND) -> "NZ$"
43-
Currency.getInstance(Locales.CANADA) -> "CA$"
58+
Currency.getInstance(Locales.EN_AU) -> "A$"
59+
Currency.getInstance(Locales.EN_NZ) -> "NZ$"
60+
Currency.getInstance(Locales.EN_CA) -> "CA$"
61+
Currency.getInstance(Locales.FR_CA) -> "CA$"
4462
else -> currencySymbol
4563
}
4664
}
4765
}
48-
} else if (currencySymbol == usCurrencySymbol && configuration.currency != localCurrency) {
66+
} else if (configuration.currency != localCurrency) {
4967
currencyFormatter.apply {
50-
this.applyPattern("¤#,##0.00 ¤¤")
68+
decimalFormatSymbols = decimalFormatSymbols.apply {
69+
this.currencySymbol = currencySymbol
70+
}
71+
72+
when (currencySymbol) {
73+
usCurrencySymbol -> this.applyPattern("¤#,##0.00 ¤¤")
74+
gbCurrencySymbol -> this.applyPattern("¤#,##0.00")
75+
euCurrencySymbol -> this.applyPattern("#,##0.00¤")
76+
}
5177
}
5278
}
5379

@@ -59,9 +85,16 @@ internal sealed class AfterpayInstalment {
5985
)
6086
}
6187

62-
val numberOfInstalments = 4.toBigDecimal()
88+
val numberOfInstalments = numberOfInstalments(configuration.currency).toBigDecimal()
6389
val instalment = totalCost.divide(numberOfInstalments, 2, RoundingMode.HALF_EVEN)
6490
return Available(instalmentAmount = currencyFormatter.format(instalment))
6591
}
92+
93+
fun numberOfInstalments(currency: Currency): Int {
94+
return when (currency.currencyCode) {
95+
"EUR" -> 3
96+
else -> 4
97+
}
98+
}
6699
}
67100
}

0 commit comments

Comments
 (0)