/** * Gerer la reponse du POST JS sur paiement/abonnement * @param array $config * @param array $response * @return array */ function stripe_traite_reponse_transaction($config, &$response) { $mode = $config['presta']; if (isset($config['mode_test']) and $config['mode_test']) { $mode .= "_test"; } $config_id = bank_config_id($config); $is_abo = (isset($response['abo']) and $response['abo']); if (!isset($response['id_transaction']) or !isset($response['transaction_hash'])) { return bank_transaction_invalide(0, array('mode' => $mode, 'erreur' => "transaction inconnue", 'log' => var_export($response, true))); } if ((!isset($response['charge_id']) or !$response['charge_id']) and (!isset($response['token']) or !$response['token'])) { return bank_transaction_invalide(0, array('mode' => $mode, 'erreur' => "token/charge_id absent dans la reponse", 'log' => var_export($response, true))); } $id_transaction = $response['id_transaction']; $transaction_hash = $response['transaction_hash']; if (!($row = sql_fetsel('*', 'spip_transactions', 'id_transaction=' . intval($id_transaction)))) { return bank_transaction_invalide($id_transaction, array('mode' => $mode, 'erreur' => "transaction non trouvee", 'log' => var_export($response, true))); } if ($transaction_hash != $row['transaction_hash']) { return bank_transaction_invalide($id_transaction, array('mode' => $mode, 'erreur' => "hash {$transaction_hash} non conforme", 'log' => var_export($response, true))); } $montant = intval(round(100 * $row['montant'], 0)); if (strlen($montant) < 3) { $montant = str_pad($montant, 3, '0', STR_PAD_LEFT); } $email = bank_porteur_email($row); // ok, on traite le reglement $date = $_SERVER['REQUEST_TIME']; $date_paiement = date('Y-m-d H:i:s', $date); $erreur = ""; $erreur_code = 0; // charger l'API Stripe avec la cle stripe_init_api($config); // preparer le paiement $nom_site = textebrut($GLOBALS['meta']['nom_site']); $desc_charge = array('amount' => $montant, "currency" => "eur", "source" => $response['token'], "description" => "Transaction #" . $id_transaction . " [{$nom_site}]", "receipt_email" => $email, "metadata" => array('id_transaction' => $id_transaction, 'id_auteur' => $row['id_auteur'], 'nom_site' => $nom_site, 'url_site' => $GLOBALS['meta']['adresse_site'])); // la charge existe deja (autoresponse webhook sur abonnement) if (isset($response['charge_id']) and $response['charge_id']) { try { $charge = \Stripe\Charge::retrieve($response['charge_id']); $charge->description = $desc_charge['description']; $charge->metadata = $desc_charge['metadata']; $charge->save(); if (!$charge->paid) { $erreur_code = 'unpaid'; $erreur = 'payment failed'; } } catch (Exception $e) { if ($body = $e->getJsonBody()) { $err = $body['error']; list($erreur_code, $erreur) = stripe_error_code($err); } else { $erreur = $e->getMessage(); $erreur_code = 'error'; } } } else { // est-ce un abonnement ? if ($is_abo) { // on decrit l'echeance if ($decrire_echeance = charger_fonction("decrire_echeance", "abos", true) and $echeance = $decrire_echeance($id_transaction)) { if ($echeance['montant'] > 0) { $montant_echeance = intval(round(100 * $echeance['montant'], 0)); if (strlen($montant_echeance) < 3) { $montant_echeance = str_pad($montant_echeance, 3, '0', STR_PAD_LEFT); } $interval = 'month'; if (isset($echeance['freq']) and $echeance['freq'] == 'yearly') { $interval = 'year'; } $desc_plan = array('amount' => $montant_echeance, 'interval' => $interval, 'name' => "#{$id_transaction} [{$nom_site}]", 'currency' => $desc_charge['currency'], 'metadata' => $desc_charge['metadata']); // dans tous les cas on fait preleve la premiere echeance en paiement unique // et en faisant démarrer l'abonnement par "1 periode" en essai sans paiement // ca permet de gerer le cas paiement initial different, et de recuperer les infos de CB dans tous les cas $time_start = strtotime($date_paiement); $time_paiement_1_interval = strtotime("+1 {$interval}", $time_start); $nb_days = intval(round(($time_paiement_1_interval - $time_start) / 86400)); $desc_plan['trial_period_days'] = $nb_days; // un id unique (sauf si on rejoue le meme paiement) $desc_plan['id'] = md5(json_encode($desc_plan) . "-{$transaction_hash}"); try { $plan = \Stripe\Plan::retrieve($desc_plan['id']); } catch (Exception $e) { // erreur si on ne retrouve pas le plan, on ignore $plan = false; } try { if (!$plan) { $plan = \Stripe\Plan::create($desc_plan); } if (!$plan) { $erreur = "Erreur creation plan d'abonnement"; $erreur_code = "plan_failed"; } } catch (Exception $e) { if ($body = $e->getJsonBody()) { $err = $body['error']; list($erreur_code, $erreur) = stripe_error_code($err); } else { $erreur = $e->getMessage(); $erreur_code = 'error'; } } if ($erreur or $erreur_code) { // regarder si l'annulation n'arrive pas apres un reglement (internaute qui a ouvert 2 fenetres de paiement) if ($row['reglee'] == 'oui') { return array($id_transaction, true); } // sinon enregistrer l'absence de paiement et l'erreur return bank_transaction_echec($id_transaction, array('mode' => $mode, 'config_id' => $config_id, 'date_paiement' => $date_paiement, 'code_erreur' => $erreur_code, 'erreur' => $erreur, 'log' => var_export($response, true))); } } } } // essayer de retrouver ou creer un customer pour l'id_auteur $customer = null; try { if ($row['id_auteur']) { $customer_id = sql_getfetsel('pay_id', 'spip_transactions', 'pay_id!=' . sql_quote('') . ' AND id_auteur=' . intval($row['id_auteur']) . ' AND statut=' . sql_quote('ok') . ' AND mode=' . sql_quote("{$mode}/{$config_id}"), '', 'date_paiement DESC', '0,1'); if ($customer_id) { $customer = \Stripe\Customer::retrieve($customer_id); } } // si customer retrouve, on ajoute la source et la transaction if ($customer and $customer->email === $email) { $customer->source = $desc_charge['source']; $metadata = $customer->metadata; if (!$metadata) { $metadata = array(); } if (isset($metadata['id_transaction'])) { $metadata['id_transaction'] .= ',' . $id_transaction; } else { $metadata['id_transaction'] = $id_transaction; } $metadata['id_auteur'] = $row['id_auteur']; $customer->metadata = $metadata; $customer->description = sql_getfetsel('nom', 'spip_auteurs', 'id_auteur=' . intval($row['id_auteur'])); $customer->save(); } else { $d = array('email' => $email, 'source' => $desc_charge['source'], 'metadata' => $desc_charge['metadata']); if ($row['id_auteur']) { $d['description'] = sql_getfetsel('nom', 'spip_auteurs', 'id_auteur=' . intval($row['id_auteur'])); } $customer = \Stripe\Customer::create($d); } if ($is_abo and !$customer) { $erreur = "Erreur creation customer"; $erreur_code = "cust_failed"; } } catch (Exception $e) { if ($body = $e->getJsonBody()) { $err = $body['error']; list($erreur_code, $erreur) = stripe_error_code($err); } else { $erreur = $e->getMessage(); $erreur_code = 'error'; } spip_log("Echec creation/recherche customer transaction #{$id_transaction} {$erreur}", $mode . _LOG_ERREUR); } if ($is_abo and ($erreur or $erreur_code)) { // regarder si l'annulation n'arrive pas apres un reglement (internaute qui a ouvert 2 fenetres de paiement) if ($row['reglee'] == 'oui') { return array($id_transaction, true); } // sinon enregistrer l'absence de paiement et l'erreur return bank_transaction_echec($id_transaction, array('mode' => $mode, 'config_id' => $config_id, 'date_paiement' => $date_paiement, 'code_erreur' => $erreur_code, 'erreur' => $erreur, 'log' => var_export($response, true))); } // Create a charge if needed: this will charge the user's card try { // If we have a Customer if ($customer and $customer->id) { $desc_charge['customer'] = $customer->id; $response['pay_id'] = $customer->id; // permet de faire de nouveau paiement sans saisie CB unset($desc_charge['source']); } if ($desc_charge['amount']) { $charge = \Stripe\Charge::create($desc_charge); // pour les logs en cas d'echec $r = $charge->getLastResponse()->json; $response = array_merge($response, $r); if (!$charge) { $erreur = "Erreur creation charge"; $erreur_code = "charge_failed"; } elseif (!$charge['paid']) { $erreur_code = 'not_paid'; $erreur = 'echec paiement stripe'; if ($charge['failure_code'] or $charge['failure_message']) { $erreur_code = $charge['failure_code']; $erreur = $charge['failure_message']; } } } } catch (\Stripe\Error\Card $e) { // Since it's a decline, \Stripe\Error\Card will be caught $body = $e->getJsonBody(); $err = $body['error']; list($erreur_code, $erreur) = stripe_error_code($err); } catch (Exception $e) { if ($body = $e->getJsonBody()) { $err = $body['error']; list($erreur_code, $erreur) = stripe_error_code($err); } else { $erreur = $e->getMessage(); $erreur_code = 'error'; } } // si abonnement : on a un customer et un plan, creer la subscription if ($is_abo) { if ($plan and $customer) { $desc_sub = array('customer' => $customer->id, 'plan' => $plan->id, 'metadata' => array('id_transaction' => $id_transaction)); try { $sub = \Stripe\Subscription::create($desc_sub); if (!$sub) { $erreur = "Erreur creation subscription"; $erreur_code = "sub_failed"; } else { $response['abo_uid'] = $sub->id; } } catch (Exception $e) { if ($body = $e->getJsonBody()) { $err = $body['error']; list($erreur_code, $erreur) = stripe_error_code($err); } else { $erreur = $e->getMessage(); $erreur_code = 'error'; } } } else { $erreur = "Erreur creation subscription (plan or customer missing)"; $erreur_code = "sub_failed"; } } } if ($erreur or $erreur_code) { // regarder si l'annulation n'arrive pas apres un reglement (internaute qui a ouvert 2 fenetres de paiement) if ($row['reglee'] == 'oui') { return array($id_transaction, true); } // sinon enregistrer l'absence de paiement et l'erreur return bank_transaction_echec($id_transaction, array('mode' => $mode, 'config_id' => $config_id, 'date_paiement' => $date_paiement, 'code_erreur' => $erreur_code, 'erreur' => $erreur, 'log' => var_export($response, true))); } // Ouf, le reglement a ete accepte // on verifie que le montant est bon ! $montant_regle = 0; if ($charge) { $montant_regle = $charge['amount'] / 100; } elseif ($sub) { $montant_regle = $sub->plan->amount; } if ($montant_regle != $row['montant']) { spip_log($t = "call_response : id_transaction {$id_transaction}, montant regle {$montant_regle}!=" . $row['montant'] . ":" . var_export($charge, true), $mode); // on log ca dans un journal dedie spip_log($t, $mode . '_reglements_partiels'); } if ($charge) { $transaction = $charge['balance_transaction']; $authorisation_id = $charge['id']; } elseif ($sub) { $transaction = $sub->id; $authorisation_id = $plan->id; } $set = array("autorisation_id" => "{$transaction}/{$authorisation_id}", "mode" => "{$mode}/{$config_id}", "montant_regle" => $montant_regle, "date_paiement" => $date_paiement, "statut" => 'ok', "reglee" => 'oui'); if (isset($response['pay_id'])) { $set['pay_id'] = $response['pay_id']; } if (isset($response['abo_uid'])) { $set['abo_uid'] = $response['abo_uid']; } // type et numero de carte ? if ($charge) { if (isset($charge['source']) and $charge['source']['object'] == 'card') { // par defaut on note carte et BIN6 dans refcb $set['refcb'] = ''; if (isset($charge['source']['brand'])) { $set['refcb'] .= $charge['source']['brand']; } if (isset($charge['source']['last4']) and $charge['source']['last4']) { $set['refcb'] .= ' ****' . $charge['source']['last4']; } $set['refcb'] = trim($set['refcb']); // validite de carte ? if (isset($charge['source']['exp_month']) and $charge['source']['exp_year']) { $set['validite'] = $charge['source']['exp_year'] . "-" . str_pad($charge['source']['exp_month'], 2, '0', STR_PAD_LEFT); } } } $response = array_merge($response, $set); // il faudrait stocker le $charge aussi pour d'eventuels retour ? sql_updateq("spip_transactions", $set, "id_transaction=" . intval($id_transaction)); spip_log("call_response : id_transaction {$id_transaction}, reglee", $mode); $regler_transaction = charger_fonction('regler_transaction', 'bank'); $regler_transaction($id_transaction, array('row_prec' => $row)); return array($id_transaction, true); }
/** * Preparation de la requete par cartes * il faut avoir un id_transaction et un transaction_hash coherents * pour se premunir d'une tentative d'appel exterieur * * @param int $id_transaction * @param string $transaction_hash * @param $config * configuration du module * @return array */ function presta_sips_call_request_dist($id_transaction, $transaction_hash, $config) { $mode = 'sips'; if (!is_array($config) or !isset($config['type']) or !isset($config['presta'])) { spip_log("call_request : config invalide " . var_export($config, true), $mode . _LOG_ERREUR); $mode = $config['presta']; } if (!($row = sql_fetsel("*", "spip_transactions", "id_transaction=" . intval($id_transaction) . " AND transaction_hash=" . sql_quote($transaction_hash)))) { spip_log("call_request : transaction {$id_transaction} / {$transaction_hash} introuvable", $mode . _LOG_ERREUR); return ""; } if (!$row['id_auteur'] and isset($GLOBALS['visiteur_session']['id_auteur']) and $GLOBALS['visiteur_session']['id_auteur']) { sql_updateq("spip_transactions", array("id_auteur" => intval($row['id_auteur'] = $GLOBALS['visiteur_session']['id_auteur'])), "id_transaction=" . intval($id_transaction)); } $mail = bank_porteur_email($row); // passage en centimes d'euros : round en raison des approximations de calcul de PHP $montant = intval(round(100 * $row['montant'], 0)); $merchant_id = $config['merchant_id']; $service = $config['service']; $certif = $config['certificat']; // Affectation des parametres obligatoires $parm = array(); $parm['merchant_id'] = $merchant_id; $parm['merchant_country'] = "fr"; $parm['currency_code'] = "978"; $parm['amount'] = $montant; $parm['customer_id'] = intval($row['id_auteur']) ? $row['id_auteur'] : $row['auteur_id']; $parm['order_id'] = intval($id_transaction); $parm['transaction_id'] = bank_transaction_id($row); $parm['customer_email'] = substr($mail, 0, 128); $parm['normal_return_url'] = bank_url_api_retour($config, 'response'); $parm['cancel_return_url'] = bank_url_api_retour($config, 'cancel'); $parm['automatic_response_url'] = bank_url_api_retour($config, 'autoresponse'); // ajouter les logos de paiement si configures foreach (array('logo_id', 'logo_id2', 'advert') as $logo_key) { if (isset($config[$logo_key]) and $file = $config[$logo_key]) { $parm[$logo_key] = $file; } } // Les valeurs suivantes ne sont utilisables qu'en pre-production // Elles necessitent l'installation de vos fichiers sur le serveur de paiement // // $parm="$parm normal_return_logo="; // $parm="$parm cancel_return_logo="; // $parm="$parm submit_logo="; // $parm="$parm logo_id="; // $parm="$parm logo_id2="; // $parm="$parm advert="; // $parm="$parm background_id="; // $parm="$parm templatefile="; include_spip("presta/sips/inc/sips"); $res = sips_request($service, $parm, $certif); $res['service'] = $service; return $res; }
/** * Generer le contexte pour le formulaire de requete de paiement * il faut avoir un id_transaction et un transaction_hash coherents * pour se premunir d'une tentative d'appel exterieur * * @param int $id_transaction * @param string $transaction_hash * @param array $config * array cartes * @param string $action * REGISTER : enregsitrement simple et on recupere un numero d'abonne/identifiant * REGISTER_UPDATE : mise a jour des coordonnes liees au numero d'abonne * REGISTER_PAY : payer et enregistrer * REGISTER_SUBSCRIBE : abonner et enregistrer * PAYMENT : avec un identifiant optionnel qui evite de resaisir les numeros de CB * SUBSCRIBE : abonner avec un identifiant qui evite de resaisir les numeros de CB * @param array $options * string $abo_uid : utile pour les actions REGISTER_UPDATE, PAYMENT, SUBSCRIBE * int $delay : nb jours avant effet du paiement ponctuel (vads_capture_delay) * int $delay_subscribe : nb jours avant effet de l'abonnement (vads_sub_effect_date) * @return array */ function presta_systempay_call_request_dist($id_transaction, $transaction_hash, $config = array(), $action = "PAYMENT", $options = array()) { $mode = $config['presta']; if (isset($config['mode_test']) and $config['mode_test']) { $mode .= "_test"; } $cartes = array('CB', 'VISA', 'MASTERCARD', 'E-CARTEBLEUE'); if (isset($config['cartes']) and $config['cartes']) { $cartes = $config['cartes']; } $c = $config; $c['type'] = strpos($action, "SUBSCRIBE") !== false ? 'abo' : 'acte'; $cartes_possibles = systempay_available_cards($c); $options = array_merge(array('abo_uid' => '', 'delay' => 0, 'delay_subscribe' => 0), $options); $abo_uid = $options['abo_uid']; if (!in_array($action, array('REGISTER', 'REGISTER_UPDATE', 'REGISTER_PAY', 'REGISTER_SUBSCRIBE', 'REGISTER_PAY_SUBSCRIBE', 'PAYMENT', 'SUBSCRIBE'))) { spip_log("Action {$action} inconnue", $mode . _LOG_ERREUR); return false; } if (in_array($action, array('REGISTER_UPDATE', 'SUBSCRIBE')) and !$abo_uid) { spip_log("Action {$action} : abo_uid manquant pour generer le formulaire", $mode . _LOG_ERREUR); return false; } if (!($row = sql_fetsel("*", "spip_transactions", "id_transaction=" . intval($id_transaction) . " AND transaction_hash=" . sql_quote($transaction_hash)))) { return array(); } if (!$row['id_auteur'] and isset($GLOBALS['visiteur_session']['id_auteur']) and $GLOBALS['visiteur_session']['id_auteur']) { sql_updateq("spip_transactions", array("id_auteur" => intval($row['id_auteur'] = $GLOBALS['visiteur_session']['id_auteur'])), "id_transaction=" . intval($id_transaction)); } include_spip('inc/filtres'); $parm = array(); $parm['vads_site_id'] = $config['SITE_ID']; $parm['vads_ctx_mode'] = $config['mode_test'] ? "TEST" : "PRODUCTION"; $parm['vads_version'] = _SYSTEMPAY_VERSION; $parm['vads_trans_id'] = bank_transaction_id($row); $parm['vads_order_id'] = $row['id_transaction']; // il ne faut pas utiliser la date de la transaction qui peut dater de plusieurs heures/jour // mais la date de generation du formulaire de paiement, car il y a une verif de coherence chez payzen // la demande doit arriver entre -30min et +2h30 par rapport a cette date $parm['vads_trans_date'] = gmdate("YmdHis"); $parm['vads_page_action'] = $action; if ($abo_uid) { $parm['vads_identifier'] = $abo_uid; } $parm['vads_action_mode'] = "INTERACTIVE"; $parm['vads_payment_config'] = "SINGLE"; //$parm['vads_capture_delay'] = 0; //$parm['vads_validation_mode'] = 0; // passage en centimes d'euros : round en raison des approximations de calcul de PHP $parm['vads_currency'] = 978; $parm['vads_amount'] = intval(round(100 * $row['montant'], 0)); $parm['vads_language'] = $GLOBALS['spip_lang']; // recuperer l'email $parm['vads_cust_email'] = bank_porteur_email($row); // si il y a du SEPA, il faut si possible nom et prenom if (in_array('SDD', $cartes) and isset($cartes_possibles['SDD'])) { $parm['vads_cust_first_name'] = bank_porteur_prenom($row); $parm['vads_cust_last_name'] = bank_porteur_nom($row); } // nom et url de la boutique $parm['vads_shop_url'] = $GLOBALS['meta']['adresse_site']; $parm['vads_shop_name'] = textebrut($GLOBALS['meta']['nom_site']); // Urls de retour $parm['vads_return_mode'] = "GET"; // POST pour privacy et ne pas loger par Apache, mais GET pour ne pas avoir un message d'avertissement au retour utilisateur $parm['vads_url_return'] = bank_url_api_retour($config, "response"); $parm['vads_url_cancel'] = bank_url_api_retour($config, "cancel"); $url_check = bank_url_api_retour($config, "autoresponse"); if (strpos($url_check, "localhost") === false) { $parm['vads_url_check'] = bank_url_api_retour($config, "autoresponse"); } $now = time(); // c'est un abonnement if (in_array($action, array('REGISTER_PAY_SUBSCRIBE', 'REGISTER_SUBSCRIBE', 'SUBSCRIBE'))) { // on decrit l'echeance if ($decrire_echeance = charger_fonction("decrire_echeance", "abos", true) and $echeance = $decrire_echeance($id_transaction)) { if ($echeance['montant'] > 0) { // on commence maintenant $date_effet = $now; if (isset($echeance['date_start']) and $echeance['date_start'] and strtotime($echeance['date_start']) > $now) { $date_effet = strtotime($echeance['date_start']); } if (isset($options['delay_subscribe']) and $options['delay_subscribe']) { $date_effet = strtotime("+" . $options['delay_subscribe'] . " DAY", $date_effet); } $parm['vads_sub_effect_date'] = gmdate("Ymd", $date_effet); $nb = 0; $nb_init = 0; if (isset($echeance['count'])) { $nb = intval($echeance['count']); } if (isset($echeance['count_init'])) { $nb_init = intval($echeance['count_init']); } // dans le cas Payzen $nb est le nombre total d'echeances, en incluant les echeances initiales if ($nb and $nb_init) { $nb += $nb_init; } $freq = "MONTHLY"; if (isset($echeance['freq']) and $echeance['freq'] == 'yearly') { $freq = "YEARLY"; } // si on fait le premier paiement maintenant, il ne faut pas le compter dans l'abonnement if ($action === "REGISTER_PAY_SUBSCRIBE") { // on decale l'effet a +1mois ou +1an $parm['vads_sub_effect_date'] = gmdate("Ymd", strtotime("+1 " . substr($freq, 0, -2), $date_effet)); // on le decompte du nombre d'echeance if ($nb_init > 0) { $nb_init--; } if ($nb > 0) { $nb--; } } // montant de l'echeance $parm['vads_sub_amount'] = intval(round(100 * $echeance['montant'], 0)); // meme devise que le paiement initial $parm['vads_sub_currency'] = $parm['vads_currency']; // regle de recurrence $rule = "RRULE:"; $rule .= "FREQ={$freq};"; if ($freq == "MONTHLY") { $monthday = intval(substr($parm['vads_sub_effect_date'], -2)); switch ($monthday) { case 31: $rule .= "BYMONTHDAY=28,29,30,31;BYSETPOS=-1;"; break; case 30: $rule .= "BYMONTHDAY=28,29,30;BYSETPOS=-1;"; break; case 29: $rule .= "BYMONTHDAY=28,29;BYSETPOS=-1;"; break; default: $rule .= "BYMONTHDAY={$monthday};"; break; } } if ($nb > 0) { $rule .= "COUNT={$nb};"; } $parm['vads_sub_desc'] = $rule; if ($nb_init > 0) { $parm['vads_sub_init_amount_number'] = $nb_init; $parm['vads_sub_init_amount'] = $parm['vads_amount']; if (isset($echeance['montant_init']) and ($m = intval(round(100 * $echeance['montant_init'], 0))) > 0) { $parm['vads_sub_init_amount'] = $m; } } } } } if (in_array($action, array('REGISTER_PAY', 'REGISTER_PAY_SUBSCRIBE', 'PAYMENT'))) { if ($options['delay']) { $parm['vads_capture_delay'] = $options['delay']; } } // s'annoncer fierement : SPIP + bank vx $parm['vads_contrib'] = bank_annonce_version_plugin(); #$parm['vads_redirect_success_timeout'] = 1; #$parm['vads_redirect_success_message'] = "OK"; #$parm['vads_redirect_error_timeout'] = 1; #$parm['vads_redirect_error_message'] = "Echec"; // cas particulier de la carte SDD : // si on fait un REGISTER_SUBSCRIBE ou un SUBSCRIBE il faut un delai minimum de 13j sur le subscribe // pas de probleme avec le REGISTER_PAY_SUBSCRIBE car le subscribe est decale d'une echeance dans ce cas if (isset($cartes_possibles['SDD']) and in_array('SDD', $cartes) and (in_array($action, array('REGISTER_SUBSCRIBE', 'SUBSCRIBE')) and intval($options['delay_subscribe']) < 13)) { $action_sdd = $action; $config_sdd = $config; $config_sdd['cartes'] = array('SDD'); $options_sdd = $options; $options_sdd['delay_subscribe'] = max($options_sdd['delay_subscribe'], 13); // minimum 13 jours pour un SEPA $contexte = presta_systempay_call_request_dist($id_transaction, $transaction_hash, $config_sdd, $action_sdd, $options_sdd); unset($cartes_possibles['SDD']); } else { $contexte = array('hidden' => array(), 'action' => systempay_url_serveur($config), 'backurl' => url_absolue(self()), 'id_transaction' => $id_transaction, 'transaction_hash' => $transaction_hash); } foreach ($cartes as $carte) { if (isset($cartes_possibles[$carte])) { $parm['vads_payment_cards'] = $carte; $contexte['hidden'][$carte] = systempay_form_hidden($config, $parm); $contexte['logo'][$carte] = $cartes_possibles[$carte]; } } return $contexte; }
/** * Preparation de la requete par cartes * il faut avoir un id_transaction et un transaction_hash coherents * pour se premunir d'une tentative d'appel exterieur * * @param int $id_transaction * @param string $transaction_hash * @param $config * configuration du module * @param string $type * type de paiement : acte ou abo * @return array */ function presta_paybox_call_request_dist($id_transaction, $transaction_hash, $config, $type = "acte") { $mode = 'paybox'; if (!is_array($config) or !isset($config['type']) or !isset($config['presta'])) { spip_log("call_request : config invalide " . var_export($config, true), $mode . _LOG_ERREUR); return ""; } $mode = $config['presta']; if (!($row = sql_fetsel("*", "spip_transactions", "id_transaction=" . intval($id_transaction) . " AND transaction_hash=" . sql_quote($transaction_hash)))) { spip_log("call_request : transaction {$id_transaction} / {$transaction_hash} introuvable", $mode . _LOG_ERREUR); return ""; } $cartes = array('CB', 'VISA', 'EUROCARD_MASTERCARD', 'E_CARD'); if (isset($config['cartes']) and is_array($config['cartes']) and $config['cartes']) { $cartes = $config['cartes']; } if (!$row['id_auteur'] and isset($GLOBALS['visiteur_session']['id_auteur']) and $GLOBALS['visiteur_session']['id_auteur']) { sql_updateq("spip_transactions", array("id_auteur" => intval($row['id_auteur'] = $GLOBALS['visiteur_session']['id_auteur'])), "id_transaction=" . intval($id_transaction)); } $mail = bank_porteur_email($row); // passage en centimes d'euros : round en raison des approximations de calcul de PHP $montant = intval(round(100 * $row['montant'], 0)); if (strlen($montant) < 3) { $montant = str_pad($montant, 3, '0', STR_PAD_LEFT); } // Affectation des parametres obligatoires // seuls les PBX_ sont envoyees dans le formulaire $parm = $config; // cas de PBX_RANG : paybox fournit 001 mais il faut envoyer 01 au serveur $parm['PBX_RANG'] = str_pad(intval($parm['PBX_RANG']), 2, '0', STR_PAD_LEFT); $parm['PBX_OUTPUT'] = "C"; // recuperer uniquement les hidden $parm['PBX_LANGUE'] = "FRA"; $parm['PBX_DEVISE'] = "978"; $parm['PBX_TOTAL'] = $montant; $parm['PBX_PORTEUR'] = defined('_PBX_PORTEUR') ? _PBX_PORTEUR : $mail; $parm['PBX_CMD'] = intval($id_transaction); // si le porteur est generique, on ajoute l'email au numero de commande // pour la tracabilite dans l'admin paybox if (defined('_PBX_PORTEUR')) { $parm['PBX_CMD'] .= "/" . $mail; } // temps de validite de la page de paiement paybox (par defaut 900s) if (defined('_PBX_DISPLAY')) { $parm['PBX_DISPLAY'] = _PBX_DISPLAY; } $parm['PBX_EFFECTUE'] = bank_url_api_retour($config, "response"); $parm['PBX_REFUSE'] = bank_url_api_retour($config, "cancel"); $parm['PBX_ANNULE'] = bank_url_api_retour($config, "cancel"); $parm['PBX_REPONDRE_A'] = bank_url_api_retour($config, "autoresponse"); $parm['PBX_RETOUR'] = 'montant:M;id_transaction:R;auth:A;trans:S;abo:B;erreur:E;carte:C;BIN6:N;valid:D;'; if ($type == 'abo' and $config['type'] !== 'acte') { // on decrit l'echeance, en indiquant qu'on peut la gerer manuellement grace a PayBoxDirectPlus if ($decrire_echeance = charger_fonction("decrire_echeance", "abos", true) and $echeance = $decrire_echeance($id_transaction, false)) { if ($echeance['montant'] > 0) { $montant_echeance = str_pad(intval(round(100 * $echeance['montant'])), 10, "0", STR_PAD_LEFT); // si plus d'une echeance initiale prevue on ne sait pas faire avec Paybox if (isset($echeance['count_init']) and $echeance['count_init'] > 1) { spip_log("Transaction #{$id_transaction} : nombre d'echeances init " . $echeance['count_init'] . ">1 non supporte", $mode . _LOG_ERREUR); return ""; } // infos de l'abonnement : // montant identique recurrent, frequence mensuelle ou annuelle, a date anniversaire, sans delai $freq = "01"; if (isset($echeance['freq']) and $echeance['freq'] == 'yearly') { $freq = "12"; } $nbpaie = "00"; if (isset($echeance['count']) and $n = intval($echeance['count'])) { // paybox ne compte pas la premiere echeance, donc comptee ici (car pas dans count_init) il faut la deduire if (!isset($echeance['count_init']) or !$echeance['count_init']) { $n--; } if ($n and $n < 100) { $nbpaie = str_pad($n, 2, "0", STR_PAD_LEFT); } } $parm['PBX_CMD'] .= "IBS_2MONT{$montant_echeance}" . "IBS_NBPAIE{$nbpaie}" . "IBS_FREQ{$freq}" . "IBS_QUAND00"; } else { $parm['PBX_RETOUR'] .= 'ppps:U;'; } } } // fermer le retour avec la signature $parm['PBX_RETOUR'] .= 'sign:K'; //var_dump($parm); include_spip('inc/filtres_mini'); // url_absolue $contexte = array('hidden' => array(), 'action' => paybox_url_paiment($config), 'backurl' => url_absolue(self()), 'id_transaction' => $id_transaction); // forcer le type de config pour n'avoir que les cartes possibles en cas d'abonnement $config['type'] = $type; $cartes_possibles = paybox_available_cards($config); foreach ($cartes as $carte) { if (isset($cartes_possibles[$carte])) { $parm['PBX_TYPEPAIEMENT'] = 'CARTE'; $parm['PBX_TYPECARTE'] = $carte; $contexte['hidden'][$carte] = paybox_form_hidden($parm); $contexte['logo'][$carte] = $cartes_possibles[$carte]; } } return $contexte; }
/** * Generer le contexte pour le formulaire de requete de paiement * il faut avoir un id_transaction et un transaction_hash coherents * pour se premunir d'une tentative d'appel exterieur * * @param int $id_transaction * @param string $transaction_hash * @param $config * configuration du module * @return array */ function presta_ogone_call_request_dist($id_transaction, $transaction_hash, $config) { if (!($row = sql_fetsel("*", "spip_transactions", "id_transaction=" . intval($id_transaction) . " AND transaction_hash=" . sql_quote($transaction_hash)))) { return array(); } if (!$row['id_auteur'] and isset($GLOBALS['visiteur_session']['id_auteur']) and $GLOBALS['visiteur_session']['id_auteur']) { sql_updateq("spip_transactions", array("id_auteur" => intval($row['id_auteur'] = $GLOBALS['visiteur_session']['id_auteur'])), "id_transaction=" . intval($id_transaction)); } $cartes = array('VISA', 'MasterCard', 'American Express'); if (isset($config['cartes']) and is_array($config['cartes']) and $config['cartes']) { $cartes = $config['cartes']; } include_spip('inc/filtres'); $contexte = array(); $contexte['PSPID'] = $config['PSPID']; $contexte['orderID'] = $id_transaction . "/" . modulo($row['transaction_hash'], 999999); $contexte['operation'] = "SAL"; // c'est un paiement a l'acte immediat // passage en centimes d'euros : round en raison des approximations de calcul de PHP $contexte['currency'] = "EUR"; $contexte['amount'] = intval(round(100 * $row['montant'], 0)); #if (strlen($montant)<3) # $montant = str_pad($montant,3,'0',STR_PAD_LEFT); $contexte['language'] = ogone_language_code($GLOBALS['spip_lang']); // recuperer l'email $contexte['EMAIL'] = bank_porteur_email($row); $contexte['CN'] = ""; $contexte['ownerZIP'] = ""; $contexte['owneraddress'] = ""; $contexte['ownercty'] = ""; $contexte['ownertown'] = ""; $contexte['ownertelno'] = ""; // Urls de retour include_spip("inc/bank"); $contexte['accepturl'] = bank_url_api_retour($config, 'response', "id={$id_transaction};{$transaction_hash}"); $contexte['declineurl'] = bank_url_api_retour($config, 'cancel', "id={$id_transaction};{$transaction_hash}"); $contexte['cancelurl'] = bank_url_api_retour($config, 'cancel', "id={$id_transaction};{$transaction_hash}"); $contexte['exceptionurl'] = bank_url_api_retour($config, 'response', "id={$id_transaction};{$transaction_hash}"); $hidden = ""; foreach ($contexte as $k => $v) { $hidden .= "<input type='hidden' name='{$k}' value='" . str_replace("'", "'", $v) . "' />"; } include_spip('inc/filtres_mini'); $contexte = array('hidden' => $hidden, 'action' => ogone_url_serveur($config), 'backurl' => url_absolue(self()), 'id_transaction' => $id_transaction, 'transaction_hash' => $transaction_hash); $cartes_possibles = ogone_available_cards($config); $contexte['cards'] = array(); foreach ($cartes as $carte) { if (isset($cartes_possibles[$carte])) { $contexte['cards'][$carte] = $cartes_possibles[$carte]; } } return $contexte; }
/** * Preparation de la requete par cartes * il faut avoir un id_transaction et un transaction_hash coherents * pour se premunir d'une tentative d'appel exterieur * * @param int $id_transaction * @param string $transaction_hash * @param $config * configuration du module * @param string $type * type de paiement : acte ou abo * @return array */ function presta_stripe_call_request_dist($id_transaction, $transaction_hash, $config, $type = "acte") { $mode = 'stripe'; if (!is_array($config) or !isset($config['type']) or !isset($config['presta'])) { spip_log("call_request : config invalide " . var_export($config, true), $mode . _LOG_ERREUR); return ""; } $mode = $config['presta']; if (isset($config['mode_test']) and $config['mode_test']) { $mode .= "_test"; } if (!($row = sql_fetsel("*", "spip_transactions", "id_transaction=" . intval($id_transaction) . " AND transaction_hash=" . sql_quote($transaction_hash)))) { spip_log("call_request : transaction {$id_transaction} / {$transaction_hash} introuvable", $mode . _LOG_ERREUR); return ""; } if (!$row['id_auteur'] and isset($GLOBALS['visiteur_session']['id_auteur']) and $GLOBALS['visiteur_session']['id_auteur']) { sql_updateq("spip_transactions", array("id_auteur" => intval($row['id_auteur'] = $GLOBALS['visiteur_session']['id_auteur'])), "id_transaction=" . intval($id_transaction)); } // si c'est un abonnement, verifier qu'on saura le traiter vu les limitations de Stripe // c'est un abonnement if ($type === 'abo') { // on decrit l'echeance if ($decrire_echeance = charger_fonction("decrire_echeance", "abos", true) and $echeance = $decrire_echeance($id_transaction)) { if ($echeance['montant'] > 0) { // si plus d'une echeance initiale prevue on ne sait pas faire avec Stripe if (isset($echeance['count_init']) and $echeance['count_init'] > 1) { spip_log("Transaction #{$id_transaction} : nombre d'echeances init " . $echeance['count_init'] . ">1 non supporte", $mode . _LOG_ERREUR); return ""; } // si nombre d'echeances limitees, on ne sait pas faire avec Stripe if (isset($echeance['count']) and $echeance['count'] > 0) { spip_log("Transaction #{$id_transaction} : nombre d'echeances " . $echeance['count'] . ">0 non supporte", $mode . _LOG_ERREUR); return ""; } if (isset($echeance['date_start']) and $echeance['date_start'] and strtotime($echeance['date_start']) > time()) { spip_log("Transaction #{$id_transaction} : date_start " . $echeance['date_start'] . " non supportee", $mode . _LOG_ERREUR); return ""; } } } } $email = bank_porteur_email($row); // passage en centimes d'euros : round en raison des approximations de calcul de PHP $montant = intval(round(100 * $row['montant'], 0)); if (strlen($montant) < 3) { $montant = str_pad($montant, 3, '0', STR_PAD_LEFT); } include_spip('inc/filtres_mini'); // url_absolue $contexte = array('id_transaction' => $id_transaction, 'transaction_hash' => $transaction_hash); if ($type === 'abo') { $contexte['abo'] = 1; } $contexte['sign'] = bank_sign_response_simple($mode, $contexte); $action = bank_url_api_retour($config, "response"); foreach ($contexte as $k => $v) { $action = parametre_url($action, $k, $v); } $contexte['action'] = $action; $contexte['email'] = $email; $contexte['amount'] = $montant; $contexte['currency'] = 'eur'; $contexte['key'] = $config['mode_test'] ? $config['PUBLISHABLE_KEY_test'] : $config['PUBLISHABLE_KEY']; $contexte['name'] = textebrut($GLOBALS['meta']['nom_site']); $contexte['description'] = _T('bank:titre_transaction') . '#' . $id_transaction; $contexte['image'] = find_in_path('img/logo-paiement-stripe.png'); if (!$contexte['image']) { $chercher_logo = charger_fonction('chercher_logo', 'inc'); if ($logo = $chercher_logo(0, 'site')) { $logo = reset($logo); $contexte['image'] = $logo; } } if ($contexte['image']) { $contexte['image'] = url_absolue($contexte['image']); } return $contexte; }
/** * Generer le contexte pour le formulaire de requete de paiement * il faut avoir un id_transaction et un transaction_hash coherents * pour se premunir d'une tentative d'appel exterieur * * @param int $id_transaction * @param string $transaction_hash * @param $config * configuration du module * @return array */ function presta_cmcic_call_request_dist($id_transaction, $transaction_hash, $config) { if (!($row = sql_fetsel("*", "spip_transactions", "id_transaction=" . intval($id_transaction) . " AND transaction_hash=" . sql_quote($transaction_hash)))) { return array(); } include_spip('inc/filtres'); $contexte = array(); $oTpe = new CMCIC_Tpe($config, strtoupper($GLOBALS['spip_lang'])); if (!$oTpe->isOK) { return false; } $oHmac = new CMCIC_Hmac($oTpe); // Control String for support $CtlHmac = sprintf(_CMCIC_CTLHMAC, $oTpe->sVersion, $oTpe->sNumero, $oHmac->computeHmac(sprintf(_CMCIC_CTLHMACSTR, $oTpe->sVersion, $oTpe->sNumero))); // Currency : ISO 4217 compliant $devise = "EUR"; // Amount : format "xxxxx.yy" (no spaces) $montant = $row['montant']; $contexte['version'] = $oTpe->sVersion; $contexte['TPE'] = $oTpe->sNumero; // transaction date : format d/m/y:h:m:s $contexte['date'] = date("d/m/Y:H:i:s"); $contexte['montant'] = $montant . $devise; // Reference: unique, alphaNum (A-Z a-z 0-9), 12 characters max $contexte['reference'] = substr($transaction_hash, 0, 12); $contexte['lgue'] = $oTpe->sLangue; $contexte['societe'] = $oTpe->sCodeSociete; // on transmet dans le texte libre les données id_transaction & hash // pour les avoir dans le retour URL CGI2 qui est une url à donner à la banque // et qui n'a pas connaissance autrement de notre id_transaction et hash :( // URL CGI2 à donner à la banque : // http(s)://votresite.org/?action=bank_autoresponse&bankp=cmcic $contenu = array('id' => $id_transaction, 'hash' => $transaction_hash, 'lang' => $GLOBALS['spip_lang'], 'contenu' => $row['contenu']); // texte-libre doit etre protege car le formulaire est parfois reinjecte par Cmcic // dans une page de redirection pour les mobiles $contexte['texte-libre'] = urlencode(serialize($contenu)); $contexte['mail'] = bank_porteur_email($row); // Data to certify $PHP1_FIELDS = sprintf(_CMCIC_CGI1_FIELDS, $contexte['TPE'], $contexte['date'], $montant, $devise, $contexte['reference'], $contexte['texte-libre'], $oTpe->sVersion, $oTpe->sLangue, $oTpe->sCodeSociete, $contexte['mail'], "", "", "", "", "", "", "", "", "", ""); // MAC computation $contexte['MAC'] = $oHmac->computeHmac($PHP1_FIELDS); // Urls de retour. // La banque poste d'abord sur l'URL CGI2 (cf cmcic/config.php) qui doit traiter // le paiement positif et en attend une réponse (texte). // Puis, elle présente sur la banque au choix ces urls pour revenir sur le site // - retour OK si le paiement s'est bien déroulé $contexte['url_retour_ok'] = bank_url_api_retour($config, "response", "id={$id_transaction};{$transaction_hash}"); // - retour err si le paiement a été refusé $contexte['url_retour_err'] = bank_url_api_retour($config, "cancel", "id={$id_transaction};{$transaction_hash}"); // - retour (bouton Annuler) si le bonhomme décide d'abandonner le paiement $contexte['url_retour'] = $contexte['url_retour_ok']; $hidden = ""; foreach ($contexte as $k => $v) { $hidden .= "<input type='hidden' name='{$k}' value='" . str_replace("'", "'", $v) . "' />"; } include_spip('inc/filtres_mini'); $contexte = array('hidden' => $hidden, 'action' => cmcic_url_serveur($config), 'backurl' => url_absolue(self()), 'id_transaction' => $id_transaction, 'transaction_hash' => $transaction_hash); return $contexte; }