PayPal IPN:(PHP)发送不带<form> </form>的自定义字段

时间:2013-04-06 12:09:17

标签: php codeigniter paypal paypal-ipn

我正在使用CodeIgniter创建一个页面,用户可以在该页面注册我的俱乐部正在组织的慈善周期。

注册页面接受姓名/电话/电话号码等信息,并询问用户是否要在线或当天付款。单击提交按钮将信息发送到同一页面,运行表单验证,将信息插入数据库(包括时间戳)并检查用户是否选择在线支付。如果是这样,用户将被重定向到PayPal捐赠按钮 网址 以完成付款。

我的问题是,如何通过网址发送PayPal自定义字段?我已经尝试将&amp; custom = any附加到按钮URL,(其中“无论什么”是新数据库行ID和时间戳)但在使用沙箱帐户完成捐赠后这不起作用。

IPN:

public function ipn()
{
    // STEP 1: Read POST data

    // reading posted data from directly from $_POST causes serialization 
    // issues with array data in POST
    // reading raw POST data from input stream instead. 
    $raw_post_data = file_get_contents('php://input');
    $raw_post_array = explode('&', $raw_post_data);
    $myPost = array();
    foreach($raw_post_array as $keyval) 
    {
        $keyval = explode ('=', $keyval);
        if(count($keyval) == 2)
        {
            $myPost[$keyval[0]] = urldecode($keyval[1]);
        }
    }

    // read the post from PayPal system and add 'cmd'
    $req = 'cmd=_notify-validate';
    if(function_exists('get_magic_quotes_gpc')) 
    {
        $get_magic_quotes_exists = true;
    } 
    foreach($myPost 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('https://www.sandbox.paypal.com/cgi-bin/webscr');
    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, dirname(__FILE__) . '/cacert.pem');
    if(!($res = curl_exec($ch))) 
    {
        // error_log("Got " . curl_error($ch) . " when processing IPN data");
        curl_close($ch);
        exit;
    }
    curl_close($ch);


    // STEP 3: Inspect IPN validation result and act accordingly    

    if(strcmp($res, "VERIFIED") == 0) 
    {
        // PAYMENT VALIDATED & VERIFIED! 
        $custom = explode('_', $_POST['custom']);
        $reg_id = $custom[0];
        $date_registered = $custom[1];

        $query = $this->db->query('SELECT date_registered FROM registrations WHERE id=' . $reg_id);
        $array = $query->result_array();
        if($array['date_registered'] == $date_registered)
        {
            $data = array(
                'has_payed' => 1
            );
            $this->db->where('id', $reg_id);
            $this->db->update('registrations', $data);      
        }           
    }  
    elseif(strcmp($res, "INVALID") == 0) 
    {  
        // do whatever
    }           
}

请注意,我需要这个来更新数据库的'has_payed'字段,这需要在提交注册页面时发送行ID。

注册管理员:

// check payment online
if($this->input->post('pay_online') == 1) 
{
    // redirect to paypal depending on route
    switch($route)
    {
        case '80':
        case '40':
            // €20 for over 16s
            if($age >= 16)
            {
                redirect('https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=H3PFP5GGN2X5J&custom=' . urlencode($reg_id . '_' . $sql['date_registered']));
            }
            // €10 for anyone under 16
            else 
            {
                redirect('a different button URL');
            }
            break;
        case '15':
            // €15 for family
            redirect('a different button URL');
            break;
    }
}

上面的代码正在运行,因为我在提交具有适当值的表单时(即,做80公里或40公里的路线,超过16yo),我被重定向到按钮URL。当我在PayPal页面完成付款时,数据库中的'has_payed'字段不会更新(请参阅IPN页面)。

另外,请注意我的沙盒卖家帐户显然已启用IPN。

我已经搜索了几个小时的解决方案,但找不到任何东西。也许我忽略了一些简单的事情!我很感激任何帮助。

谢谢!


更新

我现在不是将用户重定向到PayPal按钮网址,而是将其重定向到包含<form>代码的HTML页面,以及在加载页面时自动提交表单的Javascript。这工作正常,但是当用户捐赠时,数据库字段仍然没有更新。

<form action="https://www.sandbox.paypal.com/cgi-bin/webscr" id="paypal_form" method="post" target="_top">
    <input type="hidden" name="cmd" value="_s-xclick">
    <input type="hidden" name="hosted_button_id" value="H3PFP5GGN2X5J">
    <input type="hidden" name="notify_url" value="#IPN URL#" />
    <input type="hidden" name="custom" value="<?php echo urlencode($reg_id . '_' . $sql['date_registered']); ?>">
    <input type="image" src="https://www.sandbox.paypal.com/en_US/GB/i/btn/btn_donateCC_LG.gif" border="0" name="submit" alt="PayPal – The safer, easier way to pay online.">
    <img alt="" border="0" src="https://www.sandbox.paypal.com/en_GB/i/scr/pixel.gif" width="1" height="1">
</form>

2 个答案:

答案 0 :(得分:0)

您可以将您发送的按钮代码中的变量“custom”传递给PayPal。然后通过IPN POST将其发送回您的系统。然后,您应该能够从那里抓取它并执行您需要的操作。

答案 1 :(得分:0)

问题当然很简单。

config.php中的启用了保护,导致IPN无法正常工作。禁用它可以解决问题。