Skip to content

Commit 8e87d37

Browse files
committed
Enhancement: Improve BillableMiddleware for SPAs
1 parent 52dabf2 commit 8e87d37

File tree

2 files changed

+78
-21
lines changed

2 files changed

+78
-21
lines changed

src/Http/Middleware/Billable.php

Lines changed: 32 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
use Illuminate\Support\Facades\Redirect;
99
use Osiset\ShopifyApp\Contracts\ShopModel as IShopModel;
1010
use Osiset\ShopifyApp\Util;
11-
use RuntimeException;
1211

1312
/**
1413
* Responsible for ensuring the shop is being billed.
@@ -19,35 +18,47 @@ class Billable
1918
* Checks if a shop has paid for access.
2019
*
2120
* @param Request $request The request object.
22-
* @param Closure $next The next action.
21+
* @param Closure $next The next action.
2322
*
24-
*@throws Exception
23+
* @throws Exception
2524
*
2625
* @return mixed
2726
*/
2827
public function handle(Request $request, Closure $next)
2928
{
30-
if (!Util::isMPAApplication()) {
31-
throw new RuntimeException('You cannot use Billable middleware with SPA mode');
29+
if (Util::getShopifyConfig('billing_enabled') !== true) {
30+
return $next($request);
3231
}
3332

34-
if (Util::getShopifyConfig('billing_enabled') === true) {
35-
/** @var $shop IShopModel */
36-
$shop = auth()->user();
37-
if (!$shop->plan && !$shop->isFreemium() && !$shop->isGrandfathered()) {
38-
// They're not grandfathered in, and there is no charge or charge was declined... redirect to billing
39-
return Redirect::route(
40-
Util::getShopifyConfig('route_names.billing'),
41-
array_merge($request->input(), [
42-
'shop' => $shop->getDomain()->toNative(),
43-
'host' => $request->get('host'),
44-
'locale' => $request->get('locale'),
45-
])
46-
);
47-
}
33+
// Proceed if we are on SPA mode & it's a non ajax request
34+
if (!Util::isMPAApplication() && ! $request->ajax()) {
35+
return $next($request);
4836
}
4937

50-
// Move on, everything's fine
51-
return $next($request);
38+
/** @var $shop IShopModel */
39+
$shop = auth()->user();
40+
41+
// if shop has plan or is on freemium or is grandfathered then move on with request
42+
if (! $shop || $shop->plan || $shop->isFreemium() || $shop->isGrandfathered()) {
43+
return $next($request);
44+
}
45+
46+
$args = [
47+
Util::getShopifyConfig('route_names.billing'),
48+
array_merge($request->input(), [
49+
'shop' => $shop->getDomain()->toNative(),
50+
'host' => $request->get('host'),
51+
'locale' => $request->get('locale'),
52+
]),
53+
];
54+
55+
if ($request->ajax()) {
56+
return response()->json(
57+
['forceRedirectUrl' => route(...$args)],
58+
402
59+
);
60+
}
61+
62+
return Redirect::route(...$args);
5263
}
5364
}

tests/Http/Middleware/BillableTest.php

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Osiset\ShopifyApp\Test\Http\Middleware;
44

55
use Illuminate\Auth\AuthManager;
6+
use Illuminate\Http\Request;
67
use Osiset\ShopifyApp\Http\Middleware\Billable as BillableMiddleware;
78
use Osiset\ShopifyApp\Storage\Models\Charge;
89
use Osiset\ShopifyApp\Storage\Models\Plan;
@@ -100,4 +101,49 @@ public function testDisabledBillingShouldPassOn(): void
100101

101102
$this->assertTrue($result[0]);
102103
}
104+
105+
public function testNoNativeAppBridgeAndNoAjaxRequest(): void
106+
{
107+
$plan = factory(Util::getShopifyConfig('models.plan', Plan::class))->states('type_recurring')->create();
108+
$shop = factory($this->model)->create(['plan_id' => $plan->getId()->toNative()]);
109+
110+
factory(Util::getShopifyConfig('models.charge', Charge::class))->states('type_recurring')->create(
111+
[
112+
'plan_id' => $plan->getId()->toNative(),
113+
'user_id' => $shop->getId()->toNative(),
114+
]
115+
);
116+
117+
$this->auth->login($shop);
118+
$this->app['config']->set('shopify-app.billing_enabled', true);
119+
$this->app['config']->set('shopify-app.frontend_engine', 'REACT');
120+
121+
$request = Request::create('/test', 'GET');
122+
123+
$this->assertFalse($request->ajax());
124+
125+
$result = $this->runMiddleware(BillableMiddleware::class, $request);
126+
127+
$this->assertTrue($result[0]);
128+
}
129+
130+
public function testAjaxRequest(): void
131+
{
132+
$shop = factory($this->model)->create();
133+
134+
$this->auth->login($shop);
135+
$this->app['config']->set('shopify-app.billing_enabled', true);
136+
$this->app['config']->set('shopify-app.frontend_engine', 'REACT');
137+
138+
$request = Request::create('/test', 'GET');
139+
$request->headers->set('X-Requested-With', 'XMLHttpRequest');
140+
141+
$this->assertTrue($request->ajax());
142+
143+
$response = $this->runMiddleware(BillableMiddleware::class, $request);
144+
145+
$this->assertFalse($response[0]);
146+
$this->assertEquals(402, $response[1]->getStatusCode());
147+
$this->assertArrayHasKey('forceRedirectUrl', $response[1]->getData(true));
148+
}
103149
}

0 commit comments

Comments
 (0)