refactor: yagni and flow of external compliance
This commit is contained in:
parent
b06927fd1c
commit
04eea85a0d
29 changed files with 389 additions and 1417 deletions
|
|
@ -1,462 +1,55 @@
|
|||
const _ = require('lodash/fp')
|
||||
|
||||
const request = require('./request')
|
||||
const sumsubApi = require('./sumsub.api')
|
||||
const { WAIT, RETRY, APPROVED, REJECTED } = require('../consts')
|
||||
|
||||
const CODE = 'sumsub'
|
||||
|
||||
const hasRequiredFields = fields => obj => _.every(_.partial(_.has, [_, obj]), fields)
|
||||
const getMissingRequiredFields = (fields, obj) =>
|
||||
_.reduce(
|
||||
(acc, value) => {
|
||||
if (!_.has(value, obj)) {
|
||||
acc.push(value)
|
||||
}
|
||||
return acc
|
||||
},
|
||||
[],
|
||||
fields
|
||||
)
|
||||
|
||||
const createApplicantExternalLink = opts => {
|
||||
const REQUIRED_FIELDS = ['userId', 'levelName']
|
||||
|
||||
if (_.isEmpty(opts) || !hasRequiredFields(REQUIRED_FIELDS, opts)) {
|
||||
return Promise.reject(`Missing required fields: ${getMissingRequiredFields(REQUIRED_FIELDS, opts)}`)
|
||||
}
|
||||
|
||||
return request({
|
||||
method: 'POST',
|
||||
url: `/resources/sdkIntegrations/levels/${opts.levelName}/websdkLink?ttlInSecs=${600}&externalUserId=${opts.userId}`,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json'
|
||||
}
|
||||
})
|
||||
const getApplicantByExternalId = (account, userId) => {
|
||||
return sumsubApi.getApplicantByExternalId(account, userId)
|
||||
.then(r => r.data)
|
||||
}
|
||||
|
||||
const createApplicant = opts => {
|
||||
const REQUIRED_FIELDS = ['levelName', 'externalUserId']
|
||||
|
||||
if (_.isEmpty(opts) || !hasRequiredFields(REQUIRED_FIELDS, opts)) {
|
||||
return Promise.reject(`Missing required fields: ${getMissingRequiredFields(REQUIRED_FIELDS, opts)}`)
|
||||
}
|
||||
|
||||
return request({
|
||||
method: 'POST',
|
||||
url: `/resources/applicants?levelName=${opts.levelName}`,
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
data: {
|
||||
externalUserId: opts.externalUserId
|
||||
}
|
||||
})
|
||||
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 changeRequiredLevel = opts => {
|
||||
const REQUIRED_FIELDS = ['applicantId', 'levelName']
|
||||
|
||||
if (_.isEmpty(opts) || !hasRequiredFields(REQUIRED_FIELDS, opts)) {
|
||||
return Promise.reject(`Missing required fields: ${getMissingRequiredFields(REQUIRED_FIELDS, opts)}`)
|
||||
}
|
||||
|
||||
return request({
|
||||
method: 'POST',
|
||||
url: `/resources/applicants/${opts.applicantId}/moveToLevel?name=${opts.levelName}`,
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
const createLink = (account, userId, level) => {
|
||||
return sumsubApi.createLink(account, userId, level)
|
||||
.then(r => r.data.url)
|
||||
}
|
||||
|
||||
const getApplicant = (opts, knowsApplicantId = true) => {
|
||||
const REQUIRED_FIELDS = knowsApplicantId
|
||||
? ['applicantId']
|
||||
: ['externalUserId']
|
||||
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 (_.isEmpty(opts) || !hasRequiredFields(REQUIRED_FIELDS, opts)) {
|
||||
return Promise.reject(`Missing required fields: ${getMissingRequiredFields(REQUIRED_FIELDS, opts)}`)
|
||||
}
|
||||
console.log('levelName', levelName)
|
||||
console.log('reviewStatus', reviewStatus)
|
||||
console.log('reviewAnswer', reviewAnswer)
|
||||
console.log('reviewRejectType', reviewRejectType)
|
||||
|
||||
return request({
|
||||
method: 'GET',
|
||||
url: knowsApplicantId ? `/resources/applicants/${opts.applicantId}/one` : `/resources/applicants/-;externalUserId=${opts.externalUserId}/one`,
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
}
|
||||
let answer = WAIT
|
||||
if (reviewAnswer === 'GREEN') answer = APPROVED
|
||||
if (reviewAnswer === 'RED' && reviewRejectType === 'RETRY') answer = RETRY
|
||||
if (reviewAnswer === 'RED' && reviewRejectType === 'FINAL') answer = REJECTED
|
||||
|
||||
const getApplicantStatus = opts => {
|
||||
const REQUIRED_FIELDS = ['applicantId']
|
||||
|
||||
if (_.isEmpty(opts) || !hasRequiredFields(REQUIRED_FIELDS, opts)) {
|
||||
return Promise.reject(`Missing required fields: ${getMissingRequiredFields(REQUIRED_FIELDS, opts)}`)
|
||||
}
|
||||
|
||||
return request({
|
||||
method: 'GET',
|
||||
url: `/resources/applicants/${opts.applicantId}/status`,
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const getApplicantIdDocsStatus = opts => {
|
||||
const REQUIRED_FIELDS = ['applicantId']
|
||||
|
||||
if (_.isEmpty(opts) || !hasRequiredFields(REQUIRED_FIELDS, opts)) {
|
||||
return Promise.reject(`Missing required fields: ${getMissingRequiredFields(REQUIRED_FIELDS, opts)}`)
|
||||
}
|
||||
|
||||
return request({
|
||||
method: 'GET',
|
||||
url: `/resources/applicants/${opts.applicantId}/requiredIdDocsStatus`,
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const addIdDocument = opts => {
|
||||
const REQUIRED_FIELDS = ['applicantId', 'metadata', 'metadata.idDocType', 'metadata.country']
|
||||
|
||||
if (_.isEmpty(opts) || !hasRequiredFields(REQUIRED_FIELDS, opts)) {
|
||||
return Promise.reject(`Missing required fields: ${getMissingRequiredFields(REQUIRED_FIELDS, opts)}`)
|
||||
}
|
||||
|
||||
const form = new FormData()
|
||||
form.append('metadata', opts.metadata)
|
||||
form.append('content', opts.content)
|
||||
|
||||
return request({
|
||||
method: 'POST',
|
||||
url: `/resources/applicants/${opts.applicantId}/info/idDoc`,
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'multipart/form-data',
|
||||
'X-Return-Doc-Warnings': 'true'
|
||||
},
|
||||
data: form
|
||||
})
|
||||
}
|
||||
|
||||
const changeApplicantFixedInfo = opts => {
|
||||
const REQUIRED_FIELDS = ['applicantId', 'newData']
|
||||
|
||||
if (_.isEmpty(opts) || !hasRequiredFields(REQUIRED_FIELDS, opts)) {
|
||||
return Promise.reject(`Missing required fields: ${getMissingRequiredFields(REQUIRED_FIELDS, opts)}`)
|
||||
}
|
||||
|
||||
return request({
|
||||
method: 'PATCH',
|
||||
url: `/resources/applicants/${opts.applicantId}/fixedInfo`,
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
data: opts.newData
|
||||
})
|
||||
}
|
||||
|
||||
const getApplicantRejectReasons = opts => {
|
||||
const REQUIRED_FIELDS = ['applicantId']
|
||||
|
||||
if (_.isEmpty(opts) || !hasRequiredFields(REQUIRED_FIELDS, opts)) {
|
||||
return Promise.reject(`Missing required fields: ${getMissingRequiredFields(REQUIRED_FIELDS, opts)}`)
|
||||
}
|
||||
|
||||
return request({
|
||||
method: 'GET',
|
||||
url: `/resources/moderationStates/-;applicantId=${opts.applicantId}`,
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const requestApplicantCheck = opts => {
|
||||
const REQUIRED_FIELDS = ['applicantId']
|
||||
|
||||
if (_.isEmpty(opts) || !hasRequiredFields(REQUIRED_FIELDS, opts)) {
|
||||
return Promise.reject(`Missing required fields: ${getMissingRequiredFields(REQUIRED_FIELDS, opts)}`)
|
||||
}
|
||||
|
||||
return request({
|
||||
method: 'POST',
|
||||
url: `/resources/applicants/${opts.applicantId}/status/pending${!_.isNil(opts.reason) ? `?reason=${opts.reason}` : ``}`,
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const requestApplicantCheckDiffVerificationType = opts => {
|
||||
const REQUIRED_FIELDS = ['applicantId', 'reasonCode']
|
||||
|
||||
if (_.isEmpty(opts) || !hasRequiredFields(REQUIRED_FIELDS, opts)) {
|
||||
return Promise.reject(`Missing required fields: ${getMissingRequiredFields(REQUIRED_FIELDS, opts)}`)
|
||||
}
|
||||
|
||||
return request({
|
||||
method: 'POST',
|
||||
url: `/resources/applicants/${opts.applicantId}/status/pending${!_.isNil(opts.reasonCode) ? `?reasonCode=${opts.reasonCode}` : ``}`,
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const getDocumentImages = opts => {
|
||||
const REQUIRED_FIELDS = ['inspectionId', 'imageId']
|
||||
|
||||
if (_.isEmpty(opts) || !hasRequiredFields(REQUIRED_FIELDS, opts)) {
|
||||
return Promise.reject(`Missing required fields: ${getMissingRequiredFields(REQUIRED_FIELDS, opts)}`)
|
||||
}
|
||||
|
||||
return request({
|
||||
method: 'GET',
|
||||
url: `/resources/inspections/${opts.inspectionId}/resources/${opts.imageId}`,
|
||||
headers: {
|
||||
'Accept': 'image/jpeg, image/png, application/pdf, video/mp4, video/webm, video/quicktime',
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const blockApplicant = opts => {
|
||||
const REQUIRED_FIELDS = ['applicantId', 'note']
|
||||
|
||||
if (_.isEmpty(opts) || !hasRequiredFields(REQUIRED_FIELDS, opts)) {
|
||||
return Promise.reject(`Missing required fields: ${getMissingRequiredFields(REQUIRED_FIELDS, opts)}`)
|
||||
}
|
||||
|
||||
return request({
|
||||
method: 'POST',
|
||||
url: `/resources/applicants/${opts.applicantId}/blacklist?note=${opts.note}`,
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const generateShareToken = opts => {
|
||||
const REQUIRED_FIELDS = ['applicantId', 'clientId']
|
||||
|
||||
if (_.isEmpty(opts) || !hasRequiredFields(REQUIRED_FIELDS, opts)) {
|
||||
return Promise.reject(`Missing required fields: ${getMissingRequiredFields(REQUIRED_FIELDS, opts)}`)
|
||||
}
|
||||
|
||||
return request({
|
||||
method: 'POST',
|
||||
url: `/resources/accessTokens/-/shareToken?applicantId=${opts.applicantId}&forClientId=${opts.clientId}${!_.isNil(opts.ttlInSecs) ? `&ttlInSecs=${opts.ttlInSecs}` : ``}`,
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const importRawApplicant = opts => {
|
||||
const REQUIRED_FIELDS = ['applicantObj']
|
||||
|
||||
if (_.isEmpty(opts) || !hasRequiredFields(REQUIRED_FIELDS, opts)) {
|
||||
return Promise.reject(`Missing required fields: ${getMissingRequiredFields(REQUIRED_FIELDS, opts)}`)
|
||||
}
|
||||
|
||||
return request({
|
||||
method: 'POST',
|
||||
url: `/resources/applicants/-/ingestCompleted`,
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
data: opts.applicantObj
|
||||
})
|
||||
}
|
||||
|
||||
const importApplicantFromPartnerService = opts => {
|
||||
const REQUIRED_FIELDS = ['shareToken']
|
||||
|
||||
if (_.isEmpty(opts) || !hasRequiredFields(REQUIRED_FIELDS, opts)) {
|
||||
return Promise.reject(`Missing required fields: ${getMissingRequiredFields(REQUIRED_FIELDS, opts)}`)
|
||||
}
|
||||
|
||||
return request({
|
||||
method: 'POST',
|
||||
url: `/resources/applicants/-/import?shareToken=${opts.shareToken}`,
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const resetVerificationStep = opts => {
|
||||
const REQUIRED_FIELDS = ['applicantId', 'idDocSetType']
|
||||
|
||||
if (_.isEmpty(opts) || !hasRequiredFields(REQUIRED_FIELDS, opts)) {
|
||||
return Promise.reject(`Missing required fields: ${getMissingRequiredFields(REQUIRED_FIELDS, opts)}`)
|
||||
}
|
||||
|
||||
return request({
|
||||
method: 'POST',
|
||||
url: `/resources/applicants/${opts.applicantId}/resetStep/${opts.idDocSetType}`,
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const resetApplicant = opts => {
|
||||
const REQUIRED_FIELDS = ['applicantId']
|
||||
|
||||
if (_.isEmpty(opts) || !hasRequiredFields(REQUIRED_FIELDS, opts)) {
|
||||
return Promise.reject(`Missing required fields: ${getMissingRequiredFields(REQUIRED_FIELDS, opts)}`)
|
||||
}
|
||||
|
||||
return request({
|
||||
method: 'POST',
|
||||
url: `/resources/applicants/${opts.applicantId}/reset`,
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const patchApplicantTopLevelInfo = opts => {
|
||||
const REQUIRED_FIELDS = ['applicantId']
|
||||
|
||||
if (_.isEmpty(opts) || !hasRequiredFields(REQUIRED_FIELDS, opts)) {
|
||||
return Promise.reject(`Missing required fields: ${getMissingRequiredFields(REQUIRED_FIELDS, opts)}`)
|
||||
}
|
||||
|
||||
return request({
|
||||
method: 'POST',
|
||||
url: `/resources/applicants/`,
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
data: {
|
||||
id: opts.applicantId,
|
||||
externalUserId: opts.externalUserId,
|
||||
email: opts.email,
|
||||
phone: opts.phone,
|
||||
sourceKey: opts.sourceKey,
|
||||
type: opts.type,
|
||||
lang: opts.lang,
|
||||
questionnaires: opts.questionnaires,
|
||||
metadata: opts.metadata,
|
||||
deleted: opts.deleted
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const setApplicantRiskLevel = opts => {
|
||||
const REQUIRED_FIELDS = ['applicantId', 'comment', 'riskLevel']
|
||||
|
||||
if (_.isEmpty(opts) || !hasRequiredFields(REQUIRED_FIELDS, opts)) {
|
||||
return Promise.reject(`Missing required fields: ${getMissingRequiredFields(REQUIRED_FIELDS, opts)}`)
|
||||
}
|
||||
|
||||
return request({
|
||||
method: 'POST',
|
||||
url: `/resources/applicants/${opts.applicantId}/riskLevel/entries`,
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
data: {
|
||||
comment: opts.comment,
|
||||
riskLevel: opts.riskLevel
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const addApplicantTags = opts => {
|
||||
const REQUIRED_FIELDS = ['applicantId', 'tags']
|
||||
|
||||
if (_.isEmpty(opts) || !hasRequiredFields(REQUIRED_FIELDS, opts)) {
|
||||
return Promise.reject(`Missing required fields: ${getMissingRequiredFields(REQUIRED_FIELDS, opts)}`)
|
||||
}
|
||||
|
||||
return request({
|
||||
method: 'POST',
|
||||
url: `/resources/applicants/${opts.applicantId}/tags`,
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
data: opts.tags
|
||||
})
|
||||
}
|
||||
|
||||
const markImageAsInactive = opts => {
|
||||
const REQUIRED_FIELDS = ['inspectionId', 'imageId']
|
||||
|
||||
if (_.isEmpty(opts) || !hasRequiredFields(REQUIRED_FIELDS, opts)) {
|
||||
return Promise.reject(`Missing required fields: ${getMissingRequiredFields(REQUIRED_FIELDS, opts)}`)
|
||||
}
|
||||
|
||||
return request({
|
||||
method: 'DELETE',
|
||||
url: `/resources/inspections/${opts.inspectionId}/resources/${opts.imageId}?revert=false`
|
||||
})
|
||||
}
|
||||
|
||||
const markImageAsActive = opts => {
|
||||
const REQUIRED_FIELDS = ['inspectionId', 'imageId']
|
||||
|
||||
if (_.isEmpty(opts) || !hasRequiredFields(REQUIRED_FIELDS, opts)) {
|
||||
return Promise.reject(`Missing required fields: ${getMissingRequiredFields(REQUIRED_FIELDS, opts)}`)
|
||||
}
|
||||
|
||||
return request({
|
||||
method: 'DELETE',
|
||||
url: `/resources/inspections/${opts.inspectionId}/resources/${opts.imageId}?revert=true`
|
||||
})
|
||||
}
|
||||
|
||||
const getApiHealth = () => {
|
||||
return request({
|
||||
method: 'GET',
|
||||
url: `/resources/status/api`
|
||||
})
|
||||
return { level: levelName, answer }
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
CODE,
|
||||
createApplicantExternalLink,
|
||||
createApplicant,
|
||||
getApplicant,
|
||||
addIdDocument,
|
||||
changeApplicantFixedInfo,
|
||||
getApplicantStatus,
|
||||
getApplicantIdDocsStatus,
|
||||
getApplicantRejectReasons,
|
||||
requestApplicantCheck,
|
||||
requestApplicantCheckDiffVerificationType,
|
||||
getDocumentImages,
|
||||
blockApplicant,
|
||||
generateShareToken,
|
||||
importRawApplicant,
|
||||
importApplicantFromPartnerService,
|
||||
resetVerificationStep,
|
||||
resetApplicant,
|
||||
patchApplicantTopLevelInfo,
|
||||
setApplicantRiskLevel,
|
||||
addApplicantTags,
|
||||
markImageAsInactive,
|
||||
markImageAsActive,
|
||||
getApiHealth,
|
||||
changeRequiredLevel
|
||||
}
|
||||
getApplicantByExternalId,
|
||||
createLink
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue