more validation on credit card info; change smoke test for payment service to have a valid credit card
This commit is contained in:
parent
c7e7692057
commit
88ac6d8fc1
5 changed files with 80 additions and 14 deletions
64
src/paymentservice/charge.js
Normal file
64
src/paymentservice/charge.js
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
const cardValidator = require('simple-card-validator');
|
||||||
|
|
||||||
|
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 number.
|
||||||
|
*/
|
||||||
|
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,
|
||||||
|
cvv_length: cvvLength,
|
||||||
|
} = 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);
|
||||||
|
|
||||||
|
console.log(`Transaction processed: ${cardType} ending ${cardNumber.substr(-4)} \
|
||||||
|
Amount: ${amount.currency_code}${amount.amount.decimal}.${amount.amount.fractional}`)
|
||||||
|
|
||||||
|
return { transaction_id: -1 }
|
||||||
|
}
|
||||||
|
|
5
src/paymentservice/package-lock.json
generated
5
src/paymentservice/package-lock.json
generated
|
@ -723,6 +723,11 @@
|
||||||
"yargs": "3.32.0"
|
"yargs": "3.32.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"simple-card-validator": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/simple-card-validator/-/simple-card-validator-1.1.0.tgz",
|
||||||
|
"integrity": "sha1-675uRp/q7Cy7SBX4Qyu+BMccNvk="
|
||||||
|
},
|
||||||
"string-width": {
|
"string-width": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@grpc/proto-loader": "^0.1.0",
|
"@grpc/proto-loader": "^0.1.0",
|
||||||
"grpc": "^1.12.3"
|
"grpc": "^1.12.3",
|
||||||
|
"simple-card-validator": "^1.1.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
const grpc = require('grpc');
|
const grpc = require('grpc');
|
||||||
const protoLoader = require('@grpc/proto-loader');
|
const protoLoader = require('@grpc/proto-loader');
|
||||||
|
|
||||||
|
const charge = require('./charge');
|
||||||
|
|
||||||
class HipsterShopServer {
|
class HipsterShopServer {
|
||||||
constructor(protoFile, port = HipsterShopServer.DEFAULT_PORT) {
|
constructor(protoFile, port = HipsterShopServer.DEFAULT_PORT) {
|
||||||
this.port = port;
|
this.port = port;
|
||||||
|
@ -16,24 +18,18 @@ class HipsterShopServer {
|
||||||
*/
|
*/
|
||||||
static ChargeServiceHandler(call, callback) {
|
static ChargeServiceHandler(call, callback) {
|
||||||
try {
|
try {
|
||||||
const response = this.charge(call.request)
|
console.log(`PaymentService#Charge invoked with request ${JSON.stringify(call.request)}`)
|
||||||
|
const response = charge(call.request)
|
||||||
callback(null, response);
|
callback(null, response);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
console.warn(err);
|
||||||
callback(err);
|
callback(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Charge function
|
|
||||||
* @param {*} request
|
|
||||||
* @return transaction_id
|
|
||||||
*/
|
|
||||||
static charge(request) {
|
|
||||||
return { transaction_id: -1 }
|
|
||||||
}
|
|
||||||
|
|
||||||
listen() {
|
listen() {
|
||||||
this.server.bind(`0.0.0.0:${this.port}`, grpc.ServerCredentials.createInsecure());
|
this.server.bind(`0.0.0.0:${this.port}`, grpc.ServerCredentials.createInsecure());
|
||||||
|
console.log(`PaymentService grpc server listening on ${this.port}`);
|
||||||
this.server.start();
|
this.server.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -167,7 +167,7 @@ func testRecommendationService() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func testPaymentService() error {
|
func testPaymentService() error {
|
||||||
addr := os.Getenv("RECOMMENDATION_SERVICE_ADDR")
|
addr := os.Getenv("PAYMENT_SERVICE_ADDR")
|
||||||
conn, err := grpc.Dial(addr, grpc.WithInsecure())
|
conn, err := grpc.Dial(addr, grpc.WithInsecure())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -184,13 +184,13 @@ func testPaymentService() error {
|
||||||
Fractional: 55},
|
Fractional: 55},
|
||||||
},
|
},
|
||||||
CreditCard: &pb.CreditCardInfo{
|
CreditCard: &pb.CreditCardInfo{
|
||||||
CreditCardNumber: "9999-9999-9999-9999",
|
CreditCardNumber: "4444-4530-1092-6639",
|
||||||
CreditCardCvv: 612,
|
CreditCardCvv: 612,
|
||||||
CreditCardExpirationYear: 2022,
|
CreditCardExpirationYear: 2022,
|
||||||
CreditCardExpirationMonth: 10},
|
CreditCardExpirationMonth: 10},
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return err
|
||||||
}
|
}
|
||||||
log.Printf("--> resp: %+v", resp)
|
log.Printf("--> resp: %+v", resp)
|
||||||
return nil
|
return nil
|
||||||
|
|
Loading…
Add table
Reference in a new issue