Completed
Branch master (6a6544)
by Pierre-Henry
33:43
created

framework/Payment/Gateway/Api/PayPal.class.php (2 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * @title            PayPal Class
4
 *
5
 * @author           Pierre-Henry Soria <[email protected]>
6
 * @copyright        (c) 2012-2017, Pierre-Henry Soria. All Rights Reserved.
7
 * @license          GNU General Public License; See PH7.LICENSE.txt and PH7.COPYRIGHT.txt in the root directory.
8
 * @package          PH7 / Framework / Payment / Gateway / Api
9
 * @version          1.1
10
 */
11
12
namespace PH7\Framework\Payment\Gateway\Api;
13
14
defined('PH7') or exit('Restricted access');
15
16
use PH7\Framework\File\Stream;
17
use PH7\Framework\Url\Url;
18
19
/**
20
 * PayPal class using PayPal's API
21
 *
22
 * @link https://developer.paypal.com/docs/integration/direct/identity/seamless-checkout/
23
 */
24
class Paypal extends Provider implements Api
25
{
26
    const SANDBOX_PAYMENT_URL = 'https://www.sandbox.paypal.com/cgi-bin/webscr';
27
    const PAYMENT_URL = 'https://www.paypal.com/cgi-bin/webscr';
28
29
    /** @var string */
30
    private $_sUrl;
31
32
    /** @var string */
33
    private $_sRequest = 'cmd=_notify-validate';
34
35
    /** @var string */
36
    private $_sMsg;
37
38
    /** @var string|null */
39
    private $_bValid = null;
40
41
42
    /**
43
     * @param boolean $bSandbox Default FALSE
44
     */
45
    public function __construct($bSandbox = false)
46
    {
47
        if ($bSandbox) {
48
            $this->_sUrl = self::SANDBOX_PAYMENT_URL;
49
        } else {
50
            $this->_sUrl = self::PAYMENT_URL;
51
        }
52
53
        $this->param('cmd', '_xclick');
54
    }
55
56
    /**
57
     * Get Checkout URL.
58
     *
59
     * @param string $sParam
60
     *
61
     * @return string
62
     * @internal We added an empty parameter for the method only to be compatible with the API interface.
63
     */
64
    public function getUrl($sParam = '')
65
    {
66
        return $this->_sUrl;
67
    }
68
69
    /**
70
     * Get message status.
71
     *
72
     * @return string
73
     */
74
    public function getMsg()
75
    {
76
        return $this->_sMsg;
77
    }
78
79
    /**
80
     * Check if the transaction is valid.
81
     *
82
     * @param string $sParam1
83
     * @param string $sParam2
84
     *
85
     * @return boolean
86
     * @internal We added two empty parameters for the method only to be compatible with the API interface.
87
     */
88
    public function valid($sParam1 = '', $sParam2 = '')
89
    {
90
        // If already validated, just return last result
91
        if (true === $this->_bValid || false === $this->_bValid) {
92
            return $this->_bValid;
93
        }
94
95
        $this->setParams();
96
97
        $mStatus = $this->getStatus();
98
99
        if (0 == strcmp('VERIFIED', $mStatus)) {
100
            // Valid
101
            if ($_POST['payment_status'] == 'Completed') {
102
                $this->_bValid = true;
0 ignored issues
show
Documentation Bug introduced by
It seems like true of type boolean is incompatible with the declared type string|null of property $_bValid.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
103
                $this->_sMsg = t('Transaction valid and completed.');
104
            } else {
105
                $this->_bValid = false;
0 ignored issues
show
Documentation Bug introduced by
It seems like false of type false is incompatible with the declared type string|null of property $_bValid.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
106
                $this->_sMsg = t('Transaction valid but not completed.');
107
            }
108
        } elseif (0 == strcmp('INVALID', $mStatus)) {
109
            // Bad Connection
110
            $this->_bValid = false;
111
            $this->_sMsg = t('Invalid transaction.');
112
        } else {
113
            // Bad Connection
114
            $this->_bValid = false;
115
            $this->_sMsg = t('Connection to PayPal failed.');
116
        }
117
118
        return $this->_bValid;
119
    }
120
121
    /**
122
     * Connect to Paypal.
123
     *
124
     * @return boolean|string Message from the transaction status on success or FALSE on failure.
125
     */
126
     protected function getStatus()
127
     {
128
         $rCh = curl_init($this->_sUrl);
129
         curl_setopt($rCh, CURLOPT_POST, 1);
130
         curl_setopt($rCh, CURLOPT_RETURNTRANSFER, 1);
131
         curl_setopt($rCh, CURLOPT_POSTFIELDS, $this->_sRequest);
132
         curl_setopt($rCh, CURLOPT_SSL_VERIFYPEER, 1);
133
         curl_setopt($rCh, CURLOPT_SSL_VERIFYHOST, 2);
134
         curl_setopt($rCh, CURLOPT_HTTPHEADER, array('Host: www.paypal.com'));
135
         $mRes = curl_exec($rCh);
136
         curl_close($rCh);
137
         unset($rCh);
138
139
         return $mRes;
140
     }
141
142
    /**
143
     * Set the data parameters POST from PayPal system.
144
     *
145
     * @return self
146
     */
147
     protected function setParams()
148
     {
149
         foreach ($this->getPostDatas() as $sKey => $sValue) {
150
             $this->setUrlData($sKey, $sValue);
151
         }
152
153
         return $this;
154
     }
155
156
    /**
157
     * Set data URL e.g., "&key=value"
158
     *
159
     * @param string $sName
160
     * @param string $sValue
161
     *
162
     * @return self
163
     */
164
    protected function setUrlData($sName, $sValue)
165
    {
166
        $this->_sRequest .= '&' . $sName . '=' . Url::encode($sValue);
167
        return $this;
168
    }
169
170
    /**
171
     * Get the Post Data.
172
     *
173
     * @return array
174
     */
175
    protected function getPostDatas()
176
    {
177
        $rRawPost = Stream::getInput();
178
        $aRawPost = explode('&', $rRawPost);
179
        $aPostData = array();
180
181
        foreach ($aRawPost as $sKeyVal) {
182
            $aKeyVal = explode ('=', $sKeyVal);
183
            if (count($aKeyVal) == 2) {
184
                $aPostData[$aKeyVal[0]] = Url::encode($aKeyVal[1]);
185
            }
186
            unset($aKeyVal);
187
        }
188
        unset($aRawPost);
189
190
        return $aPostData;
191
    }
192
}
193