';
+}
+
// Activate Payment Request API
if ($conf->global->MAIN_FEATURES_LEVEL >= 2) { // TODO Not used by current code
print '
';
diff --git a/htdocs/stripe/ajax/ajax.php b/htdocs/stripe/ajax/ajax.php
new file mode 100644
index 00000000000..e50b426ee87
--- /dev/null
+++ b/htdocs/stripe/ajax/ajax.php
@@ -0,0 +1,124 @@
+
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+/**
+ * \file htdocs/stripe/ajax/ajax.php
+ * \brief Ajax action for Stipe ie: Terminal
+ */
+
+if (!defined('NOCSRFCHECK')) {
+ define('NOCSRFCHECK', '1');
+}
+if (!defined('NOTOKENRENEWAL')) {
+ define('NOTOKENRENEWAL', '1');
+}
+if (!defined('NOREQUIREMENU')) {
+ define('NOREQUIREMENU', '1');
+}
+if (!defined('NOREQUIREHTML')) {
+ define('NOREQUIREHTML', '1');
+}
+if (!defined('NOREQUIREAJAX')) {
+ define('NOREQUIREAJAX', '1');
+}
+if (!defined('NOBROWSERNOTIF')) {
+ define('NOBROWSERNOTIF', '1');
+}
+
+require '../../main.inc.php'; // Load $user and permissions
+require_once DOL_DOCUMENT_ROOT.'/includes/stripe/stripe-php/init.php';
+require_once DOL_DOCUMENT_ROOT.'/stripe/class/stripe.class.php';
+require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
+
+$action = GETPOST('action', 'aZ09');
+$location = GETPOST('location', 'alphanohtml');
+$stripeacc = GETPOST('stripeacc', 'alphanohtml');
+$servicestatus = GETPOST('servicestatus', 'int');
+$amount = GETPOST('amount', 'int');
+
+if (empty($user->rights->takepos->run)) {
+ accessforbidden();
+}
+
+
+/*
+ * View
+ */
+
+if ($action == 'getConnexionToken') {
+ try {
+ // Be sure to authenticate the endpoint for creating connection tokens.
+ // Force to use the correct API key
+ global $stripearrayofkeysbyenv;
+ \Stripe\Stripe::setApiKey($stripearrayofkeysbyenv[$servicestatus]['secret_key']);
+ // The ConnectionToken's secret lets you connect to any Stripe Terminal reader
+ // and take payments with your Stripe account.
+ $array = array();
+ if (isset($location) && !empty($location)) $array['location'] = $location;
+ if (empty($stripeacc)) { // If the Stripe connect account not set, we use common API usage
+ $connectionToken = \Stripe\Terminal\ConnectionToken::create($array);
+ } else {
+ $connectionToken = \Stripe\Terminal\ConnectionToken::create($array, array("stripe_account" => $stripeacc));
+ }
+ echo json_encode(array('secret' => $connectionToken->secret));
+ } catch (Error $e) {
+ http_response_code(500);
+ echo json_encode(['error' => $e->getMessage()]);
+ }
+} elseif ($action == 'createPaymentIntent') {
+ try {
+ $json_str = file_get_contents('php://input');
+ $json_obj = json_decode($json_str);
+
+ // For Terminal payments, the 'payment_method_types' parameter must include
+ // 'card_present' and the 'capture_method' must be set to 'manual'
+ $object = new Facture($db);
+ $object->fetch($json_obj->invoiceid);
+ $object->fetch_thirdparty();
+
+ $fulltag='INV='.$object->id.'.CUS='.$object->thirdparty->id;
+ $tag=null;
+ $fulltag=dol_string_unaccent($fulltag);
+
+ $stripe = new Stripe($db);
+ $customer = $stripe->customerStripe($object->thirdparty, $stripeacc, $servicestatus, 1);
+
+ $intent = $stripe->getPaymentIntent($json_obj->amount, $object->multicurrency_code, null, 'Stripe payment: '.$fulltag.(is_object($object)?' ref='.$object->ref:''), $object, $customer, $stripeacc, $servicestatus, 1, 'terminal', false, null, 0, 1);
+
+ echo json_encode(array('client_secret' => $intent->client_secret));
+ } catch (Error $e) {
+ http_response_code(500);
+ echo json_encode(['error' => $e->getMessage()]);
+ }
+} elseif ($action == 'capturePaymentIntent') {
+ try {
+ // retrieve JSON from POST body
+ $json_str = file_get_contents('php://input');
+ $json_obj = json_decode($json_str);
+ if (empty($stripeacc)) { // If the Stripe connect account not set, we use common API usage
+ $intent = \Stripe\PaymentIntent::retrieve($json_obj->id);
+ } else {
+ $intent = \Stripe\PaymentIntent::retrieve($json_obj->id, array("stripe_account" => $stripeacc));
+ }
+ $intent = $intent->capture();
+
+ echo json_encode($intent);
+ } catch (Error $e) {
+ http_response_code(500);
+ echo json_encode(['error' => $e->getMessage()]);
+ }
+}
diff --git a/htdocs/stripe/class/stripe.class.php b/htdocs/stripe/class/stripe.class.php
index 36e67d2827c..b14ed0e8ca6 100644
--- a/htdocs/stripe/class/stripe.class.php
+++ b/htdocs/stripe/class/stripe.class.php
@@ -290,6 +290,34 @@ class Stripe extends CommonObject
return $stripepaymentmethod;
}
+ /**
+ * Get the Stripe reader Object from its ID
+ *
+ * @param string $reader Reader ID
+ * @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)
+ * @return \Stripe\Terminal\Reader|null Stripe Reader or null if not found
+ */
+ public function getSelectedReader($reader, $key = '', $status = 0)
+ {
+ $selectedreader = null;
+
+ try {
+ // Force to use the correct API key
+ global $stripearrayofkeysbyenv;
+ \Stripe\Stripe::setApiKey($stripearrayofkeysbyenv[$status]['secret_key']);
+ if (empty($key)) { // If the Stripe connect account not set, we use common API usage
+ $selectedreader = \Stripe\Terminal\Reader::retrieve(''.$reader.'');
+ } else {
+ $stripepaymentmethod = \Stripe\Terminal\Reader::retrieve(''.$reader.'', array("stripe_account" => $key));
+ }
+ } catch (Exception $e) {
+ $this->error = $e->getMessage();
+ }
+
+ return $selectedreader;
+ }
+
/**
* Get the Stripe payment intent. Create it with confirmnow=false
* Warning. If a payment was tried and failed, a payment intent was created.
@@ -350,7 +378,7 @@ class Stripe extends CommonObject
$paymentintent = null;
- if (is_object($object) && !empty($conf->global->STRIPE_REUSE_EXISTING_INTENT_IF_FOUND)) {
+ if (is_object($object) && !empty($conf->global->STRIPE_REUSE_EXISTING_INTENT_IF_FOUND) && empty($conf->global->STRIPE_CARD_PRESENT)) {
// 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 that does not change the idempotency key), reusing same payment intent is not allowed by Stripe.
// Recommended solution is to recreate a new payment intent each time we need one (old one will be automatically closed by Stripe after a delay), Stripe will
@@ -424,6 +452,9 @@ class Stripe extends CommonObject
if (!empty($conf->global->STRIPE_SOFORT)) {
$paymentmethodtypes[] = "sofort";
}
+ if (!empty($conf->global->STRIPE_CARD_PRESENT) && $mode == 'terminal') {
+ $paymentmethodtypes = array("card_present");
+ }
$dataforintent = array(
"confirm" => $confirmnow, // Do not confirm immediatly during creation of intent
@@ -456,6 +487,11 @@ class Stripe extends CommonObject
if (!empty($conf->global->STRIPE_KLARNA)) {
unset($dataforintent['setup_future_usage']);
}
+ if (!empty($conf->global->STRIPE_CARD_PRESENT) && $mode == 'terminal') {
+ unset($dataforintent['setup_future_usage']);
+ $dataforintent["capture_method"] = "manual";
+ $dataforintent["confirmation_method"] = "manual";
+ }
if (!is_null($payment_method)) {
$dataforintent["payment_method"] = $payment_method;
$description .= ' - '.$payment_method;
@@ -607,6 +643,9 @@ class Stripe extends CommonObject
if (!empty($conf->global->STRIPE_BANCONTACT)) {
$paymentmethodtypes[] = "bancontact";
}
+ if (!empty($conf->global->STRIPE_KLARNA)) {
+ $paymentmethodtypes[] = "klarna";
+ }
if (!empty($conf->global->STRIPE_IDEAL)) {
$paymentmethodtypes[] = "ideal";
}
diff --git a/htdocs/takepos/admin/terminal.php b/htdocs/takepos/admin/terminal.php
index f6562d81693..64ce74b6022 100644
--- a/htdocs/takepos/admin/terminal.php
+++ b/htdocs/takepos/admin/terminal.php
@@ -1,6 +1,7 @@
* Copyright (C) 2011-2017 Juanjo Menent
+ * Copyright (C) 2021 Thibault FOUCART
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -28,6 +29,7 @@ require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php';
require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
require_once DOL_DOCUMENT_ROOT."/core/lib/takepos.lib.php";
+require_once DOL_DOCUMENT_ROOT.'/stripe/class/stripe.class.php';
$terminal = GETPOST('terminal', 'int');
// If socid provided by ajax company selector
@@ -73,6 +75,9 @@ if (GETPOST('action', 'alpha') == 'set') {
$res = dolibarr_set_const($db, "CASHDESK_ID_BANKACCOUNT_CASH".$terminaltouse, (GETPOST('CASHDESK_ID_BANKACCOUNT_CASH'.$terminaltouse, 'alpha') > 0 ? GETPOST('CASHDESK_ID_BANKACCOUNT_CASH'.$terminaltouse, 'alpha') : ''), 'chaine', 0, '', $conf->entity);
$res = dolibarr_set_const($db, "CASHDESK_ID_BANKACCOUNT_CHEQUE".$terminaltouse, (GETPOST('CASHDESK_ID_BANKACCOUNT_CHEQUE'.$terminaltouse, 'alpha') > 0 ? GETPOST('CASHDESK_ID_BANKACCOUNT_CHEQUE'.$terminaltouse, 'alpha') : ''), 'chaine', 0, '', $conf->entity);
$res = dolibarr_set_const($db, "CASHDESK_ID_BANKACCOUNT_CB".$terminaltouse, (GETPOST('CASHDESK_ID_BANKACCOUNT_CB'.$terminaltouse, 'alpha') > 0 ? GETPOST('CASHDESK_ID_BANKACCOUNT_CB'.$terminaltouse, 'alpha') : ''), 'chaine', 0, '', $conf->entity);
+ if (!empty($conf->stripe->enabled) && !empty($conf->global->STRIPE_CARD_PRESENT)) {
+ $res = dolibarr_set_const($db, "CASHDESK_ID_BANKACCOUNT_STRIPETERMINAL".$terminaltouse, GETPOST('CASHDESK_ID_BANKACCOUNT_STRIPETERMINAL'.$terminaltouse, 'alpha'), 'chaine', 0, '', $conf->entity);
+ }
if (!empty($conf->global->TAKEPOS_ENABLE_SUMUP)) {
$res = dolibarr_set_const($db, "CASHDESK_ID_BANKACCOUNT_SUMUP".$terminaltouse, (GETPOST('CASHDESK_ID_BANKACCOUNT_SUMUP'.$terminaltouse, 'alpha') > 0 ? GETPOST('CASHDESK_ID_BANKACCOUNT_SUMUP'.$terminaltouse, 'alpha') : ''), 'chaine', 0, '', $conf->entity);
}
@@ -174,6 +179,44 @@ if (!empty($conf->banque->enabled)) {
$atleastonefound++;
}
print '