forked from GoogleCloudPlatform/microservices-demo
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcharge.js
115 lines (94 loc) · 3.58 KB
/
charge.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
// Copyright 2018 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
const cardValidator = require('simple-card-validator');
const uuid = require('uuid/v4');
const pino = require('pino');
const { BigQuery } = require('@google-cloud/bigquery');
// gcp credentails can be found in /config/team2-bg.json
process.env['GOOGLE_APPLICATION_CREDENTIALS'] = '/config/team2-bg.json';
const datasetId = 'hipstertamagochi';
const tableId = 'payments';
// Create a client
const bigqueryClient = new BigQuery();
const logger = pino({
name: 'paymentservice-charge',
messageKey: 'message',
changeLevelName: 'severity',
useLevelLabels: true
});
class CreditCardError extends Error {
constructor (message) {
super(message);
this.code = 400; // Invalid argument error
}
}
class InvalidCreditCard extends CreditCardError {
constructor (cardType) {
super(`Credit card info is invalid`);
}
}
class UnacceptedCreditCard extends CreditCardError {
constructor (cardType) {
super(`Sorry, we cannot process ${cardType} credit cards. Only VISA or MasterCard is accepted.`);
}
}
class ExpiredCreditCard extends CreditCardError {
constructor (number, month, year) {
super(`Your credit card (ending ${number.substr(-4)}) expired on ${month}/${year}`);
}
}
/**
* Verifies the credit card number and (pretend) charges the card.
*
* @param {*} request
* @return transaction_id - a random uuid v4.
*/
module.exports = function charge (request) {
const { amount, credit_card: creditCard } = request;
const cardNumber = creditCard.credit_card_number;
const cardInfo = cardValidator(cardNumber);
const {
card_type: cardType,
valid
} = cardInfo.getCardDetails();
if (!valid) { throw new InvalidCreditCard(); }
// Only VISA and mastercard is accepted, other card types (AMEX, dinersclub) will
// throw UnacceptedCreditCard error.
if (!(cardType === 'visa' || cardType === 'mastercard')) { throw new UnacceptedCreditCard(cardType); }
// Also validate expiration is > today.
const currentMonth = new Date().getMonth() + 1;
const currentYear = new Date().getFullYear();
const { credit_card_expiration_year: year, credit_card_expiration_month: month } = creditCard;
if ((currentYear * 12 + currentMonth) > (year * 12 + month)) { throw new ExpiredCreditCard(cardNumber.replace('-', ''), month, year); }
// publish transaction to our bigquery database - if we have a bigquery client
if (bigqueryClient) {
logger.info('sending data to Big Query');
const rows = [
{
"amount": amount.units + (amount.nanos / 1000000000),
"amount_currency_code": amount.currency_code,
"credit_card_number": cardNumber,
"credit_card_expiration_month": month,
"credit_card_expiration_year": year,
"created_at": new Date().getTime() / 1000
}]
bigqueryClient
.dataset(datasetId)
.table(tableId)
.insert(rows);
}
logger.info(`XXXTransaction processed: ${cardType} ending ${cardNumber.substr(-4)} \
Amount: ${amount.currency_code}${amount.units}.${amount.nanos}`);
return { transaction_id: uuid() };
};