From bc2a949bab5aae13a21eb915772c23f17017dbc3 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 31 Oct 2019 16:47:27 +0100 Subject: [PATCH] New Add option to disable idempotency when using Stripe payments. --- htdocs/public/payment/newpayment.php | 8 ++++++-- htdocs/stripe/class/stripe.class.php | 25 ++++++++++++++----------- htdocs/stripe/config.php | 2 +- 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/htdocs/public/payment/newpayment.php b/htdocs/public/payment/newpayment.php index 067c371bf67..4a3d08f6602 100644 --- a/htdocs/public/payment/newpayment.php +++ b/htdocs/public/payment/newpayment.php @@ -1725,6 +1725,7 @@ if ($action != 'dopayment') { // If STRIPE_PICTO_FOR_PAYMENT is 'cb' we show a picto of a crdit card instead of stripe print '
'; + print ''; print '
'; print ''.$langs->trans("CreditOrDebitCard").''; print '
'; @@ -1858,12 +1859,12 @@ if (preg_match('/^dopayment/', $action)) // If we choosed/click on the payment $service = 'StripeLive'; $servicestatus = 1; - if (empty($conf->global->STRIPE_LIVE) || GETPOST('forcesandbox', 'alpha')) { $service = 'StripeTest'; $servicestatus = 0; } + $stripe = new Stripe($db); $stripeacc = $stripe->getStripeAccount($service); $stripecu = null; @@ -1871,7 +1872,10 @@ if (preg_match('/^dopayment/', $action)) // If we choosed/click on the payment if (! empty($conf->global->STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION)) { - $paymentintent=$stripe->getPaymentIntent($amount, $currency, $tag, 'Stripe payment: '.$fulltag.(is_object($object)?' ref='.$object->ref:''), $object, $stripecu, $stripeacc, $servicestatus); + $noidempotency_key = (GETPOSTISSET('noidempotency') ? GETPOST('noidempotency', 'int') : 0); // By default noidempotency is unset, so we must use a different tag/ref for each payment. If set, we can pay several times the same tag/ref. + $paymentintent=$stripe->getPaymentIntent($amount, $currency, $tag, 'Stripe payment: '.$fulltag.(is_object($object)?' ref='.$object->ref:''), $object, $stripecu, $stripeacc, $servicestatus, 0, 'automatic', false, null, 0, $noidempotency_key); + // The paymentintnent has status 'requires_payment_method' (even if paymentintent was already payed) + //var_dump($paymentintent); if ($stripe->error) setEventMessages($stripe->error, null, 'errors'); } } diff --git a/htdocs/stripe/class/stripe.class.php b/htdocs/stripe/class/stripe.class.php index 021a9fac1f9..c30e3169ee5 100644 --- a/htdocs/stripe/class/stripe.class.php +++ b/htdocs/stripe/class/stripe.class.php @@ -318,9 +318,10 @@ class Stripe extends CommonObject * @param boolean $confirmnow false=default, true=try to confirm immediatly after create (if conditions are ok) * @param string $payment_method 'pm_....' (if known) * @param string $off_session If we use an already known payment method to pay off line. + * @param string $noidempotency_key Do not use the idempotency_key when creating the PaymentIntent * @return \Stripe\PaymentIntent|null Stripe PaymentIntent or null if not found and failed to create */ - public function getPaymentIntent($amount, $currency_code, $tag, $description = '', $object = null, $customer = null, $key = null, $status = 0, $usethirdpartyemailforreceiptemail = 0, $mode = 'automatic', $confirmnow = false, $payment_method = null, $off_session = 0) + public function getPaymentIntent($amount, $currency_code, $tag, $description = '', $object = null, $customer = null, $key = null, $status = 0, $usethirdpartyemailforreceiptemail = 0, $mode = 'automatic', $confirmnow = false, $payment_method = null, $off_session = 0, $noidempotency_key = 0) { global $conf; @@ -352,9 +353,10 @@ class Stripe extends CommonObject if (is_object($object)) { // Warning. If a payment was tried and failed, a payment intent was created. - // But if we change someting on object to pay (amount or other), reusing same payment intent is not allowed. - // Recommanded solution is to recreate a new payment intent each time we need one (old one will be automatically closed after a delay), - // that's why i comment the part of code to retreive a payment intent with object id (never mind if we cumulate payment intent with old that will not be used) + // But if we change someting on object to pay (amount or other that does not change the idempotency key), reusing same payment intent is not allowed. + // Recommanded solution is to recreate a new payment intent each time we need one (old one will be automatically closed after a delay), Stripe will + // automatically return the existing payment intent if idempotency is provided when we try to create the new one. + // That's why we can comment the part of code to retreive a payment intent with object id (never mind if we cumulate payment intent with old ones that will not be used) /* $sql = "SELECT pi.ext_payment_id, pi.entity, pi.fk_facture, pi.sourcetype, pi.ext_payment_site"; $sql.= " FROM " . MAIN_DB_PREFIX . "prelevement_facture_demande as pi"; @@ -445,14 +447,15 @@ class Stripe extends CommonObject global $stripearrayofkeysbyenv; \Stripe\Stripe::setApiKey($stripearrayofkeysbyenv[$status]['secret_key']); - // Note: If all data for payment intent are same than a previous on, even if we use 'create', Stripe will return ID of the old existing payment intent. - if (empty($key)) { // If the Stripe connect account not set, we use common API usage - $paymentintent = \Stripe\PaymentIntent::create($dataforintent, array("idempotency_key" => "$description")); - //$paymentintent = \Stripe\PaymentIntent::create($dataforintent, array()); - } else { - $paymentintent = \Stripe\PaymentIntent::create($dataforintent, array("idempotency_key" => "$description", "stripe_account" => $key)); - //$paymentintent = \Stripe\PaymentIntent::create($dataforintent, array("stripe_account" => $key)); + $arrayofoptions = array(); + if (empty($noidempotency_key)) { + $arrayofoptions["idempotency_key"] = $description; } + // Note: If all data for payment intent are same than a previous on, even if we use 'create', Stripe will return ID of the old existing payment intent. + if (! empty($key)) { // If the Stripe connect account not set, we use common API usage + $arrayofoptions["stripe_account"] = $key; + } + $paymentintent = \Stripe\PaymentIntent::create($dataforintent, $arrayofoptions); // Store the payment intent if (is_object($object)) diff --git a/htdocs/stripe/config.php b/htdocs/stripe/config.php index 0030bdb5535..1070f605eb8 100644 --- a/htdocs/stripe/config.php +++ b/htdocs/stripe/config.php @@ -28,7 +28,7 @@ require_once DOL_DOCUMENT_ROOT.'/includes/stripe/init.php'; require_once DOL_DOCUMENT_ROOT.'/includes/stripe/lib/Stripe.php'; -global $stripe; +//global $stripe; global $conf; global $stripearrayofkeysbyenv;