mirror of
https://github.com/PretendoNetwork/website.git
synced 2026-08-04 17:17:46 -05:00
self heal from missed webhooks
This commit is contained in:
parent
027321911b
commit
e622a1e759
|
|
@ -3,11 +3,12 @@ const PNIDSchema = require('./schema/pnid');
|
|||
const config = require('../config.json');
|
||||
|
||||
const accountServerConfig = config.database.account;
|
||||
const { uri, database, options } = accountServerConfig;
|
||||
let accountServerDBConnection;
|
||||
let PNID;
|
||||
|
||||
async function connect() {
|
||||
accountServerDBConnection = await mongoose.createConnection(accountServerConfig.uri, accountServerConfig.options);
|
||||
accountServerDBConnection = await mongoose.createConnection(`${uri}/${database}`, options);
|
||||
accountServerDBConnection.on('error', console.error.bind(console, 'Mongoose connection error:'));
|
||||
accountServerDBConnection.on('close', () => {
|
||||
accountServerDBConnection.removeAllListeners();
|
||||
|
|
|
|||
|
|
@ -4,18 +4,16 @@ const DiscordOauth2 = require('discord-oauth2');
|
|||
const { v4: uuidv4 } = require('uuid');
|
||||
const AdmZip = require('adm-zip');
|
||||
const Stripe = require('stripe');
|
||||
const gmail = require('gmail-send');
|
||||
const database = require('../database');
|
||||
const util = require('../util');
|
||||
const config = require('../../config.json');
|
||||
|
||||
const stripe = new Stripe(config.stripe.secret_key);
|
||||
const router = new Router();
|
||||
const sendGmail = gmail(config.gmail);
|
||||
|
||||
const { Router } = express;
|
||||
const aesKey = Buffer.from(config.aes_key, 'hex');
|
||||
|
||||
const stripe = new Stripe(config.stripe.secret_key);
|
||||
const router = new Router();
|
||||
|
||||
// Create OAuth client
|
||||
const discordOAuth = new DiscordOauth2({
|
||||
clientId: config.discord.client_id,
|
||||
|
|
@ -637,70 +635,7 @@ router.post('/stripe-wh', express.raw({ type: 'application/json' }), async (requ
|
|||
return response.status(400).send(`Webhook Error: ${err.message}`);
|
||||
}
|
||||
|
||||
if (event.type === 'customer.subscription.updated' || event.type === 'customer.subscription.deleted') {
|
||||
const subscription = event.data.object;
|
||||
const product = await stripe.products.retrieve(subscription.plan.product);
|
||||
const customer = await stripe.customers.retrieve(subscription.customer);
|
||||
|
||||
if (!customer.metadata.pnid_pid && subscription.status !== 'canceled' && subscription.status !== 'unpaid') {
|
||||
// No PNID PID linked to customer. Abort and refund!
|
||||
await stripe.subscriptions.del(subscription.id);
|
||||
|
||||
const invoice = await stripe.invoices.retrieve(subscription.latest_invoice);
|
||||
await stripe.refunds.create({
|
||||
payment_intent: invoice.payment_intent
|
||||
});
|
||||
|
||||
await sendGmail({
|
||||
to: customer.email,
|
||||
subject: 'Pretendo Subscription Failed - No Linked PNID',
|
||||
text: `Your recent subscription to Pretendo Network has failed.\nThis is due to no PNID PID being linked to the Stripe customer account used. The subscription has been canceled and refunded. Please contact Jon immediately.\nStripe Customer ID: ${customer.id}`
|
||||
});
|
||||
|
||||
return response.json({ received: true });
|
||||
}
|
||||
|
||||
const pid = Number(customer.metadata.pnid_pid);
|
||||
const pnid = await database.PNID.findOne({ pid });
|
||||
|
||||
if (!pnid && subscription.status !== 'canceled' && subscription.status !== 'unpaid') {
|
||||
// PNID does not exist. Abort and refund!
|
||||
await stripe.subscriptions.del(subscription.id);
|
||||
|
||||
const invoice = await stripe.invoices.retrieve(subscription.latest_invoice);
|
||||
await stripe.refunds.create({
|
||||
payment_intent: invoice.payment_intent
|
||||
});
|
||||
|
||||
await sendGmail({
|
||||
to: customer.email,
|
||||
subject: 'Pretendo Subscription Failed - PNID Not Found',
|
||||
text: `Your recent subscription to Pretendo Network has failed.\nThis is due to the provided PNID not being found. The subscription has been canceled and refunded. Please contact Jon immediately.\nStripe Customer ID: ${customer.id}\nPNID PID: ${pid}`
|
||||
});
|
||||
|
||||
return response.json({ received: true });
|
||||
}
|
||||
|
||||
const updateData = {};
|
||||
|
||||
if (product.metadata.beta === 'true') {
|
||||
switch (subscription.status) {
|
||||
case 'active':
|
||||
updateData.access_level = 1;
|
||||
break;
|
||||
|
||||
case 'canceled': // Subscription was canceled
|
||||
case 'unpaid': // User missed too many payments
|
||||
updateData.access_level = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
await database.PNID.updateOne({ pid }, { $set: updateData }, { upsert: true }).exec();
|
||||
}
|
||||
}
|
||||
await util.handleStripeEvent(event);
|
||||
|
||||
response.json({ received: true });
|
||||
});
|
||||
|
|
|
|||
|
|
@ -5,15 +5,16 @@ const handlebars = require('express-handlebars');
|
|||
const morgan = require('morgan');
|
||||
const expressLocale = require('express-locale');
|
||||
const cookieParser = require('cookie-parser');
|
||||
const Stripe = require('stripe');
|
||||
const logger = require('./logger');
|
||||
const database = require('./database');
|
||||
const util = require('./util');
|
||||
const config = require('../config.json');
|
||||
|
||||
const defaultLocale = require('../locales/US_en.json');
|
||||
|
||||
const { http: { port } } = config;
|
||||
const app = express();
|
||||
const stripe = new Stripe(config.stripe.secret_key);
|
||||
|
||||
logger.info('Setting up Middleware');
|
||||
app.use(morgan('dev'));
|
||||
|
|
@ -158,7 +159,15 @@ app.set('view engine', 'handlebars');
|
|||
|
||||
logger.info('Starting server');
|
||||
database.connect().then(() => {
|
||||
app.listen(port, () => {
|
||||
app.listen(port, async () => {
|
||||
const events = await stripe.events.list({
|
||||
delivery_success: false // failed webhooks
|
||||
});
|
||||
|
||||
for (const event of events.data) {
|
||||
await util.handleStripeEvent(event);
|
||||
}
|
||||
|
||||
logger.success(`Server listening on http://localhost:${port}`);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
77
src/util.js
77
src/util.js
|
|
@ -1,7 +1,14 @@
|
|||
const fs = require('fs-extra');
|
||||
const got = require('got');
|
||||
const crypto = require('crypto');
|
||||
const gmail = require('gmail-send');
|
||||
const Stripe = require('stripe');
|
||||
const database = require('./database');
|
||||
const logger = require('./logger');
|
||||
const config = require('../config.json');
|
||||
|
||||
const stripe = new Stripe(config.stripe.secret_key);
|
||||
const sendGmail = gmail(config.gmail);
|
||||
|
||||
function fullUrl(request) {
|
||||
return `${request.protocol}://${request.hostname}${request.originalUrl}`;
|
||||
|
|
@ -68,11 +75,79 @@ function nintendoPasswordHash(password, pid) {
|
|||
return hashed;
|
||||
}
|
||||
|
||||
async function handleStripeEvent(event) {
|
||||
if (event.type === 'customer.subscription.updated' || event.type === 'customer.subscription.deleted') {
|
||||
const subscription = event.data.object;
|
||||
const product = await stripe.products.retrieve(subscription.plan.product);
|
||||
const customer = await stripe.customers.retrieve(subscription.customer);
|
||||
|
||||
if (!customer.metadata.pnid_pid && subscription.status !== 'canceled' && subscription.status !== 'unpaid') {
|
||||
// No PNID PID linked to customer. Abort and refund!
|
||||
await stripe.subscriptions.del(subscription.id);
|
||||
|
||||
const invoice = await stripe.invoices.retrieve(subscription.latest_invoice);
|
||||
await stripe.refunds.create({
|
||||
payment_intent: invoice.payment_intent
|
||||
});
|
||||
|
||||
await sendGmail({
|
||||
to: customer.email,
|
||||
subject: 'Pretendo Subscription Failed - No Linked PNID',
|
||||
text: `Your recent subscription to Pretendo Network has failed.\nThis is due to no PNID PID being linked to the Stripe customer account used. The subscription has been canceled and refunded. Please contact Jon immediately.\nStripe Customer ID: ${customer.id}`
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const pid = Number(customer.metadata.pnid_pid);
|
||||
const pnid = await database.PNID.findOne({ pid });
|
||||
|
||||
if (!pnid && subscription.status !== 'canceled' && subscription.status !== 'unpaid') {
|
||||
// PNID does not exist. Abort and refund!
|
||||
await stripe.subscriptions.del(subscription.id);
|
||||
|
||||
const invoice = await stripe.invoices.retrieve(subscription.latest_invoice);
|
||||
await stripe.refunds.create({
|
||||
payment_intent: invoice.payment_intent
|
||||
});
|
||||
|
||||
await sendGmail({
|
||||
to: customer.email,
|
||||
subject: 'Pretendo Subscription Failed - PNID Not Found',
|
||||
text: `Your recent subscription to Pretendo Network has failed.\nThis is due to the provided PNID not being found. The subscription has been canceled and refunded. Please contact Jon immediately.\nStripe Customer ID: ${customer.id}\nPNID PID: ${pid}`
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const updateData = {};
|
||||
|
||||
if (product.metadata.beta === 'true') {
|
||||
switch (subscription.status) {
|
||||
case 'active':
|
||||
updateData.access_level = 1;
|
||||
break;
|
||||
|
||||
case 'canceled': // Subscription was canceled
|
||||
case 'unpaid': // User missed too many payments
|
||||
updateData.access_level = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
await database.PNID.updateOne({ pid }, { $set: updateData }, { upsert: true }).exec();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
fullUrl,
|
||||
getLocale,
|
||||
apiGetRequest,
|
||||
apiPostGetRequest,
|
||||
apiDeleteGetRequest,
|
||||
nintendoPasswordHash
|
||||
nintendoPasswordHash,
|
||||
handleStripeEvent
|
||||
};
|
||||
Loading…
Reference in New Issue
Block a user