I am using a PHP class that I have created based on the sample code from the paypal website. I am also using this with CodeIgniter. I test the IPN listener with the IPN simulator. My emails are sent, so I know it is being accessed. The problem is that I always get a response of INVALID and I have no idea why. This is my first time integrating PayPal within one of my sites. What could be causing this problem?
我使用的是基于贝宝网站的示例代码创建的PHP类。我也在CodeIgniter中使用这个。我使用IPN模拟器测试IPN监听器。我的邮件被发送了,所以我知道它正在被访问。问题是我总是得到一个无效的响应,我不知道为什么。这是我第一次在我的一个网站上整合贝宝。是什么导致了这个问题?
Here is my class:
这是我的类:
<?php
class Paypal {
public $sandbox = false;
private $_url;
public $verified = false;
public $fields = array();
public $post_fields = array();
public $result;
public function __construct($params = array()){
$this->sandbox = (isset($params['sandbox'])) ? $params['sandbox'] : false;
$this->_url = ($this->sandbox) ? 'https://www.sandbox.paypal.com/cgi-bin/webscr' : 'https://www.paypal.com/cgi-bin/webscr';
}
public function run(){
$this->verified = false;
// STEP 1: read POST data
// Reading POSTed data directly from $_POST causes serialization issues with array data in the POST.
// Instead, read raw POST data from the input stream.
$raw_post_data = file_get_contents('php://input');
$raw_post_array = explode('&', $raw_post_data);
foreach ($raw_post_array as $keyval) {
$keyval = explode ('=', $keyval);
if (count($keyval) == 2)
$this->post_fields[$keyval[0]] = urldecode($keyval[1]);
}
// read the IPN message sent from PayPal and prepend 'cmd=_notify-validate'
$req = 'cmd=_notify-validate';
if (function_exists('get_magic_quotes_gpc')) {
$get_magic_quotes_exists = true;
}
foreach ($this->post_fields as $key => $value) {
if ($get_magic_quotes_exists == true && get_magic_quotes_gpc() == 1) {
$value = urlencode(stripslashes($value));
} else {
$value = urlencode($value);
}
$req .= "&$key=$value";
}
// Step 2: POST IPN data back to PayPal to validate
$ch = curl_init($this->_url);
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: Close'));
// In wamp-like environments that do not come bundled with root authority certificates,
// please download 'cacert.pem' from "http://curl.haxx.se/docs/caextract.html" and set
// the directory path of the certificate as shown below:
curl_setopt($ch, CURLOPT_CAINFO, FCPATH.'cacert.pem');
if ( !($res = curl_exec($ch)) ) {
// error_log("Got " . curl_error($ch) . " when processing IPN data");
curl_close($ch);
die('curl did not work<br>'.FCPATH.'cacert.pem');
}
curl_close($ch);
if (strcmp ($res, "VERIFIED") == 0) {
$this->verified = true;
}
$this->result = $res;
}
Here is my CI Controller:
这是我的CI控制器:
function paypalipn(){
$this->load->model('subscription');
$this->load->library('paypal', array('sandbox' => true));;
$this->paypal->run();
$fields = $this->paypal->post_fields;
if($this->paypal->verified){
$data = array(
'user_id' => $fields['buyer_id'],
'txn_id' => $fields['txn_id'],
'payment_gross' => $fields['mc_gross'],
'currency_code' => $fields['mc_currency'],
'payer_email' => $fields['payer_email'],
'plan_id' => $fields['item_number'],
'payment_status' => $fields['payment_status']
);
$this->subscription->create_payment($data);
}
$this->load->library('email');
$this->email->to('*******@gmail.com');
$this->email->from('**************');
$this->email->subject('PayPal IPN');
$this->email->message($this->paypal->result."\nAmount: ".$fields['mc_gross']."\nCurrency: ".$fields['mc_currency']."\nUser ID: ".$fields['buyer_id']);
$this->email->send();
}
All of the fields are blank in the email message and $this->paypal->result always returns "INVALID". Anybody have any ideas? Thanks for your time.
所有字段在电子邮件消息中为空,$this->paypal->结果总是返回“无效”。谁有什么好主意吗?谢谢你的时间。
1 个解决方案
#1
0
In your CI controller if you have written your code like this:
在您的CI控制器中,如果您编写了如下代码:
function paypalipn(){
$this->load->model('subscription');
$this->load->library('paypal', array('sandbox' => true));;
$this->paypal->run();
$fields = $this->paypal->post_fields;
if($this->paypal->verified){
$data = array(
'user_id' => $fields['buyer_id'],
'txn_id' => $fields['txn_id'],
'payment_gross' => $fields['mc_gross'],
'currency_code' => $fields['mc_currency'],
'payer_email' => $fields['payer_email'],
'plan_id' => $fields['item_number'],
'payment_status' => $fields['payment_status']
);
$this->subscription->create_payment($data);
$this->load->library('email');
$this->email->to('*******@gmail.com');
$this->email->from('**************');
$this->email->subject('PayPal IPN');
$this->email->message($this->paypal->result."\nAmount: ".$fields['mc_gross']."\nCurrency: ".$fields['mc_currency']."\nUser ID: ".$fields['buyer_id']);
$this->email->send();
}
}
OR if you have stopped the script in case the if statement failed
或者,如果在if语句失败时停止了脚本
if($this->paypal->verified){
$data = array(
'user_id' => $fields['buyer_id'],
'txn_id' => $fields['txn_id'],
'payment_gross' => $fields['mc_gross'],
'currency_code' => $fields['mc_currency'],
'payer_email' => $fields['payer_email'],
'plan_id' => $fields['item_number'],
'payment_status' => $fields['payment_status']
);
$this->subscription->create_payment($data);
} else {
exit("We are sad to inform you that verification FAILED. Bye!");
}
you would not receive any email. The issue is in public function run()
in your paypal class and this is most probably the failing part.
您不会收到任何电子邮件。问题在您的paypal类的public function run()中,这很可能是失败的部分。
if ( !($res = curl_exec($ch)) ) {
curl_close($ch);
die('curl did not work<br>'.FCPATH.'cacert.pem');
}
curl_close($ch);
if (strcmp ($res, "VERIFIED") == 0) {
$this->verified = true;
}
Try re-writing it like this
试着这样重写
$res=curl_exec($ch); // define $res
if($res==null){ // check if $res is null
exit('curl did not work<br>'.FCPATH.'cacert.pem');
}
curl_close($ch);
if (strcmp ($res, "VERIFIED") === 0) {
$this->verified = true;
}
Regarding the last 3 lines where strcmp()
is used, and based on a user comment in strcmp()
documentation.
关于使用strcmp()的最后三行,并基于strcmp()文档中的用户注释。
- strcmp() will return NULL on failure.
- 如果失败,strcmp()将返回NULL。
- This has the side effect of equating to a match when using an equals comparison (==).
- 这有一个副作用,当使用equals比较(==)时等于一个匹配。
- Instead, you may wish to test matches using the identical comparison (===), which should not catch a NULL return.
- 相反,您可能希望使用相同的比较(===)来测试匹配,该比较不应该捕获空返回。
What does the above mean? In a small example.
以上是什么意思?在一个小例子。
if(null==0) {
echo "1";
}
if(null===0) {
echo "2";
}
The above example will only output => 1 which in your case that means that if strcmp()
fails you will have set verified
to true
which is not correct.
上面的示例将只输出=> 1,在您的示例中,这意味着如果strcmp()失败,您将会将已验证的设置为true,这是不正确的。
#1
0
In your CI controller if you have written your code like this:
在您的CI控制器中,如果您编写了如下代码:
function paypalipn(){
$this->load->model('subscription');
$this->load->library('paypal', array('sandbox' => true));;
$this->paypal->run();
$fields = $this->paypal->post_fields;
if($this->paypal->verified){
$data = array(
'user_id' => $fields['buyer_id'],
'txn_id' => $fields['txn_id'],
'payment_gross' => $fields['mc_gross'],
'currency_code' => $fields['mc_currency'],
'payer_email' => $fields['payer_email'],
'plan_id' => $fields['item_number'],
'payment_status' => $fields['payment_status']
);
$this->subscription->create_payment($data);
$this->load->library('email');
$this->email->to('*******@gmail.com');
$this->email->from('**************');
$this->email->subject('PayPal IPN');
$this->email->message($this->paypal->result."\nAmount: ".$fields['mc_gross']."\nCurrency: ".$fields['mc_currency']."\nUser ID: ".$fields['buyer_id']);
$this->email->send();
}
}
OR if you have stopped the script in case the if statement failed
或者,如果在if语句失败时停止了脚本
if($this->paypal->verified){
$data = array(
'user_id' => $fields['buyer_id'],
'txn_id' => $fields['txn_id'],
'payment_gross' => $fields['mc_gross'],
'currency_code' => $fields['mc_currency'],
'payer_email' => $fields['payer_email'],
'plan_id' => $fields['item_number'],
'payment_status' => $fields['payment_status']
);
$this->subscription->create_payment($data);
} else {
exit("We are sad to inform you that verification FAILED. Bye!");
}
you would not receive any email. The issue is in public function run()
in your paypal class and this is most probably the failing part.
您不会收到任何电子邮件。问题在您的paypal类的public function run()中,这很可能是失败的部分。
if ( !($res = curl_exec($ch)) ) {
curl_close($ch);
die('curl did not work<br>'.FCPATH.'cacert.pem');
}
curl_close($ch);
if (strcmp ($res, "VERIFIED") == 0) {
$this->verified = true;
}
Try re-writing it like this
试着这样重写
$res=curl_exec($ch); // define $res
if($res==null){ // check if $res is null
exit('curl did not work<br>'.FCPATH.'cacert.pem');
}
curl_close($ch);
if (strcmp ($res, "VERIFIED") === 0) {
$this->verified = true;
}
Regarding the last 3 lines where strcmp()
is used, and based on a user comment in strcmp()
documentation.
关于使用strcmp()的最后三行,并基于strcmp()文档中的用户注释。
- strcmp() will return NULL on failure.
- 如果失败,strcmp()将返回NULL。
- This has the side effect of equating to a match when using an equals comparison (==).
- 这有一个副作用,当使用equals比较(==)时等于一个匹配。
- Instead, you may wish to test matches using the identical comparison (===), which should not catch a NULL return.
- 相反,您可能希望使用相同的比较(===)来测试匹配,该比较不应该捕获空返回。
What does the above mean? In a small example.
以上是什么意思?在一个小例子。
if(null==0) {
echo "1";
}
if(null===0) {
echo "2";
}
The above example will only output => 1 which in your case that means that if strcmp()
fails you will have set verified
to true
which is not correct.
上面的示例将只输出=> 1,在您的示例中,这意味着如果strcmp()失败,您将会将已验证的设置为true,这是不正确的。