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

modules/payment/controllers/MainController.php (10 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          Main Controller
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 / App / System / Module / Payment / Controller
9
 * @version        1.4
10
 */
11
12
namespace PH7;
13
14
use PH7\Framework\Mvc\Model\DbConfig;
15
use PH7\Framework\Mail\Mail;
16
17
class MainController extends Controller
18
{
19
    /** @var AffiliateCoreModel */
20
    protected $oUserModel;
21
22
    /** @var PaymentModel */
23
    protected $oPayModel;
24
25
    /** @var string */
26
    protected $sTitle;
27
28
    /** @var int */
29
    protected $iProfileId;
30
31
    /** @var bool Payment status. Default is failure (FALSE) */
32
    private $_bStatus = false;
33
34
35
    public function __construct()
36
    {
37
        parent::__construct();
38
39
        $this->oUserModel = new AffiliateCoreModel;
40
        $this->oPayModel = new PaymentModel;
41
        $this->iProfileId = $this->session->get('member_id');
42
    }
43
44
    public function index()
45
    {
46
        $this->sTitle = t('Payment Zone');
47
        $this->view->page_title = $this->view->h1_title = $this->sTitle;
48
        $this->output();
0 ignored issues
show
The method output() does not seem to exist on object<PH7\MainController>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
49
    }
50
51
    public function membership()
52
    {
53
        $oMembershipModel = $this->oPayModel->getMemberships();
54
55
        if (empty($oMembershipModel))
56
        {
57
            $this->displayPageNotFound(t('No membership found!'));
0 ignored issues
show
The method displayPageNotFound() does not seem to exist on object<PH7\MainController>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
58
        }
59
        else
60
        {
61
            $this->sTitle = t('Memberships List');
62
            $this->view->page_title = $this->view->h2_title = $this->sTitle;
63
            $this->view->memberships = $oMembershipModel;
64
            $this->output();
0 ignored issues
show
The method output() does not seem to exist on object<PH7\MainController>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
65
        }
66
    }
67
68
    public function pay($iMembershipId = null)
69
    {
70
        $iMembershipId = (int) $iMembershipId;
71
72
        $oMembershipModel = $this->oPayModel->getMemberships($iMembershipId);
73
74
        if (empty($iMembershipId) || empty($oMembershipModel))
75
        {
76
            $this->displayPageNotFound(t('No membership found!'));
77
        }
78
        else
79
        {
80
            // Adding the stylesheet for Gatway Logo
81
            $this->design->addCss(PH7_LAYOUT . PH7_SYS . PH7_MOD . $this->registry->module . PH7_SH . PH7_TPL . PH7_TPL_MOD_NAME . PH7_SH . PH7_CSS, 'common.css');
82
83
            // Regenerate the session ID to prevent the session fixation attack
84
            $this->session->regenerateId();
85
86
            $this->sTitle = t('Pay!');
87
            $this->view->page_title = $this->view->h2_title = $this->sTitle;
88
            $this->view->membership = $oMembershipModel;
89
            $this->output();
0 ignored issues
show
The method output() does not seem to exist on object<PH7\MainController>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
90
        }
91
    }
92
93
    public function process($sProvider = '')
94
    {
95
        switch ($sProvider)
96
        {
97
            case 'paypal':
98
            {
99
                $oPayPal = new PayPal($this->config->values['module.setting']['sandbox.enabled']);
100
                if ($oPayPal->valid() && $this->httpRequest->postExists('custom'))
101
                {
102
                    $aData = explode('|', base64_decode($this->httpRequest->post('custom')));
103
                    $iItemNumber = (int) $aData[0];
104
                    $fPrice = $aData[1];
105
                    if ($this->oUserModel->updateMembership($iItemNumber, $this->iProfileId, $fPrice, $this->dateTime->get()->dateTime('Y-m-d H:i:s')))
0 ignored issues
show
The property iProfileId does not seem to exist. Did you mean _iProfileId?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
106
                    {
107
                        $this->_bStatus = true; // Status is OK
108
                        // PayPal will call automatically the "notification()" method thanks its IPN feature and "notify_url" form attribute.
109
                    }
110
                }
111
                unset($oPayPal);
112
            }
113
            break;
114
115
            case 'stripe':
116
            {
117
                if ($this->httpRequest->postExists('stripeToken'))
118
                {
119
                    \Stripe\Stripe::setApiKey($this->config->values['module.setting']['stripe.secret_key']);
120
                    $sAmount = $this->httpRequest->post('amount');
121
122
                    try
123
                    {
124
                        $oCharge = \Stripe\Charge::create(
125
                            [
126
                                'amount' => Stripe::getAmount($sAmount),
127
                                'currency' => $this->config->values['module.setting']['currency'],
128
                                'source' => $this->httpRequest->post('stripeToken'),
129
                                'description'    => 'Membership charged for ' . $this->httpRequest->post('stripeEmail')
130
                            ]
131
                        );
132
133
                        if ($this->oUserModel->updateMembership($this->httpRequest->post('item_number'), $this->iProfileId, $sAmount, $this->dateTime->get()->dateTime('Y-m-d H:i:s')))
0 ignored issues
show
The property iProfileId does not seem to exist. Did you mean _iProfileId?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
134
                        {
135
                            $this->_bStatus = true; // Status is OK
136
                            $this->notification('Stripe'); // Add info into the log file
137
                        }
138
                    }
139
                    catch (\Stripe\Error\Card $oE)
140
                    {
141
                        // The card has been declined
142
                        // Do nothing here as "$this->_bStatus" is by default FALSE and so it will display "Error occurred" msg later
143
                    }
144
                    catch (\Stripe\Error\Base $oE)
145
                    {
146
                        $this->design->setMessage( $this->str->escape($oE->getMessage(), true) );
147
                    }
148
                }
149
            }
150
            break;
151
152
            case '2co':
153
            {
154
                $o2CO = new TwoCO($this->config->values['module.setting']['sandbox.enabled']);
155
                $sVendorId = $this->config->values['module.setting']['2co.vendor_id'];
156
                $sSecretWord = $this->config->values['module.setting']['2co.secret_word'];
157
158
                if ($o2CO->valid($sVendorId, $sSecretWord) && $this->httpRequest->postExists('sale_id'))
159
                {
160
                    if ($this->oUserModel->updateMembership($this->httpRequest->post('cart_order_id'), $this->iProfileId, $this->httpRequest->post('total'), $this->dateTime->get()->dateTime('Y-m-d H:i:s')))
0 ignored issues
show
The property iProfileId does not seem to exist. Did you mean _iProfileId?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
161
                    {
162
                        $this->_bStatus = true; // Status is OK
163
                        $this->notification('TwoCO'); // Add info into the log file
164
                    }
165
                }
166
                unset($o2CO);
167
            }
168
            break;
169
170
            case 'ccbill':
171
            {
172
                // In developing...
173
                // Contact us at <[email protected]> or <[email protected]> if you want to help us by developing the payment system CCBill
174
            }
175
            break;
176
177
            default:
178
                $this->displayPageNotFound(t('Provinder Not Found!'));
179
        }
180
181
        // Set the page titles
182
        $this->sTitle = ($this->_bStatus) ? t('Thank you!') : t('Error occurred!');
183
        $this->view->page_title = $this->view->h2_title = $this->sTitle;
184
185
        if ($this->_bStatus)
186
        {
187
            $this->updateAffCom();
188
            $this->clearCache();
189
        }
190
191
        // Set the valid page
192
        $sPage = ($this->_bStatus) ? 'success' : 'error';
193
        $this->manualTplInclude($sPage . $this->view->getTplExt());
194
195
        // Output
196
        $this->output();
0 ignored issues
show
The method output() does not seem to exist on object<PH7\MainController>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
197
    }
198
199
    public function notification($sGatewayName = '')
200
    {
201
        // Save buyer information to a log file
202
        if ($sGatewayName == 'PayPal' || $sGatewayName == 'Stripe' || $sGatewayName == 'TwoCO' || $sGatewayName == 'CCBill')
203
        {
204
            $sGatewayName = 'PH7\\' . $sGatewayName;
205
            $this->log(new $sGatewayName(false), t('%0% payment was made with the following information:', $sGatewayName));
206
        }
207
208
        // Send a notification email
209
        $this->sendNotifyMail();
210
    }
211
212
    public function info()
213
    {
214
        $this->sTitle = t('Details of the membership');
215
        $this->view->page_title = $this->view->h2_title = $this->sTitle;
216
217
        $oInfo = $this->oUserModel->getMembershipDetails($this->iProfileId);
218
        if ($oInfo->expirationDays != 0 && !empty($oInfo->membershipDate)) {
219
            $oDate = new \DateTime($oInfo->membershipDate);
220
            $oDate->add(new \DateInterval( sprintf('P%dD', $oInfo->expirationDays)) );
221
            $this->view->expirationDate = $oDate->format($this->config->values['language.application']['date_time_format']);
222
            unset($oDate);
223
        } else {
224
            $this->view->expirationDate = t('Never');
225
        }
226
        $this->view->membershipName = $oInfo->membershipName;
227
        unset($oInfo);
228
229
        $this->output();
0 ignored issues
show
The method output() does not seem to exist on object<PH7\MainController>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
230
    }
231
232
    /**
233
     * Update the Affiliate Commission.
234
     *
235
     * @return void
236
     */
237
    protected function updateAffCom()
238
    {
239
        // Load the Affiliate config file
240
        $this->config->load(PH7_PATH_SYS_MOD . 'affiliate' . PH7_DS . PH7_CONFIG . PH7_CONFIG_FILE);
241
242
        $iAffId = $this->oUserModel->getAffiliatedId($this->iProfileId);
243
        if ($iAffId < 1) return; // If there is no valid ID, we stop the method.
244
245
        $iAmount = $this->oUserModel->readProfile($this->iProfileId)->price;
246
        $iAffCom = ($iAmount*$this->config->values['module.setting']['rate.user_membership_payment']/100);
247
248
        if ($iAffCom > 0)
249
            $this->oUserModel->updateUserJoinCom($iAffId, $iAffCom);
250
    }
251
252
    /**
253
     * Send a notification email to the admin about the payment (IPN -> Instant Payment Notification).
254
     *
255
     * @return integer Number of recipients who were accepted for delivery.
256
     */
257
    protected function sendNotifyMail()
258
    {
259
        $sTo = DbConfig::getSetting('adminEmail');
260
        $sBuyer = $this->session->get('member_first_name') . ' (' . $this->session->get('member_username') . ')';
261
262
        $this->view->intro = t('Hello!') . '<br />' . t('You received a new Payment from %0%', $sBuyer);
263
        $this->view->date = t('Date of the payment: %0%', $this->dateTime->get()->date());
264
        $this->view->browser_info = t('User Browser info: %0%', $this->browser->getUserAgent());
265
        $this->view->ip = t('Ip of the buyer: %0%', $this->design->ip(null, false));
266
        $this->view->details_text = t('Please find all other details below');
267
        $this->view->details_data = print_r($_POST, true);
268
269
        $sMessageHtml = $this->view->parseMail(PH7_PATH_SYS . 'global/' . PH7_VIEWS . PH7_TPL_MAIL_NAME . '/tpl/mail/sys/mod/payment/ipn.tpl', $sTo);
270
271
        $aInfo = [
272
            'to' => $sTo,
273
            'subject' => t('New Payment Received from %0%', $sBuyer)
274
        ];
275
276
        return (new Mail)->send($aInfo, $sMessageHtml);
277
    }
278
279
    /**
280
     * Create a Payment Log file.
281
     *
282
     * @param \PH7\Framework\Payment\Gateway\Api\Api $oProvider A provider class.
283
     * @param string $sMsg
284
     * @return void
285
     */
286
    protected function log(Framework\Payment\Gateway\Api\Api $oProvider, $sMsg)
0 ignored issues
show
log uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
287
    {
288
        if ($this->config->values['module.setting']['log_file.enabled'])
289
        {
290
            $sLogTxt = $sMsg . Framework\File\File::EOL . Framework\File\File::EOL . Framework\File\File::EOL . Framework\File\File::EOL;
291
            $oProvider->saveLog($sLogTxt . print_r($_POST, true), $this->registry);
292
        }
293
    }
294
295
    /**
296
     * Clear Membership cache.
297
     *
298
     * @return void
299
     */
300
    protected function clearCache()
301
    {
302
        (new Framework\Cache\Cache)->start(UserCoreModel::CACHE_GROUP, 'membershipdetails' . $this->iProfileId, null)->clear();
303
    }
304
}
305