Beginner’s guide DigiLocker system implementation
DigiLocker is part of the Digital India initiative. There are two primary visions DigiLocker – Shareable Private Space on Public Cloud and Digital Documents certificates on Cloud. Current prevailing challenges are documents in physical form, copy/scan/courier for submission, fake documents in circulation etc. faced by citizens as well as the government departments.
DigiLocker is a cloud-based platform for issuance and verification of documents & certificates digitally. But how does the DigiLocker system work? Issuers can issue documents which are digitally generated and requester can access documents by requesting online via the DigiLocker App.
DigiLocker contains two parts – Issued Documents & Self Uploaded Documents.
- Issued Documents: Issued from Original Source (Single Source of Truth) & no separate document copy – just reference link to source
- Self-Uploaded Documents: Legacy / old documents can be uploaded, using e-Sign for self-attestation & Similar to DropBox, Google Drive (1GB free space)
DigiLocker Benefits:
- Based on User Consent
- Fully secure access
- Anywhere, anytime – desktop/mobile
- Paperless & environment friendly
Following is the technical specification of DigiLocker:
Following is the implementation step to access digital documents which are issued by Issuers into DigiLocker.
#Step 1: We have to create Issuers’ User Account in DigiLocker System access (In this case, we have to contact the DigiLocker Team for account creation).
#Step 2: Provide document name to the DigiLocker team for the creation/generation of document type in DigiLocker. The DigiLocker team will provide generated document type names. The following are some examples of documents generated for one department:
Doc Type (Created By DigiLocker Team) | Application Name |
MOCER | Mortgage Permission |
TRCER | Transfer Order |
TRCER | Transfer Order |
#Step 3: Developed REST based API for DigiLocker system.
1. Created Pull URI Request API
API Code:
#region "1) Pull URI Request API "
[HttpPost]
public async Task<HttpResponseMessage> XMLGIDCRequestedURIForDGLockerAPI([NakedBody] string requestedDGLockerXML)
{
string response = string.Empty;
string URI = string.Empty;
StringReader reader = null;
XDocument xDocRequest = null;
string strXmlRequest = string.Empty;
reader = new StringReader(requestedDGLockerXML);
strXmlRequest = await reader.ReadToEndAsync();
xDocRequest = XDocument.Parse(strXmlRequest);
string str = xDocRequest.Root.ToString();
string sTxn = xDocRequest.Root.Attribute("txn").Value;
string sTs = xDocRequest.Root.Attribute("ts").Value;
string ResponseStatus = "1";
string UDF1 = xDocRequest.Root.Element("DocDetails").Element("PartyCode").Value;
string UDF2 = xDocRequest.Root.Element("DocDetails").Element("OutwardDate").Value;
string UDF3 = xDocRequest.Root.Element("DocDetails").Element("ApplicantEmailId").Value;
string UDF4 = "";
if (xDocRequest.Root.Element("DocDetails").Elements("TypeofCertificate") != null)
{
UDF4 = xDocRequest.Root.Element("DocDetails").Element("TypeofCertificate").Value;
}
string DocType = xDocRequest.Root.Element("DocDetails").Element("DocType").Value;
string DigiLockerId = xDocRequest.Root.Element("DocDetails").Element("DigiLockerId").Value;
string DocContent = "";
DataTable dtDetails = null;
string docTypeName = "";
try
{
object[] objPara1 = new object[4];
switch (DocType)
{
case "MOCER": // Unique parameter list to be passed for fetched document
objPara1[0] = Convert.ToString(UDF1.ToString());
objPara1[1] = Convert.ToString(UDF2.ToString());
objPara1[2] = Convert.ToString(UDF3.ToString());
DocContent = (GeneratedPDF(UDF1.ToString(), UDF2.ToString(), UDF3.ToString())).ToString().Trim(); // Converted Based 64 string as per requirement
DevCommon.Select("SPNAMEToGETDocument", ref dtDetails, objPara1);
// Define in Digilocker System
docTypeName = DocType;
// Unique generated by User Request
URI = "department unique URI-" + docTypeName + "-" + dtDetails.Rows[0]["ReferenceNo"].ToString() + "XXXX";
response = "<?xml version='1.0' encoding='UTF-8' standalone='yes'?>" +
"<PullURIResponse xmlns:ns2='http://tempuri.org/'>" +
"<ResponseStatus Status='1' ts='" + sTs + "' txn='" + sTxn + "'>" + ResponseStatus + "</ResponseStatus>" +
"<DocDetails>" +
"<DocType>" +
DocType +
"</DocType>" +
"<DigiLockerId>" +
DigiLockerId +
"</DigiLockerId>" +
"<PartyCode>" + UDF1 + "</PartyCode>" +
"<OutwardDate>" + UDF2 + "</OutwardDate>" +
"<ApplicantEmailId>" + UDF3 + "</ApplicantEmailId>" +
"<TypeofCertificate>" + UDF4 + "</TypeofCertificate>" +
"<URI>" + URI + "</URI>" +
"<DocContent>" + DocContent + "</DocContent>" +
"</DocDetails>" +
"</PullURIResponse>";
break;
}
}
catch (Exception ex)
{
response = "<?xml version='1.0' encoding='UTF-8' standalone='yes'?>" +
"<PullURIResponse xmlns:ns2='http://tempuri.org/'>" +
"<ResponseStatus Status='1' ts='" + sTs + "' txn='" + sTxn + "'>" + "0" + "</ResponseStatus>" +
"<DocDetails>" +
"<DocType>" +
DocType +
"</DocType>" +
"<DigiLockerId>" +
DigiLockerId +
"</DigiLockerId>" +
"<DocContent>" + "Document Yet not Created ! " + "</DocContent>" +
"</DocDetails>" +
"</PullURIResponse>";
}
return new HttpResponseMessage()
{
Content = new StringContent(response, Encoding.UTF8, "application/xml")
};
}
#endregion
URI: We have passed unique key for linked document by pull doc API
URI = “Department Unique URI-” + docTypeName + “-” + UniqueNo;
DocType: To pass DocType Which is created by the DiGiLocker system.
DigiLockerId: Response received from Requested Data.
DocContent: To passed Base64string of converted PDF file.
[XML Template Format]
1.1 Requested XML: (this XML requested by Digilocker’s System)
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<PullURIRequest xmlns:ns2="http://tempuri.org/" ver="1.0" ts="2021-05-12T14:38:03+05:30" txn="88ec19c1c9f03a2b67147e59e8b16c7d" orgId="in.gov.gujarat.gidc" keyhash="e2e16ffabf229224eb4074b8ca0f2d5002cb699666997748e6281baafae14089" format="pdf">
<DocDetails>
<DocType> DocType </DocType>
<DigiLockerId>sample11-1aa1-11a1-10a0-digilockerid</DigiLockerId>
<ApplicantEmailId> UDF1 </ApplicantEmailId>
<OutwardDate> UDF1 </OutwardDate>
<PartyCode> UDF1 </PartyCode>
<TypeofCertificate> UDF1 </TypeofCertificate>
</DocDetails>
</PullURIRequest>
1.2 Response XML (We have developed RESTful API):
<?xml version='1.0' encoding='UTF-8' standalone='yes'?>" +
"<PullURIResponse xmlns:ns2='http://tempuri.org/'>" +
"<ResponseStatus Status='1' ts='" + sTs + "' txn='" + sTxn + "'>"
+ ResponseStatus +
"</ResponseStatus>" +
"<DocDetails>" +
"<DocType>" +
DocType +
"</DocType>" +
"<DigiLockerId>" +
DigiLockerId +
"</DigiLockerId>" +
"<PartyCode>" + UDF1 + "</PartyCode>" +
"<OutwardDate>" + UDF2 + "</OutwardDate>" +
"<ApplicantEmailId>" + UDF3 + "</ApplicantEmailId>" +
"<TypeofCertificate>" + UDF4 + "</TypeofCertificate>" +
"<URI>" + URI + "</URI>" +
"<DocContent>" + DocContent + "</DocContent>" +
"</DocDetails>" +
"</PullURIResponse>
2. Created Pull DOC Request API
API Code
#region "2) Pull DOC Request API"
[HttpPost]
public async Task<HttpResponseMessage> XMLGIDCRequestedDOCForDGLockerAPI([NakedBody] string requestedDGLockerXML)
{
string response = string.Empty;
string URI = string.Empty;
StringReader reader = null;
XDocument xDocRequest = null;
string strXmlRequest = string.Empty;
reader = new StringReader(requestedDGLockerXML);
strXmlRequest = await reader.ReadToEndAsync();
xDocRequest = XDocument.Parse(strXmlRequest);
string str = xDocRequest.Root.ToString();
string sTxn = xDocRequest.Root.Attribute("txn").Value;
string sTs = xDocRequest.Root.Attribute("ts").Value;
string ResponseStatus = "1";
URI = xDocRequest.Root.Element("DocDetails").Element("URI").Value;
string[] strURI = URI.Split('-');
string DocType = strURI[1].ToString();
string OriginalApplicationNo = strURI[2].ToString();
string[] strApplicationNo = OriginalApplicationNo.Split(new string[] { "XXXX" }, StringSplitOptions.None);
string UDF1 = strApplicationNo[0].ToString().Replace("ZZZZ", "_");
string UDF4 = strApplicationNo[1].ToString();
string DigiLockerId = xDocRequest.Root.Element("DocDetails").Element("DigiLockerId").Value;
string DocContent = "";
DataTable dtDetails = null;
string docTypeName = "";
try
{
object[] objPara1 = new object[4];
switch (DocType)
{
case "MOCER":
DocContent = (GeneratedDocPDF(UDF1.ToString())).ToString().Trim(); // Base 64 string return;
//DataTable dtDetails = null;
objPara1[0] = Convert.ToString(UDF1.ToString());
DevCommon.Select("SPNameToFetchDocument", ref dtDetails, objPara1);
// Define in Digilocker System
docTypeName = DocType;
// Unique generated by User Request
URI = "department Unique URI-" + docTypeName + "-" + dtDetails.Rows[0]["ReferenceNo"].ToString();
response = "<?xml version='1.0' encoding='UTF-8' standalone='yes'?>" +
"<PullDocResponse xmlns:ns2='http://tempuri.org/'>" +
"<ResponseStatus Status='1' ts='" + sTs + "' txn='" + sTxn + "'>" + ResponseStatus + "</ResponseStatus>" +
"<DocDetails>" +
"<DocContent>" + DocContent + "</DocContent>" +
"</DocDetails>" +
"</PullDocResponse>";
break;
}
}
catch (Exception ex)
{
response = "<?xml version='1.0' encoding='UTF-8' standalone='yes'?>" +
"<PullDocResponse xmlns:ns2='http://tempuri.org/'>" +
"<ResponseStatus Status='1' ts='" + sTs + "' txn='" + sTxn + "'>" + "0" + "</ResponseStatus>" +
"<DocDetails>" +
"<DocContent>" + "Document Yet not Created ! " + "</DocContent>" +
"</DocDetails>" +
"</PullDocResponse>";
}
//return XDocument.Parse(response);
return new HttpResponseMessage()
{
Content = new StringContent(response, Encoding.UTF8, "application/xml")
};
}
#endregion
2.1 Requested XML: (this XML requested by Digilocker’s System)
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><PullDocRequest xmlns:ns2="http://tempuri.org/" ver="1.0" ts="2021-05-12T14:40:12+05:30" txn="0764e898e3b07e783e78b3d80ef61a31" orgId="in.gov.gujarat.gidc" keyhash="8da0c393c347e5327196f71ce2393c4464b3e514691caa43e68aabae76b3282d" format="pdf"><DocDetails><URI>123213</URI><DigiLockerId>sample00-1aa1-11a1-10a0-digilockerid</DigiLockerId></DocDetails></PullDocRequest>
2.2 Response XML (We have developed RESTful API):
<?xml version='1.0' encoding='UTF-8' standalone='yes'?>" +
"<PullDocResponse xmlns:ns2='http://tempuri.org/'>" +
"<ResponseStatus Status='1' ts='" + sTs + "' txn='" + sTxn + "'>" + ResponseStatus + "</ResponseStatus>" +
"<DocDetails>" +
"<DocContent>" + DocContent + "</DocContent>" +
"</DocDetails>" +
"</PullDocResponse>
#Step 4: REST API registered using DigiLocker System
Step 5: Document Type Mapping using DigiLocker System
Wrapping Up
So, this was the extensive DigiLocker implementation guidelines. We believe this was super resourceful.