Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AdamJLemmon/f91e366e04e9a708518d3528e0e8cae7 to your computer and use it in GitHub Desktop.
Save AdamJLemmon/f91e366e04e9a708518d3528e0e8cae7 to your computer and use it in GitHub Desktop.
// Dependencies
const axios = require('axios')
// Environment Variables
const API_URL = process.env.API_URL || 'https://api.dev.trybe.id'
const VCX_API_KEY = process.env.VCX_API_KEY || '42d34daf-29fc-4703-b52c-82c69f4e1a58'
const ORG_ID = process.env.ORG_ID || '60130d1fd955617015ece84b'
// API authZ
const orgId = ORG_ID
const headers = {
'vcx-api-key': VCX_API_KEY
}
// Credential data
// Patient - "required": ["resourceType", "extension", "identifier", "name", "gender", "birthDate"],
const Patient = {
resourceType: "Patient",
extension: [{
url: "http://hl7.org/fhir/StructureDefinition/patient-nationality",
code: { "text": "SG" }
}],
identifier: [{
type: { "text": "NRIC" },
value: "S9098989Z"
}],
name: [{
text: "Tan Chen Chen"
}],
gender: "female",
birthDate: "1990-01-15"
}
// Specimen - "required": ["resourceType", "type", "collection"],
const Specimen = {
resourceType: "Specimen",
type: {
coding: [{
system: "http://snomed.info/sct",
code: "258500001",
display: "Nasopharyngeal swab"
}]
},
collection: {
collectedDateTime: "2020-09-27T06:15:00Z"
}
}
// Observation - "required": [ "resourceType", "identifier", "code", "valueCodeableConcept", "effectiveDateTime", "qualification", "status" ],
const Observation = {
"resourceType": "Observation",
"identifier": [{
"value": "123456789",
"type": "ACSN"
}],
"code": {
"coding": [{
"system": "http://loinc.org",
"code": "94531-1",
"display": "Reverse transcription polymerase chain reaction (rRT-PCR) test"
}]
},
"valueCodeableConcept": {
"coding": [{
"system": "http://snomed.info/sct",
"code": "260385009",
"display": "Negative"
}]
},
"effectiveDateTime": "2020-09-28T06:15:00Z",
"status": "final",
"performer": {
"name": [{
"text": "Dr Michael Lim"
}]
},
"qualification": [{
"identifier": "MCR 123214",
"issuer": "MOH"
}]
}
// Organization - "required": ["resourceType", "name", "type", "contact"],
// Organization: Healtcare Provider
const Organization1 = {
"resourceType": "Organization",
"name": "MacRitchie Medical Clinic",
"type": "Licensed Healthcare Provider",
"contact": {
"telecom": [{
"system": "phone",
"value": "+6563113111"
}],
"address": {
"type": "physical",
"use": "work",
"text": "MacRitchie Hospital Thomson Road Singapore 123000"
}
}
}
// Organization: Quest
const Organization2 = {
"resourceType": "Organization",
"name": "Quest Laboratories",
"type": "Accredited Laboratory",
"contact": {
"telecom": [{
"system": "phone",
"value": "+6563113111"
}],
"address": {
"type": "physical",
"use": "work",
"text": "Quest Laboratories Address"
},
}
}
// Package it all up into the credential
const credential = {
"type": [ "VerifiableCredential", "HealthPassportBundleCredentialV1" ],
credentialSubject: {
data: {
// "required": ["id", "name", "validFrom", "fhirVersion", "fhirBundle"]
'@type': 'BundleContainer',
id: 'Unique test ID',
name: 'HealthCert',
validFrom: new Date().toISOString(),
fhirVersion: '4.0.1',
fhirBundle: {
'@type': 'Bundle',
resourceType: 'Bundle',
type: 'collection',
entry: [ Patient, Specimen, Observation, Organization1, Organization2 ],
},
},
},
}
/**
* Complete flow to issue a HealthCerts Verifiable Credential
*/
const issueCredential = async ({ orgId, credential, options }) => {
const body = { credential, options, orgId }
const url = `${API_URL}/provider/issueCustomCredential`
const response = await axios.post(url, body, { headers })
return response.data;
}
const run = async () => {
// Default response of wallet install and download URL no authN
let options = {}
let response = await issueCredential({ orgId, credential, options })
console.log({ response1: response })
// Default response of wallet install and download URL, user authN with passport number
options = {
requiredUserAuthentication: [{
property: 'ppn',
acceptedValues: [ 'hn1234' ],
reason: "authentication",
description: 'Internaitonal Passport Number.',
reason: 'authentication'
}],
}
response = await issueCredential({ orgId, credential, options })
console.log({ response2: response })
// multiple response type including wallet install and download URL as well as qr code presentation URL, user authN with passport number
options = {
responseType: [
'walletInstallAndCredentialDownloadUrl',
'encryptedCredentialPresentationUrl'
],
requiredUserAuthentication: [{
property: 'ppn',
acceptedValues: [ 'hn1234' ],
reason: "authentication",
description: 'Internaitonal Passport Number.',
reason: 'authentication'
}],
}
response = await issueCredential({ orgId, credential, options })
console.log({ response3: response })
// greedy response type, returning the raw credential and URLs
options = {
responseType: [
'credential',
'walletInstallAndCredentialDownloadUrl',
'encryptedCredentialPresentationUrl'
],
}
response = await issueCredential({ orgId, credential, options })
console.log({ response4: response })
// Raw QR code data, base64 data URI
options = {
responseType: 'encryptedCredentialPresentationQrCode',
}
response = await issueCredential({ orgId, credential, options })
console.log({ response5: response })
// download URL and QR code as well as presentation URL and QR code data
options = {
responseType: [
'walletInstallAndCredentialDownloadUrl',
'walletInstallAndCredentialDownloadQrCode',
'encryptedCredentialPresentationUrl',
'encryptedCredentialPresentationQrCode',
]
}
response = await issueCredential({ orgId, credential, options })
console.log({ response5: response })
}
run()
// VCX_API_KEY=663b4151-2b80-4d46-80c2-c9ae3728a134 ORG_ID=5fc7d717da620b611af5de4f node apiProviderHealthCert.js
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment