我最近使用PayPal Lib在 CodeIgniter2 中实现了一个 PayPal IPN 。我正在使用该系统进行订阅。
我的数据库中有一个表,记录了数据库中的所有 IPN 请求。
出于某种原因,每次注册后,IPN 请求都无法正常通过。我倾向于获得一个 subscr_payment 和几个 subscr_signups,所有这些都具有相同的 subscr_id。由于显而易见的原因,它在系统内造成了无数的麻烦。更重要的是,IPN 请求的顺序不正确,有时我在 subscr_signup 之前得到 subscr_payment - 由于注册时没有 subscr_id 将其链接到用户,因此无法跟踪。
我有一个谷歌,在这方面找不到太多,我似乎有点反常。我想知道这是否与我正在使用的 PayPal Lib 有关,但我真的不想在 CodeIgniter 之外进行,因为我正在做很多处理。以下是完整的 IPN 脚本。
class Paypal extends CI_Controller {
function _construct()
{
parent::_construct();
$this->load->library('paypal_lib');
}
function ipn()
{
$this->output->enable_profiler(TRUE);
$this->load->model('payments_model');
$this->load->model('paypal_model');
$this->load->model('users_model');
ob_start();
if ($this->paypal_lib->validate_ipn())
{
$paypal_id = $this->paypal_model->add_paypal_ipn($this->paypal_lib->ipn_data);
// Split the 'custom' field up, containing ID of temp user, ID of package and coupon
$custom = explode(';', $this->paypal_lib->ipn_data['custom']);
###
# subscription sign up
###
if($this->paypal_lib->ipn_data['txn_type'] == 'subscr_signup') {
// Activate user/move from temp > live
$this->users_model->move_temp($custom[0], $this->paypal_lib->ipn_data['subscr_id']);
} # end subscr_signup
###
# subscription payment
###
if($this->paypal_lib->ipn_data['txn_type'] == 'subscr_payment') {
// Grab the coupon info, if we have one
$discount = 1;
if(!empty($custom[2])){
$this->load->model('coupons_model');
$couponinfo = $this->coupons_model->get_coupon($custom[2]);
$discount = $couponinfo->discount;
}
// Grab the package info
$package = $this->packages_model->get_package($custom[1]);
$price = $package->monthly * $discount; // Calculate discount, 0.8 = 20% off
// Does the price calculated match the gross price? If not something fishy is going on, block it
if($price != $this->paypal_lib->ipn_data['mc_gross']){
mail(CONTACT_EMAIL, SITE_NAME.' failed payment attempt, possible hack', 'Price paid doesnt match price computed... paid: '.$this->paypal_lib->ipn_data['mc_gross'].' - price worked out: '.$price."\n\n".print_r($this->paypal_lib->ipn_data, true));
exit;
}
// Grab the user's details based on the subscr_id
$user = $this->users_model->get_user_by_subscr_id($this->paypal_lib->ipn_data['subscr_id']);
// Add payment to the payments table
$data = array(
'user_id' => $user->user_id,
'subscr_id' => $user->subscr_id,
'txn_id' => $this->paypal_lib->ipn_data['txn_id'],
'amount' => $this->paypal_lib->ipn_data['mc_gross'],
'package_id' => $custom[1],
'coupon' => (empty($custom[2]) ? '' : $custom[2])
);
$this->payments_model->add_payment($data);
// Set (forced) user as active, and update their current active package
$data1 = array(
'package_id' => $custom[1],
'active' => 1
);
$this->users_model->update_user($data1, $user->user_id);
} # end subscr_payment
###
# subscription failed/cancelled
###
if($this->paypal_lib->ipn_data['txn_type'] == 'subscr_cancel' || $this->paypal_lib->ipn_data['txn_type'] == 'subscr_failed') {
// Grab user
$user = $this->users_model->get_user_by_subscr_id($this->paypal_lib->ipn_data['subscr_id']);
// Make user inactive
$data = array('active' => 0);
$this->users_model->update_user($data, $user->user_id);
} # end subscr_cancel|subscr_failed
###
# subscription modified/payment changed
###
if($this->paypal_lib->ipn_data['txn_type'] == 'subscr_modify') {
// Grab the coupon info, if we have one
$discount = 1;
if(!empty($custom[2])){
$this->load->model('coupons_model');
$couponinfo = $this->coupons_model->get_coupon($custom[2]);
$discount = $couponinfo->discount;
}
// Grab the package info
$package = $this->packages_model->get_package($custom[1]);
$price = $package->monthly * $discount; // Calculate discount, 0.8 = 20% off
// Does the price calculated match the gross price? If not something fishy is going on, block it
if($price != $this->paypal_lib->ipn_data['mc_gross']){
mail(CONTACT_EMAIL, SITE_NAME.' failed payment attempt, possible hack', 'Price paid doesnt match price computed... paid: '.$this->paypal_lib->ipn_data['mc_gross'].' - price worked out: '.$price."\n\n".print_r($this->paypal_lib->ipn_data, true));
exit;
}
// Grab the user's details based on the subscr_id
$user = $this->users_model->get_user_by_subscr_id($this->paypal_lib->ipn_data['subscr_id']);
// Add payment to the payments table
$data = array(
'user_id' => $user->user_id,
'subscr_id' => $user->subscr_id,
'txn_id' => $this->paypal_lib->ipn_data['txn_id'],
'amount' => $this->paypal_lib->ipn_data['mc_gross'],
'package_id' => $custom[1],
'coupon' => (empty($custom[2]) ? '' : $custom[2])
);
$this->payments_model->add_payment($data);
// Set (forced) user as active, and update their current active package
$data1 = array(
'package_id' => $custom[1],
'active' => 1
);
$this->users_model->update_user($data1, $user->user_id);
} # end subscr_modify
}
}
以下是为每笔交易 (CSV) 对我的 IPN 进行的调用示例。
paypal_id,txn_id,subscr_id,txn_type,created
1,NULL,I-FMUK0B5KJWKA,subscr_signup,2011-02-03 16:19:43
2,9XM95194MM564230E,I-FMUK0B5KJWKA,subscr_payment,2011-02-03 16:19:45
3,NULL,I-FMUK0B5KJWKA,subscr_signup,2011-02-03 16:19:57
4,NULL,I-FMUK0B5KJWKA,subscr_signup,2011-02-03 16:20:19
6,NULL,I-FMUK0B5KJWKA,subscr_signup,2011-02-03 16:21:03
7,NULL,I-FMUK0B5KJWKA,subscr_signup,2011-02-03 16:22:25
8,NULL,I-FMUK0B5KJWKA,subscr_signup,2011-02-03 16:25:08
10,NULL,I-FMUK0B5KJWKA,subscr_signup,2011-02-03 16:30:33
12,NULL,I-FMUK0B5KJWKA,subscr_signup,2011-02-03 16:41:16
14,NULL,I-FMUK0B5KJWKA,subscr_signup,2011-02-03 17:02:42
16,NULL,I-FMUK0B5KJWKA,subscr_signup,2011-02-03 17:45:26