DEV Community

Cover image for The Migration Guide to Upgrading to Adyen .NET Library 10.0.0
Kwok He Chu for Adyen

Posted on • Updated on • Originally published at adyen.Medium

The Migration Guide to Upgrading to Adyen .NET Library 10.0.0

This migration guide is intended for developers who are planning to upgrade to .NET Adyen Library version 10.0.0. We'll cover new features and breaking changes from 9.x.x to ensure your upgrade goes as smoothly as possible.

The new version allows for an easy integration of new products and features as they become available on the Adyen platform, and it introduces naming conventions that are consistent across other libraries and our Adyen endpoints.

The goal is to make the library comprehensive (all API versions are updated to the latest release, there is support for Adyen for Platforms and Embedded Financial Services), fast (providing built-in methods for JSON processing) and easy (added adapter classes mapping each payment method).

TL;DR: In this migration guide, we'll go over what has changed and why we've made these changes to ensure that developers can migrate as smoothly as possible.

Coding Conventions

The following changes have been implemented to better align with Microsoft's C# Coding Conventions.

1. Interface support on service-level
It's common practice to use names with an I-prefix to indicate that they are interfaces. This helps to distinguish interfaces from classes and other types, and makes it clear that the type represents an interface. For example: IPaymentsService.cs indicates that the type represents an interface for the Payments API. We've introduced these interfaces in our service classes. Developers can make use of these interfaces, which expose only the set of public methods required for integration purposes.

2. Service classes
It's also common practice to suffix classes with -Service on service-level. This helps developers distinguish service classes from other classes such as requests, responses, other models and types. For example: Recurring is now renamed to RecurringService, which now inherits from the IRecurringService interface.

3. Asynchronous methods
To handle asynchronous requests, we've added the -Async()-suffix to all asynchronous methods. On top of that, we allow developers to pass on cancellation tokens to these methods. This enables cooperative cancellation between threads, thread pool work items, or Task objects, freeing up remaining resources if a request is canceled manually or unexpectedly.

4. HttpClient support
System.Net.Http.HttpClient has replaced System.Net.HttpWebRequest to conform to Microsoft's best practices. The System.Net.Http.HttpClient class sends and receives HTTP requests and handles these responses from a resource that can be identified by a URI. An HttpClient instance consists of a collection of settings that are applied to all requests executed by that instance. Additionally, each instance operates its own connection pool, which isolates its requests from others. Starting in .NET Core 2.1, the The underlying SocketsHttpHandler class provides the implementation, making behavior consistent across all platforms when using the HttpClient.

When creating the AdyenClient, developers can now inject their own HttpClient on the constructor level. If a custom HttpClient is not provided, a default one will be provided by the HttpClientFactory. We have also marked username and password authentication as obsolete to ensure best practices when working with our APIs. Instead, it's recommended to pass the API-Key as part of the Config class in the constructor. Here's what the initial client configuration looks like when working with our APIs in .NET:

Example of using direct object instantiation in C#:

var httpClient = new HttpClient(); // Reuse the HttpClient, see below why.

var adyenClient = new Adyen.Client(
   new Config()
   {
      XApiKey = "ADYEN_API_KEY",
      HmacKey = "ADYEN_HMAC_KEY",
      MerchantAccount = "ADYEN_MERCHANT_ACCOUNT",
      Environment = Environment.Test
 },
   httpClient // Do not instantiate a new one for every request.
);

Adyen.Service.Checkout.IPaymentsService service = new Adyen.Service.Checkout.PaymentsService(adyenClient);
Enter fullscreen mode Exit fullscreen mode

Note: Please keep in mind that it's best practice to reuse the HttpClient. To prevent socket exhaustion, the HttpClient is intended to be instantiated once per application, rather than per-use. We highly recommend using the HttpClientFactory for this reason and have the factory provide the client. You can read more details here on StackOverflow. We recommend the following for Dependency Injection:

Example instantiation using Dependency Injection in ASP.NET Core:

string httpClientName = "YourCustomHttpClientName";

// Register the Adyen.Client with the HttpClientFactory in ASP.NET Core.

services.AddSingleton(
   new Adyen.Client(
      new Config()
      {
         XApiKey = "ADYEN_API_KEY",,
         HmacKey = "ADYEN_HMAC_KEY",
         MerchantAccount = "ADYEN_MERCHANT_ACCOUNT",
         Environment = Environment.Test
      }, 
      provider.GetRequiredService<IHttpClientFactory>(),
      httpClientName
   )
);

// Add the named HttpClient.
services.AddHttpClient(httpClientName, httpClient =>
{
    /// Customize your HttpClient here.
    //using Microsoft.Net.Http.Headers;
    //httpClient.DefaultRequestHeaders.Add("accept", "application/json");
    //httpClient.DefaultRequestHeaders.Add("user-agent", "YourUserAgent");
});

services.AddSingleton<Adyen.Service.Checkout.IPaymentsService, Adyen.Service.Checkout.PaymentsService>();
Enter fullscreen mode Exit fullscreen mode

5. Models generation from OpenAPI specifications
Another significant change is the adoption of OpenAPI-driven code generation.

The models are now generated from the latest OpenAPI specifications. C# classes that map the request and response payloads are now generated using OpenAPI Generator, ensuring that the code complies with the contract, and avoiding errors and inconsistencies. This also ensures that other Ayden libraries will have consistent naming amongst them.

To improve the maintainability of the library easier for the long run, we've removed several properties that are no longer there and reduced boilerplate code. You can find them in our release notes.

With the automation project, our team at Adyen can now deliver faster to our developers. They can use the latest endpoints when including the latest version of the library in their application.

Feel free to take a look at the following model and service-generation. The following new services and respective endpoints have been generated using the OpenAPI specifications:

New endpoints support

Deprecated

Hosted Payment Pages (HPP) has been deprecated and are no longer available. The classic Hosted Payment Pages integration has reached end-of-life and we are no longer processing transactions through HPP.

Quick Cheat Sheet

Most of the services, some examples "Balance", "Payout" or "BinLookup" have been renamed to "BalanceService", "PayoutService" and "BinLookupService" respectively. Because they're quite straightforward to find when applying the above mentioned naming conventions, they're not listed in the table below.

We've highlighted a couple of commonly used services, models and methods that have been moved, and are less trivial to find.

// Before (.NET 9.x.x)
Checkout.cs

// After (.NET 10.x.x) - Renamed
Adyen.Services.Checkout.PaymentsService.cs  // Service
Adyen.Services.Checkout.IPaymentsService.cs // Interface
Enter fullscreen mode Exit fullscreen mode
// Before (.NET 9.x.x)
Checkout.PaymentLinks() // Method

// After (.NET 10.x.x) - This has been moved to its own service
Adyen.Services.Checkout.PaymentLinksService.cs  // Service
Adyen.Services.Checkout.IPaymentLinksService.cs // Interface
Enter fullscreen mode Exit fullscreen mode
// Before (.NET 9.x.x)
Recurring.cs

// After (.NET 10.x.x) - Renamed
Adyen.Services.RecurringService.cs  // Service
Adyen.Services.IRecurringService.cs // Interface
Enter fullscreen mode Exit fullscreen mode
// Before (.NET 9.x.x)
Checkout.PaymentsAsync() method

// After (.NET 10.x.x)
// Adyen.Model.Checkout.PaymentRequest contains a PaymentMethod parameter.
// When making a payment, using the recurringDetailReference retrieved from tokenization, use: 
PaymentMethod = new CheckoutPaymentMethod(new StoredPaymentMethodDetails(storedPaymentMethodId: recurringDetailReference));
Enter fullscreen mode Exit fullscreen mode
// Before (.NET 9.x.x)
Adyen.Model.Checkout.Details.IPaymentMethodDetails

// After (.NET 10.x.x) - Have a look at our .NET checkout-example-advanced flow 
// on github.com/adyen-examples to see how you can pass this as part of its request.
Adyen.Model.Checkout.CheckoutPaymentMethod
Enter fullscreen mode Exit fullscreen mode
// Before (.NET 9.x.x)
namespace Adyen.Model.Enum.Environment

// After (.NET 10.x.x) - Moved to another namespace
namespace Adyen.Model.Environment
Enter fullscreen mode Exit fullscreen mode
// Before (.NET 9.x.x)
Adyen.Model.Checkout.PaymentsDetailsRequest.cs

// After (.NET 10.x.x) - Renamed
// This will be correctly renamed to PaymentDetailsRequest in a later release
// A `PaymentDetailRequest` model should have an equivalent `PaymentDetailResponse` for consistency
Adyen.Model.Checkout.DetailsRequest.cs
Enter fullscreen mode Exit fullscreen mode
// Before (.NET 9.x.x)
new Adyen.Client(username, password, environment) // or
new Adyen.Client(xapikey, environment)

// After (.NET 10.x.x)
var httpClient = new HttpClient(); // Reuse the HttpClient, we explained the why above.

var client = new Client(
   new Config()
   {
      XApiKey = "ADYEN_API_KEY",
      HmacKey = "ADYEN_HMAC_KEY",
      MerchantAccount = "ADYEN_MERCHANT_ACCOUNT",
      Environment = Environment.Test
 },
   httpClient // Do not instantiate a new one for every request.
);

var adyenClient = new Adyen.Client(config);
Enter fullscreen mode Exit fullscreen mode
// Before (.NET 9.x.x)
Adyen.Service.PosPaymentLocalApi
Adyen.Service.PosPaymentCloudApi

// After (.NET 10.x.x) - Using POS with HttpClient:
var httpClient = new HttpClient(
   // See Adyen.HttpClient.HttpClientExtension.cs to configure the certificate.
   HttpClientExtensions.ConfigureHttpMessageHandler(config)
); 

// You can also  optionally configure your HttpClient timeouts here.
// httpClient.Timeout = …;

IPosPaymentLocalApi = new PosPaymentLocalApi(new Client(config, httpClient)); // or
IPosPaymentCloudApi = new PosPaymentCloudApi(new Client(config, httpClient));
Enter fullscreen mode Exit fullscreen mode
// After (.NET 10.x.x) - Setting Local Terminal API endpoint
new Config() {
   // ...
   LocalTerminalApiEndpoint = "https://192.168.1.10:8443/nexo"
   // ...
}
Enter fullscreen mode Exit fullscreen mode

If you have an existing integration implementing one of the Checkout (sessions / payments endpoints), Subscription (tokenization), Pay by Link or Gift Card use cases, you can have a look at the this pull request to see a detailed list of all changes necessary to migrate to v10.0.0.

Feel free to open an issue on GitHub if you're encountering any problems or ping us on Twitter (@AdyenDevs).

Happy migration! 🛠️

Top comments (0)