diff --git a/htdocs/accountancy/admin/journals_list.php b/htdocs/accountancy/admin/journals_list.php index 620a7786310..7612e7b261a 100644 --- a/htdocs/accountancy/admin/journals_list.php +++ b/htdocs/accountancy/admin/journals_list.php @@ -177,6 +177,11 @@ if (GETPOST('actionadd') || GETPOST('actionmodify')) $msg .= $langs->transnoentities('ErrorFieldFormat', $langs->transnoentities('Code')).'
'; }*/ } + if (! GETPOST('label','alpha')) + { + setEventMessages($langs->transnoentities("ErrorFieldRequired", $langs->transnoentitiesnoconv("Label")), null, 'errors'); + $ok=0; + } // Clean some parameters if ($_POST["accountancy_code"] <= 0) $_POST["accountancy_code"]=''; // If empty, we force to null @@ -208,7 +213,7 @@ if (GETPOST('actionadd') || GETPOST('actionmodify')) if ($tabrowid[$id] && ! in_array($tabrowid[$id],$listfieldinsert)) $sql.= $tabrowid[$id].","; $sql.= $tabfieldinsert[$id]; - $sql.=",active)"; + $sql.=",active,entity)"; $sql.= " VALUES("; // List of values @@ -221,11 +226,11 @@ if (GETPOST('actionadd') || GETPOST('actionmodify')) $_POST[$listfieldvalue[$i]] = $conf->entity; } if ($i) $sql.=","; - if ($_POST[$listfieldvalue[$i]] == '' && ! ($listfieldvalue[$i] == 'code' && $id == 10)) $sql.="null"; // For vat, we want/accept code = '' + if ($_POST[$listfieldvalue[$i]] == '') $sql.="null"; // For vat, we want/accept code = '' else $sql.="'".$db->escape($_POST[$listfieldvalue[$i]])."'"; $i++; } - $sql.=",1)"; + $sql.=",1,".$conf->entity.")"; dol_syslog("actionadd", LOG_DEBUG); $result = $db->query($sql); @@ -275,6 +280,7 @@ if (GETPOST('actionadd') || GETPOST('actionmodify')) $i++; } $sql.= " WHERE ".$rowidcol." = '".$rowid."'"; + $sql.=" AND entity = ".$conf->entity; dol_syslog("actionmodify", LOG_DEBUG); //print $sql; @@ -298,6 +304,7 @@ if ($action == 'confirm_delete' && $confirm == 'yes') // delete else { $rowidcol="rowid"; } $sql = "DELETE from ".$tabname[$id]." WHERE ".$rowidcol."='".$rowid."'"; + $sql.=" AND entity = ".$conf->entity; dol_syslog("delete", LOG_DEBUG); $result = $db->query($sql); @@ -326,6 +333,7 @@ if ($action == $acts[0]) elseif ($code) { $sql = "UPDATE ".$tabname[$id]." SET active = 1 WHERE code='".$code."'"; } + $sql.=" AND entity = ".$conf->entity; $result = $db->query($sql); if (!$result) @@ -346,6 +354,7 @@ if ($action == $acts[1]) elseif ($code) { $sql = "UPDATE ".$tabname[$id]." SET active = 0 WHERE code='".$code."'"; } + $sql.=" AND entity = ".$conf->entity; $result = $db->query($sql); if (!$result) @@ -389,13 +398,7 @@ if ($id) { // Complete requete recherche valeurs avec critere de tri $sql=$tabsql[$id]; - - if ($search_country_id > 0) - { - if (preg_match('/ WHERE /',$sql)) $sql.= " AND "; - else $sql.=" WHERE "; - $sql.= " c.rowid = ".$search_country_id; - } + $sql.= " WHERE a.entity = ".$conf->entity; if ($sortfield) { @@ -416,7 +419,6 @@ if ($id) } $sql.=$tabsqlsort[$id]; $sql.=$db->plimit($listlimit+1,$offset); - //print $sql; $fieldlist=explode(',',$tabfield[$id]); diff --git a/htdocs/accountancy/class/bookkeeping.class.php b/htdocs/accountancy/class/bookkeeping.class.php index b59258f6cd7..16f40139a38 100644 --- a/htdocs/accountancy/class/bookkeeping.class.php +++ b/htdocs/accountancy/class/bookkeeping.class.php @@ -48,7 +48,7 @@ class BookKeeping extends CommonObject */ public $table_element = 'accounting_bookkeeping'; - public $entity = 1; + public $entity; /** * @var BookKeepingLine[] Lines @@ -295,7 +295,7 @@ class BookKeeping extends CommonObject $sql .= ",'" . $this->db->escape($this->code_journal) . "'"; $sql .= ",'" . $this->db->escape($this->journal_label) . "'"; $sql .= "," . $this->db->escape($this->piece_num); - $sql .= ", " . (! isset($this->entity) ? '1' : $this->entity); + $sql .= ", " . (! isset($this->entity) ? $conf->entity : $this->entity); $sql .= ")"; dol_syslog(get_class($this) . ":: create sql=" . $sql, LOG_DEBUG); @@ -363,6 +363,8 @@ class BookKeeping extends CommonObject * @return int <0 if KO, Id of created object if OK */ public function createStd(User $user, $notrigger = false, $mode='') { + global $conf; + dol_syslog(__METHOD__, LOG_DEBUG); $error = 0; @@ -486,7 +488,7 @@ class BookKeeping extends CommonObject $sql .= ' ' . (empty($this->code_journal) ? 'NULL' : "'" . $this->db->escape($this->code_journal) . "'") . ','; $sql .= ' ' . (empty($this->journal_label) ? 'NULL' : "'" . $this->db->escape($this->journal_label) . "'") . ','; $sql .= ' ' . (empty($this->piece_num) ? 'NULL' : $this->db->escape($this->piece_num)).','; - $sql .= ' ' . (! isset($this->entity) ? '1' : $this->entity); + $sql .= ' ' . (! isset($this->entity) ? $conf->entity : $this->entity); $sql .= ')'; $this->db->begin(); diff --git a/htdocs/accountancy/journal/bankjournal.php b/htdocs/accountancy/journal/bankjournal.php index f67956c1a74..3bbbaa5faca 100644 --- a/htdocs/accountancy/journal/bankjournal.php +++ b/htdocs/accountancy/journal/bankjournal.php @@ -455,6 +455,7 @@ if (! $error && $action == 'writebookkeeping') { // No subledger_account value for the bank line but add a specific label_operation $bookkeeping->subledger_account = ''; $bookkeeping->label_operation = $reflabel; + $bookkeeping->entity = $conf->entity; $totaldebit += $bookkeeping->debit; $totalcredit += $bookkeeping->credit; @@ -561,8 +562,8 @@ if (! $error && $action == 'writebookkeeping') { $bookkeeping->label_compte = ''; } } - $bookkeeping->label_operation = $reflabel; + $bookkeeping->entity = $conf->entity; $totaldebit += $bookkeeping->debit; $totalcredit += $bookkeeping->credit; @@ -608,8 +609,8 @@ if (! $error && $action == 'writebookkeeping') { $bookkeeping->fk_user_author = $user->id; $bookkeeping->date_create = $now; $bookkeeping->label_compte = ''; - $bookkeeping->label_operation = $reflabel; + $bookkeeping->entity = $conf->entity; $totaldebit += $bookkeeping->debit; $totalcredit += $bookkeeping->credit; diff --git a/htdocs/accountancy/journal/expensereportsjournal.php b/htdocs/accountancy/journal/expensereportsjournal.php index 2b5aa063887..265628eb35a 100644 --- a/htdocs/accountancy/journal/expensereportsjournal.php +++ b/htdocs/accountancy/journal/expensereportsjournal.php @@ -216,6 +216,7 @@ if ($action == 'writebookkeeping') { $bookkeeping->code_journal = $journal; $bookkeeping->journal_label = $journal_label; $bookkeeping->fk_user_author = $user->id; + $bookkeeping->entity = $conf->entity; $totaldebit += $bookkeeping->debit; $totalcredit += $bookkeeping->credit; @@ -265,6 +266,7 @@ if ($action == 'writebookkeeping') { $bookkeeping->code_journal = $journal; $bookkeeping->journal_label = $journal_label; $bookkeeping->fk_user_author = $user->id; + $bookkeeping->entity = $conf->entity; $totaldebit += $bookkeeping->debit; $totalcredit += $bookkeeping->credit; @@ -320,6 +322,7 @@ if ($action == 'writebookkeeping') { $bookkeeping->code_journal = $journal; $bookkeeping->journal_label = $journal_label; $bookkeeping->fk_user_author = $user->id; + $bookkeeping->entity = $conf->entity; $totaldebit += $bookkeeping->debit; $totalcredit += $bookkeeping->credit; diff --git a/htdocs/accountancy/journal/purchasesjournal.php b/htdocs/accountancy/journal/purchasesjournal.php index ec21937c8ff..27f4521de4b 100644 --- a/htdocs/accountancy/journal/purchasesjournal.php +++ b/htdocs/accountancy/journal/purchasesjournal.php @@ -318,6 +318,7 @@ if ($action == 'writebookkeeping') { $bookkeeping->code_journal = $journal; $bookkeeping->journal_label = $journal_label; $bookkeeping->fk_user_author = $user->id; + $bookkeeping->entity = $conf->entity; $totaldebit += $bookkeeping->debit; $totalcredit += $bookkeeping->credit; @@ -371,6 +372,7 @@ if ($action == 'writebookkeeping') { $bookkeeping->code_journal = $journal; $bookkeeping->journal_label = $journal_label; $bookkeeping->fk_user_author = $user->id; + $bookkeeping->entity = $conf->entity; $totaldebit += $bookkeeping->debit; $totalcredit += $bookkeeping->credit; @@ -430,6 +432,7 @@ if ($action == 'writebookkeeping') { $bookkeeping->code_journal = $journal; $bookkeeping->journal_label = $journal_label; $bookkeeping->fk_user_author = $user->id; + $bookkeeping->entity = $conf->entity; $totaldebit += $bookkeeping->debit; $totalcredit += $bookkeeping->credit; @@ -482,6 +485,7 @@ if ($action == 'writebookkeeping') { $bookkeeping->code_journal = $journal; $bookkeeping->journal_label = $journal_label; $bookkeeping->fk_user_author = $user->id; + $bookkeeping->entity = $conf->entity; $totaldebit += $bookkeeping->debit; $totalcredit += $bookkeeping->credit; diff --git a/htdocs/accountancy/journal/sellsjournal.php b/htdocs/accountancy/journal/sellsjournal.php index 5088841b3d1..c10cc2b311f 100644 --- a/htdocs/accountancy/journal/sellsjournal.php +++ b/htdocs/accountancy/journal/sellsjournal.php @@ -121,6 +121,7 @@ if ($in_bookkeeping == 'notyet') // $sql .= " AND fd.rowid NOT IN (SELECT fk_docdet FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping as ab WHERE ab.doc_type='customer_invoice')"; // Useless, we save one line for all products with same account } $sql .= " ORDER BY f.datef"; +//print $sql; dol_syslog('accountancy/journal/sellsjournal.php', LOG_DEBUG); $result = $db->query($sql); @@ -319,6 +320,7 @@ if ($action == 'writebookkeeping') { $bookkeeping->code_journal = $journal; $bookkeeping->journal_label = $journal_label; $bookkeeping->fk_user_author = $user->id; + $bookkeeping->entity = $conf->entity; $totaldebit += $bookkeeping->debit; $totalcredit += $bookkeeping->credit; @@ -372,6 +374,7 @@ if ($action == 'writebookkeeping') { $bookkeeping->code_journal = $journal; $bookkeeping->journal_label = $journal_label; $bookkeeping->fk_user_author = $user->id; + $bookkeeping->entity = $conf->entity; $totaldebit += $bookkeeping->debit; $totalcredit += $bookkeeping->credit; @@ -430,6 +433,7 @@ if ($action == 'writebookkeeping') { $bookkeeping->code_journal = $journal; $bookkeeping->journal_label = $journal_label; $bookkeeping->fk_user_author = $user->id; + $bookkeeping->entity = $conf->entity; $totaldebit += $bookkeeping->debit; $totalcredit += $bookkeeping->credit; diff --git a/htdocs/adherents/card.php b/htdocs/adherents/card.php index 65f9c65e641..250c8e18b4e 100644 --- a/htdocs/adherents/card.php +++ b/htdocs/adherents/card.php @@ -1822,7 +1822,7 @@ else // Presend form $modelmail='member'; - $defaulttopic='SendMemberRef'; + $defaulttopic='CardContent'; $diroutput = $conf->adherent->dir_output; $trackid = 'mem'.$object->id; diff --git a/htdocs/admin/company.php b/htdocs/admin/company.php index b2b7efc3a1c..1a0680363a9 100644 --- a/htdocs/admin/company.php +++ b/htdocs/admin/company.php @@ -313,10 +313,9 @@ if ($action == 'edit' || $action == 'updateedit') print '
'; print ''; print ''; - $var=true; print ''; - print ''."\n"; + print ''."\n"; // Name @@ -411,7 +410,6 @@ if ($action == 'edit' || $action == 'updateedit') // IDs of the company (country-specific) print '
'.$langs->trans("CompanyInfo").''.$langs->trans("Value").'
'.$langs->trans("CompanyInfo").''.$langs->trans("Value").'
'; print ''; - $var=true; $langs->load("companies"); @@ -697,11 +695,12 @@ else //print ''.$langs->trans("Modify").''; //print '
'; + print '
'; print '
'.$langs->trans("CompanyIds").''.$langs->trans("Value").'
'; print ''; - print ''; @@ -791,7 +790,7 @@ else print ''; print '
'.$langs->trans("CompanyInfo").''.$langs->trans("Value").'
'.$langs->trans("CompanyName").''; + print '
'.$langs->trans("CompanyName").''; if (! empty($conf->global->MAIN_INFO_SOCIETE_NOM)) print $conf->global->MAIN_INFO_SOCIETE_NOM; else print img_warning().' '.$langs->trans("ErrorFieldRequired",$langs->transnoentitiesnoconv("CompanyName")).''; print '
'.$langs->trans("Note").'' . (! empty($conf->global->MAIN_INFO_SOCIETE_NOTE) ? nl2br($conf->global->MAIN_INFO_SOCIETE_NOTE) : '') . '
'; - + print ""; print '
'; @@ -799,8 +798,10 @@ else // IDs of the company (country-specific) print ''; print ''; + + print '
'; print ''; - print ''; + print ''; // Managing Director(s) @@ -956,12 +957,16 @@ else print ''; print '
'.$langs->trans("CompanyIds").''.$langs->trans("Value").'
'.$langs->trans("CompanyIds").''.$langs->trans("Value").'
'.$langs->trans("CompanyObject").'' . (! empty($conf->global->MAIN_INFO_SOCIETE_OBJECT) ? nl2br($conf->global->MAIN_INFO_SOCIETE_OBJECT) : '') . '
'; + print "
"; + print '
'; /* * fiscal year beginning */ print '
'; + + print '
'; print ''; print ''; print ''; @@ -973,11 +978,13 @@ else print dol_print_date(dol_mktime(12,0,0,$monthstart,1,2000,1),'%B','gm') . ''; print "
'.$langs->trans("FiscalYearInformation").''.$langs->trans("Value").'
"; + print "
"; /* * tax options */ print '
'; + print '
'; print ''; print ''; print ''; @@ -1005,7 +1012,7 @@ else print "\n"; print "
'.$langs->trans("VATManagement").''.$langs->trans("Description").'
"; - + print "
"; /* * Local Taxes @@ -1014,6 +1021,7 @@ else { // Local Tax 1 print '
'; + print '
'; print ''; print ''; print ''; @@ -1061,11 +1069,13 @@ else print "\n"; print "
'.$langs->transcountry("LocalTax1Management",$mysoc->country_code).''.$langs->trans("Description").'
"; + print "
"; } if ($mysoc->useLocalTax(2)) // True if we found at least on vat with a setup adding a localtax 1 { // Local Tax 2 print '
'; + print '
'; print ''; print ''; print ''; @@ -1113,6 +1123,7 @@ else print "\n"; print "
'.$langs->transcountry("LocalTax2Management",$mysoc->country_code).''.$langs->trans("Description").'
"; + print "
"; } diff --git a/htdocs/admin/pdf.php b/htdocs/admin/pdf.php index 8028c81cf04..2f1ae179948 100644 --- a/htdocs/admin/pdf.php +++ b/htdocs/admin/pdf.php @@ -611,18 +611,6 @@ else // Show print ''.$langs->trans("Value").''."\n"; print "\n"; - if (! empty($dolibarr_pdf_force_fpdf)) - { - - print ''."\n"; - print 'dolibarr_pdf_force_fpdf'."\n"; - print ''; - print $dolibarr_pdf_force_fpdf; - print ''; - print ''; - } - - print ''."\n"; print ''.$langs->trans("LibraryToBuildPDF").''."\n"; print ''; @@ -663,11 +651,6 @@ else // Show print "\n"; print ''; - if (! empty($dolibarr_pdf_force_fpdf)) - { - print info_admin($langs->trans("WarningUsingFPDF")).'
'; - } - print '
'; print ''.$langs->trans("Modify").''; print '
'; diff --git a/htdocs/admin/system/dolibarr.php b/htdocs/admin/system/dolibarr.php index c36db521f70..468a2c493a7 100644 --- a/htdocs/admin/system/dolibarr.php +++ b/htdocs/admin/system/dolibarr.php @@ -116,7 +116,7 @@ if (function_exists('curl_init')) } else { - print $langs->trans("LastStableVersion").' : ' .$langs->trans("Check").''; + print $langs->trans("LastStableVersion").' : ' .$langs->trans("Check").''; } } @@ -325,13 +325,14 @@ $configfileparameters=array( '?dolibarr_font_DOL_DEFAULT_TTF_BOLD' => 'dolibarr_font_DOL_DEFAULT_TTF_BOLD', 'separator4' => '', 'dolibarr_main_prod' => 'Production mode (Hide all error messages)', + 'dolibarr_main_restrict_os_commands' => 'Restrict CLI commands for backups', + 'dolibarr_main_restrict_ip' => 'Restrict access to some IPs only', '?dolibarr_mailing_limit_sendbyweb' => 'Limit nb of email sent by page', '?dolibarr_mailing_limit_sendbycli' => 'Limit nb of email sent by cli', - '?dolibarr_strict_mode' => 'Strict mode is on/off', - '?dolibarr_pdf_force_fpdf' => 'Force fpdf usage to generate PDF' + '?dolibarr_strict_mode' => 'Strict mode is on/off', + '?dolibarr_nocsrfcheck' => 'Disable CSRF security checks' ); -$var=true; print '
'; print ''; print ''; @@ -441,8 +442,8 @@ if ($resql) $obj = $db->fetch_object($resql); print ''; - print ''."\n"; - print ''."\n"; + print ''."\n"; + print ''."\n"; if (empty($conf->multicompany->enabled) || !$user->entity) print ''."\n"; // If superadmin or multicompany disabled print "\n"; diff --git a/htdocs/admin/taxes.php b/htdocs/admin/taxes.php index a4aa1afbd8c..684577a6d6d 100644 --- a/htdocs/admin/taxes.php +++ b/htdocs/admin/taxes.php @@ -3,7 +3,7 @@ * Copyright (C) 2004-2008 Laurent Destailleur * Copyright (C) 2005-2009 Regis Houssin * Copyright (C) 2011-2013 Juanjo Menent - * Copyright (C) 2015 Alexandre Spangaro + * Copyright (C) 2015-2018 Alexandre Spangaro * * 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 @@ -30,17 +30,20 @@ require_once DOL_DOCUMENT_ROOT . '/core/lib/admin.lib.php'; if (! empty($conf->accounting->enabled)) require_once DOL_DOCUMENT_ROOT . '/core/class/html.formaccounting.class.php'; $langs->load('admin'); +$langs->load('objects'); +$langs->load("companies"); $langs->load("products"); if (!$user->admin) accessforbidden(); $action = GETPOST('action','alpha'); -// Other parameters ACCOUNTING_* +// Other parameters $list = array ( 'ACCOUNTING_VAT_PAY_ACCOUNT' ); + /* * Actions */ @@ -60,137 +63,174 @@ $list = array ( $tax_mode = empty($conf->global->TAX_MODE)?0:$conf->global->TAX_MODE; if ($action == 'update') { - $error = 0; + $error = 0; // Tax mode $tax_mode = GETPOST('tax_mode','alpha'); - $db->begin(); + $db->begin(); - $res = dolibarr_set_const($db, 'TAX_MODE', $tax_mode,'chaine',0,'',$conf->entity); - if (! $res > 0) $error++; + $res = dolibarr_set_const($db, 'TAX_MODE', $tax_mode,'chaine',0,'',$conf->entity); + if (! $res > 0) $error++; - switch ($tax_mode) - { - case 0: - $value = 'payment'; - break; - case 1: - $value = 'invoice'; - break; - } + switch ($tax_mode) + { + case 0: + $value = 'payment'; + break; + case 1: + $value = 'invoice'; + break; + } - $res = dolibarr_set_const($db, 'TAX_MODE_SELL_PRODUCT', 'invoice','chaine',0,'',$conf->entity); - if (! $res > 0) $error++; - $res = dolibarr_set_const($db, 'TAX_MODE_BUY_PRODUCT', 'invoice','chaine',0,'',$conf->entity); - if (! $res > 0) $error++; - $res = dolibarr_set_const($db, 'TAX_MODE_SELL_SERVICE', $value,'chaine',0,'',$conf->entity); - if (! $res > 0) $error++; - $res = dolibarr_set_const($db, 'TAX_MODE_BUY_SERVICE', $value,'chaine',0,'',$conf->entity); - if (! $res > 0) $error++; + $res = dolibarr_set_const($db, 'TAX_MODE_SELL_PRODUCT', 'invoice','chaine',0,'',$conf->entity); + if (! $res > 0) $error++; + $res = dolibarr_set_const($db, 'TAX_MODE_BUY_PRODUCT', 'invoice','chaine',0,'',$conf->entity); + if (! $res > 0) $error++; + $res = dolibarr_set_const($db, 'TAX_MODE_SELL_SERVICE', $value,'chaine',0,'',$conf->entity); + if (! $res > 0) $error++; + $res = dolibarr_set_const($db, 'TAX_MODE_BUY_SERVICE', $value,'chaine',0,'',$conf->entity); + if (! $res > 0) $error++; + + dolibarr_set_const($db, "MAIN_INFO_TVAINTRA", GETPOST("tva",'alpha'),'chaine',0,'',$conf->entity); + + dolibarr_set_const($db, "MAIN_INFO_VAT_RETURN", GETPOST("MAIN_INFO_VAT_RETURN",'alpha'),'chaine',0,'',$conf->entity); // Others options - foreach ($list as $constname) { - $constvalue = GETPOST($constname, 'alpha'); + foreach ($list as $constname) { + $constvalue = GETPOST($constname, 'alpha'); - if (!dolibarr_set_const($db, $constname, $constvalue, 'chaine', 0, '', $conf->entity)) { - $error++; - } - } + if (!dolibarr_set_const($db, $constname, $constvalue, 'chaine', 0, '', $conf->entity)) { + $error++; + } + } - if (! $error) { - $db->commit(); - setEventMessages($langs->trans("SetupSaved"), null, 'mesgs'); - } else { - $db->rollback(); - setEventMessages($langs->trans("Error"), null, 'errors'); - } + if (! $error) { + $db->commit(); + setEventMessages($langs->trans("SetupSaved"), null, 'mesgs'); + } else { + $db->rollback(); + setEventMessages($langs->trans("Error"), null, 'errors'); + } } + /* * View */ -llxHeader(); +llxHeader('', $langs->trans("TaxSetup")); + $form=new Form($db); if (! empty($conf->accounting->enabled)) $formaccounting = new FormAccounting($db); $linkback=''.$langs->trans("BackToModuleList").''; print load_fiche_titre($langs->trans('TaxSetup'),$linkback,'title_setup'); -dol_fiche_head(); +//dol_fiche_head(null, '', '', -1); if (empty($mysoc->tva_assuj)) { - print $langs->trans("YourCompanyDoesNotUseVAT").'
'; + print $langs->trans("YourCompanyDoesNotUseVAT").'
'; } else { - print '
'.$obj->name.''.$obj->value.''.$obj->name.''.dol_escape_htmltag($obj->value).''.$obj->entity.'
'; + print ''; + print ''; + print ''; - // Cas des parametres TAX_MODE_SELL/BUY_SERVICE/PRODUCT - print ''; - print ''; - print ''; + print '
'; + print ''; - print ''; - print ''; - print "\n"; - print ''; - print '\n"; - print ''; - print '\n"; + print ''; - print "
'.$langs->trans("CompanyIds").''.$langs->trans("Value").'
'.$langs->trans('OptionVatMode').''.$langs->trans('Description').'
'.$langs->trans('OptionVATDefault').''.nl2br($langs->trans('OptionVatDefaultDesc')); - print "
'.$langs->trans('OptionVATDebitOption').''.nl2br($langs->trans('OptionVatDebitOptionDesc'))."
'; + print ''; + print '
\n"; + print ''; + if (! $conf->use_javascript_ajax) + { + print ''; + print $langs->trans("NotAvailableWhenAjaxDisabled"); + print ""; + } + else + { + print ''; + $listval=array('0'=>$langs->trans(""), + '1'=>$langs->trans("Monthly"), + '2'=>$langs->trans("Quarterly"), + '3'=>$langs->trans("Annual"), + ); + print $form->selectarray("MAIN_INFO_VAT_RETURN", $listval, $conf->global->MAIN_INFO_VAT_RETURN); + print ""; + } + print ''; - print '
'; - print load_fiche_titre($langs->trans("SummaryOfVatExigibilityUsedByDefault"),'',''); - //print ' ('.$langs->trans("CanBeChangedWhenMakingInvoice").')'; + print ''; - print ''; - print ''; + print "
\n"; - // Products - print ''; - print ''; - print ''; + print '
 '.$langs->trans("Buy").''.$langs->trans("Sell").'
'.$langs->trans("Product").''; - print $langs->trans("OnDelivery"); - print ' ('.$langs->trans("SupposedToBeInvoiceDate").')'; - print ''; - print $langs->trans("OnDelivery"); - print ' ('.$langs->trans("SupposedToBeInvoiceDate").')'; - print '
'; - // Services - print ''; - print ''; - print ''; + // Cas des parametres TAX_MODE_SELL/BUY_SERVICE/PRODUCT + print ''; + print ''; + print "\n"; + print ''; + print '\n"; + print ''; + print '\n"; - print '
'.$langs->trans("Services").''; - if ($tax_mode == 0) - { - print $langs->trans("OnPayment"); - print ' ('.$langs->trans("SupposedToBePaymentDate").')'; - } - if ($tax_mode == 1) - { - print $langs->trans("OnInvoice"); - print ' ('.$langs->trans("InvoiceDateUsed").')'; - } - print ''; - if ($tax_mode == 0) - { - print $langs->trans("OnPayment"); - print ' ('.$langs->trans("SupposedToBePaymentDate").')'; - } - if ($tax_mode == 1) - { - print $langs->trans("OnInvoice"); - print ' ('.$langs->trans("InvoiceDateUsed").')'; - } - print '
'.$langs->trans('OptionVatMode').''.$langs->trans('Description').'
'.$langs->trans('OptionVATDefault').''.nl2br($langs->trans('OptionVatDefaultDesc')); + print "
'.$langs->trans('OptionVATDebitOption').''.nl2br($langs->trans('OptionVatDebitOptionDesc'))."
'; + print "\n"; + + print '
'; + print load_fiche_titre($langs->trans("SummaryOfVatExigibilityUsedByDefault"),'',''); + //print ' ('.$langs->trans("CanBeChangedWhenMakingInvoice").')'; + + print ''; + print ''; + + // Products + print ''; + print ''; + print ''; + + // Services + print ''; + print ''; + print ''; + + print '
 '.$langs->trans("Buy").''.$langs->trans("Sell").'
'.$langs->trans("Product").''; + print $langs->trans("OnDelivery"); + print ' ('.$langs->trans("SupposedToBeInvoiceDate").')'; + print ''; + print $langs->trans("OnDelivery"); + print ' ('.$langs->trans("SupposedToBeInvoiceDate").')'; + print '
'.$langs->trans("Services").''; + if ($tax_mode == 0) + { + print $langs->trans("OnPayment"); + print ' ('.$langs->trans("SupposedToBePaymentDate").')'; + } + if ($tax_mode == 1) + { + print $langs->trans("OnInvoice"); + print ' ('.$langs->trans("InvoiceDateUsed").')'; + } + print ''; + if ($tax_mode == 0) + { + print $langs->trans("OnPayment"); + print ' ('.$langs->trans("SupposedToBePaymentDate").')'; + } + if ($tax_mode == 1) + { + print $langs->trans("OnInvoice"); + print ' ('.$langs->trans("InvoiceDateUsed").')'; + } + print '
'; } print "
\n"; @@ -205,12 +245,10 @@ print "\n"; foreach ($list as $key) { - - print ''; // Param - $label = $langs->trans($key); + $label = $langs->trans($key); print ''; // Value @@ -228,7 +266,9 @@ foreach ($list as $key) print ''; -dol_fiche_end(); + +//dol_fiche_end(); + print '
'; print ''; diff --git a/htdocs/blockedlog/admin/blockedlog_list.php b/htdocs/blockedlog/admin/blockedlog_list.php index 9410ef9be5e..e8b2dc8b73b 100644 --- a/htdocs/blockedlog/admin/blockedlog_list.php +++ b/htdocs/blockedlog/admin/blockedlog_list.php @@ -196,7 +196,7 @@ else if (GETPOST('downloadcsv','alpha')) $block_static->user_fullname = $obj->user_fullname; $block_static->fk_user = $obj->fk_user; $block_static->signature = $obj->signature; - $block_static->object_data = unserialize($obj->object_data); + $block_static->object_data = $block_static->dolDecodeBlockedData($obj->object_data); $checksignature = $block_static->checkSignature($previoushash); // If $previoushash is not defined, checkSignature will search it diff --git a/htdocs/blockedlog/ajax/block-info.php b/htdocs/blockedlog/ajax/block-info.php index a092b13ca99..d4d4eef4e07 100644 --- a/htdocs/blockedlog/ajax/block-info.php +++ b/htdocs/blockedlog/ajax/block-info.php @@ -85,10 +85,16 @@ function formatObject($objtoshow, $prefix) { if (! is_object($val) && ! is_array($val)) { + // TODO $val can be '__PHP_Incomplete_Class', the is_object return false $s.=''.($prefix?$prefix.' > ':'').$key.''; $s.=''; if (in_array($key, array('date','datef','dateh','datec','datem','datep'))) { + /*var_dump(is_object($val)); + var_dump(is_array($val)); + var_dump(is_array($val)); + var_dump(@get_class($val)); + var_dump($val);*/ $s.=dol_print_date($val, 'dayhour'); } else diff --git a/htdocs/blockedlog/class/blockedlog.class.php b/htdocs/blockedlog/class/blockedlog.class.php index 1bddb23de1d..6a38bc3ab49 100644 --- a/htdocs/blockedlog/class/blockedlog.class.php +++ b/htdocs/blockedlog/class/blockedlog.class.php @@ -18,10 +18,23 @@ * See https://medium.com/@lhartikk/a-blockchain-in-200-lines-of-code-963cc1cc0e54 */ + + + +/*ini_set('unserialize_callback_func', 'mycallback'); + +function mycallback($classname) +{ + //var_dump($classname); + include_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; + +}*/ + + + /** * Class to manage Blocked Log */ - class BlockedLog { /** @@ -636,7 +649,7 @@ class BlockedLog $this->fk_user = $obj->fk_user; $this->user_fullname = $obj->user_fullname; - $this->object_data = unserialize($obj->object_data); + $this->object_data = $this->dolDecodeBlockedData($obj->object_data); $this->signature = $obj->signature; $this->signature_line = $obj->signature_line; @@ -658,6 +671,31 @@ class BlockedLog } + + /** + * Decode data + * + * @param string $data Data to unserialize + * @param string $mode 0=unserialize, 1=json_decode + * @return string Value unserialized + */ + public function dolDecodeBlockedData($data, $mode=0) + { + try + { + //include_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; + //include_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; + $aaa = unserialize($data); + //$aaa = unserialize($data); + } + catch(Exception $e) + { + //print $e->getErrs); + } + return $aaa; + } + + /** * Set block certified by authority * diff --git a/htdocs/comm/action/card.php b/htdocs/comm/action/card.php index 2f59df43803..d0d97f83435 100644 --- a/htdocs/comm/action/card.php +++ b/htdocs/comm/action/card.php @@ -1044,7 +1044,7 @@ if ($id > 0) } // Title - print 'global->AGENDA_USE_EVENT_TYPE)?' class="fieldrequired"':'').'>'.$langs->trans("Title").''; + print ''.$langs->trans("Title").''; // Full day event print ''.$langs->trans("EventOnFullDay").'fulldayevent?' checked':'').'>'; diff --git a/htdocs/comm/action/class/actioncomm.class.php b/htdocs/comm/action/class/actioncomm.class.php index f0bb9f92e22..6452e3ca922 100644 --- a/htdocs/comm/action/class/actioncomm.class.php +++ b/htdocs/comm/action/class/actioncomm.class.php @@ -1236,8 +1236,12 @@ class ActionComm extends CommonObject $result=''; - // Set label of typ - $labeltype = ($langs->transnoentities("Action".$this->type_code) != "Action".$this->type_code)?$langs->transnoentities("Action".$this->type_code):$this->type_label; + // Set label of type + $labeltype = ''; + if ($this->type_code) + { + $labeltype = ($langs->transnoentities("Action".$this->type_code) != "Action".$this->type_code)?$langs->transnoentities("Action".$this->type_code):$this->type_label; + } if (empty($conf->global->AGENDA_USE_EVENT_TYPE)) { if ($this->type_code != 'AC_OTH_AUTO') $labeltype = $langs->trans('ActionAC_MANUAL'); @@ -1289,7 +1293,7 @@ class ActionComm extends CommonObject $linkstart.=$linkclose.'>'; $linkend=''; - //print 'rrr'.$this->libelle.'-'.$withpicto; + //print 'rrr'.$this->libelle.'rrr'.$this->label.'rrr'.$withpicto; if ($withpicto == 2) { @@ -1309,7 +1313,10 @@ class ActionComm extends CommonObject { if (! empty($conf->global->AGENDA_USE_EVENT_TYPE)) // Add code into () { - $libelle.=(($this->type_code && $libelle!=$langs->transnoentities("Action".$this->type_code) && $langs->transnoentities("Action".$this->type_code)!="Action".$this->type_code)?' ('.$langs->transnoentities("Action".$this->type_code).')':''); + if ($labeltype) + { + $libelle.=(preg_match('/'.preg_quote($labeltype,'/').'/', $libelle)?'':' ('.$langs->transnoentities("Action".$this->type_code).')'); + } } } diff --git a/htdocs/comm/action/index.php b/htdocs/comm/action/index.php index efdad6a3738..9fae2dd47a9 100644 --- a/htdocs/comm/action/index.php +++ b/htdocs/comm/action/index.php @@ -589,6 +589,7 @@ if ($resql) $event->type_color=$obj->type_color; $event->libelle=$obj->label; + $event->label=$obj->label; $event->percentage=$obj->percent; $event->authorid=$obj->fk_user_author; // user id of creator $event->userownerid=$obj->fk_user_action; // user id of owner @@ -601,7 +602,9 @@ if ($resql) $event->elementtype=$obj->elementtype; $event->societe->id=$obj->fk_soc; + $event->thirdparty_id=$obj->fk_soc; $event->contact->id=$obj->fk_contact; + $event->contact_id=$obj->fk_contact; // Defined date_start_in_calendar and date_end_in_calendar property // They are date start and end of action but modified to not be outside calendar view. @@ -1176,19 +1179,72 @@ else // View by day $timestamp=dol_mktime(12,0,0,$month,$day,$year); $arraytimestamp=dol_getdate($timestamp); - print '
'; // You can use div-table-responsive-no-min if you dont need reserved height for your table - echo ''; - echo ' '; - echo ' \n"; - echo " \n"; - echo " \n"; - echo ' \n"; - echo " \n"; + //echo '
'.$langs->trans("Day".$arraytimestamp['wday'])."
'; - $maxnbofchar=80; - show_day_events($db, $day, $month, $year, $month, $style, $eventarray, 0, $maxnbofchar, $newparam, 1, 300); - echo "
'; + echo '
'; + + echo ' '; + echo ' '; + echo ' \n"; + echo " \n"; + + /* + echo '
'; + echo '
'; + echo '
'; + echo show_day_events($db, $day, $month, $year, $month, $style, $eventarray, 0, $maxnbofchar, $newparam, 1, 300, -1); + echo '
'."\n"; + echo "
\n"; + */ + echo '
'.$langs->trans("Day".$arraytimestamp['wday'])."
'; - print '
'; + + /* WIP View per hour */ + $useviewhour = 0; + if ($useviewhour) + { + print '
'; // You can use div-table-responsive-no-min if you dont need reserved height for your table + + $maxheightwin=(isset($_SESSION["dol_screenheight"]) && $_SESSION["dol_screenheight"] > 500)?($_SESSION["dol_screenheight"]-200):660; // Also into index.php file + + echo '
'; + echo '
'; + + $maxnbofchar=80; + + $tmp = explode('-', $conf->global->MAIN_DEFAULT_WORKING_HOURS); + $minhour = round($tmp[0],0); + $maxhour = round($tmp[1],0); + if ($minhour > 23) $minhour = 23; + if ($maxhour < 1) $maxhour = 1; + if ($maxhour <= $minhour) { $maxhour = $minhour + 1; } + + $i = 0; + $j = 0; + while ($i < 24) + { + echo '
'."\n"; + echo '
'.dol_print_date($i*3600, 'hour', 'gmt').'
'; + echo '
'; + echo "
\n"; + echo "
\n"; + $i++; + $j++; + } + + echo '
'; + + show_day_events($db, $day, $month, $year, $month, $style, $eventarray, 0, $maxnbofchar, $newparam, 1, 300, 1); + + print '
'; + } + else + { + print '
'; // You can use div-table-responsive-no-min if you dont need reserved height for your table + + show_day_events($db, $day, $month, $year, $month, $style, $eventarray, 0, $maxnbofchar, $newparam, 1, 300, 0); + + print '
'; + } } print "\n".''; @@ -1213,9 +1269,10 @@ $db->close(); * @param string $newparam Parameters on current URL * @param int $showinfo Add extended information (used by day and week view) * @param int $minheight Minimum height for each event. 60px by default. + * @param string $nonew 0=Add "new entry button", 1=No "new entry button", -1=Only "new entry button" * @return void */ -function show_day_events($db, $day, $month, $year, $monthshown, $style, &$eventarray, $maxprint=0, $maxnbofchar=16, $newparam='', $showinfo=0, $minheight=60) +function show_day_events($db, $day, $month, $year, $monthshown, $style, &$eventarray, $maxprint=0, $maxnbofchar=16, $newparam='', $showinfo=0, $minheight=60, $nonew=0) { global $user, $conf, $langs; global $action, $filter, $filtert, $status, $actioncode; // Filters used into search form @@ -1230,26 +1287,35 @@ function show_day_events($db, $day, $month, $year, $monthshown, $style, &$eventa $curtime = dol_mktime(0, 0, 0, $month, $day, $year); print '
'."\n"; - print '
'; - if ($user->rights->agenda->myactions->create || $user->rights->agenda->allactions->create) + if ($nonew <= 0) { - $newparam.='&month='.str_pad($month, 2, "0", STR_PAD_LEFT).'&year='.$year; + print '
'; + if ($user->rights->agenda->myactions->create || $user->rights->agenda->allactions->create) + { + $newparam.='&month='.str_pad($month, 2, "0", STR_PAD_LEFT).'&year='.$year; - //$param='month='.$monthshown.'&year='.$year; - $hourminsec='100000'; - print ''; - print img_picto($langs->trans("NewAction"),'edit_add.png'); - print ''; + //$param='month='.$monthshown.'&year='.$year; + $hourminsec='100000'; + print ''; + print img_picto($langs->trans("NewAction"),'edit_add.png'); + print ''; + } + print '
'."\n"; + } + + if ($nonew < 0) + { + print '
'; + return; } - print '
'."\n"; // Line with td contains all div of each events print '
'; @@ -1390,6 +1456,7 @@ function show_day_events($db, $day, $month, $year, $monthshown, $style, &$eventa //print ' position: absolute; top: 40px; width: 50%;'; //print '"'; print '>'; + //var_dump($event->userassigned); //var_dump($event->transparency); print 'trans("DoneActions"); - if ($status == 'todo') $title=$langs->trans("ToDoActions"); - */ - $title=$langs->trans("ListOfEvents"); - - $newtitle=$langs->trans($title); + // Local calendar + $newtitle ='
' . $langs->trans("LocalAgenda").'  
'; + //$newtitle=$langs->trans($title); $tabactive='cardlist'; @@ -430,12 +426,12 @@ if ($resql) if (! empty($arrayfields['c.libelle']['checked'])) print ''; if (! empty($arrayfields['a.label']['checked'])) print ''; if (! empty($arrayfields['a.datep']['checked'])) { - print ''; } if (! empty($arrayfields['a.datep2']['checked'])) { - print ''; } @@ -517,8 +513,8 @@ if ($resql) print ''; + // Ref if (! empty($arrayfields['a.id']['checked'])) { - // Ref print ''; diff --git a/htdocs/commande/list.php b/htdocs/commande/list.php index 793fb2cf708..784f44aad4c 100644 --- a/htdocs/commande/list.php +++ b/htdocs/commande/list.php @@ -670,7 +670,7 @@ if ($resql) // Status billed if (! empty($arrayfields['c.facture']['checked'])) { - print ''; } diff --git a/htdocs/compta/bank/bankentries_list.php b/htdocs/compta/bank/bankentries_list.php index 91e496d998c..56eb8beeca7 100644 --- a/htdocs/compta/bank/bankentries_list.php +++ b/htdocs/compta/bank/bankentries_list.php @@ -673,7 +673,7 @@ if ($resql) print ''; print ''; print ''; print ''; } if (! empty($arrayfields['b.num_chq']['checked'])) diff --git a/htdocs/compta/bank/various_payment/index.php b/htdocs/compta/bank/various_payment/index.php index d52cbeb7595..41c0baa61d5 100644 --- a/htdocs/compta/bank/various_payment/index.php +++ b/htdocs/compta/bank/various_payment/index.php @@ -187,7 +187,7 @@ if ($result) // Type print ''; // Account diff --git a/htdocs/compta/facture/invoicetemplate_list.php b/htdocs/compta/facture/invoicetemplate_list.php index 6cd80d8dff6..0a2b9f72d60 100644 --- a/htdocs/compta/facture/invoicetemplate_list.php +++ b/htdocs/compta/facture/invoicetemplate_list.php @@ -419,19 +419,19 @@ if ($resql) // Date invoice if (! empty($arrayfields['f.date_last_gen']['checked'])) { - print ''; } // Date next generation if (! empty($arrayfields['f.date_when']['checked'])) { - print ''; } // Extra fields diff --git a/htdocs/compta/facture/list.php b/htdocs/compta/facture/list.php index bacaddcffd4..8319f42bd97 100644 --- a/htdocs/compta/facture/list.php +++ b/htdocs/compta/facture/list.php @@ -701,19 +701,19 @@ if ($resql) // Date invoice if (! empty($arrayfields['f.date']['checked'])) { - print ''; } // Date due if (! empty($arrayfields['f.date_lim_reglement']['checked'])) { - print ''; } @@ -756,7 +756,7 @@ if ($resql) if (! empty($arrayfields['f.fk_mode_reglement']['checked'])) { print ''; } if (! empty($arrayfields['f.total_ht']['checked'])) @@ -775,14 +775,14 @@ if ($resql) } if (! empty($arrayfields['f.total_localtax1']['checked'])) { - // Amount + // Localtax1 print ''; } if (! empty($arrayfields['f.total_localtax2']['checked'])) { - // Amount + // Localtax2 print ''; diff --git a/htdocs/compta/paiement/card.php b/htdocs/compta/paiement/card.php index 6179fb9ac22..2a8267aefb5 100644 --- a/htdocs/compta/paiement/card.php +++ b/htdocs/compta/paiement/card.php @@ -332,21 +332,22 @@ if ($resql) if ($num > 0) { - $var=True; - while ($i < $num) { $objp = $db->fetch_object($resql); - print ''; + $thirdpartystatic->fetch($objp->socid); - $invoice=new Facture($db); - $invoice->fetch($objp->facid); - $paiement = $invoice->getSommePaiement(); - $creditnotes=$invoice->getSumCreditNotesUsed(); - $deposits=$invoice->getSumDepositsUsed(); - $alreadypayed=price2num($paiement + $creditnotes + $deposits,'MT'); - $remaintopay=price2num($invoice->total_ttc - $paiement - $creditnotes - $deposits,'MT'); + $invoice=new Facture($db); + $invoice->fetch($objp->facid); + + $paiement = $invoice->getSommePaiement(); + $creditnotes=$invoice->getSumCreditNotesUsed(); + $deposits=$invoice->getSumDepositsUsed(); + $alreadypayed=price2num($paiement + $creditnotes + $deposits,'MT'); + $remaintopay=price2num($invoice->total_ttc - $paiement - $creditnotes - $deposits,'MT'); + + print ''; // Invoice print ''; diff --git a/htdocs/compta/resultat/clientfourn.php b/htdocs/compta/resultat/clientfourn.php index fe7d927b6df..1bbeb9f2f29 100644 --- a/htdocs/compta/resultat/clientfourn.php +++ b/htdocs/compta/resultat/clientfourn.php @@ -255,7 +255,7 @@ if ($modecompta == 'BOOKKEEPING') $sql.= " WHERE f.numero_compte = aa.account_number"; //$sql.= " AND fk_statut in (1,2)"; $sql.= " AND ".$predefinedgroupwhere; - $sql.= " AND aa.fk_pcg_version = '".$charofaccountstring."'"; + $sql.= " AND f.entity = ".$conf->entity; if (! empty($date_start) && ! empty($date_end)) $sql.= " AND f.doc_date >= '".$db->idate($date_start)."' AND f.doc_date <= '".$db->idate($date_end)."'"; $sql.= " GROUP BY pcg_type, pcg_subtype, name, socid"; diff --git a/htdocs/compta/resultat/index.php b/htdocs/compta/resultat/index.php index 156576fa4bc..26f12e3f7c5 100644 --- a/htdocs/compta/resultat/index.php +++ b/htdocs/compta/resultat/index.php @@ -828,7 +828,6 @@ if (! empty($conf->accounting->enabled) && ($modecompta == 'BOOKKEEPING')) if (! empty($date_start) && ! empty($date_end)) $sql.= " AND b.doc_date >= '".$db->idate($date_start)."' AND b.doc_date <= '".$db->idate($date_end)."'"; $sql.= " GROUP BY b.doc_ref, b.numero_compte, b.subledger_account, b.subledger_label, pcg_type, dm"; - //print $sql; dol_syslog("get bookkeeping record"); diff --git a/htdocs/compta/salaries/index.php b/htdocs/compta/salaries/index.php index 47cafad0f0a..f911636a7ef 100644 --- a/htdocs/compta/salaries/index.php +++ b/htdocs/compta/salaries/index.php @@ -179,7 +179,7 @@ if ($result) print ''; // Type print ''; // Account if (! empty($conf->banque->enabled)) diff --git a/htdocs/compta/stats/index.php b/htdocs/compta/stats/index.php index 335cf581740..598de2ba490 100644 --- a/htdocs/compta/stats/index.php +++ b/htdocs/compta/stats/index.php @@ -142,9 +142,7 @@ else if ($modecompta=="BOOKKEEPING") $calcmode.='
('.$langs->trans("SeeReportInInputOutputMode",'','').')'; $period=$form->select_date($date_start,'date_start',0,0,0,'',1,0,1).' - '.$form->select_date($date_end,'date_end',0,0,0,'',1,0,1); $periodlink=($year_start?"".img_previous()."".img_next()."":""); - $description=$langs->trans("RulesCADue"); - if (! empty($conf->global->FACTURE_DEPOSITS_ARE_JUST_PAYMENTS)) $description.= $langs->trans("DepositsAreNotIncluded"); - else $description.= $langs->trans("DepositsAreIncluded"); + $description=$langs->trans("RulesCATotalSaleJournal"); $builddate=dol_now(); //$exportlink=$langs->trans("NotYetAvailable"); } @@ -187,15 +185,14 @@ if ($socid) $sql.= " AND f.fk_soc = ".$socid; else if ($modecompta=="BOOKKEEPING") { $sql = "SELECT date_format(b.doc_date,'%Y-%m') as dm, sum(b.credit) as amount_ttc"; - $sql.= " FROM ".MAIN_DB_PREFIX."accounting_bookkeeping as b"; - $sql.= " WHERE b.numero_compte IN (SELECT a.account_number" ; - $sql.= " FROM ".MAIN_DB_PREFIX."accounting_account as a"; - $sql.= " WHERE a.fk_accounting_category = 1 ) " ; // todo sql with accounting category, but we need to define category in turnover + $sql.= " FROM ".MAIN_DB_PREFIX."accounting_bookkeeping as b, ".MAIN_DB_PREFIX."accounting_journal as aj"; + $sql.= " WHERE b.entity = ".$conf->entity; + $sql.= " AND b.code_journal = aj.code AND aj.nature = 2" ; // @TODO currently count amount in sale journal, but we need to define a category group for turnover } - $sql.= " GROUP BY dm"; $sql.= " ORDER BY dm"; +//print $sql; $result = $db->query($sql); if ($result) @@ -221,7 +218,7 @@ else { } // On ajoute les paiements anciennes version, non lies par paiement_facture (very old versions) -if ($modecompta != 'CREANCES-DETTES') +if ($modecompta == 'RECETTES-DEPENSES') { $sql = "SELECT date_format(p.datep,'%Y-%m') as dm, sum(p.amount) as amount_ttc"; $sql.= " FROM ".MAIN_DB_PREFIX."bank as b"; @@ -269,10 +266,11 @@ for ($annee = $year_start ; $annee <= $year_end ; $annee++) { if ($modecompta == 'CREANCES-DETTES') print ''; + if ($modecompta != 'BOOKKEEPING') print ''; + print ''; if ($annee != $year_end) print ''; } print ''; @@ -336,7 +334,9 @@ for ($mois = 1+$nb_mois_decalage ; $mois <= 12+$nb_mois_decalage ; $mois++) if ($cum[$case]) { $now_show_delta=1; // On a trouve le premier mois de la premiere annee generant du chiffre. - print ''.price($cum[$case],1).''; + if ($modecompta != 'BOOKKEEPING') print ''; + print price($cum[$case], 1); + if ($modecompta != 'BOOKKEEPING') print ''; } else { diff --git a/htdocs/compta/tva/reglement.php b/htdocs/compta/tva/reglement.php index 66099cd63db..27e314762f8 100644 --- a/htdocs/compta/tva/reglement.php +++ b/htdocs/compta/tva/reglement.php @@ -173,7 +173,7 @@ if ($result) print ''; // Type print ''; // Account if (! empty($conf->banque->enabled)) diff --git a/htdocs/core/actions_massactions.inc.php b/htdocs/core/actions_massactions.inc.php index fae976dec80..5a713168c48 100644 --- a/htdocs/core/actions_massactions.inc.php +++ b/htdocs/core/actions_massactions.inc.php @@ -686,6 +686,35 @@ if ($massaction == 'confirm_createbills') { $db->commit(); setEventMessage($langs->trans('BillCreated', $nb_bills_created)); + + // Make a redirect to avoid to bill twice if we make a refresh or back + $param=''; + if (! empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) $param.='&contextpage='.urlencode($contextpage); + if ($limit > 0 && $limit != $conf->liste_limit) $param.='&limit='.urlencode($limit); + if ($sall) $param.='&sall='.urlencode($sall); + if ($socid > 0) $param.='&socid='.urlencode($socid); + if ($viewstatut != '') $param.='&viewstatut='.urlencode($viewstatut); + if ($search_orderday) $param.='&search_orderday='.urlencode($search_orderday); + if ($search_ordermonth) $param.='&search_ordermonth='.urlencode($search_ordermonth); + if ($search_orderyear) $param.='&search_orderyear='.urlencode($search_orderyear); + if ($search_deliveryday) $param.='&search_deliveryday='.urlencode($search_deliveryday); + if ($search_deliverymonth) $param.='&search_deliverymonth='.urlencode($search_deliverymonth); + if ($search_deliveryyear) $param.='&search_deliveryyear='.urlencode($search_deliveryyear); + if ($search_ref) $param.='&search_ref='.urlencode($search_ref); + if ($search_company) $param.='&search_company='.urlencode($search_company); + if ($search_ref_customer) $param.='&search_ref_customer='.urlencode($search_ref_customer); + if ($search_user > 0) $param.='&search_user='.urlencode($search_user); + if ($search_sale > 0) $param.='&search_sale='.urlencode($search_sale); + if ($search_total_ht != '') $param.='&search_total_ht='.urlencode($search_total_ht); + if ($search_total_vat != '') $param.='&search_total_vat='.urlencode($search_total_vat); + if ($search_total_ttc != '') $param.='&search_total_ttc='.urlencode($search_total_ttc); + if ($search_project_ref >= 0) $param.="&search_project_ref=".urlencode($search_project_ref); + if ($show_files) $param.='&show_files=' .urlencode($show_files); + if ($optioncss != '') $param.='&optioncss='.urlencode($optioncss); + if ($billed != '') $param.='&billed='.urlencode($billed); + + header("Location: ".$_SERVER['PHP_SELF'].'?'.$param); + exit; } else { diff --git a/htdocs/core/boxes/box_commandes.php b/htdocs/core/boxes/box_commandes.php index 9e1e89d60fc..9bbde140dbe 100644 --- a/htdocs/core/boxes/box_commandes.php +++ b/htdocs/core/boxes/box_commandes.php @@ -136,7 +136,7 @@ class box_commandes extends ModeleBoxes ); $this->info_box_contents[$line][] = array( - 'td' => 'class="tdoverflowmax100"', + 'td' => 'class="tdoverflowmax150 maxwidth150onsmartphone"', 'text' => $societestatic->getNomUrl(1), 'asis' => 1, ); diff --git a/htdocs/core/boxes/box_contracts.php b/htdocs/core/boxes/box_contracts.php index 59db96b08aa..49d6df67d7f 100644 --- a/htdocs/core/boxes/box_contracts.php +++ b/htdocs/core/boxes/box_contracts.php @@ -128,7 +128,7 @@ class box_contracts extends ModeleBoxes ); $this->info_box_contents[$line][] = array( - 'td' => 'class="tdoverflowmax100 maxwidth100onsmartphone"', + 'td' => 'class="tdoverflowmax150 maxwidth150onsmartphone"', 'text' => $thirdpartytmp->getNomUrl(1), 'asis'=>1 ); diff --git a/htdocs/core/boxes/box_produits.php b/htdocs/core/boxes/box_produits.php index 3261572460e..53449afceeb 100644 --- a/htdocs/core/boxes/box_produits.php +++ b/htdocs/core/boxes/box_produits.php @@ -131,13 +131,13 @@ class box_produits extends ModeleBoxes $productstatic->entity = $objp->entity; $this->info_box_contents[$line][] = array( - 'td' => 'class="tdoverflowmax100 maxwidth100onsmartphone"', + 'td' => 'class="tdoverflowmax150 maxwidth150onsmartphone"', 'text' => $productstatic->getNomUrl(1), 'asis' => 1, ); $this->info_box_contents[$line][] = array( - 'td' => 'class="tdoverflowmax100 maxwidth100onsmartphone"', + 'td' => 'class="tdoverflowmax150 maxwidth150onsmartphone"', 'text' => $objp->label, ); diff --git a/htdocs/core/boxes/box_produits_alerte_stock.php b/htdocs/core/boxes/box_produits_alerte_stock.php index 9dc75612773..ee49e9e4534 100644 --- a/htdocs/core/boxes/box_produits_alerte_stock.php +++ b/htdocs/core/boxes/box_produits_alerte_stock.php @@ -144,7 +144,7 @@ class box_produits_alerte_stock extends ModeleBoxes ); $this->info_box_contents[$line][] = array( - 'td' => 'class="tdoverflowmax100 maxwidth100onsmartphone"', + 'td' => 'class="tdoverflowmax150 maxwidth150onsmartphone"', 'text' => $objp->label, ); diff --git a/htdocs/core/boxes/box_propales.php b/htdocs/core/boxes/box_propales.php index a94ee0c1f08..8dad41f64a1 100644 --- a/htdocs/core/boxes/box_propales.php +++ b/htdocs/core/boxes/box_propales.php @@ -131,13 +131,13 @@ class box_propales extends ModeleBoxes ); $this->info_box_contents[$line][] = array( - 'td' => 'class="tdoverflowmax100"', + 'td' => 'class="tdoverflowmax150 maxwidth150onsmartphone"', 'text' => $societestatic->getNomUrl(1), 'asis' => 1, ); $this->info_box_contents[$line][] = array( - 'td' => 'class="right"', + 'td' => 'class="right nowraponall"', 'text' => price($objp->total_ht, 0, $langs, 0, -1, -1, $conf->currency), ); diff --git a/htdocs/core/boxes/box_services_contracts.php b/htdocs/core/boxes/box_services_contracts.php index 0cc4e68682b..44a1ca020b5 100644 --- a/htdocs/core/boxes/box_services_contracts.php +++ b/htdocs/core/boxes/box_services_contracts.php @@ -177,7 +177,7 @@ class box_services_contracts extends ModeleBoxes } - $this->info_box_contents[$i][] = array('td' => 'class="tdoverflowmax100 maxwidth100onsmartphone"', + $this->info_box_contents[$i][] = array('td' => 'class="tdoverflowmax150 maxwidth150onsmartphone"', 'text' => $s, 'asis' => 1 ); @@ -187,7 +187,7 @@ class box_services_contracts extends ModeleBoxes 'asis' => 1 ); - $this->info_box_contents[$i][] = array('td' => 'class="tdoverflowmax100 maxwidth100onsmartphone"', + $this->info_box_contents[$i][] = array('td' => 'class="tdoverflowmax150 maxwidth150onsmartphone"', 'text' => $thirdpartytmp->getNomUrl(1), 'asis' => 1 ); diff --git a/htdocs/core/boxes/box_services_expired.php b/htdocs/core/boxes/box_services_expired.php index f123872b85b..72d4390a2e2 100644 --- a/htdocs/core/boxes/box_services_expired.php +++ b/htdocs/core/boxes/box_services_expired.php @@ -126,7 +126,7 @@ class box_services_expired extends ModeleBoxes 'asis' => 1 ); - $this->info_box_contents[$i][] = array('td' => 'class="tdoverflowmax100 maxwidth100onsmartphone" align="left"', + $this->info_box_contents[$i][] = array('td' => 'class="tdoverflowmax150 maxwidth150onsmartphone" align="left"', 'text' => $thirdpartytmp->getNomUrl(1, 'customer'), 'asis' => 1 ); diff --git a/htdocs/core/boxes/modules_boxes.php b/htdocs/core/boxes/modules_boxes.php index 025cfba71a5..74f0ffc9d9d 100644 --- a/htdocs/core/boxes/modules_boxes.php +++ b/htdocs/core/boxes/modules_boxes.php @@ -248,7 +248,7 @@ class ModeleBoxes // Can't be abtract as it is instantiated to build "empty" $out.= '>'; if ($conf->use_javascript_ajax) { - $out.= '
'; + print ''; print $form->select_date($datestart, 'datestart', 0, 0, 1, '', 1, 0, 1); print ''; + print ''; print $form->select_date($dateend, 'dateend', 0, 0, 1, '', 1, 0, 1); print '
'; print $actionstatic->getNomUrl(1,-1); print ''; + print ''; print $form->selectyesno('billed', $billed, 1, 0, 1); print ' '; - $form->select_types_paiements((GETPOST('operation')?GETPOST('operation'):($object->courant == Account::TYPE_CASH ? 'LIQ' : '')),'operation','1,2',2,1); + $form->select_types_paiements((GETPOST('operation')?GETPOST('operation'):($object->courant == Account::TYPE_CASH ? 'LIQ' : '')), 'operation', '1,2', 2, 1); print ''; print ''; @@ -852,7 +852,7 @@ if ($resql) if (! empty($arrayfields['type']['checked'])) { print ''; - $form->select_types_paiements(empty($search_type)?'':$search_type, 'search_type', '', 2, 0, 1, 0, 1, 'maxwidth100'); + $form->select_types_paiements(empty($search_type)?'':$search_type, 'search_type', '', 2, 1, 1, 0, 1, 'maxwidth100'); print ''; - $form->select_types_paiements($typeid,'typeid','',0,0,1,16); + $form->select_types_paiements($typeid,'typeid','',0,1,1,16); print ''; - if (! empty($conf->global->MAIN_LIST_FILTER_ON_DAY)) print ''; - print ''; - $formother->select_year($search_year?$search_year:-1,'search_year',1, 20, 5); + print ''; + if (! empty($conf->global->MAIN_LIST_FILTER_ON_DAY)) print ''; + print ''; + $formother->select_year($search_year?$search_year:-1,'search_year',1, 20, 5, 0, 0, '', 'witdhauto valignmiddle'); print ''; - if (! empty($conf->global->MAIN_LIST_FILTER_ON_DAY)) print ''; - print ''; - $formother->select_year($search_year_date_when?$search_year_date_when:-1,'search_year_date_when',1, 20, 5); + print ''; + if (! empty($conf->global->MAIN_LIST_FILTER_ON_DAY)) print ''; + print ''; + $formother->select_year($search_year_date_when?$search_year_date_when:-1,'search_year_date_when',1, 20, 5, 0, 0, '', 'witdhauto valignmiddle'); print ''; - if (! empty($conf->global->MAIN_LIST_FILTER_ON_DAY)) print ''; - print ''; - $formother->select_year($year?$year:-1,'year',1, 20, 5); + print ''; + if (! empty($conf->global->MAIN_LIST_FILTER_ON_DAY)) print ''; + print ''; + $formother->select_year($year?$year:-1,'year',1, 20, 5, 0, 0, '', 'widthauto valignmiddle'); print ''; - if (! empty($conf->global->MAIN_LIST_FILTER_ON_DAY)) print ''; - print ''; - $formother->select_year($year_lim?$year_lim:-1,'year_lim',1, 20, 5); + print ''; + if (! empty($conf->global->MAIN_LIST_FILTER_ON_DAY)) print ''; + print ''; + $formother->select_year($year_lim?$year_lim:-1,'year_lim',1, 20, 5, 0, 0, '', 'widthauto valignmiddle'); print '
'.$langs->trans("Late"); print '
'; - $form->select_types_paiements($search_paymentmode, 'search_paymentmode', '', 0, 0, 1, 10); + $form->select_types_paiements($search_paymentmode, 'search_paymentmode', '', 0, 1, 1, 10); print ''; print ''; print ''; print ''; print '
'; @@ -355,8 +356,6 @@ if ($resql) // Third party print ''; - $thirdpartystatic->id=$objp->socid; - $thirdpartystatic->name=$objp->name; print $thirdpartystatic->getNomUrl(1); print ' '; - $form->select_types_paiements($typeid,'typeid','',0,0,1,16); + $form->select_types_paiements($typeid,'typeid','',0,1,1,16); print ' '; else print ''; - print ''; + if ($modecompta != 'BOOKKEEPING') print ''; print $annee; if ($conf->global->SOCIETE_FISCAL_MONTH_START > 1) print '-'.($annee+1); - print ' 
'; - $form->select_types_paiements($typeid,'typeid','',0,0,1,16); + $form->select_types_paiements($typeid,'typeid','',0,1,1,16); print '
'; + $out.= ''; diff --git a/htdocs/core/tpl/contacts.tpl.php b/htdocs/core/tpl/contacts.tpl.php index c700f4d6984..71b744fa67b 100644 --- a/htdocs/core/tpl/contacts.tpl.php +++ b/htdocs/core/tpl/contacts.tpl.php @@ -91,7 +91,7 @@ if ($permission) { '; ?>
trans("Users"); ?>
global->MAIN_INFO_SOCIETE_NOM; ?>
-
select_dolusers($user->id, 'userid', 0, (! empty($userAlreadySelected)?$userAlreadySelected:null), 0, null, null, 0, 56); ?>
+
select_dolusers($user->id, 'userid', 0, (! empty($userAlreadySelected)?$userAlreadySelected:null), 0, null, null, 0, 56, '', 0, '', 'minwidth200imp'); ?>
- selectCompaniesForNewContact($object, 'id', $selectedCompany, 'newcompany', '', 0); ?> + selectCompaniesForNewContact($object, 'id', $selectedCompany, 'newcompany', '', 0, '', 'minwidth300imp'); ?>
- select_contacts($selectedCompany, '', 'contactid', 0, '', '', 0, 'minwidth200'); ?> + select_contacts($selectedCompany, '', 'contactid', 0, '', '', 0, 'minwidth100imp'); ?>
element == 'shipping' && is_object($objectsrc)) $tmpobject=$objectsrc; - $formcompany->selectTypeContact($tmpobject, '', 'type','external'); ?> + $formcompany->selectTypeContact($tmpobject, '', 'type','external', 'position', 0, 'minwidth100imp'); ?>
 
diff --git a/htdocs/core/triggers/interface_50_modAgenda_ActionsAuto.class.php b/htdocs/core/triggers/interface_50_modAgenda_ActionsAuto.class.php index 3c34d0a3ee0..78053a0631c 100644 --- a/htdocs/core/triggers/interface_50_modAgenda_ActionsAuto.class.php +++ b/htdocs/core/triggers/interface_50_modAgenda_ActionsAuto.class.php @@ -655,20 +655,53 @@ class InterfaceActionsAuto extends DolibarrTriggers $object->sendtoid=0; } - elseif ($action == 'MEMBER_SUBSCRIPTION') + elseif ($action == 'MEMBER_SUBSCRIPTION_CREATE') { $langs->load("agenda"); $langs->load("other"); $langs->load("members"); - if (empty($object->actionmsg2)) $object->actionmsg2=$langs->transnoentities("MemberSubscriptionAddedInDolibarr",$object->getFullName($langs)); - $object->actionmsg=$langs->transnoentities("MemberSubscriptionAddedInDolibarr",$object->getFullName($langs)); + if (empty($object->actionmsg2)) $object->actionmsg2=$langs->transnoentities("MemberSubscriptionAddedInDolibarr",$object->ref,$object->getFullName($langs)); + $object->actionmsg=$langs->transnoentities("MemberSubscriptionAddedInDolibarr",$object->ref,$object->getFullName($langs)); $object->actionmsg.="\n".$langs->transnoentities("Member").': '.$object->getFullName($langs); $object->actionmsg.="\n".$langs->transnoentities("Type").': '.$object->type; $object->actionmsg.="\n".$langs->transnoentities("Amount").': '.$object->last_subscription_amount; $object->actionmsg.="\n".$langs->transnoentities("Period").': '.dol_print_date($object->last_subscription_date_start,'day').' - '.dol_print_date($object->last_subscription_date_end,'day'); $object->sendtoid=0; + if ($object->fk_soc > 0) $object->socid=$object->fk_soc; + } + elseif ($action == 'MEMBER_SUBSCRIPTION_MODIFY') + { + $langs->load("agenda"); + $langs->load("other"); + $langs->load("members"); + + if (empty($object->actionmsg2)) $object->actionmsg2=$langs->transnoentities("MemberSubscriptionModifiedInDolibarr",$object->ref,$object->getFullName($langs)); + $object->actionmsg=$langs->transnoentities("MemberSubscriptionModifiedInDolibarr",$object->ref,$object->getFullName($langs)); + $object->actionmsg.="\n".$langs->transnoentities("Member").': '.$object->getFullName($langs); + $object->actionmsg.="\n".$langs->transnoentities("Type").': '.$object->type; + $object->actionmsg.="\n".$langs->transnoentities("Amount").': '.$object->last_subscription_amount; + $object->actionmsg.="\n".$langs->transnoentities("Period").': '.dol_print_date($object->last_subscription_date_start,'day').' - '.dol_print_date($object->last_subscription_date_end,'day'); + + $object->sendtoid=0; + if ($object->fk_soc > 0) $object->socid=$object->fk_soc; + } + elseif ($action == 'MEMBER_SUBSCRIPTION_DELETE') + { + $langs->load("agenda"); + $langs->load("other"); + $langs->load("members"); + + if (empty($object->actionmsg2)) $object->actionmsg2=$langs->transnoentities("MemberSubscriptionDeletedInDolibarr",$object->ref,$object->getFullName($langs)); + $object->actionmsg=$langs->transnoentities("MemberSubscriptionDeletedInDolibarr",$object->ref,$object->getFullName($langs)); + $object->actionmsg.="\n".$langs->transnoentities("Member").': '.$object->getFullName($langs); + $object->actionmsg.="\n".$langs->transnoentities("Type").': '.$object->type; + $object->actionmsg.="\n".$langs->transnoentities("Amount").': '.$object->last_subscription_amount; + $object->actionmsg.="\n".$langs->transnoentities("Period").': '.dol_print_date($object->last_subscription_date_start,'day').' - '.dol_print_date($object->last_subscription_date_end,'day'); + + $object->sendtoid=0; + if ($object->fk_soc > 0) $object->socid=$object->fk_soc; } elseif ($action == 'MEMBER_RESILIATE') { @@ -816,6 +849,14 @@ class InterfaceActionsAuto extends DolibarrTriggers $projectid = isset($object->fk_project)?$object->fk_project:0; if ($object->element == 'project') $projectid = $object->id; + $elementid = $object->id; + $elementtype = $object->element; + if ($object->element == 'subscription') + { + $elementid = $object->fk_adherent; + $elementtype = 'member'; + } + // Insertion action require_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php'; $actioncomm = new ActionComm($this->db); @@ -845,8 +886,8 @@ class InterfaceActionsAuto extends DolibarrTriggers $actioncomm->email_subject = $object->email_subject; $actioncomm->errors_to = $object->errors_to; - $actioncomm->fk_element = $object->id; - $actioncomm->elementtype = $object->element; + $actioncomm->fk_element = $elementid; + $actioncomm->elementtype = $elementtype; $ret=$actioncomm->create($user); // User creating action diff --git a/htdocs/fourn/class/fournisseur.commande.class.php b/htdocs/fourn/class/fournisseur.commande.class.php index cf007659487..1fd6bb84de1 100644 --- a/htdocs/fourn/class/fournisseur.commande.class.php +++ b/htdocs/fourn/class/fournisseur.commande.class.php @@ -1535,13 +1535,17 @@ class CommandeFournisseur extends CommonOrder $txtva = preg_replace('/\s*\(.*\)/', '', $txtva); // Remove code into vatrate. } + if ($conf->multicurrency->enabled && $pu_ht_devise > 0) { + $pu = 0; + } + $tabprice = calcul_price_total($qty, $pu, $remise_percent, $txtva, $txlocaltax1, $txlocaltax2, 0, $price_base_type, $info_bits, $product_type, $this->thirdparty, $localtaxes_type, 100, $this->multicurrency_tx,$pu_ht_devise); $total_ht = $tabprice[0]; $total_tva = $tabprice[1]; $total_ttc = $tabprice[2]; $total_localtax1 = $tabprice[9]; $total_localtax2 = $tabprice[10]; - $pu_ht = $tabprice[3]; + $pu = $pu_ht = $tabprice[3]; // MultiCurrency $multicurrency_total_ht = $tabprice[16]; diff --git a/htdocs/fourn/class/fournisseur.facture.class.php b/htdocs/fourn/class/fournisseur.facture.class.php index 1f84e71df96..ccbd93b46e4 100644 --- a/htdocs/fourn/class/fournisseur.facture.class.php +++ b/htdocs/fourn/class/fournisseur.facture.class.php @@ -1387,7 +1387,7 @@ class FactureFournisseur extends CommonInvoice { dol_syslog(get_class($this)."::addline $desc,$pu,$qty,$txtva,$fk_product,$remise_percent,$date_start,$date_end,$ventil,$info_bits,$price_base_type,$type,$fk_unit", LOG_DEBUG); include_once DOL_DOCUMENT_ROOT.'/core/lib/price.lib.php'; - global $mysoc; + global $mysoc, $conf; // Clean parameters if (empty($remise_percent)) $remise_percent=0; @@ -1416,6 +1416,10 @@ class FactureFournisseur extends CommonInvoice $txlocaltax1=price2num($txlocaltax1); $txlocaltax2=price2num($txlocaltax2); + if ($conf->multicurrency->enabled && $pu_ht_devise > 0) { + $pu = 0; + } + $tabprice = calcul_price_total($qty, $pu, $remise_percent, $txtva, $txlocaltax1, $txlocaltax2, 0, $price_base_type, $info_bits, $type, $this->thirdparty, $localtaxes_type, 100, $this->multicurrency_tx, $pu_ht_devise); $total_ht = $tabprice[0]; $total_tva = $tabprice[1]; diff --git a/htdocs/fourn/class/fournisseur.product.class.php b/htdocs/fourn/class/fournisseur.product.class.php index c8c24afc942..b9a2f72b9bd 100644 --- a/htdocs/fourn/class/fournisseur.product.class.php +++ b/htdocs/fourn/class/fournisseur.product.class.php @@ -69,6 +69,13 @@ class ProductFournisseur extends Product var $supplier_reputation; // reputation of supplier var $reputations=array(); // list of available supplier reputations + // Multicurreny + var $fourn_multicurrency_id; + var $fourn_multicurrency_code; + var $fourn_multicurrency_tx; + var $fourn_multicurrency_price; + var $fourn_multicurrency_unitprice; + /** * Constructor * @@ -169,25 +176,29 @@ class ProductFournisseur extends Product /** * Modify the purchase price for a supplier * - * @param int $qty Min quantity for which price is valid - * @param float $buyprice Purchase price for the quantity min - * @param User $user Object user user made changes - * @param string $price_base_type HT or TTC - * @param Societe $fourn Supplier - * @param int $availability Product availability - * @param string $ref_fourn Supplier ref - * @param float $tva_tx New VAT Rate (For example 8.5. Should not be a string) - * @param string $charges costs affering to product - * @param float $remise_percent Discount regarding qty (percent) - * @param float $remise Discount regarding qty (amount) - * @param int $newnpr Set NPR or not - * @param int $delivery_time_days Delay in days for delivery (max). May be '' if not defined. - * @param string $supplier_reputation Reputation with this product to the defined supplier (empty, FAVORITE, DONOTORDER) - * @param array $localtaxes_array Array with localtaxes info array('0'=>type1,'1'=>rate1,'2'=>type2,'3'=>rate2) (loaded by getLocalTaxesFromRate(vatrate, 0, ...) function). - * @param string $newdefaultvatcode Default vat code + * @param int $qty Min quantity for which price is valid + * @param float $buyprice Purchase price for the quantity min + * @param User $user Object user user made changes + * @param string $price_base_type HT or TTC + * @param Societe $fourn Supplier + * @param int $availability Product availability + * @param string $ref_fourn Supplier ref + * @param float $tva_tx New VAT Rate (For example 8.5. Should not be a string) + * @param string $charges costs affering to product + * @param float $remise_percent Discount regarding qty (percent) + * @param float $remise Discount regarding qty (amount) + * @param int $newnpr Set NPR or not + * @param int $delivery_time_days Delay in days for delivery (max). May be '' if not defined. + * @param string $supplier_reputation Reputation with this product to the defined supplier (empty, FAVORITE, DONOTORDER) + * @param array $localtaxes_array Array with localtaxes info array('0'=>type1,'1'=>rate1,'2'=>type2,'3'=>rate2) (loaded by getLocalTaxesFromRate(vatrate, 0, ...) function). + * @param string $newdefaultvatcode Default vat code + * @param float $multicurrency_buyprice Purchase price for the quantity min in currency + * @param string $multicurrency_price_base_type HT or TTC in currency + * @param float $multicurrency_tx Rate currency + * @param string $multicurrency_code Currency code * @return int <0 if KO, >=0 if OK */ - function update_buyprice($qty, $buyprice, $user, $price_base_type, $fourn, $availability, $ref_fourn, $tva_tx, $charges=0, $remise_percent=0, $remise=0, $newnpr=0, $delivery_time_days=0, $supplier_reputation='', $localtaxes_array=array(), $newdefaultvatcode='') + function update_buyprice($qty, $buyprice, $user, $price_base_type, $fourn, $availability, $ref_fourn, $tva_tx, $charges=0, $remise_percent=0, $remise=0, $newnpr=0, $delivery_time_days=0, $supplier_reputation='', $localtaxes_array=array(), $newdefaultvatcode='', $multicurrency_buyprice=0, $multicurrency_price_base_type='HT',$multicurrency_tx=1,$multicurrency_code='') { global $conf, $langs; //global $mysoc; @@ -205,6 +216,25 @@ class ProductFournisseur extends Product $ttx = $tva_tx; $buyprice = $buyprice/(1+($ttx/100)); } + + // Multicurrency + if ($conf->multicurrency->enabled) { + if (empty($multicurrency_tx)) $multicurrency_tx=1; + if (empty($multicurrency_buyprice)) $multicurrency_buyprice=0; + + if (empty($multicurrency_buyprice)) $multicurrency_buyprice=0; + if ($multicurrency_price_base_type == 'TTC') + { + $ttx = $tva_tx; + $multicurrency_buyprice = $multicurrency_buyprice/(1+($ttx/100)); + } + $multicurrency_buyprice=price2num($multicurrency_buyprice,'MU'); + $multicurrency_unitBuyPrice=price2num($multicurrency_buyprice/$qty,'MU'); + + $buyprice=$multicurrency_buyprice/$multicurrency_tx; + $fk_multicurrency = MultiCurrency::getIdFromCode($this->db, $multicurrency_code); + } + $buyprice=price2num($buyprice,'MU'); $charges=price2num($charges,'MU'); $qty=price2num($qty); @@ -246,6 +276,11 @@ class ProductFournisseur extends Product $sql.= " remise = ".$remise.","; $sql.= " unitprice = ".$unitBuyPrice.","; $sql.= " fk_availability = ".$availability.","; + $sql.= " multicurrency_price = ".(isset($multicurrency_buyprice)?"'".$this->db->escape(price2num($multicurrency_buyprice))."'":'null').","; + $sql.= " multicurrency_unitprice = ".(isset($multicurrency_unitBuyPrice)?"'".$this->db->escape(price2num($multicurrency_unitBuyPrice))."'":'null').","; + $sql.= " multicurrency_tx = ".(isset($multicurrency_tx)?"'".$this->db->escape($multicurrency_tx)."'":'1').","; + $sql.= " fk_multicurrency = ".(isset($fk_multicurrency)?"'".$this->db->escape($fk_multicurrency)."'":'null').","; + $sql.= " multicurrency_code = ".(isset($multicurrency_code)?"'".$this->db->escape($multicurrency_code)."'":'null').","; $sql.= " entity = ".$conf->entity.","; $sql.= " tva_tx = ".price2num($tva_tx).","; // TODO Add localtax1 and localtax2 @@ -300,8 +335,15 @@ class ProductFournisseur extends Product if ($resql) { // Add price for this quantity to supplier $sql = "INSERT INTO " . MAIN_DB_PREFIX . "product_fournisseur_price("; + $sql.= " multicurrency_price, multicurrency_unitprice, multicurrency_tx, fk_multicurrency, multicurrency_code,"; $sql .= "datec, fk_product, fk_soc, ref_fourn, fk_user, price, quantity, remise_percent, remise, unitprice, tva_tx, charges, fk_availability, default_vat_code, info_bits, entity, delivery_time_days, supplier_reputation)"; - $sql .= " values('" . $this->db->idate($now) . "',"; + $sql .= " values("; + $sql.= (isset($multicurrency_buyprice)?"'".$this->db->escape(price2num($multicurrency_buyprice))."'":'null').","; + $sql.= (isset($multicurrency_unitBuyPrice)?"'".$this->db->escape(price2num($multicurrency_unitBuyPrice))."'":'null').","; + $sql.= (isset($multicurrency_tx)?"'".$this->db->escape($multicurrency_tx)."'":'1').","; + $sql.= (isset($fk_multicurrency)?"'".$this->db->escape($fk_multicurrency)."'":'null').","; + $sql.= (isset($multicurrency_code)?"'".$this->db->escape($multicurrency_code)."'":'null').","; + $sql .= " '" . $this->db->idate($now) . "',"; $sql .= " " . $this->id . ","; $sql .= " " . $fourn->id . ","; $sql .= " '" . $this->db->escape($ref_fourn) . "',"; @@ -334,8 +376,15 @@ class ProductFournisseur extends Product if (! $error && empty($conf->global->PRODUCT_PRICE_SUPPLIER_NO_LOG)) { // Add record into log table $sql = "INSERT INTO " . MAIN_DB_PREFIX . "product_fournisseur_price_log("; + $sql.= " multicurrency_price, multicurrency_unitprice, multicurrency_tx, fk_multicurrency, multicurrency_code,"; $sql .= "datec, fk_product_fournisseur,fk_user,price,quantity)"; - $sql .= "values('" . $this->db->idate($now) . "',"; + $sql .= "values("; + $sql.= (isset($multicurrency_buyprice)?"'".$this->db->escape(price2num($multicurrency_buyprice))."'":'null').","; + $sql.= (isset($multicurrency_unitBuyPrice)?"'".$this->db->escape(price2num($multicurrency_unitBuyPrice))."'":'null').","; + $sql.= (isset($multicurrency_tx)?"'".$this->db->escape($multicurrency_tx)."'":'1').","; + $sql.= (isset($fk_multicurrency)?"'".$this->db->escape($fk_multicurrency)."'":'null').","; + $sql.= (isset($multicurrency_code)?"'".$this->db->escape($multicurrency_code)."'":'null').","; + $sql .= " '" . $this->db->idate($now) . "',"; $sql .= " " . $this->product_fourn_id . ","; $sql .= " " . $user->id . ","; $sql .= " " . price2num($buyprice) . ","; @@ -388,6 +437,7 @@ class ProductFournisseur extends Product $sql = "SELECT pfp.rowid, pfp.price, pfp.quantity, pfp.unitprice, pfp.remise_percent, pfp.remise, pfp.tva_tx, pfp.default_vat_code, pfp.fk_availability,"; $sql.= " pfp.fk_soc, pfp.ref_fourn, pfp.fk_product, pfp.charges, pfp.fk_supplier_price_expression, pfp.delivery_time_days,"; // , pfp.recuperableonly as fourn_tva_npr"; FIXME this field not exist in llx_product_fournisseur_price $sql.= " pfp.supplier_reputation"; + $sql.= " ,pfp.multicurrency_price, pfp.multicurrency_unitprice, pfp.multicurrency_tx, pfp.fk_multicurrency, pfp.multicurrency_code"; $sql.= " FROM ".MAIN_DB_PREFIX."product_fournisseur_price as pfp"; $sql.= " WHERE pfp.rowid = ".$rowid; @@ -421,6 +471,12 @@ class ProductFournisseur extends Product $this->supplier_reputation = $obj->supplier_reputation; $this->default_vat_code = $obj->default_vat_code; + $this->fourn_multicurrency_price = $obj->multicurrency_price; + $this->fourn_multicurrency_unitprice = $obj->multicurrency_unitprice; + $this->fourn_multicurrency_tx = $obj->multicurrency_tx; + $this->fourn_multicurrency_id = $obj->fk_multicurrency; + $this->fourn_multicurrency_code = $obj->multicurrency_code; + if (empty($ignore_expression) && !empty($this->fk_supplier_price_expression)) { $priceparser = new PriceParser($this->db); @@ -471,6 +527,7 @@ class ProductFournisseur extends Product $sql = "SELECT s.nom as supplier_name, s.rowid as fourn_id,"; $sql.= " pfp.rowid as product_fourn_pri_id, pfp.ref_fourn, pfp.fk_product as product_fourn_id, pfp.fk_supplier_price_expression,"; $sql.= " pfp.price, pfp.quantity, pfp.unitprice, pfp.remise_percent, pfp.remise, pfp.tva_tx, pfp.fk_availability, pfp.charges, pfp.info_bits, pfp.delivery_time_days, pfp.supplier_reputation"; + $sql.= " ,pfp.multicurrency_price, pfp.multicurrency_unitprice, pfp.multicurrency_tx, pfp.fk_multicurrency, pfp.multicurrency_code"; $sql.= " FROM ".MAIN_DB_PREFIX."product_fournisseur_price as pfp"; $sql.= ", ".MAIN_DB_PREFIX."societe as s"; $sql.= " WHERE pfp.entity IN (".getEntity('productprice').")"; @@ -512,6 +569,12 @@ class ProductFournisseur extends Product $prodfourn->fk_supplier_price_expression = $record["fk_supplier_price_expression"]; $prodfourn->supplier_reputation = $record["supplier_reputation"]; + $prodfourn->fourn_multicurrency_price = $record["multicurrency_price"]; + $prodfourn->fourn_multicurrency_unitprice = $record["multicurrency_unitprice"]; + $prodfourn->fourn_multicurrency_tx = $record["multicurrency_tx"]; + $prodfourn->fourn_multicurrency_id = $record["fk_multicurrency"]; + $prodfourn->fourn_multicurrency_code = $record["multicurrency_code"]; + if (!empty($conf->dynamicprices->enabled) && !empty($prodfourn->fk_supplier_price_expression)) { $priceparser = new PriceParser($this->db); $price_result = $priceparser->parseProductSupplier($prodfourn); @@ -577,10 +640,17 @@ class ProductFournisseur extends Product $this->delivery_time_days = ''; $this->id = ''; + $this->fourn_multicurrency_price = ''; + $this->fourn_multicurrency_unitprice = ''; + $this->fourn_multicurrency_tx = ''; + $this->fourn_multicurrency_id = ''; + $this->fourn_multicurrency_code = ''; + $sql = "SELECT s.nom as supplier_name, s.rowid as fourn_id,"; $sql.= " pfp.rowid as product_fourn_price_id, pfp.ref_fourn,"; $sql.= " pfp.price, pfp.quantity, pfp.unitprice, pfp.tva_tx, pfp.charges,"; $sql.= " pfp.remise, pfp.remise_percent, pfp.fk_supplier_price_expression, pfp.delivery_time_days"; + $sql.= " ,pfp.multicurrency_price, pfp.multicurrency_unitprice, pfp.multicurrency_tx, pfp.fk_multicurrency, pfp.multicurrency_code"; $sql.= " FROM ".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."product_fournisseur_price as pfp"; $sql.= " WHERE s.entity IN (".getEntity('societe').")"; $sql.= " AND pfp.fk_product = ".$prodid; @@ -654,6 +724,11 @@ class ProductFournisseur extends Product $this->delivery_time_days = $record["delivery_time_days"]; $this->fk_supplier_price_expression = $record["fk_supplier_price_expression"]; $this->id = $prodid; + $this->fourn_multicurrency_price = $record["multicurrency_price"]; + $this->fourn_multicurrency_unitprice = $record["multicurrency_unitprice"]; + $this->fourn_multicurrency_tx = $record["multicurrency_tx"]; + $this->fourn_multicurrency_id = $record["fk_multicurrency"]; + $this->fourn_multicurrency_code = $record["multicurrency_code"]; $min = $fourn_unitprice; } } diff --git a/htdocs/fourn/commande/card.php b/htdocs/fourn/commande/card.php index 6f541803d55..555cde48899 100644 --- a/htdocs/fourn/commande/card.php +++ b/htdocs/fourn/commande/card.php @@ -419,7 +419,8 @@ if (empty($reshook)) $date_start, $date_end, $array_options, - $productsupplier->fk_unit + $productsupplier->fk_unit, + $productsupplier->fourn_multicurrency_unitprice ); } if ($idprod == -99 || $idprod == 0) diff --git a/htdocs/fourn/facture/card.php b/htdocs/fourn/facture/card.php index 0368d5cd7c8..1f9227ce9b6 100644 --- a/htdocs/fourn/facture/card.php +++ b/htdocs/fourn/facture/card.php @@ -1018,7 +1018,9 @@ if (empty($reshook)) 0, $array_options, $productsupplier->fk_unit, - $productsupplier->fourn_ref + 0, + $productsupplier->fourn_multicurrency_unitprice, + $productsupplier->fourn_ref ); } if ($idprod == -99 || $idprod == 0) diff --git a/htdocs/fourn/facture/list.php b/htdocs/fourn/facture/list.php index 083967935fa..f48f3d2c01d 100644 --- a/htdocs/fourn/facture/list.php +++ b/htdocs/fourn/facture/list.php @@ -655,7 +655,7 @@ if ($resql) if (! empty($arrayfields['f.fk_mode_reglement']['checked'])) { print '
'; } if (! empty($arrayfields['f.total_ht']['checked'])) diff --git a/htdocs/includes/stripe/.gitignore b/htdocs/includes/stripe/.gitignore index 93251c95077..17b94183baf 100644 --- a/htdocs/includes/stripe/.gitignore +++ b/htdocs/includes/stripe/.gitignore @@ -12,3 +12,6 @@ composer.lock # Ignore PHPUnit coverage file clover.xml + +# Ignore IDE's configuration files +.idea diff --git a/htdocs/includes/stripe/.travis.yml b/htdocs/includes/stripe/.travis.yml index 934b517bfea..d575ed51a7d 100644 --- a/htdocs/includes/stripe/.travis.yml +++ b/htdocs/includes/stripe/.travis.yml @@ -1,18 +1,40 @@ +sudo: false + language: php php: - - 5.3 - 5.4 - 5.5 - 5.6 - 7.0 - 7.1 + - 7.2 - hhvm env: - - AUTOLOAD=1 - - AUTOLOAD=0 + global: + - STRIPE_MOCK_VERSION=0.8.0 + matrix: + - AUTOLOAD=1 + - AUTOLOAD=0 + +cache: + directories: + - $HOME/.composer/cache/files + - stripe-mock + +before_install: + # Unpack and start stripe-mock so that the test suite can talk to it + - | + if [ ! -d "stripe-mock/stripe-mock_${STRIPE_MOCK_VERSION}" ]; then + mkdir -p stripe-mock/stripe-mock_${STRIPE_MOCK_VERSION}/ + curl -L "https://github.com/stripe/stripe-mock/releases/download/v${STRIPE_MOCK_VERSION}/stripe-mock_${STRIPE_MOCK_VERSION}_linux_amd64.tar.gz" -o "stripe-mock/stripe-mock_${STRIPE_MOCK_VERSION}_linux_amd64.tar.gz" + tar -zxf "stripe-mock/stripe-mock_${STRIPE_MOCK_VERSION}_linux_amd64.tar.gz" -C "stripe-mock/stripe-mock_${STRIPE_MOCK_VERSION}/" + fi + - | + stripe-mock/stripe-mock_${STRIPE_MOCK_VERSION}/stripe-mock > /dev/null & + STRIPE_MOCK_PID=$! script: ./build.php ${AUTOLOAD} + after_script: ./vendor/bin/coveralls -v -sudo: false diff --git a/htdocs/includes/stripe/CHANGELOG.md b/htdocs/includes/stripe/CHANGELOG.md index 3650c21d1c2..3f0fdfce153 100644 --- a/htdocs/includes/stripe/CHANGELOG.md +++ b/htdocs/includes/stripe/CHANGELOG.md @@ -1,237 +1,315 @@ -### 4.7.0 2017-04-10 +# Changelog +## 6.4.1 - 2018-03-02 +* [#455](https://github.com/stripe/stripe-php/pull/455) Fix namespaces in PHPDoc +* [#456](https://github.com/stripe/stripe-php/pull/456) Fix namespaces for some exceptions + +## 6.4.0 - 2018-02-28 +* [#453](https://github.com/stripe/stripe-php/pull/453) Add constants for `reason` (`REASON_*`) and `status` (`STATUS_*`) on `\Stripe\Dispute` + +## 6.3.2 - 2018-02-27 +* [#452](https://github.com/stripe/stripe-php/pull/452) Add PHPDoc for `amount_paid` and `amount_remaining` on `\Stripe\Invoice` + +## 6.3.1 - 2018-02-26 +* [#443](https://github.com/stripe/stripe-php/pull/443) Add event types as constants to `\Stripe\Event` class + +## 6.3.0 - 2018-02-23 +* [#450](https://github.com/stripe/stripe-php/pull/450) Add support for `code` attribute on all Stripe exceptions + +## 6.2.0 - 2018-02-21 +* [#440](https://github.com/stripe/stripe-php/pull/440) Add support for topups +* [#442](https://github.com/stripe/stripe-php/pull/442) Fix PHPDoc for `\Stripe\Error\SignatureVerification` + +## 6.1.0 - 2018-02-12 +* [#435](https://github.com/stripe/stripe-php/pull/435) Fix header persistence on `Collection` objects +* [#436](https://github.com/stripe/stripe-php/pull/436) Introduce new `Idempotency` error class + +## 6.0.0 - 2018-02-07 +Major version release. List of backwards incompatible changes to watch out for: ++ The minimum PHP version is now 5.4.0. If you're using PHP 5.3 or older, consider upgrading to a more recent version. +* `\Stripe\AttachedObject` no longer exists. Attributes that used to be instances of `\Stripe\AttachedObject` (such as `metadata`) are now instances of `\Stripe\StripeObject`. ++ Attributes that used to be PHP arrays (such as `legal_entity->additional_owners` on `\Stripe\Account` instances) are now instances of `\Stripe\StripeObject`, except when they are empty. `\Stripe\StripeObject` has array semantics so this should not be an issue unless you are actively checking types. +* `\Stripe\Collection` now derives from `\Stripe\StripeObject` rather than from `\Stripe\ApiResource`. + +Pull requests included in this release: +* [#410](https://github.com/stripe/stripe-php/pull/410) Drop support for PHP 5.3 +* [#411](https://github.com/stripe/stripe-php/pull/411) Use traits for common API operations +* [#414](https://github.com/stripe/stripe-php/pull/414) Use short array syntax +* [#404](https://github.com/stripe/stripe-php/pull/404) Fix serialization logic +* [#417](https://github.com/stripe/stripe-php/pull/417) Remove `ExternalAccount` class +* [#418](https://github.com/stripe/stripe-php/pull/418) Increase test coverage +* [#421](https://github.com/stripe/stripe-php/pull/421) Update CA bundle and add script for future updates +* [#422](https://github.com/stripe/stripe-php/pull/422) Use vendored CA bundle for all requests +* [#428](https://github.com/stripe/stripe-php/pull/428) Support for automatic request retries + +## 5.9.2 - 2018-02-07 +* [#431](https://github.com/stripe/stripe-php/pull/431) Update PHPDoc @property tags for latest API version + +## 5.9.1 - 2018-02-06 +* [#427](https://github.com/stripe/stripe-php/pull/427) Add and update PHPDoc @property tags on all API resources + +## 5.9.0 - 2018-01-17 +* [#421](https://github.com/stripe/stripe-php/pull/421) Updated bundled CA certificates +* [#423](https://github.com/stripe/stripe-php/pull/423) Escape unsanitized input in OAuth example + +## 5.8.0 - 2017-12-20 +* [#403](https://github.com/stripe/stripe-php/pull/403) Add `__debugInfo()` magic method to `StripeObject` + +## 5.7.0 - 2017-11-28 +* [#390](https://github.com/stripe/stripe-php/pull/390) Remove some unsupported API methods +* [#391](https://github.com/stripe/stripe-php/pull/391) Alphabetize the list of API resources in `Util::convertToStripeObject()` and add missing resources +* [#393](https://github.com/stripe/stripe-php/pull/393) Fix expiry date update for card sources + +## 5.6.0 - 2017-10-31 +* [#386](https://github.com/stripe/stripe-php/pull/386) Support for exchange rates APIs + +## 5.5.1 - 2017-10-30 +* [#387](https://github.com/stripe/stripe-php/pull/387) Allow `personal_address_kana` and `personal_address_kanji` to be updated on an account + +## 5.5.0 - 2017-10-27 +* [#385](https://github.com/stripe/stripe-php/pull/385) Support for listing source transactions + +## 5.4.0 - 2017-10-24 +* [#383](https://github.com/stripe/stripe-php/pull/383) Add static methods to manipulate resources from parent + * `Account` gains methods for external accounts and login links (e.g. `createExternalAccount`, `createLoginLink`) + * `ApplicationFee` gains methods for refunds + * `Customer` gains methods for sources + * `Transfer` gains methods for reversals + +## 5.3.0 - 2017-10-11 +* [#378](https://github.com/stripe/stripe-php/pull/378) Rename source `delete` to `detach` (and deprecate the former) + +## 5.2.3 - 2017-09-27 +* Add PHPDoc for `Card` + +## 5.2.2 - 2017-09-20 +* Fix deserialization mapping of `FileUpload` objects + +## 5.2.1 - 2017-09-14 +* Serialized `shipping` nested attribute + +## 5.2.0 - 2017-08-29 +* Add support for `InvalidClient` OAuth error + +## 5.1.3 - 2017-08-14 +* Allow `address_kana` and `address_kanji` to be updated for custom accounts + +## 5.1.2 - 2017-08-01 +* Fix documented return type of `autoPagingIterator()` (was missing namespace) + +## 5.1.1 - 2017-07-03 +* Fix order returns to use the right URL `/v1/order_returns` + +## 5.1.0 - 2017-06-30 +* Add support for OAuth + +## 5.0.0 - 2017-06-27 +* `pay` on invoice now takes params as well as opts + +## 4.13.0 - 2017-06-19 +* Add support for ephemeral keys + +## 4.12.0 - 2017-06-05 +* Clients can implement `getUserAgentInfo()` to add additional user agent information + +## 4.11.0 - 2017-06-05 +* Implement `Countable` for `AttachedObject` (`metadata` and `additional_owners`) + +## 4.10.0 - 2017-05-25 +* Add support for login links + +## 4.9.1 - 2017-05-10 +* Fix docs to include arrays on `$id` parameter for retrieve methods + +## 4.9.0 - 2017-04-28 +* Support for checking webhook signatures + +## 4.8.1 - 2017-04-24 +* Allow nested field `payout_schedule` to be updated + +## 4.8.0 - 2017-04-20 +* Add `\Stripe\Stripe::setLogger()` to support an external PSR-3 compatible logger + +## 4.7.0 - 2017-04-10 * Add support for payouts and recipient transfers -### 4.6.0 2017-04-06 - +## 4.6.0 - 2017-04-06 * Please see 4.7.0 instead (no-op release) -### 4.5.1 2017-03-22 - +## 4.5.1 - 2017-03-22 * Remove hard dependency on cURL -### 4.5.0 2017-03-20 - +## 4.5.0 - 2017-03-20 * Support for detaching sources from customers -### 4.4.2 2017-02-27 - +## 4.4.2 - 2017-02-27 * Correct handling of `owner` parameter when updating sources -### 4.4.1 2017-02-24 - +## 4.4.1 - 2017-02-24 * Correct the error check on a bad JSON decoding -### 4.4.0 2017-01-18 - +## 4.4.0 - 2017-01-18 * Add support for updating sources -### 4.3.0 2016-11-30 - +## 4.3.0 - 2016-11-30 * Add support for verifying sources -### 4.2.0 2016-11-21 - +## 4.2.0 - 2016-11-21 * Add retrieve method for 3-D Secure resources -### 4.1.1 2016-10-21 - +## 4.1.1 - 2016-10-21 * Add docblock with model properties for `Plan` -### 4.1.0 2016-10-18 - +## 4.1.0 - 2016-10-18 * Support for 403 status codes (permission denied) -### 4.0.1 2016-10-17 - +## 4.0.1 - 2016-10-17 * Fix transfer reversal materialization * Fixes for some property definitions in docblocks -### 4.0.0 2016-09-28 - +## 4.0.0 - 2016-09-28 * Support for subscription items * Drop attempt to force TLS 1.2: please note that this could be breaking if you're using old OS distributions or packages and upgraded recently (so please make sure to test your integration!) -### 3.23.0 2016-09-15 - +## 3.23.0 - 2016-09-15 * Add support for Apple Pay domains -### 3.22.0 2016-09-13 - +## 3.22.0 - 2016-09-13 * Add `Stripe::setAppInfo` to allow plugins to register user agent information -### 3.21.0 2016-08-25 - +## 3.21.0 - 2016-08-25 * Add `Source` model for generic payment sources -### 3.20.0 2016-08-08 - +## 3.20.0 - 2016-08-08 * Add `getDeclineCode` to card errors -### 3.19.0 2016-07-29 - +## 3.19.0 - 2016-07-29 * Opt requests directly into TLS 1.2 where OpenSSL >= 1.0.1 (see #277 for context) -### 3.18.0 2016-07-28 - +## 3.18.0 - 2016-07-28 * Add new `STATUS_` constants for subscriptions -### 3.17.1 2016-07-28 - +## 3.17.1 - 2016-07-28 * Fix auto-paging iterator so that it plays nicely with `iterator_to_array` -### 3.17.0 2016-07-14 - +## 3.17.0 - 2016-07-14 * Add field annotations to model classes for better editor hinting -### 3.16.0 2016-07-12 - +## 3.16.0 - 2016-07-12 * Add `ThreeDSecure` model for 3-D secure payments -### 3.15.0 2016-06-29 - +## 3.15.0 - 2016-06-29 * Add static `update` method to all resources that can be changed. -### 3.14.3 2016-06-20 - +## 3.14.3 - 2016-06-20 * Make sure that cURL never sends `Expects: 100-continue`, even on large request bodies -### 3.14.2 2016-06-03 - +## 3.14.2 - 2016-06-03 * Add `inventory` under `SKU` to list of keys that have nested data and can be updated -### 3.14.1 2016-05-27 - +## 3.14.1 - 2016-05-27 * Fix some inconsistencies in PHPDoc -### 3.14.0 2016-05-25 - +## 3.14.0 - 2016-05-25 * Add support for returning Relay orders -### 3.13.0 2016-05-04 - +## 3.13.0 - 2016-05-04 * Add `list`, `create`, `update`, `retrieve`, and `delete` methods to the Subscription class -### 3.12.1 2016-04-07 - +## 3.12.1 - 2016-04-07 * Additional check on value arrays for some extra safety -### 3.12.0 2016-03-31 - +## 3.12.0 - 2016-03-31 * Fix bug `refreshFrom` on `StripeObject` would not take an `$opts` array * Fix bug where `$opts` not passed to parent `save` method in `Account` * Fix bug where non-existent variable was referenced in `reverse` in `Transfer` * Update CA cert bundle for compatibility with OpenSSL versions below 1.0.1 -### 3.11.0 2016-03-22 - +## 3.11.0 - 2016-03-22 * Allow `CurlClient` to be initialized with default `CURLOPT_*` options -### 3.10.1 2016-03-22 - +## 3.10.1 - 2016-03-22 * Fix bug where request params and options were ignored in `ApplicationFee`'s `refund.` -### 3.10.0 2016-03-15 - +## 3.10.0 - 2016-03-15 * Add `reject` on `Account` to support the new API feature -### 3.9.2 2016-03-04 - +## 3.9.2 - 2016-03-04 * Fix error when an object's metadata is set more than once -### 3.9.1 2016-02-24 - +## 3.9.1 - 2016-02-24 * Fix encoding behavior of nested arrays for requests (see #227) -### 3.9.0 2016-02-09 - +## 3.9.0 - 2016-02-09 * Add automatic pagination mechanism with `autoPagingIterator()` * Allow global account ID to be set with `Stripe::setAccountId()` -### 3.8.0 2016-02-08 - +## 3.8.0 - 2016-02-08 * Add `CountrySpec` model for looking up country payment information -### 3.7.1 2016-02-01 - +## 3.7.1 - 2016-02-01 * Update bundled CA certs -### 3.7.0 2016-01-27 - +## 3.7.0 - 2016-01-27 * Support deleting Relay products and SKUs -### 3.6.0 2016-01-05 - +## 3.6.0 - 2016-01-05 * Allow configuration of HTTP client timeouts -### 3.5.0 2015-12-01 - +## 3.5.0 - 2015-12-01 * Add a verification routine for external accounts -### 3.4.0 2015-09-14 - +## 3.4.0 - 2015-09-14 * Products, SKUs, and Orders -- https://stripe.com/relay -### 3.3.0 2015-09-11 - +## 3.3.0 - 2015-09-11 * Add support for 429 Rate Limit response -### 3.2.0 2015-08-17 - +## 3.2.0 - 2015-08-17 * Add refund listing and retrieval without an associated charge -### 3.1.0 2015-08-03 - +## 3.1.0 - 2015-08-03 * Add dispute listing and retrieval * Add support for manage account deletion -### 3.0.0 2015-07-28 - +## 3.0.0 - 2015-07-28 * Rename `\Stripe\Object` to `\Stripe\StripeObject` (PHP 7 compatibility) * Rename `getCode` and `getParam` in exceptions to `getStripeCode` and `getStripeParam` * Add support for calling `json_encode` on Stripe objects in PHP 5.4+ * Start supporting/testing PHP 7 -### 2.3.0 2015-07-06 - +## 2.3.0 - 2015-07-06 * Add request ID to all Stripe exceptions -### 2.2.0 2015-06-01 - +## 2.2.0 - 2015-06-01 * Add support for Alipay accounts as sources * Add support for bank accounts as sources (private beta) * Add support for bank accounts and cards as external_accounts on Account objects -### 2.1.4 2015-05-13 - +## 2.1.4 - 2015-05-13 * Fix CA certificate file path (thanks @lphilps & @matthewarkin) -### 2.1.3 2015-05-12 - +## 2.1.3 - 2015-05-12 * Fix to account updating to permit `tos_acceptance` and `personal_address` to be set properly * Fix to Transfer reversal creation (thanks @neatness!) * Network requests are now done through a swappable class for easier mocking -### 2.1.2 2015-04-10 - +## 2.1.2 - 2015-04-10 * Remove SSL cert revokation checking (all pre-Heartbleed certs have expired) * Bug fixes to account updating -### 2.1.1 2015-02-27 +## 2.1.1 - 2015-02-27 * Support transfer reversals -### 2.1.0 2015-02-19 - +## 2.1.0 - 2015-02-19 * Support new API version (2015-02-18) * Added Bitcoin Receiever update and delete actions * Edited tests to prefer "source" over "card" as per new API version -### 2.0.1 2015-02-16 - +## 2.0.1 - 2015-02-16 * Fix to fetching endpoints that use a non-default baseUrl (`FileUpload`) -### 2.0.0 2015-02-14 - +## 2.0.0 - 2015-02-14 * Bumped minimum version to 5.3.3 * Switched to Stripe namespace instead of Stripe_ class name prefiexes (thanks @chadicus!) * Switched tests to PHPUnit (thanks @chadicus!) @@ -239,192 +317,134 @@ * Added $opts hash to the end of most methods: this permits passing 'idempotency_key', 'stripe_account', or 'stripe_version'. The last 2 will persist across multiple object loads. * Added support for retrieving Account by ID -### 1.18.0 2015-01-21 - +## 1.18.0 - 2015-01-21 * Support making bitcoin charges through BitcoinReceiver source object -### 1.17.5 2014-12-23 - +## 1.17.5 - 2014-12-23 * Adding support for creating file uploads. -### 1.17.4 2014-12-15 - +## 1.17.4 - 2014-12-15 * Saving objects fetched with a custom key now works (thanks @JustinHook & @jpasilan) * Added methods for reporting charges as safe or fraudulent and for specifying the reason for refunds -### 1.17.3 2014-11-06 - +## 1.17.3 - 2014-11-06 * Better handling of HHVM support for SSL certificate blacklist checking. -### 1.17.2 2014-09-23 - +## 1.17.2 - 2014-09-23 * Coupons now are backed by a `Stripe_Coupon` instead of `Stripe_Object`, and support updating metadata * Running operations (`create`, `retrieve`, `all`) on upcoming invoice items now works -### 1.17.1 2014-07-31 - +## 1.17.1 - 2014-07-31 * Requests now send Content-Type header -### 1.17.0 2014-07-29 - +## 1.17.0 - 2014-07-29 * Application Fee refunds now a list instead of array * HHVM now works * Small bug fixes (thanks @bencromwell & @fastest963) -* __toString now returns the name of the object in addition to its JSON representation - -### 1.16.0 2014-06-17 +* `__toString` now returns the name of the object in addition to its JSON representation +## 1.16.0 - 2014-06-17 * Add metadata for refunds and disputes -### 1.15.0 2014-05-28 - +## 1.15.0 - 2014-05-28 * Support canceling transfers -### 1.14.1 2014-05-21 - +## 1.14.1 - 2014-05-21 * Support cards for recipients. -### 1.13.1 2014-05-15 - +## 1.13.1 - 2014-05-15 * Fix bug in account resource where `id` wasn't in the result -### 1.13.0 2014-04-10 - +## 1.13.0 - 2014-04-10 * Add support for certificate blacklisting * Update ca bundle * Drop support for HHVM (Temporarily) -### 1.12.0 2014-04-01 - +## 1.12.0 - 2014-04-01 * Add Stripe_RateLimitError for catching rate limit errors. * Update to Zend coding style (thanks, @jpiasetz) -### 1.11.0 2014-01-29 - +## 1.11.0 - 2014-01-29 * Add support for multiple subscriptions per customer -### 1.10.1 2013-12-02 - +## 1.10.1 - 2013-12-02 * Add new ApplicationFee -### 1.9.1 2013-11-08 - +## 1.9.1 - 2013-11-08 * Fix a bug where a null nestable object causes warnings to fire. -### 1.9.0 2013-10-16 - +## 1.9.0 - 2013-10-16 * Add support for metadata API. -### 1.8.4 2013-09-18 - +## 1.8.4 - 2013-09-18 * Add support for closing disputes. -### 1.8.3 2013-08-13 - +## 1.8.3 - 2013-08-13 * Add new Balance and BalanceTransaction -### 1.8.2 2013-08-12 - -* Add support for unsetting attributes by updating to NULL. - Setting properties to a blank string is now an error. - -### 1.8.1 2013-07-12 +## 1.8.2 - 2013-08-12 +* Add support for unsetting attributes by updating to NULL. Setting properties to a blank string is now an error. +## 1.8.1 - 2013-07-12 * Add support for multiple cards API (Stripe API version 2013-07-12: https://stripe.com/docs/upgrades#2013-07-05) -### 1.8.0 2013-04-11 - +## 1.8.0 - 2013-04-11 * Allow Transfers to be creatable * Add new Recipient resource -### 1.7.15 2013-02-21 - +## 1.7.15 - 2013-02-21 * Add 'id' to the list of permanent object attributes -### 1.7.14 2013-02-20 +## 1.7.14 - 2013-02-20 -* Don't re-encode strings that are already encoded in UTF-8. If you - were previously using plan or coupon objects with UTF-8 IDs, they - may have been treated as ISO-8859-1 (Latin-1) and encoded to UTF-8 a - 2nd time. You may now need to pass the IDs to utf8_encode before - passing them to Stripe_Plan::retrieve or Stripe_Coupon::retrieve. -* Ensure that all input is encoded in UTF-8 before submitting it to - Stripe's servers. (github issue #27) +* Don't re-encode strings that are already encoded in UTF-8. If you were previously using plan or coupon objects with UTF-8 IDs, they may have been treated as ISO-8859-1 (Latin-1) and encoded to UTF-8 a 2nd time. You may now need to pass the IDs to utf8_encode before passing them to Stripe_Plan::retrieve or Stripe_Coupon::retrieve. +* Ensure that all input is encoded in UTF-8 before submitting it to Stripe's servers. (github issue #27) -### 1.7.13 2013-02-01 - -* Add support for passing options when retrieving Stripe objects - e.g., Stripe_Charge::retrieve(array("id"=>"foo", "expand" => array("customer"))) - Stripe_Charge::retrieve("foo") will continue to work - -### 1.7.12 2013-01-15 +## 1.7.13 - 2013-02-01 +* Add support for passing options when retrieving Stripe objects e.g., Stripe_Charge::retrieve(array("id"=>"foo", "expand" => array("customer"))); Stripe_Charge::retrieve("foo") will continue to work +## 1.7.12 - 2013-01-15 * Add support for setting a Stripe API version override -### 1.7.11 2012-12-30 - -* Version bump to cleanup constants and such (github issue #26) - -### 1.7.10 2012-11-08 +## 1.7.11 - 2012-12-30 +* Version bump to cleanup constants and such (fix issue #26) +## 1.7.10 - 2012-11-08 * Add support for updating charge disputes. * Fix bug preventing retrieval of null attributes -### 1.7.9 2012-11-08 +## 1.7.9 - 2012-11-08 +* Fix usage under autoloaders such as the one generated by composer (fix issue #22) -* Fix usage under autoloaders such as the one generated by composer - (github issue #22) - -### 1.7.8 2012-10-30 +## 1.7.8 - 2012-10-30 * Add support for creating invoices. * Add support for new invoice lines return format * Add support for new list objects -### 1.7.7 2012-09-14 - -* Get all of the various version numbers in the repo in sync (no other - changes) - -### 1.7.6 2012-08-31 +## 1.7.7 - 2012-09-14 +* Get all of the various version numbers in the repo in sync (no other changes) +## 1.7.6 - 2012-08-31 * Add update and pay methods to Invoice resource -### 1.7.5 2012-08-23 +## 1.7.5 - 2012-08-23 +* Change internal function names so that Stripe_SingletonApiRequest is E_STRICT-clean (github issue #16) -* Change internal function names so that Stripe_SingletonApiRequest is - E_STRICT-clean (github issue #16) - -### 1.7.4 2012-08-21 - -* Bugfix so that Stripe objects (e.g. Customer, Charge objects) used - in API calls are transparently converted to their object IDs - -### 1.7.3 2012-08-15 +## 1.7.4 - 2012-08-21 +* Bugfix so that Stripe objects (e.g. Customer, Charge objects) used in API calls are transparently converted to their object IDs +## 1.7.3 - 2012-08-15 * Add new Account resource -### 1.7.2 2012-06-26 +## 1.7.2 - 2012-06-26 +* Make clearer that you should be including lib/Stripe.php, not test/Stripe.php (github issue #14) -* Make clearer that you should be including lib/Stripe.php, not - test/Stripe.php (github issue #14) - -### 1.7.1 2012-05-24 - -* Add missing argument to Stripe_InvalidRequestError constructor in - Stripe_ApiResource::instanceUrl. Fixes a warning when - Stripe_ApiResource::instanceUrl is called on a resource with no ID - (github issue #12) - -### 1.7.0 2012-05-17 +## 1.7.1 - 2012-05-24 +* Add missing argument to Stripe_InvalidRequestError constructor in Stripe_ApiResource::instanceUrl. Fixes a warning when Stripe_ApiResource::instanceUrl is called on a resource with no ID (fix issue #12) +## 1.7.0 - 2012-05-17 * Support Composer and Packagist (github issue #9) - * Add new deleteDiscount method to Stripe_Customer - * Add new Transfer resource - -* Switch from using HTTP Basic auth to Bearer auth. (Note: Stripe will - support Basic auth for the indefinite future, but recommends Bearer - auth when possible going forward) - +* Switch from using HTTP Basic auth to Bearer auth. (Note: Stripe will support Basic auth for the indefinite future, but recommends Bearer auth when possible going forward) * Numerous test suite improvements diff --git a/htdocs/includes/stripe/README.md b/htdocs/includes/stripe/README.md index 16642900a1f..fa492c45cc4 100644 --- a/htdocs/includes/stripe/README.md +++ b/htdocs/includes/stripe/README.md @@ -10,7 +10,7 @@ You can sign up for a Stripe account at https://stripe.com. ## Requirements -PHP 5.3.3 and later. +PHP 5.4.0 and later. ## Composer @@ -20,7 +20,7 @@ You can install the bindings via [Composer](http://getcomposer.org/). Run the fo composer require stripe/stripe-php ``` -To use the bindings, use Composer's [autoload](https://getcomposer.org/doc/00-intro.md#autoloading): +To use the bindings, use Composer's [autoload](https://getcomposer.org/doc/01-basic-usage.md#autoloading): ```php require_once('vendor/autoload.php'); @@ -36,7 +36,7 @@ require_once('/path/to/stripe-php/init.php'); ## Dependencies -The bindings require the following extension in order to work properly: +The bindings require the following extensions in order to work properly: - [`curl`](https://secure.php.net/manual/en/book.curl.php), although you can use your own non-cURL client if you prefer - [`json`](https://secure.php.net/manual/en/book.json.php) @@ -50,7 +50,7 @@ Simple usage looks like: ```php \Stripe\Stripe::setApiKey('sk_test_BQokikJOvBiI2HlWgH4olfQ2'); -$charge = \Stripe\Charge::create(array('amount' => 2000, 'currency' => 'usd', 'source' => 'tok_189fqt2eZvKYlo2CTGBeg6Uq' )); +$charge = \Stripe\Charge::create(['amount' => 2000, 'currency' => 'usd', 'source' => 'tok_189fqt2eZvKYlo2CTGBeg6Uq']); echo $charge; ``` @@ -60,14 +60,19 @@ Please see https://stripe.com/docs/api for up-to-date documentation. ## Legacy Version Support +### PHP 5.3 + +If you are using PHP 5.3, you can download v5.8.0 ([zip](https://github.com/stripe/stripe-php/archive/v5.8.0.zip), [tar.gz](https://github.com/stripe/stripe-php/archive/v5.8.0.tar.gz)) from our [releases page](https://github.com/stripe/stripe-php/releases). This version will continue to work with new versions of the Stripe API for all common uses. + +### PHP 5.2 + If you are using PHP 5.2, you can download v1.18.0 ([zip](https://github.com/stripe/stripe-php/archive/v1.18.0.zip), [tar.gz](https://github.com/stripe/stripe-php/archive/v1.18.0.tar.gz)) from our [releases page](https://github.com/stripe/stripe-php/releases). This version will continue to work with new versions of the Stripe API for all common uses. This legacy version may be included via `require_once("/path/to/stripe-php/lib/Stripe.php");`, and used like: ```php Stripe::setApiKey('d8e8fca2dc0f896fd7cb4cb0031ba249'); -$myCard = array('number' => '4242424242424242', 'exp_month' => 8, 'exp_year' => 2018); -$charge = Stripe_Charge::create(array('card' => $myCard, 'amount' => 2000, 'currency' => 'usd')); +$charge = Stripe_Charge::create(array('source' => 'tok_XXXXXXXX', 'amount' => 2000, 'currency' => 'usd')); echo $charge; ``` @@ -98,13 +103,32 @@ Need to set a proxy for your requests? Pass in the requisite `CURLOPT_*` array t ```php // set up your tweaked Curl client -$curl = new \Stripe\HttpClient\CurlClient(array(CURLOPT_PROXY => 'proxy.local:80')); +$curl = new \Stripe\HttpClient\CurlClient([CURLOPT_PROXY => 'proxy.local:80']); // tell Stripe to use the tweaked client \Stripe\ApiRequestor::setHttpClient($curl); ``` Alternately, a callable can be passed to the CurlClient constructor that returns the above array based on request inputs. See `testDefaultOptions()` in `tests/CurlClientTest.php` for an example of this behavior. Note that the callable is called at the beginning of every API request, before the request is sent. +### Configuring a Logger + +The library does minimal logging, but it can be configured +with a [`PSR-3` compatible logger][psr3] so that messages +end up there instead of `error_log`: + +```php +\Stripe\Stripe::setLogger($logger); +``` + +### Accessing response data + +You can access the data from the last API response on any object via `getLastResponse()`. + +```php +$charge = \Stripe\Charge::create(['amount' => 2000, 'currency' => 'usd', 'source' => 'tok_visa']); +echo $charge->getLastResponse()->headers['Request-Id']; +``` + ### SSL / TLS compatibility issues Stripe's API now requires that [all connections use TLS 1.2](https://stripe.com/blog/upgrading-tls). Some systems (most notably some older CentOS and RHEL versions) are capable of using TLS 1.2 but will use TLS 1.0 or 1.1 by default. In this case, you'd get an `invalid_request_error` with the following error message: "Stripe no longer supports API requests made with TLS 1.0. Please initiate HTTPS connections with TLS 1.2 or later. You can learn more about this at [https://stripe.com/blog/upgrading-tls](https://stripe.com/blog/upgrading-tls).". @@ -112,10 +136,49 @@ Stripe's API now requires that [all connections use TLS 1.2](https://stripe.com/ The recommended course of action is to [upgrade your cURL and OpenSSL packages](https://support.stripe.com/questions/how-do-i-upgrade-my-stripe-integration-from-tls-1-0-to-tls-1-2#php) so that TLS 1.2 is used by default, but if that is not possible, you might be able to solve the issue by setting the `CURLOPT_SSLVERSION` option to either `CURL_SSLVERSION_TLSv1` or `CURL_SSLVERSION_TLSv1_2`: ```php -$curl = new \Stripe\HttpClient\CurlClient(array(CURLOPT_SSLVERSION => CURL_SSLVERSION_TLSv1)); +$curl = new \Stripe\HttpClient\CurlClient([CURLOPT_SSLVERSION => CURL_SSLVERSION_TLSv1]); \Stripe\ApiRequestor::setHttpClient($curl); ``` +### Per-request Configuration + +For apps that need to use multiple keys during the lifetime of a process, like +one that uses [Stripe Connect][connect], it's also possible to set a +per-request key and/or account: + +```php +\Stripe\Charge::all([], [ + 'api_key' => 'sk_test_...', + 'stripe_account' => 'acct_...' +]); + +\Stripe\Charge::retrieve("ch_18atAXCdGbJFKhCuBAa4532Z", [ + 'api_key' => 'sk_test_...', + 'stripe_account' => 'acct_...' +]); +``` + +### Configuring CA Bundles + +By default, the library will use its own internal bundle of known CA +certificates, but it's possible to configure your own: + +```php +\Stripe\Stripe::setCABundlePath("path/to/ca/bundle"); +``` + +### Configuring Automatic Retries + +The library can be configured to automatically retry requests that fail due to +an intermittent network problem: + +```php +\Stripe\Stripe::setMaxNetworkRetries(2); +``` + +[Idempotency keys][idempotency-keys] are added to requests to guarantee that +retries are safe. + ## Development Install dependencies: @@ -124,7 +187,12 @@ Install dependencies: composer install ``` -## Tests +The test suite depends on [stripe-mock], so make sure to fetch and run it from a +background terminal ([stripe-mock's README][stripe-mock] also contains +instructions for installing via Homebrew and other methods): + + go get -u github.com/stripe/stripe-mock + stripe-mock Install dependencies as mentioned above (which will resolve [PHPUnit](http://packagist.org/packages/phpunit/phpunit)), then you can run the test suite: @@ -138,6 +206,12 @@ Or to run an individual test file: ./vendor/bin/phpunit tests/UtilTest.php ``` +Update bundled CA certificates from the [Mozilla cURL release][curl]: + +```bash +./update_certs.php +``` + ## Attention plugin developers Are you writing a plugin that integrates Stripe and embeds our library? Then please use the `setAppInfo` function to identify your plugin. For example: @@ -151,3 +225,9 @@ The method should be called once, before any request is sent to the API. The sec ### SSL / TLS configuration option See the "SSL / TLS compatibility issues" paragraph above for full context. If you want to ensure that your plugin can be used on all systems, you should add a configuration option to let your users choose between different values for `CURLOPT_SSLVERSION`: none (default), `CURL_SSLVERSION_TLSv1` and `CURL_SSLVERSION_TLSv1_2`. + +[connect]: https://stripe.com/connect +[curl]: http://curl.haxx.se/docs/caextract.html +[psr3]: http://www.php-fig.org/psr/psr-3/ +[idempotency-keys]: https://stripe.com/docs/api/php#idempotent_requests +[stripe-mock]: https://github.com/stripe/stripe-mock diff --git a/htdocs/includes/stripe/VERSION b/htdocs/includes/stripe/VERSION index f6cdf40983f..4c77920fd2c 100644 --- a/htdocs/includes/stripe/VERSION +++ b/htdocs/includes/stripe/VERSION @@ -1 +1 @@ -4.7.0 +6.4.1 diff --git a/htdocs/includes/stripe/build.php b/htdocs/includes/stripe/build.php old mode 100755 new mode 100644 index 4401bb4b81f..cd053e2baea --- a/htdocs/includes/stripe/build.php +++ b/htdocs/includes/stripe/build.php @@ -10,7 +10,7 @@ if (!$autoload) { $composer = json_decode(file_get_contents('composer.json'), true); unset($composer['autoload']); unset($composer['require-dev']['squizlabs/php_codesniffer']); - file_put_contents('composer.json', json_encode($composer)); + file_put_contents('composer.json', json_encode($composer, JSON_PRETTY_PRINT)); } passthru('composer install', $returnStatus); diff --git a/htdocs/includes/stripe/composer.json b/htdocs/includes/stripe/composer.json index 8cfc38a048d..67473fca421 100644 --- a/htdocs/includes/stripe/composer.json +++ b/htdocs/includes/stripe/composer.json @@ -15,7 +15,7 @@ } ], "require": { - "php": ">=5.3.3", + "php": ">=5.4.0", "ext-curl": "*", "ext-json": "*", "ext-mbstring": "*" diff --git a/htdocs/includes/stripe/data/ca-certificates.crt b/htdocs/includes/stripe/data/ca-certificates.crt index 1c4e5b22673..39ba33683c5 100644 --- a/htdocs/includes/stripe/data/ca-certificates.crt +++ b/htdocs/includes/stripe/data/ca-certificates.crt @@ -1,20 +1,20 @@ ## ## Bundle of CA Root Certificates ## -## Certificate data from Mozilla as of: Fri Jan 22 20:39:57 2016 +## Certificate data from Mozilla as of: Wed Sep 20 03:12:05 2017 GMT ## ## This is a bundle of X.509 certificates of public Certificate Authorities ## (CA). These were automatically extracted from Mozilla's root certificates ## file (certdata.txt). This file can be found in the mozilla source tree: -## http://hg.mozilla.org/releases/mozilla-release/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt +## https://hg.mozilla.org/releases/mozilla-release/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt ## ## It contains the certificates in PEM format and therefore ## can be directly used with curl / libcurl / php_curl, or with ## an Apache+mod_ssl webserver for SSL client authentication. ## Just configure this file as the SSLCACertificateFile. ## -## Conversion done with mk-ca-bundle.pl version 1.25. -## SHA1: 0ab47e2f41518f8d223eab517cb799e5b071231e +## Conversion done with mk-ca-bundle.pl version 1.27. +## SHA256: 2b2dbe5244e0047e088c597998883a913f6c5fffd1cb5c0fe5a368c8466cb2ec ## @@ -130,30 +130,6 @@ Y71k5h+3zvDyny67G7fyUIhzksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9H RCwBXbsdtTLSR9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp -----END CERTIFICATE----- -AddTrust Low-Value Services Root -================================ ------BEGIN CERTIFICATE----- -MIIEGDCCAwCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQGEwJTRTEUMBIGA1UEChML -QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYDVQQDExhBZGRU -cnVzdCBDbGFzcyAxIENBIFJvb3QwHhcNMDAwNTMwMTAzODMxWhcNMjAwNTMwMTAzODMxWjBlMQsw -CQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBO -ZXR3b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwggEiMA0GCSqGSIb3DQEB -AQUAA4IBDwAwggEKAoIBAQCWltQhSWDia+hBBwzexODcEyPNwTXH+9ZOEQpnXvUGW2ulCDtbKRY6 -54eyNAbFvAWlA3yCyykQruGIgb3WntP+LVbBFc7jJp0VLhD7Bo8wBN6ntGO0/7Gcrjyvd7ZWxbWr -oulpOj0OM3kyP3CCkplhbY0wCI9xP6ZIVxn4JdxLZlyldI+Yrsj5wAYi56xz36Uu+1LcsRVlIPo1 -Zmne3yzxbrww2ywkEtvrNTVokMsAsJchPXQhI2U0K7t4WaPW4XY5mqRJjox0r26kmqPZm9I4XJui -GMx1I4S+6+JNM3GOGvDC+Mcdoq0Dlyz4zyXG9rgkMbFjXZJ/Y/AlyVMuH79NAgMBAAGjgdIwgc8w -HQYDVR0OBBYEFJWxtPCUtr3H2tERCSG+wa9J/RB7MAsGA1UdDwQEAwIBBjAPBgNVHRMBAf8EBTAD -AQH/MIGPBgNVHSMEgYcwgYSAFJWxtPCUtr3H2tERCSG+wa9J/RB7oWmkZzBlMQswCQYDVQQGEwJT -RTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEw -HwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBACxt -ZBsfzQ3duQH6lmM0MkhHma6X7f1yFqZzR1r0693p9db7RcwpiURdv0Y5PejuvE1Uhh4dbOMXJ0Ph -iVYrqW9yTkkz43J8KiOavD7/KCrto/8cI7pDVwlnTUtiBi34/2ydYB7YHEt9tTEv2dB8Xfjea4MY -eDdXL+gzB2ffHsdrKpV2ro9Xo/D0UrSpUwjP4E/TelOL/bscVjby/rK25Xa71SJlpz/+0WatC7xr -mYbvP33zGDLKe8bjq2RGlfgmadlVg3sslgf/WSxEo8bl6ancoWOAWiFeIc9TVPC6b4nbqKqVz4vj -ccweGyBECMB6tkD9xOQ14R0WHNC8K47Wcdk= ------END CERTIFICATE----- - AddTrust External Root ====================== -----BEGIN CERTIFICATE----- @@ -178,54 +154,6 @@ e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEXc4g/VhsxOBi0cQ+azcgOno4u G+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5amnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ= -----END CERTIFICATE----- -AddTrust Public Services Root -============================= ------BEGIN CERTIFICATE----- -MIIEFTCCAv2gAwIBAgIBATANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQGEwJTRTEUMBIGA1UEChML -QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSAwHgYDVQQDExdBZGRU -cnVzdCBQdWJsaWMgQ0EgUm9vdDAeFw0wMDA1MzAxMDQxNTBaFw0yMDA1MzAxMDQxNTBaMGQxCzAJ -BgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQIE5l -dHdvcmsxIDAeBgNVBAMTF0FkZFRydXN0IFB1YmxpYyBDQSBSb290MIIBIjANBgkqhkiG9w0BAQEF -AAOCAQ8AMIIBCgKCAQEA6Rowj4OIFMEg2Dybjxt+A3S72mnTRqX4jsIMEZBRpS9mVEBV6tsfSlbu -nyNu9DnLoblv8n75XYcmYZ4c+OLspoH4IcUkzBEMP9smcnrHAZcHF/nXGCwwfQ56HmIexkvA/X1i -d9NEHif2P0tEs7c42TkfYNVRknMDtABp4/MUTu7R3AnPdzRGULD4EfL+OHn3Bzn+UZKXC1sIXzSG -Aa2Il+tmzV7R/9x98oTaunet3IAIx6eH1lWfl2royBFkuucZKT8Rs3iQhCBSWxHveNCD9tVIkNAw -HM+A+WD+eeSI8t0A65RF62WUaUC6wNW0uLp9BBGo6zEFlpROWCGOn9Bg/QIDAQABo4HRMIHOMB0G -A1UdDgQWBBSBPjfYkrAfd59ctKtzquf2NGAv+jALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB -/zCBjgYDVR0jBIGGMIGDgBSBPjfYkrAfd59ctKtzquf2NGAv+qFopGYwZDELMAkGA1UEBhMCU0Ux -FDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRUcnVzdCBUVFAgTmV0d29yazEgMB4G -A1UEAxMXQWRkVHJ1c3QgUHVibGljIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBAAP3FUr4 -JNojVhaTdt02KLmuG7jD8WS6IBh4lSknVwW8fCr0uVFV2ocC3g8WFzH4qnkuCRO7r7IgGRLlk/lL -+YPoRNWyQSW/iHVv/xD8SlTQX/D67zZzfRs2RcYhbbQVuE7PnFylPVoAjgbjPGsye/Kf8Lb93/Ao -GEjwxrzQvzSAlsJKsW2Ox5BF3i9nrEUEo3rcVZLJR2bYGozH7ZxOmuASu7VqTITh4SINhwBk/ox9 -Yjllpu9CtoAlEmEBqCQTcAARJl/6NVDFSMwGR+gn2HCNX2TmoUQmXiLsks3/QppEIW1cxeMiHV9H -EufOX1362KqxMy3ZdvJOOjMMK7MtkAY= ------END CERTIFICATE----- - -AddTrust Qualified Certificates Root -==================================== ------BEGIN CERTIFICATE----- -MIIEHjCCAwagAwIBAgIBATANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJTRTEUMBIGA1UEChML -QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSMwIQYDVQQDExpBZGRU -cnVzdCBRdWFsaWZpZWQgQ0EgUm9vdDAeFw0wMDA1MzAxMDQ0NTBaFw0yMDA1MzAxMDQ0NTBaMGcx -CzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQ -IE5ldHdvcmsxIzAhBgNVBAMTGkFkZFRydXN0IFF1YWxpZmllZCBDQSBSb290MIIBIjANBgkqhkiG -9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5B6a/twJWoekn0e+EV+vhDTbYjx5eLfpMLXsDBwqxBb/4Oxx -64r1EW7tTw2R0hIYLUkVAcKkIhPHEWT/IhKauY5cLwjPcWqzZwFZ8V1G87B4pfYOQnrjfxvM0PC3 -KP0q6p6zsLkEqv32x7SxuCqg+1jxGaBvcCV+PmlKfw8i2O+tCBGaKZnhqkRFmhJePp1tUvznoD1o -L/BLcHwTOK28FSXx1s6rosAx1i+f4P8UWfyEk9mHfExUE+uf0S0R+Bg6Ot4l2ffTQO2kBhLEO+GR -wVY18BTcZTYJbqukB8c10cIDMzZbdSZtQvESa0NvS3GU+jQd7RNuyoB/mC9suWXY6QIDAQABo4HU -MIHRMB0GA1UdDgQWBBQ5lYtii1zJ1IC6WA+XPxUIQ8yYpzALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/ -BAUwAwEB/zCBkQYDVR0jBIGJMIGGgBQ5lYtii1zJ1IC6WA+XPxUIQ8yYp6FrpGkwZzELMAkGA1UE -BhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRUcnVzdCBUVFAgTmV0d29y -azEjMCEGA1UEAxMaQWRkVHJ1c3QgUXVhbGlmaWVkIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQAD -ggEBABmrder4i2VhlRO6aQTvhsoToMeqT2QbPxj2qC0sVY8FtzDqQmodwCVRLae/DLPt7wh/bDxG -GuoYQ992zPlmhpwsaPXpF/gxsxjE1kh9I0xowX67ARRvxdlu3rsEQmr49lx95dr6h+sNNVJn0J6X -dgWTP5XHAeZpVTh/EGGZyeNfpso+gmNIquIISD6q8rKFYqa0p9m9N5xotS1WfbC3P6CxB9bpT9ze -RXEwMn8bLgn5v1Kh7sKAPgZcLlVAwRv1cEWw3F369nJad9Jjzc9YiQBCYz95OdBEsIJuQRno3eDB -iFrRHnGTHyQwdOUeqN48Jzd/g66ed8/wMLH/S5noxqE= ------END CERTIFICATE----- - Entrust Root Certification Authority ==================================== -----BEGIN CERTIFICATE----- @@ -252,27 +180,6 @@ W3iDVuycNsMm4hH2Z0kdkquM++v/eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0 tHuu2guQOHXvgR1m0vdXcDazv/wor3ElhVsT/h5/WrQ8 -----END CERTIFICATE----- -RSA Security 2048 v3 -==================== ------BEGIN CERTIFICATE----- -MIIDYTCCAkmgAwIBAgIQCgEBAQAAAnwAAAAKAAAAAjANBgkqhkiG9w0BAQUFADA6MRkwFwYDVQQK -ExBSU0EgU2VjdXJpdHkgSW5jMR0wGwYDVQQLExRSU0EgU2VjdXJpdHkgMjA0OCBWMzAeFw0wMTAy -MjIyMDM5MjNaFw0yNjAyMjIyMDM5MjNaMDoxGTAXBgNVBAoTEFJTQSBTZWN1cml0eSBJbmMxHTAb -BgNVBAsTFFJTQSBTZWN1cml0eSAyMDQ4IFYzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC -AQEAt49VcdKA3XtpeafwGFAyPGJn9gqVB93mG/Oe2dJBVGutn3y+Gc37RqtBaB4Y6lXIL5F4iSj7 -Jylg/9+PjDvJSZu1pJTOAeo+tWN7fyb9Gd3AIb2E0S1PRsNO3Ng3OTsor8udGuorryGlwSMiuLgb -WhOHV4PR8CDn6E8jQrAApX2J6elhc5SYcSa8LWrg903w8bYqODGBDSnhAMFRD0xS+ARaqn1y07iH -KrtjEAMqs6FPDVpeRrc9DvV07Jmf+T0kgYim3WBU6JU2PcYJk5qjEoAAVZkZR73QpXzDuvsf9/UP -+Ky5tfQ3mBMY3oVbtwyCO4dvlTlYMNpuAWgXIszACwIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/ -MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBQHw1EwpKrpRa41JPr/JCwz0LGdjDAdBgNVHQ4E -FgQUB8NRMKSq6UWuNST6/yQsM9CxnYwwDQYJKoZIhvcNAQEFBQADggEBAF8+hnZuuDU8TjYcHnmY -v/3VEhF5Ug7uMYm83X/50cYVIeiKAVQNOvtUudZj1LGqlk2iQk3UUx+LEN5/Zb5gEydxiKRz44Rj -0aRV4VCT5hsOedBnvEbIvz8XDZXmxpBp3ue0L96VfdASPz0+f00/FGj1EVDVwfSQpQgdMWD/YIwj -VAqv/qFuxdF6Kmh4zx6CCiC0H63lhbJqaHVOrSU3lIW+vaHU6rcMSzyd6BIA8F+sDeGscGNz9395 -nzIlQnQFgCi/vcEkllgVsRch6YlL2weIZ/QVrXA+L02FO8K32/6YaCOJ4XQP3vTFhGMpG8zLB8kA -pKnXwiJPZ9d37CAFYd4= ------END CERTIFICATE----- - GeoTrust Global CA ================== -----BEGIN CERTIFICATE----- @@ -294,27 +201,6 @@ XE0zX5IJL4hmXXeXxx12E6nV5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvm Mw== -----END CERTIFICATE----- -GeoTrust Global CA 2 -==================== ------BEGIN CERTIFICATE----- -MIIDZjCCAk6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBEMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN -R2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFsIENBIDIwHhcNMDQwMzA0MDUw -MDAwWhcNMTkwMzA0MDUwMDAwWjBEMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5j -LjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFsIENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw -ggEKAoIBAQDvPE1APRDfO1MA4Wf+lGAVPoWI8YkNkMgoI5kF6CsgncbzYEbYwbLVjDHZ3CB5JIG/ -NTL8Y2nbsSpr7iFY8gjpeMtvy/wWUsiRxP89c96xPqfCfWbB9X5SJBri1WeR0IIQ13hLTytCOb1k -LUCgsBDTOEhGiKEMuzozKmKY+wCdE1l/bztyqu6mD4b5BWHqZ38MN5aL5mkWRxHCJ1kDs6ZgwiFA -Vvqgx306E+PsV8ez1q6diYD3Aecs9pYrEw15LNnA5IZ7S4wMcoKK+xfNAGw6EzywhIdLFnopsk/b -HdQL82Y3vdj2V7teJHq4PIu5+pIaGoSe2HSPqht/XvT+RSIhAgMBAAGjYzBhMA8GA1UdEwEB/wQF -MAMBAf8wHQYDVR0OBBYEFHE4NvICMVNHK266ZUapEBVYIAUJMB8GA1UdIwQYMBaAFHE4NvICMVNH -K266ZUapEBVYIAUJMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQUFAAOCAQEAA/e1K6tdEPx7 -srJerJsOflN4WT5CBP51o62sgU7XAotexC3IUnbHLB/8gTKY0UvGkpMzNTEv/NgdRN3ggX+d6Yvh -ZJFiCzkIjKx0nVnZellSlxG5FntvRdOW2TF9AjYPnDtuzywNA0ZF66D0f0hExghAzN4bcLUprbqL -OzRldRtxIR0sFAqwlpW41uryZfspuk/qkZN0abby/+Ea0AzRdoXLiiW9l14sbxWZJue2Kf8i7MkC -x1YAzUm5s2x7UwQa4qjJqhIFI8LO57sEAszAR6LkxCkvW0VXiVHuPOtSCP8HNR6fNWpHSlaY0VqF -H4z1Ir+rzoPz4iIprn2DQKi6bA== ------END CERTIFICATE----- - GeoTrust Universal CA ===================== -----BEGIN CERTIFICATE----- @@ -440,56 +326,6 @@ Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2G9w84FoVxp7Z 12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg== -----END CERTIFICATE----- -Comodo Secure Services root -=========================== ------BEGIN CERTIFICATE----- -MIIEPzCCAyegAwIBAgIBATANBgkqhkiG9w0BAQUFADB+MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS -R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg -TGltaXRlZDEkMCIGA1UEAwwbU2VjdXJlIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAw -MDAwMFoXDTI4MTIzMTIzNTk1OVowfjELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFu -Y2hlc3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxJDAi -BgNVBAMMG1NlY3VyZSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP -ADCCAQoCggEBAMBxM4KK0HDrc4eCQNUd5MvJDkKQ+d40uaG6EfQlhfPMcm3ye5drswfxdySRXyWP -9nQ95IDC+DwN879A6vfIUtFyb+/Iq0G4bi4XKpVpDM3SHpR7LZQdqnXXs5jLrLxkU0C8j6ysNstc -rbvd4JQX7NFc0L/vpZXJkMWwrPsbQ996CF23uPJAGysnnlDOXmWCiIxe004MeuoIkbY2qitC++rC -oznl2yY4rYsK7hljxxwk3wN42ubqwUcaCwtGCd0C/N7Lh1/XMGNooa7cMqG6vv5Eq2i2pRcV/b3V -p6ea5EQz6YiO/O1R65NxTq0B50SOqy3LqP4BSUjwwN3HaNiS/j0CAwEAAaOBxzCBxDAdBgNVHQ4E -FgQUPNiTiMLAggnMAZkGkyDpnnAJY08wDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8w -gYEGA1UdHwR6MHgwO6A5oDeGNWh0dHA6Ly9jcmwuY29tb2RvY2EuY29tL1NlY3VyZUNlcnRpZmlj -YXRlU2VydmljZXMuY3JsMDmgN6A1hjNodHRwOi8vY3JsLmNvbW9kby5uZXQvU2VjdXJlQ2VydGlm -aWNhdGVTZXJ2aWNlcy5jcmwwDQYJKoZIhvcNAQEFBQADggEBAIcBbSMdflsXfcFhMs+P5/OKlFlm -4J4oqF7Tt/Q05qo5spcWxYJvMqTpjOev/e/C6LlLqqP05tqNZSH7uoDrJiiFGv45jN5bBAS0VPmj -Z55B+glSzAVIqMk/IQQezkhr/IXownuvf7fM+F86/TXGDe+X3EyrEeFryzHRbPtIgKvcnDe4IRRL -DXE97IMzbtFuMhbsmMcWi1mmNKsFVy2T96oTy9IT4rcuO81rUBcJaD61JlfutuC23bkpgHl9j6Pw -pCikFcSF9CfUa7/lXORlAnZUtOM3ZiTTGWHIUhDlizeauan5Hb/qmZJhlv8BzaFfDbxxvA6sCx1H -RR3B7Hzs/Sk= ------END CERTIFICATE----- - -Comodo Trusted Services root -============================ ------BEGIN CERTIFICATE----- -MIIEQzCCAyugAwIBAgIBATANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS -R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg -TGltaXRlZDElMCMGA1UEAwwcVHJ1c3RlZCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczAeFw0wNDAxMDEw -MDAwMDBaFw0yODEyMzEyMzU5NTlaMH8xCzAJBgNVBAYTAkdCMRswGQYDVQQIDBJHcmVhdGVyIE1h -bmNoZXN0ZXIxEDAOBgNVBAcMB1NhbGZvcmQxGjAYBgNVBAoMEUNvbW9kbyBDQSBMaW1pdGVkMSUw -IwYDVQQDDBxUcnVzdGVkIENlcnRpZmljYXRlIFNlcnZpY2VzMIIBIjANBgkqhkiG9w0BAQEFAAOC -AQ8AMIIBCgKCAQEA33FvNlhTWvI2VFeAxHQIIO0Yfyod5jWaHiWsnOWWfnJSoBVC21ndZHoa0Lh7 -3TkVvFVIxO06AOoxEbrycXQaZ7jPM8yoMa+j49d/vzMtTGo87IvDktJTdyR0nAducPy9C1t2ul/y -/9c3S0pgePfw+spwtOpZqqPOSC+pw7ILfhdyFgymBwwbOM/JYrc/oJOlh0Hyt3BAd9i+FHzjqMB6 -juljatEPmsbS9Is6FARW1O24zG71++IsWL1/T2sr92AkWCTOJu80kTrV44HQsvAEAtdbtz6SrGsS -ivnkBbA7kUlcsutT6vifR4buv5XAwAaf0lteERv0xwQ1KdJVXOTt6wIDAQABo4HJMIHGMB0GA1Ud -DgQWBBTFe1i97doladL3WRaoszLAeydb9DAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB -/zCBgwYDVR0fBHwwejA8oDqgOIY2aHR0cDovL2NybC5jb21vZG9jYS5jb20vVHJ1c3RlZENlcnRp -ZmljYXRlU2VydmljZXMuY3JsMDqgOKA2hjRodHRwOi8vY3JsLmNvbW9kby5uZXQvVHJ1c3RlZENl -cnRpZmljYXRlU2VydmljZXMuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQDIk4E7ibSvuIQSTI3S8Ntw -uleGFTQQuS9/HrCoiWChisJ3DFBKmwCL2Iv0QeLQg4pKHBQGsKNoBXAxMKdTmw7pSqBYaWcOrp32 -pSxBvzwGa+RZzG0Q8ZZvH9/0BAKkn0U+yNj6NkZEUD+Cl5EfKNsYEYwq5GWDVxISjBc/lDb+XbDA -BHcTuPQV1T84zJQ6VdCsmPW6AF/ghhmBeC8owH7TzEIK9a5QoNE+xqFx7D+gIIxmOom0jtTYsU0l -R+4viMi14QVFwL4Ucd56/Y57fU0IlqUSc/AtyjcndBInTMu2l+nZrghtWjlA3QVHdWpaIbOjGM9O -9y5Xt5hwXsjEeLBi ------END CERTIFICATE----- - QuoVadis Root CA ================ -----BEGIN CERTIFICATE----- @@ -629,54 +465,6 @@ EtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLH llpwrN9M -----END CERTIFICATE----- -Staat der Nederlanden Root CA -============================= ------BEGIN CERTIFICATE----- -MIIDujCCAqKgAwIBAgIEAJiWijANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJOTDEeMBwGA1UE -ChMVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSYwJAYDVQQDEx1TdGFhdCBkZXIgTmVkZXJsYW5kZW4g -Um9vdCBDQTAeFw0wMjEyMTcwOTIzNDlaFw0xNTEyMTYwOTE1MzhaMFUxCzAJBgNVBAYTAk5MMR4w -HAYDVQQKExVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xJjAkBgNVBAMTHVN0YWF0IGRlciBOZWRlcmxh -bmRlbiBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmNK1URF6gaYUmHFt -vsznExvWJw56s2oYHLZhWtVhCb/ekBPHZ+7d89rFDBKeNVU+LCeIQGv33N0iYfXCxw719tV2U02P -jLwYdjeFnejKScfST5gTCaI+Ioicf9byEGW07l8Y1Rfj+MX94p2i71MOhXeiD+EwR+4A5zN9RGca -C1Hoi6CeUJhoNFIfLm0B8mBF8jHrqTFoKbt6QZ7GGX+UtFE5A3+y3qcym7RHjm+0Sq7lr7HcsBth -vJly3uSJt3omXdozSVtSnA71iq3DuD3oBmrC1SoLbHuEvVYFy4ZlkuxEK7COudxwC0barbxjiDn6 -22r+I/q85Ej0ZytqERAhSQIDAQABo4GRMIGOMAwGA1UdEwQFMAMBAf8wTwYDVR0gBEgwRjBEBgRV -HSAAMDwwOgYIKwYBBQUHAgEWLmh0dHA6Ly93d3cucGtpb3ZlcmhlaWQubmwvcG9saWNpZXMvcm9v -dC1wb2xpY3kwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSofeu8Y6R0E3QA7Jbg0zTBLL9s+DAN -BgkqhkiG9w0BAQUFAAOCAQEABYSHVXQ2YcG70dTGFagTtJ+k/rvuFbQvBgwp8qiSpGEN/KtcCFtR -EytNwiphyPgJWPwtArI5fZlmgb9uXJVFIGzmeafR2Bwp/MIgJ1HI8XxdNGdphREwxgDS1/PTfLbw -MVcoEoJz6TMvplW0C5GUR5z6u3pCMuiufi3IvKwUv9kP2Vv8wfl6leF9fpb8cbDCTMjfRTTJzg3y -nGQI0DvDKcWy7ZAEwbEpkcUwb8GpcjPM/l0WFywRaed+/sWDCN+83CI6LiBpIzlWYGeQiy52OfsR -iJf2fL1LuCAWZwWN4jvBcj+UlTfHXbme2JOhF4//DGYVwSR8MnwDHTuhWEUykw== ------END CERTIFICATE----- - -UTN USERFirst Hardware Root CA -============================== ------BEGIN CERTIFICATE----- -MIIEdDCCA1ygAwIBAgIQRL4Mi1AAJLQR0zYq/mUK/TANBgkqhkiG9w0BAQUFADCBlzELMAkGA1UE -BhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhl -IFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAd -BgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdhcmUwHhcNOTkwNzA5MTgxMDQyWhcNMTkwNzA5MTgx -OTIyWjCBlzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0 -eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVz -ZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdhcmUwggEiMA0GCSqGSIb3 -DQEBAQUAA4IBDwAwggEKAoIBAQCx98M4P7Sof885glFn0G2f0v9Y8+efK+wNiVSZuTiZFvfgIXlI -wrthdBKWHTxqctU8EGc6Oe0rE81m65UJM6Rsl7HoxuzBdXmcRl6Nq9Bq/bkqVRcQVLMZ8Jr28bFd -tqdt++BxF2uiiPsA3/4aMXcMmgF6sTLjKwEHOG7DpV4jvEWbe1DByTCP2+UretNb+zNAHqDVmBe8 -i4fDidNdoI6yqqr2jmmIBsX6iSHzCJ1pLgkzmykNRg+MzEk0sGlRvfkGzWitZky8PqxhvQqIDsjf -Pe58BEydCl5rkdbux+0ojatNh4lz0G6k0B4WixThdkQDf2Os5M1JnMWS9KsyoUhbAgMBAAGjgbkw -gbYwCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFKFyXyYbKJhDlV0HN9WF -lp1L0sNFMEQGA1UdHwQ9MDswOaA3oDWGM2h0dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VVE4tVVNF -UkZpcnN0LUhhcmR3YXJlLmNybDAxBgNVHSUEKjAoBggrBgEFBQcDAQYIKwYBBQUHAwUGCCsGAQUF -BwMGBggrBgEFBQcDBzANBgkqhkiG9w0BAQUFAAOCAQEARxkP3nTGmZev/K0oXnWO6y1n7k57K9cM -//bey1WiCuFMVGWTYGufEpytXoMs61quwOQt9ABjHbjAbPLPSbtNk28GpgoiskliCE7/yMgUsogW -XecB5BKV5UU0s4tpvc+0hY91UZ59Ojg6FEgSxvunOxqNDYJAB+gECJChicsZUN/KHAG8HQQZexB2 -lzvukJDKxA4fFm517zP4029bHpbj4HR3dHuKom4t3XbWOTCC8KucUvIqx69JXn7HaOWCgchqJ/kn -iCrVWFCVH/A7HFe7fRQ5YiuayZSSKqMiDP+JJn1fIytH1xUdqWqeUQ0qUZ6B+dQ7XnASfxAynB67 -nfhmqA== ------END CERTIFICATE----- - Camerfirma Chambers of Commerce Root ==================================== -----BEGIN CERTIFICATE----- @@ -731,41 +519,6 @@ IBHNfTIzSJRUTN3cecQwn+uOuFW114hcxWokPbLTBQNRxgfvzBRydD1ucs4YKIxKoHflCStFREes t2d/AYoFWpO+ocH/+OcOZ6RHSXZddZAa9SaP8A== -----END CERTIFICATE----- -NetLock Notary (Class A) Root -============================= ------BEGIN CERTIFICATE----- -MIIGfTCCBWWgAwIBAgICAQMwDQYJKoZIhvcNAQEEBQAwga8xCzAJBgNVBAYTAkhVMRAwDgYDVQQI -EwdIdW5nYXJ5MREwDwYDVQQHEwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6 -dG9uc2FnaSBLZnQuMRowGAYDVQQLExFUYW51c2l0dmFueWtpYWRvazE2MDQGA1UEAxMtTmV0TG9j -ayBLb3pqZWd5em9pIChDbGFzcyBBKSBUYW51c2l0dmFueWtpYWRvMB4XDTk5MDIyNDIzMTQ0N1oX -DTE5MDIxOTIzMTQ0N1owga8xCzAJBgNVBAYTAkhVMRAwDgYDVQQIEwdIdW5nYXJ5MREwDwYDVQQH -EwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6dG9uc2FnaSBLZnQuMRowGAYD -VQQLExFUYW51c2l0dmFueWtpYWRvazE2MDQGA1UEAxMtTmV0TG9jayBLb3pqZWd5em9pIChDbGFz -cyBBKSBUYW51c2l0dmFueWtpYWRvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvHSM -D7tM9DceqQWC2ObhbHDqeLVu0ThEDaiDzl3S1tWBxdRL51uUcCbbO51qTGL3cfNk1mE7PetzozfZ -z+qMkjvN9wfcZnSX9EUi3fRc4L9t875lM+QVOr/bmJBVOMTtplVjC7B4BPTjbsE/jvxReB+SnoPC -/tmwqcm8WgD/qaiYdPv2LD4VOQ22BFWoDpggQrOxJa1+mm9dU7GrDPzr4PN6s6iz/0b2Y6LYOph7 -tqyF/7AlT3Rj5xMHpQqPBffAZG9+pyeAlt7ULoZgx2srXnN7F+eRP2QM2EsiNCubMvJIH5+hCoR6 -4sKtlz2O1cH5VqNQ6ca0+pii7pXmKgOM3wIDAQABo4ICnzCCApswDgYDVR0PAQH/BAQDAgAGMBIG -A1UdEwEB/wQIMAYBAf8CAQQwEQYJYIZIAYb4QgEBBAQDAgAHMIICYAYJYIZIAYb4QgENBIICURaC -Ak1GSUdZRUxFTSEgRXplbiB0YW51c2l0dmFueSBhIE5ldExvY2sgS2Z0LiBBbHRhbGFub3MgU3pv -bGdhbHRhdGFzaSBGZWx0ZXRlbGVpYmVuIGxlaXJ0IGVsamFyYXNvayBhbGFwamFuIGtlc3p1bHQu -IEEgaGl0ZWxlc2l0ZXMgZm9seWFtYXRhdCBhIE5ldExvY2sgS2Z0LiB0ZXJtZWtmZWxlbG9zc2Vn -LWJpenRvc2l0YXNhIHZlZGkuIEEgZGlnaXRhbGlzIGFsYWlyYXMgZWxmb2dhZGFzYW5hayBmZWx0 -ZXRlbGUgYXogZWxvaXJ0IGVsbGVub3J6ZXNpIGVsamFyYXMgbWVndGV0ZWxlLiBBeiBlbGphcmFz -IGxlaXJhc2EgbWVndGFsYWxoYXRvIGEgTmV0TG9jayBLZnQuIEludGVybmV0IGhvbmxhcGphbiBh -IGh0dHBzOi8vd3d3Lm5ldGxvY2submV0L2RvY3MgY2ltZW4gdmFneSBrZXJoZXRvIGF6IGVsbGVu -b3J6ZXNAbmV0bG9jay5uZXQgZS1tYWlsIGNpbWVuLiBJTVBPUlRBTlQhIFRoZSBpc3N1YW5jZSBh -bmQgdGhlIHVzZSBvZiB0aGlzIGNlcnRpZmljYXRlIGlzIHN1YmplY3QgdG8gdGhlIE5ldExvY2sg -Q1BTIGF2YWlsYWJsZSBhdCBodHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIG9yIGJ5IGUtbWFp -bCBhdCBjcHNAbmV0bG9jay5uZXQuMA0GCSqGSIb3DQEBBAUAA4IBAQBIJEb3ulZv+sgoA0BO5TE5 -ayZrU3/b39/zcT0mwBQOxmd7I6gMc90Bu8bKbjc5VdXHjFYgDigKDtIqpLBJUsY4B/6+CgmM0ZjP -ytoUMaFP0jn8DxEsQ8Pdq5PHVT5HfBgaANzze9jyf1JsIPQLX2lS9O74silg6+NJMSEN1rUQQeJB -CWziGppWS3cC9qCbmieH6FUpccKQn0V4GuEVZD3QDtigdp+uxdAu6tYPVuxkf1qbFFgBJ34TUMdr -KuZoPL9coAob4Q566eKAw+np9v1sEZ7Q5SgnK1QyQhSCdeZK8CtmdWOMovsEPoMOmzbwGOQmIMOM -8CgHrTwXZoi1/baI ------END CERTIFICATE----- - XRamp Global CA Root ==================== -----BEGIN CERTIFICATE----- @@ -909,38 +662,6 @@ CZBUkQM8R+XVyWXgt0t97EfTsws+rZ7QdAAO671RrcDeLMDDav7v3Aun+kbfYNucpllQdSNpc5Oy +fwC00fmcc4QAu4njIT/rEUNE1yDMuAlpYYsfPQS -----END CERTIFICATE----- -Swisscom Root CA 1 -================== ------BEGIN CERTIFICATE----- -MIIF2TCCA8GgAwIBAgIQXAuFXAvnWUHfV8w/f52oNjANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQG -EwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsTHERpZ2l0YWwgQ2VydGlmaWNhdGUgU2Vy -dmljZXMxGzAZBgNVBAMTElN3aXNzY29tIFJvb3QgQ0EgMTAeFw0wNTA4MTgxMjA2MjBaFw0yNTA4 -MTgyMjA2MjBaMGQxCzAJBgNVBAYTAmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGln -aXRhbCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAxMIIC -IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0LmwqAzZuz8h+BvVM5OAFmUgdbI9m2BtRsiM -MW8Xw/qabFbtPMWRV8PNq5ZJkCoZSx6jbVfd8StiKHVFXqrWW/oLJdihFvkcxC7mlSpnzNApbjyF -NDhhSbEAn9Y6cV9Nbc5fuankiX9qUvrKm/LcqfmdmUc/TilftKaNXXsLmREDA/7n29uj/x2lzZAe -AR81sH8A25Bvxn570e56eqeqDFdvpG3FEzuwpdntMhy0XmeLVNxzh+XTF3xmUHJd1BpYwdnP2IkC -b6dJtDZd0KTeByy2dbcokdaXvij1mB7qWybJvbCXc9qukSbraMH5ORXWZ0sKbU/Lz7DkQnGMU3nn -7uHbHaBuHYwadzVcFh4rUx80i9Fs/PJnB3r1re3WmquhsUvhzDdf/X/NTa64H5xD+SpYVUNFvJbN -cA78yeNmuk6NO4HLFWR7uZToXTNShXEuT46iBhFRyePLoW4xCGQMwtI89Tbo19AOeCMgkckkKmUp -WyL3Ic6DXqTz3kvTaI9GdVyDCW4pa8RwjPWd1yAv/0bSKzjCL3UcPX7ape8eYIVpQtPM+GP+HkM5 -haa2Y0EQs3MevNP6yn0WR+Kn1dCjigoIlmJWbjTb2QK5MHXjBNLnj8KwEUAKrNVxAmKLMb7dxiNY -MUJDLXT5xp6mig/p/r+D5kNXJLrvRjSq1xIBOO0CAwEAAaOBhjCBgzAOBgNVHQ8BAf8EBAMCAYYw -HQYDVR0hBBYwFDASBgdghXQBUwABBgdghXQBUwABMBIGA1UdEwEB/wQIMAYBAf8CAQcwHwYDVR0j -BBgwFoAUAyUv3m+CATpcLNwroWm1Z9SM0/0wHQYDVR0OBBYEFAMlL95vggE6XCzcK6FptWfUjNP9 -MA0GCSqGSIb3DQEBBQUAA4ICAQA1EMvspgQNDQ/NwNurqPKIlwzfky9NfEBWMXrrpA9gzXrzvsMn -jgM+pN0S734edAY8PzHyHHuRMSG08NBsl9Tpl7IkVh5WwzW9iAUPWxAaZOHHgjD5Mq2eUCzneAXQ -MbFamIp1TpBcahQq4FJHgmDmHtqBsfsUC1rxn9KVuj7QG9YVHaO+htXbD8BJZLsuUBlL0iT43R4H -VtA4oJVwIHaM190e3p9xxCPvgxNcoyQVTSlAPGrEqdi3pkSlDfTgnXceQHAm/NrZNuR55LU/vJtl -vrsRls/bxig5OgjOR1tTWsWZ/l2p3e9M1MalrQLmjAcSHm8D0W+go/MpvRLHUKKwf4ipmXeascCl -OS5cfGniLLDqN2qk4Vrh9VDlg++luyqI54zb/W1elxmofmZ1a3Hqv7HHb6D0jqTsNFFbjCYDcKF3 -1QESVwA12yPeDooomf2xEG9L/zgtYE4snOtnta1J7ksfrK/7DZBaZmBwXarNeNQk7shBoJMBkpxq -nvy5JMWzFYJ+vq6VK+uxwNrjAWALXmmshFZhvnEX/h0TD/7Gh0Xp/jKgGg0TpJRVcaUWi7rKibCy -x/yP2FS1k2Kdzs9Z+z0YzirLNRWCXf9UIltxUvu3yf5gmwBBZPCqKuy2QkPOiWaByIufOVQDJdMW -NY6E0F/6MBr1mmz0DlP5OlvRHA== ------END CERTIFICATE----- - DigiCert Assured ID Root CA =========================== -----BEGIN CERTIFICATE----- @@ -1298,33 +1019,6 @@ wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHNpGxlaKFJdlxD ydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey -----END CERTIFICATE----- -WellsSecure Public Root Certificate Authority -============================================= ------BEGIN CERTIFICATE----- -MIIEvTCCA6WgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoM -F1dlbGxzIEZhcmdvIFdlbGxzU2VjdXJlMRwwGgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYw -NAYDVQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcN -MDcxMjEzMTcwNzU0WhcNMjIxMjE0MDAwNzU0WjCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoMF1dl -bGxzIEZhcmdvIFdlbGxzU2VjdXJlMRwwGgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYwNAYD -VQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0G -CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDub7S9eeKPCCGeOARBJe+rWxxTkqxtnt3CxC5FlAM1 -iGd0V+PfjLindo8796jE2yljDpFoNoqXjopxaAkH5OjUDk/41itMpBb570OYj7OeUt9tkTmPOL13 -i0Nj67eT/DBMHAGTthP796EfvyXhdDcsHqRePGj4S78NuR4uNuip5Kf4D8uCdXw1LSLWwr8L87T8 -bJVhHlfXBIEyg1J55oNjz7fLY4sR4r1e6/aN7ZVyKLSsEmLpSjPmgzKuBXWVvYSV2ypcm44uDLiB -K0HmOFafSZtsdvqKXfcBeYF8wYNABf5x/Qw/zE5gCQ5lRxAvAcAFP4/4s0HvWkJ+We/SlwxlAgMB -AAGjggE0MIIBMDAPBgNVHRMBAf8EBTADAQH/MDkGA1UdHwQyMDAwLqAsoCqGKGh0dHA6Ly9jcmwu -cGtpLndlbGxzZmFyZ28uY29tL3dzcHJjYS5jcmwwDgYDVR0PAQH/BAQDAgHGMB0GA1UdDgQWBBQm -lRkQ2eihl5H/3BnZtQQ+0nMKajCBsgYDVR0jBIGqMIGngBQmlRkQ2eihl5H/3BnZtQQ+0nMKaqGB -i6SBiDCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoMF1dlbGxzIEZhcmdvIFdlbGxzU2VjdXJlMRww -GgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYwNAYDVQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMg -Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHmCAQEwDQYJKoZIhvcNAQEFBQADggEBALkVsUSRzCPI -K0134/iaeycNzXK7mQDKfGYZUMbVmO2rvwNa5U3lHshPcZeG1eMd/ZDJPHV3V3p9+N701NX3leZ0 -bh08rnyd2wIDBSxxSyU+B+NemvVmFymIGjifz6pBA4SXa5M4esowRBskRDPQ5NHcKDj0E0M1NSlj -qHyita04pO2t/caaH/+Xc/77szWnk4bGdpEA5qxRFsQnMlzbc9qlk1eOPm01JghZ1edE13YgY+es -E2fDbbFwRnzVlhE9iW9dqKHrjQrawx0zbKPqZxmamX9LPYNRKh3KL4YMon4QLSvUFpULB6ouFJJJ -tylv2G0xffX8oRAHh84vWdw+WNs= ------END CERTIFICATE----- - COMODO ECC Certification Authority ================================== -----BEGIN CERTIFICATE----- @@ -1342,30 +1036,6 @@ FAkK+qDmfQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdvGDeA U/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY= -----END CERTIFICATE----- -IGC/A -===== ------BEGIN CERTIFICATE----- -MIIEAjCCAuqgAwIBAgIFORFFEJQwDQYJKoZIhvcNAQEFBQAwgYUxCzAJBgNVBAYTAkZSMQ8wDQYD -VQQIEwZGcmFuY2UxDjAMBgNVBAcTBVBhcmlzMRAwDgYDVQQKEwdQTS9TR0ROMQ4wDAYDVQQLEwVE -Q1NTSTEOMAwGA1UEAxMFSUdDL0ExIzAhBgkqhkiG9w0BCQEWFGlnY2FAc2dkbi5wbS5nb3V2LmZy -MB4XDTAyMTIxMzE0MjkyM1oXDTIwMTAxNzE0MjkyMlowgYUxCzAJBgNVBAYTAkZSMQ8wDQYDVQQI -EwZGcmFuY2UxDjAMBgNVBAcTBVBhcmlzMRAwDgYDVQQKEwdQTS9TR0ROMQ4wDAYDVQQLEwVEQ1NT -STEOMAwGA1UEAxMFSUdDL0ExIzAhBgkqhkiG9w0BCQEWFGlnY2FAc2dkbi5wbS5nb3V2LmZyMIIB -IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsh/R0GLFMzvABIaIs9z4iPf930Pfeo2aSVz2 -TqrMHLmh6yeJ8kbpO0px1R2OLc/mratjUMdUC24SyZA2xtgv2pGqaMVy/hcKshd+ebUyiHDKcMCW -So7kVc0dJ5S/znIq7Fz5cyD+vfcuiWe4u0dzEvfRNWk68gq5rv9GQkaiv6GFGvm/5P9JhfejcIYy -HF2fYPepraX/z9E0+X1bF8bc1g4oa8Ld8fUzaJ1O/Id8NhLWo4DoQw1VYZTqZDdH6nfK0LJYBcNd -frGoRpAxVs5wKpayMLh35nnAvSk7/ZR3TL0gzUEl4C7HG7vupARB0l2tEmqKm0f7yd1GQOGdPDPQ -tQIDAQABo3cwdTAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBRjAVBgNVHSAEDjAMMAoGCCqB -egF5AQEBMB0GA1UdDgQWBBSjBS8YYFDCiQrdKyFP/45OqDAxNjAfBgNVHSMEGDAWgBSjBS8YYFDC -iQrdKyFP/45OqDAxNjANBgkqhkiG9w0BAQUFAAOCAQEABdwm2Pp3FURo/C9mOnTgXeQp/wYHE4RK -q89toB9RlPhJy3Q2FLwV3duJL92PoF189RLrn544pEfMs5bZvpwlqwN+Mw+VgQ39FuCIvjfwbF3Q -MZsyK10XZZOYYLxuj7GoPB7ZHPOpJkL5ZB3C55L29B5aqhlSXa/oovdgoPaN8In1buAKBQGVyYsg -Crpa/JosPL3Dt8ldeCUFP1YUmwza+zpI/pdpXsoQhvdOlgQITeywvl3cO45Pwf2aNjSaTFR+FwNI -lQgRHAdvhQh+XU3Endv7rs6y0bO4g2wdsrN58dhwmX7wEwLOXt1R0982gaEbeC9xs/FZTEYYKKuF -0mBWWg== ------END CERTIFICATE----- - Security Communication EV RootCA1 ================================= -----BEGIN CERTIFICATE----- @@ -1410,46 +1080,6 @@ hNVQA7bihKOmNqoROgHhGEvWRGizPflTdISzRpFGlgC3gCy24eMQ4tui5yiPAZZiFj4A4xylNoEY okxSdsARo27mHbrjWr42U8U+dY+GaSlYU7Wcu2+fXMUY7N0v4ZjJ/L7fCg0= -----END CERTIFICATE----- -Microsec e-Szigno Root CA -========================= ------BEGIN CERTIFICATE----- -MIIHqDCCBpCgAwIBAgIRAMy4579OKRr9otxmpRwsDxEwDQYJKoZIhvcNAQEFBQAwcjELMAkGA1UE -BhMCSFUxETAPBgNVBAcTCEJ1ZGFwZXN0MRYwFAYDVQQKEw1NaWNyb3NlYyBMdGQuMRQwEgYDVQQL -EwtlLVN6aWdubyBDQTEiMCAGA1UEAxMZTWljcm9zZWMgZS1Temlnbm8gUm9vdCBDQTAeFw0wNTA0 -MDYxMjI4NDRaFw0xNzA0MDYxMjI4NDRaMHIxCzAJBgNVBAYTAkhVMREwDwYDVQQHEwhCdWRhcGVz -dDEWMBQGA1UEChMNTWljcm9zZWMgTHRkLjEUMBIGA1UECxMLZS1Temlnbm8gQ0ExIjAgBgNVBAMT -GU1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB -AQDtyADVgXvNOABHzNuEwSFpLHSQDCHZU4ftPkNEU6+r+ICbPHiN1I2uuO/TEdyB5s87lozWbxXG -d36hL+BfkrYn13aaHUM86tnsL+4582pnS4uCzyL4ZVX+LMsvfUh6PXX5qqAnu3jCBspRwn5mS6/N -oqdNAoI/gqyFxuEPkEeZlApxcpMqyabAvjxWTHOSJ/FrtfX9/DAFYJLG65Z+AZHCabEeHXtTRbjc -QR/Ji3HWVBTji1R4P770Yjtb9aPs1ZJ04nQw7wHb4dSrmZsqa/i9phyGI0Jf7Enemotb9HI6QMVJ -PqW+jqpx62z69Rrkav17fVVA71hu5tnVvCSrwe+3AgMBAAGjggQ3MIIEMzBnBggrBgEFBQcBAQRb -MFkwKAYIKwYBBQUHMAGGHGh0dHBzOi8vcmNhLmUtc3ppZ25vLmh1L29jc3AwLQYIKwYBBQUHMAKG -IWh0dHA6Ly93d3cuZS1zemlnbm8uaHUvUm9vdENBLmNydDAPBgNVHRMBAf8EBTADAQH/MIIBcwYD -VR0gBIIBajCCAWYwggFiBgwrBgEEAYGoGAIBAQEwggFQMCgGCCsGAQUFBwIBFhxodHRwOi8vd3d3 -LmUtc3ppZ25vLmh1L1NaU1ovMIIBIgYIKwYBBQUHAgIwggEUHoIBEABBACAAdABhAG4A+gBzAO0A -dAB2AOEAbgB5ACAA6QByAHQAZQBsAG0AZQB6AOkAcwDpAGgAZQB6ACAA6QBzACAAZQBsAGYAbwBn -AGEAZADhAHMA4QBoAG8AegAgAGEAIABTAHoAbwBsAGcA4QBsAHQAYQB0APMAIABTAHoAbwBsAGcA -4QBsAHQAYQB0AOEAcwBpACAAUwB6AGEAYgDhAGwAeQB6AGEAdABhACAAcwB6AGUAcgBpAG4AdAAg -AGsAZQBsAGwAIABlAGwAagDhAHIAbgBpADoAIABoAHQAdABwADoALwAvAHcAdwB3AC4AZQAtAHMA -egBpAGcAbgBvAC4AaAB1AC8AUwBaAFMAWgAvMIHIBgNVHR8EgcAwgb0wgbqggbeggbSGIWh0dHA6 -Ly93d3cuZS1zemlnbm8uaHUvUm9vdENBLmNybIaBjmxkYXA6Ly9sZGFwLmUtc3ppZ25vLmh1L0NO -PU1pY3Jvc2VjJTIwZS1Temlnbm8lMjBSb290JTIwQ0EsT1U9ZS1Temlnbm8lMjBDQSxPPU1pY3Jv -c2VjJTIwTHRkLixMPUJ1ZGFwZXN0LEM9SFU/Y2VydGlmaWNhdGVSZXZvY2F0aW9uTGlzdDtiaW5h -cnkwDgYDVR0PAQH/BAQDAgEGMIGWBgNVHREEgY4wgYuBEGluZm9AZS1zemlnbm8uaHWkdzB1MSMw -IQYDVQQDDBpNaWNyb3NlYyBlLVN6aWduw7MgUm9vdCBDQTEWMBQGA1UECwwNZS1TemlnbsOzIEhT -WjEWMBQGA1UEChMNTWljcm9zZWMgS2Z0LjERMA8GA1UEBxMIQnVkYXBlc3QxCzAJBgNVBAYTAkhV -MIGsBgNVHSMEgaQwgaGAFMegSXUWYYTbMUuE0vE3QJDvTtz3oXakdDByMQswCQYDVQQGEwJIVTER -MA8GA1UEBxMIQnVkYXBlc3QxFjAUBgNVBAoTDU1pY3Jvc2VjIEx0ZC4xFDASBgNVBAsTC2UtU3pp -Z25vIENBMSIwIAYDVQQDExlNaWNyb3NlYyBlLVN6aWdubyBSb290IENBghEAzLjnv04pGv2i3Gal -HCwPETAdBgNVHQ4EFgQUx6BJdRZhhNsxS4TS8TdAkO9O3PcwDQYJKoZIhvcNAQEFBQADggEBANMT -nGZjWS7KXHAM/IO8VbH0jgdsZifOwTsgqRy7RlRw7lrMoHfqaEQn6/Ip3Xep1fvj1KcExJW4C+FE -aGAHQzAxQmHl7tnlJNUb3+FKG6qfx1/4ehHqE5MAyopYse7tDk2016g2JnzgOsHVV4Lxdbb9iV/a -86g4nzUGCM4ilb7N1fy+W955a9x6qWVmvrElWl/tftOsRm1M9DKHtCAE4Gx4sHfRhUZLphK3dehK -yVZs15KrnfVJONJPU+NVkBHbmJbGSfI+9J8b4PeI3CVimUTYc78/MPMMNz7UwiiAc7EBt51alhQB -S6kRnSlqLtBdgcDPsiBDxwPgN05dCtxZICU= ------END CERTIFICATE----- - Certigna ======== -----BEGIN CERTIFICATE----- @@ -1575,58 +1205,6 @@ LBOhgLJeDEoTniDYYkCrkOpkSi+sDQESeUWoL4cZaMjihccwsnX5OD+ywJO0a+IDRM5noN+J1q2M dqMTw5RhK2vZbMEHCiIHhWyFJEapvj+LeISCfiQMnf2BN+MlqO02TpUsyZyQ2uypQjyttgI= -----END CERTIFICATE----- -Buypass Class 2 CA 1 -==================== ------BEGIN CERTIFICATE----- -MIIDUzCCAjugAwIBAgIBATANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU -QnV5cGFzcyBBUy05ODMxNjMzMjcxHTAbBgNVBAMMFEJ1eXBhc3MgQ2xhc3MgMiBDQSAxMB4XDTA2 -MTAxMzEwMjUwOVoXDTE2MTAxMzEwMjUwOVowSzELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBh -c3MgQVMtOTgzMTYzMzI3MR0wGwYDVQQDDBRCdXlwYXNzIENsYXNzIDIgQ0EgMTCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBAIs8B0XY9t/mx8q6jUPFR42wWsE425KEHK8T1A9vNkYgxC7M -cXA0ojTTNy7Y3Tp3L8DrKehc0rWpkTSHIln+zNvnma+WwajHQN2lFYxuyHyXA8vmIPLXl18xoS83 -0r7uvqmtqEyeIWZDO6i88wmjONVZJMHCR3axiFyCO7srpgTXjAePzdVBHfCuuCkslFJgNJQ72uA4 -0Z0zPhX0kzLFANq1KWYOOngPIVJfAuWSeyXTkh4vFZ2B5J2O6O+JzhRMVB0cgRJNcKi+EAUXfh/R -uFdV7c27UsKwHnjCTTZoy1YmwVLBvXb3WNVyfh9EdrsAiR0WnVE1703CVu9r4Iw7DekCAwEAAaNC -MEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUP42aWYv8e3uco684sDntkHGA1sgwDgYDVR0P -AQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQAVGn4TirnoB6NLJzKyQJHyIdFkhb5jatLPgcIV -1Xp+DCmsNx4cfHZSldq1fyOhKXdlyTKdqC5Wq2B2zha0jX94wNWZUYN/Xtm+DKhQ7SLHrQVMdvvt -7h5HZPb3J31cKA9FxVxiXqaakZG3Uxcu3K1gnZZkOb1naLKuBctN518fV4bVIJwo+28TOPX2EZL2 -fZleHwzoq0QkKXJAPTZSr4xYkHPB7GEseaHsh7U/2k3ZIQAw3pDaDtMaSKk+hQsUi4y8QZ5q9w5w -wDX3OaJdZtB7WZ+oRxKaJyOkLY4ng5IgodcVf/EuGO70SH8vf/GhGLWhC5SgYiAynB321O+/TIho ------END CERTIFICATE----- - -EBG Elektronik Sertifika Hizmet Sa\xC4\x9Flay\xc4\xb1\x63\xc4\xb1s\xc4\xb1 -========================================================================== ------BEGIN CERTIFICATE----- -MIIF5zCCA8+gAwIBAgIITK9zQhyOdAIwDQYJKoZIhvcNAQEFBQAwgYAxODA2BgNVBAMML0VCRyBF -bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMTcwNQYDVQQKDC5FQkcg -QmlsacWfaW0gVGVrbm9sb2ppbGVyaSB2ZSBIaXptZXRsZXJpIEEuxZ4uMQswCQYDVQQGEwJUUjAe -Fw0wNjA4MTcwMDIxMDlaFw0xNjA4MTQwMDMxMDlaMIGAMTgwNgYDVQQDDC9FQkcgRWxla3Ryb25p -ayBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsTE3MDUGA1UECgwuRUJHIEJpbGnFn2lt -IFRla25vbG9qaWxlcmkgdmUgSGl6bWV0bGVyaSBBLsWeLjELMAkGA1UEBhMCVFIwggIiMA0GCSqG -SIb3DQEBAQUAA4ICDwAwggIKAoICAQDuoIRh0DpqZhAy2DE4f6en5f2h4fuXd7hxlugTlkaDT7by -X3JWbhNgpQGR4lvFzVcfd2NR/y8927k/qqk153nQ9dAktiHq6yOU/im/+4mRDGSaBUorzAzu8T2b -gmmkTPiab+ci2hC6X5L8GCcKqKpE+i4stPtGmggDg3KriORqcsnlZR9uKg+ds+g75AxuetpX/dfr -eYteIAbTdgtsApWjluTLdlHRKJ2hGvxEok3MenaoDT2/F08iiFD9rrbskFBKW5+VQarKD7JK/oCZ -TqNGFav4c0JqwmZ2sQomFd2TkuzbqV9UIlKRcF0T6kjsbgNs2d1s/OsNA/+mgxKb8amTD8UmTDGy -Y5lhcucqZJnSuOl14nypqZoaqsNW2xCaPINStnuWt6yHd6i58mcLlEOzrz5z+kI2sSXFCjEmN1Zn -uqMLfdb3ic1nobc6HmZP9qBVFCVMLDMNpkGMvQQxahByCp0OLna9XvNRiYuoP1Vzv9s6xiQFlpJI -qkuNKgPlV5EQ9GooFW5Hd4RcUXSfGenmHmMWOeMRFeNYGkS9y8RsZteEBt8w9DeiQyJ50hBs37vm -ExH8nYQKE3vwO9D8owrXieqWfo1IhR5kX9tUoqzVegJ5a9KK8GfaZXINFHDk6Y54jzJ0fFfy1tb0 -Nokb+Clsi7n2l9GkLqq+CxnCRelwXQIDAJ3Zo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB -/wQEAwIBBjAdBgNVHQ4EFgQU587GT/wWZ5b6SqMHwQSny2re2kcwHwYDVR0jBBgwFoAU587GT/wW -Z5b6SqMHwQSny2re2kcwDQYJKoZIhvcNAQEFBQADggIBAJuYml2+8ygjdsZs93/mQJ7ANtyVDR2t -FcU22NU57/IeIl6zgrRdu0waypIN30ckHrMk2pGI6YNw3ZPX6bqz3xZaPt7gyPvT/Wwp+BVGoGgm -zJNSroIBk5DKd8pNSe/iWtkqvTDOTLKBtjDOWU/aWR1qeqRFsIImgYZ29fUQALjuswnoT4cCB64k -XPBfrAowzIpAoHMEwfuJJPaaHFy3PApnNgUIMbOv2AFoKuB4j3TeuFGkjGwgPaL7s9QJ/XvCgKqT -bCmYIai7FvOpEl90tYeY8pUm3zTvilORiF0alKM/fCL414i6poyWqD1SNGKfAB5UVUJnxk1Gj7sU -RT0KlhaOEKGXmdXTMIXM3rRyt7yKPBgpaP3ccQfuJDlq+u2lrDgv+R4QDgZxGhBM/nV+/x5XOULK -1+EVoVZVWRvRo68R2E7DpSvvkL/A7IITW43WciyTTo9qKd+FPNMN4KIYEsxVL0e3p5sC/kH2iExt -2qkBR4NkJ2IQgtYSe14DHzSpyZH+r11thie3I6p1GMog57AP14kOpmciY/SDQSsGS7tY1dHXt7kQ -Y9iJSrSq3RZj9W6+YKH47ejWkE8axsWgKdOnIaj1Wjz3x0miIZpKlVIglnKaZsv30oZDfCK+lvm9 -AahH3eU7QPl1K5srRmSGjR70j/sHd9DqSaIcjVIUpgqT ------END CERTIFICATE----- - certSIGN ROOT CA ================ -----BEGIN CERTIFICATE----- @@ -1647,49 +1225,6 @@ vBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNwi/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7Nz TogVZ96edhBiIL5VaZVDADlN9u6wWk5JRFRYX0KD -----END CERTIFICATE----- -CNNIC ROOT -========== ------BEGIN CERTIFICATE----- -MIIDVTCCAj2gAwIBAgIESTMAATANBgkqhkiG9w0BAQUFADAyMQswCQYDVQQGEwJDTjEOMAwGA1UE -ChMFQ05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1QwHhcNMDcwNDE2MDcwOTE0WhcNMjcwNDE2MDcw -OTE0WjAyMQswCQYDVQQGEwJDTjEOMAwGA1UEChMFQ05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1Qw -ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDTNfc/c3et6FtzF8LRb+1VvG7q6KR5smzD -o+/hn7E7SIX1mlwhIhAsxYLO2uOabjfhhyzcuQxauohV3/2q2x8x6gHx3zkBwRP9SFIhxFXf2tiz -VHa6dLG3fdfA6PZZxU3Iva0fFNrfWEQlMhkqx35+jq44sDB7R3IJMfAw28Mbdim7aXZOV/kbZKKT -VrdvmW7bCgScEeOAH8tjlBAKqeFkgjH5jCftppkA9nCTGPihNIaj3XrCGHn2emU1z5DrvTOTn1Or -czvmmzQgLx3vqR1jGqCA2wMv+SYahtKNu6m+UjqHZ0gNv7Sg2Ca+I19zN38m5pIEo3/PIKe38zrK -y5nLAgMBAAGjczBxMBEGCWCGSAGG+EIBAQQEAwIABzAfBgNVHSMEGDAWgBRl8jGtKvf33VKWCscC -wQ7vptU7ETAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIB/jAdBgNVHQ4EFgQUZfIxrSr3991S -lgrHAsEO76bVOxEwDQYJKoZIhvcNAQEFBQADggEBAEs17szkrr/Dbq2flTtLP1se31cpolnKOOK5 -Gv+e5m4y3R6u6jW39ZORTtpC4cMXYFDy0VwmuYK36m3knITnA3kXr5g9lNvHugDnuL8BV8F3RTIM -O/G0HAiw/VGgod2aHRM2mm23xzy54cXZF/qD1T0VoDy7HgviyJA/qIYM/PmLXoXLT1tLYhFHxUV8 -BS9BsZ4QaRuZluBVeftOhpm4lNqGOGqTo+fLbuXf6iFViZx9fX+Y9QCJ7uOEwFyWtcVG6kbghVW2 -G8kS1sHNzYDzAgE8yGnLRUhj2JTQ7IUOO04RZfSCjKY9ri4ilAnIXOo8gV0WKgOXFlUJ24pBgp5m -mxE= ------END CERTIFICATE----- - -ApplicationCA - Japanese Government -=================================== ------BEGIN CERTIFICATE----- -MIIDoDCCAoigAwIBAgIBMTANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJKUDEcMBoGA1UEChMT -SmFwYW5lc2UgR292ZXJubWVudDEWMBQGA1UECxMNQXBwbGljYXRpb25DQTAeFw0wNzEyMTIxNTAw -MDBaFw0xNzEyMTIxNTAwMDBaMEMxCzAJBgNVBAYTAkpQMRwwGgYDVQQKExNKYXBhbmVzZSBHb3Zl -cm5tZW50MRYwFAYDVQQLEw1BcHBsaWNhdGlvbkNBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB -CgKCAQEAp23gdE6Hj6UG3mii24aZS2QNcfAKBZuOquHMLtJqO8F6tJdhjYq+xpqcBrSGUeQ3DnR4 -fl+Kf5Sk10cI/VBaVuRorChzoHvpfxiSQE8tnfWuREhzNgaeZCw7NCPbXCbkcXmP1G55IrmTwcrN -wVbtiGrXoDkhBFcsovW8R0FPXjQilbUfKW1eSvNNcr5BViCH/OlQR9cwFO5cjFW6WY2H/CPek9AE -jP3vbb3QesmlOmpyM8ZKDQUXKi17safY1vC+9D/qDihtQWEjdnjDuGWk81quzMKq2edY3rZ+nYVu -nyoKb58DKTCXKB28t89UKU5RMfkntigm/qJj5kEW8DOYRwIDAQABo4GeMIGbMB0GA1UdDgQWBBRU -WssmP3HMlEYNllPqa0jQk/5CdTAOBgNVHQ8BAf8EBAMCAQYwWQYDVR0RBFIwUKROMEwxCzAJBgNV -BAYTAkpQMRgwFgYDVQQKDA/ml6XmnKzlm73mlL/lupwxIzAhBgNVBAsMGuOCouODl+ODquOCseOD -vOOCt+ODp+ODs0NBMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADlqRHZ3ODrs -o2dGD/mLBqj7apAxzn7s2tGJfHrrLgy9mTLnsCTWw//1sogJhyzjVOGjprIIC8CFqMjSnHH2HZ9g -/DgzE+Ge3Atf2hZQKXsvcJEPmbo0NI2VdMV+eKlmXb3KIXdCEKxmJj3ekav9FfBv7WxfEPjzFvYD -io+nEhEMy/0/ecGc/WLuo89UDNErXxc+4z6/wCs+CZv+iKZ+tJIX/COUgb1up8WMwusRRdv4QcmW -dupwX3kSa+SjB1oF7ydJzyGfikwJcGapJsErEU4z0g781mzSDjJkaP+tBXhfAx2o45CsJOAPQKdL -rosot4LKGAfmt1t06SAZf7IbiVQ= ------END CERTIFICATE----- - GeoTrust Primary Certification Authority - G3 ============================================= -----BEGIN CERTIFICATE----- @@ -1821,7 +1356,7 @@ AJw9SDkjOVgaFRJZap7v1VmyHVIsmXHNxynfGyphe3HR3vPA5Q06Sqotp9iGKt0uEA== -----END CERTIFICATE----- NetLock Arany (Class Gold) Főtanúsítvány -============================================ +======================================== -----BEGIN CERTIFICATE----- MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQGEwJIVTERMA8G A1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3MDUGA1UECwwuVGFuw7pzw610 @@ -1876,58 +1411,6 @@ IPVVYpbtbZNQvOSqeK3Zywplh6ZmwcSBo3c6WB4L7oOLnR7SUqTMHW+wmG2UMbX4cQrcufx9MmDm 66+KAQ== -----END CERTIFICATE----- -CA Disig -======== ------BEGIN CERTIFICATE----- -MIIEDzCCAvegAwIBAgIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJTSzETMBEGA1UEBxMK -QnJhdGlzbGF2YTETMBEGA1UEChMKRGlzaWcgYS5zLjERMA8GA1UEAxMIQ0EgRGlzaWcwHhcNMDYw -MzIyMDEzOTM0WhcNMTYwMzIyMDEzOTM0WjBKMQswCQYDVQQGEwJTSzETMBEGA1UEBxMKQnJhdGlz -bGF2YTETMBEGA1UEChMKRGlzaWcgYS5zLjERMA8GA1UEAxMIQ0EgRGlzaWcwggEiMA0GCSqGSIb3 -DQEBAQUAA4IBDwAwggEKAoIBAQCS9jHBfYj9mQGp2HvycXXxMcbzdWb6UShGhJd4NLxs/LxFWYgm -GErENx+hSkS943EE9UQX4j/8SFhvXJ56CbpRNyIjZkMhsDxkovhqFQ4/61HhVKndBpnXmjxUizkD -Pw/Fzsbrg3ICqB9x8y34dQjbYkzo+s7552oftms1grrijxaSfQUMbEYDXcDtab86wYqg6I7ZuUUo -hwjstMoVvoLdtUSLLa2GDGhibYVW8qwUYzrG0ZmsNHhWS8+2rT+MitcE5eN4TPWGqvWP+j1scaMt -ymfraHtuM6kMgiioTGohQBUgDCZbg8KpFhXAJIJdKxatymP2dACw30PEEGBWZ2NFAgMBAAGjgf8w -gfwwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUjbJJaJ1yCCW5wCf1UJNWSEZx+Y8wDgYDVR0P -AQH/BAQDAgEGMDYGA1UdEQQvMC2BE2Nhb3BlcmF0b3JAZGlzaWcuc2uGFmh0dHA6Ly93d3cuZGlz -aWcuc2svY2EwZgYDVR0fBF8wXTAtoCugKYYnaHR0cDovL3d3dy5kaXNpZy5zay9jYS9jcmwvY2Ff -ZGlzaWcuY3JsMCygKqAohiZodHRwOi8vY2EuZGlzaWcuc2svY2EvY3JsL2NhX2Rpc2lnLmNybDAa -BgNVHSAEEzARMA8GDSuBHpGT5goAAAABAQEwDQYJKoZIhvcNAQEFBQADggEBAF00dGFMrzvY/59t -WDYcPQuBDRIrRhCA/ec8J9B6yKm2fnQwM6M6int0wHl5QpNt/7EpFIKrIYwvF/k/Ji/1WcbvgAa3 -mkkp7M5+cTxqEEHA9tOasnxakZzArFvITV734VP/Q3f8nktnbNfzg9Gg4H8l37iYC5oyOGwwoPP/ -CBUz91BKez6jPiCp3C9WgArtQVCwyfTssuMmRAAOb54GvCKWU3BlxFAKRmukLyeBEicTXxChds6K -ezfqwzlhA5WYOudsiCUI/HloDYd9Yvi0X/vF2Ey9WLw/Q1vUHgFNPGO+I++MzVpQuGhU+QqZMxEA -4Z7CRneC9VkGjCFMhwnN5ag= ------END CERTIFICATE----- - -Juur-SK -======= ------BEGIN CERTIFICATE----- -MIIE5jCCA86gAwIBAgIEO45L/DANBgkqhkiG9w0BAQUFADBdMRgwFgYJKoZIhvcNAQkBFglwa2lA -c2suZWUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKExlBUyBTZXJ0aWZpdHNlZXJpbWlza2Vza3VzMRAw -DgYDVQQDEwdKdXVyLVNLMB4XDTAxMDgzMDE0MjMwMVoXDTE2MDgyNjE0MjMwMVowXTEYMBYGCSqG -SIb3DQEJARYJcGtpQHNrLmVlMQswCQYDVQQGEwJFRTEiMCAGA1UEChMZQVMgU2VydGlmaXRzZWVy -aW1pc2tlc2t1czEQMA4GA1UEAxMHSnV1ci1TSzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC -ggEBAIFxNj4zB9bjMI0TfncyRsvPGbJgMUaXhvSYRqTCZUXP00B841oiqBB4M8yIsdOBSvZiF3tf -TQou0M+LI+5PAk676w7KvRhj6IAcjeEcjT3g/1tf6mTll+g/mX8MCgkzABpTpyHhOEvWgxutr2TC -+Rx6jGZITWYfGAriPrsfB2WThbkasLnE+w0R9vXW+RvHLCu3GFH+4Hv2qEivbDtPL+/40UceJlfw -UR0zlv/vWT3aTdEVNMfqPxZIe5EcgEMPPbgFPtGzlc3Yyg/CQ2fbt5PgIoIuvvVoKIO5wTtpeyDa -Tpxt4brNj3pssAki14sL2xzVWiZbDcDq5WDQn/413z8CAwEAAaOCAawwggGoMA8GA1UdEwEB/wQF -MAMBAf8wggEWBgNVHSAEggENMIIBCTCCAQUGCisGAQQBzh8BAQEwgfYwgdAGCCsGAQUFBwICMIHD -HoHAAFMAZQBlACAAcwBlAHIAdABpAGYAaQBrAGEAYQB0ACAAbwBuACAAdgDkAGwAagBhAHMAdABh -AHQAdQBkACAAQQBTAC0AaQBzACAAUwBlAHIAdABpAGYAaQB0AHMAZQBlAHIAaQBtAGkAcwBrAGUA -cwBrAHUAcwAgAGEAbABhAG0ALQBTAEsAIABzAGUAcgB0AGkAZgBpAGsAYQBhAHQAaQBkAGUAIABr -AGkAbgBuAGkAdABhAG0AaQBzAGUAawBzMCEGCCsGAQUFBwIBFhVodHRwOi8vd3d3LnNrLmVlL2Nw -cy8wKwYDVR0fBCQwIjAgoB6gHIYaaHR0cDovL3d3dy5zay5lZS9qdXVyL2NybC8wHQYDVR0OBBYE -FASqekej5ImvGs8KQKcYP2/v6X2+MB8GA1UdIwQYMBaAFASqekej5ImvGs8KQKcYP2/v6X2+MA4G -A1UdDwEB/wQEAwIB5jANBgkqhkiG9w0BAQUFAAOCAQEAe8EYlFOiCfP+JmeaUOTDBS8rNXiRTHyo -ERF5TElZrMj3hWVcRrs7EKACr81Ptcw2Kuxd/u+gkcm2k298gFTsxwhwDY77guwqYHhpNjbRxZyL -abVAyJRld/JXIWY7zoVAtjNjGr95HvxcHdMdkxuLDF2FvZkwMhgJkVLpfKG6/2SSmuz+Ne6ML678 -IIbsSt4beDI3poHSna9aEhbKmVv8b20OxaAehsmR0FyYgl9jDIpaq9iVpszLita/ZEuOyoqysOkh -Mp6qqIWYNIE5ITuoOlIyPfZrN4YGWhWY3PARZv40ILcD9EEQfTmEeZZyY7aWAuVrua0ZTbvGRNs2 -yyqcjg== ------END CERTIFICATE----- - Hongkong Post Root CA 1 ======================= -----BEGIN CERTIFICATE----- @@ -2361,7 +1844,7 @@ Zt3hrvJBW8qYVoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI -----END CERTIFICATE----- Certinomis - Autorité Racine -============================= +============================ -----BEGIN CERTIFICATE----- MIIFnDCCA4SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJGUjETMBEGA1UEChMK Q2VydGlub21pczEXMBUGA1UECxMOMDAwMiA0MzM5OTg5MDMxJjAkBgNVBAMMHUNlcnRpbm9taXMg @@ -2391,41 +1874,6 @@ wk01+dIL8hf2rGbVJLJP0RyZwG71fet0BLj5TXcJ17TPBzAJ8bgAVtkXFhYKK4bfjwEZGuW7gmP/ vgt2Fl43N+bYdJeimUV5 -----END CERTIFICATE----- -Root CA Generalitat Valenciana -============================== ------BEGIN CERTIFICATE----- -MIIGizCCBXOgAwIBAgIEO0XlaDANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJFUzEfMB0GA1UE -ChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0GA1UECxMGUEtJR1ZBMScwJQYDVQQDEx5Sb290 -IENBIEdlbmVyYWxpdGF0IFZhbGVuY2lhbmEwHhcNMDEwNzA2MTYyMjQ3WhcNMjEwNzAxMTUyMjQ3 -WjBoMQswCQYDVQQGEwJFUzEfMB0GA1UEChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0GA1UE -CxMGUEtJR1ZBMScwJQYDVQQDEx5Sb290IENBIEdlbmVyYWxpdGF0IFZhbGVuY2lhbmEwggEiMA0G -CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDGKqtXETcvIorKA3Qdyu0togu8M1JAJke+WmmmO3I2 -F0zo37i7L3bhQEZ0ZQKQUgi0/6iMweDHiVYQOTPvaLRfX9ptI6GJXiKjSgbwJ/BXufjpTjJ3Cj9B -ZPPrZe52/lSqfR0grvPXdMIKX/UIKFIIzFVd0g/bmoGlu6GzwZTNVOAydTGRGmKy3nXiz0+J2ZGQ -D0EbtFpKd71ng+CT516nDOeB0/RSrFOyA8dEJvt55cs0YFAQexvba9dHq198aMpunUEDEO5rmXte -JajCq+TA81yc477OMUxkHl6AovWDfgzWyoxVjr7gvkkHD6MkQXpYHYTqWBLI4bft75PelAgxAgMB -AAGjggM7MIIDNzAyBggrBgEFBQcBAQQmMCQwIgYIKwYBBQUHMAGGFmh0dHA6Ly9vY3NwLnBraS5n -dmEuZXMwEgYDVR0TAQH/BAgwBgEB/wIBAjCCAjQGA1UdIASCAiswggInMIICIwYKKwYBBAG/VQIB -ADCCAhMwggHoBggrBgEFBQcCAjCCAdoeggHWAEEAdQB0AG8AcgBpAGQAYQBkACAAZABlACAAQwBl -AHIAdABpAGYAaQBjAGEAYwBpAPMAbgAgAFIAYQDtAHoAIABkAGUAIABsAGEAIABHAGUAbgBlAHIA -YQBsAGkAdABhAHQAIABWAGEAbABlAG4AYwBpAGEAbgBhAC4ADQAKAEwAYQAgAEQAZQBjAGwAYQBy -AGEAYwBpAPMAbgAgAGQAZQAgAFAAcgDhAGMAdABpAGMAYQBzACAAZABlACAAQwBlAHIAdABpAGYA -aQBjAGEAYwBpAPMAbgAgAHEAdQBlACAAcgBpAGcAZQAgAGUAbAAgAGYAdQBuAGMAaQBvAG4AYQBt -AGkAZQBuAHQAbwAgAGQAZQAgAGwAYQAgAHAAcgBlAHMAZQBuAHQAZQAgAEEAdQB0AG8AcgBpAGQA -YQBkACAAZABlACAAQwBlAHIAdABpAGYAaQBjAGEAYwBpAPMAbgAgAHMAZQAgAGUAbgBjAHUAZQBu -AHQAcgBhACAAZQBuACAAbABhACAAZABpAHIAZQBjAGMAaQDzAG4AIAB3AGUAYgAgAGgAdAB0AHAA -OgAvAC8AdwB3AHcALgBwAGsAaQAuAGcAdgBhAC4AZQBzAC8AYwBwAHMwJQYIKwYBBQUHAgEWGWh0 -dHA6Ly93d3cucGtpLmd2YS5lcy9jcHMwHQYDVR0OBBYEFHs100DSHHgZZu90ECjcPk+yeAT8MIGV -BgNVHSMEgY0wgYqAFHs100DSHHgZZu90ECjcPk+yeAT8oWykajBoMQswCQYDVQQGEwJFUzEfMB0G -A1UEChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0GA1UECxMGUEtJR1ZBMScwJQYDVQQDEx5S -b290IENBIEdlbmVyYWxpdGF0IFZhbGVuY2lhbmGCBDtF5WgwDQYJKoZIhvcNAQEFBQADggEBACRh -TvW1yEICKrNcda3FbcrnlD+laJWIwVTAEGmiEi8YPyVQqHxK6sYJ2fR1xkDar1CdPaUWu20xxsdz -Ckj+IHLtb8zog2EWRpABlUt9jppSCS/2bxzkoXHPjCpaF3ODR00PNvsETUlR4hTJZGH71BTg9J63 -NI8KJr2XXPR5OkowGcytT6CYirQxlyric21+eLj4iIlPsSKRZEv1UN4D2+XFducTZnV+ZfsBn5OH -iJ35Rld8TWCvmHMTI6QgkYH60GFmuH3Rr9ZvHmw96RH9qfmCIoaZM3Fa6hlXPZHNqcCjbgcTpsnt -+GijnsNacgmHKNHEc8RzGF9QdRYxn7fofMM= ------END CERTIFICATE----- - TWCA Root Certification Authority ================================= -----BEGIN CERTIFICATE----- @@ -2871,93 +2319,6 @@ poLWccret9W6aAjtmcz9opLLabid+Qqkpj5PkygqYWwHJgD/ll9ohri4zspV4KuxPX+Y1zMOWj3Y eMLEYC/HYvBhkdI4sPaeVdtAgAUSM84dkpvRabP/v/GSCmE1P93+hvS84Bpxs2Km -----END CERTIFICATE----- -China Internet Network Information Center EV Certificates Root -============================================================== ------BEGIN CERTIFICATE----- -MIID9zCCAt+gAwIBAgIESJ8AATANBgkqhkiG9w0BAQUFADCBijELMAkGA1UEBhMCQ04xMjAwBgNV -BAoMKUNoaW5hIEludGVybmV0IE5ldHdvcmsgSW5mb3JtYXRpb24gQ2VudGVyMUcwRQYDVQQDDD5D -aGluYSBJbnRlcm5ldCBOZXR3b3JrIEluZm9ybWF0aW9uIENlbnRlciBFViBDZXJ0aWZpY2F0ZXMg -Um9vdDAeFw0xMDA4MzEwNzExMjVaFw0zMDA4MzEwNzExMjVaMIGKMQswCQYDVQQGEwJDTjEyMDAG -A1UECgwpQ2hpbmEgSW50ZXJuZXQgTmV0d29yayBJbmZvcm1hdGlvbiBDZW50ZXIxRzBFBgNVBAMM -PkNoaW5hIEludGVybmV0IE5ldHdvcmsgSW5mb3JtYXRpb24gQ2VudGVyIEVWIENlcnRpZmljYXRl -cyBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAm35z7r07eKpkQ0H1UN+U8i6y -jUqORlTSIRLIOTJCBumD1Z9S7eVnAztUwYyZmczpwA//DdmEEbK40ctb3B75aDFk4Zv6dOtouSCV -98YPjUesWgbdYavi7NifFy2cyjw1l1VxzUOFsUcW9SxTgHbP0wBkvUCZ3czY28Sf1hNfQYOL+Q2H -klY0bBoQCxfVWhyXWIQ8hBouXJE0bhlffxdpxWXvayHG1VA6v2G5BY3vbzQ6sm8UY78WO5upKv23 -KzhmBsUs4qpnHkWnjQRmQvaPK++IIGmPMowUc9orhpFjIpryp9vOiYurXccUwVswah+xt54ugQEC -7c+WXmPbqOY4twIDAQABo2MwYTAfBgNVHSMEGDAWgBR8cks5x8DbYqVPm6oYNJKiyoOCWTAPBgNV -HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUfHJLOcfA22KlT5uqGDSSosqD -glkwDQYJKoZIhvcNAQEFBQADggEBACrDx0M3j92tpLIM7twUbY8opJhJywyA6vPtI2Z1fcXTIWd5 -0XPFtQO3WKwMVC/GVhMPMdoG52U7HW8228gd+f2ABsqjPWYWqJ1MFn3AlUa1UeTiH9fqBk1jjZaM -7+czV0I664zBechNdn3e9rG3geCg+aF4RhcaVpjwTj2rHO3sOdwHSPdj/gauwqRcalsyiMXHM4Ws -ZkJHwlgkmeHlPuV1LI5D1l08eB6olYIpUNHRFrrvwb562bTYzB5MRuF3sTGrvSrIzo9uoV1/A3U0 -5K2JRVRevq4opbs/eHnrc7MKDf2+yfdWrPa37S+bISnHOLaVxATywy39FCqQmbkHzJ8= ------END CERTIFICATE----- - -Swisscom Root CA 2 -================== ------BEGIN CERTIFICATE----- -MIIF2TCCA8GgAwIBAgIQHp4o6Ejy5e/DfEoeWhhntjANBgkqhkiG9w0BAQsFADBkMQswCQYDVQQG -EwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsTHERpZ2l0YWwgQ2VydGlmaWNhdGUgU2Vy -dmljZXMxGzAZBgNVBAMTElN3aXNzY29tIFJvb3QgQ0EgMjAeFw0xMTA2MjQwODM4MTRaFw0zMTA2 -MjUwNzM4MTRaMGQxCzAJBgNVBAYTAmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGln -aXRhbCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAyMIIC -IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAlUJOhJ1R5tMJ6HJaI2nbeHCOFvErjw0DzpPM -LgAIe6szjPTpQOYXTKueuEcUMncy3SgM3hhLX3af+Dk7/E6J2HzFZ++r0rk0X2s682Q2zsKwzxNo -ysjL67XiPS4h3+os1OD5cJZM/2pYmLcX5BtS5X4HAB1f2uY+lQS3aYg5oUFgJWFLlTloYhyxCwWJ -wDaCFCE/rtuh/bxvHGCGtlOUSbkrRsVPACu/obvLP+DHVxxX6NZp+MEkUp2IVd3Chy50I9AU/SpH -Wrumnf2U5NGKpV+GY3aFy6//SSj8gO1MedK75MDvAe5QQQg1I3ArqRa0jG6F6bYRzzHdUyYb3y1a -SgJA/MTAtukxGggo5WDDH8SQjhBiYEQN7Aq+VRhxLKX0srwVYv8c474d2h5Xszx+zYIdkeNL6yxS -NLCK/RJOlrDrcH+eOfdmQrGrrFLadkBXeyq96G4DsguAhYidDMfCd7Camlf0uPoTXGiTOmekl9Ab -mbeGMktg2M7v0Ax/lZ9vh0+Hio5fCHyqW/xavqGRn1V9TrALacywlKinh/LTSlDcX3KwFnUey7QY -Ypqwpzmqm59m2I2mbJYV4+by+PGDYmy7Velhk6M99bFXi08jsJvllGov34zflVEpYKELKeRcVVi3 -qPyZ7iVNTA6z00yPhOgpD/0QVAKFyPnlw4vP5w8CAwEAAaOBhjCBgzAOBgNVHQ8BAf8EBAMCAYYw -HQYDVR0hBBYwFDASBgdghXQBUwIBBgdghXQBUwIBMBIGA1UdEwEB/wQIMAYBAf8CAQcwHQYDVR0O -BBYEFE0mICKJS9PVpAqhb97iEoHF8TwuMB8GA1UdIwQYMBaAFE0mICKJS9PVpAqhb97iEoHF8Twu -MA0GCSqGSIb3DQEBCwUAA4ICAQAyCrKkG8t9voJXiblqf/P0wS4RfbgZPnm3qKhyN2abGu2sEzsO -v2LwnN+ee6FTSA5BesogpxcbtnjsQJHzQq0Qw1zv/2BZf82Fo4s9SBwlAjxnffUy6S8w5X2lejjQ -82YqZh6NM4OKb3xuqFp1mrjX2lhIREeoTPpMSQpKwhI3qEAMw8jh0FcNlzKVxzqfl9NX+Ave5XLz -o9v/tdhZsnPdTSpxsrpJ9csc1fV5yJmz/MFMdOO0vSk3FQQoHt5FRnDsr7p4DooqzgB53MBfGWcs -a0vvaGgLQ+OswWIJ76bdZWGgr4RVSJFSHMYlkSrQwSIjYVmvRRGFHQEkNI/Ps/8XciATwoCqISxx -OQ7Qj1zB09GOInJGTB2Wrk9xseEFKZZZ9LuedT3PDTcNYtsmjGOpI99nBjx8Oto0QuFmtEYE3saW -mA9LSHokMnWRn6z3aOkquVVlzl1h0ydw2Df+n7mvoC5Wt6NlUe07qxS/TFED6F+KBZvuim6c779o -+sjaC+NCydAXFJy3SuCvkychVSa1ZC+N8f+mQAWFBVzKBxlcCxMoTFh/wqXvRdpg065lYZ1Tg3TC -rvJcwhbtkj6EPnNgiLx29CzP0H1907he0ZESEOnN3col49XtmS++dYFLJPlFRpTJKSFTnCZFqhMX -5OfNeOI5wSsSnqaeG8XmDtkx2Q== ------END CERTIFICATE----- - -Swisscom Root EV CA 2 -===================== ------BEGIN CERTIFICATE----- -MIIF4DCCA8igAwIBAgIRAPL6ZOJ0Y9ON/RAdBB92ylgwDQYJKoZIhvcNAQELBQAwZzELMAkGA1UE -BhMCY2gxETAPBgNVBAoTCFN3aXNzY29tMSUwIwYDVQQLExxEaWdpdGFsIENlcnRpZmljYXRlIFNl -cnZpY2VzMR4wHAYDVQQDExVTd2lzc2NvbSBSb290IEVWIENBIDIwHhcNMTEwNjI0MDk0NTA4WhcN -MzEwNjI1MDg0NTA4WjBnMQswCQYDVQQGEwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsT -HERpZ2l0YWwgQ2VydGlmaWNhdGUgU2VydmljZXMxHjAcBgNVBAMTFVN3aXNzY29tIFJvb3QgRVYg -Q0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMT3HS9X6lds93BdY7BxUglgRCgz -o3pOCvrY6myLURYaVa5UJsTMRQdBTxB5f3HSek4/OE6zAMaVylvNwSqD1ycfMQ4jFrclyxy0uYAy -Xhqdk/HoPGAsp15XGVhRXrwsVgu42O+LgrQ8uMIkqBPHoCE2G3pXKSinLr9xJZDzRINpUKTk4Rti -GZQJo/PDvO/0vezbE53PnUgJUmfANykRHvvSEaeFGHR55E+FFOtSN+KxRdjMDUN/rhPSays/p8Li -qG12W0OfvrSdsyaGOx9/5fLoZigWJdBLlzin5M8J0TbDC77aO0RYjb7xnglrPvMyxyuHxuxenPaH -Za0zKcQvidm5y8kDnftslFGXEBuGCxobP/YCfnvUxVFkKJ3106yDgYjTdLRZncHrYTNaRdHLOdAG -alNgHa/2+2m8atwBz735j9m9W8E6X47aD0upm50qKGsaCnw8qyIL5XctcfaCNYGu+HuB5ur+rPQa -m3Rc6I8k9l2dRsQs0h4rIWqDJ2dVSqTjyDKXZpBy2uPUZC5f46Fq9mDU5zXNysRojddxyNMkM3Ox -bPlq4SjbX8Y96L5V5jcb7STZDxmPX2MYWFCBUWVv8p9+agTnNCRxunZLWB4ZvRVgRaoMEkABnRDi -xzgHcgplwLa7JSnaFp6LNYth7eVxV4O1PHGf40+/fh6Bn0GXAgMBAAGjgYYwgYMwDgYDVR0PAQH/ -BAQDAgGGMB0GA1UdIQQWMBQwEgYHYIV0AVMCAgYHYIV0AVMCAjASBgNVHRMBAf8ECDAGAQH/AgED -MB0GA1UdDgQWBBRF2aWBbj2ITY1x0kbBbkUe88SAnTAfBgNVHSMEGDAWgBRF2aWBbj2ITY1x0kbB -bkUe88SAnTANBgkqhkiG9w0BAQsFAAOCAgEAlDpzBp9SSzBc1P6xXCX5145v9Ydkn+0UjrgEjihL -j6p7jjm02Vj2e6E1CqGdivdj5eu9OYLU43otb98TPLr+flaYC/NUn81ETm484T4VvwYmneTwkLbU -wp4wLh/vx3rEUMfqe9pQy3omywC0Wqu1kx+AiYQElY2NfwmTv9SoqORjbdlk5LgpWgi/UOGED1V7 -XwgiG/W9mR4U9s70WBCCswo9GcG/W6uqmdjyMb3lOGbcWAXH7WMaLgqXfIeTK7KK4/HsGOV1timH -59yLGn602MnTihdsfSlEvoqq9X46Lmgxk7lq2prg2+kupYTNHAq4Sgj5nPFhJpiTt3tm7JFe3VE/ -23MPrQRYCd0EApUKPtN236YQHoA96M2kZNEzx5LH4k5E4wnJTsJdhw4Snr8PyQUQ3nqjsTzyP6Wq -J3mtMX0f/fwZacXduT98zca0wjAefm6S139hdlqP65VNvBFuIXxZN5nQBrz5Bm0yFqXZaajh3DyA -HmBR3NdUIR7KYndP+tiPsys6DXhyyWhBWkdKwqPrGtcKqzwyVcgKEZzfdNbwQBUdyLmPtTbFr/gi -uMod89a2GQ+fYWVq6nTIfI/DT11lgh/ZDYnadXL77/FHZxOzyNEZiCcmmpl5fx7kLD977vHeTYuW -l8PVP3wbI+2ksx0WckNLIOFZfsLorSa/ovc= ------END CERTIFICATE----- - CA Disig Root R1 ================ -----BEGIN CERTIFICATE----- @@ -3756,7 +3117,7 @@ ekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su -----END CERTIFICATE----- TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı H5 -========================================================= +==================================================== -----BEGIN CERTIFICATE----- MIIEJzCCAw+gAwIBAgIHAI4X/iQggTANBgkqhkiG9w0BAQsFADCBsTELMAkGA1UEBhMCVFIxDzAN BgNVBAcMBkFua2FyYTFNMEsGA1UECgxEVMOcUktUUlVTVCBCaWxnaSDEsGxldGnFn2ltIHZlIEJp @@ -3779,30 +3140,6 @@ lpKQd/Ct9JDpEXjXk4nAPQu6KfTomZ1yju2dL+6SfaHx/126M2CFYv4HAqGEVka+lgqaE9chTLd8 B59OTj+RdPsnnRHM3eaxynFNExc5JsUpISuTKWqW+qtB4Uu2NQvAmxU= -----END CERTIFICATE----- -TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı H6 -========================================================= ------BEGIN CERTIFICATE----- -MIIEJjCCAw6gAwIBAgIGfaHyZeyKMA0GCSqGSIb3DQEBCwUAMIGxMQswCQYDVQQGEwJUUjEPMA0G -A1UEBwwGQW5rYXJhMU0wSwYDVQQKDERUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmls -acWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLjFCMEAGA1UEAww5VMOcUktUUlVTVCBF -bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxIEg2MB4XDTEzMTIxODA5 -MDQxMFoXDTIzMTIxNjA5MDQxMFowgbExCzAJBgNVBAYTAlRSMQ8wDQYDVQQHDAZBbmthcmExTTBL -BgNVBAoMRFTDnFJLVFJVU1QgQmlsZ2kgxLBsZXRpxZ9pbSB2ZSBCaWxpxZ9pbSBHw7x2ZW5sacSf -aSBIaXptZXRsZXJpIEEuxZ4uMUIwQAYDVQQDDDlUw5xSS1RSVVNUIEVsZWt0cm9uaWsgU2VydGlm -aWthIEhpem1ldCBTYcSfbGF5xLFjxLFzxLEgSDYwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK -AoIBAQCdsGjW6L0UlqMACprx9MfMkU1xeHe59yEmFXNRFpQJRwXiM/VomjX/3EsvMsew7eKC5W/a -2uqsxgbPJQ1BgfbBOCK9+bGlprMBvD9QFyv26WZV1DOzXPhDIHiTVRZwGTLmiddk671IUP320EED -wnS3/faAz1vFq6TWlRKb55cTMgPp1KtDWxbtMyJkKbbSk60vbNg9tvYdDjTu0n2pVQ8g9P0pu5Fb -HH3GQjhtQiht1AH7zYiXSX6484P4tZgvsycLSF5W506jM7NE1qXyGJTtHB6plVxiSvgNZ1GpryHV -+DKdeboaX+UEVU0TRv/yz3THGmNtwx8XEsMeED5gCLMxAgMBAAGjQjBAMB0GA1UdDgQWBBTdVRcT -9qzoSCHK77Wv0QAy7Z6MtTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG -9w0BAQsFAAOCAQEAb1gNl0OqFlQ+v6nfkkU/hQu7VtMMUszIv3ZnXuaqs6fvuay0EBQNdH49ba3R -fdCaqaXKGDsCQC4qnFAUi/5XfldcEQlLNkVS9z2sFP1E34uXI9TDwe7UU5X+LEr+DXCqu4svLcsy -o4LyVN/Y8t3XSHLuSqMplsNEzm61kod2pLv0kmzOLBQJZo6NrRa1xxsJYTvjIKIDgI6tflEATseW -hvtDmHd9KMeP2Cpu54Rvl0EpABZeTeIT6lnAY2c6RPuY/ATTMHKm9ocJV612ph1jmv3XZch4gyt1 -O6VbuA1df74jrlZVlFjvH4GMKrLN5ptjnhi85WsGtAuYSyher4hYyw== ------END CERTIFICATE----- - Certinomis - Root CA ==================== -----BEGIN CERTIFICATE----- @@ -3892,28 +3229,418 @@ Daupn75OcsqF1NnstTJFGG+rrQIwfcf3aWMvoeGY7xMQ0Xk/0f7qO3/eVvSQsRUR2LIiFdAvwyYu a/GRspBl9JrmkO5K -----END CERTIFICATE----- -================================================================ -C: US -O: GTE Corporation -OU: GTE CyberTrust Solutions, Inc. -CN: GTE CyberTrust Global Root --- -Not Before: 1998-08-13 -Not After: 2018-08-13 -Signature: md5WithRSAEncryption -Key: RSA:1024 +SZAFIR ROOT CA2 +=============== -----BEGIN CERTIFICATE----- -MIICWjCCAcMCAgGlMA0GCSqGSIb3DQEBBAUAMHUxCzAJBgNVBAYTAlVTMRgwFgYD -VQQKEw9HVEUgQ29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRydXN0IFNv -bHV0aW9ucywgSW5jLjEjMCEGA1UEAxMaR1RFIEN5YmVyVHJ1c3QgR2xvYmFsIFJv -b3QwHhcNOTgwODEzMDAyOTAwWhcNMTgwODEzMjM1OTAwWjB1MQswCQYDVQQGEwJV -UzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQLEx5HVEUgQ3liZXJU -cnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0IEds -b2JhbCBSb290MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVD6C28FCc6HrH -iM3dFw4usJTQGz0O9pTAipTHBsiQl8i4ZBp6fmw8U+E3KHNgf7KXUwefU/ltWJTS -r41tiGeA5u2ylc9yMcqlHHK6XALnZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X4 -04Wqk2kmhXBIgD8SFcd5tB8FLztimQIDAQABMA0GCSqGSIb3DQEBBAUAA4GBAG3r -GwnpXtlR22ciYaQqPEh346B8pt5zohQDhT37qw4wxYMWM4ETCJ57NE7fQMh017l9 -3PR2VX2bY1QY6fDq81yx2YtCHrnAlU66+tXifPVoYb+O7AWXX1uw16OFNMQkpw0P -lZPvy5TYnh+dXIVtx6quTx8itc2VrbqnzPmrC3p/ +MIIDcjCCAlqgAwIBAgIUPopdB+xV0jLVt+O2XwHrLdzk1uQwDQYJKoZIhvcNAQELBQAwUTELMAkG +A1UEBhMCUEwxKDAmBgNVBAoMH0tyYWpvd2EgSXpiYSBSb3psaWN6ZW5pb3dhIFMuQS4xGDAWBgNV +BAMMD1NaQUZJUiBST09UIENBMjAeFw0xNTEwMTkwNzQzMzBaFw0zNTEwMTkwNzQzMzBaMFExCzAJ +BgNVBAYTAlBMMSgwJgYDVQQKDB9LcmFqb3dhIEl6YmEgUm96bGljemVuaW93YSBTLkEuMRgwFgYD +VQQDDA9TWkFGSVIgUk9PVCBDQTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3vD5Q +qEvNQLXOYeeWyrSh2gwisPq1e3YAd4wLz32ohswmUeQgPYUM1ljj5/QqGJ3a0a4m7utT3PSQ1hNK +DJA8w/Ta0o4NkjrcsbH/ON7Dui1fgLkCvUqdGw+0w8LBZwPd3BucPbOw3gAeqDRHu5rr/gsUvTaE +2g0gv/pby6kWIK05YO4vdbbnl5z5Pv1+TW9NL++IDWr63fE9biCloBK0TXC5ztdyO4mTp4CEHCdJ +ckm1/zuVnsHMyAHs6A6KCpbns6aH5db5BSsNl0BwPLqsdVqc1U2dAgrSS5tmS0YHF2Wtn2yIANwi +ieDhZNRnvDF5YTy7ykHNXGoAyDw4jlivAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0P +AQH/BAQDAgEGMB0GA1UdDgQWBBQuFqlKGLXLzPVvUPMjX/hd56zwyDANBgkqhkiG9w0BAQsFAAOC +AQEAtXP4A9xZWx126aMqe5Aosk3AM0+qmrHUuOQn/6mWmc5G4G18TKI4pAZw8PRBEew/R40/cof5 +O/2kbytTAOD/OblqBw7rHRz2onKQy4I9EYKL0rufKq8h5mOGnXkZ7/e7DDWQw4rtTw/1zBLZpD67 +oPwglV9PJi8RI4NOdQcPv5vRtB3pEAT+ymCPoky4rc/hkA/NrgrHXXu3UNLUYfrVFdvXn4dRVOul +4+vJhaAlIDf7js4MNIThPIGyd05DpYhfhmehPea0XGG2Ptv+tyjFogeutcrKjSoS75ftwjCkySp6 ++/NNIxuZMzSgLvWpCz/UXeHPhJ/iGcJfitYgHuNztw== +-----END CERTIFICATE----- + +Certum Trusted Network CA 2 +=========================== +-----BEGIN CERTIFICATE----- +MIIF0jCCA7qgAwIBAgIQIdbQSk8lD8kyN/yqXhKN6TANBgkqhkiG9w0BAQ0FADCBgDELMAkGA1UE +BhMCUEwxIjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMuQS4xJzAlBgNVBAsTHkNlcnR1 +bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIGA1UEAxMbQ2VydHVtIFRydXN0ZWQgTmV0d29y +ayBDQSAyMCIYDzIwMTExMDA2MDgzOTU2WhgPMjA0NjEwMDYwODM5NTZaMIGAMQswCQYDVQQGEwJQ +TDEiMCAGA1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENl +cnRpZmljYXRpb24gQXV0aG9yaXR5MSQwIgYDVQQDExtDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENB +IDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC9+Xj45tWADGSdhhuWZGc/IjoedQF9 +7/tcZ4zJzFxrqZHmuULlIEub2pt7uZld2ZuAS9eEQCsn0+i6MLs+CRqnSZXvK0AkwpfHp+6bJe+o +CgCXhVqqndwpyeI1B+twTUrWwbNWuKFBOJvR+zF/j+Bf4bE/D44WSWDXBo0Y+aomEKsq09DRZ40b +Rr5HMNUuctHFY9rnY3lEfktjJImGLjQ/KUxSiyqnwOKRKIm5wFv5HdnnJ63/mgKXwcZQkpsCLL2p +uTRZCr+ESv/f/rOf69me4Jgj7KZrdxYq28ytOxykh9xGc14ZYmhFV+SQgkK7QtbwYeDBoz1mo130 +GO6IyY0XRSmZMnUCMe4pJshrAua1YkV/NxVaI2iJ1D7eTiew8EAMvE0Xy02isx7QBlrd9pPPV3WZ +9fqGGmd4s7+W/jTcvedSVuWz5XV710GRBdxdaeOVDUO5/IOWOZV7bIBaTxNyxtd9KXpEulKkKtVB +Rgkg/iKgtlswjbyJDNXXcPiHUv3a76xRLgezTv7QCdpw75j6VuZt27VXS9zlLCUVyJ4ueE742pye +hizKV/Ma5ciSixqClnrDvFASadgOWkaLOusm+iPJtrCBvkIApPjW/jAux9JG9uWOdf3yzLnQh1vM +BhBgu4M1t15n3kfsmUjxpKEV/q2MYo45VU85FrmxY53/twIDAQABo0IwQDAPBgNVHRMBAf8EBTAD +AQH/MB0GA1UdDgQWBBS2oVQ5AsOgP46KvPrU+Bym0ToO/TAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZI +hvcNAQENBQADggIBAHGlDs7k6b8/ONWJWsQCYftMxRQXLYtPU2sQF/xlhMcQSZDe28cmk4gmb3DW +Al45oPePq5a1pRNcgRRtDoGCERuKTsZPpd1iHkTfCVn0W3cLN+mLIMb4Ck4uWBzrM9DPhmDJ2vuA +L55MYIR4PSFk1vtBHxgP58l1cb29XN40hz5BsA72udY/CROWFC/emh1auVbONTqwX3BNXuMp8SMo +clm2q8KMZiYcdywmdjWLKKdpoPk79SPdhRB0yZADVpHnr7pH1BKXESLjokmUbOe3lEu6LaTaM4tM +pkT/WjzGHWTYtTHkpjx6qFcL2+1hGsvxznN3Y6SHb0xRONbkX8eftoEq5IVIeVheO/jbAoJnwTnb +w3RLPTYe+SmTiGhbqEQZIfCn6IENLOiTNrQ3ssqwGyZ6miUfmpqAnksqP/ujmv5zMnHCnsZy4Ypo +J/HkD7TETKVhk/iXEAcqMCWpuchxuO9ozC1+9eB+D4Kob7a6bINDd82Kkhehnlt4Fj1F4jNy3eFm +ypnTycUm/Q1oBEauttmbjL4ZvrHG8hnjXALKLNhvSgfZyTXaQHXyxKcZb55CEJh15pWLYLztxRLX +is7VmFxWlgPF7ncGNf/P5O4/E2Hu29othfDNrp2yGAlFw5Khchf8R7agCyzxxN5DaAhqXzvwdmP7 +zAYspsbiDrW5viSP +-----END CERTIFICATE----- + +Hellenic Academic and Research Institutions RootCA 2015 +======================================================= +-----BEGIN CERTIFICATE----- +MIIGCzCCA/OgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBpjELMAkGA1UEBhMCR1IxDzANBgNVBAcT +BkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0 +aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNl +YXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTUwHhcNMTUwNzA3MTAxMTIxWhcNNDAwNjMwMTAx +MTIxWjCBpjELMAkGA1UEBhMCR1IxDzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMg +QWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNV +BAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIw +MTUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDC+Kk/G4n8PDwEXT2QNrCROnk8Zlrv +bTkBSRq0t89/TSNTt5AA4xMqKKYx8ZEA4yjsriFBzh/a/X0SWwGDD7mwX5nh8hKDgE0GPt+sr+eh +iGsxr/CL0BgzuNtFajT0AoAkKAoCFZVedioNmToUW/bLy1O8E00BiDeUJRtCvCLYjqOWXjrZMts+ +6PAQZe104S+nfK8nNLspfZu2zwnI5dMK/IhlZXQK3HMcXM1AsRzUtoSMTFDPaI6oWa7CJ06CojXd +FPQf/7J31Ycvqm59JCfnxssm5uX+Zwdj2EUN3TpZZTlYepKZcj2chF6IIbjV9Cz82XBST3i4vTwr +i5WY9bPRaM8gFH5MXF/ni+X1NYEZN9cRCLdmvtNKzoNXADrDgfgXy5I2XdGj2HUb4Ysn6npIQf1F +GQatJ5lOwXBH3bWfgVMS5bGMSF0xQxfjjMZ6Y5ZLKTBOhE5iGV48zpeQpX8B653g+IuJ3SWYPZK2 +fu/Z8VFRfS0myGlZYeCsargqNhEEelC9MoS+L9xy1dcdFkfkR2YgP/SWxa+OAXqlD3pk9Q0Yh9mu +iNX6hME6wGkoLfINaFGq46V3xqSQDqE3izEjR8EJCOtu93ib14L8hCCZSRm2Ekax+0VVFqmjZayc +Bw/qa9wfLgZy7IaIEuQt218FL+TwA9MmM+eAws1CoRc0CwIDAQABo0IwQDAPBgNVHRMBAf8EBTAD +AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUcRVnyMjJvXVdctA4GGqd83EkVAswDQYJKoZI +hvcNAQELBQADggIBAHW7bVRLqhBYRjTyYtcWNl0IXtVsyIe9tC5G8jH4fOpCtZMWVdyhDBKg2mF+ +D1hYc2Ryx+hFjtyp8iY/xnmMsVMIM4GwVhO+5lFc2JsKT0ucVlMC6U/2DWDqTUJV6HwbISHTGzrM +d/K4kPFox/la/vot9L/J9UUbzjgQKjeKeaO04wlshYaT/4mWJ3iBj2fjRnRUjtkNaeJK9E10A/+y +d+2VZ5fkscWrv2oj6NSU4kQoYsRL4vDY4ilrGnB+JGGTe08DMiUNRSQrlrRGar9KC/eaj8GsGsVn +82800vpzY4zvFrCopEYq+OsS7HK07/grfoxSwIuEVPkvPuNVqNxmsdnhX9izjFk0WaSrT2y7Hxjb +davYy5LNlDhhDgcGH0tGEPEVvo2FXDtKK4F5D7Rpn0lQl033DlZdwJVqwjbDG2jJ9SrcR5q+ss7F +Jej6A7na+RZukYT1HCjI/CbM1xyQVqdfbzoEvM14iQuODy+jqk+iGxI9FghAD/FGTNeqewjBCvVt +J94Cj8rDtSvK6evIIVM4pcw72Hc3MKJP2W/R8kCtQXoXxdZKNYm3QdV8hn9VTYNKpXMgwDqvkPGa +JI7ZjnHKe7iG2rKPmT4dEw0SEe7Uq/DpFXYC5ODfqiAeW2GFZECpkJcNrVPSWh2HagCXZWK0vm9q +p/UsQu0yrbYhnr68 +-----END CERTIFICATE----- + +Hellenic Academic and Research Institutions ECC RootCA 2015 +=========================================================== +-----BEGIN CERTIFICATE----- +MIICwzCCAkqgAwIBAgIBADAKBggqhkjOPQQDAjCBqjELMAkGA1UEBhMCR1IxDzANBgNVBAcTBkF0 +aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9u +cyBDZXJ0LiBBdXRob3JpdHkxRDBCBgNVBAMTO0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJj +aCBJbnN0aXR1dGlvbnMgRUNDIFJvb3RDQSAyMDE1MB4XDTE1MDcwNzEwMzcxMloXDTQwMDYzMDEw +MzcxMlowgaoxCzAJBgNVBAYTAkdSMQ8wDQYDVQQHEwZBdGhlbnMxRDBCBgNVBAoTO0hlbGxlbmlj +IEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9yaXR5MUQwQgYD +VQQDEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIEVDQyBSb290 +Q0EgMjAxNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABJKgQehLgoRc4vgxEZmGZE4JJS+dQS8KrjVP +dJWyUWRrjWvmP3CV8AVER6ZyOFB2lQJajq4onvktTpnvLEhvTCUp6NFxW98dwXU3tNf6e3pCnGoK +Vlp8aQuqgAkkbH7BRqNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O +BBYEFLQiC4KZJAEOnLvkDv2/+5cgk5kqMAoGCCqGSM49BAMCA2cAMGQCMGfOFmI4oqxiRaeplSTA +GiecMjvAwNW6qef4BENThe5SId6d9SWDPp5YSy/XZxMOIQIwBeF1Ad5o7SofTUwJCA3sS61kFyjn +dc5FZXIhF8siQQ6ME5g4mlRtm8rifOoCWCKR +-----END CERTIFICATE----- + +Certplus Root CA G1 +=================== +-----BEGIN CERTIFICATE----- +MIIFazCCA1OgAwIBAgISESBVg+QtPlRWhS2DN7cs3EYRMA0GCSqGSIb3DQEBDQUAMD4xCzAJBgNV +BAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2VydHBsdXMgUm9vdCBDQSBHMTAe +Fw0xNDA1MjYwMDAwMDBaFw0zODAxMTUwMDAwMDBaMD4xCzAJBgNVBAYTAkZSMREwDwYDVQQKDAhD +ZXJ0cGx1czEcMBoGA1UEAwwTQ2VydHBsdXMgUm9vdCBDQSBHMTCCAiIwDQYJKoZIhvcNAQEBBQAD +ggIPADCCAgoCggIBANpQh7bauKk+nWT6VjOaVj0W5QOVsjQcmm1iBdTYj+eJZJ+622SLZOZ5KmHN +r49aiZFluVj8tANfkT8tEBXgfs+8/H9DZ6itXjYj2JizTfNDnjl8KvzsiNWI7nC9hRYt6kuJPKNx +Qv4c/dMcLRC4hlTqQ7jbxofaqK6AJc96Jh2qkbBIb6613p7Y1/oA/caP0FG7Yn2ksYyy/yARujVj +BYZHYEMzkPZHogNPlk2dT8Hq6pyi/jQu3rfKG3akt62f6ajUeD94/vI4CTYd0hYCyOwqaK/1jpTv +LRN6HkJKHRUxrgwEV/xhc/MxVoYxgKDEEW4wduOU8F8ExKyHcomYxZ3MVwia9Az8fXoFOvpHgDm2 +z4QTd28n6v+WZxcIbekN1iNQMLAVdBM+5S//Ds3EC0pd8NgAM0lm66EYfFkuPSi5YXHLtaW6uOrc +4nBvCGrch2c0798wct3zyT8j/zXhviEpIDCB5BmlIOklynMxdCm+4kLV87ImZsdo/Rmz5yCTmehd +4F6H50boJZwKKSTUzViGUkAksnsPmBIgJPaQbEfIDbsYIC7Z/fyL8inqh3SV4EJQeIQEQWGw9CEj +jy3LKCHyamz0GqbFFLQ3ZU+V/YDI+HLlJWvEYLF7bY5KinPOWftwenMGE9nTdDckQQoRb5fc5+R+ +ob0V8rqHDz1oihYHAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0G +A1UdDgQWBBSowcCbkahDFXxdBie0KlHYlwuBsTAfBgNVHSMEGDAWgBSowcCbkahDFXxdBie0KlHY +lwuBsTANBgkqhkiG9w0BAQ0FAAOCAgEAnFZvAX7RvUz1isbwJh/k4DgYzDLDKTudQSk0YcbX8ACh +66Ryj5QXvBMsdbRX7gp8CXrc1cqh0DQT+Hern+X+2B50ioUHj3/MeXrKls3N/U/7/SMNkPX0XtPG +YX2eEeAC7gkE2Qfdpoq3DIMku4NQkv5gdRE+2J2winq14J2by5BSS7CTKtQ+FjPlnsZlFT5kOwQ/ +2wyPX1wdaR+v8+khjPPvl/aatxm2hHSco1S1cE5j2FddUyGbQJJD+tZ3VTNPZNX70Cxqjm0lpu+F +6ALEUz65noe8zDUa3qHpimOHZR4RKttjd5cUvpoUmRGywO6wT/gUITJDT5+rosuoD6o7BlXGEilX +CNQ314cnrUlZp5GrRHpejXDbl85IULFzk/bwg2D5zfHhMf1bfHEhYxQUqq/F3pN+aLHsIqKqkHWe +tUNy6mSjhEv9DKgma3GX7lZjZuhCVPnHHd/Qj1vfyDBviP4NxDMcU6ij/UgQ8uQKTuEVV/xuZDDC +VRHc6qnNSlSsKWNEz0pAoNZoWRsz+e86i9sgktxChL8Bq4fA1SCC28a5g4VCXA9DO2pJNdWY9BW/ ++mGBDAkgGNLQFwzLSABQ6XaCjGTXOqAHVcweMcDvOrRl++O/QmueD6i9a5jc2NvLi6Td11n0bt3+ +qsOR0C5CB8AMTVPNJLFMWx5R9N/pkvo= +-----END CERTIFICATE----- + +Certplus Root CA G2 +=================== +-----BEGIN CERTIFICATE----- +MIICHDCCAaKgAwIBAgISESDZkc6uo+jF5//pAq/Pc7xVMAoGCCqGSM49BAMDMD4xCzAJBgNVBAYT +AkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2VydHBsdXMgUm9vdCBDQSBHMjAeFw0x +NDA1MjYwMDAwMDBaFw0zODAxMTUwMDAwMDBaMD4xCzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0 +cGx1czEcMBoGA1UEAwwTQ2VydHBsdXMgUm9vdCBDQSBHMjB2MBAGByqGSM49AgEGBSuBBAAiA2IA +BM0PW1aC3/BFGtat93nwHcmsltaeTpwftEIRyoa/bfuFo8XlGVzX7qY/aWfYeOKmycTbLXku54uN +Am8xIk0G42ByRZ0OQneezs/lf4WbGOT8zC5y0xaTTsqZY1yhBSpsBqNjMGEwDgYDVR0PAQH/BAQD +AgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNqDYwJ5jtpMxjwjFNiPwyCrKGBZMB8GA1Ud +IwQYMBaAFNqDYwJ5jtpMxjwjFNiPwyCrKGBZMAoGCCqGSM49BAMDA2gAMGUCMHD+sAvZ94OX7PNV +HdTcswYO/jOYnYs5kGuUIe22113WTNchp+e/IQ8rzfcq3IUHnQIxAIYUFuXcsGXCwI4Un78kFmjl +vPl5adytRSv3tjFzzAalU5ORGpOucGpnutee5WEaXw== +-----END CERTIFICATE----- + +OpenTrust Root CA G1 +==================== +-----BEGIN CERTIFICATE----- +MIIFbzCCA1egAwIBAgISESCzkFU5fX82bWTCp59rY45nMA0GCSqGSIb3DQEBCwUAMEAxCzAJBgNV +BAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9wZW5UcnVzdCBSb290IENBIEcx +MB4XDTE0MDUyNjA4NDU1MFoXDTM4MDExNTAwMDAwMFowQDELMAkGA1UEBhMCRlIxEjAQBgNVBAoM +CU9wZW5UcnVzdDEdMBsGA1UEAwwUT3BlblRydXN0IFJvb3QgQ0EgRzEwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQD4eUbalsUwXopxAy1wpLuwxQjczeY1wICkES3d5oeuXT2R0odsN7fa +Yp6bwiTXj/HbpqbfRm9RpnHLPhsxZ2L3EVs0J9V5ToybWL0iEA1cJwzdMOWo010hOHQX/uMftk87 +ay3bfWAfjH1MBcLrARYVmBSO0ZB3Ij/swjm4eTrwSSTilZHcYTSSjFR077F9jAHiOH3BX2pfJLKO +YheteSCtqx234LSWSE9mQxAGFiQD4eCcjsZGT44ameGPuY4zbGneWK2gDqdkVBFpRGZPTBKnjix9 +xNRbxQA0MMHZmf4yzgeEtE7NCv82TWLxp2NX5Ntqp66/K7nJ5rInieV+mhxNaMbBGN4zK1FGSxyO +9z0M+Yo0FMT7MzUj8czxKselu7Cizv5Ta01BG2Yospb6p64KTrk5M0ScdMGTHPjgniQlQ/GbI4Kq +3ywgsNw2TgOzfALU5nsaqocTvz6hdLubDuHAk5/XpGbKuxs74zD0M1mKB3IDVedzagMxbm+WG+Oi +n6+Sx+31QrclTDsTBM8clq8cIqPQqwWyTBIjUtz9GVsnnB47ev1CI9sjgBPwvFEVVJSmdz7QdFG9 +URQIOTfLHzSpMJ1ShC5VkLG631UAC9hWLbFJSXKAqWLXwPYYEQRVzXR7z2FwefR7LFxckvzluFqr +TJOVoSfupb7PcSNCupt2LQIDAQABo2MwYTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB +/zAdBgNVHQ4EFgQUl0YhVyE12jZVx/PxN3DlCPaTKbYwHwYDVR0jBBgwFoAUl0YhVyE12jZVx/Px +N3DlCPaTKbYwDQYJKoZIhvcNAQELBQADggIBAB3dAmB84DWn5ph76kTOZ0BP8pNuZtQ5iSas000E +PLuHIT839HEl2ku6q5aCgZG27dmxpGWX4m9kWaSW7mDKHyP7Rbr/jyTwyqkxf3kfgLMtMrpkZ2Cv +uVnN35pJ06iCsfmYlIrM4LvgBBuZYLFGZdwIorJGnkSI6pN+VxbSFXJfLkur1J1juONI5f6ELlgK +n0Md/rcYkoZDSw6cMoYsYPXpSOqV7XAp8dUv/TW0V8/bhUiZucJvbI/NeJWsZCj9VrDDb8O+WVLh +X4SPgPL0DTatdrOjteFkdjpY3H1PXlZs5VVZV6Xf8YpmMIzUUmI4d7S+KNfKNsSbBfD4Fdvb8e80 +nR14SohWZ25g/4/Ii+GOvUKpMwpZQhISKvqxnUOOBZuZ2mKtVzazHbYNeS2WuOvyDEsMpZTGMKcm +GS3tTAZQMPH9WD25SxdfGbRqhFS0OE85og2WaMMolP3tLR9Ka0OWLpABEPs4poEL0L9109S5zvE/ +bw4cHjdx5RiHdRk/ULlepEU0rbDK5uUTdg8xFKmOLZTW1YVNcxVPS/KyPu1svf0OnWZzsD2097+o +4BGkxK51CUpjAEggpsadCwmKtODmzj7HPiY46SvepghJAwSQiumPv+i2tCqjI40cHLI5kqiPAlxA +OXXUc0ECd97N4EOH1uS6SsNsEn/+KuYj1oxx +-----END CERTIFICATE----- + +OpenTrust Root CA G2 +==================== +-----BEGIN CERTIFICATE----- +MIIFbzCCA1egAwIBAgISESChaRu/vbm9UpaPI+hIvyYRMA0GCSqGSIb3DQEBDQUAMEAxCzAJBgNV +BAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9wZW5UcnVzdCBSb290IENBIEcy +MB4XDTE0MDUyNjAwMDAwMFoXDTM4MDExNTAwMDAwMFowQDELMAkGA1UEBhMCRlIxEjAQBgNVBAoM +CU9wZW5UcnVzdDEdMBsGA1UEAwwUT3BlblRydXN0IFJvb3QgQ0EgRzIwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQDMtlelM5QQgTJT32F+D3Y5z1zCU3UdSXqWON2ic2rxb95eolq5cSG+ +Ntmh/LzubKh8NBpxGuga2F8ORAbtp+Dz0mEL4DKiltE48MLaARf85KxP6O6JHnSrT78eCbY2albz +4e6WiWYkBuTNQjpK3eCasMSCRbP+yatcfD7J6xcvDH1urqWPyKwlCm/61UWY0jUJ9gNDlP7ZvyCV +eYCYitmJNbtRG6Q3ffyZO6v/v6wNj0OxmXsWEH4db0fEFY8ElggGQgT4hNYdvJGmQr5J1WqIP7wt +UdGejeBSzFfdNTVY27SPJIjki9/ca1TSgSuyzpJLHB9G+h3Ykst2Z7UJmQnlrBcUVXDGPKBWCgOz +3GIZ38i1MH/1PCZ1Eb3XG7OHngevZXHloM8apwkQHZOJZlvoPGIytbU6bumFAYueQ4xncyhZW+vj +3CzMpSZyYhK05pyDRPZRpOLAeiRXyg6lPzq1O4vldu5w5pLeFlwoW5cZJ5L+epJUzpM5ChaHvGOz +9bGTXOBut9Dq+WIyiET7vycotjCVXRIouZW+j1MY5aIYFuJWpLIsEPUdN6b4t/bQWVyJ98LVtZR0 +0dX+G7bw5tYee9I8y6jj9RjzIR9u701oBnstXW5DiabA+aC/gh7PU3+06yzbXfZqfUAkBXKJOAGT +y3HCOV0GEfZvePg3DTmEJwIDAQABo2MwYTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB +/zAdBgNVHQ4EFgQUajn6QiL35okATV59M4PLuG53hq8wHwYDVR0jBBgwFoAUajn6QiL35okATV59 +M4PLuG53hq8wDQYJKoZIhvcNAQENBQADggIBAJjLq0A85TMCl38th6aP1F5Kr7ge57tx+4BkJamz +Gj5oXScmp7oq4fBXgwpkTx4idBvpkF/wrM//T2h6OKQQbA2xx6R3gBi2oihEdqc0nXGEL8pZ0keI +mUEiyTCYYW49qKgFbdEfwFFEVn8nNQLdXpgKQuswv42hm1GqO+qTRmTFAHneIWv2V6CG1wZy7HBG +S4tz3aAhdT7cHcCP009zHIXZ/n9iyJVvttN7jLpTwm+bREx50B1ws9efAvSyB7DH5fitIw6mVskp +EndI2S9G/Tvw/HRwkqWOOAgfZDC2t0v7NqwQjqBSM2OdAzVWxWm9xiNaJ5T2pBL4LTM8oValX9YZ +6e18CL13zSdkzJTaTkZQh+D5wVOAHrut+0dSixv9ovneDiK3PTNZbNTe9ZUGMg1RGUFcPk8G97kr +gCf2o6p6fAbhQ8MTOWIaNr3gKC6UAuQpLmBVrkA9sHSSXvAgZJY/X0VdiLWK2gKgW0VU3jg9CcCo +SmVGFvyqv1ROTVu+OEO3KMqLM6oaJbolXCkvW0pujOotnCr2BXbgd5eAiN1nE28daCSLT7d0geX0 +YJ96Vdc+N9oWaz53rK4YcJUIeSkDiv7BO7M/Gg+kO14fWKGVyasvc0rQLW6aWQ9VGHgtPFGml4vm +u7JwqkwR3v98KzfUetF3NI/n+UL3PIEMS1IK +-----END CERTIFICATE----- + +OpenTrust Root CA G3 +==================== +-----BEGIN CERTIFICATE----- +MIICITCCAaagAwIBAgISESDm+Ez8JLC+BUCs2oMbNGA/MAoGCCqGSM49BAMDMEAxCzAJBgNVBAYT +AkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9wZW5UcnVzdCBSb290IENBIEczMB4X +DTE0MDUyNjAwMDAwMFoXDTM4MDExNTAwMDAwMFowQDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCU9w +ZW5UcnVzdDEdMBsGA1UEAwwUT3BlblRydXN0IFJvb3QgQ0EgRzMwdjAQBgcqhkjOPQIBBgUrgQQA +IgNiAARK7liuTcpm3gY6oxH84Bjwbhy6LTAMidnW7ptzg6kjFYwvWYpa3RTqnVkrQ7cG7DK2uu5B +ta1doYXM6h0UZqNnfkbilPPntlahFVmhTzeXuSIevRHr9LIfXsMUmuXZl5mjYzBhMA4GA1UdDwEB +/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRHd8MUi2I5DMlv4VBN0BBY3JWIbTAf +BgNVHSMEGDAWgBRHd8MUi2I5DMlv4VBN0BBY3JWIbTAKBggqhkjOPQQDAwNpADBmAjEAj6jcnboM +BBf6Fek9LykBl7+BFjNAk2z8+e2AcG+qj9uEwov1NcoG3GRvaBbhj5G5AjEA2Euly8LQCGzpGPta +3U1fJAuwACEl74+nBCZx4nxp5V2a+EEfOzmTk51V6s2N8fvB +-----END CERTIFICATE----- + +ISRG Root X1 +============ +-----BEGIN CERTIFICATE----- +MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAwTzELMAkGA1UE +BhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2VhcmNoIEdyb3VwMRUwEwYDVQQD +EwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQG +EwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMT +DElTUkcgUm9vdCBYMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54r +Vygch77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+0TM8ukj1 +3Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6UA5/TR5d8mUgjU+g4rk8K +b4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sWT8KOEUt+zwvo/7V3LvSye0rgTBIlDHCN +Aymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyHB5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ +4Q7e2RCOFvu396j3x+UCB5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf +1b0SHzUvKBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWnOlFu +hjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTnjh8BCNAw1FtxNrQH +usEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbwqHyGO0aoSCqI3Haadr8faqU9GY/r +OPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CIrU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4G +A1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY +9umbbjANBgkqhkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL +ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ3BebYhtF8GaV +0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KKNFtY2PwByVS5uCbMiogziUwt +hDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJw +TdwJx4nLCgdNbOhdjsnvzqvHu7UrTkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nx +e5AW0wdeRlN8NwdCjNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZA +JzVcoyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq4RgqsahD +YVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPAmRGunUHBcnWEvgJBQl9n +JEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57demyPxgcYxn/eR44/KJ4EBs+lVDR3veyJ +m+kXQ99b21/+jh5Xos1AnX5iItreGCc= +-----END CERTIFICATE----- + +AC RAIZ FNMT-RCM +================ +-----BEGIN CERTIFICATE----- +MIIFgzCCA2ugAwIBAgIPXZONMGc2yAYdGsdUhGkHMA0GCSqGSIb3DQEBCwUAMDsxCzAJBgNVBAYT +AkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTTAeFw0wODEw +MjkxNTU5NTZaFw0zMDAxMDEwMDAwMDBaMDsxCzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJD +TTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC +ggIBALpxgHpMhm5/yBNtwMZ9HACXjywMI7sQmkCpGreHiPibVmr75nuOi5KOpyVdWRHbNi63URcf +qQgfBBckWKo3Shjf5TnUV/3XwSyRAZHiItQDwFj8d0fsjz50Q7qsNI1NOHZnjrDIbzAzWHFctPVr +btQBULgTfmxKo0nRIBnuvMApGGWn3v7v3QqQIecaZ5JCEJhfTzC8PhxFtBDXaEAUwED653cXeuYL +j2VbPNmaUtu1vZ5Gzz3rkQUCwJaydkxNEJY7kvqcfw+Z374jNUUeAlz+taibmSXaXvMiwzn15Cou +08YfxGyqxRxqAQVKL9LFwag0Jl1mpdICIfkYtwb1TplvqKtMUejPUBjFd8g5CSxJkjKZqLsXF3mw +WsXmo8RZZUc1g16p6DULmbvkzSDGm0oGObVo/CK67lWMK07q87Hj/LaZmtVC+nFNCM+HHmpxffnT +tOmlcYF7wk5HlqX2doWjKI/pgG6BU6VtX7hI+cL5NqYuSf+4lsKMB7ObiFj86xsc3i1w4peSMKGJ +47xVqCfWS+2QrYv6YyVZLag13cqXM7zlzced0ezvXg5KkAYmY6252TUtB7p2ZSysV4999AeU14EC +ll2jB0nVetBX+RvnU0Z1qrB5QstocQjpYL05ac70r8NWQMetUqIJ5G+GR4of6ygnXYMgrwTJbFaa +i0b1AgMBAAGjgYMwgYAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE +FPd9xf3E6Jobd2Sn9R2gzL+HYJptMD4GA1UdIAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1o +dHRwOi8vd3d3LmNlcnQuZm5tdC5lcy9kcGNzLzANBgkqhkiG9w0BAQsFAAOCAgEAB5BK3/MjTvDD +nFFlm5wioooMhfNzKWtN/gHiqQxjAb8EZ6WdmF/9ARP67Jpi6Yb+tmLSbkyU+8B1RXxlDPiyN8+s +D8+Nb/kZ94/sHvJwnvDKuO+3/3Y3dlv2bojzr2IyIpMNOmqOFGYMLVN0V2Ue1bLdI4E7pWYjJ2cJ +j+F3qkPNZVEI7VFY/uY5+ctHhKQV8Xa7pO6kO8Rf77IzlhEYt8llvhjho6Tc+hj507wTmzl6NLrT +Qfv6MooqtyuGC2mDOL7Nii4LcK2NJpLuHvUBKwrZ1pebbuCoGRw6IYsMHkCtA+fdZn71uSANA+iW ++YJF1DngoABd15jmfZ5nc8OaKveri6E6FO80vFIOiZiaBECEHX5FaZNXzuvO+FB8TxxuBEOb+dY7 +Ixjp6o7RTUaN8Tvkasq6+yO3m/qZASlaWFot4/nUbQ4mrcFuNLwy+AwF+mWj2zs3gyLp1txyM/1d +8iC9djwj2ij3+RvrWWTV3F9yfiD8zYm1kGdNYno/Tq0dwzn+evQoFt9B9kiABdcPUXmsEKvU7ANm +5mqwujGSQkBqvjrTcuFqN1W8rB2Vt2lh8kORdOag0wokRqEIr9baRRmW1FMdW4R58MD3R++Lj8UG +rp1MYp3/RgT408m2ECVAdf4WqslKYIYvuu8wd+RU4riEmViAqhOLUTpPSPaLtrM= +-----END CERTIFICATE----- + +Amazon Root CA 1 +================ +-----BEGIN CERTIFICATE----- +MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsFADA5MQswCQYD +VQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAxMB4XDTE1 +MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpv +bjEZMBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBALJ4gHHKeNXjca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgH +FzZM9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qwIFAGbHrQ +gLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6VOujw5H5SNz/0egwLX0t +dHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L93FcXmn/6pUCyziKrlA4b9v7LWIbxcce +VOF34GfID5yHI9Y/QCB/IIDEgEw+OyQmjgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB +/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3 +DQEBCwUAA4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDIU5PM +CCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUsN+gDS63pYaACbvXy +8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vvo/ufQJVtMVT8QtPHRh8jrdkPSHCa +2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2 +xJNDd2ZhwLnoQdeXeGADbkpyrqXRfboQnoZsG4q5WTP468SQvvG5 +-----END CERTIFICATE----- + +Amazon Root CA 2 +================ +-----BEGIN CERTIFICATE----- +MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwFADA5MQswCQYD +VQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAyMB4XDTE1 +MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpv +bjEZMBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC +ggIBAK2Wny2cSkxKgXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4 +kHbZW0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg1dKmSYXp +N+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K8nu+NQWpEjTj82R0Yiw9 +AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvd +fLC6HM783k81ds8P+HgfajZRRidhW+mez/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAEx +kv8LV/SasrlX6avvDXbR8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSS +btqDT6ZjmUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz7Mt0 +Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6+XUyo05f7O0oYtlN +c/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI0u1ufm8/0i2BWSlmy5A5lREedCf+ +3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSw +DPBMMPQFWAJI/TPlUq9LhONmUjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oA +A7CXDpO8Wqj2LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY ++gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kSk5Nrp+gvU5LE +YFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl7uxMMne0nxrpS10gxdr9HIcW +xkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygmbtmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQ +gj9sAq+uEjonljYE1x2igGOpm/HlurR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbW +aQbLU8uz/mtBzUF+fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoV +Yh63n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE76KlXIx3 +KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H9jVlpNMKVv/1F2Rs76gi +JUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT4PsJYGw= +-----END CERTIFICATE----- + +Amazon Root CA 3 +================ +-----BEGIN CERTIFICATE----- +MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5MQswCQYDVQQG +EwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAzMB4XDTE1MDUy +NjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZ +MBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZB +f8ANm+gBG1bG8lKlui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjr +Zt6jQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSrttvXBp43 +rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkrBqWTrBqYaGFy+uGh0Psc +eGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteMYyRIHN8wfdVoOw== +-----END CERTIFICATE----- + +Amazon Root CA 4 +================ +-----BEGIN CERTIFICATE----- +MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5MQswCQYDVQQG +EwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSA0MB4XDTE1MDUy +NjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZ +MBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN +/sGKe0uoe0ZLY7Bi9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri +83BkM6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV +HQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WBMAoGCCqGSM49BAMDA2gA +MGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlwCkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1 +AE47xDqUEpHJWEadIRNyp4iciuRMStuW1KyLa2tJElMzrdfkviT8tQp21KW8EA== +-----END CERTIFICATE----- + +LuxTrust Global Root 2 +====================== +-----BEGIN CERTIFICATE----- +MIIFwzCCA6ugAwIBAgIUCn6m30tEntpqJIWe5rgV0xZ/u7EwDQYJKoZIhvcNAQELBQAwRjELMAkG +A1UEBhMCTFUxFjAUBgNVBAoMDUx1eFRydXN0IFMuQS4xHzAdBgNVBAMMFkx1eFRydXN0IEdsb2Jh +bCBSb290IDIwHhcNMTUwMzA1MTMyMTU3WhcNMzUwMzA1MTMyMTU3WjBGMQswCQYDVQQGEwJMVTEW +MBQGA1UECgwNTHV4VHJ1c3QgUy5BLjEfMB0GA1UEAwwWTHV4VHJ1c3QgR2xvYmFsIFJvb3QgMjCC +AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANeFl78RmOnwYoNMPIf5U2o3C/IPPIfOb9wm +Kb3FibrJgz337spbxm1Jc7TJRqMbNBM/wYlFV/TZsfs2ZUv7COJIcRHIbjuend+JZTemhfY7RBi2 +xjcwYkSSl2l9QjAk5A0MiWtj3sXh306pFGxT4GHO9hcvHTy95iJMHZP1EMShduxq3sVs35a0VkBC +wGKSMKEtFZSg0iAGCW5qbeXrt77U8PEVfIvmTroTzEsnXpk8F12PgX8zPU/TPxvsXD/wPEx1bvKm +1Z3aLQdjAsZy6ZS8TEmVT4hSyNvoaYL4zDRbIvCGp4m9SAptZoFtyMhk+wHh9OHe2Z7d21vUKpkm +FRseTJIpgp7VkoGSQXAZ96Tlk0u8d2cx3Rz9MXANF5kM+Qw5GSoXtTBxVdUPrljhPS80m8+f9niF +wpN6cj5mj5wWEWCPnolvZ77gR1o7DJpni89Gxq44o/KnvObWhWszJHAiS8sIm7vI+AIpHb4gDEa/ +a4ebsypmQjVGbKq6rfmYe+lQVRQxv7HaLe2ArWgk+2mr2HETMOZns4dA/Yl+8kPREd8vZS9kzl8U +ubG/Mb2HeFpZZYiq/FkySIbWTLkpS5XTdvN3JW1CHDiDTf2jX5t/Lax5Gw5CMZdjpPuKadUiDTSQ +MC6otOBttpSsvItO13D8xTiOZCXhTTmQzsmHhFhxAgMBAAGjgagwgaUwDwYDVR0TAQH/BAUwAwEB +/zBCBgNVHSAEOzA5MDcGByuBKwEBAQowLDAqBggrBgEFBQcCARYeaHR0cHM6Ly9yZXBvc2l0b3J5 +Lmx1eHRydXN0Lmx1MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBT/GCh2+UgFLKGu8SsbK7JT ++Et8szAdBgNVHQ4EFgQU/xgodvlIBSyhrvErGyuyU/hLfLMwDQYJKoZIhvcNAQELBQADggIBAGoZ +FO1uecEsh9QNcH7X9njJCwROxLHOk3D+sFTAMs2ZMGQXvw/l4jP9BzZAcg4atmpZ1gDlaCDdLnIN +H2pkMSCEfUmmWjfrRcmF9dTHF5kH5ptV5AzoqbTOjFu1EVzPig4N1qx3gf4ynCSecs5U89BvolbW +7MM3LGVYvlcAGvI1+ut7MV3CwRI9loGIlonBWVx65n9wNOeD4rHh4bhY79SV5GCc8JaXcozrhAIu +ZY+kt9J/Z93I055cqqmkoCUUBpvsT34tC38ddfEz2O3OuHVtPlu5mB0xDVbYQw8wkbIEa91WvpWA +VWe+2M2D2RjuLg+GLZKecBPs3lHJQ3gCpU3I+V/EkVhGFndadKpAvAefMLmx9xIX3eP/JEAdemrR +TxgKqpAd60Ae36EeRJIQmvKN4dFLRp7oRUKX6kWZ8+xm1QL68qZKJKrezrnK+T+Tb/mjuuqlPpmt +/f97mfVl7vBZKGfXkJWkE4SphMHozs51k2MavDzq1WQfLSoSOcbDWjLtR5EWDrw4wVDej8oqkDQc +7kGUnF4ZLvhFSZl0kbAEb+MEWrGrKqv+x9CWttrhSmQGbmBNvUJO/3jaJMobtNeWOWyu8Q6qp31I +iyBMz2TWuJdGsE7RKlY6oJO9r4Ak4Ap+58rVyuiFVdw2KuGUaJPHZnJED4AhMmwlxyOAgwrr +-----END CERTIFICATE----- + +TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1 +============================================= +-----BEGIN CERTIFICATE----- +MIIEYzCCA0ugAwIBAgIBATANBgkqhkiG9w0BAQsFADCB0jELMAkGA1UEBhMCVFIxGDAWBgNVBAcT +D0dlYnplIC0gS29jYWVsaTFCMEAGA1UEChM5VHVya2l5ZSBCaWxpbXNlbCB2ZSBUZWtub2xvamlr +IEFyYXN0aXJtYSBLdXJ1bXUgLSBUVUJJVEFLMS0wKwYDVQQLEyRLYW11IFNlcnRpZmlrYXN5b24g +TWVya2V6aSAtIEthbXUgU00xNjA0BgNVBAMTLVRVQklUQUsgS2FtdSBTTSBTU0wgS29rIFNlcnRp +ZmlrYXNpIC0gU3VydW0gMTAeFw0xMzExMjUwODI1NTVaFw00MzEwMjUwODI1NTVaMIHSMQswCQYD +VQQGEwJUUjEYMBYGA1UEBxMPR2ViemUgLSBLb2NhZWxpMUIwQAYDVQQKEzlUdXJraXllIEJpbGlt +c2VsIHZlIFRla25vbG9qaWsgQXJhc3Rpcm1hIEt1cnVtdSAtIFRVQklUQUsxLTArBgNVBAsTJEth +bXUgU2VydGlmaWthc3lvbiBNZXJrZXppIC0gS2FtdSBTTTE2MDQGA1UEAxMtVFVCSVRBSyBLYW11 +IFNNIFNTTCBLb2sgU2VydGlmaWthc2kgLSBTdXJ1bSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAr3UwM6q7a9OZLBI3hNmNe5eA027n/5tQlT6QlVZC1xl8JoSNkvoBHToP4mQ4t4y8 +6Ij5iySrLqP1N+RAjhgleYN1Hzv/bKjFxlb4tO2KRKOrbEz8HdDc72i9z+SqzvBV96I01INrN3wc +wv61A+xXzry0tcXtAA9TNypN9E8Mg/uGz8v+jE69h/mniyFXnHrfA2eJLJ2XYacQuFWQfw4tJzh0 +3+f92k4S400VIgLI4OD8D62K18lUUMw7D8oWgITQUVbDjlZ/iSIzL+aFCr2lqBs23tPcLG07xxO9 +WSMs5uWk99gL7eqQQESolbuT1dCANLZGeA4fAJNG4e7p+exPFwIDAQABo0IwQDAdBgNVHQ4EFgQU +ZT/HiobGPN08VFw1+DrtUgxHV8gwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJ +KoZIhvcNAQELBQADggEBACo/4fEyjq7hmFxLXs9rHmoJ0iKpEsdeV31zVmSAhHqT5Am5EM2fKifh +AHe+SMg1qIGf5LgsyX8OsNJLN13qudULXjS99HMpw+0mFZx+CFOKWI3QSyjfwbPfIPP54+M638yc +lNhOT8NrF7f3cuitZjO1JVOr4PhMqZ398g26rrnZqsZr+ZO7rqu4lzwDGrpDxpa5RXI4s6ehlj2R +e37AIVNMh+3yC1SVUZPVIqUNivGTDj5UDrDYyU7c8jEyVupk+eq1nRZmQnLzf9OxMUP8pI4X8W0j +q5Rm+K37DwhuJi1/FwcJsoz7UMCflo3Ptv0AnVoUmr8CRPXBwp8iXqIPoeM= -----END CERTIFICATE----- diff --git a/htdocs/includes/stripe/init.php b/htdocs/includes/stripe/init.php index 3e7f93e4e85..79cf657a7eb 100644 --- a/htdocs/includes/stripe/init.php +++ b/htdocs/includes/stripe/init.php @@ -5,6 +5,9 @@ require(dirname(__FILE__) . '/lib/Stripe.php'); // Utilities require(dirname(__FILE__) . '/lib/Util/AutoPagingIterator.php'); +require(dirname(__FILE__) . '/lib/Util/LoggerInterface.php'); +require(dirname(__FILE__) . '/lib/Util/DefaultLogger.php'); +require(dirname(__FILE__) . '/lib/Util/RandomGenerator.php'); require(dirname(__FILE__) . '/lib/Util/RequestOptions.php'); require(dirname(__FILE__) . '/lib/Util/Set.php'); require(dirname(__FILE__) . '/lib/Util/Util.php'); @@ -19,19 +22,36 @@ require(dirname(__FILE__) . '/lib/Error/Api.php'); require(dirname(__FILE__) . '/lib/Error/ApiConnection.php'); require(dirname(__FILE__) . '/lib/Error/Authentication.php'); require(dirname(__FILE__) . '/lib/Error/Card.php'); +require(dirname(__FILE__) . '/lib/Error/Idempotency.php'); require(dirname(__FILE__) . '/lib/Error/InvalidRequest.php'); require(dirname(__FILE__) . '/lib/Error/Permission.php'); require(dirname(__FILE__) . '/lib/Error/RateLimit.php'); +require(dirname(__FILE__) . '/lib/Error/SignatureVerification.php'); + +// OAuth errors +require(dirname(__FILE__) . '/lib/Error/OAuth/OAuthBase.php'); +require(dirname(__FILE__) . '/lib/Error/OAuth/InvalidClient.php'); +require(dirname(__FILE__) . '/lib/Error/OAuth/InvalidGrant.php'); +require(dirname(__FILE__) . '/lib/Error/OAuth/InvalidRequest.php'); +require(dirname(__FILE__) . '/lib/Error/OAuth/InvalidScope.php'); +require(dirname(__FILE__) . '/lib/Error/OAuth/UnsupportedGrantType.php'); +require(dirname(__FILE__) . '/lib/Error/OAuth/UnsupportedResponseType.php'); + +// API operations +require(dirname(__FILE__) . '/lib/ApiOperations/All.php'); +require(dirname(__FILE__) . '/lib/ApiOperations/Create.php'); +require(dirname(__FILE__) . '/lib/ApiOperations/Delete.php'); +require(dirname(__FILE__) . '/lib/ApiOperations/NestedResource.php'); +require(dirname(__FILE__) . '/lib/ApiOperations/Request.php'); +require(dirname(__FILE__) . '/lib/ApiOperations/Retrieve.php'); +require(dirname(__FILE__) . '/lib/ApiOperations/Update.php'); // Plumbing require(dirname(__FILE__) . '/lib/ApiResponse.php'); -require(dirname(__FILE__) . '/lib/JsonSerializable.php'); require(dirname(__FILE__) . '/lib/StripeObject.php'); require(dirname(__FILE__) . '/lib/ApiRequestor.php'); require(dirname(__FILE__) . '/lib/ApiResource.php'); require(dirname(__FILE__) . '/lib/SingletonApiResource.php'); -require(dirname(__FILE__) . '/lib/AttachedObject.php'); -require(dirname(__FILE__) . '/lib/ExternalAccount.php'); // Stripe API Resources require(dirname(__FILE__) . '/lib/Account.php'); @@ -51,10 +71,13 @@ require(dirname(__FILE__) . '/lib/CountrySpec.php'); require(dirname(__FILE__) . '/lib/Coupon.php'); require(dirname(__FILE__) . '/lib/Customer.php'); require(dirname(__FILE__) . '/lib/Dispute.php'); +require(dirname(__FILE__) . '/lib/EphemeralKey.php'); require(dirname(__FILE__) . '/lib/Event.php'); +require(dirname(__FILE__) . '/lib/ExchangeRate.php'); require(dirname(__FILE__) . '/lib/FileUpload.php'); require(dirname(__FILE__) . '/lib/Invoice.php'); require(dirname(__FILE__) . '/lib/InvoiceItem.php'); +require(dirname(__FILE__) . '/lib/LoginLink.php'); require(dirname(__FILE__) . '/lib/Order.php'); require(dirname(__FILE__) . '/lib/OrderReturn.php'); require(dirname(__FILE__) . '/lib/Payout.php'); @@ -65,9 +88,18 @@ require(dirname(__FILE__) . '/lib/RecipientTransfer.php'); require(dirname(__FILE__) . '/lib/Refund.php'); require(dirname(__FILE__) . '/lib/SKU.php'); require(dirname(__FILE__) . '/lib/Source.php'); +require(dirname(__FILE__) . '/lib/SourceTransaction.php'); require(dirname(__FILE__) . '/lib/Subscription.php'); require(dirname(__FILE__) . '/lib/SubscriptionItem.php'); require(dirname(__FILE__) . '/lib/ThreeDSecure.php'); require(dirname(__FILE__) . '/lib/Token.php'); +require(dirname(__FILE__) . '/lib/Topup.php'); require(dirname(__FILE__) . '/lib/Transfer.php'); require(dirname(__FILE__) . '/lib/TransferReversal.php'); + +// OAuth +require(dirname(__FILE__) . '/lib/OAuth.php'); + +// Webhooks +require(dirname(__FILE__) . '/lib/Webhook.php'); +require(dirname(__FILE__) . '/lib/WebhookSignature.php'); diff --git a/htdocs/includes/stripe/lib/Account.php b/htdocs/includes/stripe/lib/Account.php index 3899b8233a6..d77d60dedbc 100644 --- a/htdocs/includes/stripe/lib/Account.php +++ b/htdocs/includes/stripe/lib/Account.php @@ -7,11 +7,13 @@ namespace Stripe; * * @property string $id * @property string $object - * @property mixed $business_logo + * @property string $business_logo * @property string $business_name - * @property mixed $business_url + * @property string $business_primary_color + * @property string $business_url * @property bool $charges_enabled * @property string $country + * @property int $created * @property bool $debit_negative_balances * @property mixed $decline_charge_on * @property string $default_currency @@ -20,23 +22,46 @@ namespace Stripe; * @property string $email * @property mixed $external_accounts * @property mixed $legal_entity - * @property bool $managed + * @property StripeObject $metadata * @property mixed $payout_schedule - * @property mixed $payout_statement_descriptor + * @property string $payout_statement_descriptor * @property bool $payouts_enabled - * @property mixed $product_description - * @property mixed $statement_descriptor - * @property mixed $support_email - * @property mixed $support_phone + * @property string $product_description + * @property string $statement_descriptor + * @property string $support_email + * @property string $support_phone * @property string $timezone * @property mixed $tos_acceptance * @property mixed $verification - * @property mixed $keys * * @package Stripe */ class Account extends ApiResource { + use ApiOperations\All; + use ApiOperations\Create; + use ApiOperations\Delete; + use ApiOperations\NestedResource; + use ApiOperations\Retrieve { + retrieve as protected _retrieve; + } + use ApiOperations\Update; + + public static function getSavedNestedResources() + { + static $savedNestedResources = null; + if ($savedNestedResources === null) { + $savedNestedResources = new Util\Set([ + 'external_account', + 'bank_account', + ]); + } + return $savedNestedResources; + } + + const PATH_EXTERNAL_ACCOUNTS = '/external_accounts'; + const PATH_LOGIN_LINKS = '/login_links'; + public function instanceUrl() { if ($this['id'] === null) { @@ -47,7 +72,8 @@ class Account extends ApiResource } /** - * @param string|null $id + * @param array|string|null $id The ID of the account to retrieve, or an + * options array containing an `id` key. * @param array|string|null $opts * * @return Account @@ -61,50 +87,6 @@ class Account extends ApiResource return self::_retrieve($id, $opts); } - /** - * @param array|null $params - * @param array|string|null $opts - * - * @return Account - */ - public static function create($params = null, $opts = null) - { - return self::_create($params, $opts); - } - - /** - * @param string $id The ID of the account to update. - * @param array|null $params - * @param array|string|null $options - * - * @return Account The updated account. - */ - public static function update($id, $params = null, $options = null) - { - return self::_update($id, $params, $options); - } - - /** - * @param array|string|null $opts - * - * @return Account - */ - public function save($opts = null) - { - return $this->_save($opts); - } - - /** - * @param array|null $params - * @param array|string|null $opts - * - * @return Account The deleted account. - */ - public function delete($params = null, $opts = null) - { - return $this->_delete($params, $opts); - } - /** * @param array|null $params * @param array|string|null $opts @@ -120,13 +102,133 @@ class Account extends ApiResource } /** + * @param array|null $clientId + * @param array|string|null $opts + * + * @return StripeObject Object containing the response from the API. + */ + public function deauthorize($clientId = null, $opts = null) + { + $params = [ + 'client_id' => $clientId, + 'stripe_user_id' => $this->id, + ]; + OAuth::deauthorize($params, $opts); + } + + /** + * @param array|null $id The ID of the account on which to create the external account. * @param array|null $params * @param array|string|null $opts * - * @return Collection of Accounts + * @return BankAccount|Card */ - public static function all($params = null, $opts = null) + public static function createExternalAccount($id, $params = null, $opts = null) { - return self::_all($params, $opts); + return self::_createNestedResource($id, static::PATH_EXTERNAL_ACCOUNTS, $params, $opts); + } + + /** + * @param array|null $id The ID of the account to which the external account belongs. + * @param array|null $externalAccountId The ID of the external account to retrieve. + * @param array|null $params + * @param array|string|null $opts + * + * @return BankAccount|Card + */ + public static function retrieveExternalAccount($id, $externalAccountId, $params = null, $opts = null) + { + return self::_retrieveNestedResource($id, static::PATH_EXTERNAL_ACCOUNTS, $externalAccountId, $params, $opts); + } + + /** + * @param array|null $id The ID of the account to which the external account belongs. + * @param array|null $externalAccountId The ID of the external account to update. + * @param array|null $params + * @param array|string|null $opts + * + * @return BankAccount|Card + */ + public static function updateExternalAccount($id, $externalAccountId, $params = null, $opts = null) + { + return self::_updateNestedResource($id, static::PATH_EXTERNAL_ACCOUNTS, $externalAccountId, $params, $opts); + } + + /** + * @param array|null $id The ID of the account to which the external account belongs. + * @param array|null $externalAccountId The ID of the external account to delete. + * @param array|null $params + * @param array|string|null $opts + * + * @return BankAccount|Card + */ + public static function deleteExternalAccount($id, $externalAccountId, $params = null, $opts = null) + { + return self::_deleteNestedResource($id, static::PATH_EXTERNAL_ACCOUNTS, $externalAccountId, $params, $opts); + } + + /** + * @param array|null $id The ID of the account on which to retrieve the external accounts. + * @param array|null $params + * @param array|string|null $opts + * + * @return BankAccount|Card + */ + public static function allExternalAccounts($id, $params = null, $opts = null) + { + return self::_allNestedResources($id, static::PATH_EXTERNAL_ACCOUNTS, $params, $opts); + } + + /** + * @param array|null $id The ID of the account on which to create the login link. + * @param array|null $params + * @param array|string|null $opts + * + * @return LoginLink + */ + public static function createLoginLink($id, $params = null, $opts = null) + { + return self::_createNestedResource($id, static::PATH_LOGIN_LINKS, $params, $opts); + } + + public function serializeParameters($force = false) + { + $update = parent::serializeParameters($force); + if (isset($this->_values['legal_entity'])) { + $entity = $this['legal_entity']; + if (isset($entity->_values['additional_owners'])) { + $owners = $entity['additional_owners']; + $entityUpdate = isset($update['legal_entity']) ? $update['legal_entity'] : []; + $entityUpdate['additional_owners'] = $this->serializeAdditionalOwners($entity, $owners); + $update['legal_entity'] = $entityUpdate; + } + } + return $update; + } + + private function serializeAdditionalOwners($legalEntity, $additionalOwners) + { + if (isset($legalEntity->_originalValues['additional_owners'])) { + $originalValue = $legalEntity->_originalValues['additional_owners']; + } else { + $originalValue = []; + } + if (($originalValue) && (count($originalValue) > count($additionalOwners))) { + throw new \InvalidArgumentException( + "You cannot delete an item from an array, you must instead set a new array" + ); + } + + $updateArr = []; + foreach ($additionalOwners as $i => $v) { + $update = ($v instanceof StripeObject) ? $v->serializeParameters() : $v; + + if ($update !== []) { + if (!$originalValue || ($update != $legalEntity->serializeParamsValue($originalValue[$i], null, false, true))) { + $updateArr[$i] = $update; + } + } + } + return $updateArr; } } diff --git a/htdocs/includes/stripe/lib/AlipayAccount.php b/htdocs/includes/stripe/lib/AlipayAccount.php index 1ba34bfa646..fb7d5bb791e 100644 --- a/htdocs/includes/stripe/lib/AlipayAccount.php +++ b/htdocs/includes/stripe/lib/AlipayAccount.php @@ -6,8 +6,64 @@ namespace Stripe; * Class AlipayAccount * * @package Stripe + * + * @deprecated Alipay accounts are deprecated. Please use the sources API instead. + * @link https://stripe.com/docs/sources/alipay */ -class AlipayAccount extends ExternalAccount +class AlipayAccount extends ApiResource { + use ApiOperations\Delete; + use ApiOperations\Update; + /** + * @return string The instance URL for this resource. It needs to be special + * cased because it doesn't fit into the standard resource pattern. + */ + public function instanceUrl() + { + if ($this['customer']) { + $base = Customer::classUrl(); + $parent = $this['customer']; + $path = 'sources'; + } else { + $msg = "Alipay accounts cannot be accessed without a customer ID."; + throw new Error\InvalidRequest($msg, null); + } + $parentExtn = urlencode(Util\Util::utf8($parent)); + $extn = urlencode(Util\Util::utf8($this['id'])); + return "$base/$parentExtn/$path/$extn"; + } + + /** + * @param array|string $_id + * @param array|string|null $_opts + * + * @throws \Stripe\Error\InvalidRequest + * + * @deprecated Alipay accounts are deprecated. Please use the sources API instead. + * @link https://stripe.com/docs/sources/alipay + */ + public static function retrieve($_id, $_opts = null) + { + $msg = "Alipay accounts cannot be accessed without a customer ID. " . + "Retrieve an Alipay account using \$customer->sources->retrieve('alipay_account_id') instead."; + throw new Error\InvalidRequest($msg, null); + } + + /** + * @param string $_id + * @param array|null $_params + * @param array|string|null $_options + * + * @throws \Stripe\Error\InvalidRequest + * + * @deprecated Alipay accounts are deprecated. Please use the sources API instead. + * @link https://stripe.com/docs/sources/alipay + */ + public static function update($_id, $_params = null, $_options = null) + { + $msg = "Alipay accounts cannot be accessed without a customer ID. " . + "Call save() on \$customer->sources->retrieve('alipay_account_id') instead."; + throw new Error\InvalidRequest($msg, null); + } } diff --git a/htdocs/includes/stripe/lib/ApiOperations/All.php b/htdocs/includes/stripe/lib/ApiOperations/All.php new file mode 100644 index 00000000000..d1c6424816f --- /dev/null +++ b/htdocs/includes/stripe/lib/ApiOperations/All.php @@ -0,0 +1,34 @@ +json, $opts); + if (!is_a($obj, 'Stripe\\Collection')) { + $class = get_class($obj); + $message = "Expected type \"Stripe\\Collection\", got \"$class\" instead"; + throw new Error\Api($message); + } + $obj->setLastResponse($response); + $obj->setRequestParams($params); + return $obj; + } +} diff --git a/htdocs/includes/stripe/lib/ApiOperations/Create.php b/htdocs/includes/stripe/lib/ApiOperations/Create.php new file mode 100644 index 00000000000..0fb341d029b --- /dev/null +++ b/htdocs/includes/stripe/lib/ApiOperations/Create.php @@ -0,0 +1,28 @@ +json, $opts); + $obj->setLastResponse($response); + return $obj; + } +} diff --git a/htdocs/includes/stripe/lib/ApiOperations/Delete.php b/htdocs/includes/stripe/lib/ApiOperations/Delete.php new file mode 100644 index 00000000000..7df6797919a --- /dev/null +++ b/htdocs/includes/stripe/lib/ApiOperations/Delete.php @@ -0,0 +1,27 @@ +instanceUrl(); + list($response, $opts) = $this->_request('delete', $url, $params, $opts); + $this->refreshFrom($response, $opts); + return $this; + } +} diff --git a/htdocs/includes/stripe/lib/ApiOperations/NestedResource.php b/htdocs/includes/stripe/lib/ApiOperations/NestedResource.php new file mode 100644 index 00000000000..1c3a73f45de --- /dev/null +++ b/htdocs/includes/stripe/lib/ApiOperations/NestedResource.php @@ -0,0 +1,115 @@ +json, $opts); + $obj->setLastResponse($response); + return $obj; + } + + /** + * @param string $id + * @param string $nestedPath + * @param string|null $nestedId + * + * @return string + */ + protected static function _nestedResourceUrl($id, $nestedPath, $nestedId = null) + { + $url = static::resourceUrl($id) . $nestedPath; + if ($nestedId !== null) { + $url .= "/$nestedId"; + } + return $url; + } + + /** + * @param string $id + * @param string $nestedPath + * @param array|null $params + * @param array|string|null $options + * + * @return \Stripe\StripeObject + */ + protected static function _createNestedResource($id, $nestedPath, $params = null, $options = null) + { + $url = static::_nestedResourceUrl($id, $nestedPath); + return self::_nestedResourceOperation('post', $url, $params, $options); + } + + /** + * @param string $id + * @param string $nestedPath + * @param array|null $params + * @param array|string|null $options + * + * @return \Stripe\StripeObject + */ + protected static function _retrieveNestedResource($id, $nestedPath, $nestedId, $params = null, $options = null) + { + $url = static::_nestedResourceUrl($id, $nestedPath, $nestedId); + return self::_nestedResourceOperation('get', $url, $params, $options); + } + + /** + * @param string $id + * @param string $nestedPath + * @param array|null $params + * @param array|string|null $options + * + * @return \Stripe\StripeObject + */ + protected static function _updateNestedResource($id, $nestedPath, $nestedId, $params = null, $options = null) + { + $url = static::_nestedResourceUrl($id, $nestedPath, $nestedId); + return self::_nestedResourceOperation('post', $url, $params, $options); + } + + /** + * @param string $id + * @param string $nestedPath + * @param array|null $params + * @param array|string|null $options + * + * @return \Stripe\StripeObject + */ + protected static function _deleteNestedResource($id, $nestedPath, $nestedId, $params = null, $options = null) + { + $url = static::_nestedResourceUrl($id, $nestedPath, $nestedId); + return self::_nestedResourceOperation('delete', $url, $params, $options); + } + + /** + * @param string $id + * @param string $nestedPath + * @param array|null $params + * @param array|string|null $options + * + * @return \Stripe\StripeObject + */ + protected static function _allNestedResources($id, $nestedPath, $params = null, $options = null) + { + $url = static::_nestedResourceUrl($id, $nestedPath); + return self::_nestedResourceOperation('get', $url, $params, $options); + } +} diff --git a/htdocs/includes/stripe/lib/ApiOperations/Request.php b/htdocs/includes/stripe/lib/ApiOperations/Request.php new file mode 100644 index 00000000000..c6b06585ad2 --- /dev/null +++ b/htdocs/includes/stripe/lib/ApiOperations/Request.php @@ -0,0 +1,60 @@ + 100, " + . "'currency' => 'usd', 'source' => 'tok_1234'])\")"; + throw new \Stripe\Error\Api($message); + } + } + + /** + * @param string $method HTTP method ('get', 'post', etc.) + * @param string $url URL for the request + * @param array $params list of parameters for the request + * @param array|string|null $options + * + * @return array tuple containing (the JSON response, $options) + */ + protected function _request($method, $url, $params = [], $options = null) + { + $opts = $this->_opts->merge($options); + list($resp, $options) = static::_staticRequest($method, $url, $params, $opts); + $this->setLastResponse($resp); + return [$resp->json, $options]; + } + + /** + * @param string $method HTTP method ('get', 'post', etc.) + * @param string $url URL for the request + * @param array $params list of parameters for the request + * @param array|string|null $options + * + * @return array tuple containing (the JSON response, $options) + */ + protected static function _staticRequest($method, $url, $params, $options) + { + $opts = \Stripe\Util\RequestOptions::parse($options); + $requestor = new \Stripe\ApiRequestor($opts->apiKey, static::baseUrl()); + list($response, $opts->apiKey) = $requestor->request($method, $url, $params, $opts->headers); + $opts->discardNonPersistentHeaders(); + return [$response, $opts]; + } +} diff --git a/htdocs/includes/stripe/lib/ApiOperations/Retrieve.php b/htdocs/includes/stripe/lib/ApiOperations/Retrieve.php new file mode 100644 index 00000000000..a037326b3e8 --- /dev/null +++ b/htdocs/includes/stripe/lib/ApiOperations/Retrieve.php @@ -0,0 +1,27 @@ +refresh(); + return $instance; + } +} diff --git a/htdocs/includes/stripe/lib/ApiOperations/Update.php b/htdocs/includes/stripe/lib/ApiOperations/Update.php new file mode 100644 index 00000000000..0683e77af1a --- /dev/null +++ b/htdocs/includes/stripe/lib/ApiOperations/Update.php @@ -0,0 +1,46 @@ +json, $opts); + $obj->setLastResponse($response); + return $obj; + } + + /** + * @param array|string|null $opts + * + * @return \Stripe\ApiResource The saved resource. + */ + public function save($opts = null) + { + $params = $this->serializeParameters(); + if (count($params) > 0) { + $url = $this->instanceUrl(); + list($response, $opts) = $this->_request('post', $url, $params, $opts); + $this->refreshFrom($response, $opts); + } + return $this; + } +} diff --git a/htdocs/includes/stripe/lib/ApiRequestor.php b/htdocs/includes/stripe/lib/ApiRequestor.php index 03c718f4e1e..334d84425b3 100644 --- a/htdocs/includes/stripe/lib/ApiRequestor.php +++ b/htdocs/includes/stripe/lib/ApiRequestor.php @@ -33,7 +33,7 @@ class ApiRequestor } elseif ($d === false) { return 'false'; } elseif (is_array($d)) { - $res = array(); + $res = []; foreach ($d as $k => $v) { $res[$k] = self::_encodeObjects($v); } @@ -54,17 +54,13 @@ class ApiRequestor */ public function request($method, $url, $params = null, $headers = null) { - if (!$params) { - $params = array(); - } - if (!$headers) { - $headers = array(); - } + $params = $params ?: []; + $headers = $headers ?: []; list($rbody, $rcode, $rheaders, $myApiKey) = $this->_requestRaw($method, $url, $params, $headers); $json = $this->_interpretResponse($rbody, $rcode, $rheaders); $resp = new ApiResponse($rbody, $rcode, $rheaders, $json); - return array($resp, $myApiKey); + return [$resp, $myApiKey]; } /** @@ -74,6 +70,7 @@ class ApiRequestor * @param array $resp * * @throws Error\InvalidRequest if the error is caused by the user. + * @throws Error\Idempotency if the error is caused by an idempotency key. * @throws Error\Authentication if the error is caused by a lack of * permissions. * @throws Error\Permission if the error is caused by insufficient @@ -84,7 +81,7 @@ class ApiRequestor * hitting the API. * @throws Error\Api otherwise. */ - public function handleApiError($rbody, $rcode, $rheaders, $resp) + public function handleErrorResponse($rbody, $rcode, $rheaders, $resp) { if (!is_array($resp) || !isset($resp['error'])) { $msg = "Invalid response object from API: $rbody " @@ -92,35 +89,75 @@ class ApiRequestor throw new Error\Api($msg, $rcode, $rbody, $resp, $rheaders); } - $error = $resp['error']; - $msg = isset($error['message']) ? $error['message'] : null; - $param = isset($error['param']) ? $error['param'] : null; - $code = isset($error['code']) ? $error['code'] : null; + $errorData = $resp['error']; + + $error = null; + if (is_string($errorData)) { + $error = self::_specificOAuthError($rbody, $rcode, $rheaders, $resp, $errorData); + } + if (!$error) { + $error = self::_specificAPIError($rbody, $rcode, $rheaders, $resp, $errorData); + } + + throw $error; + } + + private static function _specificAPIError($rbody, $rcode, $rheaders, $resp, $errorData) + { + $msg = isset($errorData['message']) ? $errorData['message'] : null; + $param = isset($errorData['param']) ? $errorData['param'] : null; + $code = isset($errorData['code']) ? $errorData['code'] : null; + $type = isset($errorData['type']) ? $errorData['type'] : null; switch ($rcode) { case 400: // 'rate_limit' code is deprecated, but left here for backwards compatibility // for API versions earlier than 2015-09-08 if ($code == 'rate_limit') { - throw new Error\RateLimit($msg, $param, $rcode, $rbody, $resp, $rheaders); + return new Error\RateLimit($msg, $param, $rcode, $rbody, $resp, $rheaders); + } + if ($type == 'idempotency_error') { + return new Error\Idempotency($msg, $rcode, $rbody, $resp, $rheaders); } // intentional fall-through case 404: - throw new Error\InvalidRequest($msg, $param, $rcode, $rbody, $resp, $rheaders); + return new Error\InvalidRequest($msg, $param, $rcode, $rbody, $resp, $rheaders); case 401: - throw new Error\Authentication($msg, $rcode, $rbody, $resp, $rheaders); + return new Error\Authentication($msg, $rcode, $rbody, $resp, $rheaders); case 402: - throw new Error\Card($msg, $param, $code, $rcode, $rbody, $resp, $rheaders); + return new Error\Card($msg, $param, $code, $rcode, $rbody, $resp, $rheaders); case 403: - throw new Error\Permission($msg, $rcode, $rbody, $resp, $rheaders); + return new Error\Permission($msg, $rcode, $rbody, $resp, $rheaders); case 429: - throw new Error\RateLimit($msg, $param, $rcode, $rbody, $resp, $rheaders); + return new Error\RateLimit($msg, $param, $rcode, $rbody, $resp, $rheaders); default: - throw new Error\Api($msg, $rcode, $rbody, $resp, $rheaders); + return new Error\Api($msg, $rcode, $rbody, $resp, $rheaders); } } + private static function _specificOAuthError($rbody, $rcode, $rheaders, $resp, $errorCode) + { + $description = isset($resp['error_description']) ? $resp['error_description'] : $errorCode; + + switch ($errorCode) { + case 'invalid_client': + return new Error\OAuth\InvalidClient($errorCode, $description, $rcode, $rbody, $resp, $rheaders); + case 'invalid_grant': + return new Error\OAuth\InvalidGrant($errorCode, $description, $rcode, $rbody, $resp, $rheaders); + case 'invalid_request': + return new Error\OAuth\InvalidRequest($errorCode, $description, $rcode, $rbody, $resp, $rheaders); + case 'invalid_scope': + return new Error\OAuth\InvalidScope($errorCode, $description, $rcode, $rbody, $resp, $rheaders); + case 'unsupported_grant_type': + return new Error\OAuth\UnsupportedGrantType($errorCode, $description, $rcode, $rbody, $resp, $rheaders); + case 'unsupported_response_type': + return new Error\OAuth\UnsupportedResponseType($errorCode, $description, $rcode, $rbody, $resp, $rheaders); + } + + return null; + } + private static function _formatAppInfo($appInfo) { if ($appInfo !== null) { @@ -137,44 +174,34 @@ class ApiRequestor } } - private static function _defaultHeaders($apiKey) + private static function _defaultHeaders($apiKey, $clientInfo = null) { - $appInfo = Stripe::getAppInfo(); - $uaString = 'Stripe/v1 PhpBindings/' . Stripe::VERSION; $langVersion = phpversion(); $uname = php_uname(); - $httplib = 'unknown'; - $ssllib = 'unknown'; - - if (function_exists('curl_version')) { - $curlVersion = curl_version(); - $httplib = 'curl ' . $curlVersion['version']; - $ssllib = $curlVersion['ssl_version']; - } - $appInfo = Stripe::getAppInfo(); - $ua = array( + $ua = [ 'bindings_version' => Stripe::VERSION, 'lang' => 'php', 'lang_version' => $langVersion, 'publisher' => 'stripe', 'uname' => $uname, - 'httplib' => $httplib, - 'ssllib' => $ssllib, - ); + ]; + if ($clientInfo) { + $ua = array_merge($clientInfo, $ua); + } if ($appInfo !== null) { $uaString .= ' ' . self::_formatAppInfo($appInfo); $ua['application'] = $appInfo; } - $defaultHeaders = array( + $defaultHeaders = [ 'X-Stripe-Client-User-Agent' => json_encode($ua), 'User-Agent' => $uaString, 'Authorization' => 'Bearer ' . $apiKey, - ); + ]; return $defaultHeaders; } @@ -193,9 +220,17 @@ class ApiRequestor throw new Error\Authentication($msg); } + // Clients can supply arbitrary additional keys to be included in the + // X-Stripe-Client-User-Agent header via the optional getUserAgentInfo() + // method + $clientUAInfo = null; + if (method_exists($this->httpClient(), 'getUserAgentInfo')) { + $clientUAInfo = $this->httpClient()->getUserAgentInfo(); + } + $absUrl = $this->_apiBase.$url; $params = self::_encodeObjects($params); - $defaultHeaders = $this->_defaultHeaders($myApiKey); + $defaultHeaders = $this->_defaultHeaders($myApiKey, $clientUAInfo); if (Stripe::$apiVersion) { $defaultHeaders['Stripe-Version'] = Stripe::$apiVersion; } @@ -222,7 +257,7 @@ class ApiRequestor } $combinedHeaders = array_merge($defaultHeaders, $headers); - $rawHeaders = array(); + $rawHeaders = []; foreach ($combinedHeaders as $header => $value) { $rawHeaders[] = $header . ': ' . $value; @@ -235,7 +270,7 @@ class ApiRequestor $params, $hasFile ); - return array($rbody, $rcode, $rheaders, $myApiKey); + return [$rbody, $rcode, $rheaders, $myApiKey]; } private function _processResourceParam($resource, $hasCurlFile) @@ -272,7 +307,7 @@ class ApiRequestor } if ($rcode < 200 || $rcode >= 300) { - $this->handleApiError($rbody, $rcode, $rheaders, $resp); + $this->handleErrorResponse($rbody, $rcode, $rheaders, $resp); } return $resp; } diff --git a/htdocs/includes/stripe/lib/ApiResource.php b/htdocs/includes/stripe/lib/ApiResource.php index 0c03d49c3b9..f73b22c9663 100644 --- a/htdocs/includes/stripe/lib/ApiResource.php +++ b/htdocs/includes/stripe/lib/ApiResource.php @@ -9,11 +9,42 @@ namespace Stripe; */ abstract class ApiResource extends StripeObject { - private static $HEADERS_TO_PERSIST = array('Stripe-Account' => true, 'Stripe-Version' => true); + use ApiOperations\Request; - public static function baseUrl() + /** + * @return \Stripe\Util\Set A list of fields that can be their own type of + * API resource (say a nested card under an account for example), and if + * that resource is set, it should be transmitted to the API on a create or + * update. Doing so is not the default behavior because API resources + * should normally be persisted on their own RESTful endpoints. + */ + public static function getSavedNestedResources() { - return Stripe::$apiBase; + static $savedNestedResources = null; + if ($savedNestedResources === null) { + $savedNestedResources = new Util\Set(); + } + return $savedNestedResources; + } + + /** + * @var boolean A flag that can be set a behavior that will cause this + * resource to be encoded and sent up along with an update of its parent + * resource. This is usually not desirable because resources are updated + * individually on their own endpoints, but there are certain cases, + * replacing a customer's source for example, where this is allowed. + */ + public $saveWithParent = false; + + public function __set($k, $v) + { + parent::__set($k, $v); + $v = $this->$k; + if ((static::getSavedNestedResources()->includes($k)) && + ($v instanceof ApiResource)) { + $v->saveWithParent = true; + } + return $v; } /** @@ -59,6 +90,14 @@ abstract class ApiResource extends StripeObject return $name; } + /** + * @return string The base URL for the given class. + */ + public static function baseUrl() + { + return Stripe::$apiBase; + } + /** * @return string The endpoint URL for the given class. */ @@ -92,112 +131,4 @@ abstract class ApiResource extends StripeObject { return static::resourceUrl($this['id']); } - - protected static function _validateParams($params = null) - { - if ($params && !is_array($params)) { - $message = "You must pass an array as the first argument to Stripe API " - . "method calls. (HINT: an example call to create a charge " - . "would be: \"Stripe\\Charge::create(array('amount' => 100, " - . "'currency' => 'usd', 'card' => array('number' => " - . "4242424242424242, 'exp_month' => 5, 'exp_year' => 2015)))\")"; - throw new Error\Api($message); - } - } - - protected function _request($method, $url, $params = array(), $options = null) - { - $opts = $this->_opts->merge($options); - list($resp, $options) = static::_staticRequest($method, $url, $params, $opts); - $this->setLastResponse($resp); - return array($resp->json, $options); - } - - protected static function _staticRequest($method, $url, $params, $options) - { - $opts = Util\RequestOptions::parse($options); - $requestor = new ApiRequestor($opts->apiKey, static::baseUrl()); - list($response, $opts->apiKey) = $requestor->request($method, $url, $params, $opts->headers); - foreach ($opts->headers as $k => $v) { - if (!array_key_exists($k, self::$HEADERS_TO_PERSIST)) { - unset($opts->headers[$k]); - } - } - return array($response, $opts); - } - - protected static function _retrieve($id, $options = null) - { - $opts = Util\RequestOptions::parse($options); - $instance = new static($id, $opts); - $instance->refresh(); - return $instance; - } - - protected static function _all($params = null, $options = null) - { - self::_validateParams($params); - $url = static::classUrl(); - - list($response, $opts) = static::_staticRequest('get', $url, $params, $options); - $obj = Util\Util::convertToStripeObject($response->json, $opts); - if (!is_a($obj, 'Stripe\\Collection')) { - $class = get_class($obj); - $message = "Expected type \"Stripe\\Collection\", got \"$class\" instead"; - throw new Error\Api($message); - } - $obj->setLastResponse($response); - $obj->setRequestParams($params); - return $obj; - } - - protected static function _create($params = null, $options = null) - { - self::_validateParams($params); - $url = static::classUrl(); - - list($response, $opts) = static::_staticRequest('post', $url, $params, $options); - $obj = Util\Util::convertToStripeObject($response->json, $opts); - $obj->setLastResponse($response); - return $obj; - } - - /** - * @param string $id The ID of the API resource to update. - * @param array|null $params - * @param array|string|null $opts - * - * @return ApiResource the updated API resource - */ - protected static function _update($id, $params = null, $options = null) - { - self::_validateParams($params); - $url = static::resourceUrl($id); - - list($response, $opts) = static::_staticRequest('post', $url, $params, $options); - $obj = Util\Util::convertToStripeObject($response->json, $opts); - $obj->setLastResponse($response); - return $obj; - } - - protected function _save($options = null) - { - $params = $this->serializeParameters(); - if (count($params) > 0) { - $url = $this->instanceUrl(); - list($response, $opts) = $this->_request('post', $url, $params, $options); - $this->refreshFrom($response, $opts); - } - return $this; - } - - protected function _delete($params = null, $options = null) - { - self::_validateParams($params); - - $url = $this->instanceUrl(); - list($response, $opts) = $this->_request('delete', $url, $params, $options); - $this->refreshFrom($response, $opts); - return $this; - } } diff --git a/htdocs/includes/stripe/lib/ApplePayDomain.php b/htdocs/includes/stripe/lib/ApplePayDomain.php index 8c522c8b933..124c5dc0632 100644 --- a/htdocs/includes/stripe/lib/ApplePayDomain.php +++ b/htdocs/includes/stripe/lib/ApplePayDomain.php @@ -9,7 +9,11 @@ namespace Stripe; */ class ApplePayDomain extends ApiResource { - + use ApiOperations\All; + use ApiOperations\Create; + use ApiOperations\Delete; + use ApiOperations\Retrieve; + /** * @return string The class URL for this resource. It needs to be special * cased because it doesn't fit into the standard resource pattern. @@ -18,48 +22,4 @@ class ApplePayDomain extends ApiResource { return '/v1/apple_pay/domains'; } - - /** - * @param string $id The ID of the domain to retrieve. - * @param array|string|null $opts - * - * @return ApplePayDomain - */ - public static function retrieve($id, $opts = null) - { - return self::_retrieve($id, $opts); - } - - /** - * @param array|null $params - * @param array|string|null $opts - * - * @return ApplePayDomain The created domain. - */ - public static function create($params = null, $opts = null) - { - return self::_create($params, $opts); - } - - /** - * @param array|null $params - * @param array|string|null $opts - * - * @return ApplePayDomain The deleted domain. - */ - public function delete($params = null, $opts = null) - { - return $this->_delete($params, $opts); - } - - /** - * @param array|null $params - * @param array|string|null $opts - * - * @return Collection of ApplePayDomains - */ - public static function all($params = null, $opts = null) - { - return self::_all($params, $opts); - } } diff --git a/htdocs/includes/stripe/lib/ApplicationFee.php b/htdocs/includes/stripe/lib/ApplicationFee.php index 8145541c17e..05b94ea9235 100644 --- a/htdocs/includes/stripe/lib/ApplicationFee.php +++ b/htdocs/includes/stripe/lib/ApplicationFee.php @@ -5,10 +5,31 @@ namespace Stripe; /** * Class ApplicationFee * + * @property string $id + * @property string $object + * @property string $account + * @property int $amount + * @property int $amount_refunded + * @property string $application + * @property string $balance_transaction + * @property string $charge + * @property int $created + * @property string $currency + * @property bool $livemode + * @property string $originating_transaction + * @property bool $refunded + * @property Collection $refunds + * * @package Stripe */ class ApplicationFee extends ApiResource { + use ApiOperations\All; + use ApiOperations\NestedResource; + use ApiOperations\Retrieve; + + const PATH_REFUNDS = '/refunds'; + /** * This is a special case because the application fee endpoint has an * underscore in it. The parent `className` function strips underscores. @@ -20,40 +41,6 @@ class ApplicationFee extends ApiResource return 'application_fee'; } - /** - * @param string $id The ID of the application fee to retrieve. - * @param array|string|null $opts - * - * @return ApplicationFee - */ - public static function retrieve($id, $opts = null) - { - return self::_retrieve($id, $opts); - } - - /** - * @param string $id The ID of the application fee to update. - * @param array|null $params - * @param array|string|null $options - * - * @return ApplicationFee The updated application fee. - */ - public static function update($id, $params = null, $options = null) - { - return self::_update($id, $params, $options); - } - - /** - * @param array|null $params - * @param array|string|null $opts - * - * @return Collection of ApplicationFees - */ - public static function all($params = null, $opts = null) - { - return self::_all($params, $opts); - } - /** * @param array|null $params * @param array|string|null $opts @@ -66,4 +53,54 @@ class ApplicationFee extends ApiResource $this->refresh(); return $this; } + + /** + * @param array|null $id The ID of the application fee on which to create the refund. + * @param array|null $params + * @param array|string|null $opts + * + * @return ApplicationFeeRefund + */ + public static function createRefund($id, $params = null, $opts = null) + { + return self::_createNestedResource($id, static::PATH_REFUNDS, $params, $opts); + } + + /** + * @param array|null $id The ID of the application fee to which the refund belongs. + * @param array|null $refundId The ID of the refund to retrieve. + * @param array|null $params + * @param array|string|null $opts + * + * @return ApplicationFeeRefund + */ + public static function retrieveRefund($id, $refundId, $params = null, $opts = null) + { + return self::_retrieveNestedResource($id, static::PATH_REFUNDS, $refundId, $params, $opts); + } + + /** + * @param array|null $id The ID of the application fee to which the refund belongs. + * @param array|null $refundId The ID of the refund to update. + * @param array|null $params + * @param array|string|null $opts + * + * @return ApplicationFeeRefund + */ + public static function updateRefund($id, $refundId, $params = null, $opts = null) + { + return self::_updateNestedResource($id, static::PATH_REFUNDS, $refundId, $params, $opts); + } + + /** + * @param array|null $id The ID of the application fee on which to retrieve the refunds. + * @param array|null $params + * @param array|string|null $opts + * + * @return ApplicationFeeRefund + */ + public static function allRefunds($id, $params = null, $opts = null) + { + return self::_allNestedResources($id, static::PATH_REFUNDS, $params, $opts); + } } diff --git a/htdocs/includes/stripe/lib/ApplicationFeeRefund.php b/htdocs/includes/stripe/lib/ApplicationFeeRefund.php index 44695ef88cd..4b1c425a8ee 100644 --- a/htdocs/includes/stripe/lib/ApplicationFeeRefund.php +++ b/htdocs/includes/stripe/lib/ApplicationFeeRefund.php @@ -5,10 +5,23 @@ namespace Stripe; /** * Class ApplicationFeeRefund * + * @property string $id + * @property string $object + * @property int $amount + * @property string $balance_transaction + * @property int $created + * @property string $currency + * @property string $fee + * @property StripeObject $metadata + * * @package Stripe */ class ApplicationFeeRefund extends ApiResource { + use ApiOperations\Update { + save as protected _save; + } + /** * @return string The API URL for this Stripe refund. */ diff --git a/htdocs/includes/stripe/lib/AttachedObject.php b/htdocs/includes/stripe/lib/AttachedObject.php deleted file mode 100644 index 489517d6693..00000000000 --- a/htdocs/includes/stripe/lib/AttachedObject.php +++ /dev/null @@ -1,31 +0,0 @@ -_values), array_keys($properties)); - // Don't unset, but rather set to null so we send up '' for deletion. - foreach ($removed as $k) { - $this->$k = null; - } - - foreach ($properties as $k => $v) { - $this->$k = $v; - } - } -} diff --git a/htdocs/includes/stripe/lib/Balance.php b/htdocs/includes/stripe/lib/Balance.php index 3b551eb84df..115307f843b 100644 --- a/htdocs/includes/stripe/lib/Balance.php +++ b/htdocs/includes/stripe/lib/Balance.php @@ -6,9 +6,9 @@ namespace Stripe; * Class Balance * * @property string $object - * @property mixed $available - * @property bool $livedmode - * @property mixed $pending + * @property array $available + * @property bool $livemode + * @property array $pending * * @package Stripe */ diff --git a/htdocs/includes/stripe/lib/BalanceTransaction.php b/htdocs/includes/stripe/lib/BalanceTransaction.php index b84619ece81..f82888ab1dd 100644 --- a/htdocs/includes/stripe/lib/BalanceTransaction.php +++ b/htdocs/includes/stripe/lib/BalanceTransaction.php @@ -12,11 +12,11 @@ namespace Stripe; * @property int $created * @property string $currency * @property string $description + * @property float $exchange_rate * @property int $fee * @property mixed $fee_details * @property int $net * @property string $source - * @property mixed $sourced_transfers * @property string $status * @property string $type * @@ -24,6 +24,9 @@ namespace Stripe; */ class BalanceTransaction extends ApiResource { + use ApiOperations\All; + use ApiOperations\Retrieve; + /** * @return string The class URL for this resource. It needs to be special * cased because it doesn't fit into the standard resource pattern. @@ -32,26 +35,4 @@ class BalanceTransaction extends ApiResource { return "/v1/balance/history"; } - - /** - * @param string $id The ID of the balance transaction to retrieve. - * @param array|string|null $opts - * - * @return BalanceTransaction - */ - public static function retrieve($id, $opts = null) - { - return self::_retrieve($id, $opts); - } - - /** - * @param array|null $params - * @param array|string|null $opts - * - * @return Collection of BalanceTransactions - */ - public static function all($params = null, $opts = null) - { - return self::_all($params, $opts); - } } diff --git a/htdocs/includes/stripe/lib/BankAccount.php b/htdocs/includes/stripe/lib/BankAccount.php index 2f11c067c36..2afc312d003 100644 --- a/htdocs/includes/stripe/lib/BankAccount.php +++ b/htdocs/includes/stripe/lib/BankAccount.php @@ -5,11 +5,82 @@ namespace Stripe; /** * Class BankAccount * + * @property string $id + * @property string $object + * @property string $account + * @property string $account_holder_name + * @property string $account_holder_type + * @property string $bank_name + * @property string $country + * @property string $currency + * @property string $customer + * @property bool $default_for_currency + * @property string $fingerprint + * @property string $last4 + * @property StripeObject $metadata + * @property string $routing_number + * @property string $status + * * @package Stripe */ -class BankAccount extends ExternalAccount +class BankAccount extends ApiResource { + use ApiOperations\Delete; + use ApiOperations\Update; + /** + * @return string The instance URL for this resource. It needs to be special + * cased because it doesn't fit into the standard resource pattern. + */ + public function instanceUrl() + { + if ($this['customer']) { + $base = Customer::classUrl(); + $parent = $this['customer']; + $path = 'sources'; + } elseif ($this['account']) { + $base = Account::classUrl(); + $parent = $this['account']; + $path = 'external_accounts'; + } else { + $msg = "Bank accounts cannot be accessed without a customer ID or account ID."; + throw new Error\InvalidRequest($msg, null); + } + $parentExtn = urlencode(Util\Util::utf8($parent)); + $extn = urlencode(Util\Util::utf8($this['id'])); + return "$base/$parentExtn/$path/$extn"; + } + + /** + * @param array|string $_id + * @param array|string|null $_opts + * + * @throws \Stripe\Error\InvalidRequest + */ + public static function retrieve($_id, $_opts = null) + { + $msg = "Bank accounts cannot be accessed without a customer ID or account ID. " . + "Retrieve a bank account using \$customer->sources->retrieve('bank_account_id') or " . + "\$account->external_accounts->retrieve('bank_account_id') instead."; + throw new Error\InvalidRequest($msg, null); + } + + /** + * @param string $_id + * @param array|null $_params + * @param array|string|null $_options + * + * @throws \Stripe\Error\InvalidRequest + */ + public static function update($_id, $_params = null, $_options = null) + { + $msg = "Bank accounts cannot be accessed without a customer ID or account ID. " . + "Call save() on \$customer->sources->retrieve('bank_account_id') or " . + "\$account->external_accounts->retrieve('bank_account_id') instead."; + throw new Error\InvalidRequest($msg, null); + } + + /** * @param array|null $params * @param array|string|null $options * diff --git a/htdocs/includes/stripe/lib/BitcoinReceiver.php b/htdocs/includes/stripe/lib/BitcoinReceiver.php index 3f2c835b96f..8d04256b5db 100644 --- a/htdocs/includes/stripe/lib/BitcoinReceiver.php +++ b/htdocs/includes/stripe/lib/BitcoinReceiver.php @@ -6,9 +6,15 @@ namespace Stripe; * Class BitcoinReceiver * * @package Stripe + * + * @deprecated Bitcoin receivers are deprecated. Please use the sources API instead. + * @link https://stripe.com/docs/sources/bitcoin */ -class BitcoinReceiver extends ExternalAccount +class BitcoinReceiver extends ApiResource { + use ApiOperations\All; + use ApiOperations\Retrieve; + /** * @return string The class URL for this resource. It needs to be special * cased because it doesn't fit into the standard resource pattern. @@ -24,62 +30,17 @@ class BitcoinReceiver extends ExternalAccount */ public function instanceUrl() { - $result = parent::instanceUrl(); - if ($result) { - return $result; + if ($this['customer']) { + $base = Customer::classUrl(); + $parent = $this['customer']; + $path = 'sources'; + $parentExtn = urlencode(Util\Util::utf8($parent)); + $extn = urlencode(Util\Util::utf8($this['id'])); + return "$base/$parentExtn/$path/$extn"; } else { - $id = $this['id']; - $id = Util\Util::utf8($id); - $extn = urlencode($id); $base = BitcoinReceiver::classUrl(); + $extn = urlencode(Util\Util::utf8($this['id'])); return "$base/$extn"; } } - - /** - * @param string $id The ID of the Bitcoin Receiver to retrieve. - * @param array|string|null $opts - * - * @return BitcoinReceiver - */ - public static function retrieve($id, $opts = null) - { - return self::_retrieve($id, $opts); - } - - /** - * @param array|null $params - * @param array|string|null $opts - * - * @return Collection of BitcoinReceivers - */ - public static function all($params = null, $opts = null) - { - return self::_all($params, $opts); - } - - /** - * @param array|null $params - * @param array|string|null $opts - * - * @return BitcoinReceiver The created Bitcoin Receiver item. - */ - public static function create($params = null, $opts = null) - { - return self::_create($params, $opts); - } - - /** - * @param array|null $params - * @param array|string|null $options - * - * @return BitcoinReceiver The refunded Bitcoin Receiver item. - */ - public function refund($params = null, $options = null) - { - $url = $this->instanceUrl() . '/refund'; - list($response, $opts) = $this->_request('post', $url, $params, $options); - $this->refreshFrom($response, $opts); - return $this; - } } diff --git a/htdocs/includes/stripe/lib/Card.php b/htdocs/includes/stripe/lib/Card.php index 227bee13873..7e57423601a 100644 --- a/htdocs/includes/stripe/lib/Card.php +++ b/htdocs/includes/stripe/lib/Card.php @@ -5,9 +5,93 @@ namespace Stripe; /** * Class Card * + * @property string $id + * @property string $object + * @property string $address_city + * @property string $address_country + * @property string $address_line1 + * @property string $address_line1_check + * @property string $address_line2 + * @property string $address_state + * @property string $address_zip + * @property string $address_zip_check + * @property string $brand + * @property string $country + * @property string $customer + * @property string $cvc_check + * @property string $dynamic_last4 + * @property int $exp_month + * @property int $exp_year + * @property string $fingerprint + * @property string $funding + * @property string $last4 + * @property StripeObject $metadata + * @property string $name + * @property string $tokenization_method + * * @package Stripe */ -class Card extends ExternalAccount +class Card extends ApiResource { + use ApiOperations\Delete; + use ApiOperations\Update; + /** + * @return string The instance URL for this resource. It needs to be special + * cased because cards are nested resources that may belong to different + * top-level resources. + */ + public function instanceUrl() + { + if ($this['customer']) { + $base = Customer::classUrl(); + $parent = $this['customer']; + $path = 'sources'; + } elseif ($this['account']) { + $base = Account::classUrl(); + $parent = $this['account']; + $path = 'external_accounts'; + } elseif ($this['recipient']) { + $base = Recipient::classUrl(); + $parent = $this['recipient']; + $path = 'cards'; + } else { + $msg = "Cards cannot be accessed without a customer ID, account ID or recipient ID."; + throw new Error\InvalidRequest($msg, null); + } + $parentExtn = urlencode(Util\Util::utf8($parent)); + $extn = urlencode(Util\Util::utf8($this['id'])); + return "$base/$parentExtn/$path/$extn"; + } + + /** + * @param array|string $_id + * @param array|string|null $_opts + * + * @throws \Stripe\Error\InvalidRequest + */ + public static function retrieve($_id, $_opts = null) + { + $msg = "Cards cannot be accessed without a customer, recipient or account ID. " . + "Retrieve a card using \$customer->sources->retrieve('card_id'), " . + "\$recipient->cards->retrieve('card_id'), or"; + "\$account->external_accounts->retrieve('card_id') instead."; + throw new Error\InvalidRequest($msg, null); + } + + /** + * @param string $_id + * @param array|null $_params + * @param array|string|null $_options + * + * @throws \Stripe\Error\InvalidRequest + */ + public static function update($_id, $_params = null, $_options = null) + { + $msg = "Cards cannot be accessed without a customer, recipient or account ID. " . + "Call save() on \$customer->sources->retrieve('card_id'), " . + "\$recipient->cards->retrieve('card_id'), or"; + "\$account->external_accounts->retrieve('card_id') instead."; + throw new Error\InvalidRequest($msg, null); + } } diff --git a/htdocs/includes/stripe/lib/Charge.php b/htdocs/includes/stripe/lib/Charge.php index ab1d5a33f8a..6d448022877 100644 --- a/htdocs/includes/stripe/lib/Charge.php +++ b/htdocs/includes/stripe/lib/Charge.php @@ -9,91 +9,47 @@ namespace Stripe; * @property string $object * @property int $amount * @property int $amount_refunded - * @property mixed $application_fee + * @property string $application + * @property string $application_fee * @property string $balance_transaction * @property bool $captured * @property int $created * @property string $currency * @property string $customer - * @property mixed $description - * @property mixed $destination - * @property string|null $dispute - * @property mixed $failure_code - * @property mixed $failure_message + * @property string $description + * @property string $destination + * @property string $dispute + * @property string $failure_code + * @property string $failure_message * @property mixed $fraud_details - * @property mixed $invoice + * @property string $invoice * @property bool $livemode - * @property mixed $metadata - * @property mixed $order + * @property StripeObject $metadata + * @property string $on_behalf_of + * @property string $order + * @property mixed $outcome * @property bool $paid - * @property mixed $receipt_email - * @property mixed $receipt_number + * @property string $receipt_email + * @property string $receipt_number * @property bool $refunded - * @property mixed $refunds + * @property Collection $refunds + * @property string $review * @property mixed $shipping * @property mixed $source - * @property mixed $source_transfer - * @property mixed $statement_descriptor + * @property string $source_transfer + * @property string $statement_descriptor * @property string $status + * @property string $transfer + * @property string $transfer_group * * @package Stripe */ class Charge extends ApiResource { - /** - * @param string $id The ID of the charge to retrieve. - * @param array|string|null $options - * - * @return Charge - */ - public static function retrieve($id, $options = null) - { - return self::_retrieve($id, $options); - } - - /** - * @param array|null $params - * @param array|string|null $options - * - * @return Collection of Charges - */ - public static function all($params = null, $options = null) - { - return self::_all($params, $options); - } - - /** - * @param array|null $params - * @param array|string|null $options - * - * @return Charge The created charge. - */ - public static function create($params = null, $options = null) - { - return self::_create($params, $options); - } - - /** - * @param string $id The ID of the charge to update. - * @param array|null $params - * @param array|string|null $options - * - * @return Charge The updated charge. - */ - public static function update($id, $params = null, $options = null) - { - return self::_update($id, $params, $options); - } - - /** - * @param array|string|null $options - * - * @return Charge The saved charge. - */ - public function save($options = null) - { - return $this->_save($options); - } + use ApiOperations\All; + use ApiOperations\Create; + use ApiOperations\Retrieve; + use ApiOperations\Update; /** * @param array|null $params @@ -135,7 +91,7 @@ class Charge extends ApiResource { $url = $this->instanceUrl() . '/dispute'; list($response, $opts) = $this->_request('post', $url, $params, $options); - $this->refreshFrom(array('dispute' => $response), $opts, true); + $this->refreshFrom(['dispute' => $response], $opts, true); return $this->dispute; } @@ -161,7 +117,7 @@ class Charge extends ApiResource */ public function markAsFraudulent($opts = null) { - $params = array('fraud_details' => array('user_report' => 'fraudulent')); + $params = ['fraud_details' => ['user_report' => 'fraudulent']]; $url = $this->instanceUrl(); list($response, $opts) = $this->_request('post', $url, $params, $opts); $this->refreshFrom($response, $opts); @@ -175,7 +131,7 @@ class Charge extends ApiResource */ public function markAsSafe($opts = null) { - $params = array('fraud_details' => array('user_report' => 'safe')); + $params = ['fraud_details' => ['user_report' => 'safe']]; $url = $this->instanceUrl(); list($response, $opts) = $this->_request('post', $url, $params, $opts); $this->refreshFrom($response, $opts); diff --git a/htdocs/includes/stripe/lib/Collection.php b/htdocs/includes/stripe/lib/Collection.php index 0beb3a18918..cfb4014a0fe 100644 --- a/htdocs/includes/stripe/lib/Collection.php +++ b/htdocs/includes/stripe/lib/Collection.php @@ -12,9 +12,19 @@ namespace Stripe; * * @package Stripe */ -class Collection extends ApiResource +class Collection extends StripeObject { - protected $_requestParams = array(); + use ApiOperations\Request; + + protected $_requestParams = []; + + /** + * @return string The base URL for the given class. + */ + public static function baseUrl() + { + return Stripe::$apiBase; + } public function setRequestParams($params) { @@ -56,7 +66,7 @@ class Collection extends ApiResource } /** - * @return AutoPagingIterator An iterator that can be used to iterate + * @return Util\AutoPagingIterator An iterator that can be used to iterate * across all objects across all pages. As page boundaries are * encountered, the next page will be fetched automatically for * continued iteration. @@ -76,12 +86,11 @@ class Collection extends ApiResource if (isset($url['query'])) { // If the URL contains a query param, parse it out into $params so they // don't interact weirdly with each other. - $query = array(); + $query = []; parse_str($url['query'], $query); - // PHP 5.2 doesn't support the ?: operator :( - $params = array_merge($params ? $params : array(), $query); + $params = array_merge($params ?: [], $query); } - return array($url['path'], $params); + return [$url['path'], $params]; } } diff --git a/htdocs/includes/stripe/lib/CountrySpec.php b/htdocs/includes/stripe/lib/CountrySpec.php index dabb88b4522..cdaa4e84d89 100644 --- a/htdocs/includes/stripe/lib/CountrySpec.php +++ b/htdocs/includes/stripe/lib/CountrySpec.php @@ -5,10 +5,21 @@ namespace Stripe; /** * Class CountrySpec * + * @property string $id + * @property string $object + * @property string $default_currency + * @property mixed $supported_bank_account_currencies + * @property string[] $supported_payment_currencies + * @property string[] $supported_payment_methods + * @property mixed $verification_fields + * * @package Stripe */ class CountrySpec extends ApiResource { + use ApiOperations\All; + use ApiOperations\Retrieve; + /** * This is a special case because the country specs endpoint has an * underscore in it. The parent `className` function strips underscores. @@ -19,26 +30,4 @@ class CountrySpec extends ApiResource { return 'country_spec'; } - - /** - * @param string $country The ISO country code of the country we retrieve the CountrySpec for. - * @param array|string|null $opts - * - * @return CountrySpec - */ - public static function retrieve($country, $opts = null) - { - return self::_retrieve($country, $opts); - } - - /** - * @param array|null $params - * @param array|string|null $opts - * - * @return Collection of CountrySpecs - */ - public static function all($params = null, $opts = null) - { - return self::_all($params, $opts); - } } diff --git a/htdocs/includes/stripe/lib/Coupon.php b/htdocs/includes/stripe/lib/Coupon.php index 079cc10b478..a2d44443ce5 100644 --- a/htdocs/includes/stripe/lib/Coupon.php +++ b/htdocs/includes/stripe/lib/Coupon.php @@ -5,73 +5,28 @@ namespace Stripe; /** * Class Coupon * + * @property string $id + * @property string $object + * @property int $amount_off + * @property int $created + * @property string $currency + * @property string $duration + * @property int $duration_in_months + * @property bool $livemode + * @property int $max_redemptions + * @property StripeObject $metadata + * @property int $percent_off + * @property int $redeem_by + * @property int $times_redeemed + * @property bool $valid + * * @package Stripe */ class Coupon extends ApiResource { - /** - * @param string $id The ID of the coupon to retrieve. - * @param array|string|null $opts - * - * @return Coupon - */ - public static function retrieve($id, $opts = null) - { - return self::_retrieve($id, $opts); - } - - /** - * @param array|null $params - * @param array|string|null $opts - * - * @return Coupon The created coupon. - */ - public static function create($params = null, $opts = null) - { - return self::_create($params, $opts); - } - - /** - * @param string $id The ID of the coupon to update. - * @param array|null $params - * @param array|string|null $options - * - * @return Coupon The updated coupon. - */ - public static function update($id, $params = null, $options = null) - { - return self::_update($id, $params, $options); - } - - /** - * @param array|null $params - * @param array|string|null $opts - * - * @return Coupon The deleted coupon. - */ - public function delete($params = null, $opts = null) - { - return $this->_delete($params, $opts); - } - - /** - * @param array|string|null $opts - * - * @return Coupon The saved coupon. - */ - public function save($opts = null) - { - return $this->_save($opts); - } - - /** - * @param array|null $params - * @param array|string|null $opts - * - * @return Collection of Coupons - */ - public static function all($params = null, $opts = null) - { - return self::_all($params, $opts); - } + use ApiOperations\All; + use ApiOperations\Create; + use ApiOperations\Delete; + use ApiOperations\Retrieve; + use ApiOperations\Update; } diff --git a/htdocs/includes/stripe/lib/Customer.php b/htdocs/includes/stripe/lib/Customer.php index 1dfbfc6a16b..8d31b5ac0aa 100644 --- a/htdocs/includes/stripe/lib/Customer.php +++ b/htdocs/includes/stripe/lib/Customer.php @@ -17,7 +17,7 @@ namespace Stripe; * @property mixed $discount * @property string $email * @property bool $livemode - * @property array $metadata + * @property StripeObject $metadata * @property mixed $shipping * @property Collection $sources * @property Collection $subscriptions @@ -26,71 +26,25 @@ namespace Stripe; */ class Customer extends ApiResource { - /** - * @param string $id The ID of the customer to retrieve. - * @param array|string|null $opts - * - * @return Customer - */ - public static function retrieve($id, $opts = null) + use ApiOperations\All; + use ApiOperations\Create; + use ApiOperations\Delete; + use ApiOperations\NestedResource; + use ApiOperations\Retrieve; + use ApiOperations\Update; + + public static function getSavedNestedResources() { - return self::_retrieve($id, $opts); + static $savedNestedResources = null; + if ($savedNestedResources === null) { + $savedNestedResources = new Util\Set([ + 'source', + ]); + } + return $savedNestedResources; } - /** - * @param array|null $params - * @param array|string|null $opts - * - * @return Collection of Customers - */ - public static function all($params = null, $opts = null) - { - return self::_all($params, $opts); - } - - /** - * @param array|null $params - * @param array|string|null $opts - * - * @return Customer The created customer. - */ - public static function create($params = null, $opts = null) - { - return self::_create($params, $opts); - } - - /** - * @param string $id The ID of the customer to update. - * @param array|null $params - * @param array|string|null $options - * - * @return Customer The updated customer. - */ - public static function update($id, $params = null, $options = null) - { - return self::_update($id, $params, $options); - } - - /** - * @param array|string|null $opts - * - * @return Customer The saved customer. - */ - public function save($opts = null) - { - return $this->_save($opts); - } - - /** - * @param array|null $params - * @param array|string|null $opts - * - * @return Customer The deleted customer. - */ - public function delete($params = null, $opts = null) - { - return $this->_delete($params, $opts); - } + const PATH_SOURCES = '/sources'; /** * @param array|null $params @@ -99,9 +53,7 @@ class Customer extends ApiResource */ public function addInvoiceItem($params = null) { - if (!$params) { - $params = array(); - } + $params = $params ?: []; $params['customer'] = $this->id; $ii = InvoiceItem::create($params, $this->_opts); return $ii; @@ -114,9 +66,7 @@ class Customer extends ApiResource */ public function invoices($params = null) { - if (!$params) { - $params = array(); - } + $params = $params ?: []; $params['customer'] = $this->id; $invoices = Invoice::all($params, $this->_opts); return $invoices; @@ -129,9 +79,7 @@ class Customer extends ApiResource */ public function invoiceItems($params = null) { - if (!$params) { - $params = array(); - } + $params = $params ?: []; $params['customer'] = $this->id; $iis = InvoiceItem::all($params, $this->_opts); return $iis; @@ -144,9 +92,7 @@ class Customer extends ApiResource */ public function charges($params = null) { - if (!$params) { - $params = array(); - } + $params = $params ?: []; $params['customer'] = $this->id; $charges = Charge::all($params, $this->_opts); return $charges; @@ -161,7 +107,7 @@ class Customer extends ApiResource { $url = $this->instanceUrl() . '/subscription'; list($response, $opts) = $this->_request('post', $url, $params); - $this->refreshFrom(array('subscription' => $response), $opts, true); + $this->refreshFrom(['subscription' => $response], $opts, true); return $this->subscription; } @@ -174,7 +120,7 @@ class Customer extends ApiResource { $url = $this->instanceUrl() . '/subscription'; list($response, $opts) = $this->_request('delete', $url, $params); - $this->refreshFrom(array('subscription' => $response), $opts, true); + $this->refreshFrom(['subscription' => $response], $opts, true); return $this->subscription; } @@ -185,6 +131,69 @@ class Customer extends ApiResource { $url = $this->instanceUrl() . '/discount'; list($response, $opts) = $this->_request('delete', $url); - $this->refreshFrom(array('discount' => null), $opts, true); + $this->refreshFrom(['discount' => null], $opts, true); + } + + /** + * @param array|null $id The ID of the customer on which to create the source. + * @param array|null $params + * @param array|string|null $opts + * + * @return ApiResource + */ + public static function createSource($id, $params = null, $opts = null) + { + return self::_createNestedResource($id, static::PATH_SOURCES, $params, $opts); + } + + /** + * @param array|null $id The ID of the customer to which the source belongs. + * @param array|null $sourceId The ID of the source to retrieve. + * @param array|null $params + * @param array|string|null $opts + * + * @return ApiResource + */ + public static function retrieveSource($id, $sourceId, $params = null, $opts = null) + { + return self::_retrieveNestedResource($id, static::PATH_SOURCES, $sourceId, $params, $opts); + } + + /** + * @param array|null $id The ID of the customer to which the source belongs. + * @param array|null $sourceId The ID of the source to update. + * @param array|null $params + * @param array|string|null $opts + * + * @return ApiResource + */ + public static function updateSource($id, $sourceId, $params = null, $opts = null) + { + return self::_updateNestedResource($id, static::PATH_SOURCES, $sourceId, $params, $opts); + } + + /** + * @param array|null $id The ID of the customer to which the source belongs. + * @param array|null $sourceId The ID of the source to delete. + * @param array|null $params + * @param array|string|null $opts + * + * @return ApiResource + */ + public static function deleteSource($id, $sourceId, $params = null, $opts = null) + { + return self::_deleteNestedResource($id, static::PATH_SOURCES, $sourceId, $params, $opts); + } + + /** + * @param array|null $id The ID of the customer on which to retrieve the sources. + * @param array|null $params + * @param array|string|null $opts + * + * @return ApiResource + */ + public static function allSources($id, $params = null, $opts = null) + { + return self::_allNestedResources($id, static::PATH_SOURCES, $params, $opts); } } diff --git a/htdocs/includes/stripe/lib/Dispute.php b/htdocs/includes/stripe/lib/Dispute.php index ce70d499b35..7f4c233b009 100644 --- a/htdocs/includes/stripe/lib/Dispute.php +++ b/htdocs/includes/stripe/lib/Dispute.php @@ -16,7 +16,7 @@ namespace Stripe; * @property mixed $evidence_details * @property bool $is_charge_refundable * @property bool $livemode - * @property mixed $metadata + * @property StripeObject $metadata * @property string $reason * @property string $status * @@ -24,49 +24,40 @@ namespace Stripe; */ class Dispute extends ApiResource { - /** - * @param string $id The ID of the dispute to retrieve. - * @param array|string|null $options - * - * @return Dispute - */ - public static function retrieve($id, $options = null) - { - return self::_retrieve($id, $options); - } + use ApiOperations\All; + use ApiOperations\Retrieve; + use ApiOperations\Update; /** - * @param array|null $params - * @param array|string|null $options - * - * @return array An array of Disputes. + * Possible string representations of dispute reasons. + * @link https://stripe.com/docs/api#dispute_object */ - public static function all($params = null, $options = null) - { - return self::_all($params, $options); - } + const REASON_BANK_CANNOT_PROCESS = 'bank_cannot_process'; + const REASON_CREDIT_NOT_PROCESSED = 'credit_not_processed'; + const REASON_CUSTOMER_INITIATED = 'customer_initiated'; + const REASON_DEBIT_NOT_AUTHORIZED = 'debit_not_authorized'; + const REASON_DUPLICATE = 'duplicate'; + const REASON_FRAUDULENT = 'fraudulent'; + const REASON_GENERAL = 'general'; + const REASON_INCORRECT_ACCOUNT_DETAILS = 'incorrect_account_details'; + const REASON_INSUFFICIENT_FUNDS = 'insufficient_funds'; + const REASON_PRODUCT_NOT_RECEIVED = 'product_not_received'; + const REASON_PRODUCT_UNACCEPTABLE = 'product_unacceptable'; + const REASON_SUBSCRIPTION_CANCELED = 'subscription_canceled'; + const REASON_UNRECOGNIZED = 'unrecognized'; /** - * @param string $id The ID of the dispute to update. - * @param array|null $params - * @param array|string|null $options - * - * @return Dispute The updated dispute. + * Possible string representations of dispute statuses. + * @link https://stripe.com/docs/api#dispute_object */ - public static function update($id, $params = null, $options = null) - { - return self::_update($id, $params, $options); - } - - /** - * @param array|string|null $options - * - * @return Dispute The saved charge. - */ - public function save($options = null) - { - return $this->_save($options); - } + const STATUS_CHARGE_REFUNDED = 'charge_refunded'; + const STATUS_LOST = 'lost'; + const STATUS_NEEDS_RESPONSE = 'needs_response'; + const STATUS_UNDER_REVIEW = 'under_review'; + const STATUS_WARNING_CLOSED = 'warning_closed'; + const STATUS_WARNING_NEEDS_RESPONSE = 'warning_needs_response'; + const STATUS_WARNING_UNDER_REVIEW = 'warning_under_review'; + const STATUS_WON = 'won'; /** * @param array|string|null $options diff --git a/htdocs/includes/stripe/lib/EphemeralKey.php b/htdocs/includes/stripe/lib/EphemeralKey.php new file mode 100644 index 00000000000..5bbef09165d --- /dev/null +++ b/htdocs/includes/stripe/lib/EphemeralKey.php @@ -0,0 +1,49 @@ +httpHeaders = $httpHeaders; $this->requestId = null; + // TODO: make this a proper constructor argument in the next major + // release. + $this->stripeCode = isset($jsonBody["error"]["code"]) ? $jsonBody["error"]["code"] : null; + if ($httpHeaders && isset($httpHeaders['Request-Id'])) { $this->requestId = $httpHeaders['Request-Id']; } } + public function getStripeCode() + { + return $this->stripeCode; + } + public function getHttpStatus() { return $this->httpStatus; diff --git a/htdocs/includes/stripe/lib/Error/Card.php b/htdocs/includes/stripe/lib/Error/Card.php index 9004db271e3..f3ff343d899 100644 --- a/htdocs/includes/stripe/lib/Error/Card.php +++ b/htdocs/includes/stripe/lib/Error/Card.php @@ -15,12 +15,16 @@ class Card extends Base ) { parent::__construct($message, $httpStatus, $httpBody, $jsonBody, $httpHeaders); $this->stripeParam = $stripeParam; + + // TODO: once Error\Base accepts the error code as an argument, pass it + // in the call to parent::__construct() and stop setting it here. $this->stripeCode = $stripeCode; // This one is not like the others because it was added later and we're // trying to do our best not to change the public interface of this class' - // constructor. We should consider changing its implementation on the - // next major version bump of this library. + // constructor. + // TODO: make this a proper constructor argument in the next major + // release. $this->declineCode = isset($jsonBody["error"]["decline_code"]) ? $jsonBody["error"]["decline_code"] : null; } @@ -29,11 +33,6 @@ class Card extends Base return $this->declineCode; } - public function getStripeCode() - { - return $this->stripeCode; - } - public function getStripeParam() { return $this->stripeParam; diff --git a/htdocs/includes/stripe/lib/Error/Idempotency.php b/htdocs/includes/stripe/lib/Error/Idempotency.php new file mode 100644 index 00000000000..ea44d12e4ea --- /dev/null +++ b/htdocs/includes/stripe/lib/Error/Idempotency.php @@ -0,0 +1,7 @@ +code = $code; + } + + public function getErrorCode() + { + return $this->code; + } +} diff --git a/htdocs/includes/stripe/lib/Error/OAuth/UnsupportedGrantType.php b/htdocs/includes/stripe/lib/Error/OAuth/UnsupportedGrantType.php new file mode 100644 index 00000000000..421adc99645 --- /dev/null +++ b/htdocs/includes/stripe/lib/Error/OAuth/UnsupportedGrantType.php @@ -0,0 +1,11 @@ +sigHeader = $sigHeader; + } + + public function getSigHeader() + { + return $this->sigHeader; + } +} diff --git a/htdocs/includes/stripe/lib/Event.php b/htdocs/includes/stripe/lib/Event.php index 6a1ed6c44ba..2add5ce11be 100644 --- a/htdocs/includes/stripe/lib/Event.php +++ b/htdocs/includes/stripe/lib/Event.php @@ -12,32 +12,103 @@ namespace Stripe; * @property mixed $data * @property bool $livemode * @property int $pending_webhooks - * @property string $request + * @property mixed $request * @property string $type * * @package Stripe */ class Event extends ApiResource { - /** - * @param string $id The ID of the event to retrieve. - * @param array|string|null $opts - * - * @return Event + /** + * Possible string representations of event types. + * @link https://stripe.com/docs/api#event_types */ - public static function retrieve($id, $opts = null) - { - return self::_retrieve($id, $opts); - } + const ACCOUNT_UPDATED = 'account.updated'; + const ACCOUNT_APPLICATION_DEAUTHORIZED = 'account.application.deauthorized'; + const ACCOUNT_EXTERNAL_ACCOUNT_CREATED = 'account.external_account.created'; + const ACCOUNT_EXTERNAL_ACCOUNT_DELETED = 'account.external_account.deleted'; + const ACCOUNT_EXTERNAL_ACCOUNT_UPDATED = 'account.external_account.updated'; + const APPLICATION_FEE_CREATED = 'application_fee.created'; + const APPLICATION_FEE_REFUNDED = 'application_fee.refunded'; + const APPLICATION_FEE_REFUND_UPDATED = 'application_fee.refund.updated'; + const BALANCE_AVAILABLE = 'balance.available'; + const CHARGE_CAPTURED = 'charge.captured'; + const CHARGE_FAILED = 'charge.failed'; + const CHARGE_PENDING = 'charge.pending'; + const CHARGE_REFUNDED = 'charge.refunded'; + const CHARGE_SUCCEEDED = 'charge.succeeded'; + const CHARGE_UPDATED = 'charge.updated'; + const CHARGE_DISPUTE_CLOSED = 'charge.dispute.closed'; + const CHARGE_DISPUTE_CREATED = 'charge.dispute.created'; + const CHARGE_DISPUTE_FUNDS_REINSTATED = 'charge.dispute.funds_reinstated'; + const CHARGE_DISPUTE_FUNDS_WITHDRAWN = 'charge.dispute.funds_withdrawn'; + const CHARGE_DISPUTE_UPDATED = 'charge.dispute.updated'; + const CHARGE_REFUND_UPDATED = 'charge.refund.updated'; + const COUPON_CREATED = 'coupon.created'; + const COUPON_DELETED = 'coupon.deleted'; + const COUPON_UPDATED = 'coupon.updated'; + const CUSTOMER_CREATED = 'customer.created'; + const CUSTOMER_DELETED = 'customer.deleted'; + const CUSTOMER_UPDATED = 'customer.updated'; + const CUSTOMER_DISCOUNT_CREATED = 'customer.discount.created'; + const CUSTOMER_DISCOUNT_DELETED = 'customer.discount.deleted'; + const CUSTOMER_DISCOUNT_UPDATED = 'customer.discount.updated'; + const CUSTOMER_SOURCE_CREATED = 'customer.source.created'; + const CUSTOMER_SOURCE_DELETED = 'customer.source.deleted'; + const CUSTOMER_SOURCE_EXPIRING = 'customer.source.expiring'; + const CUSTOMER_SOURCE_UPDATED = 'customer.source.updated'; + const CUSTOMER_SUBSCRIPTION_CREATED = 'customer.subscription.created'; + const CUSTOMER_SUBSCRIPTION_DELETED = 'customer.subscription.deleted'; + const CUSTOMER_SUBSCRIPTION_TRIAL_WILL_END = 'customer.subscription.trial_will_end'; + const CUSTOMER_SUBSCRIPTION_UPDATED = 'customer.subscription.updated'; + const FILE_CREATED = 'file.created'; + const INVOICE_CREATED = 'invoice.created'; + const INVOICE_PAYMENT_FAILED = 'invoice.payment_failed'; + const INVOICE_PAYMENT_SUCCEEDED = 'invoice.payment_succeeded'; + const INVOICE_SENT = 'invoice.sent'; + const INVOICE_UPCOMING = 'invoice.upcoming'; + const INVOICE_UPDATED = 'invoice.updated'; + const INVOICEITEM_CREATED = 'invoiceitem.created'; + const INVOICEITEM_DELETED = 'invoiceitem.deleted'; + const INVOICEITEM_UPDATED = 'invoiceitem.updated'; + const ORDER_CREATED = 'order.created'; + const ORDER_PAYMENT_FAILED = 'order.payment_failed'; + const ORDER_PAYMENT_SUCCEEDED = 'order.payment_succeeded'; + const ORDER_UPDATED = 'order.updated'; + const ORDER_RETURN_CREATED = 'order_return.created'; + const PAYOUT_CANCELED = 'payout.canceled'; + const PAYOUT_CREATED = 'payout.created'; + const PAYOUT_FAILED = 'payout.failed'; + const PAYOUT_PAID = 'payout.paid'; + const PAYOUT_UPDATED = 'payout.updated'; + const PING = 'ping'; + const PLAN_CREATED = 'plan.created'; + const PLAN_DELETED = 'plan.deleted'; + const PLAN_UPDATED = 'plan.updated'; + const PRODUCT_CREATED = 'product.created'; + const PRODUCT_DELETED = 'product.deleted'; + const PRODUCT_UPDATED = 'product.updated'; + const RECIPIENT_CREATED = 'recipient.created'; + const RECIPIENT_DELETED = 'recipient.deleted'; + const RECIPIENT_UPDATED = 'recipient.updated'; + const REVIEW_CLOSED = 'review.closed'; + const REVIEW_OPENED = 'review.opened'; + const SIGMA_SCHEDULED_QUERY_RUN_CREATED = 'sigma.scheduled_query_run.created'; + const SKU_CREATED = 'sku.created'; + const SKU_DELETED = 'sku.deleted'; + const SKU_UPDATED = 'sku.updated'; + const SOURCE_CANCELED = 'source.canceled'; + const SOURCE_CHARGEABLE = 'source.chargeable'; + const SOURCE_FAILED = 'source.failed'; + const SOURCE_MANDATE_NOTIFICATION = 'source.mandate_notification'; + const SOURCE_TRANSACTION_CREATED = 'source.transaction.created'; + const TOPUP_CREATED = 'topup.created'; + const TOPUP_FAILED = 'topup.failed'; + const TOPUP_SUCCEEDED = 'topup.succeeded'; + const TRANSFER_CREATED = 'transfer.created'; + const TRANSFER_REVERSED = 'transfer.reversed'; + const TRANSFER_UPDATED = 'transfer.updated'; - /** - * @param array|null $params - * @param array|string|null $opts - * - * @return Collection of Events - */ - public static function all($params = null, $opts = null) - { - return self::_all($params, $opts); - } + use ApiOperations\All; + use ApiOperations\Retrieve; } diff --git a/htdocs/includes/stripe/lib/ExchangeRate.php b/htdocs/includes/stripe/lib/ExchangeRate.php new file mode 100644 index 00000000000..40763261834 --- /dev/null +++ b/htdocs/includes/stripe/lib/ExchangeRate.php @@ -0,0 +1,25 @@ +_delete($params, $opts); - } - - /** - * @param array|string|null $opts - * - * @return ExternalAccount The saved external account. - */ - public function save($opts = null) - { - return $this->_save($opts); - } - - /** - * @param array|null $params - * @param array|string|null $opts - * - * @return ExternalAccount The verified (or not) external account. - */ - public function verify($params = null, $opts = null) - { - if ($this['customer']) { - $url = $this->instanceUrl() . '/verify'; - list($response, $options) = $this->_request('post', $url, $params, $opts); - $this->refreshFrom($response, $options); - return $this; - } else { - $message = 'Only customer external accounts can be verified in this manner.'; - throw new Error\Api($message); - } - } -} diff --git a/htdocs/includes/stripe/lib/FileUpload.php b/htdocs/includes/stripe/lib/FileUpload.php index 7dc98c78d1c..aa0b733959c 100644 --- a/htdocs/includes/stripe/lib/FileUpload.php +++ b/htdocs/includes/stripe/lib/FileUpload.php @@ -16,6 +16,10 @@ namespace Stripe; */ class FileUpload extends ApiResource { + use ApiOperations\All; + use ApiOperations\Create; + use ApiOperations\Retrieve; + public static function baseUrl() { return Stripe::$apiUploadBase; @@ -25,37 +29,4 @@ class FileUpload extends ApiResource { return 'file'; } - - /** - * @param string $id The ID of the file upload to retrieve. - * @param array|string|null $opts - * - * @return FileUpload - */ - public static function retrieve($id, $opts = null) - { - return self::_retrieve($id, $opts); - } - - /** - * @param array|null $params - * @param array|string|null $opts - * - * @return FileUpload The created file upload. - */ - public static function create($params = null, $opts = null) - { - return self::_create($params, $opts); - } - - /** - * @param array|null $params - * @param array|string|null $opts - * - * @return Collection of FileUploads - */ - public static function all($params = null, $opts = null) - { - return self::_all($params, $opts); - } } diff --git a/htdocs/includes/stripe/lib/HttpClient/ClientInterface.php b/htdocs/includes/stripe/lib/HttpClient/ClientInterface.php index dc4af5d1dc2..606ddb1a597 100644 --- a/htdocs/includes/stripe/lib/HttpClient/ClientInterface.php +++ b/htdocs/includes/stripe/lib/HttpClient/ClientInterface.php @@ -11,8 +11,8 @@ interface ClientInterface * @param array $params KV pairs for parameters. Can be nested for arrays and hashes * @param boolean $hasFile Whether or not $params references a file (via an @ prefix or * CurlFile) - * @throws Error\Api & Error\ApiConnection - * @return array($rawBody, $httpStatusCode, $httpHeader) + * @throws \Stripe\Error\Api & \Stripe\Error\ApiConnection + * @return [$rawBody, $httpStatusCode, $httpHeader] */ public function request($method, $absUrl, $headers, $params, $hasFile); } diff --git a/htdocs/includes/stripe/lib/HttpClient/CurlClient.php b/htdocs/includes/stripe/lib/HttpClient/CurlClient.php index e070d324d72..6bc86e32b3a 100644 --- a/htdocs/includes/stripe/lib/HttpClient/CurlClient.php +++ b/htdocs/includes/stripe/lib/HttpClient/CurlClient.php @@ -36,6 +36,8 @@ class CurlClient implements ClientInterface protected $defaultOptions; + protected $userAgentInfo; + /** * CurlClient constructor. * @@ -49,9 +51,20 @@ class CurlClient implements ClientInterface * * @param array|callable|null $defaultOptions */ - public function __construct($defaultOptions = null) + public function __construct($defaultOptions = null, $randomGenerator = null) { $this->defaultOptions = $defaultOptions; + $this->randomGenerator = $randomGenerator ?: new Util\RandomGenerator(); + $this->initUserAgentInfo(); + } + + public function initUserAgentInfo() + { + $curlVersion = curl_version(); + $this->userAgentInfo = [ + 'httplib' => 'curl ' . $curlVersion['version'], + 'ssllib' => $curlVersion['ssl_version'], + ]; } public function getDefaultOptions() @@ -59,6 +72,11 @@ class CurlClient implements ClientInterface return $this->defaultOptions; } + public function getUserAgentInfo() + { + return $this->userAgentInfo; + } + // USER DEFINED TIMEOUTS const DEFAULT_TIMEOUT = 80; @@ -93,10 +111,9 @@ class CurlClient implements ClientInterface public function request($method, $absUrl, $headers, $params, $hasFile) { - $curl = curl_init(); $method = strtolower($method); - $opts = array(); + $opts = []; if (is_callable($this->defaultOptions)) { // call defaultOptions callback, set options to return value $opts = call_user_func_array($this->defaultOptions, func_get_args()); if (!is_array($opts)) { @@ -114,24 +131,32 @@ class CurlClient implements ClientInterface } $opts[CURLOPT_HTTPGET] = 1; if (count($params) > 0) { - $encoded = self::encode($params); + $encoded = Util\Util::urlEncode($params); $absUrl = "$absUrl?$encoded"; } } elseif ($method == 'post') { $opts[CURLOPT_POST] = 1; - $opts[CURLOPT_POSTFIELDS] = $hasFile ? $params : self::encode($params); + $opts[CURLOPT_POSTFIELDS] = $hasFile ? $params : Util\Util::urlEncode($params); } elseif ($method == 'delete') { $opts[CURLOPT_CUSTOMREQUEST] = 'DELETE'; if (count($params) > 0) { - $encoded = self::encode($params); + $encoded = Util\Util::urlEncode($params); $absUrl = "$absUrl?$encoded"; } } else { throw new Error\Api("Unrecognized method $method"); } + // It is only safe to retry network failures on POST requests if we + // add an Idempotency-Key header + if (($method == 'post') && (Stripe::$maxNetworkRetries > 0)) { + if (!isset($headers['Idempotency-Key'])) { + array_push($headers, 'Idempotency-Key: ' . $this->randomGenerator->uuid()); + } + } + // Create a callback to capture HTTP headers for the response - $rheaders = array(); + $rheaders = []; $headerCallback = function ($curl, $header_line) use (&$rheaders) { // Ignore the HTTP request line (HTTP/1.1 200 OK) if (strpos($header_line, ":") === false) { @@ -163,50 +188,63 @@ class CurlClient implements ClientInterface $opts[CURLOPT_TIMEOUT] = $this->timeout; $opts[CURLOPT_HEADERFUNCTION] = $headerCallback; $opts[CURLOPT_HTTPHEADER] = $headers; - if (!Stripe::$verifySslCerts) { + $opts[CURLOPT_CAINFO] = Stripe::getCABundlePath(); + if (!Stripe::getVerifySslCerts()) { $opts[CURLOPT_SSL_VERIFYPEER] = false; } - curl_setopt_array($curl, $opts); - $rbody = curl_exec($curl); + list($rbody, $rcode) = $this->executeRequestWithRetries($opts, $absUrl); - if (!defined('CURLE_SSL_CACERT_BADFILE')) { - define('CURLE_SSL_CACERT_BADFILE', 77); // constant not defined in PHP - } - - $errno = curl_errno($curl); - if ($errno == CURLE_SSL_CACERT || - $errno == CURLE_SSL_PEER_CERTIFICATE || - $errno == CURLE_SSL_CACERT_BADFILE - ) { - array_push( - $headers, - 'X-Stripe-Client-Info: {"ca":"using Stripe-supplied CA bundle"}' - ); - $cert = self::caBundle(); - curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); - curl_setopt($curl, CURLOPT_CAINFO, $cert); - $rbody = curl_exec($curl); - } - - if ($rbody === false) { - $errno = curl_errno($curl); - $message = curl_error($curl); - curl_close($curl); - $this->handleCurlError($absUrl, $errno, $message); - } - - $rcode = curl_getinfo($curl, CURLINFO_HTTP_CODE); - curl_close($curl); - return array($rbody, $rcode, $rheaders); + return [$rbody, $rcode, $rheaders]; } /** - * @param number $errno + * @param array $opts cURL options + */ + private function executeRequestWithRetries($opts, $absUrl) + { + $numRetries = 0; + + while (true) { + $rcode = 0; + $errno = 0; + + $curl = curl_init(); + curl_setopt_array($curl, $opts); + $rbody = curl_exec($curl); + + if ($rbody === false) { + $errno = curl_errno($curl); + $message = curl_error($curl); + } else { + $rcode = curl_getinfo($curl, CURLINFO_HTTP_CODE); + } + curl_close($curl); + + if ($this->shouldRetry($errno, $rcode, $numRetries)) { + $numRetries += 1; + $sleepSeconds = $this->sleepTime($numRetries); + usleep(intval($sleepSeconds * 1000000)); + } else { + break; + } + } + + if ($rbody === false) { + $this->handleCurlError($absUrl, $errno, $message, $numRetries); + } + + return [$rbody, $rcode]; + } + + /** + * @param string $url + * @param int $errno * @param string $message + * @param int $numRetries * @throws Error\ApiConnection */ - private function handleCurlError($url, $errno, $message) + private function handleCurlError($url, $errno, $message, $numRetries) { switch ($errno) { case CURLE_COULDNT_CONNECT: @@ -231,52 +269,66 @@ class CurlClient implements ClientInterface $msg .= " let us know at support@stripe.com."; $msg .= "\n\n(Network error [errno $errno]: $message)"; + + if ($numRetries > 0) { + $msg .= "\n\nRequest was retried $numRetries times."; + } + throw new Error\ApiConnection($msg); } - private static function caBundle() + /** + * Checks if an error is a problem that we should retry on. This includes both + * socket errors that may represent an intermittent problem and some special + * HTTP statuses. + * @param int $errno + * @param int $rcode + * @param int $numRetries + * @return bool + */ + private function shouldRetry($errno, $rcode, $numRetries) { - return dirname(__FILE__) . '/../../data/ca-certificates.crt'; + if ($numRetries >= Stripe::getMaxNetworkRetries()) { + return false; + } + + // Retry on timeout-related problems (either on open or read). + if ($errno === CURLE_OPERATION_TIMEOUTED) { + return true; + } + + // Destination refused the connection, the connection was reset, or a + // variety of other connection failures. This could occur from a single + // saturated server, so retry in case it's intermittent. + if ($errno === CURLE_COULDNT_CONNECT) { + return true; + } + + // 409 conflict + if ($rcode === 409) { + return true; + } + + return false; } - /** - * @param array $arr An map of param keys to values. - * @param string|null $prefix - * - * Only public for testability, should not be called outside of CurlClient - * - * @return string A querystring, essentially. - */ - public static function encode($arr, $prefix = null) + private function sleepTime($numRetries) { - if (!is_array($arr)) { - return $arr; - } + // Apply exponential backoff with $initialNetworkRetryDelay on the + // number of $numRetries so far as inputs. Do not allow the number to exceed + // $maxNetworkRetryDelay. + $sleepSeconds = min( + Stripe::getInitialNetworkRetryDelay() * 1.0 * pow(2, $numRetries - 1), + Stripe::getMaxNetworkRetryDelay() + ); - $r = array(); - foreach ($arr as $k => $v) { - if (is_null($v)) { - continue; - } + // Apply some jitter by randomizing the value in the range of + // ($sleepSeconds / 2) to ($sleepSeconds). + $sleepSeconds *= 0.5 * (1 + $this->randomGenerator->randFloat()); - if ($prefix) { - if ($k !== null && (!is_int($k) || is_array($v))) { - $k = $prefix."[".$k."]"; - } else { - $k = $prefix."[]"; - } - } + // But never sleep less than the base sleep seconds. + $sleepSeconds = max(Stripe::getInitialNetworkRetryDelay(), $sleepSeconds); - if (is_array($v)) { - $enc = self::encode($v, $k); - if ($enc) { - $r[] = $enc; - } - } else { - $r[] = urlencode($k)."=".urlencode($v); - } - } - - return implode("&", $r); + return $sleepSeconds; } } diff --git a/htdocs/includes/stripe/lib/Invoice.php b/htdocs/includes/stripe/lib/Invoice.php index e994566cd96..07d67f74a8a 100644 --- a/htdocs/includes/stripe/lib/Invoice.php +++ b/htdocs/includes/stripe/lib/Invoice.php @@ -5,54 +5,52 @@ namespace Stripe; /** * Class Invoice * + * @property string $id + * @property string $object + * @property int $amount_due + * @property int $amount_paid + * @property int $amount_remaining + * @property int $application_fee + * @property int $attempt_count + * @property bool $attempted + * @property string $billing + * @property string $charge + * @property bool $closed + * @property string $currency + * @property string $customer + * @property int $date + * @property string $description + * @property mixed $discount + * @property int $due_date + * @property int $ending_balance + * @property bool $forgiven + * @property Collection $lines + * @property bool $livemode + * @property StripeObject $metadata + * @property int $next_payment_attempt + * @property string $number + * @property bool $paid + * @property int $period_end + * @property int $period_start + * @property string $receipt_number + * @property int $starting_balance + * @property string $statement_descriptor + * @property string $subscription + * @property int $subscription_proration_date + * @property int $subtotal + * @property int $tax + * @property float $tax_percent + * @property int $total + * @property int $webhooks_delivered_at + * * @package Stripe */ class Invoice extends ApiResource { - /** - * @param array|null $params - * @param array|string|null $opts - * - * @return Invoice The created invoice. - */ - public static function create($params = null, $opts = null) - { - return self::_create($params, $opts); - } - - /** - * @param string $id The ID of the invoice to retrieve. - * @param array|string|null $opts - * - * @return Invoice - */ - public static function retrieve($id, $opts = null) - { - return self::_retrieve($id, $opts); - } - - /** - * @param array|null $params - * @param array|string|null $opts - * - * @return Collection of Invoices - */ - public static function all($params = null, $opts = null) - { - return self::_all($params, $opts); - } - - /** - * @param string $id The ID of the invoice to update. - * @param array|null $params - * @param array|string|null $options - * - * @return Invoice The updated invoice. - */ - public static function update($id, $params = null, $options = null) - { - return self::_update($id, $params, $options); - } + use ApiOperations\All; + use ApiOperations\Create; + use ApiOperations\Retrieve; + use ApiOperations\Update; /** * @param array|null $params @@ -69,23 +67,13 @@ class Invoice extends ApiResource return $obj; } - /** - * @param array|string|null $opts - * - * @return Invoice The saved invoice. - */ - public function save($opts = null) - { - return $this->_save($opts); - } - /** * @return Invoice The paid invoice. */ - public function pay($opts = null) + public function pay($params = null, $opts = null) { $url = $this->instanceUrl() . '/pay'; - list($response, $opts) = $this->_request('post', $url, null, $opts); + list($response, $opts) = $this->_request('post', $url, $params, $opts); $this->refreshFrom($response, $opts); return $this; } diff --git a/htdocs/includes/stripe/lib/InvoiceItem.php b/htdocs/includes/stripe/lib/InvoiceItem.php index ab9c4ba3327..37e39f3e105 100644 --- a/htdocs/includes/stripe/lib/InvoiceItem.php +++ b/htdocs/includes/stripe/lib/InvoiceItem.php @@ -5,73 +5,31 @@ namespace Stripe; /** * Class InvoiceItem * + * @property string $id + * @property string $object + * @property int $amount + * @property string $currency + * @property string $customer + * @property int $date + * @property string $description + * @property bool $discountable + * @property string $invoice + * @property bool $livemode + * @property StripeObject $metadata + * @property mixed $period + * @property Plan $plan + * @property bool $proration + * @property int $quantity + * @property string $subscription + * @property string $subscription_item + * * @package Stripe */ class InvoiceItem extends ApiResource { - /** - * @param string $id The ID of the invoice item to retrieve. - * @param array|string|null $opts - * - * @return InvoiceItem - */ - public static function retrieve($id, $opts = null) - { - return self::_retrieve($id, $opts); - } - - /** - * @param array|null $params - * @param array|string|null $opts - * - * @return Collection of InvoiceItems - */ - public static function all($params = null, $opts = null) - { - return self::_all($params, $opts); - } - - /** - * @param array|null $params - * @param array|string|null $opts - * - * @return InvoiceItem The created invoice item. - */ - public static function create($params = null, $opts = null) - { - return self::_create($params, $opts); - } - - /** - * @param string $id The ID of the invoice item to update. - * @param array|null $params - * @param array|string|null $options - * - * @return InvoiceItem The updated invoice item. - */ - public static function update($id, $params = null, $options = null) - { - return self::_update($id, $params, $options); - } - - /** - * @param array|string|null $opts - * - * @return InvoiceItem The saved invoice item. - */ - public function save($opts = null) - { - return $this->_save($opts); - } - - /** - * @param array|null $params - * @param array|string|null $opts - * - * @return InvoiceItem The deleted invoice item. - */ - public function delete($params = null, $opts = null) - { - return $this->_delete($params, $opts); - } + use ApiOperations\All; + use ApiOperations\Create; + use ApiOperations\Delete; + use ApiOperations\Retrieve; + use ApiOperations\Update; } diff --git a/htdocs/includes/stripe/lib/JsonSerializable.php b/htdocs/includes/stripe/lib/JsonSerializable.php deleted file mode 100644 index 2fdf8526703..00000000000 --- a/htdocs/includes/stripe/lib/JsonSerializable.php +++ /dev/null @@ -1,18 +0,0 @@ -request( + 'post', + '/oauth/token', + $params, + null + ); + return Util\Util::convertToStripeObject($response->json, $opts); + } + + /** + * Disconnects an account from your platform. + * + * @param array|null $params + * @param array|null $opts + * + * @return StripeObject Object containing the response from the API. + */ + public static function deauthorize($params = null, $opts = null) + { + $params = $params ?: []; + $base = ($opts && array_key_exists('connect_base', $opts)) ? $opts['connect_base'] : Stripe::$connectBase; + $requestor = new ApiRequestor(null, $base); + $params['client_id'] = self::_getClientId($params); + list($response, $apiKey) = $requestor->request( + 'post', + '/oauth/deauthorize', + $params, + null + ); + return Util\Util::convertToStripeObject($response->json, $opts); + } + + private static function _getClientId($params = null) + { + $clientId = ($params && array_key_exists('client_id', $params)) ? $params['client_id'] : null; + if ($clientId === null) { + $clientId = Stripe::getClientId(); + } + if ($clientId === null) { + $msg = 'No client_id provided. (HINT: set your client_id using ' + . '"Stripe::setClientId()". You can find your client_ids ' + . 'in your Stripe dashboard at ' + . 'https://dashboard.stripe.com/account/applications/settings, ' + . 'after registering your account as a platform. See ' + . 'https://stripe.com/docs/connect/standard-accounts for details, ' + . 'or email support@stripe.com if you have any questions.'; + throw new Error\Authentication($msg); + } + return $clientId; + } +} diff --git a/htdocs/includes/stripe/lib/Order.php b/htdocs/includes/stripe/lib/Order.php index 9fc65e2e166..14215bc9ee3 100644 --- a/htdocs/includes/stripe/lib/Order.php +++ b/htdocs/includes/stripe/lib/Order.php @@ -5,64 +5,38 @@ namespace Stripe; /** * Class Order * + * @property string $id + * @property string $object + * @property int $amount + * @property int $amount_returned + * @property string $application + * @property int $application_fee + * @property string $charge + * @property int $created + * @property string $currency + * @property string $customer + * @property string $email + * @property string $external_coupon_code + * @property mixed $items + * @property bool $livemode + * @property StripeObject $metadata + * @property Collection $returns + * @property string $selected_shipping_method + * @property mixed $shipping + * @property mixed $shipping_methods + * @property string $status + * @property mixed $status_transitions + * @property int $updated + * @property string $upstream_id + * * @package Stripe */ class Order extends ApiResource { - /** - * @param string $id The ID of the Order to retrieve. - * @param array|string|null $opts - * - * @return Order - */ - public static function retrieve($id, $opts = null) - { - return self::_retrieve($id, $opts); - } - - /** - * @param array|null $params - * @param array|string|null $opts - * - * @return Order The created Order. - */ - public static function create($params = null, $opts = null) - { - return self::_create($params, $opts); - } - - /** - * @param string $id The ID of the order to update. - * @param array|null $params - * @param array|string|null $options - * - * @return Order The updated order. - */ - public static function update($id, $params = null, $options = null) - { - return self::_update($id, $params, $options); - } - - /** - * @param array|string|null $opts - * - * @return Order The saved Order. - */ - public function save($opts = null) - { - return $this->_save($opts); - } - - /** - * @param array|null $params - * @param array|string|null $opts - * - * @return Collection of Orders - */ - public static function all($params = null, $opts = null) - { - return self::_all($params, $opts); - } + use ApiOperations\All; + use ApiOperations\Create; + use ApiOperations\Retrieve; + use ApiOperations\Update; /** * @return Order The paid order. diff --git a/htdocs/includes/stripe/lib/OrderReturn.php b/htdocs/includes/stripe/lib/OrderReturn.php index aa7fd4e9b99..45a69e37835 100644 --- a/htdocs/includes/stripe/lib/OrderReturn.php +++ b/htdocs/includes/stripe/lib/OrderReturn.php @@ -9,25 +9,17 @@ namespace Stripe; */ class OrderReturn extends ApiResource { - /** - * @param string $id The ID of the OrderReturn to retrieve. - * @param array|string|null $opts - * - * @return Order - */ - public static function retrieve($id, $opts = null) - { - return self::_retrieve($id, $opts); - } + use ApiOperations\All; + use ApiOperations\Retrieve; /** - * @param array|null $params - * @param array|string|null $opts + * This is a special case because the order returns endpoint has an + * underscore in it. The parent `className` function strips underscores. * - * @return Collection of OrderReturns + * @return string The name of the class. */ - public static function all($params = null, $opts = null) + public static function className() { - return self::_all($params, $opts); + return 'order_return'; } } diff --git a/htdocs/includes/stripe/lib/Payout.php b/htdocs/includes/stripe/lib/Payout.php index 90dd0fcecc3..0849cae3f61 100644 --- a/htdocs/includes/stripe/lib/Payout.php +++ b/htdocs/includes/stripe/lib/Payout.php @@ -17,7 +17,7 @@ namespace Stripe; * @property string $failure_code * @property string $failure_message * @property bool $livemode - * @property mixed $metadata + * @property StripeObject $metadata * @property string $method * @property string $recipient * @property string $source_type @@ -29,50 +29,10 @@ namespace Stripe; */ class Payout extends ApiResource { - /** - * @param string $id The ID of the payout to retrieve. - * @param array|string|null $opts - * - * @return Payout - */ - public static function retrieve($id, $opts = null) - { - return self::_retrieve($id, $opts); - } - - /** - * @param array|null $params - * @param array|string|null $opts - * - * @return Collection of Payouts - */ - public static function all($params = null, $opts = null) - { - return self::_all($params, $opts); - } - - /** - * @param array|null $params - * @param array|string|null $opts - * - * @return Payout The created payout. - */ - public static function create($params = null, $opts = null) - { - return self::_create($params, $opts); - } - - /** - * @param string $id The ID of the payout to update. - * @param array|null $params - * @param array|string|null $options - * - * @return Payout The updated payout. - */ - public static function update($id, $params = null, $options = null) - { - return self::_update($id, $params, $options); - } + use ApiOperations\All; + use ApiOperations\Create; + use ApiOperations\Retrieve; + use ApiOperations\Update; /** * @return Payout The canceled payout. @@ -84,14 +44,4 @@ class Payout extends ApiResource $this->refreshFrom($response, $opts); return $this; } - - /** - * @param array|string|null $opts - * - * @return Payout The saved payout. - */ - public function save($opts = null) - { - return $this->_save($opts); - } } diff --git a/htdocs/includes/stripe/lib/Plan.php b/htdocs/includes/stripe/lib/Plan.php index b911e17cbe6..8b0126b6f2d 100644 --- a/htdocs/includes/stripe/lib/Plan.php +++ b/htdocs/includes/stripe/lib/Plan.php @@ -7,84 +7,24 @@ namespace Stripe; * * @package Stripe * - * @property $id - * @property $object - * @property $amount - * @property $created - * @property $currency - * @property $interval - * @property $interval_count - * @property $livemode - * @property AttachedObject $metadata - * @property $name - * @property $statement_descriptor - * @property $trial_period_days + * @property string $id + * @property string $object + * @property int $amount + * @property int $created + * @property string $currency + * @property string $interval + * @property int $interval_count + * @property bool $livemode + * @property StripeObject $metadata + * @property string $nickname + * @property string $product + * @property int $trial_period_days */ class Plan extends ApiResource { - /** - * @param string $id The ID of the plan to retrieve. - * @param array|string|null $opts - * - * @return Plan - */ - public static function retrieve($id, $opts = null) - { - return self::_retrieve($id, $opts); - } - - /** - * @param array|null $params - * @param array|string|null $opts - * - * @return Plan The created plan. - */ - public static function create($params = null, $opts = null) - { - return self::_create($params, $opts); - } - - /** - * @param string $id The ID of the plan to update. - * @param array|null $params - * @param array|string|null $options - * - * @return Plan The updated plan. - */ - public static function update($id, $params = null, $options = null) - { - return self::_update($id, $params, $options); - } - - /** - * @param array|null $params - * @param array|string|null $opts - * - * @return Plan The deleted plan. - */ - public function delete($params = null, $opts = null) - { - return $this->_delete($params, $opts); - } - - /** - * @param array|string|null $opts - * - * @return Plan The saved plan. - */ - public function save($opts = null) - { - return $this->_save($opts); - } - - /** - * @param array|null $params - * @param array|string|null $opts - * - * @return Collection of Plans - */ - public static function all($params = null, $opts = null) - { - return self::_all($params, $opts); - } + use ApiOperations\All; + use ApiOperations\Create; + use ApiOperations\Delete; + use ApiOperations\Retrieve; + use ApiOperations\Update; } diff --git a/htdocs/includes/stripe/lib/Product.php b/htdocs/includes/stripe/lib/Product.php index 2fdd22a0827..20bd4e1ae44 100644 --- a/htdocs/includes/stripe/lib/Product.php +++ b/htdocs/includes/stripe/lib/Product.php @@ -5,73 +5,33 @@ namespace Stripe; /** * Class Product * + * @property string $id + * @property string $object + * @property bool $active + * @property string[] $attributes + * @property string $caption + * @property int $created + * @property string[] $deactivate_on + * @property string $description + * @property array $images + * @property bool $livemode + * @property StripeObject $metadata + * @property string $name + * @property mixed $package_dimensions + * @property bool $shippable + * @property Collection $skus + * @property string $statement_descriptor + * @property string $type + * @property int $updated + * @property string $url + * * @package Stripe */ class Product extends ApiResource { - /** - * @param string $id The ID of the Product to retrieve. - * @param array|string|null $opts - * - * @return Product - */ - public static function retrieve($id, $opts = null) - { - return self::_retrieve($id, $opts); - } - - /** - * @param array|null $params - * @param array|string|null $opts - * - * @return Product The created Product. - */ - public static function create($params = null, $opts = null) - { - return self::_create($params, $opts); - } - - /** - * @param string $id The ID of the product to update. - * @param array|null $params - * @param array|string|null $options - * - * @return Product The updated product. - */ - public static function update($id, $params = null, $options = null) - { - return self::_update($id, $params, $options); - } - - /** - * @param array|string|null $opts - * - * @return Product The saved Product. - */ - public function save($opts = null) - { - return $this->_save($opts); - } - - /** - * @param array|null $params - * @param array|string|null $opts - * - * @return Collection of Products - */ - public static function all($params = null, $opts = null) - { - return self::_all($params, $opts); - } - - /** - * @param array|null $params - * @param array|string|null $opts - * - * @return Product The deleted product. - */ - public function delete($params = null, $opts = null) - { - return $this->_delete($params, $opts); - } + use ApiOperations\All; + use ApiOperations\Create; + use ApiOperations\Delete; + use ApiOperations\Retrieve; + use ApiOperations\Update; } diff --git a/htdocs/includes/stripe/lib/Recipient.php b/htdocs/includes/stripe/lib/Recipient.php index 04bcb7bb289..9ec6a1ec847 100644 --- a/htdocs/includes/stripe/lib/Recipient.php +++ b/htdocs/includes/stripe/lib/Recipient.php @@ -9,71 +9,11 @@ namespace Stripe; */ class Recipient extends ApiResource { - /** - * @param string $id The ID of the recipient to retrieve. - * @param array|string|null $opts - * - * @return Recipient - */ - public static function retrieve($id, $opts = null) - { - return self::_retrieve($id, $opts); - } - - /** - * @param array|null $params - * @param array|string|null $opts - * - * @return Collection of Recipients - */ - public static function all($params = null, $opts = null) - { - return self::_all($params, $opts); - } - - /** - * @param array|null $params - * @param array|string|null $opts - * - * @return Recipient The created recipient. - */ - public static function create($params = null, $opts = null) - { - return self::_create($params, $opts); - } - - /** - * @param string $id The ID of the recipient to update. - * @param array|null $params - * @param array|string|null $options - * - * @return Recipient The updated recipient. - */ - public static function update($id, $params = null, $options = null) - { - return self::_update($id, $params, $options); - } - - /** - * @param array|string|null $opts - * - * @return Recipient The saved recipient. - */ - public function save($opts = null) - { - return $this->_save($opts); - } - - /** - * @param array|null $params - * - * @return Recipient The deleted recipient. - */ - public function delete($params = null, $opts = null) - { - return $this->_delete($params, $opts); - } - + use ApiOperations\All; + use ApiOperations\Create; + use ApiOperations\Delete; + use ApiOperations\Retrieve; + use ApiOperations\Update; /** * @param array|null $params @@ -82,9 +22,7 @@ class Recipient extends ApiResource */ public function transfers($params = null) { - if ($params === null) { - $params = array(); - } + $params = $params ?: []; $params['recipient'] = $this->id; $transfers = Transfer::all($params, $this->_opts); return $transfers; diff --git a/htdocs/includes/stripe/lib/RecipientTransfer.php b/htdocs/includes/stripe/lib/RecipientTransfer.php index f4e46db38dd..610514dc329 100644 --- a/htdocs/includes/stripe/lib/RecipientTransfer.php +++ b/htdocs/includes/stripe/lib/RecipientTransfer.php @@ -20,7 +20,7 @@ namespace Stripe; * @property string $failure_code * @property string $failure_message * @property bool $livemode - * @property mixed $metadata + * @property StripeObject $metadata * @property string $method * @property string $recipient * @property mixed $reversals diff --git a/htdocs/includes/stripe/lib/Refund.php b/htdocs/includes/stripe/lib/Refund.php index b4e0e76a7b0..0288895d68d 100644 --- a/htdocs/includes/stripe/lib/Refund.php +++ b/htdocs/includes/stripe/lib/Refund.php @@ -8,11 +8,13 @@ namespace Stripe; * @property string $id * @property string $object * @property int $amount - * @property mixed $balance_transaction + * @property string $balance_transaction * @property string $charge * @property int $created * @property string $currency - * @property mixed $metadata + * @property string $failure_balance_transaction + * @property string failure_reason + * @property StripeObject $metadata * @property mixed $reason * @property mixed $receipt_number * @property string $status @@ -21,59 +23,8 @@ namespace Stripe; */ class Refund extends ApiResource { - - /** - * @param string $id The ID of the refund to retrieve. - * @param array|string|null $options - * - * @return Refund - */ - public static function retrieve($id, $options = null) - { - return self::_retrieve($id, $options); - } - - /** - * @param string $id The ID of the refund to update. - * @param array|null $params - * @param array|string|null $options - * - * @return Refund The updated refund. - */ - public static function update($id, $params = null, $options = null) - { - return self::_update($id, $params, $options); - } - - /** - * @param array|null $params - * @param array|string|null $options - * - * @return Collection of Refunds - */ - public static function all($params = null, $options = null) - { - return self::_all($params, $options); - } - - /** - * @param array|null $params - * @param array|string|null $options - * - * @return Refund The created refund. - */ - public static function create($params = null, $options = null) - { - return self::_create($params, $options); - } - - /** - * @param array|string|null $opts - * - * @return Refund The saved refund. - */ - public function save($opts = null) - { - return $this->_save($opts); - } + use ApiOperations\All; + use ApiOperations\Create; + use ApiOperations\Retrieve; + use ApiOperations\Update; } diff --git a/htdocs/includes/stripe/lib/SKU.php b/htdocs/includes/stripe/lib/SKU.php index 7089604e62a..1f35da4c759 100644 --- a/htdocs/includes/stripe/lib/SKU.php +++ b/htdocs/includes/stripe/lib/SKU.php @@ -5,73 +5,28 @@ namespace Stripe; /** * Class SKU * + * @property string $id + * @property string $object + * @property bool $active + * @property mixed $attributes + * @property int $created + * @property string $currency + * @property string $image + * @property mixed $inventory + * @property bool $livemode + * @property StripeObject $metadata + * @property mixed $package_dimensions + * @property int $price + * @property string $product + * @property int $updated + * * @package Stripe */ class SKU extends ApiResource { - /** - * @param string $id The ID of the SKU to retrieve. - * @param array|string|null $opts - * - * @return SKU - */ - public static function retrieve($id, $opts = null) - { - return self::_retrieve($id, $opts); - } - - /** - * @param array|null $params - * @param array|string|null $opts - * - * @return SKU The created SKU. - */ - public static function create($params = null, $opts = null) - { - return self::_create($params, $opts); - } - - /** - * @param string $id The ID of the SKU to update. - * @param array|null $params - * @param array|string|null $options - * - * @return SKU The updated SKU. - */ - public static function update($id, $params = null, $options = null) - { - return self::_update($id, $params, $options); - } - - /** - * @param array|string|null $opts - * - * @return SKU The saved SKU. - */ - public function save($opts = null) - { - return $this->_save($opts); - } - - /** - * @param array|null $params - * @param array|string|null $opts - * - * @return Collection of SKUs - */ - public static function all($params = null, $opts = null) - { - return self::_all($params, $opts); - } - - /** - * @param array|null $params - * @param array|string|null $opts - * - * @return SKU The deleted sku. - */ - public function delete($params = null, $opts = null) - { - return $this->_delete($params, $opts); - } + use ApiOperations\All; + use ApiOperations\Create; + use ApiOperations\Delete; + use ApiOperations\Retrieve; + use ApiOperations\Update; } diff --git a/htdocs/includes/stripe/lib/Source.php b/htdocs/includes/stripe/lib/Source.php index 946586dec45..4a889c5a4e5 100644 --- a/htdocs/includes/stripe/lib/Source.php +++ b/htdocs/includes/stripe/lib/Source.php @@ -5,72 +5,39 @@ namespace Stripe; /** * Class Source * + * @property string $id + * @property string $object + * @property int $amount + * @property string $client_secret + * @property mixed $code_verification + * @property int $created + * @property string $currency + * @property string $flow + * @property bool $livemode + * @property StripeObject $metadata + * @property mixed $owner + * @property mixed $receiver + * @property mixed $redirect + * @property string $statement_descriptor + * @property string $status + * @property string $type + * @property string $usage + * * @package Stripe */ class Source extends ApiResource { - /** - * @param string $id The ID of the Source to retrieve. - * @param array|string|null $opts - * - * @return Source - */ - public static function retrieve($id, $opts = null) - { - return self::_retrieve($id, $opts); - } + use ApiOperations\Create; + use ApiOperations\Retrieve; + use ApiOperations\Update; /** - * @param array|null $params - * @param array|string|null $opts - * - * @return Collection of Sources - */ - public static function all($params = null, $opts = null) - { - return self::_all($params, $opts); - } - - /** - * @param array|null $params - * @param array|string|null $opts - * - * @return Source The created Source. - */ - public static function create($params = null, $opts = null) - { - return self::_create($params, $opts); - } - - /** - * @param string $id The ID of the source to update. * @param array|null $params * @param array|string|null $options * - * @return Source The updated source. + * @return Source The detached source. */ - public static function update($id, $params = null, $options = null) - { - return self::_update($id, $params, $options); - } - - /** - * @param array|string|null $opts - * - * @return Source The saved source. - */ - public function save($opts = null) - { - return $this->_save($opts); - } - - /** - * @param array|null $params - * @param array|string|null $opts - * - * @return Source The deleted source. - */ - public function delete($params = null, $options = null) + public function detach($params = null, $options = null) { self::_validateParams($params); @@ -92,9 +59,8 @@ class Source extends ApiResource $this->refreshFrom($response, $opts); return $this; } else { - $message = "Source objects cannot be deleted, they can only be " - . "detached from customer objects. This source object does not " - . "appear to be currently attached to a customer object."; + $message = "This source object does not appear to be currently attached " + . "to a customer object."; throw new Error\Api($message); } } @@ -103,7 +69,35 @@ class Source extends ApiResource * @param array|null $params * @param array|string|null $options * - * @return BankAccount The verified bank account. + * @return Source The detached source. + * + * @deprecated Use the `detach` method instead. + */ + public function delete($params = null, $options = null) + { + $this->detach($params, $options); + } + + /** + * @param array|null $params + * @param array|string|null $options + * + * @return Collection The list of source transactions. + */ + public function sourceTransactions($params = null, $options = null) + { + $url = $this->instanceUrl() . '/source_transactions'; + list($response, $opts) = $this->_request('get', $url, $params, $options); + $obj = Util\Util::convertToStripeObject($response, $opts); + $obj->setLastResponse($response); + return $obj; + } + + /** + * @param array|null $params + * @param array|string|null $options + * + * @return Source The verified source. */ public function verify($params = null, $options = null) { diff --git a/htdocs/includes/stripe/lib/SourceTransaction.php b/htdocs/includes/stripe/lib/SourceTransaction.php new file mode 100644 index 00000000000..a0c8d776b9a --- /dev/null +++ b/htdocs/includes/stripe/lib/SourceTransaction.php @@ -0,0 +1,13 @@ +_retrieveOptions) = Util\Util::normalizeId($id); + $this->_opts = Util\RequestOptions::parse($opts); + $this->_originalValues = []; + $this->_values = []; + $this->_unsavedValues = new Util\Set(); + $this->_transientValues = new Util\Set(); + if ($id !== null) { + $this->_values['id'] = $id; + } + } + + // Standard accessor magic methods + public function __set($k, $v) + { + if (static::getPermanentAttributes()->includes($k)) { + throw new \InvalidArgumentException( + "Cannot set $k on this object. HINT: you can't set: " . + join(', ', static::getPermanentAttributes()->toArray()) + ); + } + + if ($v === "") { + throw new \InvalidArgumentException( + 'You cannot set \''.$k.'\'to an empty string. ' + .'We interpret empty strings as NULL in requests. ' + .'You may set obj->'.$k.' = NULL to delete the property' + ); + } + + $this->_values[$k] = Util\Util::convertToStripeObject($v, $this->_opts); + $this->dirtyValue($this->_values[$k]); + $this->_unsavedValues->add($k); + } + + public function __isset($k) + { + return isset($this->_values[$k]); + } + + public function __unset($k) + { + unset($this->_values[$k]); + $this->_transientValues->add($k); + $this->_unsavedValues->discard($k); + } + + public function &__get($k) + { + // function should return a reference, using $nullval to return a reference to null + $nullval = null; + if (!empty($this->_values) && array_key_exists($k, $this->_values)) { + return $this->_values[$k]; + } else if (!empty($this->_transientValues) && $this->_transientValues->includes($k)) { + $class = get_class($this); + $attrs = join(', ', array_keys($this->_values)); + $message = "Stripe Notice: Undefined property of $class instance: $k. " + . "HINT: The $k attribute was set in the past, however. " + . "It was then wiped when refreshing the object " + . "with the result returned by Stripe's API, " + . "probably as a result of a save(). The attributes currently " + . "available on this object are: $attrs"; + Stripe::getLogger()->error($message); + return $nullval; + } else { + $class = get_class($this); + Stripe::getLogger()->error("Stripe Notice: Undefined property of $class instance: $k"); + return $nullval; + } + } + + // Magic method for var_dump output. Only works with PHP >= 5.6 + public function __debugInfo() + { + return $this->_values; + } + + // ArrayAccess methods + public function offsetSet($k, $v) + { + $this->$k = $v; + } + + public function offsetExists($k) + { + return array_key_exists($k, $this->_values); + } + + public function offsetUnset($k) + { + unset($this->$k); + } + + public function offsetGet($k) + { + return array_key_exists($k, $this->_values) ? $this->_values[$k] : null; + } + + // Countable method + public function count() + { + return count($this->_values); + } + + public function keys() + { + return array_keys($this->_values); + } + + public function values() + { + return array_values($this->_values); + } + + /** + * This unfortunately needs to be public to be used in Util\Util + * + * @param array $values + * @param null|string|array|Util\RequestOptions $opts + * + * @return StripeObject The object constructed from the given values. + */ + public static function constructFrom($values, $opts = null) + { + $obj = new static(isset($values['id']) ? $values['id'] : null); + $obj->refreshFrom($values, $opts); + return $obj; + } + + /** + * Refreshes this object using the provided values. + * + * @param array $values + * @param null|string|array|Util\RequestOptions $opts + * @param boolean $partial Defaults to false. + */ + public function refreshFrom($values, $opts, $partial = false) + { + $this->_opts = Util\RequestOptions::parse($opts); + + $this->_originalValues = self::deepCopy($values); + + if ($values instanceof StripeObject) { + $values = $values->__toArray(true); + } + + // Wipe old state before setting new. This is useful for e.g. updating a + // customer, where there is no persistent card parameter. Mark those values + // which don't persist as transient + if ($partial) { + $removed = new Util\Set(); + } else { + $removed = new Util\Set(array_diff(array_keys($this->_values), array_keys($values))); + } + + foreach ($removed->toArray() as $k) { + unset($this->$k); + } + + $this->updateAttributes($values, $opts, false); + foreach ($values as $k => $v) { + $this->_transientValues->discard($k); + $this->_unsavedValues->discard($k); + } + } + + /** + * Mass assigns attributes on the model. + * + * @param array $values + * @param null|string|array|Util\RequestOptions $opts + * @param boolean $dirty Defaults to true. + */ + public function updateAttributes($values, $opts = null, $dirty = true) + { + foreach ($values as $k => $v) { + // Special-case metadata to always be cast as a StripeObject + // This is necessary in case metadata is empty, as PHP arrays do + // not differentiate between lists and hashes, and we consider + // empty arrays to be lists. + if ($k === "metadata") { + $this->_values[$k] = StripeObject::constructFrom($v, $opts); + } else { + $this->_values[$k] = Util\Util::convertToStripeObject($v, $opts); + } + if ($dirty) { + $this->dirtyValue($this->_values[$k]); + } + $this->_unsavedValues->add($k); + } + } + + /** + * @return array A recursive mapping of attributes to values for this object, + * including the proper value for deleted attributes. + */ + public function serializeParameters($force = false) + { + $updateParams = []; + + foreach ($this->_values as $k => $v) { + // There are a few reasons that we may want to add in a parameter for + // update: + // + // 1. The `$force` option has been set. + // 2. We know that it was modified. + // 3. Its value is a StripeObject. A StripeObject may contain modified + // values within in that its parent StripeObject doesn't know about. + // + $original = array_key_exists($k, $this->_originalValues) ? $this->_originalValues[$k] : null; + $unsaved = $this->_unsavedValues->includes($k); + if ($force || $unsaved || $v instanceof StripeObject) { + $updateParams[$k] = $this->serializeParamsValue( + $this->_values[$k], + $original, + $unsaved, + $force, + $k + ); + } + } + + // a `null` that makes it out of `serializeParamsValue` signals an empty + // value that we shouldn't appear in the serialized form of the object + $updateParams = array_filter( + $updateParams, + function ($v) { + return $v !== null; + } + ); + + return $updateParams; + } + + + public function serializeParamsValue($value, $original, $unsaved, $force, $key = null) + { + // The logic here is that essentially any object embedded in another + // object that had a `type` is actually an API resource of a different + // type that's been included in the response. These other resources must + // be updated from their proper endpoints, and therefore they are not + // included when serializing even if they've been modified. + // + // There are _some_ known exceptions though. + // + // For example, if the value is unsaved (meaning the user has set it), and + // it looks like the API resource is persisted with an ID, then we include + // the object so that parameters are serialized with a reference to its + // ID. + // + // Another example is that on save API calls it's sometimes desirable to + // update a customer's default source by setting a new card (or other) + // object with `->source=` and then saving the customer. The + // `saveWithParent` flag to override the default behavior allows us to + // handle these exceptions. + // + // We throw an error if a property was set explicitly but we can't do + // anything with it because the integration is probably not working as the + // user intended it to. + if ($value === null) { + return ""; + } elseif (($value instanceof APIResource) && (!$value->saveWithParent)) { + if (!$unsaved) { + return null; + } elseif (isset($value->id)) { + return $value; + } else { + throw new \InvalidArgumentException( + "Cannot save property `$key` containing an API resource of type " . + get_class($value) . ". It doesn't appear to be persisted and is " . + "not marked as `saveWithParent`." + ); + } + } elseif (is_array($value)) { + if (Util\Util::isList($value)) { + // Sequential array, i.e. a list + $update = []; + foreach ($value as $v) { + array_push($update, $this->serializeParamsValue($v, null, true, $force)); + } + // This prevents an array that's unchanged from being resent. + if ($update !== $this->serializeParamsValue($original, null, true, $force, $key)) { + return $update; + } + } else { + // Associative array, i.e. a map + return Util\Util::convertToStripeObject($value, $this->_opts)->serializeParameters(); + } + } elseif ($value instanceof StripeObject) { + $update = $value->serializeParameters($force); + if ($original && $unsaved) { + $update = array_merge(self::emptyValues($original), $update); + } + return $update; + } else { + return $value; + } + } + + public function jsonSerialize() + { + return $this->__toArray(true); + } + + public function __toJSON() + { + return json_encode($this->__toArray(true), JSON_PRETTY_PRINT); + } + + public function __toString() + { + $class = get_class($this); + return $class . ' JSON: ' . $this->__toJSON(); + } + + public function __toArray($recursive = false) + { + if ($recursive) { + return Util\Util::convertStripeObjectToArray($this->_values); + } else { + return $this->_values; + } + } + + /** + * Sets all keys within the StripeObject as unsaved so that they will be + * included with an update when `serializeParameters` is called. This + * method is also recursive, so any StripeObjects contained as values or + * which are values in a tenant array are also marked as dirty. + */ + public function dirty() + { + $this->_unsavedValues = new Util\Set(array_keys($this->_values)); + foreach ($this->_values as $k => $v) { + $this->dirtyValue($v); + } + } + + protected function dirtyValue($value) + { + if (is_array($value)) { + foreach ($value as $v) { + $this->dirtyValue($v); + } + } elseif ($value instanceof StripeObject) { + $value->dirty(); + } + } + + /** + * Produces a deep copy of the given object including support for arrays + * and StripeObjects. + */ + protected static function deepCopy($obj) + { + if (is_array($obj)) { + $copy = []; + foreach ($obj as $k => $v) { + $copy[$k] = self::deepCopy($v); + } + return $copy; + } elseif ($obj instanceof StripeObject) { + return $obj::constructFrom( + self::deepCopy($obj->_values), + clone $obj->_opts + ); + } else { + return $obj; + } + } + + /** + * Returns a hash of empty values for all the values that are in the given + * StripeObject. + */ + public static function emptyValues($obj) + { + if (is_array($obj)) { + $values = $obj; + } elseif ($obj instanceof StripeObject) { + $values = $obj->_values; + } else { + throw new \InvalidArgumentException( + "empty_values got got unexpected object type: " . get_class($obj) + ); + } + $update = array_fill_keys(array_keys($values), ""); + return $update; } /** @@ -53,242 +440,4 @@ class StripeObject implements ArrayAccess, JsonSerializable { $this->_lastResponse = $resp; } - - protected $_opts; - protected $_values; - protected $_unsavedValues; - protected $_transientValues; - protected $_retrieveOptions; - protected $_lastResponse; - - public function __construct($id = null, $opts = null) - { - $this->_opts = $opts ? $opts : new Util\RequestOptions(); - $this->_values = array(); - $this->_unsavedValues = new Util\Set(); - $this->_transientValues = new Util\Set(); - - $this->_retrieveOptions = array(); - if (is_array($id)) { - foreach ($id as $key => $value) { - if ($key != 'id') { - $this->_retrieveOptions[$key] = $value; - } - } - $id = $id['id']; - } - - if ($id !== null) { - $this->id = $id; - } - } - - // Standard accessor magic methods - public function __set($k, $v) - { - if ($v === "") { - throw new InvalidArgumentException( - 'You cannot set \''.$k.'\'to an empty string. ' - .'We interpret empty strings as NULL in requests. ' - .'You may set obj->'.$k.' = NULL to delete the property' - ); - } - - if (self::$nestedUpdatableAttributes->includes($k) - && isset($this->$k) && $this->$k instanceof AttachedObject && is_array($v)) { - $this->$k->replaceWith($v); - } else { - // TODO: may want to clear from $_transientValues (Won't be user-visible). - $this->_values[$k] = $v; - } - if (!self::$permanentAttributes->includes($k)) { - $this->_unsavedValues->add($k); - } - } - - public function __isset($k) - { - return isset($this->_values[$k]); - } - public function __unset($k) - { - unset($this->_values[$k]); - $this->_transientValues->add($k); - $this->_unsavedValues->discard($k); - } - public function &__get($k) - { - // function should return a reference, using $nullval to return a reference to null - $nullval = null; - if (!empty($this->_values) && array_key_exists($k, $this->_values)) { - return $this->_values[$k]; - } else if (!empty($this->_transientValues) && $this->_transientValues->includes($k)) { - $class = get_class($this); - $attrs = join(', ', array_keys($this->_values)); - $message = "Stripe Notice: Undefined property of $class instance: $k. " - . "HINT: The $k attribute was set in the past, however. " - . "It was then wiped when refreshing the object " - . "with the result returned by Stripe's API, " - . "probably as a result of a save(). The attributes currently " - . "available on this object are: $attrs"; - error_log($message); - return $nullval; - } else { - $class = get_class($this); - error_log("Stripe Notice: Undefined property of $class instance: $k"); - return $nullval; - } - } - - // ArrayAccess methods - public function offsetSet($k, $v) - { - $this->$k = $v; - } - - public function offsetExists($k) - { - return array_key_exists($k, $this->_values); - } - - public function offsetUnset($k) - { - unset($this->$k); - } - public function offsetGet($k) - { - return array_key_exists($k, $this->_values) ? $this->_values[$k] : null; - } - - public function keys() - { - return array_keys($this->_values); - } - - /** - * This unfortunately needs to be public to be used in Util\Util - * - * @param array $values - * @param array $opts - * - * @return StripeObject The object constructed from the given values. - */ - public static function constructFrom($values, $opts) - { - $obj = new static(isset($values['id']) ? $values['id'] : null); - $obj->refreshFrom($values, $opts); - return $obj; - } - - /** - * Refreshes this object using the provided values. - * - * @param array $values - * @param array|Util\RequestOptions $opts - * @param boolean $partial Defaults to false. - */ - public function refreshFrom($values, $opts, $partial = false) - { - if (is_array($opts)) { - $opts = Util\RequestOptions::parse($opts); - } - - $this->_opts = $opts; - - // Wipe old state before setting new. This is useful for e.g. updating a - // customer, where there is no persistent card parameter. Mark those values - // which don't persist as transient - if ($partial) { - $removed = new Util\Set(); - } else { - $removed = array_diff(array_keys($this->_values), array_keys($values)); - } - - foreach ($removed as $k) { - if (self::$permanentAttributes->includes($k)) { - continue; - } - - unset($this->$k); - } - - foreach ($values as $k => $v) { - if (self::$permanentAttributes->includes($k) && isset($this[$k])) { - continue; - } - - if (self::$nestedUpdatableAttributes->includes($k) && is_array($v)) { - $this->_values[$k] = AttachedObject::constructFrom($v, $opts); - } else { - $this->_values[$k] = Util\Util::convertToStripeObject($v, $opts); - } - - $this->_transientValues->discard($k); - $this->_unsavedValues->discard($k); - } - } - - /** - * @return array A recursive mapping of attributes to values for this object, - * including the proper value for deleted attributes. - */ - public function serializeParameters() - { - $params = array(); - if ($this->_unsavedValues) { - foreach ($this->_unsavedValues->toArray() as $k) { - $v = $this->$k; - if ($v === null) { - $v = ''; - } - - $params[$k] = $v; - } - } - - // Get nested updates. - foreach (self::$nestedUpdatableAttributes->toArray() as $property) { - if (isset($this->$property)) { - if ($this->$property instanceof StripeObject) { - $serialized = $this->$property->serializeParameters(); - if ($serialized) { - $params[$property] = $serialized; - } - } - } - } - - return $params; - } - - public function jsonSerialize() - { - return $this->__toArray(true); - } - - public function __toJSON() - { - if (defined('JSON_PRETTY_PRINT')) { - return json_encode($this->__toArray(true), JSON_PRETTY_PRINT); - } else { - return json_encode($this->__toArray(true)); - } - } - - public function __toString() - { - $class = get_class($this); - return $class . ' JSON: ' . $this->__toJSON(); - } - - public function __toArray($recursive = false) - { - if ($recursive) { - return Util\Util::convertStripeObjectToArray($this->_values); - } else { - return $this->_values; - } - } } - -StripeObject::init(); diff --git a/htdocs/includes/stripe/lib/Subscription.php b/htdocs/includes/stripe/lib/Subscription.php index a95ab0911c9..a5a8da1beb5 100644 --- a/htdocs/includes/stripe/lib/Subscription.php +++ b/htdocs/includes/stripe/lib/Subscription.php @@ -5,10 +5,42 @@ namespace Stripe; /** * Class Subscription * + * @property string $id + * @property string $object + * @property float $application_fee_percent + * @property string $billing + * @property bool $cancel_at_period_end + * @property int $canceled_at + * @property int $created + * @property int current_period_end + * @property int current_period_start + * @property string $customer + * @property int $days_until_due + * @property mixed $discount + * @property int $ended_at + * @property Collection $items + * @property boolean $livemode + * @property StripeObject $metadata + * @property Plan $plan + * @property int $quantity + * @property int $start + * @property string $status + * @property float $tax_percent + * @property int $trial_end + * @property int $trial_start + * * @package Stripe */ class Subscription extends ApiResource { + use ApiOperations\All; + use ApiOperations\Create; + use ApiOperations\Delete { + delete as protected _delete; + } + use ApiOperations\Retrieve; + use ApiOperations\Update; + /** * These constants are possible representations of the status field. * @@ -20,49 +52,15 @@ class Subscription extends ApiResource const STATUS_TRIALING = 'trialing'; const STATUS_UNPAID = 'unpaid'; - /** - * @param string $id The ID of the subscription to retrieve. - * @param array|string|null $opts - * - * @return Subscription - */ - public static function retrieve($id, $opts = null) + public static function getSavedNestedResources() { - return self::_retrieve($id, $opts); - } - - /** - * @param array|null $params - * @param array|string|null $opts - * - * @return Collection of Subscriptions - */ - public static function all($params = null, $opts = null) - { - return self::_all($params, $opts); - } - - /** - * @param array|null $params - * @param array|string|null $opts - * - * @return Subscription The created subscription. - */ - public static function create($params = null, $opts = null) - { - return self::_create($params, $opts); - } - - /** - * @param string $id The ID of the subscription to retrieve. - * @param array|null $params - * @param array|string|null $options - * - * @return Subscription The updated subscription. - */ - public static function update($id, $params = null, $options = null) - { - return self::_update($id, $params, $options); + static $savedNestedResources = null; + if ($savedNestedResources === null) { + $savedNestedResources = new Util\Set([ + 'source', + ]); + } + return $savedNestedResources; } /** @@ -75,16 +73,6 @@ class Subscription extends ApiResource return $this->_delete($params, $opts); } - /** - * @param array|string|null $opts - * - * @return Subscription The saved subscription. - */ - public function save($opts = null) - { - return $this->_save($opts); - } - /** * @return Subscription The updated subscription. */ @@ -92,6 +80,15 @@ class Subscription extends ApiResource { $url = $this->instanceUrl() . '/discount'; list($response, $opts) = $this->_request('delete', $url); - $this->refreshFrom(array('discount' => null), $opts, true); + $this->refreshFrom(['discount' => null], $opts, true); + } + + public function serializeParameters($force = false) + { + $update = parent::serializeParameters($force); + if ($this->_unsavedValues->includes('items')) { + $update['items'] = $this->serializeParamsValue($this->items, null, true, $force, 'items'); + } + return $update; } } diff --git a/htdocs/includes/stripe/lib/SubscriptionItem.php b/htdocs/includes/stripe/lib/SubscriptionItem.php index 947d83fcb5f..9efc726aa66 100644 --- a/htdocs/includes/stripe/lib/SubscriptionItem.php +++ b/htdocs/includes/stripe/lib/SubscriptionItem.php @@ -5,10 +5,24 @@ namespace Stripe; /** * Class SubscriptionItem * + * @property string $id + * @property string $object + * @property int $created + * @property StripeObject $metadata + * @property Plan $plan + * @property int $quantity + * @property string $subscription + * * @package Stripe */ class SubscriptionItem extends ApiResource { + use ApiOperations\All; + use ApiOperations\Create; + use ApiOperations\Delete; + use ApiOperations\Retrieve; + use ApiOperations\Update; + /** * This is a special case because the subscription items endpoint has an * underscore in it. The parent `className` function strips underscores. @@ -19,70 +33,4 @@ class SubscriptionItem extends ApiResource { return 'subscription_item'; } - - /** - * @param string $id The ID of the subscription item to retrieve. - * @param array|string|null $opts - * - * @return SubscriptionItem - */ - public static function retrieve($id, $opts = null) - { - return self::_retrieve($id, $opts); - } - - /** - * @param array|null $params - * @param array|string|null $opts - * - * @return Collection of SubscriptionItems - */ - public static function all($params = null, $opts = null) - { - return self::_all($params, $opts); - } - - /** - * @param array|null $params - * @param array|string|null $opts - * - * @return SubscriptionItem The created subscription item. - */ - public static function create($params = null, $opts = null) - { - return self::_create($params, $opts); - } - - /** - * @param string $id The ID of the subscription item to update. - * @param array|null $params - * @param array|string|null $options - * - * @return SubscriptionItem The updated subscription item. - */ - public static function update($id, $params = null, $options = null) - { - return self::_update($id, $params, $options); - } - - /** - * @param array|string|null $opts - * - * @return SubscriptionItem The saved subscription item. - */ - public function save($opts = null) - { - return $this->_save($opts); - } - - /** - * @param array|null $params - * @param array|string|null $opts - * - * @return SubscriptionItem The deleted subscription item. - */ - public function delete($params = null, $opts = null) - { - return $this->_delete($params, $opts); - } } diff --git a/htdocs/includes/stripe/lib/ThreeDSecure.php b/htdocs/includes/stripe/lib/ThreeDSecure.php index 1f189b7daeb..7210bfd1f71 100644 --- a/htdocs/includes/stripe/lib/ThreeDSecure.php +++ b/htdocs/includes/stripe/lib/ThreeDSecure.php @@ -4,6 +4,9 @@ namespace Stripe; class ThreeDSecure extends ApiResource { + use ApiOperations\Create; + use ApiOperations\Retrieve; + /** * @return string The endpoint URL for the given class. */ @@ -11,26 +14,4 @@ class ThreeDSecure extends ApiResource { return "/v1/3d_secure"; } - - /** - * @param string $id The ID of the 3DS auth to retrieve. - * @param array|string|null $options - * - * @return ThreeDSecure - */ - public static function retrieve($id, $options = null) - { - return self::_retrieve($id, $options); - } - - /** - * @param array|null $params - * @param array|string|null $opts - * - * @return ThreeDSecure The created 3D Secure object. - */ - public static function create($params = null, $opts = null) - { - return self::_create($params, $opts); - } } diff --git a/htdocs/includes/stripe/lib/Token.php b/htdocs/includes/stripe/lib/Token.php index d3e5a4bcef9..fbf19bbf7b1 100644 --- a/htdocs/includes/stripe/lib/Token.php +++ b/htdocs/includes/stripe/lib/Token.php @@ -9,7 +9,7 @@ namespace Stripe; * @property string $object * @property mixed $bank_account * @property mixed $card - * @property mixed $client_ip + * @property string $client_ip * @property int $created * @property bool $livemode * @property string $type @@ -19,25 +19,6 @@ namespace Stripe; */ class Token extends ApiResource { - /** - * @param string $id The ID of the token to retrieve. - * @param array|string|null $opts - * - * @return Token - */ - public static function retrieve($id, $opts = null) - { - return self::_retrieve($id, $opts); - } - - /** - * @param array|null $params - * @param array|string|null $opts - * - * @return Token The created token. - */ - public static function create($params = null, $opts = null) - { - return self::_create($params, $opts); - } + use ApiOperations\Create; + use ApiOperations\Retrieve; } diff --git a/htdocs/includes/stripe/lib/Topup.php b/htdocs/includes/stripe/lib/Topup.php new file mode 100644 index 00000000000..33d081e3191 --- /dev/null +++ b/htdocs/includes/stripe/lib/Topup.php @@ -0,0 +1,32 @@ +_save($opts); + return self::_createNestedResource($id, static::PATH_REVERSALS, $params, $opts); + } + + /** + * @param array|null $id The ID of the transfer to which the reversal belongs. + * @param array|null $reversalId The ID of the reversal to retrieve. + * @param array|null $params + * @param array|string|null $opts + * + * @return TransferReversal + */ + public static function retrieveReversal($id, $reversalId, $params = null, $opts = null) + { + return self::_retrieveNestedResource($id, static::PATH_REVERSALS, $reversalId, $params, $opts); + } + + /** + * @param array|null $id The ID of the transfer to which the reversal belongs. + * @param array|null $reversalId The ID of the reversal to update. + * @param array|null $params + * @param array|string|null $opts + * + * @return TransferReversal + */ + public static function updateReversal($id, $reversalId, $params = null, $opts = null) + { + return self::_updateNestedResource($id, static::PATH_REVERSALS, $reversalId, $params, $opts); + } + + /** + * @param array|null $id The ID of the transfer on which to retrieve the reversals. + * @param array|null $params + * @param array|string|null $opts + * + * @return TransferReversal + */ + public static function allReversals($id, $params = null, $opts = null) + { + return self::_allNestedResources($id, static::PATH_REVERSALS, $params, $opts); } } diff --git a/htdocs/includes/stripe/lib/TransferReversal.php b/htdocs/includes/stripe/lib/TransferReversal.php index 33948c93e14..cf2a3946d85 100644 --- a/htdocs/includes/stripe/lib/TransferReversal.php +++ b/htdocs/includes/stripe/lib/TransferReversal.php @@ -11,13 +11,17 @@ namespace Stripe; * @property string $balance_transaction * @property int $created * @property string $currency - * @property mixed $metadata + * @property StripeObject $metadata * @property string $transfer * * @package Stripe */ class TransferReversal extends ApiResource { + use ApiOperations\Update { + save as protected _save; + } + /** * @return string The API URL for this Stripe transfer reversal. */ diff --git a/htdocs/includes/stripe/lib/Util/AutoPagingIterator.php b/htdocs/includes/stripe/lib/Util/AutoPagingIterator.php index 80877e6742e..167d1258a26 100644 --- a/htdocs/includes/stripe/lib/Util/AutoPagingIterator.php +++ b/htdocs/includes/stripe/lib/Util/AutoPagingIterator.php @@ -7,7 +7,7 @@ class AutoPagingIterator implements \Iterator private $lastId = null; private $page = null; private $pageOffset = 0; - private $params = array(); + private $params = []; public function __construct($collection, $params) { @@ -42,8 +42,8 @@ class AutoPagingIterator implements \Iterator $this->pageOffset += count($this->page->data); if ($this->page['has_more']) { $this->params = array_merge( - $this->params ? $this->params : array(), - array('starting_after' => $this->lastId) + $this->params ?: [], + ['starting_after' => $this->lastId] ); $this->page = $this->page->all($this->params); } else { diff --git a/htdocs/includes/stripe/lib/Util/DefaultLogger.php b/htdocs/includes/stripe/lib/Util/DefaultLogger.php new file mode 100644 index 00000000000..1a8663699f5 --- /dev/null +++ b/htdocs/includes/stripe/lib/Util/DefaultLogger.php @@ -0,0 +1,18 @@ + 0) { + throw new \Exception('DefaultLogger does not currently implement context. Please implement if you need it.'); + } + error_log($message); + } +} diff --git a/htdocs/includes/stripe/lib/Util/LoggerInterface.php b/htdocs/includes/stripe/lib/Util/LoggerInterface.php new file mode 100644 index 00000000000..bbdfc929982 --- /dev/null +++ b/htdocs/includes/stripe/lib/Util/LoggerInterface.php @@ -0,0 +1,36 @@ +apiKey = $key; $this->headers = $headers; @@ -32,6 +40,18 @@ class RequestOptions return $other_options; } + /** + * Discards all headers that we don't want to persist across requests. + */ + public function discardNonPersistentHeaders() + { + foreach ($this->headers as $k => $v) { + if (!in_array($k, self::$HEADERS_TO_PERSIST)) { + unset($this->headers[$k]); + } + } + } + /** * Unpacks an options array into an RequestOptions object * @param array|string|null $options a key => value array @@ -45,15 +65,15 @@ class RequestOptions } if (is_null($options)) { - return new RequestOptions(null, array()); + return new RequestOptions(null, []); } if (is_string($options)) { - return new RequestOptions($options, array()); + return new RequestOptions($options, []); } if (is_array($options)) { - $headers = array(); + $headers = []; $key = null; if (array_key_exists('api_key', $options)) { $key = $options['api_key']; diff --git a/htdocs/includes/stripe/lib/Util/Set.php b/htdocs/includes/stripe/lib/Util/Set.php index 2a500cd639b..d8beb8b1a39 100644 --- a/htdocs/includes/stripe/lib/Util/Set.php +++ b/htdocs/includes/stripe/lib/Util/Set.php @@ -9,9 +9,9 @@ class Set implements IteratorAggregate { private $_elts; - public function __construct($members = array()) + public function __construct($members = []) { - $this->_elts = array(); + $this->_elts = []; foreach ($members as $item) { $this->_elts[$item] = true; } diff --git a/htdocs/includes/stripe/lib/Util/Util.php b/htdocs/includes/stripe/lib/Util/Util.php index 1c8235df9bd..82fd337dd34 100644 --- a/htdocs/includes/stripe/lib/Util/Util.php +++ b/htdocs/includes/stripe/lib/Util/Util.php @@ -7,24 +7,26 @@ use Stripe\StripeObject; abstract class Util { private static $isMbstringAvailable = null; + private static $isHashEqualsAvailable = null; /** * Whether the provided array (or other) is a list rather than a dictionary. + * A list is defined as an array for which all the keys are consecutive + * integers starting at 0. Empty arrays are considered to be lists. * * @param array|mixed $array - * @return boolean True if the given object is a list. + * @return boolean true if the given object is a list. */ public static function isList($array) { if (!is_array($array)) { return false; } - - // TODO: generally incorrect, but it's correct given Stripe's response - foreach (array_keys($array) as $k) { - if (!is_numeric($k)) { - return false; - } + if ($array === []) { + return true; + } + if (array_keys($array) !== range(0, count($array) - 1)) { + return false; } return true; } @@ -37,7 +39,7 @@ abstract class Util */ public static function convertStripeObjectToArray($values) { - $results = array(); + $results = []; foreach ($values as $k => $v) { // FIXME: this is an encapsulation violation if ($k[0] == '_') { @@ -63,26 +65,34 @@ abstract class Util */ public static function convertToStripeObject($resp, $opts) { - $types = array( + $types = [ + // data structures + 'list' => 'Stripe\\Collection', + + // business objects 'account' => 'Stripe\\Account', 'alipay_account' => 'Stripe\\AlipayAccount', 'apple_pay_domain' => 'Stripe\\ApplePayDomain', - 'bank_account' => 'Stripe\\BankAccount', + 'application_fee' => 'Stripe\\ApplicationFee', + 'balance' => 'Stripe\\Balance', 'balance_transaction' => 'Stripe\\BalanceTransaction', + 'bank_account' => 'Stripe\\BankAccount', + 'bitcoin_receiver' => 'Stripe\\BitcoinReceiver', + 'bitcoin_transaction' => 'Stripe\\BitcoinTransaction', 'card' => 'Stripe\\Card', 'charge' => 'Stripe\\Charge', 'country_spec' => 'Stripe\\CountrySpec', 'coupon' => 'Stripe\\Coupon', 'customer' => 'Stripe\\Customer', 'dispute' => 'Stripe\\Dispute', - 'list' => 'Stripe\\Collection', + 'ephemeral_key' => 'Stripe\\EphemeralKey', + 'event' => 'Stripe\\Event', + 'exchange_rate' => 'Stripe\\ExchangeRate', + 'fee_refund' => 'Stripe\\ApplicationFeeRefund', + 'file_upload' => 'Stripe\\FileUpload', 'invoice' => 'Stripe\\Invoice', 'invoiceitem' => 'Stripe\\InvoiceItem', - 'event' => 'Stripe\\Event', - 'file' => 'Stripe\\FileUpload', - 'token' => 'Stripe\\Token', - 'transfer' => 'Stripe\\Transfer', - 'transfer_reversal' => 'Stripe\\TransferReversal', + 'login_link' => 'Stripe\\LoginLink', 'order' => 'Stripe\\Order', 'order_return' => 'Stripe\\OrderReturn', 'payout' => 'Stripe\\Payout', @@ -93,15 +103,17 @@ abstract class Util 'refund' => 'Stripe\\Refund', 'sku' => 'Stripe\\SKU', 'source' => 'Stripe\\Source', + 'source_transaction' => 'Stripe\\SourceTransaction', 'subscription' => 'Stripe\\Subscription', 'subscription_item' => 'Stripe\\SubscriptionItem', 'three_d_secure' => 'Stripe\\ThreeDSecure', - 'fee_refund' => 'Stripe\\ApplicationFeeRefund', - 'bitcoin_receiver' => 'Stripe\\BitcoinReceiver', - 'bitcoin_transaction' => 'Stripe\\BitcoinTransaction', - ); + 'token' => 'Stripe\\Token', + 'topup' => 'Stripe\\Topup', + 'transfer' => 'Stripe\\Transfer', + 'transfer_reversal' => 'Stripe\\TransferReversal', + ]; if (self::isList($resp)) { - $mapped = array(); + $mapped = []; foreach ($resp as $i) { array_push($mapped, self::convertToStripeObject($i, $opts)); } @@ -143,4 +155,84 @@ abstract class Util return $value; } } + + /** + * Compares two strings for equality. The time taken is independent of the + * number of characters that match. + * + * @param string $a one of the strings to compare. + * @param string $b the other string to compare. + * @return bool true if the strings are equal, false otherwise. + */ + public static function secureCompare($a, $b) + { + if (self::$isHashEqualsAvailable === null) { + self::$isHashEqualsAvailable = function_exists('hash_equals'); + } + + if (self::$isHashEqualsAvailable) { + return hash_equals($a, $b); + } else { + if (strlen($a) != strlen($b)) { + return false; + } + + $result = 0; + for ($i = 0; $i < strlen($a); $i++) { + $result |= ord($a[$i]) ^ ord($b[$i]); + } + return ($result == 0); + } + } + + /** + * @param array $arr A map of param keys to values. + * @param string|null $prefix + * + * @return string A querystring, essentially. + */ + public static function urlEncode($arr, $prefix = null) + { + if (!is_array($arr)) { + return $arr; + } + + $r = []; + foreach ($arr as $k => $v) { + if (is_null($v)) { + continue; + } + + if ($prefix) { + if ($k !== null && (!is_int($k) || is_array($v))) { + $k = $prefix."[".$k."]"; + } else { + $k = $prefix."[]"; + } + } + + if (is_array($v)) { + $enc = self::urlEncode($v, $k); + if ($enc) { + $r[] = $enc; + } + } else { + $r[] = urlencode($k)."=".urlencode($v); + } + } + + return implode("&", $r); + } + + public static function normalizeId($id) + { + if (is_array($id)) { + $params = $id; + $id = $params['id']; + unset($params['id']); + } else { + $params = []; + } + return [$id, $params]; + } } diff --git a/htdocs/includes/stripe/lib/Webhook.php b/htdocs/includes/stripe/lib/Webhook.php new file mode 100644 index 00000000000..e0ab3021a89 --- /dev/null +++ b/htdocs/includes/stripe/lib/Webhook.php @@ -0,0 +1,40 @@ + 0) && ((time() - $timestamp) > $tolerance)) { + throw new Error\SignatureVerification( + "Timestamp outside the tolerance zone", + $header, + $payload + ); + } + + return true; + } + + /** + * Extracts the timestamp in a signature header. + * + * @param string $header the signature header + * @return int the timestamp contained in the header, or -1 if no valid + * timestamp is found + */ + private static function getTimestamp($header) + { + $items = explode(",", $header); + + foreach ($items as $item) { + $itemParts = explode("=", $item, 2); + if ($itemParts[0] == "t") { + if (!is_numeric($itemParts[1])) { + return -1; + } + return intval($itemParts[1]); + } + } + + return -1; + } + + /** + * Extracts the signatures matching a given scheme in a signature header. + * + * @param string $header the signature header + * @param string $scheme the signature scheme to look for. + * @return array the list of signatures matching the provided scheme. + */ + private static function getSignatures($header, $scheme) + { + $signatures = []; + $items = explode(",", $header); + + foreach ($items as $item) { + $itemParts = explode("=", $item, 2); + if ($itemParts[0] == $scheme) { + array_push($signatures, $itemParts[1]); + } + } + + return $signatures; + } + + /** + * Computes the signature for a given payload and secret. + * + * The current scheme used by Stripe ("v1") is HMAC/SHA-256. + * + * @param string $payload the payload to sign. + * @param string $secret the secret used to generate the signature. + * @return string the signature as a string. + */ + private static function computeSignature($payload, $secret) + { + return hash_hmac("sha256", $payload, $secret); + } +} diff --git a/htdocs/includes/stripe/tests/AccountTest.php b/htdocs/includes/stripe/tests/AccountTest.php deleted file mode 100644 index 994ba6f6a8a..00000000000 --- a/htdocs/includes/stripe/tests/AccountTest.php +++ /dev/null @@ -1,300 +0,0 @@ - $id, - 'currencies_supported' => array('usd', 'aed', 'afn', '...'), - 'object' => 'account', - 'business_name' => 'Stripe.com', - 'bank_accounts' => array( - 'object' => 'list', - 'total_count' => 0, - 'has_more' => false, - 'url' => '/v1/accounts/' . $id . '/bank_accounts', - 'data' => array() - ), - 'verification' => array( - 'fields_needed' => array( - 'product_description', - 'business_url', - 'support_phone', - 'bank_account', - 'tos_acceptance.ip', - 'tos_acceptance.date' - ), - 'due_by' => null, - 'contacted' => false - ), - 'tos_acceptance' => array( - 'ip' => null, - 'date' => null, - 'user_agent' => null - ), - 'legal_entity' => array( - 'type' => null, - 'business_name' => null, - 'address' => array( - 'line1' => null, - 'line2' => null, - 'city' => null, - 'state' => null, - 'postal_code' => null, - 'country' => 'US' - ), - 'first_name' => null, - 'last_name' => null, - 'additional_owners' => null, - 'verification' => array( - 'status' => 'unverified', - 'document' => null, - 'details' => null - ) - ) - ); - } - - private function deletedAccountResponse($id) - { - return array( - 'id' => $id, - 'deleted' => true - ); - } - - public function testBasicRetrieve() - { - $this->mockRequest('GET', '/v1/account', array(), $this->managedAccountResponse('acct_ABC')); - $account = Account::retrieve(); - $this->assertSame($account->id, 'acct_ABC'); - } - - public function testIDRetrieve() - { - $this->mockRequest('GET', '/v1/accounts/acct_DEF', array(), $this->managedAccountResponse('acct_DEF')); - $account = Account::retrieve('acct_DEF'); - $this->assertSame($account->id, 'acct_DEF'); - } - - public function testCreate() - { - $this->mockRequest( - 'POST', - '/v1/accounts', - array('managed' => 'true'), - $this->managedAccountResponse('acct_ABC') - ); - $account = Account::create(array( - 'managed' => true - )); - $this->assertSame($account->id, 'acct_ABC'); - } - - public function testDelete() - { - $account = self::createTestAccount(); - - $this->mockRequest( - 'DELETE', - '/v1/accounts/' . $account->id, - array(), - $this->deletedAccountResponse('acct_ABC') - ); - $deleted = $account->delete(); - $this->assertSame($deleted->id, $account->id); - $this->assertTrue($deleted->deleted); - } - - public function testReject() - { - $account = self::createTestAccount(); - - $this->mockRequest( - 'POST', - '/v1/accounts/' . $account->id . '/reject', - array('reason' => 'fraud'), - $this->deletedAccountResponse('acct_ABC') - ); - $rejected = $account->reject(array('reason' => 'fraud')); - $this->assertSame($rejected->id, $account->id); - } - - public function testSaveLegalEntity() - { - $response = $this->managedAccountResponse('acct_ABC'); - $this->mockRequest('POST', '/v1/accounts', array('managed' => 'true'), $response); - - $response['legal_entity']['first_name'] = 'Bob'; - $this->mockRequest( - 'POST', - '/v1/accounts/acct_ABC', - array('legal_entity' => array('first_name' => 'Bob')), - $response - ); - - $account = Account::create(array('managed' => true)); - $account->legal_entity->first_name = 'Bob'; - $account->save(); - - $this->assertSame('Bob', $account->legal_entity->first_name); - } - - public function testUpdateLegalEntity() - { - $response = $this->managedAccountResponse('acct_ABC'); - $this->mockRequest('POST', '/v1/accounts', array('managed' => 'true'), $response); - - $response['legal_entity']['first_name'] = 'Bob'; - $this->mockRequest( - 'POST', - '/v1/accounts/acct_ABC', - array('legal_entity' => array('first_name' => 'Bob')), - $response - ); - - $account = Account::create(array('managed' => true)); - $account = Account::update($account['id'], array( - 'legal_entity' => array( - 'first_name' => 'Bob' - ) - )); - - $this->assertSame('Bob', $account->legal_entity->first_name); - } - - public function testCreateAdditionalOwners() - { - $request = array( - 'managed' => true, - 'country' => 'GB', - 'legal_entity' => array( - 'additional_owners' => array( - 0 => array( - 'dob' => array( - 'day' => 12, - 'month' => 5, - 'year' => 1970, - ), - 'first_name' => 'xgvukvfrde', - 'last_name' => 'rtcyvubhy', - ), - 1 => array( - 'dob' => array( - 'day' => 8, - 'month' => 4, - 'year' => 1979, - ), - 'first_name' => 'yutreuk', - 'last_name' => 'dfcgvhbjihmv', - ), - ), - ), - ); - - $acct = Account::create($request); - $response = $acct->__toArray(true); - - $req_ao = $request['legal_entity']['additional_owners']; - $resp_ao = $response['legal_entity']['additional_owners']; - - $this->assertSame($req_ao[0]['dob'], $resp_ao[0]['dob']); - $this->assertSame($req_ao[1]['dob'], $resp_ao[1]['dob']); - - $this->assertSame($req_ao[0]['first_name'], $resp_ao[0]['first_name']); - $this->assertSame($req_ao[1]['first_name'], $resp_ao[1]['first_name']); - } - - public function testUpdateAdditionalOwners() - { - $response = $this->managedAccountResponse('acct_ABC'); - $this->mockRequest('POST', '/v1/accounts', array('managed' => 'true'), $response); - - $response['legal_entity']['additional_owners'] = array(array( - 'first_name' => 'Bob', - 'last_name' => null, - 'address' => array( - 'line1' => null, - 'line2' => null, - 'city' => null, - 'state' => null, - 'postal_code' => null, - 'country' => null - ), - 'verification' => array( - 'status' => 'unverified', - 'document' => null, - 'details' => null - ) - )); - - $this->mockRequest( - 'POST', - '/v1/accounts/acct_ABC', - array('legal_entity' => array('additional_owners' => array(array('first_name' => 'Bob')))), - $response - ); - - $response['legal_entity']['additional_owners'][0]['last_name'] = 'Smith'; - $this->mockRequest( - 'POST', - '/v1/accounts/acct_ABC', - array('legal_entity' => array('additional_owners' => array(array('last_name' => 'Smith')))), - $response - ); - - $response['legal_entity']['additional_owners'][0]['last_name'] = 'Johnson'; - $this->mockRequest( - 'POST', - '/v1/accounts/acct_ABC', - array('legal_entity' => array('additional_owners' => array(array('last_name' => 'Johnson')))), - $response - ); - - $response['legal_entity']['additional_owners'][0]['verification']['document'] = 'file_123'; - $this->mockRequest( - 'POST', - '/v1/accounts/acct_ABC', - array('legal_entity' => array('additional_owners' => array(array('verification' => array('document' => 'file_123'))))), - $response - ); - - $response['legal_entity']['additional_owners'][1] = array( - 'first_name' => 'Jane', - 'last_name' => 'Doe' - ); - $this->mockRequest( - 'POST', - '/v1/accounts/acct_ABC', - array('legal_entity' => array('additional_owners' => array(1 => array('first_name' => 'Jane')))), - $response - ); - - $account = Account::create(array('managed' => true)); - $account->legal_entity->additional_owners = array(array('first_name' => 'Bob')); - $account->save(); - $this->assertSame(1, count($account->legal_entity->additional_owners)); - $this->assertSame('Bob', $account->legal_entity->additional_owners[0]->first_name); - - $account->legal_entity->additional_owners[0]->last_name = 'Smith'; - $account->save(); - $this->assertSame(1, count($account->legal_entity->additional_owners)); - $this->assertSame('Smith', $account->legal_entity->additional_owners[0]->last_name); - - $account['legal_entity']['additional_owners'][0]['last_name'] = 'Johnson'; - $account->save(); - $this->assertSame(1, count($account->legal_entity->additional_owners)); - $this->assertSame('Johnson', $account->legal_entity->additional_owners[0]->last_name); - - $account->legal_entity->additional_owners[0]->verification->document = 'file_123'; - $account->save(); - $this->assertSame('file_123', $account->legal_entity->additional_owners[0]->verification->document); - - $account->legal_entity->additional_owners[1] = array('first_name' => 'Jane'); - $account->save(); - $this->assertSame('Jane', $account->legal_entity->additional_owners[1]->first_name); - } -} diff --git a/htdocs/includes/stripe/tests/ApiRequestorTest.php b/htdocs/includes/stripe/tests/ApiRequestorTest.php deleted file mode 100644 index 859fb63a347..00000000000 --- a/htdocs/includes/stripe/tests/ApiRequestorTest.php +++ /dev/null @@ -1,68 +0,0 @@ -getMethod('_encodeObjects'); - $method->setAccessible(true); - - $a = array('customer' => new Customer('abcd')); - $enc = $method->invoke(null, $a); - $this->assertSame($enc, array('customer' => 'abcd')); - - // Preserves UTF-8 - $v = array('customer' => "☃"); - $enc = $method->invoke(null, $v); - $this->assertSame($enc, $v); - - // Encodes latin-1 -> UTF-8 - $v = array('customer' => "\xe9"); - $enc = $method->invoke(null, $v); - $this->assertSame($enc, array('customer' => "\xc3\xa9")); - } - - public function testHttpClientInjection() - { - $reflector = new \ReflectionClass('Stripe\\ApiRequestor'); - $method = $reflector->getMethod('httpClient'); - $method->setAccessible(true); - - $curl = new CurlClient(); - $curl->setTimeout(10); - ApiRequestor::setHttpClient($curl); - - $injectedCurl = $method->invoke(new ApiRequestor()); - $this->assertSame($injectedCurl, $curl); - } - - public function testDefaultHeaders() - { - $reflector = new \ReflectionClass('Stripe\\ApiRequestor'); - $method = $reflector->getMethod('_defaultHeaders'); - $method->setAccessible(true); - - // no way to stub static methods with PHPUnit 4.x :( - Stripe::setAppInfo('MyTestApp', '1.2.34', 'https://mytestapp.example'); - $apiKey = 'sk_test_notarealkey'; - - $headers = $method->invoke(null, $apiKey); - - $ua = json_decode($headers['X-Stripe-Client-User-Agent']); - $this->assertSame($ua->application->name, 'MyTestApp'); - $this->assertSame($ua->application->version, '1.2.34'); - $this->assertSame($ua->application->url, 'https://mytestapp.example'); - - $this->assertSame( - $headers['User-Agent'], - 'Stripe/v1 PhpBindings/' . Stripe::VERSION . ' MyTestApp/1.2.34 (https://mytestapp.example)' - ); - - $this->assertSame($headers['Authorization'], 'Bearer ' . $apiKey); - } -} diff --git a/htdocs/includes/stripe/tests/ApplePayDomainTest.php b/htdocs/includes/stripe/tests/ApplePayDomainTest.php deleted file mode 100644 index ebb3e7cfa9d..00000000000 --- a/htdocs/includes/stripe/tests/ApplePayDomainTest.php +++ /dev/null @@ -1,72 +0,0 @@ -mockRequest( - 'POST', - '/v1/apple_pay/domains', - array('domain_name' => 'test.com'), - array( - 'id' => 'apwc_create', - 'object' => 'apple_pay_domain' - ) - ); - $d = ApplePayDomain::create(array( - 'domain_name' => 'test.com' - )); - $this->assertSame('apwc_create', $d->id); - $this->assertInstanceOf('Stripe\\ApplePayDomain', $d); - } - - public function testRetrieve() - { - $this->mockRequest( - 'GET', - '/v1/apple_pay/domains/apwc_retrieve', - array(), - array( - 'id' => 'apwc_retrieve', - 'object' => 'apple_pay_domain' - ) - ); - $d = ApplePayDomain::retrieve('apwc_retrieve'); - $this->assertSame('apwc_retrieve', $d->id); - $this->assertInstanceOf('Stripe\\ApplePayDomain', $d); - } - - public function testDeletion() - { - self::authorizeFromEnv(); - $d = ApplePayDomain::create(array( - 'domain_name' => 'jackshack.website' - )); - $this->assertInstanceOf('Stripe\\ApplePayDomain', $d); - $this->mockRequest( - 'DELETE', - '/v1/apple_pay/domains/' . $d->id, - array(), - array('deleted' => true) - ); - $d->delete(); - $this->assertTrue($d->deleted); - } - - public function testList() - { - $this->mockRequest( - 'GET', - '/v1/apple_pay/domains', - array(), - array( - 'url' => '/v1/apple_pay/domains', - 'object' => 'list' - ) - ); - $all = ApplePayDomain::all(); - $this->assertSame($all->url, '/v1/apple_pay/domains'); - } -} diff --git a/htdocs/includes/stripe/tests/ApplicationFeeRefundTest.php b/htdocs/includes/stripe/tests/ApplicationFeeRefundTest.php deleted file mode 100644 index b8d266ad1eb..00000000000 --- a/htdocs/includes/stripe/tests/ApplicationFeeRefundTest.php +++ /dev/null @@ -1,18 +0,0 @@ -id = 'refund_id'; - $refund->fee = 'fee_id'; - - $this->assertSame( - $refund->instanceUrl(), - '/v1/application_fees/fee_id/refunds/refund_id' - ); - } -} diff --git a/htdocs/includes/stripe/tests/ApplicationFeeTest.php b/htdocs/includes/stripe/tests/ApplicationFeeTest.php deleted file mode 100644 index fe6df923084..00000000000 --- a/htdocs/includes/stripe/tests/ApplicationFeeTest.php +++ /dev/null @@ -1,22 +0,0 @@ -assertSame( - $applicationFee->instanceUrl(), - '/v1/application_fees/abcd%2Fefgh' - ); - } - - public function testList() - { - self::authorizeFromEnv(); - $d = ApplicationFee::all(); - $this->assertSame($d->url, '/v1/application_fees'); - } -} diff --git a/htdocs/includes/stripe/tests/AuthenticationErrorTest.php b/htdocs/includes/stripe/tests/AuthenticationErrorTest.php deleted file mode 100644 index 1003d6990c8..00000000000 --- a/htdocs/includes/stripe/tests/AuthenticationErrorTest.php +++ /dev/null @@ -1,16 +0,0 @@ -assertSame(401, $e->getHttpStatus()); - } - } -} diff --git a/htdocs/includes/stripe/tests/BalanceTest.php b/htdocs/includes/stripe/tests/BalanceTest.php deleted file mode 100644 index 3d6a2a668f0..00000000000 --- a/htdocs/includes/stripe/tests/BalanceTest.php +++ /dev/null @@ -1,15 +0,0 @@ -assertSame($d->object, "balance"); - $this->assertTrue(Util\Util::isList($d->available)); - $this->assertTrue(Util\Util::isList($d->pending)); - } -} diff --git a/htdocs/includes/stripe/tests/BalanceTransactionTest.php b/htdocs/includes/stripe/tests/BalanceTransactionTest.php deleted file mode 100644 index b196a288014..00000000000 --- a/htdocs/includes/stripe/tests/BalanceTransactionTest.php +++ /dev/null @@ -1,13 +0,0 @@ -assertSame($d->url, '/v1/balance/history'); - } -} diff --git a/htdocs/includes/stripe/tests/BankAccountTest.php b/htdocs/includes/stripe/tests/BankAccountTest.php deleted file mode 100644 index 285078f00ad..00000000000 --- a/htdocs/includes/stripe/tests/BankAccountTest.php +++ /dev/null @@ -1,32 +0,0 @@ -sources->create(array( - 'source' => array( - 'object' => 'bank_account', - 'account_holder_type' => 'individual', - 'account_number' => '000123456789', - 'account_holder_name' => 'John Doe', - 'routing_number' => '110000000', - 'country' => 'US' - ) - )); - - $this->assertSame($bankAccount->status, 'new'); - - $bankAccount = $bankAccount->verify(array( - 'amounts' => array(32, 45) - )); - - $this->assertSame($bankAccount->status, 'verified'); - } -} diff --git a/htdocs/includes/stripe/tests/BitcoinReceiverTest.php b/htdocs/includes/stripe/tests/BitcoinReceiverTest.php deleted file mode 100644 index fc71cf973a5..00000000000 --- a/htdocs/includes/stripe/tests/BitcoinReceiverTest.php +++ /dev/null @@ -1,120 +0,0 @@ -assertSame($classUrl, '/v1/bitcoin/receivers'); - $receiver = new BitcoinReceiver('abcd/efgh'); - $instanceUrl = $receiver->instanceUrl(); - $this->assertSame($instanceUrl, '/v1/bitcoin/receivers/abcd%2Fefgh'); - } - - public function testCreate() - { - self::authorizeFromEnv(); - - $receiver = $this->createTestBitcoinReceiver("do+fill_now@stripe.com"); - - $this->assertSame(100, $receiver->amount); - $this->assertNotNull($receiver->id); - } - - public function testRetrieve() - { - self::authorizeFromEnv(); - - $receiver = $this->createTestBitcoinReceiver("do+fill_now@stripe.com"); - - $r = BitcoinReceiver::retrieve($receiver->id); - $this->assertSame($receiver->id, $r->id); - - $this->assertInstanceOf('Stripe\\BitcoinTransaction', $r->transactions->data[0]); - } - - public function testList() - { - self::authorizeFromEnv(); - - $receiver = $this->createTestBitcoinReceiver("do+fill_now@stripe.com"); - - $receivers = BitcoinReceiver::all(); - $this->assertGreaterThan(0, count($receivers->data)); - } - - public function testListTransactions() - { - self::authorizeFromEnv(); - - $receiver = $this->createTestBitcoinReceiver("do+fill_now@stripe.com"); - $this->assertSame(0, count($receiver->transactions->data)); - - $transactions = $receiver->transactions->all(array("limit" => 1)); - $this->assertSame(1, count($transactions->data)); - } - - public function testDeleteWithCustomer() - { - self::authorizeFromEnv(); - $receiver = $this->createTestBitcoinReceiver("do+fill_now@stripe.com"); - $customer = Customer::create(array("source" => $receiver->id)); - $charge = Charge::create(array( - "customer" => $customer->id, - "amount" => $receiver->amount, - "currency" => $receiver->currency - )); - $receiver = BitcoinReceiver::retrieve($receiver->id); - $response = $receiver->delete(); - $this->assertTrue($response->deleted); - } - - public function testUpdateWithCustomer() - { - self::authorizeFromEnv(); - $receiver = $this->createTestBitcoinReceiver("do+fill_now@stripe.com"); - $customer = Customer::create(array("source" => $receiver->id)); - $receiver = BitcoinReceiver::retrieve($receiver->id); - - $receiver->description = "a new description"; - $receiver->save(); - - $base = Customer::classUrl(); - $parentExtn = $receiver['customer']; - $extn = $receiver['id']; - $this->assertEquals("$base/$parentExtn/sources/$extn", $receiver->instanceUrl()); - - $updatedReceiver = BitcoinReceiver::retrieve($receiver->id); - $this->assertEquals($receiver["description"], $updatedReceiver["description"]); - } - - public function testUpdateWithoutCustomer() - { - self::authorizeFromEnv(); - $receiver = $this->createTestBitcoinReceiver("do+fill_now@stripe.com"); - - $receiver->description = "a new description"; - $receiver->save(); - - $this->assertEquals(BitcoinReceiver::classUrl() . "/" . $receiver['id'], $receiver->instanceUrl()); - - $updatedReceiver = BitcoinReceiver::retrieve($receiver->id); - $this->assertEquals($receiver["description"], $updatedReceiver["description"]); - } - - public function testRefund() - { - self::authorizeFromEnv(); - $receiver = $this->createTestBitcoinReceiver("do+fill_now@stripe.com"); - - $receiver = BitcoinReceiver::retrieve($receiver->id); - $this->assertNull($receiver->refund_address); - - $refundAddress = "REFUNDHERE"; - $receiver->refund(array("refund_address" => $refundAddress)); - - $this->assertSame($refundAddress, $receiver->refund_address); - } -} diff --git a/htdocs/includes/stripe/tests/CardErrorTest.php b/htdocs/includes/stripe/tests/CardErrorTest.php deleted file mode 100644 index a0de752e512..00000000000 --- a/htdocs/includes/stripe/tests/CardErrorTest.php +++ /dev/null @@ -1,41 +0,0 @@ - '4000000000000002', - 'exp_month' => '3', - 'exp_year' => '2020' - ); - - $charge = array( - 'amount' => 100, - 'currency' => 'usd', - 'card' => $card - ); - - try { - Charge::create($charge); - } catch (Error\Card $e) { - $this->assertSame(402, $e->getHttpStatus()); - $this->assertTrue(strpos($e->getRequestId(), "req_") === 0, $e->getRequestId()); - $actual = $e->getJsonBody(); - $this->assertSame( - array('error' => array( - 'message' => 'Your card was declined.', - 'type' => 'card_error', - 'code' => 'card_declined', - 'decline_code' => 'generic_decline', - 'charge' => $actual['error']['charge'], - )), - $actual - ); - } - } -} diff --git a/htdocs/includes/stripe/tests/ChargeTest.php b/htdocs/includes/stripe/tests/ChargeTest.php deleted file mode 100644 index 6ec0fa1f1d4..00000000000 --- a/htdocs/includes/stripe/tests/ChargeTest.php +++ /dev/null @@ -1,204 +0,0 @@ -assertSame(Charge::classUrl(), '/v1/charges'); - $charge = new Charge('abcd/efgh'); - $this->assertSame($charge->instanceUrl(), '/v1/charges/abcd%2Fefgh'); - } - - public function testCreate() - { - self::authorizeFromEnv(); - - $card = array( - 'number' => '4242424242424242', - 'exp_month' => 5, - 'exp_year' => date('Y') + 1 - ); - - $c = Charge::create( - array( - 'amount' => 100, - 'currency' => 'usd', - 'card' => $card - ) - ); - $this->assertTrue($c->paid); - $this->assertFalse($c->refunded); - } - - public function testIdempotentCreate() - { - self::authorizeFromEnv(); - - $card = array( - 'number' => '4242424242424242', - 'exp_month' => 5, - 'exp_year' => date('Y') + 1 - ); - - $c = Charge::create( - array( - 'amount' => 100, - 'currency' => 'usd', - 'card' => $card - ), - array( - 'idempotency_key' => self::generateRandomString(), - ) - ); - - $this->assertTrue($c->paid); - $this->assertSame(200, $c->getLastResponse()->code); - } - - public function testRetrieve() - { - self::authorizeFromEnv(); - - $card = array( - 'number' => '4242424242424242', - 'exp_month' => 5, - 'exp_year' => date('Y') + 1 - ); - - $c = Charge::create( - array( - 'amount' => 100, - 'currency' => 'usd', - 'card' => $card - ) - ); - $d = Charge::retrieve($c->id); - $this->assertSame(200, $d->getLastResponse()->code); - $this->assertSame($d->id, $c->id); - } - - public function testUpdateMetadata() - { - self::authorizeFromEnv(); - - $card = array( - 'number' => '4242424242424242', - 'exp_month' => 5, - 'exp_year' => date('Y') + 1 - ); - - $charge = Charge::create( - array( - 'amount' => 100, - 'currency' => 'usd', - 'card' => $card - ) - ); - - $charge->metadata['test'] = 'foo bar'; - $charge->save(); - - $updatedCharge = Charge::retrieve($charge->id); - $this->assertSame('foo bar', $updatedCharge->metadata['test']); - } - - public function testUpdateMetadataAll() - { - self::authorizeFromEnv(); - - $card = array( - 'number' => '4242424242424242', - 'exp_month' => 5, - 'exp_year' => date('Y') + 1 - ); - - $charge = Charge::create( - array( - 'amount' => 100, - 'currency' => 'usd', - 'card' => $card - ) - ); - - $charge->metadata = array('test' => 'foo bar'); - $charge->save(); - $this->assertSame(200, $charge->getLastResponse()->code); - - $updatedCharge = Charge::retrieve($charge->id); - $this->assertSame('foo bar', $updatedCharge->metadata['test']); - } - - public function testMarkAsFraudulent() - { - self::authorizeFromEnv(); - - $card = array( - 'number' => '4242424242424242', - 'exp_month' => 5, - 'exp_year' => date('Y') + 1 - ); - - $charge = Charge::create( - array( - 'amount' => 100, - 'currency' => 'usd', - 'card' => $card - ) - ); - - $charge->refunds->create(); - $charge->markAsFraudulent(); - - $updatedCharge = Charge::retrieve($charge->id); - $this->assertSame( - 'fraudulent', - $updatedCharge['fraud_details']['user_report'] - ); - } - - public function testCreateWithBitcoinReceiverSource() - { - self::authorizeFromEnv(); - - $receiver = $this->createTestBitcoinReceiver("do+fill_now@stripe.com"); - - $charge = Charge::create( - array( - 'amount' => 100, - 'currency' => 'usd', - 'source' => $receiver->id - ) - ); - - $this->assertSame($receiver->id, $charge->source->id); - $this->assertSame("bitcoin_receiver", $charge->source->object); - $this->assertSame("succeeded", $charge->status); - $this->assertInstanceOf('Stripe\\BitcoinReceiver', $charge->source); - } - - public function markAsSafe() - { - self::authorizeFromEnv(); - - $card = array( - 'number' => '4242424242424242', - 'exp_month' => 5, - 'exp_year' => date('Y') + 1 - ); - - $charge = Charge::create( - array( - 'amount' => 100, - 'currency' => 'usd', - 'card' => $card - ) - ); - - $charge->markAsSafe(); - - $updatedCharge = Charge::retrieve($charge->id); - $this->assertSame('safe', $updatedCharge['fraud_details']['user_report']); - } -} diff --git a/htdocs/includes/stripe/tests/CollectionTest.php b/htdocs/includes/stripe/tests/CollectionTest.php deleted file mode 100644 index f8f923ff00d..00000000000 --- a/htdocs/includes/stripe/tests/CollectionTest.php +++ /dev/null @@ -1,105 +0,0 @@ - $id, - 'object' => 'pageablemodel' - )); - } - return array( - 'object' => 'list', - 'url' => '/v1/pageablemodels', - 'data' => $data, - 'has_more' => $hasMore - ); - } - - public function testAutoPagingOnePage() - { - $collection = Collection::constructFrom( - $this->pageableModelResponse(array('pm_123', 'pm_124'), false), - new Util\RequestOptions() - ); - - $seen = array(); - foreach ($collection->autoPagingIterator() as $item) { - array_push($seen, $item['id']); - } - - $this->assertSame($seen, array('pm_123', 'pm_124')); - } - - public function testAutoPagingThreePages() - { - $collection = Collection::constructFrom( - $this->pageableModelResponse(array('pm_123', 'pm_124'), true), - new Util\RequestOptions() - ); - $collection->setRequestParams(array('foo' => 'bar')); - - $this->mockRequest( - 'GET', - '/v1/pageablemodels', - array( - 'foo' => 'bar', - 'starting_after' => 'pm_124' - ), - $this->pageableModelResponse(array('pm_125', 'pm_126'), true) - ); - $this->mockRequest( - 'GET', - '/v1/pageablemodels', - array( - 'foo' => 'bar', - 'starting_after' => 'pm_126' - ), - $this->pageableModelResponse(array('pm_127'), false) - ); - - $seen = array(); - foreach ($collection->autoPagingIterator() as $item) { - array_push($seen, $item['id']); - } - - $this->assertSame($seen, array('pm_123', 'pm_124', 'pm_125', 'pm_126', 'pm_127')); - } - - public function testIteratorToArray() - { - $collection = Collection::constructFrom( - $this->pageableModelResponse(array('pm_123', 'pm_124'), true), - new Util\RequestOptions() - ); - - $this->mockRequest( - 'GET', - '/v1/pageablemodels', - array( - 'starting_after' => 'pm_124' - ), - $this->pageableModelResponse(array('pm_125', 'pm_126'), true) - ); - $this->mockRequest( - 'GET', - '/v1/pageablemodels', - array( - 'starting_after' => 'pm_126' - ), - $this->pageableModelResponse(array('pm_127'), false) - ); - - $seen = array(); - foreach (iterator_to_array($collection->autoPagingIterator()) as $item) { - array_push($seen, $item['id']); - } - - $this->assertSame($seen, array('pm_123', 'pm_124', 'pm_125', 'pm_126', 'pm_127')); - } -} diff --git a/htdocs/includes/stripe/tests/CountrySpecTest.php b/htdocs/includes/stripe/tests/CountrySpecTest.php deleted file mode 100644 index 19dc37062e5..00000000000 --- a/htdocs/includes/stripe/tests/CountrySpecTest.php +++ /dev/null @@ -1,31 +0,0 @@ -assertSame($d->object, "country_spec"); - $this->assertSame($d->id, $country); - $this->assertGreaterThan(0, count($d->supported_bank_account_currencies)); - $this->assertGreaterThan(0, count($d->supported_payment_currencies)); - $this->assertGreaterThan(0, count($d->supported_payment_methods)); - $this->assertGreaterThan(0, count($d->verification_fields)); - } - - public function testList() - { - self::authorizeFromEnv(); - - $d = CountrySpec::all(); - $this->assertSame($d->object, "list"); - $this->assertGreaterThan(0, count($d->data)); - $this->assertSame($d->data[0]->object, "country_spec"); - $this->assertInstanceOf("Stripe\\CountrySpec", $d->data[0]); - } -} diff --git a/htdocs/includes/stripe/tests/CouponTest.php b/htdocs/includes/stripe/tests/CouponTest.php deleted file mode 100644 index d23163e338e..00000000000 --- a/htdocs/includes/stripe/tests/CouponTest.php +++ /dev/null @@ -1,29 +0,0 @@ - 25, - 'duration' => 'repeating', - 'duration_in_months' => 5, - 'id' => $id, - ) - ); - $this->assertSame($id, $c->id); - // @codingStandardsIgnoreStart - $this->assertSame(25, $c->percent_off); - // @codingStandardsIgnoreEnd - $c->metadata['foo'] = 'bar'; - $c->save(); - - $stripeCoupon = Coupon::retrieve($id); - $this->assertEquals($c->metadata, $stripeCoupon->metadata); - } -} diff --git a/htdocs/includes/stripe/tests/CurlClientTest.php b/htdocs/includes/stripe/tests/CurlClientTest.php deleted file mode 100644 index 864607f088c..00000000000 --- a/htdocs/includes/stripe/tests/CurlClientTest.php +++ /dev/null @@ -1,100 +0,0 @@ -assertSame(CurlClient::DEFAULT_TIMEOUT, $curl->getTimeout()); - $this->assertSame(CurlClient::DEFAULT_CONNECT_TIMEOUT, $curl->getConnectTimeout()); - - // implicitly tests whether we're returning the CurlClient instance - $curl = $curl->setConnectTimeout(1)->setTimeout(10); - $this->assertSame(1, $curl->getConnectTimeout()); - $this->assertSame(10, $curl->getTimeout()); - - $curl->setTimeout(-1); - $curl->setConnectTimeout(-999); - $this->assertSame(0, $curl->getTimeout()); - $this->assertSame(0, $curl->getConnectTimeout()); - } - - public function testDefaultOptions() - { - // make sure options array loads/saves properly - $optionsArray = array(CURLOPT_PROXY => 'localhost:80'); - $withOptionsArray = new CurlClient($optionsArray); - $this->assertSame($withOptionsArray->getDefaultOptions(), $optionsArray); - - // make sure closure-based options work properly, including argument passing - $ref = null; - $withClosure = new CurlClient(function ($method, $absUrl, $headers, $params, $hasFile) use (&$ref) { - $ref = func_get_args(); - return array(); - }); - - $withClosure->request('get', 'https://httpbin.org/status/200', array(), array(), false); - $this->assertSame($ref, array('get', 'https://httpbin.org/status/200', array(), array(), false)); - - // this is the last test case that will run, since it'll throw an exception at the end - $withBadClosure = new CurlClient(function () { - return 'thisShouldNotWork'; - }); - $this->setExpectedException('Stripe\Error\Api', "Non-array value returned by defaultOptions CurlClient callback"); - $withBadClosure->request('get', 'https://httpbin.org/status/200', array(), array(), false); - } - - public function testEncode() - { - $a = array( - 'my' => 'value', - 'that' => array('your' => 'example'), - 'bar' => 1, - 'baz' => null - ); - - $enc = CurlClient::encode($a); - $this->assertSame('my=value&that%5Byour%5D=example&bar=1', $enc); - - $a = array('that' => array('your' => 'example', 'foo' => null)); - $enc = CurlClient::encode($a); - $this->assertSame('that%5Byour%5D=example', $enc); - - $a = array('that' => 'example', 'foo' => array('bar', 'baz')); - $enc = CurlClient::encode($a); - $this->assertSame('that=example&foo%5B%5D=bar&foo%5B%5D=baz', $enc); - - $a = array( - 'my' => 'value', - 'that' => array('your' => array('cheese', 'whiz', null)), - 'bar' => 1, - 'baz' => null - ); - - $enc = CurlClient::encode($a); - $expected = 'my=value&that%5Byour%5D%5B%5D=cheese' - . '&that%5Byour%5D%5B%5D=whiz&bar=1'; - $this->assertSame($expected, $enc); - - // Ignores an empty array - $enc = CurlClient::encode(array('foo' => array(), 'bar' => 'baz')); - $expected = 'bar=baz'; - $this->assertSame($expected, $enc); - - $a = array('foo' => array(array('bar' => 'baz'), array('bar' => 'bin'))); - $enc = CurlClient::encode($a); - $this->assertSame('foo%5B0%5D%5Bbar%5D=baz&foo%5B1%5D%5Bbar%5D=bin', $enc); - } - - public function testSslOption() - { - // make sure options array loads/saves properly - $optionsArray = array(CURLOPT_SSLVERSION => CURL_SSLVERSION_TLSv1); - $withOptionsArray = new CurlClient($optionsArray); - $this->assertSame($withOptionsArray->getDefaultOptions(), $optionsArray); - } -} diff --git a/htdocs/includes/stripe/tests/CustomerTest.php b/htdocs/includes/stripe/tests/CustomerTest.php deleted file mode 100644 index 606536ee86f..00000000000 --- a/htdocs/includes/stripe/tests/CustomerTest.php +++ /dev/null @@ -1,278 +0,0 @@ -delete(); - - $this->assertTrue($customer->deleted); - $this->assertNull($customer['active_card']); - } - - public function testSave() - { - $customer = self::createTestCustomer(); - - $customer->email = 'gdb@stripe.com'; - $customer->save(); - $this->assertSame($customer->email, 'gdb@stripe.com'); - - $stripeCustomer = Customer::retrieve($customer->id); - $this->assertSame($customer->email, $stripeCustomer->email); - - Stripe::setApiKey(null); - $customer = Customer::create(null, self::API_KEY); - $customer->email = 'gdb@stripe.com'; - $customer->save(); - - self::authorizeFromEnv(); - $updatedCustomer = Customer::retrieve($customer->id); - $this->assertSame($updatedCustomer->email, 'gdb@stripe.com'); - } - - /** - * @expectedException Stripe\Error\InvalidRequest - */ - public function testBogusAttribute() - { - $customer = self::createTestCustomer(); - $customer->bogus = 'bogus'; - $customer->save(); - } - - /** - * @expectedException InvalidArgumentException - */ - public function testUpdateDescriptionEmpty() - { - $customer = self::createTestCustomer(); - $customer->description = ''; - } - - public function testUpdateDescriptionNull() - { - $customer = self::createTestCustomer(array('description' => 'foo bar')); - $customer->description = null; - - $customer->save(); - - $updatedCustomer = Customer::retrieve($customer->id); - $this->assertSame(null, $updatedCustomer->description); - } - - public function testUpdateMetadata() - { - $customer = self::createTestCustomer(); - - $customer->metadata['test'] = 'foo bar'; - $customer->save(); - - $updatedCustomer = Customer::retrieve($customer->id); - $this->assertSame('foo bar', $updatedCustomer->metadata['test']); - } - - public function testDeleteMetadata() - { - $customer = self::createTestCustomer(); - - $customer->metadata = null; - $customer->save(); - - $updatedCustomer = Customer::retrieve($customer->id); - $this->assertSame(0, count($updatedCustomer->metadata->keys())); - } - - public function testUpdateSomeMetadata() - { - $customer = self::createTestCustomer(); - $customer->metadata['shoe size'] = '7'; - $customer->metadata['shirt size'] = 'XS'; - $customer->save(); - - $customer->metadata['shoe size'] = '9'; - $customer->save(); - - $updatedCustomer = Customer::retrieve($customer->id); - $this->assertSame('XS', $updatedCustomer->metadata['shirt size']); - $this->assertSame('9', $updatedCustomer->metadata['shoe size']); - } - - public function testUpdateAllMetadata() - { - $customer = self::createTestCustomer(); - $customer->metadata['shoe size'] = '7'; - $customer->metadata['shirt size'] = 'XS'; - $customer->save(); - - $customer->metadata = array('shirt size' => 'XL'); - $customer->save(); - - $updatedCustomer = Customer::retrieve($customer->id); - $this->assertSame('XL', $updatedCustomer->metadata['shirt size']); - $this->assertFalse(isset($updatedCustomer->metadata['shoe size'])); - } - - /** - * @expectedException Stripe\Error\InvalidRequest - */ - public function testUpdateInvalidMetadata() - { - $customer = self::createTestCustomer(); - $customer->metadata = 'something'; - $customer->save(); - } - - public function testCancelSubscription() - { - $planID = 'gold-' . self::generateRandomString(20); - self::retrieveOrCreatePlan($planID); - - $customer = self::createTestCustomer( - array( - 'plan' => $planID, - ) - ); - - $customer->cancelSubscription(array('at_period_end' => true)); - $this->assertSame($customer->subscription->status, 'active'); - $this->assertTrue($customer->subscription->cancel_at_period_end); - $customer->cancelSubscription(); - $this->assertSame($customer->subscription->status, 'canceled'); - } - - public function testCustomerAddCard() - { - $token = Token::create( - array("card" => array( - "number" => "4242424242424242", - "exp_month" => 5, - "exp_year" => date('Y') + 3, - "cvc" => "314" - )) - ); - - $customer = $this->createTestCustomer(); - $createdCard = $customer->sources->create(array("card" => $token->id)); - $customer->save(); - - $updatedCustomer = Customer::retrieve($customer->id); - $updatedCards = $updatedCustomer->sources->all(); - $this->assertSame(count($updatedCards["data"]), 2); - } - - public function testCustomerUpdateCard() - { - $customer = $this->createTestCustomer(); - $customer->save(); - - $sources = $customer->sources->all(); - $this->assertSame(count($sources["data"]), 1); - - $card = $sources['data'][0]; - $card->name = "Jane Austen"; - $card->save(); - - $updatedCustomer = Customer::retrieve($customer->id); - $updatedCards = $updatedCustomer->sources->all(); - $this->assertSame($updatedCards["data"][0]->name, "Jane Austen"); - } - - public function testCustomerDeleteCard() - { - $token = Token::create( - array("card" => array( - "number" => "4242424242424242", - "exp_month" => 5, - "exp_year" => date('Y') + 3, - "cvc" => "314" - )) - ); - - $customer = $this->createTestCustomer(); - $createdCard = $customer->sources->create(array("card" => $token->id)); - $customer->save(); - - $updatedCustomer = Customer::retrieve($customer->id); - $updatedCards = $updatedCustomer->sources->all(); - $this->assertSame(count($updatedCards["data"]), 2); - - $deleteStatus = $updatedCustomer->sources->retrieve($createdCard->id)->delete(); - $this->assertTrue($deleteStatus->deleted); - $updatedCustomer->save(); - - $postDeleteCustomer = Customer::retrieve($customer->id); - $postDeleteCards = $postDeleteCustomer->sources->all(); - $this->assertSame(count($postDeleteCards["data"]), 1); - } - - public function testCustomerAddSource() - { - self::authorizeFromEnv(); - $token = Token::create( - array("card" => array( - "number" => "4242424242424242", - "exp_month" => 5, - "exp_year" => date('Y') + 3, - "cvc" => "314" - )) - ); - - $customer = $this->createTestCustomer(); - $createdSource = $customer->sources->create(array("source" => $token->id)); - $customer->save(); - - $updatedCustomer = Customer::retrieve($customer->id); - $updatedSources = $updatedCustomer->sources->all(); - $this->assertSame(count($updatedSources["data"]), 2); - } - - public function testCustomerUpdateSource() - { - $customer = $this->createTestCustomer(); - $customer->save(); - - $sources = $customer->sources->all(); - $this->assertSame(count($sources["data"]), 1); - - $source = $sources['data'][0]; - $source->name = "Jane Austen"; - $source->save(); - - $updatedCustomer = Customer::retrieve($customer->id); - $updatedSources = $updatedCustomer->sources->all(); - $this->assertSame($updatedSources["data"][0]->name, "Jane Austen"); - } - - public function testCustomerDeleteSource() - { - self::authorizeFromEnv(); - $token = Token::create( - array("card" => array( - "number" => "4242424242424242", - "exp_month" => 5, - "exp_year" => date('Y') + 3, - "cvc" => "314" - )) - ); - - $customer = $this->createTestCustomer(); - $createdSource = $customer->sources->create(array("source" => $token->id)); - $customer->save(); - - $updatedCustomer = Customer::retrieve($customer->id); - $updatedSources = $updatedCustomer->sources->all(); - $this->assertSame(count($updatedSources["data"]), 2); - - $deleteStatus = $updatedCustomer->sources->retrieve($createdSource->id)->delete(); - $this->assertTrue($deleteStatus->deleted); - $updatedCustomer->save(); - - $postDeleteCustomer = Customer::retrieve($customer->id); - $postDeleteSources = $postDeleteCustomer->sources->all(); - $this->assertSame(count($postDeleteSources["data"]), 1); - } -} diff --git a/htdocs/includes/stripe/tests/DiscountTest.php b/htdocs/includes/stripe/tests/DiscountTest.php deleted file mode 100644 index 1e77029ad2d..00000000000 --- a/htdocs/includes/stripe/tests/DiscountTest.php +++ /dev/null @@ -1,31 +0,0 @@ - 25, - 'duration' => 'repeating', - 'duration_in_months' => 5, - 'id' => $id, - ) - ); - $customer = self::createTestCustomer(array('coupon' => $id)); - - $this->assertTrue(isset($customer->discount)); - $this->assertTrue(isset($customer->discount->coupon)); - $this->assertSame($id, $customer->discount->coupon->id); - - $customer->deleteDiscount(); - $this->assertFalse(isset($customer->discount)); - - $customer = Customer::retrieve($customer->id); - $this->assertFalse(isset($customer->discount)); - } -} diff --git a/htdocs/includes/stripe/tests/DisputeTest.php b/htdocs/includes/stripe/tests/DisputeTest.php deleted file mode 100644 index 3c4f29678ea..00000000000 --- a/htdocs/includes/stripe/tests/DisputeTest.php +++ /dev/null @@ -1,96 +0,0 @@ -assertSame(Dispute::classUrl(), '/v1/disputes'); - $dispute = new Dispute('dp_123'); - $this->assertSame($dispute->instanceUrl(), '/v1/disputes/dp_123'); - } - - private function createDisputedCharge() - { - $card = array( - 'number' => '4000000000000259', - 'exp_month' => 5, - 'exp_year' => date('Y') + 1 - ); - - $c = Charge::create( - array( - 'amount' => 100, - 'currency' => 'usd', - 'card' => $card - ) - ); - $c = Charge::retrieve($c->id); - - $attempts = 0; - - while ($c->dispute === null) { - if ($attempts > 5) { - throw new \Exception("Charge is taking too long to be disputed"); - } - sleep(1); - $c = Charge::retrieve($c->id); - $attempts += 1; - } - - return $c; - } - - public function testAll() - { - self::authorizeFromEnv(); - - $sublist = Dispute::all( - array( - 'limit' => 3, - ) - ); - $this->assertSame(3, count($sublist->data)); - } - - - public function testUpdate() - { - self::authorizeFromEnv(); - - $c = $this->createDisputedCharge(); - - $d = Dispute::retrieve($c->dispute); - $d->evidence["customer_name"] = "Bob"; - $s = $d->save(); - - $this->assertSame($c->dispute, $s->id); - $this->assertSame("Bob", $s->evidence["customer_name"]); - } - - public function testClose() - { - self::authorizeFromEnv(); - - $c = $this->createDisputedCharge(); - $d = Dispute::retrieve($c->dispute); - - $this->assertNotSame("lost", $d->status); - - $d->close(); - - $this->assertSame("lost", $d->status); - } - - public function testRetrieve() - { - self::authorizeFromEnv(); - - $c = $this->createDisputedCharge(); - - $d = Dispute::retrieve($c->dispute); - - $this->assertSame($c->dispute, $d->id); - } -} diff --git a/htdocs/includes/stripe/tests/ErrorTest.php b/htdocs/includes/stripe/tests/ErrorTest.php deleted file mode 100644 index 75362427510..00000000000 --- a/htdocs/includes/stripe/tests/ErrorTest.php +++ /dev/null @@ -1,61 +0,0 @@ - 'bar') - ); - $this->fail("Did not raise error"); - } catch (Error\Api $e) { - $this->assertSame("hello", $e->getMessage()); - $this->assertSame(500, $e->getHttpStatus()); - $this->assertSame("{'foo':'bar'}", $e->getHttpBody()); - $this->assertSame(array('foo' => 'bar'), $e->getJsonBody()); - $this->assertSame(null, $e->getHttpHeaders()); - $this->assertSame(null, $e->getRequestId()); - } - } - - public function testResponseHeaders() - { - try { - throw new Error\Api( - "hello", - 500, - "{'foo':'bar'}", - array('foo' => 'bar'), - array('Request-Id' => 'req_bar') - ); - $this->fail("Did not raise error"); - } catch (Error\Api $e) { - $this->assertSame(array('Request-Id' => 'req_bar'), $e->getHttpHeaders()); - $this->assertSame('req_bar', $e->getRequestId()); - } - } - - public function testCode() - { - try { - throw new Error\Card( - "hello", - "some_param", - "some_code", - 400, - "{'foo':'bar'}", - array('foo' => 'bar') - ); - $this->fail("Did not raise error"); - } catch (Error\Card $e) { - $this->assertSame("some_param", $e->getStripeParam()); - $this->assertSame('some_code', $e->getStripeCode()); - } - } -} diff --git a/htdocs/includes/stripe/tests/ExternalAccountTest.php b/htdocs/includes/stripe/tests/ExternalAccountTest.php deleted file mode 100644 index 70c0068bc45..00000000000 --- a/htdocs/includes/stripe/tests/ExternalAccountTest.php +++ /dev/null @@ -1,30 +0,0 @@ - array( - 'country' => 'US', - 'routing_number' => '110000000', - 'account_number' => '000123456789', - 'account_holder_name' => 'Jane Austen', - 'account_holder_type' => 'company' - ) - ) - ); - $customer = Customer::create(); - $externalAccount = $customer->sources->create(array('bank_account' => $bankAccountToken->id)); - $verifiedAccount = $externalAccount->verify(array('amounts' => array(32, 45)), null); - - $base = Customer::classUrl(); - $parentExtn = $externalAccount['customer']; - $extn = $externalAccount['id']; - $this->assertEquals("$base/$parentExtn/sources/$extn", $externalAccount->instanceUrl()); - } -} diff --git a/htdocs/includes/stripe/tests/FileUploadTest.php b/htdocs/includes/stripe/tests/FileUploadTest.php deleted file mode 100644 index 7d1faf3b00f..00000000000 --- a/htdocs/includes/stripe/tests/FileUploadTest.php +++ /dev/null @@ -1,44 +0,0 @@ - 'dispute_evidence', - 'file' => $fp, - ) - ); - fclose($fp); - $this->assertSame(95, $file->size); - $this->assertSame('png', $file->type); - } - - public function testCreateAndRetrieveCurlFile() - { - if (!class_exists('\CurlFile', false)) { - // Older PHP versions don't support this - return; - } - - $curlFile = new \CurlFile(dirname(__FILE__).'/../data/test.png'); - self::authorizeFromEnv(); - $file = FileUpload::create( - array( - 'purpose' => 'dispute_evidence', - 'file' => $curlFile, - ) - ); - $this->assertSame(95, $file->size); - $this->assertSame('png', $file->type); - - // Just check that we don't get exceptions - $file = FileUpload::retrieve($file->id); - $file->refresh(); - } -} diff --git a/htdocs/includes/stripe/tests/InvalidRequestErrorTest.php b/htdocs/includes/stripe/tests/InvalidRequestErrorTest.php deleted file mode 100644 index 6cc6d682911..00000000000 --- a/htdocs/includes/stripe/tests/InvalidRequestErrorTest.php +++ /dev/null @@ -1,26 +0,0 @@ -assertSame(404, $e->getHttpStatus()); - } - } - - public function testBadData() - { - self::authorizeFromEnv(); - try { - Charge::create(); - } catch (Error\InvalidRequest $e) { - $this->assertSame(400, $e->getHttpStatus()); - } - } -} diff --git a/htdocs/includes/stripe/tests/InvoiceTest.php b/htdocs/includes/stripe/tests/InvoiceTest.php deleted file mode 100644 index a55ab83e4ac..00000000000 --- a/htdocs/includes/stripe/tests/InvoiceTest.php +++ /dev/null @@ -1,56 +0,0 @@ - $customer->id, - 'amount' => 0, - 'currency' => 'usd', - )); - - $invoice = Invoice::upcoming(array( - 'customer' => $customer->id, - )); - $this->assertSame($invoice->customer, $customer->id); - $this->assertSame($invoice->attempted, false); - } - - public function testItemsAccessWithParameter() - { - self::authorizeFromEnv(); - $customer = self::createTestCustomer(); - - InvoiceItem::create(array( - 'customer' => $customer->id, - 'amount' => 100, - 'currency' => 'usd', - )); - - $invoice = Invoice::upcoming( - array( - 'customer' => $customer->id, - ) - ); - - $lines = $invoice->lines->all(array('limit' => 10)); - - $this->assertSame(count($lines->data), 1); - $this->assertSame($lines->data[0]->amount, 100); - } - - // This is really just making sure that this operation does not trigger any - // warnings, as it's highly nested. - public function testAll() - { - self::authorizeFromEnv(); - $invoices = Invoice::all(); - $this->assertGreaterThan(0, count($invoices)); - } -} diff --git a/htdocs/includes/stripe/tests/PayoutTest.php b/htdocs/includes/stripe/tests/PayoutTest.php deleted file mode 100644 index 5e99faede87..00000000000 --- a/htdocs/includes/stripe/tests/PayoutTest.php +++ /dev/null @@ -1,94 +0,0 @@ -managedAccount === null) { - self::authorizeFromEnv(); - $account = self::createTestManagedAccount(); - - $charge = \Stripe\Charge::create(array( - 'currency' => 'usd', - 'amount' => '10000', - 'source' => array( - 'object' => 'card', - 'number' => '4000000000000077', - 'exp_month' => '09', - 'exp_year' => date('Y') + 3, - ), - 'destination' => array( - 'account' => $account->id - ) - )); - - $this->managedAccount = $account; - } - - return $this->managedAccount; - } - - private function createPayoutFromManagedAccount($accountId) - { - $payout = Payout::create( - array( - 'amount' => 100, - 'currency' => 'usd', - ), - array( - 'stripe_account' => $accountId - ) - ); - - return $payout; - } - - public function testCreate() - { - $account = self::createAccountWithBalance(); - $payout = self::createPayoutFromManagedAccount($account->id); - - $this->assertSame('pending', $payout->status); - } - - public function testRetrieve() - { - $account = self::createAccountWithBalance(); - $payout = self::createPayoutFromManagedAccount($account->id); - $reloaded = Payout::retrieve($payout->id, array('stripe_account' => $account->id)); - $this->assertSame($reloaded->id, $payout->id); - } - - public function testPayoutUpdateMetadata() - { - $account = self::createAccountWithBalance(); - $payout = self::createPayoutFromManagedAccount($account->id); - $payout->metadata['test'] = 'foo bar'; - $payout->save(); - - $updatedPayout = Payout::retrieve($payout->id, array('stripe_account' => $account->id)); - $this->assertSame('foo bar', $updatedPayout->metadata['test']); - } - - public function testPayoutUpdateMetadataAll() - { - $account = self::createAccountWithBalance(); - $payout = self::createPayoutFromManagedAccount($account->id); - - $payout->metadata = array('test' => 'foo bar'); - $payout->save(); - - $updatedPayout = Payout::retrieve($payout->id, array('stripe_account' => $account->id)); - $this->assertSame('foo bar', $updatedPayout->metadata['test']); - } -} diff --git a/htdocs/includes/stripe/tests/PermissionsErrorTest.php b/htdocs/includes/stripe/tests/PermissionsErrorTest.php deleted file mode 100644 index cc8a5cd0be0..00000000000 --- a/htdocs/includes/stripe/tests/PermissionsErrorTest.php +++ /dev/null @@ -1,22 +0,0 @@ - array(), - ); - } - - /** - * @expectedException Stripe\Error\Permission - */ - public function testPermission() - { - $this->mockRequest('GET', '/v1/accounts/acct_DEF', array(), $this->permissionErrorResponse(), 403); - Account::retrieve('acct_DEF'); - } -} diff --git a/htdocs/includes/stripe/tests/PlanTest.php b/htdocs/includes/stripe/tests/PlanTest.php deleted file mode 100644 index 9aa3589c719..00000000000 --- a/htdocs/includes/stripe/tests/PlanTest.php +++ /dev/null @@ -1,51 +0,0 @@ - 2000, - 'interval' => 'month', - 'currency' => 'usd', - 'name' => 'Plan', - 'id' => 'gold-' . self::generateRandomString(20) - )); - $p->delete(); - $this->assertTrue($p->deleted); - } - - public function testFalseyId() - { - try { - $retrievedPlan = Plan::retrieve('0'); - } catch (Error\InvalidRequest $e) { - // Can either succeed or 404, all other errors are bad - if ($e->httpStatus !== 404) { - $this->fail(); - } - } - } - - public function testSave() - { - self::authorizeFromEnv(); - $planID = 'gold-' . self::generateRandomString(20); - $p = Plan::create(array( - 'amount' => 2000, - 'interval' => 'month', - 'currency' => 'usd', - 'name' => 'Plan', - 'id' => $planID - )); - $p->name = 'A new plan name'; - $p->save(); - $this->assertSame($p->name, 'A new plan name'); - - $stripePlan = Plan::retrieve($planID); - $this->assertSame($p->name, $stripePlan->name); - } -} diff --git a/htdocs/includes/stripe/tests/ProductTest.php b/htdocs/includes/stripe/tests/ProductTest.php deleted file mode 100644 index 668d015e380..00000000000 --- a/htdocs/includes/stripe/tests/ProductTest.php +++ /dev/null @@ -1,158 +0,0 @@ -httpStatus !== 404) { - $this->fail(); - } - } - } - - public function testProductCreateUpdateRead() - { - - Stripe::setApiKey('sk_test_JieJALRz7rPz7boV17oMma7a'); - $ProductID = 'gold-' . self::generateRandomString(20); - $p = Product::create(array( - 'name' => 'Gold Product', - 'id' => $ProductID, - 'url' => 'www.stripe.com/gold' - )); - $this->assertSame($p->url, 'www.stripe.com/gold'); - - $p->name = 'A new Product name'; - $p->save(); - $this->assertSame($p->name, 'A new Product name'); - $this->assertSame($p->url, 'www.stripe.com/gold'); - - $stripeProduct = Product::retrieve($ProductID); - $this->assertSame($p->name, $stripeProduct->name); - $this->assertSame($stripeProduct->url, 'www.stripe.com/gold'); - } - - public function testSKUCreateUpdateRead() - { - Stripe::setApiKey('sk_test_JieJALRz7rPz7boV17oMma7a'); - $ProductID = 'silver-' . self::generateRandomString(20); - $p = Product::create(array( - 'name' => 'Silver Product', - 'id' => $ProductID, - 'url' => 'www.stripe.com/silver' - )); - - $SkuID = 'silver-sku-' . self::generateRandomString(20); - $sku = SKU::create(array( - 'price' => 500, - 'currency' => 'usd', - 'id' => $SkuID, - 'inventory' => array( - 'type' => 'finite', - 'quantity' => 40 - ), - 'product' => $ProductID - )); - - $sku->price = 600; - $sku->inventory->quantity = 50; - $sku->save(); - $this->assertSame($sku->price, 600); - $this->assertSame(50, $sku->inventory->quantity); - - $stripeSku = SKU::retrieve($SkuID); - $this->assertSame($sku->price, 600); - $this->assertSame('finite', $sku->inventory->type); - $this->assertSame(50, $sku->inventory->quantity); - } - - public function testSKUProductDelete() - { - Stripe::setApiKey('sk_test_JieJALRz7rPz7boV17oMma7a'); - $ProductID = 'silver-' . self::generateRandomString(20); - $p = Product::create(array( - 'name' => 'Silver Product', - 'id' => $ProductID, - 'url' => 'stripe.com/silver' - )); - - $SkuID = 'silver-sku-' . self::generateRandomString(20); - $sku = SKU::create(array( - 'price' => 500, - 'currency' => 'usd', - 'id' => $SkuID, - 'inventory' => array( - 'type' => 'finite', - 'quantity' => 40 - ), - 'product' => $ProductID - )); - - $deletedSku = $sku->delete(); - $this->assertTrue($deletedSku->deleted); - - $deletedProduct = $p->delete(); - $this->assertTrue($deletedProduct->deleted); - } - - public function testOrderCreateUpdateRetrievePayReturn() - { - Stripe::setApiKey('sk_test_JieJALRz7rPz7boV17oMma7a'); - $ProductID = 'silver-' . self::generateRandomString(20); - $p = Product::create(array( - 'name' => 'Silver Product', - 'id' => $ProductID, - 'url' => 'www.stripe.com/silver', - 'shippable' => false, - )); - - $SkuID = 'silver-sku-' . self::generateRandomString(20); - $sku = SKU::create(array( - 'price' => 500, - 'currency' => 'usd', - 'id' => $SkuID, - 'inventory' => array( - 'type' => 'finite', - 'quantity' => 40 - ), - 'product' => $ProductID - )); - - $order = Order::create(array( - 'items' => array( - 0 => array( - 'type' => 'sku', - 'parent' => $SkuID, - ), - ), - 'currency' => 'usd', - 'email' => 'foo@bar.com', - )); - - $order->metadata->foo = "bar"; - $order->save(); - - $stripeOrder = Order::retrieve($order->id); - $this->assertSame($order->metadata->foo, "bar"); - - $order->pay(array( - 'source' => array( - 'object' => 'card', - 'number' => '4242424242424242', - 'exp_month' => '05', - 'exp_year' => '2017' - ), - )); - $this->assertSame($order->status, 'paid'); - - $orderReturn = $order->returnOrder(); - $this->assertSame($orderReturn->order, $order->id); - } -} diff --git a/htdocs/includes/stripe/tests/RateLimitErrorTest.php b/htdocs/includes/stripe/tests/RateLimitErrorTest.php deleted file mode 100644 index 2d6a6b22a2b..00000000000 --- a/htdocs/includes/stripe/tests/RateLimitErrorTest.php +++ /dev/null @@ -1,22 +0,0 @@ - array(), - ); - } - - /** - * @expectedException Stripe\Error\RateLimit - */ - public function testRateLimit() - { - $this->mockRequest('GET', '/v1/accounts/acct_DEF', array(), $this->rateLimitErrorResponse(), 429); - Account::retrieve('acct_DEF'); - } -} diff --git a/htdocs/includes/stripe/tests/RecipientTest.php b/htdocs/includes/stripe/tests/RecipientTest.php deleted file mode 100644 index e26bfe8cddd..00000000000 --- a/htdocs/includes/stripe/tests/RecipientTest.php +++ /dev/null @@ -1,112 +0,0 @@ -delete(); - - $this->assertTrue($recipient->deleted); - } - - public function testSave() - { - $recipient = self::createTestRecipient(); - - $recipient->email = 'gdb@stripe.com'; - $recipient->save(); - $this->assertSame($recipient->email, 'gdb@stripe.com'); - - $stripeRecipient = Recipient::retrieve($recipient->id); - $this->assertSame($recipient->email, $stripeRecipient->email); - } - - /** - * @expectedException Stripe\Error\InvalidRequest - */ - public function testBogusAttribute() - { - $recipient = self::createTestRecipient(); - $recipient->bogus = 'bogus'; - $recipient->save(); - } - - public function testRecipientAddCard() - { - $token = Token::create( - array("card" => array( - "number" => "4000056655665556", - "exp_month" => 5, - "exp_year" => date('Y') + 3, - "cvc" => "314" - )) - ); - - $recipient = $this->createTestRecipient(); - $createdCard = $recipient->cards->create(array("card" => $token->id)); - $recipient->save(); - - $updatedRecipient = Recipient::retrieve($recipient->id); - $updatedCards = $updatedRecipient->cards->all(); - $this->assertSame(count($updatedCards["data"]), 1); - } - - public function testRecipientUpdateCard() - { - $token = Token::create( - array("card" => array( - "number" => "4000056655665556", - "exp_month" => 5, - "exp_year" => date('Y') + 3, - "cvc" => "314" - )) - ); - - $recipient = $this->createTestRecipient(); - $createdCard = $recipient->cards->create(array("card" => $token->id)); - $recipient->save(); - - $createdCards = $recipient->cards->all(); - $this->assertSame(count($createdCards["data"]), 1); - - $card = $createdCards['data'][0]; - $card->name = "Jane Austen"; - $card->save(); - - $updatedRecipient = Recipient::retrieve($recipient->id); - $updatedCards = $updatedRecipient->cards->all(); - $this->assertSame($updatedCards["data"][0]->name, "Jane Austen"); - } - - public function testRecipientDeleteCard() - { - $token = Token::create( - array("card" => array( - "number" => "4000056655665556", - "exp_month" => 5, - "exp_year" => date('Y') + 3, - "cvc" => "314" - )) - ); - - $recipient = $this->createTestRecipient(); - $createdCard = $recipient->cards->create(array("card" => $token->id)); - $recipient->save(); - - $updatedRecipient = Recipient::retrieve($recipient->id); - $updatedCards = $updatedRecipient->cards->all(); - $this->assertSame(count($updatedCards["data"]), 1); - - $deleteStatus = - $updatedRecipient->cards->retrieve($createdCard->id)->delete(); - $this->assertTrue($deleteStatus->deleted); - $updatedRecipient->save(); - - $postDeleteRecipient = Recipient::retrieve($recipient->id); - $postDeleteCards = $postDeleteRecipient->cards->all(); - $this->assertSame(count($postDeleteCards["data"]), 0); - } -} diff --git a/htdocs/includes/stripe/tests/RefundTest.php b/htdocs/includes/stripe/tests/RefundTest.php deleted file mode 100644 index e9dd8509cd3..00000000000 --- a/htdocs/includes/stripe/tests/RefundTest.php +++ /dev/null @@ -1,131 +0,0 @@ - 100, 'charge' => $charge->id)); - $this->assertSame(100, $refund->amount); - $this->assertSame($charge->id, $refund->charge); - } - - public function testUpdateAndRetrieve() - { - $charge = self::createTestCharge(); - $ref = Refund::create(array('amount' => 100, 'charge' => $charge->id)); - $ref->metadata["key"] = "value"; - $ref->save(); - $ref = Refund::retrieve($ref->id); - $this->assertSame("value", $ref->metadata["key"], "value"); - } - - public function testListForCharge() - { - $charge = self::createTestCharge(); - $refA = Refund::create(array('amount' => 100, 'charge' => $charge->id)); - $refB = Refund::create(array('amount' => 50, 'charge' => $charge->id)); - - $all = Refund::all(array('charge' => $charge)); - $this->assertSame(false, $all['has_more']); - $this->assertSame(2, count($all->data)); - $this->assertSame($refB->id, $all->data[0]->id); - $this->assertSame($refA->id, $all->data[1]->id); - } - - public function testList() - { - $all = Refund::all(); - - // Fetches all refunds on this test account. - $this->assertSame(true, $all['has_more']); - $this->assertSame(10, count($all->data)); - } - - public function testCreateForBitcoin() - { - self::authorizeFromEnv(); - - $receiver = $this->createTestBitcoinReceiver("do+fill_now@stripe.com"); - - $charge = Charge::create( - array( - 'amount' => $receiver->amount, - 'currency' => $receiver->currency, - 'description' => $receiver->description, - 'source' => $receiver->id - ) - ); - - $ref = Refund::create( - array( - 'amount' => $receiver->amount, - 'refund_address' => 'ABCDEF', - 'charge' => $charge->id - ) - ); - $this->assertSame($receiver->amount, $ref->amount); - $this->assertNotNull($ref->id); - } - - // Deprecated charge endpoints: - - public function testCreateViaCharge() - { - $charge = self::createTestCharge(); - $ref = $charge->refunds->create(array('amount' => 100)); - $this->assertSame(100, $ref->amount); - $this->assertSame($charge->id, $ref->charge); - } - - public function testUpdateAndRetrieveViaCharge() - { - $charge = self::createTestCharge(); - $ref = $charge->refunds->create(array('amount' => 100)); - $ref->metadata["key"] = "value"; - $ref->save(); - $ref = $charge->refunds->retrieve($ref->id); - $this->assertSame("value", $ref->metadata["key"], "value"); - } - - public function testListViaCharge() - { - $charge = self::createTestCharge(); - $refA = $charge->refunds->create(array('amount' => 50)); - $refB = $charge->refunds->create(array('amount' => 50)); - - $all = $charge->refunds->all(); - $this->assertSame(false, $all['has_more']); - $this->assertSame(2, count($all->data)); - $this->assertSame($refB->id, $all->data[0]->id); - $this->assertSame($refA->id, $all->data[1]->id); - } - - public function testCreateForBitcoinViaCharge() - { - self::authorizeFromEnv(); - - $receiver = $this->createTestBitcoinReceiver("do+fill_now@stripe.com"); - - $charge = Charge::create( - array( - 'amount' => $receiver->amount, - 'currency' => $receiver->currency, - 'description' => $receiver->description, - 'source' => $receiver->id - ) - ); - - $ref = $charge->refunds->create( - array( - 'amount' => $receiver->amount, - 'refund_address' => 'ABCDEF' - ) - ); - $this->assertSame($receiver->amount, $ref->amount); - $this->assertNotNull($ref->id); - } -} diff --git a/htdocs/includes/stripe/tests/SourceTest.php b/htdocs/includes/stripe/tests/SourceTest.php deleted file mode 100644 index 5ba142b9be2..00000000000 --- a/htdocs/includes/stripe/tests/SourceTest.php +++ /dev/null @@ -1,218 +0,0 @@ -mockRequest( - 'GET', - '/v1/sources/src_foo', - array(), - array( - 'id' => 'src_foo', - 'object' => 'source', - ) - ); - $source = Source::retrieve('src_foo'); - $this->assertSame($source->id, 'src_foo'); - } - - public function testCreate() - { - $this->mockRequest( - 'POST', - '/v1/sources', - array( - 'type' => 'bitcoin', - 'amount' => 1000, - 'currency' => 'usd', - 'owner' => array('email' => 'jenny.rosen@example.com'), - ), - array( - 'id' => 'src_foo', - 'object' => 'source' - ) - ); - $source = Source::create(array( - 'type' => 'bitcoin', - 'amount' => 1000, - 'currency' => 'usd', - 'owner' => array('email' => 'jenny.rosen@example.com'), - )); - $this->assertSame($source->id, 'src_foo'); - } - - public function testSave() - { - $response = array( - 'id' => 'src_foo', - 'object' => 'source', - 'metadata' => array(), - ); - $this->mockRequest( - 'GET', - '/v1/sources/src_foo', - array(), - $response - ); - - $response['metadata'] = array('foo' => 'bar'); - $this->mockRequest( - 'POST', - '/v1/sources/src_foo', - array( - 'metadata' => array('foo' => 'bar'), - ), - $response - ); - - $source = Source::retrieve('src_foo'); - $source->metadata['foo'] = 'bar'; - $source->save(); - $this->assertSame($source->metadata['foo'], 'bar'); - } - - public function testSaveOwner() - { - $response = array( - 'id' => 'src_foo', - 'object' => 'source', - 'owner' => array( - 'name' => null, - 'address' => null, - ), - ); - $this->mockRequest( - 'GET', - '/v1/sources/src_foo', - array(), - $response - ); - - $response['owner'] = array( - 'name' => "Stripey McStripe", - 'address' => array( - 'line1' => "Test Address", - 'city' => "Test City", - 'postal_code' => "12345", - 'state' => "Test State", - 'country' => "Test Country", - ) - ); - $this->mockRequest( - 'POST', - '/v1/sources/src_foo', - array( - 'owner' => array( - 'name' => "Stripey McStripe", - 'address' => array( - 'line1' => "Test Address", - 'city' => "Test City", - 'postal_code' => "12345", - 'state' => "Test State", - 'country' => "Test Country", - ), - ), - ), - $response - ); - - $source = Source::retrieve('src_foo'); - $source->owner['name'] = "Stripey McStripe"; - $source->owner['address'] = array( - 'line1' => "Test Address", - 'city' => "Test City", - 'postal_code' => "12345", - 'state' => "Test State", - 'country' => "Test Country", - ); - $source->save(); - $this->assertSame($source->owner['name'], "Stripey McStripe"); - $this->assertSame($source->owner['address']['line1'], "Test Address"); - $this->assertSame($source->owner['address']['city'], "Test City"); - $this->assertSame($source->owner['address']['postal_code'], "12345"); - $this->assertSame($source->owner['address']['state'], "Test State"); - $this->assertSame($source->owner['address']['country'], "Test Country"); - } - - public function testDeleteAttached() - { - $response = array( - 'id' => 'src_foo', - 'object' => 'source', - 'customer' => 'cus_bar', - ); - $this->mockRequest( - 'GET', - '/v1/sources/src_foo', - array(), - $response - ); - - unset($response['customer']); - $this->mockRequest( - 'DELETE', - '/v1/customers/cus_bar/sources/src_foo', - array(), - $response - ); - - $source = Source::retrieve('src_foo'); - $source->delete(); - $this->assertFalse(array_key_exists('customer', $source)); - } - - /** - * @expectedException Stripe\Error\Api - */ - public function testDeleteUnattached() - { - $response = array( - 'id' => 'src_foo', - 'object' => 'source', - ); - $this->mockRequest( - 'GET', - '/v1/sources/src_foo', - array(), - $response - ); - - $source = Source::retrieve('src_foo'); - $source->delete(); - } - - public function testVerify() - { - $response = array( - 'id' => 'src_foo', - 'object' => 'source', - 'verification' => array('status' => 'pending'), - ); - $this->mockRequest( - 'GET', - '/v1/sources/src_foo', - array(), - $response - ); - - $response['verification']['status'] = 'succeeded'; - $this->mockRequest( - 'POST', - '/v1/sources/src_foo/verify', - array( - 'values' => array(32, 45), - ), - $response - ); - - $source = Source::retrieve('src_foo'); - $this->assertSame($source->verification->status, 'pending'); - $source->verify(array( - 'values' => array(32, 45), - )); - $this->assertSame($source->verification->status, 'succeeded'); - } -} diff --git a/htdocs/includes/stripe/tests/Stripe/AccountTest.php b/htdocs/includes/stripe/tests/Stripe/AccountTest.php new file mode 100644 index 00000000000..4c621690dcf --- /dev/null +++ b/htdocs/includes/stripe/tests/Stripe/AccountTest.php @@ -0,0 +1,365 @@ +expectsRequest( + 'get', + '/v1/accounts' + ); + $resources = Account::all(); + $this->assertTrue(is_array($resources->data)); + $this->assertInstanceOf("Stripe\\Account", $resources->data[0]); + } + + public function testIsRetrievable() + { + $this->expectsRequest( + 'get', + '/v1/accounts/' . self::TEST_RESOURCE_ID + ); + $resource = Account::retrieve(self::TEST_RESOURCE_ID); + $this->assertInstanceOf("Stripe\\Account", $resource); + } + + public function testIsRetrievableWithoutId() + { + $this->expectsRequest( + 'get', + '/v1/account' + ); + $resource = Account::retrieve(); + $this->assertInstanceOf("Stripe\\Account", $resource); + } + + public function testIsCreatable() + { + $this->expectsRequest( + 'post', + '/v1/accounts' + ); + $resource = Account::create(["type" => "custom"]); + $this->assertInstanceOf("Stripe\\Account", $resource); + } + + public function testIsSaveable() + { + $resource = Account::retrieve(self::TEST_RESOURCE_ID); + $resource->metadata["key"] = "value"; + $this->expectsRequest( + 'post', + '/v1/accounts/' . $resource->id + ); + $resource->save(); + $this->assertInstanceOf("Stripe\\Account", $resource); + } + + public function testIsUpdatable() + { + $this->expectsRequest( + 'post', + '/v1/accounts/' . self::TEST_RESOURCE_ID + ); + $resource = Account::update(self::TEST_RESOURCE_ID, [ + "metadata" => ["key" => "value"], + ]); + $this->assertInstanceOf("Stripe\\Account", $resource); + } + + public function testIsDeletable() + { + $resource = Account::retrieve(self::TEST_RESOURCE_ID); + $this->expectsRequest( + 'delete', + '/v1/accounts/' . $resource->id + ); + $resource->delete(); + $this->assertInstanceOf("Stripe\\Account", $resource); + } + + public function testIsRejectable() + { + $account = Account::retrieve(self::TEST_RESOURCE_ID); + $this->expectsRequest( + 'post', + '/v1/accounts/' . $account->id . '/reject' + ); + $resource = $account->reject(["reason" => "fraud"]); + $this->assertInstanceOf("Stripe\\Account", $resource); + $this->assertSame($resource, $account); + } + + public function testIsDeauthorizable() + { + $resource = Account::retrieve(self::TEST_RESOURCE_ID); + $this->stubRequest( + 'post', + '/oauth/deauthorize', + [ + 'client_id' => Stripe::getClientId(), + 'stripe_user_id' => $resource->id, + ], + null, + false, + [ + 'stripe_user_id' => $resource->id, + ], + 200, + Stripe::$connectBase + ); + $resource->deauthorize(); + } + + public function testCanCreateExternalAccount() + { + $this->expectsRequest( + 'post', + '/v1/accounts/' . self::TEST_RESOURCE_ID . '/external_accounts' + ); + $resource = Account::createExternalAccount(self::TEST_RESOURCE_ID, [ + "external_account" => "btok_123", + ]); + $this->assertInstanceOf("Stripe\\BankAccount", $resource); + } + + public function testCanRetrieveExternalAccount() + { + $this->expectsRequest( + 'get', + '/v1/accounts/' . self::TEST_RESOURCE_ID . '/external_accounts/' . self::TEST_EXTERNALACCOUNT_ID + ); + $resource = Account::retrieveExternalAccount(self::TEST_RESOURCE_ID, self::TEST_EXTERNALACCOUNT_ID); + $this->assertInstanceOf("Stripe\\BankAccount", $resource); + } + + public function testCanUpdateExternalAccount() + { + $this->expectsRequest( + 'post', + '/v1/accounts/' . self::TEST_RESOURCE_ID . '/external_accounts/' . self::TEST_EXTERNALACCOUNT_ID + ); + $resource = Account::updateExternalAccount(self::TEST_RESOURCE_ID, self::TEST_EXTERNALACCOUNT_ID, [ + "name" => "name", + ]); + $this->assertInstanceOf("Stripe\\BankAccount", $resource); + } + + public function testCanDeleteExternalAccount() + { + $this->expectsRequest( + 'delete', + '/v1/accounts/' . self::TEST_RESOURCE_ID . '/external_accounts/' . self::TEST_EXTERNALACCOUNT_ID + ); + $resource = Account::deleteExternalAccount(self::TEST_RESOURCE_ID, self::TEST_EXTERNALACCOUNT_ID); + $this->assertInstanceOf("Stripe\\BankAccount", $resource); + } + + public function testCanListExternalAccounts() + { + $this->expectsRequest( + 'get', + '/v1/accounts/' . self::TEST_RESOURCE_ID . '/external_accounts' + ); + $resources = Account::allExternalAccounts(self::TEST_RESOURCE_ID); + $this->assertTrue(is_array($resources->data)); + } + + public function testCanCreateLoginLink() + { + $this->expectsRequest( + 'post', + '/v1/accounts/' . self::TEST_RESOURCE_ID . '/login_links' + ); + $resource = Account::createLoginLink(self::TEST_RESOURCE_ID); + $this->assertInstanceOf("Stripe\\LoginLink", $resource); + } + + public function testSerializeNewAdditionalOwners() + { + $obj = Util\Util::convertToStripeObject([ + 'object' => 'account', + 'legal_entity' => StripeObject::constructFrom([]), + ], null); + $obj->legal_entity->additional_owners = [ + ['first_name' => 'Joe'], + ['first_name' => 'Jane'], + ]; + + $expected = [ + 'legal_entity' => [ + 'additional_owners' => [ + 0 => ['first_name' => 'Joe'], + 1 => ['first_name' => 'Jane'], + ], + ], + ]; + $this->assertSame($expected, $obj->serializeParameters()); + } + + public function testSerializePartiallyChangedAdditionalOwners() + { + $obj = Util\Util::convertToStripeObject([ + 'object' => 'account', + 'legal_entity' => [ + 'additional_owners' => [ + StripeObject::constructFrom(['first_name' => 'Joe']), + StripeObject::constructFrom(['first_name' => 'Jane']), + ], + ], + ], null); + $obj->legal_entity->additional_owners[1]->first_name = 'Stripe'; + + $expected = [ + 'legal_entity' => [ + 'additional_owners' => [ + 1 => ['first_name' => 'Stripe'], + ], + ], + ]; + $this->assertSame($expected, $obj->serializeParameters()); + } + + public function testSerializeUnchangedAdditionalOwners() + { + $obj = Util\Util::convertToStripeObject([ + 'object' => 'account', + 'legal_entity' => [ + 'additional_owners' => [ + StripeObject::constructFrom(['first_name' => 'Joe']), + StripeObject::constructFrom(['first_name' => 'Jane']), + ], + ], + ], null); + + $expected = [ + 'legal_entity' => [ + 'additional_owners' => [], + ], + ]; + $this->assertSame($expected, $obj->serializeParameters()); + } + + public function testSerializeUnsetAdditionalOwners() + { + $obj = Util\Util::convertToStripeObject([ + 'object' => 'account', + 'legal_entity' => [ + 'additional_owners' => [ + StripeObject::constructFrom(['first_name' => 'Joe']), + StripeObject::constructFrom(['first_name' => 'Jane']), + ], + ], + ], null); + $obj->legal_entity->additional_owners = null; + + // Note that the empty string that we send for this one has a special + // meaning for the server, which interprets it as an array unset. + $expected = [ + 'legal_entity' => [ + 'additional_owners' => '', + ], + ]; + $this->assertSame($expected, $obj->serializeParameters()); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testSerializeAdditionalOwnersDeletedItem() + { + $obj = Util\Util::convertToStripeObject([ + 'object' => 'account', + 'legal_entity' => [ + 'additional_owners' => [ + StripeObject::constructFrom(['first_name' => 'Joe']), + StripeObject::constructFrom(['first_name' => 'Jane']), + ], + ], + ], null); + unset($obj->legal_entity->additional_owners[0]); + + $obj->serializeParameters(); + } + + public function testSerializeExternalAccountString() + { + $obj = Util\Util::convertToStripeObject([ + 'object' => 'account', + ], null); + $obj->external_account = 'btok_123'; + + $expected = [ + 'external_account' => 'btok_123', + ]; + $this->assertSame($expected, $obj->serializeParameters()); + } + + public function testSerializeExternalAccountHash() + { + $obj = Util\Util::convertToStripeObject([ + 'object' => 'account', + ], null); + $obj->external_account = [ + 'object' => 'bank_account', + 'routing_number' => '110000000', + 'account_number' => '000123456789', + 'country' => 'US', + 'currency' => 'usd', + ]; + + $expected = [ + 'external_account' => [ + 'object' => 'bank_account', + 'routing_number' => '110000000', + 'account_number' => '000123456789', + 'country' => 'US', + 'currency' => 'usd', + ], + ]; + $this->assertSame($expected, $obj->serializeParameters()); + } + + public function testSerializeBankAccountString() + { + $obj = Util\Util::convertToStripeObject([ + 'object' => 'account', + ], null); + $obj->bank_account = 'btok_123'; + + $expected = [ + 'bank_account' => 'btok_123', + ]; + $this->assertSame($expected, $obj->serializeParameters()); + } + + public function testSerializeBankAccountHash() + { + $obj = Util\Util::convertToStripeObject([ + 'object' => 'account', + ], null); + $obj->bank_account = [ + 'object' => 'bank_account', + 'routing_number' => '110000000', + 'account_number' => '000123456789', + 'country' => 'US', + 'currency' => 'usd', + ]; + + $expected = [ + 'bank_account' => [ + 'object' => 'bank_account', + 'routing_number' => '110000000', + 'account_number' => '000123456789', + 'country' => 'US', + 'currency' => 'usd', + ], + ]; + $this->assertSame($expected, $obj->serializeParameters()); + } +} diff --git a/htdocs/includes/stripe/tests/Stripe/AlipayAccountTest.php b/htdocs/includes/stripe/tests/Stripe/AlipayAccountTest.php new file mode 100644 index 00000000000..7159f5444df --- /dev/null +++ b/htdocs/includes/stripe/tests/Stripe/AlipayAccountTest.php @@ -0,0 +1,76 @@ + self::TEST_RESOURCE_ID, + 'object' => 'card', + 'metadata' => [], + ]; + return AlipayAccount::constructFrom( + array_merge($params, $base), + new Util\RequestOptions() + ); + } + + public function testHasCorrectUrlForCustomer() + { + $resource = $this->createFixture(['customer' => 'cus_123']); + $this->assertSame( + "/v1/customers/cus_123/sources/" . self::TEST_RESOURCE_ID, + $resource->instanceUrl() + ); + } + + /** + * @expectedException \Stripe\Error\InvalidRequest + */ + public function testIsNotDirectlyRetrievable() + { + AlipayAccount::retrieve(self::TEST_RESOURCE_ID); + } + + public function testIsSaveable() + { + $resource = $this->createFixture(); + $resource->metadata["key"] = "value"; + $this->expectsRequest( + 'post', + '/v1/customers/cus_123/sources/' . self::TEST_RESOURCE_ID + ); + $resource->save(); + $this->assertSame("Stripe\\AlipayAccount", get_class($resource)); + } + + /** + * @expectedException \Stripe\Error\InvalidRequest + */ + public function testIsNotDirectlyUpdatable() + { + AlipayAccount::update(self::TEST_RESOURCE_ID, [ + "metadata" => ["key" => "value"], + ]); + } + + public function testIsDeletable() + { + $resource = $this->createFixture(); + $this->expectsRequest( + 'delete', + '/v1/customers/cus_123/sources/' . self::TEST_RESOURCE_ID + ); + $resource->delete(); + $this->assertSame("Stripe\\AlipayAccount", get_class($resource)); + } +} diff --git a/htdocs/includes/stripe/tests/Stripe/ApiRequestorTest.php b/htdocs/includes/stripe/tests/Stripe/ApiRequestorTest.php new file mode 100644 index 00000000000..6fb8229c57d --- /dev/null +++ b/htdocs/includes/stripe/tests/Stripe/ApiRequestorTest.php @@ -0,0 +1,572 @@ +getMethod('_encodeObjects'); + $method->setAccessible(true); + + $a = ['customer' => new Customer('abcd')]; + $enc = $method->invoke(null, $a); + $this->assertSame($enc, ['customer' => 'abcd']); + + // Preserves UTF-8 + $v = ['customer' => "☃"]; + $enc = $method->invoke(null, $v); + $this->assertSame($enc, $v); + + // Encodes latin-1 -> UTF-8 + $v = ['customer' => "\xe9"]; + $enc = $method->invoke(null, $v); + $this->assertSame($enc, ['customer' => "\xc3\xa9"]); + + // Encodes booleans + $v = true; + $enc = $method->invoke(null, $v); + $this->assertSame('true', $enc); + + $v = false; + $enc = $method->invoke(null, $v); + $this->assertSame('false', $enc); + } + + public function testHttpClientInjection() + { + $reflector = new \ReflectionClass('Stripe\\ApiRequestor'); + $method = $reflector->getMethod('httpClient'); + $method->setAccessible(true); + + $curl = new CurlClient(); + $curl->setTimeout(10); + ApiRequestor::setHttpClient($curl); + + $injectedCurl = $method->invoke(new ApiRequestor()); + $this->assertSame($injectedCurl, $curl); + } + + public function testDefaultHeaders() + { + $reflector = new \ReflectionClass('Stripe\\ApiRequestor'); + $method = $reflector->getMethod('_defaultHeaders'); + $method->setAccessible(true); + + // no way to stub static methods with PHPUnit 4.x :( + Stripe::setAppInfo('MyTestApp', '1.2.34', 'https://mytestapp.example'); + $apiKey = 'sk_test_notarealkey'; + $clientInfo = ['httplib' => 'testlib 0.1.2']; + + $headers = $method->invoke(null, $apiKey, $clientInfo); + + $ua = json_decode($headers['X-Stripe-Client-User-Agent']); + $this->assertSame($ua->application->name, 'MyTestApp'); + $this->assertSame($ua->application->version, '1.2.34'); + $this->assertSame($ua->application->url, 'https://mytestapp.example'); + + $this->assertSame($ua->httplib, 'testlib 0.1.2'); + + $this->assertSame( + $headers['User-Agent'], + 'Stripe/v1 PhpBindings/' . Stripe::VERSION . ' MyTestApp/1.2.34 (https://mytestapp.example)' + ); + + $this->assertSame($headers['Authorization'], 'Bearer ' . $apiKey); + } + + /** + * @expectedException \Stripe\Error\Authentication + * @expectedExceptionMessageRegExp #No API key provided# + */ + public function testRaisesAuthenticationErrorWhenNoApiKey() + { + Stripe::setApiKey(null); + Charge::create(); + } + + public function testRaisesInvalidRequestErrorOn400() + { + $this->stubRequest( + 'POST', + '/v1/charges', + [], + null, + false, + [ + 'error' => [ + 'type' => 'invalid_request_error', + 'message' => 'Missing id', + 'param' => 'id', + ], + ], + 400 + ); + + try { + Charge::create(); + $this->fail("Did not raise error"); + } catch (Error\InvalidRequest $e) { + $this->assertSame(400, $e->getHttpStatus()); + $this->assertTrue(is_array($e->getJsonBody())); + $this->assertSame('Missing id', $e->getMessage()); + $this->assertSame('id', $e->getStripeParam()); + } catch (\Exception $e) { + $this->fail("Unexpected exception: " . get_class($e)); + } + } + + public function testRaisesIdempotencyErrorOn400AndTypeIdempotencyError() + { + $this->stubRequest( + 'POST', + '/v1/charges', + array(), + null, + false, + array( + 'error' => array( + 'type' => 'idempotency_error', + 'message' => "Keys for idempotent requests can only be used with the same parameters they were first used with. Try using a key other than 'abc' if you meant to execute a different request.", + ), + ), + 400 + ); + + try { + Charge::create(); + $this->fail("Did not raise error"); + } catch (Error\Idempotency $e) { + $this->assertSame(400, $e->getHttpStatus()); + $this->assertTrue(is_array($e->getJsonBody())); + $this->assertSame("Keys for idempotent requests can only be used with the same parameters they were first used with. Try using a key other than 'abc' if you meant to execute a different request.", $e->getMessage()); + } catch (\Exception $e) { + $this->fail("Unexpected exception: " . get_class($e)); + } + } + + public function testRaisesAuthenticationErrorOn401() + { + $this->stubRequest( + 'POST', + '/v1/charges', + [], + null, + false, + [ + 'error' => [ + 'type' => 'invalid_request_error', + 'message' => 'You did not provide an API key.', + ], + ], + 401 + ); + + try { + Charge::create(); + $this->fail("Did not raise error"); + } catch (Error\Authentication $e) { + $this->assertSame(401, $e->getHttpStatus()); + $this->assertTrue(is_array($e->getJsonBody())); + $this->assertSame('You did not provide an API key.', $e->getMessage()); + } catch (\Exception $e) { + $this->fail("Unexpected exception: " . get_class($e)); + } + } + + public function testRaisesCardErrorOn402() + { + $this->stubRequest( + 'POST', + '/v1/charges', + [], + null, + false, + [ + 'error' => [ + 'type' => 'card_error', + 'message' => 'Your card was declined.', + 'code' => 'card_declined', + 'decline_code' => 'generic_decline', + 'charge' => 'ch_declined_charge', + 'param' => 'exp_month', + ], + ], + 402 + ); + + try { + Charge::create(); + $this->fail("Did not raise error"); + } catch (Error\Card $e) { + $this->assertSame(402, $e->getHttpStatus()); + $this->assertTrue(is_array($e->getJsonBody())); + $this->assertSame('Your card was declined.', $e->getMessage()); + $this->assertSame('card_declined', $e->getStripeCode()); + $this->assertSame('generic_decline', $e->getDeclineCode()); + $this->assertSame('exp_month', $e->getStripeParam()); + } catch (\Exception $e) { + $this->fail("Unexpected exception: " . get_class($e)); + } + } + + public function testRaisesPermissionErrorOn403() + { + $this->stubRequest( + 'GET', + '/v1/accounts/foo', + [], + null, + false, + [ + 'error' => [ + 'type' => 'invalid_request_error', + 'message' => "The provided key 'sk_test_********************1234' does not have access to account 'foo' (or that account does not exist). Application access may have been revoked.", + ], + ], + 403 + ); + + try { + Account::retrieve('foo'); + $this->fail("Did not raise error"); + } catch (Error\Permission $e) { + $this->assertSame(403, $e->getHttpStatus()); + $this->assertTrue(is_array($e->getJsonBody())); + $this->assertSame("The provided key 'sk_test_********************1234' does not have access to account 'foo' (or that account does not exist). Application access may have been revoked.", $e->getMessage()); + } catch (\Exception $e) { + $this->fail("Unexpected exception: " . get_class($e)); + } + } + + public function testRaisesInvalidRequestErrorOn404() + { + $this->stubRequest( + 'GET', + '/v1/charges/foo', + [], + null, + false, + [ + 'error' => [ + 'type' => 'invalid_request_error', + 'message' => 'No such charge: foo', + 'param' => 'id', + ], + ], + 404 + ); + + try { + Charge::retrieve('foo'); + $this->fail("Did not raise error"); + } catch (Error\InvalidRequest $e) { + $this->assertSame(404, $e->getHttpStatus()); + $this->assertTrue(is_array($e->getJsonBody())); + $this->assertSame('No such charge: foo', $e->getMessage()); + $this->assertSame('id', $e->getStripeParam()); + } catch (\Exception $e) { + $this->fail("Unexpected exception: " . get_class($e)); + } + } + + public function testRaisesRateLimitErrorOn429() + { + $this->stubRequest( + 'POST', + '/v1/charges', + [], + null, + false, + [ + 'error' => [ + 'message' => 'Too many requests', + ], + ], + 429 + ); + + try { + Charge::create(); + $this->fail("Did not raise error"); + } catch (Error\RateLimit $e) { + $this->assertSame(429, $e->getHttpStatus()); + $this->assertTrue(is_array($e->getJsonBody())); + $this->assertSame('Too many requests', $e->getMessage()); + } catch (\Exception $e) { + $this->fail("Unexpected exception: " . get_class($e)); + } + } + + public function testRaisesRateLimitErrorOn400AndCodeRateLimit() + { + $this->stubRequest( + 'POST', + '/v1/charges', + [], + null, + false, + [ + 'error' => [ + 'code' => 'rate_limit', + 'message' => 'Too many requests', + ], + ], + 400 + ); + + try { + Charge::create(); + $this->fail("Did not raise error"); + } catch (Error\RateLimit $e) { + $this->assertSame(400, $e->getHttpStatus()); + $this->assertTrue(is_array($e->getJsonBody())); + $this->assertSame('Too many requests', $e->getMessage()); + } catch (\Exception $e) { + $this->fail("Unexpected exception: " . get_class($e)); + } + } + + public function testRaisesOAuthInvalidRequestError() + { + $this->stubRequest( + 'POST', + '/oauth/token', + [], + null, + false, + [ + 'error' => 'invalid_request', + 'error_description' => 'No grant type specified', + ], + 400, + Stripe::$connectBase + ); + + try { + OAuth::token(); + $this->fail("Did not raise error"); + } catch (Error\OAuth\InvalidRequest $e) { + $this->assertSame(400, $e->getHttpStatus()); + $this->assertSame('invalid_request', $e->getErrorCode()); + $this->assertSame('No grant type specified', $e->getMessage()); + } catch (\Exception $e) { + $this->fail("Unexpected exception: " . get_class($e)); + } + } + + public function testRaisesOAuthInvalidClientError() + { + $this->stubRequest( + 'POST', + '/oauth/token', + [], + null, + false, + [ + 'error' => 'invalid_client', + 'error_description' => 'No authentication was provided. Send your secret API key using the Authorization header, or as a client_secret POST parameter.', + ], + 401, + Stripe::$connectBase + ); + + try { + OAuth::token(); + $this->fail("Did not raise error"); + } catch (Error\OAuth\InvalidClient $e) { + $this->assertSame(401, $e->getHttpStatus()); + $this->assertSame('invalid_client', $e->getErrorCode()); + $this->assertSame('No authentication was provided. Send your secret API key using the Authorization header, or as a client_secret POST parameter.', $e->getMessage()); + } catch (\Exception $e) { + $this->fail("Unexpected exception: " . get_class($e)); + } + } + + public function testRaisesOAuthInvalidGrantError() + { + $this->stubRequest( + 'POST', + '/oauth/token', + [], + null, + false, + [ + 'error' => 'invalid_grant', + 'error_description' => 'This authorization code has already been used. All tokens issued with this code have been revoked.', + ], + 400, + Stripe::$connectBase + ); + + try { + OAuth::token(); + $this->fail("Did not raise error"); + } catch (Error\OAuth\InvalidGrant $e) { + $this->assertSame(400, $e->getHttpStatus()); + $this->assertSame('invalid_grant', $e->getErrorCode()); + $this->assertSame('This authorization code has already been used. All tokens issued with this code have been revoked.', $e->getMessage()); + } catch (\Exception $e) { + $this->fail("Unexpected exception: " . get_class($e)); + } + } + + public function testRaisesOAuthInvalidScopeError() + { + $this->stubRequest( + 'POST', + '/oauth/token', + [], + null, + false, + [ + 'error' => 'invalid_scope', + 'error_description' => 'Invalid scope provided: invalid_scope.', + ], + 400, + Stripe::$connectBase + ); + + try { + OAuth::token(); + $this->fail("Did not raise error"); + } catch (Error\OAuth\InvalidScope $e) { + $this->assertSame(400, $e->getHttpStatus()); + $this->assertSame('invalid_scope', $e->getErrorCode()); + $this->assertSame('Invalid scope provided: invalid_scope.', $e->getMessage()); + } catch (\Exception $e) { + $this->fail("Unexpected exception: " . get_class($e)); + } + } + + public function testRaisesOAuthUnsupportedGrantTypeError() + { + $this->stubRequest( + 'POST', + '/oauth/token', + [], + null, + false, + [ + 'error' => 'unsupported_grant_type', + ], + 400, + Stripe::$connectBase + ); + + try { + OAuth::token(); + $this->fail("Did not raise error"); + } catch (Error\OAuth\UnsupportedGrantType $e) { + $this->assertSame(400, $e->getHttpStatus()); + $this->assertSame('unsupported_grant_type', $e->getErrorCode()); + } catch (\Exception $e) { + $this->fail("Unexpected exception: " . get_class($e)); + } + } + + public function testRaisesOAuthUnsupportedResponseTypeError() + { + $this->stubRequest( + 'POST', + '/oauth/token', + [], + null, + false, + [ + 'error' => 'unsupported_response_type', + 'error_description' => "Only 'code' response_type is supported, but 'unsupported_response_type' was provided", + ], + 400, + Stripe::$connectBase + ); + + try { + OAuth::token(); + $this->fail("Did not raise error"); + } catch (Error\OAuth\UnsupportedResponseType $e) { + $this->assertSame(400, $e->getHttpStatus()); + $this->assertSame('unsupported_response_type', $e->getErrorCode()); + $this->assertSame("Only 'code' response_type is supported, but 'unsupported_response_type' was provided", $e->getMessage()); + } catch (\Exception $e) { + $this->fail("Unexpected exception: " . get_class($e)); + } + } + + public function testHeaderStripeVersionGlobal() + { + Stripe::setApiVersion('2222-22-22'); + $this->stubRequest( + 'POST', + '/v1/charges', + [], + [ + 'Stripe-Version: 2222-22-22', + ], + false, + [ + 'id' => 'ch_123', + 'object' => 'charge', + ] + ); + Charge::create(); + } + + public function testHeaderStripeVersionRequestOptions() + { + $this->stubRequest( + 'POST', + '/v1/charges', + [], + [ + 'Stripe-Version: 2222-22-22', + ], + false, + [ + 'id' => 'ch_123', + 'object' => 'charge', + ] + ); + Charge::create([], ['stripe_version' => '2222-22-22']); + } + + public function testHeaderStripeAccountGlobal() + { + Stripe::setAccountId('acct_123'); + $this->stubRequest( + 'POST', + '/v1/charges', + [], + [ + 'Stripe-Account: acct_123', + ], + false, + [ + 'id' => 'ch_123', + 'object' => 'charge', + ] + ); + Charge::create(); + } + + public function testHeaderStripeAccountRequestOptions() + { + $this->stubRequest( + 'POST', + '/v1/charges', + [], + [ + 'Stripe-Account: acct_123', + ], + false, + [ + 'id' => 'ch_123', + 'object' => 'charge', + ] + ); + Charge::create([], ['stripe_account' => 'acct_123']); + } +} diff --git a/htdocs/includes/stripe/tests/Stripe/ApplePayDomainTest.php b/htdocs/includes/stripe/tests/Stripe/ApplePayDomainTest.php new file mode 100644 index 00000000000..d033f55cbb0 --- /dev/null +++ b/htdocs/includes/stripe/tests/Stripe/ApplePayDomainTest.php @@ -0,0 +1,52 @@ +expectsRequest( + 'get', + '/v1/apple_pay/domains' + ); + $resources = ApplePayDomain::all(); + $this->assertTrue(is_array($resources->data)); + $this->assertInstanceOf("Stripe\\ApplePayDomain", $resources->data[0]); + } + + public function testIsRetrievable() + { + $this->expectsRequest( + 'get', + '/v1/apple_pay/domains/' . self::TEST_RESOURCE_ID + ); + $resource = ApplePayDomain::retrieve(self::TEST_RESOURCE_ID); + $this->assertInstanceOf("Stripe\\ApplePayDomain", $resource); + } + + public function testIsCreatable() + { + $this->expectsRequest( + 'post', + '/v1/apple_pay/domains' + ); + $resource = ApplePayDomain::create([ + "domain_name" => "domain", + ]); + $this->assertInstanceOf("Stripe\\ApplePayDomain", $resource); + } + + public function testIsDeletable() + { + $resource = ApplePayDomain::retrieve(self::TEST_RESOURCE_ID); + $this->expectsRequest( + 'delete', + '/v1/apple_pay/domains/' . $resource->id + ); + $resource->delete(); + $this->assertInstanceOf("Stripe\\ApplePayDomain", $resource); + } +} diff --git a/htdocs/includes/stripe/tests/Stripe/ApplicationFeeRefundTest.php b/htdocs/includes/stripe/tests/Stripe/ApplicationFeeRefundTest.php new file mode 100644 index 00000000000..9af059ff7f3 --- /dev/null +++ b/htdocs/includes/stripe/tests/Stripe/ApplicationFeeRefundTest.php @@ -0,0 +1,21 @@ +metadata["key"] = "value"; + $this->expectsRequest( + 'post', + '/v1/application_fees/' . $resource->fee . '/refunds/' . $resource->id + ); + $resource->save(); + $this->assertInstanceOf("Stripe\\ApplicationFeeRefund", $resource); + } +} diff --git a/htdocs/includes/stripe/tests/Stripe/ApplicationFeeTest.php b/htdocs/includes/stripe/tests/Stripe/ApplicationFeeTest.php new file mode 100644 index 00000000000..66e007ff3d2 --- /dev/null +++ b/htdocs/includes/stripe/tests/Stripe/ApplicationFeeTest.php @@ -0,0 +1,83 @@ +expectsRequest( + 'get', + '/v1/application_fees' + ); + $resources = ApplicationFee::all(); + $this->assertTrue(is_array($resources->data)); + $this->assertInstanceOf("Stripe\\ApplicationFee", $resources->data[0]); + } + + public function testIsRetrievable() + { + $this->expectsRequest( + 'get', + '/v1/application_fees/' . self::TEST_RESOURCE_ID + ); + $resource = ApplicationFee::retrieve(self::TEST_RESOURCE_ID); + $this->assertInstanceOf("Stripe\\ApplicationFee", $resource); + } + + public function testIsRefundable() + { + $fee = ApplicationFee::retrieve(self::TEST_RESOURCE_ID); + $this->expectsRequest( + 'post', + '/v1/application_fees/' . $fee->id . '/refunds' + ); + $resource = $fee->refund(); + $this->assertInstanceOf("Stripe\\ApplicationFee", $resource); + $this->assertSame($resource, $fee); + } + + public function testCanCreateRefund() + { + $this->expectsRequest( + 'post', + '/v1/application_fees/' . self::TEST_RESOURCE_ID . '/refunds' + ); + $resource = ApplicationFee::createRefund(self::TEST_RESOURCE_ID); + $this->assertInstanceOf("Stripe\\ApplicationFeeRefund", $resource); + } + + public function testCanRetrieveRefund() + { + $this->expectsRequest( + 'get', + '/v1/application_fees/' . self::TEST_RESOURCE_ID . '/refunds/' . self::TEST_FEEREFUND_ID + ); + $resource = ApplicationFee::retrieveRefund(self::TEST_RESOURCE_ID, self::TEST_FEEREFUND_ID); + $this->assertInstanceOf("Stripe\\ApplicationFeeRefund", $resource); + } + + public function testCanUpdateRefund() + { + $this->expectsRequest( + 'post', + '/v1/application_fees/' . self::TEST_RESOURCE_ID . '/refunds/' . self::TEST_FEEREFUND_ID + ); + $resource = ApplicationFee::updateRefund(self::TEST_RESOURCE_ID, self::TEST_FEEREFUND_ID); + $this->assertInstanceOf("Stripe\\ApplicationFeeRefund", $resource); + } + + public function testCanListRefunds() + { + $this->expectsRequest( + 'get', + '/v1/application_fees/' . self::TEST_RESOURCE_ID . '/refunds' + ); + $resources = ApplicationFee::allRefunds(self::TEST_RESOURCE_ID); + $this->assertTrue(is_array($resources->data)); + $this->assertInstanceOf("Stripe\\ApplicationFeeRefund", $resources->data[0]); + } +} diff --git a/htdocs/includes/stripe/tests/Stripe/BalanceTest.php b/htdocs/includes/stripe/tests/Stripe/BalanceTest.php new file mode 100644 index 00000000000..ccbdbdfb747 --- /dev/null +++ b/htdocs/includes/stripe/tests/Stripe/BalanceTest.php @@ -0,0 +1,16 @@ +expectsRequest( + 'get', + '/v1/balance' + ); + $resource = Balance::retrieve(); + $this->assertInstanceOf("Stripe\\Balance", $resource); + } +} diff --git a/htdocs/includes/stripe/tests/Stripe/BalanceTransactionTest.php b/htdocs/includes/stripe/tests/Stripe/BalanceTransactionTest.php new file mode 100644 index 00000000000..8785e859113 --- /dev/null +++ b/htdocs/includes/stripe/tests/Stripe/BalanceTransactionTest.php @@ -0,0 +1,29 @@ +expectsRequest( + 'get', + '/v1/balance/history' + ); + $resources = BalanceTransaction::all(); + $this->assertTrue(is_array($resources->data)); + $this->assertInstanceOf("Stripe\\BalanceTransaction", $resources->data[0]); + } + + public function testIsRetrievable() + { + $this->expectsRequest( + 'get', + '/v1/balance/history/' . self::TEST_RESOURCE_ID + ); + $resource = BalanceTransaction::retrieve(self::TEST_RESOURCE_ID); + $this->assertInstanceOf("Stripe\\BalanceTransaction", $resource); + } +} diff --git a/htdocs/includes/stripe/tests/Stripe/BankAccountTest.php b/htdocs/includes/stripe/tests/Stripe/BankAccountTest.php new file mode 100644 index 00000000000..ab1dff9d5a8 --- /dev/null +++ b/htdocs/includes/stripe/tests/Stripe/BankAccountTest.php @@ -0,0 +1,99 @@ + self::TEST_RESOURCE_ID, + 'object' => 'bank_account', + 'metadata' => [], + ]; + return BankAccount::constructFrom( + array_merge($params, $base), + new Util\RequestOptions() + ); + } + + public function testHasCorrectUrlForCustomer() + { + $resource = $this->createFixture(['customer' => 'cus_123']); + $this->assertSame( + "/v1/customers/cus_123/sources/" . self::TEST_RESOURCE_ID, + $resource->instanceUrl() + ); + } + + public function testHasCorrectUrlForAccount() + { + $resource = $this->createFixture(['account' => 'acct_123']); + $this->assertSame( + "/v1/accounts/acct_123/external_accounts/" . self::TEST_RESOURCE_ID, + $resource->instanceUrl() + ); + } + + /** + * @expectedException \Stripe\Error\InvalidRequest + */ + public function testIsNotDirectlyRetrievable() + { + BankAccount::retrieve(self::TEST_RESOURCE_ID); + } + + public function testIsSaveable() + { + $resource = $this->createFixture(); + $resource->metadata["key"] = "value"; + $this->expectsRequest( + 'post', + '/v1/customers/cus_123/sources/' . self::TEST_RESOURCE_ID + ); + $resource->save(); + $this->assertSame("Stripe\\BankAccount", get_class($resource)); + } + + /** + * @expectedException \Stripe\Error\InvalidRequest + */ + public function testIsNotDirectlyUpdatable() + { + BankAccount::update(self::TEST_RESOURCE_ID, [ + "metadata" => ["key" => "value"], + ]); + } + + public function testIsDeletable() + { + $resource = $this->createFixture(); + $this->expectsRequest( + 'delete', + '/v1/customers/cus_123/sources/' . self::TEST_RESOURCE_ID + ); + $resource->delete(); + $this->assertSame("Stripe\\BankAccount", get_class($resource)); + } + + public function testIsVerifiable() + { + $resource = $this->createFixture(); + $this->expectsRequest( + 'post', + '/v1/customers/cus_123/sources/' . self::TEST_RESOURCE_ID . "/verify", + [ + "amounts" => [1, 2] + ] + ); + $resource->verify(["amounts" => [1, 2]]); + $this->assertInstanceOf("Stripe\\BankAccount", $resource); + } +} diff --git a/htdocs/includes/stripe/tests/Stripe/BitcoinReceiverTest.php b/htdocs/includes/stripe/tests/Stripe/BitcoinReceiverTest.php new file mode 100644 index 00000000000..cea999fc4f2 --- /dev/null +++ b/htdocs/includes/stripe/tests/Stripe/BitcoinReceiverTest.php @@ -0,0 +1,62 @@ + self::TEST_RESOURCE_ID, + 'object' => 'bitcoin_receiver', + 'metadata' => [], + ]; + return BitcoinReceiver::constructFrom( + array_merge($params, $base), + new Util\RequestOptions() + ); + } + + public function testHasCorrectStandaloneUrl() + { + $resource = $this->createFixture(); + $this->assertSame( + "/v1/bitcoin/receivers/" . self::TEST_RESOURCE_ID, + $resource->instanceUrl() + ); + } + + public function testHasCorrectUrlForCustomer() + { + $resource = $this->createFixture(['customer' => 'cus_123']); + $this->assertSame( + "/v1/customers/cus_123/sources/" . self::TEST_RESOURCE_ID, + $resource->instanceUrl() + ); + } + + public function testIsListable() + { + $this->expectsRequest( + 'get', + '/v1/bitcoin/receivers' + ); + $resources = BitcoinReceiver::all(); + $this->assertTrue(is_array($resources->data)); + $this->assertSame("Stripe\\BitcoinReceiver", get_class($resources->data[0])); + } + + public function testIsRetrievable() + { + $this->expectsRequest( + 'get', + '/v1/bitcoin/receivers/' . self::TEST_RESOURCE_ID + ); + $resource = BitcoinReceiver::retrieve(self::TEST_RESOURCE_ID); + $this->assertSame("Stripe\\BitcoinReceiver", get_class($resource)); + } +} diff --git a/htdocs/includes/stripe/tests/Stripe/CardTest.php b/htdocs/includes/stripe/tests/Stripe/CardTest.php new file mode 100644 index 00000000000..8976eff6679 --- /dev/null +++ b/htdocs/includes/stripe/tests/Stripe/CardTest.php @@ -0,0 +1,94 @@ + self::TEST_RESOURCE_ID, + 'object' => 'card', + 'metadata' => [], + ]; + return Card::constructFrom( + array_merge($params, $base), + new Util\RequestOptions() + ); + } + + public function testHasCorrectUrlForCustomer() + { + $resource = $this->createFixture(['customer' => 'cus_123']); + $this->assertSame( + "/v1/customers/cus_123/sources/" . self::TEST_RESOURCE_ID, + $resource->instanceUrl() + ); + } + + public function testHasCorrectUrlForAccount() + { + $resource = $this->createFixture(['account' => 'acct_123']); + $this->assertSame( + "/v1/accounts/acct_123/external_accounts/" . self::TEST_RESOURCE_ID, + $resource->instanceUrl() + ); + } + + public function testHasCorrectUrlForRecipient() + { + $resource = $this->createFixture(['recipient' => 'rp_123']); + $this->assertSame( + "/v1/recipients/rp_123/cards/" . self::TEST_RESOURCE_ID, + $resource->instanceUrl() + ); + } + + /** + * @expectedException \Stripe\Error\InvalidRequest + */ + public function testIsNotDirectlyRetrievable() + { + Card::retrieve(self::TEST_RESOURCE_ID); + } + + public function testIsSaveable() + { + $resource = $this->createFixture(); + $resource->metadata["key"] = "value"; + $this->expectsRequest( + 'post', + '/v1/customers/cus_123/sources/' . self::TEST_RESOURCE_ID + ); + $resource->save(); + $this->assertSame("Stripe\\Card", get_class($resource)); + } + + /** + * @expectedException \Stripe\Error\InvalidRequest + */ + public function testIsNotDirectlyUpdatable() + { + Card::update(self::TEST_RESOURCE_ID, [ + "metadata" => ["key" => "value"], + ]); + } + + public function testIsDeletable() + { + $resource = $this->createFixture(); + $this->expectsRequest( + 'delete', + '/v1/customers/cus_123/sources/' . self::TEST_RESOURCE_ID + ); + $resource->delete(); + $this->assertSame("Stripe\\Card", get_class($resource)); + } +} diff --git a/htdocs/includes/stripe/tests/Stripe/ChargeTest.php b/htdocs/includes/stripe/tests/Stripe/ChargeTest.php new file mode 100644 index 00000000000..b8c6cbabf3b --- /dev/null +++ b/htdocs/includes/stripe/tests/Stripe/ChargeTest.php @@ -0,0 +1,140 @@ +expectsRequest( + 'get', + '/v1/charges' + ); + $resources = Charge::all(); + $this->assertTrue(is_array($resources->data)); + $this->assertInstanceOf("Stripe\\Charge", $resources->data[0]); + } + + public function testIsRetrievable() + { + $this->expectsRequest( + 'get', + '/v1/charges/' . self::TEST_RESOURCE_ID + ); + $resource = Charge::retrieve(self::TEST_RESOURCE_ID); + $this->assertInstanceOf("Stripe\\Charge", $resource); + } + + public function testIsCreatable() + { + $this->expectsRequest( + 'post', + '/v1/charges' + ); + $resource = Charge::create([ + "amount" => 100, + "currency" => "usd", + "source" => "tok_123" + ]); + $this->assertInstanceOf("Stripe\\Charge", $resource); + } + + public function testIsSaveable() + { + $resource = Charge::retrieve(self::TEST_RESOURCE_ID); + $resource->metadata["key"] = "value"; + $this->expectsRequest( + 'post', + '/v1/charges/' . $resource->id + ); + $resource->save(); + $this->assertInstanceOf("Stripe\\Charge", $resource); + } + + public function testIsUpdatable() + { + $this->expectsRequest( + 'post', + '/v1/charges/' . self::TEST_RESOURCE_ID + ); + $resource = Charge::update(self::TEST_RESOURCE_ID, [ + "metadata" => ["key" => "value"], + ]); + $this->assertInstanceOf("Stripe\\Charge", $resource); + } + + public function testCanRefund() + { + $charge = Charge::retrieve(self::TEST_RESOURCE_ID); + $this->expectsRequest( + 'post', + '/v1/charges/' . $charge->id . '/refund' + ); + $resource = $charge->refund(); + $this->assertInstanceOf("Stripe\\Charge", $resource); + $this->assertSame($resource, $charge); + } + + public function testCanCapture() + { + $charge = Charge::retrieve(self::TEST_RESOURCE_ID); + $this->expectsRequest( + 'post', + '/v1/charges/' . $charge->id . '/capture' + ); + $resource = $charge->capture(); + $this->assertInstanceOf("Stripe\\Charge", $resource); + $this->assertSame($resource, $charge); + } + + public function testCanUpdateDispute() + { + $charge = Charge::retrieve(self::TEST_RESOURCE_ID); + $this->expectsRequest( + 'post', + '/v1/charges/' . $charge->id . '/dispute' + ); + $resource = $charge->updateDispute(); + $this->assertInstanceOf("Stripe\\Dispute", $resource); + } + + public function testCanCloseDispute() + { + $charge = Charge::retrieve(self::TEST_RESOURCE_ID); + $this->expectsRequest( + 'post', + '/v1/charges/' . $charge->id . '/dispute/close' + ); + $resource = $charge->closeDispute(); + $this->assertInstanceOf("Stripe\\Charge", $resource); + $this->assertSame($resource, $charge); + } + + public function testCanMarkAsFraudulent() + { + $charge = Charge::retrieve(self::TEST_RESOURCE_ID); + $this->expectsRequest( + 'post', + '/v1/charges/' . $charge->id, + ['fraud_details' => ['user_report' => 'fraudulent']] + ); + $resource = $charge->markAsFraudulent(); + $this->assertInstanceOf("Stripe\\Charge", $resource); + $this->assertSame($resource, $charge); + } + + public function testCanMarkAsSafe() + { + $charge = Charge::retrieve(self::TEST_RESOURCE_ID); + $this->expectsRequest( + 'post', + '/v1/charges/' . $charge->id, + ['fraud_details' => ['user_report' => 'safe']] + ); + $resource = $charge->markAsSafe(); + $this->assertInstanceOf("Stripe\\Charge", $resource); + $this->assertSame($resource, $charge); + } +} diff --git a/htdocs/includes/stripe/tests/Stripe/CollectionTest.php b/htdocs/includes/stripe/tests/Stripe/CollectionTest.php new file mode 100644 index 00000000000..560085aede2 --- /dev/null +++ b/htdocs/includes/stripe/tests/Stripe/CollectionTest.php @@ -0,0 +1,147 @@ +fixture = Collection::constructFrom([ + 'data' => [['id' => 1]], + 'has_more' => true, + 'url' => '/things', + ]); + } + + public function testCanList() + { + $this->stubRequest( + 'GET', + '/things', + [], + null, + false, + [ + 'data' => [['id' => 1]], + 'has_more' => true, + 'url' => '/things', + ] + ); + + $resources = $this->fixture->all(); + $this->assertTrue(is_array($resources->data)); + } + + public function testCanRetrieve() + { + $this->stubRequest( + 'GET', + '/things/1', + [], + null, + false, + [ + 'id' => 1, + ] + ); + + $this->fixture->retrieve(1); + } + + public function testCanCreate() + { + $this->stubRequest( + 'POST', + '/things', + [ + 'foo' => 'bar', + ], + null, + false, + [ + 'id' => 2, + ] + ); + + $this->fixture->create([ + 'foo' => 'bar', + ]); + } + + public function testProvidesAutoPagingIterator() + { + $this->stubRequest( + 'GET', + '/things', + [ + 'starting_after' => 1, + ], + null, + false, + [ + 'data' => [['id' => 2], ['id' => 3]], + 'has_more' => false, + ] + ); + + $seen = []; + foreach ($this->fixture->autoPagingIterator() as $item) { + array_push($seen, $item['id']); + } + + $this->assertSame([1, 2, 3], $seen); + } + + public function testSupportsIteratorToArray() + { + $this->stubRequest( + 'GET', + '/things', + [ + 'starting_after' => 1, + ], + null, + false, + [ + 'data' => [['id' => 2], ['id' => 3]], + 'has_more' => false, + ] + ); + + $seen = []; + foreach (iterator_to_array($this->fixture->autoPagingIterator()) as $item) { + array_push($seen, $item['id']); + } + + $this->assertSame([1, 2, 3], $seen); + } + + public function testHeaders() + { + $this->stubRequest( + 'POST', + '/things', + [ + 'foo' => 'bar', + ], + [ + 'Stripe-Account: acct_foo', + 'Idempotency-Key: qwertyuiop', + ], + false, + [ + 'id' => 2, + ] + ); + + $this->fixture->create([ + 'foo' => 'bar', + ], [ + 'stripe_account' => 'acct_foo', + 'idempotency_key' => 'qwertyuiop', + ]); + } +} diff --git a/htdocs/includes/stripe/tests/Stripe/CountrySpecTest.php b/htdocs/includes/stripe/tests/Stripe/CountrySpecTest.php new file mode 100644 index 00000000000..cccd4116845 --- /dev/null +++ b/htdocs/includes/stripe/tests/Stripe/CountrySpecTest.php @@ -0,0 +1,29 @@ +expectsRequest( + 'get', + '/v1/country_specs' + ); + $resources = CountrySpec::all(); + $this->assertTrue(is_array($resources->data)); + $this->assertInstanceOf("Stripe\\CountrySpec", $resources->data[0]); + } + + public function testIsRetrievable() + { + $this->expectsRequest( + 'get', + '/v1/country_specs/' . self::TEST_RESOURCE_ID + ); + $resource = CountrySpec::retrieve(self::TEST_RESOURCE_ID); + $this->assertInstanceOf("Stripe\\CountrySpec", $resource); + } +} diff --git a/htdocs/includes/stripe/tests/Stripe/CouponTest.php b/htdocs/includes/stripe/tests/Stripe/CouponTest.php new file mode 100644 index 00000000000..8a6fbf630cd --- /dev/null +++ b/htdocs/includes/stripe/tests/Stripe/CouponTest.php @@ -0,0 +1,79 @@ +expectsRequest( + 'get', + '/v1/coupons' + ); + $resources = Coupon::all(); + $this->assertTrue(is_array($resources->data)); + $this->assertInstanceOf("Stripe\\Coupon", $resources->data[0]); + } + + public function testIsRetrievable() + { + $this->expectsRequest( + 'get', + '/v1/coupons/' . self::TEST_RESOURCE_ID + ); + $resource = Coupon::retrieve(self::TEST_RESOURCE_ID); + $this->assertInstanceOf("Stripe\\Coupon", $resource); + } + + public function testIsCreatable() + { + $this->expectsRequest( + 'post', + '/v1/coupons' + ); + $resource = Coupon::create([ + "percent_off" => 25, + "duration" => "repeating", + "duration_in_months" => 3, + "id" => self::TEST_RESOURCE_ID, + ]); + $this->assertInstanceOf("Stripe\\Coupon", $resource); + } + + public function testIsSaveable() + { + $resource = Coupon::retrieve(self::TEST_RESOURCE_ID); + $resource->metadata["key"] = "value"; + $this->expectsRequest( + 'post', + '/v1/coupons/' . self::TEST_RESOURCE_ID + ); + $resource->save(); + $this->assertInstanceOf("Stripe\\Coupon", $resource); + } + + public function testIsUpdatable() + { + $this->expectsRequest( + 'post', + '/v1/coupons/' . self::TEST_RESOURCE_ID + ); + $resource = Coupon::update(self::TEST_RESOURCE_ID, [ + "metadata" => ["key" => "value"], + ]); + $this->assertInstanceOf("Stripe\\Coupon", $resource); + } + + public function testIsDeletable() + { + $resource = Coupon::retrieve(self::TEST_RESOURCE_ID); + $this->expectsRequest( + 'delete', + '/v1/coupons/' . self::TEST_RESOURCE_ID + ); + $resource->delete(); + $this->assertInstanceOf("Stripe\\Coupon", $resource); + } +} diff --git a/htdocs/includes/stripe/tests/Stripe/CustomerTest.php b/htdocs/includes/stripe/tests/Stripe/CustomerTest.php new file mode 100644 index 00000000000..e279e5489e8 --- /dev/null +++ b/htdocs/includes/stripe/tests/Stripe/CustomerTest.php @@ -0,0 +1,269 @@ +expectsRequest( + 'get', + '/v1/customers' + ); + $resources = Customer::all(); + $this->assertTrue(is_array($resources->data)); + $this->assertInstanceOf("Stripe\\Customer", $resources->data[0]); + } + + public function testIsRetrievable() + { + $this->expectsRequest( + 'get', + '/v1/customers/' . self::TEST_RESOURCE_ID + ); + $resource = Customer::retrieve(self::TEST_RESOURCE_ID); + $this->assertInstanceOf("Stripe\\Customer", $resource); + } + + public function testIsCreatable() + { + $this->expectsRequest( + 'post', + '/v1/customers' + ); + $resource = Customer::create(); + $this->assertInstanceOf("Stripe\\Customer", $resource); + } + + public function testIsSaveable() + { + $resource = Customer::retrieve(self::TEST_RESOURCE_ID); + $resource->metadata["key"] = "value"; + $this->expectsRequest( + 'post', + '/v1/customers/' . $resource->id + ); + $resource->save(); + $this->assertInstanceOf("Stripe\\Customer", $resource); + } + + public function testIsUpdatable() + { + $this->expectsRequest( + 'post', + '/v1/customers/' . self::TEST_RESOURCE_ID + ); + $resource = Customer::update(self::TEST_RESOURCE_ID, [ + "metadata" => ["key" => "value"], + ]); + $this->assertInstanceOf("Stripe\\Customer", $resource); + } + + public function testIsDeletable() + { + $resource = Customer::retrieve(self::TEST_RESOURCE_ID); + $this->expectsRequest( + 'delete', + '/v1/customers/' . $resource->id + ); + $resource->delete(); + $this->assertInstanceOf("Stripe\\Customer", $resource); + } + + public function testCanAddInvoiceItem() + { + $customer = Customer::retrieve(self::TEST_RESOURCE_ID); + $this->expectsRequest( + 'post', + '/v1/invoiceitems', + [ + "amount" => 100, + "currency" => "usd", + "customer" => $customer->id + ] + ); + $resource = $customer->addInvoiceItem([ + "amount" => 100, + "currency" => "usd" + ]); + $this->assertInstanceOf("Stripe\\InvoiceItem", $resource); + } + + public function testCanListInvoices() + { + $customer = Customer::retrieve(self::TEST_RESOURCE_ID); + $this->expectsRequest( + 'get', + '/v1/invoices', + ["customer" => $customer->id] + ); + $resources = $customer->invoices(); + $this->assertTrue(is_array($resources->data)); + $this->assertInstanceOf("Stripe\\Invoice", $resources->data[0]); + } + + public function testCanListInvoiceItems() + { + $customer = Customer::retrieve(self::TEST_RESOURCE_ID); + $this->expectsRequest( + 'get', + '/v1/invoiceitems', + ["customer" => $customer->id] + ); + $resources = $customer->invoiceItems(); + $this->assertTrue(is_array($resources->data)); + $this->assertInstanceOf("Stripe\\InvoiceItem", $resources->data[0]); + } + + public function testCanListCharges() + { + $customer = Customer::retrieve(self::TEST_RESOURCE_ID); + $this->expectsRequest( + 'get', + '/v1/charges', + ["customer" => $customer->id] + ); + $resources = $customer->charges(); + $this->assertTrue(is_array($resources->data)); + $this->assertInstanceOf("Stripe\\Charge", $resources->data[0]); + } + + public function testCanUpdateSubscription() + { + $customer = Customer::retrieve(self::TEST_RESOURCE_ID); + $this->stubRequest( + 'post', + '/v1/customers/' . $customer->id . '/subscription', + ["plan" => "plan"], + null, + false, + [ + "object" => "subscription", + "id" => "sub_foo" + ] + ); + $resource = $customer->updateSubscription(["plan" => "plan"]); + $this->assertInstanceOf("Stripe\\Subscription", $resource); + $this->assertSame("sub_foo", $customer->subscription->id); + } + + public function testCanCancelSubscription() + { + $customer = Customer::retrieve(self::TEST_RESOURCE_ID); + $this->stubRequest( + 'delete', + '/v1/customers/' . $customer->id . '/subscription', + [], + null, + false, + [ + "object" => "subscription", + "id" => "sub_foo" + ] + ); + $resource = $customer->cancelSubscription(); + $this->assertInstanceOf("Stripe\\Subscription", $resource); + $this->assertSame("sub_foo", $customer->subscription->id); + } + + public function testCanDeleteDiscount() + { + $customer = Customer::retrieve(self::TEST_RESOURCE_ID); + $this->stubRequest( + 'delete', + '/v1/customers/' . $customer->id . '/discount' + ); + $customer->deleteDiscount(); + $this->assertSame($customer->discount, null); + } + + public function testCanCreateSource() + { + $this->expectsRequest( + 'post', + '/v1/customers/' . self::TEST_RESOURCE_ID . '/sources' + ); + $resource = Customer::createSource(self::TEST_RESOURCE_ID, ["source" => "btok_123"]); + $this->assertInstanceOf("Stripe\\BankAccount", $resource); + } + + public function testCanRetrieveSource() + { + $this->expectsRequest( + 'get', + '/v1/customers/' . self::TEST_RESOURCE_ID . '/sources/' . self::TEST_SOURCE_ID + ); + $resource = Customer::retrieveSource(self::TEST_RESOURCE_ID, self::TEST_SOURCE_ID); + $this->assertInstanceOf("Stripe\\BankAccount", $resource); + } + + public function testCanUpdateSource() + { + $this->expectsRequest( + 'post', + '/v1/customers/' . self::TEST_RESOURCE_ID . '/sources/' . self::TEST_SOURCE_ID + ); + $resource = Customer::updateSource(self::TEST_RESOURCE_ID, self::TEST_SOURCE_ID, ["name" => "name"]); + // stripe-mock returns a Card on this method and not a bank account + $this->assertInstanceOf("Stripe\\Card", $resource); + } + + public function testCanDeleteSource() + { + $this->expectsRequest( + 'delete', + '/v1/customers/' . self::TEST_RESOURCE_ID . '/sources/' . self::TEST_SOURCE_ID + ); + $resource = Customer::deleteSource(self::TEST_RESOURCE_ID, self::TEST_SOURCE_ID); + $this->assertInstanceOf("Stripe\\BankAccount", $resource); + } + + public function testCanListSources() + { + $this->expectsRequest( + 'get', + '/v1/customers/' . self::TEST_RESOURCE_ID . '/sources' + ); + $resources = Customer::allSources(self::TEST_RESOURCE_ID); + $this->assertTrue(is_array($resources->data)); + } + + public function testSerializeSourceString() + { + $obj = Util\Util::convertToStripeObject([ + 'object' => 'customer', + ], null); + $obj->source = 'tok_visa'; + + $expected = [ + 'source' => 'tok_visa', + ]; + $this->assertSame($expected, $obj->serializeParameters()); + } + + public function testSerializeSourceMap() + { + $obj = Util\Util::convertToStripeObject([ + 'object' => 'customer', + ], null); + $obj->source = [ + 'object' => 'card', + 'number' => '4242424242424242', + 'exp_month' => 12, + 'exp_year' => 2032, + ]; + + $expected = [ + 'source' => [ + 'object' => 'card', + 'number' => '4242424242424242', + 'exp_month' => 12, + 'exp_year' => 2032, + ], + ]; + $this->assertSame($expected, $obj->serializeParameters()); + } +} diff --git a/htdocs/includes/stripe/tests/Stripe/DisputeTest.php b/htdocs/includes/stripe/tests/Stripe/DisputeTest.php new file mode 100644 index 00000000000..81d93da0213 --- /dev/null +++ b/htdocs/includes/stripe/tests/Stripe/DisputeTest.php @@ -0,0 +1,65 @@ +expectsRequest( + 'get', + '/v1/disputes' + ); + $resources = Dispute::all(); + $this->assertTrue(is_array($resources->data)); + $this->assertInstanceOf("Stripe\\Dispute", $resources->data[0]); + } + + public function testIsRetrievable() + { + $this->expectsRequest( + 'get', + '/v1/disputes/' . self::TEST_RESOURCE_ID + ); + $resource = Dispute::retrieve(self::TEST_RESOURCE_ID); + $this->assertInstanceOf("Stripe\\Dispute", $resource); + } + + public function testIsSaveable() + { + $resource = Dispute::retrieve(self::TEST_RESOURCE_ID); + $resource->metadata["key"] = "value"; + $this->expectsRequest( + 'post', + '/v1/disputes/' . $resource->id + ); + $resource->save(); + $this->assertInstanceOf("Stripe\\Dispute", $resource); + } + + public function testIsUpdatable() + { + $this->expectsRequest( + 'post', + '/v1/disputes/' . self::TEST_RESOURCE_ID + ); + $resource = Dispute::update(self::TEST_RESOURCE_ID, [ + "metadata" => ["key" => "value"], + ]); + $this->assertInstanceOf("Stripe\\Dispute", $resource); + } + + public function testIsClosable() + { + $dispute = Dispute::retrieve(self::TEST_RESOURCE_ID); + $this->expectsRequest( + 'post', + '/v1/disputes/' . $dispute->id . '/close' + ); + $resource = $dispute->close(); + $this->assertInstanceOf("Stripe\\Dispute", $resource); + $this->assertSame($resource, $dispute); + } +} diff --git a/htdocs/includes/stripe/tests/Stripe/EphemeralKeyTest.php b/htdocs/includes/stripe/tests/Stripe/EphemeralKeyTest.php new file mode 100644 index 00000000000..e8a1fc0e9ef --- /dev/null +++ b/htdocs/includes/stripe/tests/Stripe/EphemeralKeyTest.php @@ -0,0 +1,43 @@ +expectsRequest( + 'post', + '/v1/ephemeral_keys', + null, + ["Stripe-Version: 2017-05-25"] + ); + $resource = EphemeralKey::create([ + "customer" => "cus_123", + ], ["stripe_version" => "2017-05-25"]); + $this->assertInstanceOf("Stripe\\EphemeralKey", $resource); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testIsNotCreatableWithoutAnExplicitApiVersion() + { + $resource = EphemeralKey::create([ + "customer" => "cus_123", + ]); + } + + public function testIsDeletable() + { + $key = EphemeralKey::create([ + "customer" => "cus_123", + ], ["stripe_version" => "2017-05-25"]); + $this->expectsRequest( + 'delete', + '/v1/ephemeral_keys/' . $key->id + ); + $resource = $key->delete(); + $this->assertInstanceOf("Stripe\\EphemeralKey", $resource); + } +} diff --git a/htdocs/includes/stripe/tests/Stripe/Error/BaseTest.php b/htdocs/includes/stripe/tests/Stripe/Error/BaseTest.php new file mode 100644 index 00000000000..4c2732ed1d1 --- /dev/null +++ b/htdocs/includes/stripe/tests/Stripe/Error/BaseTest.php @@ -0,0 +1,36 @@ +getMockForAbstractClass('Stripe\\Error\\Base', [ + 'message', + 200, + '{"key": "value"}', + ['key' => 'value'], + [ + 'Some-Header' => 'Some Value', + 'Request-Id' => 'req_test', + ], + ]); + } + + public function testGetters() + { + $e = $this->createFixture(); + $this->assertSame(200, $e->getHttpStatus()); + $this->assertSame('{"key": "value"}', $e->getHttpBody()); + $this->assertSame(['key' => 'value'], $e->getJsonBody()); + $this->assertSame('Some Value', $e->getHttpHeaders()['Some-Header']); + $this->assertSame('req_test', $e->getRequestId()); + } + + public function testToString() + { + $e = $this->createFixture(); + $this->assertContains("from API request 'req_test'", (string)$e); + } +} diff --git a/htdocs/includes/stripe/tests/Stripe/Error/SignatureVerificationTest.php b/htdocs/includes/stripe/tests/Stripe/Error/SignatureVerificationTest.php new file mode 100644 index 00000000000..020a41f8f76 --- /dev/null +++ b/htdocs/includes/stripe/tests/Stripe/Error/SignatureVerificationTest.php @@ -0,0 +1,12 @@ +assertSame('sig_header', $e->getSigHeader()); + } +} diff --git a/htdocs/includes/stripe/tests/Stripe/EventTest.php b/htdocs/includes/stripe/tests/Stripe/EventTest.php new file mode 100644 index 00000000000..2e3c92f0e49 --- /dev/null +++ b/htdocs/includes/stripe/tests/Stripe/EventTest.php @@ -0,0 +1,29 @@ +expectsRequest( + 'get', + '/v1/events' + ); + $resources = Event::all(); + $this->assertTrue(is_array($resources->data)); + $this->assertInstanceOf("Stripe\\Event", $resources->data[0]); + } + + public function testIsRetrievable() + { + $this->expectsRequest( + 'get', + '/v1/events/' . self::TEST_RESOURCE_ID + ); + $resource = Event::retrieve(self::TEST_RESOURCE_ID); + $this->assertInstanceOf("Stripe\\Event", $resource); + } +} diff --git a/htdocs/includes/stripe/tests/Stripe/ExchangeRateTest.php b/htdocs/includes/stripe/tests/Stripe/ExchangeRateTest.php new file mode 100644 index 00000000000..8b07b5a1358 --- /dev/null +++ b/htdocs/includes/stripe/tests/Stripe/ExchangeRateTest.php @@ -0,0 +1,54 @@ +stubRequest( + 'get', + '/v1/exchange_rates', + [], + null, + false, + [ + 'object' => 'list', + 'data' => [ + [ + 'id' => 'eur', + 'object' => 'exchange_rate', + 'rates' => ['usd' => 1.18221], + ], + [ + 'id' => 'usd', + 'object' => 'exchange_rate', + 'rates' => ['eur' => 0.845876], + ], + ], + ] + ); + + $listRates = ExchangeRate::all(); + $this->assertTrue(is_array($listRates->data)); + $this->assertEquals('exchange_rate', $listRates->data[0]->object); + } + + public function testIsRetrievable() + { + $this->stubRequest( + 'get', + '/v1/exchange_rates/usd', + [], + null, + false, + [ + 'id' => 'usd', + 'object' => 'exchange_rate', + 'rates' => ['eur' => 0.845876], + ] + ); + $rates = ExchangeRate::retrieve("usd"); + $this->assertEquals('exchange_rate', $rates->object); + } +} diff --git a/htdocs/includes/stripe/tests/Stripe/FileUploadTest.php b/htdocs/includes/stripe/tests/Stripe/FileUploadTest.php new file mode 100644 index 00000000000..21bb0b568f6 --- /dev/null +++ b/htdocs/includes/stripe/tests/Stripe/FileUploadTest.php @@ -0,0 +1,104 @@ +fixture = [ + 'id' => self::TEST_RESOURCE_ID, + 'object' => 'file_upload', + ]; + } + + public function testIsListable() + { + $this->stubRequest( + 'get', + '/v1/files', + [], + null, + false, + [ + 'object' => 'list', + 'data' => [$this->fixture], + 'resource_url' => '/v1/files', + ], + 200, + Stripe::$apiUploadBase + ); + + $resources = FileUpload::all(); + $this->assertTrue(is_array($resources->data)); + $this->assertInstanceOf("Stripe\\FileUpload", $resources->data[0]); + } + + public function testIsRetrievable() + { + $this->stubRequest( + 'get', + '/v1/files/' . self::TEST_RESOURCE_ID, + [], + null, + false, + $this->fixture, + 200, + Stripe::$apiUploadBase + ); + $resource = FileUpload::retrieve(self::TEST_RESOURCE_ID); + $this->assertInstanceOf("Stripe\\FileUpload", $resource); + } + + public function testIsCreatableWithFileHandle() + { + $this->stubRequest( + 'post', + '/v1/files', + null, + ['Content-Type: multipart/form-data'], + true, + $this->fixture, + 200, + Stripe::$apiUploadBase + ); + $fp = fopen(dirname(__FILE__) . '/../data/test.png', 'r'); + $resource = FileUpload::create([ + "purpose" => "dispute_evidence", + "file" => $fp, + ]); + $this->assertInstanceOf("Stripe\\FileUpload", $resource); + } + + public function testIsCreatableWithCurlFile() + { + if (!class_exists('\CurlFile', false)) { + // Older PHP versions don't support this + return; + } + + $this->stubRequest( + 'post', + '/v1/files', + null, + ['Content-Type: multipart/form-data'], + true, + $this->fixture, + 200, + Stripe::$apiUploadBase + ); + $curlFile = new \CurlFile(dirname(__FILE__) . '/../data/test.png'); + $resource = FileUpload::create([ + "purpose" => "dispute_evidence", + "file" => $curlFile, + ]); + $this->assertInstanceOf("Stripe\\FileUpload", $resource); + } +} diff --git a/htdocs/includes/stripe/tests/Stripe/HttpClient/CurlClientTest.php b/htdocs/includes/stripe/tests/Stripe/HttpClient/CurlClientTest.php new file mode 100644 index 00000000000..086e6d3ee8d --- /dev/null +++ b/htdocs/includes/stripe/tests/Stripe/HttpClient/CurlClientTest.php @@ -0,0 +1,228 @@ +origMaxNetworkRetries = Stripe::getMaxNetworkRetries(); + $this->origMaxNetworkRetryDelay = Stripe::getMaxNetworkRetryDelay(); + $this->origInitialNetworkRetryDelay = Stripe::getInitialNetworkRetryDelay(); + } + + /** + * @before + */ + public function setUpReflectors() + { + $stripeReflector = new \ReflectionClass('\Stripe\Stripe'); + + $this->maxNetworkRetryDelayProperty = $stripeReflector->getProperty('maxNetworkRetryDelay'); + $this->maxNetworkRetryDelayProperty->setAccessible(true); + + $this->initialNetworkRetryDelayProperty = $stripeReflector->getProperty('initialNetworkRetryDelay'); + $this->initialNetworkRetryDelayProperty->setAccessible(true); + + $curlClientReflector = new \ReflectionClass('Stripe\HttpClient\CurlClient'); + + $this->shouldRetryMethod = $curlClientReflector->getMethod('shouldRetry'); + $this->shouldRetryMethod->setAccessible(true); + + $this->sleepTimeMethod = $curlClientReflector->getMethod('sleepTime'); + $this->sleepTimeMethod->setAccessible(true); + } + + /** + * @after + */ + public function restoreOriginalNetworkValues() + { + Stripe::setMaxNetworkRetries($this->origMaxNetworkRetries); + $this->setMaxNetworkRetryDelay($this->origMaxNetworkRetryDelay); + $this->setInitialNetworkRetryDelay($this->origInitialNetworkRetryDelay); + } + + private function setMaxNetworkRetryDelay($maxNetworkRetryDelay) + { + $this->maxNetworkRetryDelayProperty->setValue(null, $maxNetworkRetryDelay); + } + + private function setInitialNetworkRetryDelay($initialNetworkRetryDelay) + { + $this->initialNetworkRetryDelayProperty->setValue(null, $initialNetworkRetryDelay); + } + + private function createFakeRandomGenerator($returnValue = 1.0) + { + $fakeRandomGenerator = $this->getMock('Stripe\Util\RandomGenetator', ['randFloat']); + $fakeRandomGenerator->method('randFloat')->willReturn($returnValue); + return $fakeRandomGenerator; + } + + public function testTimeout() + { + $curl = new CurlClient(); + $this->assertSame(CurlClient::DEFAULT_TIMEOUT, $curl->getTimeout()); + $this->assertSame(CurlClient::DEFAULT_CONNECT_TIMEOUT, $curl->getConnectTimeout()); + + // implicitly tests whether we're returning the CurlClient instance + $curl = $curl->setConnectTimeout(1)->setTimeout(10); + $this->assertSame(1, $curl->getConnectTimeout()); + $this->assertSame(10, $curl->getTimeout()); + + $curl->setTimeout(-1); + $curl->setConnectTimeout(-999); + $this->assertSame(0, $curl->getTimeout()); + $this->assertSame(0, $curl->getConnectTimeout()); + } + + public function testUserAgentInfo() + { + $curl = new CurlClient(); + $uaInfo = $curl->getUserAgentInfo(); + $this->assertNotNull($uaInfo); + $this->assertNotNull($uaInfo['httplib']); + $this->assertNotNull($uaInfo['ssllib']); + } + + public function testDefaultOptions() + { + // make sure options array loads/saves properly + $optionsArray = [CURLOPT_PROXY => 'localhost:80']; + $withOptionsArray = new CurlClient($optionsArray); + $this->assertSame($withOptionsArray->getDefaultOptions(), $optionsArray); + + // make sure closure-based options work properly, including argument passing + $ref = null; + $withClosure = new CurlClient(function ($method, $absUrl, $headers, $params, $hasFile) use (&$ref) { + $ref = func_get_args(); + return []; + }); + + $withClosure->request('get', 'https://httpbin.org/status/200', [], [], false); + $this->assertSame($ref, ['get', 'https://httpbin.org/status/200', [], [], false]); + + // this is the last test case that will run, since it'll throw an exception at the end + $withBadClosure = new CurlClient(function () { + return 'thisShouldNotWork'; + }); + $this->setExpectedException('Stripe\Error\Api', "Non-array value returned by defaultOptions CurlClient callback"); + $withBadClosure->request('get', 'https://httpbin.org/status/200', [], [], false); + } + + public function testSslOption() + { + // make sure options array loads/saves properly + $optionsArray = [CURLOPT_SSLVERSION => CURL_SSLVERSION_TLSv1]; + $withOptionsArray = new CurlClient($optionsArray); + $this->assertSame($withOptionsArray->getDefaultOptions(), $optionsArray); + } + + public function testShouldRetryOnTimeout() + { + Stripe::setMaxNetworkRetries(2); + + $curlClient = new CurlClient(); + + $this->assertTrue($this->shouldRetryMethod->invoke($curlClient, CURLE_OPERATION_TIMEOUTED, 0, 0)); + } + + public function testShouldRetryOnConnectionFailure() + { + Stripe::setMaxNetworkRetries(2); + + $curlClient = new CurlClient(); + + $this->assertTrue($this->shouldRetryMethod->invoke($curlClient, CURLE_COULDNT_CONNECT, 0, 0)); + } + + public function testShouldRetryOnConflict() + { + Stripe::setMaxNetworkRetries(2); + + $curlClient = new CurlClient(); + + $this->assertTrue($this->shouldRetryMethod->invoke($curlClient, 0, 409, 0)); + } + + public function testShouldNotRetryAtMaximumCount() + { + Stripe::setMaxNetworkRetries(2); + + $curlClient = new CurlClient(); + + $this->assertFalse($this->shouldRetryMethod->invoke($curlClient, 0, 0, Stripe::getMaxNetworkRetries())); + } + + public function testShouldNotRetryOnCertValidationError() + { + Stripe::setMaxNetworkRetries(2); + + $curlClient = new CurlClient(); + + $this->assertFalse($this->shouldRetryMethod->invoke($curlClient, CURLE_SSL_PEER_CERTIFICATE, -1, 0)); + } + + public function testSleepTimeShouldGrowExponentially() + { + $this->setMaxNetworkRetryDelay(999); + + $curlClient = new CurlClient(null, $this->createFakeRandomGenerator()); + + $this->assertEquals( + Stripe::getInitialNetworkRetryDelay() * 1, + $this->sleepTimeMethod->invoke($curlClient, 1) + ); + $this->assertEquals( + Stripe::getInitialNetworkRetryDelay() * 2, + $this->sleepTimeMethod->invoke($curlClient, 2) + ); + $this->assertEquals( + Stripe::getInitialNetworkRetryDelay() * 4, + $this->sleepTimeMethod->invoke($curlClient, 3) + ); + $this->assertEquals( + Stripe::getInitialNetworkRetryDelay() * 8, + $this->sleepTimeMethod->invoke($curlClient, 4) + ); + } + + public function testSleepTimeShouldEnforceMaxNetworkRetryDelay() + { + $this->setInitialNetworkRetryDelay(1); + $this->setMaxNetworkRetryDelay(2); + + $curlClient = new CurlClient(null, $this->createFakeRandomGenerator()); + + $this->assertEquals(1, $this->sleepTimeMethod->invoke($curlClient, 1)); + $this->assertEquals(2, $this->sleepTimeMethod->invoke($curlClient, 2)); + $this->assertEquals(2, $this->sleepTimeMethod->invoke($curlClient, 3)); + $this->assertEquals(2, $this->sleepTimeMethod->invoke($curlClient, 4)); + } + + public function testSleepTimeShouldAddSomeRandomness() + { + $randomValue = 0.8; + $this->setInitialNetworkRetryDelay(1); + $this->setMaxNetworkRetryDelay(8); + + $curlClient = new CurlClient(null, $this->createFakeRandomGenerator($randomValue)); + + $baseValue = Stripe::getInitialNetworkRetryDelay() * (0.5 * (1 + $randomValue)); + + // the initial value cannot be smaller than the base, + // so the randomness is ignored + $this->assertEquals(Stripe::getInitialNetworkRetryDelay(), $this->sleepTimeMethod->invoke($curlClient, 1)); + + // after the first one, the randomness is applied + $this->assertEquals($baseValue * 2, $this->sleepTimeMethod->invoke($curlClient, 2)); + $this->assertEquals($baseValue * 4, $this->sleepTimeMethod->invoke($curlClient, 3)); + $this->assertEquals($baseValue * 8, $this->sleepTimeMethod->invoke($curlClient, 4)); + } +} diff --git a/htdocs/includes/stripe/tests/Stripe/InvoiceItemTest.php b/htdocs/includes/stripe/tests/Stripe/InvoiceItemTest.php new file mode 100644 index 00000000000..ffe140aa7ca --- /dev/null +++ b/htdocs/includes/stripe/tests/Stripe/InvoiceItemTest.php @@ -0,0 +1,78 @@ +expectsRequest( + 'get', + '/v1/invoiceitems' + ); + $resources = InvoiceItem::all(); + $this->assertTrue(is_array($resources->data)); + $this->assertInstanceOf("Stripe\\InvoiceItem", $resources->data[0]); + } + + public function testIsRetrievable() + { + $this->expectsRequest( + 'get', + '/v1/invoiceitems/' . self::TEST_RESOURCE_ID + ); + $resource = InvoiceItem::retrieve(self::TEST_RESOURCE_ID); + $this->assertInstanceOf("Stripe\\InvoiceItem", $resource); + } + + public function testIsCreatable() + { + $this->expectsRequest( + 'post', + '/v1/invoiceitems' + ); + $resource = InvoiceItem::create([ + "amount" => 100, + "currency" => "usd", + "customer" => "cus_123" + ]); + $this->assertInstanceOf("Stripe\\InvoiceItem", $resource); + } + + public function testIsSaveable() + { + $resource = InvoiceItem::retrieve(self::TEST_RESOURCE_ID); + $resource->metadata["key"] = "value"; + $this->expectsRequest( + 'post', + '/v1/invoiceitems/' . $resource->id + ); + $resource->save(); + $this->assertInstanceOf("Stripe\\InvoiceItem", $resource); + } + + public function testIsUpdatable() + { + $this->expectsRequest( + 'post', + '/v1/invoiceitems/' . self::TEST_RESOURCE_ID + ); + $resource = InvoiceItem::update(self::TEST_RESOURCE_ID, [ + "metadata" => ["key" => "value"], + ]); + $this->assertInstanceOf("Stripe\\InvoiceItem", $resource); + } + + public function testIsDeletable() + { + $invoiceItem = InvoiceItem::retrieve(self::TEST_RESOURCE_ID); + $this->expectsRequest( + 'delete', + '/v1/invoiceitems/' . $invoiceItem->id + ); + $resource = $invoiceItem->delete(); + $this->assertInstanceOf("Stripe\\InvoiceItem", $resource); + } +} diff --git a/htdocs/includes/stripe/tests/Stripe/InvoiceTest.php b/htdocs/includes/stripe/tests/Stripe/InvoiceTest.php new file mode 100644 index 00000000000..f1ae9378628 --- /dev/null +++ b/htdocs/includes/stripe/tests/Stripe/InvoiceTest.php @@ -0,0 +1,87 @@ +expectsRequest( + 'get', + '/v1/invoices' + ); + $resources = Invoice::all(); + $this->assertTrue(is_array($resources->data)); + $this->assertInstanceOf("Stripe\\Invoice", $resources->data[0]); + } + + public function testIsRetrievable() + { + $this->expectsRequest( + 'get', + '/v1/invoices/' . self::TEST_RESOURCE_ID + ); + $resource = Invoice::retrieve(self::TEST_RESOURCE_ID); + $this->assertInstanceOf("Stripe\\Invoice", $resource); + } + + public function testIsCreatable() + { + $this->expectsRequest( + 'post', + '/v1/invoices' + ); + $resource = Invoice::create([ + "customer" => "cus_123" + ]); + $this->assertInstanceOf("Stripe\\Invoice", $resource); + } + + public function testIsSaveable() + { + $resource = Invoice::retrieve(self::TEST_RESOURCE_ID); + $resource->metadata["key"] = "value"; + $this->expectsRequest( + 'post', + '/v1/invoices/' . $resource->id + ); + $resource->save(); + $this->assertInstanceOf("Stripe\\Invoice", $resource); + } + + public function testIsUpdatable() + { + $this->expectsRequest( + 'post', + '/v1/invoices/' . self::TEST_RESOURCE_ID + ); + $resource = Invoice::update(self::TEST_RESOURCE_ID, [ + "metadata" => ["key" => "value"], + ]); + $this->assertInstanceOf("Stripe\\Invoice", $resource); + } + + public function testCanRetrieveUpcoming() + { + $this->expectsRequest( + 'get', + '/v1/invoices/upcoming' + ); + $resource = Invoice::upcoming(["customer" => "cus_123"]); + $this->assertInstanceOf("Stripe\\Invoice", $resource); + } + + public function testIsPayable() + { + $invoice = Invoice::retrieve(self::TEST_RESOURCE_ID); + $this->expectsRequest( + 'post', + '/v1/invoices/' . $invoice->id . '/pay' + ); + $resource = $invoice->pay(); + $this->assertInstanceOf("Stripe\\Invoice", $resource); + $this->assertSame($resource, $invoice); + } +} diff --git a/htdocs/includes/stripe/tests/Stripe/OAuthTest.php b/htdocs/includes/stripe/tests/Stripe/OAuthTest.php new file mode 100644 index 00000000000..b4e43a88103 --- /dev/null +++ b/htdocs/includes/stripe/tests/Stripe/OAuthTest.php @@ -0,0 +1,97 @@ + 'read_write', + 'state' => 'csrf_token', + 'stripe_user' => [ + 'email' => 'test@example.com', + 'url' => 'https://example.com/profile/test', + 'country' => 'US', + ], + ]); + + $uri = parse_url($uriStr); + parse_str($uri['query'], $params); + + $this->assertSame('https', $uri['scheme']); + $this->assertSame('connect.stripe.com', $uri['host']); + $this->assertSame('/oauth/authorize', $uri['path']); + + $this->assertSame('ca_123', $params['client_id']); + $this->assertSame('read_write', $params['scope']); + $this->assertSame('test@example.com', $params['stripe_user']['email']); + $this->assertSame('https://example.com/profile/test', $params['stripe_user']['url']); + $this->assertSame('US', $params['stripe_user']['country']); + } + + /** + * @expectedException \Stripe\Error\Authentication + * @expectedExceptionMessageRegExp #No client_id provided# + */ + public function testRaisesAuthenticationErrorWhenNoClientId() + { + Stripe::setClientId(null); + OAuth::authorizeUrl(); + } + + public function testToken() + { + $this->stubRequest( + 'POST', + '/oauth/token', + [ + 'grant_type' => 'authorization_code', + 'code' => 'this_is_an_authorization_code', + ], + null, + false, + [ + 'access_token' => 'sk_access_token', + 'scope' => 'read_only', + 'livemode' => false, + 'token_type' => 'bearer', + 'refresh_token' => 'sk_refresh_token', + 'stripe_user_id' => 'acct_test', + 'stripe_publishable_key' => 'pk_test', + ], + 200, + Stripe::$connectBase + ); + + $resp = OAuth::token([ + 'grant_type' => 'authorization_code', + 'code' => 'this_is_an_authorization_code', + ]); + $this->assertSame('sk_access_token', $resp->access_token); + } + + public function testDeauthorize() + { + $this->stubRequest( + 'POST', + '/oauth/deauthorize', + [ + 'stripe_user_id' => 'acct_test_deauth', + 'client_id' => 'ca_123', + ], + null, + false, + [ + 'stripe_user_id' => 'acct_test_deauth', + ], + 200, + Stripe::$connectBase + ); + + $resp = OAuth::deauthorize([ + 'stripe_user_id' => 'acct_test_deauth', + ]); + $this->assertSame('acct_test_deauth', $resp->stripe_user_id); + } +} diff --git a/htdocs/includes/stripe/tests/Stripe/OrderReturnTest.php b/htdocs/includes/stripe/tests/Stripe/OrderReturnTest.php new file mode 100644 index 00000000000..bb2d65c437a --- /dev/null +++ b/htdocs/includes/stripe/tests/Stripe/OrderReturnTest.php @@ -0,0 +1,29 @@ +expectsRequest( + 'get', + '/v1/order_returns' + ); + $resources = OrderReturn::all(); + $this->assertTrue(is_array($resources->data)); + $this->assertInstanceOf("Stripe\\OrderReturn", $resources->data[0]); + } + + public function testIsRetrievable() + { + $this->expectsRequest( + 'get', + '/v1/order_returns/' . self::TEST_RESOURCE_ID + ); + $resource = OrderReturn::retrieve(self::TEST_RESOURCE_ID); + $this->assertInstanceOf("Stripe\\OrderReturn", $resource); + } +} diff --git a/htdocs/includes/stripe/tests/Stripe/OrderTest.php b/htdocs/includes/stripe/tests/Stripe/OrderTest.php new file mode 100644 index 00000000000..51d17e94fc7 --- /dev/null +++ b/htdocs/includes/stripe/tests/Stripe/OrderTest.php @@ -0,0 +1,87 @@ +expectsRequest( + 'get', + '/v1/orders' + ); + $resources = Order::all(); + $this->assertTrue(is_array($resources->data)); + $this->assertInstanceOf("Stripe\\Order", $resources->data[0]); + } + + public function testIsRetrievable() + { + $this->expectsRequest( + 'get', + '/v1/orders/' . self::TEST_RESOURCE_ID + ); + $resource = Order::retrieve(self::TEST_RESOURCE_ID); + $this->assertInstanceOf("Stripe\\Order", $resource); + } + + public function testIsCreatable() + { + $this->expectsRequest( + 'post', + '/v1/orders' + ); + $resource = Order::create([ + 'currency' => 'usd' + ]); + $this->assertInstanceOf("Stripe\\Order", $resource); + } + + public function testIsSaveable() + { + $resource = Order::retrieve(self::TEST_RESOURCE_ID); + $resource->metadata["key"] = "value"; + $this->expectsRequest( + 'post', + '/v1/orders/' . $resource->id + ); + $resource->save(); + $this->assertInstanceOf("Stripe\\Order", $resource); + } + + public function testIsUpdatable() + { + $this->expectsRequest( + 'post', + '/v1/orders/' . self::TEST_RESOURCE_ID + ); + $resource = Order::update(self::TEST_RESOURCE_ID, [ + "metadata" => ["key" => "value"], + ]); + $this->assertInstanceOf("Stripe\\Order", $resource); + } + + public function testIsPayable() + { + $resource = Order::retrieve(self::TEST_RESOURCE_ID); + $this->expectsRequest( + 'post', + '/v1/orders/' . $resource->id . '/pay' + ); + $resource->pay(); + $this->assertInstanceOf("Stripe\\Order", $resource); + } + + public function testIsReturnable() + { + $order = Order::retrieve(self::TEST_RESOURCE_ID); + $this->expectsRequest( + 'post', + '/v1/orders/' . $order->id . '/returns' + ); + $resource = $order->returnOrder(); + $this->assertInstanceOf("Stripe\\OrderReturn", $resource); + } +} diff --git a/htdocs/includes/stripe/tests/Stripe/PayoutTest.php b/htdocs/includes/stripe/tests/Stripe/PayoutTest.php new file mode 100644 index 00000000000..79c7b5fd015 --- /dev/null +++ b/htdocs/includes/stripe/tests/Stripe/PayoutTest.php @@ -0,0 +1,77 @@ +expectsRequest( + 'get', + '/v1/payouts' + ); + $resources = Payout::all(); + $this->assertTrue(is_array($resources->data)); + $this->assertInstanceOf("Stripe\\Payout", $resources->data[0]); + } + + public function testIsRetrievable() + { + $this->expectsRequest( + 'get', + '/v1/payouts/' . self::TEST_RESOURCE_ID + ); + $resource = Payout::retrieve(self::TEST_RESOURCE_ID); + $this->assertInstanceOf("Stripe\\Payout", $resource); + } + + public function testIsCreatable() + { + $this->expectsRequest( + 'post', + '/v1/payouts' + ); + $resource = Payout::create([ + "amount" => 100, + "currency" => "usd" + ]); + $this->assertInstanceOf("Stripe\\Payout", $resource); + } + + public function testIsSaveable() + { + $resource = Payout::retrieve(self::TEST_RESOURCE_ID); + $resource->metadata["key"] = "value"; + $this->expectsRequest( + 'post', + '/v1/payouts/' . $resource->id + ); + $resource->save(); + $this->assertInstanceOf("Stripe\\Payout", $resource); + } + + public function testIsUpdatable() + { + $this->expectsRequest( + 'post', + '/v1/payouts/' . self::TEST_RESOURCE_ID + ); + $resource = Payout::update(self::TEST_RESOURCE_ID, [ + "metadata" => ["key" => "value"], + ]); + $this->assertInstanceOf("Stripe\\Payout", $resource); + } + + public function testIsCancelable() + { + $resource = Payout::retrieve(self::TEST_RESOURCE_ID); + $this->expectsRequest( + 'post', + '/v1/payouts/' . $resource->id . '/cancel' + ); + $resource->cancel(); + $this->assertInstanceOf("Stripe\\Payout", $resource); + } +} diff --git a/htdocs/includes/stripe/tests/Stripe/PlanTest.php b/htdocs/includes/stripe/tests/Stripe/PlanTest.php new file mode 100644 index 00000000000..8d71745ed56 --- /dev/null +++ b/htdocs/includes/stripe/tests/Stripe/PlanTest.php @@ -0,0 +1,80 @@ +expectsRequest( + 'get', + '/v1/plans' + ); + $resources = Plan::all(); + $this->assertTrue(is_array($resources->data)); + $this->assertInstanceOf("Stripe\\Plan", $resources->data[0]); + } + + public function testIsRetrievable() + { + $this->expectsRequest( + 'get', + '/v1/plans/' . self::TEST_RESOURCE_ID + ); + $resource = Plan::retrieve(self::TEST_RESOURCE_ID); + $this->assertInstanceOf("Stripe\\Plan", $resource); + } + + public function testIsCreatable() + { + $this->expectsRequest( + 'post', + '/v1/plans' + ); + $resource = Plan::create([ + 'amount' => 100, + 'interval' => 'month', + 'currency' => 'usd', + 'name' => self::TEST_RESOURCE_ID, + 'id' => self::TEST_RESOURCE_ID + ]); + $this->assertInstanceOf("Stripe\\Plan", $resource); + } + + public function testIsSaveable() + { + $resource = Plan::retrieve(self::TEST_RESOURCE_ID); + $resource->metadata["key"] = "value"; + $this->expectsRequest( + 'post', + '/v1/plans/' . $resource->id + ); + $resource->save(); + $this->assertInstanceOf("Stripe\\Plan", $resource); + } + + public function testIsUpdatable() + { + $this->expectsRequest( + 'post', + '/v1/plans/' . self::TEST_RESOURCE_ID + ); + $resource = Plan::update(self::TEST_RESOURCE_ID, [ + "metadata" => ["key" => "value"], + ]); + $this->assertInstanceOf("Stripe\\Plan", $resource); + } + + public function testIsDeletable() + { + $resource = Plan::retrieve(self::TEST_RESOURCE_ID); + $this->expectsRequest( + 'delete', + '/v1/plans/' . $resource->id + ); + $resource->delete(); + $this->assertInstanceOf("Stripe\\Plan", $resource); + } +} diff --git a/htdocs/includes/stripe/tests/Stripe/ProductTest.php b/htdocs/includes/stripe/tests/Stripe/ProductTest.php new file mode 100644 index 00000000000..c2a3813c870 --- /dev/null +++ b/htdocs/includes/stripe/tests/Stripe/ProductTest.php @@ -0,0 +1,77 @@ +expectsRequest( + 'get', + '/v1/products' + ); + $resources = Product::all(); + $this->assertTrue(is_array($resources->data)); + $this->assertInstanceOf("Stripe\\Product", $resources->data[0]); + } + + public function testIsRetrievable() + { + $this->expectsRequest( + 'get', + '/v1/products/' . self::TEST_RESOURCE_ID + ); + $resource = Product::retrieve(self::TEST_RESOURCE_ID); + $this->assertInstanceOf("Stripe\\Product", $resource); + } + + public function testIsCreatable() + { + $this->expectsRequest( + 'post', + '/v1/products' + ); + $resource = Product::create([ + 'name' => 'name', + 'type' => 'good' + ]); + $this->assertInstanceOf("Stripe\\Product", $resource); + } + + public function testIsSaveable() + { + $resource = Product::retrieve(self::TEST_RESOURCE_ID); + $resource->metadata["key"] = "value"; + $this->expectsRequest( + 'post', + '/v1/products/' . $resource->id + ); + $resource->save(); + $this->assertInstanceOf("Stripe\\Product", $resource); + } + + public function testIsUpdatable() + { + $this->expectsRequest( + 'post', + '/v1/products/' . self::TEST_RESOURCE_ID + ); + $resource = Product::update(self::TEST_RESOURCE_ID, [ + "metadata" => ["key" => "value"], + ]); + $this->assertInstanceOf("Stripe\\Product", $resource); + } + + public function testIsDeletable() + { + $resource = Product::retrieve(self::TEST_RESOURCE_ID); + $this->expectsRequest( + 'delete', + '/v1/products/' . $resource->id + ); + $resource->delete(); + $this->assertInstanceOf("Stripe\\Product", $resource); + } +} diff --git a/htdocs/includes/stripe/tests/Stripe/RecipientTest.php b/htdocs/includes/stripe/tests/Stripe/RecipientTest.php new file mode 100644 index 00000000000..43dd6e82a79 --- /dev/null +++ b/htdocs/includes/stripe/tests/Stripe/RecipientTest.php @@ -0,0 +1,90 @@ +expectsRequest( + 'get', + '/v1/recipients' + ); + $resources = Recipient::all(); + $this->assertTrue(is_array($resources->data)); + $this->assertInstanceOf("Stripe\\Recipient", $resources->data[0]); + } + + public function testIsRetrievable() + { + $this->expectsRequest( + 'get', + '/v1/recipients/' . self::TEST_RESOURCE_ID + ); + $resource = Recipient::retrieve(self::TEST_RESOURCE_ID); + $this->assertInstanceOf("Stripe\\Recipient", $resource); + } + + public function testIsCreatable() + { + $this->expectsRequest( + 'post', + '/v1/recipients' + ); + $resource = Recipient::create([ + "name" => "name", + "type" => "individual" + ]); + $this->assertInstanceOf("Stripe\\Recipient", $resource); + } + + public function testIsSaveable() + { + $resource = Recipient::retrieve(self::TEST_RESOURCE_ID); + $resource->metadata["key"] = "value"; + $this->expectsRequest( + 'post', + '/v1/recipients/' . $resource->id + ); + $resource->save(); + $this->assertInstanceOf("Stripe\\Recipient", $resource); + } + + public function testIsUpdatable() + { + $this->expectsRequest( + 'post', + '/v1/recipients/' . self::TEST_RESOURCE_ID + ); + $resource = Recipient::update(self::TEST_RESOURCE_ID, [ + "metadata" => ["key" => "value"], + ]); + $this->assertInstanceOf("Stripe\\Recipient", $resource); + } + + public function testIsDeletable() + { + $resource = Recipient::retrieve(self::TEST_RESOURCE_ID); + $this->expectsRequest( + 'delete', + '/v1/recipients/' . $resource->id + ); + $resource->delete(); + $this->assertInstanceOf("Stripe\\Recipient", $resource); + } + + public function testCanListTransfers() + { + $recipient = Recipient::retrieve(self::TEST_RESOURCE_ID); + $this->expectsRequest( + 'get', + '/v1/transfers', + ["recipient" => $recipient->id] + ); + $resources = $recipient->transfers(); + $this->assertTrue(is_array($resources->data)); + $this->assertInstanceOf("Stripe\\Transfer", $resources->data[0]); + } +} diff --git a/htdocs/includes/stripe/tests/Stripe/RefundTest.php b/htdocs/includes/stripe/tests/Stripe/RefundTest.php new file mode 100644 index 00000000000..788361d4d9d --- /dev/null +++ b/htdocs/includes/stripe/tests/Stripe/RefundTest.php @@ -0,0 +1,65 @@ +expectsRequest( + 'get', + '/v1/refunds' + ); + $resources = Refund::all(); + $this->assertTrue(is_array($resources->data)); + $this->assertInstanceOf("Stripe\\Refund", $resources->data[0]); + } + + public function testIsRetrievable() + { + $this->expectsRequest( + 'get', + '/v1/refunds/' . self::TEST_RESOURCE_ID + ); + $resource = Refund::retrieve(self::TEST_RESOURCE_ID); + $this->assertInstanceOf("Stripe\\Refund", $resource); + } + + public function testIsCreatable() + { + $this->expectsRequest( + 'post', + '/v1/refunds' + ); + $resource = Refund::create([ + "charge" => "ch_123" + ]); + $this->assertInstanceOf("Stripe\\Refund", $resource); + } + + public function testIsSaveable() + { + $resource = Refund::retrieve(self::TEST_RESOURCE_ID); + $resource->metadata["key"] = "value"; + $this->expectsRequest( + 'post', + '/v1/refunds/' . $resource->id + ); + $resource->save(); + $this->assertInstanceOf("Stripe\\Refund", $resource); + } + + public function testIsUpdatable() + { + $this->expectsRequest( + 'post', + '/v1/refunds/' . self::TEST_RESOURCE_ID + ); + $resource = Refund::update(self::TEST_RESOURCE_ID, [ + "metadata" => ["key" => "value"], + ]); + $this->assertInstanceOf("Stripe\\Refund", $resource); + } +} diff --git a/htdocs/includes/stripe/tests/Stripe/SKUTest.php b/htdocs/includes/stripe/tests/Stripe/SKUTest.php new file mode 100644 index 00000000000..d4fc2ad408b --- /dev/null +++ b/htdocs/includes/stripe/tests/Stripe/SKUTest.php @@ -0,0 +1,82 @@ +expectsRequest( + 'get', + '/v1/skus' + ); + $resources = SKU::all(); + $this->assertTrue(is_array($resources->data)); + $this->assertInstanceOf("Stripe\\SKU", $resources->data[0]); + } + + public function testIsRetrievable() + { + $this->expectsRequest( + 'get', + '/v1/skus/' . self::TEST_RESOURCE_ID + ); + $resource = SKU::retrieve(self::TEST_RESOURCE_ID); + $this->assertInstanceOf("Stripe\\SKU", $resource); + } + + public function testIsCreatable() + { + $this->expectsRequest( + 'post', + '/v1/skus' + ); + $resource = SKU::create([ + 'currency' => 'usd', + 'inventory' => [ + 'type' => 'finite', + 'quantity' => 1 + ], + 'price' => 100, + 'product' => "prod_123" + ]); + $this->assertInstanceOf("Stripe\\SKU", $resource); + } + + public function testIsSaveable() + { + $resource = SKU::retrieve(self::TEST_RESOURCE_ID); + $resource->metadata["key"] = "value"; + $this->expectsRequest( + 'post', + '/v1/skus/' . $resource->id + ); + $resource->save(); + $this->assertInstanceOf("Stripe\\SKU", $resource); + } + + public function testIsUpdatable() + { + $this->expectsRequest( + 'post', + '/v1/skus/' . self::TEST_RESOURCE_ID + ); + $resource = SKU::update(self::TEST_RESOURCE_ID, [ + "metadata" => ["key" => "value"], + ]); + $this->assertInstanceOf("Stripe\\SKU", $resource); + } + + public function testIsDeletable() + { + $resource = SKU::retrieve(self::TEST_RESOURCE_ID); + $this->expectsRequest( + 'delete', + '/v1/skus/' . $resource->id + ); + $resource->delete(); + $this->assertInstanceOf("Stripe\\SKU", $resource); + } +} diff --git a/htdocs/includes/stripe/tests/Stripe/SourceTest.php b/htdocs/includes/stripe/tests/Stripe/SourceTest.php new file mode 100644 index 00000000000..ad11b0d3455 --- /dev/null +++ b/htdocs/includes/stripe/tests/Stripe/SourceTest.php @@ -0,0 +1,134 @@ +expectsRequest( + 'get', + '/v1/sources/' . self::TEST_RESOURCE_ID + ); + $resource = Source::retrieve(self::TEST_RESOURCE_ID); + $this->assertInstanceOf("Stripe\\Source", $resource); + } + + public function testIsCreatable() + { + $this->expectsRequest( + 'post', + '/v1/sources' + ); + $resource = Source::create([ + "type" => "card" + ]); + $this->assertInstanceOf("Stripe\\Source", $resource); + } + + public function testIsSaveable() + { + $resource = Source::retrieve(self::TEST_RESOURCE_ID); + $resource->metadata["key"] = "value"; + $this->expectsRequest( + 'post', + '/v1/sources/' . $resource->id + ); + $resource->save(); + $this->assertInstanceOf("Stripe\\Source", $resource); + } + + public function testIsUpdatable() + { + $this->expectsRequest( + 'post', + '/v1/sources/' . self::TEST_RESOURCE_ID + ); + $resource = Source::update(self::TEST_RESOURCE_ID, [ + "metadata" => ["key" => "value"], + ]); + $this->assertInstanceOf("Stripe\\Source", $resource); + } + + public function testCanSaveCardExpiryDate() + { + $response = [ + 'id' => 'src_foo', + 'object' => 'source', + 'card' => [ + 'exp_month' => 8, + 'exp_year' => 2019, + ], + ]; + $source = Source::constructFrom($response); + + $response['card']['exp_month'] = 12; + $response['card']['exp_year'] = 2022; + $this->stubRequest( + 'POST', + '/v1/sources/src_foo', + [ + 'card' => [ + 'exp_month' => 12, + 'exp_year' => 2022, + ] + ], + null, + false, + $response + ); + + $source->card->exp_month = 12; + $source->card->exp_year = 2022; + $source->save(); + + $this->assertSame(12, $source->card->exp_month); + $this->assertSame(2022, $source->card->exp_year); + } + + public function testIsDetachableWhenAttached() + { + $resource = Source::retrieve(self::TEST_RESOURCE_ID); + $resource->customer = "cus_123"; + $this->expectsRequest( + 'delete', + '/v1/customers/cus_123/sources/' . $resource->id + ); + $resource->delete(); + $this->assertInstanceOf("Stripe\\Source", $resource); + } + + /** + * @expectedException \Stripe\Error\Api + */ + public function testIsNotDetachableWhenUnattached() + { + $resource = Source::retrieve(self::TEST_RESOURCE_ID); + $resource->detach(); + } + + public function testCanListSourceTransactions() + { + $source = Source::retrieve(self::TEST_RESOURCE_ID); + $this->expectsRequest( + 'get', + '/v1/sources/' . $source->id . "/source_transactions" + ); + $resources = $source->sourceTransactions(); + $this->assertTrue(is_array($resources->data)); + $this->assertInstanceOf("Stripe\\SourceTransaction", $resources->data[0]); + } + + public function testCanVerify() + { + $resource = Source::retrieve(self::TEST_RESOURCE_ID); + $this->expectsRequest( + 'post', + '/v1/sources/' . $resource->id . "/verify" + ); + $resource->verify(["values" => [32, 45]]); + $this->assertInstanceOf("Stripe\\Source", $resource); + } +} diff --git a/htdocs/includes/stripe/tests/Stripe/StripeObjectTest.php b/htdocs/includes/stripe/tests/Stripe/StripeObjectTest.php new file mode 100644 index 00000000000..af1cd936e1c --- /dev/null +++ b/htdocs/includes/stripe/tests/Stripe/StripeObjectTest.php @@ -0,0 +1,453 @@ +deepCopyReflector = new \ReflectionMethod('Stripe\\StripeObject', 'deepCopy'); + $this->deepCopyReflector->setAccessible(true); + + // This is used to access the `_opts` protected variable + $this->optsReflector = new \ReflectionProperty('Stripe\\StripeObject', '_opts'); + $this->optsReflector->setAccessible(true); + } + + public function testArrayAccessorsSemantics() + { + $s = new StripeObject(); + $s['foo'] = 'a'; + $this->assertSame($s['foo'], 'a'); + $this->assertTrue(isset($s['foo'])); + unset($s['foo']); + $this->assertFalse(isset($s['foo'])); + } + + public function testNormalAccessorsSemantics() + { + $s = new StripeObject(); + $s->foo = 'a'; + $this->assertSame($s->foo, 'a'); + $this->assertTrue(isset($s->foo)); + unset($s->foo); + $this->assertFalse(isset($s->foo)); + } + + public function testArrayAccessorsMatchNormalAccessors() + { + $s = new StripeObject(); + $s->foo = 'a'; + $this->assertSame($s['foo'], 'a'); + + $s['bar'] = 'b'; + $this->assertSame($s->bar, 'b'); + } + + public function testCount() + { + $s = new StripeObject(); + $this->assertSame(0, count($s)); + + $s['key1'] = 'value1'; + $this->assertSame(1, count($s)); + + $s['key2'] = 'value2'; + $this->assertSame(2, count($s)); + + unset($s['key1']); + $this->assertSame(1, count($s)); + } + + public function testKeys() + { + $s = new StripeObject(); + $s->foo = 'bar'; + $this->assertSame($s->keys(), ['foo']); + } + + public function testValues() + { + $s = new StripeObject(); + $s->foo = 'bar'; + $this->assertSame($s->values(), ['bar']); + } + + public function testToArray() + { + $s = new StripeObject(); + $s->foo = 'a'; + + $converted = $s->__toArray(); + + $this->assertInternalType('array', $converted); + $this->assertArrayHasKey('foo', $converted); + $this->assertEquals('a', $converted['foo']); + } + + public function testRecursiveToArray() + { + $s = new StripeObject(); + $z = new StripeObject(); + + $s->child = $z; + $z->foo = 'a'; + + $converted = $s->__toArray(true); + + $this->assertInternalType('array', $converted); + $this->assertArrayHasKey('child', $converted); + $this->assertInternalType('array', $converted['child']); + $this->assertArrayHasKey('foo', $converted['child']); + $this->assertEquals('a', $converted['child']['foo']); + } + + public function testNonexistentProperty() + { + $s = new StripeObject(); + $this->assertNull($s->nonexistent); + } + + public function testPropertyDoesNotExists() + { + $s = new StripeObject(); + $this->assertNull($s['nonexistent']); + } + + public function testJsonEncode() + { + $s = new StripeObject(); + $s->foo = 'a'; + + $this->assertEquals('{"foo":"a"}', json_encode($s)); + } + + public function testToString() + { + $s = new StripeObject(); + $s->foo = 'a'; + + $string = $s->__toString(); + $expected = <<assertEquals($expected, $string); + } + + public function testReplaceNewNestedUpdatable() + { + $s = new StripeObject(); + + $s->metadata = ['bar']; + $this->assertSame($s->metadata, ['bar']); + $s->metadata = ['baz', 'qux']; + $this->assertSame($s->metadata, ['baz', 'qux']); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testSetPermanentAttribute() + { + $s = new StripeObject(); + $s->id = 'abc_123'; + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testSetEmptyStringValue() + { + $s = new StripeObject(); + $s->foo = ''; + } + + public function testSerializeParametersOnEmptyObject() + { + $obj = StripeObject::constructFrom([]); + $this->assertSame([], $obj->serializeParameters()); + } + + public function testSerializeParametersOnNewObjectWithSubObject() + { + $obj = new StripeObject(); + $obj->metadata = ['foo' => 'bar']; + $this->assertSame(['metadata' => ['foo' => 'bar']], $obj->serializeParameters()); + } + + public function testSerializeParametersOnBasicObject() + { + $obj = StripeObject::constructFrom(['foo' => null]); + $obj->updateAttributes(['foo' => 'bar']); + $this->assertSame(['foo' => 'bar'], $obj->serializeParameters()); + } + + public function testSerializeParametersOnMoreComplexObject() + { + $obj = StripeObject::constructFrom([ + 'foo' => StripeObject::constructFrom([ + 'bar' => null, + 'baz' => null, + ]), + ]); + $obj->foo->bar = 'newbar'; + $this->assertSame(['foo' => ['bar' => 'newbar']], $obj->serializeParameters()); + } + + public function testSerializeParametersOnArray() + { + $obj = StripeObject::constructFrom([ + 'foo' => null, + ]); + $obj->foo = ['new-value']; + $this->assertSame(['foo' => ['new-value']], $obj->serializeParameters()); + } + + public function testSerializeParametersOnArrayThatShortens() + { + $obj = StripeObject::constructFrom([ + 'foo' => ['0-index', '1-index', '2-index'], + ]); + $obj->foo = ['new-value']; + $this->assertSame(['foo' => ['new-value']], $obj->serializeParameters()); + } + + public function testSerializeParametersOnArrayThatLengthens() + { + $obj = StripeObject::constructFrom([ + 'foo' => ['0-index', '1-index', '2-index'], + ]); + $obj->foo = array_fill(0, 4, 'new-value'); + $this->assertSame(['foo' => array_fill(0, 4, 'new-value')], $obj->serializeParameters()); + } + + public function testSerializeParametersOnArrayOfHashes() + { + $obj = StripeObject::constructFrom(['foo' => null]); + $obj->foo = [ + StripeObject::constructFrom(['bar' => null]), + ]; + + $obj->foo[0]->bar = 'baz'; + $this->assertSame(['foo' => [['bar' => 'baz']]], $obj->serializeParameters()); + } + + public function testSerializeParametersDoesNotIncludeUnchangedValues() + { + $obj = StripeObject::constructFrom([ + 'foo' => null, + ]); + $this->assertSame([], $obj->serializeParameters()); + } + + public function testSerializeParametersOnUnchangedArray() + { + $obj = StripeObject::constructFrom([ + 'foo' => ['0-index', '1-index', '2-index'], + ]); + $obj->foo = ['0-index', '1-index', '2-index']; + $this->assertSame([], $obj->serializeParameters()); + } + + public function testSerializeParametersWithStripeObject() + { + $obj = StripeObject::constructFrom([]); + $obj->metadata = StripeObject::constructFrom(['foo' => 'bar']); + + $serialized = $obj->serializeParameters(); + $this->assertSame(['foo' => 'bar'], $serialized['metadata']); + } + + public function testSerializeParametersOnReplacedStripeObject() + { + $obj = StripeObject::constructFrom([ + 'metadata' => StripeObject::constructFrom(['bar' => 'foo']), + ]); + $obj->metadata = StripeObject::constructFrom(['baz' => 'foo']); + + $serialized = $obj->serializeParameters(); + $this->assertSame(['bar' => '', 'baz' => 'foo'], $serialized['metadata']); + } + + public function testSerializeParametersOnArrayOfStripeObjects() + { + $obj = StripeObject::constructFrom([]); + $obj->metadata = [ + StripeObject::constructFrom(['foo' => 'bar']), + ]; + + $serialized = $obj->serializeParameters(); + $this->assertSame([['foo' => 'bar']], $serialized['metadata']); + } + + public function testSerializeParametersOnSetApiResource() + { + $customer = Customer::constructFrom(['id' => 'cus_123']); + $obj = StripeObject::constructFrom([]); + + // the key here is that the property is set explicitly (and therefore + // marked as unsaved), which is why it gets included below + $obj->customer = $customer; + + $serialized = $obj->serializeParameters(); + $this->assertSame(['customer' => $customer], $serialized); + } + + public function testSerializeParametersOnNotSetApiResource() + { + $customer = Customer::constructFrom(['id' => 'cus_123']); + $obj = StripeObject::constructFrom(['customer' => $customer]); + + $serialized = $obj->serializeParameters(); + $this->assertSame([], $serialized); + } + + public function testSerializeParametersOnApiResourceFlaggedWithSaveWithParent() + { + $customer = Customer::constructFrom(['id' => 'cus_123']); + $customer->saveWithParent = true; + + $obj = StripeObject::constructFrom(['customer' => $customer]); + + $serialized = $obj->serializeParameters(); + $this->assertSame(['customer' => []], $serialized); + } + + public function testSerializeParametersRaisesExceotionOnOtherEmbeddedApiResources() + { + // This customer doesn't have an ID and therefore the library doesn't know + // what to do with it and throws an InvalidArgumentException because it's + // probably not what the user expected to happen. + $customer = Customer::constructFrom([]); + + $obj = StripeObject::constructFrom([]); + $obj->customer = $customer; + + try { + $serialized = $obj->serializeParameters(); + $this->fail("Did not raise error"); + } catch (\InvalidArgumentException $e) { + $this->assertSame( + "Cannot save property `customer` containing an API resource of type Stripe\Customer. " . + "It doesn't appear to be persisted and is not marked as `saveWithParent`.", + $e->getMessage() + ); + } catch (\Exception $e) { + $this->fail("Unexpected exception: " . get_class($e)); + } + } + + public function testSerializeParametersForce() + { + $obj = StripeObject::constructFrom([ + 'id' => 'id', + 'metadata' => StripeObject::constructFrom([ + 'bar' => 'foo', + ]), + ]); + + $serialized = $obj->serializeParameters(true); + $this->assertSame(['id' => 'id', 'metadata' => ['bar' => 'foo']], $serialized); + } + + public function testDirty() + { + $obj = StripeObject::constructFrom([ + 'id' => 'id', + 'metadata' => StripeObject::constructFrom([ + 'bar' => 'foo', + ]), + ]); + + // note that `$force` and `dirty()` are for different things, but are + // functionally equivalent + $obj->dirty(); + + $serialized = $obj->serializeParameters(); + $this->assertSame(['id' => 'id', 'metadata' => ['bar' => 'foo']], $serialized); + } + + public function testDeepCopy() + { + $opts = [ + "api_base" => Stripe::$apiBase, + "api_key" => "apikey", + ]; + $values = [ + "id" => 1, + "name" => "Stripe", + "arr" => [ + StripeObject::constructFrom(["id" => "index0"], $opts), + "index1", + 2, + ], + "map" => [ + "0" => StripeObject::constructFrom(["id" => "index0"], $opts), + "1" => "index1", + "2" => 2 + ], + ]; + + $copyValues = $this->deepCopyReflector->invoke(null, $values); + + // we can't compare the hashes directly because they have embedded + // objects which are different from each other + $this->assertEquals($values["id"], $copyValues["id"]); + $this->assertEquals($values["name"], $copyValues["name"]); + $this->assertEquals(count($values["arr"]), count($copyValues["arr"])); + + // internal values of the copied StripeObject should be the same, + // but the object itself should be new (hence the assertNotSame) + $this->assertEquals($values["arr"][0]["id"], $copyValues["arr"][0]["id"]); + $this->assertNotSame($values["arr"][0], $copyValues["arr"][0]); + + // likewise, the Util\RequestOptions instance in _opts should have + // copied values but be a new instance + $this->assertEquals( + $this->optsReflector->getValue($values["arr"][0]), + $this->optsReflector->getValue($copyValues["arr"][0]) + ); + $this->assertNotSame( + $this->optsReflector->getValue($values["arr"][0]), + $this->optsReflector->getValue($copyValues["arr"][0]) + ); + + // scalars however, can be compared + $this->assertEquals($values["arr"][1], $copyValues["arr"][1]); + $this->assertEquals($values["arr"][2], $copyValues["arr"][2]); + + // and a similar story with the hash + $this->assertEquals($values["map"]["0"]["id"], $copyValues["map"]["0"]["id"]); + $this->assertNotSame($values["map"]["0"], $copyValues["map"]["0"]); + $this->assertNotSame( + $this->optsReflector->getValue($values["arr"][0]), + $this->optsReflector->getValue($copyValues["arr"][0]) + ); + $this->assertEquals( + $this->optsReflector->getValue($values["map"]["0"]), + $this->optsReflector->getValue($copyValues["map"]["0"]) + ); + $this->assertNotSame( + $this->optsReflector->getValue($values["map"]["0"]), + $this->optsReflector->getValue($copyValues["map"]["0"]) + ); + $this->assertEquals($values["map"]["1"], $copyValues["map"]["1"]); + $this->assertEquals($values["map"]["2"], $copyValues["map"]["2"]); + } + + public function testDeepCopyMaintainClass() + { + $charge = Charge::constructFrom(["id" => 1], null); + $copyCharge = $this->deepCopyReflector->invoke(null, $charge); + $this->assertEquals(get_class($charge), get_class($copyCharge)); + } +} diff --git a/htdocs/includes/stripe/tests/Stripe/StripeTest.php b/htdocs/includes/stripe/tests/Stripe/StripeTest.php new file mode 100644 index 00000000000..f594518d13d --- /dev/null +++ b/htdocs/includes/stripe/tests/Stripe/StripeTest.php @@ -0,0 +1,30 @@ +orig = [ + 'caBundlePath' => Stripe::$caBundlePath, + ]; + } + + /** + * @after + */ + public function restoreOriginalValues() + { + Stripe::$caBundlePath = $this->orig['caBundlePath']; + } + + public function testCABundlePathAccessors() + { + Stripe::setCABundlePath('path/to/ca/bundle'); + $this->assertEquals('path/to/ca/bundle', Stripe::getCABundlePath()); + } +} diff --git a/htdocs/includes/stripe/tests/Stripe/SubscriptionItemTest.php b/htdocs/includes/stripe/tests/Stripe/SubscriptionItemTest.php new file mode 100644 index 00000000000..09e766c1bec --- /dev/null +++ b/htdocs/includes/stripe/tests/Stripe/SubscriptionItemTest.php @@ -0,0 +1,77 @@ +expectsRequest( + 'get', + '/v1/subscription_items' + ); + $resources = SubscriptionItem::all(); + $this->assertTrue(is_array($resources->data)); + $this->assertInstanceOf("Stripe\\SubscriptionItem", $resources->data[0]); + } + + public function testIsRetrievable() + { + $this->expectsRequest( + 'get', + '/v1/subscription_items/' . self::TEST_RESOURCE_ID + ); + $resource = SubscriptionItem::retrieve(self::TEST_RESOURCE_ID); + $this->assertInstanceOf("Stripe\\SubscriptionItem", $resource); + } + + public function testIsCreatable() + { + $this->expectsRequest( + 'post', + '/v1/subscription_items' + ); + $resource = SubscriptionItem::create([ + "plan" => "plan", + "subscription" => "sub_123" + ]); + $this->assertInstanceOf("Stripe\\SubscriptionItem", $resource); + } + + public function testIsSaveable() + { + $resource = SubscriptionItem::retrieve(self::TEST_RESOURCE_ID); + $resource->metadata["key"] = "value"; + $this->expectsRequest( + 'post', + '/v1/subscription_items/' . $resource->id + ); + $resource->save(); + $this->assertInstanceOf("Stripe\\SubscriptionItem", $resource); + } + + public function testIsUpdatable() + { + $this->expectsRequest( + 'post', + '/v1/subscription_items/' . self::TEST_RESOURCE_ID + ); + $resource = SubscriptionItem::update(self::TEST_RESOURCE_ID, [ + "metadata" => ["key" => "value"], + ]); + $this->assertInstanceOf("Stripe\\SubscriptionItem", $resource); + } + + public function testIsDeletable() + { + $resource = SubscriptionItem::retrieve(self::TEST_RESOURCE_ID); + $this->expectsRequest( + 'delete', + '/v1/subscription_items/' . $resource->id + ); + $resource->delete(); + $this->assertInstanceOf("Stripe\\SubscriptionItem", $resource); + } +} diff --git a/htdocs/includes/stripe/tests/Stripe/SubscriptionTest.php b/htdocs/includes/stripe/tests/Stripe/SubscriptionTest.php new file mode 100644 index 00000000000..4a42e218224 --- /dev/null +++ b/htdocs/includes/stripe/tests/Stripe/SubscriptionTest.php @@ -0,0 +1,115 @@ +expectsRequest( + 'get', + '/v1/subscriptions' + ); + $resources = Subscription::all(); + $this->assertTrue(is_array($resources->data)); + $this->assertInstanceOf("Stripe\\Subscription", $resources->data[0]); + } + + public function testIsRetrievable() + { + $this->expectsRequest( + 'get', + '/v1/subscriptions/' . self::TEST_RESOURCE_ID + ); + $resource = Subscription::retrieve(self::TEST_RESOURCE_ID); + $this->assertInstanceOf("Stripe\\Subscription", $resource); + } + + public function testIsCreatable() + { + $this->expectsRequest( + 'post', + '/v1/subscriptions' + ); + $resource = Subscription::create([ + "customer" => "cus_123", + "plan" => "plan" + ]); + $this->assertInstanceOf("Stripe\\Subscription", $resource); + } + + public function testIsSaveable() + { + $resource = Subscription::retrieve(self::TEST_RESOURCE_ID); + $resource->metadata["key"] = "value"; + $this->expectsRequest( + 'post', + '/v1/subscriptions/' . $resource->id + ); + $resource->save(); + $this->assertInstanceOf("Stripe\\Subscription", $resource); + } + + public function testIsUpdatable() + { + $this->expectsRequest( + 'post', + '/v1/subscriptions/' . self::TEST_RESOURCE_ID + ); + $resource = Subscription::update(self::TEST_RESOURCE_ID, [ + "metadata" => ["key" => "value"], + ]); + $this->assertInstanceOf("Stripe\\Subscription", $resource); + } + + public function testIsCancelable() + { + $resource = Subscription::retrieve(self::TEST_RESOURCE_ID); + $this->expectsRequest( + 'delete', + '/v1/subscriptions/' . $resource->id, + [ + 'at_period_end' => 'true', + ] + ); + $resource->cancel([ + 'at_period_end' => true, + ]); + $this->assertInstanceOf("Stripe\\Subscription", $resource); + } + + public function testCanDeleteDiscount() + { + $resource = Subscription::retrieve(self::TEST_RESOURCE_ID); + $this->expectsRequest( + 'delete', + '/v1/subscriptions/' . $resource->id . '/discount' + ); + $resource->deleteDiscount(); + $this->assertInstanceOf("Stripe\\Subscription", $resource); + } + + public function testSerializeParametersItems() + { + $obj = Util\Util::convertToStripeObject([ + 'object' => 'subscription', + 'items' => Util\Util::convertToStripeObject([ + 'object' => 'list', + 'data' => [], + ], null), + ], null); + $obj->items = [ + ['id' => 'si_foo', 'deleted' => true], + ['plan' => 'plan_bar'], + ]; + $expected = [ + 'items' => [ + 0 => ['id' => 'si_foo', 'deleted' => true], + 1 => ['plan' => 'plan_bar'], + ], + ]; + $this->assertSame($expected, $obj->serializeParameters()); + } +} diff --git a/htdocs/includes/stripe/tests/Stripe/ThreeDSecureTest.php b/htdocs/includes/stripe/tests/Stripe/ThreeDSecureTest.php new file mode 100644 index 00000000000..f56e649cbc1 --- /dev/null +++ b/htdocs/includes/stripe/tests/Stripe/ThreeDSecureTest.php @@ -0,0 +1,32 @@ +expectsRequest( + 'get', + '/v1/3d_secure/' . self::TEST_RESOURCE_ID + ); + $resource = ThreeDSecure::retrieve(self::TEST_RESOURCE_ID); + $this->assertInstanceOf("Stripe\\ThreeDSecure", $resource); + } + + public function testIsCreatable() + { + $this->expectsRequest( + 'post', + '/v1/3d_secure' + ); + $resource = ThreeDSecure::create([ + "amount" => 100, + "currency" => "usd", + "return_url" => "url" + ]); + $this->assertInstanceOf("Stripe\\ThreeDSecure", $resource); + } +} diff --git a/htdocs/includes/stripe/tests/Stripe/TokenTest.php b/htdocs/includes/stripe/tests/Stripe/TokenTest.php new file mode 100644 index 00000000000..36bb4bc8283 --- /dev/null +++ b/htdocs/includes/stripe/tests/Stripe/TokenTest.php @@ -0,0 +1,28 @@ +expectsRequest( + 'get', + '/v1/tokens/' . self::TEST_RESOURCE_ID + ); + $resource = Token::retrieve(self::TEST_RESOURCE_ID); + $this->assertInstanceOf("Stripe\\Token", $resource); + } + + public function testIsCreatable() + { + $this->expectsRequest( + 'post', + '/v1/tokens' + ); + $resource = Token::create(["card" => "tok_visa"]); + $this->assertInstanceOf("Stripe\\Token", $resource); + } +} diff --git a/htdocs/includes/stripe/tests/Stripe/TopupTest.php b/htdocs/includes/stripe/tests/Stripe/TopupTest.php new file mode 100644 index 00000000000..994447636c6 --- /dev/null +++ b/htdocs/includes/stripe/tests/Stripe/TopupTest.php @@ -0,0 +1,69 @@ +expectsRequest( + 'get', + '/v1/topups' + ); + $resources = Topup::all(); + $this->assertTrue(is_array($resources->data)); + $this->assertInstanceOf("Stripe\\Topup", $resources->data[0]); + } + + public function testIsRetrievable() + { + $this->expectsRequest( + 'get', + '/v1/topups/' . self::TEST_RESOURCE_ID + ); + $resource = Topup::retrieve(self::TEST_RESOURCE_ID); + $this->assertInstanceOf("Stripe\\Topup", $resource); + } + + public function testIsCreatable() + { + $this->expectsRequest( + 'post', + '/v1/topups' + ); + $resource = Topup::create([ + "amount" => 100, + "currency" => "usd", + "source" => "tok_123", + "description" => "description", + "statement_descriptor" => "statement descriptor" + ]); + $this->assertInstanceOf("Stripe\\Topup", $resource); + } + + public function testIsSaveable() + { + $resource = Topup::retrieve(self::TEST_RESOURCE_ID); + $resource->metadata["key"] = "value"; + $this->expectsRequest( + 'post', + '/v1/topups/' . $resource->id + ); + $resource->save(); + $this->assertInstanceOf("Stripe\\Topup", $resource); + } + + public function testIsUpdatable() + { + $this->expectsRequest( + 'post', + '/v1/topups/' . self::TEST_RESOURCE_ID + ); + $resource = Topup::update(self::TEST_RESOURCE_ID, [ + "metadata" => ["key" => "value"], + ]); + $this->assertInstanceOf("Stripe\\Topup", $resource); + } +} diff --git a/htdocs/includes/stripe/tests/Stripe/TransferReversalTest.php b/htdocs/includes/stripe/tests/Stripe/TransferReversalTest.php new file mode 100644 index 00000000000..37101c73208 --- /dev/null +++ b/htdocs/includes/stripe/tests/Stripe/TransferReversalTest.php @@ -0,0 +1,21 @@ +metadata["key"] = "value"; + $this->expectsRequest( + 'post', + '/v1/transfers/' . $resource->transfer . '/reversals/' . $resource->id + ); + $resource->save(); + $this->assertInstanceOf("Stripe\\TransferReversal", $resource); + } +} diff --git a/htdocs/includes/stripe/tests/Stripe/TransferTest.php b/htdocs/includes/stripe/tests/Stripe/TransferTest.php new file mode 100644 index 00000000000..d60d560e7c5 --- /dev/null +++ b/htdocs/includes/stripe/tests/Stripe/TransferTest.php @@ -0,0 +1,140 @@ +expectsRequest( + 'get', + '/v1/transfers' + ); + $resources = Transfer::all(); + $this->assertTrue(is_array($resources->data)); + $this->assertInstanceOf("Stripe\\Transfer", $resources->data[0]); + } + + public function testIsRetrievable() + { + $this->expectsRequest( + 'get', + '/v1/transfers/' . self::TEST_RESOURCE_ID + ); + $resource = Transfer::retrieve(self::TEST_RESOURCE_ID); + $this->assertInstanceOf("Stripe\\Transfer", $resource); + } + + public function testIsCreatable() + { + $this->expectsRequest( + 'post', + '/v1/transfers' + ); + $resource = Transfer::create([ + "amount" => 100, + "currency" => "usd", + "destination" => "acct_123" + ]); + $this->assertInstanceOf("Stripe\\Transfer", $resource); + } + + public function testIsSaveable() + { + $resource = Transfer::retrieve(self::TEST_RESOURCE_ID); + $resource->metadata["key"] = "value"; + $this->expectsRequest( + 'post', + '/v1/transfers/' . $resource->id + ); + $resource->save(); + $this->assertInstanceOf("Stripe\\Transfer", $resource); + } + + public function testIsUpdatable() + { + $this->expectsRequest( + 'post', + '/v1/transfers/' . self::TEST_RESOURCE_ID + ); + $resource = Transfer::update(self::TEST_RESOURCE_ID, [ + "metadata" => ["key" => "value"], + ]); + $this->assertInstanceOf("Stripe\\Transfer", $resource); + } + + public function testIsReversable() + { + $resource = Transfer::retrieve(self::TEST_RESOURCE_ID); + $this->expectsRequest( + 'post', + '/v1/transfers/' . $resource->id . '/reversals' + ); + $resource->reverse(); + $this->assertInstanceOf("Stripe\\Transfer", $resource); + } + + public function testIsCancelable() + { + $transfer = Transfer::retrieve(self::TEST_RESOURCE_ID); + + // stripe-mock does not support this anymore so we stub it + $this->stubRequest( + 'post', + '/v1/transfers/' . $transfer->id . '/cancel' + ); + $resource = $transfer->cancel(); + $this->assertInstanceOf("Stripe\\Transfer", $resource); + $this->assertSame($resource, $transfer); + } + + public function testCanCreateReversal() + { + $this->expectsRequest( + 'post', + '/v1/transfers/' . self::TEST_RESOURCE_ID . '/reversals' + ); + $resource = Transfer::createReversal(self::TEST_RESOURCE_ID); + $this->assertInstanceOf("Stripe\\TransferReversal", $resource); + } + + public function testCanRetrieveReversal() + { + $this->expectsRequest( + 'get', + '/v1/transfers/' . self::TEST_RESOURCE_ID . '/reversals/' . self::TEST_REVERSAL_ID + ); + $resource = Transfer::retrieveReversal(self::TEST_RESOURCE_ID, self::TEST_REVERSAL_ID); + $this->assertInstanceOf("Stripe\\TransferReversal", $resource); + } + + public function testCanUpdateReversal() + { + $this->expectsRequest( + 'post', + '/v1/transfers/' . self::TEST_RESOURCE_ID . '/reversals/' . self::TEST_REVERSAL_ID + ); + $resource = Transfer::updateReversal( + self::TEST_RESOURCE_ID, + self::TEST_REVERSAL_ID, + [ + "metadata" => ["key" => "value"], + ] + ); + $this->assertInstanceOf("Stripe\\TransferReversal", $resource); + } + + public function testCanListReversal() + { + $this->expectsRequest( + 'get', + '/v1/transfers/' . self::TEST_RESOURCE_ID . '/reversals' + ); + $resources = Transfer::allReversals(self::TEST_RESOURCE_ID); + $this->assertTrue(is_array($resources->data)); + $this->assertInstanceOf("Stripe\\TransferReversal", $resources->data[0]); + } +} diff --git a/htdocs/includes/stripe/tests/Stripe/Util/DefaultLoggerTest.php b/htdocs/includes/stripe/tests/Stripe/Util/DefaultLoggerTest.php new file mode 100644 index 00000000000..711af03c4a0 --- /dev/null +++ b/htdocs/includes/stripe/tests/Stripe/Util/DefaultLoggerTest.php @@ -0,0 +1,28 @@ +error("message"); + + global $lastMessage; + $this->assertSame($lastMessage, "message"); + } +} + +// This is a little terrible, but unfortunately there's no clean way to stub a +// call to `error_log`. Here we overwrite it so that we can get the last arguments +// that went to it. This is obviously bad, but luckily it's constrained to +// being just in \Stripe\Util (i.e. won't interfere with PHPUnit for example) +// and _just_ present when tests are running. +function error_log($message) +{ + global $lastMessage; + $lastMessage = $message; +} diff --git a/htdocs/includes/stripe/tests/RequestOptionsTest.php b/htdocs/includes/stripe/tests/Stripe/Util/RequestOptionsTest.php similarity index 60% rename from htdocs/includes/stripe/tests/RequestOptionsTest.php rename to htdocs/includes/stripe/tests/Stripe/Util/RequestOptionsTest.php index 11546dd6ece..558f73982ea 100644 --- a/htdocs/includes/stripe/tests/RequestOptionsTest.php +++ b/htdocs/includes/stripe/tests/Stripe/Util/RequestOptionsTest.php @@ -8,55 +8,55 @@ class RequestOptionsTest extends TestCase { $opts = Util\RequestOptions::parse("foo"); $this->assertSame("foo", $opts->apiKey); - $this->assertSame(array(), $opts->headers); + $this->assertSame([], $opts->headers); } public function testNull() { $opts = Util\RequestOptions::parse(null); $this->assertSame(null, $opts->apiKey); - $this->assertSame(array(), $opts->headers); + $this->assertSame([], $opts->headers); } public function testEmptyArray() { - $opts = Util\RequestOptions::parse(array()); + $opts = Util\RequestOptions::parse([]); $this->assertSame(null, $opts->apiKey); - $this->assertSame(array(), $opts->headers); + $this->assertSame([], $opts->headers); } public function testAPIKeyArray() { $opts = Util\RequestOptions::parse( - array( + [ 'api_key' => 'foo', - ) + ] ); $this->assertSame('foo', $opts->apiKey); - $this->assertSame(array(), $opts->headers); + $this->assertSame([], $opts->headers); } public function testIdempotentKeyArray() { $opts = Util\RequestOptions::parse( - array( + [ 'idempotency_key' => 'foo', - ) + ] ); $this->assertSame(null, $opts->apiKey); - $this->assertSame(array('Idempotency-Key' => 'foo'), $opts->headers); + $this->assertSame(['Idempotency-Key' => 'foo'], $opts->headers); } public function testKeyArray() { $opts = Util\RequestOptions::parse( - array( + [ 'idempotency_key' => 'foo', 'api_key' => 'foo' - ) + ] ); $this->assertSame('foo', $opts->apiKey); - $this->assertSame(array('Idempotency-Key' => 'foo'), $opts->headers); + $this->assertSame(['Idempotency-Key' => 'foo'], $opts->headers); } /** @@ -66,4 +66,16 @@ class RequestOptionsTest extends TestCase { $opts = Util\RequestOptions::parse(5); } + + public function testDiscardNonPersistentHeaders() + { + $opts = Util\RequestOptions::parse( + [ + 'stripe_account' => 'foo', + 'idempotency_key' => 'foo', + ] + ); + $opts->discardNonPersistentHeaders(); + $this->assertSame(['Stripe-Account' => 'foo'], $opts->headers); + } } diff --git a/htdocs/includes/stripe/tests/Stripe/Util/UtilTest.php b/htdocs/includes/stripe/tests/Stripe/Util/UtilTest.php new file mode 100644 index 00000000000..cf5130208db --- /dev/null +++ b/htdocs/includes/stripe/tests/Stripe/Util/UtilTest.php @@ -0,0 +1,90 @@ +assertTrue(Util\Util::isList($list)); + + $notlist = [5, 'nstaoush', [], 'bar' => 'baz']; + $this->assertFalse(Util\Util::isList($notlist)); + } + + public function testThatPHPHasValueSemanticsForArrays() + { + $original = ['php-arrays' => 'value-semantics']; + $derived = $original; + $derived['php-arrays'] = 'reference-semantics'; + + $this->assertSame('value-semantics', $original['php-arrays']); + } + + public function testConvertStripeObjectToArrayIncludesId() + { + $customer = Util\Util::convertToStripeObject([ + 'id' => 'cus_123', + 'object' => 'customer', + ], null); + $this->assertTrue(array_key_exists("id", $customer->__toArray(true))); + } + + public function testUtf8() + { + // UTF-8 string + $x = "\xc3\xa9"; + $this->assertSame(Util\Util::utf8($x), $x); + + // Latin-1 string + $x = "\xe9"; + $this->assertSame(Util\Util::utf8($x), "\xc3\xa9"); + + // Not a string + $x = true; + $this->assertSame(Util\Util::utf8($x), $x); + } + + public function testUrlEncode() + { + $a = [ + 'my' => 'value', + 'that' => ['your' => 'example'], + 'bar' => 1, + 'baz' => null + ]; + + $enc = Util\Util::urlEncode($a); + $this->assertSame('my=value&that%5Byour%5D=example&bar=1', $enc); + + $a = ['that' => ['your' => 'example', 'foo' => null]]; + $enc = Util\Util::urlEncode($a); + $this->assertSame('that%5Byour%5D=example', $enc); + + $a = ['that' => 'example', 'foo' => ['bar', 'baz']]; + $enc = Util\Util::urlEncode($a); + $this->assertSame('that=example&foo%5B%5D=bar&foo%5B%5D=baz', $enc); + + $a = [ + 'my' => 'value', + 'that' => ['your' => ['cheese', 'whiz', null]], + 'bar' => 1, + 'baz' => null + ]; + + $enc = Util\Util::urlEncode($a); + $expected = 'my=value&that%5Byour%5D%5B%5D=cheese' + . '&that%5Byour%5D%5B%5D=whiz&bar=1'; + $this->assertSame($expected, $enc); + + // Ignores an empty array + $enc = Util\Util::urlEncode(['foo' => [], 'bar' => 'baz']); + $expected = 'bar=baz'; + $this->assertSame($expected, $enc); + + $a = ['foo' => [['bar' => 'baz'], ['bar' => 'bin']]]; + $enc = Util\Util::urlEncode($a); + $this->assertSame('foo%5B0%5D%5Bbar%5D=baz&foo%5B1%5D%5Bbar%5D=bin', $enc); + } +} diff --git a/htdocs/includes/stripe/tests/Stripe/WebhookTest.php b/htdocs/includes/stripe/tests/Stripe/WebhookTest.php new file mode 100644 index 00000000000..dcd82671afc --- /dev/null +++ b/htdocs/includes/stripe/tests/Stripe/WebhookTest.php @@ -0,0 +1,110 @@ +generateHeader(); + $event = Webhook::constructEvent(self::EVENT_PAYLOAD, $sigHeader, self::SECRET); + $this->assertEquals("evt_test_webhook", $event->id); + } + + /** + * @expectedException \UnexpectedValueException + */ + public function testInvalidJson() + { + $payload = "this is not valid JSON"; + $sigHeader = $this->generateHeader(["payload" => $payload]); + Webhook::constructEvent($payload, $sigHeader, self::SECRET); + } + + /** + * @expectedException \Stripe\Error\SignatureVerification + */ + public function testValidJsonAndInvalidHeader() + { + $sigHeader = "bad_header"; + Webhook::constructEvent(self::EVENT_PAYLOAD, $sigHeader, self::SECRET); + } + + /** + * @expectedException \Stripe\Error\SignatureVerification + * @expectedExceptionMessage Unable to extract timestamp and signatures from header + */ + public function testMalformedHeader() + { + $sigHeader = "i'm not even a real signature header"; + WebhookSignature::verifyHeader(self::EVENT_PAYLOAD, $sigHeader, self::SECRET); + } + + /** + * @expectedException \Stripe\Error\SignatureVerification + * @expectedExceptionMessage No signatures found with expected scheme + */ + public function testNoSignaturesWithExpectedScheme() + { + $sigHeader = $this->generateHeader(["scheme" => "v0"]); + WebhookSignature::verifyHeader(self::EVENT_PAYLOAD, $sigHeader, self::SECRET); + } + + /** + * @expectedException \Stripe\Error\SignatureVerification + * @expectedExceptionMessage No signatures found matching the expected signature for payload + */ + public function testNoValidSignatureForPayload() + { + $sigHeader = $this->generateHeader(["signature" => "bad_signature"]); + WebhookSignature::verifyHeader(self::EVENT_PAYLOAD, $sigHeader, self::SECRET); + } + + /** + * @expectedException \Stripe\Error\SignatureVerification + * @expectedExceptionMessage Timestamp outside the tolerance zone + */ + public function testTimestampOutsideTolerance() + { + $sigHeader = $this->generateHeader(["timestamp" => time() - 15]); + WebhookSignature::verifyHeader(self::EVENT_PAYLOAD, $sigHeader, self::SECRET, 10); + } + + public function testValidHeaderAndSignature() + { + $sigHeader = $this->generateHeader(); + $this->assertTrue(WebhookSignature::verifyHeader(self::EVENT_PAYLOAD, $sigHeader, self::SECRET, 10)); + } + + public function testHeaderContainsValidSignature() + { + $sigHeader = $this->generateHeader() . ",v1=bad_signature"; + $this->assertTrue(WebhookSignature::verifyHeader(self::EVENT_PAYLOAD, $sigHeader, self::SECRET, 10)); + } + + public function testTimestampOffButNoTolerance() + { + $sigHeader = $this->generateHeader(["timestamp" => 12345]); + $this->assertTrue(WebhookSignature::verifyHeader(self::EVENT_PAYLOAD, $sigHeader, self::SECRET)); + } +} diff --git a/htdocs/includes/stripe/tests/StripeObjectTest.php b/htdocs/includes/stripe/tests/StripeObjectTest.php deleted file mode 100644 index 5f922228270..00000000000 --- a/htdocs/includes/stripe/tests/StripeObjectTest.php +++ /dev/null @@ -1,108 +0,0 @@ -assertSame($s['foo'], 'a'); - $this->assertTrue(isset($s['foo'])); - unset($s['foo']); - $this->assertFalse(isset($s['foo'])); - } - - public function testNormalAccessorsSemantics() - { - $s = new StripeObject(); - $s->foo = 'a'; - $this->assertSame($s->foo, 'a'); - $this->assertTrue(isset($s->foo)); - unset($s->foo); - $this->assertFalse(isset($s->foo)); - } - - public function testArrayAccessorsMatchNormalAccessors() - { - $s = new StripeObject(); - $s->foo = 'a'; - $this->assertSame($s['foo'], 'a'); - - $s['bar'] = 'b'; - $this->assertSame($s->bar, 'b'); - } - - public function testKeys() - { - $s = new StripeObject(); - $s->foo = 'a'; - $this->assertSame($s->keys(), array('foo')); - } - - public function testToArray() - { - $s = new StripeObject(); - $s->foo = 'a'; - - $converted = $s->__toArray(); - - $this->assertInternalType('array', $converted); - $this->assertArrayHasKey('foo', $converted); - $this->assertEquals('a', $converted['foo']); - } - - public function testRecursiveToArray() - { - $s = new StripeObject(); - $z = new StripeObject(); - - $s->child = $z; - $z->foo = 'a'; - - $converted = $s->__toArray(true); - - $this->assertInternalType('array', $converted); - $this->assertArrayHasKey('child', $converted); - $this->assertInternalType('array', $converted['child']); - $this->assertArrayHasKey('foo', $converted['child']); - $this->assertEquals('a', $converted['child']['foo']); - } - - public function testNonexistentProperty() - { - $s = new StripeObject(); - $this->assertNull($s->nonexistent); - } - - public function testPropertyDoesNotExists() - { - $s = new StripeObject(); - $this->assertNull($s['nonexistent']); - } - - public function testJsonEncode() - { - // We can only JSON encode our objects in PHP 5.4+. 5.3 must use ->__toJSON() - if (version_compare(phpversion(), '5.4.0', '<')) { - return; - } - - $s = new StripeObject(); - $s->foo = 'a'; - - $this->assertEquals('{"foo":"a"}', json_encode($s->__toArray())); - } - - public function testReplaceNewNestedUpdatable() - { - StripeObject::init(); // Populate the $nestedUpdatableAttributes Set - $s = new StripeObject(); - - $s->metadata = array('bar'); - $this->assertSame($s->metadata, array('bar')); - $s->metadata = array('baz', 'qux'); - $this->assertSame($s->metadata, array('baz', 'qux')); - } -} diff --git a/htdocs/includes/stripe/tests/SubscriptionItemTest.php b/htdocs/includes/stripe/tests/SubscriptionItemTest.php deleted file mode 100644 index 4e4a545a5b1..00000000000 --- a/htdocs/includes/stripe/tests/SubscriptionItemTest.php +++ /dev/null @@ -1,38 +0,0 @@ - $plan0ID, 'customer' => $customer->id)); - - $plan1ID = 'gold-' . self::generateRandomString(20); - self::retrieveOrCreatePlan($plan1ID); - - $subItem = SubscriptionItem::create(array('plan' => $plan1ID, 'subscription' => $sub->id)); - $this->assertSame($subItem->plan->id, $plan1ID); - - $subItem->quantity = 2; - $subItem->save(); - - $subItem = SubscriptionItem::retrieve($subItem->id); - $this->assertSame($subItem->quantity, 2); - - // Update the quantity parameter one more time - $subItem = SubscriptionItem::update($subItem->id, array('quantity' => 3)); - $this->assertSame($subItem->quantity, 3); - - $subItems = SubscriptionItem::all(array('subscription'=>$sub->id, 'limit'=>3)); - $this->assertSame(get_class($subItems->data[0]), 'Stripe\SubscriptionItem'); - $this->assertSame(2, count($subItems->data)); - - $subItem->delete(); - $this->assertTrue($subItem->deleted); - } -} diff --git a/htdocs/includes/stripe/tests/SubscriptionTest.php b/htdocs/includes/stripe/tests/SubscriptionTest.php deleted file mode 100644 index 08f74108061..00000000000 --- a/htdocs/includes/stripe/tests/SubscriptionTest.php +++ /dev/null @@ -1,132 +0,0 @@ -subscriptions->create(array('plan' => $planID)); - - $this->assertSame($sub->status, 'active'); - $this->assertSame($sub->plan->id, $planID); - - $sub->quantity = 2; - $sub->save(); - - $sub = $customer->subscriptions->retrieve($sub->id); - $this->assertSame($sub->status, 'active'); - $this->assertSame($sub->plan->id, $planID); - $this->assertSame($sub->quantity, 2); - - $subs = $customer->subscriptions->all(array('limit'=>3)); - $this->assertSame(get_class($subs->data[0]), 'Stripe\Subscription'); - - $sub->cancel(array('at_period_end' => true)); - - $sub = $customer->subscriptions->retrieve($sub->id); - $this->assertSame($sub->status, 'active'); - // @codingStandardsIgnoreStart - $this->assertTrue($sub->cancel_at_period_end); - // @codingStandardsIgnoreEnd - } - - public function testCreateUpdateListCancel() - { - $planID = 'gold-' . self::generateRandomString(20); - self::retrieveOrCreatePlan($planID); - - $customer = self::createTestCustomer(); - - $sub = Subscription::create(array('plan' => $planID, 'customer' => $customer->id)); - - $this->assertSame($sub->status, 'active'); - $this->assertSame($sub->plan->id, $planID); - - $sub->quantity = 2; - $sub->save(); - - $sub = Subscription::retrieve($sub->id); - $this->assertSame($sub->status, 'active'); - $this->assertSame($sub->plan->id, $planID); - $this->assertSame($sub->quantity, 2); - - // Update the quantity parameter one more time - $sub = Subscription::update($sub->id, array("quantity" => 3)); - $this->assertSame($sub->status, 'active'); - $this->assertSame($sub->plan->id, $planID); - $this->assertSame($sub->quantity, 3); - - $subs = Subscription::all(array('customer'=>$customer->id, 'plan'=>$planID, 'limit'=>3)); - $this->assertSame(get_class($subs->data[0]), 'Stripe\Subscription'); - - $sub->cancel(array('at_period_end' => true)); - - $sub = Subscription::retrieve($sub->id); - $this->assertSame($sub->status, 'active'); - $this->assertTrue($sub->cancel_at_period_end); - } - - public function testCreateUpdateListCancelWithItems() - { - $plan0ID = 'gold-' . self::generateRandomString(20); - self::retrieveOrCreatePlan($plan0ID); - - $customer = self::createTestCustomer(); - - $sub = Subscription::create(array( - 'customer' => $customer->id, - 'items' => array( - array('plan' => $plan0ID), - ), - )); - - $this->assertSame(count($sub->items->data), 1); - $this->assertSame($sub->items->data[0]->plan->id, $plan0ID); - - $plan1ID = 'gold-' . self::generateRandomString(20); - self::retrieveOrCreatePlan($plan1ID); - - $sub = Subscription::update($sub->id, array( - 'items' => array( - array('plan' => $plan1ID), - ), - )); - - $this->assertSame(count($sub->items->data), 2); - $this->assertSame($sub->items->data[0]->plan->id, $plan0ID); - $this->assertSame($sub->items->data[1]->plan->id, $plan1ID); - } - - public function testDeleteDiscount() - { - $planID = 'gold-' . self::generateRandomString(20); - self::retrieveOrCreatePlan($planID); - - $couponID = '25off-' . self::generateRandomString(20); - self::retrieveOrCreateCoupon($couponID); - - $customer = self::createTestCustomer(); - - $sub = $customer->subscriptions->create( - array( - 'plan' => $planID, - 'coupon' => $couponID - ) - ); - - $this->assertSame($sub->status, 'active'); - $this->assertSame($sub->plan->id, $planID); - $this->assertSame($sub->discount->coupon->id, $couponID); - - $sub->deleteDiscount(); - $sub = $customer->subscriptions->retrieve($sub->id); - $this->assertNull($sub->discount); - } -} diff --git a/htdocs/includes/stripe/tests/TestCase.php b/htdocs/includes/stripe/tests/TestCase.php index a1fdc94f917..840c0ec58c1 100644 --- a/htdocs/includes/stripe/tests/TestCase.php +++ b/htdocs/includes/stripe/tests/TestCase.php @@ -3,269 +3,175 @@ namespace Stripe; /** - * Base class for Stripe test cases, provides some utility methods for creating - * objects. + * Base class for Stripe test cases. */ class TestCase extends \PHPUnit_Framework_TestCase { - const API_KEY = 'tGN0bIwXnHdwOa85VABjPdSn8nWY7G7I'; + /** @var string original API base URL */ + protected $origApiBase; - private $mock; + /** @var string original API key */ + protected $origApiKey; - protected static function authorizeFromEnv() - { - $apiKey = getenv('STRIPE_API_KEY'); - if (!$apiKey) { - $apiKey = self::API_KEY; - } + /** @var string original client ID */ + protected $origClientId; - Stripe::setApiKey($apiKey); - } + /** @var string original API version */ + protected $origApiVersion; + + /** @var string original account ID */ + protected $origAccountId; + + /** @var object HTTP client mocker */ + protected $clientMock; protected function setUp() { + // Save original values so that we can restore them after running tests + $this->origApiBase = Stripe::$apiBase; + $this->origApiKey = Stripe::getApiKey(); + $this->origClientId = Stripe::getClientId(); + $this->origApiVersion = Stripe::getApiVersion(); + $this->origAccountId = Stripe::getAccountId(); + + // Set up host and credentials for stripe-mock + Stripe::$apiBase = "http://localhost:" . MOCK_PORT; + Stripe::setApiKey("sk_test_123"); + Stripe::setClientId("ca_123"); + Stripe::setApiVersion(null); + Stripe::setAccountId(null); + + // Set up the HTTP client mocker + $this->clientMock = $this->getMock('\Stripe\HttpClient\ClientInterface'); + + // By default, use the real HTTP client ApiRequestor::setHttpClient(HttpClient\CurlClient::instance()); - - // Peg the API version so that it can be varied independently of the - // one set on the test account. - Stripe::setApiVersion('2017-04-06'); - - $this->mock = null; - $this->call = 0; } - protected function mockRequest($method, $path, $params = array(), $return = array('id' => 'myId'), $rcode = 200) + protected function tearDown() { - $mock = $this->setUpMockRequest(); - $mock->expects($this->at($this->call++)) - ->method('request') - ->with(strtolower($method), 'https://api.stripe.com' . $path, $this->anything(), $params, false) - ->willReturn(array(json_encode($return), $rcode, array())); + // Restore original values + Stripe::$apiBase = $this->origApiBase; + Stripe::setApiKey($this->origApiKey); + Stripe::setClientId($this->origClientId); + Stripe::setApiVersion($this->origApiVersion); + Stripe::setAccountId($this->origAccountId); } - private function setUpMockRequest() - { - if (!$this->mock) { - self::authorizeFromEnv(); - $this->mock = $this->getMock('\Stripe\HttpClient\ClientInterface'); - ApiRequestor::setHttpClient($this->mock); + /** + * Sets up a request expectation with the provided parameters. The request + * will actually go through and be emitted. + * + * @param string $method HTTP method (e.g. 'post', 'get', etc.) + * @param string $path relative path (e.g. '/v1/charges') + * @param array|null $params array of parameters. If null, parameters will + * not be checked. + * @param string[]|null $headers array of headers. Does not need to be + * exhaustive. If null, headers are not checked. + * @param bool $hasFile Whether the request parameters contains a file. + * Defaults to false. + */ + protected function expectsRequest( + $method, + $path, + $params = null, + $headers = null, + $hasFile = false + ) { + $this->prepareRequestMock($method, $path, $params, $headers, $hasFile) + ->will($this->returnCallback( + function ($method, $absUrl, $headers, $params, $hasFile) { + $curlClient = HttpClient\CurlClient::instance(); + ApiRequestor::setHttpClient($curlClient); + return $curlClient->request($method, $absUrl, $headers, $params, $hasFile); + } + )); + } + + /** + * Sets up a request expectation with the provided parameters. The request + * will not actually be emitted, instead the provided response parameters + * will be returned. + * + * @param string $method HTTP method (e.g. 'post', 'get', etc.) + * @param string $path relative path (e.g. '/v1/charges') + * @param array|null $params array of parameters. If null, parameters will + * not be checked. + * @param string[]|null $headers array of headers. Does not need to be + * exhaustive. If null, headers are not checked. + * @param bool $hasFile Whether the request parameters contains a file. + * Defaults to false. + * @param array $response + * @param integer $rcode + * @param string|null $base + * + * @return array + */ + protected function stubRequest( + $method, + $path, + $params = null, + $headers = null, + $hasFile = false, + $response = [], + $rcode = 200, + $base = null + ) { + $this->prepareRequestMock($method, $path, $params, $headers, $hasFile, $base) + ->willReturn([json_encode($response), $rcode, []]); + } + + /** + * Prepares the client mocker for an invocation of the `request` method. + * This helper method is used by both `expectsRequest` and `stubRequest` to + * prepare the client mocker to expect an invocation of the `request` method + * with the provided arguments. + * + * @param string $method HTTP method (e.g. 'post', 'get', etc.) + * @param string $path relative path (e.g. '/v1/charges') + * @param array|null $params array of parameters. If null, parameters will + * not be checked. + * @param string[]|null $headers array of headers. Does not need to be + * exhaustive. If null, headers are not checked. + * @param bool $hasFile Whether the request parameters contains a file. + * Defaults to false. + * @param string|null $base base URL (e.g. 'https://api.stripe.com') + * + * @return PHPUnit_Framework_MockObject_Builder_InvocationMocker + */ + private function prepareRequestMock( + $method, + $path, + $params = null, + $headers = null, + $hasFile = false, + $base = null + ) { + ApiRequestor::setHttpClient($this->clientMock); + + if ($base === null) { + $base = Stripe::$apiBase; } - return $this->mock; - } + $absUrl = $base . $path; - /** - * Create a valid test charge. - */ - protected static function createTestCharge(array $attributes = array()) - { - self::authorizeFromEnv(); - - return Charge::create( - $attributes + array( - 'amount' => 2000, - 'currency' => 'usd', - 'description' => 'Charge for test@example.com', - 'card' => array( - 'number' => '4242424242424242', - 'exp_month' => 5, - 'exp_year' => date('Y') + 3, - ), - ) - ); - } - - /** - * Create a valid test transfer. - */ - protected static function createTestTransfer(array $attributes = array(), $opts = null) - { - self::authorizeFromEnv(); - - $recipient = self::createTestRecipient(); - - return Transfer::create( - $attributes + array( - 'amount' => 2000, - 'currency' => 'usd', - 'description' => 'Transfer to test@example.com', - 'recipient' => $recipient->id - ), - $opts - ); - } - - /** - * Create a valid test customer. - */ - protected static function createTestCustomer(array $attributes = array()) - { - self::authorizeFromEnv(); - - return Customer::create( - $attributes + array( - 'card' => array( - 'number' => '4242424242424242', - 'exp_month' => 5, - 'exp_year' => date('Y') + 3, - ), - ) - ); - } - - /** - * Create a valid test recipient - */ - protected static function createTestRecipient(array $attributes = array()) - { - self::authorizeFromEnv(); - - return Recipient::create( - $attributes + array( - 'name' => 'PHP Test', - 'type' => 'individual', - 'tax_id' => '000000000', - 'bank_account' => array( - 'country' => 'US', - 'routing_number' => '110000000', - 'account_number' => '000123456789' - ), - ) - ); - } - - /** - * Create a test account - */ - protected static function createTestAccount(array $attributes = array()) - { - self::authorizeFromEnv(); - - return Account::create( - $attributes + array( - 'managed' => false, - 'country' => 'US', - 'email' => self::generateRandomEmail(), - ) - ); - } - - /** - * Create a test account - */ - protected static function createTestManagedAccount(array $attributes = array()) - { - self::authorizeFromEnv(); - - return Account::create( - $attributes + array( - 'managed' => true, - 'country' => 'US', - 'external_account' => array( - 'object' => 'bank_account', - 'country' => 'US', - 'currency' => 'usd', - 'routing_number' => '110000000', - 'account_number' => '000123456789' - ), - 'legal_entity' => array( - 'type' => 'individual', - 'personal_id_number' => '000000000', - 'type' => 'individual', - 'dob' => array('year' => '1980', 'month' => '01', 'day' => '01'), - 'first_name' => 'John', - 'last_name' => 'Doe', - 'address' => array( - 'line1' => '1234 Main Street', - 'postal_code' => '94110', - 'city' => 'San Francisco' - ), - 'personal_address' => array( - 'line1' => '1234 Main Street', - 'postal_code' => '94110', - 'city' => 'San Francisco' - ) - ), - 'tos_acceptance' => array('date' => time(), 'ip' => '127.0.0.1') - ) - ); - } - - /** - * Verify that a plan with a given ID exists, or create a new one if it does - * not. - */ - protected static function retrieveOrCreatePlan($id) - { - self::authorizeFromEnv(); - - try { - $plan = Plan::retrieve($id); - } catch (Error\InvalidRequest $exception) { - $plan = Plan::create( - array( - 'id' => $id, - 'amount' => 0, - 'currency' => 'usd', - 'interval' => 'month', - 'name' => 'Gold Test Plan', - ) + return $this->clientMock + ->expects($this->once()) + ->method('request') + ->with( + $this->identicalTo(strtolower($method)), + $this->identicalTo($absUrl), + // for headers, we only check that all of the headers provided in $headers are + // present in the list of headers of the actual request + $headers === null ? $this->anything() : $this->callback(function ($array) use ($headers) { + foreach ($headers as $header) { + if (!in_array($header, $array)) { + return false; + } + } + return true; + }), + $params === null ? $this->anything() : $this->identicalTo($params), + $this->identicalTo($hasFile) ); - } - } - - /** - * Verify that a coupon with a given ID exists, or create a new one if it - * does not. - */ - protected static function retrieveOrCreateCoupon($id) - { - self::authorizeFromEnv(); - - try { - $coupon = Coupon::retrieve($id); - } catch (Error\InvalidRequest $exception) { - $coupon = Coupon::create( - array( - 'id' => $id, - 'duration' => 'forever', - 'percent_off' => 25, - ) - ); - } - } - - /** - * Generate a semi-random string - */ - protected static function generateRandomString($length = 24) - { - $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTU'; - $charactersLength = strlen($characters); - $randomString = ''; - for ($i = 0; $i < $length; $i++) { - $randomString .= $characters[rand(0, $charactersLength - 1)]; - } - return $randomString; - } - - /** - * Generate a semi-random email. - */ - protected static function generateRandomEmail() - { - return 'dev-platform-bots+php-'.self::generateRandomString(12).'@stripe.com'; - } - - protected static function createTestBitcoinReceiver($email) - { - $receiver = BitcoinReceiver::create( - array( - 'amount' => 100, - 'currency' => 'usd', - 'description' => 'some details', - 'email' => $email - ) - ); - return $receiver; } } diff --git a/htdocs/includes/stripe/tests/ThreeDSecureTest.php b/htdocs/includes/stripe/tests/ThreeDSecureTest.php deleted file mode 100644 index ebdd62335ee..00000000000 --- a/htdocs/includes/stripe/tests/ThreeDSecureTest.php +++ /dev/null @@ -1,46 +0,0 @@ -mockRequest( - 'GET', - '/v1/3d_secure/tdsrc_test', - array(), - array( - 'id' => 'tdsrc_test', - 'object' => 'three_d_secure' - ) - ); - $three_d_secure = ThreeDSecure::retrieve('tdsrc_test'); - $this->assertSame($three_d_secure->id, 'tdsrc_test'); - } - - public function testCreate() - { - $this->mockRequest( - 'POST', - '/v1/3d_secure', - array( - 'card' => 'tok_test', - 'amount' => 1500, - 'currency' => 'usd', - 'return_url' => 'https://example.org/3d-secure-result' - ), - array( - 'id' => 'tdsrc_test', - 'object' => 'three_d_secure' - ) - ); - $three_d_secure = ThreeDSecure::create(array( - 'card' => 'tok_test', - 'amount' => 1500, - 'currency' => 'usd', - 'return_url' => 'https://example.org/3d-secure-result' - )); - $this->assertSame($three_d_secure->id, 'tdsrc_test'); - } -} diff --git a/htdocs/includes/stripe/tests/TokenTest.php b/htdocs/includes/stripe/tests/TokenTest.php deleted file mode 100644 index 60ec76a1544..00000000000 --- a/htdocs/includes/stripe/tests/TokenTest.php +++ /dev/null @@ -1,13 +0,0 @@ -assertSame(Token::classUrl(), '/v1/tokens'); - $token = new Token('abcd/efgh'); - $this->assertSame($token->instanceUrl(), '/v1/tokens/abcd%2Fefgh'); - } -} diff --git a/htdocs/includes/stripe/tests/TransferReversalTest.php b/htdocs/includes/stripe/tests/TransferReversalTest.php deleted file mode 100644 index 86d746650f5..00000000000 --- a/htdocs/includes/stripe/tests/TransferReversalTest.php +++ /dev/null @@ -1,19 +0,0 @@ - '2017-02-14'); - - public function testList() - { - $transfer = self::createTestTransfer(array(), $this->opts); - $all = $transfer->reversals->all(); - $this->assertSame(false, $all['has_more']); - $this->assertSame(0, count($all->data)); - } -} diff --git a/htdocs/includes/stripe/tests/TransferTest.php b/htdocs/includes/stripe/tests/TransferTest.php deleted file mode 100644 index f4fd347dc4e..00000000000 --- a/htdocs/includes/stripe/tests/TransferTest.php +++ /dev/null @@ -1,46 +0,0 @@ - '2017-02-14'); - - public function testCreate() - { - $transfer = self::createTestTransfer(array(), $this->opts); - $this->assertSame('transfer', $transfer->object); - } - - public function testRetrieve() - { - $transfer = self::createTestTransfer(array(), $this->opts); - $reloaded = Transfer::retrieve($transfer->id, $this->opts); - $this->assertSame($reloaded->id, $transfer->id); - } - - public function testTransferUpdateMetadata() - { - $transfer = self::createTestTransfer(array(), $this->opts); - - $transfer->metadata['test'] = 'foo bar'; - $transfer->save(); - - $updatedTransfer = Transfer::retrieve($transfer->id, $this->opts); - $this->assertSame('foo bar', $updatedTransfer->metadata['test']); - } - - public function testTransferUpdateMetadataAll() - { - $transfer = self::createTestTransfer(array(), $this->opts); - - $transfer->metadata = array('test' => 'foo bar'); - $transfer->save(); - - $updatedTransfer = Transfer::retrieve($transfer->id, $this->opts); - $this->assertSame('foo bar', $updatedTransfer->metadata['test']); - } -} diff --git a/htdocs/includes/stripe/tests/UtilTest.php b/htdocs/includes/stripe/tests/UtilTest.php deleted file mode 100644 index a1206d698f7..00000000000 --- a/htdocs/includes/stripe/tests/UtilTest.php +++ /dev/null @@ -1,45 +0,0 @@ -assertTrue(Util\Util::isList($list)); - - $notlist = array(5, 'nstaoush', array(), 'bar' => 'baz'); - $this->assertFalse(Util\Util::isList($notlist)); - } - - public function testThatPHPHasValueSemanticsForArrays() - { - $original = array('php-arrays' => 'value-semantics'); - $derived = $original; - $derived['php-arrays'] = 'reference-semantics'; - - $this->assertSame('value-semantics', $original['php-arrays']); - } - - public function testConvertStripeObjectToArrayIncludesId() - { - $customer = self::createTestCustomer(); - $this->assertTrue(array_key_exists("id", $customer->__toArray(true))); - } - - public function testUtf8() - { - // UTF-8 string - $x = "\xc3\xa9"; - $this->assertSame(Util\Util::utf8($x), $x); - - // Latin-1 string - $x = "\xe9"; - $this->assertSame(Util\Util::utf8($x), "\xc3\xa9"); - - // Not a string - $x = true; - $this->assertSame(Util\Util::utf8($x), $x); - } -} diff --git a/htdocs/includes/stripe/tests/bootstrap.no_autoload.php b/htdocs/includes/stripe/tests/bootstrap.no_autoload.php index 7358058780a..7011a3f4782 100644 --- a/htdocs/includes/stripe/tests/bootstrap.no_autoload.php +++ b/htdocs/includes/stripe/tests/bootstrap.no_autoload.php @@ -1,4 +1,5 @@ $fp, + CURLOPT_TIMEOUT => 3600, + CURLOPT_URL => 'https://curl.haxx.se/ca/cacert.pem', +); + +$ch = curl_init(); +curl_setopt_array($ch, $options); +curl_exec($ch); +curl_close($ch); +fclose($fp); diff --git a/htdocs/install/mysql/data/llx_c_action_trigger.sql b/htdocs/install/mysql/data/llx_c_action_trigger.sql index ccc1f9b77bd..35077eb5bc5 100644 --- a/htdocs/install/mysql/data/llx_c_action_trigger.sql +++ b/htdocs/install/mysql/data/llx_c_action_trigger.sql @@ -74,7 +74,9 @@ insert into llx_c_action_trigger (code,label,description,elementtype,rang) value insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('SHIPPING_SENTBYMAIL','Shipping sent by mail','Executed when a shipping is sent by mail','shipping',21); insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('MEMBER_VALIDATE','Member validated','Executed when a member is validated','member',22); insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('MEMBER_SENTBYMAIL','Mails sent from member card','Executed when you send email from member card','member',23); -insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('MEMBER_SUBSCRIPTION','Member subscribed','Executed when a member is subscribed','member',24); +insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('MEMBER_SUBSCRIPTION_CREATE','Member subscribtion recorded','Executed when a member subscribtion is deleted','member',24); +insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('MEMBER_SUBSCRIPTION_MODIFY','Member subscribtion modified','Executed when a member subscribtion is modified','member',24); +insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('MEMBER_SUBSCRIPTION_DELETE','Member subscribtion deleted','Executed when a member subscribtion is deleted','member',24); insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('MEMBER_RESILIATE','Member resiliated','Executed when a member is resiliated','member',25); insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('MEMBER_DELETE','Member deleted','Executed when a member is deleted','member',26); insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('FICHINTER_VALIDATE','Intervention validated','Executed when a intervention is validated','ficheinter',30); diff --git a/htdocs/install/mysql/data/llx_c_paiement.sql b/htdocs/install/mysql/data/llx_c_paiement.sql index b192dd3c8b0..2e459cd12a7 100644 --- a/htdocs/install/mysql/data/llx_c_paiement.sql +++ b/htdocs/install/mysql/data/llx_c_paiement.sql @@ -30,16 +30,13 @@ -- Types paiement -- -delete from llx_c_paiement; -insert into llx_c_paiement (id,code,libelle,type,active) values ( 0, '', '-', 3,1); insert into llx_c_paiement (id,code,libelle,type,active) values ( 1, 'TIP', 'TIP', 2,0); -insert into llx_c_paiement (id,code,libelle,type,active) values ( 2, 'VIR', 'Virement', 2,1); -insert into llx_c_paiement (id,code,libelle,type,active) values ( 3, 'PRE', 'Prélèvement', 2,1); -insert into llx_c_paiement (id,code,libelle,type,active) values ( 4, 'LIQ', 'Espèces', 2,1); -insert into llx_c_paiement (id,code,libelle,type,active) values ( 6, 'CB', 'Carte Bancaire', 2,1); -insert into llx_c_paiement (id,code,libelle,type,active) values ( 7, 'CHQ', 'Chèque', 2,1); -insert into llx_c_paiement (id,code,libelle,type,active) values (50, 'VAD', 'Paiement en ligne', 2,0); +insert into llx_c_paiement (id,code,libelle,type,active) values ( 2, 'VIR', 'Transfer', 2,1); +insert into llx_c_paiement (id,code,libelle,type,active) values ( 3, 'PRE', 'Debit order', 2,1); +insert into llx_c_paiement (id,code,libelle,type,active) values ( 4, 'LIQ', 'Cash', 2,1); +insert into llx_c_paiement (id,code,libelle,type,active) values ( 6, 'CB', 'Credit card', 2,1); +insert into llx_c_paiement (id,code,libelle,type,active) values ( 7, 'CHQ', 'Cheque', 2,1); +insert into llx_c_paiement (id,code,libelle,type,active) values (50, 'VAD', 'Online payment', 2,0); insert into llx_c_paiement (id,code,libelle,type,active) values (51, 'TRA', 'Traite', 2,0); insert into llx_c_paiement (id,code,libelle,type,active) values (52, 'LCR', 'LCR', 2,0); insert into llx_c_paiement (id,code,libelle,type,active) values (53, 'FAC', 'Factor', 2,0); ---insert into llx_c_paiement (id,code,libelle,type,active) values (54, 'PRO', 'Proforma', 2,0); diff --git a/htdocs/install/mysql/migration/6.0.0-7.0.0.sql b/htdocs/install/mysql/migration/6.0.0-7.0.0.sql index 2a130fad193..442b99fbfb1 100644 --- a/htdocs/install/mysql/migration/6.0.0-7.0.0.sql +++ b/htdocs/install/mysql/migration/6.0.0-7.0.0.sql @@ -94,6 +94,11 @@ ALTER TABLE llx_website_page ADD COLUMN type_container varchar(16) NOT NULL DEFA -- For 7.0 +delete from llx_c_action_trigger where code = 'MEMBER_SUBSCRIPTION'; +insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('MEMBER_SUBSCRIPTION_CREATE','Member subscribtion recorded','Executed when a member subscribtion is deleted','member',24); +insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('MEMBER_SUBSCRIPTION_MODIFY','Member subscribtion modified','Executed when a member subscribtion is modified','member',24); +insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('MEMBER_SUBSCRIPTION_DELETE','Member subscribtion deleted','Executed when a member subscribtion is deleted','member',24); + ALTER TABLE llx_product_attribute_value DROP INDEX unique_ref; ALTER TABLE llx_product_attribute_value ADD UNIQUE INDEX uk_product_attribute_value (fk_product_attribute, ref); diff --git a/htdocs/install/mysql/migration/7.0.0-8.0.0.sql b/htdocs/install/mysql/migration/7.0.0-8.0.0.sql index 34711051d8e..2b2bb6949d5 100644 --- a/htdocs/install/mysql/migration/7.0.0-8.0.0.sql +++ b/htdocs/install/mysql/migration/7.0.0-8.0.0.sql @@ -62,8 +62,18 @@ insert into llx_c_type_container (code,label,module,active) values ('banner', insert into llx_c_type_container (code,label,module,active) values ('blogpost', 'BlogPost', 'system', 1); insert into llx_c_type_container (code,label,module,active) values ('other', 'Other', 'system', 1); +-- For supplier product buy price in multicurency +ALTER TABLE llx_product_fournisseur_price CHANGE COLUMN multicurrency_price_ttc multicurrency_unitprice DOUBLE(24,8) NULL DEFAULT NULL; +ALTER TABLE llx_product_fournisseur_price_log CHANGE COLUMN multicurrency_price_ttc multicurrency_unitprice DOUBLE(24,8) NULL DEFAULT NULL; ALTER TABLE llx_expensereport_det ADD COLUMN docnumber varchar(128) after fk_expensereport; ALTER TABLE llx_website_page ADD COLUMN aliasalt varchar(255) after pageurl; +-- Add missing keys and primary key +DELETE FROM llx_c_paiement WHERE code = '' or code = '-' or id = 0; +ALTER TABLE llx_c_paiement DROP INDEX uk_c_paiement; +ALTER TABLE llx_c_paiement ADD UNIQUE INDEX uk_c_paiement_code(entity, code); +ALTER TABLE llx_c_paiement CHANGE COLUMN id id INTEGER AUTO_INCREMENT PRIMARY KEY; + + diff --git a/htdocs/install/mysql/tables/llx_c_paiement.key.sql b/htdocs/install/mysql/tables/llx_c_paiement.key.sql index ad1930fba2e..1e22789d7bf 100644 --- a/htdocs/install/mysql/tables/llx_c_paiement.key.sql +++ b/htdocs/install/mysql/tables/llx_c_paiement.key.sql @@ -18,3 +18,5 @@ -- ======================================================================== ALTER TABLE llx_c_paiement ADD UNIQUE INDEX uk_c_paiement(id, entity, code); + +ALTER TABLE llx_c_paiement ADD UNIQUE INDEX uk_c_paiement_code(entity, code); diff --git a/htdocs/install/mysql/tables/llx_c_paiement.sql b/htdocs/install/mysql/tables/llx_c_paiement.sql index 55cb44fb257..1c26cb7aaeb 100644 --- a/htdocs/install/mysql/tables/llx_c_paiement.sql +++ b/htdocs/install/mysql/tables/llx_c_paiement.sql @@ -21,7 +21,7 @@ create table llx_c_paiement ( - id integer, + id integer AUTO_INCREMENT PRIMARY KEY, entity integer DEFAULT 1 NOT NULL, -- multi company id code varchar(6) NOT NULL, libelle varchar(62), diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index 0c5962c1183..d6514db4d2c 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -420,7 +420,6 @@ ExtrafieldParamHelpsellist=List of values comes from a table
Syntax : table_n ExtrafieldParamHelpchkbxlst=List of values comes from a table
Syntax : table_name:label_field:id_field::filter
Example : c_typent:libelle:id::filter

filter can be a simple test (eg active=1) to display only active value
You can also use $ID$ in filter witch is the current id of current object
To do a SELECT in filter use $SEL$
if you want to filter on extrafields use syntax extra.fieldcode=... (where field code is the code of extrafield)

In order to have the list depending on another complementary attribute list :
c_typent:libelle:id:options_parent_list_code|parent_column:filter

In order to have the list depending on another list:
c_typent:libelle:id:parent_list_code|parent_column:filter ExtrafieldParamHelplink=Parameters must be ObjectName:Classpath
Syntax : ObjectName:Classpath
Examples :
Societe:societe/class/societe.class.php
Contact:contact/class/contact.class.php LibraryToBuildPDF=Library used for PDF generation -WarningUsingFPDF=Warning: Your conf.php contains directive dolibarr_pdf_force_fpdf=1. This means you use the FPDF library to generate PDF files. This library is old and does not support a lot of features (Unicode, image transparency, cyrillic, arab and asiatic languages, ...), so you may experience errors during PDF generation.
To solve this and have a full support of PDF generation, please download TCPDF library, then comment or remove the line $dolibarr_pdf_force_fpdf=1, and add instead $dolibarr_lib_TCPDF_PATH='path_to_TCPDF_dir' LocalTaxDesc=Some countries apply 2 or 3 taxes on each invoice line. If this is the case, choose type for second and third tax and its rate. Possible type are:
1 : local tax apply on products and services without vat (localtax is calculated on amount without tax)
2 : local tax apply on products and services including vat (localtax is calculated on amount + main tax)
3 : local tax apply on products without vat (localtax is calculated on amount without tax)
4 : local tax apply on products including vat (localtax is calculated on amount + main vat)
5 : local tax apply on services without vat (localtax is calculated on amount without tax)
6 : local tax apply on services including vat (localtax is calculated on amount + tax) SMS=SMS LinkToTestClickToDial=Enter a phone number to call to show a link to test the ClickToDial url for user %s diff --git a/htdocs/langs/en_US/agenda.lang b/htdocs/langs/en_US/agenda.lang index 0c70a160204..4ab64a98224 100644 --- a/htdocs/langs/en_US/agenda.lang +++ b/htdocs/langs/en_US/agenda.lang @@ -53,7 +53,9 @@ MemberValidatedInDolibarr=Member %s validated MemberModifiedInDolibarr=Member %s modified MemberResiliatedInDolibarr=Member %s terminated MemberDeletedInDolibarr=Member %s deleted -MemberSubscriptionAddedInDolibarr=Subscription for member %s added +MemberSubscriptionAddedInDolibarr=Subscription %s for member %s added +MemberSubscriptionModifiedInDolibarr=Subscription %s for member %s modified +MemberSubscriptionDeletedInDolibarr=Subscription %s for member %s deleted ShipmentValidatedInDolibarr=Shipment %s validated ShipmentClassifyClosedInDolibarr=Shipment %s classified billed ShipmentUnClassifyCloseddInDolibarr=Shipment %s classified reopened diff --git a/htdocs/langs/en_US/banks.lang b/htdocs/langs/en_US/banks.lang index 78ac859e706..93fea797c81 100644 --- a/htdocs/langs/en_US/banks.lang +++ b/htdocs/langs/en_US/banks.lang @@ -7,6 +7,7 @@ BankName=Bank name FinancialAccount=Account BankAccount=Bank account BankAccounts=Bank accounts +BankAccountsAndGateways=Bank accounts | Gateways ShowAccount=Show Account AccountRef=Financial account ref AccountLabel=Financial account label diff --git a/htdocs/langs/en_US/companies.lang b/htdocs/langs/en_US/companies.lang index 7d2b878c5cc..57ff05ed8ac 100644 --- a/htdocs/langs/en_US/companies.lang +++ b/htdocs/langs/en_US/companies.lang @@ -258,6 +258,7 @@ ProfId4DZ=NIS VATIntra=Sales tax ID VATIntraShort=Tax ID VATIntraSyntaxIsValid=Syntax is valid +VATReturn=VAT return ProspectCustomer=Prospect / Customer Prospect=Prospect CustomerCard=Customer Card diff --git a/htdocs/langs/en_US/compta.lang b/htdocs/langs/en_US/compta.lang index 0be07faecf6..7b2c99fe8fc 100644 --- a/htdocs/langs/en_US/compta.lang +++ b/htdocs/langs/en_US/compta.lang @@ -157,6 +157,7 @@ RulesResultDue=- It includes outstanding invoices, expenses, VAT, donations whet RulesResultInOut=- It includes the real payments made on invoices, expenses, VAT and salaries.
- It is based on the payment dates of the invoices, expenses, VAT and salaries. The donation date for donation. RulesCADue=- It includes the client's due invoices whether they are paid or not.
- It is based on the validation date of these invoices.
RulesCAIn=- It includes all the effective payments of invoices received from clients.
- It is based on the payment date of these invoices
+RulesCATotalSaleJournal=It includes all credit lines from the Sale journal. RulesAmountOnInOutBookkeepingRecord=It includes record in your Ledger with accounting accounts that has the group "EXPENSE" or "INCOME" RulesResultBookkeepingPredefined=It includes record in your Ledger with accounting accounts that has the group "EXPENSE" or "INCOME" RulesResultBookkeepingPersonalized=It show record in your Ledger with accounting accounts grouped by personalized groups diff --git a/htdocs/langs/en_US/main.lang b/htdocs/langs/en_US/main.lang index 1e6f9478313..4f402501c9a 100644 --- a/htdocs/langs/en_US/main.lang +++ b/htdocs/langs/en_US/main.lang @@ -325,8 +325,10 @@ Default=Default DefaultValue=Default value DefaultValues=Default values Price=Price +PriceCurrency=Price (currency) UnitPrice=Unit price UnitPriceHT=Unit price (net) +UnitPriceHTCurrency=Unit price (net) (currency) UnitPriceTTC=Unit price PriceU=U.P. PriceUHT=U.P. (net) @@ -354,6 +356,7 @@ AmountLT2ES=Amount IRPF AmountTotal=Total amount AmountAverage=Average amount PriceQtyMinHT=Price quantity min. (net of tax) +PriceQtyMinHTCurrency=Price quantity min. (net of tax) (currency) Percentage=Percentage Total=Total SubTotal=Subtotal @@ -430,6 +433,9 @@ ActionsOnCompany=Events about this third party ActionsOnMember=Events about this member ActionsOnProduct=Events about this product NActionsLate=%s late +ToDo=To do +Completed=Completed +Running=In progress RequestAlreadyDone=Request already recorded Filter=Filter FilterOnInto=Search criteria '%s' into fields %s @@ -923,3 +929,6 @@ CommentDeleted=Comment deleted Everybody=Everybody PayedBy=Payed by PayedTo=Payed to +Monthly=Monthly +Quarterly=Quarterly +Annual=Annual \ No newline at end of file diff --git a/htdocs/langs/en_US/other.lang b/htdocs/langs/en_US/other.lang index d90bfb35032..066f761bb32 100644 --- a/htdocs/langs/en_US/other.lang +++ b/htdocs/langs/en_US/other.lang @@ -80,8 +80,8 @@ LinkedObject=Linked object NbOfActiveNotifications=Number of notifications (nb of recipient emails) PredefinedMailTest=__(Hello)__\nThis is a test mail sent to __EMAIL__.\nThe two lines are separated by a carriage return.\n\n__USER_SIGNATURE__ PredefinedMailTestHtml=__(Hello)__\nThis is a test mail (the word test must be in bold).
The two lines are separated by a carriage return.

__USER_SIGNATURE__ -PredefinedMailContentSendInvoice=__(Hello)__\n\nYou will find here the invoice __REF__\n\n__ONLINE_PAYMENT_URL__\n\n__(Sincerely)__\n\n__USER_SIGNATURE__ -PredefinedMailContentSendInvoiceReminder=__(Hello)__\n\nWe would like to warn you that the invoice __REF__ seems to not be payed. So this is the invoice in attachment again, as a reminder.\n\n__ONLINE_PAYMENT_URL__\n\n__(Sincerely)__\n\n__USER_SIGNATURE__ +PredefinedMailContentSendInvoice=__(Hello)__\n\nYou will find here the invoice __REF__\n\nThis is the link to make your online payment if this invoice is not already payed:\n__ONLINE_PAYMENT_URL__\n\n__(Sincerely)__\n\n__USER_SIGNATURE__ +PredefinedMailContentSendInvoiceReminder=__(Hello)__\n\nWe would like to warn you that the invoice __REF__ seems to not be payed. So this is the invoice in attachment again, as a reminder.\n\nThis is the link to make your online payment:\n__ONLINE_PAYMENT_URL__\n\n__(Sincerely)__\n\n__USER_SIGNATURE__ PredefinedMailContentSendProposal=__(Hello)__\n\nYou will find here the commercial proposal __PREF__\n\n\n__(Sincerely)__\n\n__USER_SIGNATURE__ PredefinedMailContentSendSupplierProposal=__(Hello)__\n\nYou will find here the price request __REF__\n\n\n__(Sincerely)__\n\n__USER_SIGNATURE__ PredefinedMailContentSendOrder=__(Hello)__\n\nYou will find here the order __REF__\n\n\n__(Sincerely)__\n\n__USER_SIGNATURE__ diff --git a/htdocs/langs/en_US/products.lang b/htdocs/langs/en_US/products.lang index 1ff1fb0e427..e5393466c3d 100644 --- a/htdocs/langs/en_US/products.lang +++ b/htdocs/langs/en_US/products.lang @@ -123,6 +123,7 @@ ConfirmDeleteProductLine=Are you sure you want to delete this product line? ProductSpecial=Special QtyMin=Minimum Qty PriceQtyMin=Price for this min. qty (w/o discount) +PriceQtyMinCurrency=Price for this min. qty (w/o discount) (currency) VATRateForSupplierProduct=VAT Rate (for this supplier/product) DiscountQtyMin=Default discount for qty NoPriceDefinedForThisSupplier=No price/qty defined for this supplier/product diff --git a/htdocs/langs/en_US/stripe.lang b/htdocs/langs/en_US/stripe.lang index 2b5823c28fb..9bc202685dd 100644 --- a/htdocs/langs/en_US/stripe.lang +++ b/htdocs/langs/en_US/stripe.lang @@ -35,8 +35,12 @@ NewStripePaymentReceived=New Stripe payment received NewStripePaymentFailed=New Stripe payment tried but failed STRIPE_TEST_SECRET_KEY=Secret test key STRIPE_TEST_PUBLISHABLE_KEY=Publishable test key +STRIPE_TEST_WEBHOOK_KEY=Webhook test key STRIPE_LIVE_SECRET_KEY=Secret live key STRIPE_LIVE_PUBLISHABLE_KEY=Publishable live key +STRIPE_LIVE_WEBHOOK_KEY=Webhook live key +ONLINE_PAYMENT_WAREHOUSE=Stock to use for stock decrease when payment online payment is done (TODO When option to decrease stock is done on an action on invoice and the online payment generate itself the invoice ?) StripeLiveEnabled=Stripe live enabled (otherwise test/sandbox mode) StripeImportPayment=Import Stripe payments -ExampleOfTestCreditCard=Example of credit card for test: %s (valid), %s (error CVC), %s (expired), %s (charge fails) \ No newline at end of file +ExampleOfTestCreditCard=Example of credit card for test: %s (valid), %s (error CVC), %s (expired), %s (charge fails) +StripeGateways=Stripe gateways \ No newline at end of file diff --git a/htdocs/langs/fr_FR/main.lang b/htdocs/langs/fr_FR/main.lang index cd087a9a4b8..edb756ce1d8 100644 --- a/htdocs/langs/fr_FR/main.lang +++ b/htdocs/langs/fr_FR/main.lang @@ -325,8 +325,10 @@ Default=Défaut DefaultValue=Valeur par défaut DefaultValues=Valeurs par défaut Price=Prix +PriceCurrency=Prix (devise) UnitPrice=Prix unitaire UnitPriceHT=Prix unitaire HT +UnitPriceHTCurrency=Prix unitaire HT (devise) UnitPriceTTC=Prix unitaire TTC PriceU=P.U. PriceUHT=P.U. HT @@ -353,6 +355,7 @@ AmountLT2ES=Montant IRPF AmountTotal=Montant total AmountAverage=Montant moyen PriceQtyMinHT=Prix quantité min. HT +PriceQtyMinHTCurrency=Prix quantité min. HT (devise) Percentage=Pourcentage Total=Total SubTotal=Sous-total diff --git a/htdocs/langs/fr_FR/other.lang b/htdocs/langs/fr_FR/other.lang index 610a4f59ab3..d34ca3c3498 100644 --- a/htdocs/langs/fr_FR/other.lang +++ b/htdocs/langs/fr_FR/other.lang @@ -78,8 +78,8 @@ LinkedObject=Objet lié NbOfActiveNotifications=Nombre de notifications (nb de destinataires emails) PredefinedMailTest=__(Hello)__,\nCeci est un mail de test envoyé à __EMAIL__.\nLes deux lignes sont séparées par un saut de ligne.\n\n__USER_SIGNATURE__ PredefinedMailTestHtml=__(Hello)__\nCeci est un message de test (le mot test doit être en gras).
Les 2 lignes sont séparées par un retour à la ligne.

__SIGNATURE__ -PredefinedMailContentSendInvoice=__(Hello)__\n\nVeuillez trouver, ci-joint, la facture __REF__\n\n__ONLINE_PAYMENT_URL__\n\n__(Sincerely)__\n\n__USER_SIGNATURE__ -PredefinedMailContentSendInvoiceReminder=__(Hello)__\n\nNous voulons porter à votre connaissance le fait que la facture __REF__ semble non payée. Aussi, voici la facture à nouveau en pièce jointe pour rappel.\n\n__ONLINE_PAYMENT_URL__\n\n__(Sincerely)__\n\n__USER_SIGNATURE__ +PredefinedMailContentSendInvoice=__(Hello)__\n\nVeuillez trouver, ci-joint, la facture __REF__\n\nVoici le lien pour un paiement en ligne au cas ou celle-ci n'aurait pas encore été payé:\n\n__ONLINE_PAYMENT_URL__\n\n__(Sincerely)__\n\n__USER_SIGNATURE__ +PredefinedMailContentSendInvoiceReminder=__(Hello)__\n\nNous voulons porter à votre connaissance le fait que la facture __REF__ semble non payée. Aussi, voici la facture à nouveau en pièce jointe pour rappel.\n\nVoici le lien pour un paiement en ligne:\n__ONLINE_PAYMENT_URL__\n\n__(Sincerely)__\n\n__USER_SIGNATURE__ PredefinedMailContentSendProposal=__(Hello)__\n\nVeuillez trouver, ci-joint, la proposition commerciale __PREF__\n\n\n__(Sincerely)__\n\n__USER_SIGNATURE__ PredefinedMailContentSendSupplierProposal=__(Hello)__\n\nVeuillez trouver, ci-joint, une demande de prix avec la référence __REF__\n\n\n__(Sincerely)__\n\n__USER_SIGNATURE__ PredefinedMailContentSendOrder=__(Hello)__\n\nVeuillez trouver, ci-joint, la commande __REF__\n\n\n__(Sincerely)__\n\n__USER_SIGNATURE__ diff --git a/htdocs/langs/fr_FR/products.lang b/htdocs/langs/fr_FR/products.lang index 3a94e1cc0c6..8f9d6b81c9c 100644 --- a/htdocs/langs/fr_FR/products.lang +++ b/htdocs/langs/fr_FR/products.lang @@ -122,6 +122,7 @@ ConfirmDeleteProductLine=Êtes-vous sûr de vouloir effacer cette ligne produit ProductSpecial=Special QtyMin=Quantité minimum PriceQtyMin=Prix quantité min. (sans remise) +PriceQtyMinCurrency=Prix quantité min. (sans remise) (devise) VATRateForSupplierProduct=Taux TVA (pour ce produit/fournisseur) DiscountQtyMin=Remise par défaut quantité min. NoPriceDefinedForThisSupplier=Aucun prix/qté défini pour ce fournisseur/produit diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index c1f218f15f8..9779b51f200 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -1525,6 +1525,7 @@ class Product extends CommonObject $sql = "SELECT pfp.rowid, pfp.price as price, pfp.quantity as quantity, pfp.remise_percent,"; $sql.= " pfp.fk_product, pfp.ref_fourn, pfp.fk_soc, pfp.tva_tx, pfp.fk_supplier_price_expression"; $sql.= " ,pfp.default_vat_code"; + $sql.= " ,pfp.multicurrency_price, pfp.multicurrency_unitprice, pfp.multicurrency_tx, pfp.fk_multicurrency, pfp.multicurrency_code"; $sql.= " FROM ".MAIN_DB_PREFIX."product_fournisseur_price as pfp"; $sql.= " WHERE pfp.rowid = ".$prodfournprice; if ($qty > 0) $sql.= " AND pfp.quantity <= ".$qty; @@ -1561,6 +1562,11 @@ class Product extends CommonObject $this->remise_percent = $obj->remise_percent; // remise percent if present and not typed $this->vatrate_supplier = $obj->tva_tx; // Vat ref supplier $this->default_vat_code = $obj->default_vat_code; // Vat code supplier + $this->fourn_multicurrency_price = $obj->multicurrency_price; + $this->fourn_multicurrency_unitprice = $obj->multicurrency_unitprice; + $this->fourn_multicurrency_tx = $obj->multicurrency_tx; + $this->fourn_multicurrency_id = $obj->fk_multicurrency; + $this->fourn_multicurrency_code = $obj->multicurrency_code; $result=$obj->fk_product; return $result; } @@ -1570,6 +1576,7 @@ class Product extends CommonObject $sql = "SELECT pfp.rowid, pfp.price as price, pfp.quantity as quantity, pfp.fk_soc,"; $sql.= " pfp.fk_product, pfp.ref_fourn as ref_supplier, pfp.tva_tx, pfp.fk_supplier_price_expression"; $sql.= " ,pfp.default_vat_code"; + $sql.= " ,pfp.multicurrency_price, pfp.multicurrency_unitprice, pfp.multicurrency_tx, pfp.fk_multicurrency, pfp.multicurrency_code"; $sql.= " FROM ".MAIN_DB_PREFIX."product_fournisseur_price as pfp"; $sql.= " WHERE pfp.fk_product = ".$product_id; if ($fourn_ref != 'none') $sql.= " AND pfp.ref_fourn = '".$fourn_ref."'"; @@ -1610,6 +1617,11 @@ class Product extends CommonObject $this->remise_percent = $obj->remise_percent; // remise percent if present and not typed $this->vatrate_supplier = $obj->tva_tx; // Vat ref supplier $this->default_vat_code = $obj->default_vat_code; // Vat code supplier + $this->fourn_multicurrency_price = $obj->multicurrency_price; + $this->fourn_multicurrency_unitprice = $obj->multicurrency_unitprice; + $this->fourn_multicurrency_tx = $obj->multicurrency_tx; + $this->fourn_multicurrency_id = $obj->fk_multicurrency; + $this->fourn_multicurrency_code = $obj->multicurrency_code; $result=$obj->fk_product; return $result; } diff --git a/htdocs/product/fournisseurs.php b/htdocs/product/fournisseurs.php index 4f266611940..a2f79e4c402 100644 --- a/htdocs/product/fournisseurs.php +++ b/htdocs/product/fournisseurs.php @@ -31,6 +31,7 @@ require '../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php'; require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.product.class.php'; require_once DOL_DOCUMENT_ROOT.'/product/dynamic_price/class/price_expression.class.php'; @@ -201,6 +202,23 @@ if (empty($reshook)) $_POST["price"] = 0; } } + if ($conf->multicurrency->enabled) { + if (empty($_POST["multicurrency_code"])) { + $error++; + $langs->load("errors"); + setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Currency")), null, 'errors'); + } + if ($_POST["multicurrency_tx"] <= 0 || $_POST["multicurrency_tx"] == '') { + $error++; + $langs->load("errors"); + setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("CurrencyRate")), null, 'errors'); + } + if ($_POST["multicurrency_price"] < 0 || $_POST["multicurrency_price"] == '') { + $error++; + $langs->load("errors"); + setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("PriceCurrency")), null, 'errors'); + } + } if (! $error) { @@ -232,7 +250,11 @@ if (empty($reshook)) if (isset($_POST['ref_fourn_price_id'])) $object->fetch_product_fournisseur_price($_POST['ref_fourn_price_id']); - $ret=$object->update_buyprice($quantity, $_POST["price"], $user, $_POST["price_base_type"], $supplier, $_POST["oselDispo"], $ref_fourn, $tva_tx, $_POST["charges"], $remise_percent, 0, $npr, $delivery_time_days, $supplier_reputation); + if ($conf->multicurrency->enabled) { + $ret = $object->update_buyprice($quantity, $_POST["price"], $user, $_POST["price_base_type"], $supplier, $_POST["oselDispo"], $ref_fourn, $tva_tx, $_POST["charges"], $remise_percent, 0, $npr, $delivery_time_days, $supplier_reputation, array(), '', $_POST["multicurrency_price"], $_POST["multicurrency_price_base_type"], $_POST["multicurrency_tx"], $_POST["multicurrency_code"]); + } else { + $ret = $object->update_buyprice($quantity, $_POST["price"], $user, $_POST["price_base_type"], $supplier, $_POST["oselDispo"], $ref_fourn, $tva_tx, $_POST["charges"], $remise_percent, 0, $npr, $delivery_time_days, $supplier_reputation); + } if ($ret < 0) { @@ -526,12 +548,101 @@ if ($id > 0 || $ref) '; } - // Price qty min - print '
'; - print ''; + if ($conf->multicurrency->enabled) { + // Currency + print ''; + print ''; + print ''; + + // Currency tx + print ''; + print ''; + print ''; + + // Currency price qty min + print ''; + $pricesupplierincurrencytouse=(GETPOST('multicurrency_price')?GETPOST('multicurrency_price'):(isset($object->fourn_multicurrency_price)?$object->fourn_multicurrency_price:'')); + print ''; + + // Price qty min + print ''; + print ''; + + $currencies = array(); + $sql = 'SELECT rowid FROM '.MAIN_DB_PREFIX.'multicurrency WHERE entity = '.$conf->entity; + $resql = $db->query($sql); + if ($resql) { + $currency = new MultiCurrency($db); + while ($obj = $db->fetch_object($resql)) { + $currency->fetch($obj->rowid); + $currencies[$currency->code] = $currency->rate->rate; + } + } + $currencies = json_encode($currencies); + + print << +SCRIPT; + } else { + // Price qty min + print ''; + print ''; + } + // Discount qty min print ''; @@ -634,7 +745,14 @@ if ($id > 0 || $ref) print_liste_field_titre("QtyMin",$_SERVER["PHP_SELF"],"pfp.quantity","",$param,'align="right"',$sortfield,$sortorder); print_liste_field_titre("VATRate",$_SERVER["PHP_SELF"],'','',$param,'align="right"',$sortfield,$sortorder); print_liste_field_titre("PriceQtyMinHT",$_SERVER["PHP_SELF"],'','',$param,'align="right"',$sortfield,$sortorder); - print_liste_field_titre("UnitPriceHT",$_SERVER["PHP_SELF"],"pfp.unitprice","",$param,'align="right"',$sortfield,$sortorder); + if ($conf->multicurrency->enabled) { + print_liste_field_titre("PriceQtyMinHTCurrency", $_SERVER["PHP_SELF"], '', '', $param, 'align="right"', $sortfield, $sortorder); + } + print_liste_field_titre("UnitPriceHT",$_SERVER["PHP_SELF"],"pfp.unitprice","",$param,'align="right"',$sortfield,$sortorder); + if ($conf->multicurrency->enabled) { + print_liste_field_titre("UnitPriceHTCurrency", $_SERVER["PHP_SELF"], "pfp.multicurrency_unitprice", "", $param, 'align="right"', $sortfield, $sortorder); + print_liste_field_titre("Currency", $_SERVER["PHP_SELF"], "", "", $param, 'align="right"', $sortfield, $sortorder); + } print_liste_field_titre("DiscountQtyMin",$_SERVER["PHP_SELF"],'','',$param,'align="right"',$sortfield,$sortorder); print_liste_field_titre("NbDaysToDelivery",$_SERVER["PHP_SELF"],"pfp.delivery_time_days","",$param,'align="right"',$sortfield,$sortorder); print_liste_field_titre("ReputationForThisProduct",$_SERVER["PHP_SELF"],"pfp.supplier_reputation","",$param,'align="center"',$sortfield,$sortorder); @@ -680,12 +798,31 @@ if ($id > 0 || $ref) print $productfourn->fourn_price?price($productfourn->fourn_price):""; print ''; + if ($conf->multicurrency->enabled) { + // Price for the quantity in currency + print ''; + } + // Unit price print ''; + if ($conf->multicurrency->enabled) { + // Unit price in currency + print ''; + + // Currency + print ''; + } + // Discount print ''; } // End date if (! empty($arrayfields['p.datee']['checked'])) { - print ''; } if (! empty($arrayfields['p.public']['checked'])) diff --git a/htdocs/projet/tasks/comment.php b/htdocs/projet/tasks/comment.php index fb553a1b837..cf6e29d5ef6 100644 --- a/htdocs/projet/tasks/comment.php +++ b/htdocs/projet/tasks/comment.php @@ -97,7 +97,12 @@ if ($id > 0 || ! empty($ref)) { if ($object->fetch($id,$ref) > 0) { - $res=$object->fetch_optionals(); + $result=$object->fetch_optionals(); + + $result=$object->fetchComments(); + if ($result<0){ + setEventMessages($object->error,$object->errors,'errors'); + } $result=$projectstatic->fetch($object->fk_project); if (! empty($projectstatic->socid)) $projectstatic->fetch_thirdparty(); diff --git a/htdocs/projet/tasks/contact.php b/htdocs/projet/tasks/contact.php index a2bb784c062..a2db82fc0ed 100644 --- a/htdocs/projet/tasks/contact.php +++ b/htdocs/projet/tasks/contact.php @@ -285,7 +285,7 @@ if ($id > 0 || ! empty($ref)) //$arrayofuseridoftask=$object->getListContactId('internal'); $head = task_prepare_head($object); - dol_fiche_head($head, 'task_contact', $langs->trans("Task"), -1, 'projecttask'); + dol_fiche_head($head, 'task_contact', $langs->trans("Task"), -1, 'projecttask', 0, '', 'reposition'); $param=(GETPOST('withproject')?'&withproject=1':''); diff --git a/htdocs/projet/tasks/document.php b/htdocs/projet/tasks/document.php index 7fc0b981902..1cb5acb73b5 100644 --- a/htdocs/projet/tasks/document.php +++ b/htdocs/projet/tasks/document.php @@ -224,7 +224,7 @@ if ($object->id > 0) } $head = task_prepare_head($object); - dol_fiche_head($head, 'task_document', $langs->trans("Task"), -1, 'projecttask'); + dol_fiche_head($head, 'task_document', $langs->trans("Task"), -1, 'projecttask', 0, '', 'reposition'); // Files list constructor $filearray=dol_dir_list($upload_dir,"files",0,'','(\.meta|_preview.*\.png)$',$sortfield,(strtolower($sortorder)=='desc'?SORT_DESC:SORT_ASC),1); diff --git a/htdocs/projet/tasks/note.php b/htdocs/projet/tasks/note.php index da33b8b7607..f915aaf836a 100644 --- a/htdocs/projet/tasks/note.php +++ b/htdocs/projet/tasks/note.php @@ -202,7 +202,7 @@ if ($object->id > 0) } $head = task_prepare_head($object); - dol_fiche_head($head, 'task_notes', $langs->trans('Task'), -1, 'projecttask'); + dol_fiche_head($head, 'task_notes', $langs->trans('Task'), -1, 'projecttask', 0, '', 'reposition'); $param=(GETPOST('withproject')?'&withproject=1':''); diff --git a/htdocs/projet/tasks/task.php b/htdocs/projet/tasks/task.php index b70c09cb2bd..10f64869257 100644 --- a/htdocs/projet/tasks/task.php +++ b/htdocs/projet/tasks/task.php @@ -221,7 +221,7 @@ if ($id > 0 || ! empty($ref)) // Tabs for project $tab='tasks'; $head=project_prepare_head($projectstatic); - dol_fiche_head($head, $tab, $langs->trans("Project"), -1, ($projectstatic->public?'projectpub':'project')); + dol_fiche_head($head, $tab, $langs->trans("Project"), -1, ($projectstatic->public?'projectpub':'project'), 0, '', ''); $param=($mode=='mine'?'&mode=mine':''); @@ -352,7 +352,7 @@ if ($id > 0 || ! empty($ref)) print ''; print ''; - dol_fiche_head($head, 'task_task', $langs->trans("Task"),0,'projecttask'); + dol_fiche_head($head, 'task_task', $langs->trans("Task"), 0, 'projecttask', 0, '', ''); print '
'; } if (! empty($head['text'])) { diff --git a/htdocs/core/class/comment.class.php b/htdocs/core/class/comment.class.php index a21057662f2..9aeebd575bf 100644 --- a/htdocs/core/class/comment.class.php +++ b/htdocs/core/class/comment.class.php @@ -7,20 +7,22 @@ class Comment extends CommonObject public $element='comment'; //!< Id that identify managed objects public $table_element='comment'; //!< Name of table without prefix where object is stored - var $fk_element; - var $element_type; + public $fk_element; + public $element_type; - var $description; + public $description; - var $tms; + public $tms; - var $datec; + public $datec; - var $fk_user_author; + public $fk_user_author; - var $entity; + public $entity; - var $import_key; + public $import_key; + + public $comments = array(); public $oldcopy; @@ -289,10 +291,10 @@ class Comment extends CommonObject * @param int $fk_element Id of element * @return array Comment array */ - public static function fetchAllFor($element_type, $fk_element) + public function fetchAllFor($element_type, $fk_element) { global $db,$conf; - $TComments = array(); + $this->comments = array(); if(!empty($element_type) && !empty($fk_element)) { $sql = "SELECT"; $sql.= " c.rowid"; @@ -302,7 +304,7 @@ class Comment extends CommonObject $sql.= " AND c.entity = ".$conf->entity; $sql.= " ORDER BY c.tms DESC"; - dol_syslog("Comment::fetchAllFor", LOG_DEBUG); + dol_syslog(get_class($this).'::'.__METHOD__, LOG_DEBUG); $resql=$db->query($sql); if ($resql) { @@ -313,12 +315,17 @@ class Comment extends CommonObject { $comment = new self($db); $comment->fetch($obj->rowid); - $TComments[] = $comment; + $this->comments[] = $comment; } } $db->free($resql); + } else { + $error++; $this->errors[]="Error ".$this->db->lasterror(); + return -1; } + } - return $TComments; + + return count($this->comments); } } \ No newline at end of file diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 7e565e0222f..8abac10fc11 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -6678,8 +6678,14 @@ abstract class CommonObject require_once DOL_DOCUMENT_ROOT.'/core/class/comment.class.php'; $comment = new Comment($this->db); - $this->comments = Comment::fetchAllFor($this->element, $this->id); - return 1; + $result=$comment->fetchAllFor($this->element, $this->id); + if ($result<0) { + $this->errors=array_merge($this->errors,$comment->errors); + return -1; + } else { + $this->comments = $comment->comments; + } + return count($this->comments); } /** diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 7b74fc05850..61d21cec7e8 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -3100,7 +3100,7 @@ class Form * @param string $morecss Add more CSS on select tag * @return void */ - function select_types_paiements($selected='', $htmlname='paiementtype', $filtertype='', $format=0, $empty=0, $noadmininfo=0, $maxlength=0, $active=1, $morecss='') + function select_types_paiements($selected='', $htmlname='paiementtype', $filtertype='', $format=0, $empty=1, $noadmininfo=0, $maxlength=0, $active=1, $morecss='') { global $langs,$user; diff --git a/htdocs/core/class/html.formcompany.class.php b/htdocs/core/class/html.formcompany.class.php index d3990acc9c8..faa548a5d16 100644 --- a/htdocs/core/class/html.formcompany.class.php +++ b/htdocs/core/class/html.formcompany.class.php @@ -545,9 +545,10 @@ class FormCompany * @param array $limitto Disable answers that are not id in this array list * @param int $forceid This is to force another object id than object->id * @param string $moreparam String with more param to add into url when noajax search is used. + * @param string $morecss More CSS on select component * @return int The selected third party ID */ - function selectCompaniesForNewContact($object, $var_id, $selected='', $htmlname='newcompany', $limitto='', $forceid=0, $moreparam='') + function selectCompaniesForNewContact($object, $var_id, $selected='', $htmlname='newcompany', $limitto='', $forceid=0, $moreparam='', $morecss='') { global $conf, $langs; @@ -649,7 +650,7 @@ class FormCompany $resql = $this->db->query($sql); if ($resql) { - print ''; $desc = GETPOST('comment_description'); -$doleditor = new DolEditor('comment_description', $desc, '', 80, 'dolibarr_notes', 'In', 0, false, true, ROWS_3, '100%'); +$doleditor = new DolEditor('comment_description', $desc, '', 80, 'dolibarr_notes', 'In', 0, true, true, ROWS_3, '100%'); print $doleditor->Create(1); print ' '; - $form->select_types_paiements($search_paymentmode, 'search_paymentmode', '', 0, 0, 1, 10); + $form->select_types_paiements($search_paymentmode, 'search_paymentmode', '', 0, 1, 1, 10); print '
'.$langs->trans("PriceQtyMin").''; - print ' '; - print $form->selectPriceBaseType((GETPOST('price_base_type')?GETPOST('price_base_type'):'HT'), "price_base_type"); // We keep 'HT' here, price_base_type is not yet supported for supplier prices - print '
'.$langs->trans("Currency").''; + $currencycodetouse = GETPOST('multicurrency_code')?GETPOST('multicurrency_code'):(isset($object->fourn_multicurrency_code)?$object->fourn_multicurrency_code:''); + if (empty($currencycodetouse) && $object->fourn_multicurrency_tx == 1) $currencycodetouse=$conf->currency; + print $form->selectMultiCurrency($currencycodetouse, "multicurrency_code", 1); + print '
'.$langs->trans("CurrencyRate").''; + print '
'.$langs->trans("PriceQtyMinCurrency").''; + print ' '; + print $form->selectPriceBaseType((GETPOST('multicurrency_price_base_type')?GETPOST('multicurrency_price_base_type'):'HT'), "multicurrency_price_base_type"); // We keep 'HT' here, multicurrency_price_base_type is not yet supported for supplier prices + print '
' . $langs->trans("PriceQtyMin") . ''; + print ''; + print ''; + print ' '; + print $form->selectPriceBaseType('', "disabled_price_base_type"); + print '
' . $langs->trans("PriceQtyMin") . ''; + print ' '; + print $form->selectPriceBaseType((GETPOST('price_base_type') ? GETPOST('price_base_type') : 'HT'), "price_base_type"); // We keep 'HT' here, price_base_type is not yet supported for supplier prices + print '
'.$langs->trans("DiscountQtyMin").''; + print $productfourn->fourn_multicurrency_price ? price($productfourn->fourn_multicurrency_price) : ""; + print ''; print price($productfourn->fourn_unitprice); //print $objp->unitprice? price($objp->unitprice) : ($objp->quantity?price($objp->price/$objp->quantity):" "); print ''; + print price($productfourn->fourn_multicurrency_unitprice); + print ''; + print $productfourn->fourn_multicurrency_code ? currency_name($productfourn->fourn_multicurrency_code) : ''; + print ''; print price2num($productfourn->fourn_remise_percent).'%'; @@ -710,7 +847,7 @@ if ($id > 0 || $ref) } // Modify-Remove - print ''; + print ''; if ($user->rights->produit->creer || $user->rights->service->creer) { print ''.img_edit().""; diff --git a/htdocs/projet/class/task.class.php b/htdocs/projet/class/task.class.php index eeacf27aaec..28b3c9b12f3 100644 --- a/htdocs/projet/class/task.class.php +++ b/htdocs/projet/class/task.class.php @@ -1696,7 +1696,7 @@ class Task extends CommonObject */ function getLibStatut($mode=0) { - return $this->LibStatut($this->fk_statut,$mode); + return $this->LibStatut($this->fk_statut, $mode); } /** @@ -1706,18 +1706,18 @@ class Task extends CommonObject * @param integer $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto * @return string Label */ - function LibStatut($statut,$mode=0) + function LibStatut($statut, $mode=0) { // list of Statut of the task $this->statuts[0]='Draft'; - $this->statuts[1]='Validated'; + $this->statuts[1]='ToDo'; $this->statuts[2]='Running'; $this->statuts[3]='Finish'; $this->statuts[4]='Transfered'; $this->statuts_short[0]='Draft'; - $this->statuts_short[1]='Validated'; + $this->statuts_short[1]='ToDo'; $this->statuts_short[2]='Running'; - $this->statuts_short[3]='Finish'; + $this->statuts_short[3]='Completed'; $this->statuts_short[4]='Transfered'; global $langs; @@ -1735,7 +1735,7 @@ class Task extends CommonObject if ($statut==0) return img_picto($langs->trans($this->statuts_short[$statut]),'statut0').' '.$langs->trans($this->statuts_short[$statut]); if ($statut==1) return img_picto($langs->trans($this->statuts_short[$statut]),'statut1').' '.$langs->trans($this->statuts_short[$statut]); if ($statut==2) return img_picto($langs->trans($this->statuts_short[$statut]),'statut3').' '.$langs->trans($this->statuts_short[$statut]); - if ($statut==3) return img_picto($langs->trans($this->statuts_short[$statut]),'statut4').' '.$langs->trans($this->statuts_short[$statut]); + if ($statut==3) return img_picto($langs->trans($this->statuts_short[$statut]),'statut6').' '.$langs->trans($this->statuts_short[$statut]); if ($statut==4) return img_picto($langs->trans($this->statuts_short[$statut]),'statut6').' '.$langs->trans($this->statuts_short[$statut]); if ($statut==5) return img_picto($langs->trans($this->statuts_short[$statut]),'statut5').' '.$langs->trans($this->statuts_short[$statut]); } @@ -1744,7 +1744,7 @@ class Task extends CommonObject if ($statut==0) return img_picto($langs->trans($this->statuts_short[$statut]),'statut0'); if ($statut==1) return img_picto($langs->trans($this->statuts_short[$statut]),'statut1'); if ($statut==2) return img_picto($langs->trans($this->statuts_short[$statut]),'statut3'); - if ($statut==3) return img_picto($langs->trans($this->statuts_short[$statut]),'statut4'); + if ($statut==3) return img_picto($langs->trans($this->statuts_short[$statut]),'statut6'); if ($statut==4) return img_picto($langs->trans($this->statuts_short[$statut]),'statut6'); if ($statut==5) return img_picto($langs->trans($this->statuts_short[$statut]),'statut5'); } @@ -1753,27 +1753,31 @@ class Task extends CommonObject if ($statut==0) return img_picto($langs->trans($this->statuts_short[$statut]),'statut0').' '.$langs->trans($this->statuts[$statut]); if ($statut==1) return img_picto($langs->trans($this->statuts_short[$statut]),'statut1').' '.$langs->trans($this->statuts[$statut]); if ($statut==2) return img_picto($langs->trans($this->statuts_short[$statut]),'statut3').' '.$langs->trans($this->statuts[$statut]); - if ($statut==3) return img_picto($langs->trans($this->statuts_short[$statut]),'statut4').' '.$langs->trans($this->statuts[$statut]); + if ($statut==3) return img_picto($langs->trans($this->statuts_short[$statut]),'statut6').' '.$langs->trans($this->statuts[$statut]); if ($statut==4) return img_picto($langs->trans($this->statuts_short[$statut]),'statut6').' '.$langs->trans($this->statuts[$statut]); if ($statut==5) return img_picto($langs->trans($this->statuts_short[$statut]),'statut5').' '.$langs->trans($this->statuts[$statut]); } if ($mode == 5) - { - if ($statut==0) return $langs->trans($this->statuts_short[$statut]).' '.img_picto($langs->trans($this->statuts_short[$statut]),'statut0'); - if ($statut==1) return $langs->trans($this->statuts_short[$statut]).' '.img_picto($langs->trans($this->statuts_short[$statut]),'statut1'); - if ($statut==2) return $langs->trans($this->statuts_short[$statut]).' '.img_picto($langs->trans($this->statuts_short[$statut]),'statut3'); - if ($statut==3) return $langs->trans($this->statuts_short[$statut]).' '.img_picto($langs->trans($this->statuts_short[$statut]),'statut4'); - if ($statut==4) return $langs->trans($this->statuts_short[$statut]).' '.img_picto($langs->trans($this->statuts_short[$statut]),'statut6'); - if ($statut==5) return $langs->trans($this->statuts_short[$statut]).' '.img_picto($langs->trans($this->statuts_short[$statut]),'statut5'); - } - if ($mode == 6) { /*if ($statut==0) return $langs->trans($this->statuts_short[$statut]).' '.img_picto($langs->trans($this->statuts_short[$statut]),'statut0'); if ($statut==1) return $langs->trans($this->statuts_short[$statut]).' '.img_picto($langs->trans($this->statuts_short[$statut]),'statut1'); if ($statut==2) return $langs->trans($this->statuts_short[$statut]).' '.img_picto($langs->trans($this->statuts_short[$statut]),'statut3'); - if ($statut==3) return $langs->trans($this->statuts_short[$statut]).' '.img_picto($langs->trans($this->statuts_short[$statut]),'statut4'); + if ($statut==3) return $langs->trans($this->statuts_short[$statut]).' '.img_picto($langs->trans($this->statuts_short[$statut]),'statut6'); if ($statut==4) return $langs->trans($this->statuts_short[$statut]).' '.img_picto($langs->trans($this->statuts_short[$statut]),'statut6'); - if ($statut==5) return $langs->trans($this->statuts_short[$statut]).' '.img_picto($langs->trans($this->statuts_short[$statut]),'statut5');*/ + if ($statut==5) return $langs->trans($this->statuts_short[$statut]).' '.img_picto($langs->trans($this->statuts_short[$statut]),'statut5'); + */ + //return $this->progress.' %'; + return ' '; + } + if ($mode == 6) + { + /*if ($statut==0) return $langs->trans($this->statuts[$statut]).' '.img_picto($langs->trans($this->statuts_short[$statut]),'statut0'); + if ($statut==1) return $langs->trans($this->statuts[$statut]).' '.img_picto($langs->trans($this->statuts_short[$statut]),'statut1'); + if ($statut==2) return $langs->trans($this->statuts[$statut]).' '.img_picto($langs->trans($this->statuts_short[$statut]),'statut3'); + if ($statut==3) return $langs->trans($this->statuts[$statut]).' '.img_picto($langs->trans($this->statuts_short[$statut]),'statut6'); + if ($statut==4) return $langs->trans($this->statuts[$statut]).' '.img_picto($langs->trans($this->statuts_short[$statut]),'statut6'); + if ($statut==5) return $langs->trans($this->statuts[$statut]).' '.img_picto($langs->trans($this->statuts_short[$statut]),'statut5'); + */ //return $this->progress.' %'; return ' '; } diff --git a/htdocs/projet/list.php b/htdocs/projet/list.php index 6b3613a7b0a..e148caeb328 100644 --- a/htdocs/projet/list.php +++ b/htdocs/projet/list.php @@ -508,19 +508,19 @@ if (! empty($arrayfields['commercial']['checked'])) // Start date if (! empty($arrayfields['p.dateo']['checked'])) { - print ''; - if (! empty($conf->global->MAIN_LIST_FILTER_ON_DAY)) print ''; - print ''; - $formother->select_year($search_syear?$search_syear:-1,'search_syear',1, 20, 5); + print ''; + if (! empty($conf->global->MAIN_LIST_FILTER_ON_DAY)) print ''; + print ''; + $formother->select_year($search_syear?$search_syear:-1,'search_syear',1, 20, 5, 0, 0, '', 'widthauto valignmiddle'); print ''; - if (! empty($conf->global->MAIN_LIST_FILTER_ON_DAY)) print ''; - print ''; - $formother->select_year($search_eyear?$search_eyear:-1,'search_eyear',1, 20, 5); + print ''; + if (! empty($conf->global->MAIN_LIST_FILTER_ON_DAY)) print ''; + print ''; + $formother->select_year($search_eyear?$search_eyear:-1,'search_eyear',1, 20, 5, 0, 0, '', 'widthauto valignmiddle'); print '
'; @@ -437,7 +437,7 @@ if ($id > 0 || ! empty($ref)) $param=($withproject?'&withproject=1':''); $linkback=$withproject?''.$langs->trans("BackToList").'':''; - dol_fiche_head($head, 'task_task', $langs->trans("Task"), -1, 'projecttask'); + dol_fiche_head($head, 'task_task', $langs->trans("Task"), -1, 'projecttask', 0, '', 'reposition'); if ($action == 'delete') { diff --git a/htdocs/projet/tasks/time.php b/htdocs/projet/tasks/time.php index 174da003e14..5f826baf03e 100644 --- a/htdocs/projet/tasks/time.php +++ b/htdocs/projet/tasks/time.php @@ -436,7 +436,7 @@ if (($id > 0 || ! empty($ref)) || $projectidforalltimes > 0) if (empty($projectidforalltimes)) { $head=task_prepare_head($object); - dol_fiche_head($head, 'task_time', $langs->trans("Task"), -1, 'projecttask'); + dol_fiche_head($head, 'task_time', $langs->trans("Task"), -1, 'projecttask', 0, '', 'reposition'); if ($action == 'deleteline') { @@ -547,6 +547,7 @@ if (($id > 0 || ! empty($ref)) || $projectidforalltimes > 0) print ''; print ''; + print '
'; print '
'; print ''; @@ -603,7 +604,10 @@ if (($id > 0 || ! empty($ref)) || $projectidforalltimes > 0) print ''; print ''; - print '
'; + print '
'; + print '
'; + + print ''; print '
'; } diff --git a/htdocs/public/payment/newpayment.php b/htdocs/public/payment/newpayment.php index 37873033535..f7ceb201da5 100644 --- a/htdocs/public/payment/newpayment.php +++ b/htdocs/public/payment/newpayment.php @@ -542,7 +542,7 @@ if (! empty($conf->paypal->enabled) && (! empty($conf->global->PAYPAL_API_SANDBO { dol_htmloutput_mesg($langs->trans('YouAreCurrentlyInSandboxMode','Paypal'),'','warning'); } -if (! empty($conf->stripe->enabled) && (empty($conf->global->STRIPE_LIVE) || GETPOST('forcesandbox','alpha'))) +if (! empty($conf->stripe->enabled) && (empty($conf->global->STRIPE_LIVE) || empty($conf->global->STRIPECONNECT_LIVE) || GETPOST('forcesandbox','alpha'))) { dol_htmloutput_mesg($langs->trans('YouAreCurrentlyInSandboxMode','Stripe'),'','warning'); } @@ -1554,3 +1554,4 @@ htmlPrintOnlinePaymentFooter($mysoc,$langs,1,$suffix,$object); llxFooter('', 'public'); $db->close(); + diff --git a/htdocs/societe/paymentmodes.php b/htdocs/societe/paymentmodes.php new file mode 100644 index 00000000000..33db57b2ac4 --- /dev/null +++ b/htdocs/societe/paymentmodes.php @@ -0,0 +1,1005 @@ + + * Copyright (C) 2003 Jean-Louis Bergamo + * Copyright (C) 2004-2016 Laurent Destailleur + * Copyright (C) 2005-2009 Regis Houssin + * Copyright (C) 2013 Peter Fontaine + * Copyright (C) 2015-2016 Marcos García + * Copyright (C) 2017 Ferran Marcet + * + * 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/societe/rib.php + * \ingroup societe + * \brief BAN tab for companies + */ + +require '../main.inc.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/bank.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; +require_once DOL_DOCUMENT_ROOT.'/societe/class/companybankaccount.class.php'; +require_once DOL_DOCUMENT_ROOT.'/compta/prelevement/class/bonprelevement.class.php'; +//require_once DOL_DOCUMENT_ROOT.'/stripe/class/stripe.class.php'; + +$langs->load("companies"); +$langs->load("commercial"); +$langs->load("banks"); +$langs->load("bills"); + +// Security check +$socid = GETPOST("socid","int"); +if ($user->societe_id) $socid=$user->societe_id; +$result = restrictedArea($user, 'societe','',''); + +$id=GETPOST("id","int"); +$source=GETPOST("source","alpha"); +$ribid=GETPOST("ribid","int"); +$action=GETPOST("action", 'alpha', 3); + +$object = new Societe($db); +$object->fetch($socid); + +$account = new CompanyBankAccount($db); +$prelevement = new BonPrelevement($db); + +$extrafields = new ExtraFields($db); + +// fetch optionals attributes and labels +$extralabels=$extrafields->fetch_name_optionals_label($object->table_element); + +// Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context +$hookmanager->initHooks(array('thirdpartybancard','globalcard')); + + +// Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context +$hookmanager->initHooks(array('thirdpartybancard')); + + + +/* + * Actions + */ + +$parameters=array('id'=>$socid, 'objcanvas'=>$objcanvas); +$reshook=$hookmanager->executeHooks('doActions',$parameters,$object,$action); // Note that $action and $object may have been modified by some hooks +if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + +if (empty($reshook)) +{ + if ($cancel) + { + $action=''; + if (! empty($backtopage)) + { + header("Location: ".$backtopage); + exit; + } + } + + + if ($action == 'update' && ! $_POST["cancel"]) + { + // Modification + if (! GETPOST('label')) + { + setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Label")), null, 'errors'); + $action='edit'; + $error++; + } + if (! GETPOST('bank')) + { + setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("BankName")), null, 'errors'); + $action='edit'; + $error++; + } + if ($account->needIBAN() == 1) + { + if (! GETPOST('iban')) + { + setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("IBAN")), null, 'errors'); + $action='edit'; + $error++; + } + if (! GETPOST('bic')) + { + setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("BIC")), null, 'errors'); + $action='edit'; + $error++; + } + } + + $account->fetch($id); + if (! $error) + { + $account->socid = $object->id; + + $account->bank = GETPOST('bank','alpha'); + $account->label = GETPOST('label','alpha'); + $account->courant = GETPOST('courant','alpha'); + $account->clos = GETPOST('clos','alpha'); + $account->code_banque = GETPOST('code_banque','alpha'); + $account->code_guichet = GETPOST('code_guichet','alpha'); + $account->number = GETPOST('number','alpha'); + $account->cle_rib = GETPOST('cle_rib','alpha'); + $account->bic = GETPOST('bic','alpha'); + $account->iban = GETPOST('iban','alpha'); + $account->domiciliation = GETPOST('domiciliation','alpha'); + $account->proprio = GETPOST('proprio','alpha'); + $account->owner_address = GETPOST('owner_address','alpha'); + $account->frstrecur = GETPOST('frstrecur','alpha'); + $account->rum = GETPOST('rum','alpha'); + if (empty($account->rum)) + { + $account->rum = $prelevement->buildRumNumber($object->code_client, $account->datec, $account->id); + $account->date_rum = dol_now(); + } + + $result = $account->update($user); + if (! $result) + { + setEventMessages($account->error, $account->errors, 'errors'); + } + else + { + // If this account is the default bank account, we disable others + if ($account->default_rib) + { + $account->setAsDefault($id); // This will make sure there is only one default rib + } + + $url=DOL_URL_ROOT.'/societe/rib.php?socid='.$object->id; + header('Location: '.$url); + exit; + } + } + } + + if ($action == 'add' && ! $_POST["cancel"]) + { + $error=0; + + if (! GETPOST('label')) + { + setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Label")), null, 'errors'); + $action='create'; + $error++; + } + if (! GETPOST('bank')) + { + setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("BankName")), null, 'errors'); + $action='create'; + $error++; + } + + if (! $error) + { + // Ajout + $account = new CompanyBankAccount($db); + + $account->socid = $object->id; + + $account->bank = GETPOST('bank','alpha'); + $account->label = GETPOST('label','alpha'); + $account->courant = GETPOST('courant','alpha'); + $account->clos = GETPOST('clos','alpha'); + $account->code_banque = GETPOST('code_banque','alpha'); + $account->code_guichet = GETPOST('code_guichet','alpha'); + $account->number = GETPOST('number','alpha'); + $account->cle_rib = GETPOST('cle_rib','alpha'); + $account->bic = GETPOST('bic','alpha'); + $account->iban = GETPOST('iban','alpha'); + $account->domiciliation = GETPOST('domiciliation','alpha'); + $account->proprio = GETPOST('proprio','alpha'); + $account->owner_address = GETPOST('owner_address','alpha'); + $account->frstrecur = GETPOST('frstrecur'); + $account->rum = GETPOST('rum','alpha'); + $account->datec = dol_now(); + + $db->begin(); + + // This test can be done only once properties were set + if ($account->needIBAN() == 1) + { + if (! GETPOST('iban')) + { + setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("IBAN")), null, 'errors'); + $action='create'; + $error++; + } + if (! GETPOST('bic')) + { + setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("BIC")), null, 'errors'); + $action='create'; + $error++; + } + } + + if (! $error) + { + $result = $account->create($user); + if ($result < 0) + { + $error++; + setEventMessages($account->error, $account->errors, 'errors'); + $action='create'; // Force chargement page création + } + + if (empty($account->rum)) + { + $account->rum = $prelevement->buildRumNumber($object->code_client, $account->datec, $account->id); + $account->date_rum = dol_now(); + } + } + + if (! $error) + { + $result = $account->update($user); // This will set the UMR number. + if ($result < 0) + { + $error++; + setEventMessages($account->error, $account->errors, 'errors'); + $action='create'; + } + } + + if (! $error) + { + $db->commit(); + + $url=DOL_URL_ROOT.'/societe/rib.php?socid='.$object->id; + header('Location: '.$url); + exit; + } + else + { + $db->rollback(); + } + } + } + + if ($action == 'setasdefault') + { + $account = new CompanyBankAccount($db); + $res = $account->setAsDefault(GETPOST('ribid','int')); + if ($res) + { + $url=DOL_URL_ROOT.'/societe/gateway.php?socid='.$object->id; + header('Location: '.$url); + exit; + } + else + { + setEventMessages($db->lasterror, null, 'errors'); + } + } + + if ($action == 'confirm_delete' && $_GET['confirm'] == 'yes') + { + $account = new CompanyBankAccount($db); + if ($account->fetch($ribid?$ribid:$id)) + { + $result = $account->delete($user); + if ($result > 0) + { + $url = $_SERVER['PHP_SELF']."?socid=".$object->id; + header('Location: '.$url); + exit; + } + else + { + setEventMessages($account->error, $account->errors, 'errors'); + } + } + else + { + setEventMessages($account->error, $account->errors, 'errors'); + } + } + + $savid=$id; + + // Actions to build doc + if ($action == 'builddocrib') + { + $action = 'builddoc'; + $moreparams = array( + 'use_companybankid'=>GETPOST('companybankid'), + 'force_dir_output'=>$conf->societe->multidir_output[$object->entity].'/'.dol_sanitizeFileName($object->id) + ); + $_POST['lang_id'] = GETPOST('lang_idrib'.GETPOST('companybankid')); + $_POST['model'] = GETPOST('modelrib'.GETPOST('companybankid')); + } + $id = $socid; + $upload_dir = $conf->societe->multidir_output[$object->entity]; + $permissioncreate=$user->rights->societe->creer; + include DOL_DOCUMENT_ROOT.'/core/actions_builddoc.inc.php'; + + $id = $savid; +} + +if (class_exists('StripeConnexion')) +{ + $stripeconnect=new StripeConnexion($db); + $customerstripe=$stripeconnect->CustomerStripe($socid,$stripeconnect->GetStripeAccount($conf->entity)); + if ($customerstripe->id) { + $cu = \Stripe\Customer::retrieve("".$customerstripe->id."",array("stripe_account" => $stripeconnect->GetStripeAccount($conf->entity)));} + $url=DOL_URL_ROOT.'/societe/gateway.php?socid='.$object->id; + if ($action == 'setasdefault') + { + $cu->default_source = "$source"; // obtained with Stripe.js + $cu->save(); + + header('Location: '.$url); + exit; + } + elseif ($action == 'delete') + { + $cu->sources->retrieve("$source")->delete(); + + header('Location: '.$url); + exit; + } +} + + +/* + * View + */ + +$form = new Form($db); +$formfile = new FormFile($db); + +llxHeader(); + +$head=societe_prepare_head($object); +if (! $id) +{ + $account->fetch(0,$object->id); +} +else +{ + $account->fetch($id); +} +if (empty($account->socid)) $account->socid=$object->id; + +if ($socid && $action == 'edit' && $user->rights->societe->creer) +{ + print '
'; + print ''; + print ''; + print ''; +} +if ($socid && $action == 'create' && $user->rights->societe->creer) +{ + print ''; + print ''; + print ''; +} + + +// View +if ($socid && $action != 'edit' && $action != "create") +{ + dol_fiche_head($head, 'rib', $langs->trans("ThirdParty"), -1, 'company'); + + // Confirm delete third party + if ($action == 'delete') + { + print $form->formconfirm($_SERVER["PHP_SELF"]."?socid=".$object->id."&ribid=".($ribid?$ribid:$id), $langs->trans("DeleteARib"), $langs->trans("ConfirmDeleteRib", $account->getRibLabel()), "confirm_delete", '', 0, 1); + } + + $linkback = ''.$langs->trans("BackToList").''; + + dol_banner_tab($object, 'socid', $linkback, ($user->societe_id?0:1), 'rowid', 'nom'); + + + if (! (empty($conf->stripe->enabled))) + { + print load_fiche_titre($langs->trans('StripeGateways'), '', ''); + + if (is_object($stripeconnect) && $stripeconnect->GetStripeAccount($conf->entity)) + { + $customerstripe=$stripeconnect->CustomerStripe($object->id,$stripeconnect->GetStripeAccount($conf->entity)); + } + + if ($customerstripe->id) { + $input=$customerstripe->sources->data; + } + + print ''."\n"; + print ''; + print ''; + print ''; + print ''; + print ''; + print "\n"; + + if (is_array($input)) + { + foreach ($input as $src) + { + print ''; + print ''; + // Default + print ''; + print ''; + } + } + if (empty($input)) + { + print ''; + } + print "
'.$langs->trans('Type').''.$langs->trans('Informations').''.$langs->trans('Default').'
'; + if ($src->object=='card') + { + if ($src->brand == 'Visa') {$brand='cc-visa';} + elseif ($src->brand == 'MasterCard') {$brand='cc-mastercard';} + elseif ($src->brand == 'American Express') {$brand='cc-amex';} + elseif ($src->brand == 'Discover') {$brand='cc-discover';} + elseif ($src->brand == 'JCB') {$brand='cc-jcb';} + elseif ($src->brand == 'Diners Club') {$brand='cc-diners-club';} + else {$brand='credit-card';} + print ''; + } + elseif ($src->object=='source' && $src->type=='card') + { + if ($src->card->brand == 'Visa') {$brand='cc-visa';} + elseif ($src->card->brand == 'MasterCard') {$brand='cc-mastercard';} + elseif ($src->card->brand == 'American Express') {$brand='cc-amex';} + elseif ($src->card->brand == 'Discover') {$brand='cc-discover';} + elseif ($src->card->brand == 'JCB') {$brand='cc-jcb';} + elseif ($src->card->brand == 'Diners Club') {$brand='cc-diners-club';} + else {$brand='credit-card';} + print ''; + } + elseif ($src->object=='source' && $src->type=='sepa_debit') + { + print ''; + } + + print''; + if ($src->object=='card') + { + print '**** '.$src->last4.' - '.$src->exp_month.'/'.$src->exp_year.''; + print ''; + if ($src->country) + { + $img=picto_from_langcode($src->country); + print $img?$img.' ':''; + print getCountry($src->country,1); + } + else print img_warning().' '.$langs->trans("ErrorFieldRequired",$langs->transnoentitiesnoconv("CompanyCountry")).''; + } + elseif ($src->object=='source' && $src->type=='card') + { + print $src->owner->name.'
**** '.$src->card->last4.' - '.$src->card->exp_month.'/'.$src->card->exp_year.''; + print '
'; + + if ($src->card->country) + { + $img=picto_from_langcode($src->card->country); + print $img?$img.' ':''; + print getCountry($src->card->country,1); + } + else print img_warning().' '.$langs->trans("ErrorFieldRequired",$langs->transnoentitiesnoconv("CompanyCountry")).''; + } + elseif ($src->object=='source' && $src->type=='sepa_debit') + { + print 'info sepa'; + print ''; + if ($src->sepa_debit->country) + { + $img=picto_from_langcode($src->sepa_debit->country); + print $img?$img.' ':''; + print getCountry($src->sepa_debit->country,1); + } + else print img_warning().' '.$langs->trans("ErrorFieldRequired",$langs->transnoentitiesnoconv("CompanyCountry")).''; + } + print ''; + if (($cu->default_source!=$src->id)) + { + print ''; + print ""; + print ''; + } else { + print ""; + } + print ''; + if ($user->rights->societe->creer) + { + // print ''; + // print img_picto($langs->trans("Modify"),'edit'); + // print ''; + // print ' '; + print ''; + print ""; + print ''; + } + print '
'.$langs->trans("NoSource").'
"; + } + + + // List of bank accounts + + $morehtmlright=''.$langs->trans("Add").''; + + print load_fiche_titre($langs->trans("AllRIB"), $morehtmlright, ''); + + $rib_list = $object->get_all_rib(); + $var = false; + if (is_array($rib_list)) + { + print '
'; // You can use div-table-responsive-no-min if you dont need reserved height for your table + print ''; + + print ''; + print_liste_field_titre("LabelRIB"); + print_liste_field_titre("Bank"); + print_liste_field_titre("RIB"); + print_liste_field_titre("IBAN"); + print_liste_field_titre("BIC"); + if (! empty($conf->prelevement->enabled)) + { + print print_liste_field_titre("RUM"); + print print_liste_field_titre("WithdrawMode"); + } + print_liste_field_titre("DefaultRIB", '', '', '', '', 'align="center"'); + print_liste_field_titre('', '', '', '', '', 'align="center"'); + print_liste_field_titre('',$_SERVER["PHP_SELF"],"",'','','',$sortfield,$sortorder,'maxwidthsearch '); + print "\n"; + + foreach ($rib_list as $rib) + { + print ''; + // Label + print ''; + // Bank name + print ''; + // Account number + print ''; + // IBAN + print ''; + // BIC + print ''; + + if (! empty($conf->prelevement->enabled)) + { + // RUM + //print ''; + print ''; + + // FRSTRECUR + print ''; + } + + // Default + print ''; + + // Generate doc + print ''; + + // Edit/Delete + print ''; + + print ''; + } + + if (count($rib_list) == 0) + { + $colspan=8; + if (! empty($conf->prelevement->enabled)) $colspan+=2; + print ''; + } + + print '
'.$rib->label.''.$rib->bank.''; + $string=''; + foreach ($rib->getFieldsToShow() as $val) { + + if ($val == 'BankCode') { + $string .= $rib->code_banque.' '; + } elseif ($val == 'BankAccountNumber') { + $string .= $rib->number.' '; + } elseif ($val == 'DeskCode') { + $string .= $rib->code_guichet.' '; + } elseif ($val == 'BankAccountNumberKey') { + $string .= $rib->cle_rib.' '; + /* Already output after + }elseif ($val == 'BIC') { + $string .= $rib->bic.' '; + }elseif ($val == 'IBAN') { + $string .= $rib->iban.' ';*/ + } + } + if (! empty($rib->label) && $rib->number) { + if (! checkBanForAccount($rib)) { + $string.= ' '.img_picto($langs->trans("ValueIsNotValid"),'warning'); + } else { + $string.= ' '.img_picto($langs->trans("ValueIsValid"),'info'); + } + } + + print $string; + print ''.$rib->iban; + if (! empty($rib->iban)) { + if (! checkIbanForAccount($rib)) { + print ' '.img_picto($langs->trans("IbanNotValid"),'warning'); + } else { + print ' '.img_picto($langs->trans("IbanValid"),'info'); + } + } + print ''.$rib->bic; + if (! empty($rib->bic)) { + if (! checkSwiftForAccount($rib)) { + print ' '.img_picto($langs->trans("SwiftNotValid"),'warning'); + } else { + print ' '.img_picto($langs->trans("SwiftValid"),'info'); + } + } + print ''.$prelevement->buildRumNumber($object->code_client, $rib->datec, $rib->id).''.$rib->rum.''.$rib->frstrecur.''; + if (!$rib->default_rib) { + print ''; + print img_picto($langs->trans("Disabled"),'off'); + print ''; + } else { + print img_picto($langs->trans("Enabled"),'on'); + } + print ''; + + $buttonlabel = $langs->trans("BuildDoc"); + $forname='builddocrib'.$rib->id; + + include_once DOL_DOCUMENT_ROOT.'/core/modules/bank/modules_bank.php'; + $modellist=ModeleBankAccountDoc::liste_modeles($db); + + $out = ''; + if (is_array($modellist) && count($modellist)) + { + $out.= ''; + $out.= ''; + $out.= ''; + $out.= ''; + $out.= ''; + + if (is_array($modellist) && count($modellist) == 1) // If there is only one element + { + $arraykeys=array_keys($modellist); + $modelselected=$arraykeys[0]; + } + if (! empty($conf->global->BANKADDON_PDF)) $modelselected = $conf->global->BANKADDON_PDF; + + $out.= $form->selectarray('modelrib'.$rib->id, $modellist, $modelselected, $showempty, 0, 0, '', 0, 0, 0, '', 'minwidth100'); + $out.= ajax_combobox('modelrib'.$rib->id); + + // Language code (if multilang) + if ($conf->global->MAIN_MULTILANGS) + { + include_once DOL_DOCUMENT_ROOT.'/core/class/html.formadmin.class.php'; + $formadmin=new FormAdmin($db); + $defaultlang=$codelang?$codelang:$langs->getDefaultLang(); + $morecss='maxwidth150'; + if (! empty($conf->browser->phone)) $morecss='maxwidth100'; + $out.= $formadmin->select_language($defaultlang, 'lang_idrib'.$rib->id, 0, 0, 0, 0, 0, $morecss); + } + // Button + $genbutton = 'dol_no_mouse_hover) && $modulepart != 'unpaid') + { + $langs->load("errors"); + $genbutton.= ' '.img_warning($langs->transnoentitiesnoconv("WarningNoDocumentModelActivated")); + } + if (! $allowgenifempty && ! is_array($modellist) && empty($modellist) && empty($conf->dol_no_mouse_hover) && $modulepart != 'unpaid') $genbutton=''; + if (empty($modellist) && ! $showempty && $modulepart != 'unpaid') $genbutton=''; + $out.= $genbutton; + $out.= ''; + } + print $out; + print ''; + if ($user->rights->societe->creer) + { + print ''; + print img_picto($langs->trans("Modify"),'edit'); + print ''; + + print ' '; + + print ''; + print img_picto($langs->trans("Delete"),'delete'); + print ''; + } + print '
'.$langs->trans("NoBANRecord").'
'; + print '
'; + } else { + dol_print_error($db); + } + + dol_fiche_end(); +/* + if ($socid && $action != 'edit' && $action != 'create') + { + // Barre d'actions + print '
'; + + if ($user->rights->societe->creer) + { + print ''.$langs->trans("Add").''; + } + + print '
'; + } +*/ + if (empty($conf->global->SOCIETE_DISABLE_BUILDDOC)) + { + print '
'; + print ''; // ancre + + /* + * Documents generes + */ + $filedir=$conf->societe->multidir_output[$object->entity].'/'.$object->id; + $urlsource=$_SERVER["PHP_SELF"]."?socid=".$object->id; + $genallowed=$user->rights->societe->lire; + $delallowed=$user->rights->societe->creer; + + $var=true; + + print $formfile->showdocuments('company', $object->id, $filedir, $urlsource, $genallowed, $delallowed, $object->modelpdf, 0, 0, 0, 28, 0, 'entity='.$object->entity, 0, '', $object->default_lang); + + print '
'; + + + print '
'; + + print '
'; + } + /* + include_once DOL_DOCUMENT_ROOT.'/core/modules/bank/modules_bank.php'; + $modellist=ModeleBankAccountDoc::liste_modeles($db); + //print ''; + if (is_array($modellist) && count($modellist) == 1) // If there is only one element + { + $arraykeys=array_keys($modellist); + $modelselected=$arraykeys[0]; + } + $out.= $form->selectarray('model', $modellist, $modelselected, 0, 0, 0, '', 0, 0, 0, '', 'minwidth100'); + $out.= ajax_combobox('model'); + //print $out; + $buttonlabel=$langs->trans("Generate"); + $genbutton = ''; // TODO Add link to generate doc + */ +} + +// Edit +if ($socid && $action == 'edit' && $user->rights->societe->creer) +{ + dol_fiche_head($head, 'rib', $langs->trans("ThirdParty"),0,'company'); + + $linkback = ''.$langs->trans("BackToList").''; + + dol_banner_tab($object, 'socid', $linkback, ($user->societe_id?0:1), 'rowid', 'nom'); + + print '
'; + + print '
'; + print ''; + + print ''; + print ''; + + print ''; + print ''; + + // Show fields of bank account + foreach ($account->getFieldsToShow(1) as $val) { + + $require=false; + if ($val == 'BankCode') { + $name = 'code_banque'; + $size = 8; + $content = $account->code_banque; + } elseif ($val == 'DeskCode') { + $name = 'code_guichet'; + $size = 8; + $content = $account->code_guichet; + } elseif ($val == 'BankAccountNumber') { + $name = 'number'; + $size = 18; + $content = $account->number; + } elseif ($val == 'BankAccountNumberKey') { + $name = 'cle_rib'; + $size = 3; + $content = $account->cle_rib; + } elseif ($val == 'IBAN') { + $name = 'iban'; + $size = 30; + $content = $account->iban; + if ($account->needIBAN()) $require=true; + } elseif ($val == 'BIC') { + $name = 'bic'; + $size = 12; + $content = $account->bic; + if ($account->needIBAN()) $require=true; + } + + print ''.$langs->trans($val).''; + print ''; + print ''; + } + + print '"; + + print ''; + print ''; + print "\n"; + + print '"; + + print '
'.$langs->trans("LabelRIB").'
'.$langs->trans("BankName").'
'.$langs->trans("BankAccountDomiciliation").''; + print '
'.$langs->trans("BankAccountOwner").'
'.$langs->trans("BankAccountOwnerAddress").''; + print '
'; + + if ($conf->prelevement->enabled) + { + print '
'; + + print ''; + + if (empty($account->rum)) $account->rum = $prelevement->buildRumNumber($object->code_client, $account->datec, $account->id); + + // RUM + print ''; + print ''; + + print ''; + + print '
'.$langs->trans("RUM").'
'.$langs->trans("WithdrawMode").''; + $tblArraychoice = array("FRST" => $langs->trans("FRST"), "RECUR" => $langs->trans("RECUR")); + print $form->selectarray("frstrecur", $tblArraychoice, dol_escape_htmltag(GETPOST('frstrecur')?GETPOST('frstrecur'):$account->frstrecur), 0); + print '
'; + } + + print '
'; + + dol_fiche_end(); + + print '
'; + print ''; + print '     '; + print ''; + print '
'; +} + + +// Create +if ($socid && $action == 'create' && $user->rights->societe->creer) +{ + dol_fiche_head($head, 'rib', $langs->trans("ThirdParty"),0,'company'); + + $linkback = ''.$langs->trans("BackToList").''; + + dol_banner_tab($object, 'socid', $linkback, ($user->societe_id?0:1), 'rowid', 'nom'); + + print '
'; + + print '
'; + print ''; + + print ''; + print ''; + + print ''; + print ''; + + // Show fields of bank account + foreach ($account->getFieldsToShow(1) as $val) { + + $require=false; + if ($val == 'BankCode') { + $name = 'code_banque'; + $size = 8; + } elseif ($val == 'DeskCode') { + $name = 'code_guichet'; + $size = 8; + } elseif ($val == 'BankAccountNumber') { + $name = 'number'; + $size = 18; + } elseif ($val == 'BankAccountNumberKey') { + $name = 'cle_rib'; + $size = 3; + } elseif ($val == 'IBAN') { + $name = 'iban'; + $size = 30; + if ($account->needIBAN()) $require=true; + } elseif ($val == 'BIC') { + $name = 'bic'; + $size = 12; + if ($account->needIBAN()) $require=true; + } + + print ''.$langs->trans($val).''; + print ''; + print ''; + } + + print '"; + + print ''; + print ''; + print "\n"; + + print '"; + + print '
'.$langs->trans("LabelRIB").'
'.$langs->trans("Bank").'
'.$langs->trans("BankAccountDomiciliation").''; + print '
'.$langs->trans("BankAccountOwner").'
'.$langs->trans("BankAccountOwnerAddress").''; + print '
'; + + if ($conf->prelevement->enabled) + { + print '
'; + + print ''; + + // RUM + print ''; + print ''; + + print ''; + + print '
'.$langs->trans("RUM").'
'.$langs->trans("RUMWillBeGenerated").'
'.$langs->trans("WithdrawMode").''; + $tblArraychoice = array("FRST" => $langs->trans("FRST"), "RECUR" => $langs->trans("RECUR")); + print $form->selectarray("frstrecur", $tblArraychoice, (isset($_POST['frstrecur'])?GETPOST('frstrecur'):'FRST'), 0); + print '
'; + } + + print '
'; + + dol_fiche_end(); + + print '
'; + print ''; + print '     '; + print ''; + print '
'; +} + +if ($socid && $action == 'edit' && $user->rights->societe->creer) +{ + print ''; +} +if ($socid && $action == 'create' && $user->rights->societe->creer) +{ + print ''; +} + + +llxFooter(); + +$db->close(); diff --git a/htdocs/stripe/admin/stripe.php b/htdocs/stripe/admin/stripe.php index 8f7a8ae9d86..bc098fb15ac 100644 --- a/htdocs/stripe/admin/stripe.php +++ b/htdocs/stripe/admin/stripe.php @@ -2,6 +2,7 @@ /* Copyright (C) 2017 Alexandre Spangaro * Copyright (C) 2017 Olivier Geffroy * Copyright (C) 2017 Saasprov + * Copyright (C) 2018 ptibogxiv * * 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 @@ -27,6 +28,7 @@ require '../../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/stripe/lib/stripe.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; +require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php'; $servicename='Stripe'; @@ -45,20 +47,28 @@ if ($action == 'setvalue' && $user->admin) { $db->begin(); - $result=dolibarr_set_const($db, "STRIPE_LIVE",GETPOST('STRIPE_LIVE','alpha'),'chaine',0,'',$conf->entity); - if (! $result > 0) $error++; + $result=dolibarr_set_const($db, "STRIPE_LIVE",GETPOST('STRIPE_LIVE','alpha'),'chaine',0,'',$conf->entity); + if (! $result > 0) $error++; +if (empty($conf->stripeconnect->enabled)) { $result=dolibarr_set_const($db, "STRIPE_TEST_PUBLISHABLE_KEY",GETPOST('STRIPE_TEST_PUBLISHABLE_KEY','alpha'),'chaine',0,'',$conf->entity); if (! $result > 0) $error++; $result=dolibarr_set_const($db, "STRIPE_TEST_SECRET_KEY",GETPOST('STRIPE_TEST_SECRET_KEY','alpha'),'chaine',0,'',$conf->entity); if (! $result > 0) $error++; + $result=dolibarr_set_const($db, "STRIPE_TEST_WEBHOOK_KEY",GETPOST('STRIPE_TEST_WEBHOOK_KEY','alpha'),'chaine',0,'',$conf->entity); + if (! $result > 0) $error++; $result=dolibarr_set_const($db, "STRIPE_LIVE_PUBLISHABLE_KEY",GETPOST('STRIPE_LIVE_PUBLISHABLE_KEY','alpha'),'chaine',0,'',$conf->entity); if (! $result > 0) $error++; $result=dolibarr_set_const($db, "STRIPE_LIVE_SECRET_KEY",GETPOST('STRIPE_LIVE_SECRET_KEY','alpha'),'chaine',0,'',$conf->entity); if (! $result > 0) $error++; + $result=dolibarr_set_const($db, "STRIPE_LIVE_WEBHOOK_KEY",GETPOST('STRIPE_LIVE_WEBHOOK_KEY','alpha'),'chaine',0,'',$conf->entity); + if (! $result > 0) $error++; +} $result=dolibarr_set_const($db, "ONLINE_PAYMENT_CREDITOR",GETPOST('ONLINE_PAYMENT_CREDITOR','alpha'),'chaine',0,'',$conf->entity); if (! $result > 0) $error++; $result=dolibarr_set_const($db, "STRIPE_BANK_ACCOUNT_FOR_PAYMENTS",GETPOST('STRIPE_BANK_ACCOUNT_FOR_PAYMENTS','int'),'chaine',0,'',$conf->entity); if (! $result > 0) $error++; + $result=dolibarr_set_const($db, "STRIPE_BANK_ACCOUNT_FOR_BANKTRANSFERS",GETPOST('STRIPE_BANK_ACCOUNT_FOR_BANKTRANSFERS','int'),'chaine',0,'',$conf->entity); + if (! $result > 0) $error++; $result=dolibarr_set_const($db, "ONLINE_PAYMENT_CSS_URL",GETPOST('ONLINE_PAYMENT_CSS_URL','alpha'),'chaine',0,'',$conf->entity); if (! $result > 0) $error++; $result=dolibarr_set_const($db, "ONLINE_PAYMENT_MESSAGE_FORM",GETPOST('ONLINE_PAYMENT_MESSAGE_FORM','alpha'),'chaine',0,'',$conf->entity); @@ -69,6 +79,9 @@ if ($action == 'setvalue' && $user->admin) if (! $result > 0) $error++; $result=dolibarr_set_const($db, "ONLINE_PAYMENT_SENDEMAIL",GETPOST('ONLINE_PAYMENT_SENDEMAIL'),'chaine',0,'',$conf->entity); if (! $result > 0) $error++; + // Stock decrement + $result=dolibarr_set_const($db,"ONLINE_PAYMENT_WAREHOUSE",(GETPOST('ONLINE_PAYMENT_WAREHOUSE','alpha') > 0 ? GETPOST('ONLINE_PAYMENT_WAREHOUSE','alpha') : ''),'chaine',0,'',$conf->entity); + if (! $result > 0) $error++; // Payment token for URL $result=dolibarr_set_const($db, "PAYMENT_SECURITY_TOKEN",GETPOST('PAYMENT_SECURITY_TOKEN','alpha'),'chaine',0,'',$conf->entity); if (! $result > 0) $error++; @@ -108,16 +121,7 @@ if ($action=="setlive") */ $form=new Form($db); - -//$SECRET_TEST_KEY="sk_test_xxxxxxxxxxxxxxxxxxxxxxxx"; // Stripe test secret key -//if (empty($conf->global->STRIPE_TEST_SECRET_KEY)) $conf->global->STRIPE_TEST_SECRET_KEY = $SECRET_TEST_KEY; -//$PUBLISHABLE_TEST_KEY="pk_test_xxxxxxxxxxxxxxxxxxxxxxxx"; // Stripe test publishable key -//if (empty($conf->global->STRIPE_TEST_PUBLISHABLE_KEY)) $conf->global->STRIPE_TEST_PUBLISHABLE_KEY = $PUBLISHABLE_TEST_KEY; - -//$SECRET_LIVE_KEY="sk_live_xxxxxxxxxxxxxxxxxxxxxxxx"; // Stripe live secret key -//if (empty($conf->global->STRIPE_LIVE_SECRET_KEY)) $conf->global->STRIPE_LIVE_SECRET_KEY = $SECRET_LIVE_KEY; -//$PUBLISHABLE_LIVE_KEY="pk_live_xxxxxxxxxxxxxxxxxxxxxxxx"; // Stripe live publishable key -//if (empty($conf->global->STRIPE_LIVE_PUBLISHABLE_KEY)) $conf->global->STRIPE_LIVE_PUBLISHABLE_KEY = $PUBLISHABLE_LIVE_KEY; +$formproduct=new FormProduct($db); llxHeader('',$langs->trans("StripeSetup")); @@ -145,18 +149,27 @@ print "\n"; print ''; print ''; print $langs->trans("StripeLiveEnabled").''; +if (empty($conf->global->STRIPECONNECT_LIVE) && ! empty($conf->stripeconnect->enabled)) { +if (!empty($conf->global->STRIPE_LIVE)) + print ''; + print img_picto($langs->trans("Disabled"),'switch_off'); +print ''; +} +else { if (!empty($conf->global->STRIPE_LIVE)) { - print ''; + print ''; print img_picto($langs->trans("Activated"),'switch_on'); } else { - print ''; + print ''; print img_picto($langs->trans("Disabled"),'switch_off'); } +print ''; +} print ''; - +if (empty($conf->stripeconnect->enabled)) { print ''; print ''.$langs->trans("STRIPE_TEST_PUBLISHABLE_KEY").''; print ''; @@ -169,6 +182,12 @@ print 'trans("Example").': sk_test_xxxxxxxxxxxxxxxxxxxxxxxx'; print ''; +print ''; +print ''.$langs->trans("STRIPE_TEST_WEBHOOK_KEY").''; +print ''; +print '   '.$langs->trans("Example").': whsec_xxxxxxxxxxxxxxxxxxxxxxxx'; +print ''; + print ''; print ''.$langs->trans("STRIPE_LIVE_PUBLISHABLE_KEY").''; print ''; @@ -181,6 +200,16 @@ print 'trans("Example").': sk_live_xxxxxxxxxxxxxxxxxxxxxxxx'; print ''; +print ''; +print ''.$langs->trans("STRIPE_LIVE_WEBHOOK_KEY").''; +print ''; +print '   '.$langs->trans("Example").': whsec_xxxxxxxxxxxxxxxxxxxxxxxx'; +print ''; +} else { +print ''.$langs->trans("STRIPECONNECT").''; +print 'Ce module est configuré en mode marketplace'; +} + print ''; print '
'; @@ -203,6 +232,23 @@ if (! empty($conf->banque->enabled)) print $langs->trans("BankAccount").''; print $form->select_comptes($conf->global->STRIPE_BANK_ACCOUNT_FOR_PAYMENTS, 'STRIPE_BANK_ACCOUNT_FOR_PAYMENTS', 0, '', 1); print ''; + + if ($conf->global->MAIN_FEATURES_LEVEL >= 2) // What is this for ? + { + print ''; + print $langs->trans("BankAccountForBankTransfer").''; + print $form->select_comptes($conf->global->STRIPE_BANK_ACCOUNT_FOR_BANKTRANSFERS, 'STRIPE_BANK_ACCOUNT_FOR_BANKTRANSFERS', 0, '', 1); + print ''; + } +} + +if ($conf->global->MAIN_FEATURES_LEVEL >= 2) // What is this for ? +{ + // Stock for automatic decrement + print ''; + print $langs->trans("ONLINE_PAYMENT_WAREHOUSE").''; + print $formproduct->selectWarehouses($conf->global->ONLINE_PAYMENT_WAREHOUSE,'ONLINE_PAYMENT_WAREHOUSE','',1,$disabled); + print ''; } print ''; @@ -281,3 +327,4 @@ if (! empty($conf->use_javascript_ajax)) llxFooter(); $db->close(); + diff --git a/htdocs/stripe/charge b/htdocs/stripe/charge new file mode 100644 index 00000000000..28b990fe811 --- /dev/null +++ b/htdocs/stripe/charge @@ -0,0 +1,149 @@ + + * + * 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 . + */ + +// Put here all includes required by your class file + +require '../main.inc.php'; +require_once DOL_DOCUMENT_ROOT.'/stripe/class/stripe.class.php'; +//require_once DOL_DOCUMENT_ROOT.'/core/lib/stripe.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'; +require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php'; +require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; +if (! empty($conf->accounting->enabled)) require_once DOL_DOCUMENT_ROOT . '/accountancy/class/accountingjournal.class.php'; + +$langs->load("compta"); +$langs->load("salaries"); +$langs->load("bills"); +$langs->load("hrm"); +$langs->load("stripe"); + +// Security check +$socid = GETPOST("socid","int"); +if ($user->societe_id) $socid=$user->societe_id; +//$result = restrictedArea($user, 'salaries', '', '', ''); + +$limit = GETPOST('limit')?GETPOST('limit','int'):$conf->liste_limit; +$rowid = GETPOST("rowid",'alpha'); +$sortfield = GETPOST("sortfield",'alpha'); +$sortorder = GETPOST("sortorder",'alpha'); +$page = GETPOST("page",'int'); +if (empty($page) || $page == -1) { $page = 0; } // If $page is not defined, or '' or -1 +$offset = $conf->liste_limit * $page; +$pageprev = $page - 1; +$pagenext = $page + 1; + +/* +* View +*/ +llxHeader('', $langs->trans("StripeChargeList")); +$form = new Form($db); +$societestatic = new societe($db); +$acc = new Account($db); +$stripeconnect=new StripeConnexion($db); +if (! empty($conf->stripe->enabled) && (empty($conf->global->STRIPE_LIVE) || empty($conf->global->STRIPECONNECT_LIVE) || GETPOST('forcesandbox','alpha'))) +{ + dol_htmloutput_mesg($langs->trans('YouAreCurrentlyInSandboxMode','Stripe'),'','warning'); +} +if (!$rowid){ + + print '
'; + if ($optioncss != '') print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + + print_barre_liste($langs->trans("StripeChargeList"),$page,$_SERVER["PHP_SELF"],$param,$sortfield,$sortorder,'',$num, $totalnboflines, 'title_accountancy.png', 0, '', '', $limit); + + print '
'; + print ''."\n"; + + print ''; + print_liste_field_titre("Ref",$_SERVER["PHP_SELF"],"","","","",$sortfield,$sortorder); + print_liste_field_titre("Customer",$_SERVER["PHP_SELF"],"","","","",$sortfield,$sortorder); + print_liste_field_titre("Origin",$_SERVER["PHP_SELF"],"","","","",$sortfield,$sortorder); + print_liste_field_titre("DatePayment",$_SERVER["PHP_SELF"],"","","",'align="center"',$sortfield,$sortorder); + print_liste_field_titre("Status",$_SERVER["PHP_SELF"],"","","",'align="left"'); + print_liste_field_titre("Type",$_SERVER["PHP_SELF"],"","","",'align="left"',$sortfield,$sortorder); + print_liste_field_titre("Paid",$_SERVER["PHP_SELF"],"","","",'align="right"',$sortfield,$sortorder); + print "\n"; + + print "\n"; + +$list=\Stripe\Charge::all(array("limit" => $limit),array("stripe_account" => $stripeconnect->GetStripeAccount($conf->entity))); +//print $list; +foreach ($list->data as $charge) { + print ''; + $societestatic->fetch($charge->metadata->idcustomer); + $societestatic->id=$charge->metadata->idcustomer; + $societestatic->lastname=$obj->lastname; + $societestatic->firstname=$obj->firstname; + $societestatic->admin=$obj->admin; + $societestatic->login=$obj->login; + $societestatic->email=$obj->email; + $societestatic->societe_id=$obj->fk_soc; + // Ref + print "\n"; + // Employee + print "\n"; + // Origine + print "\n"; + // Date payment + print '\n"; + // Label payment + print "\n"; + // Type + print ''; + // Amount + print ""; + print "\n"; + } +} else { + +} + +llxFooter(); +$db->close(); diff --git a/htdocs/stripe/config.php b/htdocs/stripe/config.php index 9f5f0e4de96..a692e541050 100644 --- a/htdocs/stripe/config.php +++ b/htdocs/stripe/config.php @@ -33,6 +33,15 @@ global $conf; //use \includes\stripe as stripe; $stripe = array(); +if ((empty($conf->global->STRIPECONNECT_LIVE) && ! (empty($conf->stripeconnect->enabled))) || GETPOST('forcesandbox','alpha')) +{ + $stripe = array( + "secret_key" => $conf->global->STRIPE_TEST_SECRET_KEY, + "publishable_key" => $conf->global->STRIPE_TEST_PUBLISHABLE_KEY + ); +} +else +{ if (empty($conf->global->STRIPE_LIVE) || GETPOST('forcesandbox','alpha')) { $stripe = array( @@ -47,8 +56,13 @@ else "publishable_key" => $conf->global->STRIPE_LIVE_PUBLISHABLE_KEY ); } +} require_once DOL_DOCUMENT_ROOT."/includes/stripe/lib/Stripe.php"; require_once DOL_DOCUMENT_ROOT.'/core/lib/payments.lib.php'; \Stripe\Stripe::setApiKey($stripe['secret_key']); + +require_once DOL_DOCUMENT_ROOT.'/core/lib/payments.lib.php'; + +\Stripe\Stripe::setAppInfo("Stripe", "dolibarr version", "https://www.dolibarr.org"); // add dolibarr version diff --git a/htdocs/stripe/transaction.php b/htdocs/stripe/transaction.php new file mode 100644 index 00000000000..b350154bee9 --- /dev/null +++ b/htdocs/stripe/transaction.php @@ -0,0 +1,148 @@ + + * + * 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 . + */ + +// Put here all includes required by your class file + +require '../main.inc.php'; +require_once DOL_DOCUMENT_ROOT.'/stripe/class/stripe.class.php'; +//require_once DOL_DOCUMENT_ROOT.'/core/lib/stripe.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php'; +require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php'; +require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; +if (! empty($conf->accounting->enabled)) require_once DOL_DOCUMENT_ROOT . '/accountancy/class/accountingjournal.class.php'; + +$langs->load("compta"); +$langs->load("salaries"); +$langs->load("bills"); +$langs->load("hrm"); +$langs->load("stripe"); + +// Security check +$socid = GETPOST("socid","int"); +if ($user->societe_id) $socid=$user->societe_id; +//$result = restrictedArea($user, 'salaries', '', '', ''); + +$limit = GETPOST('limit')?GETPOST('limit','int'):$conf->liste_limit; +$rowid = GETPOST("rowid",'alpha'); +$sortfield = GETPOST("sortfield",'alpha'); +$sortorder = GETPOST("sortorder",'alpha'); +$page = GETPOST("page",'int'); +if (empty($page) || $page == -1) { $page = 0; } // If $page is not defined, or '' or -1 +$offset = $conf->liste_limit * $page; +$pageprev = $page - 1; +$pagenext = $page + 1; + +/* +* View +*/ +llxHeader('', $langs->trans("StripeTransactionList")); +$form = new Form($db); +$societestatic = new societe($db); +$acc = new Account($db); +$stripeconnect=new StripeConnexion($db); +if (! empty($conf->stripe->enabled) && (empty($conf->global->STRIPE_LIVE) || empty($conf->global->STRIPECONNECT_LIVE) || GETPOST('forcesandbox','alpha'))) +{ + dol_htmloutput_mesg($langs->trans('YouAreCurrentlyInSandboxMode','Stripe'),'','warning'); +} +if (!$rowid){ + + print ''; + if ($optioncss != '') print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + + print_barre_liste($langs->trans("StripeTransactionList"),$page,$_SERVER["PHP_SELF"],$param,$sortfield,$sortorder,'',$num, $totalnboflines, 'title_accountancy.png', 0, '', '', $limit); + + print '
'; + print '
".$charge->id."".$societestatic->getNomUrl(1).""; +if ($charge->metadata->source=="order"){ +$object = new Commande($db); +$object->fetch($charge->metadata->idsource); + print "".img_picto('', 'object_order')." ".$object->ref.""; +} elseif ($charge->metadata->source=="invoice"){ +$object = new Facture($db); +$object->fetch($charge->metadata->idsource); + print "".img_picto('', 'object_invoice')." ".$object->ref.""; +} + print "'.dol_print_date($charge->created,'%d/%m/%Y %H:%M').""; +if ($charge->refunded=='1'){ + print $langs->trans("refunded"); +} elseif ($charge->paid=='1'){ + print $langs->trans("".$charge->status.""); +} else { +$label="Message: ".$charge->failure_message."
"; +$label.="Réseau: ".$charge->outcome->network_status."
"; +$label.="Statut: ".$langs->trans("".$charge->outcome->seller_message.""); + print $form->textwithpicto($langs->trans("".$charge->status.""),$label,1); +} + print "
'; +if ($charge->source->type=='card'){ + print $langs->trans("card"); +} elseif ($charge->source->type=='three_d_secure'){ + print $langs->trans("card3DS"); +} + print '".price(($charge->amount-$charge->amount_refunded)/100)."
'."\n"; + + print ''; + print_liste_field_titre("Ref",$_SERVER["PHP_SELF"],"","","","",$sortfield,$sortorder); + print_liste_field_titre("Customer",$_SERVER["PHP_SELF"],"","","","",$sortfield,$sortorder); + print_liste_field_titre("Origin",$_SERVER["PHP_SELF"],"","","","",$sortfield,$sortorder); + print_liste_field_titre("DatePayment",$_SERVER["PHP_SELF"],"","","",'align="center"',$sortfield,$sortorder); + print_liste_field_titre("Status",$_SERVER["PHP_SELF"],"","","",'align="left"'); + print_liste_field_titre("Type",$_SERVER["PHP_SELF"],"","","",'align="left"',$sortfield,$sortorder); + print_liste_field_titre("Paid",$_SERVER["PHP_SELF"],"","","",'align="right"',$sortfield,$sortorder); + print_liste_field_titre("Fee",$_SERVER["PHP_SELF"],"","","",'align="right"',$sortfield,$sortorder); + print "\n"; + + print "\n"; + +$txn=\Stripe\BalanceTransaction::all(array("limit" => $limit), array("stripe_account" => $stripeconnect->GetStripeAccount($conf->entity))); +foreach ($txn->data as $txn) { + print ''; + $societestatic->fetch($charge->metadata->idcustomer); + $societestatic->id=$charge->metadata->idcustomer; + $societestatic->lastname=$obj->lastname; + $societestatic->firstname=$obj->firstname; + $societestatic->admin=$obj->admin; + $societestatic->login=$obj->login; + $societestatic->email=$obj->email; + $societestatic->societe_id=$obj->fk_soc; + + // Ref + print "\n"; + // Employee + print "\n"; + // Origine + print "\n"; + // Date payment + print '\n"; + // Label payment + print "\n"; + // Type + print ''; + // Amount + print ""; + print ""; + print "\n"; + } + print "
".$txn->source."".$societestatic->getNomUrl(1).""; +if ($charge->metadata->source=="order"){ +$object = new Commande($db); +$object->fetch($charge->metadata->idsource); + print "".img_picto('', 'object_order')." ".$object->ref.""; +} elseif ($txn->metadata->source=="invoice"){ +$object = new Facture($db); +$object->fetch($txn->metadata->idsource); + print "".img_picto('', 'object_invoice')." ".$object->ref.""; +} + print "'.dol_print_date($txn->created,'%d/%m/%Y %H:%M').""; +if ($charge->refunded=='1'){ + print $langs->trans("refunded"); +} elseif ($charge->paid=='1'){ + print $langs->trans("".$charge->status.""); +} else { +$label="Message: ".$charge->failure_message."
"; +$label.="Réseau: ".$charge->outcome->network_status."
"; +$label.="Statut: ".$langs->trans("".$charge->outcome->seller_message.""); + print $form->textwithpicto($langs->trans("".$charge->status.""),$label,1); +} + print "
'.$txn->type.'".price(($txn->amount)/100)."".price(($txn->fee)/100)."
"; + print '
'; + print '
'; +}else{ + +} + +llxFooter(); +$db->close(); diff --git a/htdocs/supplier_proposal/card.php b/htdocs/supplier_proposal/card.php index 8d8e46a6ae9..27f38b3a298 100644 --- a/htdocs/supplier_proposal/card.php +++ b/htdocs/supplier_proposal/card.php @@ -643,8 +643,11 @@ if (empty($reshook)) $label, $array_options, $ref_supplier, - $fk_unit - ); + $fk_unit, + '', + 0, + $productsupplier->fourn_multicurrency_unitprice + ); //var_dump($tva_tx);var_dump($productsupplier->fourn_pu);var_dump($price_base_type);exit; } if ($idprod == -99 || $idprod == 0) diff --git a/htdocs/supplier_proposal/class/supplier_proposal.class.php b/htdocs/supplier_proposal/class/supplier_proposal.class.php index 1e24190f90d..8a713bccb95 100644 --- a/htdocs/supplier_proposal/class/supplier_proposal.class.php +++ b/htdocs/supplier_proposal/class/supplier_proposal.class.php @@ -367,13 +367,14 @@ class SupplierProposal extends CommonObject * @param int $fk_unit Id of the unit to use. * @param string $origin 'order', 'supplier_proposal', ... * @param int $origin_id Id of origin line + * @param double $pu_ht_devise Amount in currency * @return int >0 if OK, <0 if KO * * @see add_product */ - function addline($desc, $pu_ht, $qty, $txtva, $txlocaltax1=0, $txlocaltax2=0, $fk_product=0, $remise_percent=0, $price_base_type='HT', $pu_ttc=0, $info_bits=0, $type=0, $rang=-1, $special_code=0, $fk_parent_line=0, $fk_fournprice=0, $pa_ht=0, $label='',$array_option=0, $ref_fourn='', $fk_unit='', $origin='', $origin_id=0) + function addline($desc, $pu_ht, $qty, $txtva, $txlocaltax1=0, $txlocaltax2=0, $fk_product=0, $remise_percent=0, $price_base_type='HT', $pu_ttc=0, $info_bits=0, $type=0, $rang=-1, $special_code=0, $fk_parent_line=0, $fk_fournprice=0, $pa_ht=0, $label='',$array_option=0, $ref_fourn='', $fk_unit='', $origin='', $origin_id=0, $pu_ht_devise=0) { - global $mysoc; + global $mysoc, $conf; dol_syslog(get_class($this)."::addline supplier_proposalid=$this->id, desc=$desc, pu_ht=$pu_ht, qty=$qty, txtva=$txtva, fk_product=$fk_product, remise_except=$remise_percent, price_base_type=$price_base_type, pu_ttc=$pu_ttc, info_bits=$info_bits, type=$type"); include_once DOL_DOCUMENT_ROOT.'/core/lib/price.lib.php'; @@ -418,17 +419,23 @@ class SupplierProposal extends CommonObject $localtaxes_type=getLocalTaxesFromRate($txtva,0,$this->thirdparty,$mysoc); $txtva = preg_replace('/\s*\(.*\)/','',$txtva); // Remove code into vatrate. - $tabprice=calcul_price_total($qty, $pu, $remise_percent, $txtva, $txlocaltax1, $txlocaltax2, 0, $price_base_type, $info_bits, $type, $this->thirdparty, $localtaxes_type, 100, $this->multicurrency_tx); + if ($conf->multicurrency->enabled && $pu_ht_devise > 0) { + $pu = 0; + } + + $tabprice=calcul_price_total($qty, $pu, $remise_percent, $txtva, $txlocaltax1, $txlocaltax2, 0, $price_base_type, $info_bits, $type, $this->thirdparty, $localtaxes_type, 100, $this->multicurrency_tx, $pu_ht_devise); $total_ht = $tabprice[0]; $total_tva = $tabprice[1]; $total_ttc = $tabprice[2]; $total_localtax1 = $tabprice[9]; $total_localtax2 = $tabprice[10]; + $pu = $pu_ht = $tabprice[3]; // MultiCurrency $multicurrency_total_ht = $tabprice[16]; $multicurrency_total_tva = $tabprice[17]; $multicurrency_total_ttc = $tabprice[18]; + $pu_ht_devise = $tabprice[19]; // Rang to use $rangtouse = $rang; @@ -493,7 +500,7 @@ class SupplierProposal extends CommonObject // Multicurrency $this->line->fk_multicurrency = $this->fk_multicurrency; $this->line->multicurrency_code = $this->multicurrency_code; - $this->line->multicurrency_subprice = price2num($pu_ht * $this->multicurrency_tx); + $this->line->multicurrency_subprice = $pu_ht_devise; $this->line->multicurrency_total_ht = $multicurrency_total_ht; $this->line->multicurrency_total_tva = $multicurrency_total_tva; $this->line->multicurrency_total_ttc = $multicurrency_total_ttc; diff --git a/htdocs/theme/eldy/style.css.php b/htdocs/theme/eldy/style.css.php index bfd1b75ac91..c7b00629b3b 100644 --- a/htdocs/theme/eldy/style.css.php +++ b/htdocs/theme/eldy/style.css.php @@ -295,12 +295,12 @@ input, input.flat, textarea, textarea.flat, form.flat select, select, select.fla } input { - line-height: 17px; - padding: 4px; + line-height: 1.3em; + padding: 5px; padding-left: 5px; } select { - padding: 4px; + padding: 5px; padding-left: 2px; } input, select { @@ -419,7 +419,6 @@ td.actionbuttons a { select.flat, form.flat select { font-weight: normal; font-size: unset; - height: 2em; } .optionblue { color: rgb(); @@ -992,7 +991,7 @@ select.selectarrowonleft option { input, input[type=text], input[type=password], select, textarea { min-width: 20px; min-height: 1.4em; - line-height: 1.4em; + /* line-height: 1.4em; */ /* padding: .4em .1em; */ /* border-bottom: 1px solid #BBB; */ /* max-width: inherit; why this ? */ @@ -1936,7 +1935,7 @@ img.login, img.printer, img.entity { color: white; font-weight: bold; } -.userimgatoplogin img.userphoto { /* size for user photo in login bar */ +.userimg.atoplogin img.userphoto, .userimgatoplogin img.userphoto { /* size for user photo in login bar */ width: 16px; height: 16px; border-radius: 8px; @@ -3768,13 +3767,16 @@ table.cal_event { border: none; border-collapse: collapse; margin-bottom: 1px table.cal_event td { border: none; padding-: 2px; padding-: 2px; padding-top: 0px; padding-bottom: 0px; } table.cal_event td.cal_event { padding: 4px 4px !important; } table.cal_event td.cal_event_right { padding: 4px 4px !important; } -.cal_event a:link { color: #111111; font-size: 11px; font-weight: normal !important; } -.cal_event a:visited { color: #111111; font-size: 11px; font-weight: normal !important; } -.cal_event a:active { color: #111111; font-size: 11px; font-weight: normal !important; } -.cal_event_busy a:hover { color: #111111; font-size: 11px; font-weight: normal !important; color:rgba(255,255,255,.75); } +.cal_event { font-size: 1em; } +.cal_event a:link { color: #111111; font-weight: normal !important; } +.cal_event a:visited { color: #111111; font-weight: normal !important; } +.cal_event a:active { color: #111111; font-weight: normal !important; } +.cal_event_busy a:hover { color: #111111; font-weight: normal !important; color:rgba(255,255,255,.75); } .cal_event_busy { } .cal_peruserviewname { max-width: 140px; height: 22px; } +.calendarviewcontainertr { height: 100px; } + /* ============================================================================== */ /* Ajax - Liste deroulante de l'autocompletion */ diff --git a/htdocs/theme/md/style.css.php b/htdocs/theme/md/style.css.php index 5b4040b0501..51b3294d7b9 100644 --- a/htdocs/theme/md/style.css.php +++ b/htdocs/theme/md/style.css.php @@ -884,6 +884,7 @@ select.selectarrowonleft option { } .widthauto { width: auto; } .width25 { width: 25px; } +.width75 { width: 75px; } .width50 { width: 50px; } .width75 { width: 75px; } .width100 { width: 100px; } @@ -1938,7 +1939,7 @@ img.login, img.printer, img.entity { color: white; font-weight: bold; } -.userimgatoplogin img.userphoto { /* size for user photo in login bar */ +.userimg.atoplogin img.userphoto, .userimgatoplogin img.userphoto { /* size for user photo in login bar */ border-radius: 8px; width: 16px; height: 16px; @@ -3734,10 +3735,11 @@ table.cal_event { border: none; border-collapse: collapse; margin-bottom: 1px table.cal_event td { border: none; padding-: 2px; padding-: 2px; padding-top: 0px; padding-bottom: 0px; } table.cal_event td.cal_event { padding: 4px 4px !important; } table.cal_event td.cal_event_right { padding: 4px 4px !important; } -.cal_event a:link { color: #111111; font-size: 11px; font-weight: normal !important; } -.cal_event a:visited { color: #111111; font-size: 11px; font-weight: normal !important; } -.cal_event a:active { color: #111111; font-size: 11px; font-weight: normal !important; } -.cal_event_busy a:hover { color: #111111; font-size: 11px; font-weight: normal !important; color:rgba(255,255,255,.75); } +.cal_event { font-size: 1em; } +.cal_event a:link { color: #111111; font-weight: normal !important; } +.cal_event a:visited { color: #111111; font-weight: normal !important; } +.cal_event a:active { color: #111111; font-weight: normal !important; } +.cal_event_busy a:hover { color: #111111; font-weight: normal !important; color:rgba(255,255,255,.75); } .cal_event_busy { } .cal_peruserviewname { max-width: 140px; height: 22px; } diff --git a/htdocs/user/class/user.class.php b/htdocs/user/class/user.class.php index 3fcdf411a24..049275fc5b4 100644 --- a/htdocs/user/class/user.class.php +++ b/htdocs/user/class/user.class.php @@ -2221,14 +2221,14 @@ class User extends CommonObject $paddafterimage=''; if (abs($withpictoimg) == 1) $paddafterimage='style="margin-right: 3px;"'; // Only picto - if ($withpictoimg > 0) $picto='
'.img_object('', 'user', $paddafterimage.' '.($notooltip?'':'class="classfortooltip"'), 0, 0, $notooltip?0:1).'
'; + if ($withpictoimg > 0) $picto='
'.img_object('', 'user', $paddafterimage.' '.($notooltip?'':'class="classfortooltip"'), 0, 0, $notooltip?0:1).'
'; // Picto must be a photo - else $picto='
'.Form::showphoto('userphoto', $this, 0, 0, 0, 'userphoto'.($withpictoimg==-3?'small':''), 'mini', 0, 1).'
'; + else $picto='
'.Form::showphoto('userphoto', $this, 0, 0, 0, 'userphoto'.($withpictoimg==-3?'small':''), 'mini', 0, 1).'
'; $result.=$picto; } if ($withpictoimg > -2 && $withpictoimg != 2) { - if (empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) $result.='
'; + if (empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) $result.='
'; if ($mode == 'login') $result.=dol_trunc($this->login, $maxlen); else $result.=$this->getFullName($langs,'',($mode == 'firstname' ? 2 : -1),$maxlen); if (empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) $result.='
'; @@ -2741,12 +2741,24 @@ class User extends CommonObject // Init $this->users array $sql = "SELECT DISTINCT u.rowid, u.firstname, u.lastname, u.fk_user, u.fk_soc, u.login, u.email, u.gender, u.admin, u.statut, u.photo, u.entity"; // Distinct reduce pb with old tables with duplicates $sql.= " FROM ".MAIN_DB_PREFIX."user as u"; - if(! empty($conf->multicompany->enabled) && $conf->entity == 1 && (! empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE) || (! empty($user->admin) && empty($user->entity)))) - { - $sql.= " WHERE u.entity IS NOT NULL"; - } - else - { + // TODO add hook + if (! empty($conf->multicompany->enabled)) { + if (! empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE)) { + if (! empty($user->admin) && empty($user->entity)) { + if ($conf->entity == 1) { + $sql.= " WHERE u.entity IS NOT NULL"; + } else { + $sql.= " WHERE u.entity IN (".getEntity('user').")"; + } + } else { + $sql.= ",".MAIN_DB_PREFIX."usergroup_user as ug"; + $sql.= " WHERE ug.fk_user = u.rowid"; + $sql.= " AND ug.entity IN (".getEntity('user').")"; + } + } else { + $sql.= " WHERE u.entity IN (".getEntity('user').")"; + } + } else { $sql.= " WHERE u.entity IN (".getEntity('user').")"; } if ($filter) $sql.=" AND ".$filter; diff --git a/htdocs/user/home.php b/htdocs/user/home.php index 6600d262002..0a4cb253c0f 100644 --- a/htdocs/user/home.php +++ b/htdocs/user/home.php @@ -89,7 +89,7 @@ print '
'; */ $max=10; -$sql = "SELECT u.rowid, u.lastname, u.firstname, u.admin, u.login, u.fk_soc, u.datec, u.statut"; +$sql = "SELECT DISTINCT u.rowid, u.lastname, u.firstname, u.admin, u.login, u.fk_soc, u.datec, u.statut"; $sql.= ", u.entity"; $sql.= ", u.ldap_sid"; $sql.= ", u.photo"; @@ -101,13 +101,25 @@ $sql.= ", s.code_client"; $sql.= ", s.canvas"; $sql.= " FROM ".MAIN_DB_PREFIX."user as u"; $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON u.fk_soc = s.rowid"; -if (! empty($conf->multicompany->enabled) && $conf->entity == 1 && ($conf->global->MULTICOMPANY_TRANSVERSE_MODE || ($user->admin && ! $user->entity))) -{ - $sql.= " WHERE u.entity IS NOT NULL"; -} -else -{ - $sql.= " WHERE u.entity IN (0,".$conf->entity.")"; +// TODO add hook +if (! empty($conf->multicompany->enabled)) { + if (! empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE)) { + if (! empty($user->admin) && empty($user->entity)) { + if ($conf->entity == 1) { + $sql.= " WHERE u.entity IS NOT NULL"; + } else { + $sql.= " WHERE u.entity IN (".getEntity('user').")"; + } + } else { + $sql.= ",".MAIN_DB_PREFIX."usergroup_user as ug"; + $sql.= " WHERE ug.fk_user = u.rowid"; + $sql.= " AND ug.entity IN (".getEntity('user').")"; + } + } else { + $sql.= " WHERE u.entity IN (".getEntity('user').")"; + } +} else { + $sql.= " WHERE u.entity IN (".getEntity('user').")"; } if (!empty($socid)) $sql.= " AND u.fk_soc = ".$socid; $sql.= $db->order("u.datec","DESC"); diff --git a/htdocs/user/index.php b/htdocs/user/index.php index b5edbafa89e..704c04d2593 100644 --- a/htdocs/user/index.php +++ b/htdocs/user/index.php @@ -175,7 +175,7 @@ $user2=new User($db); $buttonviewhierarchy='
'; -$sql = "SELECT u.rowid, u.lastname, u.firstname, u.admin, u.fk_soc, u.login, u.email, u.accountancy_code, u.gender, u.employee, u.photo,"; +$sql = "SELECT DISTINCT u.rowid, u.lastname, u.firstname, u.admin, u.fk_soc, u.login, u.email, u.accountancy_code, u.gender, u.employee, u.photo,"; $sql.= " u.datelastlogin, u.datepreviouslogin,"; $sql.= " u.ldap_sid, u.statut, u.entity,"; $sql.= " u.tms as date_update, u.datec as date_creation,"; @@ -191,12 +191,24 @@ $sql.= " FROM ".MAIN_DB_PREFIX."user as u"; if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label)) $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."user_extrafields as ef on (u.rowid = ef.fk_object)"; $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON u.fk_soc = s.rowid"; $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."user as u2 ON u.fk_user = u2.rowid"; -if(! empty($conf->multicompany->enabled) && $conf->entity == 1 && (! empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE) || (! empty($user->admin) && empty($user->entity)))) -{ - $sql.= " WHERE u.entity IS NOT NULL"; -} -else -{ +// TODO add hook +if (! empty($conf->multicompany->enabled)) { + if (! empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE)) { + if (! empty($user->admin) && empty($user->entity)) { + if ($conf->entity == 1) { + $sql.= " WHERE u.entity IS NOT NULL"; + } else { + $sql.= " WHERE u.entity IN (".getEntity('user').")"; + } + } else { + $sql.= ",".MAIN_DB_PREFIX."usergroup_user as ug"; + $sql.= " WHERE ug.fk_user = u.rowid"; + $sql.= " AND ug.entity IN (".getEntity('user').")"; + } + } else { + $sql.= " WHERE u.entity IN (".getEntity('user').")"; + } +} else { $sql.= " WHERE u.entity IN (".getEntity('user').")"; } if ($socid > 0) $sql.= " AND u.fk_soc = ".$socid;