diff --git a/.gitignore b/.gitignore index 4693e53..ab26476 100644 --- a/.gitignore +++ b/.gitignore @@ -10,11 +10,12 @@ # dependencies /node_modules src/node_modules +src/serviceAccountKey.json # misc npm-debug.log* +firebase-debug.log # vs studio code jsconfig.json typings/ - diff --git a/database.rules.json b/database.rules.json index 601e885..ef69cee 100644 --- a/database.rules.json +++ b/database.rules.json @@ -114,6 +114,9 @@ "isFeatured": { ".validate": "newData.isBoolean() && (data.exists() && newData.val() === data.val() || newData.val() === false)" }, + "isPremium": { + ".validate": "newData.isBoolean() && (data.exists() && newData.val() === data.val() || newData.val() === false)" + }, "link": { ".validate": "newData.isString() && newData.val().length < 150" }, diff --git a/src/app.js b/src/app.js index e04b4f3..83705be 100644 --- a/src/app.js +++ b/src/app.js @@ -1,8 +1,16 @@ +require('dotenv').config() const express = require('express') +const admin = require('firebase-admin') +const functions = require('firebase-functions') +const bodyParser = require('body-parser') const got = require('got') +const cors = require('cors') +const pkg = require('./package.json') const getIframe = require('./utils/get-iframe') const getOEmbed = require('./utils/get-oembed') +const payments = require('./payments') + /* * start Express server @@ -10,6 +18,31 @@ const getOEmbed = require('./utils/get-oembed') const app = express() +app.use(cors()) +app.use(bodyParser.json()) + + +/* + If we want to run the server outside of firebase's function servers + we'll need a service account, to have the right authorization + to connect as admin to our firebase instance. + + const serviceAccount = require("./serviceAccountKey.json") + admin.initializeApp({ + credential: admin.credential.cert(serviceAccount), + databaseURL: "https://radio4000-staging.firebaseio.com" + }); +*/ + +/* + When used on firebase servers, we just need to pull the config + and run the server that way: + $ firebase serve --only functions + source: https://firebase.google.com/docs/functions/local-emulator +*/ + +admin.initializeApp(functions.config().firebase); + /* * Global variables + @@ -93,6 +126,9 @@ function getChannelBySlug(slug) { } +app.use('/payments', payments) + + /* * Run server * */ diff --git a/src/index.js b/src/index.js index 25dad08..7889fbe 100644 --- a/src/index.js +++ b/src/index.js @@ -1,4 +1,5 @@ const functions = require('firebase-functions') const app = require('./app.js') + exports.api = functions.https.onRequest(app) diff --git a/src/package-lock.json b/src/package-lock.json new file mode 100644 index 0000000..34735bf --- /dev/null +++ b/src/package-lock.json @@ -0,0 +1,12 @@ +{ + "name": "functions", + "requires": true, + "lockfileVersion": 1, + "dependencies": { + "dotenv": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-4.0.0.tgz", + "integrity": "sha1-hk7xN5rO1Vzm+V3r7NzhefegzR0=" + } + } +} diff --git a/src/package.json b/src/package.json index 55eb756..ecacc4a 100644 --- a/src/package.json +++ b/src/package.json @@ -1,3 +1,4 @@ + { "name": "functions", "description": "Cloud Functions for Firebase", @@ -5,10 +6,14 @@ "start": "node ." }, "dependencies": { + "body-parser": "^1.17.2", + "dotenv": "^4.0.0", "express": "^4.15.3", + "cors": "^2.8.4", "firebase-admin": "^5.1.0", "firebase-functions": "^0.6.1", - "got": "^6.7.1" + "got": "^6.7.1", + "stripe": "^4.24.0" }, "private": true, "devDependencies": {} diff --git a/src/payments/index.js b/src/payments/index.js new file mode 100644 index 0000000..52ee83f --- /dev/null +++ b/src/payments/index.js @@ -0,0 +1,111 @@ +const express = require('express'); +const stripe = require('stripe') +const admin = require('firebase-admin') +const functions = require('firebase-functions') + +const payments = express.Router(); + +const keyPublishable = process.env.PUBLISHABLE_KEY; +/* const keySecret = process.env.SECRET_KEY;*/ +const keySecret = 'sk_test_F2Qx73O5Q4ggCF46ueqhte3c'; + +const stripeApp = stripe(keySecret); + +payments.post('/', function (req, res) { + const data = req.body + if (!data || !data.stripeCard) return res.sendStatus(400) + + const amount = 1400; + const { stripeCard, radio4000ChannelId } = data; + + const newCustomer = { + email: stripeCard.email, + source: stripeCard.id + } + + console.log('@payments:data', data) + console.log('@payments:newCustomer', newCustomer); + + stripeApp.customers.create(newCustomer).then(customer => { + console.log('@customers.create:customer', customer); + + const charge = { + customer: customer.id, + source: customer.default_source, + amount: 1400, + currency: "eur", + description: "Radio4000 Premium", + } + + stripeApp.charges.create(charge).then(answer => { + console.log('@charges.charge:charge', charge) + console.log('@charges.charge:answer', answer) + + if(answer.paid) { + var db = admin.database(); + var ref = db.ref(`channels/${radio4000ChannelId}`); + + console.log('radio4000ChannelId', radio4000ChannelId) + + ref.child('isPremium') + .set(true) + .then(completion => { + + res.status(200).json({ + message: 'charge sucess && channel.isPremium = true' + }) + + }).catch(completionError => { + console.log('@firebase:isPremium-c-error', completionError) + res.status(500).json({ + message: 'charge error: card charged, but channel not upgraded to premium' + }) + }) + } else { + // send error response + console.log('answer.paid', answer.paid) + res.status(500).json({ + message: 'charge error, answer.paid = false' + }) + } + }).catch(error => { + console.log('error charges.create', error); + res.status(500).json({ + message: 'charge create error' + }) + }); + }).catch(error => { + console.log('error customers.create', error); + res.status(500).json({ + message: 'customer create error' + }) + }) +}) + +/* Card object received + card: { + id: 'card_1AsEzGCSxcuHyPxSi2JYkGHM', + object: 'card', + address_city: null, + address_country: null, + address_line1: null, + address_line1_check: null, + address_line2: null, + address_state: null, + address_zip: null, + address_zip_check: null, + brand: 'Visa', + country: 'US', + cvc_check: 'pass', + dynamic_last4: null, + exp_month: 2, + exp_year: 2044, + funding: 'credit', + last4: '4242', + metadata: {}, + name: 'hu@hu.hu', + tokenization_method: null + } + */ + +module.exports = payments;