Merge pull request #1689 from RafaelTaranto/chore/sumsub-rebase-simplified
chore: sumsub rebase simplified
This commit is contained in:
commit
09c3fb8a70
29 changed files with 828 additions and 73 deletions
80
lib/compliance-external.js
Normal file
80
lib/compliance-external.js
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
const _ = require('lodash/fp')
|
||||
|
||||
const logger = require('./logger')
|
||||
const configManager = require('./new-config-manager')
|
||||
const ph = require('./plugin-helper')
|
||||
|
||||
const getPlugin = (settings, pluginCode) => {
|
||||
const account = settings.accounts[pluginCode]
|
||||
const plugin = ph.load(ph.COMPLIANCE, pluginCode)
|
||||
|
||||
return ({ plugin, account })
|
||||
}
|
||||
|
||||
const getStatus = (settings, service, customerId) => {
|
||||
try {
|
||||
const { plugin, account } = getPlugin(settings, service)
|
||||
|
||||
return plugin.getApplicantStatus(account, customerId)
|
||||
.then((status) => ({
|
||||
service,
|
||||
status
|
||||
}))
|
||||
.catch((error) => {
|
||||
if (error.response.status !== 404) logger.error(`Error getting applicant for service ${service}:`, error.message)
|
||||
return {
|
||||
service: service,
|
||||
status: null,
|
||||
}
|
||||
})
|
||||
} catch (error) {
|
||||
logger.error(`Error loading plugin for service ${service}:`, error)
|
||||
return Promise.resolve({
|
||||
service: service,
|
||||
status: null,
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const getStatusMap = (settings, customerExternalCompliance) => {
|
||||
const triggers = configManager.getTriggers(settings.config)
|
||||
const services = _.flow(
|
||||
_.map('externalService'),
|
||||
_.compact,
|
||||
_.uniq
|
||||
)(triggers)
|
||||
|
||||
const applicantPromises = _.map(service => {
|
||||
return getStatus(settings, service, customerExternalCompliance)
|
||||
})(services)
|
||||
|
||||
return Promise.all(applicantPromises)
|
||||
.then((applicantResults) => {
|
||||
return _.reduce((map, result) => {
|
||||
if (result.status) map[result.service] = result.status
|
||||
return map
|
||||
}, {})(applicantResults)
|
||||
})
|
||||
}
|
||||
|
||||
const createApplicant = (settings, externalService, customerId) => {
|
||||
const account = settings.accounts[externalService]
|
||||
const { plugin } = getPlugin(settings, externalService)
|
||||
|
||||
return plugin.createApplicant(account, customerId, account.applicantLevel)
|
||||
}
|
||||
|
||||
const createLink = (settings, externalService, customerId) => {
|
||||
const account = settings.accounts[externalService]
|
||||
const { plugin } = getPlugin(settings, externalService)
|
||||
|
||||
return plugin.createLink(account, customerId, account.applicantLevel)
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getStatusMap,
|
||||
getStatus,
|
||||
createApplicant,
|
||||
createLink
|
||||
}
|
||||
106
lib/customers.js
106
lib/customers.js
|
|
@ -17,6 +17,9 @@ const NUM_RESULTS = 1000
|
|||
const sms = require('./sms')
|
||||
const settingsLoader = require('./new-settings-loader')
|
||||
const logger = require('./logger')
|
||||
const externalCompliance = require('./compliance-external')
|
||||
|
||||
const { APPROVED, RETRY } = require('./plugins/compliance/consts')
|
||||
|
||||
const TX_PASSTHROUGH_ERROR_CODES = ['operatorCancel', 'scoreThresholdReached', 'walletScoringError']
|
||||
|
||||
|
|
@ -243,7 +246,7 @@ function deleteEditedData (id, data) {
|
|||
'id_card_data',
|
||||
'id_card_photo',
|
||||
'us_ssn',
|
||||
'subcriber_info',
|
||||
'subscriber_info',
|
||||
'name'
|
||||
]
|
||||
const filteredData = _.pick(defaults, _.mapKeys(_.snakeCase, data))
|
||||
|
|
@ -322,6 +325,7 @@ function getById (id) {
|
|||
return db.oneOrNone(sql, [id])
|
||||
.then(assignCustomerData)
|
||||
.then(getCustomInfoRequestsData)
|
||||
.then(getExternalComplianceMachine)
|
||||
.then(camelize)
|
||||
}
|
||||
|
||||
|
|
@ -342,7 +346,11 @@ function camelize (customer) {
|
|||
function camelizeDeep (customer) {
|
||||
return _.flow(
|
||||
camelize,
|
||||
it => ({ ...it, notes: (it.notes ?? []).map(camelize) })
|
||||
it => ({
|
||||
...it,
|
||||
notes: (it.notes ?? []).map(camelize),
|
||||
externalCompliance: (it.externalCompliance ?? []).map(camelize)
|
||||
})
|
||||
)(customer)
|
||||
}
|
||||
|
||||
|
|
@ -587,6 +595,7 @@ function getCustomerById (id) {
|
|||
return db.oneOrNone(sql, [passableErrorCodes, id])
|
||||
.then(assignCustomerData)
|
||||
.then(getCustomInfoRequestsData)
|
||||
.then(getExternalCompliance)
|
||||
.then(camelizeDeep)
|
||||
.then(formatSubscriberInfo)
|
||||
}
|
||||
|
|
@ -927,6 +936,95 @@ function updateLastAuthAttempt (customerId) {
|
|||
return db.none(sql, [customerId])
|
||||
}
|
||||
|
||||
function getExternalComplianceMachine (customer) {
|
||||
return settingsLoader.loadLatest()
|
||||
.then(settings => externalCompliance.getStatusMap(settings, customer.id))
|
||||
.then(statusMap => {
|
||||
return updateExternalComplianceByMap(customer.id, statusMap)
|
||||
.then(() => customer.externalCompliance = statusMap)
|
||||
.then(() => customer)
|
||||
})
|
||||
}
|
||||
|
||||
function updateExternalCompliance(customerId, service, status) {
|
||||
const sql = `
|
||||
UPDATE customer_external_compliance SET last_known_status = $1, last_updated = now()
|
||||
WHERE customer_id=$2 AND service=$3
|
||||
`
|
||||
return db.none(sql, [status, customerId, service])
|
||||
}
|
||||
|
||||
function updateExternalComplianceByMap(customerId, serviceMap) {
|
||||
const sql = `
|
||||
UPDATE customer_external_compliance SET last_known_status = $1, last_updated = now()
|
||||
WHERE customer_id=$2 AND service=$3
|
||||
`
|
||||
const pairs = _.toPairs(serviceMap)
|
||||
const promises = _.map(([service, status]) => db.none(sql, [status.answer, customerId, service]))(pairs)
|
||||
return Promise.all(promises)
|
||||
}
|
||||
|
||||
function getExternalCompliance(customer) {
|
||||
const sql = `SELECT external_id, service, last_known_status, last_updated
|
||||
FROM customer_external_compliance where customer_id=$1`
|
||||
return db.manyOrNone(sql, [customer.id])
|
||||
.then(compliance => {
|
||||
customer.externalCompliance = compliance
|
||||
})
|
||||
.then(() => customer)
|
||||
}
|
||||
|
||||
function getOpenExternalCompliance() {
|
||||
const sql = `SELECT customer_id, service, last_known_status FROM customer_external_compliance where last_known_status in ('PENDING', 'RETRY') or last_known_status is null`
|
||||
return db.manyOrNone(sql)
|
||||
}
|
||||
|
||||
function notifyRetryExternalCompliance(settings, customerId, service) {
|
||||
const sql = 'SELECT phone FROM customers WHERE id=$1'
|
||||
const promises = [db.one(sql, [customerId]), externalCompliance.createLink(settings, service, customerId)]
|
||||
|
||||
return Promise.all(promises)
|
||||
.then(([toNumber, link]) => {
|
||||
const body = `Your external compliance verification has failed. Please try again. Link for retry: ${link}`
|
||||
|
||||
return sms.sendMessage(settings, { toNumber, body })
|
||||
})
|
||||
}
|
||||
|
||||
function notifyApprovedExternalCompliance(settings, customerId) {
|
||||
const sql = 'SELECT phone FROM customers WHERE id=$1'
|
||||
return db.one(sql, [customerId])
|
||||
.then((toNumber) => {
|
||||
const body = 'Your external compliance verification has been approved.'
|
||||
|
||||
return sms.sendMessage(settings, { toNumber, body })
|
||||
})
|
||||
}
|
||||
|
||||
function checkExternalCompliance(settings) {
|
||||
return getOpenExternalCompliance()
|
||||
.then(externals => {
|
||||
console.log(externals)
|
||||
const promises = _.map(external => {
|
||||
return externalCompliance.getStatus(settings, external.service, external.customer_id)
|
||||
.then(status => {
|
||||
console.log('status', status, external.customer_id, external.service)
|
||||
if (status.status.answer === RETRY) notifyRetryExternalCompliance(settings, external.customer_id, status.service)
|
||||
if (status.status.answer === APPROVED) notifyApprovedExternalCompliance(settings, external.customer_id)
|
||||
|
||||
return updateExternalCompliance(external.customer_id, external.service, status.status.answer)
|
||||
})
|
||||
}, externals)
|
||||
return Promise.all(promises)
|
||||
})
|
||||
}
|
||||
|
||||
function addExternalCompliance(customerId, service, id) {
|
||||
const sql = `INSERT INTO customer_external_compliance (customer_id, external_id, service) VALUES ($1, $2, $3)`
|
||||
return db.none(sql, [customerId, id, service])
|
||||
}
|
||||
|
||||
|
||||
module.exports = {
|
||||
add,
|
||||
addWithEmail,
|
||||
|
|
@ -950,5 +1048,7 @@ module.exports = {
|
|||
updateTxCustomerPhoto,
|
||||
enableTestCustomer,
|
||||
disableTestCustomer,
|
||||
updateLastAuthAttempt
|
||||
updateLastAuthAttempt,
|
||||
addExternalCompliance,
|
||||
checkExternalCompliance
|
||||
}
|
||||
|
|
|
|||
|
|
@ -109,6 +109,7 @@ type Trigger {
|
|||
thresholdDays: Int
|
||||
customInfoRequestId: String
|
||||
customInfoRequest: CustomInfoRequest
|
||||
externalService: String
|
||||
}
|
||||
|
||||
type TermsDetails {
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ const ID_VERIFIER = 'idVerifier'
|
|||
const EMAIL = 'email'
|
||||
const ZERO_CONF = 'zeroConf'
|
||||
const WALLET_SCORING = 'wallet_scoring'
|
||||
const COMPLIANCE = 'compliance'
|
||||
|
||||
const ALL_ACCOUNTS = [
|
||||
{ code: 'bitfinex', display: 'Bitfinex', class: TICKER, cryptos: bitfinex.CRYPTO },
|
||||
|
|
@ -61,7 +62,9 @@ const ALL_ACCOUNTS = [
|
|||
{ code: 'blockcypher', display: 'Blockcypher', class: ZERO_CONF, cryptos: [BTC] },
|
||||
{ code: 'mock-zero-conf', display: 'Mock 0-conf', class: ZERO_CONF, cryptos: ALL_CRYPTOS, dev: true },
|
||||
{ code: 'scorechain', display: 'Scorechain', class: WALLET_SCORING, cryptos: [BTC, ETH, LTC, BCH, DASH, USDT, USDT_TRON, TRX] },
|
||||
{ code: 'mock-scoring', display: 'Mock scoring', class: WALLET_SCORING, cryptos: ALL_CRYPTOS, dev: true }
|
||||
{ code: 'mock-scoring', display: 'Mock scoring', class: WALLET_SCORING, cryptos: ALL_CRYPTOS, dev: true },
|
||||
{ code: 'sumsub', display: 'Sumsub', class: COMPLIANCE },
|
||||
{ code: 'mock-compliance', display: 'Mock Compliance', class: COMPLIANCE, dev: true },
|
||||
]
|
||||
|
||||
const devMode = require('minimist')(process.argv.slice(2)).dev
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ const typeDef = gql`
|
|||
customInfoRequests: [CustomRequestData]
|
||||
notes: [CustomerNote]
|
||||
isTestCustomer: Boolean
|
||||
externalCompliance: [JSONObject]
|
||||
}
|
||||
|
||||
input CustomerInput {
|
||||
|
|
|
|||
|
|
@ -29,7 +29,9 @@ const SECRET_FIELDS = [
|
|||
'inforu.apiKey',
|
||||
'galoy.walletId',
|
||||
'galoy.apiSecret',
|
||||
'bitfinex.secret'
|
||||
'bitfinex.secret',
|
||||
'sumsub.apiToken',
|
||||
'sumsub.privateKey'
|
||||
]
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -11,7 +11,8 @@ const pluginCodes = {
|
|||
LAYER2: 'layer2',
|
||||
SMS: 'sms',
|
||||
EMAIL: 'email',
|
||||
ZERO_CONF: 'zero-conf'
|
||||
ZERO_CONF: 'zero-conf',
|
||||
COMPLIANCE: 'compliance'
|
||||
}
|
||||
|
||||
module.exports = _.assign({load}, pluginCodes)
|
||||
|
|
|
|||
6
lib/plugins/compliance/consts.js
Normal file
6
lib/plugins/compliance/consts.js
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
module.exports = {
|
||||
PENDING: 'PENDING',
|
||||
RETRY: 'RETRY',
|
||||
APPROVED: 'APPROVED',
|
||||
REJECTED: 'REJECTED'
|
||||
}
|
||||
31
lib/plugins/compliance/mock-compliance/mock-compliance.js
Normal file
31
lib/plugins/compliance/mock-compliance/mock-compliance.js
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
const uuid = require('uuid')
|
||||
|
||||
const {APPROVED} = require('../consts')
|
||||
|
||||
const CODE = 'mock-compliance'
|
||||
|
||||
const createLink = (settings, userId, level) => {
|
||||
return `this is a mock external link, ${userId}, ${level}`
|
||||
}
|
||||
|
||||
const getApplicantStatus = (account, userId) => {
|
||||
return Promise.resolve({
|
||||
service: CODE,
|
||||
status: {
|
||||
level: account.applicantLevel, answer: APPROVED
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const createApplicant = () => {
|
||||
return Promise.resolve({
|
||||
id: uuid.v4()
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
CODE,
|
||||
createApplicant,
|
||||
getApplicantStatus,
|
||||
createLink
|
||||
}
|
||||
34
lib/plugins/compliance/sumsub/request.js
Normal file
34
lib/plugins/compliance/sumsub/request.js
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
const axios = require('axios')
|
||||
const crypto = require('crypto')
|
||||
const _ = require('lodash/fp')
|
||||
const FormData = require('form-data')
|
||||
|
||||
const axiosConfig = {
|
||||
baseURL: 'https://api.sumsub.com'
|
||||
}
|
||||
|
||||
const getSigBuilder = (apiToken, secretKey) => config => {
|
||||
const timestamp = Math.floor(Date.now() / 1000)
|
||||
const signature = crypto.createHmac('sha256', secretKey)
|
||||
|
||||
signature.update(`${timestamp}${_.toUpper(config.method)}${config.url}`)
|
||||
if (config.data instanceof FormData) {
|
||||
signature.update(config.data.getBuffer())
|
||||
} else if (config.data) {
|
||||
signature.update(JSON.stringify(config.data))
|
||||
}
|
||||
|
||||
config.headers['X-App-Token'] = apiToken
|
||||
config.headers['X-App-Access-Sig'] = signature.digest('hex')
|
||||
config.headers['X-App-Access-Ts'] = timestamp
|
||||
|
||||
return config
|
||||
}
|
||||
|
||||
const request = ((account, config) => {
|
||||
const instance = axios.create(axiosConfig)
|
||||
instance.interceptors.request.use(getSigBuilder(account.apiToken, account.secretKey), Promise.reject)
|
||||
return instance(config)
|
||||
})
|
||||
|
||||
module.exports = request
|
||||
98
lib/plugins/compliance/sumsub/sumsub.api.js
Normal file
98
lib/plugins/compliance/sumsub/sumsub.api.js
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
const request = require('./request')
|
||||
|
||||
const createApplicant = (account, userId, level) => {
|
||||
if (!userId || !level) {
|
||||
return Promise.reject(`Missing required fields: userId: ${userId}, level: ${level}`)
|
||||
}
|
||||
|
||||
const config = {
|
||||
method: 'POST',
|
||||
url: `/resources/applicants?levelName=${level}`,
|
||||
data: {
|
||||
externalUserId: userId,
|
||||
sourceKey: 'lamassu'
|
||||
},
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json'
|
||||
}
|
||||
}
|
||||
|
||||
return request(account, config)
|
||||
}
|
||||
|
||||
const createLink = (account, userId, level) => {
|
||||
if (!userId || !level) {
|
||||
return Promise.reject(`Missing required fields: userId: ${userId}, level: ${level}`)
|
||||
}
|
||||
|
||||
const config = {
|
||||
method: 'POST',
|
||||
url: `/resources/sdkIntegrations/levels/${level}/websdkLink?ttlInSecs=${600}&externalUserId=${userId}`,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json'
|
||||
}
|
||||
}
|
||||
|
||||
return request(account, config)
|
||||
}
|
||||
|
||||
const getApplicantByExternalId = (account, id) => {
|
||||
if (!id) {
|
||||
return Promise.reject('Missing required fields: id')
|
||||
}
|
||||
|
||||
const config = {
|
||||
method: 'GET',
|
||||
url: `/resources/applicants/-;externalUserId=${id}/one`,
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
}
|
||||
|
||||
return request(account, config)
|
||||
}
|
||||
|
||||
const getApplicantStatus = (account, id) => {
|
||||
if (!id) {
|
||||
return Promise.reject(`Missing required fields: id`)
|
||||
}
|
||||
|
||||
const config = {
|
||||
method: 'GET',
|
||||
url: `/resources/applicants/${id}/status`,
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
}
|
||||
|
||||
return request(account, config)
|
||||
}
|
||||
|
||||
const getApplicantById = (account, id) => {
|
||||
if (!id) {
|
||||
return Promise.reject(`Missing required fields: id`)
|
||||
}
|
||||
|
||||
const config = {
|
||||
method: 'GET',
|
||||
url: `/resources/applicants/${id}/one`,
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
}
|
||||
|
||||
return request(account, config)
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
createLink,
|
||||
createApplicant,
|
||||
getApplicantByExternalId,
|
||||
getApplicantById,
|
||||
getApplicantStatus
|
||||
}
|
||||
52
lib/plugins/compliance/sumsub/sumsub.js
Normal file
52
lib/plugins/compliance/sumsub/sumsub.js
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
const _ = require('lodash/fp')
|
||||
|
||||
const sumsubApi = require('./sumsub.api')
|
||||
const { PENDING, RETRY, APPROVED, REJECTED } = require('../consts')
|
||||
|
||||
const CODE = 'sumsub'
|
||||
|
||||
const getApplicantByExternalId = (account, userId) => {
|
||||
return sumsubApi.getApplicantByExternalId(account, userId)
|
||||
.then(r => r.data)
|
||||
}
|
||||
|
||||
const createApplicant = (account, userId, level) => {
|
||||
return sumsubApi.createApplicant(account, userId, level)
|
||||
.then(r => r.data)
|
||||
.catch(err => {
|
||||
if (err.response.status === 409) return getApplicantByExternalId(account, userId)
|
||||
throw err
|
||||
})
|
||||
}
|
||||
|
||||
const createLink = (account, userId, level) => {
|
||||
return sumsubApi.createLink(account, userId, level)
|
||||
.then(r => r.data.url)
|
||||
}
|
||||
|
||||
const getApplicantStatus = (account, userId) => {
|
||||
return sumsubApi.getApplicantByExternalId(account, userId)
|
||||
.then(r => {
|
||||
const levelName = _.get('data.review.levelName', r)
|
||||
const reviewStatus = _.get('data.review.reviewStatus', r)
|
||||
const reviewAnswer = _.get('data.review.reviewResult.reviewAnswer', r)
|
||||
const reviewRejectType = _.get('data.review.reviewResult.reviewRejectType', r)
|
||||
|
||||
// if last review was from a different level, return the current level and RETRY
|
||||
if (levelName !== account.applicantLevel) return { level: account.applicantLevel, answer: RETRY }
|
||||
|
||||
let answer = PENDING
|
||||
if (reviewAnswer === 'GREEN' && reviewStatus === 'completed') answer = APPROVED
|
||||
if (reviewAnswer === 'RED' && reviewRejectType === 'RETRY') answer = RETRY
|
||||
if (reviewAnswer === 'RED' && reviewRejectType === 'FINAL') answer = REJECTED
|
||||
|
||||
return { level: levelName, answer }
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
CODE,
|
||||
createApplicant,
|
||||
getApplicantStatus,
|
||||
createLink
|
||||
}
|
||||
|
|
@ -6,6 +6,7 @@ const T = require('./time')
|
|||
const logger = require('./logger')
|
||||
const cashOutTx = require('./cash-out/cash-out-tx')
|
||||
const cashInTx = require('./cash-in/cash-in-tx')
|
||||
const customers = require('./customers')
|
||||
const sanctionsUpdater = require('./ofac/update')
|
||||
const sanctions = require('./ofac/index')
|
||||
const coinAtmRadar = require('./coinatmradar/coinatmradar')
|
||||
|
|
@ -31,6 +32,7 @@ const RADAR_UPDATE_INTERVAL = 5 * T.minutes
|
|||
const PRUNE_MACHINES_HEARTBEAT = 1 * T.day
|
||||
const TRANSACTION_BATCH_LIFECYCLE = 20 * T.minutes
|
||||
const TICKER_RATES_INTERVAL = 59 * T.seconds
|
||||
const EXTERNAL_COMPLIANCE_INTERVAL = 1 * T.minutes
|
||||
|
||||
const CHECK_NOTIFICATION_INTERVAL = 20 * T.seconds
|
||||
const PENDING_INTERVAL = 10 * T.seconds
|
||||
|
|
@ -127,6 +129,10 @@ function updateCoinAtmRadar () {
|
|||
.then(rates => coinAtmRadar.update(rates, settings()))
|
||||
}
|
||||
|
||||
// function checkExternalCompliance (settings) {
|
||||
// return customers.checkExternalCompliance(settings)
|
||||
// }
|
||||
|
||||
function initializeEachSchema (schemas = ['public']) {
|
||||
// for each schema set "thread variables" and do polling
|
||||
return _.forEach(schema => {
|
||||
|
|
@ -190,6 +196,7 @@ function doPolling (schema) {
|
|||
pi().sweepHd()
|
||||
notifier.checkNotification(pi())
|
||||
updateCoinAtmRadar()
|
||||
// checkExternalCompliance(settings())
|
||||
|
||||
addToQueue(pi().getRawRates, TICKER_RATES_INTERVAL, schema, QUEUE.FAST)
|
||||
addToQueue(pi().executeTrades, TRADE_INTERVAL, schema, QUEUE.FAST)
|
||||
|
|
@ -206,6 +213,7 @@ function doPolling (schema) {
|
|||
addToQueue(updateAndLoadSanctions, SANCTIONS_UPDATE_INTERVAL, schema, QUEUE.SLOW)
|
||||
addToQueue(updateCoinAtmRadar, RADAR_UPDATE_INTERVAL, schema, QUEUE.SLOW)
|
||||
addToQueue(pi().pruneMachinesHeartbeat, PRUNE_MACHINES_HEARTBEAT, schema, QUEUE.SLOW, settings)
|
||||
// addToQueue(checkExternalCompliance, EXTERNAL_COMPLIANCE_INTERVAL, schema, QUEUE.SLOW, settings)
|
||||
}
|
||||
|
||||
function setup (schemasToAdd = [], schemasToRemove = []) {
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ const plugins = require('../plugins')
|
|||
const Tx = require('../tx')
|
||||
const loyalty = require('../loyalty')
|
||||
const logger = require('../logger')
|
||||
const externalCompliance = require('../compliance-external')
|
||||
|
||||
function updateCustomerCustomInfoRequest (customerId, patch) {
|
||||
const promise = _.isNil(patch.data) ?
|
||||
|
|
@ -234,6 +235,28 @@ function sendSmsReceipt (req, res, next) {
|
|||
})
|
||||
}
|
||||
|
||||
function getExternalComplianceLink (req, res, next) {
|
||||
const customerId = req.query.customer
|
||||
const triggerId = req.query.trigger
|
||||
const isRetry = req.query.isRetry
|
||||
if (_.isNil(customerId) || _.isNil(triggerId)) return next(httpError('Not Found', 404))
|
||||
|
||||
const settings = req.settings
|
||||
const triggers = configManager.getTriggers(settings.config)
|
||||
const trigger = _.find(it => it.id === triggerId)(triggers)
|
||||
const externalService = trigger.externalService
|
||||
|
||||
if (isRetry) {
|
||||
return externalCompliance.createLink(settings, externalService, customerId)
|
||||
.then(url => respond(req, res, { url }))
|
||||
}
|
||||
|
||||
return externalCompliance.createApplicant(settings, externalService, customerId)
|
||||
.then(applicant => customers.addExternalCompliance(customerId, externalService, applicant.id))
|
||||
.then(() => externalCompliance.createLink(settings, externalService, customerId))
|
||||
.then(url => respond(req, res, { url }))
|
||||
}
|
||||
|
||||
function addOrUpdateCustomer (customerData, config, isEmailAuth) {
|
||||
const triggers = configManager.getTriggers(config)
|
||||
const maxDaysThreshold = complianceTriggers.maxDaysThreshold(triggers)
|
||||
|
|
@ -311,6 +334,7 @@ router.patch('/:id/suspend', triggerSuspend)
|
|||
router.patch('/:id/photos/idcarddata', updateIdCardData)
|
||||
router.patch('/:id/:txId/photos/customerphoto', updateTxCustomerPhoto)
|
||||
router.post('/:id/smsreceipt', sendSmsReceipt)
|
||||
router.get('/external', getExternalComplianceLink)
|
||||
router.post('/phone_code', getOrAddCustomerPhone)
|
||||
router.post('/email_code', getOrAddCustomerEmail)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue