Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 86 |
|
0.00% |
0 / 7 |
CRAP | |
0.00% |
0 / 1 |
PaymentController | |
0.00% |
0 / 86 |
|
0.00% |
0 / 7 |
506 | |
0.00% |
0 / 1 |
index | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
paymentMethods | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
defaultPaymentMethod | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
setDefaultPaymentMethod | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
6 | |||
store | |
0.00% |
0 / 66 |
|
0.00% |
0 / 1 |
182 | |||
nextBillingDate | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
6 | |||
getPaymentMethods | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 |
1 | <?php |
2 | |
3 | namespace App\Http\Controllers\v1\Stripe; |
4 | |
5 | use App\Http\Controllers\Controller; |
6 | use App\Http\Models\Plans; |
7 | use App\Http\Models\Auth\User; |
8 | use App\Http\Models\Subscription; |
9 | use App\Http\Requests\StoreSubscriptionRequest; |
10 | use App\Traits\SubscriptionTrait; |
11 | use Carbon\Carbon; |
12 | use Exception; |
13 | use Illuminate\Http\JsonResponse; |
14 | use Illuminate\Http\Request; |
15 | use Illuminate\Support\Str; |
16 | |
17 | class PaymentController extends Controller |
18 | { |
19 | use SubscriptionTrait; |
20 | |
21 | public function index(Request $request): JsonResponse |
22 | { |
23 | return response()->json($request->user()->createSetupIntent()); |
24 | } |
25 | |
26 | public function paymentMethods(Request $request) |
27 | { |
28 | return $this->getPaymentMethods($request->user()); |
29 | } |
30 | |
31 | public function defaultPaymentMethod(Request $request): JsonResponse |
32 | { |
33 | return response()->json($request->user()->defaultPaymentMethod()); |
34 | } |
35 | |
36 | public function setDefaultPaymentMethod(Request $request): JsonResponse |
37 | { |
38 | $this->validate($request, [ |
39 | 'payment_method_id' => 'required', |
40 | ]); |
41 | |
42 | try { |
43 | $request->user()->updateDefaultPaymentMethod($request->payment_method_id); |
44 | |
45 | return response()->json(['message' => 'Successfully updated default payment method'], 201); |
46 | } catch (Exception $e) { |
47 | return response()->json(['message' => $e->getMessage()], 422); |
48 | } |
49 | } |
50 | |
51 | public function store(StoreSubscriptionRequest $request): JsonResponse |
52 | { |
53 | $this->validate($request, [ |
54 | 'payment_method_id' => 'required', |
55 | ]); |
56 | |
57 | try { |
58 | $user = $request->user(); |
59 | if (!$user->hasStripeId()) { |
60 | $user->createAsStripeCustomer([ |
61 | 'name' => $user->first_name . ' ' . $user->last_name, |
62 | 'email' => $user->email, |
63 | ]); |
64 | } |
65 | |
66 | $user->updateDefaultPaymentMethod($request->payment_method_id); |
67 | |
68 | $paymentMethodId = $request->payment_method_id; |
69 | $stripe = new \Stripe\StripeClient(config('services.stripe.secret')); |
70 | $paymentMethod = $stripe->paymentMethods->retrieve($paymentMethodId, []); |
71 | $user->addPaymentMethod($paymentMethod); |
72 | |
73 | if (! $user->hasDefaultPaymentMethod()) { |
74 | $user->updateDefaultPaymentMethod($paymentMethod); |
75 | } |
76 | |
77 | $plan = Plans::where('identifier', '=', $request->plan) |
78 | ->whereNull('pricing_version') |
79 | ->firstOrFail(); |
80 | |
81 | $subscriptionResult = null; |
82 | |
83 | if ($user->subscribed('main')) { |
84 | $current_subscription = $user->subscriptions()->first(); |
85 | if ($current_subscription->stripe_plan == $plan->stripe_id) { |
86 | throw new Exception(Str::replaceArray('?', [$plan->title], 'You are already Subscribed to ? plan')); |
87 | } |
88 | |
89 | $subscriptionResult = $user->subscription('main')->swapAndInvoice($plan->stripe_id); |
90 | |
91 | // Give stripe a delay of 5 seconds to return webhook. |
92 | $attempts = 0; |
93 | $maxAttempts = 10; |
94 | $interval = 500000; // 500ms in microseconds |
95 | |
96 | do { |
97 | usleep($interval); |
98 | $currentPlans = Subscription::where("name", "main")->where("user_id", $user->id)->get()->pluck('plan'); |
99 | $attempts++; |
100 | } while (!$currentPlans->contains('identifier', $plan->identifier) && $attempts < $maxAttempts); |
101 | |
102 | $currentPlan = $currentPlans->firstWhere('identifier', $plan->identifier); |
103 | |
104 | if ($subscriptionResult?->plan->identifier !== $plan->identifier || !$currentPlans->contains('identifier', $plan->identifier)) { |
105 | return response()->json([ |
106 | 'message' => 'Your subscription to ' . $plan->title . ' failed!', |
107 | 'data' => $currentPlan |
108 | ], 422); |
109 | } |
110 | } else { |
111 | if (filled($request->discount_code)) { |
112 | $subscriptionResult = $user->newSubscription('main', $plan->stripe_id) |
113 | ->withCoupon($request->discount_code) |
114 | ->create($paymentMethod, [ |
115 | 'receipt_email' => "$user->email", |
116 | ]); |
117 | } else { |
118 | $subscriptionResult = $user->newSubscription('main', $plan->stripe_id) |
119 | ->create($paymentMethod, [ |
120 | 'receipt_email' => "$user->email", |
121 | ]); |
122 | } |
123 | |
124 | // Give stripe a delay of 5 seconds to return webhook. |
125 | $attempts = 0; |
126 | $maxAttempts = 10; |
127 | $interval = 500000; // 500ms in microseconds |
128 | |
129 | do { |
130 | usleep($interval); |
131 | $currentPlans = Subscription::where("name", "main")->where("user_id", $user->id)->get()->pluck('plan'); |
132 | $attempts++; |
133 | } while (!$currentPlans->contains('identifier', $plan->identifier) && $attempts < $maxAttempts); |
134 | |
135 | if ($subscriptionResult?->plan->identifier !== $plan->identifier || !$currentPlans->contains('identifier', $plan->identifier)) { |
136 | return response()->json([ |
137 | 'message' => 'Your subscription to ' . $plan->title . ' failed!', |
138 | ], 422); |
139 | } |
140 | } |
141 | |
142 | $currentPlan = $currentPlans->firstWhere('identifier', $plan->identifier); |
143 | |
144 | return response()->json([ |
145 | 'message' => 'You are successfully subscribed to the plan ' . $plan->title, |
146 | 'data' => $currentPlan |
147 | ]); |
148 | } catch (Exception $e) { |
149 | return response()->json(['message' => $e->getMessage()], 403); |
150 | } |
151 | } |
152 | |
153 | public function nextBillingDate(Request $request): JsonResponse |
154 | { |
155 | $current_subscription = $request->user()->subscription('main'); |
156 | |
157 | if (! $current_subscription) { |
158 | return response()->json(false); |
159 | } |
160 | |
161 | $now = Carbon::now(); |
162 | $date = Carbon::createFromTimeStamp($current_subscription->asStripeSubscription()->current_period_end); |
163 | |
164 | return response()->json($date->diff($now)->days); |
165 | } |
166 | |
167 | protected function getPaymentMethods(User $user): array |
168 | { |
169 | $paymentMethods = []; |
170 | |
171 | foreach ($user->paymentMethods() as $paymentMethod) { |
172 | $paymentMethods[] = $paymentMethod->asStripePaymentMethod(); |
173 | } |
174 | |
175 | return $paymentMethods; |
176 | } |
177 | } |