@tapayadot/accept-react-native 1.0.0 → 1.2.0
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/README.md +199 -28
- package/android/build.gradle +4 -3
- package/android/src/main/java/com/tapaya/acceptsdkreactnative/AcceptSdkReactNativeModule.kt +316 -20
- package/build/AcceptSdkReactNative.types.d.ts +152 -15
- package/build/AcceptSdkReactNative.types.d.ts.map +1 -1
- package/build/AcceptSdkReactNative.types.js.map +1 -1
- package/build/AcceptSdkReactNativeModule.d.ts +12 -2
- package/build/AcceptSdkReactNativeModule.d.ts.map +1 -1
- package/build/AcceptSdkReactNativeModule.js.map +1 -1
- package/build/index.d.ts +103 -7
- package/build/index.d.ts.map +1 -1
- package/build/index.js +81 -4
- package/build/index.js.map +1 -1
- package/build/utils.d.ts +11 -0
- package/build/utils.d.ts.map +1 -0
- package/build/utils.js +21 -0
- package/build/utils.js.map +1 -0
- package/ios/AcceptSdkReactNativeModule.swift +373 -40
- package/package.json +22 -7
- package/plugin/withCustomRepoModule.js +2 -7
package/README.md
CHANGED
|
@@ -47,36 +47,70 @@ The iOS SDK is resolved via Swift Package Manager during `prebuild` / `pod insta
|
|
|
47
47
|
### Setup
|
|
48
48
|
|
|
49
49
|
```ts
|
|
50
|
-
import
|
|
50
|
+
import Accept from '@tapayadot/accept-react-native';
|
|
51
51
|
|
|
52
52
|
// Initialize once at app launch
|
|
53
|
-
await
|
|
53
|
+
await Accept.initialize(/* demo: */ false);
|
|
54
54
|
|
|
55
55
|
// Authenticate with your merchant token
|
|
56
|
-
await
|
|
56
|
+
await Accept.authenticate('your-merchant-token');
|
|
57
57
|
```
|
|
58
58
|
|
|
59
|
+
### UI Theming
|
|
60
|
+
|
|
61
|
+
Customize colors and logos at initialization or any time after:
|
|
62
|
+
|
|
63
|
+
```ts
|
|
64
|
+
import Accept, { type AcceptThemeConfiguration } from '@tapayadot/accept-react-native';
|
|
65
|
+
import { assetToBase64 } from '@tapayadot/accept-react-native/utils';
|
|
66
|
+
|
|
67
|
+
const theme: AcceptThemeConfiguration = {
|
|
68
|
+
colors: {
|
|
69
|
+
accent: '#FF8400',
|
|
70
|
+
error: '#E6282B',
|
|
71
|
+
warning: '#FF8000',
|
|
72
|
+
success: '#228800',
|
|
73
|
+
brandGradientColors: { start: '#FF8400', end: '#9A94E9' },
|
|
74
|
+
},
|
|
75
|
+
images: {
|
|
76
|
+
brandLogo: await assetToBase64(require('./assets/brand-logo.png')),
|
|
77
|
+
toolbarLogo: await assetToBase64(require('./assets/toolbar-logo.png')),
|
|
78
|
+
solidLogo: await assetToBase64(require('./assets/solid-logo.png')),
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
// Pass at initialization
|
|
83
|
+
await Accept.initialize(false, theme);
|
|
84
|
+
|
|
85
|
+
// Or apply after initialization
|
|
86
|
+
await Accept.setTheme(theme);
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Omit `colors` or `images` to keep SDK defaults for that slot. Images must be PNG or JPEG — SVG is not supported.
|
|
90
|
+
|
|
91
|
+
> `assetToBase64` requires `expo-asset` and `expo-file-system`. Both are included in managed Expo projects. Bare React Native users must install them manually.
|
|
92
|
+
|
|
59
93
|
### Request Location Permission
|
|
60
94
|
|
|
61
95
|
Required before processing card payments (Tap-to-Pay):
|
|
62
96
|
|
|
63
97
|
```ts
|
|
64
|
-
await
|
|
98
|
+
await Accept.requestLocationPermission();
|
|
65
99
|
```
|
|
66
100
|
|
|
67
101
|
### Card Payment (Tap-to-Pay)
|
|
68
102
|
|
|
69
103
|
```ts
|
|
70
|
-
import
|
|
104
|
+
import Accept, { CardPaymentIntent } from '@tapayadot/accept-react-native';
|
|
71
105
|
|
|
72
106
|
const intent: CardPaymentIntent = {
|
|
73
107
|
paymentIntentId: 'pi_xxx',
|
|
74
108
|
amount: 1500,
|
|
75
|
-
requestedCurrency: 'CZK',
|
|
109
|
+
requestedCurrency: 'CZK', // ISO 4217 alpha-3
|
|
76
110
|
settlementCurrency: 'EUR',
|
|
77
111
|
};
|
|
78
112
|
|
|
79
|
-
const result = await
|
|
113
|
+
const result = await Accept.payments.startCardPayment(
|
|
80
114
|
intent,
|
|
81
115
|
(status) => console.log('Status update:', status),
|
|
82
116
|
(message, exception) => console.error('Error:', message, exception),
|
|
@@ -92,10 +126,28 @@ switch (result.status) {
|
|
|
92
126
|
}
|
|
93
127
|
```
|
|
94
128
|
|
|
129
|
+
### Refund a Card Payment
|
|
130
|
+
|
|
131
|
+
```ts
|
|
132
|
+
const refund = await Accept.payments.refund({
|
|
133
|
+
paymentToken: 'pi_xxx', // source payment intent id (or server payment UUID)
|
|
134
|
+
reason: 'customerRequest', // 'customerRequest' | 'duplicate' | 'fraudulent' | 'expiredCharge'
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
console.log(refund.status); // 'success' | 'pending' | 'cancelled' | 'refunded' | 'failed' | 'actionNeeded'
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Cancel an Active Payment
|
|
141
|
+
|
|
142
|
+
```ts
|
|
143
|
+
// Dismisses any payment UI and cancels the in-flight transaction.
|
|
144
|
+
await Accept.payments.cancelActivePayment();
|
|
145
|
+
```
|
|
146
|
+
|
|
95
147
|
### SEPA Instant Credit Transfer
|
|
96
148
|
|
|
97
149
|
```ts
|
|
98
|
-
const result = await
|
|
150
|
+
const result = await Accept.payments.startSepaPayment(
|
|
99
151
|
{
|
|
100
152
|
paymentIntentId: 'pi_xxx',
|
|
101
153
|
amount: 1000,
|
|
@@ -114,7 +166,7 @@ if (result.status === 'verified') {
|
|
|
114
166
|
### Certis (Czech Instant Transfer)
|
|
115
167
|
|
|
116
168
|
```ts
|
|
117
|
-
const result = await
|
|
169
|
+
const result = await Accept.payments.startCertisPayment(
|
|
118
170
|
{
|
|
119
171
|
paymentIntentId: 'pi_xxx',
|
|
120
172
|
amount: 10000,
|
|
@@ -126,11 +178,26 @@ const result = await AcceptSDK.payments.startCertisPayment(
|
|
|
126
178
|
);
|
|
127
179
|
```
|
|
128
180
|
|
|
181
|
+
### Onboarding Status
|
|
182
|
+
|
|
183
|
+
```ts
|
|
184
|
+
// Aggregate status across all payment methods
|
|
185
|
+
const onboarding = await Accept.identity.getOnboardingStatus();
|
|
186
|
+
console.log(onboarding.isOnboarded);
|
|
187
|
+
onboarding.paymentMethods.forEach((m) =>
|
|
188
|
+
console.log(m.method, m.status), // e.g. 'CARD', 'ACTIVE'
|
|
189
|
+
);
|
|
190
|
+
|
|
191
|
+
// Single-method status
|
|
192
|
+
const cardStatus = await Accept.identity.getPaymentMethodStatus('CARD');
|
|
193
|
+
// 'NOT_STARTED' | 'PENDING' | 'ACTIVE' | 'ATTENTION_NEEDED' | 'ACTION_REQUIRED' | 'BLOCKED'
|
|
194
|
+
```
|
|
195
|
+
|
|
129
196
|
### KYB Onboarding
|
|
130
197
|
|
|
131
198
|
```ts
|
|
132
199
|
// Check if onboarding is needed before launching the KYB flow
|
|
133
|
-
await
|
|
200
|
+
await Accept.identity.presentKyb({
|
|
134
201
|
businessType: 'company',
|
|
135
202
|
legalName: 'Acme s.r.o.',
|
|
136
203
|
businessEmail: 'billing@acme.com',
|
|
@@ -151,13 +218,34 @@ await AcceptSDK.identity.presentKyb({
|
|
|
151
218
|
|
|
152
219
|
```ts
|
|
153
220
|
// Check current SDK status
|
|
154
|
-
const status = await
|
|
221
|
+
const status = await Accept.getStatus(); // 'IDLE' | 'INITIALIZED' | 'LOGGED_IN'
|
|
155
222
|
|
|
156
223
|
// Query the result of a previous payment
|
|
157
|
-
const result = await
|
|
224
|
+
const result = await Accept.getPaymentStatus('pi_xxx');
|
|
158
225
|
|
|
159
226
|
// Log out
|
|
160
|
-
await
|
|
227
|
+
await Accept.logOut();
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### Demo Mode
|
|
231
|
+
|
|
232
|
+
```ts
|
|
233
|
+
await Accept.demo.enable(); // simulate payments without real terminals
|
|
234
|
+
const isDemo = await Accept.demo.isEnabled();
|
|
235
|
+
await Accept.demo.disable();
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### UI Behavior (Android only)
|
|
239
|
+
|
|
240
|
+
```ts
|
|
241
|
+
await Accept.setUiBehavior({
|
|
242
|
+
resultScreenDurationSeconds: 5,
|
|
243
|
+
showResultScreen: true,
|
|
244
|
+
nfcZone: {
|
|
245
|
+
indicator: 'BELOW', // 'DEFAULT' | 'ABOVE' | 'BELOW' | 'FRONT' | 'BEHIND'
|
|
246
|
+
position: { xBias: 0.5, yBias: 0.7 }, // omit to use terminal default
|
|
247
|
+
},
|
|
248
|
+
});
|
|
161
249
|
```
|
|
162
250
|
|
|
163
251
|
### Companion App (iOS only)
|
|
@@ -165,14 +253,14 @@ await AcceptSDK.logOut();
|
|
|
165
253
|
The Tapaya companion app is required for card payments on iOS:
|
|
166
254
|
|
|
167
255
|
```ts
|
|
168
|
-
const installed = await
|
|
256
|
+
const installed = await Accept.isCompanionAppInstalled();
|
|
169
257
|
|
|
170
258
|
if (!installed) {
|
|
171
259
|
// Prompt user to install via App Store sheet
|
|
172
|
-
await
|
|
260
|
+
await Accept.presentCompanionAppSheet();
|
|
173
261
|
} else {
|
|
174
262
|
// Pair with the companion app
|
|
175
|
-
await
|
|
263
|
+
await Accept.pairWithCompanionApp();
|
|
176
264
|
}
|
|
177
265
|
```
|
|
178
266
|
|
|
@@ -182,7 +270,9 @@ if (!installed) {
|
|
|
182
270
|
|
|
183
271
|
| Method | Description |
|
|
184
272
|
|---|---|
|
|
185
|
-
| `initialize(demo?)` | Initialize the SDK. Pass `true` for sandbox mode. |
|
|
273
|
+
| `initialize(demo?, theme?)` | Initialize the SDK. Pass `true` for sandbox mode. Optionally provide a UI theme. |
|
|
274
|
+
| `setTheme(theme)` | Apply a UI theme after initialization. |
|
|
275
|
+
| `setUiBehavior(behavior)` | Android only. Configure result screen + NFC zone. |
|
|
186
276
|
| `authenticate(token)` | Authenticate with a merchant JWT token. |
|
|
187
277
|
| `getStatus()` | Returns `'IDLE' \| 'INITIALIZED' \| 'LOGGED_IN'`. |
|
|
188
278
|
| `getPaymentStatus(paymentIntentId)` | Retrieve the result of a previous payment. |
|
|
@@ -192,30 +282,44 @@ if (!installed) {
|
|
|
192
282
|
| `presentCompanionAppSheet()` | iOS only. Show App Store sheet for companion app. |
|
|
193
283
|
| `pairWithCompanionApp()` | iOS only. Pair with the installed companion app. |
|
|
194
284
|
|
|
195
|
-
### `
|
|
285
|
+
### `Accept.payments`
|
|
196
286
|
|
|
197
287
|
| Method | Description |
|
|
198
288
|
|---|---|
|
|
199
289
|
| `startCardPayment(intent, onStatus, onError)` | Start a card/Tap-to-Pay payment. |
|
|
200
290
|
| `startSepaPayment(intent, onStatus, onError)` | Start a SEPA Instant payment. |
|
|
201
291
|
| `startCertisPayment(intent, onStatus, onError)` | Start a Certis Instant payment. |
|
|
292
|
+
| `refund(intent)` | Refund a previously completed card payment (headless, no UI). |
|
|
293
|
+
| `cancelActivePayment()` | Dismiss in-flight payment UI and cancel the transaction. |
|
|
202
294
|
|
|
203
|
-
### `
|
|
295
|
+
### `Accept.identity`
|
|
204
296
|
|
|
205
297
|
| Method | Description |
|
|
206
298
|
|---|---|
|
|
207
299
|
| `presentKyb(prefilling?)` | Launch the KYB onboarding UI with optional prefill data. |
|
|
300
|
+
| `getOnboardingStatus()` | Returns aggregate merchant onboarding status across payment methods. |
|
|
301
|
+
| `getPaymentMethodStatus(method)` | Returns onboarding status for a single payment method. |
|
|
302
|
+
|
|
303
|
+
### `Accept.demo`
|
|
304
|
+
|
|
305
|
+
| Method | Description |
|
|
306
|
+
|---|---|
|
|
307
|
+
| `enable()` | Enable demo mode — payments are simulated, no real terminal required. |
|
|
308
|
+
| `disable()` | Return to real terminal flows. |
|
|
309
|
+
| `isEnabled()` | Whether demo mode is currently enabled. |
|
|
208
310
|
|
|
209
311
|
## Types
|
|
210
312
|
|
|
211
|
-
|
|
212
|
-
|
|
313
|
+
Currency and country fields are plain ISO strings:
|
|
314
|
+
- Currency — ISO 4217 alpha-3 (`'CZK'`, `'EUR'`, `'GBP'`, …)
|
|
315
|
+
- Country — ISO 3166-1 alpha-2 (`'CZ'`, `'GB'`, …)
|
|
213
316
|
|
|
317
|
+
```ts
|
|
214
318
|
type CardPaymentIntent = {
|
|
215
319
|
paymentIntentId: string
|
|
216
320
|
amount: number // smallest currency unit (e.g. hellers)
|
|
217
|
-
requestedCurrency:
|
|
218
|
-
settlementCurrency?:
|
|
321
|
+
requestedCurrency: string // ISO 4217 alpha-3
|
|
322
|
+
settlementCurrency?: string // defaults to requestedCurrency
|
|
219
323
|
}
|
|
220
324
|
|
|
221
325
|
type CardPaymentResult = {
|
|
@@ -225,18 +329,85 @@ type CardPaymentResult = {
|
|
|
225
329
|
authorizationCode?: string
|
|
226
330
|
terminalId?: string
|
|
227
331
|
companyName?: string
|
|
332
|
+
companyAddress1?: string
|
|
333
|
+
companyAddress2?: string
|
|
334
|
+
companyCity?: string
|
|
335
|
+
companyCountry?: string // ISO 3166-1 alpha-2
|
|
228
336
|
reason?: string
|
|
337
|
+
receiptUrl?: string
|
|
338
|
+
refundToken?: string // present when this card payment was refunded
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
type SepaPaymentIntent = { paymentIntentId: string; amount: number; requestedCurrency: string; settlementCurrency?: string }
|
|
342
|
+
type SepaPaymentResult = { status: 'pending' | 'verified' | 'aborted' | 'refunded' | 'declined'; postponed: boolean; receivedAt: string; receivedFromIban: string; receiptUrl?: string }
|
|
343
|
+
|
|
344
|
+
type CertisPaymentIntent = { paymentIntentId: string; amount: number; requestedCurrency: string; settlementCurrency?: string }
|
|
345
|
+
type CertisPaymentResult = { status: 'pending' | 'verified' | 'aborted' | 'refunded' | 'declined'; postponed: boolean; receivedAt: string; receivedFromIban: string; receiptUrl?: string }
|
|
346
|
+
|
|
347
|
+
type RefundReason = 'customerRequest' | 'duplicate' | 'fraudulent' | 'expiredCharge'
|
|
348
|
+
type TransactionStatus = 'pending' | 'success' | 'cancelled' | 'refunded' | 'failed' | 'actionNeeded'
|
|
349
|
+
|
|
350
|
+
type RefundIntent = {
|
|
351
|
+
paymentToken: string // source payment UUID or original paymentIntentId
|
|
352
|
+
refundToken?: string // idempotency token, pass same value on retry
|
|
353
|
+
reason: RefundReason
|
|
229
354
|
}
|
|
230
355
|
|
|
231
|
-
type
|
|
232
|
-
|
|
356
|
+
type RefundResult = {
|
|
357
|
+
refundToken?: string
|
|
358
|
+
status: TransactionStatus
|
|
359
|
+
refundReason: RefundReason
|
|
360
|
+
paymentMethod?: PaymentMethod
|
|
361
|
+
requestedAmount?: number
|
|
362
|
+
requestedCurrency?: string
|
|
363
|
+
settlementAmount?: number
|
|
364
|
+
settlementCurrency?: string
|
|
365
|
+
fxRate?: number
|
|
366
|
+
createdAt?: string // ISO 8601 UTC
|
|
367
|
+
processedAt?: string // ISO 8601 UTC
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
type PaymentMethod = 'CARD' | 'SEPA' | 'CERTIS' | 'CRYPTO'
|
|
371
|
+
type PaymentMethodStatus = 'NOT_STARTED' | 'PENDING' | 'ACTIVE' | 'ATTENTION_NEEDED' | 'ACTION_REQUIRED' | 'BLOCKED'
|
|
372
|
+
|
|
373
|
+
type AcceptPaymentMethodStatus = { method: PaymentMethod; status: PaymentMethodStatus }
|
|
374
|
+
type AcceptOnboardingStatus = { isOnboarded: boolean; paymentMethods: AcceptPaymentMethodStatus[] }
|
|
375
|
+
|
|
376
|
+
type GradientColors = { start: string; end: string }
|
|
233
377
|
|
|
234
|
-
type
|
|
235
|
-
|
|
378
|
+
type AcceptColorTheme = {
|
|
379
|
+
accent: string // #RRGGBB or #AARRGGBB
|
|
380
|
+
error: string
|
|
381
|
+
warning: string
|
|
382
|
+
success: string
|
|
383
|
+
brandGradientColors?: GradientColors
|
|
384
|
+
brandSubtleGradientColors?: GradientColors
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
type AcceptImageTheme = {
|
|
388
|
+
brandLogo: string // base64 PNG/JPEG
|
|
389
|
+
toolbarLogo: string
|
|
390
|
+
solidLogo: string
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
type AcceptThemeConfiguration = {
|
|
394
|
+
colors?: AcceptColorTheme
|
|
395
|
+
images?: AcceptImageTheme
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
// Android-only
|
|
399
|
+
type NfcIndicator = 'DEFAULT' | 'ABOVE' | 'BELOW' | 'FRONT' | 'BEHIND'
|
|
400
|
+
type NfcPosition = { xBias: number; yBias: number } // 0..1 normalized; omit position for terminal default
|
|
401
|
+
type NfcZone = { indicator: NfcIndicator; position?: NfcPosition }
|
|
402
|
+
type AcceptUiBehavior = {
|
|
403
|
+
resultScreenDurationSeconds?: number
|
|
404
|
+
showResultScreen?: boolean
|
|
405
|
+
nfcZone?: NfcZone
|
|
406
|
+
}
|
|
236
407
|
|
|
237
408
|
type KybPrefillData = {
|
|
238
409
|
businessType?: 'individual' | 'company' | 'nonProfit' | 'governmentEntity'
|
|
239
|
-
countryCode?: string
|
|
410
|
+
countryCode?: string // ISO 3166-1 alpha-2
|
|
240
411
|
registrationNumber?: string
|
|
241
412
|
vatNumber?: string
|
|
242
413
|
legalName?: string
|
package/android/build.gradle
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
apply plugin: 'com.android.library'
|
|
2
2
|
|
|
3
3
|
group = 'com.tapaya.acceptsdkreactnative'
|
|
4
|
-
version = '
|
|
4
|
+
version = '1.2.0'
|
|
5
5
|
|
|
6
6
|
def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
|
|
7
7
|
apply from: expoModulesCorePlugin
|
|
@@ -35,7 +35,7 @@ android {
|
|
|
35
35
|
namespace "com.tapaya.acceptsdkreactnative"
|
|
36
36
|
defaultConfig {
|
|
37
37
|
versionCode 1
|
|
38
|
-
versionName "
|
|
38
|
+
versionName "1.2.0"
|
|
39
39
|
}
|
|
40
40
|
lintOptions {
|
|
41
41
|
abortOnError false
|
|
@@ -43,7 +43,8 @@ android {
|
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
dependencies {
|
|
46
|
-
implementation 'com.tapaya:accept:1.0
|
|
46
|
+
implementation 'com.tapaya:accept:1.2.0'
|
|
47
47
|
implementation 'com.google.code.gson:gson:2.13.2'
|
|
48
48
|
implementation 'androidx.appcompat:appcompat:1.7.1'
|
|
49
|
+
implementation 'androidx.compose.ui:ui:1.8.2'
|
|
49
50
|
}
|