Ejemplo n.º 1
1
/**
 * 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);
}
Ejemplo n.º 2
0
/**
 * 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;
}
Ejemplo n.º 3
0
/**
 * 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;
}
Ejemplo n.º 4
0
/**
 * 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;
}
Ejemplo n.º 5
0
/**
 * 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("'", "&#39;", $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;
}
Ejemplo n.º 6
0
/**
 * 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;
}
Ejemplo n.º 7
0
/**
 * 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("'", "&#39;", $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;
}