Skip to content

1. OpenAPI generator upgrade: add templates and shared classes - #897

Draft
gcatanese wants to merge 20 commits into
mainfrom
openapi-generator-upgrade
Draft

gcatanese wants to merge 20 commits into
mainfrom
openapi-generator-upgrade

Conversation

@gcatanese

Copy link
Copy Markdown
Contributor

First iteration of the OpenAPI Generator upgrade:

  • add and customise Mustache templates
  • add code shared by different APIs (Configuration, BaseService, etc...)
  • generate BinlookUp services and models
  • add tests for shared code and BinlookUp to verify main use cases: initialise objects, send requests, add custom headers, throw exceptions upon 4xx/5xx errors

At the moment the new code co-exist with the old version, therefore there is a bit of mix of approaches and code, I also had to disable few tests (to verify/refactor later). This will improve as we progress this migration.

@gcatanese gcatanese changed the title Openapi generator upgrade 1. OpenAPI generator upgrade: add templates and shared classes Mar 11, 2026
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request represents the first iteration of upgrading the OpenAPI Generator. It introduces new code alongside the old version, which will be refined in subsequent iterations. The changes include adding and customizing Mustache templates, incorporating shared code, generating BinlookUp services and models, and adding tests to verify core functionalities.

Highlights

  • OpenAPI Generator Upgrade: This PR initiates the upgrade of the OpenAPI Generator, incorporating customized Mustache templates and shared code for different APIs.
  • Service and Model Generation: The PR generates BinlookUp services and models, enhancing the library's capabilities.
  • Testing and Verification: Tests have been added to verify the main use cases, including object initialization, request sending, custom header addition, and exception handling for 4xx/5xx errors.
  • Dependency Updates: The composer.json file has been updated to reflect changes in PHP version requirements and package dependencies.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • composer.json
    • Updated PHP version requirement to ^8.1.
    • Replaced dms/phpunit-arraysubset-asserts, php-coveralls/php-coveralls with guzzlehttp/guzzle and guzzlehttp/psr7.
    • Updated phpunit/phpunit and friendsofphp/php-cs-fixer dev dependencies.
  • src/Adyen/BaseService.php
    • Added BaseService class to serve as a parent class for API services, handling API key and environment configurations.
  • src/Adyen/Configuration.php
    • Added Configuration class to manage API keys, environment settings, and other configurations.
  • src/Adyen/Exception/AdyenException.php
    • Added AdyenException class for handling API exceptions, including response headers and bodies.
  • src/Adyen/HeaderSelector.php
    • Added HeaderSelector class to select appropriate Accept and Content-Type headers for requests.
  • src/Adyen/Model/BinLookup/Amount.php
    • Modified Amount model to align with updated OpenAPI generator standards.
  • src/Adyen/Model/BinLookup/BinDetail.php
    • Modified BinDetail model to align with updated OpenAPI generator standards.
  • src/Adyen/Model/BinLookup/CardBin.php
    • Modified CardBin model to align with updated OpenAPI generator standards.
  • src/Adyen/Model/BinLookup/CostEstimateAssumptions.php
    • Modified CostEstimateAssumptions model to align with updated OpenAPI generator standards.
  • src/Adyen/Model/BinLookup/CostEstimateRequest.php
    • Modified CostEstimateRequest model to align with updated OpenAPI generator standards.
  • src/Adyen/Model/BinLookup/CostEstimateResponse.php
    • Modified CostEstimateResponse model to align with updated OpenAPI generator standards.
  • src/Adyen/Model/BinLookup/DSPublicKeyDetail.php
    • Modified DSPublicKeyDetail model to align with updated OpenAPI generator standards.
  • src/Adyen/Model/BinLookup/ModelInterface.php
    • Modified ModelInterface to align with updated OpenAPI generator standards.
  • src/Adyen/Model/BinLookup/ObjectSerializer.php
    • Modified ObjectSerializer to align with updated OpenAPI generator standards.
  • src/Adyen/Model/BinLookup/Recurring.php
    • Modified Recurring model to align with updated OpenAPI generator standards.
  • src/Adyen/Model/BinLookup/ServiceError.php
    • Modified ServiceError model to align with updated OpenAPI generator standards.
  • src/Adyen/Model/BinLookup/ThreeDS2CardRangeDetail.php
    • Modified ThreeDS2CardRangeDetail model to align with updated OpenAPI generator standards.
  • src/Adyen/Model/BinLookup/ThreeDSAvailabilityRequest.php
    • Modified ThreeDSAvailabilityRequest model to align with updated OpenAPI generator standards.
  • src/Adyen/Model/BinLookup/ThreeDSAvailabilityResponse.php
    • Modified ThreeDSAvailabilityResponse model to align with updated OpenAPI generator standards.
  • src/Adyen/RequestOptions.php
    • Added RequestOptions class to support adding custom headers to API requests.
  • src/Adyen/Service/BinLookup/BinLookupApi.php
    • Added BinLookupApi class to encapsulate BinLookup API calls.
  • src/Adyen/Service/BinLookupApi.php
    • Modified BinLookupApi to align with updated OpenAPI generator standards.
  • templates-v7/ModelInterface.mustache
    • Added templates-v7/ModelInterface.mustache.
  • templates-v7/ObjectSerializer.mustache
    • Added templates-v7/ObjectSerializer.mustache.
  • templates-v7/api-single.mustache
    • Added templates-v7/api-single.mustache.
  • templates-v7/api.mustache
    • Added templates-v7/api.mustache.
  • templates-v7/api_parameters.mustache
    • Added templates-v7/api_parameters.mustache.
  • templates-v7/config.yaml
    • Added templates-v7/config.yaml.
  • templates-v7/left_bracket.mustache
    • Added templates-v7/left_bracket.mustache.
  • templates/ModelInterface.mustache
    • Renamed templates/ModelInterface.mustache to templates-old/ModelInterface.mustache.
  • templates/ObjectSerializer.mustache
    • Renamed templates/ObjectSerializer.mustache to templates-old/ObjectSerializer.mustache.
  • templates/api-single.mustache
    • Renamed templates/api-single.mustache to templates-old/api-single.mustache.
  • templates/api.mustache
    • Renamed templates/api.mustache to templates-old/api.mustache.
  • templates/api_parameters.mustache
    • Renamed templates/api_parameters.mustache to templates-old/api_parameters.mustache.
  • templates/config.yaml
    • Renamed templates/config.yaml to templates-old/config.yaml.
  • templates/left_bracket.mustache
    • Renamed templates/left_bracket.mustache to templates-old/left_bracket.mustache.
  • templates/model.mustache
    • Renamed templates/model.mustache to templates-old/model.mustache.
  • templates/model_generic.mustache
    • Renamed templates/model_generic.mustache to templates-old/model_generic.mustache.
  • templates/partial_header.mustache
    • Renamed templates/partial_header.mustache to templates-old/partial_header.mustache.
  • templates/right_bracket.mustache
    • Renamed templates/right_bracket.mustache to templates-old/right_bracket.mustache.
Activity
  • Added and customized Mustache templates.
  • Added code shared by different APIs (Configuration, BaseService, etc...).
  • Generated BinlookUp services and models.
  • Added tests for shared code and BinlookUp to verify main use cases.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a significant upgrade to the OpenAPI generator, adding new shared classes like Configuration and BaseService, and generating the BinLookup API client. The changes are extensive and bring in modern PHP features. My review focuses on improving the new shared components and fixing some bugs in the generated code. I've identified a critical issue in the error handling within the new BinLookupApi client, along with some design concerns in the Configuration class and other bugs. The feedback provided aims to enhance the robustness, maintainability, and correctness of the new code.

Note: Security Review did not run due to the size of the PR.

Comment thread src/Adyen/Service/BinLookup/BinLookupApi.php
Comment thread src/Adyen/Configuration.php Outdated
Comment thread src/Adyen/Service/BinLookup/BinLookupApi.php Outdated
Comment thread src/Adyen/BaseService.php Outdated
Comment thread src/Adyen/Configuration.php Outdated
Comment thread src/Adyen/Configuration.php Outdated
@sonarqubecloud

Copy link
Copy Markdown

@gcatanese
gcatanese marked this pull request as ready for review March 12, 2026 14:32
@gcatanese
gcatanese requested review from a team as code owners March 12, 2026 14:32
@gcatanese
gcatanese marked this pull request as draft June 29, 2026 11:00
@ashwaniarya-adyen ashwaniarya-adyen self-assigned this Sep 8, 2026
Comment thread src/Adyen/BaseService.php Outdated
*/
public function __construct(Configuration $configuration)
{
if (!$configuration->getAdyenApiKey()) {

@ashwaniarya-adyen ashwaniarya-adyen Sep 8, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we making this change intentional ?
Because in the older version, we have
elseif ($service->requiresApiKey()) { $msg = "Please provide a valid Checkout API Key"; throw new AdyenException($msg);
in client where we depend on the flag passed by service to determine wether we need to validate API key

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting. I don't think we should allow the option to skip API key validation. All our APIs are behind authentication.
I notice though that we don't have support for Basic Authentication, which is a legacy authentication but still relevant (according to the Docs).
We should introduce it, either here or create a new ticket for later.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added support to handle both API Key and Basic Authentication here

Added test cases to test here

Comment thread templates-v7/model_generic.mustache Outdated
}
{{/isNullable}}
{{^isNullable}}
if (is_null(${{name}})) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this stricter setter behavior an intentional breaking SDK change? Previously, setters accepted null, and the SDK did not automatically call valid() before sending a request

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. In theory we shouldn't accept null unless the attribute is nullable, but this is a significant breaking change (as you point out 👍). The other important aspect is that we want to avoid validation in the SDKs (when possible) so we avoid drifting from the API (for example the API changes a property to be nullable but the merchants don't upgrade the SDK version).

This is the same reason why we don't call valid() before sending a request.

To summarise:

  • remove validation of nullability (no longer throw the exception): we rely on the validation of the API
  • valid: consider if it is better to remove or make a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed all the validation from SDK

Comment thread composer.json
strategy:
matrix:
php-version: [ '7.3', '8.2', '8.4', '8.5' ]
php-version: [ '8.1', '8.2', '8.4' ]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adds PHP 8.1 to the test matrix because it is the minimum PHP version declared by this branch.

Comment thread src/Adyen/Configuration.php
Comment thread src/Adyen/Service/BinLookup/BinLookupApi.php
Comment thread templates-v7/api.mustache
$headers
);

$operationHost = $this->config->getHost() ?: $this->baseURL;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When no custom host was configured, getHost() returned an empty value and the generated request contains only a relative path. Guzzle cannot send this because it has no Adyen server address. Fall back to the BinLookup base URL to build a complete request URL while preserving any merchant-provided custom host.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to revise this since custom hosts are not a supported merchant feature. API URLs are defined in createBaseUrl, and they support:

  • test and live host
  • for payments only we support a merchant prefix i.e. https://abcdef-pal-live.adyenpayments.com

We should maybe cleanup the code to avoid even providing a custom host, to be investigated

@ashwaniarya-adyen ashwaniarya-adyen Sep 14, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Support for custom host removed here
BinkLookAPI - Here

Comment thread templates-v7/api.mustache Outdated
$operationHost = Configuration::getHostString($hostSettings, $hostIndex, $variables);
{{/servers.0}}
{{^servers.0}}
$operationHost = $this->config->getHost() ?: $this->baseURL;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comment about custom host

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Support for custom host removed here

$headers
);

$operationHost = $this->config->getHost() ?: $this->baseURL;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comment about custom host

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BinkLookAPI - Here

Comment thread src/Adyen/Service/BinLookup/BinLookupApi.php Outdated
Comment thread src/Adyen/Service/BinLookup/BinLookupApi.php Outdated
Comment thread templates-v7/api.mustache Outdated
Comment thread templates-v7/api.mustache Outdated
Comment thread templates-v7/api.mustache
Comment thread templates-v7/api.mustache
Comment thread src/Adyen/Model/BinLookup/Amount.php Outdated
if ($this->container['currency'] === null) {
$invalidProperties[] = "'currency' can't be null";
}
if ($this->container['currency'] !== null && mb_strlen($this->container['currency']) > 3) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A required property can still be null while a model is being validated. The validation method adds the correct “can’t be null” error but continues to the length checks. Calling mb_strlen(null) is deprecated in PHP 8.1+, so check that the value is not null before checking its length. Here

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good work. The null guard is applied to maxLength/minLength, but the same issue appears in the template for pattern (preg_match(pattern, null), deprecated in PHP 8.1+) and maxItems/minItems (count(null), TypeError) when a required property is null.

Note that valid() and listInvalidProperties() are never called by the SDK itself, we should assess what's best:

  • remove them (code is clearer and cleaner)
  • leave them optional for merchants to use (to be mentioned in the README maybe)

If decide to go for option 2, we may need to revise all validations scenario, I suggest to create a new ticket for this step.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Validation Removed

Comment thread templates-v7/model_generic.mustache Outdated
{{/isEnum}}
{{#hasValidation}}
{{#maxLength}}
if ($this->container['{{name}}'] !== null && mb_strlen($this->container['{{name}}']) > {{maxLength}}) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comment about validation above

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Validation Removed

Comment thread templates-v7/model_generic.mustache Outdated
}
{{/maxLength}}
{{#minLength}}
if ($this->container['{{name}}'] !== null && mb_strlen($this->container['{{name}}']) < {{minLength}}) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comment about validation above

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Validation Removed

Comment thread src/Adyen/Model/BinLookup/ObjectSerializer.php
Comment thread templates-v7/ObjectSerializer.mustache
$this->assertEmpty($headers);
}

public function testRequestUsesBaseUrl()

@ashwaniarya-adyen ashwaniarya-adyen Sep 10, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a regression test for the missing-host case. It verifies that BinLookup creates a complete URL using its default base URL, rather than a relative endpoint path that Guzzle cannot send.

Comment thread tests/Unit/BinLookupTest.php Outdated
Comment thread src/Adyen/Service/BinLookup/BinLookupApi.php Outdated
* @throws \InvalidArgumentException
* @return \Adyen\Model\BinLookup\ThreeDSAvailabilityResponse
*/
public function get3dsAvailability(\Adyen\Model\BinLookup\ThreeDSAvailabilityRequest$threeDSAvailabilityRequest, ?\Adyen\RequestOptions $requestOptions = null): \Adyen\Model\BinLookup\ThreeDSAvailabilityResponse

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is an inconsistency across similar methods:

  • get3dsAvailability: main method, body required
  • get3dsAvailabilityWithHttpInfo: WithHttpInfo variant, body optional and nullable
  • get3dsAvailabilityRequest: request builder, body required and non-nullable

Methods could be aligned to define the body as required and non-nullable.

Unfortunately our specs don't mark the request body as required: true, so we cannot rely on the OpenAPI contract. We don't have a use case of a request with an empty body (for POST and PATCH), so we can assume here that we always need one.

@ashwaniarya-adyen ashwaniarya-adyen Sep 14, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

get3dsAvailability - Link
get3dsAvailabilityWithHttpInfo - Link
get3dsAvailabilityRequest - Link

Null is generated only when the parameter is not a body parameter. Therefore, body parameters remain required and non-nullable across all three generated methods.

@gcatanese gcatanese left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work @ashwaniarya-adyen, I left some comments, we need to iterate over few points, but overall it looks really good!

@sonarqubecloud

Copy link
Copy Markdown

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants