Starting repo

This commit is contained in:
Julien Lengrand-Lambert
2022-08-08 22:47:10 +02:00
commit 43b442eb5b
7 changed files with 10242 additions and 0 deletions

24
.gitignore vendored Normal file
View File

@@ -0,0 +1,24 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# production
/build
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
.env
npm-debug.log*
yarn-debug.log*
yarn-error.log*

9899
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

38
package.json Normal file
View File

@@ -0,0 +1,38 @@
{
"name": "vanilla",
"version": "1.0.0",
"description": "",
"main": "server.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node server.js",
"dev": "nodemon index",
"build": "rollup -c rollup.config.js"
},
"dependencies": {
"@adyen/adyen-web": "^5.21.0",
"@adyen/api-library": "^11.0.0",
"ansi-regex": "^6.0.1",
"dot-prop": "^7.2.0",
"dotenv": "^16.0.1",
"express": "^4.18.1",
"express-handlebars": "^6.0.6",
"minimist": "^1.2.6",
"morgan": "^1.10.0",
"node-gyp": "^9.0.0",
"undefsafe": "~2.0.5",
"uuidv4": "^6.2.13"
},
"devDependencies": {
"@babel/core": "^7.18.10",
"@babel/preset-env": "^7.18.10",
"@rollup/plugin-babel": "^5.3.1",
"@rollup/plugin-commonjs": "^22.0.2",
"@rollup/plugin-node-resolve": "^13.3.0",
"babel-loader": "^8.2.5",
"nodemon": "^2.0.18",
"rollup": "^2.77.2"
},
"author": "",
"license": "ISC"
}

34
public/adyen.js Normal file
View File

@@ -0,0 +1,34 @@
import AdyenCheckout from '@adyen/adyen-web';
// import '@adyen/adyen-web/dist/adyen.css';
const configuration = {
environment: 'test', // Change to 'live' for the live environment.
clientKey: 'test_LETB6D7TMZCIZFSNMDRGMEPJ3UVB2TYP', // Public key used for client-side authentication: https://docs.adyen.com/development-resources/client-side-authentication
onPaymentCompleted: (result, component) => {
console.info(result, component);
},
onError: (error, component) => {
console.error(error.name, error.message, error.stack, component);
},
paymentMethodsConfiguration: {
card: {
hasHolderName: true,
holderNameRequired: true,
billingAddressRequired: true
}
}
};
console.log(configuration.clientKey);
try{
// Create an instance of AdyenCheckout using the configuration object.
const checkout = await AdyenCheckout(configuration);
// Create an instance of Drop-in and mount it to the container you created.
checkout.create('dropin').mount('#dropin-container');
}catch(error){
console.log(error);
}

38
public/index.html Normal file
View File

@@ -0,0 +1,38 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
<meta name="Description" content="Put your description here.">
<base href="/">
<style>
html,
body {
margin: 0;
padding: 0;
font-family: sans-serif;
background-color: #ededed;
}
#dropin-container {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
</style>
<title>Adyen Web</title>
</head>
<body>
<h1>Adyen Web simple demo</h1>
<div id="dropin-container"></div>
https://stackoverflow.com/questions/52612446/importing-a-package-in-es6-failed-to-resolve-module-specifier-vue
<script type="module" src="./dist/adyen.js"></script>
</body>
</html>

34
rollup.config.js Normal file
View File

@@ -0,0 +1,34 @@
import nodeResolve from '@rollup/plugin-node-resolve';
import babel from '@rollup/plugin-babel';
// import css from "rollup-plugin-import-css";
import commonjs from '@rollup/plugin-commonjs';
export default {
input: 'public/adyen.js',
output: {
dir: 'public/dist',
format: 'es'
},
plugins: [
nodeResolve(),
// css(),
// commonjs(),
babel({
presets: [
[
require.resolve('@babel/preset-env'),
{
targets: [
'last 3 Chrome major versions',
'last 3 Firefox major versions',
'last 3 Edge major versions',
'last 3 Safari major versions',
],
modules: false,
bugfixes: true,
},
],
]
}),
],
};

175
server.js Normal file
View File

@@ -0,0 +1,175 @@
const express = require("express");
const path = require("path");
const hbs = require("express-handlebars");
const dotenv = require("dotenv");
const morgan = require("morgan");
const { uuid } = require("uuidv4");
const { hmacValidator } = require('@adyen/api-library');
const { Client, Config, CheckoutAPI } = require("@adyen/api-library");
// init app
const app = express();
// setup request logging
app.use(morgan("dev"));
// Parse JSON bodies
app.use(express.json());
// Parse URL-encoded bodies
app.use(express.urlencoded({ extended: true }));
// Serve client from build folder
app.use(express.static(path.join(__dirname, "/public")));
// enables environment variables by
// parsing the .env file and assigning it to process.env
dotenv.config({
path: "./.env",
});
// Adyen Node.js API library boilerplate (configuration, etc.)
const config = new Config();
config.apiKey = process.env.ADYEN_API_KEY;
const client = new Client({ config });
client.setEnvironment("TEST"); // change to LIVE for production
const checkout = new CheckoutAPI(client);
/* ################# API ENDPOINTS ###################### */
// Invoke /sessions endpoint
app.post("/api/sessions", async (req, res) => {
try {
// unique ref for the transaction
const orderRef = uuid();
// Allows for gitpod support
const localhost = req.get('host');
// const isHttps = req.connection.encrypted;
const protocol = req.socket.encrypted? 'https' : 'http';
// Ideally the data passed here should be computed based on business logic
const response = await checkout.sessions({
amount: { currency: "EUR", value: 1000 }, // value is 10€ in minor units
countryCode: "NL",
merchantAccount: process.env.ADYEN_MERCHANT_ACCOUNT, // required
reference: orderRef, // required: your Payment Reference
returnUrl: `${protocol}://${localhost}/api/handleShopperRedirect?orderRef=${orderRef}` // set redirect URL required for some payment methods
});
res.json(response);
} catch (err) {
console.error(`Error: ${err.message}, error code: ${err.errorCode}`);
res.status(err.statusCode).json(err.message);
}
});
// Handle all redirects from payment type
app.all("/api/handleShopperRedirect", async (req, res) => {
// Create the payload for submitting payment details
const redirect = req.method === "GET" ? req.query : req.body;
const details = {};
if (redirect.redirectResult) {
details.redirectResult = redirect.redirectResult;
} else if (redirect.payload) {
details.payload = redirect.payload;
}
try {
const response = await checkout.paymentsDetails({ details });
// Conditionally handle different result codes for the shopper
switch (response.resultCode) {
case "Authorised":
res.redirect("/result/success");
break;
case "Pending":
case "Received":
res.redirect("/result/pending");
break;
case "Refused":
res.redirect("/result/failed");
break;
default:
res.redirect("/result/error");
break;
}
} catch (err) {
console.error(`Error: ${err.message}, error code: ${err.errorCode}`);
res.redirect("/result/error");
}
});
/* ################# end API ENDPOINTS ###################### */
/* ################# CLIENT SIDE ENDPOINTS ###################### */
// Index (select a demo)
app.get("/", (req, res) => res.render("index"));
// Cart (continue to checkout)
app.get("/preview", (req, res) =>
res.render("preview", {
type: req.query.type,
})
);
// Checkout page (make a payment)
app.get("/checkout", (req, res) =>
res.render("checkout", {
type: req.query.type,
clientKey: process.env.ADYEN_CLIENT_KEY
})
);
// Result page
app.get("/result/:type", (req, res) =>
res.render("result", {
type: req.params.type,
})
);
/* ################# end CLIENT SIDE ENDPOINTS ###################### */
/* ################# WEBHOOK ###################### */
app.post("/api/webhooks/notifications", async (req, res) => {
// YOUR_HMAC_KEY from the Customer Area
const hmacKey = process.env.ADYEN_HMAC_KEY;
const validator = new hmacValidator()
// Notification Request JSON
const notificationRequest = req.body;
const notificationRequestItems = notificationRequest.notificationItems
// Handling multiple notificationRequests
notificationRequestItems.forEach(function(notificationRequestItem) {
const notification = notificationRequestItem.NotificationRequestItem
// Handle the notification
if( validator.validateHMAC(notification, hmacKey) ) {
// Process the notification based on the eventCode
const merchantReference = notification.merchantReference;
const eventCode = notification.eventCode;
console.log('merchantReference:' + merchantReference + " eventCode:" + eventCode);
} else {
// invalid hmac: do not send [accepted] response
console.log("Invalid HMAC signature: " + notification);
res.status(401).send('Invalid HMAC signature');
}
});
res.send('[accepted]')
});
/* ################# end WEBHOOK ###################### */
/* ################# UTILS ###################### */
function getPort() {
return process.env.PORT || 9000;
}
/* ################# end UTILS ###################### */
// Start server
app.listen(getPort(), () => console.log(`Server started -> http://localhost:${getPort()}`));