mirror of
https://github.com/jlengrand/vanilla-js.git
synced 2026-03-10 00:41:19 +00:00
Starting repo
This commit is contained in:
24
.gitignore
vendored
Normal file
24
.gitignore
vendored
Normal 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
9899
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
38
package.json
Normal file
38
package.json
Normal 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
34
public/adyen.js
Normal 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
38
public/index.html
Normal 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
34
rollup.config.js
Normal 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
175
server.js
Normal 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()}`));
|
||||
Reference in New Issue
Block a user