problema con carrello e transazione carta di credito

ciao,

ho un carrello multilingua in cui il cliente al momento del checkout, deve scegliere la modalità di pagamento.

Per il contrassegno/bonifico/bollettino al submit del checkout faccio eseguire una funzione in cui svuoto il carrello e inserisco l'ordine nel DB. e fin qua tutto bene.

il problema arriva con il pagamento tramite carta di credito.

mi spiego.

al submit del checkout passo tutti dati necessari al sito della banca ( uso bankpass), ma non posso far eseguire la funzione al submit del checkout perchè nel caso in cui il cliente decide di cambiare il metodo di pagamento, ritornando nella pagina del carrello, si troverebbe il carrello vuoto.

allora ho modificato la funzione in modo che se il cliente paga con carta di credito, finchè non è avvenuta la transazione il carrello non viene svuotato.

Dal sito di bankpass a transazione avvenuta, devo specificare un "URLDONE" cioè un url di ritorno al sito.

è a questo punto che, specificato un url di ritorno che punta ad una pagina, ho pensato di utilizzare quella funzione per svuotare il carrello e inserire l'ordine, ma qui avviene il problema, perchè mi perde le sessioni e quindi mi genera degli errori.

posto il file di checkout con lo switch per la modalità di pagamento:

<?php
require_once 'library/config.php';
require_once 'library/cart-functions.php';
require_once 'library/checkout-functions.php';

if (isCartEmpty()) {
   // the shopping cart is still empty
   // so checkout is not allowed
   header('Location: home.php?page=cart');
} else if (isset($_GET['step']) && (int)$_GET['step'] > 0 && (int)$_GET['step'] <= 3) {
   $step = (int)$_GET['step'];

   $includeFile = '';
   if ($step == 1) {
      $includeFile = 'shippingAndPaymentInfo.php';
      $pageTitle   = 'Checkout - Step 1 of 2';
   } else if ($step == 2) {
      $includeFile = 'checkoutConfirmation.php';
      $pageTitle   = 'Checkout - Step 2 of 2';
   } else if ($step == 3) {


switch($_SESSION['id_pag']) {

   case '2':
   case '3':
   case '4':
      $orderId     = saveOrder();
      $orderAmount = getOrderAmount($orderId);

      $_SESSION['orderId'] = $orderId;
      echo"<meta http-equiv=\"Refresh\" content=\"0;url=home.php?page=success\">";
break;

   case '1':
  $orderId     = saveOrder2();
   $orderAmount = getOrderAmount($orderId);
      $_SESSION['orderId'] = $orderId;
             $includeFile = 'bankpass.php';
break;
   }
  }
} else {
   // missing or invalid step number, just redirect
   header('Location: home.php?page=cart');
}

?>
<script type="text/javascript" src="library/checkout.js"></script>
<?php
require_once "../include/$includeFile";

?>

e la funzione che esegue lo svuotamento del carrello e l'inserimento dell'ordine nel DB:

<?php

function saveOrder()
{

$cartContent = getCartContent();

$numItem  = count($cartContent);
    $subTotal = 0;
       for ($i = 0; $i < $numItem; $i++) {
          extract($cartContent[$i]);

   $orderId        = 10;
   $shippingCost = $shipping;

}
   $requiredField = array('hidShippingFirstName', 'hidShippingLastName', 'hidShippingAddress1', 'hidShippingCity', 'hidShippingState',
                                 'hidShippingPostalCode', 'hidShippingPhone', 'hidShippingEmail');


   if (checkRequiredPost($requiredField)) {
       extract($_POST);

      // make sure the first character in the
      // customer and city name are properly upper cased
      $hidShippingFirstName = ucwords($hidShippingFirstName);
      $hidShippingLastName  = ucwords($hidShippingLastName);
      $hidShippingCity      = ucwords($hidShippingCity);


      //$cartContent = getCartContent();
      //$numItem     = count($cartContent);

      if (!empty($_SESSION['comunicati'])) {
         $press = 'S';
      } else {$press = 'N'; }

       $query = mysql_query("SELECT id_pag, pagamento FROM tbl_pagamento WHERE id_pag = {$_SESSION['id_pag']}") or die(mysql_error());
               $row = dbFetchAssoc($query);
                 extract($row);


      // save order & get order id
      $sql = "INSERT INTO tbl_order(od_date, od_last_update, od_shipping_first_name, od_shipping_last_name, od_shipping_address1,
                                    od_shipping_phone, od_shipping_state, od_shipping_city, od_shipping_postal_code, od_shipping_cost, od_shipping_email, od_payment, od_press )
                VALUES (NOW(), NOW(), '$hidShippingFirstName', '$hidShippingLastName', '$hidShippingAddress1',
                     '$hidShippingPhone', '$hidShippingState', '$hidShippingCity', '$hidShippingPostalCode', '$shippingCost', '$hidShippingEmail', '$pagamento', '$press')";

      $result = dbQuery($sql)or die(mysql_error());

      // get the order id
      $orderId = dbInsertId();

      if ($orderId) {
         // save order items
         for ($i = 0; $i < $numItem; $i++) {
            $sql = "INSERT INTO tbl_order_item(od_id, pd_id, od_qty, od_lang_name)
                  VALUES ($orderId, {$cartContent[$i]['pd_id']}, {$cartContent[$i]['ct_qty']}, '{$cartContent[$i]['lang_name']}' )";
            $result = dbQuery($sql)or die(mysql_error());
         }


         // update product stock
         for ($i = 0; $i < $numItem; $i++) {
            $sql = "UPDATE tbl_product
                    SET pd_qty = pd_qty - {$cartContent[$i]['ct_qty']}
                  WHERE pd_id = {$cartContent[$i]['pd_id']}";
            $result = dbQuery($sql);
         }


         // then remove the ordered items from cart
         for ($i = 0; $i < $numItem; $i++) {
            $sql = "DELETE FROM tbl_cart
                    WHERE ct_id = {$cartContent[$i]['ct_id']}";
            $result = dbQuery($sql);
         }
      }
   }

   return $orderId;
}

?>

spero mi possiate dare un idea di come risolvere...

Grazie

inviato 9 anni fa
iTek
iTek
1
X 0 X

Il problema suppongo sia dovuto al fatto che la sessione della pagina di urldone è differente da quella con cui è partito (entra nel sito sessione1->pagamento sessione2 sulla banca->ritorna al sito con nuova sessione).

Così su 2 piedi penso che sia lì il problema.

Per ovviare, anche questa è un'idea di getto va studiata bene, potresti salvare il carrello in un file (e salvare il nome dello stesso in un cookie), svuotare il carrello.

Se il cliente torna indietro per cambiare il pagamento controlli il cookie e ripristini il file riempiendo nuovamente il carrello.

risposto 9 anni fa
LonelyWolf
X 0 X

ok, posso salvare/ripristinare il carrello, ma con le sessioni come faccio?

salvo le sessioni in una...sessione?

 ;D

perchè non ho solo i dati del carrello ma anche la lingua usata dal cliente e anche altre cose.

risposto 9 anni fa
iTek
iTek
1
X 0 X

Se hai la certezza che il problema della sessione sia come io ho "supposto" puoi fare la stessa cosa, salvi nel file anche tutti gli altri dati e li ripristini di nuovo.

risposto 9 anni fa
LonelyWolf
X 0 X

allora ho eliminato dall' URLDONE l'url che puntava a un file per esegure la famosa funzione.

adesso cosa faccio?

<?php
require_once 'library/config.php';
require_once 'library/cart-functions.php';
require_once 'library/checkout-functions.php';

if (isCartEmpty()) {
   // the shopping cart is still empty
   // so checkout is not allowed
   header('Location: home.php?page=cart');
} else if (isset($_GET['step']) && (int)$_GET['step'] > 0 && (int)$_GET['step'] <= 4) {
   $step = (int)$_GET['step'];

   $includeFile = '';
   if ($step == 1) {
      $includeFile = 'shippingAndPaymentInfo.php';
      $pageTitle   = 'Checkout - Step 1 of 2';
   } else if ($step == 2) {
      $includeFile = 'checkoutConfirmation.php';
      $pageTitle   = 'Checkout - Step 2 of 2';
   } else if ($step == 3) {

      $orderId     = saveOrder();
      $orderAmount = getOrderAmount($orderId);

      $_SESSION['orderId'] = $orderId;

      echo"<meta http-equiv=\"Refresh\" content=\"0;url=home.php?page=success\">";
exit;

} else if ($step == 4) {

  $orderId     = saveOrder2();
   $orderAmount = getOrderAmount($orderId);
      $_SESSION['orderId'] = $orderId;
             $includeFile = 'bankpass.php';

}
}
else {
   // missing or invalid step number, just redirect
    //echo"<meta http-equiv=\"Refresh\" content=\"0;url=home.php?page=cart\">";
}

?>
<script type="text/javascript" src="library/checkout.js"></script>
<?php
require_once "../include/$includeFile";

?>

ho aggiunto un $step == 4 per il pagamento della carta di credito in modo che mi crea solo l'di ordine ($orderId) e mi lascia il prodotto nel carrello.

a transazione eseguita URDONE lo faccio puntare al file sopra postato ma a $step == 3 in modo che mi faccia eseguire tutta la funzione.

cosa fa la funzione saveOrder()?

in pratica salva il contenuto del carrello nella tabella ordini e elimina il contenuto del carrello.

il problema però rimane, perchè anche se non ho più gli errori di warning perchè avevo perso le sessioni, in questo caso non fa assolutamente nulla, cioè non salva il contenuto del carrello nella tabella ordini e lo svuota.... :'(

non capisco. Però se anzichè usare la carta di credito come pagamento, utilizzo ad esempio il contrassegno e quindi punta direttamente allo $step == 3, funziona tutto normalmente....

sono disperato! non so da cosa dipenda e cosa fareee!

posto di nuovo la funzione saveOrder()

<?php
function saveOrder()
{

$cartContent = getCartContent();

$numItem  = count($cartContent);
    $subTotal = 0;
       for ($i = 0; $i < $numItem; $i++) {
          extract($cartContent[$i]);

   //$orderId        = 10;
   $shippingCost = $shipping;

}
   $requiredField = array('hidShippingFirstName', 'hidShippingLastName', 'hidShippingAddress1', 'hidShippingCity', 'hidShippingState',
                                 'hidShippingPostalCode', 'hidShippingPhone', 'hidShippingEmail');


   if (checkRequiredPost($requiredField)) {
       extract($_POST);

      // make sure the first character in the
      // customer and city name are properly upper cased
      $hidShippingFirstName = ucwords($hidShippingFirstName);
      $hidShippingLastName  = ucwords($hidShippingLastName);
      $hidShippingCity      = ucwords($hidShippingCity);


      //$cartContent = getCartContent();
      //$numItem     = count($cartContent);

      if (!empty($_SESSION['comunicati'])) {
         $press = 'S';
      } else {$press = 'N'; }

       $query = mysql_query("SELECT id_pag, pagamento FROM tbl_pagamento WHERE id_pag = {$_SESSION['id_pag']}") or die(mysql_error());
               $row = dbFetchAssoc($query);
                 extract($row);


      // save order & get order id
      $sql = "INSERT INTO tbl_order(od_date, od_last_update, od_shipping_first_name, od_shipping_last_name, od_shipping_address1,
                                    od_shipping_phone, od_shipping_state, od_shipping_city, od_shipping_postal_code, od_shipping_cost, od_shipping_email, od_payment, od_press )
                VALUES (NOW(), NOW(), '$hidShippingFirstName', '$hidShippingLastName', '$hidShippingAddress1',
                     '$hidShippingPhone', '$hidShippingState', '$hidShippingCity', '$hidShippingPostalCode', '$shippingCost', '$hidShippingEmail', '$pagamento', '$press')";

      $result = dbQuery($sql)or die(mysql_error());

      // get the order id
      $orderId = dbInsertId();

      if ($orderId) {
         // save order items
         for ($i = 0; $i < $numItem; $i++) {
            $sql = "INSERT INTO tbl_order_item(od_id, pd_id, od_qty, od_lang_name)
                  VALUES ($orderId, {$cartContent[$i]['pd_id']}, {$cartContent[$i]['ct_qty']}, '{$cartContent[$i]['lang_name']}' )";
            $result = dbQuery($sql)or die(mysql_error());
         }


         /*// update product stock
         for ($i = 0; $i < $numItem; $i++) {
            $sql = "UPDATE tbl_product
                    SET pd_qty = pd_qty - {$cartContent[$i]['ct_qty']}
                  WHERE pd_id = {$cartContent[$i]['pd_id']}";
            $result = dbQuery($sql);
         }*/


         // then remove the ordered items from cart
         for ($i = 0; $i < $numItem; $i++) {
            $sql = "DELETE FROM tbl_cart
                    WHERE ct_id = {$cartContent[$i]['ct_id']}";
            $result = dbQuery($sql);
         }
      }
   }

   return $orderId;
}
?>
risposto 9 anni fa
iTek
iTek
1
X 0 X

Allora allo step 3 salva il carrello nella tabella, giusto? Sei sicuro che prima di arrivare al pagamento con carta (step4) lo step 3 venga eseguito?

risposto 9 anni fa
LonelyWolf
X 0 X

no, mi spiego meglio.

nel DB è già presente una tabella "cart" per il carrello.

lo step 3 preleva i dati dalla tabella cart e li inserisce nella tabella "ordini", dopodichè svuota la tabella cart.

e questo va bene per tutti i tipi di pagamento tranne che per la carta di credito.

io ho creato uno step 4 proprio per bypassare lo step 3, per impedire lo svuotamento del carrello prima dell'avvenuta transazione. poi dall URLDONE della banca reindirizzo il browser allo step 3 in modo fare quello che dovrebbe...che invece non fa perchè non lo so..sto ancora indagando.

 :-\

risposto 9 anni fa
iTek
iTek
1
X 0 X

Allora non sarebbe meglio invertire gli step?

cioè per tutti i pagamenti tranne carta step2 -> step 4

con carta step2 ->step3 ->step 4

nel 4 fai cancellare il tutto, controllando prima l'orderid, mi sa che è quello che ti fa perdere il filo, purtroppo non ho il tempo di guardare per bene il codice, ma se crei orderid prima del pagamento dopo non puoi fare un nuovo inserimento che crea un nuovo orderid, rischi di avere un ordine che ha solo un numero a cui fai riferimento mentre un ordine contenente tutti i dati che ha un altro id perso.

risposto 9 anni fa
LonelyWolf
X 0 X
ma se crei orderid prima del pagamento dopo non puoi fare un nuovo inserimento che crea un nuovo orderid, rischi di avere un ordine che ha solo un numero a cui fai riferimento mentre un ordine contenente tutti i dati che ha un altro id perso.

infatti è quello a cui sono giunto a conclusione adesso... :-\

il problema è che a bankpass io devo passare l' orderid come uno degli identificativi del pagamento.

quindi devo crearlo prima di svuotare il carrello...

che casino....

risposto 9 anni fa
iTek
iTek
1
X 0 X
ma se crei orderid prima del pagamento dopo non puoi fare un nuovo inserimento che crea un nuovo orderid, rischi di avere un ordine che ha solo un numero a cui fai riferimento mentre un ordine contenente tutti i dati che ha un altro id perso.

infatti è quello a cui sono giunto a conclusione adesso... :-\

il problema è che a bankpass io devo passare l' orderid come uno degli identificativi del pagamento.

quindi devo crearlo prima di svuotare il carrello...

che casino....

fai una funzione updateorder e gli passi l'id così aggiunge il contenuto!

cmq sono tutti passaggi da verificare per bene prima, mi raccomando

risposto 9 anni fa
LonelyWolf
X 0 X

ciao,

scusami ma non ho capito cosa intendi per fare una funzione updateorder.

io avevo pensato di fare nello step 4, una query di  SELECT  sull'id_order dell'ordine precedente poi aggiungere un +1 al risultato in modo da simulare nello step 4, la creazione dell'id con mysql_insert_id();

in questo modo avrei già l'orderid, ma non so se possa funzionare

risposto 9 anni fa
iTek
iTek
1
modificato 9 anni fa
X 0 X

niente da fare.... :(

non riesco a venire a capo della faccenda...

in step 4 ho creato una funzione ( o meglio, ho semplificato saveOrder() ) che evita di svuotare il carrello e mi estraggo orderId in un modo forse un pò artigianale, ma che funziona:

<?php

function saveOrder2()
{

       $query = mysql_query("SELECT od_id FROM tbl_order ORDER BY od_id DESC LIMIT 0, 1")or die(mysql_error());
            $row = dbFetchAssoc($query);
                 extract($row);

        $orderId = $od_id +1;

   return $orderId;
}
?>

in pratica cosa faccio: mi vado a prendere l'ultimo id degli ordini inseriti e lo incremento di 1 in previsione dell' inserimento diciamo "reale" di $orderId quando il carrello viene svuotato.

però non cambia nulla...

alla banca passo l'id ordine, poi da URLDONE punto a step 3 per far eseguire la funzione, ma non succede nulla. Non svuota il carrello, non inserisce i dati nella tabella ordini e non ho nessun tipo di errore.

mentre se faccio eseguire direttamente lo step 3, tutto funziona regolarmente. >:(

il fatto è che la funzione saveOrder() non fa nulla di particolare.

prende i dati dalla tabella "cart", gli inserisce nella tabella "ordini", crea l'id ordine --> $orderId = mysql_insert_id();, svuota il carrello.

come visto, $orderId viene creato al volo dopo INSERT nella tabella ordini.

ho controllato anche con print_r($_SESSION) e i dati ci sono tutti....

non so più che santi chiamare.... :'(

risposto 9 anni fa
iTek
iTek
1
X 0 X

come prima cosa evita di creare un id in quel modo perchè a regime potrebbe esserci qualcun altro che conferma l'ordine e si prende l'orderid che tu hai ottenuto con +1 (sempre che siano unici gli orderid per tutti e non per utente).

Puoi controllare il valore di $_SESSION['id_pag'] prima e dopo aver pagato con carta?

cmq spero ti aiuti qualk1 altro, da ora stacco e fino a lunedì...

Buon fine settimana

risposto 9 anni fa
LonelyWolf
X 0 X

allora, alla fine sono riuscito a trovare il problema...

in pratica nella funzione saveOrder() c'è un richiamo ad un'altra funzione che controlla i campi hidden provenienti da form ( quindi POST )

$requiredField = array('hidShippingFirstName', 'hidShippingLastName', 'hidShippingAddress1', 'hidShippingCity', 'hidShippingState',
                                 'hidShippingPostalCode', 'hidShippingPhone', 'hidShippingEmail');


   if (checkRequiredPost($requiredField)) {
       extract($_POST);

io arrivavo da URL  per richiamare le funzione saveOrder(), quindi da POST non ricevevo nulla.

Per questo che non succedeva nulla... >:(

ho tolto tutta quella parte e dal form ho messo tutti dati in sessione, in modo che quando ritorno al sito da URLDONE, le sessioni sono ancora lì e cmq controllo con isset se sono settate oppure no.

cosa ne dici?

mi rimane il problema di come recuperare l'id ordine......

risposto 9 anni fa
iTek
iTek
1
modificato 9 anni fa
X 0 X

Sembra una soluzione valida.

Ma l'id dell'ordine non lo puoi salvare anche lui nella sessione?

Oppure passarlo assieme a urldone così ti viene restituito e lo puoi recuperare con $_GET, una cosa tipo:

URLDONE-> www. dominio.it/checked.php

diventa

URLDONE-> www. dominio.it/checked.php?id=idordine

risposto 9 anni fa
LonelyWolf
X 0 X

ciao LonelyWolf,

il problema è che io invio i dati alla banca prima di creare l'id_ordine ( step 4 ).

se ti ricordi l'id_ordine viene creato quando svuoto il carrello ed eseguo la query di INSERT , quindi nel step3.

Ma la mia domanda è anche:

è necessario che l'id_ordine che invio alla banca sia identico a quello che io, amministratore, per gestire gli ordini?

risposto 9 anni fa
iTek
iTek
1
X 0 X

...

Ma la mia domanda è anche:

è necessario che l'id_ordine che invio alla banca sia identico a quello che io, amministratore, per gestire gli ordini?

...

Mi sembrava di ricordare che creavi un idordine prima nel caso di carta di credito.

A questa domanda puoi rispondere solo tu, io non so per quale motivo la banca voglia un idordine; suppongo che sia per la causale dell'addebito sulla carta, così il tuo cliente si vede addebitato un importo per un idordine che può controllare sul sito e a te Amministratore per verificare gli addebiti del servizio.

risposto 9 anni fa
LonelyWolf
X 0 X
Mi sembrava di ricordare che creavi un idordine prima nel caso di carta di credito.

si è vero, però lo creavo in quel modo che non era molto valido:

<?php
$query = mysql_query("SELECT od_id FROM tbl_order ORDER BY od_id DESC LIMIT 0, 1")or die(mysql_error());
            $row = dbFetchAssoc($query);
                 extract($row);

        $orderId = $od_id +1;

   return $orderId;

quindi il problema rimane lo stesso, cioè come fare in modo di avere l'id ordine prima di...averlo creato!

 :buck:

risposto 9 anni fa
iTek
iTek
1
X 0 X

Cambia la funzione di saveorder mettendo un controllo sullo step, se paga con carta di credito fa tutto ma non svuota il carrello (che sarà svuotato da urldone) così ottieni l'idordine corretto.

magari lo dividi in 2: saveorder() che salva il carrello e crea l'ordine, emptycart() che svuota il carrello; saveorder dopo tutto il suo lavoro controlla lo step e se non è 4 (pagamento con carta) chiama emptycart() che svuota il carrello; urldone si limiterà a chiamare emptycart().

Devi sempre però controllare che l'ordine non sia già stato salvato, perchè se inizia i pagamento con carta e torna indietro rischi di avere 2 ordini.

risposto 9 anni fa
LonelyWolf
X 0 X

mmmh, sembra macchinoso

perchè inoltre, se il cliente decide di cambiare la modalità di pagamento, o di aggiungere qualcos'altro al carrello, devo cancellare l'ordine nella tabella ordini ( perchè viene salvato nella tabella ), perchè oltre a urldone devo specificare anche un URLBACK proprio per quel motivo, cioè l'abbandono del pagamento con carta di credito.

ma poi come faccio a sapere se arrivo da urldone e non sto facendo un pagamento con contrassegno?

e se poi il cliente abbandona l'ordine, o si spegne il pc o altro? mi rimane l'ordine inserito, quindi tanto vale eliminare lo step 4 e lasciare tutto com'era, cioè lo step 3  che fa tutto....

 :-\

risposto 9 anni fa
iTek
iTek
1
modificato 9 anni fa
X 0 X
Effettua l'accesso o registrati per rispondere a questa domanda