@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 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 AcceptSDK from '@tapayadot/accept-react-native';
50
+ import Accept from '@tapayadot/accept-react-native';
51
51
 
52
52
  // Initialize once at app launch
53
- await AcceptSDK.initialize(/* demo: */ false);
53
+ await Accept.initialize(/* demo: */ false);
54
54
 
55
55
  // Authenticate with your merchant token
56
- await AcceptSDK.authenticate('your-merchant-token');
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 AcceptSDK.requestLocationPermission();
98
+ await Accept.requestLocationPermission();
65
99
  ```
66
100
 
67
101
  ### Card Payment (Tap-to-Pay)
68
102
 
69
103
  ```ts
70
- import AcceptSDK, { CardPaymentIntent } from '@tapayadot/accept-react-native';
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 AcceptSDK.payments.startCardPayment(
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 AcceptSDK.payments.startSepaPayment(
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 AcceptSDK.payments.startCertisPayment(
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 AcceptSDK.identity.presentKyb({
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 AcceptSDK.getStatus(); // 'IDLE' | 'INITIALIZED' | 'LOGGED_IN'
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 AcceptSDK.getPaymentStatus('pi_xxx');
224
+ const result = await Accept.getPaymentStatus('pi_xxx');
158
225
 
159
226
  // Log out
160
- await AcceptSDK.logOut();
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 AcceptSDK.isCompanionAppInstalled();
256
+ const installed = await Accept.isCompanionAppInstalled();
169
257
 
170
258
  if (!installed) {
171
259
  // Prompt user to install via App Store sheet
172
- await AcceptSDK.presentCompanionAppSheet();
260
+ await Accept.presentCompanionAppSheet();
173
261
  } else {
174
262
  // Pair with the companion app
175
- await AcceptSDK.pairWithCompanionApp();
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
- ### `AcceptSDK.payments`
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
- ### `AcceptSDK.identity`
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
- ```ts
212
- type Currency = 'CZK' | 'EUR' | 'GBP'
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: Currency
218
- settlementCurrency?: Currency
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 SepaPaymentIntent = { paymentIntentId: string; amount: number; requestedCurrency: Currency; settlementCurrency?: Currency }
232
- type SepaPaymentResult = { status: 'pending' | 'verified' | 'aborted' | 'refunded' | 'declined'; postponed: boolean; receivedAt: string; receivedFromIban: string }
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 CertisPaymentIntent = { paymentIntentId: string; amount: number; requestedCurrency: Currency; settlementCurrency?: Currency }
235
- type CertisPaymentResult = { status: 'pending' | 'verified' | 'aborted' | 'refunded' | 'declined'; postponed: boolean; receivedAt: string; receivedFromIban: string }
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
@@ -1,7 +1,7 @@
1
1
  apply plugin: 'com.android.library'
2
2
 
3
3
  group = 'com.tapaya.acceptsdkreactnative'
4
- version = '0.1.0'
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 "0.1.0"
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.29'
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
  }