-
Notifications
You must be signed in to change notification settings - Fork 263
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
WIP: Google pay android implementation (#441)
* chore: google pay new approach implementation * chore: clean up * chore: google pay customization * chore: add documentation, fix linter * fix: appium tests * chore: increate JVM memory size * chore: improvements, refactor * chore: bump android-emulator api level to 30 * chore: bump api level * Update e2e-tests.yml * fix: tests * chore: bump node version * chore: bump node version * chore: bump node version * chore: bump chrome driver * chore: appium conf * chore: appium conf * chore: appium conf * chore: downgrade api-level * chore: use google apis * chore: change arch * chore: update chrome driver version * chore: e2e config attempt * chore: e2e config attempt * chore: e2e conf attempt * chore: accept terms and conditions * chore: accept terms and conditions * chore: accept terms and conditions * chore: accept terms and conditions * fix: init on mount only * fix: init issue * chore: handle exception * chore: add google pay button * chore: handle dark mode * chore: clean up * chore: tests clean up * chore: clean up * chore: clean up Co-authored-by: Arkadiusz Kubaczkowski <arek.kubaczkowski@callstak.com>
- Loading branch information
1 parent
9646d1f
commit 961d6d1
Showing
156 changed files
with
4,621 additions
and
2,324 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
chromedriver_version=74.0.3729.6 | ||
chromedriver_version=2.44 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
30 changes: 30 additions & 0 deletions
30
android/src/main/java/com/reactnativestripesdk/GooglePayButtonManager.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package com.reactnativestripesdk | ||
|
||
import com.facebook.react.uimanager.SimpleViewManager | ||
import com.facebook.react.uimanager.ThemedReactContext | ||
import com.facebook.react.uimanager.annotations.ReactProp | ||
|
||
class GooglePayButtonManager : SimpleViewManager<GooglePayButtonView?>() { | ||
override fun getName(): String { | ||
return REACT_CLASS | ||
} | ||
|
||
override fun onAfterUpdateTransaction(view: GooglePayButtonView) { | ||
super.onAfterUpdateTransaction(view) | ||
|
||
view.initialize() | ||
} | ||
|
||
@ReactProp(name = "buttonType") | ||
fun buttonType(view: GooglePayButtonView, buttonType: String) { | ||
view.setType(buttonType) | ||
} | ||
|
||
override fun createViewInstance(reactContext: ThemedReactContext): GooglePayButtonView { | ||
return GooglePayButtonView(reactContext) | ||
} | ||
|
||
companion object { | ||
const val REACT_CLASS = "GooglePayButton" | ||
} | ||
} |
28 changes: 28 additions & 0 deletions
28
android/src/main/java/com/reactnativestripesdk/GooglePayButtonView.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package com.reactnativestripesdk | ||
|
||
import android.view.LayoutInflater | ||
import android.widget.FrameLayout | ||
import com.facebook.react.uimanager.ThemedReactContext | ||
|
||
class GooglePayButtonView(private val context: ThemedReactContext) : FrameLayout(context) { | ||
var buttonType: String? = null | ||
|
||
fun initialize() { | ||
val type = when (buttonType) { | ||
"pay" -> R.layout.pay_with_googlepay_button_no_shadow | ||
"pay_shadow" -> R.layout.pay_with_googlepay_button | ||
"standard_shadow" -> R.layout.googlepay_button | ||
"standard" -> R.layout.googlepay_button_no_shadow | ||
else -> R.layout.googlepay_button | ||
} | ||
val button = LayoutInflater.from(context).inflate( | ||
type, null | ||
) | ||
|
||
addView(button) | ||
} | ||
|
||
fun setType(type: String) { | ||
buttonType = type | ||
} | ||
} |
173 changes: 173 additions & 0 deletions
173
android/src/main/java/com/reactnativestripesdk/GooglePayFragment.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,173 @@ | ||
package com.reactnativestripesdk | ||
|
||
import android.content.Intent | ||
import android.os.Bundle | ||
import android.view.LayoutInflater | ||
import android.view.View | ||
import android.view.ViewGroup | ||
import android.widget.FrameLayout | ||
import androidx.fragment.app.Fragment | ||
import com.facebook.react.bridge.WritableNativeMap | ||
import com.stripe.android.googlepaylauncher.GooglePayEnvironment | ||
import com.stripe.android.googlepaylauncher.GooglePayLauncher | ||
import com.stripe.android.googlepaylauncher.GooglePayPaymentMethodLauncher | ||
import com.stripe.android.model.StripeIntent | ||
|
||
class GooglePayFragment : Fragment() { | ||
private var googlePayLauncher: GooglePayLauncher? = null | ||
private var googlePayMethodLauncher: GooglePayPaymentMethodLauncher? = null | ||
|
||
override fun onCreateView( | ||
inflater: LayoutInflater, | ||
container: ViewGroup?, | ||
savedInstanceState: Bundle? | ||
): View { | ||
return FrameLayout(requireActivity()).also { | ||
it.visibility = View.GONE | ||
} | ||
} | ||
|
||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { | ||
super.onViewCreated(view, savedInstanceState) | ||
val testEnv = arguments?.getBoolean("testEnv") | ||
val merchantName = arguments?.getString("merchantName").orEmpty() | ||
val countryCode = arguments?.getString("countryCode").orEmpty() | ||
val isEmailRequired = arguments?.getBoolean("isEmailRequired") ?: false | ||
val existingPaymentMethodRequired = arguments?.getBoolean("existingPaymentMethodRequired") ?: false | ||
|
||
val billingAddressConfigBundle = arguments?.getBundle("billingAddressConfig") ?: Bundle() | ||
val isRequired = billingAddressConfigBundle.getBoolean("isRequired") | ||
val formatString = billingAddressConfigBundle.getString("format").orEmpty() | ||
val isPhoneNumberRequired = billingAddressConfigBundle.getBoolean("isPhoneNumberRequired") | ||
|
||
val billingAddressConfig = mapToGooglePayPaymentMethodLauncherBillingAddressConfig(formatString, isRequired, isPhoneNumberRequired) | ||
|
||
googlePayMethodLauncher = GooglePayPaymentMethodLauncher( | ||
fragment = this, | ||
config = GooglePayPaymentMethodLauncher.Config( | ||
environment = if (testEnv == true) GooglePayEnvironment.Test else GooglePayEnvironment.Production, | ||
merchantCountryCode = countryCode, | ||
merchantName = merchantName, | ||
billingAddressConfig = billingAddressConfig, | ||
isEmailRequired = isEmailRequired, | ||
existingPaymentMethodRequired = existingPaymentMethodRequired | ||
), | ||
readyCallback = ::onGooglePayReady, | ||
resultCallback = ::onGooglePayResult | ||
) | ||
|
||
val paymentMethodBillingAddressConfig = mapToGooglePayLauncherBillingAddressConfig(formatString, isRequired, isPhoneNumberRequired) | ||
googlePayLauncher = GooglePayLauncher( | ||
fragment = this, | ||
config = GooglePayLauncher.Config( | ||
environment = if (testEnv == true) GooglePayEnvironment.Test else GooglePayEnvironment.Production, | ||
merchantCountryCode = countryCode, | ||
merchantName = merchantName, | ||
billingAddressConfig = paymentMethodBillingAddressConfig, | ||
isEmailRequired = isEmailRequired, | ||
existingPaymentMethodRequired = existingPaymentMethodRequired | ||
), | ||
readyCallback = ::onGooglePayReady, | ||
resultCallback = ::onGooglePayResult | ||
) | ||
|
||
val intent = Intent(ON_GOOGLE_PAY_FRAGMENT_CREATED) | ||
activity?.sendBroadcast(intent) | ||
} | ||
|
||
fun presentForPaymentIntent(clientSecret: String) { | ||
val launcher = googlePayLauncher ?: run { | ||
val intent = Intent(ON_GOOGLE_PAY_RESULT) | ||
intent.putExtra("error", "GooglePayLauncher is not initialized.") | ||
activity?.sendBroadcast(intent) | ||
return | ||
} | ||
runCatching { | ||
launcher.presentForPaymentIntent(clientSecret) | ||
}.onFailure { | ||
val intent = Intent(ON_GOOGLE_PAY_RESULT) | ||
intent.putExtra("error", it.localizedMessage) | ||
activity?.sendBroadcast(intent) | ||
} | ||
} | ||
|
||
fun presentForSetupIntent(clientSecret: String, currencyCode: String) { | ||
val launcher = googlePayLauncher ?: run { | ||
val intent = Intent(ON_GOOGLE_PAY_RESULT) | ||
intent.putExtra("error", "GooglePayLauncher is not initialized.") | ||
activity?.sendBroadcast(intent) | ||
return | ||
} | ||
runCatching { | ||
launcher.presentForSetupIntent(clientSecret, currencyCode) | ||
}.onFailure { | ||
val intent = Intent(ON_GOOGLE_PAY_RESULT) | ||
intent.putExtra("error", it.localizedMessage) | ||
activity?.sendBroadcast(intent) | ||
} | ||
} | ||
|
||
fun createPaymentMethod(currencyCode: String, amount: Int) { | ||
val launcher = googlePayMethodLauncher ?: run { | ||
val intent = Intent(ON_GOOGLE_PAYMENT_METHOD_RESULT) | ||
intent.putExtra("error", "GooglePayPaymentMethodLauncher is not initialized.") | ||
activity?.sendBroadcast(intent) | ||
return | ||
} | ||
|
||
runCatching { | ||
launcher.present( | ||
currencyCode = currencyCode, | ||
amount = amount | ||
) | ||
}.onFailure { | ||
val intent = Intent(ON_GOOGLE_PAYMENT_METHOD_RESULT) | ||
intent.putExtra("error", it.localizedMessage) | ||
activity?.sendBroadcast(intent) | ||
} | ||
} | ||
|
||
private fun onGooglePayReady(isReady: Boolean) { | ||
val intent = Intent(ON_INIT_GOOGLE_PAY) | ||
intent.putExtra("isReady", isReady) | ||
activity?.sendBroadcast(intent) | ||
} | ||
|
||
private fun onGooglePayResult(result: GooglePayLauncher.Result) { | ||
val intent = Intent(ON_GOOGLE_PAY_RESULT) | ||
intent.putExtra("paymentResult", result) | ||
activity?.sendBroadcast(intent) | ||
} | ||
|
||
private fun onGooglePayResult(result: GooglePayPaymentMethodLauncher.Result) { | ||
val intent = Intent(ON_GOOGLE_PAYMENT_METHOD_RESULT) | ||
intent.putExtra("paymentResult", result) | ||
activity?.sendBroadcast(intent) | ||
} | ||
|
||
private fun mapToGooglePayLauncherBillingAddressConfig(formatString: String, isRequired: Boolean, isPhoneNumberRequired: Boolean): GooglePayLauncher.BillingAddressConfig { | ||
val format = when (formatString) { | ||
"FULL" -> GooglePayLauncher.BillingAddressConfig.Format.Full | ||
"MIN" -> GooglePayLauncher.BillingAddressConfig.Format.Min | ||
else -> GooglePayLauncher.BillingAddressConfig.Format.Min | ||
} | ||
return GooglePayLauncher.BillingAddressConfig( | ||
isRequired = isRequired, | ||
format = format, | ||
isPhoneNumberRequired = isPhoneNumberRequired | ||
) | ||
} | ||
|
||
private fun mapToGooglePayPaymentMethodLauncherBillingAddressConfig(formatString: String, isRequired: Boolean, isPhoneNumberRequired: Boolean): GooglePayPaymentMethodLauncher.BillingAddressConfig { | ||
val format = when (formatString) { | ||
"FULL" -> GooglePayPaymentMethodLauncher.BillingAddressConfig.Format.Full | ||
"MIN" -> GooglePayPaymentMethodLauncher.BillingAddressConfig.Format.Min | ||
else -> GooglePayPaymentMethodLauncher.BillingAddressConfig.Format.Min | ||
} | ||
return GooglePayPaymentMethodLauncher.BillingAddressConfig( | ||
isRequired = isRequired, | ||
format = format, | ||
isPhoneNumberRequired = isPhoneNumberRequired | ||
) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.