@cocreate/stripe
Version:
A simple stripe component in vanilla javascript. Easily configured using HTML5 attributes and/or JavaScript API.
312 lines (287 loc) • 13.4 kB
JavaScript
'use strict'
const name = 'stripe'
async function send(data) {
try {
if (data.req)
return await webhooks(data)
let environment = data.environment || 'production';
if (!data.environment && (data.host.startsWith('dev.') || data.host.startsWith('test.')))
environment = 'test'
const key = data.apis[environment].key;
const stripe = require('stripe')(key);
let param
if (data.parameters) {
param = data.stripe.parameters
}
if (data.stripe.$param) {
param = data.stripe.$param[0]
delete data.stripe.$param
}
switch (data.method.replace('stripe.', '')) {
case 'accounts.create':
data.stripe = await stripe.accounts.create(data.stripe);
break;
case 'accounts.update':
data.stripe = await stripe.accounts.update(param, data.stripe);
break;
case 'files.create':
data.stripe = await stripe.files.create(data.stripe)
break;
case 'customers.list':
data.stripe = await stripe.customers.list();
break;
case 'customers.create':
data.stripe = await stripe.customers.create(data.stripe);
break;
case 'customers.update':
delete data.stripe['customer'];
data.stripe = await stripe.customers.update(customer, data.stripe);
break;
case 'customers.createSource':
data.stripe = await stripe.customers.createSource(customer, data.stripe);
break;
case 'tokens.create':
data.stripe = await stripe.tokens.create(data.stripe);
break;
case 'charges.create':
data.stripe = await stripe.charges.create(data.stripe);
break;
case 'balance.retrieve':
data.stripe = await stripe.balance.retrieve();
break;
case 'balanceTransactions.retrieve':
data.stripe = await stripe.balanceTransactions.retrieve(
data.stripe.balance_transaction
);
break;
case 'balanceTransactions.list':
data.stripe = await stripe.balanceTransactions.list();
break;
case 'paymentIntents.create':
data.stripe = await stripe.paymentIntents.create(data.paymentIntents);
break;
case 'checkout.sessions':
data.stripe = await stripe.checkout.sessions.retrieve(data.sessionId);
// Check if the session has a customer associated with it
// if (session.customer) {
// return session.customer; // This is the Customer ID
// } else {
// console.log('No customer associated with this session.');
// return null;
// }
break;
case 'subscriptions.update':
data.stripe = await stripe.subscriptions.update(param, data.stripe);
break;
case 'subscriptionItems.update':
data.stripe = await stripe.subscriptionItems.update(param, data.stripe);
break;
case 'subscriptions.del':
data.stripe = await stripe.subscriptions.del(data.stripe.subscriptionId);
break;
case 'subscriptions.create':
data.stripe = await stripe.subscriptions.create(data.stripe);
break;
case 'transfers.create':
data.stripe = await stripe.transfers.create(data.stripe);
break;
default:
data.error = "unknown method"
}
return data
} catch (error) {
data.error = error.message
return data
}
}
async function webhooks(data) {
try {
let environment = data.environment || 'production';
if (data.host.startsWith('dev.') || data.host.startsWith('test.'))
environment = 'test'
const key = data.apis[environment].key;
const stripe = require('stripe')(key);
let name = data.req.url.split('/');
name = name[3] || name[2] || name[1]
let rawBody = '';
await new Promise((resolve, reject) => {
data.req.on('data', chunk => {
rawBody += chunk.toString();
});
data.req.on('end', () => {
resolve();
});
data.req.on('error', (err) => {
reject(err);
});
});
const webhookSecret = data.apis[environment].webhooks[name];
const sig = data.req.headers['stripe-signature'];
const event = stripe.webhooks.constructEvent(rawBody, sig, webhookSecret);
switch (data.req.method) {
case 'POST':
case 'PUT':
// Handle the event
switch (event.type) {
case 'customer.subscription.deleted':
let subscription = event.data.object; // The subscription object
let subscriptionId = subscription.id;
await data.crud.send({
host: data.host,
broadcast: false,
broadcastSender: true,
method: 'object.update',
array: 'users',
object: {
subscription: 'canceled'
},
$filter: {
query: { subscriptionId }
},
organization_id: data.organization_id
})
break;
case 'checkout.session.completed':
const session = event.data.object;
const userId = session.metadata.user_id;
console.log('userId', userId)
// Process the session object as needed
break;
case 'invoice.payment_succeeded':
const invoice = event.data.object;
const user = await data.crud.send({
host: data.host,
broadcast: false,
broadcastSender: true,
method: 'object.read',
array: 'users',
$filter: {
query: { customerId: invoice.customer }
},
organization_id: data.organization_id
})
if (user.object && user.object[0] && user.object[0]) {
await data.crud.send({
host: data.host,
broadcast: false,
broadcastSender: true,
method: 'object.create',
array: 'payments',
object: {
amount: invoice.amount_paid,
user_id: user.object[0]._id,
customerId: invoice.customer,
subscription: user.object[0].subscription,
subscriptionId: invoice.subscription,
ambassador: user.object[0].ambassador
},
organization_id: data.organization_id
})
if (user.object[0].ambassador) {
await data.crud.send({
host: data.host,
broadcast: false,
broadcastSender: true,
method: 'object.update',
array: 'payouts',
object: {
$inc: { amount: (invoice.amount_paid * 0.15) / 100 },
user_id: user.object[0]._id,
ambassador: user.object[0].ambassador,
status: "pending",
},
$filter: {
query: {
ambassador: user.object[0].ambassador,
status: 'pending'
}
},
upsert: true,
organization_id: data.organization_id
})
}
}
break;
case 'account.updated':
// Handle additional information request
await data.crud.send({
host: data.host,
broadcast: false,
broadcastSender: true,
method: 'object.update',
array: 'users',
object: {
"stripe.account": event.data.object,
},
$filter: {
query: {
"stripe.account.id": event.data.object.id
}
},
organization_id: data.organization_id
})
break;
case 'balance.available':
await data.crud.send({
host: data.host,
broadcast: false,
broadcastSender: true,
method: 'object.update',
array: 'users',
$filter: {
query: { ambassadorAccount: event.data.object.accountId }
},
object: {
"stripe.balance": event.data.object
},
organization_id: data.organization_id
})
break;
case 'payout.created':
await data.crud.send({
host: data.host,
broadcast: false,
broadcastSender: true,
method: 'object.create',
array: 'payouts',
object: event.data.object,
organization_id: data.organization_id
})
break;
case 'payout.paid':
case 'payout.failed':
await data.crud.send({
host: data.host,
broadcast: false,
broadcastSender: true,
method: 'object.update',
array: 'payouts',
$filter: {
query: { "id": event.data.object.id } // Use the payout ID to find the correct record
},
object: event.data.object, // Directly use the event data object
organization_id: data.organization_id
});
break;
// Handle other event types
default:
console.log(`Unhandled event type ${event.type}`);
}
break;
case 'GET':
case 'DELETE':
// Handle GET and DELETE requests if necessary
break;
// Add other cases as needed
}
data.res.writeHead(200, { 'Content-Type': 'application/json' });
data.res.end(JSON.stringify({ message: 'Webhook received and processed' }));
return data
} catch (error) {
data.error = error.message
data.res.writeHead(400, { 'Content-Type': 'text/plain' });
data.res.end(`Webhook Error: ${err.message}`);
return data
}
}
module.exports = { send, webhooks };