dolibarr 25.0.0-alpha
charge.php
1<?php
2/* Copyright (C) 2018-2022 Thibault FOUCART <support@ptibogxiv.net>
3 * Copyright (C) 2019-2025 Frédéric France <frederic.france@free.fr>
4 * Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
5 * Copyright (C) 2026 Jose Martinez <jose.martinez@pichinov.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
21// Put here all includes required by your class file
22
23// Load Dolibarr environment
24require '../main.inc.php';
32require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php';
33require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php';
34require_once DOL_DOCUMENT_ROOT.'/stripe/class/stripe.class.php';
35//require_once DOL_DOCUMENT_ROOT.'/core/lib/stripe.lib.php';
36require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php';
37require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
38require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
39if (isModEnabled('accounting')) {
40 require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountingjournal.class.php';
41}
42
43// Load translation files required by the page
44$langs->loadLangs(array('compta', 'salaries', 'bills', 'hrm', 'stripe'));
45
46// Security check
47$socid = GETPOSTINT("socid");
48if ($user->socid) {
49 $socid = $user->socid;
50}
51//restrictedArea($user, 'salaries', '', '', '');
52
53$limit = GETPOSTINT('limit') ? GETPOSTINT('limit') : $conf->liste_limit;
54$rowid = GETPOST("rowid", 'alpha');
55$sortfield = GETPOST('sortfield', 'aZ09comma');
56$sortorder = GETPOST('sortorder', 'aZ09comma');
57$page = GETPOSTISSET('pageplusone') ? (GETPOSTINT('pageplusone') - 1) : GETPOSTINT("page");
58if (empty($page) || $page == -1) {
59 $page = 0;
60} // If $page is not defined, or '' or -1
61$offset = $limit * $page;
62$pageprev = $page - 1;
63$pagenext = $page + 1;
64
65$result = restrictedArea($user, 'banque');
66$optioncss = GETPOST('optioncss', 'alpha');
67
68
69/*
70 * View
71 */
72
73$form = new Form($db);
74$societestatic = new Societe($db);
75$memberstatic = new Adherent($db);
76$acc = new Account($db);
77$stripe = new Stripe($db);
78
79llxHeader('', $langs->trans("StripeChargeList"));
80
81if (isModEnabled('stripe') && (!getDolGlobalString('STRIPE_LIVE')/* || GETPOST('forcesandbox', 'alpha') */)) {
82 $service = 'StripeTest';
83 $servicestatus = '0';
84 dol_htmloutput_mesg($langs->trans('YouAreCurrentlyInSandboxMode', 'Stripe'), [], 'warning');
85} else {
86 $service = 'StripeLive';
87 $servicestatus = '1';
88}
89
90$stripeacc = $stripe->getStripeAccount($service);
91/*if (empty($stripeaccount))
92{
93 print $langs->trans('ErrorStripeAccountNotDefined');
94}*/
95
96if (!$rowid) {
97 $option = array('limit' => $limit + 1);
98 $num = 0;
99
100 $param = '';
101 $totalnboflines = '';
102 $moreforfilter = '';
103 $list = null;
104 if (GETPOSTISSET('starting_after_'.$page)) {
105 $option['starting_after'] = GETPOST('starting_after_'.$page, 'alphanohtml');
106 }
107 print '<form method="POST" action="'.dolBuildUrl($_SERVER["PHP_SELF"]).'">';
108 if ($optioncss != '') {
109 print '<input type="hidden" name="optioncss" value="'.$optioncss.'">';
110 }
111
112 print '<input type="hidden" name="token" value="'.newToken().'">';
113 print '<input type="hidden" name="formfilteraction" id="formfilteraction" value="list">';
114 print '<input type="hidden" name="action" value="list">';
115 print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
116 print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
117 print '<input type="hidden" name="page" value="'.$page.'">';
118
119 $title = $langs->trans("StripeChargeList");
120 $title .= $form->textwithpicto('', $stripeacc ? ' (Stripe connection with Stripe OAuth Connect account '.$stripeacc.')' : ' (Stripe connection with keys from Stripe module setup)');
121
122 print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num, $totalnboflines, 'title_accountancy.png', 0, '', 'hidepaginationprevious', $limit);
123
124 $hookmanager->initHooks(array('stripechargelist'));
125
126 print '<div class="div-table-responsive">';
127 print '<table class="tagtable liste'.($moreforfilter ? " listwithfilterbefore" : "").'">'."\n";
128
129 print '<tr class="liste_titre">';
130 print_liste_field_titre("StripePaymentId", $_SERVER["PHP_SELF"], "", "", "", "", $sortfield, $sortorder);
131 print_liste_field_titre("StripeCustomerId", $_SERVER["PHP_SELF"], "", "", "", "", $sortfield, $sortorder);
132 print_liste_field_titre("Customer", $_SERVER["PHP_SELF"], "", "", "", "", $sortfield, $sortorder);
133 print_liste_field_titre("Origin", $_SERVER["PHP_SELF"], "", "", "", "", $sortfield, $sortorder);
134 print_liste_field_titre("Description", $_SERVER["PHP_SELF"], "", "", "", "", $sortfield, $sortorder);
135 print_liste_field_titre("DatePayment", $_SERVER["PHP_SELF"], "", "", "", '', $sortfield, $sortorder, 'center ');
136 print_liste_field_titre("Type", $_SERVER["PHP_SELF"], "", "", "", '', $sortfield, $sortorder, 'left ');
137 print_liste_field_titre("Paid", $_SERVER["PHP_SELF"], "", "", "", '', $sortfield, $sortorder, 'right ');
138 print_liste_field_titre("Status", $_SERVER["PHP_SELF"], "", "", "", '', '', '', 'center ');
139 print "</tr>\n";
140
141 try {
142 if ($stripeacc) {
143 $list = \Stripe\Charge::all($option, array("stripe_account" => $stripeacc));
144 } else {
145 $list = \Stripe\Charge::all($option);
146 }
147
148 '@phan-var-force \Stripe\Charge $list'; // TStripeObject suggested, but is a template
149 $num = count($list->data);
150
151
152 //if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) $param .= '&contextpage='.urlencode($contextpage);
153 if ($limit > 0 && $limit != $conf->liste_limit) {
154 $param .= '&limit='.((int) $limit);
155 }
156 $param .= '&starting_after_'.($page + 1).'='.$list->data[($limit - 1)]->id;
157 //$param.='&ending_before_'.($page+1).'='.$list->data[($limit-1)]->id;
158 } catch (Exception $e) {
159 print '<tr><td colspan="9">'.$e->getMessage().'</td></td>';
160 }
161
162 //print $list;
163 $i = 0;
164 if (!empty($list)) {
165 foreach ($list->data as $charge) {
166 '@phan-var-force \Stripe\Charge $charge'; // TStripeObject suggested, but is a template
167 if ($i >= $limit) {
168 break;
169 }
170
171 $label = '';
172 if ($charge->refunded == '1') {
173 $status = img_picto($langs->trans("refunded"), 'statut6');
174 } elseif ($charge->paid == '1') {
175 $status = img_picto($langs->trans((string) $charge->status), 'statut4');
176 } elseif (empty($charge->failure_message)) {
177 $label .= $langs->trans("Network").": ".$charge->outcome->network_status."<br>";
178 $label .= $langs->trans("Status").": ".$langs->trans((string) $charge->outcome->seller_message);
179 $status = $form->textwithpicto(img_picto($langs->trans((string) $charge->status), 'statut4'), $label, 1);
180 } else {
181 $label .= $langs->trans("Error").": ".$charge->failure_message."<br>";
182 $label .= $langs->trans("Network").": ".$charge->outcome->network_status."<br>";
183 $label .= $langs->trans("Status").": ".$langs->trans((string) $charge->outcome->seller_message);
184 $status = $form->textwithpicto(img_picto($langs->trans((string) $charge->status), 'statut8'), $label, 1);
185 }
186
187 if (isset($charge->payment_method_details->type) && $charge->payment_method_details->type == 'card') {
188 $type = $langs->trans("card");
189 } elseif (isset($charge->source->type) && $charge->source->type == 'card') {
190 $type = $langs->trans("card");
191 } elseif (isset($charge->payment_method_details->type) && $charge->payment_method_details->type == 'three_d_secure') {
192 $type = $langs->trans("card3DS");
193 } elseif (isset($charge->payment_method_details->type) && $charge->payment_method_details->type == 'sepa_debit') {
194 $type = $langs->trans("sepadebit");
195 } elseif (isset($charge->payment_method_details->type) && $charge->payment_method_details->type == 'ideal') {
196 $type = $langs->trans("iDEAL");
197 } else {
198 $type = '';
199 }
200
201 // Why this ?
202 /*if (!empty($charge->payment_intent)) {
203 if (empty($stripeacc)) { // If the Stripe connect account not set, we use common API usage
204 $charge = \Stripe\PaymentIntent::retrieve($charge->payment_intent);
205 } else {
206 $charge = \Stripe\PaymentIntent::retrieve($charge->payment_intent, array("stripe_account" => $stripeacc));
207 }
208 }*/
209
210 // The metadata FULLTAG is defined by the online payment page
211 $FULLTAG = $charge->metadata->FULLTAG;
212
213 // Save into $tmparray all metadata
214 $tmparray = dolExplodeIntoArray($FULLTAG, '.', '=');
215 // Load origin object according to metadata
216 if (!empty($tmparray['CUS']) && (int) $tmparray['CUS'] > 0) {
217 $societestatic->fetch((int) $tmparray['CUS']);
218 } elseif (!empty($charge->metadata->dol_thirdparty_id) && $charge->metadata->dol_thirdparty_id > 0) {
219 $societestatic->fetch($charge->metadata->dol_thirdparty_id);
220 } else {
221 $societestatic->id = 0;
222 }
223 if (!empty($tmparray['MEM']) && (int) $tmparray['MEM'] > 0) {
224 $memberstatic->fetch((int) $tmparray['MEM']);
225 } else {
226 $memberstatic->id = 0;
227 }
228
229 print '<tr class="oddeven">';
230
231 if (!empty($stripeacc)) {
232 $connect = $stripeacc.'/';
233 } else {
234 $connect = '';
235 }
236
237 // Ref
238 $url = 'https://dashboard.stripe.com/'.$connect.'test/payments/'.$charge->id;
239 if ($servicestatus) {
240 $url = 'https://dashboard.stripe.com/'.$connect.'payments/'.$charge->id;
241 }
242 print '<td class="tdoverflowmax150">';
243 print "<a href='".$url."' target='_stripe'>".img_picto($langs->trans('ShowInStripe'), 'globe')." ".$charge->id."</a>";
244 if ($charge->payment_intent) {
245 print '<br><span class="opacitymedium">'.$charge->payment_intent.'</span>';
246 }
247 print "</td>\n";
248
249 // Stripe customer
250 print '<td class="tdoverflowmax150">';
251 if (isModEnabled('stripe') && !empty($stripeacc)) {
252 $connect = $stripeacc.'/';
253 }
254 $url = 'https://dashboard.stripe.com/'.$connect.'test/customers/'.$charge->customer;
255 if ($servicestatus) {
256 $url = 'https://dashboard.stripe.com/'.$connect.'customers/'.$charge->customer;
257 }
258 if (!empty($charge->customer)) {
259 print '<a href="'.$url.'" target="_stripe">'.img_picto($langs->trans('ShowInStripe'), 'globe').' '.$charge->customer.'</a>';
260 }
261 print "</td>\n";
262
263 // Customer
264 print '<td class="tdoverflowmax200">';
265 // Allow a module to fill this cell (e.g. charges without Dolibarr metadata)
266 $parameters = array('charge' => $charge, 'field' => 'customer');
267 $reshook = $hookmanager->executeHooks('printStripeChargeField', $parameters);
268 print $hookmanager->resPrint;
269 if ($reshook <= 0) {
270 if ($societestatic->id > 0) {
271 print $societestatic->getNomUrl(1);
272 } elseif ($memberstatic->id > 0) {
273 print $memberstatic->getNomUrl(1);
274 }
275 }
276 print "</td>\n";
277
278 // Origin
279 print '<td class="nowraponall">';
280 $parameters = array('charge' => $charge, 'field' => 'origin');
281 $reshook = $hookmanager->executeHooks('printStripeChargeField', $parameters);
282 print $hookmanager->resPrint;
283 if ($reshook <= 0) {
284 if ($charge->metadata->dol_type == "order" || $charge->metadata->dol_type == "commande") {
285 $object = new Commande($db);
286 $object->fetch($charge->metadata->dol_id);
287 if ($object->id > 0) {
288 print "<a href='".DOL_URL_ROOT."/commande/card.php?id=".$object->id."'>".img_picto('', 'order')." ".$object->ref."</a>";
289 } else {
290 print $FULLTAG;
291 }
292 } elseif ($charge->metadata->dol_type == "invoice" || $charge->metadata->dol_type == "facture") {
293 $object = new Facture($db);
294 $object->fetch($charge->metadata->dol_id);
295 if ($object->id > 0) {
296 print "<a href='".DOL_URL_ROOT."/compta/facture/card.php?facid=".$charge->metadata->dol_id."'>".img_picto('', 'bill')." ".$object->ref."</a>";
297 } else {
298 print $FULLTAG;
299 }
300 } else {
301 print $FULLTAG;
302 }
303 }
304 print "</td>\n";
305
306 // Description
307 print '<td class="tdoverflowmax200" title="'.dol_escape_htmltag($charge->description).'">'.dol_escape_htmltag($charge->description).'</td>'."\n";
308
309 // Date payment
310 print '<td class="center nowraponall">'.dol_print_date($charge->created, 'dayhour')."</td>\n";
311 // Type
312 print '<td>';
313 print $type;
314 print '</td>';
315 // Amount
316 print '<td class="right"><span class="amount">'.price(($charge->amount - $charge->amount_refunded) / 100, 0, '', 1, - 1, - 1, strtoupper($charge->currency))."</span></td>";
317 // Status
318 print '<td class="nowraponall center">';
319 print $status;
320 print "</td>\n";
321
322 print "</tr>\n";
323
324 $i++;
325 }
326 }
327
328 print '</table>';
329 print '</div>';
330 print '</form>';
331}
332
333// End of page
334llxFooter();
335$db->close();
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
llxFooter($comment='', $zone='private', $disabledoutputofmessages=0)
Empty footer.
Definition wrapper.php:91
if(!defined('NOREQUIRESOC')) if(!defined( 'NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined( 'NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined( 'NOREQUIREAJAX')) llxHeader($head='', $title='', $help_url='', $target='', $disablejs=0, $disablehead=0, $arrayofjs='', $arrayofcss='', $morequerystring='', $morecssonbody='', $replacemainareaby='', $disablenofollow=0, $disablenoindex=0)
Empty header.
Definition wrapper.php:73
Class to manage bank accounts.
Class to manage members of a foundation.
Class to manage customers orders.
Class to manage invoices.
Class to manage generation of HTML components Only common components must be here.
Class to manage third parties objects (customers, suppliers, prospects...)
Stripe class @TODO No reason to extend CommonObject.
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
dolExplodeIntoArray($string, $delimiter=';', $kv='=')
Split a string with 2 keys into key array.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0, $nodefault=0)
Return value of a param into GET or POST supervariable.
GETPOSTINT($paramname, $method=0, $nodefault=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
GETPOSTISSET($paramname)
Return true if we are in a context of submitting the parameter $paramname from a POST of a form.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
print_liste_field_titre($name, $file="", $field="", $begin="", $param="", $moreattrib="", $sortfield="", $sortorder="", $prefix="", $tooltip="", $forcenowrapcolumntitle=0)
Show title line of an array.
dol_htmloutput_mesg($mesgstring='', $mesgarray=array(), $style='ok', $keepembedded=0)
Print formatted messages to output (Used to show messages on html output).
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Definition html.lib.php:181
restrictedArea(User $user, $features, $object=0, $tableandshare='', $feature2='', $dbt_keyfield='fk_soc', $dbt_select='rowid', $isdraft=0, $nodie=0, $mode='')
Check permissions of a user to show a page and an object.