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

StripeJS directly from custom button #270

Closed austinh closed 9 years ago

austinh commented 9 years ago

I am having trouble using StripeJS with the PayumBundle.

Is there anyway to use stripejs checkout without having the button be on a seperate blank page. I have created my own page with two buttons: paypal and stripe checkout. paypals button goes directly to the prepare page which then redirects goes to paypal, and back to my website. Works perfectly.

Users see Paypal Button -> Paypal -> Confirm Action Success Page

Unfortunately, Stripe process as setup in the docs/sandbox is not as nice.

When I click the StripeJS button, it brings up the Stripe dialog, and then you click "Buy" and it brings you to a blank page with ANOTHER StripeJS button and dialog with the same confirmation info. Users see Stripe Button -> Dialog Popup -> Blank page with Stripe Button -> Another Dialog Popup -> Finally Confirm Action Success Page

I want to skip this step and just go directly through Stripe like Paypal Express does, but I cant seem to get it work. I've tinkered with lots of code but there's no way to customize this and still use payum it seems. Can anyone help? It seems that 0.15 docs and examples are not up to date in the Sandbox so I'm not sure what I'm doing wrong.

I also tried OmniPay Direct but it has another form inbetween the steps. I just want it to submit directly from the client TokenID.

shairyar commented 9 years ago

I would like to know this too

smarques commented 9 years ago

:+1:

guizm0b commented 9 years ago

I have the same problem here, but I think that in the demo bundle it works like it should / like you want @austinh : http://sandbox.payum.forma-dev.com/stripe/prepare_checkout. When you click on the "Pay with card" button, you have the pop up with the form for your payment information and then when you click on the "Pay" button you are redirected to the "Done" action.

BUT, I'm experiencing the same problem as you with the double pop up and I need to fill my payment information twice. And I don't know why as I have the same code as in the demo bundle...

When I create the capture token I set a route to my doneAction but I'm redirected to the default captureAction with the blank page and only one button.

Anyone can help us with that ?

Thank you (and sorry for my English)

austinh commented 9 years ago

The most recent version of Payum doen't seem to support this part of the code:

if ($request->isMethod('POST') && $request->request->get('stripeToken')) {

            $payment["card"] = $request->request->get('stripeToken');
            $storage->update($payment);

            $captureToken = $this->getTokenFactory()->createCaptureToken(
                $gatewayName,
                $payment,
                'acme_payment_details_view'
            );

            return $this->redirect($captureToken->getTargetUrl());
        }

There is no "card" property in the latest 0.14-15 version of Payum, so the data is not saved. Thus it needs to capture it again. Instead there is the ->setCreditCard method but that requires something else entirely (a CreditCard object). This may be the reason why it is not capturing it. It seems the example on the site is using a very old version of payum, whereas the new version does not seem to work with this. Maybe I am wrong?

However, after further investigation I have also found that generating a capture token requires that you go to the following template:

src/Payum/Stripe/Resources/views/Action/obtain_checkout_token.html.twig

I do not want to go to this just to be able to capture a token.

I should be able to go to my own page.

guizm0b commented 9 years ago

@austinh did you manage to do what you wanted ? I'm still stuck with this problem.

austinh commented 9 years ago

Nope I'm still stuck with this problem as well.

On Tue, Jun 23, 2015 at 7:20 AM -0700, "guizm0b" notifications@github.com wrote:

@austinh did you manage to do what you wanted ?

I'm still stuck with this problem.

— Reply to this email directly or view it on GitHub.

guizm0b commented 9 years ago

@makasim can you give us a little help here ?

makasim commented 9 years ago

Hm, the button must not be shown if card was set.

It is a stripe token which use lately to capture the payment. Could you make sure that this field is correctly stored before you processed to capture url?

makasim commented 9 years ago

Ok, I'll look into it.

guizm0b commented 9 years ago

Thank you. But how do you set the card as like austinh said, there is no "card" property and the setCreditCard method is expecting an instance of CreditCardInterface ? At this point we only have a token. Maybe I can show you some of my code if you need.

makasim commented 9 years ago

The capture action deals with payment details not payment object (you refering to setCreditCard method from it).

makasim commented 9 years ago

Look at payment object, there is setDetails\getDetails method, this is where you have to look for card field.

guizm0b commented 9 years ago

I followed the documentation here: http://payum.org/doc/0.15/PayumBundle/get_it_started. But in this example it's an offline payment so there is no card to set up and I don't know how to do it for stripe_checkout. I'll try to follow the code from the sandbox and see if I can make it work.

guizm0b commented 9 years ago

I finally found a way to make it work following the code from the sandbox and not the example in the documentation.

smarques commented 9 years ago

could you share it? I think it would be useful for many people here :)

On Wed, Jun 24, 2015 at 5:40 PM, guizm0b notifications@github.com wrote:

I finally found a way to make it work following the code from the sandbox and not the example in the documentation.

— Reply to this email directly or view it on GitHub https://github.com/Payum/PayumBundle/issues/270#issuecomment-114915665.

guizm0b commented 9 years ago

Of course ! I will do it tomorrow, I just need to clean my code before.

smarques commented 9 years ago

:wave: :+1:

guizm0b commented 9 years ago

So here is my solution. I followed the code from the sandbox bundle and I created a custom Payment class that extends a PaymentDetails class that extends an Array object.

My Payment class :

<?php

namespace Acme\PaymentBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Acme\PaymentBundle\Entity\PaymentDetails as BasePaymentDetails;

/**
 * @ORM\Table(name="acme_payment")
 * @ORM\Entity
 */
class Payment extends BasePaymentDetails
{
    /**
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     *
     * @var integer $id
     */
    protected $id;

    // Add your custom fields here

    /**
     * Get id
     *
     * @return integer
     */
    public function getId()
    {
        return $this->id;
    }
}

My PaymentDetails class :

<?php
namespace Acme\PaymentBundle\Entity;

use Payum\Core\Model\ArrayObject;

class PaymentDetails extends ArrayObject
{
    protected $id;

    /**
     * @return int
     */
    public function getId()
    {
        return $this->id;
    }
}

Then here is my prepareAction in my controller :

public function prepareAction(Request $request){
    $currency = "your_currency";

    $gatewayName = 'stripe_checkout';
    $storage = $this->getPayum()->getStorage('Acme\PaymentBundle\Entity\Payment');

    $payment = $storage->create();
    $payment["currency"] = $currency;
    $payment["description"] = "a description";

    $payment["amount"] = "your_amount";

    if($request->isMethod('POST') && $request->request->get('stripeToken')){

        $payment["card"] = $request->request->get('stripeToken');
        $storage->update($payment);

        $captureToken = $this->getTokenFactory()->createCaptureToken(
            $gatewayName,
            $payment,
            "your_route"
        );

        return $this->redirect($captureToken->getTargetUrl());
    }

    return $this->render('AcmePaymentBundle:Frontend/Payment:prepare.html.twig', array(
        'currency' => $currency,
        'totalAmount' => $payment["amount"],
        'publishable_key' => $this->container->getParameter('stripe.publishable_key'),
        'payment' => $payment,
        'gatewayName' => $gatewayName
    ));
}

And finally my template to show the payment button :

    <form id="form-stripe-checkout" action="" method="POST">
        <script src="https://checkout.stripe.com/checkout.js" class="stripe-button"
            data-key="{{ publishable_key }}"
            data-image="{{ asset('bundles/acme/frontend/images/logo_stripe.png', absolute=true) }}"
            data-name="your_name"
            data-description="{{ payment.description }}"
            data-currency="{{ currency }}",
            data-amount="{{ payment.amount }}",
            data-label="{{ "Valider et payer ma commande"|trans }}">
        </script>
    </form>

Here you go now it works and you only have on Stripe pop up for the payment. I hope it will help some people =) PS: I'm using 0.15 branch

Sybio commented 8 years ago

@guizm0b This is too bad you used the old deprecated snippet of sandbox !

I had the same problem, and i solved it in my config.yml by overriding this gateway parameter :

payum.template.obtain_token

payum:
    gateways:
        stripe_checkout:
            factory: stripe_checkout
            publishable_key: %stripe_public_key%
            secret_key: %stripe_secret_key%
            payum.template.obtain_token: "front/subscription/order_offer.html.twig"

Here i use my custom template for the action capture at path :

app/Resources/views/front/subscription/order_offer.html.twig

Note in your case you need to replace stripe_checkout for stripe_js !

jimiero commented 4 years ago

Hello,

I tried to follow your suggestions, but if I do the custom template, i get one time the form to enter the card details, I click submit, then it redirects me to Payum default blank template for stripe, asking again to submit card details.

Any idea ?