Beginner’s guide DigiLocker system implementation

DigiLocker_GuideLine

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 Work Process

DigiLocker contains two parts – Issued Documents & Self Uploaded Documents. 

  1. Issued Documents: Issued from Original Source (Single Source of Truth) & no separate document copy – just reference link to source
  2. 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:

  1. Based on User Consent
  2. Fully secure access
  3. Anywhere, anytime – desktop/mobile
  4. Paperless & environment friendly

Following is the technical specification of DigiLocker:

DigiLocker technical specification:

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).

DigiLocker system access

#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

DigiLocker Document type

Wrapping Up

So, this was the extensive DigiLocker implementation guidelines. We believe this was super resourceful.