Skip to content

Commit

Permalink
add stripe endpoint for genesis re
Browse files Browse the repository at this point in the history
  • Loading branch information
GregTrifan committed Feb 26, 2024
1 parent 59527ce commit ae7bbc5
Show file tree
Hide file tree
Showing 6 changed files with 206 additions and 3 deletions.
6 changes: 5 additions & 1 deletion .env.sample
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
INFURA_KEY=
INFURA_KEY=
STRIPE_SECRET_KEY=sk_
STRIPE_PUBLISHABLE_KEY=pk_
STRIPE_WEBHOOK_SECRET=whsec_
STATIC_DIR="https://genesis.re/"
13 changes: 13 additions & 0 deletions contracts/min-Genesis.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
const GENESIS_ADDRESS = "0x3ef61d25b2bf303de52efdd5e50698bed8f9eb8d";
const GENESIS_ABI = [
{
//@ts-ignore
inputs: [],
name: "currentPrice",
outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
stateMutability: "view",
type: "function",
},
];

module.exports = { GENESIS_ADDRESS, GENESIS_ABI };
155 changes: 155 additions & 0 deletions controllers/stripeController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
const { default: Stripe } = require("stripe");
const { GENESIS_ABI, GENESIS_ADDRESS } = require("../contracts/min-Genesis");
const express = require("express");
const { ethers } = require("ethers");
const bodyParser = require("body-parser");
const env = require("dotenv");
env.config({ path: "./.env" });
const router = express.Router();
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY, {
apiVersion: "2023-10-16",
appInfo: {
// For sample support and debugging, not required for production:
name: "Genesis RE",
url: "https://genesis.re/",
version: "1.1.0",
},
});

router.get("/config", (_, res) => {
// Serve checkout page.
res.send({
publishableKey: process.env.STRIPE_PUBLISHABLE_KEY,
});
});

async function convertEthToEur(ethPrice) {
try {
const response = await fetch(
"https://api.coingecko.com/api/v3/simple/price?ids=ethereum&vs_currencies=eur"
);
const data = await response.json();

const eurPrice = ethPrice * data.ethereum.eur;
return eurPrice;
} catch (err) {
console.error(err);
return null;
}
}
async function getCurrentPrice() {
try {
const network = "homestead"; // MAINNET

const provider = new ethers.providers.InfuraProvider(
network,
process.env.INFURA_KEY
);
let GENESIS = new ethers.Contract(GENESIS_ADDRESS, GENESIS_ABI, provider);
let currentPrice = ethers.utils.formatEther(await GENESIS.currentPrice());

const currentPriceEur = await convertEthToEur(Number(currentPrice));
if (currentPriceEur !== null) {
console.log(
"Current price: " + currentPrice + " ETH or " + currentPriceEur + " EUR"
);
return currentPriceEur;
} else {
console.log("Unable to fetch EUR price");
}
} catch (err) {
console.log(err);
}
}
router.get("/create-payment-intent", async (req, res) => {
const price = await getCurrentPrice();
// Create a PaymentIntent with the order amount and currency.
const params = {
amount: Math.round(Number(price * 100)),
currency: "EUR",
automatic_payment_methods: {
enabled: true,
},
};
try {
const paymentIntent = await stripe.paymentIntents.create(params);

// Send publishable key and PaymentIntent client_secret to client.
res.send({
clientSecret: paymentIntent.client_secret,
amount: Math.round(Number(price)),
});
} catch (e) {
res.status(400).send({
error: {
message: e.message,
},
});
}
});
router.get("/create-test-intent", async (req, res) => {
// Create a PaymentIntent with the order amount and currency.
const params = {
amount: 100,
currency: "EUR",
automatic_payment_methods: {
enabled: true,
},
};
try {
const paymentIntent = await stripe.paymentIntents.create(params);

// Send publishable key and PaymentIntent client_secret to client.
res.send({
clientSecret: paymentIntent.client_secret,
amount: 1,
});
} catch (e) {
res.status(400).send({
error: {
message: e.message,
},
});
}
});
router.post(
"/webhook",
// Use body-parser to retrieve the raw body as a buffer.
// @ts-ignore
bodyParser.raw({ type: "application/json" }),
async (req, res) => {
// Retrieve the event by verifying the signature using the raw body and secret.
let event;

try {
event = stripe.webhooks.constructEvent(
req.body,
req.headers["stripe-signature"],
process.env.STRIPE_WEBHOOK_SECRET
);
} catch (err) {
console.log(`⚠️ Webhook signature verification failed.`);
res.sendStatus(400);
return;
}

// Extract the data from the event.
const data = event.data;
const eventType = event.type;

if (eventType === "payment_intent.succeeded") {
// Cast the event into a PaymentIntent to make use of the types.
const pi = data.object;
// Funds have been captured
// Fulfill any orders, e-mail receipts, etc
// To cancel the payment after capture you will need to issue a Refund (https://stripe.com/docs/api/refunds).
console.log("💰 Payment captured!");
} else if (eventType === "payment_intent.payment_failed") {
// Cast the event into a PaymentIntent to make use of the types.
const pi = data.object;
console.log("❌ Payment failed.");
}
res.sendStatus(200);
}
);
module.exports = router;
3 changes: 3 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const ADDRESS_staging = require("./contracts/Address-staging");

const ABI_prod = require("./contracts/ABI-prod");
const ABI_staging = require("./contracts/ABI-staging");
const stripeController = require("./controllers/stripeController");
const evaluationController = require("./controllers/evaluationController");

// Some quirky issue: https://github.com/ethers-io/ethers.js/discussions/4387 (hard to tell why it is required, a dedicated format for events)
Expand Down Expand Up @@ -434,6 +435,8 @@ function _saveOrganisationToDB(

app.use("/", evaluationController);

app.use("/", stripeController);

app.get("/reports", async (req, res) => {
const reportItems = await grabReports();
res.json(reportItems);
Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@
"dotenv": "^16.3.1",
"ethers": "^5.6",
"express": "^4.18.2",
"sqlite3": "^5.1.6"
"sqlite3": "^5.1.6",
"stripe": "^14.18.0"
},
"devDependencies": {
"nodemon": "^3.0.1"
}
}
}
27 changes: 27 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,13 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.33.tgz#8c29a0036771569662e4635790ffa9e057db379b"
integrity sha512-qelS/Ra6sacc4loe/3MSjXNL1dNQ/GjxNHVzuChwMfmk7HuycRLVQN2qNY3XahK+fZc5E2szqQSKUyAF0E+2bg==

"@types/node@>=8.1.0":
version "20.11.20"
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.20.tgz#f0a2aee575215149a62784210ad88b3a34843659"
integrity sha512-7/rR21OS+fq8IyHTgtLkDK949uzsa6n8BkziAKtPVpugIkO6D+/ooXMvzXxDnZrmtXVfjb1bKQafYpb8s89LOg==
dependencies:
undici-types "~5.26.4"

"@vercel/[email protected]":
version "7.4.1"
resolved "https://registry.yarnpkg.com/@vercel/build-utils/-/build-utils-7.4.1.tgz#5274e79e6ec64606cf262bb43108e028212825cb"
Expand Down Expand Up @@ -2150,6 +2157,13 @@ [email protected]:
dependencies:
side-channel "^1.0.4"

qs@^6.11.0:
version "6.11.2"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.2.tgz#64bea51f12c1f5da1bc01496f48ffcff7c69d7d9"
integrity sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==
dependencies:
side-channel "^1.0.4"

queue-microtask@^1.2.2:
version "1.2.3"
resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
Expand Down Expand Up @@ -2420,6 +2434,14 @@ strip-json-comments@~2.0.1:
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==

stripe@^14.18.0:
version "14.18.0"
resolved "https://registry.yarnpkg.com/stripe/-/stripe-14.18.0.tgz#71f6d192c322418bd0962897006b0f47e232f94c"
integrity sha512-yLqKPqYgGJbMxrQiE4+i2i00ZVA2NRIZbZ1rejzj5XR3F3Uc+1iy9QE133knZudhVGMw367b8vTpB8D9pYMETw==
dependencies:
"@types/node" ">=8.1.0"
qs "^6.11.0"

supports-color@^5.5.0:
version "5.5.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
Expand Down Expand Up @@ -2548,6 +2570,11 @@ undefsafe@^2.0.5:
resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.5.tgz#38733b9327bdcd226db889fb723a6efd162e6e2c"
integrity sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==

undici-types@~5.26.4:
version "5.26.5"
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617"
integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==

[email protected]:
version "5.26.5"
resolved "https://registry.yarnpkg.com/undici/-/undici-5.26.5.tgz#f6dc8c565e3cad8c4475b187f51a13e505092838"
Expand Down

0 comments on commit ae7bbc5

Please sign in to comment.