Payum / PayumBundle

Payum offers everything you need to work with payments. From simplest use cases to very advanced ones.
https://payum.gitbook.io/payum
MIT License
569 stars 142 forks source link

Gateways not registered in Symfony 6 #549

Closed joesenova closed 1 year ago

joesenova commented 1 year ago

This is the error I get after upgrading to Symfony 6 from Symfony 4. I have removed the entire bundle and all code references. I reinstalled the bundle and reimplemented the Payum Bundle, still the same error. I use the Payum Bundle with The payPal Express Checkout gateway.

Request Capture{model: Identity} is not supported. Make sure the storage extension for "App\Entity\PaymentDetails" is registered to the gateway. Make sure the storage find method returns an instance by id "289". Make sure the gateway supports the requests and there is an action which supports this request (The method returns true). There may be a bug, so look for a related issue on the issue tracker.

Also no storages are registered either:

A storage for model App\Entity\Payment was not registered. There are storages for next models: . A storage for model App\Entity\PaymentDetails was not registered. There are storages for next models: .

config.yaml

payum:
    storages:
        App\Entity\PaymentDetails: { doctrine: orm }

    security:
        token_storage:
           App\Entity\PaymentToken: { doctrine: orm }

    gateways:
        paypal_express_checkout:
            factory: paypal_express_checkout
            username: "payments-facilitator_api1.domain.net"
            password: "xxx"
            signature: "xxx"
            sandbox: true

Please can anyone let me know if there is Symfony 6 issues with this bundle, and if so, where can I start looking to get this fixed.

I have the following files too:

Payment.php

<?php
namespace App\Entity;

use Payum\Core\Model\ArrayObject;

class Payment extends ArrayObject
{
    protected int $id;
    /**
     * @return int
     */
    public function getId(): int
    {
        return $this->id;
    }
}

PaymentDetails.php

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;
use App\Entity\Payment as PaymentModel;

#[ORM\Table(name: 'PAYUM_PAYMENT_DETAIL')]
#[ORM\Entity]
class PaymentDetails extends PaymentModel
{

    #[ORM\Column(name: 'id')]
    #[ORM\Id]
    #[ORM\GeneratedValue(strategy: 'IDENTITY')]
    protected int $id;

    public function getId(): int
    {
        return $this->id;
    }

}

Token Object from doAction():

App\Entity\PaymentToken {#1341 ▼
  #details: Payum\Core\Model\Identity {#1339 ▶}
  #hash: "xxx"
  #afterUrl: "http://localhost/event/payment/complete?payum_token=xxx"
  #targetUrl: "http://localhost/payment/capture/xxx"
  #gatewayName: "paypal"
}

Partial from the gateway object:


8 => Payum\Core\Action\GetTokenAction {#1168 ▼
      -tokenStorage: Payum\Core\Bridge\Doctrine\Storage\DoctrineStorage {[#1006 ▼](http://localhost/payment/capture/xxx#sf-dump-123-ref123)
        #modelClass: "App\Entity\PaymentToken"
        #objectManager: Container4hxdUk5\EntityManagerGhostEbeb667 {[#401](http://localhost/payment/capture/xxx#sf-dump-123-ref123) …12}
      }
    }
9 => Payum\Paypal\ExpressCheckout\Nvp\Action\CaptureAction {#1153 ▼
      #gateway: null
      #tokenFactory: null
    }

The following code fails: CaptureController.php

public function doAction(Request $request): RedirectResponse
    {
        $token = $this->getPayum()->getHttpRequestVerifier()->verify($request);

        $gateway = $this->getPayum()->getGateway($token->getGatewayName());
        HERE -----> $gateway->execute(new Capture($token)); <----- HERE

        $this->getPayum()->getHttpRequestVerifier()->invalidate($token);

        return $this->redirect($token->getAfterUrl());
    }

Gateway.php -> dump($request)

Payum\Core\Request\Capture {#1350 ▼
  #model: App\Entity\PaymentToken {[#1341 ▼](http://localhost/payment/capture/xxx#sf-dump-123-ref123)
   HERE ----- >  **#details: Payum\Core\Model\Identity** {#1339 ▼ < ----- HERE
      #class: "App\Entity\PaymentDetails"
      #id: 290
    }
    #hash: "xxx"
    #afterUrl: "http://localhost/event/payment/complete?payum_token=xxx"
    #targetUrl: "http://localhost/payment/capture/xxx
    #gatewayName: "paypal"
  }
  #firstModel: null
  #token: App\Entity\PaymentToken {[#1341 ▶](http://localhost/payment/capture/xxx#sf-dump-1071473380-ref21341)}
}

This returns true:

$context->getAction()->supports($request)

But this gives the Initial Error on this post: Request Capture{model: Identity} is not supported

 $context->getAction()->execute($request);

Partial dump($context);

Payum\Core\Extension\Context {[#1349 ▼](http://localhost/payment/capture/xx#sf-dump-1187676561-ref21349)
  #gateway: Payum\Core\Gateway {[#1202 ▼](http://localhost/payment/capture/xxx#sf-dump-1187676561-ref21202)
    #actions: array:35 [▼
      0 => Payum\Core\Bridge\Symfony\Action\GetHttpRequestAction {#1005 ▶}
      1 => Payum\Core\Bridge\Symfony\Action\ObtainCreditCardAction {#1159 ▶}
      2 => Payum\Core\Action\CapturePaymentAction {#1161 ▶}
      3 => Payum\Core\Action\AuthorizePaymentAction {#1162 ▶}
      4 => Payum\Core\Action\PayoutPayoutAction {#1163 ▶}
      5 => Payum\Core\Action\ExecuteSameRequestWithModelDetailsAction {[#1164 ▶](http://localhost/payment/capture/xxx#sf-dump-1187676561-ref21164)}
      6 => Payum\Core\Bridge\Twig\Action\RenderTemplateAction {#1218 ▶}
      7 => Payum\Core\Action\GetCurrencyAction {#1165 ▶}
      8 => Payum\Core\Action\GetTokenAction {#1168 ▼
        -tokenStorage: Payum\Core\Bridge\Doctrine\Storage\DoctrineStorage {[#1006 ▼](http://localhost/payment/capture/xxx#sf-dump-1187676561-ref21006)
          #modelClass: "App\Entity\PaymentToken"
          #objectManager: Container4hxdUk5\EntityManagerGhostEbeb667 {[#401](http://localhost/payment/capture/xxx#sf-dump-1187676561-ref2401) …12}
        }
      }
      9 => Payum\Paypal\ExpressCheckout\Nvp\Action\CaptureAction {#1153 ▼
       HERE -----> #gateway: null < ----- HERE
       HERE -----> #tokenFactory: null < ----- HERE
      }

Also this fails When I try comment out some of the supports methdos that seem to nt be working: Request GetHumanStatus{model: Identity} is not supported.

Payum\Core\Request\GetHumanStatus {#1433 ▼
  #model: App\Entity\PaymentToken {[#1421 ▶](http://localhost/event/payment/complete?payum_token=xxx#sf-dump-123-ref123)}
  #firstModel: null
  #token: App\Entity\PaymentToken {[#1421 ▼](http://localhost/event/payment/complete?payum_token=xxx#sf-dump-123-ref123)
    #details: Payum\Core\Model\Identity {#1419 ▶}
    #hash: "xxx"
    #afterUrl: null
    #targetUrl: "http://localhost/event/payment/complete?payum_token=xxx"
    #gatewayName: "paypal"
  }
  #status: "unknown"
}

All of this points back to my Entity, PaymentDetails, that is not registered to the Gateway? Make sure the storage extension for "App\Entity\PaymentDetails"

Thank you.

joesenova commented 1 year ago

The issue is the next line in the Cache Dev directory:

App_KernelDevDebug.php $instance->addCoreGatewayFactoryConfig(['twig.env' => ($this->services['.container.private.twig'] ?? $this->get_Container_Private_TwigService())]);

This line fails and causes the Storage extensions to not be added to the CoreGatewayConfig on the following line.

joesenova commented 1 year ago

The fix will be to remove the twig.env = new Reference('twig') from the config.

Then replace where twig.env is called with with new Environment(new FileSystemLoader())

Then also remove all the config tests that test for twig.env is of Twig\Environment::class, that will be true as it will create a new instance of Environment().

joesenova commented 1 year ago

This commit in the Payum/Core is the cause of this bug.

I will post a PR to fix this soon

joesenova commented 1 year ago

550

Here is the PR for this bug

pierredup commented 1 year ago

@joesenova I think the issue here is with the entities.

You have a class PaymentDetails which extends App\Entity\Payment, and your App\Entity\Payment class extends ArrayObject. None of your entities extends Payum\Core\Model\Payment, which is required for most of the actions to be executed. (You can have a look at the Configure docs to see how the entities can be configure)

joesenova commented 1 year ago

Believe I went through all that, nothing changed in config side.

We had it working before, updated the core and it stopped working.

I fixed it and using our own forked branch now. The core is doing something weird with the config building in the Dependency Injection builder.

look at the config of the Twig Env builder and see what the array replace recursive does in the core.

pierredup commented 1 year ago

look at the config of the Twig Env builder and see what the array replace recursive does in the core.

I have, and it doesn't do anything weird. The twig.env value is correctly being added to the config. array_replace_recursive won't clear any existing values, it will just append the value to the array if it doesn't exist, and if the keys exist, then it will just replace the values for that specific key and won't clear anything else in the array

joesenova commented 1 year ago

I am busy debugging every extension and overload we do on twig, will revert if I find anything that causes the break on the Payum Builder code to case the storage extension not to laod.