简体   繁体   中英

Paypal IPN subscription (php)

I am trying to set up a subscription using Paypal and their IPN system for days now. I could not understand most tutorials and finally found one that made sense to me.

With help of Sean on here I have changed the code slightly but still no luck.

To create the subscription button, I use the following code:

<form action="https://sandbox.paypal.com/cgi-bin/webscr" method="post">
<input type="hidden" name="cmd" value="_xclick-subscriptions">
<input type="hidden" name="business" value="info@mydomain.com">
<input type="hidden" name="lc" value="NL">
<input type="hidden" name="item_name" value="Mydomain.com Abonnement">
<input type="hidden" name="no_note" value="1">
<input type="hidden" name="no_shipping" value="2">
<input type="hidden" name="notify_url" value="http://www.mydomain.com/pp-ipn-handler.php">
<input type="hidden" name="return" value="http://www.mydomain.com/ppsuccess.php">
<input type="hidden" name="src" value="1">
<input type="hidden" name="currency_code" value="EUR">
<input type="hidden" name="bn" value="PP-SubscriptionsBF:btn_subscribeCC_LG.gif:NonHosted">
<input type="hidden" name="custom" value="'. $username .'">
<table>
<tr><td><input type="hidden" name="on0" value="Betaalperiode"><strong>Kies uw betaalperiode:</strong></td></tr><tr><td><select name="os0">
    <option value="Per maand">Per maand : &euro;25.00 EUR</option>
    <option value="Per jaar">Per jaar : &euro;240.00 EUR</option>
</select> </td></tr>
</table>
<input type="hidden" name="currency_code" value="EUR">
<input type="hidden" name="option_select0" value="Per maand">
<input type="hidden" name="option_amount0" value="25.00">
<input type="hidden" name="option_period0" value="M">
<input type="hidden" name="option_frequency0" value="1">
<input type="hidden" name="option_select1" value="Per jaar">
<input type="hidden" name="option_amount1" value="240.00">
<input type="hidden" name="option_period1" value="Y">
<input type="hidden" name="option_frequency1" value="1">
<input type="hidden" name="option_index" value="0">
<input type="image" src="https://www.paypalobjects.com/nl_NL/NL/i/btn/btn_subscribe_LG.gif" border="0" name="submit" alt="PayPal, de veilige en complete manier van online betalen.">
</form>

To handle the ipn response I have a file named pp-ipn-handler.php with the following code:

<?php
// 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 .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= "Content-Length: " . strlen($req) . "\r\n\r\n";
// assign posted variables to local variables
$payment_status = $_POST['payment_status'];
$payment_amount = $_POST['mc_gross'];
// $payment_currency = $_POST['mc_currency'];
$payment_currency = 'EUR';
$ppusername = $_POST['custom'];
$fp = fsockopen ('sandbox.paypal.com', 80, $errno, $errstr, 30);
if (!$fp)
{
}
else
{
fputs ($fp, $header . $req);
while (!feof($fp))
{
$res = fgets ($fp, 1024);
if (strcmp ($res, "VERIFIED") == 0)
{
// When a payment has gone trough
    //When payment is 25EUR make it a month validity
    if ($ppusername&&($payment_currency=='EUR')&&($payment_amount=='25'))
    {
        $period = '+1 month';       
    }
    //When payment is 240EUR make it a year validity
    else if ($ppusername&&($payment_currency=='EUR')&&($payment_amount=='25'))
    {
        $period = '+1 year';        
    }
    //There is incorrect information in this payment
    else
    {

    }


    //Lets first get the date in mysql format
    $date = date('m/d/Y h:i:s', time());
    $date = date('m/d/Y h:i:s', strtotime("$date -7 hours"));
    //Now lets update the subscription records
    require_once('core/dbconnect.php');
    $subscriptionrecordexists = mysql_query("SELECT * FROM subscriptions WHERE username='$ppusername'");
    if (mysql_num_rows($subscriptionrecordexists))
    {
        //User has purchase before. Adjust his subscription record and ad an invoice.
        require_once('core/dbconnect.php');
        $subscriptionrecord = mysql_query("SELECT * FROM subscriptions WHERE username='$ppusername'");
        $row = mysql_fetch_array($subscriptionrecord);
        //Update subscription record
        $currentvalidity = $row['validity'];
        if ($currentvalidity >= $date)
        {
            //Add period if subscription is still valid
            $newvalidity = date('m/d/Y h:i:s', strtotime("$currentvalidity $period"));
            require_once('core/dbconnect.php');
            mysql_query("UPDATE subscriptions SET validity='$newvalidity' WHERE username='$ppusername'");
            //Add invoice to user
            if ($period == '+1 month')
            {$product = 'NLTVMee.com voor 1 maand';}
            if ($period == '+1 year')
            {$product = 'NLTVMee.com voor 1 jaar';}
            $paymentmethode = 'Paypal';
            $oldvalid = $currentvalidity;
            $newvalid = $newvalidity;
            require_once('core/dbconnect.php');
            mysql_query("INSERT INTO invoices VALUES ('','$date','$ppusername','$product','$paymentmethode','$payment_currency','$payment_amount','$oldvalid','$newvalid')");
        }
        else
        {
            //Add period from current date if validity is not valid anymore
            $newvalidity = date('m/d/Y h:i:s', strtotime("$date $period"));
            require_once('core/dbconnect.php');
            mysql_query("UPDATE subscriptions SET validity='$newvalidity' WHERE username='$ppusername'");
            //Ad invoice to user
            if ($period == '+1 month')
            {$product = 'NLTVMee.com voor 1 maand';}
            if ($period == '+1 year')
            {$product = 'NLTVMee.com voor 1 jaar';}
            $paymentmethode = 'Paypal';
            $newvalid = $newvalidity;
            require_once('core/dbconnect.php');
            mysql_query("INSERT INTO invoices VALUES ('','$date','$ppusername','$product','$paymentmethode','$payment_currency','$payment_amount','','$newvalid')");
        }
    }
    else
    {
        //User has never purchased before. Make new subscription record and add invoice.
        //Add period from current date if validity is not valid anymore
        $newvalidity = date('m/d/Y h:i:s', strtotime("$date $period"));
        require_once('core/dbconnect.php');
        mysql_query("INSERT INTO subscriptions VALUES ('','$ppusername','$newvalidity')");
        //Ad invoice to user
        if ($period == '+1 month')
        {$product = 'NLTVMee.com voor 1 maand';}
        if ($period == '+1 year')
        {$product = 'NLTVMee.com voor 1 jaar';}
        $paymentmethode = 'Paypal';
        $newvalid = $newvalidity;
        require_once('core/dbconnect.php');
        mysql_query("INSERT INTO invoices VALUES ('','$date','$ppusername','$product','$paymentmethode','$payment_currency','$payment_amount','','$newvalid')");
    }

}
//End
else if (strcmp ($res, "INVALID") == 0)
{

}
}
fclose ($fp);
}
?>

As you can see it is now configured with the Paypal sandbox urls to try it out, but when I do and make the payment nothing is changed in the db and as you can see the IPN handler page should change things.

It is a blank page because you have your ipn listener as your return value, which is where you are sent after completion, but no info is sent. The postback to Paypal will have no values and your code will fail.
( from the docs - The URL to which PayPal redirects buyers' browser after they complete their payments. For example, specify a URL on your site that displays a "Thank you for your payment" page. )

<input type="hidden" name="return" value="http://www.mydomain.com/pp-ipn-handler.php">

You need to use notify_url
( from the docs - The URL to which PayPal posts information about the payment, in the form of Instant Payment Notification messages. )

<input type="hidden" name="notify_url" value="http://www.mydomain.com/pp-ipn-handler.php">
<input type="hidden" name="return" value="http://www.mydomain.com/payment_complete_thank_message.php">

Edit
I see 3 additional errors in the code

Your query on line #65 is $subscriptionrecord , but on line #66 you are using $userinfo

    $subscriptionrecord = mysql_query("SELECT * FROM subscriptions WHERE username='$ppusername'");
    $row = mysql_fetch_array($userinfo);

Correction
these below are not true as enclosing them in quotes "$currentvalidity $period" is the same as $currentvalidity.$period

On line #72 you need to concat $currentvalidity & $period inside strtotime() - $currentvalidity.$period

$newvalidity = date('m/d/Y h:i:s', strtotime("$currentvalidity $period"));

On line #91 & #111 you need to concat $date & $period inside strtotime() - $date.$period

$newvalidity = date('m/d/Y h:i:s', strtotime("$date $period"));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM