Failed Conditions
Pull Request — master (#82)
by Maximo
05:55
created

api/controllers/PaymentsController.php (2 issues)

Labels
Severity
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Gewaer\Api\Controllers;
6
7
use Phalcon\Cashier\Traits\StripeWebhookHandlersTrait;
8
use Phalcon\Http\Response;
9
use Gewaer\Models\Users;
10
use Gewaer\Models\EmailTemplates;
11
use Gewaer\Models\Subscription;
12
use Gewaer\Models\CompaniesSettings;
13
use Phalcon\Di;
14
use Exception;
15
16
/**
17
 * Class PaymentsController
18
 *
19
 * Class to handle payment webhook from our cashier library
20
 *
21
 * @package Gewaer\Api\Controllers
22
 * @property Log $log
23
 * @property App $app
24
 *
25
 */
26
class PaymentsController extends BaseController
27
{
28
    /**
29
     * Stripe Webhook Handlers
30
     */
31
    use StripeWebhookHandlersTrait;
32
33
    /**
34
     * Handle stripe webhoook calls
35
     *
36
     * @return Response
37
     */
38 4
    public function handleWebhook(): Response
39
    {
40
        //we cant processs if we dont find the stripe header
41 4
        if (!$this->request->hasHeader('Stripe-Signature')) {
0 ignored issues
show
The method hasHeader() does not exist on Phalcon\Http\RequestInterface. It seems like you code against a sub-type of said class. However, the method does not exist in Gewaer\Contracts\RequestJwtInterface. Are you sure you never get one of those? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

41
        if (!$this->request->/** @scrutinizer ignore-call */ hasHeader('Stripe-Signature')) {
Loading history...
42
            throw new Exception('Route not found for this call');
43
        }
44 4
        $request = $this->request->getPost();
45 4
        if (empty($request)) {
46
            $request = $this->request->getJsonRawBody(true);
0 ignored issues
show
The method getJsonRawBody() does not exist on Phalcon\Http\RequestInterface. It seems like you code against a sub-type of said class. However, the method does not exist in Gewaer\Contracts\RequestJwtInterface. Are you sure you never get one of those? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

46
            /** @scrutinizer ignore-call */ 
47
            $request = $this->request->getJsonRawBody(true);
Loading history...
47
        }
48 4
        $type = str_replace('.', '', ucwords(str_replace('_', '', $request['type']), '.'));
49 4
        $method = 'handle' . $type;
50 4
        $payloadContent = json_encode($request);
51 4
        $this->log->info("Webhook Handler Method: {$method} \n");
52 4
        $this->log->info("Payload: {$payloadContent} \n");
53 4
        if (method_exists($this, $method)) {
54 4
            return $this->{$method}($request, $method);
55
        } else {
56
            return $this->response(['Missing Method to Handled']);
57
        }
58
    }
59
60
    /**
61
     * Handle customer subscription updated.
62
     *
63
     * @param  array $payload
64
     * @return Response
65
     */
66
    protected function handleCustomerSubscriptionUpdated(array $payload, string $method): Response
67
    {
68
        $user = Users::findFirstByStripeId($payload['data']['object']['customer']);
69
        if ($user) {
70
            //We need to send a mail to the user
71
            $this->sendWebhookResponseEmail($user, $payload, $method);
72
        }
73
        return $this->response(['Webhook Handled']);
74
    }
75
76
    /**
77
     * Handle customer subscription free trial ending.
78
     *
79
     * @param  array $payload
80
     * @return Response
81
     */
82 1
    protected function handleCustomerSubscriptionTrialwillend(array $payload, string $method): Response
83
    {
84 1
        $user = Users::findFirstByStripeId($payload['data']['object']['customer']);
85 1
        if ($user) {
86
            //We need to send a mail to the user
87
            $this->sendWebhookResponseEmail($user, $payload, $method);
88
        }
89 1
        return $this->response(['Webhook Handled']);
90
    }
91
92
    /**
93
     * Handle sucessfull payment
94
     *
95
     * @param array $payload
96
     * @return Response
97
     */
98 1
    protected function handleChargeSucceeded(array $payload, string $method): Response
99
    {
100 1
        $user = Users::findFirstByStripeId($payload['data']['object']['customer']);
101 1
        if ($user) {
102
            //Update current subscription's paid column to true and store date of payment
103
            $this->updateSubscriptionPaymentStatus($user, $payload);
104
            $this->sendWebhookResponseEmail($user, $payload, $method);
105
        }
106 1
        return $this->response(['Webhook Handled']);
107
    }
108
109
    /**
110
     * Handle bad payment
111
     *
112
     * @param array $payload
113
     * @return Response
114
     */
115 1
    protected function handleChargeFailed(array $payload, string $method) : Response
116
    {
117 1
        $user = Users::findFirstByStripeId($payload['data']['object']['customer']);
118 1
        if ($user) {
119
            //We need to send a mail to the user
120
            $this->updateSubscriptionPaymentStatus($user, $payload);
121
            $this->sendWebhookResponseEmail($user, $payload, $method);
122
        }
123 1
        return $this->response(['Webhook Handled']);
124
    }
125
126
    /**
127
     * Handle pending payments
128
     *
129
     * @param array $payload
130
     * @return Response
131
     */
132 1
    protected function handleChargePending(array $payload, string $method) : Response
133
    {
134 1
        $user = Users::findFirstByStripeId($payload['data']['object']['customer']);
135 1
        if ($user) {
136
            //We need to send a mail to the user
137
            $this->sendWebhookResponseEmail($user, $payload, $method);
138
        }
139 1
        return $this->response(['Webhook Handled']);
140
    }
141
142
    /**
143
     * Send webhook related emails to user
144
     * @param Users $user
145
     * @param array $payload
146
     * @param string $method
147
     * @return void
148
     */
149
    protected function sendWebhookResponseEmail(Users $user, array $payload, string $method): void
150
    {
151
        switch ($method) {
152
            case 'handleCustomerSubscriptionTrialwillend':
153
                $templateName = 'users-trial-end';
154
                break;
155
            case 'handleCustomerSubscriptionUpdated':
156
                $templateName = 'users-subscription-updated';
157
                break;
158
159
            case 'handleChargeSucceeded':
160
                $templateName = 'users-charge-success';
161
                break;
162
163
            case 'handleChargeFailed':
164
                $templateName = 'users-charge-failed';
165
                break;
166
167
            case 'handleChargePending':
168
                $templateName = 'users-charge-pending';
169
                break;
170
171
            default:
172
                break;
173
        }
174
175
        //Search for actual template by templateName
176
        $emailTemplate = EmailTemplates::getByName($templateName);
177
178
        Di::getDefault()->getMail()
179
            ->to($user->email)
180
            ->subject('Canvas Payments and Subscriptions')
181
            ->content($emailTemplate->template)
182
            ->sendNow();
183
    }
184
185
    /**
186
     * Updates subscription payment status depending on charge event
187
     * @param $user
188
     * @param $payload
189
     * @return void
190
     */
191
    public function updateSubscriptionPaymentStatus(Users $user, array $payload): void
192
    {
193
        $chargeDate = date('Y-m-d H:i:s', $payload['data']['object']['created']);
194
195
        //Fetch current user subscription
196
        $subscription = Subscription::getByDefaultCompany($user);
197
198
        if (is_object($subscription)) {
199
            $subscription->paid = $payload['data']['object']['paid'] ? 1 : 0;
200
            $subscription->charge_date = $chargeDate;
201
202
            if ($subscription->paid) {
203
                $subscription->is_freetrial = 0;
204
                $subscription->trial_ends_days = 0;
205
            }
206
207
            if ($subscription->update()) {
208
                //Update companies setting
209
                $paidSetting = CompaniesSettings::findFirst([
210
                    'conditions' => "companies_id = ?0 and name = 'paid' and is_deleted = 0",
211
                    'bind' => [$user->default_company]
212
                ]);
213
214
                $paidSetting->value = (string)$subscription->paid;
215
                $paidSetting->update();
216
            }
217
            $this->log->info("User with id: {$user->id} charged status was {$payload['data']['object']['paid']} \n");
218
        }
219
220
        $this->log->error("Subscription not found\n");
221
    }
222
}
223