Skip to content

Commit

Permalink
Merge pull request #33 from CedricTheveneau/payment
Browse files Browse the repository at this point in the history
[WIP] Better implementation of Stripe with tracking of donations
  • Loading branch information
CedricTheveneau authored Dec 13, 2024
2 parents da052f2 + 407eded commit a14e742
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 2 deletions.
4 changes: 3 additions & 1 deletion Auth/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,6 @@ TOKEN_EXPIRATION=

EMAIL_USER=
EMAIL_PASS=
FRONTEND_URL=
FRONTEND_URL=

STRIPE_SECRET_KEY=
62 changes: 61 additions & 1 deletion Auth/app/controllers/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const bcrypt = require("bcrypt");
const jwt = require("jsonwebtoken");
const { sendConfirmationEmail, sendContactEmail } = require("../utils/emailUtils");
const crypto = require("crypto");
const stripe = require("stripe")(process.env.STRIPE_SECRET_KEY);

// Création de compte
exports.register = async (req, res) => {
Expand Down Expand Up @@ -609,7 +610,6 @@ exports.getAll = async (req, res) => {
}
};

// Envoi d'un mail de contact
exports.contact = async (req, res) => {
try {
// Récupération des éléments dans le corps de requête
Expand Down Expand Up @@ -647,4 +647,64 @@ exports.contact = async (req, res) => {
"Something wrong happened with your request to create a new user.",
});
}
};

exports.donate = async (req, res) => {
const { amount, currency = "EUR" } = req.body;

if (!amount || amount <= 0) {
return res.status(400).json({ message: "Invalid donation amount" });
}

try {
const paymentIntent = await stripe.paymentIntents.create({
amount, // Montant en cents
currency,
payment_method_types: ["card"],
});

res.status(200).json({
clientSecret: paymentIntent.client_secret,
transactionId: paymentIntent.id
});
} catch (error) {
console.error("Stripe error:", error.message);
res.status(500).json({ message: "Failed to create payment" });
}
};

exports.handlePaymentSuccess = async (req, res) => {
const { paymentIntentId } = req.body;

try {
const paymentIntent = await stripe.paymentIntents.retrieve(paymentIntentId);

if (paymentIntent.status !== "succeeded") {
return res.status(400).json({ message: "Payment not successful" });
}

const user = await User.findById(req.user.id);

const newTransaction = {
transactionId: paymentIntent.id,
amount: paymentIntent.amount,
currency: paymentIntent.currency,
receiptUrl: paymentIntent.charges.data[0]?.receipt_url || "",
status: paymentIntent.status,
paymentMethod: {
type: paymentIntent.payment_method_types[0],
brand: paymentIntent.charges.data[0]?.payment_method_details.card.brand,
last4: paymentIntent.charges.data[0]?.payment_method_details.card.last4,
},
createdAt: paymentIntent.created,
};

user.transactions.push(newTransaction);
await user.save();

res.status(200).json({ message: "Donation recorded", transaction: newTransaction });
} catch (error) {
console.error("Error recording donation:", error.message);
res.status(500).json({ message: "Failed to record donation" });
}
};
15 changes: 15 additions & 0 deletions Auth/app/models/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,21 @@ const userSchema = new mongoose.Schema({
default: 0,
max: 3,
}
// transactions: [
// {
// transactionId: { type: String, required: true },
// amount: { type: Number, required: true }, // Montant en cents
// currency: { type: String, required: true, default: "EUR" },
// receiptUrl: { type: String },
// status: { type: String, required: true },
// paymentMethod: {
// type: { type: String },
// brand: { type: String },
// last4: { type: String },
// },
// createdAt: { type: Number, default: () => Math.floor(Date.now() / 1000) },
// },
// ],
});

userSchema.plugin(uniqueValidator);
Expand Down
2 changes: 2 additions & 0 deletions Auth/app/routes/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ router.get('/swagger.json', (req, res) => {
router.post("/register", userCtrl.register);
router.post("/#", userCtrl.login);
router.post("/contact", userCtrl.contact);
router.post("/donate", auth, userCtrl.donate);
router.post("/payment-success", auth, userCtrl.handlePaymentSuccess);
router.put("/saveArticle/:id", auth, userCtrl.saveArticle);
router.put("/upvoteArticle/:id", auth, userCtrl.upvoteArticle);
router.put("/articlesHistory/:id", auth, userCtrl.articlesHistory);
Expand Down
23 changes: 23 additions & 0 deletions Auth/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Auth/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"node-cron": "^3.0.3",
"nodemailer": "^6.9.15",
"nodemon": "^3.1.4",
"stripe": "^17.4.0",
"supertest": "^7.0.0",
"swagger-jsdoc": "^6.2.8",
"uuid": "^11.0.2",
Expand Down

0 comments on commit a14e742

Please # to comment.