How to set up JMSpayment Bundle and add the paypal plugin

Publié le par Sébastien Flamant

We will set up JMSPaymentCoreBundle in order to manage different types of payment. We will install the paypal bundle, but you can make your own plugin to manage credit cards.

/* Bundle configuration with Symfony 2.1 */

&lt;br /&gt;<br />
&amp;quot;sensio/framework-extra-bundle&amp;quot;: &amp;quot;2.1.x-dev&amp;quot;,&lt;br /&gt;<br />
&amp;quot;jms/security-extra-bundle&amp;quot;: &amp;quot;1.2.*&amp;quot;,&lt;br /&gt;<br />
&amp;quot;jms/di-extra-bundle&amp;quot;: &amp;quot;1.1.*&amp;quot;,&lt;br /&gt;<br />
&amp;quot;jms/payment-paypal-bundle&amp;quot;: &amp;quot;*&amp;quot;,&lt;br /&gt;<br />
&amp;quot;jms/payment-core-bundle&amp;quot;: &amp;quot;dev-master&amp;quot;,&lt;/p&gt;<br />
&lt;p&gt;//appKernel&lt;br /&gt;<br />
new Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle() ,&lt;br /&gt;<br />
new JMS\DiExtraBundle\JMSDiExtraBundle($this),&lt;br /&gt;<br />
new JMS\SecurityExtraBundle\JMSSecurityExtraBundle(),&lt;br /&gt;<br />
new JMS\Payment\CoreBundle\JMSPaymentCoreBundle(),&lt;br /&gt;<br />
new JMS\Payment\PaypalBundle\JMSPaymentPaypalBundle(),&lt;/p&gt;<br />
&lt;p&gt;//Here it is for the config.yml file:&lt;br /&gt;<br />
sensio_framework_extra:&lt;br /&gt;<br />
    view:&lt;br /&gt;<br />
        annotations: false&lt;br /&gt;<br />
jms_payment_core:&lt;br /&gt;<br />
    secret: 0123&lt;/p&gt;<br />
&lt;p&gt;jms_payment_paypal:&lt;br /&gt;<br />
    username:;br /&gt;<br />
    password: 13554848&lt;br /&gt;<br />
    signature: LbGakzdnaokndand&lt;br /&gt;<br />
    debug: true&lt;/p&gt;<br />
&lt;p&gt;jms_di_extra:&lt;br /&gt;<br />
    locations:&lt;br /&gt;<br />
        all_bundles: false&lt;br /&gt;<br />
        bundles: [HereYourAppBundle]&lt;br /&gt;<br />
        directories: [&amp;quot;%kernel.root_dir%/../src&amp;quot;]&lt;br /&gt;<br />
    automatic_controller_injections:&lt;br /&gt;<br />
        properties:&lt;br /&gt;<br />
            request: &amp;quot;@request&amp;quot;&lt;br /&gt;<br />
            router: &amp;quot;@router&amp;quot;&lt;br /&gt;<br />
        method_calls:&lt;br /&gt;<br />
            setRouter: [&amp;quot;@router&amp;quot;]&lt;br /&gt;<br />

Install the bundles via

php composer.phar update

and don’t forget to update the database

php app/console doctrine:schema:update --force

First of all, you have to register on
You can see the whole paypal documentation here ( Paypal Doc )
When you are logged in, you can see your API Credentials by clicking in Api and Payement Credentials on the left menu. You have to set your name,password and signature in your config.yml

jms_payment_paypal:&lt;br /&gt;<br />
    username:;br /&gt;<br />
    password: 13554848&lt;br /&gt;<br />
    signature: LbGakzdnaokndand&lt;br /&gt;<br />
    debug: true&lt;br /&gt;<br />

Then go to « tests accounts ». You can create a new one by selecting « preconfigured ». Now fill the fields and choose « buyer », put some money on your bank account and the most important: copy past the generated password. Now create your account( it takes a long time with me… ) You can see your new fake buyer account and the associated email address.

This is the account you have to use when you are redirected to from your website.

Now, the order class, twig and the controller.
On the JMSPaymentCoreBundle, you can see an order class. You should use it or use your own and adding a paymentInstruction attribute, getters and setters.
JMSPaymentCoreBundle Class , and don’t forget the use instructions..

Your Order Class&lt;br /&gt;<br />
use JMS\Payment\CoreBundle\Entity\PaymentInstruction;&lt;/p&gt;<br />
&lt;p&gt;    /**  * @ORM\OneToOne(targetEntity=&amp;quot;JMS\Payment\CoreBundle\Entity\PaymentInstruction&amp;quot;)&lt;br /&gt;<br />
     */&lt;br /&gt;<br />
    private $paymentInstruction;&lt;br /&gt;<br />

I modified a little bit the examples to fit my wish.
It’s important to understand this class, because, when you get an error, you just have a  » Transaction was not successful  » message..

&lt;br /&gt;<br />
class PaiementController extends Controller&lt;br /&gt;<br />
{&lt;br /&gt;<br />
    /** @DI\Inject */&lt;br /&gt;<br />
    private $request;&lt;/p&gt;<br />
&lt;p&gt;    /** @DI\Inject */&lt;br /&gt;<br />
    private $router;&lt;/p&gt;<br />
&lt;p&gt;    /** @DI\Inject(&amp;quot;doctrine.orm.entity_manager&amp;quot;) */&lt;br /&gt;<br />
    private $em;&lt;/p&gt;<br />
&lt;p&gt;    /** @DI\Inject(&amp;quot;payment.plugin_controller&amp;quot;) */&lt;br /&gt;<br />
    private $ppc;&lt;/p&gt;<br />
&lt;p&gt;    /**&lt;br /&gt;<br />
     * @Route(&amp;quot;/{id}&amp;quot;, name=&amp;quot;paiement&amp;quot;)&lt;br /&gt;<br />
     * @Template()&lt;br /&gt;<br />
     */&lt;br /&gt;<br />
    public function paymentAction($id=0) // this is a personnal ID i pass to the controler to identify the previous shopping cart&lt;br /&gt;<br />
    {&lt;br /&gt;<br />
        $form = $this-&amp;gt;getFormFactory()-&amp;gt;create('jms_choose_payment_method', null, array(&lt;br /&gt;<br />
            'amount'   =&amp;gt; $order-&amp;gt;getPrice(),&lt;br /&gt;<br />
            'currency' =&amp;gt; 'EUR',&lt;br /&gt;<br />
            'default_method' =&amp;gt; 'payment_paypal', // Optional&lt;br /&gt;<br />
            'predefined_data' =&amp;gt; array()&lt;br /&gt;<br />
        ));&lt;/p&gt;<br />
&lt;p&gt;        if ('POST' === $this-&amp;gt;request-&amp;gt;getMethod()) {&lt;br /&gt;<br />
            $form-&amp;gt;bindRequest($this-&amp;gt;request);&lt;br /&gt;<br />
            $order = new Order();&lt;br /&gt;<br />
            $this-&amp;gt;em-&amp;gt;persist( $order);&lt;br /&gt;<br />
            $this-&amp;gt;em-&amp;gt;flush( $order);&lt;/p&gt;<br />
&lt;p&gt;            $form = $this-&amp;gt;getFormFactory()-&amp;gt;create('jms_choose_payment_method', null, array(&lt;br /&gt;<br />
                'amount'   =&amp;gt; $order-&amp;gt;getPrice(),&lt;br /&gt;<br />
                'currency' =&amp;gt; 'EUR',&lt;br /&gt;<br />
                'default_method' =&amp;gt; 'payment_paypal', // Optional&lt;br /&gt;<br />
                'predefined_data' =&amp;gt; array(&lt;br /&gt;<br />
                    'paypal_express_checkout' =&amp;gt; array(&lt;br /&gt;<br />
                        'return_url' =&amp;gt; $this-&amp;gt;router-&amp;gt;generate('payment_complete', array(&lt;br /&gt;<br />
                            'id' =&amp;gt;$order-&amp;gt;getId()&lt;br /&gt;<br />
                        ), true),&lt;br /&gt;<br />
                        'cancel_url' =&amp;gt; $this-&amp;gt;router-&amp;gt;generate('payment_cancel', array(&lt;br /&gt;<br />
                            'id' =&amp;gt; $order-&amp;gt;getId()&lt;br /&gt;<br />
                        ), true)&lt;br /&gt;<br />
                    ),&lt;br /&gt;<br />
                ),&lt;br /&gt;<br />
            ));&lt;/p&gt;<br />
&lt;p&gt;            $form-&amp;gt;bindRequest($this-&amp;gt;request);&lt;/p&gt;<br />
&lt;p&gt;	// Once the Form is validate, you update the order with payment instruction&lt;br /&gt;<br />
            if ($form-&amp;gt;isValid()) {&lt;br /&gt;<br />
                $instruction = $form-&amp;gt;getData();&lt;br /&gt;<br />
                $this-&amp;gt;ppc-&amp;gt;createPaymentInstruction($instruction);&lt;br /&gt;<br />
                $order-&amp;gt;setPaymentInstruction($instruction);&lt;br /&gt;<br />
                $this-&amp;gt;em-&amp;gt;persist($order);&lt;br /&gt;<br />
                $this-&amp;gt;em-&amp;gt;flush($order);&lt;br /&gt;<br />
				// now, let's redirect to payment_complete with the order id&lt;br /&gt;<br />
                return new RedirectResponse($this-&amp;gt;router-&amp;gt;generate('payment_complete', array('id' =&amp;gt; $order-&amp;gt;getId() )));&lt;br /&gt;<br />
            }&lt;br /&gt;<br />
        }&lt;br /&gt;<br />
        return $this-&amp;gt;render('YourBundle:Paiement:paymentChooseTemplate.html.twig',array('form' =&amp;gt; $form-&amp;gt;createView() , 'id' =&amp;gt; $id));&lt;br /&gt;<br />
    }&lt;br /&gt;<br />

&lt;br /&gt;<br />
    /**&lt;br /&gt;<br />
     * @Route(&amp;quot;/complete/{id}&amp;quot;, name = &amp;quot;payment_complete&amp;quot;)&lt;br /&gt;<br />
     */&lt;br /&gt;<br />
    public function completeAction($id=0) // id of the order&lt;br /&gt;<br />
    {&lt;br /&gt;<br />
        if ( $id != 0 ){&lt;br /&gt;<br />
            $order = $this-&amp;gt;getDoctrine()-&amp;gt;getRepository(&amp;quot;YourBundle:order&amp;quot;)-&amp;gt;find($id);}&lt;/p&gt;<br />
&lt;p&gt;        $instruction = $order-&amp;gt;getPaymentInstruction();&lt;br /&gt;<br />
        if (null === $pendingTransaction = $instruction-&amp;gt;getPendingTransaction()) {&lt;br /&gt;<br />
            $payment = $this-&amp;gt;ppc-&amp;gt;createPayment($instruction-&amp;gt;getId(), $instruction-&amp;gt;getAmount() - $instruction-&amp;gt;getDepositedAmount());&lt;br /&gt;<br />
        } else {&lt;br /&gt;<br />
            $payment = $pendingTransaction-&amp;gt;getPayment();&lt;br /&gt;<br />
        }&lt;/p&gt;<br />
&lt;p&gt;        $result = $this-&amp;gt;ppc-&amp;gt;approveAndDeposit($payment-&amp;gt;getId(), $payment-&amp;gt;getTargetAmount());&lt;br /&gt;<br />
        if (Result::STATUS_PENDING === $result-&amp;gt;getStatus()) {&lt;br /&gt;<br />
            $ex = $result-&amp;gt;getPluginException();&lt;br /&gt;<br />
            if ($ex instanceof ActionRequiredException) {&lt;br /&gt;<br />
                $action = $ex-&amp;gt;getAction();&lt;br /&gt;<br />
                if ($action instanceof VisitUrl) {&lt;br /&gt;<br />
                    return new RedirectResponse($action-&amp;gt;getUrl());&lt;br /&gt;<br />
                }&lt;br /&gt;<br />
                throw $ex;&lt;br /&gt;<br />
            }&lt;br /&gt;<br />
        } else if (Result::STATUS_SUCCESS !== $result-&amp;gt;getStatus()) {&lt;br /&gt;<br />
            throw new \RuntimeException('Transaction was not successful: '.$result-&amp;gt;getReasonCode());&lt;br /&gt;<br />
        }&lt;br /&gt;<br />
		// if successfull, i render my order validation template&lt;br /&gt;<br />
        return $this-&amp;gt;render('YourBundle:Paiement:validation.html.twig',array('order'=&amp;gt;$order ));&lt;/p&gt;<br />
&lt;p&gt;    }&lt;/p&gt;<br />
&lt;p&gt;    /** @DI\LookupMethod(&amp;quot;form.factory&amp;quot;) */&lt;br /&gt;<br />
    protected function getFormFactory() { }&lt;/p&gt;<br />
&lt;p&gt;    /**&lt;br /&gt;<br />
     * @Route(&amp;quot;/cancel&amp;quot;, name = &amp;quot;payment_cancel&amp;quot;)&lt;br /&gt;<br />
     */&lt;br /&gt;<br />
    public function CancelAction( )&lt;br /&gt;<br />
    {&lt;br /&gt;<br />
        $this-&amp;gt;get('session')-&amp;gt;getFlashBag()-&amp;gt;add('info', 'Transaction annulAi??e.');&lt;br /&gt;<br />
        return $this-&amp;gt;redirect($this-&amp;gt;generateUrl('yourTemplate'));&lt;br /&gt;<br />
    }&lt;br /&gt;<br />
}&lt;br /&gt;<br />

If the payment succeded, you can see useful informations about it in Payments table. You can see the deposited amount, the state of the payment etc..

A really basic twig for paymentChooseTemplate; It just chow A Paypal radio Button:

&lt;br /&gt;<br />
{% extends &amp;quot;::layout.html.twig&amp;quot; %}&lt;br /&gt;<br />
{% block body %}&lt;br /&gt;<br />
&amp;lt;div class=&amp;quot;container&amp;quot;&amp;gt;&lt;br /&gt;<br />
&amp;lt;form action=&amp;quot;{{ path('paiement' , {'id': id } ) }}&amp;quot; method=&amp;quot;post&amp;quot;&amp;gt;&lt;br /&gt;<br />
        {{ form_widget(form) }}&lt;br /&gt;<br />
        &amp;lt;input type=&amp;quot;submit&amp;quot; /&amp;gt;&lt;br /&gt;<br />
    &amp;lt;/form&amp;gt;&lt;br /&gt;<br />
{% endblock %}&lt;br /&gt;<br />

Cette entrée a été publiée dans Symfony 2 Utils, avec comme mot(s)-clef(s) , , , , . Vous pouvez la mettre en favoris avec ce permalien.

13 réponses à How to set up JMSpayment Bundle and add the paypal plugin

  1. Félix dit :

    Thanks for the article. Unfortunately there is not much iformación regarding this « bundle » and has been fortunate that you shared your knowledge.

  2. Paulo dit :


    Merci pour votre article. Il serait possible de fournir un exemple pour le téléchargement?

    Excusez mon français …


  3. Baptiste dit :

    Bonjour à tous,

    J’ai bien implémenté le bundle mais il y’a un problème que je n’arrive pas à résoudre.
    Comment est-il possible de customizé le form pour qu’il ne ressemble pas à une choice list en anglais mais un simple boutton paypal paiement par exemple.

    Mercie à vous

  4. Xavi dit :

    Hi! I’m getting « The requested package jms/payment-paypal-bundle could not be found in any version, there may be a typo in the package name. » and i have copy-pasted the code. I don’t know what i’m doing wrong… any help please???

  5. Ahmad HAJJ-CHEHADE dit :

    merci pour ce tutoriel, mais je suis bloquer au point où il faut modifier l’order class et le paiement controlller , les ources du bundle que j’ai trouvé sont ici
    mais je trouve pos les controlleur….

  6. Stephen dit :


    Je suis novice sur Symfony2 et je travaille sur Mac OS X 10.9. Actuelle, je travaille sur un site commerce et j’ai donc besoin de ce bundle. Je bloque dès le début de ce tuto, quand je mets les 5 premiers lignes dans composer.json, voici l’erreur que j’ai:

    Problem 1
    – Installation request for jms/payment-core-bundle dev-master -> satisfiable by jms/payment-core-bundle[dev-master].
    – jms/payment-core-bundle dev-master requires ext-mcrypt * -> the requested PHP extension mcrypt is missing from your system.
    Problem 2
    – jms/payment-core-bundle 1.0.x-dev requires ext-mcrypt * -> the requested PHP extension mcrypt is missing from your system.
    – jms/payment-core-bundle 1.0.0 requires ext-mcrypt * -> the requested PHP extension mcrypt is missing from your system.
    – jms/payment-paypal-bundle 1.0.0 requires jms/payment-core-bundle ~1.0 -> satisfiable by jms/payment-core-bundle[1.0.0, 1.0.x-dev].
    – Installation request for jms/payment-paypal-bundle * -> satisfiable by jms/payment-paypal-bundle[1.0.0].

    J’ai vérifié mon php.ini et j’ai bien cette ligne :

    Quand je vais dans phpInfo sur mamp, j’ai bien « mcrypt support: enabled » et « mcrypt_filter support: enabled ».

    Quelqu’un aurai une idée pour résoudre ce problème?

  7. Ludovic dit :

    Bonjour !
    Je suis à la recherche d’un Bundle qui me permettrait de gérer des paiements de services sur un site web réalisé sous SF2 via Paypal. Votre solution est-t-elle toujours compatible avec Paypal aujourd’hui ?

  8. Benjamin dit :

    Super pour les explications mais totalement nouveau… je ne vois pas quand je dois appeler paymentAction. J’ai tenté de comprendre la nouvelle doc mais … je cale un peu.

    Dois-je faire un formulaire avec mes produits et sauvegarder en DB la ‘commande’ puis rediriger vers paymentAction ? Si oui à quoi ça sert de persister à nouveau la commande ?

    Merci !!!

  9. Aimeric dit :


    Je voudrais pouvoir valider le paiement des produits sur mon site e-commerce avec paypal. Mon controller Validation simule un faux paiement. Maintenant je voudrais pouvoir réaliser un vrai paiement avec paypal pour cela j’ai suivi les instructions dans votre tutoriel. j’ai remplacé mon controller validation par completeAction. Mais cette erreur:

    Error: Call to a member function getPendingTransaction() on null

    if (null === $pendingTransaction = $instruction->getPendingTransaction()) {

    Sur le lien suivant il y a mon controller validation et le controller completeAction.


Répondre à Paulo Annuler la réponse.

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *


9 - five =

Vous pouvez utiliser ces balises et attributs HTML : <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>