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 from "express"; // import http from "http"; import https from "https"; // import * as paypal from "./paypal-api.js"; var mysql = require('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'); // Replace if using a different env file or config // require('dotenv').config({ path: './.env' }); // 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); /** * 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}`); } }); }); async function func__webhook_create(stripe,req,res,data){ const webhookEndpoint = await stripe.webhookEndpoints.create({ enabled_events: data.clientdata.enabled_events, //['charge.succeeded', 'charge.failed'], url: 'https://stripewebhooks.appfactory.studio/webhook_action'// 'https://example.com/my/webhook/endpoint', }); } async function func__webhook_update(stripe,req,res,data){ const webhookEndpoint = await stripe.webhookEndpoints.update( 'we_1Mr5jULkdIwHu7ix1ibLTM0x', { url: 'https://example.com/new_endpoint', } ); } async function func__webhook_stuff(){ const deleted = await stripe.webhookEndpoints.del('we_1Mr5jULkdIwHu7ix1ibLTM0x'); } async function func_server_products_list(stripe,req,res,mydata){ try{ const products = await stripe.products.list({}); res.jsonp({products}); }catch(err){ res.jsonp({ error: { message: error.message } }); } } async function func_server_create_subscription_plan(stripe,req,res,data){ const interval = data.clientdata.interval; const unit_amount = data.clientdata.unit_amount; const product_name = data.clientdata.product_name; const lookup_key = data.clientdata.lookup_key; const processor = data.processor; try { const price = await stripe.prices.create({ currency: 'usd', unit_amount: unit_amount, lookup_key: lookup_key, recurring: { interval: interval, }, product_data: { name: product_name, } }); if(processor.json.subscriptions==undefined){ processor.json.subscriptions = []; } processor.json.subscriptions.push(price); helperjs.updateJsonData(processor,"plugin_processors",createMySQLConnection()); res.jsonp({ price: price, processor: processor }); } catch (error){ res.jsonp({ error: { message: error.message } }); } } /** * This creates the subscription for the customer. * * * @param {*} stripe * @param {*} req * @param {*} res * @param {*} data * @returns */ async function func_client_create_subscription_for_customer(stripe,req,res,data){ const email = data.clientdata.email; const customerId = data.clientdata.customer_id; const priceId = data.clientdata.price_id; try { const prices = await stripe.prices.list({ lookup_keys: ['sample_basic', 'sample_premium'], expand: ['data.product'] }); const customer = await stripe.customer.create({ email: data.clientdata.email, }); // helperjs.getMemberUser(createMySQLConnection(), email, function(user){ // helperjs.updateMySQLMemberUsersJSONData(createMySQLConnection(),email,json_data); // }); const subscription = await stripe.subscriptions.create({ customer: customerId, items: [{ price: priceId, }], payment_behavior: 'default_incomplete', payment_settings: { save_default_payment_method: 'on_subscription' }, expand: ['latest_invoice.payment_intent'], }); // /home/appfactorystudio/websites/www15/portal/admin/services/stripe/ res.jsonp({ response: "true", price: priceId, customerId: customerId, subscription: subscription, subscriptionId: subscription.id, clientSecret: subscription.latest_invoice.payment_intent.client_secret }); } catch (error) { res.jsonp({ error: { message: error.message } }); } } async function func__subscription_product_create(stripe,req,res,data){ try{ const product = await stripe.products.create({ name: data.clientdata.product_name, }); res.jsonp({products}); }catch(err){ res.jsonp({ error: { message: error.message } }); } res.jsonp({ response: product, }); } async function func__subscription_screate_schedule(stripe,req,res,data){ const subscriptionSchedule = await stripe.subscriptionSchedules.create ({ customer: 'cus_GBHHxuvBvO26Ea', start_date: 'now', end_behavior: 'release', phases: [ { items: [ { price: 'price_1GqNdGAJVYItwOKqEHb', quantity: 1, }, ], iterations: 12, }, ], }); // const orderID = req.query.orderID; // const captureData = await paypal.refundPayment(orderID); res.jsonp(subscriptionSchedule); // const subscriptionSchedule = await stripe.subscriptionSchedules.create // ({ // from_subscription: 'sub_GB98WOvaRAWPl6', // }); } async function func__subscription_create_product(stripe,req,res,data){ const product = await stripe.products.create({ name: data.clientdata.name, }); res.jsonp(product); } async function func__subscription_create_price(stripe,req,res,data){ const price = await stripe.prices.create(data.clientdata.price_data); res.jsonp(price); } async function func__config(stripe,req,res,data){ const prices = await stripe.prices.list({ lookup_keys: ['sample_basic', 'sample_premium'], expand: ['data.product'] }); res.jsonp({ prices: prices.data, }); } async function func__create_customer(stripe,req,res,data){ // Create a new customer object const customer = await stripe.customer.create({ email: data.clientdata.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 }); let email = data.clientdata.email; helperjs.getMemberUser(createMySQLConnection(), email, function(user){ helperjs.updateMySQLMemberUsersJSONData(createMySQLConnection(),email,json_data); }); res.jsonp({ customer: customer }); } async function func__create_subscription(stripe,req,res,data){ // 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, }); res.jsonp(price); } catch (error) { // res.jsonp(price); return res.status(400).send({ error: { message: error.message } }); } } async function func__invoice_preview(stripe,req,res,data){ 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 }); } async function func__cancel_subscription(stripe,req,res,data){ // Cancel the subscription try { const deletedSubscription = await stripe.subscriptions.del( req.body.subscriptionId ); res.send({ subscription: deletedSubscription }); res.jsonp(price); } catch (error) { // res.jsonp(price); return res.status(400).send({ error: { message: error.message } }); } } async function func__update_subscription(stripe,req,res,data){ 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 }); res.jsonp(price); } catch (error) { // res.jsonp(price); return res.status(400).send({ error: { message: error.message } }); } } async function func__subscriptions_list(stripe,req,res,data){ // 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}); } function run(managed_domain,processors){ // function run(opts,opts1){ 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; // if(mode=="sandbox"){ // base = "https://api-m.sandbox.paypal.com"; // }else{ // base = "https://api-m.paypal.com"; // } app.get("/"+active_processor.json.service_end_point, async (req, res) => { 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" } }); // console.log(base); let mydata = { clientdata: JSON.parse(req.query.data), managed_domain: managed_domain, processor: active_processor }; try { if(req.query.type=="check"){ res.jsonp({action:true}); }else if(req.query.type=="admin-create-subscription"){ func_server_create_subscription_plan(stripe,req,res,mydata); }else if(req.query.type=="admin_list_products"){ func_server_products_list(stripe,req,res,mydata); }else if(req.query.type=="subscription-create-product"){ func_client_create_subscription_for_customer(stripe,req,res,mydata); }else if(req.query.type=="subscription-create-product"){ func__subscription_create_product(stripe,req,res,mydata); }else if(req.query.type=="subscription_create_product"){ func__subscription_product_create(stripe,req,res,mydata); }else if(req.query.type=="subscription_create_price"){ func__subscription_create_price(stripe,req,res,mydata); }else if(req.query.type=="subscriptions_list"){ func__subscriptions_list(stripe,req,res,mydata); }else if(req.query.type=="subscription_update"){ func__update_subscription(stripe,req,res,mydata); }else if(req.query.type=="subscription_cancel"){ func__cancel_subscription(stripe,req,res,mydata); }else if(req.query.type=="invoice-preview"){ func__invoice_preview(stripe,req,res,mydata); }else if(req.query.type=="subscription_create"){ func__create_subscription(stripe,req,res,mydata); }else if(req.query.type=="customer_create"){ func__create_customer(stripe,req,res,mydata); }else if(req.query.type=="config"){ func__config(stripe,req,res,mydata); }else if(req.query.type=="webhook_create"){ func__webhook_create(stripe,req,res,mydata); }else if(req.query.type=="subscription_create_schedule"){ func__subscription_screate_schedule(stripe,req,res,mydata); }else{ res.jsonp("working"); } } catch (err) { console.log(err.message) res.jsonp(err.message); } }); // https://www.appfactory.studio/portal/admin/api/php/webhook.php // https://stripewebhooks.appfactory.studio/webhook_action // https://webhooks.appfactory.studio/stripe/webhook_action app.post('/webhook_action', bodyParser.raw({ type: 'application/json' }), async (req, res) => { 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" } }); // 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(`⚠️ Falied 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); } ); var httpsServer = https.createServer(credentials, app); httpsServer.listen(active_processor.json.service_port); } //{"obj":"www15-stripe-vCLAgOX2"}{"message":"success"} // pm2 delete www15;pm2 start server.js --name "www15" -- www15;pm2 log --lines 200 www15 // pm2 start server.js --name "www15" -- www15 // pm2 start server.js --name "www10" -- www10 // pm2 delete www15;pm2 start server.js --name www15 -- www15;pm2 logs www --lines 1000 // pm2 logs --lines 1000 //process.argv.forEach(function (val, index, array) {console.log(index + ': ' + val);}); // pm2 start server.js --name "www15_paypal" --namespace payapl -- www15 // pm2 start server.js --name "www15_stripe" --namespace stripe -- www15 // pm2 log --lines 500 www15-paypal