-
Endpoints:
/status
: Kyc status endpoints. Called by mobile app. Response KycRecordStatus/login
: SSO endpoints. Called by mobile app. Triggered by scanning qr code or opening Applink/register
: Registration or re-new certificate request (later). Triggered by pressing Register button on mobile application/resubmit
: Update data for existing KYC record/upload
: Upload user rawData. Triggered when mobile application receives nextAction=upload returned by/login
,/register
or/resubmit
-
KycProfile: User profile object returned by Blockpass Api
-
KycToken: Access token object. Use to exchange data between Services and Blockpass API (each user will have different token)
-
KycRecord: Object stored kyc data, managed by Services. It usually contains 3 parts(BlockpassKycProfile + RawData + Service Extra Info)
Example:
{
//
//[Blockpass-KycProfile]
//
blockpassId: 'service_udid',// udid of user ( unique for each services )
kycToken: {...}, // kycToken for this user
rootHash: 'sha3-hash' // user root of merke tree
isSynching: "syncing" | "complete" // status of smartcontract syncing
//
//[Blockpass-RawData]
//
phone: xxx,
email: yyy,
[cer]onfido: '....',
//
//[Service Extra info]
//
etherAddress: '....'
}
- KycRecordStatus: Object stored kycRecord status following Mobile App format
// Format
{
status: 'notFound|waiting|inreview|approved',
message: 'summary current status',
createdDate: 'DateTime KycRecord created',
allowResubmit: true|false
identities: [
{
slug: 'slug name',
status: 'received|rejected| approved|missing',
comment: 'reviewer comment'
},
//....
],
certificates: [
{
slug: 'slug name',
status: 'received|rejected| approved|missing',
comment: 'reviewer comment'
},
//....
]
}
-
Step 1: Declare logic handler
findKycById
: Find and return KycRecordcreateKyc
: Create new kycRecordupdateKyc
: Update kycRecordqueryKycStatus
: Query KycRecord statusgenerateSsoPayload
: Generate SSo payload (this custom data will be sent to web-client)
const sdk = new ServerSdk({
// Developer dashboard fields
baseUrl: BLOCKPASS_BASEURL,
clientId: SERVICE_CLIENTID,
secretId: SERVICE_SECRETID,
autoFetchMetadata: true
// Custom implement
findKycById: findKycById ,
createKyc: createKyc,
updateKyc: updateKyc,
queryKycStatus: queryKycStatus,
generateSsoPayload: generateSsoPayload
})
sdk.once('onLoaded', _ => {
// Sdk loaded
})
sdk.once('onError' _ => {
// Sdk init error
})
//-------------------------------------------------------------------------
// lookup blockpassId -> kycRecord
//-------------------------------------------------------------------------
async function findKycById(blockpassId) {
return await KYCModel.findOne({ blockPassID })
}
//-------------------------------------------------------------------------
// Update create new kycRecord
//-------------------------------------------------------------------------
async function createKyc({ kycProfile, refId }) {
const { id, smartContractId, rootHash, isSynching } = kycProfile;
const newIns = new KYCModel({
blockPassID: id,
refId,
rootHash,
smartContractId,
isSynching
})
return await newIns.save()
}
//-------------------------------------------------------------------------
// Update rawData -> kycRecord
//-------------------------------------------------------------------------
async function updateKyc({
kycRecord,
kycProfile,
kycToken,
userRawData
}) {
const { id, smartContractId, rootHash, isSynching } = kycProfile;
// Store file and raw data fields -> kycRecord
const jobs = Object.keys(userRawData).map(async (key) => {
const metaData = userRawData[key];
if (metaData.type === 'string')
return kycRecord[key] = metaData.value
if (metaData.type === 'file') {
const { buffer, originalname } = metaData;
const ext = originalname.split('.')[1];
const fileName = `${id}_${key}.${ext}`;
// store file somewhere
const fileHandler = await FileStorage.writeFile({
fileName,
mimetype: `image/${ext}`,
fileBuffer: buffer
})
return kycRecord[key] = fileHandler._id
}
})
await Promise.all(jobs);
// [Advanced] - Link kyc record with existing user data in your database
// Example: This email|phone contained in our database
// calculate token expired date from 'expires_in'
const expiredDate = new Date(Date.now() + kycToken.expires_in * 1000)
kycRecord.bpToken = {
...kycToken,
expires_at: expiredDate
}
kycRecord.rootHash = rootHash
kycRecord.smartContractId = smartContractId
kycRecord.isSynching = isSynching
return await kycRecord.save()
}
//-------------------------------------------------------------------------
// Return KycRecord Status for Mobile application
//-------------------------------------------------------------------------
async function queryKycStatus({ kycRecord }) {
const status = kycRecord.status
return {
status,
message: '',
createdDate: new Date(),
identities: [],
certificates: []
}
}
//-------------------------------------------------------------------------
// Kyc successfull. Generate services token for client
//-------------------------------------------------------------------------
async function generateSsoPayload({ kycProfile, kycRecord, kycToken, payload }) {
return {
_id: kycRecord._id,
serviceToken: '...' // AccessToken for services
}
}
-
Step 2: Create api:
- /login -> sdk.loginFow(...)
- /upload -> sdk.updateDataFlow(...)
- /register -> sdk.registerFlow(...)
- /status -> sdk.queryStatusFlow(...)
- /resubmit -> sdk.resubmitDataFlow(...)
Ps: See express
examples
$ npm test # run tests with Jest
$ npm run coverage # run tests with coverage and open it on browser
$ npm run lint # lint code
$ npm run docs # generate docs
$ npm run build # generate docs and transpile code
ApacheV2