-
Couldn't load subscription status.
- Fork 0
Home
METADATEN
Modul: Web Technologien (MMI Master)
Entstehungsjahr: 2018
Autor: Anatol Walger
Keywords: w3c payment request api, tutorial, node.js, kreditkarte
Zielgruppe: Das Tutorial richtet sich an alle, die auf ihrer Webseite Bezahlprozesse abwickeln wollen. Dies sind in erster Linie Unternehmen mit Online-Shops, Crowdfunding-Seiten, Spenden-Seiten.. Überall wo es nötig ist, persönliche Daten + Zahlungsdaten immer wieder neu einzugeben. Natürlich können auch Early Adopter und Technikbegeisterte teilnehmen, die einfach neue Technologien ausprobieren wollen.
Beschreibung: Gegenstand des Tutorials ist die W3C Payment Request API, die am besten in Google Chrome funktioniert und dabei hilft, Zahlungen schneller und eleganter zu tätigen. Ziel soll sein, selber einen Payment Request mit unterstützten Zahlungsmethoden, benötigten Daten des Benutzers und weiteren Parametern (Gesamtsumme, Rabatte) zu erstellen, sodass der Browser einen entsprechenden Payment-Dialog mit den Daten präsentiert, wobei man dann über einen vorher aufgesetzten node.js Server die Zahlung virtuell abwickelt. Ebenso sollen Fälle abgedeckt werden, in denen der Browser keine unterstützte Zahlungsmethode hat oder noch weitere Informationen vom Benutzer notwendig sind (neue bzw. andere Lieferadresse).
Voraussetzungen:
- Grundkenntnisse in Javascript, HTML, CSS
- Erste Erfahrungen mit node.js
- bestenfalls Browser Google Chrome (Version >64)
- Computer/Mac
- Kreditkarte
Herzlich Willkommen zum Tutorial, das Ihnen das W3C Payment Request API näher bringen soll. Mithilfe der nachfolgenden Anweisungen soll es Ihnen so leicht wie möglich gemacht werden, einen node.js Server und die HTML-Webseite für die Ausführung des Payment Requests aufzusetzen.
Wir konfigurieren einen node.js Server, um die persönlichen Daten und Zahlungsdaten vom Benutzer, welche vom Browser durch das Payment Request API gesendet werden, zu empfangen. Somit ist es möglich, einen Erfolgshinweis und auch die empfangenen Daten nochmals anzuzeigen.
Zur Installation von node.js muss der Installer von dieser Webseite heruntergeladen werden. Es sollte die "LTS"-Version genutzt werden, da sie auf einem stabilen Build basiert. Neuere Funktionen sind nicht notwendig.
Ebenso muss mongoDB installiert werden. Dazu die .tgz-Datei von dieser Webseite herunterladen und mit folgenden Befehlen installieren (zunächst mit cd in das entsprechende Verzeichnis wechseln):
tar -zxvf mongodb-osx-x86_64-3.6.5.tgz
mkdir -p mongodb
cp -R -n mongodb-osx-x86_64-3.6.5/ mongodb
Danach muss noch ein Ordner für die mongodb im Root-Verzeichnis angelegt werden, wobei man sich als Benutzer die Zugriffsrechte darauf gibt. Dazu folgende Befehle ausführen:
sudo mkdir -p /data/db/
sudo chown `id -u` /data/db
Nach der Installation von node.js muss eine Ordnerstruktur angelegt werden. Diese sieht wie folgt aus:
- server/
- server.js // konfiguriert den Server und definiert die Routen
- index.html // hier kommt der Code für den Payment Request hinein
Im Terminal lassen sich Ordner mit mkdir und Dateien mit touch anlegen.
Nachdem alle Ordner und Dateien angelegt sind, mit cd in den Ordner server navigieren und mit dem Befehl npm init eine package.json erstellen. Bei der Abfrage den Namen "payment-server" eingeben, alle anderen Abfragen mit der Eingabetaste bestätigen.
Danach mit dem Befehl npm install express body-parser --save die nötigen Abhängigkeiten installieren, wobei diese automatisch in die package.json übernommen werden. Wir definieren mit express die Middleware, die uns später das Definieren von Routen erleichtert. Der body-parser ermöglicht uns, den Body einer HTTP-Anfrage auszulesen. Somit kann der POST-Request für die Duchführung einer Zahlung verwaltet werden.
Nun wird die server.js mit Code befüllt. Dazu den nachfolgenden Code in die Datei einfügen:
// Abhängigkeiten definieren
var express = require('express');
var server = express(); // express an die Variable "server" binden
var bodyParser = require('body-parser');
var MongoClient = require('mongodb').MongoClient // Variable für Datenbank-Client
var path = require("path");
var db; // Variable für Datenbank definieren
// bodyparser konfigurieren
server.use(bodyParser.urlencoded({
extended: true
}));
server.use(bodyParser.json());
var router = express.Router(); // Instanz des express Routers
server.use('/', router); // Router konfigurieren
router.get('/', (req, res) => {
res.sendFile(path.join(__dirname + '/index.html'));
})
router.post('/payment', (req, res) => {
db.collection('payment').save(req.body, (err, result) => {
if (err) return console.log(err)
console.log('saved to database')
res.status(201).json(req.body);
})
});
MongoClient.connect('mongodb://localhost:27017/paymentDb', (err, client) => {
if (err) return console.log(err)
db = client.db('paymentDb')
server.listen(8080, () => {
console.log("Server starten mit localhost:8080");
});
});
Damit der Server laufen kann, muss zunächst in einem anderen Terminal-Fenster die mongoDb gestartet werden. Dies erfolgt der Einfachheit halber direkt über die heruntergeladene Datei (bsp: /Users/<Benutzername>/Downloads/mongodb/bin/mongod). Diese Datei in das Terminal-Fenster ziehen, um den Dateipfad zu erhalten.
Wenn die Datenbank geladen ist, kann der Server nach Navigation mit cd in den Ordner server mit node server.js gestartet werden. Dieser ist jetzt über die Eingabe von localhost:8080 in einem beliebigen Browser erreichbar.
Nun muss die index.html mit einem beliebigen Editor geöffnet und mit folgendem Code befüllt werden:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title>W3C Payment Request API Tutorial</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
* {
margin: 0;
}
html {
font-family: sans-serif;
line-height: 1.4;
padding: 2em;
}
body> :not(:first-child) {
margin-top: 1.5em;
}
h1,
h2 {
line-height: 1.15;
}
.produkt {
max-width: 13em;
padding: 1em;
background: #fff;
}
.produkt> :not(:first-child) {
margin-top: 0.85em;
}
.produkt_bought {
padding: 1em;
background: #fff;
}
.data_list {
max-width: 100%;
}
.produkt_bought> :not(:first-child) {
margin-top: 0.85em;
}
.produkt_bought {
display: none;
}
.produkt_shadow {
position: relative;
-webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
}
.produkt_shadow:after {
content: "";
position: absolute;
z-index: -1;
-webkit-box-shadow: 0 0 40px rgba(0, 0, 0, 0.8);
box-shadow: 0 0 40px rgba(0, 0, 0, 0.8);
bottom: 0px;
left: 10%;
right: 10%;
width: 80%;
height: 50%;
-moz-border-radius: 100%;
border-radius: 100%;
}
.produkt_meta {
display: flex;
align-items: center;
justify-content: space-between;
}
.produkt_button {
background-color: #008CBA;
color: #fff;
padding: 0.25em 1em;
text-decoration: none;
}
</style>
</head>
<body>
<h1>W3C Payment Request API Tutorial</h1>
<p> Teil 1: Einfacher Payment Request </p>
<div class="produkt produkt_shadow" id="produkt">
<h2>Beispielprodukt</h2>
<p>Ich bin ein ganz tolles Produkt! Kauf mich!</p>
<div class="produkt_meta">
<strong class="produkt_preis">nur 49.99 €</strong>
<a href="#" id="produkt_button" class="produkt_button">Kaufen</a>
</div>
</div>
<div class="produkt_bought" id="produkt_bought">
<h2>Beispielprodukt gekauft!</h2>
<p>Sie haben das Beispielprodukt erfolgreich für 49,99 € gekauft.</p>
<p>Ihre Daten:</p>
<div id="data_list"></div>
</div>
<script>
function handleProduktClick(e) {
e.preventDefault();
const creditCardPaymentMethod = {
supportedMethods: 'basic-card',
};
const supportedPaymentMethods = [creditCardPaymentMethod];
const paymentDetails = {
total: {
label: 'Beispielprodukt',
amount: {
currency: 'EUR',
value: 49.99
}
}
};
var paymentRequest = new PaymentRequest(supportedPaymentMethods, paymentDetails);
paymentRequest
.show()
.then(paymentResponse => {
return verifyPaymentWithBackend(paymentResponse).then((success) => {
if (success) {
showPaymentResponse(success);
return paymentResponse.complete('success');
} else {
return paymentResponse.complete('fail');
}
});
})
.catch(err => {
console.log('Error:', err);
});
};
function showPaymentResponse(data) {
document.getElementById("produkt_button").innerHTML = 'Gekauft';
document.getElementById("produkt_button").style.backgroundColor = "#4CAF50";
document.getElementById("produkt_button").removeEventListener('click', handleProduktClick);
document.getElementById("produkt_bought").style.display = "block";
document.getElementById("data_list").innerHTML = data;
}
function verifyPaymentWithBackend(data) {
return new Promise((resolve, reject) => {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onload = function() {
if (xmlhttp.status == 201) {
resolve(xmlhttp.responseText);
} else {
resolve(false)
}
};
xmlhttp.open("POST", "/payment");
xmlhttp.setRequestHeader("Content-Type", "application/json");
xmlhttp.send(JSON.stringify(data));
});
}
document.getElementById("produkt_button").addEventListener('click', handleProduktClick)
</script>
</body>
</html>
Wir gehen die index.html nun Schritt für Schritt durch.
Zunächst werden die üblichen HTML-Tags und Metadaten gesetzt, dann der viewport für die mobile Ansicht. Es folgt das CSS-Styling für die Seite und deren Elemente. Da dies nicht Teil des Tutorials ist, wird nicht weiter darauf eingegangen. Danach folgt der HTML-Code für das Produkt. Das Produkt ist in einem div-Element eingefasst, das eine Überschrift und Produktbeschreibung enthält. Ein weiteres Div ist für den Preis und den "Kaufen"-Button integriert.
Es folgt der Javascript-Code, in dem wir schließlich den PaymentRequest zusammenbauen. Wir beginnen dort mit der Funktion handleProduktClick(e) {}, die durch Klicken auf den Button "Kaufen" gestartet wird. Der entsprechende Event Listener dafür ist weiter unten definiert mit document.getElementById("produkt_button").addEventListener('click', handleProduktClick).
Die Funktion handleProduktClick(e) {} enthält den kompletten Code für den PaymentRequest. Dort wird die Zahlungsmethode per Kreditkarte definiert mit
var creditCardPaymentMethod = {
supportedMethods: 'basic-card',
};
Dies bedeutet, dass wir alle Kreditkarten unterstützten wollen, also auch Prepaid-Kreditkarten, Kreditkarten von Visa, MasterCard etc. Die Variable ist bewusst so genannt, um später weitere Zahlungsmethoden anlegen zu können, die dann in dem Array supportedPaymentMethods hinterlegt werden, was aktuell die obige Zahlungsmethode enthält:
var supportedPaymentMethods = [creditCardPaymentMethod];
Weiter geht es mit den paymentDetails, worin der Gesamtpreis, die Währung, der Einzelpreis und der Name des Produktes eingetragen werden. Diese Informationen sind später auch im PaymentRequest sichtbar.
var paymentDetails = {
total: {
label: 'Beispielprodukt',
amount: {
currency: 'EUR',
value: 49.99
}
}
};
Es folgt schließlich die Definition der Variable paymentRequest, die eines Instanz des PaymentRequests mit obiger Konfiguration definiert.
var paymentRequest = new PaymentRequest(supportedPaymentMethods, paymentDetails);
Danach wird das PaymentRequest-Fenster mit der show()-Methode angezeigt und es wird definiert, was im Erfolgs- bzw. Fehlerfall passieren soll. show() definiert einen Promise, der im Erfolgsfall das Objekt paymentResponse enthält, mit allen Daten, die der Nutzer in das PaymentRequest-Fenster eingegeben hat. Sollte es einen Fehler bei der Rückgabe des paymentResponse geben, wird im PaymentRequest-Fenster der entsprechende Fehler angezeigt return paymentResponse.complete('fail');. Sollte der Benutzer das Fenster schließen oder ein sonstiger Fehler auftreten, wird in den Bereich .catch(err => {}) gesprungen und der Fehler in der Konsole ausgegeben.
paymentRequest
.show()
.then(paymentResponse => {
return verifyPaymentWithBackend(paymentResponse).then((success) => {
if (success) {
showPaymentResponse(success);
return paymentResponse.complete('success');
} else {
return paymentResponse.complete('fail');
}
});
})
.catch(err => {
console.log('Error:', err);
});
};
Die Methode verifyPaymentWithBackend(paymentResponse) ist dazu da, die eingegebenen Daten des Benutzers im PaymentRequest-Fenster an den Server zu schicken. Dies funktioniert durch ein XMLHTTPREQUEST, das die Daten an die vorher definierte Ressource /payment sendet. Sollte, wie bei einem POST üblich, der Statuscode 201 zurückkommen, wurde die Ressource erfolgreich angelegt und die Daten zur Zahlung in der Datenbank gespeichert. Um den Erfolgsfall an den PaymentRequest zurückzugeben, "resolven" wir den Promise und geben als Parameter die Antwort des Servers mit, um die Daten später anzeigen zu können. Im Fehlerfall gibt der Resolve ein false zurück, um eine Fehlermeldung im PaymentRequest auszulösen.
function verifyPaymentWithBackend(data) {
return new Promise((resolve, reject) => {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onload = function() {
if (xmlhttp.status == 201) {
resolve(xmlhttp.responseText);
} else {
resolve(false)
}
};
xmlhttp.open("POST", "/payment");
xmlhttp.setRequestHeader("Content-Type", "application/json");
xmlhttp.send(JSON.stringify(data));
});
}
Schließlich wird die Methode showPaymentResponse(data) ausgeführt, die einige UI-Elemente verändert, um eine erfolgreiche Zahlung darzustellen. Um das Tutorial nicht unnötig kompliziert werden zu lassen, wurde auf eine Single-Page Application z.B. mit vue.js verzichtet. Ebenso existiert keine Nutzer-Authentifizierung, um eine Zahlung später einem bestimmten Benutzer zuzuordnen.
In der showPaymentResponse(data) wird der Text vom Produkt-Button von "Kaufen" in "Gekauft" geändert, außerdem dessen Hintergrund verändert und der Event Listener entfernt, um einen weiteren Kauf bis zum erneuten Laden der Seite zu verhindern. In der data_list wird anschließend das JSON-Objekt vom Server zurückgegeben, das die eingegebenen Daten des Benutzers enthält.
function showPaymentResponse(data) {
document.getElementById("produkt_button").innerHTML = 'Gekauft';
document.getElementById("produkt_button").style.backgroundColor = "#4CAF50";
document.getElementById("produkt_button").removeEventListener('click', handleProduktClick);
document.getElementById("produkt_bought").style.display = "block";
document.getElementById("data_list").innerHTML = data;
}
Wenn die index.html entsprechend definiert wurde, kann unter der URL localhost:8080 die Seite idealerweise im Browser Google Chrome aufgerufen werden.