From 8e836155338a47e6831760724e9d33141627b8dd Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Fri, 13 Sep 2019 18:52:35 +0200 Subject: [PATCH] Add method getSetupIntent --- htdocs/stripe/class/stripe.class.php | 148 ++++++++++++++++++++++++++- 1 file changed, 146 insertions(+), 2 deletions(-) diff --git a/htdocs/stripe/class/stripe.class.php b/htdocs/stripe/class/stripe.class.php index 9defab81a73..9c0bc9ebae3 100644 --- a/htdocs/stripe/class/stripe.class.php +++ b/htdocs/stripe/class/stripe.class.php @@ -293,7 +293,7 @@ class Stripe extends CommonObject } /** - * Get the Stripe payment intent. Create it with confirm=false + * Get the Stripe payment intent. Create it with confirmnow=false * Warning. If a payment was tried and failed, a payment intent was created. * But if we change something 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), @@ -312,7 +312,7 @@ class Stripe extends CommonObject * @param int $usethirdpartyemailforreceiptemail 1=use thirdparty email for receipt * @param int $mode automatic=automatic confirmation/payment when conditions are ok, manual=need to call confirm() on intent * @param boolean $confirmnow false=default, true=try to confirm immediatly after create (if conditions are ok) - * @return \Stripe\PaymentIntent|null Stripe PaymentIntent or null if not found + * @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) { @@ -503,6 +503,149 @@ class Stripe extends CommonObject } } + + /** + * Get the Stripe payment intent. Create it with confirmnow=false + * Warning. If a payment was tried and failed, a payment intent was created. + * But if we change something 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 ones that will not be used) + * Note: This is used when option STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION is on when making a payment from the public/payment/newpayment.php page + * but not when using the STRIPE_USE_NEW_CHECKOUT. + * + * @param string $description Description + * @param Societe $object Object to pay with Stripe + * @param string $customer Stripe customer ref 'cus_xxxxxxxxxxxxx' via customerStripe() + * @param string $key ''=Use common API. If not '', it is the Stripe connect account 'acc_....' to use Stripe connect + * @param int $status Status (0=test, 1=live) + * @param int $usethirdpartyemailforreceiptemail 1=use thirdparty email for receipt + * @param boolean $confirmnow false=default, true=try to confirm immediatly after create (if conditions are ok) + * @return \Stripe\SetupIntent|null Stripe SetupIntent or null if not found and failed to create + */ + public function getSetupIntent($description, $object, $customer, $key, $status, $usethirdpartyemailforreceiptemail = 0, $confirmnow = false) + { + global $conf; + + dol_syslog("getSetupIntent", LOG_INFO, 1); + + $error = 0; + + if (empty($status)) $service = 'StripeTest'; + else $service = 'StripeLive'; + + $setupintent = null; + + if (empty($setupintent)) + { + $ipaddress=getUserRemoteIP(); + $metadata = array('dol_version'=>DOL_VERSION, 'dol_entity'=>$conf->entity, 'ipaddress'=>$ipaddress); + if (is_object($object)) + { + $metadata['dol_type'] = $object->element; + $metadata['dol_id'] = $object->id; + if (is_object($object->thirdparty) && $object->thirdparty->id > 0) $metadata['dol_thirdparty_id'] = $object->thirdparty->id; + } + + $dataforintent = array( + "confirm" => $confirmnow, // Do not confirm immediatly during creation of intent + "payment_method_types" => array("card"), + "description" => $description, + "usage" => "off_session", + "metadata" => $metadata + ); + if (! is_null($customer)) $dataforintent["customer"]=$customer; + // payment_method = + // payment_method_types = array('card') + //var_dump($dataforintent); + + if ($usethirdpartyemailforreceiptemail && is_object($object) && $object->thirdparty->email) + { + $dataforintent["receipt_email"] = $object->thirdparty->email; + } + + try { + // Force to use the correct API key + 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 + //$setupintent = \Stripe\SetupIntent::create($dataforintent, array("idempotency_key" => "$description")); + $setupintent = \Stripe\SetupIntent::create($dataforintent, array()); + } else { + //$setupintent = \Stripe\SetupIntent::create($dataforintent, array("idempotency_key" => "$description", "stripe_account" => $key)); + $setupintent = \Stripe\SetupIntent::create($dataforintent, array("stripe_account" => $key)); + } + //var_dump($setupintent->id); + + // Store the setup intent + /*if (is_object($object)) + { + $setupintentalreadyexists = 0; + // Check that payment intent $setupintent->id is not already recorded. + $sql = "SELECT pi.rowid"; + $sql.= " FROM " . MAIN_DB_PREFIX . "prelevement_facture_demande as pi"; + $sql.= " WHERE pi.entity IN (".getEntity('societe').")"; + $sql.= " AND pi.ext_payment_site = '" . $service . "'"; + $sql.= " AND pi.ext_payment_id = '".$this->db->escape($setupintent->id)."'"; + + dol_syslog(get_class($this) . "::getPaymentIntent search if payment intent already in prelevement_facture_demande", LOG_DEBUG); + $resql = $this->db->query($sql); + if ($resql) { + $num = $this->db->num_rows($resql); + if ($num) + { + $obj = $this->db->fetch_object($resql); + if ($obj) $setupintentalreadyexists++; + } + } + else dol_print_error($this->db); + + // If not, we create it. + if (! $setupintentalreadyexists) + { + $now=dol_now(); + $sql = "INSERT INTO " . MAIN_DB_PREFIX . "prelevement_facture_demande (date_demande, fk_user_demande, ext_payment_id, fk_facture, sourcetype, entity, ext_payment_site)"; + $sql .= " VALUES ('".$this->db->idate($now)."', '0', '".$this->db->escape($setupintent->id)."', ".$object->id.", '".$this->db->escape($object->element)."', " . $conf->entity . ", '" . $service . "')"; + $resql = $this->db->query($sql); + if (! $resql) + { + $error++; + $this->error = $this->db->lasterror(); + dol_syslog(get_class($this) . "::PaymentIntent failed to insert paymentintent with id=".$setupintent->id." into database."); + } + } + } + else + { + $_SESSION["stripe_setup_intent"] = $setupintent; + }*/ + } + catch(Exception $e) + { + /*var_dump($dataforintent); + var_dump($description); + var_dump($key); + var_dump($setupintent); + var_dump($e->getMessage());*/ + $error++; + $this->error = $e->getMessage(); + } + } + + dol_syslog("getSetupIntent return error=".$error, LOG_INFO, -1); + + if (! $error) + { + return $setupintent; + } + else + { + return null; + } + } + + /** * Get the Stripe card of a company payment mode (with option to create it on Stripe if not linked yet) * @@ -609,6 +752,7 @@ class Stripe extends CommonObject /** * Create charge with public/payment/newpayment.php, stripe/card.php, cronjobs or REST API + * This is using old Stripe API charge. * * @param int $amount Amount to pay * @param string $currency EUR, GPB...