0

I'm trying to integrate ominipay with PayPal Express Checkout in my website. I have a table commande (order in english) where i'm saving the reference, date, user_id , commande =>[commande is storing : priceTTC, priceHT, address, quantity, token].

When the user click on the button Pay i have this error:

Controller "FLY\BookingsBundle\Controller\PayController::postPaymentAction" for URI "/payment/2" is not callable.

This is my validation.html.twig

 <form action="{{ path('postPayment', { 'id' : commande.id }) }}" 
    method="POST"/>
    <input name="token" type="hidden" value="{{ commande.commande.token }}" />
    <input name="price" type="hidden" value="{{ commande.commande.priceTTC }}" />
    <input name="date" type="hidden" value="{{ commande.date|date('dmyhms') }}" />
    <button type="submit" class="btn btn-success pull-right">Pay</button>
  </form>

Routing.yml

postPayment:
     pattern:  /payment/{id}
     defaults: { _controller: FLYBookingsBundle:Pay:postPayment }

getSuccessPayment:
     pattern:  /success/{id}
     defaults: { _controller: FLYBookingsBundle:Pay:getSuccessPayment }

PayController.php

class PayController extends Controller
{

    public function postPayment (Commandes $commande)
    {
        $params = array(
            'cancelUrl' => 'here you should place the url to which the users will be redirected if they cancel the payment',
            'returnUrl' => 'here you should place the url to which the response of PayPal will be proceeded', // in your case             //  you have registered in the routes 'payment_success'
            'amount' => $commande->get('priceTTC'),
        );

        session()->put('params', $params); // here you save the params to the session so you can use them later.
        session()->save();

        $gateway = Omnipay::create('PayPal_Express');
        $gateway->setUsername('xxxxxxxxx-facilitator_api1.gmail.com'); // here you should place the email of the business sandbox account
        $gateway->setPassword('xxxxxxxxxxxxxx'); // here will be the password for the account
        $gateway->setSignature('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); // and the signature for the account
        $gateway->setTestMode(true); // set it to true when you develop and when you go to production to false
        $response = $gateway->purchase($params)->send(); // here you send details to PayPal

        if ($response->isRedirect()) {
            // redirect to offsite payment gateway
            $response->redirect();
        }
        else {
            // payment failed: display message to customer
            echo $response->getMessage();
        }
    }

.

public function getSuccessPayment (Auth $auth, Transaction $transaction)
    {
        $gateway = Omnipay::create('PayPal_Express');
        $gateway->setUsername('xxxxxxxxxxx-facilitator_api1.gmail.com\''); // here you should place the email of the business sandbox account
        $gateway->setPassword('xxxxxxxxxxxxxxxx'); // here will be the password for the account
        $gateway->setSignature('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); // and the signature for the account
        $gateway->setTestMode(true);
        $params = session()->get('params');
        $response = $gateway->completePurchase($params)->send();
        $paypalResponse = $response->getData(); // this is the raw response object

        if(isset($paypalResponse['PAYMENTINFO_0_ACK']) && $paypalResponse['PAYMENTINFO_0_ACK'] === 'Success') {
            // here you process the response. Save to database ...

        }
        else {
            // Failed transaction ...
        }
    }
}
Sirius
  • 653
  • 1
  • 14
  • 37
  • This looks more like a symfony issue than an omnipay issue. What you are doing there in your controller action looks correct from an omnipay point of view but the error message seems to indicate that the symfony router is not finding your controller. I'm not a symfony expert but perhaps your controller action needs to be named postPaymentAction instead of postPayment? – delatbabel Mar 28 '16 at 04:34
  • I deleted the route in routing.yml and i created a route on top of my controller like this: `/** * * @Route("/", name="pay") * @Method("GET") */` then in validation.html.twig i changed the path by `pay`. It seems to work, but when i click on the button pay it redirect me to a blank page. `http://127.0.0.1/symfony/web/app_dev.php/?id=34` . i think i should be redirect to paypal so the user can make the payment...? – Sirius Mar 28 '16 at 10:41
  • i also changed postPayment to postPaymentAction. Now i have this error: `Attempted to call function "session" from namespace "FLY\BookingsBundle\Controller"` `session()->put('params', $params);` I think i know why i have many errors, is because the controller that i have is made to work with laravel and not symfony2. – Sirius Mar 28 '16 at 12:07
  • Yes you can't use laravel controllers with symfony or vice-versa. – delatbabel Mar 29 '16 at 10:41

1 Answers1

1

A Symfony controller callable method should end with the Action word.

public function postPayment(...) --> public function postPaymentAction(...)

Then, some of your controller methods are not symfony-valid, they seem laravel-based instead.

// Laravel
session()->put('params', $params); // here you save the params to the session so you can use them later.
session()->save();

-->
// Symfony

use Symfony\Component\HttpFoundation\Request;

public function postPaymentAction(Commandes $commande, Request $request)

$request->getSession(); // The request should be incldued as an action parameter
$session->set('params', $params);

Then, about the use of Omnipay itself, I would say that using a 3rd party library inside a Symfony controller is a terrible practice.

I recommand you to use a service instead, and pass your credentials informations from its configuration (potentially parameters).

http://symfony.com/doc/current/service_container.html

// Direct, bad practice
$gateway = Omnipay::create('PayPal_Express');
$gateway->setUsername('xxxxxxxxx-facilitator_api1.gmail.com'); // here you should place the email of the business sandbox account
$gateway->setPassword('xxxxxxxxxxxxxx'); // here will be the password for the account
$gateway->setSignature('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); // and the signature for the account
$gateway->setTestMode(true); // set it to true when you develop and when you go to production to false

$response = $gateway->purchase($params)->send(); // here you send details to PayPal

You even already have a 3rd-party bundle to do that :

https://github.com/colinodell/omnipay-bundle

// Using a Service to get a full-configured gateway
$gateway = $this->get('omnipay')->getDefaultGateway();

$response = $gateway->purchase($params)->send();

You could also lock the HTTP methods in your router file, even if it is optionnal :

postPayment:
     pattern:  /payment/{id}
     method:   POST
     defaults: { _controller: FLYBookingsBundle:Pay:postPayment }

getSuccessPayment:
     pattern:  /success/{id}
     method:   GET
     defaults: { _controller: FLYBookingsBundle:Pay:getSuccessPayment }
Flo Schild
  • 5,104
  • 4
  • 40
  • 55
  • Thank you for you response. I already find a solution to my issue, i have decided to use Paypal express checkout with Payum. In my next project i will try to use Omnipay and your answer will be helpful. :) – Sirius Sep 02 '16 at 09:59