adyen-magento2 icon indicating copy to clipboard operation
adyen-magento2 copied to clipboard

[ECP-9711] 😍 Mutation adyenPaymentDetails - Support exception message

Open dimitriBouteille opened this issue 6 months ago • 1 comments

Description

As discussed in ticket https://github.com/Adyen/adyen-magento2/issues/2056, the idea is to offer the developer to return custom exceptions in the graphQl adyenPaymentDetails query. The objective is to be able to manage more easily the different cases (Refused, Canceled,...) in headless projects.

Today the mutation returns a generic error, which can pose problems for headless projects, it is impossible to manage the different cases (Refused, Canceled,...)

This PR allows to manage more finely the different cases by adding a few lines of code via a plugin or a preference on the handleException function.

Here is an example of a plugin that could be set up by a developer:


class GetAdyenPaymentDetailsPlugin
{
    /**
     * @param \Adyen\Payment\Model\Resolver\GetAdyenPaymentDetails $subject
     * @param \Exception $cause
     * @param \Magento\Sales\Model\Order $order
     * @param \Magento\Quote\Api\Data\CartInterface $cart
     * @param \Magento\Framework\GraphQl\Config\Element\Field $field
     * @param \Magento\Framework\GraphQl\Query\Resolver\ContextInterface $context
     * @param \Magento\Framework\GraphQl\Schema\Type\ResolveInfo $info
     * @return void
     * @throws \Adyen\Payment\Exception\GraphQlAdyenException
     */
    public function aroundHandleException(
        \Adyen\Payment\Model\Resolver\GetAdyenPaymentDetails $subject,
        \Exception $cause,
        Order $order,
        CartInterface $cart,
        Field $field,
        ContextInterface $context,
        ResolveInfo $info
    ): void {
        if ($cause instanceof AdyenPaymentDetailsException) {
            throw match ($cause->getErrorType()) {
                PaymentDetailsError::Refused => new GraphQlAdyenException(__('Payment Refused'), null, 000),
                PaymentDetailsError::Canceled => new GraphQlAdyenException(__('Payment canceled'), null, 000),
                default => new GraphQlAdyenException(__('An unknown error has occurred'), null, 000),
            };
        }

        // In the future, use the message and the code passed by the exception. Since currently the message and code are not
        // being passed, use this generic message.
        throw new GraphQlAdyenException(__('An unknown error has occurred'), null, 000);
    }
}

Tested scenarios

Fixes https://github.com/Adyen/adyen-magento2/issues/2056

dimitriBouteille avatar May 22 '25 10:05 dimitriBouteille

Hello @dimitriBouteille,

Thank you for your contribution. Your agility to provide a solution is commendable! Let us review this PR and get back to you as soon as possible.

Best Regards, Can

candemiralp avatar May 22 '25 12:05 candemiralp

Hey @dimitriBouteille,

Hope you are doing great!

Thank you for your contribution, the effort here is really appreciated, and we agree with the problem you’re solving - today the adyenPaymentDetails mutation only returns a generic error, which makes it difficult for headless storefronts to distinguish between expected payment outcomes (Refused, Cancelled) and actual system issues.

That said, introducing new exception messages at this point would be a Breaking Change for integrators who may already rely on the current generic error format. To avoid unexpected regressions, we’ll only be able to cater this request in a slightly modified form as part of the next major release of the plugin.

Our planned approach is:

Instead of throwing different exception messages for refusal/cancellation or any other scenarios, we will handle the resultCode explicitly. We did some similar changes for the /payments request recently in this PR - https://github.com/Adyen/adyen-magento2/pull/3092

Shopper-facing messages will remain consistent, while the detailed resultCode will be logged in a more readable and self explanatory format.

This way we improve observability and developer experience following magento's best practices.

Again, thank you for raising this and putting effort into a PR, it’s very valuable input and will influence the new major version design.

Regards Khushboo

khushboo-singhvi avatar Oct 28 '25 14:10 khushboo-singhvi

Hi @khushboo-singhvi Thanks for your feedback.

The fix made in #3092 is available in v10 or v11 (so the next major version) ?

I don't understand the PR, if the payment failed, which response is returned by the graphQL request adyenPaymentDetails ? Can you share an example

Dimitri

dimitriBouteille avatar Oct 29 '25 11:10 dimitriBouteille

Hey @dimitriBouteille,

Thanks for your follow-up.

To clarify:

  • The fix in #3092 was more of an example implementation to align with Magento’s best practices, i.e. avoiding throwing ValidatorException / LocalizedException and instead returning a ResultInterface for validation outcomes that the frontend can handle gracefully.

  • That change was safe and went into v10 since it didn’t introduce any breaking changes.

For the adyenPaymentDetails mutation specifically, handling the different resultCode values (rather than always returning a generic error) would alter the response surface and thus introduce a breaking change. For this reason, we’re planning to ship it as part of the next major version (v11).

Appreciate your understanding here. We’ll keep you updated once this is implemented and available.

Regards, Khushboo

khushboo-singhvi avatar Oct 30 '25 13:10 khushboo-singhvi

Hi @khushboo-singhvi Thanks for the details, everything is good👌

dimitriBouteille avatar Nov 02 '25 00:11 dimitriBouteille