fix(env): make PayPal env config dynamic

This commit is contained in:
Mrugesh Mohapatra
2020-03-16 14:32:35 +05:30
parent 6c6eadfbe4
commit f9277b4fec
7 changed files with 45 additions and 58 deletions

View File

@ -12,18 +12,12 @@ import {
import { import {
durationKeysConfig, durationKeysConfig,
donationOneTimeConfig, donationOneTimeConfig,
donationSubscriptionConfig, donationSubscriptionConfig
paypalConfig
} from '../../../config/donation-settings'; } from '../../../config/donation-settings';
import keys from '../../../config/secrets'; import keys from '../../../config/secrets';
const log = debug('fcc:boot:donate'); const log = debug('fcc:boot:donate');
const paypalWebhookId =
process.env.FREECODECAMP_NODE_ENV === 'production'
? paypalConfig.production.webhookId
: paypalConfig.development.webhookId;
export default function donateBoot(app, done) { export default function donateBoot(app, done) {
let stripe = false; let stripe = false;
const api = app.loopback.Router(); const api = app.loopback.Router();
@ -255,6 +249,7 @@ export default function donateBoot(app, done) {
.send({ error: 'Donation failed due to a server error.' }) .send({ error: 'Donation failed due to a server error.' })
); );
} }
function addDonation(req, res) { function addDonation(req, res) {
const { user, body } = req; const { user, body } = req;
@ -284,7 +279,7 @@ export default function donateBoot(app, done) {
return Promise.resolve(req) return Promise.resolve(req)
.then(verifyWebHookType) .then(verifyWebHookType)
.then(getAsyncPaypalToken) .then(getAsyncPaypalToken)
.then(token => verifyWebHook(headers, body, token, paypalWebhookId)) .then(token => verifyWebHook(headers, body, token, keys.paypal.webhookId))
.then(hookBody => updateUser(hookBody, app)) .then(hookBody => updateUser(hookBody, app))
.then(() => res.status(200).json({ message: 'received hook' })) .then(() => res.status(200).json({ message: 'received hook' }))
.catch(err => { .catch(err => {
@ -310,37 +305,21 @@ export default function donateBoot(app, done) {
!hmacKey || hmacKey === 'secret_key_from_servicebot_dashboard'; !hmacKey || hmacKey === 'secret_key_from_servicebot_dashboard';
const paypalInvalid = paypalPublicInvalid || paypalSecretInvalid; const paypalInvalid = paypalPublicInvalid || paypalSecretInvalid;
const stripeInvalid = stripeSecretInvalid || stripPublicInvalid; const stripeInvalid = stripeSecretInvalid || stripPublicInvalid;
if (stripeInvalid) {
if (stripeInvalid || paypalInvalid || hmacKeyInvalid) {
if (process.env.FREECODECAMP_NODE_ENV === 'production') { if (process.env.FREECODECAMP_NODE_ENV === 'production') {
throw new Error('Stripe API keys are required to boot the server!'); throw new Error('Donation API keys are required to boot the server!');
} }
console.info('No Stripe API keys were found, moving on...'); log('Donation disabled in development unless ALL test keys are provided');
done();
} else { } else {
api.post('/charge-stripe', createStripeDonation); api.post('/charge-stripe', createStripeDonation);
api.post('/create-hmac-hash', createHmacHash); api.post('/create-hmac-hash', createHmacHash);
}
if (paypalInvalid) {
if (process.env.FREECODECAMP_NODE_ENV === 'production') {
throw new Error('PayPal API keys are required to boot the server!');
}
console.info('No PayPal API keys were found, moving on...');
} else {
api.post('/update-paypal', updatePaypal);
api.post('/add-donation', addDonation); api.post('/add-donation', addDonation);
} api.post('/update-paypal', updatePaypal);
if (hmacKeyInvalid) {
if (process.env.FREECODECAMP_NODE_ENV === 'production') {
throw new Error('Servicebot HMAC key is required to boot the server!');
}
console.info('No servicebot HMAC key was found, moving on...');
}
donateRouter.use('/donate', api); donateRouter.use('/donate', api);
app.use(donateRouter); app.use(donateRouter);
app.use('/internal', donateRouter); app.use('/internal', donateRouter);
if (stripeInvalid) {
done();
} else {
connectToStripe().then(done); connectToStripe().then(done);
} }
} }

View File

@ -5,14 +5,14 @@ import keys from '../../../config/secrets';
const log = debug('fcc:boot:donate'); const log = debug('fcc:boot:donate');
const sandBoxSubdomain = const paypalverifyWebhookURL =
process.env.FREECODECAMP_NODE_ENV === 'production' ? '' : 'sandbox.'; keys.paypal.verifyWebhookURL ||
`https://api.sandbox.paypal.com/v1/notifications/verify-webhook-signature`;
const verificationUrl = `https://api.${sandBoxSubdomain}paypal.com/v1/notifications/verify-webhook-signature`; const paypalTokenURL =
const tokenUrl = `https://api.${sandBoxSubdomain}paypal.com/v1/oauth2/token`; keys.paypal.tokenUrl || `https://api.sandbox.paypal.com/v1/oauth2/token`;
export async function getAsyncPaypalToken() { export async function getAsyncPaypalToken() {
const res = await axios.post(tokenUrl, null, { const res = await axios.post(paypalTokenURL, null, {
headers: { headers: {
'Content-Type': 'application/x-www-form-urlencoded' 'Content-Type': 'application/x-www-form-urlencoded'
}, },
@ -48,7 +48,7 @@ export async function verifyWebHook(headers, body, token, webhookId) {
webhook_event: webhookEventBody webhook_event: webhookEventBody
}; };
const response = await axios.post(verificationUrl, payload, { const response = await axios.post(paypalverifyWebhookURL, payload, {
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
Authorization: `Bearer ${token}` Authorization: `Bearer ${token}`

View File

@ -22,11 +22,8 @@ import {
jest.mock('axios'); jest.mock('axios');
const sandBoxSubdomain = const verificationUrl = `https://api.sandbox.paypal.com/v1/notifications/verify-webhook-signature`;
process.env.FREECODECAMP_NODE_ENV === 'production' ? '' : 'sandbox.'; const tokenUrl = `https://api.sandbox.paypal.com/v1/oauth2/token`;
const verificationUrl = `https://api.${sandBoxSubdomain}paypal.com/v1/notifications/verify-webhook-signature`;
const tokenUrl = `https://api.${sandBoxSubdomain}paypal.com/v1/oauth2/token`;
const { const {
body: activationHookBody, body: activationHookBody,
headers: activationHookHeaders headers: activationHookHeaders

View File

@ -1,5 +1,4 @@
/* eslint-disable camelcase */ /* eslint-disable camelcase */
/* global ENVIRONMENT */
import React, { Component } from 'react'; import React, { Component } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
@ -11,16 +10,13 @@ import { verifySubscriptionPaypal } from '../../utils/ajax';
import { paypalConfig } from '../../../../config/donation-settings'; import { paypalConfig } from '../../../../config/donation-settings';
import { signInLoadingSelector, userSelector, executeGA } from '../../redux'; import { signInLoadingSelector, userSelector, executeGA } from '../../redux';
const paypalDurationPlans = const { durationPlans } = paypalConfig;
ENVIRONMENT === 'production'
? paypalConfig.production.durationPlans
: paypalConfig.development.durationPlans;
export class PaypalButton extends Component { export class PaypalButton extends Component {
constructor(...props) { constructor(...props) {
super(...props); super(...props);
this.state = { this.state = {
planId: paypalDurationPlans.month['500'].planId planId: durationPlans.month['500'].planId
}; };
this.handleApproval = this.handleApproval.bind(this); this.handleApproval = this.handleApproval.bind(this);
} }

View File

@ -1,3 +1,5 @@
require('dotenv').config();
// Configuration for client side // Configuration for client side
const durationsConfig = { const durationsConfig = {
year: 'yearly', year: 'yearly',
@ -40,9 +42,8 @@ const donationSubscriptionConfig = {
}; };
// Shared paypal configuration // Shared paypal configuration
const paypalConfig = { const paypalConfigTypes = {
production: { live: {
webhookId: '8AM40465WC915574A',
durationPlans: { durationPlans: {
month: { month: {
'500': { '500': {
@ -51,8 +52,7 @@ const paypalConfig = {
} }
} }
}, },
development: { staging: {
webhookId: '2UL63757DN298592C',
durationPlans: { durationPlans: {
month: { month: {
'500': { '500': {
@ -63,6 +63,10 @@ const paypalConfig = {
} }
}; };
const paypalConfig = process.env.DEPLOYMENT_ENV
? paypalConfigTypes['live']
: paypalConfigTypes['staging'];
module.exports = { module.exports = {
durationsConfig, durationsConfig,
amountsConfig, amountsConfig,

View File

@ -37,7 +37,10 @@ const {
SERVICEBOT_HMAC_SECRET_KEY, SERVICEBOT_HMAC_SECRET_KEY,
PAYPAL_CLIENT_ID, PAYPAL_CLIENT_ID,
PAYPAL_SECRET PAYPAL_SECRET,
PAYPAL_VERIFY_WEBHOOK_URL,
PAYPAL_API_TOKEN_URL,
PAYPAL_WEBHOOK_ID
} = process.env; } = process.env;
module.exports = { module.exports = {
@ -104,7 +107,10 @@ module.exports = {
paypal: { paypal: {
client: PAYPAL_CLIENT_ID, client: PAYPAL_CLIENT_ID,
secret: PAYPAL_SECRET secret: PAYPAL_SECRET,
verifyWebhookURL: PAYPAL_VERIFY_WEBHOOK_URL,
tokenUrl: PAYPAL_API_TOKEN_URL,
webhookId: PAYPAL_WEBHOOK_ID
}, },
servicebot: { servicebot: {

View File

@ -23,8 +23,13 @@ SERVICEBOT_ID=servicebot_id_from_servicebot_dashboard
SERVICEBOT_HMAC_SECRET_KEY=secret_key_from_servicebot_dashboard SERVICEBOT_HMAC_SECRET_KEY=secret_key_from_servicebot_dashboard
PAYPAL_SUPPORTERS=1703 PAYPAL_SUPPORTERS=1703
PAYPAL_CLIENT_ID=id_from_paypal_dashboard PAYPAL_CLIENT_ID=id_from_paypal_dashboard
PAYPAL_SECRET=secret_from_paypal_dashboard PAYPAL_SECRET=secret_from_paypal_dashboard
PAYPAL_VERIFY_WEBHOOK_URL='https://api.sandbox.paypal.com/v1/notifications/verify-webhook-signature'
PAYPAL_API_TOKEN_URL='https://api.sandbox.paypal.com/v1/oauth2/token'
PAYPAL_WEBHOOK_ID=webhook_id_from_paypal_dashboard
DEPLOYMENT_ENV='staging'
PEER=stuff PEER=stuff
DEBUG=true DEBUG=true