1. Advertising
    y u no do it?

    Advertising (learn more)

    Advertise virtually anything here, with CPM banner ads, CPM email ads and CPC contextual links. You can target relevant areas of the site and show ads based on geographical location of the user if you wish.

    Starts at just $1 per CPM or $0.10 per CPC.

Need Help -- PayPal IPN

Discussion in 'PHP' started by scottlpool2003, Apr 12, 2013.

  1. #1
    I'm working on a recurrent payment system and currently have it nearly working on the sandbox site.

    The IPN simulator works and sends the test data back to my server, but I can't get the actual test payment to send any data back to the server.

    Once the user presses the subscribe button, they can make a payment. This works, and I actually receive the funds but I can't seem to find anywhere to send the user back to the server with a conformation string allowing me to update the database as 'user subscribed'

    Here is what I have so far:

    index.php

    
     
    <?php
     
    require('Paypal_IPN.php');
     
    $paypal = new Paypal_IPN('sandbox');
    $paypal->run();
     
     
    ?>
     
    
    PHP:
    Paypal_IPN.php
    
     
    <?php
     
    class Paypal_IPN
    {
       /** @var string $_url The paypal url to go to through cURL
       private $_url;
     
       /**
       * @param string $mode 'live' or 'sandbox' 
       */
       public function __construct($mode = 'live')
       {
           if ($mode == 'live')
           $this->_url = 'https://www.paypal.com/cgi-bin/webscr';
           
           else
           $this->_url = 'https://www.sandbox.paypal.com/cgi-bin/webscr';
       }
     
       public function run()
       {
           $postFields = 'cmd=_notify-validate';
           
           foreach($_POST as $key => $value)
           {
               $postFields .= "&$key=".urlencode($value);
           }
       
           $ch = curl_init();
     
           curl_setopt_array($ch, array(
               CURLOPT_URL => $this->_url,
               CURLOPT_RETURNTRANSFER => true,
               CURLOPT_SSL_VERIFYPEER => false,
               CURLOPT_POST => true,
               CURLOPT_POSTFIELDS => $postFields
           ));
           
           $result = curl_exec($ch);
           curl_close($ch);
     
     
     
           $fh = fopen('newfile.txt', 'w');
           fputs($fh, $result . ' -- ' . $postFields);
     
     
           echo $result;
       }
     
    }
    ?>
     
    
    PHP:
    newfile.txt
    
    VERIFIED -- cmd=_notify-validate&address_state=CA&quantity=1&txn_id=566886121&last_name=Smith&mc_currency=USD&payer_status=verified&address_status=confirmed&tax=2.02&invoice=abc1234&shipping=3.04&address_street=123%2C+any+street&payer_email=buyer%40paypalsandbox.com&mc_gross1=9.34&item_name=something&first_name=John&business=seller%40paypalsandbox.com&verify_sign=r43f4t3453tg54g45ghg4&payer_id=TESTBUYERID01&payment_date=06%3A33%3A34+12+Apr+2013+PDT&address_country=United+States&payment_status=Completed&receiver_email=seller%40paypalsandbox.com&payment_type=instant&address_zip=95131&address_city=San+Jose&mc_gross=12.34&mc_fee=0.44&residence_country=US&address_country_code=US&notify_version=2.1&receiver_id=seller%40paypalsandbox.com&txn_type=web_accept&custom=xyz123&item_number=AK-1234&address_name=John+Smith&test_ipn=1
    
    PHP:
    I then added a subscribe button to index.php
    
     
    <?php
     
    require('Paypal_IPN.php');
     
    $paypal = new Paypal_IPN('sandbox');
    $paypal->run();
     
     
    ?>
     
    <form name="_xclick" action="https://www.sandbox.paypal.com/cgi-bin/webscr" method="post">
    <input type="hidden" name="cmd" value="_xclick-subscriptions">
    <input type="hidden" name="business" value="sales@sales.com">
    <input type="hidden" name="currency_code" value="GBP">
    <input type="hidden" name="no_shipping" value="1">
    <input type="image" src="http://www.paypal.com/en_GB/i/btn/x-click-but20.gif" border="0" name="submit" alt="Make payments with PayPal - it's fast, free and secure!">
    <input type="hidden" name="a3" value="5.00">
    <input type="hidden" name="p3" value="1">
    <input type="hidden" name="t3" value="M">
    <input type="hidden" name="src" value="1">
    <input type="hidden" name="sra" value="1">
    </form>
     
    
    PHP:
    Does anybody know of a way for me to send the user back to the website with information saying they have paid.

    Also, what would be the process for me to check on the next pay date that the user has paid?
     
    scottlpool2003, Apr 12, 2013 IP
  2. ThePHPMaster

    ThePHPMaster Well-Known Member

    Messages:
    737
    Likes Received:
    52
    Best Answers:
    33
    Trophy Points:
    150
    #2
    Try adding the following hidden form element:

    
    <input name="notify_url" value="http://yourdomain.com/notify_url.php" type="hidden">
    
    Code (markup):
    Where notify_url.php is the script you want paypal to hit you up with the following info on a transaction when its done:
    • mc_gross
    • invoice
    • settle_amount
    • 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
    • exchange_rate
    • address_name
    • notify_version
    • settle_currency
    • custom
    • payer_status
    • business
    • address_country
    • address_city
    • verify_sign
    • payer_email
    • txn_id
    • payment_type
    Source
     
    ThePHPMaster, Apr 12, 2013 IP
  3. rainborick

    rainborick Well-Known Member

    Messages:
    424
    Likes Received:
    33
    Best Answers:
    0
    Trophy Points:
    120
    #3
    It's been a while since I worked on PayPal IPN, but in my old code, I used:
    
    <input type="hidden" name="return" value="<?=$return?>" /><!-- Return to site URL -->
    
    Code (markup):
     
    rainborick, Apr 12, 2013 IP
  4. kmap

    kmap Well-Known Member

    Messages:
    2,215
    Likes Received:
    29
    Best Answers:
    2
    Trophy Points:
    135
    #4
    yes its the return url u need to put it form either using $return or hard code it

    Regards

    Alex
     
    kmap, Apr 12, 2013 IP
  5. scottlpool2003

    scottlpool2003 Well-Known Member

    Messages:
    1,708
    Likes Received:
    49
    Best Answers:
    9
    Trophy Points:
    150
    #5
    Thanks for your help.

    I've tried what you both said but to no avail. I figured out that I also needed to set up the IPN notification url in the profile tab on the Sandbox website. I did this but still not getting a redirect.

    Any ideas?
     
    scottlpool2003, Apr 15, 2013 IP
  6. scottlpool2003

    scottlpool2003 Well-Known Member

    Messages:
    1,708
    Likes Received:
    49
    Best Answers:
    9
    Trophy Points:
    150
    #6
    EDIT

    I can get it to work using a standard 1 off payment, but for the life of me I can't get it to work with a subscription.

    Updated index.php:
    <form action="https://sandbox.paypal.com/cgi-bin/webscr" method="post" id="paypalpost" name="paypalpost">
                    <input type="hidden" name="cmd" value="_xclick">
                    <input type="hidden" name="business" value="admin@domain.com">
                    <input type="hidden" name="item_name" value="Your Subscription">
                    <input type="hidden" name="currency_code" value="GBP">
                    <input type="hidden" name="return" value="http://website.com/paypal/thankyou.php">
                    <input type="hidden" name="p3" value="1">
                    <input type="hidden" name="t3" value="M">
                    <input type="hidden" name="src" value="1">
                    <input type="hidden" name="sra" value="1">
     
     
                <input type="submit" name="submit" id="pay" class="buttonBlueBg" value="Checkout" >
     
                </form>
    
    PHP:
    updated thankyou.php
    <?php
    print_r('<pre>');
    print_r($_POST);
    // read the post from PayPal system and add 'cmd'
    $req = 'cmd=_notify-validate';
     
    foreach ($_POST as $key => $value) {
        $value = urlencode(stripslashes($value));
        $req .= "&$key=$value";
    }
     
    // post back to PayPal system to validate
    $header .= "POST /cgi-bin/webscr HTTP/1.0\r\n";
    $header .= "Host: www.sandbox.paypal.com\r\n";
    $header .= "Content-Type: application/x-www-form-urlencoded\r\n";
    $header .= "Content-Length: " . strlen($req) . "\r\n\r\n";
    $fp = fsockopen ('ssl://www.sandbox.paypal.com', 443, $errno, $errstr, 30);
     
    // assign posted variables to local variables
    $item_name = $_POST['item_name'];
    $item_number = $_POST['item_number'];
    $payment_status = $_POST['payment_status'];
    $payment_amount = $_POST['mc_gross'];
    $payment_currency = $_POST['mc_currency'];
    $txn_id = $_POST['txn_id'];
    $receiver_email = $_POST['receiver_email'];
    $payer_email = $_POST['payer_email'];
     
    if (!$fp) {
    // HTTP ERROR
        echo "HTTP Error";
    } else {
        fputs ($fp, $header . $req);
        while (!feof($fp)) {
            $res = fgets ($fp, 1024);
            echo $res;
            if (strcmp ($res, "VERIFIED") == 0) {
                // check the payment_status is Completed
                // check that txn_id has not been previously processed
                // check that receiver_email is your Primary PayPal email
                // check that payment_amount/payment_currency are correct
                // process payment
                echo("verified");
            }
            else if (strcmp ($res, "INVALID") == 0) {
                // log for manual investigation
                echo ("invalid");
            }
        }
        fclose ($fp);
    }
    echo "end";
    ?>
    PHP:
    On a standard 1 off payment, it returns the correct array, but if I set it up as above with a subscription it returns invalid.
     
    scottlpool2003, Apr 15, 2013 IP
  7. scottlpool2003

    scottlpool2003 Well-Known Member

    Messages:
    1,708
    Likes Received:
    49
    Best Answers:
    9
    Trophy Points:
    150
    #7
    Okay, I now have it working and sending back a "Completed" variable which is great. I can now authenticate the user using this variable.

    So next question...

    What can I do for next months payment? I need to do 1 of 3 things, but I don't know how I can handle them using Paypal as the user will not do anything, the billing is automatic isn't it?

    1. Paypal notifies me that user has cancelled
    2. Paypal notifies me of successful payment
    3. Paypal notifies me of unsuccessful payment

    Is there a way I can do 1 of the above?

    Thanks
     
    scottlpool2003, Apr 15, 2013 IP
  8. rchurchill

    rchurchill Greenhorn

    Messages:
    14
    Likes Received:
    1
    Best Answers:
    0
    Trophy Points:
    13
    #8
    You need to grab the txn type...
    $type = $_POST['txn_type'];

    Then write a case for each..
    <?php
     
    //ensure payment is valid and what you expected..
    //then you can process based on trans type
     
    $type = $_POST['txn_type'];
     
    if($type == 'subscr_signup'){
    // for new subscriptions
    }elseif ($type == 'subscr_cancel'){
    //for canceled subscriptions..
    }elseif ($type == 'subscr_modify'){
    // if they modify the subscription
    }elseif ($type == 'subscr_payment'){
    // monthly subscription payment
    }else{
    // for a non subscription payment
    }
     
    ?>
    PHP:
     
    rchurchill, Apr 18, 2013 IP