@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.
- package/README.md +2573 -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 +561 -830
- package/docs/open-wallet-buttons.md +1652 -0
- package/package.json +1 -1
- package/slate.md +1673 -0
package/slate.md
CHANGED
|
@@ -1311,6 +1311,1679 @@ Similarly, for **GooglePay via MPGS** you can initialize the `PaymentMethodSpeci
|
|
|
1311
1311
|
</html>
|
|
1312
1312
|
```
|
|
1313
1313
|
|
|
1314
|
+
## Express Wallet Buttons
|
|
1315
|
+
|
|
1316
|
+
Express Wallet Buttons allow to integrate with E-Wallets in an "express" operational mode, allowing to show the respective button in product or cart pages.
|
|
1317
|
+
|
|
1318
|
+
The general flow to use the widgets is:
|
|
1319
|
+
1. Configure your gateway and connect it using Paydock API or Dashboard.
|
|
1320
|
+
2. Create a container in your site
|
|
1321
|
+
```html
|
|
1322
|
+
<div id="widget"></div>
|
|
1323
|
+
```
|
|
1324
|
+
3. Initialize the specific WalletButtonExpress, providing your Access Token (preferred) or Public Key, plus required and optional meta parameters for the wallet in use. The general format is:
|
|
1325
|
+
```js
|
|
1326
|
+
new paydock.{Provider}WalletButtonExpress(
|
|
1327
|
+
"#widget",
|
|
1328
|
+
accessTokenOrPublicKey,
|
|
1329
|
+
gatewayId,
|
|
1330
|
+
gatewaySpecificMeta,
|
|
1331
|
+
);
|
|
1332
|
+
```
|
|
1333
|
+
4. (optional) If the screen where the button is rendered allows for cart/amount changes, call `setMeta` method to update the meta information.
|
|
1334
|
+
5. Handle the `onClick` callback, where you should call your server, initialize the wallet charge via `POST v1/charges/wallet` and return the wallet token.
|
|
1335
|
+
6. Handle the `onPaymentSuccessful`, `onPaymentError` and `onPaymentInReview` (if fraud is applicable) for payment results.
|
|
1336
|
+
|
|
1337
|
+
### Supported Providers
|
|
1338
|
+
1. [Apple Pay](#apple-pay-wallet-button-express)
|
|
1339
|
+
2. [Paypal](#paypal-wallet-button-express)
|
|
1340
|
+
|
|
1341
|
+
### Apple Pay Wallet Button Express
|
|
1342
|
+
|
|
1343
|
+
A full description of the meta parameters for [ApplePayWalletButtonExpress](#ApplePayWalletButtonExpress) meta parameters can be found [here](#ApplePayWalletMeta). Below you will find a fully working html example.
|
|
1344
|
+
|
|
1345
|
+
```html
|
|
1346
|
+
<!DOCTYPE html>
|
|
1347
|
+
<html lang="en">
|
|
1348
|
+
<head>
|
|
1349
|
+
<meta charset="UTF-8">
|
|
1350
|
+
<title>Title</title>
|
|
1351
|
+
</head>
|
|
1352
|
+
<body>
|
|
1353
|
+
<h2>Payment using PayDock ApplePayWalletButtonExpress!</h2>
|
|
1354
|
+
<div id="widget"></div>
|
|
1355
|
+
</body>
|
|
1356
|
+
<script src="https://widget.paydock.com/sdk/latest/widget.umd.min.js" ></script>
|
|
1357
|
+
<script>
|
|
1358
|
+
let button = new paydock.ApplePayWalletButtonExpress(
|
|
1359
|
+
"#widget",
|
|
1360
|
+
accessTokenOrPublicKey,
|
|
1361
|
+
gatewayId,
|
|
1362
|
+
{
|
|
1363
|
+
amount_label: 'TOTAL',
|
|
1364
|
+
country: 'AU',
|
|
1365
|
+
currency: 'AUD',
|
|
1366
|
+
amount: 15.5,
|
|
1367
|
+
// merchant_capabilities: ['supports3DS', 'supportsEMV', 'supportsCredit', 'supportsDebit'],
|
|
1368
|
+
// supported_networks: ['visa', 'masterCard', 'amex', 'chinaUnionPay', 'discover', 'interac', 'jcb', 'privateLabel'],
|
|
1369
|
+
// required_billing_contact_fields: ['email', 'name', 'phone', 'postalAddress'], // phone and email do not work according to relevant testing
|
|
1370
|
+
// required_shipping_contact_fields: ['email', 'phone'], // Workaround to pull phone and email from shipping contact instead - does not require additional shipping address information
|
|
1371
|
+
// supported_countries: ["AU"],
|
|
1372
|
+
// style: {
|
|
1373
|
+
// button_type: "buy",
|
|
1374
|
+
// button_style: "black",
|
|
1375
|
+
// },
|
|
1376
|
+
}
|
|
1377
|
+
);
|
|
1378
|
+
|
|
1379
|
+
button.setEnv('sandbox');
|
|
1380
|
+
|
|
1381
|
+
button.onUnavailable(function() {
|
|
1382
|
+
console.log("Button not available");
|
|
1383
|
+
});
|
|
1384
|
+
|
|
1385
|
+
button.onError(function(error) {
|
|
1386
|
+
console.log("On Error Callback", error);
|
|
1387
|
+
});
|
|
1388
|
+
|
|
1389
|
+
button.onPaymentSuccessful(function(data) {
|
|
1390
|
+
console.log("Payment successful");
|
|
1391
|
+
console.log(data);
|
|
1392
|
+
});
|
|
1393
|
+
|
|
1394
|
+
button.onPaymentError(function(err) {
|
|
1395
|
+
console.log("Payment error");
|
|
1396
|
+
console.log(err);
|
|
1397
|
+
});
|
|
1398
|
+
|
|
1399
|
+
button.onPaymentInReview(function(data) {
|
|
1400
|
+
console.log("The payment is on fraud review");
|
|
1401
|
+
console.log(data);
|
|
1402
|
+
});
|
|
1403
|
+
|
|
1404
|
+
button.onClick(async (data) => {
|
|
1405
|
+
console.log("Button clicked", data);
|
|
1406
|
+
|
|
1407
|
+
const responseData = await fetch('https://your-server-url/initialize-wallet-charge');
|
|
1408
|
+
const parsedData = await responseData.json();
|
|
1409
|
+
return parsedData.resource.data.token;
|
|
1410
|
+
});
|
|
1411
|
+
|
|
1412
|
+
button.onCheckoutClose(() => {
|
|
1413
|
+
console.log("Checkout closed");
|
|
1414
|
+
});
|
|
1415
|
+
|
|
1416
|
+
button.load();
|
|
1417
|
+
</script>
|
|
1418
|
+
</html>
|
|
1419
|
+
```
|
|
1420
|
+
|
|
1421
|
+
### Apple Pay Wallet Button Express with Shipping
|
|
1422
|
+
|
|
1423
|
+
A full description of the meta parameters for [ApplePayWalletButtonExpress](#ApplePayWalletButtonExpress) meta parameters can be found [here](#ApplePayWalletMeta). Below you will find a fully working html example.
|
|
1424
|
+
|
|
1425
|
+
```html
|
|
1426
|
+
<html>
|
|
1427
|
+
<head>
|
|
1428
|
+
<title>Apple Pay Express test page</title>
|
|
1429
|
+
<style>
|
|
1430
|
+
#inputModal {
|
|
1431
|
+
display: none;
|
|
1432
|
+
position: fixed;
|
|
1433
|
+
left: 0;
|
|
1434
|
+
top: 0;
|
|
1435
|
+
width: 100%;
|
|
1436
|
+
height: 100%;
|
|
1437
|
+
background-color: rgba(0,0,0,0.5);
|
|
1438
|
+
z-index: 1000;
|
|
1439
|
+
}
|
|
1440
|
+
#inputBox {
|
|
1441
|
+
position: absolute;
|
|
1442
|
+
left: 50%;
|
|
1443
|
+
top: 50%;
|
|
1444
|
+
transform: translate(-50%, -50%);
|
|
1445
|
+
padding: 20px;
|
|
1446
|
+
background: white;
|
|
1447
|
+
border-radius: 5px;
|
|
1448
|
+
box-shadow: 2px 2px 10px rgba(0,0,0,0.5);
|
|
1449
|
+
}
|
|
1450
|
+
</style>
|
|
1451
|
+
</head>
|
|
1452
|
+
<body>
|
|
1453
|
+
<table id='paymentTable'>
|
|
1454
|
+
<tr>
|
|
1455
|
+
<td>Environment:</td>
|
|
1456
|
+
<td>
|
|
1457
|
+
<select id="environment" name="environment">
|
|
1458
|
+
<option value="sandbox">Sandbox</option>
|
|
1459
|
+
<option value="local">Local</option>
|
|
1460
|
+
</select>
|
|
1461
|
+
</td>
|
|
1462
|
+
</tr>
|
|
1463
|
+
<tr>
|
|
1464
|
+
<td>Access Token / Public Key:</td>
|
|
1465
|
+
<td><input type="text" name="access" id="access" /></td>
|
|
1466
|
+
</tr>
|
|
1467
|
+
<tr>
|
|
1468
|
+
<td>Secret Key:</td>
|
|
1469
|
+
<td><input type="text" name="secretKey" id="secretKey" /></td>
|
|
1470
|
+
</tr>
|
|
1471
|
+
<tr>
|
|
1472
|
+
<td>Gateway Id:</td>
|
|
1473
|
+
<td><input type="text" name="gateway" id="gateway" /></td>
|
|
1474
|
+
</tr>
|
|
1475
|
+
<tr>
|
|
1476
|
+
<td>Wallet Charge - for apple pay we need to add it here because the apple pay popup does not allow us to
|
|
1477
|
+
inject it there but it will be used only on click. So is optional, if not provided it simulates an error
|
|
1478
|
+
when creating B2B wallet charge on click:</td>
|
|
1479
|
+
<td><input type="text" name="token" id="token" /></td>
|
|
1480
|
+
</tr>
|
|
1481
|
+
<tr>
|
|
1482
|
+
<td>Charge id - Used to update the charge with the shipping data/shipping options</td>
|
|
1483
|
+
<td><input type="text" name="chargeId" id="chargeId" /></td>
|
|
1484
|
+
</tr>
|
|
1485
|
+
<tr>
|
|
1486
|
+
<td>Meta:</td>
|
|
1487
|
+
<td><textarea id="meta" name="meta" rows="4" cols="50"></textarea></td>
|
|
1488
|
+
</tr>
|
|
1489
|
+
</table>
|
|
1490
|
+
<div id="button">
|
|
1491
|
+
<input type="submit" name="event" value="Send" class="button" onclick="return loadButtons()" />
|
|
1492
|
+
</div>
|
|
1493
|
+
<div id="widget"></div>
|
|
1494
|
+
</body>
|
|
1495
|
+
|
|
1496
|
+
<script src="https://widget.paydock.com/sdk/latest/widget.umd.min.js"></script>
|
|
1497
|
+
<script type=text/javascript>
|
|
1498
|
+
// Environment enum with API URLs
|
|
1499
|
+
const ENVIRONMENTS = {
|
|
1500
|
+
PRODUCTION: {
|
|
1501
|
+
name: 'production',
|
|
1502
|
+
apiUrl: 'https://api.paydock.com'
|
|
1503
|
+
},
|
|
1504
|
+
SANDBOX: {
|
|
1505
|
+
name: 'sandbox',
|
|
1506
|
+
apiUrl: 'https://api-sandox.paydock.com'
|
|
1507
|
+
}
|
|
1508
|
+
};
|
|
1509
|
+
|
|
1510
|
+
// Function to get API URL based on selected environment
|
|
1511
|
+
function getApiUrl(environmentName) {
|
|
1512
|
+
const env = Object.values(ENVIRONMENTS).find(env => env.name === environmentName);
|
|
1513
|
+
return env ? env.apiUrl : ENVIRONMENTS.SANDBOX.apiUrl;
|
|
1514
|
+
}
|
|
1515
|
+
|
|
1516
|
+
// Function to get current base URL from selected environment
|
|
1517
|
+
function getBaseUrl() {
|
|
1518
|
+
const selectedEnvironment = document.getElementById("environment").value;
|
|
1519
|
+
return getApiUrl(selectedEnvironment);
|
|
1520
|
+
}
|
|
1521
|
+
|
|
1522
|
+
async function updateCharge(secretKey, chargeId, updateData) {
|
|
1523
|
+
try {
|
|
1524
|
+
const baseUrl = getBaseUrl();
|
|
1525
|
+
const response = await fetch(`${baseUrl}/v1/charges/wallet/${chargeId}`, {
|
|
1526
|
+
method: 'PUT',
|
|
1527
|
+
headers: {
|
|
1528
|
+
'x-user-secret-key': secretKey,
|
|
1529
|
+
'Content-Type': 'application/json',
|
|
1530
|
+
},
|
|
1531
|
+
body: JSON.stringify(updateData),
|
|
1532
|
+
});
|
|
1533
|
+
const data = await response.json();
|
|
1534
|
+
console.log('Update charge response:', data);
|
|
1535
|
+
return data;
|
|
1536
|
+
} catch (error) {
|
|
1537
|
+
console.error('Error updating charge:', error);
|
|
1538
|
+
}
|
|
1539
|
+
};
|
|
1540
|
+
|
|
1541
|
+
const shippingOptions = [
|
|
1542
|
+
{
|
|
1543
|
+
label: "Test 1",
|
|
1544
|
+
detail: "This is a test 1 shipping methods",
|
|
1545
|
+
amount: 10,
|
|
1546
|
+
id: "randomId1",
|
|
1547
|
+
date_components_range: {
|
|
1548
|
+
start_date_components: {
|
|
1549
|
+
years: 0,
|
|
1550
|
+
months: 0,
|
|
1551
|
+
days: 5,
|
|
1552
|
+
hours: 0,
|
|
1553
|
+
},
|
|
1554
|
+
end_date_components: {
|
|
1555
|
+
years: 0,
|
|
1556
|
+
months: 0,
|
|
1557
|
+
days: 10,
|
|
1558
|
+
hours: 0,
|
|
1559
|
+
}
|
|
1560
|
+
}
|
|
1561
|
+
},
|
|
1562
|
+
{
|
|
1563
|
+
label: "Test 2",
|
|
1564
|
+
detail: "This is a test 2 shipping methods",
|
|
1565
|
+
amount: 14,
|
|
1566
|
+
id: "randomId2",
|
|
1567
|
+
date_components_range: {
|
|
1568
|
+
start_date_components: {
|
|
1569
|
+
years: 0,
|
|
1570
|
+
months: 0,
|
|
1571
|
+
days: 6,
|
|
1572
|
+
hours: 0,
|
|
1573
|
+
},
|
|
1574
|
+
end_date_components: {
|
|
1575
|
+
years: 0,
|
|
1576
|
+
months: 0,
|
|
1577
|
+
days: 12,
|
|
1578
|
+
hours: 0,
|
|
1579
|
+
},
|
|
1580
|
+
},
|
|
1581
|
+
},
|
|
1582
|
+
];
|
|
1583
|
+
|
|
1584
|
+
function loadButtons() {
|
|
1585
|
+
const secretKey = document.getElementById("secretKey").value;
|
|
1586
|
+
if (!secretKey) {
|
|
1587
|
+
alert("Please enter the secret key.");
|
|
1588
|
+
return false;
|
|
1589
|
+
}
|
|
1590
|
+
|
|
1591
|
+
let button = new paydock.ApplePayWalletButtonExpress(
|
|
1592
|
+
"#widget",
|
|
1593
|
+
document.getElementById("access").value,
|
|
1594
|
+
document.getElementById("gateway").value,
|
|
1595
|
+
JSON.parse(document.getElementById("meta").value),
|
|
1596
|
+
);
|
|
1597
|
+
|
|
1598
|
+
button.setEnv(document.getElementById("environment").value);
|
|
1599
|
+
|
|
1600
|
+
let charge_id;
|
|
1601
|
+
|
|
1602
|
+
button.onClick(async (data) => {
|
|
1603
|
+
const { token, chargeId } = await getUserInput();
|
|
1604
|
+
charge_id = chargeId;
|
|
1605
|
+
return token;
|
|
1606
|
+
});
|
|
1607
|
+
|
|
1608
|
+
const amount = JSON.parse(document.getElementById('meta').value).amount;
|
|
1609
|
+
|
|
1610
|
+
button.onUnavailable(function() {
|
|
1611
|
+
console.log("Button unavailable");
|
|
1612
|
+
});
|
|
1613
|
+
button.onError(function(error) {
|
|
1614
|
+
console.log("On Error Callback", error);
|
|
1615
|
+
});
|
|
1616
|
+
button.onPaymentSuccessful(function(data) {
|
|
1617
|
+
console.log("Payment successful");
|
|
1618
|
+
console.log(data);
|
|
1619
|
+
});
|
|
1620
|
+
button.onPaymentError(function(err) {
|
|
1621
|
+
console.log("Payment error");
|
|
1622
|
+
console.log(err);
|
|
1623
|
+
});
|
|
1624
|
+
button.onPaymentInReview(function(data) {
|
|
1625
|
+
console.log("The payment is on fraud review");
|
|
1626
|
+
console.log(data);
|
|
1627
|
+
});
|
|
1628
|
+
button.onCheckoutClose(() => {
|
|
1629
|
+
console.log("Checkout closed");
|
|
1630
|
+
});
|
|
1631
|
+
|
|
1632
|
+
button.onShippingAddressChange(async function(data) {
|
|
1633
|
+
console.log("Shipping address has been updated", data);
|
|
1634
|
+
|
|
1635
|
+
const defaultOption = shippingOptions[0];
|
|
1636
|
+
|
|
1637
|
+
const updateData = {
|
|
1638
|
+
shipping: {
|
|
1639
|
+
...data.data,
|
|
1640
|
+
amount: defaultOption.amount,
|
|
1641
|
+
method: defaultOption.id,
|
|
1642
|
+
options: shippingOptions,
|
|
1643
|
+
},
|
|
1644
|
+
amount: amount + defaultOption.amount
|
|
1645
|
+
};
|
|
1646
|
+
|
|
1647
|
+
const res = await updateCharge(secretKey, charge_id, updateData);
|
|
1648
|
+
return { token: res.resource.data.token };
|
|
1649
|
+
});
|
|
1650
|
+
|
|
1651
|
+
button.onShippingOptionsChange(async function(data) {
|
|
1652
|
+
console.log("Shipping options have been updated", JSON.stringify(data, null, 2));
|
|
1653
|
+
|
|
1654
|
+
const updateData = {
|
|
1655
|
+
shipping: {
|
|
1656
|
+
method: data.data.shipping_option_id,
|
|
1657
|
+
amount: data.data.amount,
|
|
1658
|
+
},
|
|
1659
|
+
amount: amount + Number(data.data.amount)
|
|
1660
|
+
};
|
|
1661
|
+
|
|
1662
|
+
const res = await updateCharge(secretKey, charge_id, updateData);
|
|
1663
|
+
return { token: res.resource.data.token };
|
|
1664
|
+
});
|
|
1665
|
+
|
|
1666
|
+
button.load()
|
|
1667
|
+
|
|
1668
|
+
document.getElementById("paymentTable").style.display = "none";
|
|
1669
|
+
document.getElementById("button").style.display = "none";
|
|
1670
|
+
return true;
|
|
1671
|
+
}
|
|
1672
|
+
|
|
1673
|
+
function getUserInput(message) {
|
|
1674
|
+
return new Promise((resolve, reject) => {
|
|
1675
|
+
console.log("Simulating B2B call to generate token...");
|
|
1676
|
+
setTimeout(() => {
|
|
1677
|
+
const token = document.getElementById("token").value;
|
|
1678
|
+
const chargeId = document.getElementById("chargeId").value;
|
|
1679
|
+
if (token && chargeId)
|
|
1680
|
+
return resolve({ token, chargeId });
|
|
1681
|
+
return reject("No token or Charge Id provided");
|
|
1682
|
+
}, 2000);
|
|
1683
|
+
});
|
|
1684
|
+
}
|
|
1685
|
+
|
|
1686
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
1687
|
+
// Function to get the value of a query parameter by name
|
|
1688
|
+
function getQueryParam(name) {
|
|
1689
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
1690
|
+
return urlParams.get(name);
|
|
1691
|
+
}
|
|
1692
|
+
|
|
1693
|
+
// Function to set input values from URL parameters
|
|
1694
|
+
function setInputValues() {
|
|
1695
|
+
const meta = {
|
|
1696
|
+
apple_pay_capabilities: ['credentials_available', 'credentials_status_unknown', 'credentials_unavailable'],
|
|
1697
|
+
amount_label: 'TOTAL',
|
|
1698
|
+
country: 'AU',
|
|
1699
|
+
currency: 'AUD',
|
|
1700
|
+
amount: 10,
|
|
1701
|
+
shipping_editing_mode: 'available', // available, store_pickup
|
|
1702
|
+
required_shipping_contact_fields: [
|
|
1703
|
+
'postalAddress',
|
|
1704
|
+
'name',
|
|
1705
|
+
'phone',
|
|
1706
|
+
'email',
|
|
1707
|
+
],
|
|
1708
|
+
shipping: {
|
|
1709
|
+
amount: 5,
|
|
1710
|
+
address_line1: "Address Line 1",
|
|
1711
|
+
address_city: "Test Locality",
|
|
1712
|
+
address_state: "NSW",
|
|
1713
|
+
address_country: "Australia",
|
|
1714
|
+
address_country_code: "AU",
|
|
1715
|
+
address_postcode: "3000",
|
|
1716
|
+
contact: {
|
|
1717
|
+
phone: "+61400245562",
|
|
1718
|
+
email: "qa.notifications+appleid@paydock.com",
|
|
1719
|
+
first_name: "QA",
|
|
1720
|
+
last_name: "QA",
|
|
1721
|
+
},
|
|
1722
|
+
options: shippingOptions,
|
|
1723
|
+
},
|
|
1724
|
+
// merchant_capabilities: ['supports3DS', 'supportsEMV', 'supportsCredit', 'supportsDebit'],
|
|
1725
|
+
// supported_networks: ['visa', 'masterCard', 'amex', 'chinaUnionPay', 'discover', 'interac', 'jcb', 'privateLabel'],
|
|
1726
|
+
// required_billing_contact_fields: ['email', 'name', 'phone', 'postalAddress', 'phoneticName'],
|
|
1727
|
+
// required_shipping_contact_fields: ['email', 'phone' /*, 'name', 'postalAddress', 'phoneticName'*/],
|
|
1728
|
+
// supported_countries: [],
|
|
1729
|
+
// style: {
|
|
1730
|
+
// button_type: 'continue',
|
|
1731
|
+
// button_style: 'white',
|
|
1732
|
+
// },
|
|
1733
|
+
};
|
|
1734
|
+
document.getElementById('meta').value = JSON.stringify(meta, null, 2);
|
|
1735
|
+
}
|
|
1736
|
+
|
|
1737
|
+
setInputValues();
|
|
1738
|
+
});
|
|
1739
|
+
</script>
|
|
1740
|
+
</html>
|
|
1741
|
+
```
|
|
1742
|
+
|
|
1743
|
+
When supporting shipping, the method `onShippingAddressChange` and `onShippingOptionsChange` are required to update the shipping address and options.
|
|
1744
|
+
|
|
1745
|
+
```javascript
|
|
1746
|
+
button.onShippingAddressChange(async function(data) {
|
|
1747
|
+
console.log("Shipping address has been updated", data);
|
|
1748
|
+
|
|
1749
|
+
const updateData = {
|
|
1750
|
+
shipping: {
|
|
1751
|
+
...data.data,
|
|
1752
|
+
amount: defaultOption.amount,
|
|
1753
|
+
method: defaultOption.id,
|
|
1754
|
+
options: shippingOptions,
|
|
1755
|
+
},
|
|
1756
|
+
amount: amount + defaultOption.amount
|
|
1757
|
+
};
|
|
1758
|
+
|
|
1759
|
+
const res = await updateCharge(secretKey, charge_id, updateData);
|
|
1760
|
+
return { token: res.resource.data.token };
|
|
1761
|
+
});
|
|
1762
|
+
|
|
1763
|
+
button.onShippingOptionsChange(async function(data) {
|
|
1764
|
+
console.log("Shipping options have been updated", data);
|
|
1765
|
+
|
|
1766
|
+
const updateData = {
|
|
1767
|
+
shipping: {
|
|
1768
|
+
method: data.data.shipping_option_id,
|
|
1769
|
+
amount: data.data.amount,
|
|
1770
|
+
},
|
|
1771
|
+
amount: amount + Number(data.data.amount)
|
|
1772
|
+
};
|
|
1773
|
+
|
|
1774
|
+
const res = await updateCharge(secretKey, charge_id, updateData);
|
|
1775
|
+
return { token: res.resource.data.token };
|
|
1776
|
+
});
|
|
1777
|
+
```
|
|
1778
|
+
|
|
1779
|
+
The `updateCharge` method is a custom method to update the charge with the shipping data/shipping options. It is not part of the Paydock SDK and it should use the Paydock's public API to update the charge from the merchant's server.
|
|
1780
|
+
|
|
1781
|
+
### Supported Cases
|
|
1782
|
+
#### Injected Shipping Address, non-editable by the customer
|
|
1783
|
+
|
|
1784
|
+
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.
|
|
1785
|
+
|
|
1786
|
+
The required meta parameters for this case are:
|
|
1787
|
+
- shipping_editing_mode: 'store_pickup'
|
|
1788
|
+
- required_shipping_contact_fields: ['postalAddress'] <-- At least one of the fields is required so the shipping address is shown at Apple Pay.
|
|
1789
|
+
|
|
1790
|
+
```javascript
|
|
1791
|
+
meta: {
|
|
1792
|
+
apple_pay_capabilities: ['credentials_available', 'credentials_status_unknown', 'credentials_unavailable'],
|
|
1793
|
+
amount_label: 'TOTAL',
|
|
1794
|
+
country: 'AU',
|
|
1795
|
+
currency: 'AUD',
|
|
1796
|
+
amount: 10,
|
|
1797
|
+
shipping_editing_mode: 'store_pickup',
|
|
1798
|
+
required_shipping_contact_fields: [
|
|
1799
|
+
'postalAddress', // At least one of the fields is required so the shipping address is shown at Apple Pay.
|
|
1800
|
+
'name',
|
|
1801
|
+
'phone',
|
|
1802
|
+
'email',
|
|
1803
|
+
],
|
|
1804
|
+
shipping: {
|
|
1805
|
+
amount: 5,
|
|
1806
|
+
address_line1: "Address Line 1",
|
|
1807
|
+
address_city: "Test Locality",
|
|
1808
|
+
address_state: "NSW",
|
|
1809
|
+
address_country: "Australia",
|
|
1810
|
+
address_country_code: "AU",
|
|
1811
|
+
address_postcode: "3000",
|
|
1812
|
+
contact: {
|
|
1813
|
+
phone: "+61400245562",
|
|
1814
|
+
email: "qa.notifications+appleid@paydock.com",
|
|
1815
|
+
first_name: "QA",
|
|
1816
|
+
last_name: "QA",
|
|
1817
|
+
},
|
|
1818
|
+
options: [
|
|
1819
|
+
{
|
|
1820
|
+
label: "Test 1",
|
|
1821
|
+
detail: "This is a test 1 shipping methods",
|
|
1822
|
+
amount: 10,
|
|
1823
|
+
id: "randomId1",
|
|
1824
|
+
date_components_range: {
|
|
1825
|
+
start_date_components: {
|
|
1826
|
+
years: 0,
|
|
1827
|
+
months: 0,
|
|
1828
|
+
days: 5,
|
|
1829
|
+
hours: 0,
|
|
1830
|
+
},
|
|
1831
|
+
end_date_components: {
|
|
1832
|
+
years: 0,
|
|
1833
|
+
months: 0,
|
|
1834
|
+
days: 10,
|
|
1835
|
+
hours: 0,
|
|
1836
|
+
}
|
|
1837
|
+
}
|
|
1838
|
+
}
|
|
1839
|
+
],
|
|
1840
|
+
},
|
|
1841
|
+
}
|
|
1842
|
+
```
|
|
1843
|
+
|
|
1844
|
+
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.
|
|
1845
|
+
|
|
1846
|
+
The required meta parameters for this case are:
|
|
1847
|
+
- shipping_editing_mode: 'available'
|
|
1848
|
+
- required_shipping_contact_fields: ['postalAddress'] <-- At least one of the fields is required so the shipping address is shown at Apple Pay.
|
|
1849
|
+
|
|
1850
|
+
```javascript
|
|
1851
|
+
meta: {
|
|
1852
|
+
apple_pay_capabilities: ['credentials_available', 'credentials_status_unknown', 'credentials_unavailable'],
|
|
1853
|
+
amount_label: 'TOTAL',
|
|
1854
|
+
country: 'AU',
|
|
1855
|
+
currency: 'AUD',
|
|
1856
|
+
amount: 10,
|
|
1857
|
+
shipping_editing_mode: 'available',
|
|
1858
|
+
required_shipping_contact_fields: [
|
|
1859
|
+
'postalAddress', // At least one of the fields is required so the shipping address is shown at Apple Pay.
|
|
1860
|
+
'name',
|
|
1861
|
+
'phone',
|
|
1862
|
+
'email',
|
|
1863
|
+
],
|
|
1864
|
+
shipping: {
|
|
1865
|
+
amount: 5,
|
|
1866
|
+
address_line1: "Address Line 1",
|
|
1867
|
+
address_city: "Test Locality",
|
|
1868
|
+
address_state: "NSW",
|
|
1869
|
+
address_country: "Australia",
|
|
1870
|
+
address_country_code: "AU",
|
|
1871
|
+
address_postcode: "3000",
|
|
1872
|
+
contact: {
|
|
1873
|
+
phone: "+61400245562",
|
|
1874
|
+
email: "qa.notifications+appleid@paydock.com",
|
|
1875
|
+
first_name: "QA",
|
|
1876
|
+
last_name: "QA",
|
|
1877
|
+
},
|
|
1878
|
+
options: [
|
|
1879
|
+
{
|
|
1880
|
+
label: "Test 1",
|
|
1881
|
+
detail: "This is a test 1 shipping methods",
|
|
1882
|
+
amount: 10,
|
|
1883
|
+
id: "randomId1",
|
|
1884
|
+
date_components_range: {
|
|
1885
|
+
start_date_components: {
|
|
1886
|
+
years: 0,
|
|
1887
|
+
months: 0,
|
|
1888
|
+
days: 5,
|
|
1889
|
+
hours: 0,
|
|
1890
|
+
},
|
|
1891
|
+
end_date_components: {
|
|
1892
|
+
years: 0,
|
|
1893
|
+
months: 0,
|
|
1894
|
+
days: 10,
|
|
1895
|
+
hours: 0,
|
|
1896
|
+
}
|
|
1897
|
+
}
|
|
1898
|
+
}
|
|
1899
|
+
],
|
|
1900
|
+
},
|
|
1901
|
+
}
|
|
1902
|
+
```
|
|
1903
|
+
|
|
1904
|
+
#### Shipping address editable by the customer
|
|
1905
|
+
|
|
1906
|
+
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.
|
|
1907
|
+
|
|
1908
|
+
The required meta parameters for this case are:
|
|
1909
|
+
- shipping_editing_mode: 'available'
|
|
1910
|
+
- required_shipping_contact_fields: ['postalAddress'] <-- At least one of the fields is required so the shipping address is shown at Apple Pay.
|
|
1911
|
+
|
|
1912
|
+
```javascript
|
|
1913
|
+
meta: {
|
|
1914
|
+
apple_pay_capabilities: ['credentials_available', 'credentials_status_unknown', 'credentials_unavailable'],
|
|
1915
|
+
amount_label: 'TOTAL',
|
|
1916
|
+
country: 'AU',
|
|
1917
|
+
currency: 'AUD',
|
|
1918
|
+
amount: 10,
|
|
1919
|
+
shipping_editing_mode: 'available',
|
|
1920
|
+
required_shipping_contact_fields: [
|
|
1921
|
+
'postalAddress', // At least one of the fields is required so the shipping address is shown at Apple Pay.
|
|
1922
|
+
'name',
|
|
1923
|
+
'phone',
|
|
1924
|
+
'email',
|
|
1925
|
+
],
|
|
1926
|
+
}
|
|
1927
|
+
```
|
|
1928
|
+
|
|
1929
|
+
When the the customer selects an address, the `onShippingAddressChange` method is called with the shipping address data. If the merchant wants to update the charge with the shipping address, it should update the charge using Paydock's public API Update Charge method with the shipping address data.
|
|
1930
|
+
|
|
1931
|
+
It can include the shipping options in the update data, that will be used to show the shipping options in the Apple Pay popup.
|
|
1932
|
+
|
|
1933
|
+
```javascript
|
|
1934
|
+
button.onShippingAddressChange(async function(data) {
|
|
1935
|
+
console.log("Shipping address has been updated", data);
|
|
1936
|
+
|
|
1937
|
+
const updateData = {
|
|
1938
|
+
shipping: {
|
|
1939
|
+
...data.data,
|
|
1940
|
+
amount: defaultOption.amount,
|
|
1941
|
+
method: defaultOption.id,
|
|
1942
|
+
options: shippingOptions,
|
|
1943
|
+
},
|
|
1944
|
+
amount: amount + defaultOption.amount
|
|
1945
|
+
};
|
|
1946
|
+
});
|
|
1947
|
+
```
|
|
1948
|
+
|
|
1949
|
+
#### No shipping address
|
|
1950
|
+
|
|
1951
|
+
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.
|
|
1952
|
+
|
|
1953
|
+
**Important:**
|
|
1954
|
+
- No shipping address should be provided in the meta object.
|
|
1955
|
+
- Shipping address could be provided in the initial POST `/v1/charges/wallet` endpoint, if collected previously.
|
|
1956
|
+
|
|
1957
|
+
The required meta parameters for this case are:
|
|
1958
|
+
- `required_shipping_contact_fields`: Only include contact fields if needed (phone, email), but NOT `postalAddress`.
|
|
1959
|
+
|
|
1960
|
+
```javascript
|
|
1961
|
+
meta: {
|
|
1962
|
+
"amount_label": "TOTAL",
|
|
1963
|
+
"country": "AU",
|
|
1964
|
+
"currency": "AUD",
|
|
1965
|
+
"amount": 10,
|
|
1966
|
+
"shipping_editing_mode": "available",
|
|
1967
|
+
"required_shipping_contact_fields": ["phone", "email"],
|
|
1968
|
+
"apple_pay_capabilities": ["credentials_available", "credentials_status_unknown", "credentials_unavailable"]
|
|
1969
|
+
}
|
|
1970
|
+
```
|
|
1971
|
+
|
|
1972
|
+
### Paypal Wallet Button Express
|
|
1973
|
+
A full description of the meta parameters for [PaypalWalletButtonExpress](#PaypalWalletButtonExpress) meta parameters can be found [here](#PaypalWalletMeta). Below you will find a fully working html example.
|
|
1974
|
+
|
|
1975
|
+
```html
|
|
1976
|
+
<!DOCTYPE html>
|
|
1977
|
+
<html lang="en">
|
|
1978
|
+
<head>
|
|
1979
|
+
<meta charset="UTF-8">
|
|
1980
|
+
<title>Title</title>
|
|
1981
|
+
</head>
|
|
1982
|
+
<body>
|
|
1983
|
+
<h2>Payment using PayDock PaypalWalletButtonExpress!</h2>
|
|
1984
|
+
<div id="widget"></div>
|
|
1985
|
+
</body>
|
|
1986
|
+
<script src="https://widget.paydock.com/sdk/latest/widget.umd.min.js" ></script>
|
|
1987
|
+
<script>
|
|
1988
|
+
let button = new paydock.PaypalWalletButtonExpress(
|
|
1989
|
+
"#widget",
|
|
1990
|
+
accessTokenOrPublicKey,
|
|
1991
|
+
gatewayId,
|
|
1992
|
+
{
|
|
1993
|
+
amount: 15.5,
|
|
1994
|
+
currency: 'AUD',
|
|
1995
|
+
pay_later: false,
|
|
1996
|
+
standalone: false,
|
|
1997
|
+
capture: true,
|
|
1998
|
+
// style: {
|
|
1999
|
+
// layout: 'horizontal', // or 'vertical'
|
|
2000
|
+
// color: 'gold', // or 'blue', 'silver', 'black', 'white'
|
|
2001
|
+
// shape: 'rect', // or 'pill', 'sharp'
|
|
2002
|
+
// borderRadius: 5,
|
|
2003
|
+
// height: 40,
|
|
2004
|
+
// disableMaxWidth: false,
|
|
2005
|
+
// label: 'paypal', // or 'checkout', 'buynow', 'pay', 'installment'
|
|
2006
|
+
// tagline: true,
|
|
2007
|
+
// messages: {
|
|
2008
|
+
// layout: 'text', // or 'flex'
|
|
2009
|
+
// logo: {
|
|
2010
|
+
// type: 'primary', // or 'alternative', 'inline', 'none'
|
|
2011
|
+
// position: 'left', // or 'right', 'top'
|
|
2012
|
+
// },
|
|
2013
|
+
// text: {
|
|
2014
|
+
// color: 'black', // or 'white', 'monochrome', 'grayscale'
|
|
2015
|
+
// size: 10, // or 11, 12, 13, 14, 15, 16
|
|
2016
|
+
// align: 'left', // or 'center', 'right'
|
|
2017
|
+
// },
|
|
2018
|
+
// color: 'blue', // or 'black', 'white', 'white-no-border', 'gray', 'monochrome', 'grayscale'
|
|
2019
|
+
// ratio: '1x1', // or '1x4', '8x1', '20x1'
|
|
2020
|
+
// },
|
|
2021
|
+
// }
|
|
2022
|
+
}
|
|
2023
|
+
);
|
|
2024
|
+
|
|
2025
|
+
button.setEnv('sandbox');
|
|
2026
|
+
|
|
2027
|
+
button.onUnavailable(function() {
|
|
2028
|
+
console.log("Button not available");
|
|
2029
|
+
});
|
|
2030
|
+
|
|
2031
|
+
button.onError(function(error) {
|
|
2032
|
+
console.log("On Error Callback", error);
|
|
2033
|
+
});
|
|
2034
|
+
|
|
2035
|
+
button.onPaymentSuccessful(function(data) {
|
|
2036
|
+
console.log("Payment successful");
|
|
2037
|
+
console.log(data);
|
|
2038
|
+
});
|
|
2039
|
+
|
|
2040
|
+
button.onPaymentError(function(err) {
|
|
2041
|
+
console.log("Payment error");
|
|
2042
|
+
console.log(err);
|
|
2043
|
+
});
|
|
2044
|
+
|
|
2045
|
+
button.onPaymentInReview(function(data) {
|
|
2046
|
+
console.log("The payment is on fraud review");
|
|
2047
|
+
console.log(data);
|
|
2048
|
+
});
|
|
2049
|
+
|
|
2050
|
+
button.onClick(async (data) => {
|
|
2051
|
+
console.log("Button clicked", data);
|
|
2052
|
+
|
|
2053
|
+
const responseData = await fetch('https://your-server-url/initialize-wallet-charge');
|
|
2054
|
+
const parsedData = await responseData.json();
|
|
2055
|
+
return parsedData.resource.data.token;
|
|
2056
|
+
});
|
|
2057
|
+
|
|
2058
|
+
button.onCheckoutClose(() => {
|
|
2059
|
+
console.log("Checkout closed");
|
|
2060
|
+
});
|
|
2061
|
+
|
|
2062
|
+
button.load();
|
|
2063
|
+
</script>
|
|
2064
|
+
</html>
|
|
2065
|
+
```
|
|
2066
|
+
|
|
2067
|
+
## Open Wallet Buttons
|
|
2068
|
+
You can find description of all methods and parameters [here](https://www.npmjs.com/package/@paydock/client-sdk#open-wallet-buttons-simple-example)
|
|
2069
|
+
|
|
2070
|
+
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.
|
|
2071
|
+
|
|
2072
|
+
Each wallet type has its own dedicated class with fully typed metadata:
|
|
2073
|
+
- [ApplePayOpenWalletButton](#ApplePayOpenWalletButton) - for Apple Pay integration
|
|
2074
|
+
- [GooglePayOpenWalletButton](#GooglePayOpenWalletButton) - for Google Pay integration
|
|
2075
|
+
|
|
2076
|
+
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.
|
|
2077
|
+
|
|
2078
|
+
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.
|
|
2079
|
+
|
|
2080
|
+
## Apple Pay Open Wallet Button
|
|
2081
|
+
|
|
2082
|
+
### Container
|
|
2083
|
+
|
|
2084
|
+
```html
|
|
2085
|
+
<div id="widget"></div>
|
|
2086
|
+
```
|
|
2087
|
+
|
|
2088
|
+
You must create a container for the Open Wallet Button. Inside this tag, the button will be initialized.
|
|
2089
|
+
|
|
2090
|
+
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.
|
|
2091
|
+
|
|
2092
|
+
### Initialization
|
|
2093
|
+
|
|
2094
|
+
```javascript
|
|
2095
|
+
let button = new paydock.ApplePayOpenWalletButton(
|
|
2096
|
+
"#widget",
|
|
2097
|
+
publicKeyOrAccessToken,
|
|
2098
|
+
serviceId,
|
|
2099
|
+
{
|
|
2100
|
+
amount: 100,
|
|
2101
|
+
currency: "AUD",
|
|
2102
|
+
country: "AU",
|
|
2103
|
+
amount_label: "TOTAL",
|
|
2104
|
+
store_name: "My Store",
|
|
2105
|
+
apple_pay_capabilities: ['credentials_available', 'credentials_status_unknown', 'credentials_unavailable'],
|
|
2106
|
+
}
|
|
2107
|
+
);
|
|
2108
|
+
button.load();
|
|
2109
|
+
```
|
|
2110
|
+
|
|
2111
|
+
```javascript
|
|
2112
|
+
// ES2015 | TypeScript
|
|
2113
|
+
import { ApplePayOpenWalletButton } from '@paydock/client-sdk';
|
|
2114
|
+
|
|
2115
|
+
var button = new ApplePayOpenWalletButton(
|
|
2116
|
+
'#widget',
|
|
2117
|
+
publicKeyOrAccessToken,
|
|
2118
|
+
serviceId,
|
|
2119
|
+
{
|
|
2120
|
+
amount: 100,
|
|
2121
|
+
currency: 'AUD',
|
|
2122
|
+
country: 'AU',
|
|
2123
|
+
amount_label: 'TOTAL',
|
|
2124
|
+
store_name: 'My Store',
|
|
2125
|
+
}
|
|
2126
|
+
);
|
|
2127
|
+
button.load();
|
|
2128
|
+
```
|
|
2129
|
+
|
|
2130
|
+
### Constructor Parameters
|
|
2131
|
+
|
|
2132
|
+
The ApplePayOpenWalletButton constructor accepts the following parameters:
|
|
2133
|
+
|
|
2134
|
+
1. **selector** (string): CSS selector for the container element
|
|
2135
|
+
2. **publicKeyOrAccessToken** (string): Your PayDock public key or access token
|
|
2136
|
+
3. **serviceId** (string): The Apple Pay service ID configured in PayDock dashboard
|
|
2137
|
+
4. **meta** (ApplePayOpenWalletMeta): Apple Pay-specific configuration object
|
|
2138
|
+
|
|
2139
|
+
> **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.
|
|
2140
|
+
|
|
2141
|
+
### Setting environment
|
|
2142
|
+
|
|
2143
|
+
Current method can change environment. By default environment = sandbox.
|
|
2144
|
+
Bear in mind that you must set an environment before calling `button.load()`.
|
|
2145
|
+
|
|
2146
|
+
```javascript
|
|
2147
|
+
button.setEnv('sandbox');
|
|
2148
|
+
```
|
|
2149
|
+
|
|
2150
|
+
### Full Apple Pay example
|
|
2151
|
+
|
|
2152
|
+
```html
|
|
2153
|
+
<!DOCTYPE html>
|
|
2154
|
+
<html lang="en">
|
|
2155
|
+
<head>
|
|
2156
|
+
<meta charset="UTF-8">
|
|
2157
|
+
<title>Apple Pay with Open Wallets</title>
|
|
2158
|
+
</head>
|
|
2159
|
+
<body>
|
|
2160
|
+
<h2>Payment using PayDock Apple Pay Open Wallet Button!</h2>
|
|
2161
|
+
<div id="widget"></div>
|
|
2162
|
+
</body>
|
|
2163
|
+
<script src="https://widget.paydock.com/sdk/latest/widget.umd.min.js" ></script>
|
|
2164
|
+
<script>
|
|
2165
|
+
let button = new paydock.ApplePayOpenWalletButton(
|
|
2166
|
+
"#widget",
|
|
2167
|
+
publicKeyOrAccessToken,
|
|
2168
|
+
serviceId,
|
|
2169
|
+
{
|
|
2170
|
+
amount: 100,
|
|
2171
|
+
currency: "AUD",
|
|
2172
|
+
country: "AU",
|
|
2173
|
+
amount_label: "TOTAL",
|
|
2174
|
+
store_name: "My Store",
|
|
2175
|
+
request_shipping: true,
|
|
2176
|
+
request_payer_name: true,
|
|
2177
|
+
request_payer_email: true,
|
|
2178
|
+
request_payer_phone: true,
|
|
2179
|
+
show_billing_address: true,
|
|
2180
|
+
style: {
|
|
2181
|
+
button_type: 'buy',
|
|
2182
|
+
button_style: 'black'
|
|
2183
|
+
},
|
|
2184
|
+
shipping_options: [
|
|
2185
|
+
{
|
|
2186
|
+
id: "standard",
|
|
2187
|
+
label: "Standard Shipping",
|
|
2188
|
+
detail: "Arrives in 5 to 7 days",
|
|
2189
|
+
amount: 5.00,
|
|
2190
|
+
date_components_range: {
|
|
2191
|
+
start_date_components: {
|
|
2192
|
+
years: 0,
|
|
2193
|
+
months: 0,
|
|
2194
|
+
days: 5,
|
|
2195
|
+
hours: 0,
|
|
2196
|
+
},
|
|
2197
|
+
end_date_components: {
|
|
2198
|
+
years: 0,
|
|
2199
|
+
months: 0,
|
|
2200
|
+
days: 7,
|
|
2201
|
+
hours: 0,
|
|
2202
|
+
}
|
|
2203
|
+
}
|
|
2204
|
+
},
|
|
2205
|
+
{
|
|
2206
|
+
id: "express",
|
|
2207
|
+
label: "Express Shipping",
|
|
2208
|
+
detail: "Arrives in 1 to 2 days",
|
|
2209
|
+
amount: 15.00,
|
|
2210
|
+
date_components_range: {
|
|
2211
|
+
start_date_components: {
|
|
2212
|
+
years: 0,
|
|
2213
|
+
months: 0,
|
|
2214
|
+
days: 1,
|
|
2215
|
+
hours: 0,
|
|
2216
|
+
},
|
|
2217
|
+
end_date_components: {
|
|
2218
|
+
years: 0,
|
|
2219
|
+
months: 0,
|
|
2220
|
+
days: 2,
|
|
2221
|
+
hours: 0,
|
|
2222
|
+
}
|
|
2223
|
+
}
|
|
2224
|
+
}
|
|
2225
|
+
],
|
|
2226
|
+
apple_pay_capabilities: ['credentials_available', 'credentials_status_unknown', 'credentials_unavailable']
|
|
2227
|
+
}
|
|
2228
|
+
);
|
|
2229
|
+
|
|
2230
|
+
button.setEnv('sandbox');
|
|
2231
|
+
|
|
2232
|
+
button.onUnavailable((data) => {
|
|
2233
|
+
console.log("Apple Pay not available:", data);
|
|
2234
|
+
// Show alternative payment methods
|
|
2235
|
+
});
|
|
2236
|
+
|
|
2237
|
+
button.onClick((data) => {
|
|
2238
|
+
console.log("Apple Pay button clicked");
|
|
2239
|
+
// Perform pre-payment validation
|
|
2240
|
+
});
|
|
2241
|
+
|
|
2242
|
+
button.onSuccess((data) => {
|
|
2243
|
+
console.log("Payment successful:", data);
|
|
2244
|
+
// Process the OTT token on your backend
|
|
2245
|
+
processPayment(data.token);
|
|
2246
|
+
});
|
|
2247
|
+
|
|
2248
|
+
button.onError((data) => {
|
|
2249
|
+
console.error("Payment error:", data);
|
|
2250
|
+
// Handle error appropriately
|
|
2251
|
+
});
|
|
2252
|
+
|
|
2253
|
+
button.onCancel((data) => {
|
|
2254
|
+
console.log("Payment cancelled");
|
|
2255
|
+
// Handle cancellation
|
|
2256
|
+
});
|
|
2257
|
+
|
|
2258
|
+
button.onShippingAddressChange(async (addressData) => {
|
|
2259
|
+
// Update shipping costs based on address
|
|
2260
|
+
const response = await updateShippingCosts(addressData);
|
|
2261
|
+
return {
|
|
2262
|
+
amount: response.newAmount,
|
|
2263
|
+
shipping_options: response.shippingOptions
|
|
2264
|
+
};
|
|
2265
|
+
});
|
|
2266
|
+
|
|
2267
|
+
button.onShippingOptionsChange(async (optionData) => {
|
|
2268
|
+
// Update total based on selected shipping option
|
|
2269
|
+
const response = await updateTotal(optionData);
|
|
2270
|
+
return {
|
|
2271
|
+
amount: response.newAmount
|
|
2272
|
+
};
|
|
2273
|
+
});
|
|
2274
|
+
|
|
2275
|
+
button.load();
|
|
2276
|
+
|
|
2277
|
+
async function updateShippingCosts(addressData) {
|
|
2278
|
+
// Your shipping calculation logic based on address
|
|
2279
|
+
const baseAmount = 100;
|
|
2280
|
+
const updatedShippingOptions = [
|
|
2281
|
+
{
|
|
2282
|
+
id: "updated-standard",
|
|
2283
|
+
label: "Updated Standard Shipping",
|
|
2284
|
+
detail: "Based on your location",
|
|
2285
|
+
amount: 8.00
|
|
2286
|
+
},
|
|
2287
|
+
{
|
|
2288
|
+
id: "updated-express",
|
|
2289
|
+
label: "Updated Express Shipping",
|
|
2290
|
+
detail: "Fast delivery to your area",
|
|
2291
|
+
amount: 18.00
|
|
2292
|
+
}
|
|
2293
|
+
];
|
|
2294
|
+
|
|
2295
|
+
return {
|
|
2296
|
+
newAmount: baseAmount + updatedShippingOptions[0].amount,
|
|
2297
|
+
shippingOptions: updatedShippingOptions
|
|
2298
|
+
};
|
|
2299
|
+
}
|
|
2300
|
+
|
|
2301
|
+
async function updateTotal(optionData) {
|
|
2302
|
+
// Your total calculation logic
|
|
2303
|
+
const baseAmount = 100;
|
|
2304
|
+
const shippingAmount = optionData.amount || optionData.data?.amount;
|
|
2305
|
+
return {
|
|
2306
|
+
newAmount: baseAmount + shippingAmount
|
|
2307
|
+
};
|
|
2308
|
+
}
|
|
2309
|
+
|
|
2310
|
+
function processPayment(ottToken) {
|
|
2311
|
+
// Send OTT token to your backend for payment processing
|
|
2312
|
+
fetch('/api/process-payment', {
|
|
2313
|
+
method: 'POST',
|
|
2314
|
+
headers: { 'Content-Type': 'application/json' },
|
|
2315
|
+
body: JSON.stringify({ ott_token: ottToken })
|
|
2316
|
+
});
|
|
2317
|
+
}
|
|
2318
|
+
</script>
|
|
2319
|
+
</html>
|
|
2320
|
+
```
|
|
2321
|
+
|
|
2322
|
+
### Apple Pay with Shipping
|
|
2323
|
+
|
|
2324
|
+
For Apple Pay with shipping enabled:
|
|
2325
|
+
```javascript
|
|
2326
|
+
let button = new paydock.ApplePayOpenWalletButton(
|
|
2327
|
+
"#widget",
|
|
2328
|
+
publicKeyOrAccessToken,
|
|
2329
|
+
serviceId,
|
|
2330
|
+
{
|
|
2331
|
+
amount: 100,
|
|
2332
|
+
currency: "AUD",
|
|
2333
|
+
country: "AU",
|
|
2334
|
+
amount_label: "TOTAL",
|
|
2335
|
+
store_name: "My Store",
|
|
2336
|
+
request_shipping: true,
|
|
2337
|
+
shipping_editing_mode: 'available',
|
|
2338
|
+
required_shipping_contact_fields: [
|
|
2339
|
+
'postalAddress',
|
|
2340
|
+
'name',
|
|
2341
|
+
'phone',
|
|
2342
|
+
'email',
|
|
2343
|
+
],
|
|
2344
|
+
shipping_options: [
|
|
2345
|
+
{
|
|
2346
|
+
id: "standard",
|
|
2347
|
+
label: "Standard Shipping",
|
|
2348
|
+
detail: "5-7 business days",
|
|
2349
|
+
amount: 5.00
|
|
2350
|
+
},
|
|
2351
|
+
{
|
|
2352
|
+
id: "express",
|
|
2353
|
+
label: "Express Shipping",
|
|
2354
|
+
detail: "1-2 business days",
|
|
2355
|
+
amount: 15.00
|
|
2356
|
+
}
|
|
2357
|
+
],
|
|
2358
|
+
apple_pay_capabilities: ['credentials_available', 'credentials_status_unknown', 'credentials_unavailable']
|
|
2359
|
+
}
|
|
2360
|
+
);
|
|
2361
|
+
button.load();
|
|
2362
|
+
```
|
|
2363
|
+
|
|
2364
|
+
When supporting shipping, the methods `onShippingAddressChange` and `onShippingOptionsChange` are required to update the shipping address and options.
|
|
2365
|
+
|
|
2366
|
+
```javascript
|
|
2367
|
+
button.onShippingAddressChange(async function(data) {
|
|
2368
|
+
console.log("Shipping address has been updated", data);
|
|
2369
|
+
// Call your backend to recalculate shipping
|
|
2370
|
+
return {
|
|
2371
|
+
amount: newAmount,
|
|
2372
|
+
shipping_options: updatedShippingOptions
|
|
2373
|
+
};
|
|
2374
|
+
});
|
|
2375
|
+
|
|
2376
|
+
button.onShippingOptionsChange(async function(data) {
|
|
2377
|
+
console.log("Shipping option selected", data);
|
|
2378
|
+
// Update total based on selected shipping option
|
|
2379
|
+
return {
|
|
2380
|
+
amount: newTotalAmount
|
|
2381
|
+
};
|
|
2382
|
+
});
|
|
2383
|
+
```
|
|
2384
|
+
|
|
2385
|
+
### Supported Shipping Cases
|
|
2386
|
+
|
|
2387
|
+
#### Injected Shipping Address, non-editable by the customer
|
|
2388
|
+
|
|
2389
|
+
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.
|
|
2390
|
+
|
|
2391
|
+
The required meta parameters for this case are:
|
|
2392
|
+
- shipping_editing_mode: 'store_pickup'
|
|
2393
|
+
- required_shipping_contact_fields: ['postalAddress'] <-- At least one of the fields is required so the shipping address is shown at Apple Pay.
|
|
2394
|
+
|
|
2395
|
+
```javascript
|
|
2396
|
+
meta: {
|
|
2397
|
+
apple_pay_capabilities: ['credentials_available', 'credentials_status_unknown', 'credentials_unavailable'],
|
|
2398
|
+
amount_label: 'TOTAL',
|
|
2399
|
+
country: 'AU',
|
|
2400
|
+
currency: 'AUD',
|
|
2401
|
+
amount: 10,
|
|
2402
|
+
shipping_editing_mode: 'store_pickup',
|
|
2403
|
+
required_shipping_contact_fields: [
|
|
2404
|
+
'postalAddress',
|
|
2405
|
+
'name',
|
|
2406
|
+
'phone',
|
|
2407
|
+
'email',
|
|
2408
|
+
],
|
|
2409
|
+
shipping: {
|
|
2410
|
+
amount: 5,
|
|
2411
|
+
address_line1: "Address Line 1",
|
|
2412
|
+
address_city: "Test Locality",
|
|
2413
|
+
address_state: "NSW",
|
|
2414
|
+
address_country: "Australia",
|
|
2415
|
+
address_country_code: "AU",
|
|
2416
|
+
address_postcode: "3000",
|
|
2417
|
+
contact: {
|
|
2418
|
+
phone: "+61400245562",
|
|
2419
|
+
email: "test@example.com",
|
|
2420
|
+
first_name: "QA",
|
|
2421
|
+
last_name: "QA",
|
|
2422
|
+
},
|
|
2423
|
+
options: [
|
|
2424
|
+
{
|
|
2425
|
+
label: "Test 1",
|
|
2426
|
+
detail: "This is a test 1 shipping methods",
|
|
2427
|
+
amount: 10,
|
|
2428
|
+
id: "randomId1",
|
|
2429
|
+
}
|
|
2430
|
+
],
|
|
2431
|
+
},
|
|
2432
|
+
}
|
|
2433
|
+
```
|
|
2434
|
+
|
|
2435
|
+
#### Injected Shipping Address, editable by the customer
|
|
2436
|
+
|
|
2437
|
+
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.
|
|
2438
|
+
|
|
2439
|
+
The required meta parameters for this case are:
|
|
2440
|
+
- shipping_editing_mode: 'available'
|
|
2441
|
+
- required_shipping_contact_fields: ['postalAddress'] <-- At least one of the fields is required so the shipping address is shown at Apple Pay.
|
|
2442
|
+
|
|
2443
|
+
```javascript
|
|
2444
|
+
meta: {
|
|
2445
|
+
apple_pay_capabilities: ['credentials_available', 'credentials_status_unknown', 'credentials_unavailable'],
|
|
2446
|
+
amount_label: 'TOTAL',
|
|
2447
|
+
country: 'AU',
|
|
2448
|
+
currency: 'AUD',
|
|
2449
|
+
amount: 10,
|
|
2450
|
+
shipping_editing_mode: 'available',
|
|
2451
|
+
required_shipping_contact_fields: [
|
|
2452
|
+
'postalAddress',
|
|
2453
|
+
'name',
|
|
2454
|
+
'phone',
|
|
2455
|
+
'email',
|
|
2456
|
+
],
|
|
2457
|
+
shipping: {
|
|
2458
|
+
amount: 5,
|
|
2459
|
+
address_line1: "Address Line 1",
|
|
2460
|
+
address_city: "Test Locality",
|
|
2461
|
+
address_state: "NSW",
|
|
2462
|
+
address_country: "Australia",
|
|
2463
|
+
address_country_code: "AU",
|
|
2464
|
+
address_postcode: "3000",
|
|
2465
|
+
contact: {
|
|
2466
|
+
phone: "+61400245562",
|
|
2467
|
+
email: "test@example.com",
|
|
2468
|
+
first_name: "QA",
|
|
2469
|
+
last_name: "QA",
|
|
2470
|
+
},
|
|
2471
|
+
options: [
|
|
2472
|
+
{
|
|
2473
|
+
label: "Test 1",
|
|
2474
|
+
detail: "This is a test 1 shipping methods",
|
|
2475
|
+
amount: 10,
|
|
2476
|
+
id: "randomId1",
|
|
2477
|
+
}
|
|
2478
|
+
],
|
|
2479
|
+
},
|
|
2480
|
+
}
|
|
2481
|
+
```
|
|
2482
|
+
|
|
2483
|
+
#### Shipping address editable by the customer (no pre-filled address)
|
|
2484
|
+
|
|
2485
|
+
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.
|
|
2486
|
+
|
|
2487
|
+
The required meta parameters for this case are:
|
|
2488
|
+
- shipping_editing_mode: 'available'
|
|
2489
|
+
- required_shipping_contact_fields: ['postalAddress'] <-- At least one of the fields is required so the shipping address is shown at Apple Pay.
|
|
2490
|
+
|
|
2491
|
+
```javascript
|
|
2492
|
+
meta: {
|
|
2493
|
+
apple_pay_capabilities: ['credentials_available', 'credentials_status_unknown', 'credentials_unavailable'],
|
|
2494
|
+
amount_label: 'TOTAL',
|
|
2495
|
+
country: 'AU',
|
|
2496
|
+
currency: 'AUD',
|
|
2497
|
+
amount: 10,
|
|
2498
|
+
shipping_editing_mode: 'available',
|
|
2499
|
+
required_shipping_contact_fields: [
|
|
2500
|
+
'postalAddress',
|
|
2501
|
+
'name',
|
|
2502
|
+
'phone',
|
|
2503
|
+
'email',
|
|
2504
|
+
],
|
|
2505
|
+
}
|
|
2506
|
+
```
|
|
2507
|
+
|
|
2508
|
+
#### No shipping address
|
|
2509
|
+
|
|
2510
|
+
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.
|
|
2511
|
+
|
|
2512
|
+
**Important:**
|
|
2513
|
+
- No shipping address should be provided in the meta object.
|
|
2514
|
+
- Shipping address could be provided in the initial POST `/v1/charges/wallet` endpoint, if collected previously.
|
|
2515
|
+
|
|
2516
|
+
The required meta parameters for this case are:
|
|
2517
|
+
- `required_shipping_contact_fields`: Only include contact fields if needed (phone, email), but NOT `postalAddress`.
|
|
2518
|
+
|
|
2519
|
+
```javascript
|
|
2520
|
+
meta: {
|
|
2521
|
+
amount_label: "TOTAL",
|
|
2522
|
+
country: "AU",
|
|
2523
|
+
currency: "AUD",
|
|
2524
|
+
amount: 10,
|
|
2525
|
+
shipping_editing_mode: "available",
|
|
2526
|
+
required_shipping_contact_fields: ["phone", "email"],
|
|
2527
|
+
apple_pay_capabilities: ["credentials_available", "credentials_status_unknown", "credentials_unavailable"]
|
|
2528
|
+
}
|
|
2529
|
+
```
|
|
2530
|
+
|
|
2531
|
+
## Google Pay Open Wallet Button
|
|
2532
|
+
|
|
2533
|
+
### Initialization
|
|
2534
|
+
|
|
2535
|
+
```javascript
|
|
2536
|
+
let button = new paydock.GooglePayOpenWalletButton(
|
|
2537
|
+
"#widget",
|
|
2538
|
+
publicKeyOrAccessToken,
|
|
2539
|
+
serviceId,
|
|
2540
|
+
{
|
|
2541
|
+
amount: 100,
|
|
2542
|
+
currency: "AUD",
|
|
2543
|
+
country: "AU",
|
|
2544
|
+
merchant_name: "Your Store",
|
|
2545
|
+
}
|
|
2546
|
+
);
|
|
2547
|
+
button.load();
|
|
2548
|
+
```
|
|
2549
|
+
|
|
2550
|
+
```javascript
|
|
2551
|
+
// ES2015 | TypeScript
|
|
2552
|
+
import { GooglePayOpenWalletButton } from '@paydock/client-sdk';
|
|
2553
|
+
|
|
2554
|
+
var button = new GooglePayOpenWalletButton(
|
|
2555
|
+
'#widget',
|
|
2556
|
+
publicKeyOrAccessToken,
|
|
2557
|
+
serviceId,
|
|
2558
|
+
{
|
|
2559
|
+
amount: 100,
|
|
2560
|
+
currency: 'AUD',
|
|
2561
|
+
country: 'AU',
|
|
2562
|
+
merchant_name: 'Your Store',
|
|
2563
|
+
}
|
|
2564
|
+
);
|
|
2565
|
+
button.load();
|
|
2566
|
+
```
|
|
2567
|
+
|
|
2568
|
+
### Constructor Parameters
|
|
2569
|
+
|
|
2570
|
+
The GooglePayOpenWalletButton constructor accepts the following parameters:
|
|
2571
|
+
|
|
2572
|
+
1. **selector** (string): CSS selector for the container element
|
|
2573
|
+
2. **publicKeyOrAccessToken** (string): Your PayDock public key or access token
|
|
2574
|
+
3. **serviceId** (string): The Google Pay service ID configured in PayDock dashboard
|
|
2575
|
+
4. **meta** (GooglePayOpenWalletMeta): Google Pay-specific configuration object
|
|
2576
|
+
|
|
2577
|
+
> **Note:** Required meta fields (`amount`, `currency`, `country`) are validated automatically by the `GooglePayOpenWalletButton` class. You do not need to specify them manually.
|
|
2578
|
+
|
|
2579
|
+
### Full Google Pay Example
|
|
2580
|
+
|
|
2581
|
+
```html
|
|
2582
|
+
<!DOCTYPE html>
|
|
2583
|
+
<html lang="en">
|
|
2584
|
+
<head>
|
|
2585
|
+
<meta charset="UTF-8">
|
|
2586
|
+
<title>Google Pay with Open Wallets</title>
|
|
2587
|
+
</head>
|
|
2588
|
+
<body>
|
|
2589
|
+
<h2>Payment using PayDock Google Pay Open Wallet Button!</h2>
|
|
2590
|
+
<div id="widget"></div>
|
|
2591
|
+
</body>
|
|
2592
|
+
<script src="https://widget.paydock.com/sdk/latest/widget.umd.min.js" ></script>
|
|
2593
|
+
<script>
|
|
2594
|
+
let button = new paydock.GooglePayOpenWalletButton(
|
|
2595
|
+
"#widget",
|
|
2596
|
+
publicKeyOrAccessToken,
|
|
2597
|
+
serviceId,
|
|
2598
|
+
{
|
|
2599
|
+
amount: 100,
|
|
2600
|
+
currency: "AUD",
|
|
2601
|
+
country: "AU",
|
|
2602
|
+
amount_label: "Total",
|
|
2603
|
+
request_shipping: true,
|
|
2604
|
+
show_billing_address: true,
|
|
2605
|
+
merchant_name: 'Test Merchant',
|
|
2606
|
+
style: {
|
|
2607
|
+
button_type: 'buy',
|
|
2608
|
+
button_color: 'default',
|
|
2609
|
+
button_size_mode: 'fill'
|
|
2610
|
+
},
|
|
2611
|
+
shipping_options: [
|
|
2612
|
+
{
|
|
2613
|
+
id: "standard",
|
|
2614
|
+
label: "Standard Shipping",
|
|
2615
|
+
detail: "Arrives in 5 to 7 days",
|
|
2616
|
+
amount: 5.00,
|
|
2617
|
+
type: "ELECTRONIC"
|
|
2618
|
+
},
|
|
2619
|
+
{
|
|
2620
|
+
id: "express",
|
|
2621
|
+
label: "Express Shipping",
|
|
2622
|
+
detail: "Arrives in 1 to 2 days",
|
|
2623
|
+
amount: 15.00,
|
|
2624
|
+
type: "PICKUP"
|
|
2625
|
+
}
|
|
2626
|
+
]
|
|
2627
|
+
}
|
|
2628
|
+
);
|
|
2629
|
+
|
|
2630
|
+
button.setEnv('sandbox');
|
|
2631
|
+
|
|
2632
|
+
// Required handlers
|
|
2633
|
+
button.onSuccess((data) => {
|
|
2634
|
+
console.log("Payment successful:", data);
|
|
2635
|
+
processPayment(data.token);
|
|
2636
|
+
});
|
|
2637
|
+
|
|
2638
|
+
button.onShippingAddressChange(async (addressData) => {
|
|
2639
|
+
const response = await updateShippingCosts(addressData);
|
|
2640
|
+
return {
|
|
2641
|
+
amount: response.newAmount,
|
|
2642
|
+
shipping_options: response.shippingOptions
|
|
2643
|
+
};
|
|
2644
|
+
});
|
|
2645
|
+
|
|
2646
|
+
button.onShippingOptionsChange(async (optionData) => {
|
|
2647
|
+
const response = await updateTotal(optionData);
|
|
2648
|
+
return {
|
|
2649
|
+
amount: response.newAmount
|
|
2650
|
+
};
|
|
2651
|
+
});
|
|
2652
|
+
|
|
2653
|
+
// Optional handlers
|
|
2654
|
+
button.onUnavailable((data) => {
|
|
2655
|
+
console.log("Google Pay not available:", data);
|
|
2656
|
+
// Show alternative payment methods
|
|
2657
|
+
});
|
|
2658
|
+
|
|
2659
|
+
button.onError((data) => {
|
|
2660
|
+
console.error("Payment error:", data);
|
|
2661
|
+
// Handle error appropriately
|
|
2662
|
+
});
|
|
2663
|
+
|
|
2664
|
+
button.onCancel((data) => {
|
|
2665
|
+
console.log("Payment cancelled");
|
|
2666
|
+
// Handle cancellation
|
|
2667
|
+
});
|
|
2668
|
+
|
|
2669
|
+
button.onClick((data) => {
|
|
2670
|
+
console.log("Google Pay button clicked");
|
|
2671
|
+
// Perform pre-payment validation
|
|
2672
|
+
});
|
|
2673
|
+
|
|
2674
|
+
button.load();
|
|
2675
|
+
|
|
2676
|
+
// Helper functions
|
|
2677
|
+
async function updateShippingCosts(addressData) {
|
|
2678
|
+
const baseAmount = 100;
|
|
2679
|
+
const updatedShippingOptions = [
|
|
2680
|
+
{
|
|
2681
|
+
id: "updated-standard",
|
|
2682
|
+
label: "Updated Standard Shipping",
|
|
2683
|
+
detail: "Based on your location",
|
|
2684
|
+
amount: 8.00,
|
|
2685
|
+
type: "ELECTRONIC"
|
|
2686
|
+
},
|
|
2687
|
+
{
|
|
2688
|
+
id: "updated-express",
|
|
2689
|
+
label: "Updated Express Shipping",
|
|
2690
|
+
detail: "Fast delivery to your area",
|
|
2691
|
+
amount: 18.00,
|
|
2692
|
+
type: "PICKUP"
|
|
2693
|
+
}
|
|
2694
|
+
];
|
|
2695
|
+
|
|
2696
|
+
return {
|
|
2697
|
+
newAmount: baseAmount + updatedShippingOptions[0].amount,
|
|
2698
|
+
shippingOptions: updatedShippingOptions
|
|
2699
|
+
};
|
|
2700
|
+
}
|
|
2701
|
+
|
|
2702
|
+
async function updateTotal(optionData) {
|
|
2703
|
+
const baseAmount = 100;
|
|
2704
|
+
const shippingAmount = optionData.amount || optionData.data?.amount;
|
|
2705
|
+
return {
|
|
2706
|
+
newAmount: baseAmount + shippingAmount
|
|
2707
|
+
};
|
|
2708
|
+
}
|
|
2709
|
+
|
|
2710
|
+
function processPayment(ottToken) {
|
|
2711
|
+
fetch('/api/process-payment', {
|
|
2712
|
+
method: 'POST',
|
|
2713
|
+
headers: { 'Content-Type': 'application/json' },
|
|
2714
|
+
body: JSON.stringify({ ott_token: ottToken })
|
|
2715
|
+
});
|
|
2716
|
+
}
|
|
2717
|
+
</script>
|
|
2718
|
+
</html>
|
|
2719
|
+
```
|
|
2720
|
+
|
|
2721
|
+
## Common API
|
|
2722
|
+
|
|
2723
|
+
Both `ApplePayOpenWalletButton` and `GooglePayOpenWalletButton` share the same event handler API inherited from the base class.
|
|
2724
|
+
|
|
2725
|
+
### Checking for button availability
|
|
2726
|
+
|
|
2727
|
+
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.
|
|
2728
|
+
|
|
2729
|
+
```javascript
|
|
2730
|
+
button.onUnavailable((data) => console.log("No wallet button available", data));
|
|
2731
|
+
```
|
|
2732
|
+
|
|
2733
|
+
### Service type validation
|
|
2734
|
+
|
|
2735
|
+
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`:
|
|
2736
|
+
|
|
2737
|
+
```javascript
|
|
2738
|
+
// This will raise an error if the service ID does not correspond to a Google Pay service
|
|
2739
|
+
let button = new paydock.GooglePayOpenWalletButton(
|
|
2740
|
+
"#widget",
|
|
2741
|
+
publicKeyOrAccessToken,
|
|
2742
|
+
applePayServiceId, // Wrong! This is an Apple Pay service ID
|
|
2743
|
+
meta
|
|
2744
|
+
);
|
|
2745
|
+
|
|
2746
|
+
button.onError((data) => {
|
|
2747
|
+
// Error: Service configuration type 'ApplePay' does not match expected wallet type 'google'.
|
|
2748
|
+
console.error(data.error.message);
|
|
2749
|
+
});
|
|
2750
|
+
|
|
2751
|
+
button.load();
|
|
2752
|
+
```
|
|
2753
|
+
|
|
2754
|
+
### Performing actions when the wallet button is clicked
|
|
2755
|
+
|
|
2756
|
+
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.
|
|
2757
|
+
|
|
2758
|
+
```javascript
|
|
2759
|
+
// Synchronous example
|
|
2760
|
+
button.onClick((data) => {
|
|
2761
|
+
console.log("Perform actions on button click");
|
|
2762
|
+
// Perform validation logic
|
|
2763
|
+
// Optionally use attachResult to control flow
|
|
2764
|
+
data.attachResult(true); // Continue with payment
|
|
2765
|
+
// data.attachResult(false); // Halt payment
|
|
2766
|
+
});
|
|
2767
|
+
|
|
2768
|
+
// Asynchronous example
|
|
2769
|
+
button.onClick((data) => {
|
|
2770
|
+
// Attach a Promise to control the wallet flow
|
|
2771
|
+
data.attachResult(
|
|
2772
|
+
fetch('/api/validate-order')
|
|
2773
|
+
.then(response => response.json())
|
|
2774
|
+
.then(result => {
|
|
2775
|
+
if (!result.valid) {
|
|
2776
|
+
throw new Error('Order validation failed');
|
|
2777
|
+
}
|
|
2778
|
+
return result;
|
|
2779
|
+
})
|
|
2780
|
+
);
|
|
2781
|
+
});
|
|
2782
|
+
```
|
|
2783
|
+
|
|
2784
|
+
### Handling successful OTT creation
|
|
2785
|
+
|
|
2786
|
+
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.
|
|
2787
|
+
|
|
2788
|
+
```javascript
|
|
2789
|
+
button.onSuccess((data) => {
|
|
2790
|
+
console.log("OTT created successfully:", data.token);
|
|
2791
|
+
console.log("Amount:", data.amount);
|
|
2792
|
+
console.log("Shipping:", data.shipping);
|
|
2793
|
+
console.log("Billing:", data.billing);
|
|
2794
|
+
|
|
2795
|
+
// Use the OTT token to complete payment on your backend
|
|
2796
|
+
fetch('/api/process-payment', {
|
|
2797
|
+
method: 'POST',
|
|
2798
|
+
headers: { 'Content-Type': 'application/json' },
|
|
2799
|
+
body: JSON.stringify({ ott_token: data.token })
|
|
2800
|
+
});
|
|
2801
|
+
});
|
|
2802
|
+
```
|
|
2803
|
+
|
|
2804
|
+
**Important**: The `onSuccess` event handler is mandatory. Not providing one will result in an error.
|
|
2805
|
+
|
|
2806
|
+
### Updating meta after initialization
|
|
2807
|
+
|
|
2808
|
+
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:
|
|
2809
|
+
|
|
2810
|
+
```javascript
|
|
2811
|
+
// For Apple Pay - accepts ApplePayOpenWalletMeta
|
|
2812
|
+
applePayButton.setMeta({ ...meta, amount: 29.99, amount_label: 'NEW TOTAL' });
|
|
2813
|
+
|
|
2814
|
+
// For Google Pay - accepts GooglePayOpenWalletMeta
|
|
2815
|
+
googlePayButton.setMeta({ ...meta, amount: 29.99, merchant_name: 'Updated Store' });
|
|
2816
|
+
```
|
|
2817
|
+
|
|
2818
|
+
### Handling errors
|
|
2819
|
+
|
|
2820
|
+
Register a callback function to handle errors that occur during wallet operations, including service type mismatches.
|
|
2821
|
+
|
|
2822
|
+
```javascript
|
|
2823
|
+
button.onError((data) => {
|
|
2824
|
+
console.error("Open Wallet error:", data.error);
|
|
2825
|
+
console.log("Error context:", data.context);
|
|
2826
|
+
|
|
2827
|
+
// Show user-friendly error message
|
|
2828
|
+
showErrorMessage("Payment initialization failed. Please try again.");
|
|
2829
|
+
});
|
|
2830
|
+
```
|
|
2831
|
+
|
|
2832
|
+
### Handling checkout cancellation
|
|
2833
|
+
|
|
2834
|
+
When the user cancels or closes the wallet payment interface, you can perform cleanup operations.
|
|
2835
|
+
|
|
2836
|
+
```javascript
|
|
2837
|
+
button.onCancel((data) => {
|
|
2838
|
+
console.log("Wallet checkout cancelled", data);
|
|
2839
|
+
|
|
2840
|
+
// Perform cleanup or redirect user
|
|
2841
|
+
window.location.href = '/checkout';
|
|
2842
|
+
});
|
|
2843
|
+
```
|
|
2844
|
+
|
|
2845
|
+
### Cleaning up
|
|
2846
|
+
|
|
2847
|
+
Remove the wallet button from the DOM when it is no longer needed:
|
|
2848
|
+
|
|
2849
|
+
```javascript
|
|
2850
|
+
button.destroy();
|
|
2851
|
+
```
|
|
2852
|
+
|
|
2853
|
+
### Events
|
|
2854
|
+
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.
|
|
2855
|
+
|
|
2856
|
+
**Available Event Handler Methods:**
|
|
2857
|
+
- `onClick(handler)` - Button click events (supports attachResult for flow control)
|
|
2858
|
+
- `onSuccess(handler)` - **Required** - OTT creation success events
|
|
2859
|
+
- `onUnavailable(handler)` - Wallet unavailable events (supports Promise pattern)
|
|
2860
|
+
- `onError(handler)` - Error events (supports Promise pattern)
|
|
2861
|
+
- `onCancel(handler)` - Checkout cancellation events (supports Promise pattern)
|
|
2862
|
+
- `onLoaded(handler)` - Button loaded/rendered events
|
|
2863
|
+
- `onShippingAddressChange(handler)` - **Required for shipping** - Address change events
|
|
2864
|
+
- `onShippingOptionsChange(handler)` - **Required for shipping options** - Option change events
|
|
2865
|
+
|
|
2866
|
+
**Event Handler Patterns:**
|
|
2867
|
+
|
|
2868
|
+
```javascript
|
|
2869
|
+
// Required handlers (will throw error if not provided)
|
|
2870
|
+
button.onSuccess(handler); // Always required
|
|
2871
|
+
button.onShippingAddressChange(handler); // Required when shipping enabled
|
|
2872
|
+
button.onShippingOptionsChange(handler); // Required when shipping options provided
|
|
2873
|
+
|
|
2874
|
+
// Optional handlers with Promise support
|
|
2875
|
+
button.onUnavailable(handler); // or await button.onUnavailable()
|
|
2876
|
+
button.onError(handler); // or await button.onError()
|
|
2877
|
+
button.onCancel(handler); // or await button.onCancel()
|
|
2878
|
+
|
|
2879
|
+
// Click handler with flow control
|
|
2880
|
+
button.onClick(handler); // Use data.attachResult() for async operations
|
|
2881
|
+
|
|
2882
|
+
// Loaded handler
|
|
2883
|
+
button.onLoaded(handler); // Notified when button renders
|
|
2884
|
+
```
|
|
2885
|
+
|
|
2886
|
+
### Apple Pay-Specific Meta Properties
|
|
2887
|
+
|
|
2888
|
+
A full description of the [ApplePayOpenWalletMeta](#ApplePayOpenWalletMeta) properties:
|
|
2889
|
+
|
|
2890
|
+
**Required:**
|
|
2891
|
+
- `amount`: The payment amount (number)
|
|
2892
|
+
- `currency`: The currency code (string, e.g., "AUD")
|
|
2893
|
+
- `country`: The country code (string, e.g., "AU")
|
|
2894
|
+
- `amount_label`: Label for the total amount (string)
|
|
2895
|
+
- `store_name`: Merchant store name (string)
|
|
2896
|
+
|
|
2897
|
+
**Optional:**
|
|
2898
|
+
- `request_shipping?: boolean`: Enable shipping address collection
|
|
2899
|
+
- `shipping_options?: IApplePayShippingOption[]`: Array of shipping options
|
|
2900
|
+
- `show_billing_address?: boolean`: Show billing address fields
|
|
2901
|
+
- `apple_pay_capabilities?: string[]`: Device capabilities
|
|
2902
|
+
- `merchant_capabilities?: string[]`: Merchant capabilities
|
|
2903
|
+
- `supported_networks?: string[]`: Supported payment networks
|
|
2904
|
+
- `required_billing_contact_fields?: string[]`: Required billing contact fields
|
|
2905
|
+
- `required_shipping_contact_fields?: string[]`: Required shipping contact fields
|
|
2906
|
+
- `supported_countries?: string[]`: Supported countries
|
|
2907
|
+
- `shipping_editing_mode?: 'available' | 'store_pickup'`: Shipping address editing mode
|
|
2908
|
+
- `style?: { button_type?: ApplePayButtonType, button_style?: ApplePayButtonStyle }`: Button styling
|
|
2909
|
+
|
|
2910
|
+
### Google Pay-Specific Meta Properties
|
|
2911
|
+
|
|
2912
|
+
A full description of the [GooglePayOpenWalletMeta](#GooglePayOpenWalletMeta) properties:
|
|
2913
|
+
|
|
2914
|
+
**Required:**
|
|
2915
|
+
- `amount`: The payment amount (number)
|
|
2916
|
+
- `currency`: The currency code (string, e.g., "AUD")
|
|
2917
|
+
- `country`: The country code (string, e.g., "AU")
|
|
2918
|
+
|
|
2919
|
+
**Optional:**
|
|
2920
|
+
- `amount_label?: string`: Label for the total amount
|
|
2921
|
+
- `merchant_name?: string`: Display name for the merchant
|
|
2922
|
+
- `request_shipping?: boolean`: Enable shipping address collection
|
|
2923
|
+
- `shipping_options?: IGooglePayShippingOption[]`: Array of shipping options
|
|
2924
|
+
- `show_billing_address?: boolean`: Show billing address fields
|
|
2925
|
+
- `card_config?: GooglePayCardConfig`: Card configuration (auth methods, networks, tokenization)
|
|
2926
|
+
- `style?: { button_type?: GooglePayButtonType, button_color?: GooglePayButtonColor, button_size_mode?: GooglePayButtonSizeMode }`: Button styling
|
|
2927
|
+
|
|
2928
|
+
### Shipping Options Format
|
|
2929
|
+
```javascript
|
|
2930
|
+
shipping_options: [
|
|
2931
|
+
{
|
|
2932
|
+
id: "option_id", // Unique identifier (string)
|
|
2933
|
+
label: "Option Name", // Display name (string)
|
|
2934
|
+
detail: "Description", // Optional description (string)
|
|
2935
|
+
amount: 10.00, // Shipping cost as number
|
|
2936
|
+
date_components_range: { // Optional: delivery date range (Apple Pay only)
|
|
2937
|
+
start_date_components: {
|
|
2938
|
+
years: 0,
|
|
2939
|
+
months: 0,
|
|
2940
|
+
days: 5,
|
|
2941
|
+
hours: 0,
|
|
2942
|
+
},
|
|
2943
|
+
end_date_components: {
|
|
2944
|
+
years: 0,
|
|
2945
|
+
months: 0,
|
|
2946
|
+
days: 10,
|
|
2947
|
+
hours: 0,
|
|
2948
|
+
}
|
|
2949
|
+
}
|
|
2950
|
+
}
|
|
2951
|
+
]
|
|
2952
|
+
```
|
|
2953
|
+
|
|
2954
|
+
**Important**:
|
|
2955
|
+
- `amount` should be a **number**, not a string
|
|
2956
|
+
- `date_components_range` is optional but provides delivery estimates (Apple Pay only)
|
|
2957
|
+
- Updated shipping options returned from event handlers don't require `date_components_range`
|
|
2958
|
+
|
|
2959
|
+
### Environment Setup
|
|
2960
|
+
```javascript
|
|
2961
|
+
// Always set environment before loading
|
|
2962
|
+
button.setEnv('sandbox');
|
|
2963
|
+
button.load();
|
|
2964
|
+
```
|
|
2965
|
+
|
|
2966
|
+
### Error Handling Best Practices
|
|
2967
|
+
```javascript
|
|
2968
|
+
button.onError(function(data) {
|
|
2969
|
+
console.error('Full error object:', data);
|
|
2970
|
+
|
|
2971
|
+
// Check different error properties
|
|
2972
|
+
const errorMessage = data.error?.message ||
|
|
2973
|
+
data.message ||
|
|
2974
|
+
'Unknown error occurred';
|
|
2975
|
+
|
|
2976
|
+
// Handle different error types
|
|
2977
|
+
if (data.context?.operation === 'wallet_operation') {
|
|
2978
|
+
// Handle wallet-specific errors
|
|
2979
|
+
showWalletError(errorMessage);
|
|
2980
|
+
} else {
|
|
2981
|
+
// Handle general errors
|
|
2982
|
+
showGeneralError(errorMessage);
|
|
2983
|
+
}
|
|
2984
|
+
});
|
|
2985
|
+
```
|
|
2986
|
+
|
|
1314
2987
|
# Click To Pay
|
|
1315
2988
|
|
|
1316
2989
|
## Overview
|