@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,281 @@
1
+ import { useState, useCallback, useMemo, useEffect } from 'react'
2
+ import { NitroModules } from 'react-native-nitro-modules'
3
+ import type { PaymentHandler } from '../specs/PaymentHandler.nitro'
4
+
5
+ const HybridPaymentHandler =
6
+ NitroModules.createHybridObject<PaymentHandler>('PaymentHandler')
7
+ import type {
8
+ PaymentRequest,
9
+ PaymentResult,
10
+ PaymentItem,
11
+ PayServiceStatus,
12
+ GooglePayEnvironment,
13
+ } from '../types'
14
+ import { createPaymentItem, calculateTotal } from '../utils'
15
+
16
+ export interface UsePaymentCheckoutConfig {
17
+ merchantIdentifier: string
18
+ countryCode?: string
19
+ currencyCode?: string
20
+ supportedNetworks?: string[]
21
+ merchantCapabilities?: string[]
22
+ googlePayEnvironment?: GooglePayEnvironment
23
+ googlePayGateway?: string
24
+ googlePayGatewayMerchantId?: string
25
+ }
26
+
27
+ export interface UsePaymentCheckoutReturn {
28
+ // Payment availability
29
+ canMakePayments: boolean
30
+ canSetupCards: boolean
31
+ isCheckingStatus: boolean
32
+
33
+ // Cart management
34
+ items: PaymentItem[]
35
+ total: number
36
+ addItem: (label: string, amount: number, type?: 'final' | 'pending') => void
37
+ addItems: (
38
+ items: Array<{ label: string; amount: number; type?: 'final' | 'pending' }>
39
+ ) => void
40
+ removeItem: (index: number) => void
41
+ updateItem: (index: number, updates: Partial<PaymentItem>) => void
42
+ clearItems: () => void
43
+
44
+ // Payment processing
45
+ startPayment: () => Promise<PaymentResult | null>
46
+ isProcessing: boolean
47
+ result: PaymentResult | null
48
+ error: Error | null
49
+
50
+ // Utilities
51
+ reset: () => void
52
+ paymentRequest: PaymentRequest
53
+ }
54
+
55
+ /**
56
+ * All-in-one hook for payment checkout flow
57
+ *
58
+ * Handles:
59
+ * - Payment availability checking
60
+ * - Shopping cart management
61
+ * - Payment processing
62
+ * - State management
63
+ *
64
+ * @param config - Payment configuration
65
+ * @returns Complete payment checkout interface
66
+ *
67
+ * @example
68
+ * ```typescript
69
+ * function CheckoutScreen() {
70
+ * const {
71
+ * canMakePayments,
72
+ * items,
73
+ * total,
74
+ * addItem,
75
+ * addItems,
76
+ * removeItem,
77
+ * startPayment,
78
+ * isProcessing,
79
+ * error,
80
+ * } = usePaymentCheckout({
81
+ * merchantIdentifier: 'merchant.com.example',
82
+ * currencyCode: 'USD',
83
+ * countryCode: 'US',
84
+ * })
85
+ *
86
+ * // Add single item
87
+ * const handleAddOne = () => addItem('Coffee', 4.99)
88
+ *
89
+ * // Add multiple items at once
90
+ * const handleAddCart = () => addItems([
91
+ * { label: 'Coffee', amount: 4.99 },
92
+ * { label: 'Sandwich', amount: 8.99 },
93
+ * { label: 'Tax', amount: 1.20, type: 'final' }
94
+ * ])
95
+ *
96
+ * if (!canMakePayments) {
97
+ * return <Text>Payment not available</Text>
98
+ * }
99
+ *
100
+ * return (
101
+ * <>
102
+ * <Button title="Add Coffee" onPress={handleAddOne} />
103
+ * <Button title="Add Cart" onPress={handleAddCart} />
104
+ * <Text>Total: ${total.toFixed(2)}</Text>
105
+ * {isProcessing ? (
106
+ * <ActivityIndicator />
107
+ * ) : (
108
+ * <ApplePayButton onPress={startPayment} />
109
+ * )}
110
+ * {error && <Text>Error: {error.message}</Text>}
111
+ * </>
112
+ * )
113
+ * }
114
+ * ```
115
+ */
116
+ export function usePaymentCheckout(
117
+ config: UsePaymentCheckoutConfig
118
+ ): UsePaymentCheckoutReturn {
119
+ // Payment status state
120
+ const [status, setStatus] = useState<PayServiceStatus | null>(null)
121
+ const [isCheckingStatus, setIsCheckingStatus] = useState(true)
122
+
123
+ // Cart state
124
+ const [items, setItems] = useState<PaymentItem[]>([])
125
+
126
+ // Payment state
127
+ const [isProcessing, setIsProcessing] = useState(false)
128
+ const [result, setResult] = useState<PaymentResult | null>(null)
129
+ const [error, setError] = useState<Error | null>(null)
130
+
131
+ // Check payment status on mount
132
+ useEffect(() => {
133
+ try {
134
+ const paymentStatus = HybridPaymentHandler.payServiceStatus()
135
+ setStatus(paymentStatus)
136
+ } catch (err) {
137
+ console.error('Failed to check payment status:', err)
138
+ setStatus({ canMakePayments: false, canSetupCards: false })
139
+ } finally {
140
+ setIsCheckingStatus(false)
141
+ }
142
+ }, [])
143
+
144
+ // Calculate total
145
+ const total = useMemo(() => calculateTotal(items), [items])
146
+
147
+ // Build payment request
148
+ const paymentRequest = useMemo<PaymentRequest>(() => {
149
+ const {
150
+ merchantIdentifier,
151
+ countryCode = 'US',
152
+ currencyCode = 'USD',
153
+ supportedNetworks = ['visa', 'mastercard', 'amex', 'discover'],
154
+ merchantCapabilities = ['3DS'],
155
+ googlePayEnvironment,
156
+ googlePayGateway,
157
+ googlePayGatewayMerchantId,
158
+ } = config
159
+
160
+ return {
161
+ merchantIdentifier,
162
+ countryCode,
163
+ currencyCode,
164
+ supportedNetworks,
165
+ merchantCapabilities,
166
+ paymentItems:
167
+ items.length > 0 ? items : [createPaymentItem('Total', 0, 'final')],
168
+ googlePayEnvironment,
169
+ googlePayGateway,
170
+ googlePayGatewayMerchantId,
171
+ }
172
+ }, [config, items])
173
+
174
+ // Cart operations
175
+ const addItem = useCallback(
176
+ (label: string, amount: number, type: 'final' | 'pending' = 'final') => {
177
+ const item = createPaymentItem(label, amount, type)
178
+ setItems((prev) => [...prev, item])
179
+ },
180
+ []
181
+ )
182
+
183
+ const addItems = useCallback(
184
+ (
185
+ itemsToAdd: Array<{
186
+ label: string
187
+ amount: number
188
+ type?: 'final' | 'pending'
189
+ }>
190
+ ) => {
191
+ const newItems = itemsToAdd.map((item) =>
192
+ createPaymentItem(item.label, item.amount, item.type || 'final')
193
+ )
194
+ setItems((prev) => [...prev, ...newItems])
195
+ },
196
+ []
197
+ )
198
+
199
+ const removeItem = useCallback((index: number) => {
200
+ setItems((prev) => prev.filter((_, i) => i !== index))
201
+ }, [])
202
+
203
+ const updateItem = useCallback(
204
+ (index: number, updates: Partial<PaymentItem>) => {
205
+ setItems((prev) =>
206
+ prev.map((item, i) => (i === index ? { ...item, ...updates } : item))
207
+ )
208
+ },
209
+ []
210
+ )
211
+
212
+ const clearItems = useCallback(() => {
213
+ setItems([])
214
+ }, [])
215
+
216
+ // Start payment
217
+ const startPayment = useCallback(async (): Promise<PaymentResult | null> => {
218
+ if (items.length === 0) {
219
+ const emptyCartError = new Error('Cart is empty')
220
+ setError(emptyCartError)
221
+ return null
222
+ }
223
+
224
+ setIsProcessing(true)
225
+ setResult(null)
226
+ setError(null)
227
+
228
+ try {
229
+ const paymentResult =
230
+ await HybridPaymentHandler.startPayment(paymentRequest)
231
+
232
+ setResult(paymentResult)
233
+
234
+ if (!paymentResult.success) {
235
+ setError(new Error(paymentResult.error || 'Payment failed'))
236
+ }
237
+
238
+ return paymentResult
239
+ } catch (err) {
240
+ const paymentError =
241
+ err instanceof Error ? err : new Error('Payment processing failed')
242
+ setError(paymentError)
243
+ return null
244
+ } finally {
245
+ setIsProcessing(false)
246
+ }
247
+ }, [items, paymentRequest])
248
+
249
+ // Reset all state
250
+ const reset = useCallback(() => {
251
+ setIsProcessing(false)
252
+ setResult(null)
253
+ setError(null)
254
+ }, [])
255
+
256
+ return {
257
+ // Status
258
+ canMakePayments: status?.canMakePayments ?? false,
259
+ canSetupCards: status?.canSetupCards ?? false,
260
+ isCheckingStatus,
261
+
262
+ // Cart
263
+ items,
264
+ total,
265
+ addItem,
266
+ addItems,
267
+ removeItem,
268
+ updateItem,
269
+ clearItems,
270
+
271
+ // Payment
272
+ startPayment,
273
+ isProcessing,
274
+ result,
275
+ error,
276
+
277
+ // Utilities
278
+ reset,
279
+ paymentRequest,
280
+ }
281
+ }
package/src/index.ts ADDED
@@ -0,0 +1,32 @@
1
+ import { NitroModules, getHostComponent } from 'react-native-nitro-modules'
2
+ import type {
3
+ ApplePayButtonProps,
4
+ ApplePayButtonMethods,
5
+ } from './specs/ApplePayButton.nitro'
6
+ import type {
7
+ GooglePayButtonProps,
8
+ GooglePayButtonMethods,
9
+ } from './specs/GooglePayButton.nitro'
10
+ import type { PaymentHandler } from './specs/PaymentHandler.nitro'
11
+
12
+ export const HybridPaymentHandler =
13
+ NitroModules.createHybridObject<PaymentHandler>('PaymentHandler')
14
+
15
+ export type { PaymentHandler } from './specs/PaymentHandler.nitro'
16
+
17
+ import ApplePayButtonConfig from '../nitrogen/generated/shared/json/ApplePayButtonConfig.json'
18
+ import GooglePayButtonConfig from '../nitrogen/generated/shared/json/GooglePayButtonConfig.json'
19
+
20
+ export const ApplePayButton = getHostComponent<
21
+ ApplePayButtonProps,
22
+ ApplePayButtonMethods
23
+ >('ApplePayButton', () => ApplePayButtonConfig)
24
+
25
+ export const GooglePayButton = getHostComponent<
26
+ GooglePayButtonProps,
27
+ GooglePayButtonMethods
28
+ >('GooglePayButton', () => GooglePayButtonConfig)
29
+
30
+ export * from './types'
31
+ export * from './utils'
32
+ export * from './hooks'
@@ -0,0 +1,17 @@
1
+ import type { ConfigPlugin } from 'expo/config-plugins'
2
+ import type { ReactNativePayPluginProps } from './type'
3
+ import { withApplePay } from './withApplePay'
4
+ import { withGooglePay } from './withGooglePay'
5
+
6
+ const withReactNativePay: ConfigPlugin<ReactNativePayPluginProps> = (
7
+ config,
8
+ props
9
+ ) => {
10
+ config = withGooglePay(config, props)
11
+
12
+ config = withApplePay(config, props)
13
+
14
+ return config
15
+ }
16
+
17
+ export default withReactNativePay
@@ -0,0 +1,4 @@
1
+ export interface ReactNativePayPluginProps {
2
+ merchantIdentifier?: string | string[]
3
+ enableGooglePay?: boolean
4
+ }
@@ -0,0 +1,44 @@
1
+ import { withEntitlementsPlist, type ConfigPlugin } from 'expo/config-plugins'
2
+ import type { ReactNativePayPluginProps } from './type'
3
+
4
+ export function setApplePayEntitlement(
5
+ merchantIdentifiers: string | string[],
6
+ entitlements: Record<string, any>
7
+ ): Record<string, any> {
8
+ const key = 'com.apple.developer.in-app-payments'
9
+
10
+ const merchants: string[] = entitlements[key] ?? []
11
+
12
+ if (!Array.isArray(merchantIdentifiers)) {
13
+ merchantIdentifiers = [merchantIdentifiers]
14
+ }
15
+
16
+ for (const id of merchantIdentifiers) {
17
+ if (id && !merchants.includes(id)) {
18
+ merchants.push(id)
19
+ }
20
+ }
21
+
22
+ if (merchants.length) {
23
+ entitlements[key] = merchants
24
+ }
25
+ return entitlements
26
+ }
27
+
28
+ export const withApplePay: ConfigPlugin<ReactNativePayPluginProps> = (
29
+ expoConfig,
30
+ { merchantIdentifier }
31
+ ) => {
32
+ // If merchantIdentifier is not passed Apple Pay won't be initialize
33
+ if (!merchantIdentifier) {
34
+ return expoConfig
35
+ }
36
+
37
+ return withEntitlementsPlist(expoConfig, (config) => {
38
+ config.modResults = setApplePayEntitlement(
39
+ merchantIdentifier,
40
+ config.modResults
41
+ )
42
+ return config
43
+ })
44
+ }
@@ -0,0 +1,41 @@
1
+ import {
2
+ AndroidConfig,
3
+ withAndroidManifest,
4
+ type ConfigPlugin,
5
+ } from 'expo/config-plugins'
6
+ import type { ReactNativePayPluginProps } from './type'
7
+
8
+ const {
9
+ addMetaDataItemToMainApplication,
10
+ getMainApplicationOrThrow,
11
+ removeMetaDataItemFromMainApplication,
12
+ } = AndroidConfig.Manifest
13
+
14
+ export const withGooglePay: ConfigPlugin<ReactNativePayPluginProps> = (
15
+ expoConfig,
16
+ { enableGooglePay = false }
17
+ ) => {
18
+ return withAndroidManifest(expoConfig, (config) => {
19
+ config.modResults = setGooglePayMetaData(enableGooglePay, config.modResults)
20
+ return config
21
+ })
22
+ }
23
+
24
+ export function setGooglePayMetaData(
25
+ enabled: boolean,
26
+ modResults: AndroidConfig.Manifest.AndroidManifest
27
+ ): AndroidConfig.Manifest.AndroidManifest {
28
+ const GOOGLE_PAY_META_NAME = 'com.google.android.gms.wallet.api.enabled'
29
+ const mainApplication = getMainApplicationOrThrow(modResults)
30
+ if (enabled) {
31
+ addMetaDataItemToMainApplication(
32
+ mainApplication,
33
+ GOOGLE_PAY_META_NAME,
34
+ 'true'
35
+ )
36
+ } else {
37
+ removeMetaDataItemFromMainApplication(mainApplication, GOOGLE_PAY_META_NAME)
38
+ }
39
+
40
+ return modResults
41
+ }
@@ -0,0 +1,37 @@
1
+ import type {
2
+ HybridView,
3
+ HybridViewProps,
4
+ HybridViewMethods,
5
+ } from 'react-native-nitro-modules'
6
+
7
+ export type ApplePayButtonType =
8
+ | 'buy'
9
+ | 'setUp'
10
+ | 'book'
11
+ | 'donate'
12
+ | 'continue'
13
+ | 'reload'
14
+ | 'addMoney'
15
+ | 'topUp'
16
+ | 'order'
17
+ | 'rent'
18
+ | 'support'
19
+ | 'contribute'
20
+ | 'tip'
21
+ export type ApplePayButtonStyle = 'white' | 'whiteOutline' | 'black'
22
+
23
+ export interface ApplePayButtonProps extends HybridViewProps {
24
+ buttonType: ApplePayButtonType
25
+ buttonStyle: ApplePayButtonStyle
26
+ onPress?: () => void
27
+ }
28
+
29
+ export interface ApplePayButtonMethods extends HybridViewMethods {
30
+ // No additional methods needed for the button
31
+ }
32
+
33
+ export type ApplePayButton = HybridView<
34
+ ApplePayButtonProps,
35
+ ApplePayButtonMethods,
36
+ { ios: 'swift' }
37
+ >
@@ -0,0 +1,34 @@
1
+ import type {
2
+ HybridView,
3
+ HybridViewProps,
4
+ HybridViewMethods,
5
+ } from 'react-native-nitro-modules'
6
+
7
+ export type GooglePayButtonType =
8
+ | 'buy'
9
+ | 'book'
10
+ | 'checkout'
11
+ | 'donate'
12
+ | 'order'
13
+ | 'pay'
14
+ | 'subscribe'
15
+ | 'plain'
16
+
17
+ export type GooglePayButtonTheme = 'dark' | 'light'
18
+
19
+ export interface GooglePayButtonProps extends HybridViewProps {
20
+ buttonType: GooglePayButtonType
21
+ theme: GooglePayButtonTheme
22
+ radius?: number
23
+ onPress?: () => void
24
+ }
25
+
26
+ export interface GooglePayButtonMethods extends HybridViewMethods {
27
+ // No additional methods needed for the button
28
+ }
29
+
30
+ export type GooglePayButton = HybridView<
31
+ GooglePayButtonProps,
32
+ GooglePayButtonMethods,
33
+ { android: 'kotlin' }
34
+ >
@@ -0,0 +1,13 @@
1
+ import type { HybridObject } from 'react-native-nitro-modules'
2
+ import type {
3
+ PayServiceStatus,
4
+ PaymentRequest,
5
+ PaymentResult,
6
+ } from '../types/Payment'
7
+
8
+ export interface PaymentHandler
9
+ extends HybridObject<{ ios: 'swift'; android: 'kotlin' }> {
10
+ payServiceStatus(): PayServiceStatus
11
+ startPayment(request: PaymentRequest): Promise<PaymentResult>
12
+ canMakePayments(usingNetworks: string[]): boolean
13
+ }
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Contact types based on CNContact from Contacts framework
3
+ * @see https://developer.apple.com/documentation/contacts/cncontact
4
+ */
5
+
6
+ export type CNContactType = 'person' | 'organization'
7
+
8
+ export interface CNPhoneNumber {
9
+ stringValue: string
10
+ }
11
+
12
+ export interface CNPostalAddress {
13
+ street?: string
14
+ city?: string
15
+ state?: string
16
+ postalCode?: string
17
+ country?: string
18
+ isoCountryCode?: string
19
+ }
20
+
21
+ export interface CNLabeledPhoneNumber {
22
+ label?: string
23
+ value: CNPhoneNumber
24
+ }
25
+
26
+ export interface CNLabeledEmailAddress {
27
+ label?: string
28
+ value: string
29
+ }
30
+
31
+ export interface CNLabeledPostalAddress {
32
+ label?: string
33
+ value: CNPostalAddress
34
+ }
35
+
36
+ export interface CNContact {
37
+ identifier: string
38
+ contactType: CNContactType
39
+ namePrefix: string
40
+ givenName: string
41
+ middleName: string
42
+ familyName: string
43
+ previousFamilyName: string
44
+ nameSuffix: string
45
+ nickname: string
46
+ organizationName: string
47
+ departmentName: string
48
+ jobTitle: string
49
+ phoneticGivenName: string
50
+ phoneticMiddleName: string
51
+ phoneticFamilyName: string
52
+ phoneticOrganizationName?: string // Available from iOS 10.0+
53
+ note: string
54
+ imageDataAvailable?: boolean // Available from iOS 9.0+
55
+ phoneNumbers: CNLabeledPhoneNumber[]
56
+ emailAddresses: CNLabeledEmailAddress[]
57
+ postalAddresses: CNLabeledPostalAddress[]
58
+ }
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Payment types based on PassKit framework
3
+ * @see https://developer.apple.com/documentation/passkit
4
+ */
5
+
6
+ import type { CNContact } from './Contact'
7
+
8
+ export type PaymentItemType = 'final' | 'pending'
9
+
10
+ export type PaymentMethodType =
11
+ | 'unknown'
12
+ | 'debit'
13
+ | 'credit'
14
+ | 'prepaid'
15
+ | 'store'
16
+
17
+ export type PaymentNetwork =
18
+ | 'visa'
19
+ | 'mastercard'
20
+ | 'amex'
21
+ | 'discover'
22
+ | 'jcb'
23
+ | 'maestro'
24
+ | 'electron'
25
+ | 'elo'
26
+ | 'idcredit'
27
+ | 'interac'
28
+ | 'privateLabel'
29
+
30
+ export type PassActivationState =
31
+ | 'activated'
32
+ | 'requiresActivation'
33
+ | 'activating'
34
+ | 'suspended'
35
+ | 'deactivated'
36
+
37
+ export type GooglePayEnvironment = 'TEST' | 'PRODUCTION'
38
+
39
+ export interface PKPass {
40
+ passTypeIdentifier: string
41
+ serialNumber: string
42
+ organizationName?: string
43
+ }
44
+
45
+ export interface PKSecureElementPass extends PKPass {
46
+ primaryAccountIdentifier: string
47
+ primaryAccountNumberSuffix: string
48
+ deviceAccountIdentifier: string
49
+ deviceAccountNumberSuffix: string
50
+ passActivationState: PassActivationState
51
+ devicePassIdentifier?: string
52
+ pairedTerminalIdentifier?: string
53
+ }
54
+
55
+ export interface PaymentItem {
56
+ label: string
57
+ amount: number
58
+ type: PaymentItemType
59
+ }
60
+
61
+ export interface PaymentMethod {
62
+ displayName?: string
63
+ network?: PaymentNetwork
64
+ type: PaymentMethodType
65
+ secureElementPass?: PKSecureElementPass // Available from iOS 13.4+
66
+ billingAddress?: CNContact // Available from iOS 13.0+
67
+ }
68
+
69
+ export interface PaymentToken {
70
+ paymentMethod: PaymentMethod
71
+ transactionIdentifier: string
72
+ paymentData: string // Base64 encoded Data from PKPaymentToken
73
+ }
74
+ export interface PaymentRequest {
75
+ merchantIdentifier: string
76
+ countryCode: string
77
+ currencyCode: string
78
+ paymentItems: PaymentItem[]
79
+ merchantCapabilities: string[]
80
+ supportedNetworks: string[]
81
+ shippingType?: string
82
+ shippingMethods?: PaymentItem[]
83
+ billingContactRequired?: boolean
84
+ shippingContactRequired?: boolean
85
+ // Google Pay specific configuration (Android only)
86
+ googlePayEnvironment?: GooglePayEnvironment
87
+ googlePayGateway?: string
88
+ googlePayGatewayMerchantId?: string
89
+ }
90
+
91
+ export interface PaymentResult {
92
+ success: boolean
93
+ transactionId?: string
94
+ token?: PaymentToken
95
+ error?: string
96
+ }
97
+
98
+ export interface PayServiceStatus {
99
+ canMakePayments: boolean
100
+ canSetupCards: boolean
101
+ }
102
+
103
+ // Backward compatibility alias
104
+ export type ApplePayStatus = PayServiceStatus
@@ -0,0 +1,2 @@
1
+ export * from './Contact'
2
+ export * from './Payment'
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Utility functions for react-native-pay
3
+ */
4
+
5
+ export * from './paymentHelpers'