@paydock/client-sdk 1.139.0 → 1.140.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2543 -0
- package/bundles/index.cjs +1296 -508
- package/bundles/index.cjs.d.ts +1377 -200
- package/bundles/index.mjs +1295 -509
- package/bundles/index.mjs.d.ts +1377 -200
- package/bundles/types/checkout/checkout.d.ts.map +1 -1
- package/bundles/types/checkout/v1/instructions/instruction.card_form.show.d.ts.map +1 -1
- package/bundles/types/checkout/v3/instructions/instruction.card_form.show.d.ts.map +1 -1
- package/bundles/types/checkout/v3/instructions/instruction.payment_methods.show.d.ts.map +1 -1
- package/bundles/types/checkout-button/zipmoney/zipmoney-contextual.runner.d.ts +1 -2
- package/bundles/types/checkout-button/zipmoney/zipmoney-contextual.runner.d.ts.map +1 -1
- package/bundles/types/open-wallets/apple-pay-open-wallet-button.d.ts +70 -0
- package/bundles/types/open-wallets/apple-pay-open-wallet-button.d.ts.map +1 -0
- package/bundles/types/open-wallets/base/open-wallet-buttons.d.ts +242 -74
- package/bundles/types/open-wallets/base/open-wallet-buttons.d.ts.map +1 -1
- package/bundles/types/open-wallets/base/open-wallet.service.d.ts +62 -4
- package/bundles/types/open-wallets/base/open-wallet.service.d.ts.map +1 -1
- package/bundles/types/open-wallets/enum/error-operation.enum.d.ts +15 -0
- package/bundles/types/open-wallets/enum/error-operation.enum.d.ts.map +1 -0
- package/bundles/types/open-wallets/enum/event.enum.d.ts +11 -3
- package/bundles/types/open-wallets/enum/event.enum.d.ts.map +1 -1
- package/bundles/types/open-wallets/enum/token-type.enum.d.ts +10 -0
- package/bundles/types/open-wallets/enum/token-type.enum.d.ts.map +1 -0
- package/bundles/types/open-wallets/google-pay-open-wallet-button.d.ts +65 -0
- package/bundles/types/open-wallets/google-pay-open-wallet-button.d.ts.map +1 -0
- package/bundles/types/open-wallets/index.d.ts +293 -0
- package/bundles/types/open-wallets/index.d.ts.map +1 -1
- package/bundles/types/open-wallets/interfaces/events.interface.d.ts +87 -14
- package/bundles/types/open-wallets/interfaces/events.interface.d.ts.map +1 -1
- package/bundles/types/open-wallets/interfaces/google-pay/google-pay-meta.interface.d.ts +6 -0
- package/bundles/types/open-wallets/interfaces/google-pay/google-pay-meta.interface.d.ts.map +1 -1
- package/bundles/types/open-wallets/interfaces/index.d.ts +2 -2
- package/bundles/types/open-wallets/interfaces/index.d.ts.map +1 -1
- package/bundles/types/open-wallets/interfaces/open-wallet-meta.interface.d.ts +12 -0
- package/bundles/types/open-wallets/interfaces/open-wallet-meta.interface.d.ts.map +1 -1
- package/bundles/types/open-wallets/interfaces/payment-source.interface.d.ts +28 -2
- package/bundles/types/open-wallets/interfaces/payment-source.interface.d.ts.map +1 -1
- package/bundles/types/open-wallets/services/apple-pay/apple-pay.open-wallet.service.d.ts +27 -2
- package/bundles/types/open-wallets/services/apple-pay/apple-pay.open-wallet.service.d.ts.map +1 -1
- package/bundles/types/open-wallets/services/google-pay/constants/google-pay.constants.d.ts +9 -0
- package/bundles/types/open-wallets/services/google-pay/constants/google-pay.constants.d.ts.map +1 -1
- package/bundles/types/open-wallets/services/google-pay/google-pay.open-wallet.service.d.ts +20 -9
- package/bundles/types/open-wallets/services/google-pay/google-pay.open-wallet.service.d.ts.map +1 -1
- package/bundles/types/open-wallets/services/google-pay/utils/google-pay.utils.d.ts +45 -0
- package/bundles/types/open-wallets/services/google-pay/utils/google-pay.utils.d.ts.map +1 -1
- package/bundles/types/open-wallets/services/google-pay/utils/index.d.ts +1 -1
- package/bundles/types/open-wallets/services/google-pay/utils/index.d.ts.map +1 -1
- package/bundles/types/open-wallets/services/google-pay/validation/google-pay.validation.d.ts +13 -0
- package/bundles/types/open-wallets/services/google-pay/validation/google-pay.validation.d.ts.map +1 -1
- package/bundles/types/open-wallets/types/base-event-data.interface.d.ts +24 -2
- package/bundles/types/open-wallets/types/base-event-data.interface.d.ts.map +1 -1
- package/bundles/types/open-wallets/types/index.d.ts +2 -1
- package/bundles/types/open-wallets/types/index.d.ts.map +1 -1
- package/bundles/types/open-wallets/types/on-shipping-address-change-event-data.interface.d.ts +16 -2
- package/bundles/types/open-wallets/types/on-shipping-address-change-event-data.interface.d.ts.map +1 -1
- package/bundles/types/open-wallets/types/on-shipping-address-change-event-response.interface.d.ts +20 -2
- package/bundles/types/open-wallets/types/on-shipping-address-change-event-response.interface.d.ts.map +1 -1
- package/bundles/types/open-wallets/types/on-shipping-option-change-event-data.interface.d.ts +13 -2
- package/bundles/types/open-wallets/types/on-shipping-option-change-event-data.interface.d.ts.map +1 -1
- package/bundles/types/open-wallets/types/on-shipping-option-change-event-response.interface.d.ts +12 -0
- package/bundles/types/open-wallets/types/on-shipping-option-change-event-response.interface.d.ts.map +1 -1
- package/bundles/types/open-wallets/types/payment-source.type.d.ts +3 -2
- package/bundles/types/open-wallets/types/payment-source.type.d.ts.map +1 -1
- package/bundles/types/open-wallets/types/shipping-event-to-response.type.d.ts +8 -0
- package/bundles/types/open-wallets/types/shipping-event-to-response.type.d.ts.map +1 -1
- package/bundles/widget.umd.js +1296 -508
- package/bundles/widget.umd.js.d.ts +1377 -200
- package/bundles/widget.umd.js.min.d.ts +1377 -200
- package/bundles/widget.umd.min.js +1 -1
- package/docs/open-wallet-buttons-examples.md +523 -822
- package/docs/open-wallet-buttons.md +1652 -0
- package/package.json +1 -1
- package/slate.md +1643 -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
|
-
|
|
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
|
|
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
|
|
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.
|
|
29
|
+
let button = new paydock.ApplePayOpenWalletButton(
|
|
43
30
|
"#widget",
|
|
44
31
|
publicKeyOrAccessToken,
|
|
45
32
|
serviceId,
|
|
46
33
|
{
|
|
47
34
|
amount: 100,
|
|
48
|
-
currency: "
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
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 {
|
|
47
|
+
import { ApplePayOpenWalletButton } from '@paydock/client-sdk';
|
|
59
48
|
|
|
60
|
-
var button = new
|
|
49
|
+
var button = new ApplePayOpenWalletButton(
|
|
61
50
|
'#widget',
|
|
62
51
|
publicKeyOrAccessToken,
|
|
63
52
|
serviceId,
|
|
64
53
|
{
|
|
65
54
|
amount: 100,
|
|
66
|
-
currency: '
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
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
|
|
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** (
|
|
113
|
-
|
|
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.
|
|
99
|
+
let button = new paydock.ApplePayOpenWalletButton(
|
|
335
100
|
"#widget",
|
|
336
101
|
publicKeyOrAccessToken,
|
|
337
102
|
serviceId,
|
|
338
103
|
{
|
|
339
104
|
amount: 100,
|
|
340
|
-
currency: "
|
|
341
|
-
|
|
342
|
-
|
|
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,57 +158,49 @@ 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
|
-
|
|
401
|
-
button.onUnavailable((data) => {
|
|
165
|
+
|
|
166
|
+
button.onUnavailable(({ data }) => {
|
|
402
167
|
console.log("Apple Pay not available:", data);
|
|
403
|
-
// Show alternative payment methods
|
|
404
168
|
});
|
|
405
|
-
|
|
406
|
-
button.onClick((
|
|
169
|
+
|
|
170
|
+
button.onClick(() => {
|
|
407
171
|
console.log("Apple Pay button clicked");
|
|
408
|
-
// Perform pre-payment validation
|
|
409
172
|
});
|
|
410
|
-
|
|
411
|
-
button.onSuccess((data) => {
|
|
173
|
+
|
|
174
|
+
button.onSuccess(({ data }) => {
|
|
412
175
|
console.log("Payment successful:", data);
|
|
413
|
-
// Process the OTT token on your backend
|
|
414
176
|
processPayment(data.token);
|
|
415
177
|
});
|
|
416
|
-
|
|
417
|
-
button.onError((data) => {
|
|
178
|
+
|
|
179
|
+
button.onError(({ data }) => {
|
|
418
180
|
console.error("Payment error:", data);
|
|
419
|
-
// Handle error appropriately
|
|
420
181
|
});
|
|
421
|
-
|
|
422
|
-
button.onCancel((
|
|
182
|
+
|
|
183
|
+
button.onCancel(() => {
|
|
423
184
|
console.log("Payment cancelled");
|
|
424
|
-
// Handle cancellation
|
|
425
185
|
});
|
|
426
|
-
|
|
427
|
-
button.onShippingAddressChange(async (
|
|
428
|
-
|
|
429
|
-
const response = await updateShippingCosts(addressData);
|
|
186
|
+
|
|
187
|
+
button.onShippingAddressChange(async ({ data }) => {
|
|
188
|
+
const response = await updateShippingCosts(data);
|
|
430
189
|
return {
|
|
431
190
|
amount: response.newAmount,
|
|
432
191
|
shipping_options: response.shippingOptions
|
|
433
192
|
};
|
|
434
193
|
});
|
|
435
|
-
|
|
436
|
-
button.onShippingOptionsChange(async (
|
|
437
|
-
|
|
438
|
-
const response = await updateTotal(optionData);
|
|
194
|
+
|
|
195
|
+
button.onShippingOptionsChange(async ({ data }) => {
|
|
196
|
+
const response = await updateTotal(data);
|
|
439
197
|
return {
|
|
440
198
|
amount: response.newAmount
|
|
441
199
|
};
|
|
442
200
|
});
|
|
443
|
-
|
|
201
|
+
|
|
444
202
|
button.load();
|
|
445
|
-
|
|
203
|
+
|
|
446
204
|
async function updateShippingCosts(addressData) {
|
|
447
205
|
// Your shipping calculation logic based on address
|
|
448
206
|
const baseAmount = 100;
|
|
@@ -460,25 +218,22 @@ button.onCancel((data) => {
|
|
|
460
218
|
amount: 18.00
|
|
461
219
|
}
|
|
462
220
|
];
|
|
463
|
-
|
|
221
|
+
|
|
464
222
|
return {
|
|
465
223
|
newAmount: baseAmount + updatedShippingOptions[0].amount,
|
|
466
224
|
shippingOptions: updatedShippingOptions
|
|
467
225
|
};
|
|
468
226
|
}
|
|
469
|
-
|
|
470
|
-
async function updateTotal(
|
|
471
|
-
// Your total calculation logic
|
|
227
|
+
|
|
228
|
+
async function updateTotal(shippingOption) {
|
|
472
229
|
const baseAmount = 100;
|
|
473
|
-
|
|
474
|
-
const shippingAmount = optionData.amount || optionData.data?.amount;
|
|
230
|
+
const shippingAmount = shippingOption.amount;
|
|
475
231
|
return {
|
|
476
232
|
newAmount: baseAmount + shippingAmount
|
|
477
233
|
};
|
|
478
234
|
}
|
|
479
|
-
|
|
235
|
+
|
|
480
236
|
function processPayment(ottToken) {
|
|
481
|
-
// Send OTT token to your backend for payment processing
|
|
482
237
|
fetch('/api/process-payment', {
|
|
483
238
|
method: 'POST',
|
|
484
239
|
headers: { 'Content-Type': 'application/json' },
|
|
@@ -489,7 +244,262 @@ button.onCancel((data) => {
|
|
|
489
244
|
</html>
|
|
490
245
|
```
|
|
491
246
|
|
|
492
|
-
###
|
|
247
|
+
### Apple Pay with Shipping
|
|
248
|
+
|
|
249
|
+
For Apple Pay with shipping enabled:
|
|
250
|
+
```javascript
|
|
251
|
+
let button = new paydock.ApplePayOpenWalletButton(
|
|
252
|
+
"#widget",
|
|
253
|
+
publicKeyOrAccessToken,
|
|
254
|
+
serviceId,
|
|
255
|
+
{
|
|
256
|
+
amount: 100,
|
|
257
|
+
currency: "AUD",
|
|
258
|
+
country: "AU",
|
|
259
|
+
amount_label: "TOTAL",
|
|
260
|
+
store_name: "My Store",
|
|
261
|
+
request_shipping: true,
|
|
262
|
+
shipping_editing_mode: 'available',
|
|
263
|
+
required_shipping_contact_fields: [
|
|
264
|
+
'postalAddress',
|
|
265
|
+
'name',
|
|
266
|
+
'phone',
|
|
267
|
+
'email',
|
|
268
|
+
],
|
|
269
|
+
shipping_options: [
|
|
270
|
+
{
|
|
271
|
+
id: "standard",
|
|
272
|
+
label: "Standard Shipping",
|
|
273
|
+
detail: "5-7 business days",
|
|
274
|
+
amount: 5.00
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
id: "express",
|
|
278
|
+
label: "Express Shipping",
|
|
279
|
+
detail: "1-2 business days",
|
|
280
|
+
amount: 15.00
|
|
281
|
+
}
|
|
282
|
+
],
|
|
283
|
+
apple_pay_capabilities: ['credentials_available', 'credentials_status_unknown', 'credentials_unavailable']
|
|
284
|
+
}
|
|
285
|
+
);
|
|
286
|
+
button.load();
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
When supporting shipping, registering `onShippingAddressChange` and `onShippingOptionsChange` handlers lets you recalculate totals and update shipping options dynamically. If no handler is registered (or the handler throws), the SDK auto-accepts with the current amount and options.
|
|
290
|
+
|
|
291
|
+
```javascript
|
|
292
|
+
button.onShippingAddressChange(async function({ data }) {
|
|
293
|
+
console.log("Shipping address has been updated", data);
|
|
294
|
+
return {
|
|
295
|
+
amount: newAmount,
|
|
296
|
+
shipping_options: updatedShippingOptions
|
|
297
|
+
};
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
button.onShippingOptionsChange(async function({ data }) {
|
|
301
|
+
console.log("Shipping option selected", data);
|
|
302
|
+
return {
|
|
303
|
+
amount: newTotalAmount
|
|
304
|
+
};
|
|
305
|
+
});
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
### Supported Shipping Cases
|
|
309
|
+
|
|
310
|
+
#### Injected Shipping Address, non-editable by the customer
|
|
311
|
+
|
|
312
|
+
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.
|
|
313
|
+
|
|
314
|
+
The required meta parameters for this case are:
|
|
315
|
+
- shipping_editing_mode: 'store_pickup'
|
|
316
|
+
- required_shipping_contact_fields: ['postalAddress'] <-- At least one of the fields is required so the shipping address is shown at Apple Pay.
|
|
317
|
+
|
|
318
|
+
```javascript
|
|
319
|
+
meta: {
|
|
320
|
+
apple_pay_capabilities: ['credentials_available', 'credentials_status_unknown', 'credentials_unavailable'],
|
|
321
|
+
amount_label: 'TOTAL',
|
|
322
|
+
country: 'AU',
|
|
323
|
+
currency: 'AUD',
|
|
324
|
+
amount: 10,
|
|
325
|
+
shipping_editing_mode: 'store_pickup',
|
|
326
|
+
required_shipping_contact_fields: [
|
|
327
|
+
'postalAddress',
|
|
328
|
+
'name',
|
|
329
|
+
'phone',
|
|
330
|
+
'email',
|
|
331
|
+
],
|
|
332
|
+
shipping: {
|
|
333
|
+
amount: 5,
|
|
334
|
+
address_line1: "Address Line 1",
|
|
335
|
+
address_city: "Test Locality",
|
|
336
|
+
address_state: "NSW",
|
|
337
|
+
address_country: "Australia",
|
|
338
|
+
address_country_code: "AU",
|
|
339
|
+
address_postcode: "3000",
|
|
340
|
+
contact: {
|
|
341
|
+
phone: "+61400245562",
|
|
342
|
+
email: "test@example.com",
|
|
343
|
+
first_name: "QA",
|
|
344
|
+
last_name: "QA",
|
|
345
|
+
},
|
|
346
|
+
options: [
|
|
347
|
+
{
|
|
348
|
+
label: "Test 1",
|
|
349
|
+
detail: "This is a test 1 shipping methods",
|
|
350
|
+
amount: 10,
|
|
351
|
+
id: "randomId1",
|
|
352
|
+
}
|
|
353
|
+
],
|
|
354
|
+
},
|
|
355
|
+
}
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
#### Injected Shipping Address, editable by the customer
|
|
359
|
+
|
|
360
|
+
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.
|
|
361
|
+
|
|
362
|
+
The required meta parameters for this case are:
|
|
363
|
+
- shipping_editing_mode: 'available'
|
|
364
|
+
- required_shipping_contact_fields: ['postalAddress'] <-- At least one of the fields is required so the shipping address is shown at Apple Pay.
|
|
365
|
+
|
|
366
|
+
```javascript
|
|
367
|
+
meta: {
|
|
368
|
+
apple_pay_capabilities: ['credentials_available', 'credentials_status_unknown', 'credentials_unavailable'],
|
|
369
|
+
amount_label: 'TOTAL',
|
|
370
|
+
country: 'AU',
|
|
371
|
+
currency: 'AUD',
|
|
372
|
+
amount: 10,
|
|
373
|
+
shipping_editing_mode: 'available',
|
|
374
|
+
required_shipping_contact_fields: [
|
|
375
|
+
'postalAddress',
|
|
376
|
+
'name',
|
|
377
|
+
'phone',
|
|
378
|
+
'email',
|
|
379
|
+
],
|
|
380
|
+
shipping: {
|
|
381
|
+
amount: 5,
|
|
382
|
+
address_line1: "Address Line 1",
|
|
383
|
+
address_city: "Test Locality",
|
|
384
|
+
address_state: "NSW",
|
|
385
|
+
address_country: "Australia",
|
|
386
|
+
address_country_code: "AU",
|
|
387
|
+
address_postcode: "3000",
|
|
388
|
+
contact: {
|
|
389
|
+
phone: "+61400245562",
|
|
390
|
+
email: "test@example.com",
|
|
391
|
+
first_name: "QA",
|
|
392
|
+
last_name: "QA",
|
|
393
|
+
},
|
|
394
|
+
options: [
|
|
395
|
+
{
|
|
396
|
+
label: "Test 1",
|
|
397
|
+
detail: "This is a test 1 shipping methods",
|
|
398
|
+
amount: 10,
|
|
399
|
+
id: "randomId1",
|
|
400
|
+
}
|
|
401
|
+
],
|
|
402
|
+
},
|
|
403
|
+
}
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
#### Shipping address editable by the customer (no pre-filled address)
|
|
407
|
+
|
|
408
|
+
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.
|
|
409
|
+
|
|
410
|
+
The required meta parameters for this case are:
|
|
411
|
+
- shipping_editing_mode: 'available'
|
|
412
|
+
- required_shipping_contact_fields: ['postalAddress'] <-- At least one of the fields is required so the shipping address is shown at Apple Pay.
|
|
413
|
+
|
|
414
|
+
```javascript
|
|
415
|
+
meta: {
|
|
416
|
+
apple_pay_capabilities: ['credentials_available', 'credentials_status_unknown', 'credentials_unavailable'],
|
|
417
|
+
amount_label: 'TOTAL',
|
|
418
|
+
country: 'AU',
|
|
419
|
+
currency: 'AUD',
|
|
420
|
+
amount: 10,
|
|
421
|
+
shipping_editing_mode: 'available',
|
|
422
|
+
required_shipping_contact_fields: [
|
|
423
|
+
'postalAddress',
|
|
424
|
+
'name',
|
|
425
|
+
'phone',
|
|
426
|
+
'email',
|
|
427
|
+
],
|
|
428
|
+
}
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
#### No shipping address
|
|
432
|
+
|
|
433
|
+
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.
|
|
434
|
+
|
|
435
|
+
**Important:**
|
|
436
|
+
- No shipping address should be provided in the meta object.
|
|
437
|
+
- Shipping address could be provided in the initial POST `/v1/charges/wallet` endpoint, if collected previously.
|
|
438
|
+
|
|
439
|
+
The required meta parameters for this case are:
|
|
440
|
+
- `required_shipping_contact_fields`: Only include contact fields if needed (phone, email), but NOT `postalAddress`.
|
|
441
|
+
|
|
442
|
+
```javascript
|
|
443
|
+
meta: {
|
|
444
|
+
amount_label: "TOTAL",
|
|
445
|
+
country: "AU",
|
|
446
|
+
currency: "AUD",
|
|
447
|
+
amount: 10,
|
|
448
|
+
shipping_editing_mode: "available",
|
|
449
|
+
required_shipping_contact_fields: ["phone", "email"],
|
|
450
|
+
apple_pay_capabilities: ["credentials_available", "credentials_status_unknown", "credentials_unavailable"]
|
|
451
|
+
}
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
## Google Pay Open Wallet Button
|
|
455
|
+
|
|
456
|
+
### Initialization
|
|
457
|
+
|
|
458
|
+
```javascript
|
|
459
|
+
let button = new paydock.GooglePayOpenWalletButton(
|
|
460
|
+
"#widget",
|
|
461
|
+
publicKeyOrAccessToken,
|
|
462
|
+
serviceId,
|
|
463
|
+
{
|
|
464
|
+
amount: 100,
|
|
465
|
+
currency: "AUD",
|
|
466
|
+
country: "AU",
|
|
467
|
+
merchant_name: "Your Store",
|
|
468
|
+
}
|
|
469
|
+
);
|
|
470
|
+
button.load();
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
```javascript
|
|
474
|
+
// ES2015 | TypeScript
|
|
475
|
+
import { GooglePayOpenWalletButton } from '@paydock/client-sdk';
|
|
476
|
+
|
|
477
|
+
var button = new GooglePayOpenWalletButton(
|
|
478
|
+
'#widget',
|
|
479
|
+
publicKeyOrAccessToken,
|
|
480
|
+
serviceId,
|
|
481
|
+
{
|
|
482
|
+
amount: 100,
|
|
483
|
+
currency: 'AUD',
|
|
484
|
+
country: 'AU',
|
|
485
|
+
merchant_name: 'Your Store',
|
|
486
|
+
}
|
|
487
|
+
);
|
|
488
|
+
button.load();
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
### Constructor Parameters
|
|
492
|
+
|
|
493
|
+
The GooglePayOpenWalletButton constructor accepts the following parameters:
|
|
494
|
+
|
|
495
|
+
1. **selector** (string): CSS selector for the container element
|
|
496
|
+
2. **publicKeyOrAccessToken** (string): Your PayDock public key or access token
|
|
497
|
+
3. **serviceId** (string): The Google Pay service ID configured in PayDock dashboard
|
|
498
|
+
4. **meta** (GooglePayOpenWalletMeta): Google Pay-specific configuration object
|
|
499
|
+
|
|
500
|
+
> **Note:** Required meta fields (`amount`, `currency`, `country`) are validated automatically by the `GooglePayOpenWalletButton` class. You do not need to specify them manually.
|
|
501
|
+
|
|
502
|
+
### Full Google Pay Example
|
|
493
503
|
|
|
494
504
|
```html
|
|
495
505
|
<!DOCTYPE html>
|
|
@@ -504,30 +514,23 @@ button.onCancel((data) => {
|
|
|
504
514
|
</body>
|
|
505
515
|
<script src="https://widget.paydock.com/sdk/latest/widget.umd.min.js" ></script>
|
|
506
516
|
<script>
|
|
507
|
-
let button = new paydock.
|
|
517
|
+
let button = new paydock.GooglePayOpenWalletButton(
|
|
508
518
|
"#widget",
|
|
509
519
|
publicKeyOrAccessToken,
|
|
510
520
|
serviceId,
|
|
511
521
|
{
|
|
512
522
|
amount: 100,
|
|
513
|
-
currency: "
|
|
514
|
-
amount_label: "Total",
|
|
523
|
+
currency: "AUD",
|
|
515
524
|
country: "AU",
|
|
525
|
+
amount_label: "Total",
|
|
516
526
|
request_shipping: true,
|
|
517
527
|
show_billing_address: true,
|
|
518
528
|
merchant_name: 'Test Merchant',
|
|
519
529
|
style: {
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
button_size_mode: 'fill'
|
|
524
|
-
}
|
|
530
|
+
button_type: 'buy',
|
|
531
|
+
button_color: 'default',
|
|
532
|
+
button_size_mode: 'fill'
|
|
525
533
|
},
|
|
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
534
|
shipping_options: [
|
|
532
535
|
{
|
|
533
536
|
id: "standard",
|
|
@@ -539,64 +542,56 @@ button.onCancel((data) => {
|
|
|
539
542
|
{
|
|
540
543
|
id: "express",
|
|
541
544
|
label: "Express Shipping",
|
|
542
|
-
detail: "Arrives in 1 to 2 days",
|
|
545
|
+
detail: "Arrives in 1 to 2 days",
|
|
543
546
|
amount: 15.00,
|
|
544
547
|
type: "PICKUP"
|
|
545
548
|
}
|
|
546
549
|
]
|
|
547
|
-
}
|
|
548
|
-
['amount_label', 'country', 'request_shipping', 'shipping_options', 'merchant_name']
|
|
550
|
+
}
|
|
549
551
|
);
|
|
550
|
-
|
|
552
|
+
|
|
551
553
|
button.setEnv('sandbox');
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
button.onSuccess((data) => {
|
|
554
|
+
|
|
555
|
+
button.onSuccess(({ data }) => {
|
|
555
556
|
console.log("Payment successful:", data);
|
|
556
557
|
processPayment(data.token);
|
|
557
558
|
});
|
|
558
|
-
|
|
559
|
-
button.onShippingAddressChange(async (
|
|
560
|
-
const response = await updateShippingCosts(
|
|
559
|
+
|
|
560
|
+
button.onShippingAddressChange(async ({ data }) => {
|
|
561
|
+
const response = await updateShippingCosts(data);
|
|
561
562
|
return {
|
|
562
563
|
amount: response.newAmount,
|
|
563
564
|
shipping_options: response.shippingOptions
|
|
564
565
|
};
|
|
565
566
|
});
|
|
566
|
-
|
|
567
|
-
button.onShippingOptionsChange(async (
|
|
568
|
-
const response = await updateTotal(
|
|
567
|
+
|
|
568
|
+
button.onShippingOptionsChange(async ({ data }) => {
|
|
569
|
+
const response = await updateTotal(data);
|
|
569
570
|
return {
|
|
570
571
|
amount: response.newAmount
|
|
571
572
|
};
|
|
572
573
|
});
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
button.onUnavailable((data) => {
|
|
574
|
+
|
|
575
|
+
button.onUnavailable(({ data }) => {
|
|
576
576
|
console.log("Google Pay not available:", data);
|
|
577
|
-
// Show alternative payment methods
|
|
578
577
|
});
|
|
579
|
-
|
|
580
|
-
button.onError((data) => {
|
|
578
|
+
|
|
579
|
+
button.onError(({ data }) => {
|
|
581
580
|
console.error("Payment error:", data);
|
|
582
|
-
// Handle error appropriately
|
|
583
581
|
});
|
|
584
|
-
|
|
585
|
-
button.onCancel((
|
|
582
|
+
|
|
583
|
+
button.onCancel(() => {
|
|
586
584
|
console.log("Payment cancelled");
|
|
587
|
-
// Handle cancellation
|
|
588
585
|
});
|
|
589
|
-
|
|
590
|
-
button.onClick((
|
|
586
|
+
|
|
587
|
+
button.onClick(() => {
|
|
591
588
|
console.log("Google Pay button clicked");
|
|
592
|
-
// Perform pre-payment validation
|
|
593
589
|
});
|
|
594
|
-
|
|
590
|
+
|
|
595
591
|
button.load();
|
|
596
|
-
|
|
597
|
-
// Helper functions
|
|
592
|
+
|
|
593
|
+
// Helper functions
|
|
598
594
|
async function updateShippingCosts(addressData) {
|
|
599
|
-
// Your shipping calculation logic based on address
|
|
600
595
|
const baseAmount = 100;
|
|
601
596
|
const updatedShippingOptions = [
|
|
602
597
|
{
|
|
@@ -614,24 +609,22 @@ button.onCancel((data) => {
|
|
|
614
609
|
type: "PICKUP"
|
|
615
610
|
}
|
|
616
611
|
];
|
|
617
|
-
|
|
612
|
+
|
|
618
613
|
return {
|
|
619
614
|
newAmount: baseAmount + updatedShippingOptions[0].amount,
|
|
620
615
|
shippingOptions: updatedShippingOptions
|
|
621
616
|
};
|
|
622
617
|
}
|
|
623
|
-
|
|
624
|
-
async function updateTotal(
|
|
625
|
-
// Your total calculation logic
|
|
618
|
+
|
|
619
|
+
async function updateTotal(shippingOption) {
|
|
626
620
|
const baseAmount = 100;
|
|
627
|
-
const shippingAmount =
|
|
621
|
+
const shippingAmount = shippingOption.amount;
|
|
628
622
|
return {
|
|
629
623
|
newAmount: baseAmount + shippingAmount
|
|
630
624
|
};
|
|
631
625
|
}
|
|
632
|
-
|
|
626
|
+
|
|
633
627
|
function processPayment(ottToken) {
|
|
634
|
-
// Send OTT token to your backend for payment processing
|
|
635
628
|
fetch('/api/process-payment', {
|
|
636
629
|
method: 'POST',
|
|
637
630
|
headers: { 'Content-Type': 'application/json' },
|
|
@@ -642,264 +635,207 @@ button.onCancel((data) => {
|
|
|
642
635
|
</html>
|
|
643
636
|
```
|
|
644
637
|
|
|
645
|
-
|
|
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.
|
|
638
|
+
## Common API
|
|
647
639
|
|
|
648
|
-
|
|
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
|
|
656
|
-
|
|
657
|
-
**Event Handler Patterns:**
|
|
640
|
+
Both `ApplePayOpenWalletButton` and `GooglePayOpenWalletButton` share the same event handler API inherited from the base class.
|
|
658
641
|
|
|
659
|
-
|
|
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
|
|
642
|
+
### Checking for button availability
|
|
664
643
|
|
|
665
|
-
|
|
666
|
-
button.onUnavailable(handler); // or await button.onUnavailable()
|
|
667
|
-
button.onError(handler); // or await button.onError()
|
|
668
|
-
button.onCancel(handler); // or await button.onCancel()
|
|
644
|
+
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.
|
|
669
645
|
|
|
670
|
-
|
|
671
|
-
button.
|
|
646
|
+
```javascript
|
|
647
|
+
button.onUnavailable(({ data }) => console.log("No wallet button available", data));
|
|
672
648
|
```
|
|
673
649
|
|
|
674
|
-
###
|
|
650
|
+
### Service type validation
|
|
675
651
|
|
|
676
|
-
|
|
652
|
+
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`:
|
|
677
653
|
|
|
678
|
-
|
|
679
|
-
|
|
654
|
+
```javascript
|
|
655
|
+
// This will raise an error if the service ID does not correspond to a Google Pay service
|
|
656
|
+
let button = new paydock.GooglePayOpenWalletButton(
|
|
657
|
+
"#widget",
|
|
658
|
+
publicKeyOrAccessToken,
|
|
659
|
+
applePayServiceId, // Wrong! This is an Apple Pay service ID
|
|
660
|
+
meta
|
|
661
|
+
);
|
|
680
662
|
|
|
681
|
-
|
|
663
|
+
button.onError(({ data }) => {
|
|
664
|
+
// Error: Service configuration type 'ApplePay' does not match expected wallet type 'google'.
|
|
665
|
+
console.error(data.error.message);
|
|
666
|
+
});
|
|
682
667
|
|
|
683
|
-
|
|
668
|
+
button.load();
|
|
669
|
+
```
|
|
684
670
|
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
- `capture?: boolean`: Whether to capture the payment immediately
|
|
689
|
-
- `reference?: string`: Payment reference
|
|
690
|
-
- `id?: string`: Payment ID
|
|
691
|
-
- `credentials?: object`: Gateway credentials
|
|
671
|
+
### Performing actions when the wallet button is clicked
|
|
672
|
+
|
|
673
|
+
You can perform validations or actions when the user clicks on the wallet button. The callback supports both synchronous and asynchronous operations using its return value: return `false` to abort, return a `Promise` to defer the wallet sheet, or throw an error to abort.
|
|
692
674
|
|
|
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
675
|
```javascript
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
676
|
+
// Synchronous — continue normally
|
|
677
|
+
button.onClick(() => {
|
|
678
|
+
console.log("Perform actions on button click");
|
|
679
|
+
});
|
|
680
|
+
|
|
681
|
+
// Synchronous — return false to abort the payment flow
|
|
682
|
+
button.onClick(() => {
|
|
683
|
+
if (!isOrderValid()) return false;
|
|
684
|
+
});
|
|
685
|
+
|
|
686
|
+
// Asynchronous — defer the wallet sheet until the promise resolves
|
|
687
|
+
button.onClick(async () => {
|
|
688
|
+
const response = await fetch('/api/validate-order');
|
|
689
|
+
const result = await response.json();
|
|
690
|
+
if (!result.valid) {
|
|
691
|
+
throw new Error('Order validation failed');
|
|
741
692
|
}
|
|
742
|
-
}
|
|
693
|
+
});
|
|
743
694
|
```
|
|
744
695
|
|
|
745
|
-
###
|
|
696
|
+
### Handling successful OTT creation
|
|
746
697
|
|
|
747
|
-
|
|
698
|
+
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.
|
|
748
699
|
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
700
|
+
```javascript
|
|
701
|
+
button.onSuccess(({ data }) => {
|
|
702
|
+
console.log("OTT created successfully:", data.token);
|
|
703
|
+
console.log("Amount:", data.amount);
|
|
704
|
+
console.log("Shipping:", data.shipping);
|
|
705
|
+
console.log("Billing:", data.billing);
|
|
753
706
|
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
707
|
+
fetch('/api/process-payment', {
|
|
708
|
+
method: 'POST',
|
|
709
|
+
headers: { 'Content-Type': 'application/json' },
|
|
710
|
+
body: JSON.stringify({ ott_token: data.token })
|
|
711
|
+
});
|
|
712
|
+
});
|
|
713
|
+
```
|
|
757
714
|
|
|
758
|
-
**
|
|
759
|
-
- `merchant_name?: string`: Display name for the merchant
|
|
715
|
+
**Important**: The `onSuccess` event handler is mandatory. Not providing one will result in an error.
|
|
760
716
|
|
|
761
|
-
###
|
|
717
|
+
### Updating meta after initialization
|
|
762
718
|
|
|
763
|
-
|
|
719
|
+
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:
|
|
764
720
|
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
721
|
+
```javascript
|
|
722
|
+
// For Apple Pay - accepts ApplePayOpenWalletMeta
|
|
723
|
+
applePayButton.setMeta({ ...meta, amount: 29.99, amount_label: 'NEW TOTAL' });
|
|
724
|
+
|
|
725
|
+
// For Google Pay - accepts GooglePayOpenWalletMeta
|
|
726
|
+
googlePayButton.setMeta({ ...meta, amount: 29.99, merchant_name: 'Updated Store' });
|
|
727
|
+
```
|
|
768
728
|
|
|
769
|
-
|
|
729
|
+
### Handling errors
|
|
770
730
|
|
|
771
|
-
|
|
731
|
+
Register a callback function to handle errors that occur during wallet operations, including service type mismatches.
|
|
772
732
|
|
|
773
733
|
```javascript
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
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
|
-
};
|
|
734
|
+
button.onError(({ data }) => {
|
|
735
|
+
console.error("Open Wallet error:", data.error);
|
|
736
|
+
console.log("Error context:", data.context);
|
|
737
|
+
|
|
738
|
+
showErrorMessage("Payment initialization failed. Please try again.");
|
|
739
|
+
});
|
|
825
740
|
```
|
|
826
741
|
|
|
827
|
-
|
|
742
|
+
### Handling checkout cancellation
|
|
828
743
|
|
|
829
|
-
|
|
744
|
+
When the user cancels or closes the wallet payment interface, you can perform cleanup operations.
|
|
830
745
|
|
|
831
746
|
```javascript
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
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
|
-
};
|
|
747
|
+
button.onCancel(() => {
|
|
748
|
+
console.log("Wallet checkout cancelled");
|
|
749
|
+
window.location.href = '/checkout';
|
|
750
|
+
});
|
|
863
751
|
```
|
|
864
752
|
|
|
865
|
-
|
|
753
|
+
### Cleaning up
|
|
754
|
+
|
|
755
|
+
Remove the wallet button from the DOM when it is no longer needed:
|
|
756
|
+
|
|
757
|
+
```javascript
|
|
758
|
+
button.destroy();
|
|
759
|
+
```
|
|
866
760
|
|
|
867
|
-
|
|
761
|
+
### Events
|
|
762
|
+
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
763
|
|
|
869
|
-
|
|
870
|
-
|
|
764
|
+
**Available Event Handler Methods:**
|
|
765
|
+
- `onClick(handler)` - Button click events (return `false` to abort, `Promise` to defer)
|
|
766
|
+
- `onSuccess(handler)` - **Required** - OTT creation success events
|
|
767
|
+
- `onUnavailable(handler)` - Wallet unavailable events (supports Promise pattern)
|
|
768
|
+
- `onError(handler)` - Error events (supports Promise pattern)
|
|
769
|
+
- `onCancel(handler)` - Checkout cancellation events (supports Promise pattern)
|
|
770
|
+
- `onLoaded(handler)` - Button loaded/rendered events
|
|
771
|
+
- `onShippingAddressChange(handler)` - **Recommended for shipping** - Address change events (auto-accepted if not registered)
|
|
772
|
+
- `onShippingOptionsChange(handler)` - **Recommended for shipping options** - Option change events (auto-accepted if not registered)
|
|
871
773
|
|
|
872
|
-
|
|
774
|
+
**Event Handler Patterns:**
|
|
873
775
|
|
|
874
776
|
```javascript
|
|
875
|
-
//
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
allowedCardNetworks: ['VISA', 'MASTERCARD', 'AMEX']
|
|
893
|
-
}
|
|
894
|
-
};
|
|
777
|
+
// Required handler
|
|
778
|
+
button.onSuccess(handler); // Always required
|
|
779
|
+
|
|
780
|
+
// Recommended when shipping is enabled (auto-accepted if not registered)
|
|
781
|
+
button.onShippingAddressChange(handler);
|
|
782
|
+
button.onShippingOptionsChange(handler);
|
|
783
|
+
|
|
784
|
+
// Optional handlers with Promise support
|
|
785
|
+
button.onUnavailable(handler); // or await button.onUnavailable()
|
|
786
|
+
button.onError(handler); // or await button.onError()
|
|
787
|
+
button.onCancel(handler); // or await button.onCancel()
|
|
788
|
+
|
|
789
|
+
// Click handler with flow control
|
|
790
|
+
button.onClick(handler); // Return false to abort, or a Promise to defer
|
|
791
|
+
|
|
792
|
+
// Loaded handler
|
|
793
|
+
button.onLoaded(handler); // Notified when button renders
|
|
895
794
|
```
|
|
896
795
|
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
796
|
+
### Apple Pay-Specific Meta Properties
|
|
797
|
+
|
|
798
|
+
A full description of the [ApplePayOpenWalletMeta](#ApplePayOpenWalletMeta) properties:
|
|
799
|
+
|
|
800
|
+
**Required:**
|
|
801
|
+
- `amount`: The payment amount (number)
|
|
802
|
+
- `currency`: The currency code (string, e.g., "AUD")
|
|
803
|
+
- `country`: The country code (string, e.g., "AU")
|
|
804
|
+
- `amount_label`: Label for the total amount (string)
|
|
805
|
+
- `store_name`: Merchant store name (string)
|
|
806
|
+
|
|
807
|
+
**Optional:**
|
|
808
|
+
- `request_shipping?: boolean`: Enable shipping address collection
|
|
809
|
+
- `shipping_options?: IApplePayShippingOption[]`: Array of shipping options
|
|
810
|
+
- `show_billing_address?: boolean`: Show billing address fields
|
|
811
|
+
- `apple_pay_capabilities?: string[]`: Device capabilities
|
|
812
|
+
- `merchant_capabilities?: string[]`: Merchant capabilities
|
|
813
|
+
- `supported_networks?: string[]`: Supported payment networks
|
|
814
|
+
- `required_billing_contact_fields?: string[]`: Required billing contact fields
|
|
815
|
+
- `required_shipping_contact_fields?: string[]`: Required shipping contact fields
|
|
816
|
+
- `supported_countries?: string[]`: Supported countries
|
|
817
|
+
- `shipping_editing_mode?: 'available' | 'store_pickup'`: Shipping address editing mode
|
|
818
|
+
- `style?: { button_type?: ApplePayButtonType, button_style?: ApplePayButtonStyle }`: Button styling
|
|
819
|
+
|
|
820
|
+
### Google Pay-Specific Meta Properties
|
|
821
|
+
|
|
822
|
+
A full description of the [GooglePayOpenWalletMeta](#GooglePayOpenWalletMeta) 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
|
+
|
|
829
|
+
**Optional:**
|
|
830
|
+
- `amount_label?: string`: Label for the total amount
|
|
831
|
+
- `merchant_name?: string`: Display name for the merchant
|
|
832
|
+
- `request_shipping?: boolean`: Enable shipping address collection
|
|
833
|
+
- `shipping_options?: IGooglePayShippingOption[]`: Array of shipping options
|
|
834
|
+
- `show_billing_address?: boolean`: Show billing address fields
|
|
835
|
+
- `card_config?: GooglePayCardConfig`: Card configuration (auth methods, networks, tokenization)
|
|
836
|
+
- `style?: { button_type?: GooglePayButtonType, button_color?: GooglePayButtonColor, button_size_mode?: GooglePayButtonSizeMode }`: Button styling
|
|
901
837
|
|
|
902
|
-
|
|
838
|
+
### Shipping Options Format
|
|
903
839
|
```javascript
|
|
904
840
|
shipping_options: [
|
|
905
841
|
{
|
|
@@ -907,12 +843,12 @@ shipping_options: [
|
|
|
907
843
|
label: "Option Name", // Display name (string)
|
|
908
844
|
detail: "Description", // Optional description (string)
|
|
909
845
|
amount: 10.00, // Shipping cost as number
|
|
910
|
-
date_components_range: { // Optional: delivery date range
|
|
846
|
+
date_components_range: { // Optional: delivery date range (Apple Pay only)
|
|
911
847
|
start_date_components: {
|
|
912
|
-
years: 0,
|
|
913
|
-
months: 0,
|
|
914
|
-
days: 5,
|
|
915
|
-
hours: 0,
|
|
848
|
+
years: 0,
|
|
849
|
+
months: 0,
|
|
850
|
+
days: 5,
|
|
851
|
+
hours: 0,
|
|
916
852
|
},
|
|
917
853
|
end_date_components: {
|
|
918
854
|
years: 0,
|
|
@@ -925,263 +861,28 @@ shipping_options: [
|
|
|
925
861
|
]
|
|
926
862
|
```
|
|
927
863
|
|
|
928
|
-
**Important**:
|
|
864
|
+
**Important**:
|
|
929
865
|
- `amount` should be a **number**, not a string
|
|
930
|
-
- `date_components_range` is optional but provides delivery estimates
|
|
866
|
+
- `date_components_range` is optional but provides delivery estimates (Apple Pay only)
|
|
931
867
|
- Updated shipping options returned from event handlers don't require `date_components_range`
|
|
932
868
|
|
|
933
|
-
|
|
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
|
|
869
|
+
### Environment Setup
|
|
1163
870
|
```javascript
|
|
1164
871
|
// Always set environment before loading
|
|
1165
|
-
|
|
1166
|
-
|
|
872
|
+
button.setEnv('sandbox');
|
|
873
|
+
button.load();
|
|
1167
874
|
```
|
|
1168
875
|
|
|
1169
|
-
|
|
876
|
+
### Error Handling Best Practices
|
|
1170
877
|
```javascript
|
|
1171
|
-
|
|
878
|
+
button.onError(function({ data }) {
|
|
1172
879
|
console.error('Full error object:', data);
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
data.message ||
|
|
1177
|
-
'Unknown error occurred';
|
|
1178
|
-
|
|
1179
|
-
// Handle different error types
|
|
880
|
+
|
|
881
|
+
const errorMessage = data.error?.message || 'Unknown error occurred';
|
|
882
|
+
|
|
1180
883
|
if (data.context?.operation === 'wallet_operation') {
|
|
1181
|
-
// Handle wallet-specific errors
|
|
1182
884
|
showWalletError(errorMessage);
|
|
1183
885
|
} else {
|
|
1184
|
-
// Handle general errors
|
|
1185
886
|
showGeneralError(errorMessage);
|
|
1186
887
|
}
|
|
1187
888
|
});
|