Closed francesco-laricchia closed 3 years ago
Hello @francesco-laricchia
The gateway stripe_checkout_session
allow to pay, subscribe or store a credit card thanks to a Stripe hosted portal, then at the end of the process returning to your website the payment/subscription/setup is completed
. But nothing disallow you to use each API Action outside those Stripe Checkout processes to make your own re-payment flow.
There is now (master
branch) a CreatePaymentIntent
request which will allow you to create your own PaymentIntent
, here is an exemple :
$model = [
'amount' => 2000,
'currency' => 'eur',
'payment_method' => 'pm_123456',
'customer' => 'cus_123456',
];
$request = new CreatePaymentIntent($model);
$payum->getGateway('stripe_checkout_session')->execute($request);
$paymentIntent = $request->getApiResource();
Let me know if you succeeded.
Let me know if you succeeded.
I eventually managed to complete a payment with a previously saved card, even if it requires to go through SCA flow again every time. Thank you for the hint!
With legacy Payum/Stripe I used GetCreditCardTokenAction to save card token, which was only the "customer" field, to my database so I could Stripe::charge() the same card later without asking the user for the card data again.
I'm still using it with your library, but now after the first payment succeeds I set
$token = [
'customer' => $model['customer'],
'payment_method' => $model['payment_method'],
];
$request->token = serialize($token);
In CaptureAction, I'm just adding
$model->offsetSet('return_url', $token->getTargetUrl());
in order to manage SCA authentication request. And this is all I need to create a new PaymentIntent. If no SCA is required again, that's it. If SCA il enforced, I created a new action so:
$redirectToScaPage = new RedirectToScaPage($paymentIntent->toArray());
$this->gateway->execute($redirectToScaPage);
redirects the user's browser to Stripe hosted authorization page which will manage it all for me. Then it goes back to return_url, the payment is captured and the order fulfilled.
Payum is not the easiest stuff to learn, but I'm getting to the grips with it.
@francesco-laricchia using Stripe JS Element through stripe_js
gateway is also possible I made a test project with your workflow and this work also well with or without SCA.
Here is the payment object I set (prepare.php
if we follow the original Payum doc):
use Payum\Core\Model\Payment;
$storage = $payum->getStorage(Payment::class);
/** @var Payment $payment */
$payment = $storage->create();
$payment->setNumber(uniqid());
$payment->setCurrencyCode('EUR');
$payment->setTotalAmount(123);
$payment->setDescription('A description');
$payment->setClientId('anId');
$payment->setClientEmail('foo@example.com');
$payment->setDetails([
'customer' => 'cus_123456',
'payment_method' => 'card_123456'
]);
$storage->update($payment);
Here is the twig overrides I build to handle your case :
{# templates/bundles/FluxSEPayumStripe/Action/pay.html.twig #}
{% extends "@!FluxSEPayumStripe/Action/pay.html.twig" %}
{% block payum_body %}
{{ parent() }}
<form action="{{ action_url|default('') }}" method="POST" name="payment-form" id="payment-form" data-secret="{{ model.client_secret }}">
<!-- We'll put the error messages in this element -->
<div id="card-errors" role="alert"></div>
</form>
{% endblock %}
{% block payum_javascripts_stripejs_common %}
<script type="text/javascript">
var stripe = Stripe('{{ publishable_key }}');
var form = document.getElementById('payment-form');
var showError = function(errorMsgText) {
var displayError = document.getElementById('card-errors');
displayError.textContent = errorMsgText;
};
stripe.confirmCardPayment(form.dataset['secret'], {
payment_method: {{ model.payment_method|json_encode|raw }}
}).then(function (result) {
if (result.error) {
showError(result.error.message);
} else {
// The payment has been processed!
var paymentIntent = result.paymentIntent;
if (paymentIntent.status === 'succeeded') {
// Show a success message to your customer
// There's a risk of the customer closing the window before callback
// execution. Set up a webhook or plugin to listen for the
// payment_intent.succeeded event that handles any business critical
// post-payment actions.
form.submit();
}
}
});
</script>
{% endblock %}
The SCA popup will be prompt if needed then the customer is redirected to the end of the Payum process.
So you have choices between using stripe checkout session portal or a pure Stripe JS implementation ;)
Hi, I'm migrating from legacy Payum/Stripe in order to comply to new SCA regulations. This is working beautifully with simple one-time payments, still I can't figure out how to charge a saved card.
Previously I just had to retrieve the "customer" token, I had stored on my db, and capture would charge the corresponding card. It looks like this library does not support this flow at all, yet.
I'm studyng Stripe docs and this is the point I reached:
then
In Postman, this does work.
Now I'm bashing my head on Payum docs and examples in order to understand how to achieve this. Any plan to implement this in this library?
EDIT: I've already set up my custom GatewayFactory which extends StripeCheckoutSessionGatewayFactory and started creating custom Actions.