New Add option to disable idempotency when using Stripe payments.

This commit is contained in:
Laurent Destailleur 2019-10-31 16:47:27 +01:00
parent 607c38775d
commit bc2a949bab
3 changed files with 21 additions and 14 deletions

View File

@ -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 '<br><div class="button buttonpayment" id="div_dopayment_stripe"><span class="fa fa-credit-card"></span> <input class="" type="submit" id="dopayment_stripe" name="dopayment_stripe" value="'.$langs->trans("StripeDoPayment").'">';
print '<input type="hidden" name="noidempotency" value="'.GETPOST('noidempotency', 'int').'">';
print '<br>';
print '<span class="buttonpaymentsmall">'.$langs->trans("CreditOrDebitCard").'</span>';
print '</div>';
@ -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');
}
}

View File

@ -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))

View File

@ -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;