├── .env.default
├── .github
└── stale.yml
├── .gitignore
├── CODE_OF_CONDUCT.md
├── LICENSE
├── Procfile
├── README.md
├── app.json
├── package.json
├── screenshot.png
├── server
├── node
│ ├── api
│ │ ├── clientKeys.js
│ │ ├── details.js
│ │ ├── originKeys.js
│ │ ├── paymentMethods.js
│ │ ├── payments.js
│ │ └── sessions.js
│ ├── index.js
│ └── utils
│ │ ├── config.js
│ │ ├── getPostParameters.js
│ │ └── handleCallback.js
└── php
│ ├── api
│ ├── clientKeys.php
│ ├── details.php
│ ├── originKeys.php
│ ├── paymentMethods.php
│ ├── payments.php
│ └── sessions.php
│ ├── index.php
│ └── start.sh
├── src
├── ach
│ ├── ach.js
│ └── index.html
├── bancontact
│ ├── bancontact.js
│ └── index.html
├── bcmc
│ ├── bcmc.js
│ └── index.html
├── boleto
│ ├── boleto.js
│ └── index.html
├── card
│ ├── card.js
│ └── index.html
├── customcard
│ ├── customCard.js
│ ├── customCards.config.js
│ ├── customcards.style.css
│ └── index.html
├── demo.css
├── demo.js
├── dropin
│ ├── dropin.js
│ └── index.html
├── favicon.ico
├── googlepay
│ ├── googlepay.js
│ └── index.html
├── ideal
│ ├── ideal.js
│ └── index.html
├── index.html
├── multibanco
│ ├── index.html
│ └── multibanco.js
├── sepa
│ ├── index.html
│ └── sepa.js
├── sessions
│ ├── dropin.js
│ └── index.html
├── swish
│ ├── index.html
│ └── swish.js
├── utils.js
└── wechatpay
│ ├── index.html
│ └── wechatpay.js
└── start.sh
/.env.default:
--------------------------------------------------------------------------------
1 | MERCHANT_ACCOUNT=
2 | CHECKOUT_APIKEY=
3 | CLIENT_KEY=
4 | API_VERSION=
5 |
--------------------------------------------------------------------------------
/.github/stale.yml:
--------------------------------------------------------------------------------
1 | # Configuration for probot-stale - https://github.com/probot/stale
2 |
3 | # Number of days of inactivity before an Issue or Pull Request becomes stale
4 | daysUntilStale: 60
5 |
6 | # Number of days of inactivity before an Issue or Pull Request with the stale label is closed.
7 | # Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale.
8 | daysUntilClose: 7
9 |
10 | # Only issues or pull requests with all of these labels are check if stale. Defaults to `[]` (disabled)
11 | # onlyLabels: []
12 |
13 | # Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable
14 | exemptLabels:
15 | - pinned
16 | - security
17 | - "[Status] Maybe Later"
18 |
19 | # Set to true to ignore issues in a project (defaults to false)
20 | # exemptProjects: false
21 |
22 | # Set to true to ignore issues in a milestone (defaults to false)
23 | # exemptMilestones: false
24 |
25 | # Set to true to ignore issues with an assignee (defaults to false)
26 | # exemptAssignees: false
27 |
28 | # Label to use when marking as stale
29 | staleLabel: wontfix
30 |
31 | # Comment to post when marking as stale. Set to `false` to disable
32 | markComment: >
33 | This issue has been automatically marked as stale because it has not had
34 | recent activity. It will be closed if no further activity occurs. Thank you
35 | for your contributions.
36 |
37 | # Comment to post when removing the stale label.
38 | # unmarkComment: >
39 | # Your comment here.
40 |
41 | # Comment to post when closing a stale Issue or Pull Request.
42 | # closeComment: >
43 | # Your comment here.
44 |
45 | # Limit the number of actions per hour, from 1-30. Default is 30
46 | limitPerRun: 30
47 |
48 | # Limit to only `issues` or `pulls`
49 | # only: issues
50 |
51 | # Optionally, specify configuration settings that are specific to just 'issues' or 'pulls':
52 | # pulls:
53 | # daysUntilStale: 30
54 | # markComment: >
55 | # This pull request has been automatically marked as stale because it has not had
56 | # recent activity. It will be closed if no further activity occurs. Thank you
57 | # for your contributions.
58 |
59 | # issues:
60 | # exemptLabels:
61 | # - confirmed
62 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /.idea
2 | .DS_Store
3 | .env
4 | *.log
5 | coverage
6 | logs
7 | node_modules/
8 | npm-debug.log*
9 | package-lock.json
10 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as
6 | contributors and maintainers pledge to making participation in our project and
7 | our community a harassment-free experience for everyone, regardless of age, body
8 | size, disability, ethnicity, sex characteristics, gender identity and expression,
9 | level of experience, education, socio-economic status, nationality, personal
10 | appearance, race, religion, or sexual identity and orientation.
11 |
12 | ## Our Standards
13 |
14 | Examples of behavior that contributes to creating a positive environment
15 | include:
16 |
17 | * Using welcoming and inclusive language
18 | * Being respectful of differing viewpoints and experiences
19 | * Gracefully accepting constructive criticism
20 | * Focusing on what is best for the community
21 | * Showing empathy towards other community members
22 |
23 | Examples of unacceptable behavior by participants include:
24 |
25 | * The use of sexualized language or imagery and unwelcome sexual attention or
26 | advances
27 | * Trolling, insulting/derogatory comments, and personal or political attacks
28 | * Public or private harassment
29 | * Publishing others' private information, such as a physical or electronic
30 | address, without explicit permission
31 | * Other conduct which could reasonably be considered inappropriate in a
32 | professional setting
33 |
34 | ## Our Responsibilities
35 |
36 | Project maintainers are responsible for clarifying the standards of acceptable
37 | behavior and are expected to take appropriate and fair corrective action in
38 | response to any instances of unacceptable behavior.
39 |
40 | Project maintainers have the right and responsibility to remove, edit, or
41 | reject comments, commits, code, wiki edits, issues, and other contributions
42 | that are not aligned to this Code of Conduct, or to ban temporarily or
43 | permanently any contributor for other behaviors that they deem inappropriate,
44 | threatening, offensive, or harmful.
45 |
46 | ## Scope
47 |
48 | This Code of Conduct applies both within project spaces and in public spaces
49 | when an individual is representing the project or its community. Examples of
50 | representing a project or community include using an official project e-mail
51 | address, posting via an official social media account, or acting as an appointed
52 | representative at an online or offline event. Representation of a project may be
53 | further defined and clarified by project maintainers.
54 |
55 | ## Enforcement
56 |
57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
58 | reported by contacting the project team at support@adyen.com. All
59 | complaints will be reviewed and investigated and will result in a response that
60 | is deemed necessary and appropriate to the circumstances. The project team is
61 | obligated to maintain confidentiality with regard to the reporter of an incident.
62 | Further details of specific enforcement policies may be posted separately.
63 |
64 | Project maintainers who do not follow or enforce the Code of Conduct in good
65 | faith may face temporary or permanent repercussions as determined by other
66 | members of the project's leadership.
67 |
68 | ## Attribution
69 |
70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
72 |
73 | [homepage]: https://www.contributor-covenant.org
74 |
75 | For answers to common questions about this code of conduct, see
76 | https://www.contributor-covenant.org/faq
77 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License
2 |
3 | Copyright (c) Adyen B.V. (https://www.adyen.com)
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Procfile:
--------------------------------------------------------------------------------
1 | web: node server/node
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Adyen Web sample code
2 |
3 | 
4 |
5 | > ⚠️ **This repository is for demo purposes only**
6 |
7 | ## Requirements
8 |
9 | To run this project, **create** a `.env` file on your project's root folder following the example on `.env.default`.
10 |
11 | ```
12 | MERCHANT_ACCOUNT=MyMerchantAccount
13 | CHECKOUT_APIKEY=MY_CHECKOUT_API_KEY
14 | CLIENT_KEY=MY_CLIENT_KEY
15 | ```
16 |
17 | These variables can be found in Adyen Customer Area. For more information, visit our [Get started with Adyen guide](https://docs.adyen.com/get-started-with-adyen#page-introduction).
18 |
19 | If the forms don't seem to load, please check if you have:
20 |
21 | 1. Used the correct `clientKey`
22 | 2. Configured the `origin` on the Customer Area as an allowed origin
23 |
24 | ## Installation
25 |
26 | ### Running the PHP Server
27 |
28 | Navigate to the root of the project and run the `start.sh` script:
29 |
30 | ```
31 | $ cd adyen-components-js-sample-code
32 | $ ./start.sh
33 | ```
34 |
35 | A PHP server will start on `http://localhost:3000`.
36 |
37 | ### Running the Node.js Server
38 |
39 | If preferred, you can run a Node.js server instead.
40 | To do this, navigate to the root of the project, install the dependencies (only the first time) and run the start script:
41 |
42 | ```
43 | $ cd adyen-components-js-sample-code
44 | $ npm i
45 | $ npm start
46 | ```
47 |
48 | A Node.js server will start on `http://localhost:3000`.
49 |
50 | ### Deploying this example to Heroku
51 |
52 | Alternatively, you can install this example by using this shortcut to deploy to Heroku:
53 |
54 | [](https://heroku.com/deploy?template=https://github.com/Adyen/adyen-components-js-sample-code)
55 |
56 | After deploying, to use Sessions Drop-in, add your ```CLIENT_KEY``` to the config vars.
57 |
58 | ## Documentation
59 |
60 | For the complete integration guide, refer to the [Web Components documentation](https://docs.adyen.com/online-payments/web-components).
61 |
62 | ## Other sample projects
63 |
64 | Find other sample projects in our [example projects repositories](https://github.com/adyen-examples).
65 |
66 | ## License
67 |
68 | This repository is open source and available under the MIT license. For more information, see the LICENSE file.
69 |
--------------------------------------------------------------------------------
/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Adyen Components Sample Code",
3 | "description": "A php server example containing our Javascript SDK",
4 | "keywords": [
5 | "Adyen",
6 | "Checkout",
7 | "Components",
8 | "Dropin",
9 | "Web",
10 | "JavaScript",
11 | "payments"
12 | ],
13 | "website": "https://www.adyen.com/",
14 | "repository": "https://github.com/Adyen/adyen-components-js-sample-code",
15 | "env": {
16 | "MERCHANT_ACCOUNT": {
17 | "description": "Your merchant account"
18 | },
19 | "CHECKOUT_APIKEY": {
20 | "description": "Your Checkout API key"
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "checkout-components-sample-code",
3 | "version": "1.0.0",
4 | "description": "Adyen Components Sample Code",
5 | "main": "src/index.js",
6 | "scripts": {
7 | "start": "npm run devserver",
8 | "test": "echo \"Error: no test specified\" && exit 1",
9 | "devserver": "node ./server/node/index.js"
10 | },
11 | "repository": {
12 | "type": "git",
13 | "url": ""
14 | },
15 | "keywords": [
16 | "Adyen",
17 | "Demo",
18 | "Payments",
19 | "Checkout",
20 | "Components",
21 | "Dropin"
22 | ],
23 | "author": "Adyen",
24 | "license": "MIT",
25 | "engines": {
26 | "node": "~8.11.2",
27 | "npm": "~6.1.0"
28 | },
29 | "dependencies": {
30 | "dotenv": "^6.1.0",
31 | "express": "^4.16.4",
32 | "request": "^2.81.0"
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Adyen/adyen-components-js-sample-code/dd5a2925f714f636ebf80d2ea6224a62ce22b286/screenshot.png
--------------------------------------------------------------------------------
/server/node/api/clientKeys.js:
--------------------------------------------------------------------------------
1 | const { CLIENT_KEY: clientKey } = require('../utils/config');
2 | const handleCallback = require('../utils/handleCallback');
3 |
4 | module.exports = (res, request) => {
5 | handleCallback({ body: { clientKey } }, res);
6 | };
7 |
--------------------------------------------------------------------------------
/server/node/api/details.js:
--------------------------------------------------------------------------------
1 | const { post } = require('request');
2 | const getPostParameters = require('../utils/getPostParameters');
3 | const handleCallback = require('../utils/handleCallback');
4 |
5 | module.exports = (res, request) => {
6 | const params = getPostParameters('/payments/details', { ...request });
7 |
8 | post(params, (err, response, body) => handleCallback({ err, response, body }, res));
9 | };
10 |
--------------------------------------------------------------------------------
/server/node/api/originKeys.js:
--------------------------------------------------------------------------------
1 | const { post } = require('request');
2 | const { MERCHANT_ACCOUNT } = require('../utils/config');
3 | const getPostParameters = require('../utils/getPostParameters');
4 | const handleCallback = require('../utils/handleCallback');
5 |
6 | module.exports = (res, request) => {
7 | const originDomains = [`${request.protocol}://${request.headers.host}`];
8 | const params = getPostParameters('originKeys', { originDomains });
9 |
10 | post(params, (err, response, body) => handleCallback({ err, response, body }, res));
11 | };
12 |
--------------------------------------------------------------------------------
/server/node/api/paymentMethods.js:
--------------------------------------------------------------------------------
1 | const { post } = require('request');
2 | const getPostParameters = require('../utils/getPostParameters');
3 | const handleCallback = require('../utils/handleCallback');
4 |
5 | module.exports = (res, request) => {
6 | const params = getPostParameters('paymentMethods', request);
7 |
8 | post(params, (error, response, body) => handleCallback({ error, response, body }, res));
9 | };
10 |
--------------------------------------------------------------------------------
/server/node/api/payments.js:
--------------------------------------------------------------------------------
1 | const { post } = require('request');
2 | const getPostParameters = require('../utils/getPostParameters');
3 | const handleCallback = require('../utils/handleCallback');
4 |
5 | module.exports = (res, request) => {
6 | const params = getPostParameters('/payments', request);
7 |
8 | post(params, (err, response, body) => handleCallback({ err, response, body }, res));
9 | };
10 |
--------------------------------------------------------------------------------
/server/node/api/sessions.js:
--------------------------------------------------------------------------------
1 | const { post } = require('request');
2 | const getPostParameters = require('../utils/getPostParameters');
3 | const handleCallback = require('../utils/handleCallback');
4 |
5 | module.exports = (res, request) => {
6 | const params = getPostParameters('/sessions', request);
7 |
8 | post(params, (err, response, body) => handleCallback({ err, response, body }, res));
9 | };
10 |
--------------------------------------------------------------------------------
/server/node/index.js:
--------------------------------------------------------------------------------
1 | require('dotenv').config();
2 | const express = require('express');
3 | const app = express();
4 | const path = require('path');
5 | const getPaymentMethods = require('./api/paymentMethods');
6 | const getOriginKeys = require('./api/originKeys');
7 | const getClientKeys = require('./api/clientKeys');
8 | const makePayment = require('./api/payments');
9 | const postDetails = require('./api/details');
10 | const sessions = require('./api/sessions');
11 |
12 | module.exports = (() => {
13 | app.use(express.json());
14 | app.use(express.urlencoded({ extended: true }));
15 |
16 | app.use((req, res, next) => {
17 | res.header('Access-Control-Allow-Origin', '*');
18 | res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
19 | next();
20 | });
21 |
22 | app.use(express.static(path.resolve(__dirname, '../../src')));
23 |
24 | app.all('/originKeys', (req, res) => getOriginKeys(res, req));
25 | app.all('/paymentMethods', (req, res) => getPaymentMethods(res, req.body));
26 | app.all('/payments', (req, res) => makePayment(res, req.body));
27 | app.all('/details', (req, res) => postDetails(res, req.body));
28 | app.all('/sessions', (req, res) => sessions(res, req.body));
29 | app.all('/clientKeys', (req, res) => getClientKeys(res, req));
30 |
31 | const port = process.env.PORT || 3000;
32 | app.listen(port, () => console.log(`Listening on localhost:${port}`));
33 | })();
34 |
--------------------------------------------------------------------------------
/server/node/utils/config.js:
--------------------------------------------------------------------------------
1 | const { CHECKOUT_APIKEY, MERCHANT_ACCOUNT, CLIENT_KEY, API_VERSION } = process.env;
2 |
3 | const CHECKOUT_URL = `https://checkout-test.adyen.com/${API_VERSION}`;
4 |
5 | module.exports = {
6 | CHECKOUT_APIKEY,
7 | CHECKOUT_URL,
8 | MERCHANT_ACCOUNT,
9 | CLIENT_KEY
10 | };
11 |
--------------------------------------------------------------------------------
/server/node/utils/getPostParameters.js:
--------------------------------------------------------------------------------
1 | const { CHECKOUT_APIKEY, CHECKOUT_URL, MERCHANT_ACCOUNT } = require('./config');
2 |
3 | module.exports = (endpoint, request) => {
4 | const body = JSON.stringify({
5 | merchantAccount: MERCHANT_ACCOUNT,
6 | ...request
7 | });
8 |
9 | console.log('### getPostParameters::exports:: CHECKOUT_URL=', `${CHECKOUT_URL}/${endpoint}`);
10 |
11 | return {
12 | body,
13 | url: `${CHECKOUT_URL}/${endpoint}`,
14 | headers: {
15 | 'Access-Control-Allow-Origin': '*',
16 | 'Content-Type': 'application/json',
17 | 'Content-Length': Buffer.byteLength(body, 'utf8'),
18 | 'X-Api-Key': CHECKOUT_APIKEY
19 | }
20 | };
21 | };
22 |
--------------------------------------------------------------------------------
/server/node/utils/handleCallback.js:
--------------------------------------------------------------------------------
1 | module.exports = ({ error, response = {}, body }, res) => {
2 | if (error) {
3 | console.error(error);
4 | return res.send(error);
5 | }
6 |
7 | if (response.statusCode && response.statusMessage) {
8 | console.log(`Request to ${res.req.url} ended with status ${response.statusCode} - ${response.statusMessage}`);
9 | }
10 |
11 | res.send(body);
12 | };
13 |
--------------------------------------------------------------------------------
/server/php/api/clientKeys.php:
--------------------------------------------------------------------------------
1 | $clientKey
12 | ];
13 |
14 | $result = json_encode($data);
15 |
16 | return $result;
17 | }
18 |
--------------------------------------------------------------------------------
/server/php/api/details.php:
--------------------------------------------------------------------------------
1 | $merchantAccount
24 | ];
25 |
26 | // Convert data to JSON
27 | $json_data = json_encode(array_merge($data, $request));
28 |
29 | // Initiate curl
30 | $curlAPICall = curl_init();
31 |
32 | // Set to POST
33 | curl_setopt($curlAPICall, CURLOPT_CUSTOMREQUEST, "POST");
34 |
35 | // Will return the response, if false it print the response
36 | curl_setopt($curlAPICall, CURLOPT_RETURNTRANSFER, true);
37 |
38 | // Add JSON message
39 | curl_setopt($curlAPICall, CURLOPT_POSTFIELDS, $json_data);
40 |
41 | // Set the url
42 | curl_setopt($curlAPICall, CURLOPT_URL, $url);
43 |
44 | // Api key
45 | curl_setopt($curlAPICall, CURLOPT_HTTPHEADER,
46 | array(
47 | "X-Api-Key: " . $apikey,
48 | "Content-Type: application/json",
49 | "Content-Length: " . strlen($json_data)
50 | )
51 | );
52 |
53 | // Execute
54 | $result = curl_exec($curlAPICall);
55 |
56 | // Error Check
57 | if ($result === false){
58 | throw new Exception(curl_error($curlAPICall), curl_errno($curlAPICall));
59 | }
60 |
61 | // Closing
62 | curl_close($curlAPICall);
63 |
64 | // This file returns a JSON object
65 | return $result;
66 | }
67 |
--------------------------------------------------------------------------------
/server/php/api/originKeys.php:
--------------------------------------------------------------------------------
1 | [$protocol.$domain]
19 | ];
20 |
21 | // Convert data to JSON
22 | $json_data = json_encode($data);
23 |
24 | // Initiate curl
25 | $curlAPICall = curl_init();
26 |
27 | // Set to POST
28 | curl_setopt($curlAPICall, CURLOPT_CUSTOMREQUEST, "POST");
29 |
30 | // Will return the response, if false it print the response
31 | curl_setopt($curlAPICall, CURLOPT_RETURNTRANSFER, true);
32 |
33 | // Add JSON message
34 | curl_setopt($curlAPICall, CURLOPT_POSTFIELDS, $json_data);
35 |
36 | // Set the url
37 | curl_setopt($curlAPICall, CURLOPT_URL, $url);
38 |
39 | // Api key
40 | curl_setopt($curlAPICall, CURLOPT_HTTPHEADER,
41 | array(
42 | "X-Api-Key: " . $apikey,
43 | "Content-Type: application/json",
44 | "Content-Length: " . strlen($json_data)
45 | )
46 | );
47 |
48 | // Execute
49 | $result = curl_exec($curlAPICall);
50 |
51 | // Error Check
52 | if ($result === false){
53 | throw new Exception(curl_error($curlAPICall), curl_errno($curlAPICall));
54 | }
55 |
56 | // Closing
57 | curl_close($curlAPICall);
58 |
59 | // This file returns a JSON object
60 | return $result;
61 | }
62 |
--------------------------------------------------------------------------------
/server/php/api/paymentMethods.php:
--------------------------------------------------------------------------------
1 | $merchantAccount
25 | ];
26 |
27 | // Convert data to JSON
28 | $json_data = json_encode(array_merge($data, $request));
29 |
30 | // Initiate curl
31 | $curlAPICall = curl_init();
32 |
33 | // Set to POST
34 | curl_setopt($curlAPICall, CURLOPT_CUSTOMREQUEST, "POST");
35 |
36 | // Will return the response, if false it print the response
37 | curl_setopt($curlAPICall, CURLOPT_RETURNTRANSFER, true);
38 |
39 | // Add JSON message
40 | curl_setopt($curlAPICall, CURLOPT_POSTFIELDS, $json_data);
41 |
42 | // Set the url
43 | curl_setopt($curlAPICall, CURLOPT_URL, $url);
44 |
45 | // Api key
46 | curl_setopt($curlAPICall, CURLOPT_HTTPHEADER,
47 | array(
48 | "X-Api-Key: " . $apikey,
49 | "Content-Type: application/json",
50 | "Content-Length: " . strlen($json_data)
51 | )
52 | );
53 |
54 | // Execute
55 | $result = curl_exec($curlAPICall);
56 |
57 | // Error Check
58 | if ($result === false){
59 | throw new Exception(curl_error($curlAPICall), curl_errno($curlAPICall));
60 | }
61 |
62 | // Closing
63 | curl_close($curlAPICall);
64 |
65 | // This file returns a JSON object
66 | return $result;
67 | }
68 |
--------------------------------------------------------------------------------
/server/php/api/payments.php:
--------------------------------------------------------------------------------
1 | [
24 | 'currency' => 'EUR',
25 | 'value' => 1000
26 | ],
27 | 'reference' => 'Order Reference',
28 | 'returnUrl' => 'https://your-company.com/...',
29 | 'merchantAccount' => $merchantAccount
30 | ];
31 |
32 | // Convert data to JSON
33 | $json_data = json_encode(array_merge($data, $request));
34 |
35 | // Initiate curl
36 | $curlAPICall = curl_init();
37 |
38 | // Set to POST
39 | curl_setopt($curlAPICall, CURLOPT_CUSTOMREQUEST, "POST");
40 |
41 | // Will return the response, if false it print the response
42 | curl_setopt($curlAPICall, CURLOPT_RETURNTRANSFER, true);
43 |
44 | // Add JSON message
45 | curl_setopt($curlAPICall, CURLOPT_POSTFIELDS, $json_data);
46 |
47 | // Set the url
48 | curl_setopt($curlAPICall, CURLOPT_URL, $url);
49 |
50 | // Api key
51 | curl_setopt($curlAPICall, CURLOPT_HTTPHEADER,
52 | array(
53 | "X-Api-Key: " . $apikey,
54 | "Content-Type: application/json",
55 | "Content-Length: " . strlen($json_data)
56 | )
57 | );
58 |
59 | // Execute
60 | $result = curl_exec($curlAPICall);
61 |
62 | // Error Check
63 | if ($result === false){
64 | throw new Exception(curl_error($curlAPICall), curl_errno($curlAPICall));
65 | }
66 |
67 | // Closing
68 | curl_close($curlAPICall);
69 |
70 | // This file returns a JSON object
71 | return $result;
72 | }
73 |
--------------------------------------------------------------------------------
/server/php/api/sessions.php:
--------------------------------------------------------------------------------
1 | [
24 | 'currency' => 'EUR',
25 | 'value' => 1000
26 | ],
27 | 'reference' => 'Order Reference',
28 | 'returnUrl' => 'https://your-company.com/...',
29 | 'merchantAccount' => $merchantAccount
30 | ];
31 |
32 | // Convert data to JSON
33 | $json_data = json_encode(array_merge($data, $request));
34 |
35 | // Initiate curl
36 | $curlAPICall = curl_init();
37 |
38 | // Set to POST
39 | curl_setopt($curlAPICall, CURLOPT_CUSTOMREQUEST, "POST");
40 |
41 | // Will return the response, if false it print the response
42 | curl_setopt($curlAPICall, CURLOPT_RETURNTRANSFER, true);
43 |
44 | // Add JSON message
45 | curl_setopt($curlAPICall, CURLOPT_POSTFIELDS, $json_data);
46 |
47 | // Set the url
48 | curl_setopt($curlAPICall, CURLOPT_URL, $url);
49 |
50 | // Api key
51 | curl_setopt($curlAPICall, CURLOPT_HTTPHEADER,
52 | array(
53 | "X-Api-Key: " . $apikey,
54 | "Content-Type: application/json",
55 | "Content-Length: " . strlen($json_data)
56 | )
57 | );
58 |
59 | // Execute
60 | $result = curl_exec($curlAPICall);
61 |
62 | // Error Check
63 | if ($result === false){
64 | throw new Exception(curl_error($curlAPICall), curl_errno($curlAPICall));
65 | }
66 |
67 | // Closing
68 | curl_close($curlAPICall);
69 |
70 | // This file returns a JSON object
71 | return $result;
72 | }
73 |
--------------------------------------------------------------------------------
/server/php/index.php:
--------------------------------------------------------------------------------
1 | {
3 |
4 | // Optional, provide a translations object for labels and fields
5 | // const translations = {
6 | // "en-GB": {
7 | // "ach.bankAccount": "Bank account",
8 | // "ach.accountHolderNameField.title": "Account holder name",
9 | // "ach.accountHolderNameField.placeholder": "J. Smith",
10 | // }
11 | // };
12 |
13 | // 1. Create an instance of AdyenCheckout
14 | const checkout = await AdyenCheckout({
15 | locale: "en-GB",
16 | environment: 'test',
17 | // Optional, provide translations for labels and fields
18 | // https://docs.adyen.com/online-payments/web-components/localization-components
19 | // translations: translations,
20 | clientKey: clientKey, // Mandatory. clientKey from Customer Area
21 | });
22 |
23 | // 2. Create and mount the Component
24 | const ach = checkout
25 | .create('ach', {
26 | // Optional Configuration
27 | // hasHolderName: false, // Defaults to true
28 |
29 | // Optional. Customize the look and feel of the payment form
30 | // https://docs.adyen.com/developers/checkout/api-integration/configure-secured-fields/styling-secured-fields
31 | styles: {},
32 |
33 | // Optionally show a Pay Button
34 | showPayButton: true,
35 |
36 | // Events
37 | onSubmit: (state, component) => {
38 | if (state.isValid) {
39 | // ACH only works in US or PR, with payment in USD
40 | const additionalConfig = {
41 | countryCode: state.data.billingAddress.country,
42 | amount: {
43 | value: 1000,
44 | currency: 'USD'
45 | }
46 | }
47 | makePayment(ach.data, additionalConfig);
48 | }
49 | },
50 |
51 | onChange: (state, component) => {
52 | // state.data;
53 | // state.isValid;
54 | updateStateContainer(state); // Demo purposes only
55 | },
56 |
57 | // Optional: insert address information, if you already have it
58 | // data: {
59 | // holderName: 'B. Fish',
60 | // billingAddress: {
61 | // street: 'Infinite Loop',
62 | // postalCode: '95014',
63 | // city: 'Cupertino',
64 | // houseNumberOrName: '1',
65 | // country: 'US',
66 | // stateOrProvince: 'CA'
67 | // }
68 | // }
69 | })
70 | .mount('#ach-container');
71 | });
--------------------------------------------------------------------------------
/src/ach/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Adyen Checkout Components sample code
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
Back
16 |
17 |
ACH Component
18 |
23 |
24 |
25 |
36 |
37 |
38 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
--------------------------------------------------------------------------------
/src/bancontact/bancontact.js:
--------------------------------------------------------------------------------
1 | // 0. Get clientKey
2 | getClientKey().then(async clientKey => {
3 | // 1. Create an instance of AdyenCheckout providing the clientKey
4 | const checkout = await AdyenCheckout({
5 | clientKey: clientKey, // Mandatory. clientKey from Customer Area
6 | environment: 'test',
7 | amount: {
8 | currency: 'EUR',
9 | value: 1000
10 | }, // amount to be shown next to the qrcode
11 | onAdditionalDetails: result => {
12 | console.log(result);
13 | },
14 | onError: error => {
15 | console.log(error);
16 | }
17 | });
18 |
19 | // Override our default demo config for this payment method
20 | const bancontactData = {
21 | countryCode: 'BE',
22 | amount: {
23 | value: 1000,
24 | currency: 'EUR'
25 | },
26 | paymentMethod: {
27 | type: 'bcmc_mobile_QR'
28 | }
29 | };
30 |
31 | /** Call the /payments endpoint to retrieve the necessary data to start the Bancontact component
32 | * We need the following parts of the response
33 | * - qrCodeData (redirect.data.qrCodeData): The data the QR Code will contain
34 | * - paymentData Necessary to communicate with Adyen to check the current payment status
35 | */
36 | makePayment(bancontactData).then(response => {
37 | if (!!response.action) {
38 | // 2. Create and mount the Component
39 | const bancontact = checkout.createFromAction(response.action).mount('#bancontact-container');
40 | }
41 | });
42 | });
--------------------------------------------------------------------------------
/src/bancontact/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Adyen Checkout Components sample code
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
Back
16 |
17 |
Bancontact Mobile Component
18 |
24 |
25 |
26 |
27 | Check the Source Code to see the full implementation.
28 |
29 |
30 | For more information, please refer to the Checkout Components documentation .
31 |
32 |
33 |
34 |
35 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/src/bcmc/bcmc.js:
--------------------------------------------------------------------------------
1 | /**
2 | * IMPORTANT - Set a boolean indicating whether index.html is loading a version of adyen.js (& adyen.css) >= 5.0.0
3 | */
4 | const head = document.head.innerHTML;
5 | const version = head.substring(head.indexOf('sdk/') + 4, head.indexOf('/adyen'));
6 | const majorVn = Number(version.substring(0, version.indexOf('.')));
7 | const IS_VERSION_5 = majorVn >= 5;
8 |
9 | // 0. Get client key
10 | getClientKey().then(async clientKey => {
11 |
12 | // 1. Create an instance of AdyenCheckout providing the clientKey
13 | const configObj = {
14 | clientKey: clientKey,
15 | environment: 'test',
16 | amount: {
17 | currency: 'EUR',
18 | value: 1000
19 | },
20 | showPayButton: true,
21 | onSubmit: (state, component) => {
22 | makePayment(state.data);
23 | }
24 | }
25 |
26 | if (!IS_VERSION_5) {
27 | window.checkout = new AdyenCheckout(configObj);
28 | } else {
29 | window.checkout = await AdyenCheckout(configObj);
30 | }
31 |
32 | // 2. Create and mount component.
33 | checkout.create('bcmc').mount('#bcmc-container');
34 | });
--------------------------------------------------------------------------------
/src/bcmc/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Adyen Checkout Components sample code
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
Back
16 |
17 |
Bancontact Card Component
18 |
24 |
25 |
26 |
27 | Check the Source Code to see the full implementation.
28 |
29 |
30 | For more information, please refer to the Checkout Components documentation .
31 |
32 |
33 |
34 |
35 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/src/boleto/boleto.js:
--------------------------------------------------------------------------------
1 | // 1. Create an instance of AdyenCheckout
2 |
3 | async function initiateComponent() {
4 | const checkout = await AdyenCheckout({
5 | environment: 'test',
6 | showPayButton: true,
7 | onSubmit: (state, component) => {
8 | makePayment(state.data);
9 | },
10 | onChange: (state, component) => {
11 | // state.data;
12 | // state.isValid;
13 |
14 | updateStateContainer(state); // Demo purposes only
15 | }
16 | });
17 | // 2. Create and mount the Component
18 | const boleto = checkout.create('boletobancario').mount('#boletobancario-container');
19 |
20 | // This is a mock of the /payments response action property
21 | const actionMock = {
22 | downloadUrl: 'https://...',
23 | expiresAt: '2022-09-11T00:00:00',
24 | initialAmount: {
25 | currency: 'BRL',
26 | value: 1000
27 | },
28 | paymentMethodType: 'boletobancario',
29 | reference: '12345.12345 12345.123456 12345.123456 1 12345678901',
30 | totalAmount: {
31 | currency: 'BRL',
32 | value: 1000
33 | },
34 | type: 'voucher'
35 | };
36 |
37 | // 3. Get the action property from the /payments response and use it to render the voucher
38 | const boletoVoucher = checkout.createFromAction(actionMock).mount('#boletobancario-result-container');
39 | }
40 | initiateComponent()
--------------------------------------------------------------------------------
/src/boleto/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Adyen Checkout Components sample code
8 |
9 |
10 |
11 |
12 |
13 |
14 |
Back
15 |
16 |
17 |
Boleto Bancario Component
18 |
Shopper Details Form
19 |
24 |
25 |
Payment Result (Voucher)
26 |
31 |
32 |
33 |
34 |
35 | Check the Source Code to see the full implementation.
36 |
37 |
38 | For more information, please refer to the Checkout Components documentation .
39 |
40 |
41 |
42 |
43 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
--------------------------------------------------------------------------------
/src/card/card.js:
--------------------------------------------------------------------------------
1 |
2 | /**
3 | * Handling redirect results
4 | */
5 | function handleRedirectResult() {
6 | const { redirectResult } = getSearchParameters(window.location.search);
7 |
8 | console.log('### card::handleRedirectResult:: redirectResult', redirectResult);
9 |
10 | if (redirectResult) {
11 | // Makes call to /payments/details
12 | return handleAdditionalDetails({
13 | data: {
14 | details: {
15 | redirectResult
16 | }
17 | }
18 | })
19 | }
20 |
21 | return false;
22 | }
23 |
24 | handleRedirectResult();
25 |
26 | /**
27 | * IMPORTANT - Set a boolean indicating whether index.html is loading a version of adyen.js (& adyen.css) >= 5.0.0
28 | */
29 | const head = document.head.innerHTML;
30 | const version = head.substring(head.indexOf('sdk/') + 4, head.indexOf('/adyen'));
31 | const majorVn = Number(version.substring(0, version.indexOf('.')));
32 | const IS_VERSION_5 = majorVn >= 5;
33 |
34 | // 0. Get clientKey
35 | Promise.all([ getClientKey(), getPaymentMethods()]).then(async response => {
36 |
37 | // Optional, define custom placeholders for the Card fields
38 | // https://docs.adyen.com/online-payments/web-components/localization-components
39 | // const translations = {
40 | // "en-GB": {
41 | // "creditCard.numberField.placeholder": "1234 5678 9012 3456",
42 | // "creditCard.expiryDateField.placeholder": "MM/YY",
43 | // }
44 | // };
45 |
46 | const configObj = {
47 | environment: 'test',
48 | locale: "en-GB",
49 | // translations: translations,
50 | clientKey: response[0],
51 | paymentMethodsResponse: response[1],
52 | // Events
53 | onSubmit: (state, component) => {
54 | if (state.isValid) {
55 |
56 | const config = {
57 | additionalData: {allow3DS2: true}, // allows regular, "in app", 3DS2
58 | }
59 |
60 | const cardData = {...card.data}
61 |
62 | makePayment(cardData, config).then(response => {
63 | if (response.action) {
64 | component.handleAction(response.action);
65 | // checkout.createFromAction(response.action, { challengeWindowSize: '01' }).mount('#card-container')
66 | console.log('### handlers::handleResponse::response.action=', response.action);
67 | }
68 | });
69 | }
70 | },
71 |
72 | onChange: (state, component) => {
73 | // state.data;
74 | // state.isValid;
75 |
76 | updateStateContainer(state); // Demo purposes only
77 | },
78 | onAdditionalDetails: (details) => {
79 | console.log('### card::onAdditionalDetails:: calling' );
80 | handleAdditionalDetails(details).then(response => {
81 | console.log('### card::onAdditionalDetails:: response', response);
82 | });
83 | },
84 |
85 | onError: (e)=>{
86 | console.log('### Checkout config onError:: e=', e);
87 | }
88 | }
89 |
90 | // 1. Create an instance of AdyenCheckout
91 | if (!IS_VERSION_5) {
92 | window.checkout = new AdyenCheckout(configObj);
93 | } else {
94 | window.checkout = await AdyenCheckout(configObj);
95 | }
96 |
97 | // 2. Create and mount the Component
98 | window.card = checkout
99 | .create('card', {
100 | // Optional Configuration
101 | // hasHolderName: true,
102 | // holderNameRequired: true,
103 |
104 | // Optional. Customize the look and feel of the payment form
105 | // https://docs.adyen.com/developers/checkout/api-integration/configure-secured-fields/styling-secured-fields
106 | styles: {},
107 |
108 | // Optionally show a Pay Button
109 | showPayButton: true,
110 | enableStoreDetails: true,
111 |
112 | _disableClickToPay: true,
113 |
114 | onBinLookup: (obj)=>{
115 | console.log('### Card config::onBinLookup:: obj=', obj);
116 | },
117 | onFocus: (obj) => {
118 | console.log('### Cards::onFocus:: obj',obj);
119 | },
120 | onBlur: (obj) => {
121 | console.log('### Cards::onBlur:: obj',obj);
122 | }
123 | })
124 | .mount('#card-container');
125 | });
--------------------------------------------------------------------------------
/src/card/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Adyen Checkout Components sample code
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
Back
17 |
18 |
Card Component
19 |
24 |
25 |
26 |
37 |
38 |
39 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
--------------------------------------------------------------------------------
/src/customcard/customCard.js:
--------------------------------------------------------------------------------
1 | import {setFocus, onBrand, onConfigSuccess, onBinLookup, setCCErrors, onChange, onChangeV5} from './customCards.config.js';
2 |
3 | /**
4 | * IMPORTANT - Set a boolean indicating whether index.html is loading a version of adyen.js (& adyen.css) >= 5.0.0
5 | */
6 | const head = document.head.innerHTML;
7 | const version = head.substring(head.indexOf('sdk/') + 4, head.indexOf('/adyen'));
8 | const majorVn = Number(version.substring(0, version.indexOf('.')));
9 | const IS_VERSION_5 = majorVn >= 5;
10 |
11 | //const mockPaymentMethodsResponse = {
12 | // paymentMethods: [
13 | // {
14 | // brands: ['mc', 'visa', 'amex', 'maestro', 'cup', 'diners', 'discover', 'jcb', 'bijcard'],
15 | // name: 'Credit Card',
16 | // type: 'scheme'
17 | // }
18 | // ]
19 | //}
20 |
21 | // 0. Get clientKey
22 | getClientKey().then(async clientKey => {
23 |
24 | const configObj = {
25 | clientKey : clientKey,
26 | environment : 'test',
27 | locale : 'en-US',
28 | // paymentMethodsResponse: mockPaymentMethodsResponse
29 | }
30 |
31 | // 1. Create an instance of AdyenCheckout
32 | if (!IS_VERSION_5) {
33 | window.checkout = new AdyenCheckout(configObj);
34 | } else {
35 | window.checkout = await AdyenCheckout(configObj);
36 | }
37 |
38 | window.securedFields = checkout
39 | .create('securedfields', {
40 | type: 'card',
41 | brands : ['mc', 'visa', 'amex', 'bcmc', 'maestro', 'cartebancaire'],
42 | onConfigSuccess,
43 | onBrand,
44 | onFocus : setFocus,
45 | onBinLookup,
46 |
47 | ...(!IS_VERSION_5 && {onError : setCCErrors}), // For version < 5.0.0
48 |
49 | onChange : (state, component) => {
50 | /**
51 | * For version < 5.0.0
52 | */
53 | if (!IS_VERSION_5) {
54 | onChange(state, component);
55 |
56 | updateStateContainer(state);// Demo purposes only
57 | return;
58 | }
59 |
60 | /**
61 | * For version >= 5.0.0
62 | */
63 | onChangeV5(state, component);
64 |
65 | // In v5, we enhance the securedFields state.errors object with a rootNode prop
66 | // but calling updateStateContainer with the ref to this rootNode element will cause a "Converting circular structure to JSON" error
67 | // so replace any rootNode values in the objects in state.errors with an empty string
68 | if (!!Object.keys(state.errors).length) {
69 | const nuErrors = Object.entries(state.errors).reduce((acc, [fieldType, error]) => {
70 | acc[fieldType] = error ? {...error, rootNode : ''} : error;
71 | return acc;
72 | }, {});
73 | state.errors = nuErrors;
74 | }
75 |
76 | updateStateContainer(state);// Demo purposes only
77 | }
78 | })
79 | .mount('#card-container');
80 |
81 | createPayButton('#card-container', window.securedFields, 'securedfields');
82 |
83 | function createPayButton(parent, component, attribute) {
84 | const payBtn = document.createElement('button');
85 |
86 | payBtn.textContent = 'Pay';
87 | payBtn.name = 'pay';
88 | payBtn.classList.add('adyen-checkout__button', 'js-components-button--one-click', `js-${attribute}`);
89 |
90 | payBtn.addEventListener('click', e => {
91 | e.preventDefault();
92 |
93 | if (!component.isValid) {
94 | return component.showValidation();
95 | }
96 |
97 | makePayment(component.formatData());
98 |
99 | payBtn.style.opacity = '0.5';
100 | });
101 |
102 | document.querySelector(parent).appendChild(payBtn);
103 |
104 | return payBtn;
105 | }
106 | });
107 |
108 |
--------------------------------------------------------------------------------
/src/customcard/customCards.config.js:
--------------------------------------------------------------------------------
1 | let hideCVC = false;
2 | let optionalCVC = false;
3 | let hideDate = false;
4 | let optionalDate = false;
5 | let isDualBranding = false;
6 |
7 | function setAttributes(el, attrs) {
8 | for (const key in attrs) {
9 | el.setAttribute(key, attrs[key]);
10 | }
11 | }
12 |
13 | function setLogosActive(rootNode, mode) {
14 | const imageHolder = rootNode.querySelector('.pm-image');
15 | const dualBrandingImageHolder = rootNode.querySelector('.pm-image-dual');
16 |
17 | switch (mode) {
18 | case 'dualBranding_notValid':
19 | Object.assign(imageHolder.style, { display: 'none' });
20 | Object.assign(dualBrandingImageHolder.style, { display: 'block', 'pointer-events': 'none', opacity: 0.5 });
21 | break;
22 |
23 | case 'dualBranding_valid':
24 | Object.assign(imageHolder.style, { display: 'none' });
25 | Object.assign(dualBrandingImageHolder.style, { display: 'block', 'pointer-events': 'auto', opacity: 1 });
26 | break;
27 |
28 | default:
29 | // reset
30 | Object.assign(imageHolder.style, { display: 'block' });
31 | Object.assign(dualBrandingImageHolder.style, { display: 'none' });
32 | }
33 | }
34 |
35 | // Can be imported by customCard and added to the config object used in checkout.create('securedfields')
36 | export const styles = {
37 | // base: {
38 | // caretColor: 'red'
39 | // },
40 | error: {
41 | color: 'red'
42 | },
43 | validated: {
44 | color: 'green',
45 | fontWeight: 'bold'
46 | // background: 'blue'
47 | },
48 | placeholder: {
49 | color: '#d8d8d8'
50 | }
51 | };
52 |
53 | export function onConfigSuccess(pCallbackObj) {
54 | /**
55 | * Set the UI to it's starting state
56 | */
57 | document.querySelector('.card-input__spinner__holder').style.display = 'none';
58 |
59 | // For <= v4.5.0 no rootNode prop was sent on the pCallbackObj
60 | const rootNode = pCallbackObj.rootNode || document.getElementById('card-container');
61 |
62 | rootNode.style.display = 'block';
63 |
64 | rootNode.querySelector('.pm-image-dual').style.display = 'none';
65 |
66 | setLogosActive(rootNode);
67 |
68 | /**
69 | * Set focus on first element
70 | */
71 | setTimeout(() => {
72 | // Allow time for screen to redraw after spinner is hidden
73 | window.securedFields.setFocusOn('encryptedCardNumber');
74 | }, 100);
75 |
76 | // window.securedFields.updateStyles({
77 | // base: {
78 | // color: '#000',
79 | //// fontSize: '18px',
80 | //// lineHeight: '18px'
81 | // },
82 | // error: {
83 | // color: 'orange'
84 | // },
85 | // validated: {
86 | // color: 'blue',
87 | // fontWeight: 'bold'
88 | // },
89 | // placeholder: {
90 | // color: 'green'
91 | // }
92 | // });
93 | }
94 |
95 | export function setCCErrors(pCallbackObj) {
96 | if (!pCallbackObj.rootNode) return;
97 |
98 | const sfNode = pCallbackObj.rootNode.querySelector(`[data-cse="${pCallbackObj.fieldType}"]`);
99 | const errorNode = sfNode.parentNode.querySelector('.pm-form-label__error-text');
100 |
101 | if (errorNode.innerText === '' && pCallbackObj.error === '') return;
102 |
103 | if (pCallbackObj.error !== '') {
104 | errorNode.style.display = 'block';
105 | errorNode.innerText = pCallbackObj.errorI18n;
106 |
107 | // Add error classes
108 | setErrorClasses(sfNode, true);
109 | return;
110 | }
111 |
112 | // Else: error === ''
113 | errorNode.style.display = 'none';
114 | errorNode.innerText = '';
115 |
116 | // Remove error classes
117 | setErrorClasses(sfNode, false);
118 | }
119 |
120 | export function setFocus(pCallbackObj) {
121 | const sfNode = pCallbackObj.rootNode.querySelector(`[data-cse="${pCallbackObj.fieldType}"]`);
122 | setFocusClasses(sfNode, pCallbackObj.focus);
123 | }
124 |
125 | export function onBrand(pCallbackObj) {
126 | /**
127 | * If not in dual branding mode - add card brand to first image element
128 | */
129 | if (!isDualBranding) {
130 | const brandLogo1 = pCallbackObj.rootNode.querySelector('.pm-image-1');
131 | setAttributes(brandLogo1, {
132 | src: pCallbackObj.brandImageUrl,
133 | alt: pCallbackObj.brand
134 | });
135 | }
136 |
137 | /**
138 | * Deal with showing/hiding CVC field
139 | */
140 | const cvcNode = pCallbackObj.rootNode.querySelector('.pm-form-label--cvc');
141 |
142 | if (pCallbackObj.cvcPolicy === 'hidden' && !hideCVC) {
143 | hideCVC = true;
144 | cvcNode.style.display = 'none';
145 | }
146 |
147 | if (hideCVC && pCallbackObj.cvcPolicy !== 'hidden') {
148 | hideCVC = false;
149 | cvcNode.style.display = 'block';
150 | }
151 |
152 | // Optional cvc fields
153 | if (pCallbackObj.cvcPolicy === 'optional' && !optionalCVC) {
154 | optionalCVC = true;
155 | if (cvcNode) cvcNode.querySelector('.pm-form-label__text').innerText = 'CVV/CVC (optional):';
156 | }
157 |
158 | if (optionalCVC && pCallbackObj.cvcPolicy !== 'optional') {
159 | optionalCVC = false;
160 | if (cvcNode) cvcNode.querySelector('.pm-form-label__text').innerText = 'CVV/CVC';
161 | }
162 |
163 | /**
164 | * Deal with showing/hiding date field(s)
165 | */
166 | const dateNode = pCallbackObj.rootNode.querySelector('.pm-form-label--exp-date');
167 | const monthNode = pCallbackObj.rootNode.querySelector('.pm-form-label--exp-month');
168 | const yearNode = pCallbackObj.rootNode.querySelector('.pm-form-label--exp-year');
169 |
170 | if (pCallbackObj.expiryDatePolicy === 'hidden' && !hideDate) {
171 | hideDate = true;
172 | if (dateNode) dateNode.style.display = 'none';
173 | if (monthNode) monthNode.style.display = 'none';
174 | if (yearNode) yearNode.style.display = 'none';
175 | }
176 |
177 | if (hideDate && pCallbackObj.expiryDatePolicy !== 'hidden') {
178 | hideDate = false;
179 | if (dateNode) dateNode.style.display = 'block';
180 | if (monthNode) monthNode.style.display = 'block';
181 | if (yearNode) yearNode.style.display = 'block';
182 | }
183 |
184 | // Optional date fields
185 | if (pCallbackObj.expiryDatePolicy === 'optional' && !optionalDate) {
186 | optionalDate = true;
187 | if (dateNode) dateNode.querySelector('.pm-form-label__text').innerText = 'Expiry date (optional):';
188 | if (monthNode) monthNode.querySelector('.pm-form-label__text').innerText = 'Expiry month (optional):';
189 | if (yearNode) yearNode.querySelector('.pm-form-label__text').innerText = 'Expiry year (optional):';
190 | }
191 |
192 | if (optionalDate && pCallbackObj.expiryDatePolicy !== 'optional') {
193 | optionalDate = false;
194 | if (dateNode) dateNode.querySelector('.pm-form-label__text').innerText = 'Expiry date:';
195 | if (monthNode) monthNode.querySelector('.pm-form-label__text').innerText = 'Expiry month:';
196 | if (yearNode) yearNode.querySelector('.pm-form-label__text').innerText = 'Expiry year:';
197 | }
198 | }
199 |
200 | function dualBrandListener(e) {
201 | securedFields.dualBrandingChangeHandler(e);
202 | }
203 |
204 | function resetDualBranding(rootNode) {
205 | isDualBranding = false;
206 |
207 | setLogosActive(rootNode);
208 |
209 | const brandLogo1 = rootNode.querySelector('.pm-image-dual-1');
210 | brandLogo1.removeEventListener('click', dualBrandListener);
211 |
212 | const brandLogo2 = rootNode.querySelector('.pm-image-dual-2');
213 | brandLogo2.removeEventListener('click', dualBrandListener);
214 | }
215 |
216 | /**
217 | * Implementing dual branding
218 | */
219 | function onDualBrand(pCallbackObj) {
220 | const brandLogo1 = pCallbackObj.rootNode.querySelector('.pm-image-dual-1');
221 | const brandLogo2 = pCallbackObj.rootNode.querySelector('.pm-image-dual-2');
222 |
223 | isDualBranding = true;
224 |
225 | const supportedBrands = pCallbackObj.supportedBrandsRaw;
226 |
227 | /**
228 | * Set first brand icon (and, importantly also add alt &/or data-value attrs); and add event listener
229 | */
230 | setAttributes(brandLogo1, {
231 | src: supportedBrands[0].brandImageUrl,
232 | alt: supportedBrands[0].brand,
233 | 'data-value': supportedBrands[0].brand
234 | });
235 |
236 | brandLogo1.addEventListener('click', dualBrandListener);
237 |
238 | /**
239 | * Set second brand icon (and, importantly also add alt &/or data-value attrs); and add event listener
240 | */
241 | setAttributes(brandLogo2, {
242 | src: supportedBrands[1].brandImageUrl,
243 | alt: supportedBrands[1].brand,
244 | 'data-value': supportedBrands[1].brand
245 | });
246 | brandLogo2.addEventListener('click', dualBrandListener);
247 | }
248 |
249 | export function onBinLookup(pCallbackObj) {
250 | /**
251 | * Dual branded result...
252 | */
253 | if (pCallbackObj.supportedBrandsRaw?.length > 1) {
254 | onDualBrand(pCallbackObj);
255 | return;
256 | }
257 |
258 | /**
259 | * ...else - binLookup 'reset' result or binLookup result with only one brand
260 | */
261 | resetDualBranding(pCallbackObj.rootNode);
262 | }
263 |
264 | export function onChangeV5(state, component) {
265 | // From v5 the onError handler is no longer only for card comp related errors
266 | // - so watch state.errors and use it to call the custom card specific 'setErrors' function
267 | if (!!Object.keys(state.errors).length) {
268 | const errors = Object.entries(state.errors).map(([fieldType, error]) => {
269 | return {
270 | fieldType,
271 | ...(error ? error : { error: '', rootNode: component._node })
272 | };
273 | });
274 | errors.forEach(setCCErrors);
275 | }
276 |
277 | onChange(state);
278 | }
279 |
280 | export function onChange(state) {
281 | /**
282 | * If we're in a dual branding scenario & the number field becomes valid or is valid and become invalid
283 | * - set the brand logos to the required 'state'
284 | */
285 | if (isDualBranding) {
286 | const mode = state.valid.encryptedCardNumber ? 'dualBranding_valid' : 'dualBranding_notValid';
287 | setLogosActive(document.querySelector('#card-container'), mode);
288 | }
289 | }
290 |
291 | const setErrorClasses = function(pNode, pSetErrors) {
292 | if (pSetErrors) {
293 | if (pNode.className.indexOf('pm-input-field--error') === -1) {
294 | pNode.className += ' pm-input-field--error';
295 | }
296 | return;
297 | }
298 |
299 | // Remove errors
300 | if (pNode.className.indexOf('pm-input-field--error') > -1) {
301 | const newClassName = pNode.className.replace('pm-input-field--error', '');
302 | pNode.className = newClassName.trim();
303 | }
304 | };
305 |
306 | const setFocusClasses = function(pNode, pSetFocus) {
307 | if (pSetFocus) {
308 | if (pNode.className.indexOf('pm-input-field--focus') === -1) {
309 | pNode.className += ' pm-input-field--focus';
310 | }
311 | return;
312 | }
313 |
314 | // Remove focus
315 | if (pNode.className.indexOf('pm-input-field--focus') > -1) {
316 | const newClassName = pNode.className.replace('pm-input-field--focus', '');
317 | pNode.className = newClassName.trim();
318 | }
319 | };
320 |
--------------------------------------------------------------------------------
/src/customcard/customcards.style.css:
--------------------------------------------------------------------------------
1 | #card-container{
2 | position: relative;
3 | font-family: 'Open Sans', sans-serif;
4 | font-size: 14px;
5 | padding: 0 24px;
6 | display: none;
7 | }
8 | .pm-image, .pm-image-dual{
9 | background-color: #ffffff;
10 | border-radius: 4px;
11 | -moz-border-radius: 4px;
12 | -webkit-border-radius: 4px;
13 | float: right;
14 | line-height: 0;
15 | position: relative;
16 | overflow: hidden;
17 | }
18 | .pm-form-label {
19 | float: left;
20 | padding-bottom: 1em;
21 | position: relative;
22 | width: 100%;
23 | }
24 | .pm-form-label--exp-date {
25 | width: 40%;
26 | }
27 | .pm-form-label--cvc {
28 | float: right;
29 | width: 40%;
30 | }
31 | .pm-form-label__text {
32 | color: #00112c;
33 | float: left;
34 | font-size: 0.93333em;
35 | padding-bottom: 6px;
36 | position: relative;
37 | }
38 | .pm-input-field {
39 | background: white;
40 | border: 1px solid #d8d8d8;
41 | -moz-border-radius: 4px;
42 | -webkit-border-radius: 4px;
43 | border-radius: 4px;
44 | box-sizing: border-box;
45 | clear: left;
46 | font-size: 0.93333333333em;
47 | float: left;
48 | padding: 8px;
49 | position: relative;
50 | width: 100%;
51 | height: 35px;
52 | }
53 |
54 | .pm-form-label__error-text {
55 | color: #ff7d00;
56 | display: none;
57 | float: left;
58 | font-size: 13px;
59 | padding-top: 0.4em;
60 | position: relative;
61 | width: 100%;
62 | }
63 |
64 | /* Set dynamically */
65 | .pm-input-field--error{
66 | border: 1px solid #ff7d00;
67 | }
68 |
69 | .pm-input-field--focus {
70 | border: 1px solid #969696;
71 | outline: none;
72 | }
73 | .pm-input-field--error.pm-input-field--focus {
74 | border: 1px solid #ff7d00;
75 | }
76 |
77 | .card-input__spinner__holder {
78 | position: relative;
79 | top: 0px;
80 | }
81 |
82 | .card-input__spinner {
83 | position: absolute;
84 | top: 0;
85 | left: 0;
86 | /*width: 100%;*/
87 | height: 100%;
88 | z-index: 1;
89 | display: none;
90 | }
91 |
92 | .card-input__spinner--active {
93 | display: block;
94 | }
95 |
--------------------------------------------------------------------------------
/src/customcard/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Adyen Checkout Components sample code
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
Back
17 |
18 |
Custom Card Component
19 |
20 |
21 |
22 |
28 |
29 |
30 |
35 |
40 |
41 |
42 | Card number:
43 |
44 | Please enter a valid credit card number
45 |
46 |
47 | Expiry month:
48 |
49 | Date error text
50 |
51 |
52 | Expiry year:
53 |
54 | Date error text
55 |
56 |
57 | CVV/CVC:
58 |
59 | CVC Error text
60 |
61 |
62 |
69 |
70 |
71 |
72 |
85 |
86 |
87 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
--------------------------------------------------------------------------------
/src/demo.css:
--------------------------------------------------------------------------------
1 | *,
2 | *:after,
3 | *:before {
4 | box-sizing: border-box;
5 | }
6 |
7 | *::selection {
8 | background: #99c2ff;
9 | }
10 |
11 | *::-moz-selection {
12 | background: #99c2ff;
13 | }
14 |
15 | html,
16 | body {
17 | background: #fcfcfc;
18 | font: 16px/1.21 'Fakt', sans-serif, Helvetica, Arial;
19 | font-weight: 400;
20 | margin: 0;
21 | min-height: 100vh;
22 | overflow: auto;
23 | }
24 |
25 | h1,
26 | h2,
27 | h3 {
28 | font-weight: 400;
29 | }
30 |
31 | h1 {
32 | font-size: 2em;
33 | margin: 24px 0;
34 | line-height: 38px;
35 | }
36 |
37 | .sidebar .header {
38 | height: 60px;
39 | padding: 16px 24px;
40 | margin: 0;
41 | border-bottom: 1px solid rgba(255, 255, 255, 0.2);
42 | border-top: 1px solid rgba(255, 255, 255, 0.2);
43 | line-height: 1;
44 | }
45 |
46 | .sidebar h2 {
47 | display: inline-block;
48 | font-size: 1.25em;
49 | margin: 5px 0 0;
50 | }
51 |
52 | .sidebar .copy-sample-code {
53 | background: transparent;
54 | border: 1px solid white;
55 | border-radius: 3px;
56 | color: #fff;
57 | cursor: pointer;
58 | float: right;
59 | font-size: 0.65em;
60 | margin-top: -3px;
61 | text-transform: uppercase;
62 | padding: 8px 0;
63 | transition: 0.5s all;
64 | width: 60px;
65 | }
66 |
67 | .sidebar .copy-sample-code:hover {
68 | background: #183057;
69 | }
70 |
71 | .sidebar .copy-sample-code.copy-sample-code--active {
72 | border-color: #06f;
73 | background: #06f;
74 | transition: none;
75 | }
76 |
77 | .sidebar .copy-sample-code.copy-sample-code--active:before {
78 | content: 'Copied!';
79 | }
80 |
81 | .sidebar .copy-sample-code:before {
82 | content: 'Copy';
83 | }
84 |
85 | .pay-button {
86 | background: #001b2b;
87 | border: 0;
88 | border-radius: 3px;
89 | box-shadow: 0 3px 4px rgba(0, 15, 45, 0.2);
90 | color: #fff;
91 | cursor: pointer;
92 | font-size: 1em;
93 | font-weight: 700;
94 | height: 48px;
95 | margin-top: 20px;
96 | padding: 15px;
97 | transition: background 0.3s ease-out;
98 | width: 300px;
99 | }
100 |
101 | .pay-button[disabled] {
102 | cursor: not-allowed;
103 | opacity: 0.15;
104 | }
105 |
106 | .payment_methods__list {
107 | list-style: none;
108 | margin: 0;
109 | padding: 14px 0 14px;
110 | }
111 |
112 | @media (min-width: 780px) {
113 | .payment_methods__list {
114 | padding-left: 14px;
115 | }
116 | }
117 |
118 | .payment_methods__list__element {
119 | margin: 14px 0;
120 | }
121 |
122 | a:link,
123 | a:visited {
124 | color: #06f;
125 | text-decoration: none;
126 | }
127 |
128 | a:link:hover {
129 | text-decoration: underline;
130 | }
131 |
132 | .container {
133 | margin: 0 15px;
134 | max-width: 960px;
135 | height: 100vh;
136 | }
137 |
138 | @media (min-width: 400px) {
139 | .container {
140 | margin: auto;
141 | }
142 | }
143 |
144 | .container--full-width {
145 | margin: 0;
146 | max-width: 100vw;
147 | }
148 |
149 | @media (min-width: 400px) {
150 | .container--full-width {
151 | display: flex;
152 | }
153 | }
154 |
155 | .main {
156 | display: block;
157 | overflow-y: auto;
158 | padding: 18px 15px 48px;
159 | position: relative;
160 | }
161 |
162 | @media (min-width: 400px) {
163 | .main {
164 | padding: 18px 60px;
165 | width: 60%;
166 | }
167 | }
168 |
169 | .sidebar {
170 | background: #00112c;
171 | color: #fff;
172 | overflow: hidden;
173 | overflow-y: auto;
174 | }
175 |
176 | @media (min-width: 400px) {
177 | .sidebar {
178 | width: 40%;
179 | }
180 | }
181 |
182 | .info {
183 | background: #f3f6f9;
184 | border-left: 7px solid #06f;
185 | margin: 28px 0 0;
186 | padding: 7px 14px;
187 | }
188 |
189 | @media (min-width: 780px) {
190 | .info {
191 | padding: 7px 21px;
192 | }
193 | }
194 |
195 | pre {
196 | font-size: 0.95em;
197 | margin: 24px;
198 | overflow: auto;
199 | position: relative;
200 | }
201 |
202 | .request-container .request-code,
203 | .response-container .response-code {
204 | opacity: 0;
205 | transition: opacity 0.2s ease-out;
206 | }
207 |
208 | .request-container--visible .request-code,
209 | .response-container--visible .response-code {
210 | opacity: 1;
211 | }
212 |
213 | .request-container p,
214 | .response-container p {
215 | padding: 16px 24px;
216 | font-size: 0.9em;
217 | opacity: 0.7;
218 | }
219 |
220 | .request-container--visible p,
221 | .response-container--visible p {
222 | display: none;
223 | }
224 |
225 | .payment-method {
226 | border-radius: 3px;
227 | display: block;
228 | margin: 0 -15px;
229 | padding: 3em;
230 | background: #f7f8f9;
231 | display: flex;
232 | flex-direction: column;
233 | align-items: center;
234 | }
235 |
236 | @media (min-width: 780px) {
237 | .payment-method {
238 | margin: 0 auto;
239 | }
240 | }
241 |
242 | #bancontact-container,
243 | #wechatpay-container {
244 | min-width: 70%;
245 | max-width: 350px;
246 | }
247 |
248 | .payment-method__container {
249 | width: 350px;
250 | }
251 |
252 | #dropin-container {
253 | width: 544px;
254 | }
255 |
256 | #boletobancario-container,
257 | #boletobancario-result-container {
258 | width: 550px;
259 | }
260 |
261 | #result-container {
262 | background: #f7f8f9;
263 | padding: 0px 10px;
264 | }
--------------------------------------------------------------------------------
/src/demo.js:
--------------------------------------------------------------------------------
1 | const stateContainer = document.querySelector('.current-state');
2 | const requestContainer = document.querySelector('.request-container');
3 | const responseContainer = document.querySelector('.response-container');
4 |
5 | // Demo - Update current component state container
6 | function updateStateContainer(newState) {
7 | stateContainer.innerText = JSON.stringify(newState, null, 2);
8 | }
9 |
10 | // Demo - Update request container
11 | function updateRequestContainer(response) {
12 | const defaultResponseParams = { merchantAccount: 'YOUR_MERCHANT_ACCOUNT' };
13 | requestContainer.querySelector('pre').innerText = JSON.stringify(
14 | { ...defaultResponseParams, ...response },
15 | null,
16 | 2
17 | );
18 | requestContainer.classList.add('request-container--visible');
19 | }
20 |
21 | // Demo - Update server response container
22 | function updateResponseContainer(response) {
23 | responseContainer.querySelector('pre').innerText = JSON.stringify(response, null, 2);
24 | responseContainer.classList.add('response-container--visible');
25 | }
26 |
27 | // Demo - Copy Source Code Examples
28 | document.querySelectorAll('.copy-sample-code').forEach(c => {
29 | c.addEventListener('click', () => {
30 | const code = document.querySelector('.source-code');
31 | const range = document.createRange();
32 | range.selectNode(code);
33 | window.getSelection().removeAllRanges();
34 | window.getSelection().addRange(range);
35 | document.execCommand('copy');
36 | c.classList.add('copy-sample-code--active');
37 |
38 | setTimeout(() => {
39 | c.classList.remove('copy-sample-code--active');
40 | }, 1000);
41 | });
42 | });
43 |
--------------------------------------------------------------------------------
/src/dropin/dropin.js:
--------------------------------------------------------------------------------
1 | /**
2 | * IMPORTANT - Set a boolean indicating whether index.html is loading a version of adyen.js (& adyen.css) >= 5.0.0
3 | */
4 | const head = document.head.innerHTML;
5 | const version = head.substring(head.indexOf('sdk/') + 4, head.indexOf('/adyen'));
6 | const majorVn = Number(version.substring(0, version.indexOf('.')));
7 | const IS_VERSION_5 = majorVn >= 5;
8 |
9 | const DEFAULT_COUNTRY = 'US';
10 |
11 | // 0. Get clientKey
12 | getClientKey().then(clientKey => {
13 | const urlParams = getSearchParameters(window.location.search);
14 |
15 | // Can add request params to this object
16 | const pmReqConfig = {countryCode: urlParams.countryCode || DEFAULT_COUNTRY};
17 | getPaymentMethods(pmReqConfig).then(async paymentMethodsResponse => {
18 |
19 | paymentMethodsResponse.paymentMethods.reverse();
20 |
21 | let allowedPMS = urlParams.allowedpms;// e.g. &allowedpms=[scheme,ideal]
22 | if(allowedPMS === '[]' || typeof allowedPMS === 'undefined') allowedPMS = [];// if empty, all PMs will show
23 |
24 | const configObj = {
25 | environment: 'test',
26 | clientKey: clientKey, // Mandatory. clientKey from Customer Area
27 | paymentMethodsResponse,
28 | // removePaymentMethods: ['paysafecard', 'c_cash'],
29 | allowPaymentMethods: allowedPMS,
30 | onChange: state => {
31 | updateStateContainer(state); // Demo purposes only
32 | },
33 | onSubmit: (state, dropin) => {
34 | // state.data;
35 | // state.isValid;
36 | makePayment(state.data);
37 | }
38 | };
39 |
40 | // 1. Create an instance of AdyenCheckout
41 | if (!IS_VERSION_5) {
42 | window.checkout = new AdyenCheckout(configObj);
43 | } else {
44 | window.checkout = await AdyenCheckout(configObj);
45 | }
46 |
47 | // 2. Create and mount the Component
48 | window.dropin = checkout
49 | .create('dropin', {
50 | // Events
51 | onSelect: activeComponent => {
52 | if (activeComponent.state && activeComponent.state.data) updateStateContainer(activeComponent.data); // Demo purposes only
53 | },
54 | showStoredPaymentMethods: false
55 | })
56 | .mount('#dropin-container');
57 |
58 | });
59 | });
60 |
--------------------------------------------------------------------------------
/src/dropin/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Adyen Checkout Components sample code
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
Back
18 |
19 |
Drop-in
20 |
25 |
26 |
27 |
28 |
29 | Check the Source Code to see the full implementation.
30 |
31 |
32 | To make a payment, use our test card numbers .
35 |
36 |
37 | For more information, please refer to the Drop-in documentation .
39 |
40 |
41 |
42 |
43 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/src/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Adyen/adyen-components-js-sample-code/dd5a2925f714f636ebf80d2ea6224a62ce22b286/src/favicon.ico
--------------------------------------------------------------------------------
/src/googlepay/googlepay.js:
--------------------------------------------------------------------------------
1 | async function initiateComponent() {
2 | // 1. Create an instance of AdyenCheckout
3 | const checkout = await AdyenCheckout({});
4 |
5 | // 2. Create and mount the Component
6 | const googlepay = checkout
7 | .create('paywithgoogle', {
8 | showPayButton: true,
9 | environment: 'TEST', // Google Pay environment
10 | configuration: {
11 | gatewayMerchantId: 'TestMerchantCheckout', // name of your Adyen Merchant account
12 | merchantName: 'Adyen Test' // Name to be shown
13 | // merchantIdentifier: '' // Required in Production environment. Google's merchantId: https://developers.google.com/pay/api/web/guides/test-and-deploy/deploy-production-environment#obtain-your-merchantID
14 | },
15 |
16 | // Events
17 | onSubmit: (state, component) => {
18 | // Submit Payment
19 | makePayment(state.data);
20 |
21 | updateStateContainer(state); // Demo purposes only
22 | },
23 | onError: error => {
24 | console.error(error);
25 | }
26 | })
27 | // Normally, you should check if Google Pay is available before mounting it.
28 | // Here we are mounting it directly for demo purposes.
29 | // Please refer to the documentation for more information on Google Pay's availability.
30 | .mount('#googlepay-container');
31 | }
32 | initiateComponent()
--------------------------------------------------------------------------------
/src/googlepay/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Adyen Checkout Components sample code
8 |
9 |
10 |
11 |
12 |
13 |
14 |
Back
15 |
16 |
17 |
Google Pay Component
18 |
24 |
25 |
26 |
27 |
28 | Check the Source Code to see the full implementation.
29 |
30 |
31 | For more information, please refer to the Checkout Components documentation .
32 |
33 |
34 |
35 |
36 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
--------------------------------------------------------------------------------
/src/ideal/ideal.js:
--------------------------------------------------------------------------------
1 | getPaymentMethods().then(async response => {
2 | // 1. Create an instance of AdyenCheckout
3 | const checkout = await AdyenCheckout({
4 | paymentMethodsResponse: response,
5 |
6 | // Optionally show a Pay Button
7 | showPayButton: true,
8 |
9 | // Events
10 | onSubmit: (state, component) => {
11 | // Triggered when a shopper clicks on the Pay button
12 | makePayment(state.data);
13 | },
14 | onChange: (state, component) => {
15 | updateStateContainer(state); // Demo purposes only
16 | }
17 | });
18 |
19 | // 2. Create and mount the Component
20 | const ideal = checkout.create('ideal').mount('#ideal-container');
21 | });
--------------------------------------------------------------------------------
/src/ideal/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Adyen Checkout Components sample code
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
Back
16 |
17 |
iDEAL Component
18 |
23 |
24 |
25 |
26 | Check the Source Code to see the full implementation.
27 |
28 |
29 | For more information, please refer to the Checkout Components documentation .
30 |
31 |
32 |
33 |
34 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
--------------------------------------------------------------------------------
/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Adyen Checkout Components sample code
8 |
9 |
10 |
11 |
12 |
Adyen Checkout Components sample code
13 |
14 |
15 | Components are our drop-in JavaScript modules that you can add to your payment page.
16 |
17 | They render as input fields that collect required shopper details, and provide the values you need to make a payment.
18 |
19 |
20 |
21 |
65 |
66 |
71 |
72 |
73 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/src/multibanco/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Adyen Checkout Components sample code
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
Back
16 |
17 |
Multibanco Component
18 |
24 |
25 |
26 |
27 | Check the Source Code to see the full implementation.
28 |
29 |
30 | For more information, please refer to the Checkout Components documentation .
31 |
32 |
33 |
34 |
35 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/src/multibanco/multibanco.js:
--------------------------------------------------------------------------------
1 | // 0. Get clientKey
2 | getClientKey().then(clientKey => {
3 | getPaymentMethods().then(async paymentMethodsResponse => {
4 | // 1. Create an instance of AdyenCheckout
5 | const checkout = await AdyenCheckout({
6 | clientKey: clientKey, // Mandatory. clientKey from Customer Area
7 | environment: 'test',
8 | amount: {
9 | currency: 'EUR',
10 | value: 1000
11 | },
12 | onAdditionalDetails: result => {
13 | console.log(result);
14 | },
15 | onError: error => {
16 | console.log(error);
17 | },
18 | onSubmit: initialSubmit,
19 | paymentMethodsResponse
20 | });
21 |
22 | function initialSubmit(state, component) {
23 | makePayment(state.data).then(response => {
24 | component.unmount();
25 | // 3. present the voucher using the action object returned from /payments
26 | checkout.createFromAction(response.action).mount('#multibanco-container');
27 | });
28 | }
29 |
30 | // 2. create Multibanco component
31 | checkout.create('multibanco').mount('#multibanco-container');
32 |
33 | });
34 | });
--------------------------------------------------------------------------------
/src/sepa/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Adyen Checkout Components sample code
8 |
9 |
10 |
11 |
12 |
13 |
14 |
Back
15 |
16 |
17 |
SEPA Direct Debit Component
18 |
23 |
24 |
25 |
36 |
37 |
38 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
--------------------------------------------------------------------------------
/src/sepa/sepa.js:
--------------------------------------------------------------------------------
1 | async function initiateComponent() {
2 | // 1. Create an instance of AdyenCheckout
3 | const checkout = await AdyenCheckout({
4 | environment: 'test',
5 | onChange: (state, component) => {
6 | // state.data;
7 | // state.isValid;
8 |
9 | updateStateContainer(state); // Demo purposes only
10 | }
11 | });
12 |
13 | // 2. Create and mount the Component
14 | const sepa = checkout
15 | .create('sepadirectdebit', {
16 | showPayButton: true,
17 | countryCode: 'NL', // Optional. Sets the default country of the IBAN Placeholder
18 | placeholders: {
19 | // Optional. Overwriting the default placeholders
20 | // ownerName: '',
21 | // ibanNumber: ''
22 | },
23 |
24 | // Events
25 | onSubmit: (state, component) => {
26 | makePayment(state.data);
27 | }
28 | })
29 | .mount('#sepa-container');
30 | }
31 | initiateComponent()
--------------------------------------------------------------------------------
/src/sessions/dropin.js:
--------------------------------------------------------------------------------
1 | getClientKey().then(clientKey => {
2 |
3 | // Check URL for redirectResult and sessionId
4 | const queryResultString = window.location.search;
5 | const urlParams = new URLSearchParams(queryResultString)
6 | const redirectResult = urlParams.get('redirectResult')
7 | const sessionId = urlParams.get('sessionId')
8 |
9 | function initiateSession() {
10 | sessions()
11 | .then(response => {
12 | const configuration = {
13 | environment: 'test', // Change to 'live' for the live environment.
14 | clientKey: clientKey, // Public key used for client-side authentication: https://docs.adyen.com/development-resources/client-side-authentication
15 | session: {
16 | id: response.id, // Unique identifier for the payment session.
17 | sessionData: response.sessionData // The payment session data.
18 | },
19 | onPaymentCompleted: (result, component) => {
20 | console.info(result, component);
21 | updateResponseContainer(result);
22 | },
23 | onError: (error, component) => {
24 | console.error(error.name, error.message, error.stack, component);
25 | },
26 | onChange: (state, component) => {
27 | updateStateContainer(state); // Demo purposes only
28 | },
29 | beforeSubmit: (data, component, actions) => {
30 | updateRequestContainer(data);
31 | actions.resolve(data);
32 | },
33 | // Any payment method specific configuration. Find the configuration specific to each payment method: https://docs.adyen.com/payment-methods
34 | // For example, this is 3D Secure configuration for cards:
35 | paymentMethodsConfiguration: {
36 | card: {
37 | // Optional configuration
38 | hasHolderName: true,
39 | holderNameRequired: true
40 | }
41 | }
42 | };
43 | async function initiateCheckout() {
44 | // Create an instance of AdyenCheckout using the configuration object.
45 | const checkout = await AdyenCheckout(configuration);
46 |
47 | // Create an instance of Drop-in and mount it to the container you created.
48 | const dropinComponent = checkout.create('dropin', {
49 | onSelect: activeComponent => {
50 | if (activeComponent.state && activeComponent.state.data) updateStateContainer(activeComponent.data); // Demo purposes only
51 | }
52 | }).mount('#dropin-container');
53 | }
54 | initiateCheckout()
55 | })
56 | }
57 |
58 | async function handleRedirect() {
59 | const configuration = {
60 | environment: 'test', // Change to 'live' for the live environment.
61 | clientKey: clientKey, // Public key used for client-side authentication: https://docs.adyen.com/development-resources/client-side-authentication
62 | session: {
63 | id: sessionId, // Retreived identifier for the payment completion on redirect.
64 | },
65 | onPaymentCompleted: (result, component) => {
66 | console.info(result)
67 | const paymentResult = result.resultCode
68 | if (paymentResult === 'Authorised' || paymentResult === 'Received') {
69 | document.getElementById('result-container').innerHTML = ' ';
70 |
71 | } else {
72 | document.getElementById('result-container').innerHTML = ' '
73 | }
74 | updateResponseContainer(result);
75 | },
76 | onError: (error, component) => {
77 | console.error(error.name, error.message, error.stack, component);
78 | },
79 | };
80 | // Create an instance of AdyenCheckout to handle the shopper returning to your website.
81 | // Configure the instance with the sessionId you extracted from the returnUrl.
82 | const checkout = await AdyenCheckout(configuration);
83 | // Submit the redirectResult value you extracted from the returnUrl.
84 | checkout.submitDetails({ details: { redirectResult } });
85 | }
86 |
87 | // If no paramters are present in the URL, mount the Drop-in
88 | if (!redirectResult && !sessionId) {
89 | initiateSession()
90 | // Otherwise, handle the redirect
91 | } else {
92 | handleRedirect()
93 | }
94 | })
--------------------------------------------------------------------------------
/src/sessions/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Adyen Checkout Components sample code
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
Back
16 |
17 |
Sessions Drop-in
18 |
24 |
25 |
26 |
27 |
28 | Check the Source Code to see the full implementation.
29 |
30 |
31 | To make a payment, use our test card numbers .
32 |
33 |
34 | For more information, please refer to the Drop-in documentation .
35 |
36 |
37 |
38 |
39 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/src/swish/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Adyen Checkout Components sample code
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
Back
16 |
17 |
Swish Component
18 |
23 |
24 |
25 |
26 | Check the Source Code to see the full implementation.
27 |
28 |
29 | For more information, please refer to the Checkout Components documentation .
30 |
31 |
32 |
33 |
34 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
--------------------------------------------------------------------------------
/src/swish/swish.js:
--------------------------------------------------------------------------------
1 | // 0. Get clientKey
2 | getClientKey().then(async clientKey => {
3 | // 1. Create an instance of AdyenCheckout
4 | const checkout = await AdyenCheckout({
5 | clientKey: clientKey, // Mandatory. clientKey from Customer Area
6 | environment: 'test',
7 | amount: {
8 | currency: 'EUR',
9 | value: 1000
10 | },
11 | onAdditionalDetails: result => {
12 | console.log(result);
13 | },
14 | onError: error => {
15 | console.log(error);
16 | }
17 | });
18 |
19 | const swishData = {
20 | paymentMethod: {
21 | type: 'swish'
22 | },
23 | countryCode: 'SE',
24 | amount: {
25 | currency: 'SEK',
26 | value: 10000
27 | }
28 | };
29 |
30 | makePayment(swishData).then(response => {
31 | checkout.createFromAction(response.action).mount('#swish-container');
32 | });
33 | });
--------------------------------------------------------------------------------
/src/utils.js:
--------------------------------------------------------------------------------
1 | // Function to set returnUrl, for standard Drop-in and Components, return to placeholder,
2 | // else redirect back to sessions where we handle the redirectResult
3 | function setReturnUrl() {
4 | if (window.location.pathname === '/sessions/') {
5 | return window.location.href
6 | } else {
7 | return window.location.href;//'https://your-company.com/'
8 | }
9 | }
10 |
11 | const paymentMethodsConfig = {
12 | shopperReference: 'Checkout Components sample code test',
13 | reference: 'Checkout Components sample code test',
14 | countryCode: 'NL',
15 | amount: {
16 | value: 1000,
17 | currency: 'EUR'
18 | }
19 | };
20 |
21 | const paymentsDefaultConfig = {
22 | shopperReference: 'Checkout Components sample code test',
23 | reference: 'Checkout Components sample code test',
24 | countryCode: 'NL',
25 | channel: 'Web',
26 | returnUrl: setReturnUrl(),
27 | amount: {
28 | value: 1000,
29 | currency: 'EUR'
30 | },
31 | lineItems: [
32 | {
33 | id: '1',
34 | description: 'Test Item 1',
35 | amountExcludingTax: 10000,
36 | amountIncludingTax: 11800,
37 | taxAmount: 1800,
38 | taxPercentage: 1800,
39 | quantity: 1,
40 | taxCategory: 'High'
41 | }
42 | ]
43 | };
44 |
45 | // Generic POST Helper
46 | const httpPost = (endpoint, data) =>
47 | fetch(`/${endpoint}`, {
48 | method: 'POST',
49 | headers: {
50 | Accept: 'application/json, text/plain, */*',
51 | 'Content-Type': 'application/json'
52 | },
53 | body: JSON.stringify(data)
54 | }).then(response => response.json());
55 |
56 | // Get all available payment methods from the local server
57 | const getPaymentMethods = (config = {}) =>
58 | httpPost('paymentMethods', { ...paymentMethodsConfig, ...config })
59 | .then(response => {
60 | if (response.error) throw 'No paymentMethods available';
61 |
62 | return response;
63 | })
64 | .catch(console.error);
65 |
66 | // Posts a new payment into the local server
67 | const makePayment = (paymentMethod, config = {}) => {
68 | const paymentsConfig = { ...paymentsDefaultConfig, ...config };
69 | const paymentRequest = { ...paymentsConfig, ...paymentMethod };
70 |
71 | updateRequestContainer(paymentRequest);
72 |
73 | return httpPost('payments', paymentRequest)
74 | .then(response => {
75 | if (response.error) throw 'Payment initiation failed';
76 |
77 | alert(response.resultCode);
78 | updateResponseContainer(response);
79 |
80 | return response;
81 | })
82 | .catch(console.error);
83 | };
84 |
85 | const handleAdditionalDetails = (details, component) => {
86 |
87 | updateRequestContainer(details.data);
88 |
89 | return httpPost('details', details.data)
90 | .then(response => {
91 | if (response.error) throw 'Details call failed';
92 |
93 | alert(response.resultCode);
94 | updateResponseContainer(response);
95 |
96 | return response;
97 | })
98 | .catch(console.error);
99 | };
100 |
101 | // Posts a new payment into the local server
102 | const sessions = (paymentMethod, config = {}) => {
103 | const paymentsConfig = { ...paymentsDefaultConfig, ...config };
104 | const sessionRequest = { ...paymentsConfig, ...paymentMethod };
105 |
106 | return httpPost('sessions', sessionRequest)
107 | .then(response => {
108 | if (response.error) throw 'Payment initiation failed';
109 | return response;
110 | })
111 | .catch(console.error);
112 | };
113 |
114 |
115 | // Fetches an originKey from the local server
116 | const getOriginKey = () =>
117 | httpPost('originKeys')
118 | .then(response => {
119 | if (response.error || !response.originKeys) throw 'No originKey available';
120 |
121 | return response.originKeys[Object.keys(response.originKeys)[0]];
122 | })
123 | .catch(console.error);
124 |
125 | // Fetches a clientKey from the
126 | const getClientKey = () =>
127 | httpPost('clientKeys')
128 | .then(response => {
129 | if (response.error || !response.clientKey) throw 'No clientKey available';
130 |
131 | return response.clientKey;
132 | })
133 | .catch(console.error);
134 |
135 | const getSearchParameters = (search = window.location.search) =>
136 | search
137 | .replace(/\?/g, '')
138 | .split('&')
139 | .reduce((acc, cur) => {
140 | const [key, prop = ''] = cur.split('=');
141 | acc[key] = decodeURIComponent(prop);
142 | return acc;
143 | }, {});
--------------------------------------------------------------------------------
/src/wechatpay/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Adyen Checkout Components sample code
8 |
9 |
10 |
11 |
12 |
13 |
14 |
Back
15 |
16 |
17 |
WeChat Pay Component
18 |
23 |
24 |
25 |
29 |
30 |
31 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/src/wechatpay/wechatpay.js:
--------------------------------------------------------------------------------
1 | // 0. Get clientKey
2 | getClientKey().then(async clientKey => {
3 | // 1. Create an instance of AdyenCheckout providing the clientKey
4 | const checkout = await AdyenCheckout({
5 | environment: 'test',
6 | clientKey: clientKey, // Mandatory. clientKey from Customer Area
7 | amount: {
8 | currency: 'CNY',
9 | value: 1000
10 | }, // amount to be shown next to the qrcode
11 | onAdditionalDetails: state => {
12 | console.log(state.data);
13 | },
14 | onError: error => {
15 | console.log(error);
16 | }
17 | });
18 |
19 | // Override our default demo config for this payment method
20 | const wechatData = {
21 | countryCode: 'CN',
22 | amount: {
23 | value: 1000,
24 | currency: 'CNY'
25 | },
26 | paymentMethod: {
27 | type: 'wechatpayQR'
28 | }
29 | };
30 |
31 | /** Call the /payments endpoint to retrieve the necessary data to start the Wechat Pay component
32 | * We need the following parts of the response
33 | * - qrCodeData (redirect.data.qrCodeData): The data the QR Code will contain
34 | * - paymentData Necessary to communicate with Adyen to check the current payment status
35 | */
36 | makePayment(wechatData).then(response => {
37 | if (!!response.action) {
38 | // 2. Create and mount the Component from the action received
39 | const wechatpay = checkout.createFromAction(response.action).mount('#wechatpay-container');
40 | }
41 | });
42 | });
--------------------------------------------------------------------------------
/start.sh:
--------------------------------------------------------------------------------
1 | ./server/php/start.sh
2 |
--------------------------------------------------------------------------------