Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SetupIntent without charging an amount #8

Open
zspine opened this issue Jan 15, 2021 · 8 comments
Open

SetupIntent without charging an amount #8

zspine opened this issue Jan 15, 2021 · 8 comments
Labels
enhancement New feature or request question Further information is requested

Comments

@zspine
Copy link

zspine commented Jan 15, 2021

Hi!

I am using this library (stripe_js) in a production setup and am in the process of migrating all the payments to SCA ready.

I am trying to use the Create Setup Intent API to save a card before charge the customer. But I couldn't find any examples or documentation to understand the implementation steps.

Any suggestions greatly appreciated, Thank you

@Prometee Prometee added enhancement New feature or request question Further information is requested labels Jan 15, 2021
@Prometee
Copy link
Member

Prometee commented Jan 15, 2021

Hi @zspine,

For stripe_checkout_session :
Capturing cards for later payment is pretty easy, if you will handle only setup intent with this gateway the only thing to do is to make your own ConvertPaymentAction and replace the definition of the original one.

The array to build will required this kind of data :

// @see https://github.com/FLUX-SE/PayumStripe/blob/master/src/Action/ConvertPaymentAction.php#L24-L37
// ^-- Replace those lines with the code bellow
$details = [
    'payment_method_types' => ['card'],
    'mode' => 'setup',
    // even if this field is empty, it's required by this lib but not by Stripe
    // @see https://github.com/FLUX-SE/PayumStripe/blob/master/src/Action/CaptureAction.php#L107-L109
    'setup_intent_data' => [],
];
$request->setResult($details);

For stripe_js :

I don't test it but you could create a JsCaptureSetupIntentAction base on src/Action/JsCaptureAction.php and replace the original definition with it.

<?php
declare(strict_types=1);

namespace FluxSE\PayumStripe\Action;

use FluxSE\PayumStripe\Request\Api\Pay;
use LogicException;
use Payum\Core\Bridge\Spl\ArrayObject;
use Payum\Core\Request\Capture;
use Payum\Core\Security\TokenInterface;
use Stripe\ApiResource;
use Stripe\SetupIntent;

class JsCaptureSetupIntentAction extends CaptureAction
{
    protected function createCaptureResource(ArrayObject $model, Capture $request): ApiResource
    {
        // This class CreateSetupIntent should be created by you, it will be the same class as :
        // @see \FluxSE\PayumStripe\Request\Api\Resource\CreatePaymentIntent
        // /!\ The related action have to be also created :
        // @see \FluxSE\PayumStripe\Action\Api\Resource\CreatePaymentIntentAction
        $createSetupIntent = new CreateSetupIntent($model->getArrayCopy());
        $this->gateway->execute($createSetupIntent);

        return $createSetupIntent->getApiResource();
    }

    protected function renderCapture(ApiResource $captureResource, Capture $request): void
    {
        if (false === $captureResource instanceof SetupIntent) {
            throw new LogicException(sprintf('The $captureResource should be a "%s" !', SetupIntent::class));
        }

        $token = $this->getRequestToken($request);
        $actionUrl = $token->getTargetUrl();
        $pay = new Pay($captureResource, $actionUrl);
        $this->gateway->execute($pay);
    }

    public function embedOnModeData(ArrayObject $model, TokenInterface $token, string $modeDataKey): void
    {
        // not need for this on Stripe JS
    }
}

You will also have to make your own JsConvertPaymentAction.php to provide the required $details array to the creation of the SetupIntent.

After this action the PayAction is executed displaying the actual stripe_js html/js template, looking at the difference between PaymentIntent And SetupIntent I think all will be working.

Finally
The rest (catching the SetupIntent results from Stripe, etc) is already handle by this lib so it should work.

PS: Because the stripe_checkout_session is already handling payment, setup and subscription; maybe what you are requesting could be built as a possible configuration to the stripe_js gateway or a new payment gateway named stripe_js_setup

@zspine
Copy link
Author

zspine commented Jan 15, 2021

@Prometee Hi

Thank you very much taking the time to explain this in detail.

Now I understand how the whole thing works. Amazing!!! I have spent several hours digging the source code to have an understanding of the whole functionality and flow.

Thanks again for this awesome library and symfony bundle, it saves lots of time and hassle.

@Prometee
Copy link
Member

I know Payum is not easy too at first sight...

@zspine Thank you very much for your support !

Don't forget to get back to me if you succeed, it would be very interesting to add setup intent capabilities to the stripe_js gateway.

@Prometee
Copy link
Member

Prometee commented Jan 15, 2021

PS: I edited my first comment (small corrections and add)

@zspine
Copy link
Author

zspine commented Jan 18, 2021

@Prometee Definitely, I will give it a try and will share the final code if it's successful.

@Prometee
Copy link
Member

Prometee commented Mar 8, 2021

Hi @zspine !

With @syjust we succeeded making a SetupIntent then triggered a PaymentIntent.
We would like to add a new dedicated gateway to handle this specific case and allow it to be used in the bundle and the Sylius plugin.
It will also need a specific documentation because this processus need to be handle in two time :

  • SetupIntent to store a customer and his payment method.
  • PaymentIntent to trigger the payment with full or partial amount.

If you have an other behaviour, you can share it with us, it will help making a generic gateway 😉

@zspine
Copy link
Author

zspine commented Mar 9, 2021

Hi @Prometee

Perfect timing :) almost like miracle! Thanks a million for the update!

I was on leave for 2 months due to some personal issues. I just started to work and was referring through the code base to refresh the memories. Definitely will try it this week and will give you an update!

Thank you @syjust

@Prometee
Copy link
Member

Hi @zspine,

I wanted to give you some update on the evolution of this library, I added PaymentIntent with 'capture_method' => 'manual'. Here is the associated Stripe documentation article: https://stripe.com/docs/payments/capture-later.

I know this isn't exactly what you needed, but now you can easily add a new AuthorizeAction which will create aSetupIntent, then you can create a CaptureAction which will create the associated PaymentIntent when you will need it.

I will let this issue opened because SetupIntent is something which is very important for many projects.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants