Getting Started with AS2 (IPWorks EDI)

Requirements: IPWorks EDI

Introduction

IPWorks EDI offers a simple way to add AS2 capabilities to your application. AS2 functionality consists of two components: AS2Sender and AS2Receiver. This guide details the common operations of both and includes code examples.

Contents

Overview of AS2 Flow

For all of its complexity in terms of its applications, AS2 boils down to two basic parts: A document is sent from an AS2 sender to an AS2 receiver via HTTP, and the receiver acknowledges the transfer by providing the sender with a receipt.

The following illustration demonstrates the different steps that are taken in further detail:

AS2 Process Diagram

AS2Sender may be used to send EDI or other messages over HTTP/S, using the AS2 protocol. It may also be used to verify synchronous or asynchronous server responses.

AS2Receiver implements server-side processing of EDI messages, as specified in AS2 and RFC 3335. It can be used to decrypt and verify incoming messages and to generate MDN receipts (Message Disposition Notifications). AS2Receiver is designed to be easily incorporated into an HTTP server, such as ASP.NET, but may also be used outside of a web server. The examples below assume the component is used within an environment where there is an HTTP context.

AS2Sender

To send files with AS2Sender, first set the AS2From and AS2To properties to the identifiers of the sending and receiving systems, respectively. EDIData specifies the file(s) to be sent. Then, simply set the URL property to the correct endpoint and call the Post method to send the files.

To encrypt the message set RecipientCerts, to sign the message set SigningCert. If the recipient uses different certificates for signing and encryption, the ReceiptSignerCert property should be set to verify the signed receipt. The following table summarizes the relevant certificate properties and expected values:

Certificate PropertyDescription
RecipientCertsUsed to encrypt outgoing data. Set this to your partner's public certificate.
SigningCertUsed to sign the outgoing data. Set this to your certificate with private key.
ReceiptSignerCertMay be used to verify the MDN receipt. This only needs to be set if your partner used different certificates for signing and encryption. This is uncommon and in most cases you do not need to set this property.

TLS will be used if the scheme in URL is "https". If your trading partner is using a self-signed certificate, it will be necessary to set SSLAcceptServerCert or trap the SSLServerAuthentication event to accept the certificate.

The Post method is responsible for signing, encrypting, sending the request, and verifying the response. All of the major tasks of the component are performed when the Post method is called.

Synchronous Receipts

Synchronous MDN receipts are the most commonly used type of receipts and should be used unless there is a specific reason to use asynchronous receipts. With synchronous receipts the receipt is returned over the same HTTP connection in response to the POST. The component requests synchronous receipts by default.

To request a receipt, or Message Disposition Notification (MDN), simply set the MDNTo property to any value. By default, the component will request a signed MDN over a SHA-256 hash. SignatureAlgorithm may be set to request a different signing algorithm.

The Post method will validate the MDN and (if signed) verify the signature. Any errors or warnings will cause the component to throw an exception. The MDNReceipt property will be populated with the receipt information.

AS2 Post Example (synchronous receipt):

as2client.AS2From = "TestAS2Sender";
as2client.AS2To = "TestAS2Receiver";

// Your private certificate. Used to sign the outgoing messages.
as2client.SigningCert = new Certificate(CertStoreTypes.cstPFXFile, 
    "C:\\files\\cert.pfx", "password", "*");

// Your trading partner's public certificate. Used to encrypt the outgoing message.
as2client.RecipientCerts.Add(new Certificate(CertStoreTypes.cstPublicKeyFile, 
    "C:\\files\\partnercert.cer", "", "*"));

// To request an MDN (Message Disposition Notification) based receipt, you
// should set the MDNTo property. By default the component will request a
// SIGNED receipt, with a Received-Content-MIC value that establishes
// digital non-repudiation.
as2client.MDNTo = "as2@nsoftware.com"; // Note: the actual value is irrelevant;

// If you set a log directory, the component will produce detailed log files.
as2client.LogDirectory = "C:\\logs";

// The URL to which the request will be posted.
as2client.URL = tbURL.Text;

as2client.EDIData = new EDIData();
as2client.EDIData.EDIType = "application/edi-x12";
as2client.EDIData.Data = data;

// Send request and verify the MDN. This call to Post will throw an exception
// if any errors or warnings occur.
as2client.Post();

// At this point the MDNReceipt property may be inspected.
Console.WriteLine(as2client.MDNReceipt.Message);

//The above line outputs:
//The incoming message from TestAS2Sender to TestAS2Receiver with Id <d12ea6c1-be6e-46fa-b32e-9cff269548f6@b8ae00e4-ec0f-44e1-964b-58038c5959e7> was received successfully. This is not a guarantee that the message has been processed by the receiving translator.

Asynchronous Receipts

While almost all MDN transmission is done synchronously and asynchronous MDNs are not common, AS2Sender does include options to request an asynchronous MDN receipt. To do this, set the MDNDeliveryOption property to the URL where MDNs are to be delivered.

AS2Sender may also be used to process and verify asynchronous MDNs. This can be done by invoking ReadAsyncReceipt. This will read the receipt from the current HTTP context (or from MDNReceipt, if set manually), and allow the Message Id and trading partner's identity to be determined. The ReceiptSignerCert and OriginalContentMIC properties should then be set before invoking VerifyReceipt.

AS2 Post Example (asynchronous receipt):

as2client.AS2From = "TestAS2Sender";
as2client.AS2To = "TestAS2Receiver";

// Your private certificate. Used to sign the outgoing messages.
as2client.SigningCert = new Certificate(CertStoreTypes.cstPFXFile, 
    "C:\\files\\cert.pfx", "password", "*");

// Your trading partner's public certificate. Used to encrypt the outgoing message.
as2client.RecipientCerts.Add(new Certificate(CertStoreTypes.cstPublicKeyFile, 
    "C:\\files\\partnercert.cer", "", "*"));

// To request an MDN (Message Disposition Notification) based receipt, you
// should set the MDNTo property. By default the component will request a
// SIGNED receipt, with a Received-Content-MIC value that establishes
// digital non-repudiation.
as2client.MDNTo = "as2@nsoftware.com"; // Note: the actual value is irrelevant;

// Set the following MDNDeliveryOption property, and provide additional
// processing for inbound asynchronous receipts (in your server code).
as2client.MDNDeliveryOption = "http://yourserver/asynchmdn.aspx";

// This will instruct the component to preserve the details of the transmission
// on disk, so that when the asynchronous MDN arrives, it can be matched.
as2client.AsyncMDNInfoDir = "C:\\AS2\\MDNInfo";

// If you set a log directory, the component will produce detailed log files.
as2client.LogDirectory = "C:\\logs";

// The URL to which the request will be posted.
as2client.URL = tbURL.Text;

as2client.EDIData = new EDIData();
as2client.EDIData.EDIType = "application/edi-x12";
as2client.EDIData.Data = data;

// Send request and verify the MDN. This call to Post will throw an exception
// if any errors or warnings occur.
as2client.Post();

At this point the file(s) have been sent, but a receipt has not yet been received. AS2Sender can be used within a web site to listen for the receipt.

//**** Inside a web site ****
As2sender as2 = new As2sender;
as2.ReadAsyncReceipt();

// You should now check the AS2From and AS2To properties. These will correspond to the
// originator and recipient of the *original message*; i.e., the sender of the receipt
// will be stored in AS2To.

// MessageId will also be set. You should now read this value, and look up the values
// of OriginalContentMIC and MDNOptions, which you need to have stored when you sent 
// the original message.

// This demo uses the AsnycMDNInfoDir to store the values calculated by the AS2Sender
// Alternatively, you can use your own storage mechanism for setting the MessageID,
// OriginalContentMIC, and MDNOptions
as2.AsyncMDNInfoDir = "C:\\AS2\\MDNInfo";

// Now you should set your trading partner's certificate (unless you requested an unsigned
// receipt). In a real server, this would be selected based on the value of AS2To.
as2.ReceiptSignerCert = new Certificate("C:\\files\\partnercert.cer"));

// Finally, you are ready to verify the receipt. The call to verifyReceipt will
// throw an exception if the component is unable to verify the receipt.
as2.VerifyReceipt();

AS2Receiver

Receiving Documents

To process an EDI message, first invoke ReadRequest to process the headers from the request. By default, the component will attempt to pull the request data from the HTTP context, but it can also be set manually (prior to calling ReadReqeust) via the Request property. The Request may contain both headers and body, or the headers can be specified separately in the RequestHeadersString property.

After invoking ReadRequest, AS2From and AS2To will be populated. Based on this information, the appropriate certificates can be specified. Your certificate would be set via the Certificate property and the trading partner's (signing) certificate would be set via the SignerCert property. The following table summarizes the relevant certificate properties and expected values:

Certificate PropertyDescription
CertificateUsed to decrypt incoming messages and sign receipts. Set this to your certificate with private key.
SignerCertUsed to verify the signature of incoming messages. Set this to your partner's public certificate.

ReadRequest will also populate MessageId and, if an MDN is requested, MDNTo, RequestedSignatureProtocol, RequestedMICAlgorithms, and ReceiptDeliveryOption. RequestHeaders will contain a complete list of HTTP/AS2 headers.

After the request has been read, there are a few different methods to process the received message. The first is to invoke ParseRequest. The certificate used to decrypt and sign should be specified with the Certificate property, and your partner's signing certificate should be specified with SignerCert. This will process the headers, decompress and/or decrypt the message (if applicable), and verify the signature (if present). EncryptionType, SignatureType, and CompressionFormat describe whether and how the data was encrypted, signed, and compressed, respectively. ParseRequest will also populate the EDIType and EDIData based on the transmitted EDI data.

After parsing the message, an MDN receipt would be created based on the received message, taking into account any errors that occurred during parsing, and sent back to the client. This can be done using CreateMDNReceipt and is discussed in the Sending Responses section below.

//**** Inside a web site ****
as2receiver1.ReadRequest();

// At this point, you should check the values of AS2From and AS2To.
as2receiver1.Certificate = new Certificate(CertStoreTypes.cstPFXFile, 
    "C:\\files\\cert.pfx", "password", "*");
as2receiver1.SignerCert = new Certificate("C:\\files\\partnercert.cer");
as2receiver1.LogDirectory = "C:\\as2logs";

try
{
  as2receiver1.ParseRequest();
}
catch (InEDIException ex)
{
  // Set the unexpected processing error status in the MDN
  as2receiver1.Config("ProcessingError=true");
  receiptMessage = ex.Message;
}
finally
{
  // If no error was encountered, the component will generate a default message 
  as2receiver1.CreateMDNReceipt("", "", receiptMessage);
  
  // Actually send the response (including the MDN receipt)
  as2receiver1.SendResponse();
}

Alternatively to using ParseRequest, ProcessRequest can be used. This will perform the same operations as ParseRequest, but also generate the MDNReceipt automatically. If the request was processed successfully, EDIData will be populated with the transmitted EDI data. If a problem occurred, an exception will be thrown instead. In either case, MDNReceipt will contain the RFC-compliant receipt, which would be returned to the client.

Sending Responses

Error Handling

If any errors are encountered during the parsing of the received message, ParseRequest or ProcessRequest will throw a corresponding exception and EDIData will not be populated. Information about the exception will be provided through the exception's error code and message, as well as through the ScanResult property. It is recommended that the server software trap the error and invoke CreateMDNReceipt to create an MDN receipt that reports the error to the client.

Creating an MDN Receipt

After parsing the message and handling any errors, an MDN receipt may be created by invoking the CreateMDNReceipt method. If no errors occurred, the receipt will report success. If errors were encountered, the MDN should report that an error occurred and that the EDI data was not processed. It is strongly recommended that server software trap any errors thrown by ParseRequest or ProcessRequest and return the receipt to notify the client of the error. Below is some example code for parsing the request, handling potential errors, and creating an appropriate MDN receipt:

string receiptMessage = "";
try {
  as2.ParseRequest();
  // At this point the EDIData will be populated. At a minimum
  // you will want to save EDIData to a file for later processing. 
}
catch (InEDIException ex)
{
  // Set the unexpected processing error status in the MDN
  as2.Config("ProcessingError=true");
  receiptMessage = ex.Message;
}
finally
{
  // If no error was encountered, the component will generate a default message 
  as2.CreateMDNReceipt("", "", receiptMessage);
  
  // Actually send the response (including the MDN receipt)
  as2.SendResponse();
}

The MDN receipt may be customized further by setting the parameters when invoking CreateMDNReceipt. The Message parameter may be used to customize the human-readable message in the receipt. If it is set to an empty string, an appropriate message will automatically be written whenever MDNReceipt is regenerated.

The generated receipt will be signed using the protocol requested by the sender. The certificate used to sign the receipt is specified by Certificate. The receipt will be signed in accordance to the options requested by the sender.

Error reporting may be controlled by configuring ErrorReportingFlags. By default, any errors will cause MDNReceipt to report a failure to process the message (either "failed/Failure" or "processed/Error" will be reported, according to the specification and the type of error). Setting ErrorReportingFlags will cause the MDNReceipt to overlook the chosen types of errors. If all errors are overlooked, the MDN receipt will report success and calculate a MIC on the original message as usual. A warning may be reported by setting the MDNWarning configuration setting.

Sending the Response

After errors have been handled and the receipt has been created, the response may be sent by invoking SendResponse. In most cases, the receipt will be sent in the HTTP response back to the client (synchronously). If an asynchronous receipt is requested instead, a simple acknowledgement of "200 OK" will be sent in the HTTP response and the MDN will be sent in a separate transmission to ReceiptDeliveryOption.

Additional Notes

The following sections contain additional details about specific functionality not covered above.

OAEP and PSS

The AS2 components support sending an receiving documents using RSA-OAEP (Optimal Asymmetric Encryption Padding) and RSASSA-PSS (Probabilistic Signature Scheme). When sending documents these may optionally be enabled. When receiving documents no special settings are necessary to process the document.

Note: OAEP and PSS may be used independently of each other. Enabling one does not require enabling the other. However in many cases they are both enabled if used.

Sending using OAEP or PSS

When sending OAEP may be enabled by setting the configuration setting UseOAEP to True. PSS may be enabled by setting UsePSS to True. For instance:

as2sender.Config("UseOAEP=true");
as2sender.Config("UsePSS=true");

The following settings relating to OAEP may also be set, but are uncommon. For details consult the documentation. Additional OAEP settings:

  • OAEPParams
  • OAEPMGF1HashAlgorithm
  • OAEPRSAHashAlgorithm

Receiving OAEP or PSS

To receive AS2 documents which use OAEP or PSS no special settings are required. The component will process these messages without any additional steps. You may optionally require the use of OAEP or PSS on incoming messages by setting the RequireOAEP or RequirePSS configuration settings. For instance:

as2receiver.Config("RequireOAEP=true");
as2receiver.Config("RequirePSS=true");

When sending a MDN receipt the receipt may optionally be signed with PSS. To sign the MDN using PSS set the UsePSS configuration setting to True. For instance:

as2receiver.Config("UsePSS=true"); //For MDN receipts

ASP.NET Core

The component may be used within any .NET Standard compatible platform, including .NET Core and ASP.NET Core. When using AS2Receiver within an ASP.NET Core MVC application the component can be configured to automatically read from the request context, and send using the response context. To do so pass the HttpContext to the constructor of the AS2Receiver class. For instance:

//Inside HomeController.cs
As2receiver as2 = new As2receiver(HttpContext);

We appreciate your feedback.  If you have any questions, comments, or suggestions about this article please contact our support team at kb@nsoftware.com.