From ca9404fc3944705ec7fa629efb3ebeb69c3d83c1 Mon Sep 17 00:00:00 2001 From: PaysafeAutoCommitter Date: Mon, 2 Sep 2024 13:35:12 +0000 Subject: [PATCH] 0.0.43 --- .../FragmentSelectPaymentMethod.kt | 6 +-- .../java/com/paysafe/example/util/Consts.kt | 12 +++--- .../currencyConverter/CurrencyConverter.kt | 37 +++++++++++++++++++ .../android/currencyConverter/PSCurrency.kt | 26 +++++++++++++ .../android/venmo/PSVenmoController.kt | 16 ++++++-- .../android/venmo/PSVenmoNativeController.kt | 16 ++++++-- .../android/venmo/activity/VenmoConstants.kt | 2 + .../venmo/activity/VenmoServiceConstants.kt | 8 ++++ .../activity/VenmoWebCheckoutActivity.kt | 33 +++++++++++++---- .../android/venmo/PSVenmoControllerTest.kt | 16 ++++++++ .../venmo/PSVenmoNativeControllerTest.kt | 2 + .../venmo/activity/VenmoConstantsTest.kt | 5 +++ .../activity/VenmoWebCheckoutActivityTest.kt | 9 ++++- version.properties | 2 +- 14 files changed, 165 insertions(+), 25 deletions(-) create mode 100644 paysafe-core/src/main/java/com/paysafe/android/currencyConverter/CurrencyConverter.kt create mode 100644 paysafe-core/src/main/java/com/paysafe/android/currencyConverter/PSCurrency.kt diff --git a/example/src/main/java/com/paysafe/example/select_payment_method/FragmentSelectPaymentMethod.kt b/example/src/main/java/com/paysafe/example/select_payment_method/FragmentSelectPaymentMethod.kt index 5c0b426..7064665 100644 --- a/example/src/main/java/com/paysafe/example/select_payment_method/FragmentSelectPaymentMethod.kt +++ b/example/src/main/java/com/paysafe/example/select_payment_method/FragmentSelectPaymentMethod.kt @@ -289,9 +289,9 @@ class FragmentSelectPaymentMethod : Fragment() { shippingDetails = provideShippingDetails(), customUrlScheme = "customScheme", venmoRequest = VenmoRequest( - consumerId = "ala-bala-portocalaaaa", - merchantAccountId = "", - profileId = "" + consumerId = "consumerrr@mail.com", + merchantAccountId = "merch-acc-id", + profileId = "profile-di" ) ) diff --git a/example/src/main/java/com/paysafe/example/util/Consts.kt b/example/src/main/java/com/paysafe/example/util/Consts.kt index 03365c5..e090af8 100644 --- a/example/src/main/java/com/paysafe/example/util/Consts.kt +++ b/example/src/main/java/com/paysafe/example/util/Consts.kt @@ -7,12 +7,12 @@ package com.paysafe.example.util import com.paysafe.android.core.domain.model.config.PSEnvironment object Consts { - const val MERCHANT_BACKEND_API_KEY = "" - const val API_KEY = "" - const val CARDS_ACCOUNT_ID = "" - const val PAYPAL_ACCOUNT_ID = "" - const val VENMO_ACCOUNT_ID = "" - const val PROFILE_ID = "" + const val MERCHANT_BACKEND_API_KEY = "dGVzdF9ob3N0ZWQ6Qi1xYTItMC02MDRiM2RiNS0wLTMwMmMwMjE0N2FkYTNjYTQyMGI0N2Q4ZWI5ODEyMjYzZDQ5NGJhOTU3MTRlMTQ0ZDAyMTQwMzgyMWUzYTMzZWJmMmQwMDYyNjgyZWQwNDk1MGM3ZWJjMzE5ZmFm" + const val API_KEY = "T1QtOTE0MzAwOkItcWEyLTAtNjNjODRkYjktMS0zMDJjMDIxNDQ5NzM5NTI4YmIyMWM4NWFjZWRjZWJkMmI0ODI2MjIzZjEzODcxZWEwMjE0MmE0NjQxYTU4Zjk5OTFlZDlmMDRlMDY5OTRkNTViYzk2MTBiYmZkOQ==" + const val CARDS_ACCOUNT_ID = "1002603390" + const val PAYPAL_ACCOUNT_ID = "1002720380" + const val VENMO_ACCOUNT_ID = "1002723680" + const val PROFILE_ID = "284f1502-0cad-4256-b5e5-705ed06cfbbd" val environment: PSEnvironment = PSEnvironment.TEST } \ No newline at end of file diff --git a/paysafe-core/src/main/java/com/paysafe/android/currencyConverter/CurrencyConverter.kt b/paysafe-core/src/main/java/com/paysafe/android/currencyConverter/CurrencyConverter.kt new file mode 100644 index 0000000..8ec9d3f --- /dev/null +++ b/paysafe-core/src/main/java/com/paysafe/android/currencyConverter/CurrencyConverter.kt @@ -0,0 +1,37 @@ +package com.paysafe.android.currencyConverter + +import kotlin.math.pow + +final class CurrencyConverter( + private val multiplierMap: Map +) { + + // Method to convert minor amount based on the currency. + fun convert(amount: Int, forCurrency: String): Double { + val psCurrency = PSCurrency.values().find { it.name == forCurrency } + val power = psCurrency?.let { multiplierMap[it] } ?: 2 + if (psCurrency == null) { + println("Currency doesn't need conversion: $forCurrency") + } + return amount.toDouble() / 10.0.pow(power.toDouble()) + } + + companion object { + // Default multiplier map + fun defaultCurrenciesMap(): Map { + return mapOf( + PSCurrency.BHD to 3, + PSCurrency.BYR to 0, + PSCurrency.JPY to 0, + PSCurrency.JOD to 3, + PSCurrency.KRW to 0, + PSCurrency.KWD to 3, + PSCurrency.LYD to 3, + PSCurrency.OMR to 3, + PSCurrency.PYG to 0, + PSCurrency.TND to 3, + PSCurrency.VND to 0 + ) + } + } +} \ No newline at end of file diff --git a/paysafe-core/src/main/java/com/paysafe/android/currencyConverter/PSCurrency.kt b/paysafe-core/src/main/java/com/paysafe/android/currencyConverter/PSCurrency.kt new file mode 100644 index 0000000..e12c068 --- /dev/null +++ b/paysafe-core/src/main/java/com/paysafe/android/currencyConverter/PSCurrency.kt @@ -0,0 +1,26 @@ +package com.paysafe.android.currencyConverter + +enum class PSCurrency(val value: String) { + // Bahraini Dinar + BHD("BHD"), + // Belarusian Ruble (Note: The BYR was replaced by BYN in 2016) + BYR("BYR"), + // Japanese Yen + JPY("JPY"), + // Jordanian Dinar + JOD("JOD"), + // South Korean Won + KRW("KRW"), + // Kuwaiti Dinar + KWD("KWD"), + // Libyan Dinar + LYD("LYD"), + // Omani Rial + OMR("OMR"), + // Paraguayan Guaraní + PYG("PYG"), + // Tunisian Dinar + TND("TND"), + // Vietnamese Đồng + VND("VND") +} \ No newline at end of file diff --git a/venmo/src/main/java/com/paysafe/android/venmo/PSVenmoController.kt b/venmo/src/main/java/com/paysafe/android/venmo/PSVenmoController.kt index 68ef678..f2f6137 100644 --- a/venmo/src/main/java/com/paysafe/android/venmo/PSVenmoController.kt +++ b/venmo/src/main/java/com/paysafe/android/venmo/PSVenmoController.kt @@ -306,17 +306,26 @@ internal abstract class PSVenmoController internal constructor( } lifecycleScope.launch(mainDispatcher) { when (result) { - is PSResult.Success -> handleTokenizeResultSuccess(context, venmoTokenizeOptions.customUrlScheme,result) + is PSResult.Success -> + handleTokenizeResultSuccess( + context, + venmoTokenizeOptions.venmoRequest?.profileId, + venmoTokenizeOptions.amount, + venmoTokenizeOptions.customUrlScheme, + result + ) is PSResult.Failure -> handleTokenizeResultFailure(result) } } } //Checkout process implementation needed - abstract fun startVenmoCheckout(context: Context, orderId: String, sessionToken: String, clientToken: String, customUrlScheme: String?) + abstract fun startVenmoCheckout(context: Context, orderId: String, sessionToken: String, clientToken: String, profileId: String?, amount: Int, customUrlScheme: String?) internal fun handleTokenizeResultSuccess( context: Context, + profileId: String?, + amount: Int, customUrlScheme:String?, result: PSResult.Success ) { @@ -367,9 +376,10 @@ internal abstract class PSVenmoController internal constructor( tokenizeCallback?.onFailure(paysafeException) return } + // Checkout process implementation needed tokenizationAlreadyInProgress = false - startVenmoCheckout(context, orderId, sessionToken, clientToken, customUrlScheme) + startVenmoCheckout(context, orderId, sessionToken, clientToken, profileId, amount, customUrlScheme) } internal fun handleTokenizeResultFailure(result: PSResult.Failure) { diff --git a/venmo/src/main/java/com/paysafe/android/venmo/PSVenmoNativeController.kt b/venmo/src/main/java/com/paysafe/android/venmo/PSVenmoNativeController.kt index 2a413fe..00fc800 100644 --- a/venmo/src/main/java/com/paysafe/android/venmo/PSVenmoNativeController.kt +++ b/venmo/src/main/java/com/paysafe/android/venmo/PSVenmoNativeController.kt @@ -11,6 +11,7 @@ import com.paysafe.android.brainTreeDetails.domain.models.DeviceData import com.paysafe.android.brainTreeDetails.domain.models.PayerInfo import com.paysafe.android.core.data.service.PSApiClient import com.paysafe.android.core.util.LocalLog +import com.paysafe.android.currencyConverter.CurrencyConverter import com.paysafe.android.tokenization.PSTokenization import com.paysafe.android.tokenization.PSTokenizationService import com.paysafe.android.venmo.activity.VenmoConstants @@ -59,14 +60,23 @@ internal class PSVenmoNativeController internal constructor( orderId: String, sessionToken: String, clientToken: String, + profileId: String?, + amount: Int, customUrlScheme: String? ) { LocalLog.d("PSVenmoNativeController", "startVenmoCheckout") jwtToken = sessionToken + + val currencyConverter = CurrencyConverter(CurrencyConverter.defaultCurrenciesMap()) + val amountString = + currencyConverter.convert(amount = amount, forCurrency = "USD").toString() + val intent = Intent(context, VenmoWebCheckoutActivity::class.java).apply { - putExtra("SESSION_TOKEN", sessionToken) - putExtra("CLIENT_TOKEN", clientToken) - putExtra("CUSTOM_URL_SCHEME", customUrlScheme) + putExtra(VenmoConstants.INTENT_EXTRA_SESSION_TOKEN, sessionToken) + putExtra(VenmoConstants.INTENT_EXTRA_CLIENT_TOKEN, clientToken) + putExtra(VenmoConstants.INTENT_EXTRA_PROFILE_ID, profileId) + putExtra(VenmoConstants.INTENT_EXTRA_AMOUNT, amountString) + putExtra(VenmoConstants.INTENT_EXTRA_CUSTOM_URL_SCHEME, customUrlScheme) } activityResultLauncher.launch(intent) } diff --git a/venmo/src/main/java/com/paysafe/android/venmo/activity/VenmoConstants.kt b/venmo/src/main/java/com/paysafe/android/venmo/activity/VenmoConstants.kt index d4b8fcd..71bcce8 100644 --- a/venmo/src/main/java/com/paysafe/android/venmo/activity/VenmoConstants.kt +++ b/venmo/src/main/java/com/paysafe/android/venmo/activity/VenmoConstants.kt @@ -3,7 +3,9 @@ package com.paysafe.android.venmo.activity object VenmoConstants { const val INTENT_EXTRA_SESSION_TOKEN = "SESSION_TOKEN" const val INTENT_EXTRA_CLIENT_TOKEN = "CLIENT_TOKEN" + const val INTENT_EXTRA_PROFILE_ID = "PROFILE_ID" const val INTENT_EXTRA_CUSTOM_URL_SCHEME = "CUSTOM_URL_SCHEME" + const val INTENT_EXTRA_AMOUNT = "AMOUNT" const val RESULT_SUCCESS = 1_000 const val RESULT_FAILED = 1_001 const val RESULT_VENMO_APP_IS_NOT_INSTALLED = 1_002 diff --git a/venmo/src/main/java/com/paysafe/android/venmo/activity/VenmoServiceConstants.kt b/venmo/src/main/java/com/paysafe/android/venmo/activity/VenmoServiceConstants.kt index 827f57f..795ec01 100644 --- a/venmo/src/main/java/com/paysafe/android/venmo/activity/VenmoServiceConstants.kt +++ b/venmo/src/main/java/com/paysafe/android/venmo/activity/VenmoServiceConstants.kt @@ -13,6 +13,14 @@ class VenmoServiceConstants { return VenmoConstants.INTENT_EXTRA_CUSTOM_URL_SCHEME } + fun getIntentExtraProfileId(): String { + return VenmoConstants.INTENT_EXTRA_PROFILE_ID + } + + fun getIntentExtraAmount(): String { + return VenmoConstants.INTENT_EXTRA_AMOUNT + } + fun getResultSuccess(): Any { return VenmoConstants.RESULT_SUCCESS } diff --git a/venmo/src/main/java/com/paysafe/android/venmo/activity/VenmoWebCheckoutActivity.kt b/venmo/src/main/java/com/paysafe/android/venmo/activity/VenmoWebCheckoutActivity.kt index d0189c3..42ee204 100644 --- a/venmo/src/main/java/com/paysafe/android/venmo/activity/VenmoWebCheckoutActivity.kt +++ b/venmo/src/main/java/com/paysafe/android/venmo/activity/VenmoWebCheckoutActivity.kt @@ -22,6 +22,8 @@ internal class VenmoWebCheckoutActivity : AppCompatActivity(), VenmoListener { lateinit var braintreeClient: BraintreeClient lateinit var sessionToken: String lateinit var clientToken: String + lateinit var displayAmount: String + var profileId: String? = null lateinit var customUrlScheme: String private val observer = object : DefaultLifecycleObserver { @@ -43,9 +45,14 @@ internal class VenmoWebCheckoutActivity : AppCompatActivity(), VenmoListener { val sessionTokenIntent = intent?.getStringExtra(VenmoConstants.INTENT_EXTRA_SESSION_TOKEN) val clientTokenIntent = intent?.getStringExtra(VenmoConstants.INTENT_EXTRA_CLIENT_TOKEN) - val customUrlSchemeIntent = intent?.getStringExtra(VenmoConstants.INTENT_EXTRA_CUSTOM_URL_SCHEME) - - if (sessionTokenIntent == null || clientTokenIntent == null || customUrlSchemeIntent == null ) { + val customUrlSchemeIntent = + intent?.getStringExtra(VenmoConstants.INTENT_EXTRA_CUSTOM_URL_SCHEME) + val profileIdIntent = intent?.getStringExtra(VenmoConstants.INTENT_EXTRA_PROFILE_ID) + val displayAmountIntent = intent?.getStringExtra(VenmoConstants.INTENT_EXTRA_AMOUNT) + + if (sessionTokenIntent == null || clientTokenIntent == null || + customUrlSchemeIntent == null || displayAmountIntent == null + ) { finishActivityWithResult(VenmoConstants.RESULT_FAILED, null) return } @@ -53,6 +60,8 @@ internal class VenmoWebCheckoutActivity : AppCompatActivity(), VenmoListener { sessionToken = sessionTokenIntent clientToken = clientTokenIntent customUrlScheme = customUrlSchemeIntent + profileId = profileIdIntent + displayAmount = displayAmountIntent lifecycle.addObserver(observer) } @@ -65,9 +74,13 @@ internal class VenmoWebCheckoutActivity : AppCompatActivity(), VenmoListener { removeLifecycleObserver() } - fun launchVenmo() { + fun launchVenmo() { braintreeClient = - BraintreeClient(context = this, authorization = clientToken, returnUrlScheme = customUrlScheme) + BraintreeClient( + context = this, + authorization = clientToken, + returnUrlScheme = customUrlScheme + ) venmoClient = VenmoClient(this, braintreeClient) venmoClient.setListener(this) @@ -75,15 +88,16 @@ internal class VenmoWebCheckoutActivity : AppCompatActivity(), VenmoListener { request.collectCustomerBillingAddress = true request.collectCustomerShippingAddress = true - request.profileId = sessionToken + request.profileId = profileId request.shouldVault = false + request.totalAmount = displayAmount if (venmoClient.isVenmoAppSwitchAvailable(this)) { venmoClient.tokenizeVenmoAccount(this, request) } else if (!isAppInstalled(this)) { finishActivityWithResult(VenmoConstants.RESULT_VENMO_APP_IS_NOT_INSTALLED, null) venmoClient.showVenmoInGooglePlayStore(this) - } else{ + } else { venmoClient.tokenizeVenmoAccount(this, request) } } @@ -136,7 +150,10 @@ internal class VenmoWebCheckoutActivity : AppCompatActivity(), VenmoListener { fun isAppInstalled(context: Context): Boolean { val packageManager = context.packageManager return try { - packageManager.getPackageInfo(VenmoConstants.VENMO_PACKAGE, PackageManager.GET_ACTIVITIES) + packageManager.getPackageInfo( + VenmoConstants.VENMO_PACKAGE, + PackageManager.GET_ACTIVITIES + ) true } catch (e: PackageManager.NameNotFoundException) { false diff --git a/venmo/src/test/java/com/paysafe/android/venmo/PSVenmoControllerTest.kt b/venmo/src/test/java/com/paysafe/android/venmo/PSVenmoControllerTest.kt index 0f7d155..b8e081d 100644 --- a/venmo/src/test/java/com/paysafe/android/venmo/PSVenmoControllerTest.kt +++ b/venmo/src/test/java/com/paysafe/android/venmo/PSVenmoControllerTest.kt @@ -524,6 +524,8 @@ class PSVenmoControllerTest { // Act psVenmoController.handleTokenizeResultSuccess( context = mockActivity, + profileId = "profile-id", + amount = 1000, customUrlScheme = "", result = PSResult.Success(null) ) @@ -542,6 +544,8 @@ class PSVenmoControllerTest { // Act psVenmoController.handleTokenizeResultSuccess( context = mockActivity, + profileId = "profile-id", + amount = 1000, customUrlScheme = "", result = PSResult.Success( PaymentHandle( @@ -567,6 +571,8 @@ class PSVenmoControllerTest { // Act psVenmoController.handleTokenizeResultSuccess( context = mockActivity, + profileId = "profile-id", + amount = 1000, customUrlScheme = "", result = PSResult.Success( PaymentHandle( @@ -591,6 +597,8 @@ class PSVenmoControllerTest { // Act psVenmoController.handleTokenizeResultSuccess( context = mockActivity, + profileId = "profile-id", + amount = 1000, customUrlScheme = "", result = PSResult.Success( PaymentHandle( @@ -615,6 +623,8 @@ class PSVenmoControllerTest { // Act psVenmoController.handleTokenizeResultSuccess( context = mockActivity, + profileId = null, + amount = 1000, customUrlScheme = "", result = PSResult.Success( PaymentHandle( @@ -640,6 +650,8 @@ class PSVenmoControllerTest { // Act psVenmoController.handleTokenizeResultSuccess( context = mockActivity, + profileId = "profile-id", + amount = 1000, customUrlScheme = "", result = PSResult.Success( PaymentHandle( @@ -667,6 +679,8 @@ class PSVenmoControllerTest { // Act psVenmoController.handleTokenizeResultSuccess( context = mockActivity, + profileId = null, + amount = 1000, customUrlScheme = "", result = PSResult.Success( PaymentHandle( @@ -692,6 +706,8 @@ class PSVenmoControllerTest { // Act psVenmoController.handleTokenizeResultSuccess( context = mockActivity, + profileId = "profile-id", + amount = 1000, customUrlScheme = "", result = PSResult.Success( PaymentHandle( diff --git a/venmo/src/test/java/com/paysafe/android/venmo/PSVenmoNativeControllerTest.kt b/venmo/src/test/java/com/paysafe/android/venmo/PSVenmoNativeControllerTest.kt index a336b8d..e62f73d 100644 --- a/venmo/src/test/java/com/paysafe/android/venmo/PSVenmoNativeControllerTest.kt +++ b/venmo/src/test/java/com/paysafe/android/venmo/PSVenmoNativeControllerTest.kt @@ -105,6 +105,8 @@ class PSVenmoNativeControllerTest { orderId = orderId, sessionToken = sessionToken, clientToken = clientToken, + profileId = "profile-id", + amount = 1000, customUrlScheme = customUrlScheme ) diff --git a/venmo/src/test/java/com/paysafe/android/venmo/activity/VenmoConstantsTest.kt b/venmo/src/test/java/com/paysafe/android/venmo/activity/VenmoConstantsTest.kt index 616352f..5d376dd 100644 --- a/venmo/src/test/java/com/paysafe/android/venmo/activity/VenmoConstantsTest.kt +++ b/venmo/src/test/java/com/paysafe/android/venmo/activity/VenmoConstantsTest.kt @@ -23,6 +23,11 @@ class VenmoConstantsTest { Assert.assertEquals("CUSTOM_URL_SCHEME", venmoServiceConstants.getIntentExtraCustomUrlSchemeToken()) } + @Test + fun `test INTENT_EXTRA_PROFILE_ID constant value`() { + Assert.assertEquals("PROFILE_ID", venmoServiceConstants.getIntentExtraProfileId()) + } + @Test fun `test RESULT_SUCCESS constant value`() { Assert.assertEquals(1_000, venmoServiceConstants.getResultSuccess()) diff --git a/venmo/src/test/java/com/paysafe/android/venmo/activity/VenmoWebCheckoutActivityTest.kt b/venmo/src/test/java/com/paysafe/android/venmo/activity/VenmoWebCheckoutActivityTest.kt index 5ecc16e..e82e590 100644 --- a/venmo/src/test/java/com/paysafe/android/venmo/activity/VenmoWebCheckoutActivityTest.kt +++ b/venmo/src/test/java/com/paysafe/android/venmo/activity/VenmoWebCheckoutActivityTest.kt @@ -44,12 +44,16 @@ class VenmoWebCheckoutActivityTest { private val sessionToken = "SESSION_TOKEN_MOCK" private val clientToken = "CLIENT_TOKEN_MOCK" + private val profileId = "PROFILE_ID_MOCK" + private val amount = "AMOUNT" private val customUrlScheme = "CUSTOM_URL_SCHEME_MOCK" private lateinit var venmoAccountNonce: VenmoAccountNonce private val intent = Intent().apply { putExtra(VenmoConstants.INTENT_EXTRA_SESSION_TOKEN, sessionToken) putExtra(VenmoConstants.INTENT_EXTRA_CLIENT_TOKEN, clientToken) + putExtra(VenmoConstants.INTENT_EXTRA_PROFILE_ID, profileId) + putExtra(VenmoConstants.INTENT_EXTRA_AMOUNT, amount) putExtra(VenmoConstants.INTENT_EXTRA_CUSTOM_URL_SCHEME, customUrlScheme) } @@ -63,6 +67,8 @@ class VenmoWebCheckoutActivityTest { mockVenmoClient = mockk(relaxed = true) spyActivity = spyk(Robolectric.buildActivity(VenmoWebCheckoutActivity::class.java, intent).get()) { every { sessionToken } returns this@VenmoWebCheckoutActivityTest.sessionToken + every { clientToken } returns this@VenmoWebCheckoutActivityTest.clientToken + every { profileId } returns this@VenmoWebCheckoutActivityTest.profileId } venmoAccountNonce = mockk { every { string } returns "mockedString" @@ -158,6 +164,7 @@ class VenmoWebCheckoutActivityTest { // Verify Assert.assertEquals(sessionToken, spyActivity.sessionToken) Assert.assertEquals(clientToken, spyActivity.clientToken) + Assert.assertEquals(profileId, spyActivity.profileId) Assert.assertEquals(customUrlScheme, spyActivity.customUrlScheme) } @@ -271,7 +278,7 @@ class VenmoWebCheckoutActivityTest { Assert.assertNotNull(capturedRequest) Assert.assertTrue(capturedRequest.collectCustomerBillingAddress) Assert.assertTrue(capturedRequest.collectCustomerShippingAddress) - Assert.assertEquals(sessionToken, capturedRequest.profileId) + Assert.assertEquals(profileId, capturedRequest.profileId) Assert.assertFalse(capturedRequest.shouldVault) } } \ No newline at end of file diff --git a/version.properties b/version.properties index 76f1253..d4da33e 100644 --- a/version.properties +++ b/version.properties @@ -2,4 +2,4 @@ # Copyright (c) 2024 Paysafe Group # -VERSION=0.0.42 \ No newline at end of file +VERSION=0.0.43 \ No newline at end of file