There was an error in this gadget

Friday, 10 July 2009

Calculating an IRMark for the HMRC Gateway using VB.NET

This took ages to finally work out so I thought I'd share the function. Just pass in the XML file as a Byte Array and the IRMark is returned.

Friend Shared Function GetIRMark(ByVal Xml As Byte()) As String

' Convert Byte array to string
Dim text As String = Encoding.UTF8.GetString(Xml)
Dim Doc As New XmlDocument Doc.PreserveWhitespace = True Doc.LoadXml(text)
Dim ns As New XmlNamespaceManager(Doc.NameTable) ns.AddNamespace("env", Doc.DocumentElement.NamespaceURI)
Dim Body = Doc.SelectSingleNode("//env:Body", ns) ns.AddNamespace("tax", Body.FirstChild.NextSibling.NamespaceURI)

Create an XML document of just the body section
Dim xmlBody = New XmlDocument
xmlBody.PreserveWhitespace = True
xmlBody.LoadXml(Body.OuterXml)

' Remove any existing IRMark
Dim nodeIr = xmlBody.SelectSingleNode("//tax:IRmark", ns)
If Not nodeIr Is Nothing Then
nodeIr.ParentNode.RemoveChild(nodeIr)
End If

' Normalise the document using C14N (Canonicalisation)
Dim c14n = New XmlDsigC14NTransform c14n.LoadInput(xmlBody)

Using S As Stream = c14n.GetOutput()
Dim Buffer(S.Length - 1) As Byte
S.Read(Buffer, 0, S.Length)

' Convert to string and normalise line endings
text = Encoding.UTF8.GetString(Buffer)
text = text.Replace("
", "")
text = text.Replace(vbCrLf, vbLf)
text = text.Replace(vbCr, vbLf)

' Convert the final document back into a byte array
Dim b = Encoding.UTF8.GetBytes(text)

' Create the SHA-1 hash from the final document
Dim SHA = SHA1.Create
Dim hash = SHA.ComputeHash(b)
Return Convert.ToBase64String(hash)
End Using

End Function

5 comments:

  1. Hi,

    Very interesting. I need to generate an irmark via VBA in Excel. Would it be possible to build this function into a dll file that could be accessed from the Excel COM application?

    ReplyDelete
  2. I guess so although it's years since I've done Office or VBA Development (everything seemed to break with each new version). It may need slight modification to use a string input instead of a byte array as I don't think VBA can produce a .NET Byte array although I could be wrong.

    ReplyDelete
  3. Thanks you save my life!
    I have been stucked for 5 days in this IRMark thing.

    ReplyDelete
  4. Fantastic bit of code - saved me many hours!

    ReplyDelete
  5. Thanks a lot for posting this. The c# version is available at http://neophytedeveloper.wordpress.com/asp-net-articles/hmrc-generating-irmark-c-net/ if anyone wants it.

    ReplyDelete