forked from AdeyinkaAdegbenro/Rapyd_Ecommerce
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserver.js
More file actions
107 lines (85 loc) · 3.46 KB
/
Copy pathserver.js
File metadata and controls
107 lines (85 loc) · 3.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
const axios = require("axios");
const bodyParser = require("body-parser");
const crypto = require("crypto");
require("dotenv").config();
const express = require("express");
const products = require("./products.json");
const { v4: uuidv4 } = require("uuid");
const app = express();
app.set("view engine", "ejs")
app.use(bodyParser.json());
app.use(express.static("public")); // Serve frontend assets
const RAPYD_ACCESS_KEY = process.env.RAPYD_ACCESS_KEY;
const RAPYD_SECRET_KEY = process.env.RAPYD_SECRET_KEY;
const RAPYD_BASE_URL = process.env.RAPYD_BASE_URL;
// Function to generate Rapyd API signature
function generateSignature(httpMethod, urlPath, body = "") {
const salt = crypto.randomBytes(8).toString("hex"); // 16-char salt
const timestamp = Math.round(new Date().getTime() / 1000); // Current UNIX timestamp (in seconds)
// Ensure body is a valid JSON string
const bodyString = body && Object.keys(body).length ? JSON.stringify(body) : "";
// Correct order of concatenation (NO spaces)
const toSign = httpMethod.toLowerCase() + urlPath + salt + timestamp + RAPYD_ACCESS_KEY + RAPYD_SECRET_KEY + bodyString;
// Create HMAC-SHA256 signature
const hash = crypto.createHmac("sha256", RAPYD_SECRET_KEY);
hash.update(toSign);
// Convert signature to Base64
const base64Signature = Buffer.from(hash.digest("hex")).toString("base64");
return { signature: base64Signature, salt, timestamp };
}
// Display products
app.get("/", (req, res) => {
res.render("index", { products });
});
// Load checkout page for product
app.get("/buy", (req, res) => {
const { productId, amount, currency } = req.query;
console.log({ productId, amount, currency })
res.render("checkout", { productId, amount, currency });
});
// Payment Success Page
app.get("/success", (req, res) => {
console.log('Payment succeeded...')
res.send("Payment Successful")
});
// Payment Success Page
app.get("/fail", (req, res) => {
console.log('Payment failed...')
res.send("Payment Failure")
});
app.post("/api/webhook", (req, res) => {
console.log('Webhook called...', req.body.type, req.body.payment_method_data)
res.send("OK")
});
// Route to create a payment checkout page
app.post("/create-checkout", async (req, res) => {
const { amount, currency } = req.body;
const body = {
amount: amount.toString(),
currency: currency,
country: 'SG', // change as the case may be
complete_payment_url: "http://localhost:3000/success",
error_payment_url: "http://localhost:3000/fail"
};
const { signature, salt, timestamp } = generateSignature("post", "/v1/checkout", body);
const idempotencyKey = uuidv4();
try {
const response = await axios.post(`${RAPYD_BASE_URL}/v1/checkout`, body, {
headers: {
"Content-Type": "application/json",
"access_key": RAPYD_ACCESS_KEY,
"idempotency": idempotencyKey,
"salt": salt,
"timestamp": timestamp,
"signature": signature
}
});
console.log("Rapyd's response", response.data.data)
res.json({ checkout_url: response.data.data.redirect_url, checkout_id: response.data.data.id});
} catch (error) {
console.log("Rapyd's response", error.message)
res.status(400).json({ error: error.response.data });
}
});
// Start server
app.listen(3000, () => console.log("Server running on port 3000"));