source: branches/1.1dev/lib/PayPal.inc.php

Last change on this file was 708, checked in by anonymous, 4 years ago

Update class constructor method names to construct

File size: 11.5 KB
Line 
1<?php
2/**
3 * The PayPal:: class provides functions for creating PayPal buttons and for
4 * receiving PayPal's Instant Payment Notification (IPN) service.
5 *
6 * @author  Quinn Comendant <quinn@strangecode.com>
7 * @version 1.0
8 */
9class PayPal {
10   
11    // General object parameters.
12    var $_params = array(
13        'paypal_url' => 'https://www.paypal.com/cgi-bin/webscr',
14        'test_mode' => false,
15    );
16   
17    // Options used for specific buttons and links.
18    var $_default_button_options = array();
19   
20    // Array of buttons created by newButton().
21    var $_buttons = array();
22   
23    // Store the response from the last IPN.
24    var $_ipn_response;
25   
26    /**
27     * Constructor.
28     *
29     * @param   bool    $test_mode  Use PayPal sandbox for testing.
30     */
31    function __construct($test_mode=false)
32    {
33        if ($test_mode) {
34            $this->setParam(array('test_mode' => true));
35            // Use PayPal sandbox when in test mode.
36            $url = 'www.sandbox.paypal.com';
37        } else {
38            $url = 'www.paypal.com';
39        }
40       
41        $this->_default_button_options = array(
42            '_global' => array(
43                'business' => null,
44            ),
45            'web_accept' => array(
46                'cmd' => '_xclick',
47                'button_url' => 'https://' . $url . '/cgi-bin/webscr',
48                'link_url' => 'https://' . $url . '/xclick/',
49                'submit_img' => 'https://' . $url . '/en_US/i/btn/x-click-but23.gif',
50                'submit_text' => _("Pay with PayPal"),
51            ),
52            'subscriptions' => array(
53                'cmd' => '_xclick-subscriptions',
54                'button_url' => 'https://' . $url . '/cgi-bin/webscr',
55                'link_url' => 'https://' . $url . '/subscriptions/',
56                'submit_img' => 'https://' . $url . '/en_US/i/btn/x-click-but20.gif',
57                'submit_text' => _("Subscribe with PayPal"),
58            ),
59        );
60    }
61   
62    /**
63     * Updates the _default_button_options array with options used for
64     * specific buttons, or all buttons if $type is null.
65     *
66     * @access  public
67     *
68     * @param   mixed   $type       The type of button to set defaults. If null,
69     *                              sets the global button types.
70     * @param   array   $options    Options to set for button.
71     *
72     * @return  bool    True on success, false on failure.
73     */
74    function setButtonDefaults($type, $options)
75    {
76        if (!is_array($options) || empty($options)) {
77            logMsg(sprintf('Invalid options: %s', getDump($options)), LOG_WARNING, __FILE__, __LINE__);
78            return false;
79        }
80       
81        if (is_null($type) || '_global' == $type) {
82            $this->_default_button_options['_global'] = array_merge($this->_default_button_options['_global'], $options);
83        } else if (!isset($this->_default_button_options[$type])) {
84            logMsg(sprintf('Invalid button type: %s', $type), LOG_WARNING, __FILE__, __LINE__);
85            return false;
86        }
87       
88        $this->_default_button_options[$type] = array_merge($this->_default_button_options[$type], $options);
89        return true;
90    }
91   
92    /**
93     * Creates a new element in the _buttons array. Uses _default_button_options
94     * merged with provided options.
95     *
96     * @access  public
97     *
98     * @param   string  $type       Type of button to create.
99     * @param   string  $name       Name of button to create.
100     * @param   array   $options    Options of button. Overwrites _default_button_options.
101     *
102     * @return  bool    True on success, false on failure.
103     */
104    function newButton($type, $name, $options=null)
105    {
106        if (!isset($this->_default_button_options[$type])) {
107            logMsg(sprintf('Invalid button type: %s', $type), LOG_WARNING, __FILE__, __LINE__);
108            return false;
109        }
110       
111        if (!is_array($options) || empty($options)) {
112            logMsg(sprintf('Invalid options: %s', getDump($options)), LOG_WARNING, __FILE__, __LINE__);
113            return false;
114        }
115       
116        if (isset($this->_buttons[$name])) {
117            logMsg(sprintf('Overwriting existing button name: %s', getDump($this->_buttons[$name])), LOG_DEBUG, __FILE__, __LINE__);
118        }
119       
120        $this->_buttons[$name] = array(
121            'type' => $type,
122            'options' => array_merge($this->_default_button_options['_global'], $this->_default_button_options[$type], $options)
123        );
124
125        return true;
126    }
127
128    /**
129     * Returns the URL link for specified button.
130     *
131     * @access  public
132     *
133     * @param   string  $name   Name of button for which to generate link.
134     *
135     * @return  mixed   Link of button, or false on failure.
136     */
137    function getLink($name)
138    {
139        if (!isset($this->_buttons[$name])) {
140            logMsg(sprintf('Button does not exist: %s', $name), LOG_WARNING, __FILE__, __LINE__);
141            return false;
142        }
143       
144        $query_string = '';
145        $delim = '';
146        if (is_array($this->_buttons[$name]['options']) && !empty($this->_buttons[$name]['options'])) {
147            foreach ($this->_buttons[$name]['options'] as $key=>$val) {
148                if (!in_array($key, array('button_url', 'link_url', 'cmd', 'submit_img', 'submit_text'))) {
149                    $query_string .= $delim . $key . '=' . urlencode($val);
150                    $delim = '&';
151                }
152            }
153        }
154
155        // PayPal links do not like urlencoded slashes for some stupid reason.
156        $search = array('/%2F/');
157        $replace = array('/');
158       
159        return $this->_buttons[$name]['options']['link_url'] . preg_replace($search, $replace, $query_string);
160    }
161
162    /**
163     * Prints the link returned by getLink().
164     *
165     * @access  public
166     *
167     * @param   string  $name   Name of button for which to generate link.
168     */
169    function printLink($name)
170    {
171        echo $this->getLink($name);
172    }
173
174    /**
175     * Prints button with specified name.
176     *
177     * @access  public
178     *
179     * @param   string  $name   Name of button to print.
180     */
181    function printButton($name)
182    {
183        ?>
184        <form action="<?php echo $this->_buttons[$name]['options']['button_url']; ?>" method="post">
185        <?php 
186        if (is_array($this->_buttons[$name]['options']) && !empty($this->_buttons[$name]['options'])) {
187            foreach ($this->_buttons[$name]['options'] as $key=>$val) {
188                if (!in_array($key, array('button_url', 'link_url', 'submit_img', 'submit_text'))) {
189                    ?>
190                    <input type="hidden" name="<?php echo $key; ?>" value="<?php echo $val; ?>">
191                    <?php
192                }
193            }
194        } 
195        ?>
196        <input type="image" src="<?php echo $this->_buttons[$name]['options']['submit_img']; ?>" border="0" name="submit" alt="<?php echo $this->_buttons[$name]['options']['submit_text']; ?>">
197        </form>
198        <?php
199    }
200
201    /**
202     * Set (or overwrite existing) parameters by passing an array of new parameters.
203     *
204     * @access public
205     *
206     * @param  array    $params     Array of parameters (key => val pairs).
207     */
208    function setParam($params=null)
209    {
210        if (isset($params) && is_array($params)) {
211            // Set parameters for this object.
212            $this->_params = array_merge($this->_params, $params);
213        }
214    }
215
216    /**
217     * Return the value of a parameter.
218     *
219     * @access  public
220     *
221     * @param   string  $param      The key of the parameter to return.
222     *
223     * @return  mixed               Parameter value.
224     */
225    function getParam($param)
226    {
227        return $this->_params[$param];
228    }
229
230    /**
231     * Tests if the HTTP request is a valid IPN request from PayPal.
232     *
233     * @access  public
234     *
235     * @return  bool    True if valid, false if invalid.
236     */
237    function incomingIPNRequest()
238    {
239        if ($_SERVER['REQUEST_METHOD'] == 'POST' 
240        && $_SERVER['CONTENT_TYPE'] == 'application/x-www-form-urlencoded'
241        && !empty($_POST)) {
242            return true;
243        } else {
244            return false;
245        }
246    }
247
248    /**
249     * Process incoming IPN.
250     *
251     * @access  public
252     *
253     * @return  bool    True on success, false on failure.
254     */
255    function processIPN()
256    {       
257        if (getPost('test_ipn') == '1' || $this->getParam('test_mode')) {
258            logMsg(sprintf('Processing PayPal IPN in test mode: %s', getDump(getFormData())), LOG_DEBUG, __FILE__, __LINE__);
259            $url = parse_url('https://www.sandbox.paypal.com/cgi-bin/webscr');
260        } else {
261            logMsg(sprintf('Processing PayPal IPN: %s', getDump(getFormData())), LOG_DEBUG, __FILE__, __LINE__);
262            $url = parse_url($this->getParam('paypal_url'));
263        }
264       
265        // Read POST request and add 'cmd'.
266        $received_data = getPost();
267        $return_data = 'cmd=_notify-validate';
268        foreach ($received_data as $post_key => $post_val) {
269            $return_data .= '&' . $post_key . '=' . urlencode($post_val);
270        }
271       
272        // Set the port number based on the scheme.
273        if ($url['scheme'] == "https") { 
274            $url['port'] = 443;
275            $ssl = 'ssl://';
276        } else {
277            $url['port'] = 80;
278            $ssl = '';
279        }
280           
281        // Open connection to PayPal server.
282        $fp = fsockopen($ssl . $url['host'], $url['port'], $errnum, $errstr, 30); 
283
284        if (!$fp) {
285            logMsg(sprintf('Connection to PayPal URL %s failed with error: %s (%s)', $ssl . $url['host'], $errstr, $errnum), LOG_WARNING, __FILE__, __LINE__);
286            return false;
287        } else {
288            fputs($fp, "POST {$url['path']} HTTP/1.1\r\n"); 
289            fputs($fp, "Host: {$url['host']}\r\n"); 
290            fputs($fp, "Content-type: application/x-www-form-urlencoded\r\n"); 
291            fputs($fp, "Content-length: " . strlen($return_data) . "\r\n"); 
292            fputs($fp, "Connection: close\r\n\r\n"); 
293            fputs($fp, $return_data . "\r\n\r\n"); 
294                           
295            // Loop through the response lines from the server.
296            $this->_ipn_response = '';
297            while (!feof($fp)) {
298                $this->_ipn_response .= fgets($fp, 1024);
299            }
300            fclose($fp);
301           
302            logMsg(sprintf('IPN response received: %s', $this->_ipn_response), LOG_NOTICE, __FILE__, __LINE__);
303            return true;
304        }
305    }
306   
307    /**
308     * Checks the response received from PayPal's IPN upon calling processIPN().
309     *
310     * @access  public
311     *
312     * @return  bool    True if response contains VERIFIED, false otherwise.
313     */
314    function verifiedIPN()
315    {
316        if (!isset($this->_ipn_response)) {
317            logMsg(sprintf('Cannot verify IPN, response not received.', null), LOG_WARNING, __FILE__, __LINE__);
318            return false;
319        }
320       
321        if (empty($this->_ipn_response)) {
322            logMsg(sprintf('Cannot verify IPN, response empty.', null), LOG_WARNING, __FILE__, __LINE__);
323            return false;
324        }
325       
326        if (preg_match('/VERIFIED/', $this->_ipn_response)) {
327            logMsg(sprintf('IPN verified!', null), LOG_DEBUG, __FILE__, __LINE__);
328            return true;
329        } else if (preg_match('/INVALID/', $this->_ipn_response)) {
330            logMsg(sprintf('IPN invalid.', null), LOG_DEBUG, __FILE__, __LINE__);
331            return false;
332        } else {
333            logMsg(sprintf('IPN unknown.', null), LOG_WARNING, __FILE__, __LINE__);
334            return false;
335        }
336    }
337   
338   
339} 
340// End of class.
341
342?>
Note: See TracBrowser for help on using the repository browser.