Skip to content

Commit 9f58e15

Browse files
committed
feat: added googlepay support
1 parent fc58744 commit 9f58e15

17 files changed

Lines changed: 553 additions & 114 deletions

android/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,10 +77,10 @@ def kotlin_version = getExtOrDefault("kotlinVersion")
7777
dependencies {
7878
implementation "com.facebook.react:react-android"
7979
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
80-
implementation "com.google.android.gms:play-services-wallet:19.2.1"
80+
implementation "com.google.android.gms:play-services-wallet:19.4.0"
8181
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.9.2"
8282
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.9.2"
83-
implementation "androidx.activity:activity-ktx:1.6.1"
83+
implementation "androidx.activity:activity-ktx:1.10.1"
8484
implementation project(":react-native-inappbrowser-reborn")
8585
implementation project(":react-native-svg")
8686
implementation project(":sentry_react-native")

android/src/main/assets/hyperswitch.bundle

Lines changed: 57 additions & 56 deletions
Large diffs are not rendered by default.

android/src/main/java/com/hyperswitchsdkreactnative/HyperswitchSdkReactNativeModule.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.hyperswitchsdkreactnative
22

3+
import android.annotation.SuppressLint
34
import android.app.Activity
45
import android.os.Bundle
56
import android.util.Log
@@ -149,6 +150,7 @@ class HyperswitchSdkReactNativeModule(reactContext: ReactApplicationContext) :
149150
companion object {
150151
const val NAME = "HyperswitchSDKReactNative"
151152

153+
@SuppressLint("StaticFieldLeak")
152154
@JvmStatic
153155
lateinit var paymentSession: PaymentSession
154156

@@ -170,15 +172,15 @@ class HyperswitchSdkReactNativeModule(reactContext: ReactApplicationContext) :
170172
try {
171173
sheetPromise.resolve(result)
172174
} catch (e: Exception) {
173-
Log.e("HyperswitchSDK", "Error resolving payment sheet promise", e)
175+
Log.e("HyperSwitchSDK", "Error resolving payment sheet promise", e)
174176
}
175177
}
176178

177179
fun rejectPaymentSheet(code: String, message: String) {
178180
try {
179181
sheetPromise.reject(code, message)
180182
} catch (e: Exception) {
181-
Log.e("HyperswitchSDK", "Error rejecting payment sheet promise", e)
183+
Log.e("HyperSwitchSDK", "Error rejecting payment sheet promise", e)
182184
}
183185
}
184186

android/src/main/java/com/hyperswitchsdkreactnative/HyperswitchSdkReactNativeViewManager.kt

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,16 @@ import com.facebook.react.viewmanagers.HyperswitchSdkReactNativeViewManagerInter
1010
import com.facebook.react.viewmanagers.HyperswitchSdkReactNativeViewManagerDelegate
1111

1212
@ReactModule(name = HyperswitchSdkReactNativeViewManager.NAME)
13-
class HyperswitchSdkReactNativeViewManager : SimpleViewManager<HyperswitchSdkReactNativeView>() {
14-
// HyperswitchSdkReactNativeViewManagerInterface<HyperswitchSdkReactNativeView> {
15-
// private val mDelegate: ViewManagerDelegate<HyperswitchSdkReactNativeView>
13+
class HyperswitchSdkReactNativeViewManager : SimpleViewManager<HyperswitchSdkReactNativeView>(),
14+
HyperswitchSdkReactNativeViewManagerInterface<HyperswitchSdkReactNativeView> {
15+
private val mDelegate: ViewManagerDelegate<HyperswitchSdkReactNativeView>
1616

1717
init {
18-
// mDelegate = HyperswitchSdkReactNativeViewManagerDelegate(this)
18+
mDelegate = HyperswitchSdkReactNativeViewManagerDelegate(this)
1919
}
2020

2121
override fun getDelegate(): ViewManagerDelegate<HyperswitchSdkReactNativeView>? {
22-
// return mDelegate
23-
return null
22+
return mDelegate
2423
}
2524

2625
override fun getName(): String {
@@ -32,7 +31,7 @@ class HyperswitchSdkReactNativeViewManager : SimpleViewManager<HyperswitchSdkRea
3231
}
3332

3433
@ReactProp(name = "color")
35-
fun setColor(view: HyperswitchSdkReactNativeView?, color: String?) {
34+
override fun setColor(view: HyperswitchSdkReactNativeView?, color: String?) {
3635
view?.setBackgroundColor(Color.parseColor(color))
3736
}
3837

android/src/main/java/com/hyperswitchsdkreactnative/hypermodules/HyperNativeModule.kt

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import com.facebook.react.bridge.Arguments
1010
import com.hyperswitchsdkreactnative.HyperswitchSdkReactNativeModule
1111
import com.hyperswitchsdkreactnative.NativeHyperModulesSpec
1212
import com.hyperswitchsdkreactnative.react.ReactUtils
13+
import com.hyperswitchsdkreactnative.payment.gpay.GooglePayCallbackManager
1314

1415
/**
1516
* HyperModules TurboModule implementation that bridges the bundle's expectations
@@ -51,7 +52,26 @@ class HyperNativeModule(reactContext: ReactApplicationContext) :
5152
override fun launchGPay(requestObj: String, callback: Callback) {
5253
Log.d(NAME, "launchGPay called")
5354
// Implementation for Google Pay
54-
callback.invoke("Google Pay not implemented")
55+
// callback.invoke("Google Pay not implemented")
56+
57+
58+
currentActivity?.let {
59+
GooglePayCallbackManager.setCallback(
60+
it,
61+
requestObj,
62+
fun(data: Map<String, Any?>) {
63+
callback.invoke(Arguments.fromBundle(ReactUtils.toBundle(data)))
64+
},
65+
)
66+
} ?: run {
67+
GooglePayCallbackManager.setCallback(
68+
reactApplicationContext,
69+
requestObj,
70+
fun(data: Map<String, Any?>) {
71+
callback.invoke(Arguments.fromBundle(ReactUtils.toBundle(data)))
72+
},
73+
)
74+
}
5575
}
5676

5777
@ReactMethod

android/src/main/java/com/hyperswitchsdkreactnative/hypermodules/HyperNativePackage.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import com.facebook.react.bridge.ReactApplicationContext
66
import com.facebook.react.module.model.ReactModuleInfo
77
import com.facebook.react.module.model.ReactModuleInfoProvider
88
import com.facebook.react.uimanager.ViewManager
9+
import com.hyperswitchsdkreactnative.views.GooglePayButtonManager
910
import java.util.ArrayList
1011
import java.util.HashMap
1112

@@ -21,6 +22,7 @@ class HyperNativePackage : BaseReactPackage() {
2122
override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
2223
val viewManagers: MutableList<ViewManager<*, *>> = ArrayList()
2324
viewManagers.add(HyperNativeViewManager())
25+
viewManagers.add(GooglePayButtonManager())
2426
return viewManagers
2527
}
2628

android/src/main/java/com/hyperswitchsdkreactnative/payment/gpay/GooglePayActivity.kt

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
package com.hyperswitchsdkreactnative.payment.gpay
22

3+
import android.annotation.SuppressLint
34
import android.content.Intent
45
import android.os.Bundle
56
import android.util.Log
67
import androidx.activity.viewModels
78
import androidx.appcompat.app.AppCompatActivity
8-
import com.facebook.react.bridge.Arguments
9-
//import com.google.android.gms.pay.PayClient
109
import com.google.android.gms.wallet.AutoResolveHelper
1110
import com.google.android.gms.wallet.PaymentData
12-
import com.hyperswitchsdkreactnative.HyperswitchSdkReactNativeModule.Companion.googlePayCallback
11+
import com.hyperswitchsdkreactnative.payment.gpay.GooglePayCallbackManager.getCallback
1312

1413
import org.json.JSONException
1514
import org.json.JSONObject
@@ -21,6 +20,7 @@ class GooglePayActivity : AppCompatActivity() {
2120
private val model: GooglePayViewModel by viewModels()
2221

2322

23+
@SuppressLint("SuspiciousIndentation")
2424
override fun onCreate(savedInstanceState: Bundle?) {
2525
super.onCreate(savedInstanceState)
2626
val intent = intent
@@ -54,22 +54,23 @@ class GooglePayActivity : AppCompatActivity() {
5454
AutoResolveHelper.resolveTask(task, this, gPayRequestCode)
5555
}
5656

57-
private fun handlePaymentSuccess(paymentData: PaymentData) {
58-
val map = Arguments.createMap()
59-
try {
60-
val paymentInformation = paymentData.toJson()
61-
map.putString("paymentMethodData", JSONObject(paymentInformation).toString())
62-
} catch (error: JSONException) {
63-
map.putString("error", error.message)
64-
}
65-
googlePayCallback.invoke(map)
66-
finish()
57+
private fun handlePaymentSuccess(paymentData: PaymentData) {
58+
// Use MutableMap for dynamic data
59+
val map: MutableMap<String, Any?> = mutableMapOf()
60+
try {
61+
val paymentInformation = paymentData.toJson()
62+
map["paymentMethodData"] = JSONObject(paymentInformation).toString()
63+
} catch (error: JSONException) {
64+
map["error"] = error.message
6765
}
66+
getCallback()?.invoke(map)
67+
finish()
68+
}
6869

6970
private fun handleError(message: String) {
70-
val map = Arguments.createMap()
71-
map.putString("error", message)
72-
googlePayCallback.invoke(map)
71+
val map: MutableMap<String, Any?> = mutableMapOf()
72+
map["error"] = message
73+
getCallback()?.invoke(map)
7374
finish()
7475
}
7576

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package com.hyperswitchsdkreactnative.payment.gpay
2+
3+
import android.content.Context
4+
import android.content.Intent
5+
6+
typealias Callback = (Map<String, Any?>) -> Unit
7+
8+
object GooglePayCallbackManager {
9+
private var callback: Callback? = null
10+
11+
fun setCallback(appContext: Context, request: String, newCallback: Callback) {
12+
callback = newCallback
13+
val myIntent = Intent(
14+
appContext,
15+
GooglePayActivity::class.java
16+
)
17+
myIntent.putExtra("gPayRequest", request)
18+
myIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
19+
appContext.startActivity(myIntent)
20+
}
21+
22+
fun getCallback(): Callback? {
23+
return callback
24+
}
25+
26+
fun executeCallback(data: Map<String, Any?>) {
27+
callback?.invoke(data) ?: println("No callback set")
28+
}
29+
}

android/src/main/java/com/hyperswitchsdkreactnative/react/ReactUtils.kt

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@ class ReactUtils {
5252
userAgent,
5353
ipAddress
5454
)
55-
).build()
55+
).setFabricEnabled(true)
56+
.build()
5657
val transaction = context.supportFragmentManager.beginTransaction()
5758
if (isHidden == true) {
5859
transaction.hide(reactNativeFragmentSheet!!)
@@ -121,6 +122,23 @@ class ReactUtils {
121122
}
122123
}
123124

125+
fun toBundle(readableMap: Map<*, *>): Bundle {
126+
val bundle = Bundle()
127+
for ((key, value) in readableMap) {
128+
val keyString = key.toString()
129+
when (value) {
130+
null -> {} //bundle.putString(keyString, null)
131+
is Boolean -> bundle.putBoolean(keyString, value)
132+
is Number -> bundle.putDouble(keyString, value.toDouble())
133+
is String -> bundle.putString(keyString, value)
134+
is Map<*, *> -> bundle.putBundle(keyString, toBundle(value))
135+
is Array<*> -> bundle.putSerializable(keyString, value as? Array<*>)
136+
else -> throw IllegalArgumentException("Could not convert object with key: $keyString.")
137+
}
138+
}
139+
return bundle
140+
}
141+
124142
private fun getLaunchOptions(
125143
request: Bundle,
126144
message: String,
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package com.hyperswitchsdkreactnative.views
2+
3+
import com.facebook.react.module.annotations.ReactModule
4+
import com.facebook.react.uimanager.SimpleViewManager
5+
import com.facebook.react.uimanager.ThemedReactContext
6+
import com.facebook.react.uimanager.ViewManagerDelegate
7+
import com.facebook.react.viewmanagers.GooglePayButtonManagerDelegate
8+
import com.facebook.react.viewmanagers.GooglePayButtonManagerInterface
9+
import com.google.android.gms.wallet.button.ButtonConstants
10+
import com.hyperswitchsdkreactnative.view.GooglePayButtonView
11+
import java.math.BigInteger
12+
13+
@ReactModule(name = GooglePayButtonManager.NAME)
14+
class GooglePayButtonManager : SimpleViewManager<GooglePayButtonView>(),
15+
GooglePayButtonManagerInterface<GooglePayButtonView> {
16+
private val mDelegate: ViewManagerDelegate<GooglePayButtonView> = GooglePayButtonManagerDelegate(this)
17+
18+
override fun getDelegate(): ViewManagerDelegate<GooglePayButtonView>? {
19+
return mDelegate
20+
}
21+
22+
override fun getName(): String {
23+
return NAME
24+
}
25+
26+
public override fun createViewInstance(context: ThemedReactContext): GooglePayButtonView {
27+
return GooglePayButtonView(context)
28+
}
29+
30+
public override fun onAfterUpdateTransaction(view: GooglePayButtonView) {
31+
super.onAfterUpdateTransaction(view)
32+
view.addButton()
33+
}
34+
35+
override fun setButtonType(
36+
view: GooglePayButtonView?,
37+
value: String?
38+
) {
39+
view?.type = when (value) {
40+
"BUY" -> ButtonConstants.ButtonType.BUY
41+
"BOOK" -> ButtonConstants.ButtonType.BOOK
42+
"CHECKOUT" -> ButtonConstants.ButtonType.CHECKOUT
43+
"DONATE" -> ButtonConstants.ButtonType.DONATE
44+
"ORDER" -> ButtonConstants.ButtonType.ORDER
45+
"PAY" -> ButtonConstants.ButtonType.PAY
46+
"SUBSCRIBE" -> ButtonConstants.ButtonType.SUBSCRIBE
47+
else -> ButtonConstants.ButtonType.PLAIN
48+
}
49+
}
50+
51+
override fun setButtonStyle(
52+
view: GooglePayButtonView?,
53+
value: String?
54+
) {
55+
view?.theme = when (value) {
56+
"light" -> ButtonConstants.ButtonTheme.LIGHT
57+
else -> ButtonConstants.ButtonTheme.DARK
58+
}
59+
}
60+
61+
override fun setBorderRadius(
62+
view: GooglePayButtonView?,
63+
value: Double
64+
) {
65+
view?.cornerRadius = value.toInt()
66+
}
67+
68+
override fun setAllowedPaymentMethods(
69+
view: GooglePayButtonView?,
70+
value: String?
71+
) {
72+
if (value != null) {
73+
view?.allowedPaymentMethods = value
74+
}
75+
}
76+
77+
companion object {
78+
const val NAME = "GooglePayButton"
79+
}
80+
}

0 commit comments

Comments
 (0)