Passed
Push — master ( d97477...123541 )
by Maximo
06:20 queued 10s
created

AppsPlansController::updatePaymentMethod()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 37
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
cc 3
eloc 23
nc 3
nop 1
dl 0
loc 37
ccs 0
cts 23
cp 0
crap 12
rs 9.552
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Gewaer\Api\Controllers;
6
7
use Gewaer\Models\AppsPlans;
8
use Gewaer\Exception\UnauthorizedHttpException;
9
use Gewaer\Exception\NotFoundHttpException;
10
use Stripe\Token as StripeToken;
11
use Phalcon\Http\Response;
12
use Phalcon\Validation;
13
use Phalcon\Validation\Validator\PresenceOf;
14
use Gewaer\Exception\UnprocessableEntityHttpException;
15
use Phalcon\Cashier\Subscription;
16
use Gewaer\Models\UserCompanyApps;
17
use function Gewaer\Core\paymentGatewayIsActive;
18
19
/**
20
 * Class LanguagesController
21
 *
22
 * @package Gewaer\Api\Controllers
23
 *
24
 * @property Users $userData
25
 * @property Request $request
26
 * @property Config $config
27
 * @property Apps $app
28
 * @property \Phalcon\Db\Adapter\Pdo\Mysql $db
29
 */
30
class AppsPlansController extends BaseController
31
{
32
    /*
33
     * fields we accept to create
34
     *
35
     * @var array
36
     */
37
    protected $createFields = [];
38
39
    /*
40
     * fields we accept to create
41
     *
42
     * @var array
43
     */
44
    protected $updateFields = [];
45
46
    /**
47
     * set objects
48
     *
49
     * @return void
50
     */
51 4
    public function onConstruct()
52
    {
53 4
        $this->model = new AppsPlans();
54 4
        $this->additionalSearchFields = [
55 4
            ['is_deleted', ':', '0'],
56 4
            ['apps_id', ':', $this->app->getId()],
57
        ];
58 4
    }
59
60
    /**
61
     * Given the app plan stripe id , subscribe the current company to this aps
62
     *
63
     * @return Response
64
     */
65 1
    public function create(): Response
66
    {
67 1
        if (!$this->userData->hasRole('Default.Admins')) {
68
            throw new UnauthorizedHttpException(_('You dont have permission to subscribe this apps'));
69
        }
70
71
        //Ok let validate user password
72 1
        $validation = new Validation();
73 1
        $validation->add('stripe_id', new PresenceOf(['message' => _('The plan is required.')]));
74 1
        $validation->add('number', new PresenceOf(['message' => _('Credit Card Number is required.')]));
75 1
        $validation->add('exp_month', new PresenceOf(['message' => _('Credit Card Number is required.')]));
76 1
        $validation->add('exp_year', new PresenceOf(['message' => _('Credit Card Number is required.')]));
77 1
        $validation->add('cvc', new PresenceOf(['message' => _('CVC is required.')]));
78
79
        //validate this form for password
80 1
        $messages = $validation->validate($this->request->getPost());
81 1
        if (count($messages)) {
82
            foreach ($messages as $message) {
83
                throw new UnprocessableEntityHttpException((string) $message);
84
            }
85
        }
86
87 1
        $stripeId = $this->request->getPost('stripe_id');
88 1
        $company = $this->userData->defaultCompany;
89 1
        $cardNumber = $this->request->getPost('number');
90 1
        $expMonth = $this->request->getPost('exp_month');
91 1
        $expYear = $this->request->getPost('exp_year');
92 1
        $cvc = $this->request->getPost('cvc');
93
94 1
        $appPlan = $this->model->findFirstByStripeId($stripeId);
95
96 1
        if (!is_object($appPlan)) {
97
            throw new NotFoundHttpException(_('This plan doesnt exist'));
98
        }
99
100 1
        $userSubscription = Subscription::findFirst([
101 1
            'conditions' => 'user_id = ?0 and companies_id = ?1 and apps_id = ?2 and is_deleted  = 0',
102 1
            'bind' => [$this->userData->getId(), $this->userData->currentCompanyId(), $this->app->getId()]
103
        ]);
104
105
        //we can only run stripe paymenta gateway if we have the key
106 1
        if (paymentGatewayIsActive()) {
107
            $card = StripeToken::create([
108
                'card' => [
109
                    'number' => $cardNumber,
110
                    'exp_month' => $expMonth,
111
                    'exp_year' => $expYear,
112
                    'cvc' => $cvc,
113
                ],
114
            ], [
115
                'api_key' => $this->config->stripe->secret
116
            ])->id;
117
118
            $this->db->begin();
119
120
            if ($appPlan->free_trial_dates == 0) {
121
                $this->userData->newSubscription($appPlan->name, $appPlan->stripe_id, $company, $this->app)->create($card);
122
            } else {
123
                $this->userData->newSubscription($appPlan->name, $appPlan->stripe_id, $company, $this->app)->trialDays($appPlan->free_trial_dates)->create($card);
124
            }
125
126
            //update company app
127
            $companyApp = UserCompanyApps::getCurrentApp();
128
129
            if ($userSubscription) {
0 ignored issues
show
introduced by
$userSubscription is of type Phalcon\Mvc\Model, thus it always evaluated to true.
Loading history...
130
                $userSubscription->stripe_id = $this->userData->active_subscription_id;
131
                if (!$userSubscription->update()) {
132
                    $this->db->rollback();
133
                    throw new UnprocessableEntityHttpException((string)current($userSubscription->getMessages()));
134
                }
135
            }
136
137
            //update the company app to the new plan
138
            if (is_object($companyApp)) {
139
                $subscription = $this->userData->subscription($appPlan->stripe_plan);
140
                $companyApp->stripe_id = $stripeId;
141
                $companyApp->subscriptions_id = $subscription->getId();
142
                if (!$companyApp->update()) {
143
                    $this->db->rollback();
144
                    throw new UnprocessableEntityHttpException((string)current($companyApp->getMessages()));
145
                }
146
147
                //update the subscription with the plan
148
                $subscription->apps_plans_id = $appPlan->getId();
149
                if (!$subscription->update()) {
150
                    $this->db->rollback();
151
                    throw new UnprocessableEntityHttpException((string)current($subscription->getMessages()));
152
                }
153
            }
154
155
            $this->db->commit();
156
        }
157
158
        //sucess
159 1
        return $this->response($appPlan);
160
    }
161
162
    /**
163
     * Update a given subscription
164
     *
165
     * @param string $stripeId
166
     * @return Response
167
     */
168 2
    public function edit($stripeId) : Response
169
    {
170 2
        $appPlan = $this->model->findFirstByStripeId($stripeId);
171
172 2
        if (!is_object($appPlan)) {
173
            throw new NotFoundHttpException(_('This plan doesnt exist'));
174
        }
175
176 2
        $userSubscription = Subscription::findFirst([
177 2
            'conditions' => 'user_id = ?0 and companies_id = ?1 and apps_id = ?2 and is_deleted  = 0',
178 2
            'bind' => [$this->userData->getId(), $this->userData->currentCompanyId(), $this->app->getId()]
179
        ]);
180
181 2
        if (!is_object($userSubscription)) {
182
            throw new NotFoundHttpException(_('No current subscription found'));
183
        }
184
185 2
        $this->db->begin();
186
187 2
        $subscription = $this->userData->subscription($userSubscription->name);
188
189 2
        if ($subscription->onTrial()) {
190 2
            $subscription->name = $appPlan->name;
191 2
            $subscription->stripe_plan = $appPlan->stripe_plan;
192
        } else {
193
            $subscription->swap($stripeId);
194
        }
195
196
        //update company app
197 2
        $companyApp = UserCompanyApps::getCurrentApp();
198
199
        //update the company app to the new plan
200 2
        if (is_object($companyApp)) {
201 2
            $subscription->name = $stripeId;
202 2
            $subscription->save();
203
204 2
            $companyApp->stripe_id = $stripeId;
205 2
            $companyApp->subscriptions_id = $subscription->getId();
206 2
            if (!$companyApp->update()) {
207
                $this->db->rollback();
208
                throw new UnprocessableEntityHttpException((string) current($companyApp->getMessages()));
209
            }
210
211
            //update the subscription with the plan
212 2
            $subscription->apps_plans_id = $appPlan->getId();
213 2
            if (!$subscription->update()) {
214
                $this->db->rollback();
215
216
                throw new UnprocessableEntityHttpException((string) current($subscription->getMessages()));
217
            }
218
        }
219
220 2
        $this->db->commit();
221
222
        //return the new subscription plan
223 2
        return $this->response($appPlan);
224
    }
225
226
    /**
227
     * Cancel a given subscription
228
     *
229
     * @param string $stripeId
230
     * @return Response
231
     */
232 1
    public function delete($stripeId): Response
233
    {
234 1
        $appPlan = $this->model->findFirstByStripeId($stripeId);
235
236 1
        if (!is_object($appPlan)) {
237
            throw new NotFoundHttpException(_('This plan doesnt exist'));
238
        }
239
240 1
        $userSubscription = Subscription::findFirst([
241 1
            'conditions' => 'user_id = ?0 and companies_id = ?1 and apps_id = ?2 and is_deleted  = 0',
242 1
            'bind' => [$this->userData->getId(), $this->userData->currentCompanyId(), $this->app->getId()]
243
        ]);
244
245 1
        if (!is_object($userSubscription)) {
246
            throw new NotFoundHttpException(_('No current subscription found'));
247
        }
248
249 1
        $subscription = $this->userData->subscription($userSubscription->name);
250
251
        //if on trial you can cancel without going to stripe
252 1
        if (!$subscription->onTrial()) {
253
            $subscription->cancel();
254
        }
255
256 1
        $subscription->is_deleted = 1;
257 1
        $subscription->update();
258
259 1
        return $this->response($appPlan);
260
    }
261
262
    /**
263
     * Update payment method
264
     * @param integer $id
265
     * @return Response
266
     */
267
    public function updatePaymentMethod(int $id): Response
0 ignored issues
show
Unused Code introduced by
The parameter $id is not used and could be removed. ( Ignorable by Annotation )

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

267
    public function updatePaymentMethod(/** @scrutinizer ignore-unused */ int $id): Response

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
268
    {
269
        //Ok let validate user password
270
        $validation = new Validation();
271
        $validation->add('number', new PresenceOf(['message' => _('Credit Card Number is required.')]));
272
        $validation->add('exp_month', new PresenceOf(['message' => _('Credit Card Number is required.')]));
273
        $validation->add('exp_year', new PresenceOf(['message' => _('Credit Card Number is required.')]));
274
        $validation->add('cvc', new PresenceOf(['message' => _('CVC is required.')]));
275
276
        //validate this form for password
277
        $messages = $validation->validate($this->request->getPost());
278
        if (count($messages)) {
279
            foreach ($messages as $message) {
280
                throw new UnprocessableEntityHttpException((string) $message);
281
            }
282
        }
283
284
        $cardNumber = $this->request->getPost('number');
285
        $expMonth = $this->request->getPost('exp_month');
286
        $expYear = $this->request->getPost('exp_year');
287
        $cvc = $this->request->getPost('cvc');
288
289
        $customerId = $this->userData->stripe_id;
290
291
        //Create a new card token
292
        $token = StripeToken::create([
293
            'card' => [
294
                'number' => $cardNumber,
295
                'exp_month' => $expMonth,
296
                'exp_year' => $expYear,
297
                'cvc' => $cvc,
298
            ],
299
        ], [
300
            'api_key' => $this->config->stripe->secret
301
        ])->id;
302
303
        return $this->userData->updatePaymentMethod($customerId, $token);
304
    }
305
}
306