DataFlex
DataFlex
Sign SOAP XML for New Zealand Customs Service
See more XAdES Examples
Demonstrates how to create an XAdES signed SOAP XML pertaining to the New Zealand Customs Service.Note: This example requires Chilkat v9.5.0.96 or later.
Chilkat DataFlex Downloads
Use ChilkatAx-win32.pkg
Procedure Test
Boolean iSuccess
Handle hoTsId
Handle hoStrId
Handle hoKeyInfoId
Handle hoDt
Handle hoSbNow
Integer n
PlusOneHour Handle hoSbNowPlusOneHour
Handle hoXmlToSign
Handle hoGen
Variant vXml1
Handle hoXml1
Variant vXml2
Handle hoXml2
Variant vCert
Handle hoCert
Handle hoXmlCustomKeyInfo
Variant vSbXml
Handle hoSbXml
String sTemp1
Move False To iSuccess
// This example assumes the Chilkat API to have been previously unlocked.
// See Global Unlock Sample for sample code.
Move True To iSuccess
// Create the following XML to be signed:
// <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
// xmlns:v1="http://customs.govt.nz/jbms/msggate/reqresp/v1">
// <soapenv:Header>
// <wsse:Security soapenv:mustUnderstand="1"
// xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
// xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
// <wsu:Timestamp wsu:Id="TS-037E78514E9B9132CB16817563559151">
// <wsu:Created>2023-04-17T18:32:35.913Z</wsu:Created>
// <wsu:Expires>2023-04-17T19:32:35.913Z</wsu:Expires>
// </wsu:Timestamp>
// </wsse:Security>
// </soapenv:Header>
// <soapenv:Body wsu:Id="id-8"
// xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
// <v1:RequestResponse>
// <v1:Submitter>TEST1234</v1:Submitter>
// <v1:MailboxMsgId>999999</v1:MailboxMsgId>
// </v1:RequestResponse>
// </soapenv:Body>
// </soapenv:Envelope>
// Create a random ID like this: TS-037E78514E9B9132CB16817563559151
Get Create (RefClass(cComChilkatStringBuilder)) To hoTsId
If (Not(IsComObjectCreated(hoTsId))) Begin
Send CreateComObject of hoTsId
End
Get ComAppend Of hoTsId "TS-" To iSuccess
Get ComAppendRandom Of hoTsId 16 "hex" To iSuccess
// STR-037E78514E9B9132CB16817563559614
Get Create (RefClass(cComChilkatStringBuilder)) To hoStrId
If (Not(IsComObjectCreated(hoStrId))) Begin
Send CreateComObject of hoStrId
End
Get ComAppend Of hoStrId "STR-" To iSuccess
Get ComAppendRandom Of hoStrId 16 "hex" To iSuccess
// KI-037E78514E9B9132CB16817563559583
Get Create (RefClass(cComChilkatStringBuilder)) To hoKeyInfoId
If (Not(IsComObjectCreated(hoKeyInfoId))) Begin
Send CreateComObject of hoKeyInfoId
End
Get ComAppend Of hoKeyInfoId "KI-" To iSuccess
Get ComAppendRandom Of hoKeyInfoId 16 "hex" To iSuccess
// Create a date/time for the current time with this format: 2023-04-17T18:32:35.913Z
Get Create (RefClass(cComCkDateTime)) To hoDt
If (Not(IsComObjectCreated(hoDt))) Begin
Send CreateComObject of hoDt
End
Get ComSetFromCurrentSystemTime Of hoDt To iSuccess
Get Create (RefClass(cComChilkatStringBuilder)) To hoSbNow
If (Not(IsComObjectCreated(hoSbNow))) Begin
Send CreateComObject of hoSbNow
End
Get ComGetAsTimestamp Of hoDt False To sTemp1
Get ComAppend Of hoSbNow sTemp1 To iSuccess
// If we really need the milliseconds, we can replace the "Z" with ".000Z"
// The server will also likely accept a timestamp without milliseconds, such as 2023-04-17T18:32:35Z
Get ComReplace Of hoSbNow "Z" ".000Z" To n
Get Create (RefClass(cComChilkatStringBuilder)) To hoSbNowPlusOneHour
If (Not(IsComObjectCreated(hoSbNowPlusOneHour))) Begin
Send CreateComObject of hoSbNowPlusOneHour
End
Get ComAddSeconds Of hoDt 3600 To iSuccess
Get ComGetAsTimestamp Of hoDt False To sTemp1
Get ComAppend Of hoSbNowPlusOneHour sTemp1 To iSuccess
Get ComReplace Of hoSbNowPlusOneHour "Z" ".000Z" To n
Get Create (RefClass(cComChilkatXml)) To hoXmlToSign
If (Not(IsComObjectCreated(hoXmlToSign))) Begin
Send CreateComObject of hoXmlToSign
End
Set ComTag Of hoXmlToSign To "soapenv:Envelope"
Get ComAddAttribute Of hoXmlToSign "xmlns:soapenv" "http://schemas.xmlsoap.org/soap/envelope/" To iSuccess
Get ComAddAttribute Of hoXmlToSign "xmlns:v1" "http://customs.govt.nz/jbms/msggate/reqresp/v1" To iSuccess
Get ComUpdateAttrAt Of hoXmlToSign "soapenv:Header|wsse:Security" True "soapenv:mustUnderstand" "1" To iSuccess
Get ComUpdateAttrAt Of hoXmlToSign "soapenv:Header|wsse:Security" True "xmlns:wsse" "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" To iSuccess
Get ComUpdateAttrAt Of hoXmlToSign "soapenv:Header|wsse:Security" True "xmlns:wsu" "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" To iSuccess
Get ComGetAsString Of hoTsId To sTemp1
Get ComUpdateAttrAt Of hoXmlToSign "soapenv:Header|wsse:Security|wsu:Timestamp" True "wsu:Id" sTemp1 To iSuccess
Get ComGetAsString Of hoSbNow To sTemp1
Send ComUpdateChildContent To hoXmlToSign "soapenv:Header|wsse:Security|wsu:Timestamp|wsu:Created" sTemp1
Get ComGetAsString Of hoSbNowPlusOneHour To sTemp1
Send ComUpdateChildContent To hoXmlToSign "soapenv:Header|wsse:Security|wsu:Timestamp|wsu:Expires" sTemp1
Get ComUpdateAttrAt Of hoXmlToSign "soapenv:Body" True "wsu:Id" "id-8" To iSuccess
Get ComUpdateAttrAt Of hoXmlToSign "soapenv:Body" True "xmlns:wsu" "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" To iSuccess
Send ComUpdateChildContent To hoXmlToSign "soapenv:Body|v1:RequestResponse|v1:Submitter" "TEST1234"
Send ComUpdateChildContent To hoXmlToSign "soapenv:Body|v1:RequestResponse|v1:MailboxMsgId" "999999"
Get Create (RefClass(cComChilkatXmlDSigGen)) To hoGen
If (Not(IsComObjectCreated(hoGen))) Begin
Send CreateComObject of hoGen
End
Set ComSigLocation Of hoGen To "soapenv:Envelope|soapenv:Header|wsse:Security"
Set ComSigLocationMod Of hoGen To 0
Set ComSigId Of hoGen To "SIG-037E78514E9B9132CB16817563559695"
Set ComSigNamespacePrefix Of hoGen To "ds"
Set ComSigNamespaceUri Of hoGen To "http://www.w3.org/2000/09/xmldsig#"
Set ComSignedInfoPrefixList Of hoGen To "soapenv v1"
Set ComIncNamespacePrefix Of hoGen To "ec"
Set ComIncNamespaceUri Of hoGen To "http://www.w3.org/2001/10/xml-exc-c14n#"
Set ComSignedInfoCanonAlg Of hoGen To "EXCL_C14N"
Set ComSignedInfoDigestMethod Of hoGen To "sha256"
// Set the KeyInfoId before adding references..
Get ComGetAsString Of hoKeyInfoId To sTemp1
Set ComKeyInfoId Of hoGen To sTemp1
// -------- Reference 1 --------
Get Create (RefClass(cComChilkatXml)) To hoXml1
If (Not(IsComObjectCreated(hoXml1))) Begin
Send CreateComObject of hoXml1
End
Set ComTag Of hoXml1 To "ds:Transforms"
Get ComUpdateAttrAt Of hoXml1 "ds:Transform" True "Algorithm" "http://www.w3.org/2001/10/xml-exc-c14n#" To iSuccess
Get ComUpdateAttrAt Of hoXml1 "ds:Transform|ec:InclusiveNamespaces" True "PrefixList" "wsse soapenv v1" To iSuccess
Get ComUpdateAttrAt Of hoXml1 "ds:Transform|ec:InclusiveNamespaces" True "xmlns:ec" "http://www.w3.org/2001/10/xml-exc-c14n#" To iSuccess
Get ComGetAsString Of hoTsId To sTemp1
Get pvComObject of hoXml1 to vXml1
Get ComAddSameDocRef2 Of hoGen sTemp1 "sha256" vXml1 "" To iSuccess
// -------- Reference 2 --------
Get Create (RefClass(cComChilkatXml)) To hoXml2
If (Not(IsComObjectCreated(hoXml2))) Begin
Send CreateComObject of hoXml2
End
Set ComTag Of hoXml2 To "ds:Transforms"
Get ComUpdateAttrAt Of hoXml2 "ds:Transform" True "Algorithm" "http://www.w3.org/2001/10/xml-exc-c14n#" To iSuccess
Get ComUpdateAttrAt Of hoXml2 "ds:Transform|ec:InclusiveNamespaces" True "PrefixList" "v1" To iSuccess
Get ComUpdateAttrAt Of hoXml2 "ds:Transform|ec:InclusiveNamespaces" True "xmlns:ec" "http://www.w3.org/2001/10/xml-exc-c14n#" To iSuccess
Get pvComObject of hoXml2 to vXml2
Get ComAddSameDocRef2 Of hoGen "id-8" "sha256" vXml2 "" To iSuccess
// Provide a certificate + private key. (PFX password is test123)
Get Create (RefClass(cComChilkatCert)) To hoCert
If (Not(IsComObjectCreated(hoCert))) Begin
Send CreateComObject of hoCert
End
Get ComLoadPfxFile Of hoCert "qa_data/pfx/cert_test123.pfx" "test123" To iSuccess
If (iSuccess <> True) Begin
Get ComLastErrorText Of hoCert To sTemp1
Showln sTemp1
Procedure_Return
End
Get pvComObject of hoCert to vCert
Get ComSetX509Cert Of hoGen vCert True To iSuccess
Set ComKeyInfoType Of hoGen To "Custom"
// Create the custom KeyInfo XML..
Get Create (RefClass(cComChilkatXml)) To hoXmlCustomKeyInfo
If (Not(IsComObjectCreated(hoXmlCustomKeyInfo))) Begin
Send CreateComObject of hoXmlCustomKeyInfo
End
Set ComTag Of hoXmlCustomKeyInfo To "wsse:SecurityTokenReference"
Get ComGetAsString Of hoStrId To sTemp1
Get ComAddAttribute Of hoXmlCustomKeyInfo "wsu:Id" sTemp1 To iSuccess
Get ComUpdateAttrAt Of hoXmlCustomKeyInfo "wsse:KeyIdentifier" True "EncodingType" "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" To iSuccess
Get ComUpdateAttrAt Of hoXmlCustomKeyInfo "wsse:KeyIdentifier" True "ValueType" "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" To iSuccess
// Insert the single-line base64 of the signing certificate's DER
Set ComUncommonOptions Of hoCert To "Base64CertNoCRLF"
Get ComGetEncoded Of hoCert To sTemp1
Send ComUpdateChildContent To hoXmlCustomKeyInfo "wsse:KeyIdentifier" sTemp1
Set ComEmitXmlDecl Of hoXmlCustomKeyInfo To False
Get ComGetXml Of hoXmlCustomKeyInfo To sTemp1
Set ComCustomKeyInfoXml Of hoGen To sTemp1
// Load XML to be signed...
Get Create (RefClass(cComChilkatStringBuilder)) To hoSbXml
If (Not(IsComObjectCreated(hoSbXml))) Begin
Send CreateComObject of hoSbXml
End
Get pvComObject of hoSbXml to vSbXml
Get ComGetXmlSb Of hoXmlToSign vSbXml To iSuccess
Set ComBehaviors Of hoGen To "IndentedSignature"
// Sign the XML...
Set ComVerboseLogging Of hoGen To True
Get pvComObject of hoSbXml to vSbXml
Get ComCreateXmlDSigSb Of hoGen vSbXml To iSuccess
If (iSuccess <> True) Begin
Get ComLastErrorText Of hoGen To sTemp1
Showln sTemp1
Procedure_Return
End
// Save the signed XML to a file.
Get ComWriteFile Of hoSbXml "c:/temp/qa_output/signedXml.xml" "utf-8" False To iSuccess
Get ComGetAsString Of hoSbXml To sTemp1
Showln sTemp1
End_Procedure