/** * il faut avoir un id_transaction et un transaction_hash coherents * pour se premunir d'une tentative d'appel exterieur * * @param array $config * @param null|array $response * @return array */ function presta_gratuit_call_response_dist($config, $response = null) { $mode = $config['presta']; // recuperer la reponse en post et la decoder, en verifiant la signature if (!$response) { $response = bank_response_simple($mode); } if (!isset($response['id_transaction']) or !isset($response['transaction_hash'])) { return bank_transaction_invalide(0, array('mode' => $mode, 'erreur' => "id_transaction ou transaction_hash absent", 'log' => bank_shell_args($response))); } $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 inconnue", 'log' => bank_shell_args($response))); } if ($transaction_hash != $row['transaction_hash']) { return bank_transaction_invalide($id_transaction, array('mode' => $mode, 'erreur' => "id_transaction {$id_transaction}, hash {$transaction_hash} non conforme", 'log' => bank_shell_args($response))); } // verifier que la commande a bien un total nul, sinon ce mode de paiement n'est pas autorise if (intval($row['montant']) > 0 or floatval($row['montant']) > 0.0) { return bank_transaction_invalide($id_transaction, array('mode' => $mode, 'erreur' => "id_transaction {$id_transaction}, montant " . $row['montant'] . ">0 interdit", 'log' => bank_shell_args($response))); } // OK, on peut accepter le reglement $set = array("mode" => $mode, "montant_regle" => $row['montant'], "date_paiement" => date('Y-m-d H:i:s'), "statut" => 'ok', "reglee" => 'oui'); sql_updateq("spip_transactions", $set, "id_transaction=" . intval($id_transaction)); spip_log("call_resonse : 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); }
/** * Verifier le statut d'une transaction lors du retour de l'internaute * * @param array $config * @param null|array $response * @return array */ function presta_paybox_call_response_dist($config, $response = null) { include_spip('inc/bank'); $mode = $config['presta']; if (!$response) { // recuperer la reponse en post et la decoder $response = paybox_response(); } if (!$response) { return array(0, false); } if ($response['ETAT_PBX'] === 'PBX_RECONDUCTION_ABT') { // c'est un revouvellement initie par paybox // verifier qu'on a pas deja traite cette recurrence ! if ($t2 = sql_fetsel("*", "spip_transactions", "autorisation_id=" . sql_quote($response['trans'] . "/" . $response['auth']))) { $response['id_transaction'] = $t2['id_transaction']; } elseif ($preparer_echeance = charger_fonction('preparer_echeance', 'abos', true)) { // on reinjecte le bon id de transaction ici si fourni if ($id_transaction = $preparer_echeance("uid:" . $response['abo'])) { $response['id_transaction'] = $id_transaction; } else { return bank_transaction_invalide(intval($response['id_transaction']) . 'PBX_RECONDUCTION_ABT', array('mode' => $mode, 'sujet' => 'Echec creation transaction echeance', 'erreur' => "uid:" . $response['abo'] . ' inconnu de $preparer_echeance', 'log' => bank_shell_args($response), 'update' => false, 'send_mail' => true)); } } } // depouillement de la transaction list($id_transaction, $success) = paybox_traite_reponse_transaction($config, $response); if ($response['abo'] and $id_transaction) { // c'est un premier paiement d'abonnement, l'activer if ($response['ETAT_PBX'] !== 'PBX_RECONDUCTION_ABT' and $success) { // date de fin de mois de validite de la carte $date_fin = bank_date_fin_mois(2000 + intval(substr($response['valid'], 0, 2)), substr($response['valid'], 2, 2)); #spip_log('response:'.var_export($response,true),$mode.'db'); #spip_log('date_fin:'.$date_fin,$mode.'db'); // id_transaction contient toute la trame IDB_xx deriere le numero // on ne retient que la valeur entiere $id_transaction = intval($id_transaction); if ($activer_abonnement = charger_fonction('activer_abonnement', 'abos', true)) { $activer_abonnement($id_transaction, $response['abo'], $mode, $date_fin); } } // c'est un renouvellement reussi, il faut repercuter sur l'abonnement if ($response['ETAT_PBX'] === 'PBX_RECONDUCTION_ABT' and $success) { if ($renouveler_abonnement = charger_fonction('renouveler_abonnement', 'abos', true)) { $renouveler_abonnement($id_transaction, $response['abo'], $mode); } } // c'est un renouvellement en echec, il faut le resilier if ($response['ETAT_PBX'] === 'PBX_RECONDUCTION_ABT' and !$success) { if ($resilier = charger_fonction('resilier', 'abos', true)) { $options = array('notify_bank' => false, 'immediat' => true, 'message' => "[bank] Transaction #{$id_transaction} refusee"); $resilier("uid:" . $response['abo'], $options); } } } return array($id_transaction, $success); }
function paybox_shell_args($params) { return bank_shell_args($params); }
/** * il faut avoir un id_transaction et un transaction_hash coherents * pour se premunir d'une tentative d'appel exterieur * * @param array $config * @param null|array $response * @return array */ function presta_credit_call_response_dist($config, $response = null) { $mode = $config['presta']; // recuperer la reponse en post et la decoder, en verifiant la signature if (!$response) { $response = bank_response_simple($mode); } if (!isset($response['id_transaction']) or !isset($response['transaction_hash'])) { return bank_transaction_invalide(0, array('mode' => $mode, 'erreur' => "id_transaction ou transaction_hash absent", 'log' => bank_shell_args($response))); } $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 inconnue", 'log' => bank_shell_args($response))); } if ($transaction_hash != $row['transaction_hash']) { return bank_transaction_invalide($id_transaction, array('mode' => $mode, 'erreur' => "id_transaction {$id_transaction}, hash {$transaction_hash} non conforme", 'log' => bank_shell_args($response))); } // Obtenir la devise. $auteur = $row['auteur']; include_spip('reservations_credits_fonctions'); /*$credit = credit_client('', $row['auteur'], $devise); spip_log("credit : $credit, montant $montant,auteur $auteur", 'credit');*/ if ($id_reservation = $row['id_reservation']) { $donnees = sql_fetsel('spip_reservations_details.devise,reference,email,id_auteur', 'spip_reservations LEFT JOIN spip_reservations_details USING (id_reservation)', 'spip_reservations.id_reservation=' . $id_reservation); $devise = $donnees['devise']; $descriptif = _T('reservation_bank:paiement_reservation', array('id_reservation' => $id_reservation)); } elseif ($id_commande = $row['id_commande']) { $devise = 'EUR'; $descriptif = _T('reservation_bank:paiement_commande', array('id_commande' => $id_commande)); $id_objet = $id_commande; $objet = 'commande'; } else { return bank_transaction_invalide($id_transaction, array('mode' => $mode, 'erreur' => "id_transaction {$id_transaction}, hash {$transaction_hash} objet non connu", 'log' => bank_shell_args($response))); } // Si on trouve un crédit if (isset($row['auteur']) and $email = $row['auteur'] and $credit = credit_client('', $row['auteur'], $devise) and (intval($credit) >= 0 or floatval($var) >= 0.0)) { if (!($montant_reservations_detail_total = _request('montant_reservations_detail_total'))) { include_spip('inc/reservation_bank'); $montant_reservations_detail_total = montant_reservations_detail_total($id_reservation); } $paiement_detail = array(); foreach (array_keys($montant_reservations_detail_total) as $id_reservation_detail) { $paiement_detail[$id_reservation_detail] = _request('montant_reservations_detail_' . $id_reservation_detail); } if (!($montant_regle = array_sum($paiement_detail))) { $montant_regle = $transaction['montant']; } $set = array("mode" => $mode, "montant_regle" => $montant_regle, "date_paiement" => date('Y-m-d H:i:s'), "statut" => 'ok', "reglee" => 'oui'); if (intval($credit) >= intval($row['montant']) or floatval($credit) >= floatval($row['montant'])) { // OK, on peut accepter le reglement $statut = 'reglée'; $res = true; } else { // Le crédit n'est pas suffisant $set['montant_regle'] = $montant_regle; $set['statut'] = 'attente'; $set['reglee'] = 'par'; $statut = 'reglée acompte'; $res = 'wait'; } sql_updateq("spip_transactions", $set, "id_transaction=" . intval($id_transaction)); spip_log("call_response : id_transaction {$id_transaction}, {$statut}", $mode); // Enregistrer un mouvement crédit $action = charger_fonction('editer_objet', 'action'); $reference = $donnes['reference']; $set = array('type' => 'debit', 'email' => $email, 'descriptif' => $descriptif, 'id_reservation' => $id_reservation, 'id_objet' => $id_objet, 'objet' => $objet, 'montant' => $montant_regle, 'devise' => $donnees['devise']); $action('new', 'reservation_credit_mouvement', $set); } else { return bank_transaction_invalide($id_transaction, array('mode' => $mode, 'erreur' => "id_transaction {$id_transaction}, montant " . $row['montant'] . "> pas de crédit diponible", 'log' => bank_shell_args($response))); } $regler_transaction = charger_fonction('regler_transaction', 'bank'); $regler_transaction($id_transaction, array('row_prec' => $row)); return array($id_transaction, $res); }
/** * Traiter l'annulation d'une transaction * * @param array $config * @param int $id_transaction * Identification de la transaction * @param array $response * Réponse de la banque * @param array $row * Ligne de transaction * @param bool|string $erreur * Message d'erreur eventuel * @return array **/ function cmcic_gerer_transaction_annulee($config, $id_transaction, $response, $row, $erreur = true) { $mode = $config['presta']; $config_id = bank_config_id($config); if (isset($config['mode_test']) and $config['mode_test']) { $mode .= "_test"; } // regarder si l'annulation n'arrive pas apres un reglement // (internaute qui a ouvert 2 fenetres de paiement) if ($row['reglee'] != 'oui') { $date_paiement = date('Y-m-d H:i:s'); include_spip('inc/bank'); return bank_transaction_echec($id_transaction, array('mode' => $mode, 'config_id' => $config_id, 'date_paiement' => $date_paiement, 'code_erreur' => $response['motifrefus'], 'erreur' => $erreur === true ? "" : $erreur, 'log' => bank_shell_args($response))); } return array($id_transaction, true); }
/** * Traiter la reponse * @param array $config * @param array $response * @return array */ function systempay_traite_reponse_transaction($config, $response) { #var_dump($response); $mode = $config['presta']; if (isset($config['mode_test']) and $config['mode_test']) { $mode .= "_test"; } $config_id = bank_config_id($config); $id_transaction = $response['vads_order_id']; if (!($row = sql_fetsel("*", "spip_transactions", "id_transaction=" . intval($id_transaction)))) { return bank_transaction_invalide($id_transaction, array('mode' => $mode, 'erreur' => "transaction inconnue", 'log' => bank_shell_args($response))); } $is_sepa = (isset($response['vads_card_brand']) and $response['vads_card_brand'] == "SDD"); $is_payment = true; $is_registering = false; $is_subscribing = false; // si c'est une souscription ou un register, lever les bons flags // si pas de paiement on veut enregistrer les donnees et sortir de la sans generer d'erreur (le paiement arrivera plus tard) if ($response['vads_page_action'] and in_array($response['vads_page_action'], array('REGISTER', 'REGISTER_SUBSCRIBE', 'REGISTER_PAY_SUBSCRIBE', 'SUBSCRIBE'))) { $is_registering = true; if ($response['vads_page_action'] !== 'REGISTER_PAY_SUBSCRIBE') { $is_payment = false; } if ($response['vads_page_action'] !== 'REGISTER') { $is_subscribing = true; } } elseif (in_array($response['vads_url_check_src'], array('BO', 'REC', 'RETRY'))) { if (isset($response['vads_identifier']) and $response['vads_identifier']) { $is_registering = true; } if (isset($response['vads_subscription']) and $response['vads_subscription']) { $is_subscribing = true; } elseif ($is_registering and !isset($response['vads_subscription']) and isset($response['vads_sequence_number']) and $response['vads_sequence_number']) { $is_subscribing = true; if (!$response['vads_card_number']) { $response['vads_card_number'] = 'X_X'; } } } // si c'est un debit, a-t-on bien l'operation attendue ? if ($is_payment and $response['vads_operation_type'] !== "DEBIT" and !in_array($response['vads_trans_status'], array('ABANDONED', 'NOT_CREATED', 'REFUSED'))) { // si la transaction est deja reglee, ne pas la modifier, c'est OK if ($row['statut'] == 'ok') { return array($id_transaction, true); } return bank_transaction_invalide($id_transaction, array('mode' => $mode, 'erreur' => "vads_operation_type=" . $response['vads_operation_type'] . " non prise en charge", 'log' => bank_shell_args($response), 'sujet' => "Operation invalide", 'update' => true)); } // ok, on traite le reglement $date = $response['vads_effective_creation_date']; // si c'est un paiement SEPA, on prend la date de presentation du SEPA comme date de paiement // (date_paiement dans le futur donc) if ($is_sepa) { $date = $response['vads_presentation_date']; } // date paiement et date transaction $t = gmmktime(substr($date, 8, 2), substr($date, 10, 2), substr($date, 12, 2), substr($date, 4, 2), substr($date, 6, 2), substr($date, 0, 4)); $date_paiement = date('Y-m-d H:i:s', $t); $date_transaction = $date_paiement; if (isset($response['vads_presentation_date'])) { $date = $response['vads_trans_date']; $t = gmmktime(substr($date, 8, 2), substr($date, 10, 2), substr($date, 12, 2), substr($date, 4, 2), substr($date, 6, 2), substr($date, 0, 4)); $date_transaction = date('Y-m-d H:i:s', $t); } $erreur = array(systempay_response_code($response['vads_result']), systempay_auth_response_code($response['vads_auth_result'])); $erreur = array_filter($erreur); $erreur = trim(implode(' ', $erreur)); $authorisation_id = $response['vads_auth_number']; $transaction = $response['vads_payment_certificate']; // si c'est un SEPA, on a pas encore la transaction et le numero d'autorisation car il y a un delai avant presentation // (paiement dans le futur) if ($is_sepa and !$transaction) { list($transaction, $authorisation_id) = explode("_", $response['vads_card_number']); } if ($is_payment and !$erreur and !in_array($response['vads_trans_status'], array('AUTHORISED', 'CAPTURED', 'WAITING_AUTHORISATION'))) { $erreur = "vads_trans_status " . $response['vads_trans_status'] . " (!IN AUTHORISED,CAPTURED,WAITING_AUTHORISATION)"; } if (!$erreur and $is_payment and !$transaction) { $erreur = "pas de vads_payment_certificate"; } if (!$erreur and !$authorisation_id) { $erreur = "pas de vads_auth_number"; } if ($erreur) { // 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' => $response['vads_result'], 'erreur' => $erreur, 'log' => bank_shell_args($response), 'send_mail' => intval($response['vads_result']) == 2)); } $set = array("autorisation_id" => "{$authorisation_id}/{$transaction}", "mode" => "{$mode}/{$config_id}"); if ($is_payment) { // Ouf, le reglement a ete accepte // on verifie que le montant est bon ! $montant_regle = $response['vads_effective_amount'] / 100; if ($montant_regle != $row['montant']) { spip_log($t = "call_response : id_transaction {$id_transaction}, montant regle {$montant_regle}!=" . $row['montant'] . ":" . bank_shell_args($response), $mode); // on log ca dans un journal dedie spip_log($t, $mode . '_reglements_partiels'); } $set['montant_regle'] = $montant_regle; $set['date_paiement'] = $date_paiement; $set['statut'] = 'ok'; $set['reglee'] = 'oui'; } else { $set['statut'] = 'attente'; } // si la date de transaction Systempay est anterieure a celle du site - 1h, on la met a jour // (cas ou l'on rejoue a posteriori une notification qui n'a pas marche) if ($date_transaction < $row['date_transaction'] or $date_paiement < $row['date_transaction']) { $set['date_transaction'] = $date_transaction; } // si on a les infos de validite / card number, on les note ici if (isset($response['vads_expiry_year'])) { $set['validite'] = $response['vads_expiry_year'] . "-" . $response['vads_expiry_month']; } if (isset($response['vads_card_brand']) or isset($response['vads_card_number'])) { // par defaut on note brand et number dans refcb // mais ecrase si le paiement a genere un identifiant de paiement // qui peut etre reutilise $set['refcb'] = ''; if (isset($response['vads_card_brand'])) { $set['refcb'] = $response['vads_card_brand']; if ($set['refcb'] === "SDD") { $set['refcb'] = "SEPA"; } // more user friendly } if (isset($response['vads_card_number'])) { $set['refcb'] .= " " . $response['vads_card_number']; } $set['refcb'] = trim($set['refcb']); } // si vads_identifier fourni on le note dans refcb : c'est un identifiant de paiement if (isset($response['vads_identifier']) and $response['vads_identifier']) { $set['pay_id'] = $response['vads_identifier']; } elseif ($is_registering) { // si pas de paiement, on genere un echec if (!$is_payment) { return bank_transaction_echec($id_transaction, array('mode' => $mode, 'config_id' => $config_id, 'date_paiement' => $date_paiement, 'erreur' => "Pas de vads_identifier sur operation " . $response['vads_operation_type'], 'log' => bank_shell_args($response))); } else { // sinon on enregistre l'erreur et on log+mail mais on fini le paiement en OK quand meme $set['erreur'] = "Pas de vads_identifier sur operation " . $response['vads_operation_type']; bank_transaction_invalide($id_transaction, array('mode' => $mode, 'sujet' => 'Echec REGISTER', 'erreur' => $set['erreur'], 'log' => bank_shell_args($response))); } } // si on a un numero d'abonnement on le note dans abo_uid if (isset($response['vads_subscription']) and $response['vads_subscription']) { $set['abo_uid'] = $response['vads_subscription']; } elseif ($is_subscribing) { // si pas de paiement, on genere un echec if (!$is_payment) { return bank_transaction_echec($id_transaction, array('mode' => $mode, 'config_id' => $config_id, 'date_paiement' => $date_paiement, 'erreur' => "Pas de vads_subscription sur operation " . $response['vads_operation_type'], 'log' => bank_shell_args($response))); } else { // sinon on enregistre l'erreur et on log+mail mais on fini le paiement en OK quand meme $set['erreur'] = "Pas de vads_subscription sur operation " . $response['vads_operation_type']; bank_transaction_invalide($id_transaction, array('mode' => $mode, 'sujet' => 'Echec SUBSCRIBE', 'erreur' => $set['erreur'], 'log' => bank_shell_args($response))); } } // OK on met a jour la transaction en base sql_updateq("spip_transactions", $set, "id_transaction=" . intval($id_transaction)); spip_log("call_response : id_transaction {$id_transaction}, reglee", $mode); // si on dispose des informations utilisateurs, les utiliser pour peupler la gloable bank_session // qui peut etre utilisee pour creer le compte client a la volee $var_users = array('vads_cust_email' => 'email', 'vads_cust_name' => 'nom', 'vads_cust_title' => 'civilite'); foreach ($var_users as $kr => $ks) { if (isset($response[$kr]) and $response[$kr]) { if (!isset($GLOBALS['bank_session'])) { $GLOBALS['bank_session'] = array(); } $GLOBALS['bank_session'][$ks] = $response[$kr]; } } // si transaction reglee, on poursuit le processus if (isset($set['reglee']) and $set['reglee'] == 'oui') { $regler_transaction = charger_fonction('regler_transaction', 'bank'); $regler_transaction($id_transaction, array('row_prec' => $row)); $res = true; } else { $row = sql_fetsel("*", "spip_transactions", "id_transaction=" . intval($id_transaction)); pipeline('trig_bank_reglement_en_attente', array('args' => array('statut' => 'attente', 'mode' => $row['mode'], 'type' => $row['abo_uid'] ? 'abo' : 'acte', 'id_transaction' => $id_transaction, 'row' => $row), 'data' => '')); $res = 'wait'; } // c'est un succes return array($id_transaction, $res); }
/** * Verifier le statut d'une transaction lors du retour de l'internaute * * @param array $config * @param null|array $response * @return array */ function presta_stripe_call_response_dist($config, $response = null) { include_spip('inc/bank'); $mode = $config['presta']; if (isset($config['mode_test']) and $config['mode_test']) { $mode .= "_test"; } // recuperer la reponse en post et la decoder, en verifiant la signature if (!$response) { $response = bank_response_simple($mode); } // Stripe token $token = ''; if (isset($_REQUEST['stripeToken'])) { $token = $_REQUEST['stripeToken']; } if (!$response or !$token and !$response['charge']) { spip_log("call_response : token/charge invalide", $mode . _LOG_ERREUR); return array(0, false); } if ($token) { $response['token'] = $token; } if (isset($_REQUEST['stripeTokenType'])) { $response['token_type'] = $_REQUEST['stripeTokenType']; } $recurence = false; // c'est une reconduction d'abonnement ? if ($response['charge_id'] and $response['abo_uid']) { // verifier qu'on a pas deja traite cette recurrence ! if ($t = sql_fetsel("*", "spip_transactions", "autorisation_id LIKE " . sql_quote("%/" . $response['charge_id']))) { $response['id_transaction'] = $t['id_transaction']; $response['transaction_hash'] = $t['transaction_hash']; } elseif ($preparer_echeance = charger_fonction('preparer_echeance', 'abos', true)) { $abo_uid = $response['abo_uid']; $id_transaction = $preparer_echeance("uid:" . $abo_uid); // on reinjecte le bon id de transaction ici si fourni if ($id_transaction) { $response['id_transaction'] = $id_transaction; $response['transaction_hash'] = sql_getfetsel('transaction_hash', 'spip_transactions', 'id_transaction=' . intval($id_transaction)); } else { return bank_transaction_invalide($response['abo_uid'] . '/' . $response['charge_id'], array('mode' => $mode, 'sujet' => 'Echec creation transaction echeance', 'erreur' => "uid:" . $response['abo_uid'] . ' inconnu de $preparer_echeance', 'log' => bank_shell_args($response), 'update' => false, 'send_mail' => true)); } } $recurence = true; } // depouillement de la transaction // stripe_traite_reponse_transaction modifie $response list($id_transaction, $success) = stripe_traite_reponse_transaction($config, $response); if (($recurence or $response['abo']) and $abo_uid = $response['abo_uid'] and $id_transaction) { // c'est un premier paiement d'abonnement, l'activer if (!$recurence) { if ($success) { // date de fin de mois de validite de la carte $date_fin = "0000-00-00 00:00:00"; if (isset($response['validite'])) { list($year, $month) = explode('-', $response['validite']); $date_fin = bank_date_fin_mois($year, $month); } #spip_log('response:'.var_export($response,true),$mode.'db'); #spip_log('date_fin:'.$date_fin,$mode.'db'); if ($activer_abonnement = charger_fonction('activer_abonnement', 'abos', true)) { $activer_abonnement($id_transaction, $abo_uid, $mode, $date_fin); } } } else { // reussi, il faut repercuter sur l'abonnement if ($success) { if ($renouveler_abonnement = charger_fonction('renouveler_abonnement', 'abos', true)) { $renouveler_abonnement($id_transaction, $response['abo'], $mode); } } // echoue, il faut resilier l'abonnement if (!$success) { if ($resilier = charger_fonction('resilier', 'abos', true)) { $options = array('notify_bank' => false, 'immediat' => true, 'message' => "[bank] Transaction #{$id_transaction} refusee"); $resilier("uid:{$abo_uid}", $options); } } } } return array($id_transaction, $success); }
/** * il faut avoir un id_transaction et un transaction_hash coherents * pour se premunir d'une tentative d'appel exterieur * * @param array $config * @param null|array $response * @return array */ function presta_systempay_call_response_dist($config, $response = null) { include_spip('inc/bank'); $mode = $config['presta']; if (!$response) { // recuperer la reponse en post et la decoder $response = systempay_recupere_reponse($config); } if (!$response) { return array(0, false); } $recurence = false; // c'est une reconduction d'abonnement ? if (isset($response['vads_url_check_src']) and in_array($response['vads_url_check_src'], array('REC', 'RETRY')) and isset($response['vads_recurrence_number']) and $response['vads_recurrence_number']) { // si la transaction reference n'existe pas ou a deja ete payee c'est bien une recurence // sinon c'est le paiement de la premiere transaction $trans = sql_fetsel("*", "spip_transactions", "id_transaction=" . intval($response['vads_order_id'])); // pour $response['vads_recurrence_number']=1 on est pas sur, mais au dela c'est une recurence certaine if (!$trans or $trans['statut'] == 'ok' or $response['vads_recurrence_number'] > 1) { // verifier qu'on a pas deja traite cette recurrence ! if ($t2 = sql_fetsel("*", "spip_transactions", "autorisation_id=" . sql_quote($response['vads_order_id'] . "/" . $response['vads_trans_id']))) { $response['vads_auth_number'] = $response['vads_order_id']; $response['vads_payment_certificate'] = $response['vads_trans_id']; $response['vads_order_id'] = $t2['id_transaction']; } elseif ($preparer_echeance = charger_fonction('preparer_echeance', 'abos', true)) { $id_transaction = 0; // si c'est un RETRY qui n'a pas son vads_subscription, on le prend de la transaction si possible $abo_uid = $response['vads_subscription']; if (!$abo_uid and $trans and $trans['abo_uid']) { $abo_uid = $trans['abo_uid']; $response['vads_subscription'] = $abo_uid; } if (!$abo_uid or !($id_transaction = $preparer_echeance("uid:" . $abo_uid))) { // si on avait pas le abo_uid dans la transaction initiale, essayer avec id_transaction if ($trans and !$trans['abo_uid']) { // si c'est la 1ere recurence essayer de reparer la transaction initiale if ($response['vads_recurrence_number'] == 1 and $response['vads_subscription']) { sql_updateq("spip_transactions", array('abo_uid' => $response['vads_subscription']), 'id_transaction=' . intval($trans['id_transaction'])); $trans['abo_uid'] = $response['vads_subscription']; $id_transaction = $preparer_echeance("uid:" . $abo_uid); } // sinon essayer avec le numero de transaction comme numero d'abonnement if (!$id_transaction) { $id_transaction = $preparer_echeance("uid:" . $trans['id_transaction']); if ($id_transaction) { $response['vads_subscription'] = $trans['id_transaction']; } } } } // on reinjecte le bon id de transaction ici si fourni if ($id_transaction) { $response['vads_auth_number'] = $response['vads_order_id']; $response['vads_payment_certificate'] = $response['vads_trans_id']; $response['vads_order_id'] = $id_transaction; } else { return bank_transaction_invalide($response['vads_order_id'] . 'R' . $response['vads_recurrence_number'], array('mode' => $mode, 'sujet' => 'Echec creation transaction echeance', 'erreur' => "uid:" . $response['abo'] . ' inconnu de $preparer_echeance', 'log' => bank_shell_args($response), 'update' => false, 'send_mail' => true)); } } $recurence = true; } } // depouillement de la transaction list($id_transaction, $success) = systempay_traite_reponse_transaction($config, $response); if (($recurence or strpos($response['vads_page_action'], "SUBSCRIBE") !== false or in_array($response['vads_url_check_src'], array('RETRY'))) and isset($response['vads_subscription']) and $abo_uid = $response['vads_subscription'] and $id_transaction) { $transaction = sql_fetsel("*", "spip_transactions", "id_transaction=" . intval($id_transaction)); // c'est le premier paiement de l'abonnement ? if (!$recurence and $success) { // date de fin de mois de validite de la carte (mais pas pour un SEPA qui se reconduit tout seul) $date_fin = "0000-00-00 00:00:00"; if (isset($response['vads_expiry_year']) and isset($response['vads_expiry_month']) and strncmp($transaction['refcb'], 'SEPA', 4) !== 0) { $date_fin = bank_date_fin_mois($response['vads_expiry_year'], $response['vads_expiry_month']); } if ($activer_abonnement = charger_fonction('activer_abonnement', 'abos', true)) { $activer_abonnement($id_transaction, $abo_uid, $mode, $date_fin); } } // c'est un renouvellement reussi, il faut repercuter sur l'abonnement if ($recurence and $success) { if ($renouveler_abonnement = charger_fonction('renouveler_abonnement', 'abos', true)) { $renouveler_abonnement($id_transaction, $abo_uid, $mode); } } // c'est un echec, il faut le resilier, que ce soit la premiere ou la Nieme transaction if (!$success) { if ($resilier = charger_fonction('resilier', 'abos', true)) { $options = array('notify_bank' => false, 'immediat' => true, 'message' => "[bank] Transaction #{$id_transaction} refusee"); $resilier("uid:" . $abo_uid, $options); } } } return array($id_transaction, $success); }
/** * Verifier que la notification de paiement vient bien de paypal ! * @param array $config * @param bool $is_ipn * @return bool */ function paypal_get_response($config, $is_ipn = false) { $mode = $config['presta']; if (isset($config['mode_test']) and $config['mode_test']) { $mode .= "_test"; } $bank_recuperer_post_https = charger_fonction("bank_recuperer_post_https", "inc"); // recuperer le POST $response = array(); foreach ($_POST as $key => $value) { $response[$key] = $value; } if (isset($response['tx']) and $response['tx']) { $tx = $response['tx']; } elseif (isset($response['txn_id']) and $response['txn_id']) { $tx = $response['txn_id']; } else { $tx = _request('tx'); } if (!$tx) { bank_transaction_invalide(0, array('mode' => $mode, 'erreur' => "Reponse sans tx ni txn_id", 'log' => bank_shell_args($response))); return false; } // si on a un $tx et un identity token dans la config on l'utilise de preference (PDT) if ($tx and isset($config['IDENTITY_TOKEN']) and $config['IDENTITY_TOKEN']) { $post_check = array('cmd' => '_notify-synch', 'tx' => $tx, 'at' => $config['IDENTITY_TOKEN']); // envoyer la demande de verif en post // attention, c'est une demande en ssl, il faut avoir un php qui le supporte $url = paypal_url_serveur($config); list($resultat, $erreur, $erreur_msg) = $bank_recuperer_post_https($url, $post_check, isset($response['payer_id']) ? $response['payer_id'] : ''); $resultat = trim($resultat); if (strncmp($resultat, "SUCCESS", 7) == 0) { $resultat = trim(substr($resultat, 7)); $resultat = explode("\n", $resultat); $resultat = array_map("trim", $resultat); $resultat = implode("&", $resultat); parse_str($resultat, $response); return paypal_charset_reponse($response); } // donnees invalides bank_transaction_invalide(0, array('mode' => $mode, 'erreur' => "Retour PDT :{$resultat}:Erreur {$erreur}:{$erreur_msg}:", 'log' => bank_shell_args($response))); return false; } if (!$response) { bank_transaction_invalide(0, array('mode' => $mode, 'sujet' => 'Paypal IDENTITY_TOKEN manquant', 'erreur' => "IDENTITY_TOKEN manquant pour decoder la reponse", 'log' => "tx={$tx}")); return false; } // ce n'est pas l'IPN, on ne sait pas verifier autrement // on "fait confiance" a la reponse telle quelle if (!$is_ipn) { // mais on le log+mail pour information du webmestre bank_transaction_invalide(0, array('mode' => $mode, 'sujet' => 'Transaction non securisee', 'erreur' => "IDENTITY_TOKEN non configure, impossible de verifier la reponse de Paypal (possible fraude)", 'log' => bank_shell_args($response))); // et on utilise la response return paypal_charset_reponse($response); } // notif de debug pour tests /* $response = json_decode ( '{ "residence_country": "US", "invoice": "abc1234", "address_city": "San Jose", "first_name": "John", "payer_id": "TESTBUYERID01", "shipping": "3.04", "mc_fee": "0.44", "txn_id": "611422392", "receiver_email": "*****@*****.**", "quantity": "1", "custom": "xyz123", "payment_date": "22:29:21 28 Oct 2013 PDT", "address_country_code": "US", "address_zip": "95131", "tax": "2.02", "item_name": "something", "address_name": "John Smith", "last_name": "Smith", "receiver_id": "*****@*****.**", "item_number": "AK-1234", "verify_sign": "AiPC9BjkCyDFQXbSkoZcgqH3hpacAaChsjNZq2jHG82F97aoFSMa6SED", "address_country": "United States", "payment_status": "Completed", "address_status": "confirmed", "business": "*****@*****.**", "payer_email": "*****@*****.**", "notify_version": "2.1", "txn_type": "web_accept", "test_ipn": "1", "payer_status": "verified", "mc_currency": "USD", "mc_gross": "12.34", "address_state": "CA", "mc_gross1": "12.34", "payment_type": "echeck", "address_street": "123, any street" }', true ); */ // lire la publication du systeme PayPal et ajouter 'cmd' en tete $post_check = array('cmd' => '_notify-validate'); foreach ($response as $k => $v) { $post_check[$k] = $v; } // envoyer la demande de verif en post // attention, c'est une demande en ssl, il faut avoir un php qui le supporte $c = $config; if (isset($response['test_ipn']) and $response['test_ipn']) { $c['mode_test'] = true; } else { $c['mode_test'] = false; } $url = paypal_url_serveur($c); list($resultat, $erreur, $erreur_msg) = $bank_recuperer_post_https($url, $post_check, isset($post_check['payer_id']) ? $post_check['payer_id'] : ''); if (strncmp(trim($resultat), 'VERIFIE', 7) == 0) { return paypal_charset_reponse($response); } bank_transaction_invalide(0, array('mode' => $mode, 'erreur' => "Retour IPN :{$resultat}:Erreur {$erreur}:{$erreur_msg}:", 'log' => bank_shell_args($response))); return false; }