Direct Support Site

Results for

icon-search-large No search results yet
Enter your search query above

1. Introduction

To create payments, you need to link your server to our platform via one of our integration modes.
Our .NET SDK is the ideal solution to connect to our platform if you prefer to do so with your own stand-alone system using C# language. 

Choosing the .NET SDK, you can:

To take full advantage of this SDK, make sure you meet these requirements:

  • .NET Framework 4.5 / .NET Standard 2.0 or 2.1
  • IDE: Visual Studio 2019
  • Platform: Windows

Find more details about these requirements on GitHub. Also, check out all available SDK objects and properties in our Full API Reference.

Download the newest version and follow the installation instructions. Once you are all set, read the next chapters on how to prepare and use the SDK.

This guide provides a general overview on the SDK’s functionalities. To see how they precisely work for the different integration modes, see the dedicated guides explaining every step with full code samples:

Target most up-to-date API base URL

We encourage you to always target the most up-to-date API base URL when sending requests to our platform. Have a look at our dedicated guides for a full overview:

To allow you a smooth transition, previous API base URLs remain available until further notice.

2. Initialise SDK

To use the SDK to connect your system to our platform, you first need to initialise it.

Initialising requires you to

  • Create a test/live account
  • Create an API Key and API Secret for the PSPID you wish to use for transaction processing
  • Initialise an instance of IClient using the API Key/API Secret to set up the connection to our test/live platform

    Remember to pay attention to the environment you get the key set from. API Key and API Secret are different for test and live environments.

    The full path of the API endpoint for the test/live environment is

    • https://payment.preprod.direct.worldline-solutions.com/v2/
    • https://payment.direct.worldline-solutions.com/v2/


    As our SDKs always implement the latest version of our API, you can leave out "v2" in your code as shown in the example above

After initialisation, you can start processing transactions via your PSPID. Learn how this works in the dedicated chapter.

Have a look at the code sample covering the steps mentioned above:


// Declare the IClient field for the SDK initialisation and for later use.
private IClient client;

// In case you use one PSPID, declare the IMerchantClient field.
private IMerchantClient merchantClient;

public void SetupDirectSDK()
{
	// Create a URI to target our test or live environment
	Uri apiEndpoint = new Uri("https://payment.preprod.direct.worldline-solutions.com");

	// Initialise client with the Uri and your API key/API secret from your PSPID		
	client = Factory.CreateClient(apiKey, apiSecret, apiEndpoint, integrator);

	// In case you have multiple PSPIDs, please substitute the merchantClient in the subsequent examples with this code sample: 
	merchantClient = client.WithNewMerchant(merchantId);
}
If you are ready to switch to the live environment, substitute the endpoint link apiEndpoint = 'https://payment.preprod.direct.worldline-solutions.com' for the live environment apiEndpoint = 'https://payment.direct.worldline-solutions.com/'

The following table provides an overview of the arguments accepted by the individual instances:

Properties
  • string merchantId: Your PSPID in either our test environment/live environment. Make sure to use the correct apiKey / apiSecret together with the conjoining PSPID for your transactions request
  • string apiKey: The API Key you have defined in your PSPID to which you will send the transactions to
  • string apiSecret: The API Secret you have defined in your PSPID to which you will send the transactions to

    Check out our dedicated guide to learn all about apiKey / apiSecret


  • Uri apiEndpoint: Send your transaction requests either to our test/live environment

    The full path of the of API endpoint for test/live environment is

    • https://payment.preprod.direct.worldline-solutions.com/v2/
    • https://payment.direct.worldline-solutions.com/v2/

    respectively. As our SDKs always implement the latest version of our API, you can leave out "v2" in your code as shown in the example above

    For transactions with no financial impact, use the TEST-URL. The transactions will be sent to our test environment thereby to your test account.

    For transactions with a financial impact, use the LIVE-URL. The transactions will be sent to our live environment thereby to your live account.

  • string integrator: Your (company) name or any unique identifier. We can use the value for debugging and tracking request you have sent to our platform. Therefore, we strongly suggest sending a value we can identify your requests easily in our logs
You can re-use a client instance for different calls. You can use

  • The IMerchantClient initialised in the example for all calls for that PSPID.
  • The IClient instance to create IMerchantClients for different (or the same) PSPIDs.

You can also create a new instance for each call, but this uses unnecessary additional system resources

After you have initialised the SDK, you can send requests to our platform via your PSPID. Learn in the next chapter how to do this.

For transactions with no financial impact, use TEST-URL. The transactions will be sent to our test environment, thereby to your test account

For transactions with a financial impact, use the LIVE-URL. The transactions will be sent to our live environment, thereby to your live account

3. Use SDK

After the successful initialisation of the  IClient instance, you gain full access to our RESTful API. It enables you to:

  • Send requests for new transactions for any of our server integration modes
  • Get your transactions’ current status
  • Perform maintenance requests (captures, refunds etc) on existing transactions
Make sure that the payment method you would like to use is active in your test/live account. Check in the Back Office via Configuration > Payment methods 

Check out our test cases in GitHub, including full code samples, and our Full API Reference to learn what is possible.

IClient implements the IDisposable interface, allowing you to use it in using statements. This will release resources when they are no longer needed. Alternatively, we strongly suggest closing the connection manually:

client.CloseIdleConnections(yourTimespan)

Below you may find some of the most common actions you can perform.

Create new transactions

To create a new transaction, you can use either the IMerchantClient or IClient instance for any of our integration modes to create a new transaction. It can be done through: 

  • Routing the request to your PSPID on our platform (for IClient)
  • Creating a request for the respective integration mode

The SDK instance only keeps track of the data used to initialise it. It does not track neither active sessions nor previous requests. Your system is responsible for managing Direct sessions and payments

Sessions and payments do not impact other sessions and payments

Below you can find code samples related to particular integration modes:

Hosted Checkout Page

To use this integration mode, you need to create a CreateHostedCheckoutRequest call. It must contain at least an Order object.


/* 
 *…. Initialisation....
 */

private CreateHostedCheckoutRequest createHostedCheckoutRequest = new CreateHostedCheckoutRequest { Order = new Order { AmountOfMoney = new AmountOfMoney { Amount = 100, CurrencyCode = "EUR" } } }; // Use the IMerchantClient for an asynchronous request routed to your PSPID var createHostedCheckoutResponse = await merchantClient .HostedCheckout .CreateHostedCheckout(createHostedCheckoutRequest);
You can specify an optional returnUrl, which will be used to redirect your customer back to your website

This call returns a CreateHostedCheckoutResponse response. Store the hostedCheckoutId and RETURNMAC it contains, as well as any other information relevant for you. You will need these for steps described in the following chapters.

This response also contains a partialRedirectURL.

You have to concatenate the base URL "https://payment." with partialRedirectURL according to the formula

https://payment. + partialRedirectURL

and perform a redirection of your customer to this URL. Once the customer visits the Hosted Checkout Page, the payment process continues there.

The newest version of our SDK also returns the full path in redirectURL, allowing you to skip concatenate the base URL "https://payment." with partialRedirectURL. Learn more more in our  Hosted Checkout Page guide. 

Hosted Tokenization Page

To use this integration method, you need to


private CreateHostedTokenizationRequest createHostedTokenizationRequest = new CreateHostedTokenizationRequest();

// Initiate fields for a minimal CreateHostedTokenizationRequest 
createHostedTokenizationRequest.Variant = “my-custom-template.html”;


// Use the IMerchantClient for an asynchronous request routed to your PSPID
var createHostedTokenizationResponse = await merchantClient
    .HostedTokenization
    .CreateHostedTokenization(createHostedTokenizationRequest);

From CreateHostedTokenizationResponse retrieve hostedTokenizationId and partialRedirectUrl. Use the  partialRedirectUrl for the iframe and the hostedTokenizationId or tokenId (see infobox) to create the actual payment via Server-to-server integration mode.

You can send either the tokenID or the hostedTokenizationId in your CreatePayment request. Learn more about using either option in the dedicated chapters of our Hosted Tokenization Page guide:

// Get the result of the tokenization session
var getHostedTokenizationResponse = await client
	.WithNewMerchant("YourPSPID")
	.HostedTokenization
	.GetHostedTokenization(createHostedTokenizationResponse.HostedTokenizationId);

// Get the tokenId to be used for payment creation
var tokenId = getHostedTokenizationResponse.Token.Id;
CreatePaymentRequest requestBody = new CreatePaymentRequest
{
	CardPaymentMethodSpecificInput = new CardPaymentMethodSpecificInput
	{
		Token = tokenId // Token received by calling GetHostedTokenization()
	},
	Order = new Order
	{
		AmountOfMoney = new AmountOfMoney
		{
			Amount = 100, // The amount you want to charge your customer multiplied by 100 (1.00 EUR)
			CurrencyCode = "EUR"
		}
	}
};

var response = await client
	.WithNewMerchant("YourPSPID")
	.Payments
	.CreatePayment(requestBody);

Server-to-server

A minimum paymentResponse requires you to set at least an Order object and a payment method:


// Initiate fields for a minimal CreatePaymentResponse
CreatePaymentRequest body = new CreatePaymentRequest
{
    Order = new Order
    {
        AmountOfMoney = new AmountOfMoney
            {
                Amount = 100,
                CurrencyCode = "EUR"
            }
    },
    CardPaymentMethodSpecificInput = new CardPaymentMethodSpecificInput // Find more test data here 
    {
        Card = new Card
        {
            CardholderName = "Wile E. Coyote",
            CardNumber = "4111111111111111",
            Cvv = "123",
            ExpiryDate = "1236"
        }
    }
};



// Use the IMerchantClient for an asynchronous request routed to your PSPID
var createPaymentResponse = await merchantClient
    .Payments
    .CreatePayment(body);

We have dedicated guides for each of the aforementioned integration modes:

The documents contain all crucial details you need to profit from the integration modes’ full potential, including full transaction flows, code samples and other useful features

Get transaction status

Our RESTful API allows you to request a transaction’s status anytime by one of our GET calls:

A GetPayment request looks like this: 

// Use the IMerchantClient for an asynchronous request routed to your PSPID
PaymentResponse paymentResponse = await merchantClient
.Payments
.GetPayment(paymentID);
Properties
string paymentID: The 10-digit unique reference of your transaction on our platform. This reference can be retrieved from the CreatePaymentResponse or createHostedCheckoutResponse created in the previous section.

For more information about statuses visit the status documentation page.

Perform maintenance operation

To perform follow-up actions on existing transactions (i.e. captures or refunds), use our CapturePayment or RefundPayment API call respectively:

CapturePayment


CapturePaymentRequest body = new CapturePaymentRequest
{
    Amount = 100,
    IsFinal = true
};

// Use the IMerchantClient for an asynchronous request routed to your PSPID
CaptureResponse captureResponse = await merchantClient
    .Payments
    .CapturePayment(paymentId, body);

RefundPayment


RefundRequest body = new RefundRequest

Amount = new AmountOfMoney
{
       	Amount = 100,
CurrencyCode = "EUR"
    
};

// Use the IMerchantClient for an asynchronous request routed to your PSPID
RefundResponse refundRespsonse = await merchantClient
    .Payments
    .RefundPayment(paymentId, body);
Properties
string paymentID: The 10-digit unique reference of your transaction on our platform. This reference can be retrieved from the CreatePaymentResponse or createHostedCheckoutResponse created in the previous section.

4. Handle exceptions

If a transaction is rejected, our platform provides detailed information with an Exception instance. The affiliated HTTP status code also help you troubleshoot the error.

You can encounter two types of exceptions: transaction exceptions and HTTP exceptions.

Transaction exceptions

This kind of exception refers to transaction requests that are technically correct but were rejected by your customer’s issuer or your acquirer. If the transaction is returned in the exception then, it was created in our systems but not successfully processed.

The following code samples use implicit methods provided as an example. You are expected to provide your own implementation for these or replace them with similar logic

Exception type /
HTTP status code
Code Sample
Rejected transactions / 
Various(see PaymentResponse object)
CreatePaymentRequest body = CreateRequest();
string paymentId;
try
{
     CreatePaymentResponse response = await merchantClient .Payments .CreatePayment(body);
     paymentId = response.Payment.Id;
}
catch (DeclinedPaymentException e)
{
    PaymentResponse payment = e.CreatePaymentResponse.Payment;
    paymentId = payment.Id;
    System.Console.WriteLine(e.Message);
    foreach (APIError error in e.Errors)
    {
        System.Console.WriteLine("Error {0}: {1}, {2}", error.Code, error.Id, error.Message);
    }
}   
PaymentResponse paymentResponse = await MerchantClient .Payments .GetPayment(paymentId);
if (IsNotSuccessful(payment))
{
    HandleError(payment);
}
Rejected Refund /
Various(see PaymentResponse object)
RefundRequest body = createRequest();
String refundId;
try
{
    RefundResponse response = await merchantClient .Payments .RefundPayment("PayID", body);     
    refundId = response.Id;
}
catch (DeclinedRefundException e)
{
    RefundResponse refund = e.RefundResult;
    System.Console.WriteLine(e.Message);
    foreach (APIError error in e.Errors)
    {
        System.Console.WriteLine("Error {0}: {1}, {2}", error.Code, error.Id, error.Message);
    }
}
RefundsResponse refunds = await merchantClient .Payments .GetRefunds(paymentId);
if (IsNotSuccessful(refunds, refundId))
{
    HandleError(refunds);
}






HTTP exceptions

This kind of exception refers to various problems caused by technical errors in the API call or payment request.

You can combine any of the following code snippets with this standard CreatePayment request:


CreatePaymentResponse createPaymentResponse;

// Initiate fields for a minimal CreatePaymentResponse
CreatePaymentRequest body = new CreatePaymentRequest()
{
    Order = new Order
    {
        AmountOfMoney = new AmountOfMoney
            {
                Amount = 100,
                CurrencyCode = "EUR"
            }
    },
    CardPaymentMethodSpecificInput = new CardPaymentMethodSpecificInput
    {
        Card = new Card
        {
            CardholderName = "Wile E. Coyote",
            CardNumber = "4111111111111111",
            Cvv = "123",
            ExpiryDate = "1236"
        }
    }
};

// Use the IMerchantClient for an asynchronous request routed to your PSPID 
try
{
createPaymentResponse = await merchantClient
    .Payments
    .CreatePayment(body);
}
catch (ApiException e)
{
    // refer to the list below to see how specific implementations of ApiException can be handled.
}

Exception type / 
HTTP status code
Code Sample
ValidationException
400
catch (ValidationException e)
{
    System.Console.WriteLine("Input validation error:");
    foreach (APIError error in e.Errors)
    {
        if (error.PropertyName == null)
        {
             System.Console.WriteLine("- {0}: {1}", error.Code, error.Message);
        }
        else
        { System.Console.WriteLine("- {0}: {1}: {2}", error.PropertyName, error.Code,     
          error.Message);
        }
    }
}
AuthorizationException / 
403
catch (AuthorizationException e)
{
    System.Console.WriteLine("Authorisation error:");
    foreach (APIError error ine.Errors)
    {
         System.Console.WriteLine("- {0}: {1}", error.Code, error.Message);
    }
}
IdempotenceException
409
catch (IdempotenceException e)
{
    System.Console.WriteLine("Authorization error:");
    foreach (APIError error in e.Errors)
    {
        System.Console.WriteLine("- {0}: {1}", error.Code, error.Message);
    }
}
ReferenceException
404/409/410
catch (ReferenceException e)
{
    System.Console.WriteLine("Incorrect object reference:");
    foreach (APIError error ine.Errors)
    {
        System.Console.WriteLine("- {0}: {1}", error.Code, error.Message);
    }
}
DirectException
500/502/503
catch (DirectException e)
{
    System.Console.WriteLine("Error occurred at Direct or a downstream partner/acquirer:");
    foreach (APIError error ine.Errors)
    {
        System.Console.WriteLine("- {0}: {1}", error.Code, error.Message);
    }
}
ApiException /
Any other codes
catch (ApiException e)
{
    System.Console.WriteLine("Platform error: ");
    foreach (APIError error ine.Errors)
    {
        System.Console.WriteLine("- {0}: {1}", error.Code, error.Message);
    }
}
CommunicationException / 
300 codes without a body or non-JSON response
catch (CommunicationException e)
{
    System.Console.WriteLine("Communication error: {0}", e.InnerException.ToString());
}

HTTP status codes 

All our exceptions are linked to one or more HTTP status codes, indicating the root cause for many possible errors.

Status code Description Exception type
200

Successful

Our platform processed your request correctly

-
201

Created

Our platform processed your request correctly and created a new resource. We return the URI of this resource in the Location header of the response

-
204

No content

Our platform processed your request correctly

-
Various
CreatePaymentResult is in the response

Payment Rejected

Either our platform or one of our downstream partners/acquirers rejected your request

DeclinedPaymentException

Various
PayoutResult is present in the response

Payout Rejected

Your request was rejected either by the Direct platform or one of our downstream partners/acquirers

DeclinedPayoutException

Various
RefundsResponse is in the response

Refund Rejected

Either our platform or one of our downstream partners/acquirers rejected your request

DeclinedRefundException
400

Bad Request

Your request contains errors, thus our platform cannot process it

ValidationException
403

Not Authorised

You are trying to do something that is not allowed or that you are not authorised to do

AuthorizationException
404

Not Found

The object you were trying to access could not be found on the server

ReferenceException
409

Conflict
Your idempotent request resulted in a conflict because of either: 

  • The first request has not finished yet
  • Your request resulted in a conflict. Either you submitted a duplicate request, or you are trying to create something with a duplicate key

IdempotenceException
ReferenceException

410

Gone

The object that you are trying to reach has been removed.

ReferenceException
500

Internal Server Error

An error occurred on our platform

DirectException
502 Bad Gateway

Our platform was unable to process a message from a downstream partner/acquirer
DirectException
503 Service Unavailable

The service that you are trying to reach is temporarily unavailable. Please try again later
DirectException
Other Unexpected error

An unexpected error has occurred
ApiException

5. Use additional features

The SDK has a lot more to offer. Have a look at the following features, as they will help you build the perfect solution.

Get available payment methods

Before you initiate the actual payment process, you send a GetPaymentProducts request to our platform. The response contains a list of available payment methods in your PSPID. Depending on your customers’ preferences, you can offer a selection on our Hosted Checkout Page or on your own webshop environment using subsequent CreatePayment requests.


// Prepare the request to get all active payment methods in your PSPID
var queryParams = new GetPaymentProductsParams
{
    CountryCode = "BE",
    CurrencyCode = "EUR"
};

// Send the request and get the response
GetPaymentProductsResponse response = await client
    .WithNewMerchant("YourPSPID")
    .Products
    .GetPaymentProducts(queryParams);

Send idempotent requests

One of the main REST API features is its ability to detect and prevent sending requests (i.e. payment requests) accidentally twice. The SDK makes it very easy for you to ensure that you send only unique – idempotent – requests to our platform.

Use the additional argument CallContext with its property IdempotenceKey to a CreatePayment request. The SDK will send an -GCS-Idempotence-Key header with the idempotence key as its value.

If you send requests this way to our platform, we will check the following

  • If you send subsequent request with the same idempotence key, the response contains an X-GCS-Idempotence-Request-Timestamp header. The SDK will set the IdempotenceRequestTimestamp property of the CallContext argument
  • If the first request is not finished yet, the RESTful Server API returns a  409 status code. Then the SDK throws an IdempotenceException with the original idempotence key and the idempotence request timestamp

String idempotenceKey = "YourKeyForThePayment"
CallContext context = new CallContext().WithIdempotenceKey(idempotenceKey);
try
{
    CreatePaymentResponse response = await client
        .WithNewMerchant("YourPSPID")
        .Payments
        .CreatePayment(body);
}
catch (IdempotenceException e)
{
    // A request with the same idempotenceKey is still in progress, try again after a short pause
    // e.IdempotenceRequestTimestamp contains the value of the
    // X-GCS-Idempotence-Request-Timestamp header
}
finally
{
    long? idempotenceRequestTimestamp = context.IdempotenceRequestTimestamp;
    // idempotenceRequestTimestamp contains the value of the
    // X-GCS-Idempotence-Request-Timestamp header
    // if idempotenceRequestTimestamp is not null this was not the first request
}
If an idempotence key is sent for a call that does not support idempotence, the RESTful Server API will ignore the key and treat the request as a first request.

Use logging

The SDK supports logging of requests, responses, and exceptions. These can be helpful for troubleshooting or tracing individual steps in the payment flow.
The SDK offers two implementations of the logging feature:

  • System.Console (SystemConsoleCommunicatorLogger)
  • NLog (NLogCommunicatorLogger)

You can enable/disable the logging by calling the EnableLogging/DisableLogging methods respectively on an IClient instance:


client = Factory.CreateClient("yourAPIkey", "yourAPIsecret", apiEndpoint, "YourCompanyName");
CommunicatorLogger logger = new NLogLogger(Logger.GetCurrentClassLogger(), Level.Info); 
client.EnableLogging(logger);
//... Do some calls
client.DisableLogging();

The SDK obfuscates sensitive data in the logger

Connection pooling

You can manage your network resources by limiting the number of possible connections the SDK creates and maintains. IClient instances created as discussed in the Initialise SDK chapter will have their own connection pool. IClient instances created with the same ICommunicator object share a connection pool.

If you use multiple IClient instances to share a single connection pool, make sure to follow these steps:

  1. Create a shared ICommunicator. You can use the Factory class for this
  2. Create IClient instances with that ICommunicator

ICommunicator communicator = Factory.CreateCommunicator("apiKeyId", "apiKey", apiEndpoint, "YourCompanyName"); 

// create one or more clients using the shared communicator 
IClient client = Factory.CreateClient(communicator); 

If you do not need the ICommunicator anymore, we recommend closing it. Keep the following in mind:

  • As ICommunicator and IClient implement System.IDisposable, you can use them in using statements
  • Use method CloseExpiredConnections on either the ICommunicator instance or IClient instances to evict expired HTTP connections
If you close/destroy any IClient instance sharing the same ICommunicator or use it in a using statement, the ICommunicator instance will be destroyed/closed as well. Destroying/closing the ICommunicator will destroy/close all IClient instances that share it

Customise communication

IClient instances use an ICommunicator instance to communicate with our platform. ICommunicator implementations transform a request object to a HTTP request and HTTP response to a response object.

The SDK provides a default implementation of ICommunicator, but you can provide your own implementation of this interface to match to your individual needs:


ICommunicator communicator = new YourCommunicator(); 
IClient client = Factory.CreateClient(communicator); 

Providing your own implementation is not necessary for most cases. The functionality of the default Communicator is built on classes  Authenticater, Connection,  Marshaller and  MetaDataProvider. The implementation of these classes can easily be extended or replaced to fit your needs. Marshaller  is used to marshal/unmarshal request and response objects to and from JSON, which you should not change. The other modules that are needed to communicate with our platform are

  • The RESTful Server API endpoint URI
  • A Connection for one or more HTTP connections to our server
  • An Authenticator to sign your requests
  • A MetaDataProvider constructing the header with your server’s meta data

For your convenience, an  ICommunicator builder is provided to easily replace one or more of these modules. For example, to instantiate an  IClient  that uses your own implementation of  Connection, you can use the following code snippet:


Connection connection = new YourConnection(); 
ICommunicator communicator = Factory.createCommunicator(dictionary, "apiKeyId", "apiKey") 
    .WithConnection(connection) 
    .Build(); 
Client client = Factory.CreateClient(communicator); 

Webhooks

The part of the SDK that handles the webhooks support is called the webhooks helper. It transparently handles both validation of signatures against the event bodies sent by the webhooks system (including finding the secret key for key IDs - not to be confused with the API Key and API Secret), and unmarshalling of these bodies to objects. This allows you to focus on the essentials, without going through all the additional information and extracting the desired ones by yourself. To learn more about webhooks, read our dedicated guide. 

Provide secret keys

Configure the "WebhooksKey" / "WebhooksKeySecret" and your server webhooks endpoints in the Merchant Portal:


String keyId = "WebhooksKey";
String secretKey = "WebhooksKeySecret";

Use InMemorySecretKeyStore.Instance.StoreSecretKey(keyId, secretKey) to store a secret key for a key ID.

You can add or remove keys using the following functions:

  • InMemorySecretKeyStore.Instance.GetSecretKey(keyId)
  • InMemorySecretKeyStore.Instance.RemoveSecretKey(keyId) to remove the stored secret key for a key ID
  • InMemorySecretKeyStore.Instance.Clear() to remove all stored secret keys

If you require more advanced storage, e.g. using a database or file system, we recommend writing your own implementation. 

Initialise webhooks helper

Using an implementation of com.onlinepayments.webhooks.SecretKeyStore, create an instance of  com.onlinepayments.webhooks.WebhooksHelper:


WebhooksHelper helper = Webhooks.CreateHelper(InMemorySecretKeyStore.Instance);

Use webhook helper

To process events received by a webhook, first call the unmarshal method of the WebhooksHelper object. It takes the following arguments: 

  • The body, as a string. This should be the raw body as received from the webhooks system

    String bodyOfRequest = "JSON_Body_Of_The_Request";

  • A list of request headers as received from the webhooks system. Below you will find an example of creating a list of request headers. It should contain two headers – for keyId and for signature:
    
    //   Create RequestHeader for keyId         
    RequestHeader requestHeaderKeyId = new RequestHeader("X-GCS-KeyId", keyId);
    
    //   Create RequestHeader for signature and validate it
    byte[] keyAsBytes = System.Text.UTF8Encoding.UTF8.GetBytes(secretKey);
    byte[] unencodedResult = System.Text.UTF8Encoding.UTF8.GetBytes(bodyOfRequest);
    
    HMACSHA256 myhmacsha256 = new HMACSHA256(keyAsBytes);
    
    var signature = myhmacsha256.ComputeHash(unencodedResult);
    
    RequestHeader requestHeaderSignature = new RequestHeader("X-GCS-Signature", 
    Convert.ToBase64String(signature));
    
    //  Create a list of request headers
    List requestHeaders = new List();
    requestHeaders.Add(requestHeaderSignature);
    


  • Now you can call a webhook helper to unmarshal incoming events which allow you to process data in your application:
    
    try
    {
    	helper.Unmarshal(bodyOfRequest, requestHeaders);
    }
    catch (SignatureValidationException ex)
    {
        // our code to handle errors
    }