1
votes

I used this class in my project:
http://www.saaraan.com/2012/07/paypal-expresscheckout-with-php

I modify some of the codings in process.php.
And 2 json variables passed into the php for the transaction data.
The transaction is successful. But only the total price can be displayed in seller account finally.

It is quite weird.



I have looked into the old posts, that with no luck...
- I have set to use a latest version nvp 106.0
- I have added useraction=commit for the webscr url redirection.
- I have setup items' parameters for both SetExpressCheckOut method and DoExpressCheckOut method.

Any solutions for my case??~

Here are my codings:

process.php

<?php
header("Content-type: text/html; charset=utf-8");
session_start();
include_once("config.php");
include_once("paypal.class.php");

if($_POST) //Post Data received from product list page.
{

$products_obj_arr=urldecode($_POST['products_obj_arr']);
$products_obj_arr = str_replace('\"', '"', $products_obj_arr);
$products_obj_arr=json_decode($products_obj_arr);
$current_cart_items=urldecode($_POST['current_cart_items']);
$current_cart_items = str_replace('\"', '"', $current_cart_items);
$current_cart_items=json_decode($current_cart_items);

$item_str='';
$ItemTotalPrice=0;

for($i=0;$i<sizeof($current_cart_items);$i++)
{
    $ItemNumber=$current_cart_items[$i]->product_ref;
    $ItemQty=$current_cart_items[$i]->amount;

    for($j=0;$j<sizeof($products_obj_arr);$j++)
    {
        if($products_obj_arr[$j]->product_ref==$current_cart_items[$i]->product_ref)
        {
            $ItemPrice=$products_obj_arr[$j]->product_price;
            $ItemName=$products_obj_arr[$j]->product_name_en;
            $ItemName=str_replace('<br/>', ' ', $ItemName);         
        }
    }


    $item_str.='&L_PAYMENTREQUEST_0_QTY'.$i.'='. urlencode($ItemQty).
                    '&L_PAYMENTREQUEST_0_AMT'.$i.'='.urlencode($ItemPrice).
                    '&L_PAYMENTREQUEST_0_NAME'.$i.'='.urlencode($ItemName).
                    '&L_PAYMENTREQUEST_0_NUMBER'.$i.'='.urlencode($ItemNumber).
                '&L_PAYMENTREQUEST_0_DESC'.$i.'=';


    $ItemTotalPrice += ($ItemPrice*$ItemQty);


}


$email=$_POST['paypal_email'];
$name=$_POST['paypal_name'];
$phone=$_POST['paypal_phone'];
$address=$_POST['paypal_address'];


$padata =  '&EMAIL='.urlencode($email).
            '&SHIPTONAME='.urlencode($name).
            '&SHIPTOPHONENUM='.urlencode($phone).
            '&SHIPTOSTREET='.urlencode($address).
            '&CURRENCYCODE='.urlencode($PayPalCurrencyCode).
            '&PAYMENTACTION=Sale'.
            '&ALLOWNOTE=1'.
            '&PAYMENTREQUEST_0_CURRENCYCODE='.urlencode($PayPalCurrencyCode).
            '&PAYMENTREQUEST_0_AMT='.urlencode($ItemTotalPrice).
            '&PAYMENTREQUEST_0_ITEMAMT='.urlencode($ItemTotalPrice). 
            '&AMT='.urlencode($ItemTotalPrice).             
            '&RETURNURL='.urlencode($PayPalReturnURL ).
            '&CANCELURL='.urlencode($PayPalCancelURL).$item_str;
    //We need to execute the "SetExpressCheckOut" method to obtain paypal token
    $paypal= new MyPayPal();
    $httpParsedResponseAr = $paypal->PPHttpPost('SetExpressCheckout', $padata, $PayPalApiUsername, $PayPalApiPassword, $PayPalApiSignature, $PayPalMode);

    //Respond according to message we receive from Paypal
    if("SUCCESS" == strtoupper($httpParsedResponseAr["ACK"]) || "SUCCESSWITHWARNING" == strtoupper($httpParsedResponseAr["ACK"]))
    {
        /*
            $_SESSION['email'] = $email;
            $_SESSION['name'] = $name;
            $_SESSION['phone'] = $phone;
            $_SESSION['address'] = $address;
            $_SESSION['item_str'] = $item_str;
        */

            if($PayPalMode=='sandbox')
            {
                $paypalmode     =   '.sandbox';
            }
            else
            {
                $paypalmode     =   '';
            }
            //Redirect user to PayPal store with Token received.
            $paypalurl ='https://www'.$paypalmode.'.paypal.com/cgi-bin/webscr?cmd=_express-checkout&useraction=commit&token='.$httpParsedResponseAr["TOKEN"].'';
            header('Location: '.$paypalurl);

    }else{
        //Show error message
        echo '<div style="color:red"><b>Error : </b>'.urldecode($httpParsedResponseAr["L_LONGMESSAGE0"]).'</div>';
        echo '<pre>';
        print_r($httpParsedResponseAr);
        echo '</pre>';
    }

}

//Paypal redirects back to this page using ReturnURL, We should receive TOKEN and Payer ID
if(isset($_GET["token"]) && isset($_GET["PayerID"]))
{
//we will be using these two variables to execute the "DoExpressCheckoutPayment"
//Note: we haven't received any payment yet.

$token = $_GET["token"];
$playerid = $_GET["PayerID"];

//get session variables
        $ItemTotalPrice=    $_SESSION['totalamount'] ; 

    /*  $email= $_SESSION['email'] ;
        $name=$_SESSION['name'] ;
        $phone= $_SESSION['phone'] ;
        $address=   $_SESSION['address'] ;
    */
        $item_str=  $_SESSION['item_str'] ; 


$padata =   '&TOKEN='.urlencode($token).
            '&PAYERID='.urlencode($playerid).
            '&EMAIL='.urlencode($email).
    //      '&SHIPTONAME='.urlencode($name).
    //      '&SHIPTOPHONENUM='.urlencode($phone).
    //      '&SHIPTOSTREET='.urlencode($address).
            '&CURRENCYCODE='.urlencode($PayPalCurrencyCode).
            '&PAYMENTACTION=Sale'.
            '&ALLOWNOTE=1'.
            '&PAYMENTREQUEST_0_CURRENCYCODE='.urlencode($PayPalCurrencyCode).
    //      '&PAYMENTREQUEST_0_AMT='.urlencode($ItemTotalPrice).
            '&PAYMENTREQUEST_0_ITEMAMT='.urlencode($ItemTotalPrice). 
            '&AMT='.urlencode($ItemTotalPrice).             
            '&RETURNURL='.urlencode($PayPalReturnURL ).
            '&CANCELURL='.urlencode($PayPalCancelURL).$item_str;

//We need to execute the "DoExpressCheckoutPayment" at this point to Receive payment from user.
$paypal= new MyPayPal();
$httpParsedResponseAr = $paypal->PPHttpPost('DoExpressCheckoutPayment', $padata, $PayPalApiUsername, $PayPalApiPassword, $PayPalApiSignature, $PayPalMode);

//Check if everything went ok..

if("SUCCESS" == strtoupper($httpParsedResponseAr["ACK"]) || "SUCCESSWITHWARNING" == strtoupper($httpParsedResponseAr["ACK"])) 
{
        echo '<h2>Success</h2>';
        echo 'Your Transaction ID :'.urldecode($httpParsedResponseAr["TRANSACTIONID"]);
            /*
            //Sometimes Payment are kept pending even when transaction is complete. 
            //May be because of Currency change, or user choose to review each payment etc.
            //hence we need to notify user about it and ask him manually approve the transiction
            */

            if('Completed' == $httpParsedResponseAr["PAYMENTSTATUS"])
            {
                echo '<div style="color:green">Payment Received! Your product will be sent to you very soon!</div>';
            }
            elseif('Pending' == $httpParsedResponseAr["PAYMENTSTATUS"])
            {
                echo '<div style="color:red">Transaction Complete, but payment is still pending! You need to manually authorize this payment in your <a target="_new" href="http://www.paypal.com">Paypal Account</a></div>';
            }


        echo '<br /><b>Stuff to store in database :</b><br /><pre>';

            $transactionID = urlencode($httpParsedResponseAr["TRANSACTIONID"]);
            $nvpStr = "&TRANSACTIONID=".$transactionID;
            $paypal= new MyPayPal();
            $httpParsedResponseAr = $paypal->PPHttpPost('GetTransactionDetails', $nvpStr, $PayPalApiUsername, $PayPalApiPassword, $PayPalApiSignature, $PayPalMode);

            if("SUCCESS" == strtoupper($httpParsedResponseAr["ACK"]) || "SUCCESSWITHWARNING" == strtoupper($httpParsedResponseAr["ACK"])) {

                /* 
                #### SAVE BUYER INFORMATION IN DATABASE ###
                $buyerName = $httpParsedResponseAr["FIRSTNAME"].' '.$httpParsedResponseAr["LASTNAME"];
                $buyerEmail = $httpParsedResponseAr["EMAIL"];

                $conn = mysql_connect("localhost","MySQLUsername","MySQLPassword");
                if (!$conn)
                {
                 die('Could not connect: ' . mysql_error());
                }

                mysql_select_db("Database_Name", $conn);

                mysql_query("INSERT INTO BuyerTable 
                (BuyerName,BuyerEmail,TransactionID,ItemName,ItemNumber, ItemAmount,ItemQTY)
                VALUES 
                ('$buyerName','$buyerEmail','$transactionID','$ItemName',$ItemNumber, $ItemTotalPrice,$ItemQTY)");

                mysql_close($con);
                */

                echo '<pre>';
                print_r($httpParsedResponseAr);
                echo '</pre>';
            } else  {
                echo '<div style="color:red"><b>GetTransactionDetails failed:</b>'.urldecode($httpParsedResponseAr["L_LONGMESSAGE0"]).'</div>';
                echo '<pre>';
                print_r($httpParsedResponseAr);
                echo '</pre>';

            }

}else{
        echo '<div style="color:red"><b>Error : </b>'.urldecode($httpParsedResponseAr["L_LONGMESSAGE0"]).'</div>';
        echo '<pre>';
        print_r($httpParsedResponseAr);
        echo '</pre>';
}
}
?>





config.php

$PayPalMode             = 'sandbox'; // sandbox or live
$PayPalApiUsername      = '___.___.com'; //PayPal API Username
$PayPalApiPassword      = '___'; //Paypal API password
$PayPalApiSignature     = '___.___.___'; //Paypal API Signature
$PayPalCurrencyCode     = 'HKD'; //Paypal Currency Code
$PayPalReturnURL        = 'http://___.___-___.___/___-___-/process.php'; //Point to process.php page
$PayPalCancelURL        = 'http://___.___-___.___/'; //Cancel URL if     user clicks cancel





paypal.class.php

<?php
class MyPayPal {

function PPHttpPost($methodName_, $nvpStr_, $PayPalApiUsername, $PayPalApiPassword, $PayPalApiSignature, $PayPalMode) {
        // Set up your API credentials, PayPal end point, and API version.
        $API_UserName = urlencode($PayPalApiUsername);
        $API_Password = urlencode($PayPalApiPassword);
        $API_Signature = urlencode($PayPalApiSignature);

        if($PayPalMode=='sandbox')
        {
            $paypalmode     =   '.sandbox';
        }
        else
        {
            $paypalmode     =   '';
        }

        $API_Endpoint = "https://api-3t".$paypalmode.".paypal.com/nvp";
        $version = urlencode('106.0');

        // Set the curl parameters.
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $API_Endpoint);
        curl_setopt($ch, CURLOPT_VERBOSE, 1);

        // Turn off the server and peer verification (TrustManager Concept).
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);

        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_POST, 1);

        // Set the API operation, version, and API signature in the request.
        $nvpreq = "METHOD=$methodName_&VERSION=$version&PWD=$API_Password&USER=$API_UserName&SIGNATURE=$API_Signature$nvpStr_";

        // Set the request as a POST FIELD for curl.
        curl_setopt($ch, CURLOPT_POSTFIELDS, $nvpreq);

        // Get response from the server.
        $httpResponse = curl_exec($ch);

        if(!$httpResponse) {
            exit("$methodName_ failed: ".curl_error($ch).'('.curl_errno($ch).')');
        }

        // Extract the response details.
        $httpResponseAr = explode("&", $httpResponse);

        $httpParsedResponseAr = array();
        foreach ($httpResponseAr as $i => $value) {
            $tmpAr = explode("=", $value);
            if(sizeof($tmpAr) > 1) {
                $httpParsedResponseAr[$tmpAr[0]] = $tmpAr[1];
            }
        }

        if((0 == sizeof($httpParsedResponseAr)) || !array_key_exists('ACK', $httpParsedResponseAr)) {
            exit("Invalid HTTP Response for POST request($nvpreq) to $API_Endpoint.");
        }

    return $httpParsedResponseAr;

    }

}
?>





here is the result of print_r($httpParsedResponseAr);

Array
(
[RECEIVEREMAIL] => ________
[RECEIVERID] => 32C4LC3EFLHPQ
[EMAIL] => ________
[PAYERID] => 2TKPDP8R96HJG
[PAYERSTATUS] => unverified
[COUNTRYCODE] => HK
[SHIPTONAME] => ________
[SHIPTOSTREET] => room%202%2c%20room%202%2croom%202
[SHIPTOCOUNTRYCODE] => HK
[SHIPTOCOUNTRYNAME] => Hong%20Kong
[ADDRESSOWNER] => PayPal
[ADDRESSSTATUS] => Unconfirmed
[SALESTAX] => 0%2e00
[SHIPAMOUNT] => 0%2e00
[SHIPHANDLEAMOUNT] => 0%2e00
[TIMESTAMP] => 2013%2d09%2d17T07%3a38%3a07Z
[CORRELATIONID] => ed796a185bca7
[ACK] => Success
[VERSION] => 106%2e0
[BUILD] => 7715813
[FIRSTNAME] => li
[LASTNAME] => yu
[TRANSACTIONID] => 9H1595228W773654H
[RECEIPTID] => 5527%2d6661%2d1991%2d5826
[TRANSACTIONTYPE] => expresscheckout
[PAYMENTTYPE] => instant
[ORDERTIME] => 2013%2d09%2d17T07%3a38%3a05Z
[AMT] => 540%2e00
[FEEAMT] => 20%2e71
[TAXAMT] => 0%2e00
[CURRENCYCODE] => HKD
[PAYMENTSTATUS] => Completed
[PENDINGREASON] => None
[REASONCODE] => None
[PROTECTIONELIGIBILITY] => Ineligible
[PROTECTIONELIGIBILITYTYPE] => None
[L_QTY0] => 1
[L_TAXAMT0] => 0%2e00
[L_CURRENCYCODE0] => HKD
[L_TAXABLE0] => false
)
1

1 Answers

1
votes

Is SetExpressCheckout the only call you're making? If so, that's not enough. No payment is actually made until you finalize it all with DoExpressCheckoutPayment.

You need to make sure to include the item details in the request. From the looks of your sample that's not happening, but from your code it looks like you're attempting to pass them into the library, so something about that class or the way you're passing the item details in must be inaccurate.

Here's a sample that includes item details as required for them to show up in the payment details:

[REQUESTDATA] => Array
    (
        [USER] => sandbo_1.....leye.com
        [PWD] => 12.....74
        [VERSION] => 97.0
        [BUTTONSOURCE] => AngellEYE_PHPClass
        [SIGNATURE] => AiKZhEEPLJjSIccz.....W18v
        [METHOD] => SetExpressCheckout
        [MAXAMT] => 200.00
        [RETURNURL] => http://paypal.angelleye.com/standard/samples/DoExpressCheckoutPayment.php
        [CANCELURL] => http://paypal.angelleye.com/paypal/class/cancel.php
        [REQCONFIRMSHIPPING] => 0
        [NOSHIPPING] => 1
        [ALLOWNOTE] => 1
        [SOLUTIONTYPE] => Sole
        [LANDINGPAGE] => Billing
        [BRANDNAME] => Angell EYE
        [CUSTOMERSERVICENUMBER] => 555-555-5555
        [GIFTMESSAGEENABLE] => 1
        [GIFTRECEIPTENABLE] => 1
        [GIFTWRAPENABLE] => 1
        [GIFTWRAPNAME] => Box with Ribbon
        [GIFTWRAPAMOUNT] => 2.50
        [BUYEREMAILOPTIONENABLE] => 1
        [SURVEYENABLE] => 1
        [BUYERREGISTRATIONDATE] => 2012-07-14T00:00:00Z
        [L_BILLINGTYPE0] => MerchantInitiatedBilling
        [L_BILLINGAGREEMENTDESCRIPTION0] => Billing Agreement
        [L_PAYMENTTYPE0] => Any
        [PAYMENTREQUEST_0_AMT] => 100.00
        [PAYMENTREQUEST_0_CURRENCYCODE] => USD
        [PAYMENTREQUEST_0_ITEMAMT] => 80.00
        [PAYMENTREQUEST_0_SHIPPINGAMT] => 15.00
        [PAYMENTREQUEST_0_TAXAMT] => 5.00
        [PAYMENTREQUEST_0_DESC] => This is a test order.
        [PAYMENTREQUEST_0_NOTETEXT] => This is a test note before ever having left the web site.
        [PAYMENTREQUEST_0_PAYMENTACTION] => Sale
        [L_PAYMENTREQUEST_0_NAME0] => Widget 123
        [L_PAYMENTREQUEST_0_DESC0] => Widget 123
        [L_PAYMENTREQUEST_0_AMT0] => 40.00
        [L_PAYMENTREQUEST_0_NUMBER0] => 123
        [L_PAYMENTREQUEST_0_QTY0] => 1
        [L_PAYMENTREQUEST_0_ITEMURL0] => http://www.angelleye.com/products/123.php
        [L_PAYMENTREQUEST_0_NAME1] => Widget 456
        [L_PAYMENTREQUEST_0_DESC1] => Widget 456
        [L_PAYMENTREQUEST_0_AMT1] => 40.00
        [L_PAYMENTREQUEST_0_NUMBER1] => 456
        [L_PAYMENTREQUEST_0_QTY1] => 1
        [L_PAYMENTREQUEST_0_ITEMURL1] => http://www.angelleye.com/products/456.php
        [L_PAYMENTREQUEST_0_ITEMCATEGORY1] => Digital
    )