Skip to content
This repository was archived by the owner on Mar 2, 2021. It is now read-only.

Commit 0137247

Browse files
authored
Merge pull request #23 from internet4000/feature/payments
WIP Feature/payments (handle stripe charges)
2 parents 37e8aba + 0a1ddcc commit 0137247

File tree

7 files changed

+171
-2
lines changed

7 files changed

+171
-2
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,12 @@
1010
# dependencies
1111
/node_modules
1212
src/node_modules
13+
src/serviceAccountKey.json
1314

1415
# misc
1516
npm-debug.log*
17+
firebase-debug.log
1618

1719
# vs studio code
1820
jsconfig.json
1921
typings/
20-

database.rules.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,9 @@
114114
"isFeatured": {
115115
".validate": "newData.isBoolean() && (data.exists() && newData.val() === data.val() || newData.val() === false)"
116116
},
117+
"isPremium": {
118+
".validate": "newData.isBoolean() && (data.exists() && newData.val() === data.val() || newData.val() === false)"
119+
},
117120
"link": {
118121
".validate": "newData.isString() && newData.val().length < 150"
119122
},

src/app.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,48 @@
1+
require('dotenv').config()
12
const express = require('express')
3+
const admin = require('firebase-admin')
4+
const functions = require('firebase-functions')
5+
const bodyParser = require('body-parser')
26
const got = require('got')
7+
const cors = require('cors')
8+
const pkg = require('./package.json')
39
const getIframe = require('./utils/get-iframe')
410
const getOEmbed = require('./utils/get-oembed')
511

12+
const payments = require('./payments')
13+
614

715
/*
816
* start Express server
917
* */
1018

1119
const app = express()
1220

21+
app.use(cors())
22+
app.use(bodyParser.json())
23+
24+
25+
/*
26+
If we want to run the server outside of firebase's function servers
27+
we'll need a service account, to have the right authorization
28+
to connect as admin to our firebase instance.
29+
30+
const serviceAccount = require("./serviceAccountKey.json")
31+
admin.initializeApp({
32+
credential: admin.credential.cert(serviceAccount),
33+
databaseURL: "https://radio4000-staging.firebaseio.com"
34+
});
35+
*/
36+
37+
/*
38+
When used on firebase servers, we just need to pull the config
39+
and run the server that way:
40+
$ firebase serve --only functions
41+
source: https://firebase.google.com/docs/functions/local-emulator
42+
*/
43+
44+
admin.initializeApp(functions.config().firebase);
45+
1346

1447
/*
1548
* Global variables +
@@ -93,6 +126,9 @@ function getChannelBySlug(slug) {
93126
}
94127

95128

129+
app.use('/payments', payments)
130+
131+
96132
/*
97133
* Run server
98134
* */

src/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
const functions = require('firebase-functions')
22
const app = require('./app.js')
33

4+
45
exports.api = functions.https.onRequest(app)

src/package-lock.json

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/package.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
1+
12
{
23
"name": "functions",
34
"description": "Cloud Functions for Firebase",
45
"scripts": {
56
"start": "node ."
67
},
78
"dependencies": {
9+
"body-parser": "^1.17.2",
10+
"dotenv": "^4.0.0",
811
"express": "^4.15.3",
12+
"cors": "^2.8.4",
913
"firebase-admin": "^5.1.0",
1014
"firebase-functions": "^0.6.1",
11-
"got": "^6.7.1"
15+
"got": "^6.7.1",
16+
"stripe": "^4.24.0"
1217
},
1318
"private": true,
1419
"devDependencies": {}

src/payments/index.js

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
const express = require('express');
2+
const stripe = require('stripe')
3+
const admin = require('firebase-admin')
4+
const functions = require('firebase-functions')
5+
6+
const payments = express.Router();
7+
8+
const keyPublishable = process.env.PUBLISHABLE_KEY;
9+
/* const keySecret = process.env.SECRET_KEY;*/
10+
const keySecret = 'sk_test_F2Qx73O5Q4ggCF46ueqhte3c';
11+
12+
const stripeApp = stripe(keySecret);
13+
14+
payments.post('/', function (req, res) {
15+
const data = req.body
16+
if (!data || !data.stripeCard) return res.sendStatus(400)
17+
18+
const amount = 1400;
19+
const { stripeCard, radio4000ChannelId } = data;
20+
21+
const newCustomer = {
22+
email: stripeCard.email,
23+
source: stripeCard.id
24+
}
25+
26+
console.log('@payments:data', data)
27+
console.log('@payments:newCustomer', newCustomer);
28+
29+
stripeApp.customers.create(newCustomer).then(customer => {
30+
console.log('@customers.create:customer', customer);
31+
32+
const charge = {
33+
customer: customer.id,
34+
source: customer.default_source,
35+
amount: 1400,
36+
currency: "eur",
37+
description: "Radio4000 Premium",
38+
}
39+
40+
stripeApp.charges.create(charge).then(answer => {
41+
console.log('@charges.charge:charge', charge)
42+
console.log('@charges.charge:answer', answer)
43+
44+
if(answer.paid) {
45+
var db = admin.database();
46+
var ref = db.ref(`channels/${radio4000ChannelId}`);
47+
48+
console.log('radio4000ChannelId', radio4000ChannelId)
49+
50+
ref.child('isPremium')
51+
.set(true)
52+
.then(completion => {
53+
54+
res.status(200).json({
55+
message: 'charge sucess && channel.isPremium = true'
56+
})
57+
58+
}).catch(completionError => {
59+
console.log('@firebase:isPremium-c-error', completionError)
60+
res.status(500).json({
61+
message: 'charge error: card charged, but channel not upgraded to premium'
62+
})
63+
})
64+
} else {
65+
// send error response
66+
console.log('answer.paid', answer.paid)
67+
res.status(500).json({
68+
message: 'charge error, answer.paid = false'
69+
})
70+
}
71+
}).catch(error => {
72+
console.log('error charges.create', error);
73+
res.status(500).json({
74+
message: 'charge create error'
75+
})
76+
});
77+
}).catch(error => {
78+
console.log('error customers.create', error);
79+
res.status(500).json({
80+
message: 'customer create error'
81+
})
82+
})
83+
})
84+
85+
/* Card object received
86+
card: {
87+
id: 'card_1AsEzGCSxcuHyPxSi2JYkGHM',
88+
object: 'card',
89+
address_city: null,
90+
address_country: null,
91+
address_line1: null,
92+
address_line1_check: null,
93+
address_line2: null,
94+
address_state: null,
95+
address_zip: null,
96+
address_zip_check: null,
97+
brand: 'Visa',
98+
country: 'US',
99+
cvc_check: 'pass',
100+
dynamic_last4: null,
101+
exp_month: 2,
102+
exp_year: 2044,
103+
funding: 'credit',
104+
last4: '4242',
105+
metadata: {},
106+
name: 'hu@hu.hu',
107+
tokenization_method: null
108+
}
109+
*/
110+
111+
module.exports = payments;

0 commit comments

Comments
 (0)