Adyen / adyen-magento2

Adyen Payment plugin for Magento2
MIT License
155 stars 211 forks source link

Payment method 'oxxo' does not work #2690

Closed MagicLegend closed 1 month ago

MagicLegend commented 2 months ago

Describe the bug It is not possible to pay with oxxo due to it making an invalid API request to /payments. The request it makes either:

To Reproduce Steps to reproduce the behavior:

  1. Enable oxxo as a payment method

  2. Try to pay with it

  3. It will refuse

  4. See error

  5. Enable oxxo as a payment method

  6. Try to pay with a test credit card (I use the 4111(..)111 visa card) but use DECLINED as the name so it refuses

  7. Switch to oxxo

  8. Try to pay, and make note that it tries to pay using the previous card information

Expected behavior A clear and concise description of what you expected to happen.

Magento version 2.4.4-p9

Plugin version 9.6.2

Screenshots If applicable, add screenshots to help explain your problem.

Additional context We have a headless Magento with a PWA on top, using the drop-in components. There are no customizations on the Adyen module. I have not tried it yet in a clean Magento instance, but I expect to run into similar issues.

Module v8 did not have this issue.

candemiralp commented 1 month ago

Hello @MagicLegend,

Thank you for raising this issue. However, we've successfully completed a test payment with OXXO on a clean installation.

Screenshot 2024-08-22 at 11 49 19

The error you are getting might be related to the frontend PWA implementation. paymentMethod field should be part of the state data and needs to be generated on the component. In addition to that, plugin's backend has no control over the state data. If you observe wrong/missing state data on your requests, please check the payload of /payment-information call on Magento from frontend to backend.

If the issue is persistent on your end, you can reach out to our support team via support@adyen.com.

I am closing this issue since the issue is not reproducible.

Best Regards, Can

MagicLegend commented 1 month ago

Hi Can,

Yep, I communicated with your colleague via email about the issue already. I'm not sure what's causing it, but I need a workaround for all payment methods to fix this issue in our PWA setup.

In case it helps anyone, I need to define extra arguments to override the default dataproviders in graphql/di.xml:

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\QuoteGraphQl\Model\Cart\Payment\AdditionalDataProviderPool">
        <arguments>
            <argument name="dataProviders" xsi:type="array">
                <item name="adyen_cc" xsi:type="object">YourVendor\AdyenPayments\Model\AdyenCCDataProvider</item>
                <item name="adyen_hpp" xsi:type="object">YourVendor\AdyenPayments\Model\AdyenHPPDataProvider</item>
                <item name="adyen_oxxo" xsi:type="object">YourVendor\AdyenPayments\Model\AdyenPMDataProvider</item> <!-- Note that this provider can be applied to all payment methods that use the same source provider -->
            </argument>
        </arguments>
    </type>
</config>

Which would be this generic provider that'd simply force-store the statedata:

<?php

namespace YourVendor\AdyenPayments\Model;

use Adyen\Payment\Helper\StateData;
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
use Magento\Quote\Model\MaskedQuoteIdToQuoteIdInterface;
use Magento\QuoteGraphQl\Model\Cart\Payment\AdditionalDataProviderInterface;
use Adyen\Payment\Model\Api\AdyenStateData;

/**
 * Format Adyen HPP input into value expected when setting payment method
 */
class AdyenPMDataProvider implements AdditionalDataProviderInterface
{
    /**
     * @var StateData
     */
    protected StateData $stateData;

    /**
     * @var MaskedQuoteIdToQuoteIdInterface
     */
    protected MaskedQuoteIdToQuoteIdInterface $maskedQuoteIdToQuoteId;

    /**
     * @var AdyenStateData
     */
    protected AdyenStateData $adyenStateData;

    public function __construct(
        StateData $stateData,
        MaskedQuoteIdToQuoteIdInterface $maskedQuoteIdToQuoteId,
        AdyenStateData $adyenStateData,
    ) {
        $this->stateData = $stateData;
        $this->maskedQuoteIdToQuoteId = $maskedQuoteIdToQuoteId;
        $this->adyenStateData = $adyenStateData;
    }

    /**
     * Format Adyen PM input (aka everything else) into value expected when setting payment method
     *
     * Overrides the default Adyen\Payment\Model\Cart\Payment\AdditionalDataProvider\AdyenPm provider.
     * Ensures the StateData gets saved to the database, so it can be used later. This is required in order to prevent the "Required object 'paymentMethod' is not provided." error
     *
     * @param array $args
     * @return array
     * @throws GraphQlInputException
     */
    public function getData(array $args): array
    {
        $code = $args['code'] ?? null;

        if (!isset($args[$code])) {
            throw new GraphQlInputException(
                __("Required parameter $code for $code is missing.")
            );
        }

        // vvv convert maskedQuoteId to quoteId
        $maskedId = $args[$code]['cartId'];
        $quoteId = $this->maskedQuoteIdToQuoteId->execute($maskedId);

        $stateData = $args[$code]['stateData'] ?? '';
        $this->adyenStateData->save($stateData, $quoteId);

        return $args[$code];
    }
}