/
card.js
118 lines (100 loc) · 4.1 KB
/
card.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
116
117
118
'use strict'
// NPM dependencies
const _ = require('lodash')
const changeCase = require('change-case')
const AWSXRay = require('aws-xray-sdk')
const { getNamespace } = require('continuation-local-storage')
const i18n = require('i18n')
// Local dependencies
const logger = require('../utils/logger')(__filename)
const cardIdClient = require('../services/clients/cardid_client')
const { NAMESPACE_NAME, XRAY_SEGMENT_KEY_NAME } = require('../../config/cls')
const i18nConfig = require('../../config/i18n')
i18n.configure(i18nConfig)
const checkCard = function (cardNo, allowed, language, correlationId, subSegment) {
return new Promise(function (resolve, reject) {
const startTime = new Date()
const data = { cardNumber: parseInt(cardNo) }
i18n.setLocale(language || 'en')
// Use a subSegment if passed, otherwise get our main segment
if (!subSegment) {
const namespace = getNamespace(NAMESPACE_NAME)
subSegment = namespace.get(XRAY_SEGMENT_KEY_NAME)
}
AWSXRay.captureAsyncFunc('cardIdClient_post', function (postSubsegment) {
if (cardNo.length > 0 && cardNo.length < 11) {
postSubsegment.close()
return reject(new Error(i18n.__('fieldErrors.fields.cardNo.numberIncorrectLength')))
}
cardIdClient.post({ payload: data, correlationId: correlationId }, postSubsegment)
.then((response) => {
postSubsegment.close()
logger.info(`[${correlationId}] - %s to %s ended - total time %dms`, 'POST', cardIdClient.CARD_URL, new Date() - startTime)
if (response.statusCode === 404) {
return reject(new Error('Your card is not supported'))
}
if (response.statusCode === 422) {
return reject(new Error(i18n.__('fieldErrors.fields.cardNo.message')))
}
// if the server is down, or returns non 500, just continue
if (response.statusCode !== 200) {
return resolve()
}
const body = response.body
const card = {
brand: changeCase.paramCase(body.brand),
type: normaliseCardType(body.type),
corporate: body.corporate,
prepaid: body.prepaid
}
logger.debug(`[${correlationId}] Checking card brand`, {
cardBrand: card.brand,
cardType: card.type
})
if (_.filter(allowed, { brand: card.brand }).length === 0) {
reject(new Error(i18n.__('fieldErrors.fields.cardNo.unsupportedBrand', changeCase.titleCase(card.brand))))
}
if (!_.find(allowed, { brand: card.brand, type: card.type })) {
switch (card.type) {
case 'DEBIT':
return reject(new Error(i18n.__('fieldErrors.fields.cardNo.unsupportedDebitCard', changeCase.titleCase(card.brand))))
case 'CREDIT':
return reject(new Error(i18n.__('fieldErrors.fields.cardNo.unsupportedCreditCard', changeCase.titleCase(card.brand))))
}
}
resolve(card)
})
.catch(error => {
postSubsegment.close(error)
logger.error(`[${correlationId}] ERROR CALLING CARDID AT ${cardIdClient.CARD_URL}`, error)
logger.info(`[${correlationId}] - %s to %s ended - total time %dms`, 'POST', cardIdClient.cardUrl, new Date() - startTime)
resolve()
})
}, subSegment)
})
}
const normaliseCardType = function (cardType) {
switch (cardType) {
case 'D':
return 'DEBIT'
case 'C':
return 'CREDIT'
case 'CD':
return 'CREDIT_OR_DEBIT'
}
return undefined
}
module.exports = function (allowedCards, correlationId) {
const withdrawalTypes = []
const allowed = _.clone(allowedCards)
correlationId = correlationId || ''
if (_.filter(allowedCards, { debit: true }).length !== 0) withdrawalTypes.push('debit')
if (_.filter(allowedCards, { credit: true }).length !== 0) withdrawalTypes.push('credit')
return {
withdrawalTypes: withdrawalTypes,
allowed: _.clone(allowed),
checkCard: (cardNo, language, subSegment) => {
return checkCard(cardNo, allowed, language, correlationId, subSegment)
}
}
}