Search code examples
phppaypalpaypal-adaptive-payments

How to display item description and shipping address during paypal PHP parallel payment?


I have to implement a merchant website where a customers pays a seller for some material goods and a service fee to the website via paypal as described on the picture.

I know that I need to use adaptive payments (parallel or chained) and that the REST API does not support these payments yet (correct me if I'm wrong).

The problem with the classic API (NVP/SOAP) is that during the payment when the webpage redirects the customer to paypal, paypal does not show any item name or description. The other problem is that when the customer logs in no shipping information is shown and no shipping address is sent to the seller after the purchase is made.

Any help is appreciated. Thank you.

Desired result

Note: The photo shows the desired result which is not achieved in my website.

Note 2: I want to use the shipping address that the user used when he/she set up the paypal account and not send it again when I make API calls from PHP

Thank you!

P.S. Some websites that do this kind of payment, on their redirect url to paypal have https://www.paypal.com/us/cgi-bin/merchantpaymentweb?cmd=_flow&SESSION=.....


Solution

  • You can do Parallel Payment without the Adaptive Payments API. The Express Checkout API give you the option to add multiple receivers.

    If you use the NVP string in your API call, you can do the following to have 2 receivers:

    $nvpreq="METHOD=" . $METHOD //required
    . "&VERSION=" . $VERSION  //required
    . "&PWD=" . $PWD  //required
    . "&USER=" . $USER  //required
    . "&SIGNATURE=" . $SIGNATURE  //required
    . "&RETURNURL=" . $RETURNURL  //required
    . "&CANCELURL=" . $CANCELURL  //required    
    
    . "&PAYMENTREQUEST_0_DESC=" . $OVERALLDESCRIPTION  //optional but best practices
    . "&PAYMENTREQUEST_0_PAYMENTACTION=" . $PAYMENTACTION //optional but best practices
    . "&PAYMENTREQUEST_0_AMT=" . $TOTALAMT //required = PAYMENTREQUEST_0_ITEMAMT + PAYMENTREQUEST_0_SHIPPINGAMT + PAYMENTREQUEST_0_TAXAMT + PAYMENTREQUEST_0_INURANCEAMT
    . "&PAYMENTREQUEST_0_ITEMAMT=" . $TOTALITEMAMT  //optional but best practice = (L_PAYMENTREQUEST_0_AMT0 x L_PAYMENTREQUEST_0_QTY0) + (L_PAYMENTREQUEST_0_AMT1 x L_PAYMENTREQUEST_0_QTY1)
    . "&PAYMENTREQUEST_0_SHIPPINGAMT=" . $SHIPPINGAMOUNT  //optional but best practices
    . "&PAYMENTREQUEST_0_CURRENCYCODE=" . $CURRENCYCODE  //optional but best practices
    . "&PAYMENTREQUEST_0_TAXAMT=" . $TAX  //optional but best practices
    
    //1st seller information, specific to parallel payment
    . "&PAYMENTREQUEST_0_SELLERPAYPALACCOUNTID=" . $SELLER1
    . "&PAYMENTREQUEST_0_PAYMENTREQUESTID=" . $UNIQUESELLERID1
    
    . "&PAYMENTREQUEST_0_NOTIFYURL=" . $IPNURL  //optional but best practices
    
    //Line items - (optional)
    . "&L_PAYMENTREQUEST_0_NAME0=" . $DESCRIPTION1 //optional but best practices
    . "&L_PAYMENTREQUEST_0_DESC0=" . $DESCRIPTION1 //optional but best practices
    . "&L_PAYMENTREQUEST_0_AMT0=" . $PAYMENTREQUEST_AMT1 //optional but best practices
    . "&L_PAYMENTREQUEST_0_QTY0=" . $PAYMENTQUANTITY1 //optional but best practices
    
    . "&L_PAYMENTREQUEST_0_NAME1=" . $DESCRIPTION2 //optional but best practices
    . "&L_PAYMENTREQUEST_0_DESC1=" . $DESCRIPTION2 //optional but best practices
    . "&L_PAYMENTREQUEST_0_AMT1=" . $PAYMENTREQUEST_AMT2 //optional but best practices
    . "&L_PAYMENTREQUEST_0_QTY1=" . $PAYMENTQUANTITY2 //optional but best practices
    
    . "&L_PAYMENTREQUEST_0_NAME2=" . $DISCOUNTTXT //optional but best practices
    . "&L_PAYMENTREQUEST_0_DESC2=" . $DISCOUNTTXT //optional but best practices
    . "&L_PAYMENTREQUEST_0_AMT2=" . $DISCOUNTAMT //optional but best practices
    . "&L_PAYMENTREQUEST_0_QTY2=" . $DISCOUNTQTY //optional but best practices
    
    //Address information
    . "&PAYMENTREQUEST_0_SHIPTONAME=" . $SHIPPINGNAME
    . "&PAYMENTREQUEST_0_SHIPTOSTREET=" . $SHIPPINGSTREET
    . "&PAYMENTREQUEST_0_SHIPTOSTREET2=" . $SHIPPINGSTREET2
    . "&PAYMENTREQUEST_0_SHIPTOCITY=" . $SHIPPINGCITY
    . "&PAYMENTREQUEST_0_SHIPTOSTATE=" . $SHIPPINGSTATE
    . "&PAYMENTREQUEST_0_SHIPTOZIP=" . $SHIPPINGZIPCODE
    . "&PAYMENTREQUEST_0_SHIPTOCOUNTRYCODE=" . $SHIPPINGCOUNTRYCODE
    . "&PAYMENTREQUEST_0_SHIPTOPHONENUM=" . $SHIPTOPHONENUM
    
    //2nd seller information
    . "&PAYMENTREQUEST_1_DESC=" . $DESCRIPTIONSELLER2
    . "&PAYMENTREQUEST_1_PAYMENTACTION=" . $PAYMENTACTIONSELLER2
    . "&PAYMENTREQUEST_1_AMT=" . $AMOUNTSELLER2
    . "&PAYMENTREQUEST_1_ITEMAMT=" . $AMOUNTSELLER2
    . "&PAYMENTREQUEST_1_CURRENCYCODE=" . $CURRENCYCODESELLER2
    . "&PAYMENTREQUEST_1_SELLERPAYPALACCOUNTID=" . $SELLER2
    . "&PAYMENTREQUEST_1_PAYMENTREQUESTID=" . $UNIQUESELLERID2
    
    . "&L_PAYMENTREQUEST_1_NAME0=" . $DESCRIPTIONSELLER2
    . "&L_PAYMENTREQUEST_1_DESC0=" . $DESCRIPTIONSELLER2
    . "&L_PAYMENTREQUEST_1_AMT0=" . $AMOUNTSELLER2
    . "&L_PAYMENTREQUEST_1_QTY0=" . $QUANTITYSELLER2
    . "&L_PAYMENTREQUEST_1_ITEMCATEGORY0=Digital"
    
    
    //Payment page settings
    . "&ALLOWNOTE=" . $ALLOWNOTE
    . "&ADDROVERRIDE=" . $ADDROVERRIDE
    . "&NOSHIPPING=" . $NOSHIPPING
    . "&LOCALECODE=" . $LOCALECODE
    . "&LANDINGPAGE=" . $LANDINGPAGE;
    

    As you can see, we have two receivers, but you can add more. For each receiver you can add line items which will appear on the payment page.

    In this example I add the line items only for the first receiver. If you want to add the line items for the 2nd receiver, simply add the following to the NVP string:

    . "&L_PAYMENTREQUEST_1_NAME0=" . $DESCRIPTION1 //optional but best practices
        . "&L_PAYMENTREQUEST_1_DESC0=" . $DESCRIPTION1 //optional but best practices
        . "&L_PAYMENTREQUEST_1_AMT0=" . $PAYMENTREQUEST_AMT1 //optional but best practices
        . "&L_PAYMENTREQUEST_1_QTY0=" . $PAYMENTQUANTITY1 //optional but best practices
    

    Once the user return back to your website (return url), call the GetExpressCheckout API and store the result in a variable:

    $nvpreq="USER=" . $_SESSION['USER'] 
    . "&PWD=" . $_SESSION['PWD'] 
    . "&SIGNATURE=" . $_SESSION['SIGNATURE']
    . "&METHOD=GetExpressCheckoutDetails"
    . "&VERSION=" . $_SESSION['VERSION']      
    . "&TOKEN=" . $_SESSION['PP_TOKEN']
    ;
    //Send the NVP string to the PayPal server, store the result in a variable.
    $resultECD = ....
    

    Eventually build the NVP string with the GetExpressCheckout result and call the DoExpressCheckoutPayment:

    $nvpDoECReq="USER=" . $_SESSION['USER'] 
    . "&PWD=" . $_SESSION['PWD'] 
    . "&SIGNATURE=" . $_SESSION['SIGNATURE']
    . "&METHOD=DoExpressCheckoutPayment"      
    . "&PAYMENTREQUEST_0_PAYMENTACTION=" . $_SESSION['PAYMENT_ACTION'];     // payment type
    
    //Build the DoExpressCheckout request
    foreach ($resultECD as $i => $value) {  
    //Ignore some elements of the GetExpressCheckoutDetails answer
        if ((!($i == "CHECKOUTSTATUS")) && (!($i == "TIMESTAMP")) && (!($i == "CORRELATIONID")) && (!($i == "ACK")) && (!($i == "BUILD"))) {
                        $nvpDoECReq = $nvpDoECReq . "&" . urldecode($i) . "=" . urldecode($value);
        }
    }