Newsgroup: it.comp.www.php
Titolo: Help per mambo/phpshop e banca sella

Ciao a tutti,
sto' cercando di ampliare il componente phpshop di mambo per aggiungere il 
pagamento tramite carta di credito con Banca Sella Gest Crypt.
Il "protocollo" di banca sella prevede che una serie di informazioni siano 
criptate mediante la classe java fornita e poi inviate (ad esempio con un 
form) come variabili $a e $b. Sella dovrebbe completare una serie di 
controlli e poi restituire il risultato (ok, ko) al sito sempre nella stessa 
forma (variabili $a e $b) che devono essere decriptate per poi fornire al 
cliente l'esito della transazione.
Per come e' costruito phpshop (e mambo) mi trovo a dover far eseguire tutto 
l'algoritmo spiegato da un solo metodo di una classe (quella responsabile 
del pagamento tramite sella).
Il codice che richiama tale metodo (process_payment) e'
if (file_exists(CLASSPATH . "payment/$payment_class.php") ) {
        include( CLASSPATH. "payment/$payment_class.php" );
        eval( "\$_PAYMENT = new $payment_class();" );
         if (!$_PAYMENT->process_payment($order_number,$order_total,$d)) {
           $d["error"] .= "\n ".$PHPSHOP_LANG->_PHPSHOP_PAYMENT_ERROR." 
($payment_class)";
           return False;
         }
     }
     else {
       $d["order_payment_log"] = $PHPSHOP_LANG->_PHPSHOP_CHECKOUT_MSG_LOG;
     }
Pertanto in process_payment dovrei:
-Criptare i dati con la classe di sella
-Inviare i dati alla pagina 
https://ecomm.sella.it/gestpay/pagam.asp
-Ricevere i risultati
-Continuare il ceckout dell'ordine
I punti 2 e 3 sono quelli che mi mandano in crisi, ho pensato a fsockopen 
oppure a curl ma non saprei bene come impostare la cosa, qualcuno di voi ha 
suggerimento?
In particolare non saprei come impostare la configurazione dell'account su 
sella per quanto riguarda le pagine di ok,ko e server to server.
Grazie a tutti
-- 
Danilo Bottone
danilo...@gmail.com
 

 -Continuare il ceckout dell'ordine
http://gestpaycryptphp.sourceforge.net/
http://www.phpclasses.org/browse/package/1219.html
già pronto e funzionante. usa libCURL e DISATTIVA la direttiva
allow_url_fopen.


Scusa ma non ho capito bene dove trovare cio' che mi serve in quei files 
(avevo gia' entrambi i pacchetti).
La request e la respons sono implementate una con un redirect con header e 
l'altra per essere richiamata da sella.
A me serve una cosa che incapsuli questo procedimento in modo che il 
controllo dell'esecuzione resti sempre nel modulo richiamato.
Ragionandoci un po' le strade che ho trovato sono tre:
-Usare i socket per mandare i dati e per poi riceverli
-Usare curl in modo simile ai socket
-Provare a mandare i dati con header e poi richiamare come pagina di 
risposta da banca sella una pagina "finta" che rimanda l'esecuzione dello 
script a subito dopo la chiamata ad header, restituendo tutti i valori della 
sessione e le variabili a e b di banca sella per essere decriptate
Ciao e Grazie mille ... se la cosa e' di scarso interesse sul ng (visto le 
risposte) magari possiamo continuare in privato (ovviamente poi posto la 
soluzione).
-- 
Danilo Bottone
danilo...@gmail.com
www.danilobottone.com
 (.it) 

 soluzione).
Questo mai!!! anzi, continuiamo!!!
e-


Per me ... contentissimo di continuare la discussione ovunque :)
Grazie ancora
Ciao
Metodo della classe che deve eseguire request e response (qui nell'esempio 
si interfaccia con 
authorize.net
) oi vorrei interfacciarlo con sella.
  /**************************************************************************
  ** name: process_payment()
  ** created by: jep
  ** description: process transaction 
authorize.net
  ** parameters: $order_number, the number of the order, we're processing 
here
  **            $order_total, the total $ of the order
  ** returns:
  ***************************************************************************/
   function process_payment($order_number, $order_total, &$d) {
        global $vendor_mail, $vendor_currency, $PHPSHOP_LANG, $database;
        $ps_vendor_id = $_SESSION["ps_vendor_id"];
        $auth = $_SESSION['auth'];
        $ps_checkout = new ps_checkout;
        /*** Get the Configuration File for 
authorize.net
 ***/
        require_once(CLASSPATH ."payment/".$this->classname.".cfg.php");
        // Get the Transaction Key securely from the database
        $database->setQuery( "SELECT 
DECODE(payment_passkey,'".ENCODE_KEY."') as passkey FROM 
#__pshop_payment_method WHERE payment_class='".$this->classname."'" );
        $database->loadObject( $transaction );
        if( empty($transaction->passkey)) {
            $d["error"] = $PHPSHOP_LANG->_PHPSHOP_PAYMENT_ERROR;
            return false;
        }
        // Get user billing information
        $dbbt = new ps_DB;
        $qt = "SELECT * FROM #__users WHERE id='".$auth["user_id"]."' AND 
address_type='BT'";
        $dbbt->query($qt);
        $dbbt->next_record();
        $user_info_id = $dbbt->f("user_info_id");
        if( $user_info_id != $d["ship_to_info_id"]) {
            // Get user billing information
            $dbst =& new ps_DB;
            $qt = "SELECT * FROM #__pshop_user_info WHERE 
user_info_id='".$d["ship_to_info_id"]."' AND address_type='ST'";
            $dbst->query($qt);
            $dbst->next_record();
        }
        else {
            $dbst = $dbbt;
        }
        $host = "
secure.authorize.net
";
        $port = 443;
        $path = "/gateway/transact.dll";
        //Authnet vars to send
        $formdata = array (
            'x_version' => '3.1',
            'x_login' => AN_LOGIN,
            'x_tran_key' => $transaction->passkey,
            'x_test_request' => AN_TEST_REQUEST,
            // Gateway Response Configuration
            'x_delim_data' => 'TRUE',
            'x_delim_char' => '|',
            'x_relay_response' => 'FALSE',
            // Customer Name and Billing Address
            'x_first_name' => substr($dbbt->f("first_name"), 0, 50),
            'x_last_name' => substr($dbbt->f("last_name"), 0, 50),
            'x_company' => substr($dbbt->f("company"), 0, 50),
            'x_address' => substr($dbbt->f("address_1"), 0, 60),
            'x_city' => substr($dbbt->f("city"), 0, 40),
            'x_state' => substr($dbbt->f("state"), 0, 40),
            'x_zip' => substr($dbbt->f("zip"), 0, 20),
            'x_country' => substr($dbbt->f("country"), 0, 60),
            'x_phone' => substr($dbbt->f("phone_1"), 0, 25),
            'x_fax' => substr($dbbt->f("fax"), 0, 25),
            // Customer Shipping Address
            'x_ship_to_first_name' => substr($dbst->f("first_name"), 0, 50),
            'x_ship_to_last_name' => substr($dbst->f("last_name"), 0, 50),
            'x_ship_to_company' => substr($dbst->f("company"), 0, 50),
            'x_ship_to_address' => substr($dbst->f("address_1"), 0, 60),
            'x_ship_to_city' => substr($dbst->f("city"), 0, 40),
            'x_ship_to_state' => substr($dbst->f("state"), 0, 40),
            'x_ship_to_zip' => substr($dbst->f("zip"), 0, 20),
            'x_ship_to_country' => substr($dbst->f("country"), 0, 60),
            // Additional Customer Data
            'x_cust_id' => $auth['user_id'],
            'x_customer_ip' => $_SERVER["REMOTE_ADDR"],
            'x_customer_tax_id' => $dbbt->f("tax_id"),
            // Email Settings
            'x_email' => $dbbt->f("email"),
            'x_email_customer' => 'False',
            'x_merchant_email' => $vendor_mail,
            // Invoice Information
            'x_invoice_num' => substr($order_number, 0, 20),
            'x_description' => '',
            // Transaction Data
            'x_amount' => $order_total,
            'x_currency_code' => $vendor_currency,
            'x_method' => 'CC',
            'x_type' => AN_TYPE,
            'x_recurring_billing' => AN_RECURRING,
            'x_card_num' => $_SESSION['ccdata']['order_payment_number'],
            'x_card_code' => $_SESSION['ccdata']['credit_card_code'],
            'x_exp_date' => 
($_SESSION['ccdata']['order_payment_expire_month']) . 
($_SESSION['ccdata']['order_payment_expire_year']),
            // Level 2 data
            'x_po_num' => substr($order_number, 0, 20),
            'x_tax' => substr($d['order_tax'], 0, 15),
            'x_tax_exempt' => "FALSE",
            'x_freight' => $d['order_shipping'],
            'x_duty' => 0
        );
        //build the post string
        $poststring = '';
        foreach($formdata AS $key => $val){
            $poststring .= urlencode($key) . "=" . urlencode($val) . "&";
        }
        // strip off trailing ampersand
        $poststring = substr($poststring, 0, -1);
        if( function_exists( "curl_init" )) {
            $CR = curl_init();
            curl_setopt($CR, CURLOPT_URL, "https://".$host.$path);
            curl_setopt($CR, CURLOPT_POST, 1);
            curl_setopt($CR, CURLOPT_FAILONERROR, true);
            curl_setopt($CR, CURLOPT_POSTFIELDS, $poststring);
            curl_setopt($CR, CURLOPT_RETURNTRANSFER, 1);
            // No PEER certificate validation...as we don't have
            // a certificate file for it to authenticate the host 
www.ups.com
 against!
            curl_setopt($CR, CURLOPT_SSL_VERIFYPEER, 0);
            //curl_setopt($CR, CURLOPT_SSLCERT , 
"/usr/locale/xxxx/clientcertificate.pem");
            $result = curl_exec( $CR );
            $error = curl_error( $CR );
            if( !empty( $error )) {
              echo curl_error( $CR );
              $html = "<br/><span 
class=\"message\">".$PHPSHOP_LANG->_PHPSHOP_PAYMENT_INTERNAL_ERROR." 
authorize.net
</span>";
              return false;
            }
            else {
                //echo $result; exit();
            }
            curl_close( $CR );
        }
        else {
            $fp = fsockopen("ssl://".$host, $port, $errno, $errstr, $timeout 
= 60);
            if(!$fp){
                //error tell us
                echo "$errstr ($errno)\n";
            }
            else {
                //send the server request
                fputs($fp, "POST $path HTTP/1.1\r\n");
                fputs($fp, "Host: $host\r\n");
                fputs($fp, "Content-type: 
application/x-www-form-urlencoded\r\n");
                fputs($fp, "Content-length: ".strlen($poststring)."\r\n");
                fputs($fp, "Connection: close\r\n\r\n");
                fputs($fp, $poststring . "\r\n\r\n");
                //Get the response header from the server
                $str = '';
                while(!feof($fp) && !stristr($str, 'content-length')) {
                   $str = fgets($fp, 4096);
                }
                // If didnt get content-lenght, something is wrong, return 
false.
                if (!stristr($str, 'content-length')) {
                   return false;
                }
                $data = "";
                while (!feof($fp)) {
                   $data .= fgets ($fp, 1024);
                }
                $result = trim( $data );
                 /*
                 // Get length of data to be received.
                 $length = trim(substr($str,strpos($str,'content-length') + 
15));
                 // Get buffer (blank data before real data)
                 fgets($fp, 4096);
                 // Get real data
                 $data = fgets($fp, $length);
                 fclose($fp);*/
          }
        }
        $response = explode("|", $result);
        // Approved - Success!
        if ($response[0] == '1') {
           $d["order_payment_log"] = 
$PHPSHOP_LANG->_PHPSHOP_PAYMENT_TRANSACTION_SUCCESS.": ";
           $d["order_payment_log"] .= $response[3];
           // Catch Transaction ID
           $d["order_payment_trans_id"] = $response[6];
           return True;
        }
        // Payment Declined
        elseif ($response[0] == '2') {
           $d["error"] = $response[3];
           $d["order_payment_log"] = $response[3];
           // Catch Transaction ID
           $d["order_payment_trans_id"] = $response[6];
           return False;
        }
        // Transaction Error
        elseif ($response[0] == '3') {
           $d["error"] = $response[3];
           $d["order_payment_log"] = $response[3];
           // Catch Transaction ID
           $d["order_payment_trans_id"] = $response[6];
           return False;


 
Il codice è molto interessante... anche se pone dei limiti dovuti al fatto
che non puoi passare per un sistema come paypal, o almeno cosi' mi sembra!
Nel caso di bancasella dovresti poter "passare" tutto tu, e quindi
specificare nei parametri di conf. di gestpay  che l'utente non inserisce
niente. QUesto basta a far proseguire la transazione, e dovrebbe arrivarti
una risposta (in s2s) da parte di gestpay, subito dopo l'invio dei dati
(con ENCODE). Rimane il fatto che gestpay notifica il pagamento sull'url
S2S in maniera asincrona, quindi DEVI specificare un file aggiuntivo (che
non ha niente a che fare con il processo standard di phpshop) che si occupa
di gestire l'avvenuto pagamento. in pratica devi spezzare il file che hai
postato tu in due parti, ed una di queste deve essere "esposta" verso i
server di gestpay.
(Credo)
Ciao,
e-

 e-
In effetti il problema e' tutto qui, nel senso che poi in qualche modo devo 
comunicare a phpshop com'e' andato il pagamento e quindi la pagina s2s (che 
deve essere esterna) deve esaurire il suo compito mentre il modulo postato 
resta "in attesa" ed e' questo a rompermi le scatole.
Levami un dubbio ma nel configurare sella io devo dare 3 pagine OK, KO e s2s 
giusto?
Il significato di ok e ko e' abbastanza chiaro servono per i due esiti ed io 
devo semplicemente gestire la cosa direttamente nella funzione ma la pagina 
s2s a che serve? Cioe' se si seguono le spec sella si legge un preciso 
flusso di operazioni da compiere ma non capisco cosa deve andare in s2s.
Ciao


 Ciao
S2S è il FULCRO del sistema di pagamento: non puoi fidarti di quel che ti
passa l'utente (che potrebbe essere malvagio), quindi aspetti una notifica
da parte del sistema di pagamento e solo a quel punto "termini" la
transazione.
Sono stato chiaro? no, eh? pazienza :-)

 Sono stato chiaro? no, eh? pazienza :-)
Si chiaro ma allora la pagina s2s e' quella che deve gestire il codice 
presente in request.php e response.php (i due file di esempio di sella), 
giusto?
Mentre OK e KO sono semplicemente due pagine che restituiscono l'esito 
finale della transazione, una volta giunto ad una delle due l'utente nn ha 
piu' nulla a che fare con sella, giusto?
Forse hai ragione che paypal si avvicina di piu' a questo comportamento ... 
prova a fare un giro su 
www.danilobottone.com/mambo
 e provare ad acquistare 
un prodotto con paypal (senza realm fare il pagamento ovviam) cosi' ti rendi 
conto "visivamente" di come si comporta phpshop.
