@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,31 @@
1
+ require "json"
2
+
3
+ package = JSON.parse(File.read(File.join(__dir__, "package.json")))
4
+
5
+ Pod::Spec.new do |s|
6
+ s.name = "NitroPay"
7
+ s.version = package["version"]
8
+ s.summary = package["description"]
9
+ s.homepage = package["homepage"]
10
+ s.license = package["license"]
11
+ s.authors = package["author"]
12
+
13
+ s.platforms = { :ios => min_ios_version_supported, :visionos => 1.0 }
14
+ s.source = { :git => "https://github.com/mrousavy/nitro.git", :tag => "#{s.version}" }
15
+
16
+ s.source_files = [
17
+ # Implementation (Swift)
18
+ "ios/**/*.{swift}",
19
+ # Autolinking/Registration (Objective-C++)
20
+ "ios/**/*.{m,mm}",
21
+ # Implementation (C++ objects)
22
+ "cpp/**/*.{hpp,cpp}",
23
+ ]
24
+
25
+ load 'nitrogen/generated/ios/NitroPay+autolinking.rb'
26
+ add_nitrogen_files(s)
27
+
28
+ s.dependency 'React-jsi'
29
+ s.dependency 'React-callinvoker'
30
+ install_modules_dependencies(s)
31
+ end
package/README.md ADDED
@@ -0,0 +1,455 @@
1
+ # react-native-pay
2
+
3
+ A unified React Native payment module supporting both Apple Pay (iOS) and Google Pay (Android) with a consistent API across platforms.
4
+
5
+ Built with [Nitro Modules](https://nitro.margelo.com/) for high-performance native integration.
6
+
7
+ ## Features
8
+
9
+ - ✅ **Unified API** - Same interface for both Apple Pay and Google Pay
10
+ - ✅ **One Hook Does Everything** - Simple `usePaymentCheckout()` hook for complete payment flow
11
+ - ✅ **Native UI Components** - Platform-specific payment buttons
12
+ - ✅ **Type-Safe** - Full TypeScript support with comprehensive type definitions
13
+ - ✅ **Configurable** - Dynamic environment and gateway configuration
14
+ - ✅ **Built-in Cart** - Shopping cart functionality included
15
+ - ✅ **Modern Architecture** - Built with Nitro Modules for optimal performance
16
+ - ✅ **Expo Compatible** - Config plugins for easy integration with Expo
17
+
18
+ ## Installation
19
+
20
+ ```bash
21
+ npm install react-native-pay
22
+ # or
23
+ yarn add react-native-pay
24
+ # or
25
+ bun add react-native-pay
26
+ ```
27
+
28
+ ### iOS Setup
29
+
30
+ Add Apple Pay capability to your app and configure merchant identifiers in your Expo config:
31
+
32
+ ```js
33
+ // app.json or app.config.js
34
+ {
35
+ "plugins": [
36
+ [
37
+ "react-native-pay",
38
+ {
39
+ "merchantIdentifier": "merchant.com.yourcompany.app"
40
+ }
41
+ ]
42
+ ]
43
+ }
44
+ ```
45
+
46
+ ### Android Setup
47
+
48
+ Enable Google Pay in your Expo config:
49
+
50
+ ```js
51
+ // app.json or app.config.js
52
+ {
53
+ "plugins": [
54
+ [
55
+ "react-native-pay",
56
+ {
57
+ "enableGooglePay": true
58
+ }
59
+ ]
60
+ ]
61
+ }
62
+ ```
63
+
64
+ ## Usage
65
+
66
+ ### Using the Hook (Recommended)
67
+
68
+ One hook does everything - availability checking, cart management, and payment processing:
69
+
70
+ ```typescript
71
+ import {
72
+ usePaymentCheckout,
73
+ ApplePayButton,
74
+ GooglePayButton,
75
+ } from 'react-native-pay'
76
+ import { Platform, View, Text, Button, ActivityIndicator } from 'react-native'
77
+
78
+ function CheckoutScreen() {
79
+ const {
80
+ // Payment availability
81
+ canMakePayments,
82
+
83
+ // Cart management
84
+ items,
85
+ total,
86
+ addItem,
87
+ addItems,
88
+ removeItem,
89
+
90
+ // Payment processing
91
+ startPayment,
92
+ isProcessing,
93
+ error,
94
+ } = usePaymentCheckout({
95
+ merchantIdentifier: 'merchant.com.yourcompany.app',
96
+ currencyCode: 'USD',
97
+ countryCode: 'US',
98
+ })
99
+
100
+ // Add single item
101
+ const handleAddCoffee = () => addItem('Coffee', 4.99)
102
+
103
+ // Add multiple items at once
104
+ const handleAddFullOrder = () => addItems([
105
+ { label: 'Coffee', amount: 4.99 },
106
+ { label: 'Sandwich', amount: 8.99 },
107
+ { label: 'Tax', amount: 1.20 }
108
+ ])
109
+
110
+ const handlePay = async () => {
111
+ const result = await startPayment()
112
+ if (result?.success) {
113
+ // Send result.token to your server
114
+ console.log('Payment successful:', result.transactionId)
115
+ }
116
+ }
117
+
118
+ if (!canMakePayments) {
119
+ return <Text>Payment not available</Text>
120
+ }
121
+
122
+ return (
123
+ <View>
124
+ <Button title="Add Coffee $4.99" onPress={handleAddCoffee} />
125
+ <Button title="Add Full Order" onPress={handleAddFullOrder} />
126
+
127
+ {items.map((item, i) => (
128
+ <View key={i}>
129
+ <Text>{item.label}: ${item.amount}</Text>
130
+ <Button title="Remove" onPress={() => removeItem(i)} />
131
+ </View>
132
+ ))}
133
+
134
+ <Text>Total: ${total.toFixed(2)}</Text>
135
+
136
+ {error && <Text style={{ color: 'red' }}>{error.message}</Text>}
137
+
138
+ {isProcessing ? (
139
+ <ActivityIndicator />
140
+ ) : (
141
+ Platform.OS === 'ios' ? (
142
+ <ApplePayButton onPress={handlePay} buttonType="buy" buttonStyle="black" />
143
+ ) : (
144
+ <GooglePayButton onPress={handlePay} buttonType="buy" theme="dark" />
145
+ )
146
+ )}
147
+ </View>
148
+ )
149
+ }
150
+ ```
151
+
152
+ ### Basic Payment Flow (Without Hooks)
153
+
154
+ ```typescript
155
+ import {
156
+ HybridPaymentHandler,
157
+ ApplePayButton,
158
+ GooglePayButton,
159
+ createPaymentRequest,
160
+ } from 'react-native-pay'
161
+ import { Platform } from 'react-native'
162
+
163
+ // Check if payment service is available
164
+ const status = HybridPaymentHandler.payServiceStatus()
165
+ console.log('Can make payments:', status.canMakePayments)
166
+
167
+ // Create a payment request
168
+ const paymentRequest = createPaymentRequest({
169
+ merchantIdentifier: 'merchant.com.yourcompany.app',
170
+ amount: 29.99,
171
+ label: 'Coffee Subscription',
172
+ countryCode: 'US',
173
+ currencyCode: 'USD',
174
+ // Google Pay specific (optional)
175
+ googlePayEnvironment: 'TEST', // or 'PRODUCTION'
176
+ googlePayGateway: 'stripe',
177
+ googlePayGatewayMerchantId: 'your_gateway_merchant_id',
178
+ })
179
+
180
+ // Handle payment
181
+ const handlePayment = async () => {
182
+ try {
183
+ const result = await HybridPaymentHandler.startPayment(paymentRequest)
184
+
185
+ if (result.success) {
186
+ console.log('Payment successful:', result.transactionId)
187
+ console.log('Payment token:', result.token)
188
+ // Send token to your server for processing
189
+ } else {
190
+ console.error('Payment failed:', result.error)
191
+ }
192
+ } catch (error) {
193
+ console.error('Payment error:', error)
194
+ }
195
+ }
196
+
197
+ // Render platform-specific button
198
+ {Platform.OS === 'ios' ? (
199
+ <ApplePayButton
200
+ buttonType="buy"
201
+ buttonStyle="black"
202
+ onPress={handlePayment}
203
+ style={{ width: '100%', height: 48 }}
204
+ />
205
+ ) : (
206
+ <GooglePayButton
207
+ buttonType="buy"
208
+ theme="dark"
209
+ radius={4}
210
+ onPress={handlePayment}
211
+ style={{ width: '100%', height: 48 }}
212
+ />
213
+ )}
214
+ ```
215
+
216
+ ### Payment Request Configuration
217
+
218
+ ```typescript
219
+ interface PaymentRequest {
220
+ merchantIdentifier: string
221
+ countryCode: string
222
+ currencyCode: string
223
+ paymentItems: PaymentItem[]
224
+ merchantCapabilities: string[]
225
+ supportedNetworks: string[]
226
+ shippingType?: string
227
+ shippingMethods?: PaymentItem[]
228
+ billingContactRequired?: boolean
229
+ shippingContactRequired?: boolean
230
+ // Google Pay specific (Android only)
231
+ googlePayEnvironment?: 'TEST' | 'PRODUCTION'
232
+ googlePayGateway?: string
233
+ googlePayGatewayMerchantId?: string
234
+ }
235
+ ```
236
+
237
+ ### Utility Helpers
238
+
239
+ The package includes helpful utilities for common operations:
240
+
241
+ ```typescript
242
+ import {
243
+ createPaymentItem,
244
+ calculateTotal,
245
+ formatNetworkName,
246
+ } from 'react-native-pay'
247
+
248
+ // Create payment items
249
+ const item1 = createPaymentItem('Subscription', 29.99, 'final')
250
+ const item2 = createPaymentItem('Tax', 2.4, 'final')
251
+
252
+ // Calculate total
253
+ const total = calculateTotal([item1, item2]) // 32.39
254
+
255
+ // Format network names
256
+ formatNetworkName('visa') // "Visa"
257
+ formatNetworkName('amex') // "American Express"
258
+ ```
259
+
260
+ ## API Reference
261
+
262
+ ### React Hook
263
+
264
+ #### `usePaymentCheckout(config)`
265
+
266
+ All-in-one hook for payment checkout flow.
267
+
268
+ **Configuration:**
269
+
270
+ ```typescript
271
+ {
272
+ merchantIdentifier: string
273
+ countryCode?: string // Default: 'US'
274
+ currencyCode?: string // Default: 'USD'
275
+ supportedNetworks?: string[] // Default: ['visa', 'mastercard', 'amex', 'discover']
276
+ merchantCapabilities?: string[] // Default: ['3DS']
277
+ googlePayEnvironment?: 'TEST' | 'PRODUCTION'
278
+ googlePayGateway?: string
279
+ googlePayGatewayMerchantId?: string
280
+ }
281
+ ```
282
+
283
+ **Returns:**
284
+
285
+ ```typescript
286
+ {
287
+ // Payment availability
288
+ canMakePayments: boolean
289
+ canSetupCards: boolean
290
+ isCheckingStatus: boolean
291
+
292
+ // Cart management
293
+ items: PaymentItem[]
294
+ total: number
295
+ addItem: (label: string, amount: number, type?: 'final' | 'pending') => void
296
+ addItems: (items: Array<{ label, amount, type? }>) => void // Add multiple at once
297
+ removeItem: (index: number) => void
298
+ updateItem: (index: number, updates: Partial<PaymentItem>) => void
299
+ clearItems: () => void
300
+
301
+ // Payment processing
302
+ startPayment: () => Promise<PaymentResult | null>
303
+ isProcessing: boolean
304
+ result: PaymentResult | null
305
+ error: Error | null
306
+
307
+ // Utilities
308
+ reset: () => void
309
+ paymentRequest: PaymentRequest // Full request object
310
+ }
311
+ ```
312
+
313
+ **Example:**
314
+
315
+ ```typescript
316
+ const checkout = usePaymentCheckout({
317
+ merchantIdentifier: 'merchant.com.example',
318
+ currencyCode: 'USD',
319
+ countryCode: 'US',
320
+ })
321
+
322
+ // Add single item
323
+ checkout.addItem('Product', 29.99)
324
+
325
+ // Add multiple items at once
326
+ checkout.addItems([
327
+ { label: 'Product', amount: 29.99 },
328
+ { label: 'Shipping', amount: 5.0 },
329
+ { label: 'Tax', amount: 2.8, type: 'final' },
330
+ ])
331
+
332
+ // Check total
333
+ console.log(checkout.total) // 37.79
334
+
335
+ // Process payment
336
+ const result = await checkout.startPayment()
337
+ if (result?.success) {
338
+ // Handle success
339
+ }
340
+ ```
341
+
342
+ ### HybridPaymentHandler
343
+
344
+ #### `payServiceStatus(): PayServiceStatus`
345
+
346
+ Returns the current payment service availability.
347
+
348
+ ```typescript
349
+ const status = HybridPaymentHandler.payServiceStatus()
350
+ console.log(status.canMakePayments) // boolean
351
+ console.log(status.canSetupCards) // boolean
352
+ ```
353
+
354
+ #### `startPayment(request: PaymentRequest): Promise<PaymentResult>`
355
+
356
+ Initiates a payment request.
357
+
358
+ ```typescript
359
+ const result = await HybridPaymentHandler.startPayment(paymentRequest)
360
+ ```
361
+
362
+ #### `canMakePayments(usingNetworks: string[]): boolean`
363
+
364
+ Checks if the device can make payments using specific networks.
365
+
366
+ ```typescript
367
+ const canPay = HybridPaymentHandler.canMakePayments(['visa', 'mastercard'])
368
+ ```
369
+
370
+ ### Button Components
371
+
372
+ #### ApplePayButton (iOS)
373
+
374
+ ```typescript
375
+ <ApplePayButton
376
+ buttonType="buy" | "setup" | "book" | "donate" | "order" | "continue" | ...
377
+ buttonStyle="white" | "black" | "whiteOutline" | "automatic"
378
+ onPress={() => handlePayment()}
379
+ style={styles.button}
380
+ />
381
+ ```
382
+
383
+ #### GooglePayButton (Android)
384
+
385
+ ```typescript
386
+ <GooglePayButton
387
+ buttonType="buy" | "book" | "checkout" | "donate" | "order" | "pay" | "subscribe" | "plain"
388
+ theme="dark" | "light"
389
+ radius={4} // optional corner radius
390
+ onPress={() => handlePayment()}
391
+ style={styles.button}
392
+ />
393
+ ```
394
+
395
+ ## Architecture
396
+
397
+ ### Package Structure
398
+
399
+ ```
400
+ package/
401
+ ├── android/ # Android implementation
402
+ │ └── src/main/java/com/.../pay/
403
+ │ ├── Constants.kt # Shared constants
404
+ │ ├── GooglePayButtonFactory.kt # Button creation utility
405
+ │ ├── GooglePayRequestBuilder.kt # Payment request builder
406
+ │ ├── HybridGooglePayButton.kt # Button component
407
+ │ ├── HybridPaymentHandler.kt # Payment handler
408
+ │ ├── NitroPayPackage.kt # RN package
409
+ │ └── PaymentMapper.kt # Data mapper
410
+ ├── ios/ # iOS implementation
411
+ │ ├── ApplePayButtonFactory.swift # Button creation utility
412
+ │ ├── HybridApplePayButton.swift # Button component
413
+ │ ├── HybridPaymentHandler.swift # Payment handler
414
+ │ └── PassKitTypeMapper.swift # Type converter
415
+ ├── src/ # TypeScript/JavaScript
416
+ │ ├── specs/ # Nitro type specs
417
+ │ │ ├── ApplePayButton.nitro.ts
418
+ │ │ ├── GooglePayButton.nitro.ts
419
+ │ │ └── PaymentHandler.nitro.ts
420
+ │ ├── types/ # Type definitions
421
+ │ │ ├── Contact.ts
422
+ │ │ └── Payment.ts
423
+ │ ├── utils/ # Utility helpers
424
+ │ │ └── paymentHelpers.ts
425
+ │ ├── plugin/ # Expo config plugins
426
+ │ │ ├── withApplePay.ts
427
+ │ │ └── withGooglePay.ts
428
+ │ └── index.ts # Public API
429
+ └── nitrogen/ # Generated code (auto-generated)
430
+ ```
431
+
432
+ ### Design Principles
433
+
434
+ 1. **Separation of Concerns**: Each component has a single, well-defined responsibility
435
+ 2. **Factory Pattern**: Button and request creation abstracted into factory classes
436
+ 3. **Type Safety**: Comprehensive TypeScript definitions with runtime validation
437
+ 4. **Code Reusability**: Shared utilities and helpers reduce duplication
438
+ 5. **Platform Consistency**: Unified API abstracts platform differences
439
+
440
+ ## Contributing
441
+
442
+ Contributions are welcome! Please ensure:
443
+
444
+ - Code follows existing patterns and style
445
+ - All TypeScript types are properly defined
446
+ - Native code is properly documented
447
+ - Tests pass (when available)
448
+
449
+ ## License
450
+
451
+ MIT
452
+
453
+ ## Credits
454
+
455
+ Built with [Nitro Modules](https://nitro.margelo.com/) by [Margelo](https://margelo.com/)
@@ -0,0 +1,29 @@
1
+ project(NitroPay)
2
+ cmake_minimum_required(VERSION 3.9.0)
3
+
4
+ set (PACKAGE_NAME NitroPay)
5
+ set (CMAKE_VERBOSE_MAKEFILE ON)
6
+ set (CMAKE_CXX_STANDARD 20)
7
+
8
+ # Define C++ library and add all sources
9
+ add_library(${PACKAGE_NAME} SHARED
10
+ src/main/cpp/cpp-adapter.cpp
11
+ )
12
+
13
+ # Add Nitrogen specs :)
14
+ include(${CMAKE_SOURCE_DIR}/../nitrogen/generated/android/NitroPay+autolinking.cmake)
15
+
16
+ # Set up local includes
17
+ include_directories(
18
+ "src/main/cpp"
19
+ "../cpp"
20
+ )
21
+
22
+ find_library(LOG_LIB log)
23
+
24
+ # Link all libraries together
25
+ target_link_libraries(
26
+ ${PACKAGE_NAME}
27
+ ${LOG_LIB}
28
+ android # <-- Android core
29
+ )
@@ -0,0 +1,144 @@
1
+ buildscript {
2
+ repositories {
3
+ google()
4
+ mavenCentral()
5
+ }
6
+
7
+ dependencies {
8
+ classpath "com.android.tools.build:gradle:8.13.0"
9
+ }
10
+ }
11
+
12
+ def reactNativeArchitectures() {
13
+ def value = rootProject.getProperties().get("reactNativeArchitectures")
14
+ return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"]
15
+ }
16
+
17
+ def isNewArchitectureEnabled() {
18
+ return rootProject.hasProperty("newArchEnabled") && rootProject.getProperty("newArchEnabled") == "true"
19
+ }
20
+
21
+ apply plugin: "com.android.library"
22
+ apply plugin: 'org.jetbrains.kotlin.android'
23
+ apply from: '../nitrogen/generated/android/NitroPay+autolinking.gradle'
24
+ apply from: "./fix-prefab.gradle"
25
+
26
+ if (isNewArchitectureEnabled()) {
27
+ apply plugin: "com.facebook.react"
28
+ }
29
+
30
+ def getExtOrDefault(name) {
31
+ return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties["NitroPay_" + name]
32
+ }
33
+
34
+ def getExtOrIntegerDefault(name) {
35
+ return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["NitroPay_" + name]).toInteger()
36
+ }
37
+
38
+ android {
39
+ namespace "com.margelo.nitro.pay"
40
+
41
+ ndkVersion getExtOrDefault("ndkVersion")
42
+ compileSdkVersion getExtOrIntegerDefault("compileSdkVersion")
43
+
44
+ defaultConfig {
45
+ minSdkVersion getExtOrIntegerDefault("minSdkVersion")
46
+ targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
47
+ buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
48
+
49
+ externalNativeBuild {
50
+ cmake {
51
+ cppFlags "-frtti -fexceptions -Wall -Wextra -fstack-protector-all"
52
+ arguments "-DANDROID_STL=c++_shared", "-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON"
53
+ abiFilters (*reactNativeArchitectures())
54
+
55
+ buildTypes {
56
+ debug {
57
+ cppFlags "-O1 -g"
58
+ }
59
+ release {
60
+ cppFlags "-O2"
61
+ }
62
+ }
63
+ }
64
+ }
65
+ }
66
+
67
+ externalNativeBuild {
68
+ cmake {
69
+ path "CMakeLists.txt"
70
+ }
71
+ }
72
+
73
+ packagingOptions {
74
+ excludes = [
75
+ "META-INF",
76
+ "META-INF/**",
77
+ "**/libc++_shared.so",
78
+ "**/libfbjni.so",
79
+ "**/libjsi.so",
80
+ "**/libfolly_json.so",
81
+ "**/libfolly_runtime.so",
82
+ "**/libglog.so",
83
+ "**/libhermes.so",
84
+ "**/libhermes-executor-debug.so",
85
+ "**/libhermes_executor.so",
86
+ "**/libreactnative.so",
87
+ "**/libreactnativejni.so",
88
+ "**/libturbomodulejsijni.so",
89
+ "**/libreact_nativemodule_core.so",
90
+ "**/libjscexecutor.so"
91
+ ]
92
+ }
93
+
94
+ buildFeatures {
95
+ buildConfig true
96
+ prefab true
97
+ }
98
+
99
+ buildTypes {
100
+ release {
101
+ minifyEnabled false
102
+ }
103
+ }
104
+
105
+ lintOptions {
106
+ disable "GradleCompatible"
107
+ }
108
+
109
+ compileOptions {
110
+ sourceCompatibility JavaVersion.VERSION_1_8
111
+ targetCompatibility JavaVersion.VERSION_1_8
112
+ }
113
+
114
+ sourceSets {
115
+ main {
116
+ if (isNewArchitectureEnabled()) {
117
+ java.srcDirs += [
118
+ // React Codegen files
119
+ "${project.buildDir}/generated/source/codegen/java"
120
+ ]
121
+ }
122
+ }
123
+ }
124
+ }
125
+
126
+ repositories {
127
+ mavenCentral()
128
+ google()
129
+ }
130
+
131
+
132
+ dependencies {
133
+ // For < 0.71, this will be from the local maven repo
134
+ // For > 0.71, this will be replaced by `com.facebook.react:react-android:$version` by react gradle plugin
135
+ //noinspection GradleDynamicVersion
136
+ implementation "com.facebook.react:react-native:+"
137
+
138
+ // Add a dependency on NitroModules
139
+ implementation project(":react-native-nitro-modules")
140
+
141
+ // Google Pay dependencies
142
+ implementation 'com.google.android.gms:play-services-wallet:19.3.0'
143
+ }
144
+
@@ -0,0 +1,51 @@
1
+ tasks.configureEach { task ->
2
+ // Make sure that we generate our prefab publication file only after having built the native library
3
+ // so that not a header publication file, but a full configuration publication will be generated, which
4
+ // will include the .so file
5
+
6
+ def prefabConfigurePattern = ~/^prefab(.+)ConfigurePackage$/
7
+ def matcher = task.name =~ prefabConfigurePattern
8
+ if (matcher.matches()) {
9
+ def variantName = matcher[0][1]
10
+ task.outputs.upToDateWhen { false }
11
+ task.dependsOn("externalNativeBuild${variantName}")
12
+ }
13
+ }
14
+
15
+ afterEvaluate {
16
+ def abis = reactNativeArchitectures()
17
+ rootProject.allprojects.each { proj ->
18
+ if (proj === rootProject) return
19
+
20
+ def dependsOnThisLib = proj.configurations.findAll { it.canBeResolved }.any { config ->
21
+ config.dependencies.any { dep ->
22
+ dep.group == project.group && dep.name == project.name
23
+ }
24
+ }
25
+ if (!dependsOnThisLib && proj != project) return
26
+
27
+ if (!proj.plugins.hasPlugin('com.android.application') && !proj.plugins.hasPlugin('com.android.library')) {
28
+ return
29
+ }
30
+
31
+ def variants = proj.android.hasProperty('applicationVariants') ? proj.android.applicationVariants : proj.android.libraryVariants
32
+ // Touch the prefab_config.json files to ensure that in ExternalNativeJsonGenerator.kt we will re-trigger the prefab CLI to
33
+ // generate a libnameConfig.cmake file that will contain our native library (.so).
34
+ // See this condition: https://cs.android.com/android-studio/platform/tools/base/+/mirror-goog-studio-main:build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/ExternalNativeJsonGenerator.kt;l=207-219?q=createPrefabBuildSystemGlue
35
+ variants.all { variant ->
36
+ def variantName = variant.name
37
+ abis.each { abi ->
38
+ def searchDir = new File(proj.projectDir, ".cxx/${variantName}")
39
+ if (!searchDir.exists()) return
40
+ def matches = []
41
+ searchDir.eachDir { randomDir ->
42
+ def prefabFile = new File(randomDir, "${abi}/prefab_config.json")
43
+ if (prefabFile.exists()) matches << prefabFile
44
+ }
45
+ matches.each { prefabConfig ->
46
+ prefabConfig.setLastModified(System.currentTimeMillis())
47
+ }
48
+ }
49
+ }
50
+ }
51
+ }