cyber
等待验证会员
超级管理员
UID 15380
精华
0
积分 -3
帖子 1150
金钱 -3 喜悦币
威望 0
人脉 0
阅读权限 0
注册 2002-7-21
状态 离线
|
   
Paypal 的IPN研究
经过一段时间的研究,终于弄清楚了paypal购物车的工作原理。
好像有些人还不理解,在此写出,希望有所帮助
首先,你要写一个form
比如:
<form target=\"paypal\" action=\"https://www.paypal.com/cgi-bin/webscr\" method=\"post\">
<input type=\"hidden\" name=\"cmd\" value=\"_cart\">
<input type=\"hidden\" name=\"business\" value=\"".$sub_config['paypalsiteowneremail']."\">
<input type=\"hidden\" name=\"item_name\" value=\"$_POST[membership]\">
<input type=\"hidden\" name=\"item_number\" value=\"$_POST[item_number]\">
<input type=\"hidden\" name=\"amount\" value=\"$_POST[membership_price]\">
<input type=\"hidden\" name=\"no_note\" value=\"1\">
<input type=\"hidden\" name=\"return\" value=\"".$sub_config['paid_url']."\">\n
<input type=\"hidden\" name=\"cancel_return\" value=\"".$sub_config['cancel_url']."\">
<input type=\"hidden\" name=\"custom\" value=\"".$id."\">\n
<input type=\"hidden\" name=\"notify_url\" value=\"http://mysite.com/home/notify2.php\">
<input type=\"hidden\" name=\"no_shipping\" value=\"#no_shipping\">
<input type=\"hidden\" name=\"currency_code\" value=\"GBP\">
<input type=\"image\" src=\"modules/E-Bank/images/BuyNowBig.gif\" border=\"0\" name=\"submit\" alt=\"Make payments with PayPal - it's fast, free and secure!\">
<input type=\"hidden\" name=\"add\" value=\"1\">
</form>
解读:
$sub_config['paypalsiteowneremail']是你的paypal账号
$_POST[membership]是要购买的会员身份
$_POST[item_number]是会员ID
$_POST[membership_price]是会员的价格
$sub_config['paid_url']是付款后返回的页面
$sub_config['cancel_url']是付款取消后返回的页面
$id是购买者的ID号
http://mysite.com/home/notify2.php是付款后PAYPAL自动POST数据到此页面,用于后台处理,如果成功,则写入到数据库
GBP是货币代码
第二步,写notify2.php也就是IPN(Instant Payment Notification)
1.从PAYPAL那里获取数据
function main()
{
global $_PAYPAL,
$error_message,
$socket,
$db,
$log,
$postipn,
$response,$prefix,$sub_config;
// Seed the random number generator.
mt_srand(mkseed());
// Open log file (in append mode) & write the current time into it.
// The script writes to a log so the details can be recorded (in text)
// even if the DB isn't working (v. unlikely). You might prefer to write
// a log to a DB table, or not at all.
$log = fopen($sub_config['logfile_url'], "a");
if( ! $log )
{
$error_message = 'Error: Opening log file';
return;
}
// Log entry header.
$success = logMsg( "---------- IPN " .
strftime ("%b %d %Y %H:%M:%S", time()) .
"----------");
if( ! $success ) return;
// Open DB Connection.
// Convert super globals on older php builds
if (phpversion() <= '4.0.6')
{
$_SERVER = ($HTTP_SERVER_VARS);
$_POST = ($HTTP_POST_VARS);
}
// No ipn post means this script does not exist
if (!@$_POST['txn_id'])
{
@header("Status: 404 Not Found");
$error_message = "Error: Missing transaction ID.";
return;
}
@header("Status: 200 OK");
// Prevents ipn reposts on some servers
// Add "cmd" to prepare for post back validation
// Read the ipn post from paypal or eliteweaver uk
// Fix issue with php magic quotes enabled on gpc
// Apply variable antidote (replaces array filter)
// Destroy the original ipn post (security reason)
// Reconstruct the ipn string ready for the post
$postipn = 'cmd=_notify-validate';
// Notify validate
foreach ($_POST as $ipnkey => $ipnval)
{
if (get_magic_quotes_gpc())
$ipnval = stripslashes ($ipnval); //Fix issue with magic quotes
if (!eregi("^[_0-9a-z-]{1,30}$", $ipnkey)
|| !strcasecmp ($ipnkey, 'cmd'))
{
// ^ Antidote to potential variable injection and poisoning
unset ($ipnkey);
unset ($ipnval);
} // Eliminate the above
if (@$ipnkey != '')
{
// Remove empty keys (not values)
//
// Assign data to new global array
@$_PAYPAL[$ipnkey] = $ipnval;
// Destroy the original ipn post array, sniff...
unset ($_POST);
$postipn .= '&'.@$ipnkey.'='.urlencode(@$ipnval);
}
} // Notify string
// Attempt to double default time limit incase we switch to Get
@set_time_limit(60);
// Post back the reconstructed instant payment notification
$socket = @fsockopen($sub_config['server'], 80, $errno, $errstr, 30);
$header = "POST /cgi-bin/webscr HTTP/1.0\r\n";
$header .= "User-Agent: PHP/".phpversion()."\r\n";
$header .= "Referer: ".$_SERVER['HTTP_HOST'] .
$_SERVER['PHP_SELF'].@$_SERVER['QUERY_STRING']."\r\n";
$header .= "Server: ".$_SERVER['SERVER_SOFTWARE']."\r\n";
$header .= "Host: ".$sub_config['server'].":80\r\n";
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= "Content-Length: ".strlen($postipn)."\r\n";
$header .= "Accept: */*\r\n\r\n";
//* Note: "Connection: Close" is not required using HTTP/1.0
// Problem: Now is this your firewall or your ports?
if( ! $socket )
{
// Switch to a Get request for a last ditch attempt!
if (phpversion() >= '4.3.0' &&
function_exists('file_get_contents'))
{
} // Checking for a new function
else
{
// No? We'll create it instead
function file_get_contents($ipnget)
{
$ipnget = @file($ipnget);
return $ipnget[0];
}
}
$response = @file_get_contents('http://'.$sub_config['server'].':80/cgi-bin/webscr?'.$postipn);
if (!$response)
{
$error = true;
$error_message = 'Error: GET failed';
// If this is as far as you get then you need a new web host!
return;
}
}
// If no problems have occured then we proceed with the processing
else
{
// Required on some environments
@fputs ($socket, $header.$postipn."\r\n\r\n");
while (!feof($socket))
{
$response = fgets ($socket, 1024);
}
}
//把过程写入到log,以便查看。
logMsg("response is :".$response."\r\n");
logMsg("socket is :".$socket."\r\n");
logMsg("header is :".$header."\r\n");
logMsg("postipn is :".$postipn."\r\n");
$response = trim ($response); // Also required on some environments
if ( ! strcmp ($response, "VERIFIED"))
{
handleVerified();//付款成功,调用此函数
}
// IPN was not validated as genuine and is INVALID
else
{
$error_message = "Error: INVALID transaction"; //付款不成功
}
// Log the transaction.
$pending_reason = isset($_PAYPAL['pending_reason']) ?
$_PAYPAL['pending_reason'] : '';
$reason_code = isset($_PAYPAL['reason_code']) ?
$_PAYPAL['reason_code'] : '';
$item_name = isset($_PAYPAL['item_name']) ?
$_PAYPAL['item_name'] : '';
$item_number = isset($_PAYPAL['item_number']) ?
$_PAYPAL['item_number'] : '';
$parent_txn_id = isset($_PAYPAL['parent_txn_id']) ?
$_PAYPAL['parent_txn_id'] : '';
$custom = isset($_PAYPAL['custom']) ?
$_PAYPAL['custom'] : '';
logMsg( $response ."\t".
$_PAYPAL['txn_id'] ."\t".
$parent_txn_id ."\t".
$_PAYPAL['payment_date'] ."\t".
$_PAYPAL['receiver_id'] ."\t".
$_PAYPAL['receiver_email'] ."\t".
$item_name ."\t".
$item_number ."\t".
$_PAYPAL['mc_gross'] ."\t".
$_PAYPAL['payment_status'] ."\t".
$pending_reason ."\t".
$reason_code ."\t".
$_PAYPAL['custom'] ."\t".
$_PAYPAL['option_name1'] ."\t".
$_PAYPAL['first_name'] ."\t".
$_PAYPAL['last_name'] ."\t".
$_PAYPAL['payer_id'] ."\t".
$_PAYPAL['payer_email'] ."\t".
$_PAYPAL['notify_version']
);
if( $error_message ) return;
if( $sub_config['send_succes_email'] ==1)
{
//
// Send a mail message to customer.
mail($_PAYPAL['payer_email'],
$sub_config['support_subject'],
$sub_config['support_message'] ,
"From: " . $sub_config['support_email'] . "\r\n" .
"Reply-To: " . $sub_config['support_email'] . "\r\n" .
"X-Mailer: PHP/" . phpversion()
);
}
}
2.付款验证
主要有这几样:
账号是否一致
txn_id是否有重复
item_number1和mc_gross是否正确。
时间不多,说的较乱,有空再补吧。
|
|