applepay-rn 0.0.1
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.
- package/ApplepayRn.podspec +22 -0
- package/LICENSE +20 -0
- package/README.md +551 -0
- package/android/build.gradle +67 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/java/com/applepayrn/ApplepayRnPackage.kt +17 -0
- package/android/src/main/java/com/applepayrn/ApplepayRnView.kt +15 -0
- package/android/src/main/java/com/applepayrn/ApplepayRnViewManager.kt +41 -0
- package/ios/ApplePayBridge.swift +68 -0
- package/ios/ApplepayRnView.h +14 -0
- package/ios/ApplepayRnView.mm +110 -0
- package/lib/module/ApplePayView.js +70 -0
- package/lib/module/ApplePayView.js.map +1 -0
- package/lib/module/NativeApplePayView.js +7 -0
- package/lib/module/NativeApplePayView.js.map +1 -0
- package/lib/module/index.js +4 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/types.js +2 -0
- package/lib/module/types.js.map +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/ApplePayView.d.ts +17 -0
- package/lib/typescript/src/ApplePayView.d.ts.map +1 -0
- package/lib/typescript/src/NativeApplePayView.d.ts +26 -0
- package/lib/typescript/src/NativeApplePayView.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +4 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/types.d.ts +71 -0
- package/lib/typescript/src/types.d.ts.map +1 -0
- package/package.json +177 -0
- package/src/ApplePayView.tsx +118 -0
- package/src/NativeApplePayView.ts +20 -0
- package/src/index.tsx +16 -0
- package/src/types.ts +91 -0
|
@@ -0,0 +1,22 @@
|
|
|
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 = "ApplepayRn"
|
|
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 => '16.0' }
|
|
14
|
+
s.source = { :git => "https://github.com/Tap-Payments/ApplePay-RN.git", :tag => "#{s.version}" }
|
|
15
|
+
|
|
16
|
+
s.source_files = "ios/**/*.{h,m,mm,swift}"
|
|
17
|
+
s.private_header_files = "ios/**/*.h"
|
|
18
|
+
|
|
19
|
+
s.dependency 'ApplePay-iOS', '0.0.4'
|
|
20
|
+
|
|
21
|
+
install_modules_dependencies(s)
|
|
22
|
+
end
|
package/LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 MahmoudAllam
|
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
5
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
6
|
+
in the Software without restriction, including without limitation the rights
|
|
7
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
8
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
9
|
+
furnished to do so, subject to the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be included in all
|
|
12
|
+
copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
15
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
16
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
17
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
18
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
19
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
20
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,551 @@
|
|
|
1
|
+
# ApplePay-RN
|
|
2
|
+
|
|
3
|
+
A comprehensive React Native bridge to Apple Pay integration that brings native iOS Apple Pay functionality to React Native apps. Simplifies secure payment processing with Apple Pay, including native callback handling and seamless TypeScript support.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
ApplePay-RN provides a complete React Native wrapper around the native Apple Pay iOS framework. It enables React Native developers to integrate Apple Pay payments into their applications with minimal effort while maintaining full access to native payment capabilities.
|
|
8
|
+
|
|
9
|
+
**Key Features:**
|
|
10
|
+
- ✅ Native Apple Pay integration for React Native
|
|
11
|
+
- ✅ TypeScript support with full type definitions
|
|
12
|
+
- ✅ Comprehensive callback system for payment events
|
|
13
|
+
- ✅ Flexible configuration options matching native API
|
|
14
|
+
- ✅ Support for multiple payment scenarios (one-time, recurring, deferred)
|
|
15
|
+
- ✅ Automatic native module linking (autolinking)
|
|
16
|
+
- ✅ Example app demonstrating best practices
|
|
17
|
+
|
|
18
|
+
## Requirements
|
|
19
|
+
|
|
20
|
+
- **React Native**: 0.60+
|
|
21
|
+
- **iOS**: 16.0+ (minimum deployment target)
|
|
22
|
+
- **Xcode**: 14.0+
|
|
23
|
+
- **CocoaPods**: For iOS dependency management
|
|
24
|
+
- **Node.js**: 14.0+
|
|
25
|
+
- **Yarn/npm**: For JavaScript package management
|
|
26
|
+
|
|
27
|
+
## Installation
|
|
28
|
+
|
|
29
|
+
### 1. Install the Package
|
|
30
|
+
|
|
31
|
+
Using npm:
|
|
32
|
+
```bash
|
|
33
|
+
npm install @tap-payments/applepay-rn
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Using yarn:
|
|
37
|
+
```bash
|
|
38
|
+
yarn add @tap-payments/applepay-rn
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### 2. Install Pod Dependencies
|
|
42
|
+
|
|
43
|
+
Navigate to the iOS directory and install CocoaPods dependencies:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
cd ios
|
|
47
|
+
pod install
|
|
48
|
+
cd ..
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### 3. Link Native Module (if not auto-linked)
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
npx react-native link @tap-payments/applepay-rn
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Quick Start
|
|
58
|
+
|
|
59
|
+
### 1. Import the Component
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
import ApplePayView from '@tap-payments/applepay-rn';
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### 2. Create Configuration
|
|
66
|
+
|
|
67
|
+
Define your payment configuration:
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
const applePayConfig = {
|
|
71
|
+
// REQUIRED
|
|
72
|
+
publicKey: "pk_test_********",
|
|
73
|
+
scope: "AppleToken",
|
|
74
|
+
merchant: {
|
|
75
|
+
id: "********"
|
|
76
|
+
},
|
|
77
|
+
|
|
78
|
+
// OPTIONAL
|
|
79
|
+
interface: {
|
|
80
|
+
locale: "en",
|
|
81
|
+
theme: "light",
|
|
82
|
+
edges: "curved",
|
|
83
|
+
type: "buy"
|
|
84
|
+
},
|
|
85
|
+
|
|
86
|
+
// REQUIRED
|
|
87
|
+
customer: {
|
|
88
|
+
name: [
|
|
89
|
+
{
|
|
90
|
+
lang: "en",
|
|
91
|
+
first: "John",
|
|
92
|
+
last: "Smith"
|
|
93
|
+
}
|
|
94
|
+
],
|
|
95
|
+
contact: {
|
|
96
|
+
email: "john.smith@example.com",
|
|
97
|
+
phone: {
|
|
98
|
+
countryCode: "+1",
|
|
99
|
+
number: "5551234567"
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
|
|
104
|
+
// REQUIRED
|
|
105
|
+
acceptance: {
|
|
106
|
+
supportedBrands: ["visa", "masterCard"],
|
|
107
|
+
supportedCards: ["credit", "debit"]
|
|
108
|
+
},
|
|
109
|
+
|
|
110
|
+
// REQUIRED
|
|
111
|
+
transaction: {
|
|
112
|
+
amount: "20.00",
|
|
113
|
+
currency: "KWD"
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### 3. Use the Component
|
|
119
|
+
|
|
120
|
+
```typescript
|
|
121
|
+
import React from 'react';
|
|
122
|
+
import { View, StyleSheet } from 'react-native';
|
|
123
|
+
import ApplePayView from '@tap-payments/applepay-rn';
|
|
124
|
+
|
|
125
|
+
const App = () => {
|
|
126
|
+
return (
|
|
127
|
+
<View style={styles.container}>
|
|
128
|
+
<ApplePayView
|
|
129
|
+
config={applePayConfig}
|
|
130
|
+
onReady={() => console.log('Apple Pay ready')}
|
|
131
|
+
onClick={() => console.log('Button clicked')}
|
|
132
|
+
onSuccess={(data) => console.log('Payment successful:', data)}
|
|
133
|
+
onError={(error) => console.log('Payment error:', error)}
|
|
134
|
+
onCanceled={() => console.log('Payment canceled')}
|
|
135
|
+
onMerchantValidation={(data) => console.log('Merchant validation:', data)}
|
|
136
|
+
style={styles.applePayButton}
|
|
137
|
+
/>
|
|
138
|
+
</View>
|
|
139
|
+
);
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
const styles = StyleSheet.create({
|
|
143
|
+
container: {
|
|
144
|
+
flex: 1,
|
|
145
|
+
justifyContent: 'center',
|
|
146
|
+
paddingHorizontal: 16,
|
|
147
|
+
},
|
|
148
|
+
applePayButton: {
|
|
149
|
+
height: 50,
|
|
150
|
+
},
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
export default App;
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## Configuration Parameters
|
|
157
|
+
|
|
158
|
+
### Core Configuration
|
|
159
|
+
|
|
160
|
+
| Parameter | Description | Required | Type | Example |
|
|
161
|
+
|-----------|-------------|----------|------|---------|
|
|
162
|
+
| `publicKey` | Your Tap public API key for authentication | ✅ | String | `"pk_test_********"` |
|
|
163
|
+
| `scope` | Token scope type ('AppleToken' or 'TapToken') | ✅ | String | `"AppleToken"` |
|
|
164
|
+
| `merchant` | Merchant account information with ID | ✅ | Object | `{ id: "********" }` |
|
|
165
|
+
|
|
166
|
+
### Transaction Configuration (REQUIRED)
|
|
167
|
+
|
|
168
|
+
```typescript
|
|
169
|
+
const transaction = {
|
|
170
|
+
// REQUIRED: Transaction amount as string
|
|
171
|
+
amount: "20.00",
|
|
172
|
+
|
|
173
|
+
// REQUIRED: ISO 4217 currency code (e.g., KWD, USD, AED)
|
|
174
|
+
currency: "KWD",
|
|
175
|
+
|
|
176
|
+
// OPTIONAL: Coupon code for discount
|
|
177
|
+
couponCode: "SAVE10",
|
|
178
|
+
|
|
179
|
+
// OPTIONAL: Shipping options for the transaction
|
|
180
|
+
shipping: [
|
|
181
|
+
{
|
|
182
|
+
// REQUIRED: Shipping method label
|
|
183
|
+
label: "Standard Shipping",
|
|
184
|
+
// REQUIRED: Shipping description
|
|
185
|
+
detail: "5–7 business days",
|
|
186
|
+
// REQUIRED: Shipping cost
|
|
187
|
+
amount: "1.00",
|
|
188
|
+
// REQUIRED: Unique identifier
|
|
189
|
+
identifier: "std"
|
|
190
|
+
}
|
|
191
|
+
],
|
|
192
|
+
|
|
193
|
+
// OPTIONAL: Line items breakdown
|
|
194
|
+
items: [
|
|
195
|
+
{
|
|
196
|
+
// REQUIRED: Item type ('final' or 'pending')
|
|
197
|
+
type: "final",
|
|
198
|
+
// REQUIRED: Item label/description
|
|
199
|
+
label: "Product Order",
|
|
200
|
+
// REQUIRED: Item amount
|
|
201
|
+
amount: "20.00",
|
|
202
|
+
// REQUIRED: Payment timing ('immediate', 'recurring', 'deferred', 'automaticReload')
|
|
203
|
+
paymentTiming: "immediate"
|
|
204
|
+
}
|
|
205
|
+
]
|
|
206
|
+
};
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### Customer Configuration (REQUIRED)
|
|
210
|
+
|
|
211
|
+
```typescript
|
|
212
|
+
const customer = {
|
|
213
|
+
// OPTION 1: Use customer ID (if customer already exists in system)
|
|
214
|
+
// id: "cust_123",
|
|
215
|
+
|
|
216
|
+
// OPTION 2: Provide customer details
|
|
217
|
+
name: [
|
|
218
|
+
{
|
|
219
|
+
// REQUIRED: Language code ('en', 'ar', 'fr')
|
|
220
|
+
lang: "en",
|
|
221
|
+
// REQUIRED: First name
|
|
222
|
+
first: "John",
|
|
223
|
+
// REQUIRED: Last name
|
|
224
|
+
last: "Smith",
|
|
225
|
+
// OPTIONAL: Middle name
|
|
226
|
+
middle: "David"
|
|
227
|
+
}
|
|
228
|
+
],
|
|
229
|
+
|
|
230
|
+
// REQUIRED: At least email OR phone (or both)
|
|
231
|
+
contact: {
|
|
232
|
+
// OPTIONAL: Email address (required if phone not provided)
|
|
233
|
+
email: "john.smith@example.com",
|
|
234
|
+
|
|
235
|
+
// OPTIONAL: Phone number (required if email not provided)
|
|
236
|
+
phone: {
|
|
237
|
+
// REQUIRED IF PHONE PROVIDED: Country code with + prefix
|
|
238
|
+
countryCode: "+1",
|
|
239
|
+
// REQUIRED IF PHONE PROVIDED: Phone number
|
|
240
|
+
number: "5551234567"
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
};
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
### Interface Configuration (OPTIONAL)
|
|
247
|
+
|
|
248
|
+
```typescript
|
|
249
|
+
const interfaceConfig = {
|
|
250
|
+
// OPTIONAL: Display language ('en' or 'ar', defaults to 'en')
|
|
251
|
+
locale: "en",
|
|
252
|
+
|
|
253
|
+
// OPTIONAL: Theme mode ('light', 'dark', or 'dynamic', defaults to 'light')
|
|
254
|
+
theme: "light",
|
|
255
|
+
|
|
256
|
+
// OPTIONAL: Button edges style ('curved' or 'flat', defaults to 'curved')
|
|
257
|
+
edges: "curved",
|
|
258
|
+
|
|
259
|
+
// OPTIONAL: Button type ('book', 'buy', 'check-out', 'pay', 'plain', 'subscribe')
|
|
260
|
+
type: "buy"
|
|
261
|
+
};
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
### Acceptance Configuration (REQUIRED)
|
|
265
|
+
|
|
266
|
+
```typescript
|
|
267
|
+
const acceptance = {
|
|
268
|
+
// REQUIRED: Supported card brands/networks
|
|
269
|
+
// Options: 'amex', 'mada', 'masterCard', 'visa', 'chinaUnionPay', 'discover', 'electron', 'jcb', 'maestro'
|
|
270
|
+
supportedBrands: ["visa", "masterCard"],
|
|
271
|
+
|
|
272
|
+
// REQUIRED: Supported card types
|
|
273
|
+
// Options: 'credit', 'debit'
|
|
274
|
+
supportedCards: ["credit", "debit"],
|
|
275
|
+
|
|
276
|
+
// OPTIONAL: Supported regions for payments
|
|
277
|
+
// Options: 'LOCAL' (within country), 'REGIONAL' (regional area), 'GLOBAL' (worldwide)
|
|
278
|
+
supportedRegions: ["LOCAL", "REGIONAL"],
|
|
279
|
+
|
|
280
|
+
// OPTIONAL: Supported countries (ISO 3166-1 alpha-2 codes)
|
|
281
|
+
supportedCountries: ["AE", "KW", "SA", "QA", "BH", "OM", "EG", "JO", "LB"]
|
|
282
|
+
};
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
### Features Configuration (OPTIONAL)
|
|
286
|
+
|
|
287
|
+
```typescript
|
|
288
|
+
const features = {
|
|
289
|
+
// OPTIONAL: Allow coupon code entry (defaults to false)
|
|
290
|
+
supportsCouponCode: true,
|
|
291
|
+
|
|
292
|
+
// OPTIONAL: Shipping contact fields to collect from user
|
|
293
|
+
// Options: "name" (customer name), "phone" (phone number), "email" (email address)
|
|
294
|
+
// Can be empty array [] to not collect any fields
|
|
295
|
+
shippingContactFields: ["name", "phone", "email"]
|
|
296
|
+
};
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
## Component Props
|
|
300
|
+
|
|
301
|
+
### ApplePayView Props
|
|
302
|
+
|
|
303
|
+
```typescript
|
|
304
|
+
interface ApplePayViewProps {
|
|
305
|
+
// Payment configuration object (required)
|
|
306
|
+
config: ApplePayConfig;
|
|
307
|
+
|
|
308
|
+
// Callback when Apple Pay view is ready
|
|
309
|
+
onReady?: () => void;
|
|
310
|
+
|
|
311
|
+
// Callback when user clicks the Apple Pay button
|
|
312
|
+
onClick?: () => void;
|
|
313
|
+
|
|
314
|
+
// Callback when payment succeeds
|
|
315
|
+
onSuccess?: (data: string) => void;
|
|
316
|
+
|
|
317
|
+
// Callback when payment fails
|
|
318
|
+
onError?: (data: string) => void;
|
|
319
|
+
|
|
320
|
+
// Callback when user cancels payment
|
|
321
|
+
onCanceled?: () => void;
|
|
322
|
+
|
|
323
|
+
// Callback for merchant validation
|
|
324
|
+
onMerchantValidation?: (data: string) => void;
|
|
325
|
+
|
|
326
|
+
// Callback when order is created
|
|
327
|
+
onOrderCreated?: (data: string) => void;
|
|
328
|
+
|
|
329
|
+
// Callback when charge is created
|
|
330
|
+
onChargeCreated?: (data: string) => void;
|
|
331
|
+
|
|
332
|
+
// View style props (optional)
|
|
333
|
+
style?: StyleProp<ViewStyle>;
|
|
334
|
+
}
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
## Callback Responses
|
|
338
|
+
|
|
339
|
+
### onSuccess Response Example
|
|
340
|
+
|
|
341
|
+
```json
|
|
342
|
+
{
|
|
343
|
+
"id": "tok_4WUP3423199C4Vp18rY9y554",
|
|
344
|
+
"created": 1697656174554,
|
|
345
|
+
"object": "token",
|
|
346
|
+
"type": "CARD",
|
|
347
|
+
"card": {
|
|
348
|
+
"id": "card_U8Wb34231992m7q185g9i558",
|
|
349
|
+
"brand": "VISA",
|
|
350
|
+
"last_four": "4242",
|
|
351
|
+
"exp_month": 2,
|
|
352
|
+
"exp_year": 44
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
### onError Response Example
|
|
358
|
+
|
|
359
|
+
```json
|
|
360
|
+
{
|
|
361
|
+
"error": {
|
|
362
|
+
"code": "PAYMENT_FAILED",
|
|
363
|
+
"message": "The payment could not be processed"
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
## Advanced Usage
|
|
369
|
+
|
|
370
|
+
### Recurring Payments
|
|
371
|
+
|
|
372
|
+
For subscription or recurring payment scenarios:
|
|
373
|
+
|
|
374
|
+
```typescript
|
|
375
|
+
const recurringConfig = {
|
|
376
|
+
transaction: {
|
|
377
|
+
items: [
|
|
378
|
+
{
|
|
379
|
+
type: "final",
|
|
380
|
+
label: "Monthly Subscription",
|
|
381
|
+
amount: "9.99",
|
|
382
|
+
paymentTiming: "recurring",
|
|
383
|
+
scheduledPayment: {
|
|
384
|
+
recurringStartDate: new Date().toISOString(),
|
|
385
|
+
recurringIntervalUnit: "month",
|
|
386
|
+
recurringIntervalCount: 1
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
]
|
|
390
|
+
}
|
|
391
|
+
};
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
### Deferred Payments
|
|
395
|
+
|
|
396
|
+
For payments scheduled for a future date:
|
|
397
|
+
|
|
398
|
+
```typescript
|
|
399
|
+
const deferredConfig = {
|
|
400
|
+
transaction: {
|
|
401
|
+
items: [
|
|
402
|
+
{
|
|
403
|
+
type: "final",
|
|
404
|
+
label: "Product Order",
|
|
405
|
+
amount: "20.00",
|
|
406
|
+
paymentTiming: "deferred",
|
|
407
|
+
scheduledPayment: {
|
|
408
|
+
deferredPaymentDate: new Date(Date.now() + 86400000).toISOString()
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
]
|
|
412
|
+
}
|
|
413
|
+
};
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
### Multiple Shipping Options
|
|
417
|
+
|
|
418
|
+
```typescript
|
|
419
|
+
const shippingConfig = {
|
|
420
|
+
transaction: {
|
|
421
|
+
shipping: [
|
|
422
|
+
{
|
|
423
|
+
label: "Standard",
|
|
424
|
+
detail: "5–7 days",
|
|
425
|
+
amount: "1.00",
|
|
426
|
+
identifier: "std"
|
|
427
|
+
},
|
|
428
|
+
{
|
|
429
|
+
label: "Express",
|
|
430
|
+
detail: "2–3 days",
|
|
431
|
+
amount: "5.00",
|
|
432
|
+
identifier: "exp"
|
|
433
|
+
}
|
|
434
|
+
]
|
|
435
|
+
}
|
|
436
|
+
};
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
## Error Handling
|
|
440
|
+
|
|
441
|
+
Always implement error handling in your callbacks:
|
|
442
|
+
|
|
443
|
+
```typescript
|
|
444
|
+
const handleError = (errorData: string) => {
|
|
445
|
+
try {
|
|
446
|
+
const error = JSON.parse(errorData);
|
|
447
|
+
if (error.error) {
|
|
448
|
+
const { code, message } = error.error;
|
|
449
|
+
console.error(`Error ${code}: ${message}`);
|
|
450
|
+
// Handle error appropriately
|
|
451
|
+
}
|
|
452
|
+
} catch (e) {
|
|
453
|
+
console.error('Failed to parse error:', errorData);
|
|
454
|
+
}
|
|
455
|
+
};
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
## Example Application
|
|
459
|
+
|
|
460
|
+
A complete example application is included in the `example` folder demonstrating:
|
|
461
|
+
|
|
462
|
+
- Basic Apple Pay integration
|
|
463
|
+
- Configuration management
|
|
464
|
+
- Real-time event logging
|
|
465
|
+
- Multiple payment scenarios
|
|
466
|
+
- Error handling
|
|
467
|
+
|
|
468
|
+
Run the example app:
|
|
469
|
+
|
|
470
|
+
```bash
|
|
471
|
+
cd example
|
|
472
|
+
npm install
|
|
473
|
+
cd ios
|
|
474
|
+
pod install
|
|
475
|
+
cd ..
|
|
476
|
+
npm run ios
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
## Native Dependency
|
|
480
|
+
|
|
481
|
+
This library wraps the native **ApplePay-iOS** module. The native bridge handles:
|
|
482
|
+
|
|
483
|
+
- Native Apple Pay sheet presentation
|
|
484
|
+
- Payment processing
|
|
485
|
+
- Merchant validation
|
|
486
|
+
- Native callback bridging to React Native
|
|
487
|
+
|
|
488
|
+
For detailed native implementation, see: [ApplePay-iOS](https://github.com/Tap-Payments/ApplePay-iOS)
|
|
489
|
+
|
|
490
|
+
## Security Considerations
|
|
491
|
+
|
|
492
|
+
✅ **Best Practices:**
|
|
493
|
+
- Never expose your secret keys in your app (only use public keys)
|
|
494
|
+
- Always validate payment responses on your backend
|
|
495
|
+
- Use HTTPS for all communication
|
|
496
|
+
- Never log sensitive payment data
|
|
497
|
+
- Keep dependencies updated for security patches
|
|
498
|
+
- Use TypeScript for type-safe payment configurations
|
|
499
|
+
|
|
500
|
+
## Troubleshooting
|
|
501
|
+
|
|
502
|
+
### Apple Pay not appearing
|
|
503
|
+
- Ensure you're testing on a physical iOS device with Apple Pay configured
|
|
504
|
+
- Verify your merchant identifier is correct
|
|
505
|
+
- Check that your app signing certificate is properly configured
|
|
506
|
+
- Ensure Apple Pay is enabled in Xcode capabilities
|
|
507
|
+
|
|
508
|
+
### Payment failures
|
|
509
|
+
- Verify your Tap API keys are correct
|
|
510
|
+
- Check that your public key corresponds to your merchant account
|
|
511
|
+
- Ensure the device has Apple Pay set up
|
|
512
|
+
- Verify the transaction amount is valid
|
|
513
|
+
|
|
514
|
+
### Configuration errors
|
|
515
|
+
- Validate all required fields are present in the configuration object
|
|
516
|
+
- Check for typos in parameter keys (they are case-sensitive)
|
|
517
|
+
- Ensure currency codes are valid ISO 4217 codes
|
|
518
|
+
- Use TypeScript to catch configuration errors at compile time
|
|
519
|
+
|
|
520
|
+
### Build issues
|
|
521
|
+
- Run `pod install` in the ios directory after adding the package
|
|
522
|
+
- Clear build cache: `cd ios && rm -rf Pods && pod install`
|
|
523
|
+
- For autolinking issues, verify your React Native version is 0.60+
|
|
524
|
+
|
|
525
|
+
## Support & Documentation
|
|
526
|
+
|
|
527
|
+
- **Developer Documentation**: [docs.tap.company](https://developers.tap.company)
|
|
528
|
+
- **API Reference**: [Tap API Documentation](https://developers.tap.company/docs)
|
|
529
|
+
- **iOS Native Module**: [ApplePay-iOS](https://github.com/Tap-Payments/ApplePay-iOS)
|
|
530
|
+
- **Issue Tracker**: [GitHub Issues](https://github.com/Tap-Payments/ApplePay-RN/issues)
|
|
531
|
+
|
|
532
|
+
## License
|
|
533
|
+
|
|
534
|
+
MIT License - See LICENSE file for details
|
|
535
|
+
|
|
536
|
+
## Contributing
|
|
537
|
+
|
|
538
|
+
We welcome contributions! Please feel free to submit pull requests with bug fixes, feature additions, or documentation improvements.
|
|
539
|
+
|
|
540
|
+
## Version History
|
|
541
|
+
|
|
542
|
+
### 0.0.1
|
|
543
|
+
- Initial release
|
|
544
|
+
- React Native bridge to Apple Pay iOS
|
|
545
|
+
- TypeScript support
|
|
546
|
+
- Comprehensive callback system
|
|
547
|
+
- Example app
|
|
548
|
+
|
|
549
|
+
---
|
|
550
|
+
|
|
551
|
+
**Built with ❤️ by Tap Payments**
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
buildscript {
|
|
2
|
+
ext.ApplepayRn = [
|
|
3
|
+
kotlinVersion: "2.0.21",
|
|
4
|
+
minSdkVersion: 24,
|
|
5
|
+
compileSdkVersion: 36,
|
|
6
|
+
targetSdkVersion: 36
|
|
7
|
+
]
|
|
8
|
+
|
|
9
|
+
ext.getExtOrDefault = { prop ->
|
|
10
|
+
if (rootProject.ext.has(prop)) {
|
|
11
|
+
return rootProject.ext.get(prop)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return ApplepayRn[prop]
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
repositories {
|
|
18
|
+
google()
|
|
19
|
+
mavenCentral()
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
dependencies {
|
|
23
|
+
classpath "com.android.tools.build:gradle:8.7.2"
|
|
24
|
+
// noinspection DifferentKotlinGradleVersion
|
|
25
|
+
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${getExtOrDefault('kotlinVersion')}"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
apply plugin: "com.android.library"
|
|
31
|
+
apply plugin: "kotlin-android"
|
|
32
|
+
|
|
33
|
+
apply plugin: "com.facebook.react"
|
|
34
|
+
|
|
35
|
+
android {
|
|
36
|
+
namespace "com.applepayrn"
|
|
37
|
+
|
|
38
|
+
compileSdkVersion getExtOrDefault("compileSdkVersion")
|
|
39
|
+
|
|
40
|
+
defaultConfig {
|
|
41
|
+
minSdkVersion getExtOrDefault("minSdkVersion")
|
|
42
|
+
targetSdkVersion getExtOrDefault("targetSdkVersion")
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
buildFeatures {
|
|
46
|
+
buildConfig true
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
buildTypes {
|
|
50
|
+
release {
|
|
51
|
+
minifyEnabled false
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
lint {
|
|
56
|
+
disable "GradleCompatible"
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
compileOptions {
|
|
60
|
+
sourceCompatibility JavaVersion.VERSION_1_8
|
|
61
|
+
targetCompatibility JavaVersion.VERSION_1_8
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
dependencies {
|
|
66
|
+
implementation "com.facebook.react:react-android"
|
|
67
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
package com.applepayrn
|
|
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
|
+
|
|
9
|
+
class ApplepayRnViewPackage : BaseReactPackage() {
|
|
10
|
+
override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
|
|
11
|
+
return listOf(ApplepayRnViewManager())
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? = null
|
|
15
|
+
|
|
16
|
+
override fun getReactModuleInfoProvider() = ReactModuleInfoProvider { emptyMap() }
|
|
17
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
package com.applepayrn
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.util.AttributeSet
|
|
5
|
+
import android.view.View
|
|
6
|
+
|
|
7
|
+
class ApplepayRnView : View {
|
|
8
|
+
constructor(context: Context?) : super(context)
|
|
9
|
+
constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
|
|
10
|
+
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
|
|
11
|
+
context,
|
|
12
|
+
attrs,
|
|
13
|
+
defStyleAttr
|
|
14
|
+
)
|
|
15
|
+
}
|