Table of Contents

Shop mit PayPal-Anbindung (neuer Release)

FIXME translate


Forum: http://forum.phpwcms.org/viewtopic.php?f=8&t=18505&start=15
Spezifikation: https://www.paypalobjects.com/de_DE/html/IntegrationCenter/ic_home.html
Danke an: nebenaube für PayPal Vorarbeit & OG für den Shop

Autor: Robert/ q23.media
CMS version: = ab r421 und größer

Verzeichnis: /include/inc_module/mod_shop_paypal/

Beschreibung

#1: DB-Update

Es muß eine neue Zwischenspeicher-Tabelle angelegt werden.

SQL-Anweisung in phpmyadmin ausführen:

CREATE TABLE  IF NOT EXISTS  `phpwcms_shop_transactions` (
  `transaction_id` int(10) unsigned NOT NULL auto_increment,
  `receiver_email` varchar(60) collate latin1_bin default NULL,
  `order_number` varchar(10) collate latin1_bin default NULL,
  `payment_status` varchar(10) collate latin1_bin default NULL,
  `pending_reason` varchar(10) collate latin1_bin default NULL,
  `payment_date` varchar(20) collate latin1_bin default NULL,
  `mc_gross` varchar(20) collate latin1_bin default NULL,
  `mc_fee` varchar(20) collate latin1_bin default NULL,
  `tax` varchar(20) collate latin1_bin default NULL,
  `mc_currency` varchar(3) collate latin1_bin default NULL,
  `txn_id` varchar(20) collate latin1_bin default NULL,
  `txn_type` varchar(10) collate latin1_bin default NULL,
  `first_name` varchar(30) collate latin1_bin default NULL,
  `last_name` varchar(40) collate latin1_bin default NULL,
  `address_street` varchar(50) collate latin1_bin default NULL,
  `address_city` varchar(30) collate latin1_bin default NULL,
  `address_state` varchar(30) collate latin1_bin default NULL,
  `address_zip` varchar(20) collate latin1_bin default NULL,
  `address_country` varchar(30) collate latin1_bin default NULL,
  `address_status` varchar(10) collate latin1_bin default NULL,
  `payer_email` varchar(60) collate latin1_bin default NULL,
  `contact_phone` varchar(50) collate latin1_bin default NULL,
  `payer_status` varchar(10) collate latin1_bin default NULL,
  `payment_type` varchar(10) collate latin1_bin default NULL,
  `notify_version` varchar(10) collate latin1_bin default NULL,
  `verify_sign` varchar(10) collate latin1_bin default NULL,
  `referrer_id` varchar(10) collate latin1_bin default NULL,
  PRIMARY KEY  (`transaction_id`)
) ENGINE=MyISAM AUTO_INCREMENT=14 ;





#2: Einspielen der notwendige Dateien

- front_order_process.inc.php
- paypal.class.php
hier herunterladen
phpwcms_r421andup_paypal.zip und auf den Server in include/inc_module/mod_shop_paypal/inc kopieren.



#3: Modifizieren des bestehenden Orderprocess

1. Template File

Falls nicht bereits vorhanden in der default.html (bzw. diejenige Templatedatei die verwendet wird) folgende Einstellungen

Den Abschnitt:

 <--- Config_Start --->
label_payby_prepay = "Cash with order"
label_payby_pod = "Cash on delivery"
label_payby_onbill = "On account"

mit folgendem erweitern:

label_payby_paypal = "PayPal"


Im Abschnitt:

<!--MAIL_CUSTOMER_START//-->

nach

Payment:

Ausgabe der Zahlart in der eMail mit

[PAYBY_PAYPAL]You have paid via Paypal.[/PAYBY_PAYPAL]

erreichen.

Nach

<!--MAIL_NEWORDER_END//-->

und vor Order_Done_Start:

<!--PAYPAL_ORDER_DONE_START//-->
    <h2>Order {ORDER} successfully sent</h2>
    <p>Hello <strong>{INV_FIRSTNAME} {INV_NAME}</strong>,<br />
    Thanks for your order. You will receive a notification of your oder status at <strong>{EMAIL}</strong> once confirmation of your payment has been received...</p>
    <p>Your order number is: <strong>{ORDER}</strong>. Please use this number in case you need to contact us by email.</p>
<!--PAYPAL_ORDER_DONE_END//-->
 
<!--PAYPAL_ORDER_DEBUG_START//-->
    <h2>Paypal class error message</h2>
    <p><strong>{DEBUG_MSG1} </strong></p>
    <p><strong>{DEBUG_MSG2} </strong></p>
<!--PAYPAL_ORDER_DEBUG_END//-->
 
<!--PAYPAL_ORDER_CANCELED_START//-->
    <h3>{MESSAGE}</h3>
<!--PAYPAL_ORDER_CANCELED_END//-->

Damit ist die Templatedatei für PayPal angepasst.



2: frontend.render.php

Nach

$_tmpl['mail_neworder']    = get_tmpl_section('MAIL_NEWORDER',            $_tmpl['source']);

das hinzufügen

            $_tmpl['paypal_order_success']    = get_tmpl_section('PAYPAL_ORDER_DONE',     $_tmpl['source']);
            $_tmpl['paypal_order_debug']    = get_tmpl_section('PAYPAL_ORDER_DEBUG', $_tmpl['source']);
            $_tmpl['paypal_order_canceled']    = get_tmpl_section('PAYPAL_ORDER_CANCELED', $_tmpl['source']);



und hinter

// merge config settings like translations and so on
'mail_neworder_subject'        => "[#{ORDER}] New order",

das hinzufügen:

'label_payby_paypal' => "Paypal",





Suche nach

$order_process = str_replace('{ORDER}', $order_num, $order_process);

danach einfügen

} elseif( isset($_GET['shop_order_process'])  ) {
        //process order via paypal ipn
        include($phpwcms['modules']['shop']['path'].'inc/front.order_process.inc.php');





Hinter der stelle

    // receive order db ID
    $order_data = _dbInsert('phpwcms_shop_orders', $order_data);

ein switch einfügen:

        // success inserting db record of order
        $_SESSION['shopping_cart']['order_number'] = $order_num;
 
        switch( $_SESSION[CART_KEY]['payby'] ){
 
        case 'paypal':
            headerRedirect(PHPWCMS_URL.$_tmpl['config']['cart_url']."&shop_order_process");
            break;
 
        default:

ACHTUNG: switch nach routine

// NO success

mit

} //endswitch

wieder schließen.



Suche

$supported = array('prepay' => 0, 'pod' => 0, 'onbill' => 0);

und überschreiben mit

$supported mit:

$supported = array('paypal' => 0, 'prepay' => 0, 'pod' => 0, 'onbill' => 0);

überschreiben.



Das ans ende vor dem schließenden PHP-Tag kopieren:

function validateReferrer(  $yoursite, //Your site url without 'http://' or subdomain
                            $domain_name //Type your domain with www. this time
                         )
{
 
    $referer = $_SERVER['HTTP_REFERER'];
    //Check if browser sends referrer url or not
    if ($referer == "") { //If not, set referrer as your domain
    $domain = $yoursite;
    } else {
    $domain = parse_url($referer); //If yes, parse referrer
    }
 
    if($domain['host'] == $yoursite || $domain['host'] == $domain_name) {
 
        //Run your dowloading code here normally
 
    } else {
 
        //The referrer is not your site, we bail and redirect to  home page
        header("Location: http://".$domain_name."/index.php");
 
        exit(); //Stop running the script
 
    }
}
 
 
 
function reinitialize_session(&$_tmpl){
 
    $_SESSION['shopping_cart']['order_number'] = ( isset($_POST['invoice'])    ? clean_slweg($_POST['invoice']) : '' );
    $_SESSION['shopping_cart']['step1'] = array(
 
            'INV_FIRSTNAME'    => isset($_POST['first_name'])         ? clean_slweg($_POST['first_name']) : '',
            'INV_NAME'        => isset($_POST['last_name'])         ? clean_slweg($_POST['last_name']) : '',
            'INV_ADDRESS'    => isset($_POST['address_street'])     ? clean_slweg($_POST['address_street']) : '',
            'INV_ZIP'        => isset($_POST['address_zip'])     ? clean_slweg($_POST['address_zip']) : '',
            'INV_CITY'        => isset($_POST['address_city'])     ? clean_slweg($_POST['address_city']) : '',
            'INV_REGION'    => isset($_POST['address_state'])     ? clean_slweg($_POST['address_state']) : '',
            'INV_COUNTRY'    => isset($_POST['address_country']) ? clean_slweg($_POST['address_country']) : '',
            'EMAIL'            => isset($_POST['payer_email'])     ? clean_slweg($_POST['payer_email']) : '',
            'PHONE'            => isset($_POST['contact_phone'])     ? clean_slweg($_POST['contact_phone']) : ''
 
            );
 
 
}
 
function reinitialize_cart_products( $order_num ){
 
    $cart_data = Array();
    $cart_data[0] = "uninitialized";
 
 
    $q_result = _dbQuery("SELECT * FROM ".DB_PREPEND."phpwcms_shop_orders WHERE order_number='".$order_num."' LIMIT 1");
 
    if(isset($q_result[0])){
 
            $cart_data  = unserialize($q_result[0]['order_data']);
 
    }
 
    return $cart_data;
 
}
 
function update_transactions_table(&$cart_data, &$P){
    $temp = Array(
                "txn_id",
                "reason_code",
                "receiver_email",
                "mc_gross",
                "protection_eligibility",
                "address_status",
                "payer_id",
                "tax",
                "address_street",
                "payment_date",
                "payment_status",
                "charset",
                "address_zip",
                "mc_shipping",
                "mc_handling",
                "first_name",
                "mc_fee",
                "address_country_code",
                "address_name",
                "notify_version",
                "custom",
                "invoice",
                "num_cart_items",
                "payer_status",
                "business",
                "address_country",
                "address_city",
                "payer_email",
                "contact_phone",
                "verify_sign",
                "payment_type",
                "last_name",
                "address_state",
                "payment_fee",
                "pending_reason",
                "receiver_id",
                "txn_type",
                "mc_currency",
                "residence_country",
                "receipt_id",
                "test_ipn",
                "transaction_subject",
                "payment_gross",
                "merchant_return_link",
                "form_charset"
            );
 
 
    $trans = Array();
 
    foreach( $temp  as $key ){
 
        $trans[$key] = ( isset( $_POST[$key]) ? clean_slweg($_POST[$key]) : '');
 
    }
 
    for( $i=0; $i < $trans['num_cart_items']; $i++ ){
 
 
            $trans['item_number'.($i+1)] = ( isset( $_POST['item_number' . ($i+1)]) ? clean_slweg($_POST['item_number'. ($i+1)]) : '');
            $trans['mc_gross_'.($i+1)]     = ( isset( $_POST['mc_gross_'   . ($i+1)]) ? clean_slweg($_POST['mc_gross_'  . ($i+1)]) : '');
            $trans['quantity'.($i+1)]     = ( isset( $_POST['quantity'    . ($i+1)]) ? clean_slweg($_POST['quantity'   . ($i+1)]) : '');
 
 
    }
 
    $validTransaction = true;
 
    // test the txn_id; if txn_id is used and it's not a chargeback then it's invalid
    $txn_id_is_used = _dbCount("SELECT * FROM ".DB_PREPEND."phpwcms_shop_transactions WHERE txn_id='".$trans['txn_id']."'");
 
    if(  $txn_id_is_used && !isset($trans['reason_code']) && !( empty($trans['txn_type']) && ($trans['reason_code'] === "chargeback")) ){
        $validTransaction = false;
        $lastError  .= "Failed Anti-fraud test 1: txn_id is used: ".$txn_id_is_used."   txn_type: ".$trans['txn_type']."  trans_reason_code: ".$trans['reason_code']."\n";
    }
 
    // test receiver_email
    if( $validTransaction && !( $trans['receiver_email'] === _getConfig( 'shop_pref_email_paypal', '_shopPref' ) ) ){
        $validTransaction = false;
        $lastError  .= "Failed Anti-fraud test 2: unmatched email addresses for receiver_email: ".$trans['receiver_email']." vs "._getConfig( 'shop_pref_email_paypal', '_shopPref' )."\n";
    }
 
    // validate number of items
    if( $validTransaction && ( count($cart_data['cart']) != $trans['num_cart_items'])){
        $validTransaction = false;
        $lastError .= "Failed Anti-fraud test 3: number of items mismatch: items in cart: ".count($cart_data['cart'])." vs items in post: ".$trans['num_cart_items']."\n";
    }
 
    // test to see that cart items match
    if( $validTransaction ){
 
        for( $i=0; $i < $trans['num_cart_items']; $i++ ){
 
 
            if( $cart_data['cart'][$i]['shopprod_id']       != $trans['item_number'.($i+1)] ||
                $cart_data['cart'][$i]['shopprod_price']    != $trans['mc_gross_'.($i+1)] ||
                $cart_data['cart'][$i]['shopprod_quantity'] != $trans['quantity'.($i+1)]    ){
 
                $validTransaction = false;
 
                $lastError  .= "\n\nFailed Anti-fraud test 3: product mismatch: \n";
                $lastError  .= $cart_data['cart'][$i]['shopprod_id']." != ".$trans['item_number'.($i+1)].",\n";
                $lastError  .= $cart_data['cart'][$i]['shopprod_price']." != ".$trans['mc_gross_'.($i+1)].",\n";
                $lastError  .= $cart_data['cart'][$i]['shopprod_quantity']." != ".$trans['quantity'.($i+1)]."\n\n";
 
            }
 
        }
 
 
    }
 
 
    if( $validTransaction ){  // No fraud detected
        $data = Array(
                        'receiver_email'     => $trans['receiver_email'],
                        'order_number'        => $trans['invoice'],
                        'payment_status'    => $trans['payment_status'],
                        'pending_reason'    => $trans['pending_reason'],
                        'payment_date'        => $trans['payment_date'],
                        'mc_gross'            => $trans['mc_gross'],
                        'mc_fee'            => $trans['mc_fee'],
                        'tax'                => $trans['tax'],
                        'mc_currency'        => $trans['mc_currency'],
                        'txn_id'            => $trans['txn_id'],
                        'txn_type'            => $trans['txn_type'],
                        'first_name'        => $trans['first_name'],
                        'last_name'            => $trans['last_name'],
                        'address_street'    => $trans['address_street'],
                        'address_city'        => $trans['address_city'],
                        'address_state'        => $trans['address_state'],
                        'address_zip'         => $trans['address_zip'],
                        'address_country'      => $trans['address_country'],
                        'address_status'       => $trans['address_status'],
                        'payer_email'         => $trans['payer_email'],
                        'contact_phone'        => $trans['contact_phone'],
                        'payer_status'         => $trans['payer_status'],
                        'payment_type'         => $trans['payment_type'],
                        'notify_version'       => $trans['notify_version'],
                        'verify_sign'          => $trans['verify_sign'],
                        'referrer_id'         => $trans['referrer_id']
                    );
 
 
 
        _dbInsertOrUpdate( DB_PREPEND."phpwcms_shop_transactions",    $data, "txn_id = '".$trans['txn_id']."'", '');
 
 
    }else{
 
        $P->log_error($lastError );
    }
 
    return $validTransaction;
 
}





#4: Zusammenfassung

Jetzt müßte

a. die Zahlart PayPal Auswahl im Shop verfügbar sein
b. der Shop innerhalb seiner normalen Parameter funktionieren
c. eine Weiterleitung geschehen (höchstwahrscheinlich fehlerhaft!)


Sollte eine der oben aufgeführten Punkte nicht zutreffen gibt es ein Problem. Kontrollier bitte noch einmal ganz genau die Punkt eins bis drei.


#5: config.inc.php

Mit großer Wahrscheinlichkeit ist die Weiterleitungen beim Abschliessen des Bestellprozesses fehlerhaft. Die Parameter $phpwcms['machine_alias'] und $phpwcms['site_domain'] existieren Standardmäßig nicht und sollten in die config.inc.php nachgetragen werden. Konkret wäre das:

$phpwcms['site_domain'] = 'domain.de'; // ohne www oder subdomain
$phpwcms['machine_alias'] = 'alias'; // www oder subdomain


In diesem Zusammenhang auch die frontend.render.php ⇒ function validateReferrer() einsehen und verstehen was da passiert!