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
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
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue