Files
portal_v3/admin/services/stripe/app1/server/server.js
equippedcoding-master e2c98790b2 initial commit
2025-09-17 09:37:06 -05:00

1458 lines
53 KiB
JavaScript

import { createRequire } from 'module';
import path from 'path';
import { fileURLToPath } from 'url';
const require = createRequire(import.meta.url);
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const fs = require('fs');
import {decode,encode} from 'html-entities';
//import "dotenv/config";
import express, { query } from "express";
// import http from "http";
import https from "https";
// import * as paypal from "./paypal-api.js";
var mysql = require('mysql2');
// import mysql from "mysql2";
import * as helperjs from "./helper.js";
// const express = require('express');
// const app = express();
const { resolve } = require('path');
const bodyParser = require('body-parser');
const cookieParser = require('cookie-parser');
const exec = require("child_process").exec;
// Replace if using a different env file or config
// require('dotenv').config({ path: './.env' });
// stripe login --api-key sk_test_51OIu21J7BKlr2pgsABfPagNLQmRYdn8wSDNOj9ph6q0T6ThchqyfRC585qp5iG1bHM3MrxnTHOUGQRGhZ4K6h5Sg00DmDdAv7Q
// stripe login --api-key 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
// stripe listen --forward-to https://www15.appfactory.studio:9295/webhook --skip-verify
// const stripe = require('stripe')('sk_test_...');
const subdomain = process.argv[2];
const mypath = path.join(__dirname, '../../../../../system/db/.env');
require('dotenv').config({ path: mypath })
console.log(process.env.MY_DATABASE);
console.log(mypath);
console.log(subdomain);
// 0|stripe | /home/appfactorystudio/websites/www15/portal/admin/services/stripe/app1/system/db/.env
// 0|stripe | www15
// 0|stripe | /home/appfactorystudio/websites/www15/portal/admin/services/stripe/app1/server
async function func__config(stripe,req,res,mydata){
let lookup_keys = mydata.clientdata.lookup_keys;
const prices = await stripe.prices.list({
lookup_keys: lookup_keys, //['pro_basic_v1', 'organization_v1', 'enterprise_v1'],
expand: ['data.product']
});
res.jsonp({
publishableKey: process.env.STRIPE_PUBLISHABLE_KEY,
prices: prices.data,
});
}
async function func__create_customer(stripe,req,res,mydata){
const customers = await stripe.customers.search({
query: `metadata[\'_reference_num\']:\'${mydata.clientdata.reference_num}\'`,
});
let customer = null;
if(customers==null || customers.data.length==0){
customer = await stripe.customers.create({
email: mydata.clientdata.email,
metadata: { _reference_num: mydata.clientdata.reference_num }
});
}else{
customer = customers[0];
}
if(mydata.clientdata.payment_intent!=undefined){
const paymentIntent = await stripe.paymentIntents.update(
mydata.clientdata.payment_intent.id,
{
customer: customer.id,
metadata: { _reference_num: mydata.clientdata.reference_num }
}
);
// let filename1 = `/mnt/node1/${mydata.managed_domain.SystemUser}/tmp/${mydata.clientdata.payment_intent.id}.json`;
// fs.appendFile(filename1,
// JSON.stringify({
// "payment_intent": mydata.clientdata.payment_intent,
// "customer": customer,
// "mail_handlers": mydata.clientdata.mail_handlers
// },null,4),
// function(err) {
// if(err) {
// console.log(`func__create_customer The file was saved! ${filename1}`);
// return console.log(err);
// }
// });
}
res.jsonp({
data: mydata.clientdata,
customer: customer,
customers:customers
});
}
async function func__create_subscription(stripe,req,res,mydata){
// Simulate authenticated user. In practice this will be the
// Stripe Customer ID related to the authenticated user.
const customerId = mydata.clientdata.customer
// Create the subscription
const priceId = mydata.clientdata.priceId;
try {
const subscription = await stripe.subscriptions.create({
customer: customerId,
items: [{
price: priceId,
}],
metadata: { _reference_num: mydata.clientdata.reference_num },
payment_behavior: 'default_incomplete',
expand: ['latest_invoice.payment_intent'],
});
res.jsonp({
subscription: subscription,
subscriptionId: subscription.id,
clientSecret: subscription.latest_invoice.payment_intent.client_secret,
});
} catch (error) {
return res.status(400).jsonp({ error: { message: error.message } });
}
}
async function func__invoice_preview(stripe,req,res,mydata){
const customerId = req.cookies['customer'];
const priceId = process.env[req.query.newPriceLookupKey.toUpperCase()];
const subscription = await stripe.subscriptions.retrieve(
req.query.subscriptionId
);
const invoice = await stripe.invoices.retrieveUpcoming({
customer: customerId,
subscription: req.query.subscriptionId,
subscription_items: [ {
id: subscription.items.data[0].id,
price: priceId,
}],
});
res.jsonp({ invoice });
}
async function func__cancel_subscription(stripe,req,res,mydata){
// Cancel the subscription
try {
const deletedSubscription = await stripe.subscriptions.del(
req.body.subscriptionId
);
res.jsonp({ subscription: deletedSubscription });
} catch (error) {
return res.status(400).jsonp({ error: { message: error.message } });
}
}
async function func__update_subscription(stripe,req,res,mydata){
try {
const subscription = await stripe.subscriptions.retrieve(
req.body.subscriptionId
);
const updatedSubscription = await stripe.subscriptions.update(
req.body.subscriptionId, {
items: [{
id: subscription.items.data[0].id,
price: process.env[req.body.newPriceLookupKey.toUpperCase()],
}],
}
);
res.jsonp({ subscription: updatedSubscription });
} catch (error) {
return res.status(400).jsonp({ error: { message: error.message } });
}
}
async function func__subscriptions(stripe,req,res,mydata){
// Simulate authenticated user. In practice this will be the
// Stripe Customer ID related to the authenticated user.
const customerId = req.cookies['customer'];
const subscriptions = await stripe.subscriptions.list({
customer: customerId,
status: 'all',
expand: ['data.default_payment_method'],
});
res.jsonp({subscriptions});
}
const calculate_tax = async (stripe, orderAmount, currency) => {
const taxCalculation = await stripe.tax.calculations.create({
currency,
customer_details: {
address: {
line1: "10709 Cleary Blvd",
city: "Plantation",
state: "FL",
postal_code: "33322",
country: "US",
},
address_source: "shipping",
},
line_items: [
{
amount: orderAmount,
reference: "ProductRef",
tax_behavior: "exclusive",
tax_code: "txcd_30011000"
}
],
});
return taxCalculation;
};
async function func_single_create_payment_intent(stripe,req,res,mydata){
// Create a PaymentIntent with the amount, currency, and a payment method type.
//
// See the documentation [0] for the full list of supported parameters.
//
// [0] https://stripe.com/docs/api/payment_intents/create
let orderAmount = 1400;
let paymentIntent;
const calculateTax = false;
try {
if (calculateTax) {
let taxCalculation = await calculate_tax(stripe, orderAmount, "usd")
paymentIntent = await stripe.paymentIntents.create({
currency: 'usd',
amount: taxCalculation.amount_total,
automatic_payment_methods: { enabled: true },
metadata: { tax_calculation: taxCalculation.id }
});
}
else {
paymentIntent = await stripe.paymentIntents.create({
currency: 'usd',
amount: orderAmount,
automatic_payment_methods: { enabled: true }
});
}
// Send publishable key and PaymentIntent details to client
res.jsonp({
paymentIntent: paymentIntent,
clientSecret: paymentIntent.client_secret,
});
} catch (e) {
return res.status(400).jsonp({
error: {
message: e.message,
}
});
}
}
async function webhook_update(values){
// let connection = createMySQLConnection();
// try {
// let net = parseInt(values.mysql_id);
// const sql = 'UPDATE `configurations` SET `json` = "'+JSON.stringify(values)+'" WHERE `id` = ' + net;
// // const values = ['Josh', 7];
// // console.log(JSON.stringify(values));
// const [result, fields] = await connection.execute(sql);
// console.log(result);
// console.log(fields);
// } catch (err) {
// console.log(err);
// }
}
function _create_connection(query, cb1){
let con = createMySQLConnection();
con.connect(function(err) {
if (err) throw err;
con.query(`${query}`, function (err, results) {
// con.query(`SELECT * FROM subdomain_properties WHERE SubDomain = '${subdomain}'`, function (err, results) {
if (err){
console.log(err);
throw err;
}
cb1(results);
con.end();
// if(results.length > 0){}
});
});
}
function _write_log(string,managed_domain){
let filename1 = `/mnt/node1/${managed_domain.SystemUser}/logs/node_stripe_test.log`;
fs.appendFile(filename1,
`\n\n\n----------------------------------\n${string}`,
function(err) {
if(err) {return console.log(err);}
console.log(`_write_log - The file was saved! ${filename1}`);
});
}
function _write_json_file(filename1,json){
// let filename1 = `/mnt/node1/${managed_domain.SystemUser}/logs/node_stripe_test.log`;
fs.appendFile(filename1,JSON.stringify(json),
function(err) {
if(err) {return console.log(err);}
console.log(`_write_log - The file was saved! ${filename1}`);
});
}
function isObjectEmpty(value) {
for (let prop in value) {
if (value.hasOwnProperty(prop)) return false;
}
return true;
}
function getTempWebhookList(){
let enabled_events = [
'payment_intent.payment_failed',
'payment_intent.succeeded',
'invoice.payment_succeeded',
'customer.subscription.trial_will_end',
'customer.subscription.deleted',
'invoice.finalized',
'invoice.payment_failed'
]
return [
{
stripe: null,
options: {
endpoint: "/webhook",
enabled_events: enabled_events
},
settings: {
all_events_on: true,
"events": {
"all": {
email_response:{
"active": true,
"title":"",
"body":"stripe_webook_event_response_v1",
"subject":"Than you for contacting us",
"emails":[],
"template":"stripe_webook_event_response_v1",
"from":"no-reply",
"footer":""
},
email_alert:{
"active": true,
"title":"",
"body":"stripe_webook_event_alert_v1",
"subject":"${mycompany_name} - Notification Alert",
"emails":["james@appfactory.studio"],
"template":"stripe_webook_event_alert_v1",
"from":"no-reply",
"footer":""
}
}
}
}
},
{
stripe: null,
options: {
endpoint: "/connect_webhook",
enabled_events: enabled_events
},
settings: {
all_events_on: true,
"events": {
"all": {
email_response:{
"active": true,
"title":"",
"body":"stripe_webook_event_response_v1",
"subject":"Than you for contacting us",
"emails":[],
"template":"stripe_webook_event_response_v1",
"from":"no-reply",
"footer":""
},
email_alert:{
"active": true,
"title":"",
"body":"stripe_webook_event_alert_v1",
"subject":"${mycompany_name} - Notification Alert",
"emails":["james@appfactory.studio"],
"template":"stripe_webook_event_alert_v1",
"from":"no-reply",
"footer":""
}
}
}
}
}
]
}
function generateRandomFilename(length = 10) {
const characters = 'abcdefghijklmnopqrstuvwxyz0123456789';
let result = '';
for (let i = 0; i < length; i++) {
result += characters.charAt(Math.floor(Math.random() * characters.length));
}
return result;
}
function ChangeFileOwnership(file,cb,isLog){
if (fs.existsSync(file)) {
isLog = (isLog==undefined) ? false: isLog;
changeOwner(file,"appfactorystudio","apache", (error) => {
if (error) {
console.error('Failed to change ownership:', error);
} else {
fs.chmod(file, 0o775, (err) => {
if (err) {
if(isLog) _write_log('Error changing permissions:', mydata.managed_domain);
} else {
if(isLog) _write_log('Permissions changed successfully.', mydata.managed_domain);
if(cb!=undefined && typeof cb === "function"){
cb();
}
}
});
if(isLog) _write_log('Ownership changed successfully.', mydata.managed_domain);
}
});
} else {
if(isLog) console.log('charge.succeeded: File does not exist! - ' + file);
cb();
}
}
function SendEmailHandlers(file,mydata){
ChangeFileOwnership(file,function(){
exec(`php ${__dirname}/run.php "send_email2" "null" "${file}"`, function (error, stdout, stderr) {
_write_log("error: " + error, mydata.managed_domain);
_write_log(file, mydata.managed_domain);
_write_log(stdout, mydata.managed_domain);
console.log(stderr);
console.log(stdout);
_write_log("+++++++++++++++++++++++++++++++++++++++", mydata.managed_domain);
});
});
}
function MailHandlersVariableInsert(myobj,dataObject){
for (const key in myobj.mail_handlers) {
for (let i = 0; i < myobj.mail_handlers[key].variables.system.length; i++) {
for (let n = 0; n < myobj.mail_handlers[key].variables.system[i].length; n++) {
if(myobj.mail_handlers[key].variables.system[i][n].name=="last4"){
myobj.mail_handlers[key].variables.system[i][n].value =
dataObject.payment_method_details.card.last4;
}
if(myobj.mail_handlers[key].variables.system[i][n].name=="brand"){
myobj.mail_handlers[key].variables.system[i][n].value =
dataObject.payment_method_details.card.brand;
}
if(myobj.mail_handlers[key].variables.system[i][n].name=="dollar_amount"){
myobj.mail_handlers[key].variables.system[i][n].value =
dataObject.amount_captured;
}
if(myobj.mail_handlers[key].variables.system[i][n].name=="currency"){
myobj.mail_handlers[key].variables.system[i][n].value =
dataObject.payment_method_details.card.brand;
}
if(myobj.mail_handlers[key].variables.system[i][n].name=="receipt_url"){
myobj.mail_handlers[key].variables.system[i][n].value =
dataObject.receipt_url;
}
}
}
return myobj;
}
}
function changeOwner(filePath, newOwner, newGroup, callback) {
const command = `chown ${newOwner}:${newGroup} ${filePath}`;
exec(command, (error, stdout, stderr) => {
if (error) {
console.error(`Error: ${error.message}`);
callback(error);
return;
}
if (stderr) {
console.error(`stderr: ${stderr}`);
callback(new Error(stderr));
return;
}
console.log(`Ownership changed successfully: ${stdout}`);
callback(null);
});
}
function EventFiredChargeSucceeded(stripe,event,dataObject,mydata){
// 77777 /mnt/appfactorystudio/modules/payments/
let file = `/mnt/node1/${mydata.managed_domain.SystemUser}/tmp/${dataObject.payment_intent}.json`;
fs.readFile(file, 'utf8', (err, data) => {
if (err) {
console.error(err);
return;
}
try {
let myobj = JSON.parse(data);
fs.appendFile(`/mnt/node1/${mydata.managed_domain.SystemUser}/logs/node_stripe_test2.log`,
JSON.stringify(myobj,null,4),
function(err) {
if(err) {return console.log(err);}
// console.log(JSON.stringify(myobj,null,4));
console.log("NNNN The file was saved!");
});
myobj = MailHandlersVariableInsert(myobj,dataObject);
myobj.charge = dataObject
let directoryPath = `/mnt/node1/${mydata.managed_domain.SystemUser}/modules/payments/${dataObject.customer}`;
if (!fs.existsSync(directoryPath)) {
fs.mkdirSync(directoryPath, { recursive: true });
}
let newfile = `/mnt/node1/${mydata.managed_domain.SystemUser}/modules/payments/${dataObject.customer}/${dataObject.payment_intent}.json`;
fs.writeFile(newfile, JSON.stringify(myobj,null,4),"utf-8",function(err){
// console.log(err);
ChangeFileOwnership(newfile,function(){
SendEmailHandlers(newfile,{
"managed_domain": mydata.managed_domain,
"mail_handlers": myobj.mail_handlers
});
// fs.unlink(file, (err) => {
// if (err) {
// console.error(`Error removing file: ${err}`);
// return;
// }
// console.log(`File ${file} has been successfully removed.`);
// });
});
});
} catch (parseErr) {
console.error('Error parsing JSON:', parseErr);
}
});
}
async function EventFiredInvoicePaymentSucceeded(stripe,event,dataObject,mydata){
if(dataObject['billing_reason'] == 'subscription_create') {
// The subscription automatically activates after successful payment
// Set the payment method used to pay the first invoice
// as the default payment method for that subscription
const subscription_id = dataObject['subscription']
const payment_intent_id = dataObject['payment_intent']
// Retrieve the payment intent used to pay the subscription
const payment_intent = await stripe.paymentIntents.retrieve(payment_intent_id);
try {
const subscription = await stripe.subscriptions.update(
subscription_id,
{
default_payment_method: payment_intent.payment_method,
},
);
setTimeout(() => {
const query = `SELECT * FROM general_data_storage WHERE name="${dataObject['customer']}"`;
_create_connection(query, function(results){
if(results.length==0){
_write_log("NO RESULTS!",mydata.managed_domain);
return;
}
// ppppp
// _write_log(JSON.stringify(results),mydata.managed_domain);
// stripe listen --forward-to https://www15.appfactory.studio:9295/webhook --skip-verify
let myobj = JSON.parse(decode(results[0].json));
myobj = MailHandlersVariableInsert(myobj,dataObject);
// let filename1 = `/mnt/node1/appfactorystudio/logs/a_stripe_test.json`;
// fs.appendFile(filename1, JSON.stringify(dataObject), function(err) {
// _write_log(`_write_log - MailHandler ${filename1}`);
// if(err) {return console.log(err);}
// });
let contents = JSON.stringify(myobj);
let filename = `/mnt/node1/${mydata.managed_domain.SystemUser}/members/zones/${myobj.member.zone}/json/${myobj.member.reference_num}.json`;
console.log("123--------------------------------------");
console.log(filename);
_write_log(filename, mydata.managed_domain);
fs.appendFile(filename,contents, function(err) {
if(err) {return console.log(err);}
// console.log("The file was saved!");
// const updateQuery = `UPDATE general_data_storage SET json='${stringupdate}' WHERE name='${dataObject['customer']}'`;
// _create_connection(updateQuery, function(results1){
// exec(`php ${__dirname}/run.php "send_email" "${dataObject['customer']}" "${filename}"`, function (error, stdout, stderr) {
// _write_log("error: " + error, mydata.managed_domain);
// // _write_log("stdout: " + stdout, mydata.managed_domain);
// // _write_log("stderr: " + stderr, mydata.managed_domain);
// // _write_log(JSON.stringify(results[0]), mydata.managed_domain);
// changeOwner(filename,"appfactorystudio","apache", (error) => {
// if (error) {
// console.error('Failed to change ownership:', error);
// } else {
// fs.chmod(filename, 0o775, (err) => {
// if (err) {
// _write_log('Error changing permissions:', mydata.managed_domain);
// } else {
// _write_log('Permissions changed successfully.', mydata.managed_domain);
// }
// });
// _write_log('Ownership changed successfully.', mydata.managed_domain);
// }
// });
// });
// });
});
// payment_intent.charges.data[0].payment_method_details.card.last4
// payment_intent.charges.data[0].payment_method_details.card.brand
// _write_log(JSON.stringify(myobj.mail_handlers), mydata.managed_domain);
});
// _write_log(JSON.stringify(dataObject), mydata.managed_domain);
// console.log("Default payment method set for subscription:" + payment_intent.payment_method);
// _write_log("invoice.payment_succeeded",mydata.managed_domain);
// // _write_log(JSON.stringify(payment_intent),mydata.managed_domain);
// _write_log("last4 = " + payment_intent.charges.data[0].payment_method_details.card.last4, mydata.managed_domain);
// _write_log("brand = " + payment_intent.charges.data[0].payment_method_details.card.brand, mydata.managed_domain);
// _write_log("network = " + payment_intent.charges.data[0].payment_method_details.card.network, mydata.managed_domain);
//charges.payment_method_details.card.last4
//charges.payment_method_details.card.brand
// charges.payment_method_details.card.network
},10000);
} catch (err) {
console.log(err);
console.log(`⚠️ Failed to update the default payment method for subscription: ${subscription_id}`);
_write_log(`invoice.⚠️ Failed to update the default payment method for subscription: ${subscription_id}`, mydata.managed_domain);
}
};
}
async function func__webhook(stripe,req,res,mydata){
// Retrieve the event by verifying the signature using the raw body and secret.
let event;
// TODO_1: Remove whsec_ce937ab59c83dcecc659324f312e6044cc80246e3932d9b93bee27a3a6a513ef
const endpointSecret = 'whsec_ce937ab59c83dcecc659324f312e6044cc80246e3932d9b93bee27a3a6a513ef';
// console.log("###################################################################");
// console.log(req.body);
// console.log("###################################################################");
// console.log(req.header('Stripe-Signature'));
// console.log("###################################################################");
// console.log(mydata.webhook.settings.secret);
// console.log("###################################################################");
try {
event = stripe.webhooks.constructEvent(
req.body,
req.header('stripe-signature'),
endpointSecret //mydata.webhook.settings.secret
);
} catch (err) {
// console.log(mydata.webhook);
// console.log(err);
console.log(`⚠️ Webhook signature verification failed. ${err.message}`);
return res.sendStatus(400);
}
// Extract the object from the event.
const dataObject = event.data.object;
// Handle the event
// Review important events for Billing webhooks
// https://stripe.com/docs/billing/webhooks
// Remove comment to see the various objects sent for this sample
/*
----------------------------------
Unexpected event type: customer.created
----------------------------------
Unexpected event type: payment_intent.created
----------------------------------
Unexpected event type: customer.updated
----------------------------------
Unexpected event type: customer.subscription.created
----------------------------------
Unexpected event type: invoice.created
========== after succeful payment ================
----------------------------------
- Unexpected event type: customer.subscription.updated
----------------------------------
- Unexpected event type: payment_method.attached
----------------------------------
- Unexpected event type: charge.succeeded
----------------------------------
- Unexpected event type: payment_intent.succeeded
----------------------------------
- Unexpected event type: invoice.updated
----------------------------------
- invoice.payment_succeeded
----------------------------------
- Unexpected event type: invoice.paid
----------------------------------
- Unexpected event type: customer.subscription.updated
----------------------------------
- Unexpected event type: setup_intent.created
----------------------------------
- Unexpected event type: setup_intent.succeeded
*/
let charge_succeded_count = 0;
switch (event.type) {
// random
case 'invoice.payment_failed':
// If the payment fails or the customer does not have a valid payment method,
// an invoice.payment_failed event is sent, the subscription becomes past_due.
// Use this webhook to notify your user that their payment has
// failed and to retrieve new card details.
_write_log("invoice.payment_failed",mydata.managed_domain);
break;
case 'invoice.finalized':
// If you want to manually send out invoices to your customers
// or store them locally to reference to avoid hitting Stripe rate limits.
break;
case 'customer.subscription.deleted':
if (event.request != null) {
// handle a subscription cancelled by your request
// from above.
_write_log("customer.subscription.deleted",mydata.managed_domain);
} else {
// handle subscription cancelled automatically based
// upon your subscription settings.
_write_log("customer.subscription.deleted automatic",mydata.managed_domain);
}
break;
case 'customer.subscription.trial_will_end':
// Send notification to your user that the trial will end
_write_log("customer.subscription.trial_will_end",mydata.managed_domain);
break;
// customer creation
case 'customer.created':
_write_log(`Event type: ${event.type}`,mydata.managed_domain);
break;
case 'payment_intent.created':
_write_log(`Event type: ${event.type}`,mydata.managed_domain);
break;
case 'customer.updated':
_write_log(`Event type: ${event.type}`,mydata.managed_domain);
break;
case 'customer.subscription.created':
_write_log(`Event type: ${event.type}`,mydata.managed_domain);
break;
case 'invoice.created':
_write_log(`Event type: ${event.type}`,mydata.managed_domain);
break;
// after payment succeds
case 'customer.subscription.updated':
_write_log(`Event type: ${event.type}`,mydata.managed_domain);
break;
case 'payment_method.attached':
_write_log(`Event type: ${event.type}`,mydata.managed_domain);
break;
case 'charge.succeeded': // singlecharge
_write_log(`Event type: ${event.type}`,mydata.managed_domain);
EventFiredChargeSucceeded(stripe,event,dataObject,mydata);
break;
case 'payment_intent.succeeded':
_write_log(`Event type: ${event.type}`,mydata.managed_domain);
break;
case 'invoice.updated':
break;
case 'invoice.payment_succeeded': // recurring
_write_log(`Event type: ----- ${event.type}`,mydata.managed_domain);
EventFiredInvoicePaymentSucceeded(stripe,event,dataObject,mydata);
break;
case 'invoice.paid':
_write_log(`Event type: ${event.type}`,mydata.managed_domain);
break;
case 'customer.subscription.updated':
_write_log(`Event type: ${event.type}`,mydata.managed_domain);
break;
case 'setup_intent.created':
_write_log(`Event type: ${event.type}`,mydata.managed_domain);
break;
case 'setup_intent.succeeded':
_write_log(`Event type: ${event.type}`,mydata.managed_domain);
break;
default:
_write_log(`Unexpected event type: ${event.type}`,mydata.managed_domain);
// Unexpected event type
}
res.sendStatus(200);
}
async function func__webhookListen(stripe,active_processor,managed_domain,app){
app.use((req, res, next) => {
let isWebhook = false;
for (let i = 0; i < active_processor.webhooks.length; i++) {
const index = i;
const webhook = active_processor.webhooks[index];
const endpoint = webhook.options.endpoint;
console.log(req.originalUrl)
if (req.originalUrl === endpoint) {
isWebhook = true;
break;
}
}
if(isWebhook==true){
next();
}else{
bodyParser.json()(req, res, next);
}
});
for (let i = 0; i < active_processor.webhooks.length; i++) {
const webhook = active_processor.webhooks[i];
const endpoint = webhook.options.endpoint;
console.log(endpoint)
app.post(endpoint, bodyParser.raw({ type: 'application/json' }), async (req, res) => {
let mydata = {
managed_domain: managed_domain,
processor: active_processor,
webhook: webhook
};
func__webhook(stripe,req,res,mydata);
});
}
}
/**
* Return true if there's a match for the given url within the webhookEndpoints object given by calling stripe.webhookEndpoints.list
* @param {string} url
* @param {object} webhookEndpoints
* @returns boolean
*/
function checkWebhookUrl(url,webhookEndpoints){
let doesExist = false;
let webhook = null;
for (let i = 0; i < webhookEndpoints.data.length; i++) {
const webh = webhookEndpoints.data[i];
if(webh.url==url){
doesExist = true;
webhook = webh;
break;
}
}
return {doesExist,webhook};
}
async function RunWebooks2(stripe,managed_domain,active_processor,app){
if(active_processor.webhooks==null || active_processor.webhooks==undefined){
active_processor.webhooks = getTempWebhookList();
console.log("webhook is null");
}else{
console.log("webhook is NOT null");
}
// whsec_ce937ab59c83dcecc659324f312e6044cc80246e3932d9b93bee27a3a6a513ef
if(active_processor.webhooks!=undefined && Array.isArray(active_processor.webhooks)){
const webhookEndpoints = await stripe.webhookEndpoints.list({
limit: 16,
});
// _write_log(JSON.stringify(webhookEndpoints),managed_domain);
//if(webhook.stripe!=undefined && webhook.stripe!=null && isObjectEmpty(webhook.stripe)){
for (let i = 0; i < active_processor.webhooks.length; i++) {
const index = i;
const webhook = active_processor.webhooks[index];
if(active_processor.stripe==null || active_processor.stripe==undefined){
let url = managed_domain.Address + ':' + active_processor.service_port + webhook.options.endpoint;
let obj1 = checkWebhookUrl(url,webhookEndpoints);
if(obj1.doesExist){
active_processor.webhooks[index].stripe = obj1.webhook;
continue;
}
// https://www15.appfactory.studio:9295/stripe_webook
const endpoint = await stripe.webhookEndpoints.create({
url: url,
enabled_events: webhook.options.enabled_events,
});
active_processor.webhooks[index].settings.secret = endpoint.secret;
active_processor.webhooks[index].settings.webhook = endpoint;
active_processor.webhooks[index].stripe = endpoint;
}
}
//}
// give some time for webhook creation to complete
setTimeout(() => {
webhook_update(active_processor);
func__webhookListen(stripe,active_processor,managed_domain,app);
},2000);
}
}
async function RunWebooks(request,response,stripe,managed_domain,active_processor,app){
const endpointSecret = 'whsec_5JA2kRDbUDoHVOFlDDU7TwyCPmfDUIEU';
let event = request.body;
// Only verify the event if you have an endpoint secret defined.
// Otherwise use the basic event deserialized with JSON.parse
if (endpointSecret) {
// Get the signature sent by Stripe
const signature = request.headers['stripe-signature'];
try {
event = stripe.webhooks.constructEvent(
request.body,
signature,
endpointSecret
);
} catch (err) {
console.log(`⚠️ Webhook signature verification failed.`, err.message);
return response.sendStatus(400);
}
}
// Handle the event
switch (event.type) {
case 'payment_intent.succeeded':
const paymentIntent = event.data.object;
console.log(`PaymentIntent for ${paymentIntent.amount} was successful!`);
// Then define and call a method to handle the successful payment intent.
// handlePaymentIntentSucceeded(paymentIntent);
break;
case 'payment_method.attached':
const paymentMethod = event.data.object;
console.log(paymentMethod);
// Then define and call a method to handle the successful attachment of a PaymentMethod.
// handlePaymentMethodAttached(paymentMethod);
break;
default:
// Unexpected event type
console.log(`Unhandled event type ${event.type}.`);
}
// Return a 200 response to acknowledge receipt of the event
response.send();
}
/**
* Create a mysql connect to the database with creditals.
* Make sure to call connection.end() after calling connection.connect()
* @returns mysql_connection
*/
function createMySQLConnection(){
return mysql.createConnection({
host: process.env.MY_HOSTNAME,
user: process.env.MY_USER,
password: process.env.MY_PASSWORD,
database: process.env.MY_DATABASE,
insecureAuth : true
});
}
let con = createMySQLConnection();
con.connect(function(err) {
if (err) throw err;
con.query(`SELECT * FROM subdomain_properties WHERE SubDomain = '${subdomain}'`, function (err, results) {
if (err) throw err;
// con.end();
if(results.length > 0){
let managed_domain = {};
for(let i=0; i < results.length; i++){
//console.log(results[i].SubDomain + " : " + results[i].PropertyName + " : " + results[i].PropertyValue);
managed_domain[results[i].PropertyName] = results[i].PropertyValue;
}
con.query(`SELECT * FROM configurations WHERE category="processors"`, function (err1, results1) {
if (err1) throw err1;
con.end();
if(results1.length > 0){
let processors = [];
for(let n=0; n < results1.length; n++){
let processor = results1[n];
processor.json = JSON.parse(decode(processor.json));
if(processor.json.processor=="stripe"){
processors.push(processor);
}
}
run(managed_domain, processors);
}else{
console.log(`No active server for subdomain ${subdomain}`);
}
});
}else{
console.log(`Error starting server! No port number found for subdomain ${subdomain}`);
}
});
});
let xmp = {
"real_db": "starterdb",
"db_user": "wx1234nn8nbslsj9",
"db_password": "MYblessings1984!",
"db_host": "localhost",
"Subdomain": "wx1234nn8nbslsj9",
"Username": "wx1234nn8nbslsj9",
"SystemUser": "wx1234nn8nbslsj9",
"Domain": "wx1234nn8nbslsj9.appfactory.studio",
"EmailServer": "server1.appfactory.studio",
"Address": "https://wx1234nn8nbslsj9.appfactory.studio",
"CertPrivateKeyLocation": "/etc/letsencrypt/live/wx1234nn8nbslsj9.appfactory.studio/privkey.pem",
"CertPublicKeyLocation": "/etc/letsencrypt/live/wx1234nn8nbslsj9.appfactory.studio/cert.pem"
}
function run(managed_domain,processors){
let active_processor = null;
for(let n=0; n < processors.length; n++){
if(processors[n].json.active==true){
active_processor = processors[n];
break;
}
}
console.log(active_processor);
console.log("Starting Stripe Server on port: " + active_processor.json.service_port);
let privateKey = fs.readFileSync(managed_domain.CertPrivateKeyLocation, 'utf8');
let certificate = fs.readFileSync(managed_domain.CertPublicKeyLocation, 'utf8');
let credentials = {key: privateKey, cert: certificate};
let app = express();
let clientId = active_processor.json.client_id;
let clientSecret = active_processor.json.client_secret;
let base = "";
let mode = active_processor.json.mode;
console.log(clientSecret);
console.log(managed_domain.CertPrivateKeyLocation);
console.log(managed_domain.CertPublicKeyLocation);
const stripe = require('stripe')(clientSecret, {
apiVersion: '2022-08-01',
appInfo: { // For sample support and debugging, not required for production:
name: "stripe-samples/subscription-use-cases/fixed-price",
version: "0.0.1",
url: "https://github.com/stripe-samples/subscription-use-cases/fixed-price"
}
});
// Use JSON parser for parsing payloads as JSON on all non-webhook routes.
// app.post('/webhook', express.raw({type: 'application/json'}), (request, response) => {
// RunWebooks(request,response,stripe,managed_domain,active_processor.json,app);
// });
RunWebooks2(stripe,managed_domain,active_processor.json,app);
// const endpointSecret = "whsec_5JA2kRDbUDoHVOFlDDU7TwyCPmfDUIEU"
const endpointSecret = 'whsec_ce937ab59c83dcecc659324f312e6044cc80246e3932d9b93bee27a3a6a513ef';
app.get("/"+active_processor.json.service_end_point, async (req, res) => {
// console.log(base);
let mydata = {
clientdata: JSON.parse(req.query.data),
managed_domain: managed_domain,
processor: active_processor
};
try {
if(req.query.type=="keys"){
res.jsonp({keys: {
client_id: mydata.processor.json.client_id,
client_secret: mydata.processor.json.client_secret
}});
}else if(req.query.type=="signle-create-payment-intent"){
func_single_create_payment_intent(stripe,req,res,mydata);
}else if(req.query.type=="check"){
res.jsonp({action:true});
}else if(req.query.type=="config"){
func__config(stripe,req,res,mydata);
}else if(req.query.type=="create-customer"){
func__create_customer(stripe,req,res,mydata);
}else if(req.query.type=="create-subscription"){
func__create_subscription(stripe,req,res,mydata);
}else if(req.query.type=="invoice-preview"){
func__invoice_preview(stripe,req,res,mydata);
}else if(req.query.type=="cancel-subscription"){
func__cancel_subscription(stripe,req,res,mydata);
}else if(req.query.type=="update-subscription"){
func__update_subscription();
}else if(req.query.type=="subscriptions"){
func__subscriptions(stripe,req,res,mydata);
}else if(req.query.type=="checking"){
// func__subscriptions(stripe,req,res,mydata);
res.jsonp("working 678");
}else{
res.jsonp("working 2");
}
} catch (err) {
console.log(err.message)
res.jsonp(err.message);
}
});
var httpsServer = https.createServer(credentials, app);
httpsServer.listen(active_processor.json.service_port);
}
function jumpstarter(){
if (
!process.env.STRIPE_SECRET_KEY ||
!process.env.STRIPE_PUBLISHABLE_KEY ||
!process.env.STATIC_DIR
) {
console.log(
'The .env file is not configured. Follow the instructions in the readme to configure the .env file. https://github.com/stripe-samples/subscription-use-cases'
);
console.log('');
process.env.STRIPE_SECRET_KEY
? ''
: console.log('Add STRIPE_SECRET_KEY to your .env file.');
process.env.STRIPE_PUBLISHABLE_KEY
? ''
: console.log('Add STRIPE_PUBLISHABLE_KEY to your .env file.');
process.env.STATIC_DIR
? ''
: console.log(
'Add STATIC_DIR to your .env file. Check .env.example in the root folder for an example'
);
process.exit();
}
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY, {
apiVersion: '2022-08-01',
appInfo: { // For sample support and debugging, not required for production:
name: "stripe-samples/subscription-use-cases/fixed-price",
version: "0.0.1",
url: "https://github.com/stripe-samples/subscription-use-cases/fixed-price"
}
});
// Use static to serve static assets.
app.use(express.static(process.env.STATIC_DIR));
// Use cookies to simulate logged in user.
app.use(cookieParser());
// Use JSON parser for parsing payloads as JSON on all non-webhook routes.
app.use((req, res, next) => {
if (req.originalUrl === '/webhook') {
next();
} else {
bodyParser.json()(req, res, next);
}
});
app.get('/', (req, res) => {
const path = resolve(process.env.STATIC_DIR + '/register.html');
res.sendFile(path);
});
app.get('/config', async (req, res) => {
const prices = await stripe.prices.list({
lookup_keys: ['pro_basic_v1', 'organization_v1', 'enterprise_v1'],
expand: ['data.product']
});
res.send({
publishableKey: process.env.STRIPE_PUBLISHABLE_KEY,
prices: prices.data,
});
});
app.post('/create-customer', async (req, res) => {
// Create a new customer object
const customer = await stripe.customers.create({
email: req.body.email,
});
// Save the customer.id in your database alongside your user.
// We're simulating authentication with a cookie.
res.cookie('customer', customer.id, { maxAge: 900000, httpOnly: true });
res.send({ customer: customer });
});
app.post('/create-subscription', async (req, res) => {
// Simulate authenticated user. In practice this will be the
// Stripe Customer ID related to the authenticated user.
const customerId = req.cookies['customer'];
// Create the subscription
const priceId = req.body.priceId;
try {
const subscription = await stripe.subscriptions.create({
customer: customerId,
items: [{
price: priceId,
}],
payment_behavior: 'default_incomplete',
expand: ['latest_invoice.payment_intent'],
});
res.send({
subscriptionId: subscription.id,
clientSecret: subscription.latest_invoice.payment_intent.client_secret,
});
} catch (error) {
return res.status(400).send({ error: { message: error.message } });
}
});
app.get('/invoice-preview', async (req, res) => {
const customerId = req.cookies['customer'];
const priceId = process.env[req.query.newPriceLookupKey.toUpperCase()];
const subscription = await stripe.subscriptions.retrieve(
req.query.subscriptionId
);
const invoice = await stripe.invoices.retrieveUpcoming({
customer: customerId,
subscription: req.query.subscriptionId,
subscription_items: [ {
id: subscription.items.data[0].id,
price: priceId,
}],
});
res.send({ invoice });
});
app.post('/cancel-subscription', async (req, res) => {
// Cancel the subscription
try {
const deletedSubscription = await stripe.subscriptions.del(
req.body.subscriptionId
);
res.send({ subscription: deletedSubscription });
} catch (error) {
return res.status(400).send({ error: { message: error.message } });
}
});
app.post('/update-subscription', async (req, res) => {
try {
const subscription = await stripe.subscriptions.retrieve(
req.body.subscriptionId
);
const updatedSubscription = await stripe.subscriptions.update(
req.body.subscriptionId, {
items: [{
id: subscription.items.data[0].id,
price: process.env[req.body.newPriceLookupKey.toUpperCase()],
}],
}
);
res.send({ subscription: updatedSubscription });
} catch (error) {
return res.status(400).send({ error: { message: error.message } });
}
});
app.get('/subscriptions', async (req, res) => {
// Simulate authenticated user. In practice this will be the
// Stripe Customer ID related to the authenticated user.
const customerId = req.cookies['customer'];
const subscriptions = await stripe.subscriptions.list({
customer: customerId,
status: 'all',
expand: ['data.default_payment_method'],
});
res.json({subscriptions});
});
app.post('/webhook',
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.header('Stripe-Signature'),
process.env.STRIPE_WEBHOOK_SECRET
);
} catch (err) {
console.log(err);
console.log(`⚠️ Webhook signature verification failed.`);
console.log(
`⚠️ Check the env file and enter the correct webhook secret.`
);
return res.sendStatus(400);
}
// Extract the object from the event.
const dataObject = event.data.object;
// Handle the event
// Review important events for Billing webhooks
// https://stripe.com/docs/billing/webhooks
// Remove comment to see the various objects sent for this sample
switch (event.type) {
case 'invoice.payment_succeeded':
if(dataObject['billing_reason'] == 'subscription_create') {
// The subscription automatically activates after successful payment
// Set the payment method used to pay the first invoice
// as the default payment method for that subscription
const subscription_id = dataObject['subscription']
const payment_intent_id = dataObject['payment_intent']
// Retrieve the payment intent used to pay the subscription
const payment_intent = await stripe.paymentIntents.retrieve(payment_intent_id);
try {
const subscription = await stripe.subscriptions.update(
subscription_id,
{
default_payment_method: payment_intent.payment_method,
},
);
console.log("Default payment method set for subscription:" + payment_intent.payment_method);
} catch (err) {
console.log(err);
console.log(`⚠️ Failed to update the default payment method for subscription: ${subscription_id}`);
}
};
break;
case 'invoice.payment_failed':
// If the payment fails or the customer does not have a valid payment method,
// an invoice.payment_failed event is sent, the subscription becomes past_due.
// Use this webhook to notify your user that their payment has
// failed and to retrieve new card details.
break;
case 'invoice.finalized':
// If you want to manually send out invoices to your customers
// or store them locally to reference to avoid hitting Stripe rate limits.
break;
case 'customer.subscription.deleted':
if (event.request != null) {
// handle a subscription cancelled by your request
// from above.
} else {
// handle subscription cancelled automatically based
// upon your subscription settings.
}
break;
case 'customer.subscription.trial_will_end':
// Send notification to your user that the trial will end
break;
default:
// Unexpected event type
}
res.sendStatus(200);
}
);
app.listen(4242, () => console.log(`Node server listening on port http://localhost:${4242}!`));
}// end function