v12.0.0 - initial commit

This commit is contained in:
padreug 2025-12-31 19:04:13 +01:00
commit e2c49ea43c
1145 changed files with 97211 additions and 0 deletions

View file

@ -0,0 +1,6 @@
module.exports = {
PENDING: 'PENDING',
RETRY: 'RETRY',
APPROVED: 'APPROVED',
REJECTED: 'REJECTED',
}

View file

@ -0,0 +1,31 @@
const uuid = require('uuid')
const { APPROVED } = require('../consts')
const CODE = 'mock-compliance'
const createLink = (settings, userId, level) => {
return Promise.resolve(
`https://mock-external-compliance.link/?user=${userId}&level=${level}`,
)
}
const getApplicantStatus = account => {
return Promise.resolve({
level: account.applicantLevel,
answer: APPROVED,
})
}
const createApplicant = () => {
return Promise.resolve({
id: uuid.v4(),
})
}
module.exports = {
CODE,
createApplicant,
getApplicantStatus,
createLink,
}

View file

@ -0,0 +1,37 @@
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

View file

@ -0,0 +1,102 @@
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,
}

View file

@ -0,0 +1,58 @@
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 (reviewStatus === 'init') answer = RETRY
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,
}