@paydock/client-sdk 1.139.0 → 1.140.0-beta

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 (73) hide show
  1. package/README.md +2573 -0
  2. package/bundles/index.cjs +1296 -508
  3. package/bundles/index.cjs.d.ts +1377 -200
  4. package/bundles/index.mjs +1295 -509
  5. package/bundles/index.mjs.d.ts +1377 -200
  6. package/bundles/types/checkout/checkout.d.ts.map +1 -1
  7. package/bundles/types/checkout/v1/instructions/instruction.card_form.show.d.ts.map +1 -1
  8. package/bundles/types/checkout/v3/instructions/instruction.card_form.show.d.ts.map +1 -1
  9. package/bundles/types/checkout/v3/instructions/instruction.payment_methods.show.d.ts.map +1 -1
  10. package/bundles/types/checkout-button/zipmoney/zipmoney-contextual.runner.d.ts +1 -2
  11. package/bundles/types/checkout-button/zipmoney/zipmoney-contextual.runner.d.ts.map +1 -1
  12. package/bundles/types/open-wallets/apple-pay-open-wallet-button.d.ts +70 -0
  13. package/bundles/types/open-wallets/apple-pay-open-wallet-button.d.ts.map +1 -0
  14. package/bundles/types/open-wallets/base/open-wallet-buttons.d.ts +242 -74
  15. package/bundles/types/open-wallets/base/open-wallet-buttons.d.ts.map +1 -1
  16. package/bundles/types/open-wallets/base/open-wallet.service.d.ts +62 -4
  17. package/bundles/types/open-wallets/base/open-wallet.service.d.ts.map +1 -1
  18. package/bundles/types/open-wallets/enum/error-operation.enum.d.ts +15 -0
  19. package/bundles/types/open-wallets/enum/error-operation.enum.d.ts.map +1 -0
  20. package/bundles/types/open-wallets/enum/event.enum.d.ts +11 -3
  21. package/bundles/types/open-wallets/enum/event.enum.d.ts.map +1 -1
  22. package/bundles/types/open-wallets/enum/token-type.enum.d.ts +10 -0
  23. package/bundles/types/open-wallets/enum/token-type.enum.d.ts.map +1 -0
  24. package/bundles/types/open-wallets/google-pay-open-wallet-button.d.ts +65 -0
  25. package/bundles/types/open-wallets/google-pay-open-wallet-button.d.ts.map +1 -0
  26. package/bundles/types/open-wallets/index.d.ts +293 -0
  27. package/bundles/types/open-wallets/index.d.ts.map +1 -1
  28. package/bundles/types/open-wallets/interfaces/events.interface.d.ts +87 -14
  29. package/bundles/types/open-wallets/interfaces/events.interface.d.ts.map +1 -1
  30. package/bundles/types/open-wallets/interfaces/google-pay/google-pay-meta.interface.d.ts +6 -0
  31. package/bundles/types/open-wallets/interfaces/google-pay/google-pay-meta.interface.d.ts.map +1 -1
  32. package/bundles/types/open-wallets/interfaces/index.d.ts +2 -2
  33. package/bundles/types/open-wallets/interfaces/index.d.ts.map +1 -1
  34. package/bundles/types/open-wallets/interfaces/open-wallet-meta.interface.d.ts +12 -0
  35. package/bundles/types/open-wallets/interfaces/open-wallet-meta.interface.d.ts.map +1 -1
  36. package/bundles/types/open-wallets/interfaces/payment-source.interface.d.ts +28 -2
  37. package/bundles/types/open-wallets/interfaces/payment-source.interface.d.ts.map +1 -1
  38. package/bundles/types/open-wallets/services/apple-pay/apple-pay.open-wallet.service.d.ts +27 -2
  39. package/bundles/types/open-wallets/services/apple-pay/apple-pay.open-wallet.service.d.ts.map +1 -1
  40. package/bundles/types/open-wallets/services/google-pay/constants/google-pay.constants.d.ts +9 -0
  41. package/bundles/types/open-wallets/services/google-pay/constants/google-pay.constants.d.ts.map +1 -1
  42. package/bundles/types/open-wallets/services/google-pay/google-pay.open-wallet.service.d.ts +20 -9
  43. package/bundles/types/open-wallets/services/google-pay/google-pay.open-wallet.service.d.ts.map +1 -1
  44. package/bundles/types/open-wallets/services/google-pay/utils/google-pay.utils.d.ts +45 -0
  45. package/bundles/types/open-wallets/services/google-pay/utils/google-pay.utils.d.ts.map +1 -1
  46. package/bundles/types/open-wallets/services/google-pay/utils/index.d.ts +1 -1
  47. package/bundles/types/open-wallets/services/google-pay/utils/index.d.ts.map +1 -1
  48. package/bundles/types/open-wallets/services/google-pay/validation/google-pay.validation.d.ts +13 -0
  49. package/bundles/types/open-wallets/services/google-pay/validation/google-pay.validation.d.ts.map +1 -1
  50. package/bundles/types/open-wallets/types/base-event-data.interface.d.ts +24 -2
  51. package/bundles/types/open-wallets/types/base-event-data.interface.d.ts.map +1 -1
  52. package/bundles/types/open-wallets/types/index.d.ts +2 -1
  53. package/bundles/types/open-wallets/types/index.d.ts.map +1 -1
  54. package/bundles/types/open-wallets/types/on-shipping-address-change-event-data.interface.d.ts +16 -2
  55. package/bundles/types/open-wallets/types/on-shipping-address-change-event-data.interface.d.ts.map +1 -1
  56. package/bundles/types/open-wallets/types/on-shipping-address-change-event-response.interface.d.ts +20 -2
  57. package/bundles/types/open-wallets/types/on-shipping-address-change-event-response.interface.d.ts.map +1 -1
  58. package/bundles/types/open-wallets/types/on-shipping-option-change-event-data.interface.d.ts +13 -2
  59. package/bundles/types/open-wallets/types/on-shipping-option-change-event-data.interface.d.ts.map +1 -1
  60. package/bundles/types/open-wallets/types/on-shipping-option-change-event-response.interface.d.ts +12 -0
  61. package/bundles/types/open-wallets/types/on-shipping-option-change-event-response.interface.d.ts.map +1 -1
  62. package/bundles/types/open-wallets/types/payment-source.type.d.ts +3 -2
  63. package/bundles/types/open-wallets/types/payment-source.type.d.ts.map +1 -1
  64. package/bundles/types/open-wallets/types/shipping-event-to-response.type.d.ts +8 -0
  65. package/bundles/types/open-wallets/types/shipping-event-to-response.type.d.ts.map +1 -1
  66. package/bundles/widget.umd.js +1296 -508
  67. package/bundles/widget.umd.js.d.ts +1377 -200
  68. package/bundles/widget.umd.js.min.d.ts +1377 -200
  69. package/bundles/widget.umd.min.js +1 -1
  70. package/docs/open-wallet-buttons-examples.md +561 -830
  71. package/docs/open-wallet-buttons.md +1652 -0
  72. package/package.json +1 -1
  73. package/slate.md +1673 -0
@@ -2,11 +2,16 @@
2
2
  You can find description of all methods and parameters [here](https://www.npmjs.com/package/@paydock/client-sdk#open-wallet-buttons-simple-example)
3
3
 
4
4
  Open Wallet Buttons provide a next-generation approach to integrating E-Wallets into your checkout with improved event handling and more granular control over wallet interactions.
5
- Currently supports Apple Pay and Google Pay, with more wallet types planned for future releases.
5
+
6
+ Each wallet type has its own dedicated class with fully typed metadata:
7
+ - [ApplePayOpenWalletButton](#ApplePayOpenWalletButton) - for Apple Pay integration
8
+ - [GooglePayOpenWalletButton](#GooglePayOpenWalletButton) - for Google Pay integration
9
+
10
+ On `load()`, each button fetches the service configuration from PayDock and validates that the service type matches the expected wallet. If there is a mismatch (e.g. using an Apple Pay service ID with `GooglePayOpenWalletButton`), an error will be raised via the `onError` callback.
6
11
 
7
12
  If available in your client environment, you will display a simple button that upon clicking it the user will follow the standard flow for the appropriate Wallet. If not available an event will be raised and no button will be displayed.
8
13
 
9
- ## Open Wallet Buttons simple example
14
+ ## Apple Pay Open Wallet Button
10
15
 
11
16
  ### Container
12
17
 
@@ -14,103 +19,58 @@ If available in your client environment, you will display a simple button that u
14
19
  <div id="widget"></div>
15
20
  ```
16
21
 
17
- You must create a container for the Open Wallet Buttons. Inside this tag, the button will be initialized.
22
+ You must create a container for the Open Wallet Button. Inside this tag, the button will be initialized.
18
23
 
19
- Before initializing the button, you must configure your wallet service through the PayDock dashboard and obtain the service ID that will be used to load the button configuration.
24
+ Before initializing the button, you must configure your Apple Pay wallet service through the PayDock dashboard and obtain the service ID that will be used to load the button configuration.
20
25
 
21
26
  ### Initialization
22
27
 
23
- For Apple Pay and Google Pay wallets, the amount and currency are required:
24
-
25
- **Apple Pay Example:**
26
- ```javascript
27
- let button = new paydock.OpenWalletButtons(
28
- "#widget",
29
- publicKeyOrAccessToken,
30
- serviceId,
31
- {
32
- amount: 100,
33
- currency: "USD",
34
- },
35
- [] // Optional: required meta fields validation
36
- );
37
- button.load();
38
- ```
39
-
40
- **Google Pay Example:**
41
28
  ```javascript
42
- let button = new paydock.OpenWalletButtons(
29
+ let button = new paydock.ApplePayOpenWalletButton(
43
30
  "#widget",
44
31
  publicKeyOrAccessToken,
45
32
  serviceId,
46
33
  {
47
34
  amount: 100,
48
- currency: "USD",
49
- merchant_name: "Your Store"
50
- },
51
- [] // Optional: required meta fields validation
35
+ currency: "AUD",
36
+ country: "AU",
37
+ amount_label: "TOTAL",
38
+ store_name: "My Store",
39
+ apple_pay_capabilities: ['credentials_available', 'credentials_status_unknown', 'credentials_unavailable'],
40
+ }
52
41
  );
53
42
  button.load();
54
43
  ```
55
44
 
56
45
  ```javascript
57
46
  // ES2015 | TypeScript
58
- import { OpenWalletButtons } from '@paydock/client-sdk';
47
+ import { ApplePayOpenWalletButton } from '@paydock/client-sdk';
59
48
 
60
- var button = new OpenWalletButtons(
49
+ var button = new ApplePayOpenWalletButton(
61
50
  '#widget',
62
51
  publicKeyOrAccessToken,
63
52
  serviceId,
64
53
  {
65
54
  amount: 100,
66
- currency: 'USD',
67
- },
68
- [] // Optional: required meta fields validation
69
- );
70
- button.load();
71
- ```
72
-
73
- For Apple Pay with shipping enabled:
74
- ```javascript
75
- let button = new paydock.OpenWalletButtons(
76
- "#widget",
77
- publicKeyOrAccessToken,
78
- serviceId,
79
- {
80
- amount: 100,
81
- currency: "USD",
82
- amount_label: "Total",
83
- country: "US",
84
- request_shipping: true,
85
- shipping_options: [
86
- {
87
- id: "standard",
88
- label: "Standard Shipping",
89
- detail: "5-7 business days",
90
- amount: 5.00
91
- },
92
- {
93
- id: "express",
94
- label: "Express Shipping",
95
- detail: "1-2 business days",
96
- amount: 15.00
97
- }
98
- ]
99
- },
100
- ['amount_label', 'country', 'request_shipping'] // Required meta fields validation
55
+ currency: 'AUD',
56
+ country: 'AU',
57
+ amount_label: 'TOTAL',
58
+ store_name: 'My Store',
59
+ }
101
60
  );
102
61
  button.load();
103
62
  ```
104
63
 
105
64
  ### Constructor Parameters
106
65
 
107
- The OpenWalletButtons constructor accepts the following parameters:
66
+ The ApplePayOpenWalletButton constructor accepts the following parameters:
108
67
 
109
68
  1. **selector** (string): CSS selector for the container element
110
69
  2. **publicKeyOrAccessToken** (string): Your PayDock public key or access token
111
- 3. **serviceId** (string): The service ID configured in PayDock dashboard
112
- 4. **meta** (OpenWalletMeta): Configuration object with payment and wallet settings
113
- 5. **requiredMetaFields** (string[], optional): Array of meta field names that must be present
70
+ 3. **serviceId** (string): The Apple Pay service ID configured in PayDock dashboard
71
+ 4. **meta** (ApplePayOpenWalletMeta): Apple Pay-specific configuration object
72
+
73
+ > **Note:** Required meta fields (`amount`, `currency`, `country`, `amount_label`, `store_name`) are validated automatically by the `ApplePayOpenWalletButton` class. You do not need to specify them manually.
114
74
 
115
75
  ### Setting environment
116
76
 
@@ -121,202 +81,7 @@ Bear in mind that you must set an environment before calling `button.load()`.
121
81
  button.setEnv('sandbox');
122
82
  ```
123
83
 
124
- ### Full example
125
-
126
- ```html
127
- <!DOCTYPE html>
128
- <html lang="en">
129
- <head>
130
- <meta charset="UTF-8">
131
- <title>Title</title>
132
- </head>
133
- <body>
134
- <h2>Payment using PayDock Open Wallet Button!</h2>
135
- <div id="widget"></div>
136
- </body>
137
- <script src="https://widget.paydock.com/sdk/latest/widget.umd.min.js" ></script>
138
- <script>
139
- let button = new paydock.OpenWalletButtons(
140
- "#widget",
141
- publicKeyOrAccessToken,
142
- serviceId,
143
- {
144
- amount: 100,
145
- currency: "USD",
146
- amount_label: "Total",
147
- country: "US",
148
- },
149
- ['amount', 'currency'] // Required meta fields
150
- );
151
- button.load();
152
- </script>
153
- </html>
154
- ```
155
-
156
- ## Open Wallet Buttons advanced example
157
-
158
- ### Checking for button availability
159
-
160
- If the customer's browser is not supported, or the customer does not have any card added to their wallet, the button will not load. In this case the callback onUnavailable() will be called. You can define the behavior of this function before loading the button.
161
-
162
- ```javascript
163
- button.onUnavailable((data) => console.log("No open wallet buttons available", data));
164
- ```
165
-
166
- ### Performing actions when the wallet button is clicked
167
-
168
- You can perform validations or actions when the user clicks on the wallet button. The callback supports both synchronous and asynchronous operations using the `attachResult` method.
169
-
170
- ```javascript
171
- // Synchronous example
172
- button.onClick((data) => {
173
- console.log("Perform actions on button click");
174
- // Perform validation logic
175
- // Optionally use attachResult to control flow
176
- data.attachResult(true); // Continue with payment
177
- // data.attachResult(false); // Halt payment
178
- });
179
-
180
- // Asynchronous example
181
- button.onClick((data) => {
182
- // Attach a Promise to control the wallet flow
183
- data.attachResult(
184
- fetch('/api/validate-order')
185
- .then(response => response.json())
186
- .then(result => {
187
- if (!result.valid) {
188
- throw new Error('Order validation failed');
189
- }
190
- return result;
191
- })
192
- );
193
- });
194
- ```
195
-
196
- ### Handling successful OTT creation
197
-
198
- When the One Time Token (OTT) is successfully created, the onSuccess callback will be called with the token data. **This callback is required** - if no handler is provided, an error will be thrown.
199
-
200
- ```javascript
201
- button.onSuccess((data) => {
202
- console.log("OTT created successfully:", data.token);
203
- console.log("Amount:", data.amount);
204
- console.log("Shipping:", data.shipping);
205
- console.log("Billing:", data.billing);
206
-
207
- // Use the OTT token to complete payment on your backend
208
- fetch('/api/process-payment', {
209
- method: 'POST',
210
- headers: { 'Content-Type': 'application/json' },
211
- body: JSON.stringify({ ott_token: data.token })
212
- });
213
- });
214
- ```
215
-
216
- **Important**: The `onSuccess` event handler is mandatory. Not providing one will result in an error.
217
-
218
- ### Performing actions when shipping address is updated
219
-
220
- When shipping is enabled and the customer updates their shipping address, you can recalculate shipping costs and update the payment amount. **This handler is required when shipping is enabled** - if no handler is provided, an error will be thrown.
221
-
222
- ```javascript
223
- button.onShippingAddressChange(async (data) => {
224
- console.log("Shipping address updated:", data);
225
- console.log("Address details:", {
226
- country: data.address_country,
227
- state: data.address_state,
228
- city: data.address_city,
229
- postcode: data.address_postcode,
230
- contact: data.contact
231
- });
232
-
233
- // Call your backend to recalculate shipping
234
- const response = await fetch('/api/calculate-shipping', {
235
- method: 'POST',
236
- headers: { 'Content-Type': 'application/json' },
237
- body: JSON.stringify({
238
- address_country: data.address_country,
239
- address_state: data.address_state,
240
- address_city: data.address_city,
241
- address_postcode: data.address_postcode
242
- })
243
- });
244
-
245
- const result = await response.json();
246
-
247
- return {
248
- amount: result.newAmount,
249
- shipping_options: result.availableShippingOptions
250
- };
251
- });
252
- ```
253
-
254
- **Important**: This event handler is required when using shipping functionality.
255
-
256
- ### Performing actions when shipping option is selected
257
-
258
- When the customer selects a different shipping option, you can update the total amount accordingly. **This handler is required when shipping options are provided** - if no handler is provided, an error will be thrown.
259
-
260
- ```javascript
261
- button.onShippingOptionsChange(async (data) => {
262
- console.log("Shipping option selected:", data);
263
- console.log("Selected option:", {
264
- id: data.shipping_option_id,
265
- label: data.label,
266
- detail: data.detail,
267
- amount: data.amount
268
- });
269
-
270
- // Call your backend to update total with new shipping cost
271
- const response = await fetch('/api/update-shipping-cost', {
272
- method: 'POST',
273
- headers: { 'Content-Type': 'application/json' },
274
- body: JSON.stringify({
275
- shipping_option_id: data.shipping_option_id,
276
- shipping_amount: data.amount
277
- })
278
- });
279
-
280
- const result = await response.json();
281
-
282
- // Note: In some implementations, you might need to access data.data.amount
283
- // Check your actual data structure in console.log output
284
- return {
285
- amount: result.newTotalAmount
286
- };
287
- });
288
- ```
289
-
290
- **Important**: This event handler is required when providing shipping options.
291
-
292
- ### Handling errors
293
-
294
- Register a callback function to handle errors that occur during wallet operations.
295
-
296
- ```javascript
297
- button.onError((data) => {
298
- console.error("Open Wallet error:", data.error);
299
- console.log("Error context:", data.context);
300
-
301
- // Show user-friendly error message
302
- showErrorMessage("Payment initialization failed. Please try again.");
303
- });
304
- ```
305
-
306
- ### Handling checkout cancellation
307
-
308
- When the user cancels or closes the wallet payment interface, you can perform cleanup operations.
309
-
310
- ```javascript
311
- button.onCancel((data) => {
312
- console.log("Wallet checkout cancelled", data);
313
-
314
- // Perform cleanup or redirect user
315
- window.location.href = '/checkout';
316
- });
317
- ```
318
-
319
- ### Apple Pay Full example
84
+ ### Full Apple Pay example
320
85
 
321
86
  ```html
322
87
  <!DOCTYPE html>
@@ -326,20 +91,21 @@ button.onCancel((data) => {
326
91
  <title>Apple Pay with Open Wallets</title>
327
92
  </head>
328
93
  <body>
329
- <h2>Payment using PayDock Open Wallet Button!</h2>
94
+ <h2>Payment using PayDock Apple Pay Open Wallet Button!</h2>
330
95
  <div id="widget"></div>
331
96
  </body>
332
97
  <script src="https://widget.paydock.com/sdk/latest/widget.umd.min.js" ></script>
333
98
  <script>
334
- let button = new paydock.OpenWalletButtons(
99
+ let button = new paydock.ApplePayOpenWalletButton(
335
100
  "#widget",
336
101
  publicKeyOrAccessToken,
337
102
  serviceId,
338
103
  {
339
104
  amount: 100,
340
- currency: "USD",
341
- amount_label: "Total",
342
- country: "US",
105
+ currency: "AUD",
106
+ country: "AU",
107
+ amount_label: "TOTAL",
108
+ store_name: "My Store",
343
109
  request_shipping: true,
344
110
  request_payer_name: true,
345
111
  request_payer_email: true,
@@ -392,38 +158,37 @@ button.onCancel((data) => {
392
158
  }
393
159
  ],
394
160
  apple_pay_capabilities: ['credentials_available', 'credentials_status_unknown', 'credentials_unavailable']
395
- },
396
- ['amount_label', 'country', 'request_shipping', 'shipping_options', 'apple_pay_capabilities'] // Required fields validation
161
+ }
397
162
  );
398
-
163
+
399
164
  button.setEnv('sandbox');
400
-
165
+
401
166
  button.onUnavailable((data) => {
402
167
  console.log("Apple Pay not available:", data);
403
168
  // Show alternative payment methods
404
169
  });
405
-
170
+
406
171
  button.onClick((data) => {
407
172
  console.log("Apple Pay button clicked");
408
173
  // Perform pre-payment validation
409
174
  });
410
-
175
+
411
176
  button.onSuccess((data) => {
412
177
  console.log("Payment successful:", data);
413
178
  // Process the OTT token on your backend
414
179
  processPayment(data.token);
415
180
  });
416
-
181
+
417
182
  button.onError((data) => {
418
183
  console.error("Payment error:", data);
419
184
  // Handle error appropriately
420
185
  });
421
-
186
+
422
187
  button.onCancel((data) => {
423
188
  console.log("Payment cancelled");
424
189
  // Handle cancellation
425
190
  });
426
-
191
+
427
192
  button.onShippingAddressChange(async (addressData) => {
428
193
  // Update shipping costs based on address
429
194
  const response = await updateShippingCosts(addressData);
@@ -432,7 +197,7 @@ button.onCancel((data) => {
432
197
  shipping_options: response.shippingOptions
433
198
  };
434
199
  });
435
-
200
+
436
201
  button.onShippingOptionsChange(async (optionData) => {
437
202
  // Update total based on selected shipping option
438
203
  const response = await updateTotal(optionData);
@@ -440,9 +205,9 @@ button.onCancel((data) => {
440
205
  amount: response.newAmount
441
206
  };
442
207
  });
443
-
208
+
444
209
  button.load();
445
-
210
+
446
211
  async function updateShippingCosts(addressData) {
447
212
  // Your shipping calculation logic based on address
448
213
  const baseAmount = 100;
@@ -460,23 +225,22 @@ button.onCancel((data) => {
460
225
  amount: 18.00
461
226
  }
462
227
  ];
463
-
228
+
464
229
  return {
465
230
  newAmount: baseAmount + updatedShippingOptions[0].amount,
466
231
  shippingOptions: updatedShippingOptions
467
232
  };
468
233
  }
469
-
234
+
470
235
  async function updateTotal(optionData) {
471
236
  // Your total calculation logic
472
237
  const baseAmount = 100;
473
- // Note: Check if you need data.data.amount or data.amount based on your implementation
474
238
  const shippingAmount = optionData.amount || optionData.data?.amount;
475
239
  return {
476
240
  newAmount: baseAmount + shippingAmount
477
241
  };
478
242
  }
479
-
243
+
480
244
  function processPayment(ottToken) {
481
245
  // Send OTT token to your backend for payment processing
482
246
  fetch('/api/process-payment', {
@@ -489,114 +253,362 @@ button.onCancel((data) => {
489
253
  </html>
490
254
  ```
491
255
 
492
- ### Google Pay Full Example
256
+ ### Apple Pay with Shipping
493
257
 
494
- ```html
495
- <!DOCTYPE html>
496
- <html lang="en">
497
- <head>
498
- <meta charset="UTF-8">
499
- <title>Google Pay with Open Wallets</title>
500
- </head>
501
- <body>
502
- <h2>Payment using PayDock Google Pay Open Wallet Button!</h2>
503
- <div id="widget"></div>
504
- </body>
505
- <script src="https://widget.paydock.com/sdk/latest/widget.umd.min.js" ></script>
506
- <script>
507
- let button = new paydock.OpenWalletButtons(
508
- "#widget",
509
- publicKeyOrAccessToken,
510
- serviceId,
511
- {
512
- amount: 100,
513
- currency: "USD",
514
- amount_label: "Total",
515
- country: "AU",
516
- request_shipping: true,
517
- show_billing_address: true,
518
- merchant_name: 'Test Merchant',
519
- style: {
520
- google: {
521
- button_type: 'buy',
522
- button_color: 'default',
523
- button_size_mode: 'fill'
524
- }
258
+ For Apple Pay with shipping enabled:
259
+ ```javascript
260
+ let button = new paydock.ApplePayOpenWalletButton(
261
+ "#widget",
262
+ publicKeyOrAccessToken,
263
+ serviceId,
264
+ {
265
+ amount: 100,
266
+ currency: "AUD",
267
+ country: "AU",
268
+ amount_label: "TOTAL",
269
+ store_name: "My Store",
270
+ request_shipping: true,
271
+ shipping_editing_mode: 'available',
272
+ required_shipping_contact_fields: [
273
+ 'postalAddress',
274
+ 'name',
275
+ 'phone',
276
+ 'email',
277
+ ],
278
+ shipping_options: [
279
+ {
280
+ id: "standard",
281
+ label: "Standard Shipping",
282
+ detail: "5-7 business days",
283
+ amount: 5.00
525
284
  },
526
- // Google Pay specific properties
527
- payment_method_type: 'CARD',
528
- allowed_auth_methods: ['PAN_ONLY', 'CRYPTOGRAM_3DS'],
529
- allowed_card_networks: ['AMEX', 'DISCOVER', 'JCB', 'MASTERCARD', 'VISA'],
530
- billing_address_required: true,
531
- shipping_options: [
532
- {
533
- id: "standard",
534
- label: "Standard Shipping",
535
- detail: "Arrives in 5 to 7 days",
536
- amount: 5.00,
537
- type: "ELECTRONIC"
538
- },
539
- {
540
- id: "express",
541
- label: "Express Shipping",
542
- detail: "Arrives in 1 to 2 days",
543
- amount: 15.00,
544
- type: "PICKUP"
545
- }
546
- ]
547
- },
548
- ['amount_label', 'country', 'request_shipping', 'shipping_options', 'merchant_name']
549
- );
550
-
551
- button.setEnv('sandbox');
552
-
553
- // Required handlers
554
- button.onSuccess((data) => {
555
- console.log("Payment successful:", data);
556
- processPayment(data.token);
557
- });
558
-
559
- button.onShippingAddressChange(async (addressData) => {
560
- const response = await updateShippingCosts(addressData);
561
- return {
562
- amount: response.newAmount,
563
- shipping_options: response.shippingOptions
285
+ {
286
+ id: "express",
287
+ label: "Express Shipping",
288
+ detail: "1-2 business days",
289
+ amount: 15.00
290
+ }
291
+ ],
292
+ apple_pay_capabilities: ['credentials_available', 'credentials_status_unknown', 'credentials_unavailable']
293
+ }
294
+ );
295
+ button.load();
296
+ ```
297
+
298
+ When supporting shipping, the methods `onShippingAddressChange` and `onShippingOptionsChange` are required to update the shipping address and options.
299
+
300
+ ```javascript
301
+ button.onShippingAddressChange(async function(data) {
302
+ console.log("Shipping address has been updated", data);
303
+ // Call your backend to recalculate shipping
304
+ return {
305
+ amount: newAmount,
306
+ shipping_options: updatedShippingOptions
307
+ };
308
+ });
309
+
310
+ button.onShippingOptionsChange(async function(data) {
311
+ console.log("Shipping option selected", data);
312
+ // Update total based on selected shipping option
313
+ return {
314
+ amount: newTotalAmount
315
+ };
316
+ });
317
+ ```
318
+
319
+ ### Supported Shipping Cases
320
+
321
+ #### Injected Shipping Address, non-editable by the customer
322
+
323
+ This is the case where the shipping address is injected by the merchant and is not editable by the customer. The customer can only select the shipping option.
324
+
325
+ The required meta parameters for this case are:
326
+ - shipping_editing_mode: 'store_pickup'
327
+ - required_shipping_contact_fields: ['postalAddress'] <-- At least one of the fields is required so the shipping address is shown at Apple Pay.
328
+
329
+ ```javascript
330
+ meta: {
331
+ apple_pay_capabilities: ['credentials_available', 'credentials_status_unknown', 'credentials_unavailable'],
332
+ amount_label: 'TOTAL',
333
+ country: 'AU',
334
+ currency: 'AUD',
335
+ amount: 10,
336
+ shipping_editing_mode: 'store_pickup',
337
+ required_shipping_contact_fields: [
338
+ 'postalAddress',
339
+ 'name',
340
+ 'phone',
341
+ 'email',
342
+ ],
343
+ shipping: {
344
+ amount: 5,
345
+ address_line1: "Address Line 1",
346
+ address_city: "Test Locality",
347
+ address_state: "NSW",
348
+ address_country: "Australia",
349
+ address_country_code: "AU",
350
+ address_postcode: "3000",
351
+ contact: {
352
+ phone: "+61400245562",
353
+ email: "test@example.com",
354
+ first_name: "QA",
355
+ last_name: "QA",
356
+ },
357
+ options: [
358
+ {
359
+ label: "Test 1",
360
+ detail: "This is a test 1 shipping methods",
361
+ amount: 10,
362
+ id: "randomId1",
363
+ }
364
+ ],
365
+ },
366
+ }
367
+ ```
368
+
369
+ #### Injected Shipping Address, editable by the customer
370
+
371
+ This is the case where the shipping address is injected by the merchant and is editable by the customer. The customer can edit the shipping address and select the shipping option.
372
+
373
+ The required meta parameters for this case are:
374
+ - shipping_editing_mode: 'available'
375
+ - required_shipping_contact_fields: ['postalAddress'] <-- At least one of the fields is required so the shipping address is shown at Apple Pay.
376
+
377
+ ```javascript
378
+ meta: {
379
+ apple_pay_capabilities: ['credentials_available', 'credentials_status_unknown', 'credentials_unavailable'],
380
+ amount_label: 'TOTAL',
381
+ country: 'AU',
382
+ currency: 'AUD',
383
+ amount: 10,
384
+ shipping_editing_mode: 'available',
385
+ required_shipping_contact_fields: [
386
+ 'postalAddress',
387
+ 'name',
388
+ 'phone',
389
+ 'email',
390
+ ],
391
+ shipping: {
392
+ amount: 5,
393
+ address_line1: "Address Line 1",
394
+ address_city: "Test Locality",
395
+ address_state: "NSW",
396
+ address_country: "Australia",
397
+ address_country_code: "AU",
398
+ address_postcode: "3000",
399
+ contact: {
400
+ phone: "+61400245562",
401
+ email: "test@example.com",
402
+ first_name: "QA",
403
+ last_name: "QA",
404
+ },
405
+ options: [
406
+ {
407
+ label: "Test 1",
408
+ detail: "This is a test 1 shipping methods",
409
+ amount: 10,
410
+ id: "randomId1",
411
+ }
412
+ ],
413
+ },
414
+ }
415
+ ```
416
+
417
+ #### Shipping address editable by the customer (no pre-filled address)
418
+
419
+ This is the case where the shipping address is not injected by the merchant and is editable by the customer. The customer can edit the shipping address and select the shipping option.
420
+
421
+ The required meta parameters for this case are:
422
+ - shipping_editing_mode: 'available'
423
+ - required_shipping_contact_fields: ['postalAddress'] <-- At least one of the fields is required so the shipping address is shown at Apple Pay.
424
+
425
+ ```javascript
426
+ meta: {
427
+ apple_pay_capabilities: ['credentials_available', 'credentials_status_unknown', 'credentials_unavailable'],
428
+ amount_label: 'TOTAL',
429
+ country: 'AU',
430
+ currency: 'AUD',
431
+ amount: 10,
432
+ shipping_editing_mode: 'available',
433
+ required_shipping_contact_fields: [
434
+ 'postalAddress',
435
+ 'name',
436
+ 'phone',
437
+ 'email',
438
+ ],
439
+ }
440
+ ```
441
+
442
+ #### No shipping address
443
+
444
+ This is the case where no shipping address is required at all in the popup (e.g., digital goods, services, or virtual products, or Shipping Address collected separately by the merchant). The "Send to" UI field will not be shown in the Apple Pay sheet, it will be hidden.
445
+
446
+ **Important:**
447
+ - No shipping address should be provided in the meta object.
448
+ - Shipping address could be provided in the initial POST `/v1/charges/wallet` endpoint, if collected previously.
449
+
450
+ The required meta parameters for this case are:
451
+ - `required_shipping_contact_fields`: Only include contact fields if needed (phone, email), but NOT `postalAddress`.
452
+
453
+ ```javascript
454
+ meta: {
455
+ amount_label: "TOTAL",
456
+ country: "AU",
457
+ currency: "AUD",
458
+ amount: 10,
459
+ shipping_editing_mode: "available",
460
+ required_shipping_contact_fields: ["phone", "email"],
461
+ apple_pay_capabilities: ["credentials_available", "credentials_status_unknown", "credentials_unavailable"]
462
+ }
463
+ ```
464
+
465
+ ## Google Pay Open Wallet Button
466
+
467
+ ### Initialization
468
+
469
+ ```javascript
470
+ let button = new paydock.GooglePayOpenWalletButton(
471
+ "#widget",
472
+ publicKeyOrAccessToken,
473
+ serviceId,
474
+ {
475
+ amount: 100,
476
+ currency: "AUD",
477
+ country: "AU",
478
+ merchant_name: "Your Store",
479
+ }
480
+ );
481
+ button.load();
482
+ ```
483
+
484
+ ```javascript
485
+ // ES2015 | TypeScript
486
+ import { GooglePayOpenWalletButton } from '@paydock/client-sdk';
487
+
488
+ var button = new GooglePayOpenWalletButton(
489
+ '#widget',
490
+ publicKeyOrAccessToken,
491
+ serviceId,
492
+ {
493
+ amount: 100,
494
+ currency: 'AUD',
495
+ country: 'AU',
496
+ merchant_name: 'Your Store',
497
+ }
498
+ );
499
+ button.load();
500
+ ```
501
+
502
+ ### Constructor Parameters
503
+
504
+ The GooglePayOpenWalletButton constructor accepts the following parameters:
505
+
506
+ 1. **selector** (string): CSS selector for the container element
507
+ 2. **publicKeyOrAccessToken** (string): Your PayDock public key or access token
508
+ 3. **serviceId** (string): The Google Pay service ID configured in PayDock dashboard
509
+ 4. **meta** (GooglePayOpenWalletMeta): Google Pay-specific configuration object
510
+
511
+ > **Note:** Required meta fields (`amount`, `currency`, `country`) are validated automatically by the `GooglePayOpenWalletButton` class. You do not need to specify them manually.
512
+
513
+ ### Full Google Pay Example
514
+
515
+ ```html
516
+ <!DOCTYPE html>
517
+ <html lang="en">
518
+ <head>
519
+ <meta charset="UTF-8">
520
+ <title>Google Pay with Open Wallets</title>
521
+ </head>
522
+ <body>
523
+ <h2>Payment using PayDock Google Pay Open Wallet Button!</h2>
524
+ <div id="widget"></div>
525
+ </body>
526
+ <script src="https://widget.paydock.com/sdk/latest/widget.umd.min.js" ></script>
527
+ <script>
528
+ let button = new paydock.GooglePayOpenWalletButton(
529
+ "#widget",
530
+ publicKeyOrAccessToken,
531
+ serviceId,
532
+ {
533
+ amount: 100,
534
+ currency: "AUD",
535
+ country: "AU",
536
+ amount_label: "Total",
537
+ request_shipping: true,
538
+ show_billing_address: true,
539
+ merchant_name: 'Test Merchant',
540
+ style: {
541
+ button_type: 'buy',
542
+ button_color: 'default',
543
+ button_size_mode: 'fill'
544
+ },
545
+ shipping_options: [
546
+ {
547
+ id: "standard",
548
+ label: "Standard Shipping",
549
+ detail: "Arrives in 5 to 7 days",
550
+ amount: 5.00,
551
+ type: "ELECTRONIC"
552
+ },
553
+ {
554
+ id: "express",
555
+ label: "Express Shipping",
556
+ detail: "Arrives in 1 to 2 days",
557
+ amount: 15.00,
558
+ type: "PICKUP"
559
+ }
560
+ ]
561
+ }
562
+ );
563
+
564
+ button.setEnv('sandbox');
565
+
566
+ // Required handlers
567
+ button.onSuccess((data) => {
568
+ console.log("Payment successful:", data);
569
+ processPayment(data.token);
570
+ });
571
+
572
+ button.onShippingAddressChange(async (addressData) => {
573
+ const response = await updateShippingCosts(addressData);
574
+ return {
575
+ amount: response.newAmount,
576
+ shipping_options: response.shippingOptions
564
577
  };
565
578
  });
566
-
579
+
567
580
  button.onShippingOptionsChange(async (optionData) => {
568
581
  const response = await updateTotal(optionData);
569
582
  return {
570
583
  amount: response.newAmount
571
584
  };
572
585
  });
573
-
586
+
574
587
  // Optional handlers
575
588
  button.onUnavailable((data) => {
576
589
  console.log("Google Pay not available:", data);
577
590
  // Show alternative payment methods
578
591
  });
579
-
592
+
580
593
  button.onError((data) => {
581
594
  console.error("Payment error:", data);
582
595
  // Handle error appropriately
583
596
  });
584
-
597
+
585
598
  button.onCancel((data) => {
586
599
  console.log("Payment cancelled");
587
600
  // Handle cancellation
588
601
  });
589
-
602
+
590
603
  button.onClick((data) => {
591
604
  console.log("Google Pay button clicked");
592
605
  // Perform pre-payment validation
593
606
  });
594
-
607
+
595
608
  button.load();
596
-
597
- // Helper functions (same implementation as Apple Pay example)
609
+
610
+ // Helper functions
598
611
  async function updateShippingCosts(addressData) {
599
- // Your shipping calculation logic based on address
600
612
  const baseAmount = 100;
601
613
  const updatedShippingOptions = [
602
614
  {
@@ -614,24 +626,22 @@ button.onCancel((data) => {
614
626
  type: "PICKUP"
615
627
  }
616
628
  ];
617
-
629
+
618
630
  return {
619
631
  newAmount: baseAmount + updatedShippingOptions[0].amount,
620
632
  shippingOptions: updatedShippingOptions
621
633
  };
622
634
  }
623
-
635
+
624
636
  async function updateTotal(optionData) {
625
- // Your total calculation logic
626
637
  const baseAmount = 100;
627
638
  const shippingAmount = optionData.amount || optionData.data?.amount;
628
639
  return {
629
640
  newAmount: baseAmount + shippingAmount
630
641
  };
631
642
  }
632
-
643
+
633
644
  function processPayment(ottToken) {
634
- // Send OTT token to your backend for payment processing
635
645
  fetch('/api/process-payment', {
636
646
  method: 'POST',
637
647
  headers: { 'Content-Type': 'application/json' },
@@ -642,264 +652,214 @@ button.onCancel((data) => {
642
652
  </html>
643
653
  ```
644
654
 
645
- ### Events
646
- The above events can be used in a more generic way via the `eventEmitter.subscribe` method internally, but the recommended approach is to use the dedicated event handler methods provided by the OpenWalletButtons class.
655
+ ## Common API
647
656
 
648
- **Available Event Handler Methods:**
649
- - `onClick(handler)` - Button click events (supports attachResult for flow control)
650
- - `onSuccess(handler)` - **Required** - OTT creation success events
651
- - `onUnavailable(handler)` - Wallet unavailable events (supports Promise pattern)
652
- - `onError(handler)` - Error events (supports Promise pattern)
653
- - `onCancel(handler)` - Checkout cancellation events (supports Promise pattern)
654
- - `onShippingAddressChange(handler)` - **Required for shipping** - Address change events
655
- - `onShippingOptionsChange(handler)` - **Required for shipping options** - Option change events
657
+ Both `ApplePayOpenWalletButton` and `GooglePayOpenWalletButton` share the same event handler API inherited from the base class.
656
658
 
657
- **Event Handler Patterns:**
659
+ ### Checking for button availability
660
+
661
+ If the customer's browser is not supported, or the customer does not have any card added to their wallet, the button will not load. In this case the callback onUnavailable() will be called. You can define the behavior of this function before loading the button.
658
662
 
659
663
  ```javascript
660
- // Required handlers (will throw error if not provided)
661
- button.onSuccess(handler); // Always required
662
- button.onShippingAddressChange(handler); // Required when shipping enabled
663
- button.onShippingOptionsChange(handler); // Required when shipping options provided
664
+ button.onUnavailable((data) => console.log("No wallet button available", data));
665
+ ```
664
666
 
665
- // Optional handlers with Promise support
666
- button.onUnavailable(handler); // or await button.onUnavailable()
667
- button.onError(handler); // or await button.onError()
668
- button.onCancel(handler); // or await button.onCancel()
667
+ ### Service type validation
669
668
 
670
- // Click handler with flow control
671
- button.onClick(handler); // Use data.attachResult() for async operations
669
+ Each button validates that the service configuration matches its expected wallet type. If you use an Apple Pay service ID with `GooglePayOpenWalletButton` (or vice versa), an error will be emitted via `onError`:
670
+
671
+ ```javascript
672
+ // This will raise an error if the service ID does not correspond to a Google Pay service
673
+ let button = new paydock.GooglePayOpenWalletButton(
674
+ "#widget",
675
+ publicKeyOrAccessToken,
676
+ applePayServiceId, // Wrong! This is an Apple Pay service ID
677
+ meta
678
+ );
679
+
680
+ button.onError((data) => {
681
+ // Error: Service configuration type 'ApplePay' does not match expected wallet type 'google'.
682
+ console.error(data.error.message);
683
+ });
684
+
685
+ button.load();
672
686
  ```
673
687
 
674
- ### Configuration Options
688
+ ### Performing actions when the wallet button is clicked
675
689
 
676
- #### Required Meta Fields
690
+ You can perform validations or actions when the user clicks on the wallet button. The callback supports both synchronous and asynchronous operations using the `attachResult` method.
677
691
 
678
- - `amount`: The payment amount (number)
679
- - `currency`: The currency code (string, e.g., "USD")
692
+ ```javascript
693
+ // Synchronous example
694
+ button.onClick((data) => {
695
+ console.log("Perform actions on button click");
696
+ // Perform validation logic
697
+ // Optionally use attachResult to control flow
698
+ data.attachResult(true); // Continue with payment
699
+ // data.attachResult(false); // Halt payment
700
+ });
680
701
 
681
- #### PayDock-Specific Meta Fields
702
+ // Asynchronous example
703
+ button.onClick((data) => {
704
+ // Attach a Promise to control the wallet flow
705
+ data.attachResult(
706
+ fetch('/api/validate-order')
707
+ .then(response => response.json())
708
+ .then(result => {
709
+ if (!result.valid) {
710
+ throw new Error('Order validation failed');
711
+ }
712
+ return result;
713
+ })
714
+ );
715
+ });
716
+ ```
682
717
 
683
- The following are PayDock-specific properties available in `OpenWalletMeta`:
718
+ ### Handling successful OTT creation
684
719
 
685
- **Payment Configuration:**
686
- - `amount_label?: string`: Label for the total amount
687
- - `country?: string`: Country code (e.g., "US")
688
- - `capture?: boolean`: Whether to capture the payment immediately
689
- - `reference?: string`: Payment reference
690
- - `id?: string`: Payment ID
691
- - `credentials?: object`: Gateway credentials
720
+ When the One Time Token (OTT) is successfully created, the onSuccess callback will be called with the token data. **This callback is required** - if no handler is provided, an error will be thrown.
692
721
 
693
- **Contact and Shipping:**
694
- - `request_shipping?: boolean`: Enable shipping address collection
695
- - `request_payer_name?: boolean`: Request payer name
696
- - `request_payer_email?: boolean`: Request payer email
697
- - `request_payer_phone?: boolean`: Request payer phone
698
- - `show_billing_address?: boolean`: Show billing address fields
699
- - `shipping_options?: IShippingOption[]`: Array of shipping options
700
-
701
- **UI and Display:**
702
- - `style?: WalletStyles`: Button styling options
703
- - `pay_later?: boolean`: Enable pay later options
704
- - `hide_message?: boolean`: Hide payment messages
705
- - `standalone?: boolean`: Standalone mode
706
- - `merchant_name?: string`: Merchant display name
707
-
708
- **Wallet-Specific:**
709
- - `apple_pay_capabilities?: string[]`: Apple Pay capability requirements
710
- - `wallets?: WALLET_TYPES[]`: Supported wallet types
711
- - `access_token?: string`: Access token
712
- - `refresh_token?: string`: Refresh token
713
- - `client_id?: string`: Client ID
714
-
715
- #### Extended Native Properties
716
- Since `OpenWalletMeta` extends `ApplePayJS.ApplePayPaymentRequest` and Google Pay interfaces, you can use any native Apple Pay or Google Pay properties directly in the configuration object alongside PayDock properties. See the [Extended Interface Properties](#extended-interface-properties) section for comprehensive details.
717
-
718
- #### Configuration Comparison Quick Reference
719
-
720
- | Feature | PayDock Property | Apple Pay Native Property | Google Pay Native Property |
721
- |---------|------------------|---------------------------|----------------------------|
722
- | **Country** | `country: 'US'` | `countryCode: 'US'` | `parameters.allowedCountries: ['US']` |
723
- | **Currency** | `currency: 'USD'` | `currencyCode: 'USD'` | Via PayDock property |
724
- | **Amount** | `amount: 100` | `total: { amount: '100.00' }` | Via PayDock property |
725
- | **Billing Address** | `show_billing_address: true` | `requiredBillingContactFields: [...]` | `billingAddressRequired: true` |
726
- | **Shipping Address** | `request_shipping: true` | `requiredShippingContactFields: [...]` | `shippingAddressRequired: true` |
727
- | **Card Networks** | Auto-configured | `supportedNetworks: ['visa', ...]` | `allowedCardNetworks: ['VISA', ...]` |
728
- | **Button Style** | `style.apple.button_style` | Via PayDock style property | `style.google.button_color` |
729
-
730
- #### Apple Pay Specific Style Options
731
722
  ```javascript
732
- style: {
733
- apple: {
734
- button_type: 'add-money' | 'book' | 'buy' | 'check-out' | 'continue' | 'contribute' | 'donate' | 'order' | 'pay' | 'plain' | 'reload' | 'rent' | 'set-up' | 'subscribe' | 'support' | 'tip' | 'top-up',
735
- button_style: 'black' | 'white' | 'white-outline'
736
- },
737
- google: {
738
- button_type: 'book' | 'buy' | 'checkout' | 'donate' | 'order' | 'pay' | 'plain' | 'subscribe',
739
- button_color: 'default' | 'black' | 'white',
740
- button_size_mode: 'static' | 'fill'
741
- }
742
- }
723
+ button.onSuccess((data) => {
724
+ console.log("OTT created successfully:", data.token);
725
+ console.log("Amount:", data.amount);
726
+ console.log("Shipping:", data.shipping);
727
+ console.log("Billing:", data.billing);
728
+
729
+ // Use the OTT token to complete payment on your backend
730
+ fetch('/api/process-payment', {
731
+ method: 'POST',
732
+ headers: { 'Content-Type': 'application/json' },
733
+ body: JSON.stringify({ ott_token: data.token })
734
+ });
735
+ });
743
736
  ```
744
737
 
745
- ### Google Pay Specific Properties
738
+ **Important**: The `onSuccess` event handler is mandatory. Not providing one will result in an error.
746
739
 
747
- The following are Google Pay-specific properties available in `GooglePayMeta`:
740
+ ### Updating meta after initialization
748
741
 
749
- **Payment Method Configuration:**
750
- - `payment_method_type?: google.payments.api.PaymentMethodType`: Payment method type (usually 'CARD')
751
- - `allowed_auth_methods?: google.payments.api.CardAuthMethod[]`: Authentication methods (e.g., ['PAN_ONLY', 'CRYPTOGRAM_3DS'])
752
- - `allowed_card_networks?: google.payments.api.CardNetwork[]`: Supported card networks (e.g., ['AMEX', 'DISCOVER', 'INTERAC', 'JCB', 'MASTERCARD', 'VISA'])
742
+ If the screen where the button is rendered allows for cart/amount changes, call `setMeta` method to update the meta information. The `setMeta` method is fully typed for each wallet:
753
743
 
754
- **Billing Address Configuration:**
755
- - `billing_address_required?: boolean`: Override for show_billing_address
756
- - `billing_address_format?: google.payments.api.BillingAddressFormat`: Billing address format specification
744
+ ```javascript
745
+ // For Apple Pay - accepts ApplePayOpenWalletMeta
746
+ applePayButton.setMeta({ ...meta, amount: 29.99, amount_label: 'NEW TOTAL' });
757
747
 
758
- **Merchant Configuration:**
759
- - `merchant_name?: string`: Display name for the merchant
748
+ // For Google Pay - accepts GooglePayOpenWalletMeta
749
+ googlePayButton.setMeta({ ...meta, amount: 29.99, merchant_name: 'Updated Store' });
750
+ ```
751
+
752
+ ### Handling errors
760
753
 
761
- ### Extended Interface Properties
754
+ Register a callback function to handle errors that occur during wallet operations, including service type mismatches.
762
755
 
763
- The `OpenWalletMeta` interface extends native Apple Pay and Google Pay interfaces, giving you access to their native properties alongside PayDock-specific configurations:
756
+ ```javascript
757
+ button.onError((data) => {
758
+ console.error("Open Wallet error:", data.error);
759
+ console.log("Error context:", data.context);
764
760
 
765
- - Extends `ApplePayJS.ApplePayPaymentRequest` (full Apple Pay interface)
766
- - Extends `google.payments.api.IsReadyToPayPaymentMethodSpecification` (except `tokenizationSpecification`)
767
- - Extends `google.payments.api.PaymentMethodSpecification`
761
+ // Show user-friendly error message
762
+ showErrorMessage("Payment initialization failed. Please try again.");
763
+ });
764
+ ```
768
765
 
769
- #### Apple Pay Extended Properties (ApplePayJS.ApplePayPaymentRequest)
766
+ ### Handling checkout cancellation
770
767
 
771
- Since `OpenWalletMeta` extends `ApplePayJS.ApplePayPaymentRequest`, you can use any native Apple Pay property:
768
+ When the user cancels or closes the wallet payment interface, you can perform cleanup operations.
772
769
 
773
770
  ```javascript
774
- const applePayConfig = {
775
- // PayDock specific properties
776
- amount: 100,
777
- currency: 'USD',
778
- amount_label: 'Total',
779
- country: 'US',
780
-
781
- // Native Apple Pay properties
782
- countryCode: 'US', // Country code for the payment
783
- currencyCode: 'USD', // Currency code for the payment
784
- merchantCapabilities: [ // Merchant capabilities
785
- 'supports3DS',
786
- 'supportsCredit',
787
- 'supportsDebit'
788
- ],
789
- supportedNetworks: [ // Supported card networks
790
- 'visa',
791
- 'masterCard',
792
- 'amex',
793
- 'discover'
794
- ],
795
- requiredBillingContactFields: [ // Required billing fields
796
- 'name',
797
- 'postalAddress',
798
- 'email',
799
- 'phone'
800
- ],
801
- requiredShippingContactFields: [ // Required shipping fields
802
- 'postalAddress',
803
- 'name',
804
- 'phone',
805
- 'email'
806
- ],
807
- supportedCountries: [ // Supported countries for shipping
808
- 'US', 'CA', 'GB'
809
- ],
810
- total: { // Total amount object
811
- label: 'Total',
812
- amount: '100.00',
813
- type: 'final'
814
- },
815
- shippingContact: { // Pre-filled shipping contact
816
- givenName: 'John',
817
- familyName: 'Doe',
818
- emailAddress: 'john@example.com'
819
- },
820
- billingContact: { // Pre-filled billing contact
821
- givenName: 'John',
822
- familyName: 'Doe'
823
- }
824
- };
771
+ button.onCancel((data) => {
772
+ console.log("Wallet checkout cancelled", data);
773
+
774
+ // Perform cleanup or redirect user
775
+ window.location.href = '/checkout';
776
+ });
825
777
  ```
826
778
 
827
- #### Google Pay Extended Properties
779
+ ### Cleaning up
828
780
 
829
- Since `OpenWalletMeta` extends Google Pay interfaces, you can use native Google Pay properties:
781
+ Remove the wallet button from the DOM when it is no longer needed:
830
782
 
831
783
  ```javascript
832
- const googlePayConfig = {
833
- // PayDock specific properties
834
- amount: 100,
835
- currency: 'USD',
836
- amount_label: 'Total',
837
- country: 'US',
838
-
839
- // Native Google Pay properties (from IsReadyToPayPaymentMethodSpecification)
840
- type: 'CARD', // Payment method type
841
- parameters: {
842
- allowedAuthMethods: [ // Allowed authentication methods
843
- 'PAN_ONLY',
844
- 'CRYPTOGRAM_3DS'
845
- ],
846
- allowedCardNetworks: [ // Allowed card networks
847
- 'AMEX',
848
- 'DISCOVER',
849
- 'JCB',
850
- 'MASTERCARD',
851
- 'VISA'
852
- ],
853
- billingAddressRequired: true, // Require billing address
854
- billingAddressParameters: { // Billing address parameters
855
- format: 'FULL',
856
- phoneNumberRequired: true
857
- }
858
- },
859
-
860
- // Note: tokenizationSpecification is omitted from OpenWalletMeta
861
- // as it's handled automatically by PayDock
862
- };
784
+ button.destroy();
863
785
  ```
864
786
 
865
- #### Property Inheritance
866
-
867
- Since `OpenWalletMeta` extends native Apple Pay and Google Pay interfaces, you get access to both:
787
+ ### Events
788
+ The above events can be used in a more generic way via the `eventEmitter.subscribe` method internally, but the recommended approach is to use the dedicated event handler methods provided by the button classes.
868
789
 
869
- 1. **PayDock Properties**: Simplified, cross-wallet properties (e.g., `amount`, `currency`, `country`)
870
- 2. **Native Extended Properties**: Full native wallet properties (e.g., `merchantCapabilities`, `supportedNetworks`)
790
+ **Available Event Handler Methods:**
791
+ - `onClick(handler)` - Button click events (supports attachResult for flow control)
792
+ - `onSuccess(handler)` - **Required** - OTT creation success events
793
+ - `onUnavailable(handler)` - Wallet unavailable events (supports Promise pattern)
794
+ - `onError(handler)` - Error events (supports Promise pattern)
795
+ - `onCancel(handler)` - Checkout cancellation events (supports Promise pattern)
796
+ - `onLoaded(handler)` - Button loaded/rendered events
797
+ - `onShippingAddressChange(handler)` - **Required for shipping** - Address change events
798
+ - `onShippingOptionsChange(handler)` - **Required for shipping options** - Option change events
871
799
 
872
- Both types of properties can be used together in the same configuration object:
800
+ **Event Handler Patterns:**
873
801
 
874
802
  ```javascript
875
- // Example combining PayDock and native properties
876
- const config = {
877
- // PayDock simplified properties
878
- amount: 100,
879
- currency: 'USD',
880
- country: 'US',
881
- show_billing_address: true,
882
-
883
- // Native Apple Pay properties (available due to interface extension)
884
- merchantCapabilities: ['supports3DS', 'supportsCredit'],
885
- supportedNetworks: ['visa', 'masterCard', 'amex'],
886
- requiredBillingContactFields: ['name', 'postalAddress'],
887
-
888
- // Native Google Pay properties (available due to interface extension)
889
- type: 'CARD',
890
- parameters: {
891
- allowedAuthMethods: ['PAN_ONLY', 'CRYPTOGRAM_3DS'],
892
- allowedCardNetworks: ['VISA', 'MASTERCARD', 'AMEX']
893
- }
894
- };
803
+ // Required handlers (will throw error if not provided)
804
+ button.onSuccess(handler); // Always required
805
+ button.onShippingAddressChange(handler); // Required when shipping enabled
806
+ button.onShippingOptionsChange(handler); // Required when shipping options provided
807
+
808
+ // Optional handlers with Promise support
809
+ button.onUnavailable(handler); // or await button.onUnavailable()
810
+ button.onError(handler); // or await button.onError()
811
+ button.onCancel(handler); // or await button.onCancel()
812
+
813
+ // Click handler with flow control
814
+ button.onClick(handler); // Use data.attachResult() for async operations
815
+
816
+ // Loaded handler
817
+ button.onLoaded(handler); // Notified when button renders
895
818
  ```
896
819
 
897
- **Important Notes**:
898
- - PayDock automatically handles the conversion and mapping between your configuration and the appropriate wallet APIs
899
- - The `tokenizationSpecification` property is omitted from the Google Pay interface extension as PayDock handles tokenization automatically
900
- - All properties shown are directly available in the `OpenWalletMeta` configuration object
820
+ ### Apple Pay-Specific Meta Properties
821
+
822
+ A full description of the [ApplePayOpenWalletMeta](#ApplePayOpenWalletMeta) properties:
823
+
824
+ **Required:**
825
+ - `amount`: The payment amount (number)
826
+ - `currency`: The currency code (string, e.g., "AUD")
827
+ - `country`: The country code (string, e.g., "AU")
828
+ - `amount_label`: Label for the total amount (string)
829
+ - `store_name`: Merchant store name (string)
830
+
831
+ **Optional:**
832
+ - `request_shipping?: boolean`: Enable shipping address collection
833
+ - `shipping_options?: IApplePayShippingOption[]`: Array of shipping options
834
+ - `show_billing_address?: boolean`: Show billing address fields
835
+ - `apple_pay_capabilities?: string[]`: Device capabilities
836
+ - `merchant_capabilities?: string[]`: Merchant capabilities
837
+ - `supported_networks?: string[]`: Supported payment networks
838
+ - `required_billing_contact_fields?: string[]`: Required billing contact fields
839
+ - `required_shipping_contact_fields?: string[]`: Required shipping contact fields
840
+ - `supported_countries?: string[]`: Supported countries
841
+ - `shipping_editing_mode?: 'available' | 'store_pickup'`: Shipping address editing mode
842
+ - `style?: { button_type?: ApplePayButtonType, button_style?: ApplePayButtonStyle }`: Button styling
843
+
844
+ ### Google Pay-Specific Meta Properties
845
+
846
+ A full description of the [GooglePayOpenWalletMeta](#GooglePayOpenWalletMeta) properties:
901
847
 
902
- #### Shipping Options Format
848
+ **Required:**
849
+ - `amount`: The payment amount (number)
850
+ - `currency`: The currency code (string, e.g., "AUD")
851
+ - `country`: The country code (string, e.g., "AU")
852
+
853
+ **Optional:**
854
+ - `amount_label?: string`: Label for the total amount
855
+ - `merchant_name?: string`: Display name for the merchant
856
+ - `request_shipping?: boolean`: Enable shipping address collection
857
+ - `shipping_options?: IGooglePayShippingOption[]`: Array of shipping options
858
+ - `show_billing_address?: boolean`: Show billing address fields
859
+ - `card_config?: GooglePayCardConfig`: Card configuration (auth methods, networks, tokenization)
860
+ - `style?: { button_type?: GooglePayButtonType, button_color?: GooglePayButtonColor, button_size_mode?: GooglePayButtonSizeMode }`: Button styling
861
+
862
+ ### Shipping Options Format
903
863
  ```javascript
904
864
  shipping_options: [
905
865
  {
@@ -907,12 +867,12 @@ shipping_options: [
907
867
  label: "Option Name", // Display name (string)
908
868
  detail: "Description", // Optional description (string)
909
869
  amount: 10.00, // Shipping cost as number
910
- date_components_range: { // Optional: delivery date range
870
+ date_components_range: { // Optional: delivery date range (Apple Pay only)
911
871
  start_date_components: {
912
- years: 0, // Years from now
913
- months: 0, // Months from now
914
- days: 5, // Days from now
915
- hours: 0, // Hours from now
872
+ years: 0,
873
+ months: 0,
874
+ days: 5,
875
+ hours: 0,
916
876
  },
917
877
  end_date_components: {
918
878
  years: 0,
@@ -925,257 +885,28 @@ shipping_options: [
925
885
  ]
926
886
  ```
927
887
 
928
- **Important**:
888
+ **Important**:
929
889
  - `amount` should be a **number**, not a string
930
- - `date_components_range` is optional but provides delivery estimates
890
+ - `date_components_range` is optional but provides delivery estimates (Apple Pay only)
931
891
  - Updated shipping options returned from event handlers don't require `date_components_range`
932
892
 
933
- #### Required Meta Fields Validation
934
-
935
- The `requiredMetaFields` parameter allows you to specify which fields in the meta object must be present. If any required field is missing, the constructor will throw an error:
936
-
937
- ```javascript
938
- // Example with validation
939
- const button = new paydock.OpenWalletButtons(
940
- '#widget',
941
- publicKeyOrAccessToken,
942
- serviceId,
943
- {
944
- amount: 100,
945
- currency: 'USD',
946
- // Missing amount_label will cause an error
947
- },
948
- ['amount', 'currency', 'amount_label'] // This will throw an error
949
- );
950
-
951
- // To avoid validation, pass an empty array or omit the parameter
952
- const button = new paydock.OpenWalletButtons(
953
- '#widget',
954
- publicKeyOrAccessToken,
955
- serviceId,
956
- meta,
957
- [] // No validation
958
- );
959
- ```
960
-
961
- ### Complete Test Setup Example
962
-
963
- Based on the actual test implementation, here's a complete working example for testing:
964
-
965
- ```html
966
- <!DOCTYPE html>
967
- <html lang="en">
968
- <head>
969
- <meta charset="UTF-8">
970
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
971
- <title>Open Wallet Apple Pay Test</title>
972
- </head>
973
- <body>
974
- <h1>Apple Pay Test Page</h1>
975
- <table>
976
- <tr>
977
- <td>Service ID:</td>
978
- <td><input type="text" id="service_id" placeholder="Enter your service ID" /></td>
979
- </tr>
980
- <tr>
981
- <td>Access Token/Public Key:</td>
982
- <td><input type="text" id="access_token" placeholder="Enter your access token" /></td>
983
- </tr>
984
- </table>
985
- <button onclick="loadApplePayButton()">Load Apple Pay Button</button>
986
- <div id="widget"></div>
987
-
988
- <script src="https://widget.paydock.com/sdk/latest/widget.umd.min.js"></script>
989
- <script>
990
- function loadApplePayButton() {
991
- const shippingOptions = [
992
- {
993
- label: "Standard Shipping",
994
- detail: "Arrives in 5-7 business days",
995
- amount: 10,
996
- id: "standard",
997
- date_components_range: {
998
- start_date_components: { years: 0, months: 0, days: 5, hours: 0 },
999
- end_date_components: { years: 0, months: 0, days: 7, hours: 0 }
1000
- }
1001
- },
1002
- {
1003
- label: "Express Shipping",
1004
- detail: "Arrives in 1-2 business days",
1005
- amount: 20,
1006
- id: "express",
1007
- date_components_range: {
1008
- start_date_components: { years: 0, months: 0, days: 1, hours: 0 },
1009
- end_date_components: { years: 0, months: 0, days: 2, hours: 0 }
1010
- }
1011
- }
1012
- ];
1013
-
1014
- const widget = new paydock.OpenWalletButtons(
1015
- '#widget',
1016
- document.getElementById("access_token").value,
1017
- document.getElementById("service_id").value,
1018
- {
1019
- amount: 100,
1020
- currency: 'USD',
1021
- country: 'US',
1022
- amount_label: 'Total',
1023
- apple_pay_capabilities: [
1024
- 'credentials_available',
1025
- 'credentials_status_unknown',
1026
- 'credentials_unavailable'
1027
- ],
1028
- shipping_options: shippingOptions,
1029
- request_shipping: true,
1030
-
1031
- // Extended Apple Pay properties (native interface)
1032
- merchantCapabilities: [
1033
- 'supports3DS',
1034
- 'supportsCredit',
1035
- 'supportsDebit'
1036
- ],
1037
- supportedNetworks: [
1038
- 'visa',
1039
- 'masterCard',
1040
- 'amex',
1041
- 'discover'
1042
- ],
1043
- requiredBillingContactFields: [
1044
- 'name',
1045
- 'postalAddress'
1046
- ],
1047
- requiredShippingContactFields: [
1048
- 'postalAddress',
1049
- 'name',
1050
- 'phone',
1051
- 'email'
1052
- ]
1053
- },
1054
- ['amount_label', 'country', 'request_shipping', 'shipping_options', 'apple_pay_capabilities']
1055
- );
1056
-
1057
- // Required handlers
1058
- widget.onSuccess(async function (data) {
1059
- console.log("Payment successful:", data);
1060
- // Process the OTT token
1061
- alert(`Payment successful! OTT Token: ${data.token}`);
1062
- });
1063
-
1064
- widget.onShippingAddressChange(async function (data) {
1065
- console.log("Shipping address changed:", data);
1066
-
1067
- // Simulate updated shipping options based on address
1068
- const updatedOptions = [
1069
- { label: "Local Delivery", detail: "Same day delivery", amount: 5, id: "local" },
1070
- { label: "Regional Delivery", detail: "Next day delivery", amount: 15, id: "regional" }
1071
- ];
1072
-
1073
- return {
1074
- amount: 100 + updatedOptions[0].amount,
1075
- shipping_options: updatedOptions
1076
- };
1077
- });
1078
-
1079
- widget.onShippingOptionsChange(async function (data) {
1080
- console.log("Shipping option changed:", data);
1081
-
1082
- // Note: Check your actual data structure - might be data.data.amount
1083
- const shippingCost = data.amount || data.data?.amount || 0;
1084
- return {
1085
- amount: 100 + shippingCost
1086
- };
1087
- });
1088
-
1089
- // Optional handlers
1090
- widget.onError(function (data) {
1091
- console.error("Payment error:", data);
1092
- alert("Payment failed: " + data.error.message);
1093
- });
1094
-
1095
- widget.onCancel(function (data) {
1096
- console.log("Payment cancelled:", data);
1097
- alert("Payment was cancelled");
1098
- });
1099
-
1100
- widget.onClick(function (data) {
1101
- console.log("Apple Pay button clicked:", data);
1102
- // Optional: Add validation logic here
1103
- });
1104
-
1105
- widget.setEnv('sandbox');
1106
- widget.load();
1107
- }
1108
- </script>
1109
- </body>
1110
- </html>
1111
- ```
1112
-
1113
- ### Common Issues and Troubleshooting
1114
-
1115
- #### Event Data Structure Variations
1116
- Different implementations might return data in slightly different structures. Always check the actual data structure in your console:
1117
-
1118
- ```javascript
1119
- // In your event handlers, log the data to see the actual structure
1120
- widget.onShippingOptionsChange(async function (data) {
1121
- console.log("Full data object:", data);
1122
-
1123
- // Try different access patterns based on your implementation
1124
- const amount = data.amount || // Direct access
1125
- data.data?.amount || // Nested in data property
1126
- data.shippingCost || // Alternative property name
1127
- 0; // Fallback
1128
-
1129
- return { amount: baseAmount + amount };
1130
- });
1131
- ```
1132
-
1133
- #### Required vs Optional Configuration
1134
- ```javascript
1135
- // Minimal required configuration
1136
- const minimalConfig = {
1137
- amount: 100,
1138
- currency: 'USD'
1139
- };
1140
-
1141
- // Recommended configuration with validation
1142
- const recommendedConfig = {
1143
- amount: 100,
1144
- currency: 'USD',
1145
- amount_label: 'Total',
1146
- country: 'US',
1147
- apple_pay_capabilities: ['credentials_available']
1148
- };
1149
-
1150
- // Full configuration with shipping
1151
- const fullConfig = {
1152
- amount: 100,
1153
- currency: 'USD',
1154
- amount_label: 'Total',
1155
- country: 'US',
1156
- request_shipping: true,
1157
- shipping_options: [...],
1158
- apple_pay_capabilities: ['credentials_available', 'credentials_status_unknown', 'credentials_unavailable']
1159
- };
1160
- ```
1161
-
1162
- #### Environment Setup
893
+ ### Environment Setup
1163
894
  ```javascript
1164
895
  // Always set environment before loading
1165
- widget.setEnv('sandbox');
1166
- widget.load();
896
+ button.setEnv('sandbox');
897
+ button.load();
1167
898
  ```
1168
899
 
1169
- #### Error Handling Best Practices
900
+ ### Error Handling Best Practices
1170
901
  ```javascript
1171
- widget.onError(function(data) {
902
+ button.onError(function(data) {
1172
903
  console.error('Full error object:', data);
1173
-
904
+
1174
905
  // Check different error properties
1175
- const errorMessage = data.error?.message ||
1176
- data.message ||
906
+ const errorMessage = data.error?.message ||
907
+ data.message ||
1177
908
  'Unknown error occurred';
1178
-
909
+
1179
910
  // Handle different error types
1180
911
  if (data.context?.operation === 'wallet_operation') {
1181
912
  // Handle wallet-specific errors