PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.6.5
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.6.5
1.6.5 1.6.4 1.6.3 1.6.2 1.6.1 1.6.0 1.5.4 1.5.5 1.5.3 1.5.2 1.5.1 1.5.0 1.4.2 1.4.1 1.4.0 1.3.28 1.3.27 1.3.26 1.3.25 1.3.23 1.3.22 1.3.21 1.3.20 1.3.19 trunk All 48 releases
← All changes | app/Http/Controllers/FrontendControllers/CustomerSubscriptionController.php +190 -9 1.3.23 → 1.6.5 View file →
@@ -53,8 +53,9 @@
53 53 // Include associated order and product data using 'with' for eager loading
54 54 // Sort the results by 'id' in descending order and fetch the data
55 55 $subscriptions = Subscription::query()
56 56 ->where('customer_id', $customer->id)
57 + ->with(['product'])
57 58 ->whereNotIn('status', [Status::SUBSCRIPTION_PENDING, Status::SUBSCRIPTION_INTENDED])
58 59 ->orderBy('id', 'desc')
59 60 ->paginate($perPage, ['*'], 'page', $page);
60 61
@@ -118,22 +119,34 @@
118 119 'bill_count' => $subscription->bill_count,
119 120 'variation_id' => $subscription->variation_id,
120 121 'product_id' => $subscription->product_id,
121 122 'config' => $subscription->config,
123 + 'collection_method' => $subscription->collection_method,
122 124 'reactivate_url' => $subscription->getReactivateUrl(),
123 - 'title' => $subscription->product ? $subscription->product->post_title : $subscription->item_name,
124 - 'subtitle' => $subscription->variation && $subscription->product ? $subscription->variation->variation_title : '',
125 + // item_name resolves to "<product> - <attributes>" (or the raw name),
126 + // so it carries the labeled combination on a single line.
127 + 'title' => $subscription->display_item_name,
128 + 'subtitle' => '',
125 129 'can_upgrade' => $subscription->canUpgrade(),
126 130 'can_switch_payment_method' => $subscription->canSwitchPaymentMethod(),
127 131 'switchable_payment_methods' => $subscription->switchablePaymentMethods(),
128 132 'can_update_payment_method' => $subscription->canUpdatePaymentMethod(),
133 + 'can_pause' => $subscription->canPause(),
134 + 'can_resume' => $subscription->canResume(),
129 135 'order' => [
130 136 'uuid' => $subscription->order ? $subscription->order->uuid : ''
131 137 ],
132 138 'billing_addresses' => $subscription->billing_addresses,
133 139 'recurring_amount' => $subscription->recurring_amount,
140 + 'currency' => $subscription->currency,
134 141 'can_early_pay' => EarlyPaymentFeature::canPay($subscription),
135 142 'remaining_installments' => max(0, $subscription->bill_times - $subscription->bill_count),
143 + 'card_update_url' => $subscription->url,
144 + // Auto-charged (system) subscriptions: the saved card is charged
145 + // automatically on each renewal date — the portal says so, and surfaces
146 + // the last failure so the customer knows to update the card.
147 + 'is_auto_charged' => $subscription->isSystem(),
148 + 'auto_charge_error' => Arr::get((array) $subscription->system_charge_state, 'last_error', ''),
136 149 ];
137 150
138 151
139 152 // Let's find all the transactions related to this order
@@ -150,9 +163,15 @@
150 163 ->orderBy('id', 'DESC')
151 164 ->get();
152 165
153 166 $formattedData['transactions'] = $transactions->map(function ($transaction) {
154 - return OrderService::transformTransaction($transaction);
167 + $transformedTransaction = OrderService::transformTransaction($transaction);
168 + if ($transaction->status === Status::TRANSACTION_PENDING
169 + && !empty($transformedTransaction['custom_checkout_url'])
170 + ) {
171 + $transformedTransaction['show_pay_now'] = true;
172 + }
173 + return $transformedTransaction;
155 174 });
156 175
157 176 $formattedData = apply_filters('fluent_cart/customer_portal/subscription_data', $formattedData, [
158 177 'subscription' => $subscription,
@@ -158,16 +177,36 @@
158 177 'subscription' => $subscription,
159 178 'customer' => $customer
160 179 ]);
161 180
181 + $sectionParts = apply_filters('fluent_cart/customer/subscription_details_section_parts', [
182 + 'end_of_subscription' => ''
183 + ], [
184 + 'subscription' => $subscription,
185 + 'formattedData' => $formattedData
186 + ]);
187 +
188 + $sectionParts = array_map('wp_kses_post', $sectionParts);
189 +
162 190 return $this->sendSuccess([
163 - 'message' => __('Success', 'fluent-cart'),
164 - 'subscription' => $formattedData
191 + 'message' => __('Success', 'fluent-cart'),
192 + 'subscription' => $formattedData,
193 + 'section_parts' => $sectionParts
165 194 ]);
166 195 }
167 196
168 197 public function updatePaymentMethod(Request $request, $subscription_uuid)
169 198 {
199 + $errorResponse = $this->checkUserLoggedIn();
200 + if ($errorResponse !== null) {
201 + return $errorResponse;
202 + }
203 +
204 + $customer = CustomerResource::getCurrentCustomer();
205 + if (!$customer) {
206 + return $this->sendError(['message' => __('Customer not found', 'fluent-cart')]);
207 + }
208 +
170 209 $data = $request->input('data');
171 210 $method = $data['method'];
172 211 $subscriptionUuid = $subscription_uuid;
173 212
@@ -176,9 +215,12 @@
176 215 'message' => __('Method and Subscription Id required.', 'fluent-cart')
177 216 ]);
178 217 }
179 218
180 - $subscription = Subscription::query()->where('uuid', $subscriptionUuid)->first();
219 + $subscription = Subscription::query()
220 + ->where('uuid', $subscriptionUuid)
221 + ->where('customer_id', $customer->id)
222 + ->first();
181 223
182 224 if (empty($subscription)) {
183 225 return $this->sendError([
184 226 'message' => __('Subscription not found', 'fluent-cart')
@@ -192,8 +234,13 @@
192 234 return $this->sendError([
193 235 'message' => $e->getMessage()
194 236 ]);
195 237 }
238 +
239 + return $this->sendSuccess([
240 + 'status' => 'success',
241 + 'message' => __('Payment method updated successfully', 'fluent-cart')
242 + ]);
196 243 }
197 244
198 245 return $this->sendError([
199 246 'message' => __('Could not update payment method', 'fluent-cart')
@@ -201,8 +248,18 @@
201 248 }
202 249
203 250 public function getOrCreatePlan(Request $request, $subscription_uuid)
204 251 {
252 + $errorResponse = $this->checkUserLoggedIn();
253 + if ($errorResponse !== null) {
254 + return $errorResponse;
255 + }
256 +
257 + $customer = CustomerResource::getCurrentCustomer();
258 + if (!$customer) {
259 + return $this->sendError(['message' => __('Customer not found', 'fluent-cart')]);
260 + }
261 +
205 262 $data = $request->input('data');
206 263 $method = sanitize_text_field(Arr::get($data, 'method', ''));
207 264 $reason = sanitize_text_field(Arr::get($data, 'reason', ''));
208 265
@@ -211,9 +268,12 @@
211 268 'message' => __('Missing required parameters', 'fluent-cart')
212 269 ]);
213 270 }
214 271
215 - $subscription = Subscription::query()->where('uuid', $subscription_uuid)->first();
272 + $subscription = Subscription::query()
273 + ->where('uuid', $subscription_uuid)
274 + ->where('customer_id', $customer->id)
275 + ->first();
216 276 if (empty($subscription)) {
217 277 return $this->sendError([
218 278 'message' => __('Subscription not found', 'fluent-cart')
219 279 ]);
@@ -226,8 +286,13 @@
226 286 return $this->sendError([
227 287 'message' => $e->getMessage()
228 288 ]);
229 289 }
290 +
291 + return $this->sendSuccess([
292 + 'status' => 'success',
293 + 'message' => __('Plan created successfully', 'fluent-cart')
294 + ]);
230 295 }
231 296
232 297 return $this->sendError([
233 298 'message' => __('Could not get or create plan', 'fluent-cart')
@@ -245,8 +310,13 @@
245 310 $data = $request->input('data');
246 311 $newPaymentMethod = sanitize_text_field(Arr::get($data, 'newPaymentMethod', ''));
247 312 $currentPaymentMethod = sanitize_text_field(Arr::get($data, 'currentPaymentMethod', ''));
248 313
314 + $customer = CustomerResource::getCurrentCustomer();
315 + if (!$customer) {
316 + return $this->sendError(['message' => __('Customer not found', 'fluent-cart')]);
317 + }
318 +
249 319 if (!$newPaymentMethod || !$currentPaymentMethod || !$subscription_uuid) {
250 320 return $this->sendError([
251 321 'message' => __('Missing required parameters', 'fluent-cart')
252 322 ]);
@@ -251,9 +321,12 @@
251 321 'message' => __('Missing required parameters', 'fluent-cart')
252 322 ]);
253 323 }
254 324
255 - $subscription = Subscription::query()->where('uuid', $subscription_uuid)->first();
325 + $subscription = Subscription::query()
326 + ->where('uuid', $subscription_uuid)
327 + ->where('customer_id', $customer->id)
328 + ->first();
256 329 if (empty($subscription)) {
257 330 return $this->sendError([
258 331 'message' => __('Subscription not found', 'fluent-cart')
259 332 ]);
@@ -258,8 +331,14 @@
258 331 'message' => __('Subscription not found', 'fluent-cart')
259 332 ]);
260 333 }
261 334
335 + if (!$subscription->canSwitchPaymentMethod()) {
336 + return $this->sendError([
337 + 'message' => __('This subscription cannot be moved to another payment gateway. Update the payment method on file instead.', 'fluent-cart')
338 + ]);
339 + }
340 +
262 341 if (App::gateway()->has($newPaymentMethod)) {
263 342 try {
264 343 App::gateway($newPaymentMethod)->subscriptions->switchPaymentMethod($data, $subscription->id);
265 344 } catch (\Exception $e) {
@@ -266,8 +345,13 @@
266 345 return $this->sendError([
267 346 'message' => $e->getMessage()
268 347 ]);
269 348 }
349 +
350 + return $this->sendSuccess([
351 + 'status' => 'success',
352 + 'message' => __('Payment method switched successfully', 'fluent-cart')
353 + ]);
270 354 }
271 355
272 356 return $this->sendError([
273 357 'message' => __('Could not switch payment method', 'fluent-cart')
@@ -287,8 +371,13 @@
287 371 $data = $request->input('data');
288 372 $newVendorSubscriptionId = sanitize_text_field(Arr::get($data, 'newVendorSubscriptionId', ''));
289 373 $method = sanitize_text_field(Arr::get($data, 'method', ''));
290 374
375 + $customer = CustomerResource::getCurrentCustomer();
376 + if (!$customer) {
377 + return $this->sendError(['message' => __('Customer not found', 'fluent-cart')]);
378 + }
379 +
291 380 if (!$newVendorSubscriptionId || !$method || !$subscription_uuid) {
292 381 return $this->sendError([
293 382 'message' => __('Missing required parameters', 'fluent-cart')
294 383 ]);
@@ -293,9 +382,12 @@
293 382 'message' => __('Missing required parameters', 'fluent-cart')
294 383 ]);
295 384 }
296 385
297 - $subscription = Subscription::query()->where('uuid', $subscription_uuid)->first();
386 + $subscription = Subscription::query()
387 + ->where('uuid', $subscription_uuid)
388 + ->where('customer_id', $customer->id)
389 + ->first();
298 390 if (empty($subscription)) {
299 391 return $this->sendError([
300 392 'message' => __('Subscription not found', 'fluent-cart')
301 393 ]);
@@ -300,8 +392,14 @@
300 392 'message' => __('Subscription not found', 'fluent-cart')
301 393 ]);
302 394 }
303 395
396 + if (!$subscription->canSwitchPaymentMethod()) {
397 + return $this->sendError([
398 + 'message' => __('This subscription cannot be moved to another payment gateway. Update the payment method on file instead.', 'fluent-cart')
399 + ]);
400 + }
401 +
304 402 if (APP::gateway()->has($method)) {
305 403 try {
306 404 APP::gateway($method)->subscriptions->confirmSubscriptionSwitch($data, $subscription->id);
307 405 } catch (\Exception $e) {
@@ -308,8 +406,13 @@
308 406 return $this->sendError([
309 407 'message' => $e->getMessage()
310 408 ]);
311 409 }
410 +
411 + return $this->sendSuccess([
412 + 'status' => 'success',
413 + 'message' => __('Subscription switch confirmed successfully', 'fluent-cart')
414 + ]);
312 415 }
313 416
314 417 return $this->sendError([
315 418 'message' => __('Could not confirm subscription switch', 'fluent-cart')
@@ -406,8 +509,86 @@
406 509 return App::isProActive()
407 510 && $subscription->bill_times > 0
408 511 && $subscription->bill_count < $subscription->bill_times
409 512 && in_array($subscription->status, [Status::SUBSCRIPTION_ACTIVE, Status::SUBSCRIPTION_TRIALING]);
513 + }
514 +
515 + public function pauseSubscription(Request $request, $subscription_uuid)
516 + {
517 + $errorResponse = $this->checkUserLoggedIn();
518 + if ($errorResponse !== null) {
519 + return $errorResponse;
520 + }
521 +
522 + $customer = CustomerResource::getCurrentCustomer();
523 + if (!$customer) {
524 + return $this->sendError([
525 + 'message' => __('Customer not found', 'fluent-cart')
526 + ]);
527 + }
528 +
529 + $subscription = Subscription::query()
530 + ->where('uuid', $subscription_uuid)
531 + ->where('customer_id', $customer->id)
532 + ->first();
533 +
534 + if (empty($subscription)) {
535 + return $this->sendError([
536 + 'message' => __('Subscription not found', 'fluent-cart')
537 + ]);
538 + }
539 +
540 + $reason = __('Paused by customer from customer portal', 'fluent-cart');
541 + $result = $subscription->pauseSubscription($reason);
542 +
543 + if (is_wp_error($result)) {
544 + return $this->sendError([
545 + 'message' => $result->get_error_message()
546 + ]);
547 + }
548 +
549 + return [
550 + 'message' => __('Your subscription has been successfully paused', 'fluent-cart')
551 + ];
552 + }
553 +
554 + public function resumeSubscription(Request $request, $subscription_uuid)
555 + {
556 + $errorResponse = $this->checkUserLoggedIn();
557 + if ($errorResponse !== null) {
558 + return $errorResponse;
559 + }
560 +
561 + $customer = CustomerResource::getCurrentCustomer();
562 + if (!$customer) {
563 + return $this->sendError([
564 + 'message' => __('Customer not found', 'fluent-cart')
565 + ]);
566 + }
567 +
568 + $subscription = Subscription::query()
569 + ->where('uuid', $subscription_uuid)
570 + ->where('customer_id', $customer->id)
571 + ->first();
572 +
573 + if (empty($subscription)) {
574 + return $this->sendError([
575 + 'message' => __('Subscription not found', 'fluent-cart')
576 + ]);
577 + }
578 +
579 + $reason = __('Resumed by customer from customer portal', 'fluent-cart');
580 + $result = $subscription->resumeSubscription($reason);
581 +
582 + if (is_wp_error($result)) {
583 + return $this->sendError([
584 + 'message' => $result->get_error_message()
585 + ]);
586 + }
587 +
588 + return [
589 + 'message' => __('Your subscription has been successfully resumed', 'fluent-cart')
590 + ];
410 591 }
411 592
412 593 public function getSetupIntentRemainingAttempts($subscription_uuid)
413 594 {