@gmisoftware/react-native-pay 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (203) hide show
  1. package/NitroPay.podspec +31 -0
  2. package/README.md +455 -0
  3. package/android/CMakeLists.txt +29 -0
  4. package/android/build.gradle +144 -0
  5. package/android/fix-prefab.gradle +51 -0
  6. package/android/gradle.properties +8 -0
  7. package/android/src/main/AndroidManifest.xml +2 -0
  8. package/android/src/main/cpp/cpp-adapter.cpp +6 -0
  9. package/android/src/main/java/com/margelo/nitro/pay/Constants.kt +49 -0
  10. package/android/src/main/java/com/margelo/nitro/pay/GooglePayButtonFactory.kt +95 -0
  11. package/android/src/main/java/com/margelo/nitro/pay/GooglePayRequestBuilder.kt +170 -0
  12. package/android/src/main/java/com/margelo/nitro/pay/HybridGooglePayButton.kt +146 -0
  13. package/android/src/main/java/com/margelo/nitro/pay/HybridPaymentHandler.kt +184 -0
  14. package/android/src/main/java/com/margelo/nitro/pay/NitroPayPackage.kt +26 -0
  15. package/android/src/main/java/com/margelo/nitro/pay/PaymentMapper.kt +89 -0
  16. package/app.plugin.js +1 -0
  17. package/ios/ApplePayButtonFactory.swift +53 -0
  18. package/ios/Bridge.h +8 -0
  19. package/ios/HybridApplePayButton.swift +60 -0
  20. package/ios/HybridPaymentHandler.swift +248 -0
  21. package/ios/PassKitTypeMapper.swift +192 -0
  22. package/lib/hooks/index.d.ts +7 -0
  23. package/lib/hooks/index.js +10 -0
  24. package/lib/hooks/usePaymentCheckout.d.ts +95 -0
  25. package/lib/hooks/usePaymentCheckout.js +183 -0
  26. package/lib/index.d.ts +10 -0
  27. package/lib/index.js +29 -0
  28. package/lib/plugin/index.d.ts +4 -0
  29. package/lib/plugin/index.js +10 -0
  30. package/lib/plugin/type.d.ts +4 -0
  31. package/lib/plugin/type.js +2 -0
  32. package/lib/plugin/withApplePay.d.ts +4 -0
  33. package/lib/plugin/withApplePay.js +32 -0
  34. package/lib/plugin/withGooglePay.d.ts +4 -0
  35. package/lib/plugin/withGooglePay.js +24 -0
  36. package/lib/specs/ApplePayButton.nitro.d.ts +13 -0
  37. package/lib/specs/ApplePayButton.nitro.js +2 -0
  38. package/lib/specs/GooglePayButton.nitro.d.ts +14 -0
  39. package/lib/specs/GooglePayButton.nitro.js +2 -0
  40. package/lib/specs/PaymentHandler.nitro.d.ts +10 -0
  41. package/lib/specs/PaymentHandler.nitro.js +2 -0
  42. package/lib/types/Contact.d.ts +51 -0
  43. package/lib/types/Contact.js +6 -0
  44. package/lib/types/Payment.d.ts +67 -0
  45. package/lib/types/Payment.js +6 -0
  46. package/lib/types/index.d.ts +2 -0
  47. package/lib/types/index.js +18 -0
  48. package/lib/utils/index.d.ts +4 -0
  49. package/lib/utils/index.js +20 -0
  50. package/lib/utils/paymentHelpers.d.ts +144 -0
  51. package/lib/utils/paymentHelpers.js +190 -0
  52. package/nitro.json +30 -0
  53. package/nitrogen/generated/.gitattributes +1 -0
  54. package/nitrogen/generated/android/NitroPay+autolinking.cmake +87 -0
  55. package/nitrogen/generated/android/NitroPay+autolinking.gradle +27 -0
  56. package/nitrogen/generated/android/NitroPayOnLoad.cpp +58 -0
  57. package/nitrogen/generated/android/NitroPayOnLoad.hpp +25 -0
  58. package/nitrogen/generated/android/c++/JCNContact.hpp +202 -0
  59. package/nitrogen/generated/android/c++/JCNContactType.hpp +59 -0
  60. package/nitrogen/generated/android/c++/JCNLabeledEmailAddress.hpp +62 -0
  61. package/nitrogen/generated/android/c++/JCNLabeledPhoneNumber.hpp +64 -0
  62. package/nitrogen/generated/android/c++/JCNLabeledPostalAddress.hpp +64 -0
  63. package/nitrogen/generated/android/c++/JCNPhoneNumber.hpp +57 -0
  64. package/nitrogen/generated/android/c++/JCNPostalAddress.hpp +78 -0
  65. package/nitrogen/generated/android/c++/JFunc_void.hpp +74 -0
  66. package/nitrogen/generated/android/c++/JGooglePayButtonTheme.hpp +59 -0
  67. package/nitrogen/generated/android/c++/JGooglePayButtonType.hpp +77 -0
  68. package/nitrogen/generated/android/c++/JGooglePayEnvironment.hpp +59 -0
  69. package/nitrogen/generated/android/c++/JHybridGooglePayButtonSpec.cpp +96 -0
  70. package/nitrogen/generated/android/c++/JHybridGooglePayButtonSpec.hpp +71 -0
  71. package/nitrogen/generated/android/c++/JHybridPaymentHandlerSpec.cpp +154 -0
  72. package/nitrogen/generated/android/c++/JHybridPaymentHandlerSpec.hpp +66 -0
  73. package/nitrogen/generated/android/c++/JPKSecureElementPass.hpp +96 -0
  74. package/nitrogen/generated/android/c++/JPassActivationState.hpp +68 -0
  75. package/nitrogen/generated/android/c++/JPayServiceStatus.hpp +61 -0
  76. package/nitrogen/generated/android/c++/JPaymentItem.hpp +67 -0
  77. package/nitrogen/generated/android/c++/JPaymentItemType.hpp +59 -0
  78. package/nitrogen/generated/android/c++/JPaymentMethod.hpp +97 -0
  79. package/nitrogen/generated/android/c++/JPaymentMethodType.hpp +68 -0
  80. package/nitrogen/generated/android/c++/JPaymentNetwork.hpp +86 -0
  81. package/nitrogen/generated/android/c++/JPaymentRequest.hpp +181 -0
  82. package/nitrogen/generated/android/c++/JPaymentResult.hpp +97 -0
  83. package/nitrogen/generated/android/c++/JPaymentToken.hpp +91 -0
  84. package/nitrogen/generated/android/c++/views/JHybridGooglePayButtonStateUpdater.cpp +68 -0
  85. package/nitrogen/generated/android/c++/views/JHybridGooglePayButtonStateUpdater.hpp +49 -0
  86. package/nitrogen/generated/android/kotlin/com/margelo/nitro/pay/CNContact.kt +96 -0
  87. package/nitrogen/generated/android/kotlin/com/margelo/nitro/pay/CNContactType.kt +21 -0
  88. package/nitrogen/generated/android/kotlin/com/margelo/nitro/pay/CNLabeledEmailAddress.kt +39 -0
  89. package/nitrogen/generated/android/kotlin/com/margelo/nitro/pay/CNLabeledPhoneNumber.kt +39 -0
  90. package/nitrogen/generated/android/kotlin/com/margelo/nitro/pay/CNLabeledPostalAddress.kt +39 -0
  91. package/nitrogen/generated/android/kotlin/com/margelo/nitro/pay/CNPhoneNumber.kt +36 -0
  92. package/nitrogen/generated/android/kotlin/com/margelo/nitro/pay/CNPostalAddress.kt +51 -0
  93. package/nitrogen/generated/android/kotlin/com/margelo/nitro/pay/Func_void.kt +80 -0
  94. package/nitrogen/generated/android/kotlin/com/margelo/nitro/pay/GooglePayButtonTheme.kt +21 -0
  95. package/nitrogen/generated/android/kotlin/com/margelo/nitro/pay/GooglePayButtonType.kt +27 -0
  96. package/nitrogen/generated/android/kotlin/com/margelo/nitro/pay/GooglePayEnvironment.kt +21 -0
  97. package/nitrogen/generated/android/kotlin/com/margelo/nitro/pay/HybridGooglePayButtonSpec.kt +80 -0
  98. package/nitrogen/generated/android/kotlin/com/margelo/nitro/pay/HybridPaymentHandlerSpec.kt +61 -0
  99. package/nitrogen/generated/android/kotlin/com/margelo/nitro/pay/NitroPayOnLoad.kt +35 -0
  100. package/nitrogen/generated/android/kotlin/com/margelo/nitro/pay/PKSecureElementPass.kt +63 -0
  101. package/nitrogen/generated/android/kotlin/com/margelo/nitro/pay/PassActivationState.kt +24 -0
  102. package/nitrogen/generated/android/kotlin/com/margelo/nitro/pay/PayServiceStatus.kt +39 -0
  103. package/nitrogen/generated/android/kotlin/com/margelo/nitro/pay/PaymentItem.kt +42 -0
  104. package/nitrogen/generated/android/kotlin/com/margelo/nitro/pay/PaymentItemType.kt +21 -0
  105. package/nitrogen/generated/android/kotlin/com/margelo/nitro/pay/PaymentMethod.kt +48 -0
  106. package/nitrogen/generated/android/kotlin/com/margelo/nitro/pay/PaymentMethodType.kt +24 -0
  107. package/nitrogen/generated/android/kotlin/com/margelo/nitro/pay/PaymentNetwork.kt +30 -0
  108. package/nitrogen/generated/android/kotlin/com/margelo/nitro/pay/PaymentRequest.kt +72 -0
  109. package/nitrogen/generated/android/kotlin/com/margelo/nitro/pay/PaymentResult.kt +45 -0
  110. package/nitrogen/generated/android/kotlin/com/margelo/nitro/pay/PaymentToken.kt +42 -0
  111. package/nitrogen/generated/android/kotlin/com/margelo/nitro/pay/views/HybridGooglePayButtonManager.kt +50 -0
  112. package/nitrogen/generated/android/kotlin/com/margelo/nitro/pay/views/HybridGooglePayButtonStateUpdater.kt +23 -0
  113. package/nitrogen/generated/ios/NitroPay+autolinking.rb +60 -0
  114. package/nitrogen/generated/ios/NitroPay-Swift-Cxx-Bridge.cpp +73 -0
  115. package/nitrogen/generated/ios/NitroPay-Swift-Cxx-Bridge.hpp +415 -0
  116. package/nitrogen/generated/ios/NitroPay-Swift-Cxx-Umbrella.hpp +116 -0
  117. package/nitrogen/generated/ios/NitroPayAutolinking.mm +41 -0
  118. package/nitrogen/generated/ios/NitroPayAutolinking.swift +40 -0
  119. package/nitrogen/generated/ios/c++/HybridApplePayButtonSpecSwift.cpp +11 -0
  120. package/nitrogen/generated/ios/c++/HybridApplePayButtonSpecSwift.hpp +92 -0
  121. package/nitrogen/generated/ios/c++/HybridPaymentHandlerSpecSwift.cpp +11 -0
  122. package/nitrogen/generated/ios/c++/HybridPaymentHandlerSpecSwift.hpp +148 -0
  123. package/nitrogen/generated/ios/c++/views/HybridApplePayButtonComponent.mm +106 -0
  124. package/nitrogen/generated/ios/swift/ApplePayButtonStyle.swift +44 -0
  125. package/nitrogen/generated/ios/swift/ApplePayButtonType.swift +84 -0
  126. package/nitrogen/generated/ios/swift/CNContact.swift +329 -0
  127. package/nitrogen/generated/ios/swift/CNContactType.swift +40 -0
  128. package/nitrogen/generated/ios/swift/CNLabeledEmailAddress.swift +65 -0
  129. package/nitrogen/generated/ios/swift/CNLabeledPhoneNumber.swift +65 -0
  130. package/nitrogen/generated/ios/swift/CNLabeledPostalAddress.swift +65 -0
  131. package/nitrogen/generated/ios/swift/CNPhoneNumber.swift +35 -0
  132. package/nitrogen/generated/ios/swift/CNPostalAddress.swift +204 -0
  133. package/nitrogen/generated/ios/swift/Func_void.swift +47 -0
  134. package/nitrogen/generated/ios/swift/Func_void_PaymentResult.swift +47 -0
  135. package/nitrogen/generated/ios/swift/Func_void_std__exception_ptr.swift +47 -0
  136. package/nitrogen/generated/ios/swift/GooglePayEnvironment.swift +40 -0
  137. package/nitrogen/generated/ios/swift/HybridApplePayButtonSpec.swift +51 -0
  138. package/nitrogen/generated/ios/swift/HybridApplePayButtonSpec_cxx.swift +175 -0
  139. package/nitrogen/generated/ios/swift/HybridPaymentHandlerSpec.swift +52 -0
  140. package/nitrogen/generated/ios/swift/HybridPaymentHandlerSpec_cxx.swift +155 -0
  141. package/nitrogen/generated/ios/swift/PKSecureElementPass.swift +191 -0
  142. package/nitrogen/generated/ios/swift/PassActivationState.swift +52 -0
  143. package/nitrogen/generated/ios/swift/PayServiceStatus.swift +46 -0
  144. package/nitrogen/generated/ios/swift/PaymentItem.swift +57 -0
  145. package/nitrogen/generated/ios/swift/PaymentItemType.swift +40 -0
  146. package/nitrogen/generated/ios/swift/PaymentMethod.swift +134 -0
  147. package/nitrogen/generated/ios/swift/PaymentMethodType.swift +52 -0
  148. package/nitrogen/generated/ios/swift/PaymentNetwork.swift +76 -0
  149. package/nitrogen/generated/ios/swift/PaymentRequest.swift +341 -0
  150. package/nitrogen/generated/ios/swift/PaymentResult.swift +118 -0
  151. package/nitrogen/generated/ios/swift/PaymentToken.swift +57 -0
  152. package/nitrogen/generated/shared/c++/ApplePayButtonStyle.hpp +80 -0
  153. package/nitrogen/generated/shared/c++/ApplePayButtonType.hpp +120 -0
  154. package/nitrogen/generated/shared/c++/CNContact.hpp +168 -0
  155. package/nitrogen/generated/shared/c++/CNContactType.hpp +76 -0
  156. package/nitrogen/generated/shared/c++/CNLabeledEmailAddress.hpp +80 -0
  157. package/nitrogen/generated/shared/c++/CNLabeledPhoneNumber.hpp +82 -0
  158. package/nitrogen/generated/shared/c++/CNLabeledPostalAddress.hpp +82 -0
  159. package/nitrogen/generated/shared/c++/CNPhoneNumber.hpp +75 -0
  160. package/nitrogen/generated/shared/c++/CNPostalAddress.hpp +96 -0
  161. package/nitrogen/generated/shared/c++/GooglePayButtonTheme.hpp +76 -0
  162. package/nitrogen/generated/shared/c++/GooglePayButtonType.hpp +100 -0
  163. package/nitrogen/generated/shared/c++/GooglePayEnvironment.hpp +76 -0
  164. package/nitrogen/generated/shared/c++/HybridApplePayButtonSpec.cpp +26 -0
  165. package/nitrogen/generated/shared/c++/HybridApplePayButtonSpec.hpp +73 -0
  166. package/nitrogen/generated/shared/c++/HybridGooglePayButtonSpec.cpp +28 -0
  167. package/nitrogen/generated/shared/c++/HybridGooglePayButtonSpec.hpp +75 -0
  168. package/nitrogen/generated/shared/c++/HybridPaymentHandlerSpec.cpp +23 -0
  169. package/nitrogen/generated/shared/c++/HybridPaymentHandlerSpec.hpp +74 -0
  170. package/nitrogen/generated/shared/c++/PKSecureElementPass.hpp +114 -0
  171. package/nitrogen/generated/shared/c++/PassActivationState.hpp +88 -0
  172. package/nitrogen/generated/shared/c++/PayServiceStatus.hpp +79 -0
  173. package/nitrogen/generated/shared/c++/PaymentItem.hpp +85 -0
  174. package/nitrogen/generated/shared/c++/PaymentItemType.hpp +76 -0
  175. package/nitrogen/generated/shared/c++/PaymentMethod.hpp +103 -0
  176. package/nitrogen/generated/shared/c++/PaymentMethodType.hpp +88 -0
  177. package/nitrogen/generated/shared/c++/PaymentNetwork.hpp +112 -0
  178. package/nitrogen/generated/shared/c++/PaymentRequest.hpp +130 -0
  179. package/nitrogen/generated/shared/c++/PaymentResult.hpp +90 -0
  180. package/nitrogen/generated/shared/c++/PaymentToken.hpp +85 -0
  181. package/nitrogen/generated/shared/c++/views/HybridApplePayButtonComponent.cpp +111 -0
  182. package/nitrogen/generated/shared/c++/views/HybridApplePayButtonComponent.hpp +111 -0
  183. package/nitrogen/generated/shared/c++/views/HybridGooglePayButtonComponent.cpp +123 -0
  184. package/nitrogen/generated/shared/c++/views/HybridGooglePayButtonComponent.hpp +112 -0
  185. package/nitrogen/generated/shared/json/ApplePayButtonConfig.json +12 -0
  186. package/nitrogen/generated/shared/json/GooglePayButtonConfig.json +13 -0
  187. package/package.json +116 -0
  188. package/react-native.config.js +16 -0
  189. package/src/hooks/index.ts +12 -0
  190. package/src/hooks/usePaymentCheckout.ts +281 -0
  191. package/src/index.ts +32 -0
  192. package/src/plugin/index.ts +17 -0
  193. package/src/plugin/type.ts +4 -0
  194. package/src/plugin/withApplePay.ts +44 -0
  195. package/src/plugin/withGooglePay.ts +41 -0
  196. package/src/specs/ApplePayButton.nitro.ts +37 -0
  197. package/src/specs/GooglePayButton.nitro.ts +34 -0
  198. package/src/specs/PaymentHandler.nitro.ts +13 -0
  199. package/src/types/Contact.ts +58 -0
  200. package/src/types/Payment.ts +104 -0
  201. package/src/types/index.ts +2 -0
  202. package/src/utils/index.ts +5 -0
  203. package/src/utils/paymentHelpers.ts +215 -0
@@ -0,0 +1,8 @@
1
+ NitroPay_kotlinVersion=2.1.20
2
+ NitroPay_minSdkVersion=23
3
+ NitroPay_targetSdkVersion=36
4
+ NitroPay_compileSdkVersion=36
5
+ NitroPay_ndkVersion=27.1.12297006
6
+
7
+ # Google Pay Environment: TEST or PRODUCTION
8
+ GOOGLE_PAY_ENVIRONMENT=TEST
@@ -0,0 +1,2 @@
1
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android">
2
+ </manifest>
@@ -0,0 +1,6 @@
1
+ #include <jni.h>
2
+ #include "NitroPayOnLoad.hpp"
3
+
4
+ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*) {
5
+ return margelo::nitro::pay::initialize(vm);
6
+ }
@@ -0,0 +1,49 @@
1
+ package com.margelo.nitro.pay
2
+
3
+ /**
4
+ * Constants used across the payment module
5
+ */
6
+ object PaymentConstants {
7
+ // Activity result codes
8
+ const val LOAD_PAYMENT_DATA_REQUEST_CODE = 991
9
+
10
+ // Google Pay API versions
11
+ const val API_VERSION = 2
12
+ const val API_VERSION_MINOR = 0
13
+
14
+ // Payment method types
15
+ const val PAYMENT_METHOD_CARD = "CARD"
16
+
17
+ // Auth methods
18
+ const val AUTH_PAN_ONLY = "PAN_ONLY"
19
+ const val AUTH_CRYPTOGRAM_3DS = "CRYPTOGRAM_3DS"
20
+
21
+ // Card networks
22
+ const val NETWORK_VISA = "VISA"
23
+ const val NETWORK_MASTERCARD = "MASTERCARD"
24
+ const val NETWORK_AMEX = "AMEX"
25
+ const val NETWORK_DISCOVER = "DISCOVER"
26
+
27
+ // Tokenization
28
+ const val TOKENIZATION_PAYMENT_GATEWAY = "PAYMENT_GATEWAY"
29
+ const val DEFAULT_GATEWAY = "example"
30
+ const val DEFAULT_GATEWAY_MERCHANT_ID = "exampleGatewayMerchantId"
31
+
32
+ // Transaction
33
+ const val TOTAL_PRICE_STATUS_FINAL = "FINAL"
34
+ const val TOTAL_PRICE_LABEL_DEFAULT = "Total"
35
+ const val LINE_ITEM_TYPE = "LINE_ITEM"
36
+ const val PENDING_TYPE = "PENDING"
37
+
38
+ // Merchant
39
+ const val DEFAULT_MERCHANT_NAME = "Example Merchant"
40
+
41
+ // Supported networks (lowercase for comparison)
42
+ val SUPPORTED_NETWORKS = listOf("visa", "mastercard", "amex", "discover")
43
+
44
+ // Logging tags
45
+ const val TAG_PAYMENT_HANDLER = "HybridPaymentHandler"
46
+ const val TAG_GOOGLE_PAY_BUTTON = "HybridGooglePayButton"
47
+ }
48
+
49
+
@@ -0,0 +1,95 @@
1
+ package com.margelo.nitro.pay
2
+
3
+ import android.content.Context
4
+ import android.util.Log
5
+ import com.google.android.gms.wallet.button.ButtonConstants
6
+ import com.google.android.gms.wallet.button.ButtonOptions
7
+ import com.google.android.gms.wallet.button.PayButton
8
+
9
+ /**
10
+ * Factory for creating and configuring Google Pay buttons
11
+ */
12
+ object GooglePayButtonFactory {
13
+
14
+ /**
15
+ * Creates a configured PayButton
16
+ */
17
+ fun createButton(
18
+ context: Context,
19
+ buttonType: GooglePayButtonType,
20
+ theme: GooglePayButtonTheme,
21
+ radius: Double?,
22
+ onPress: (() -> Unit)?
23
+ ): PayButton {
24
+ val allowedPaymentMethods = GooglePayRequestBuilder.createAllowedCardNetworks()
25
+
26
+ val buttonOptions = ButtonOptions.newBuilder()
27
+ .setButtonType(mapButtonType(buttonType))
28
+ .setButtonTheme(mapTheme(theme))
29
+ .setAllowedPaymentMethods(createAllowedPaymentMethodsJson(allowedPaymentMethods))
30
+ .apply {
31
+ radius?.let { r ->
32
+ if (r >= 0) {
33
+ setCornerRadius(r.toInt())
34
+ }
35
+ }
36
+ }
37
+ .build()
38
+
39
+ val button = PayButton(context)
40
+ button.initialize(buttonOptions)
41
+ button.setOnClickListener {
42
+ onPress?.invoke()
43
+ }
44
+
45
+ return button
46
+ }
47
+
48
+ /**
49
+ * Maps GooglePayButtonType to ButtonConstants
50
+ */
51
+ private fun mapButtonType(type: GooglePayButtonType): Int {
52
+ return when (type) {
53
+ GooglePayButtonType.BUY -> ButtonConstants.ButtonType.BUY
54
+ GooglePayButtonType.BOOK -> ButtonConstants.ButtonType.BOOK
55
+ GooglePayButtonType.CHECKOUT -> ButtonConstants.ButtonType.CHECKOUT
56
+ GooglePayButtonType.DONATE -> ButtonConstants.ButtonType.DONATE
57
+ GooglePayButtonType.ORDER -> ButtonConstants.ButtonType.ORDER
58
+ GooglePayButtonType.PAY -> ButtonConstants.ButtonType.PAY
59
+ GooglePayButtonType.SUBSCRIBE -> ButtonConstants.ButtonType.SUBSCRIBE
60
+ GooglePayButtonType.PLAIN -> ButtonConstants.ButtonType.PLAIN
61
+ }
62
+ }
63
+
64
+ /**
65
+ * Maps GooglePayButtonTheme to ButtonConstants
66
+ */
67
+ private fun mapTheme(theme: GooglePayButtonTheme): Int {
68
+ return when (theme) {
69
+ GooglePayButtonTheme.DARK -> ButtonConstants.ButtonTheme.DARK
70
+ GooglePayButtonTheme.LIGHT -> ButtonConstants.ButtonTheme.LIGHT
71
+ }
72
+ }
73
+
74
+ /**
75
+ * Creates allowed payment methods JSON for button configuration
76
+ */
77
+ private fun createAllowedPaymentMethodsJson(
78
+ allowedNetworks: org.json.JSONArray
79
+ ): String {
80
+ return org.json.JSONArray().apply {
81
+ put(org.json.JSONObject().apply {
82
+ put("type", PaymentConstants.PAYMENT_METHOD_CARD)
83
+ put("parameters", org.json.JSONObject().apply {
84
+ put("allowedAuthMethods", org.json.JSONArray().apply {
85
+ put(PaymentConstants.AUTH_PAN_ONLY)
86
+ put(PaymentConstants.AUTH_CRYPTOGRAM_3DS)
87
+ })
88
+ put("allowedCardNetworks", allowedNetworks)
89
+ })
90
+ })
91
+ }.toString()
92
+ }
93
+ }
94
+
95
+
@@ -0,0 +1,170 @@
1
+ package com.margelo.nitro.pay
2
+
3
+ import com.google.android.gms.wallet.WalletConstants
4
+ import org.json.JSONArray
5
+ import org.json.JSONObject
6
+
7
+ /**
8
+ * Builder for Google Pay API request objects
9
+ */
10
+ object GooglePayRequestBuilder {
11
+
12
+ /**
13
+ * Creates an IsReadyToPay request
14
+ */
15
+ fun createIsReadyToPayRequest(): JSONObject {
16
+ return JSONObject().apply {
17
+ put("apiVersion", PaymentConstants.API_VERSION)
18
+ put("apiVersionMinor", PaymentConstants.API_VERSION_MINOR)
19
+ put("allowedPaymentMethods", JSONArray().apply {
20
+ put(createBaseCardPaymentMethod())
21
+ })
22
+ }
23
+ }
24
+
25
+ /**
26
+ * Creates a complete payment data request
27
+ */
28
+ fun createPaymentDataRequest(
29
+ request: PaymentRequest,
30
+ environment: Int
31
+ ): JSONObject {
32
+ return JSONObject().apply {
33
+ put("apiVersion", PaymentConstants.API_VERSION)
34
+ put("apiVersionMinor", PaymentConstants.API_VERSION_MINOR)
35
+ put("merchantInfo", createMerchantInfo(request, environment))
36
+ put("allowedPaymentMethods", JSONArray().apply {
37
+ put(createCardPaymentMethod(request, environment))
38
+ })
39
+ put("transactionInfo", createTransactionInfo(request))
40
+ }
41
+ }
42
+
43
+ /**
44
+ * Creates merchant info object
45
+ */
46
+ private fun createMerchantInfo(
47
+ request: PaymentRequest,
48
+ environment: Int
49
+ ): JSONObject {
50
+ return JSONObject().apply {
51
+ put("merchantName", PaymentConstants.DEFAULT_MERCHANT_NAME)
52
+ // Add merchant ID only for PRODUCTION environment
53
+ if (environment == WalletConstants.ENVIRONMENT_PRODUCTION) {
54
+ put("merchantId", request.merchantIdentifier)
55
+ }
56
+ }
57
+ }
58
+
59
+ /**
60
+ * Creates base card payment method (no tokenization)
61
+ */
62
+ private fun createBaseCardPaymentMethod(): JSONObject {
63
+ return JSONObject().apply {
64
+ put("type", PaymentConstants.PAYMENT_METHOD_CARD)
65
+ put("parameters", JSONObject().apply {
66
+ put("allowedAuthMethods", createAllowedAuthMethods())
67
+ put("allowedCardNetworks", createAllowedCardNetworks())
68
+ })
69
+ }
70
+ }
71
+
72
+ /**
73
+ * Creates card payment method with tokenization
74
+ */
75
+ private fun createCardPaymentMethod(
76
+ request: PaymentRequest,
77
+ environment: Int
78
+ ): JSONObject {
79
+ val baseMethod = createBaseCardPaymentMethod()
80
+ baseMethod.put("tokenizationSpecification", createTokenizationSpec(request, environment))
81
+ return baseMethod
82
+ }
83
+
84
+ /**
85
+ * Creates tokenization specification
86
+ */
87
+ private fun createTokenizationSpec(
88
+ request: PaymentRequest,
89
+ environment: Int
90
+ ): JSONObject {
91
+ return JSONObject().apply {
92
+ put("type", PaymentConstants.TOKENIZATION_PAYMENT_GATEWAY)
93
+ put("parameters", JSONObject().apply {
94
+ val isProduction = environment == WalletConstants.ENVIRONMENT_PRODUCTION
95
+ put("gateway", request.googlePayGateway ?: PaymentConstants.DEFAULT_GATEWAY)
96
+ put(
97
+ "gatewayMerchantId",
98
+ request.googlePayGatewayMerchantId
99
+ ?: if (isProduction) request.merchantIdentifier
100
+ else PaymentConstants.DEFAULT_GATEWAY_MERCHANT_ID
101
+ )
102
+ })
103
+ }
104
+ }
105
+
106
+ /**
107
+ * Creates transaction info
108
+ */
109
+ private fun createTransactionInfo(request: PaymentRequest): JSONObject {
110
+ val totalAmount = request.paymentItems.sumOf { it.amount }
111
+
112
+ return JSONObject().apply {
113
+ put("totalPriceStatus", PaymentConstants.TOTAL_PRICE_STATUS_FINAL)
114
+ put("totalPrice", String.format("%.2f", totalAmount))
115
+ put("totalPriceLabel", PaymentConstants.TOTAL_PRICE_LABEL_DEFAULT)
116
+ put("currencyCode", request.currencyCode)
117
+ put("countryCode", request.countryCode)
118
+
119
+ // Add display items if present
120
+ if (request.paymentItems.isNotEmpty()) {
121
+ put("displayItems", createDisplayItems(request.paymentItems))
122
+ }
123
+ }
124
+ }
125
+
126
+ /**
127
+ * Creates display items array
128
+ */
129
+ private fun createDisplayItems(items: Array<PaymentItem>): JSONArray {
130
+ return JSONArray().apply {
131
+ items.forEach { item ->
132
+ put(JSONObject().apply {
133
+ put("label", item.label)
134
+ put(
135
+ "type",
136
+ if (item.type == PaymentItemType.FINAL)
137
+ PaymentConstants.LINE_ITEM_TYPE
138
+ else
139
+ PaymentConstants.PENDING_TYPE
140
+ )
141
+ put("price", String.format("%.2f", item.amount))
142
+ })
143
+ }
144
+ }
145
+ }
146
+
147
+ /**
148
+ * Creates allowed auth methods
149
+ */
150
+ private fun createAllowedAuthMethods(): JSONArray {
151
+ return JSONArray().apply {
152
+ put(PaymentConstants.AUTH_PAN_ONLY)
153
+ put(PaymentConstants.AUTH_CRYPTOGRAM_3DS)
154
+ }
155
+ }
156
+
157
+ /**
158
+ * Creates allowed card networks
159
+ */
160
+ fun createAllowedCardNetworks(): JSONArray {
161
+ return JSONArray().apply {
162
+ put(PaymentConstants.NETWORK_VISA)
163
+ put(PaymentConstants.NETWORK_MASTERCARD)
164
+ put(PaymentConstants.NETWORK_AMEX)
165
+ put(PaymentConstants.NETWORK_DISCOVER)
166
+ }
167
+ }
168
+ }
169
+
170
+
@@ -0,0 +1,146 @@
1
+ package com.margelo.nitro.pay
2
+
3
+ import android.util.Log
4
+ import android.view.View
5
+ import android.view.ViewGroup
6
+ import android.widget.FrameLayout
7
+ import com.facebook.react.uimanager.ThemedReactContext
8
+ import com.google.android.gms.wallet.button.PayButton
9
+
10
+ /**
11
+ * Hybrid implementation of GooglePayButton view component
12
+ */
13
+ class HybridGooglePayButton(context: ThemedReactContext) : HybridGooglePayButtonSpec() {
14
+
15
+ // View state
16
+ private var payButton: PayButton? = null
17
+ private val container: FrameLayout = FrameLayout(context)
18
+
19
+ // Configuration tracking for change detection
20
+ private var currentButtonType: GooglePayButtonType? = null
21
+ private var currentTheme: GooglePayButtonTheme? = null
22
+ private var currentRadius: Double? = null
23
+
24
+ // Props
25
+ override var buttonType: GooglePayButtonType = GooglePayButtonType.BUY
26
+ override var theme: GooglePayButtonTheme = GooglePayButtonTheme.DARK
27
+ override var radius: Double? = null
28
+ override var onPress: (() -> Unit)? = null
29
+
30
+ override var view: View = container
31
+ override val memorySize: Long get() = 0L
32
+
33
+ init {
34
+ Log.d(PaymentConstants.TAG_GOOGLE_PAY_BUTTON, "Initializing Google Pay button")
35
+ setupButton()
36
+ }
37
+
38
+ override fun afterUpdate() {
39
+ setupButton()
40
+ }
41
+
42
+ // MARK: - Private helpers
43
+
44
+ private fun setupButton() {
45
+ val context = container.context ?: return
46
+
47
+ try {
48
+ if (shouldReuseButton()) {
49
+ updateExistingButton()
50
+ return
51
+ }
52
+
53
+ recreateButton(context)
54
+
55
+ } catch (e: Exception) {
56
+ Log.e(PaymentConstants.TAG_GOOGLE_PAY_BUTTON, "Error setting up button", e)
57
+ restoreExistingButton()
58
+ }
59
+ }
60
+
61
+ /**
62
+ * Checks if the existing button can be reused
63
+ */
64
+ private fun shouldReuseButton(): Boolean {
65
+ val hasButton = payButton != null && payButton?.parent == container
66
+ val propsUnchanged = currentButtonType == buttonType &&
67
+ currentTheme == theme &&
68
+ currentRadius == radius
69
+ return hasButton && propsUnchanged
70
+ }
71
+
72
+ /**
73
+ * Updates the click listener on existing button
74
+ */
75
+ private fun updateExistingButton() {
76
+ payButton?.setOnClickListener {
77
+ onPress?.invoke()
78
+ }
79
+ Log.d(PaymentConstants.TAG_GOOGLE_PAY_BUTTON, "Button reused - props unchanged")
80
+ }
81
+
82
+ /**
83
+ * Recreates the button with new configuration
84
+ */
85
+ private fun recreateButton(context: android.content.Context) {
86
+ Log.d(
87
+ PaymentConstants.TAG_GOOGLE_PAY_BUTTON,
88
+ "Recreating button - type: $buttonType, theme: $theme, radius: $radius"
89
+ )
90
+
91
+ // Remove existing button
92
+ container.removeAllViews()
93
+
94
+ // Create new button
95
+ val newButton = GooglePayButtonFactory.createButton(
96
+ context,
97
+ buttonType,
98
+ theme,
99
+ radius,
100
+ onPress
101
+ )
102
+
103
+ // Update state
104
+ payButton = newButton
105
+ currentButtonType = buttonType
106
+ currentTheme = theme
107
+ currentRadius = radius
108
+
109
+ // Add to container
110
+ val layoutParams = FrameLayout.LayoutParams(
111
+ ViewGroup.LayoutParams.MATCH_PARENT,
112
+ ViewGroup.LayoutParams.MATCH_PARENT
113
+ )
114
+ container.addView(newButton, layoutParams)
115
+ container.requestLayout()
116
+
117
+ Log.d(PaymentConstants.TAG_GOOGLE_PAY_BUTTON, "Button created successfully")
118
+ }
119
+
120
+ /**
121
+ * Attempts to restore existing button if setup fails
122
+ */
123
+ private fun restoreExistingButton() {
124
+ payButton?.let { existingButton ->
125
+ try {
126
+ if (existingButton.parent == null) {
127
+ container.removeAllViews()
128
+ container.addView(
129
+ existingButton,
130
+ FrameLayout.LayoutParams(
131
+ ViewGroup.LayoutParams.MATCH_PARENT,
132
+ ViewGroup.LayoutParams.MATCH_PARENT
133
+ )
134
+ )
135
+ Log.d(PaymentConstants.TAG_GOOGLE_PAY_BUTTON, "Restored existing button")
136
+ }
137
+ } catch (restoreException: Exception) {
138
+ Log.e(
139
+ PaymentConstants.TAG_GOOGLE_PAY_BUTTON,
140
+ "Failed to restore button",
141
+ restoreException
142
+ )
143
+ }
144
+ }
145
+ }
146
+ }
@@ -0,0 +1,184 @@
1
+ package com.margelo.nitro.pay
2
+
3
+ import android.app.Activity
4
+ import android.content.Intent
5
+ import android.util.Log
6
+ import com.facebook.react.bridge.ActivityEventListener
7
+ import com.facebook.react.bridge.ReactApplicationContext
8
+ import com.google.android.gms.wallet.AutoResolveHelper
9
+ import com.google.android.gms.wallet.IsReadyToPayRequest
10
+ import com.google.android.gms.wallet.PaymentData
11
+ import com.google.android.gms.wallet.PaymentDataRequest
12
+ import com.google.android.gms.wallet.PaymentsClient
13
+ import com.google.android.gms.wallet.Wallet
14
+ import com.google.android.gms.wallet.WalletConstants
15
+ import com.margelo.nitro.core.Promise
16
+ import com.margelo.nitro.NitroModules
17
+
18
+ /**
19
+ * Hybrid implementation of PaymentHandler for Google Pay on Android
20
+ */
21
+ class HybridPaymentHandler : HybridPaymentHandlerSpec(), ActivityEventListener {
22
+
23
+ private val reactContext: ReactApplicationContext by lazy {
24
+ NitroModules.applicationContext as? ReactApplicationContext
25
+ ?: throw IllegalStateException("Application context is not ReactApplicationContext")
26
+ }
27
+
28
+ private var paymentPromise: Promise<PaymentResult>? = null
29
+ private var currentEnvironment: Int = WalletConstants.ENVIRONMENT_TEST
30
+
31
+ init {
32
+ reactContext.addActivityEventListener(this)
33
+ }
34
+
35
+ override val memorySize: Long get() = 0L
36
+
37
+ // MARK: - Public API
38
+
39
+ override fun payServiceStatus(): PayServiceStatus {
40
+ return try {
41
+ val request = IsReadyToPayRequest.fromJson(
42
+ GooglePayRequestBuilder.createIsReadyToPayRequest().toString()
43
+ )
44
+
45
+ val client = createPaymentsClient(currentEnvironment)
46
+ client.isReadyToPay(request) // Trigger async check
47
+
48
+ // Return optimistic status (actual check is async)
49
+ PayServiceStatus(canMakePayments = true, canSetupCards = true)
50
+ } catch (e: Exception) {
51
+ Log.e(PaymentConstants.TAG_PAYMENT_HANDLER, "Error checking status", e)
52
+ PayServiceStatus(canMakePayments = false, canSetupCards = false)
53
+ }
54
+ }
55
+
56
+ override fun canMakePayments(usingNetworks: Array<String>): Boolean {
57
+ return usingNetworks.any { network ->
58
+ PaymentConstants.SUPPORTED_NETWORKS.contains(network.lowercase())
59
+ }
60
+ }
61
+
62
+ override fun startPayment(request: PaymentRequest): Promise<PaymentResult> {
63
+ val promise = Promise<PaymentResult>()
64
+ paymentPromise = promise
65
+
66
+ try {
67
+ val environment = determineEnvironment(request.googlePayEnvironment)
68
+ currentEnvironment = environment
69
+
70
+ val paymentDataRequest = GooglePayRequestBuilder.createPaymentDataRequest(
71
+ request,
72
+ environment
73
+ )
74
+
75
+ logPaymentRequest(paymentDataRequest, environment)
76
+
77
+ val activity = reactContext.currentActivity
78
+ if (activity == null) {
79
+ handlePaymentError("No activity available to show payment UI")
80
+ return promise
81
+ }
82
+
83
+ launchPaymentUI(paymentDataRequest, activity, environment)
84
+
85
+ } catch (e: Exception) {
86
+ Log.e(PaymentConstants.TAG_PAYMENT_HANDLER, "Failed to start payment", e)
87
+ handlePaymentError("Failed to start payment: ${e.message}")
88
+ }
89
+
90
+ return promise
91
+ }
92
+
93
+ // MARK: - ActivityEventListener
94
+
95
+ override fun onActivityResult(
96
+ activity: Activity,
97
+ requestCode: Int,
98
+ resultCode: Int,
99
+ data: Intent?
100
+ ) {
101
+ if (requestCode != PaymentConstants.LOAD_PAYMENT_DATA_REQUEST_CODE) return
102
+
103
+ when (resultCode) {
104
+ Activity.RESULT_OK -> {
105
+ data?.let {
106
+ PaymentData.getFromIntent(it)?.let { paymentData ->
107
+ handlePaymentSuccess(paymentData)
108
+ }
109
+ } ?: handlePaymentError("No payment data received")
110
+ }
111
+ Activity.RESULT_CANCELED -> {
112
+ Log.d(PaymentConstants.TAG_PAYMENT_HANDLER, "Payment cancelled by user")
113
+ handlePaymentError("Payment cancelled by user")
114
+ }
115
+ AutoResolveHelper.RESULT_ERROR -> {
116
+ val status = data?.let { AutoResolveHelper.getStatusFromIntent(it) }
117
+ val message = status?.statusMessage ?: "Unknown error"
118
+ Log.e(PaymentConstants.TAG_PAYMENT_HANDLER, "Payment error: $message")
119
+ handlePaymentError("Payment error: $message")
120
+ }
121
+ else -> {
122
+ handlePaymentError("Payment failed with result code: $resultCode")
123
+ }
124
+ }
125
+ }
126
+
127
+ override fun onNewIntent(intent: Intent) {
128
+ // Not used for Google Pay
129
+ }
130
+
131
+ // MARK: - Private helpers
132
+
133
+ private fun createPaymentsClient(environment: Int): PaymentsClient {
134
+ val walletOptions = Wallet.WalletOptions.Builder()
135
+ .setEnvironment(environment)
136
+ .build()
137
+ return Wallet.getPaymentsClient(reactContext, walletOptions)
138
+ }
139
+
140
+ private fun determineEnvironment(envConfig: GooglePayEnvironment?): Int {
141
+ return when (envConfig) {
142
+ GooglePayEnvironment.PRODUCTION -> WalletConstants.ENVIRONMENT_PRODUCTION
143
+ GooglePayEnvironment.TEST, null -> WalletConstants.ENVIRONMENT_TEST
144
+ }
145
+ }
146
+
147
+ private fun launchPaymentUI(
148
+ paymentDataRequest: org.json.JSONObject,
149
+ activity: Activity,
150
+ environment: Int
151
+ ) {
152
+ val request = PaymentDataRequest.fromJson(paymentDataRequest.toString())
153
+ val client = createPaymentsClient(environment)
154
+
155
+ AutoResolveHelper.resolveTask(
156
+ client.loadPaymentData(request),
157
+ activity,
158
+ PaymentConstants.LOAD_PAYMENT_DATA_REQUEST_CODE
159
+ )
160
+
161
+ Log.d(PaymentConstants.TAG_PAYMENT_HANDLER, "Payment UI launched")
162
+ }
163
+
164
+ private fun handlePaymentSuccess(paymentData: PaymentData) {
165
+ Log.d(PaymentConstants.TAG_PAYMENT_HANDLER, "Payment successful")
166
+ val result = PaymentMapper.mapPaymentDataToResult(paymentData)
167
+ paymentPromise?.resolve(result)
168
+ paymentPromise = null
169
+ }
170
+
171
+ private fun handlePaymentError(errorMessage: String) {
172
+ val result = PaymentMapper.createErrorResult(errorMessage)
173
+ paymentPromise?.resolve(result)
174
+ paymentPromise = null
175
+ }
176
+
177
+ private fun logPaymentRequest(request: org.json.JSONObject, environment: Int) {
178
+ Log.d(PaymentConstants.TAG_PAYMENT_HANDLER, "Payment request: $request")
179
+ Log.d(
180
+ PaymentConstants.TAG_PAYMENT_HANDLER,
181
+ "Environment: ${if (environment == WalletConstants.ENVIRONMENT_TEST) "TEST" else "PRODUCTION"}"
182
+ )
183
+ }
184
+ }
@@ -0,0 +1,26 @@
1
+ package com.margelo.nitro.pay
2
+
3
+ import com.facebook.react.BaseReactPackage
4
+ import com.facebook.react.bridge.NativeModule
5
+ import com.facebook.react.bridge.ReactApplicationContext
6
+ import com.facebook.react.module.model.ReactModuleInfoProvider
7
+ import com.facebook.react.uimanager.ViewManager
8
+ import com.margelo.nitro.pay.views.HybridGooglePayButtonManager
9
+
10
+ class NitroPayPackage : BaseReactPackage() {
11
+ override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? = null
12
+
13
+ override fun getReactModuleInfoProvider(): ReactModuleInfoProvider = ReactModuleInfoProvider { HashMap() }
14
+
15
+ override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
16
+ val viewManagers = ArrayList<ViewManager<*, *>>()
17
+ viewManagers.add(HybridGooglePayButtonManager())
18
+ return viewManagers
19
+ }
20
+
21
+ companion object {
22
+ init {
23
+ NitroPayOnLoad.initializeNative()
24
+ }
25
+ }
26
+ }