Skip to content
This repository has been archived by the owner on Nov 30, 2022. It is now read-only.

Refactor #154

Merged
merged 33 commits into from
Dec 20, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
214c607
Starting with the billing... moved logic to the billing plan service,…
gnikyt Dec 16, 2018
5dd97af
Usage charge updated more
gnikyt Dec 16, 2018
f45f233
Refactored billing controller
gnikyt Dec 16, 2018
7108761
More work completed
gnikyt Dec 16, 2018
58bf8a2
Passing tests again for billing plan service
gnikyt Dec 17, 2018
def45ca
Billing controller passing again
gnikyt Dec 17, 2018
fc609c7
Moved to facades, provided some comments to the classes
gnikyt Dec 17, 2018
a41f82a
Completed code refactor... now to do tests and review
gnikyt Dec 17, 2018
f2bf15d
Fix to some tests...
gnikyt Dec 17, 2018
ed5a72d
Few more fixed tested
gnikyt Dec 17, 2018
8505af1
Controller tests re-worked to be more concise
gnikyt Dec 19, 2018
8472bd0
Middleware test for proxy adjusted
gnikyt Dec 19, 2018
05a9db1
Auth shop middleware adjusted
gnikyt Dec 19, 2018
50aeefc
Auth webhook test adjusted
gnikyt Dec 19, 2018
23fab17
Billable middleware test adjusted
gnikyt Dec 19, 2018
108d903
Webhook tests adjusted
gnikyt Dec 19, 2018
d6a8151
Introduction to factories
gnikyt Dec 20, 2018
3cfc5c0
Factories for middleware tests
gnikyt Dec 20, 2018
a2d7358
Models moved to use factories
gnikyt Dec 20, 2018
c4aa8b7
Observer moved to use facades and factories
gnikyt Dec 20, 2018
a4e1cae
Scoped moved to use factories and facades
gnikyt Dec 20, 2018
4837882
Tests almost back to normal...
gnikyt Dec 20, 2018
c95f20d
Passing tests again... now for coverage
gnikyt Dec 20, 2018
68e71eb
Completed code
gnikyt Dec 20, 2018
3b7ded9
Apply fixes from StyleCI
gnikyt Dec 20, 2018
cd4ffd1
Merge pull request #152 from ohmybrew/analysis-8LVyvo
gnikyt Dec 20, 2018
998ea36
Add authorize for <5.7 laravels
gnikyt Dec 20, 2018
ee5417a
Removal of 5.5 laravel
gnikyt Dec 20, 2018
d15015e
Adjustment to routes
gnikyt Dec 20, 2018
0122685
Fixes to billing routes
gnikyt Dec 20, 2018
d34aaef
Merged #153 by @amosmos
gnikyt Dec 20, 2018
8a805b4
StyleCI merge
gnikyt Dec 20, 2018
5503bc1
Merge branch 'master' into refactor
gnikyt Dec 20, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ php:
- 7.2

env:
- LARAVEL_VERSION=5.5.*
- LARAVEL_VERSION=5.6.*
- LARAVEL_VERSION=5.7.*

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
[![StyleCI](https://styleci.io/repos/96462257/shield?branch=master)](https://styleci.io/repos/96462257)
[![License](https://poser.pugx.org/ohmybrew/laravel-shopify/license)](https://packagist.org/packages/ohmybrew/laravel-shopify)

A full-featured Laravel package for aiding in Shopify App development, similar to `shopify_app` for Rails. Works for Laravel 5.5-5.7.
A full-featured Laravel package for aiding in Shopify App development, similar to `shopify_app` for Rails. Works for Laravel 5.6+

![Screenshot](https://github.com/ohmybrew/laravel-shopify/raw/master/screenshot.png)
![Screenshot: Billable](https://github.com/ohmybrew/laravel-shopify/raw/master/screenshot-billable.png)
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
],
"require": {
"php": ">=7.1.0",
"laravel/framework": "~5.5",
"laravel/framework": "~5.6",
"ohmybrew/basic-shopify-api": "~4.0",
"doctrine/dbal": "~2.5"
},
Expand Down
4 changes: 2 additions & 2 deletions phpunit.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
stopOnError="false"
stopOnFailure="true"
stopOnError="true"
stopOnIncomplete="false"
stopOnSkipped="false">
<testsuites>
Expand Down
2 changes: 1 addition & 1 deletion src/ShopifyApp/Console/stubs/webhook-job.stub
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class DummyClass implements ShouldQueue
* Create a new job instance.
*
* @param string $shopDomain The shop's myshopify domain
* @param object $webhook The webhook data (JSON decoded)
* @param object $webhook The webhook data (JSON decoded)
*
* @return void
*/
Expand Down
3 changes: 3 additions & 0 deletions src/ShopifyApp/Controllers/AuthController.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
use Illuminate\Routing\Controller;
use OhMyBrew\ShopifyApp\Traits\AuthControllerTrait;

/**
* Responsible for authenticating the shop.
*/
class AuthController extends Controller
{
use AuthControllerTrait;
Expand Down
3 changes: 3 additions & 0 deletions src/ShopifyApp/Controllers/BillingController.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
use Illuminate\Routing\Controller;
use OhMyBrew\ShopifyApp\Traits\BillingControllerTrait;

/**
* Responsible for billing a shop for plans and usage charges.
*/
class BillingController extends Controller
{
use BillingControllerTrait;
Expand Down
3 changes: 3 additions & 0 deletions src/ShopifyApp/Controllers/HomeController.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
use Illuminate\Routing\Controller;
use OhMyBrew\ShopifyApp\Traits\HomeControllerTrait;

/**
* Responsible for showing the main homescreen for the app.
*/
class HomeController extends Controller
{
use HomeControllerTrait;
Expand Down
3 changes: 3 additions & 0 deletions src/ShopifyApp/Controllers/WebhookController.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
use Illuminate\Routing\Controller;
use OhMyBrew\ShopifyApp\Traits\WebhookControllerTrait;

/**
* Responsible for handling incoming webhook requests.
*/
class WebhookController extends Controller
{
use WebhookControllerTrait;
Expand Down
3 changes: 3 additions & 0 deletions src/ShopifyApp/Facades/ShopifyApp.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

use Illuminate\Support\Facades\Facade;

/**
* Package's facade mapper for Laravel.
*/
class ShopifyApp extends Facade
{
/**
Expand Down
22 changes: 9 additions & 13 deletions src/ShopifyApp/Jobs/AppUninstalledJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,18 @@

namespace OhMyBrew\ShopifyApp\Jobs;

use Carbon\Carbon;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Config;
use OhMyBrew\ShopifyApp\Models\Charge;
use OhMyBrew\ShopifyApp\Models\Shop;

/**
* Webhook job responsible for handling when the app is uninstalled.
*/
class AppUninstalledJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
Expand Down Expand Up @@ -62,9 +65,9 @@ public function handle()
return false;
}

$this->cancelCharge();
$this->cleanShop();
$this->softDeleteShop();
$this->cancelCharge();

return true;
}
Expand Down Expand Up @@ -99,16 +102,9 @@ protected function softDeleteShop()
*/
protected function cancelCharge()
{
$lastCharge = $this->shop->charges()
->withTrashed()
->whereIn('type', [Charge::CHARGE_RECURRING, Charge::CHARGE_ONETIME])
->orderBy('created_at', 'desc')
->first();

if ($lastCharge && !$lastCharge->isDeclined() && !$lastCharge->isCancelled()) {
$lastCharge->status = 'cancelled';
$lastCharge->cancelled_on = Carbon::today()->format('Y-m-d');
$lastCharge->save();
$planCharge = $this->shop->planCharge();
if ($planCharge && !$planCharge->isDeclined() && !$planCharge->isCancelled()) {
$planCharge->cancel();
}
}

Expand All @@ -119,7 +115,7 @@ protected function cancelCharge()
*/
protected function findShop()
{
$shopModel = config('shopify-app.shop_model');
$shopModel = Config::get('shopify-app.shop_model');

return $shopModel::where(['shopify_domain' => $this->shopDomain])->first();
}
Expand Down
8 changes: 7 additions & 1 deletion src/ShopifyApp/Jobs/ScripttagInstaller.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;

/**
* Webhook job responsible for handling installing scripttag.
*/
class ScripttagInstaller implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
Expand Down Expand Up @@ -55,7 +58,10 @@ public function handle()
$shopScripttags = $api->rest(
'GET',
'/admin/script_tags.json',
['limit' => 250, 'fields' => 'id,src']
[
'limit' => 250,
'fields' => 'id,src',
]
)->body->script_tags;

foreach ($this->scripttags as $scripttag) {
Expand Down
8 changes: 7 additions & 1 deletion src/ShopifyApp/Jobs/WebhookInstaller.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;

/**
* Webhook job responsible for handling installation of webhook listeners.
*/
class WebhookInstaller implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
Expand Down Expand Up @@ -55,7 +58,10 @@ public function handle()
$shopWebhooks = $api->rest(
'GET',
'/admin/webhooks.json',
['limit' => 250, 'fields' => 'id,address']
[
'limit' => 250,
'fields' => 'id,address',
]
)->body->webhooks;

foreach ($this->webhooks as $webhook) {
Expand Down
11 changes: 8 additions & 3 deletions src/ShopifyApp/Middleware/AuthProxy.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,13 @@

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Response;
use Illuminate\Support\Facades\Session;
use OhMyBrew\ShopifyApp\Facades\ShopifyApp;

/**
* Responsible for ensuring a proper app proxy request.
*/
class AuthProxy
{
/**
Expand All @@ -19,19 +24,19 @@ class AuthProxy
public function handle(Request $request, Closure $next)
{
// Grab the query parameters we need, remove signature since its not part of the signature calculation
$query = request()->query->all();
$query = $request->query->all();
$signature = $query['signature'];
unset($query['signature']);

// Build a local signature
$signatureLocal = ShopifyApp::createHmac(['data' => $query, 'buildQuery' => true]);
if ($signature !== $signatureLocal || !isset($query['shop'])) {
// Issue with HMAC or missing shop header
abort(401, 'Invalid proxy signature');
return Response::make('Invalid proxy signature.', 401);
}

// Save shop domain to session
session(['shopify_domain' => ShopifyApp::sanitizeShopDomain(request('shop'))]);
Session::put('shopify_domain', ShopifyApp::sanitizeShopDomain($request->get('shop')));

// All good, process proxy request
return $next($request);
Expand Down
18 changes: 12 additions & 6 deletions src/ShopifyApp/Middleware/AuthShop.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,15 @@

use Closure;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Redirect;
use Illuminate\Support\Facades\Session;
use OhMyBrew\ShopifyApp\Facades\ShopifyApp;
use Symfony\Component\HttpFoundation\Response;

/**
* Response for ensuring an authenticated shop.
*/
class AuthShop
{
/**
Expand All @@ -20,7 +26,7 @@ class AuthShop
public function handle(Request $request, Closure $next)
{
$shop = ShopifyApp::shop();
$shopParam = ShopifyApp::sanitizeShopDomain(request('shop'));
$shopParam = ShopifyApp::sanitizeShopDomain($request->get('shop'));

// Check if shop has a session, also check the shops to ensure a match
if (
Expand All @@ -30,12 +36,12 @@ public function handle(Request $request, Closure $next)
$shop->trashed()
) {
// Either no shop session or shops do not match
session()->forget('shopify_domain');
Session::forget('shopify_domain');

// Set the return-to path so we can redirect after successful authentication
session(['return_to' => $request->fullUrl()]);
Session::put('return_to', $request->fullUrl());

return redirect()->route('authenticate', ['shop' => $shopParam]);
return Redirect::route('authenticate', ['shop' => $shopParam]);
}

// Shop is OK, move on...
Expand All @@ -45,7 +51,7 @@ public function handle(Request $request, Closure $next)
$response = new Response($response);
}

if (config('shopify-app.esdk_enabled')) {
if (Config::get('shopify-app.esdk_enabled')) {
// Headers applicable to ESDK only
$response->headers->set('P3P', 'CP="Not used"');
$response->headers->remove('X-Frame-Options');
Expand Down
12 changes: 8 additions & 4 deletions src/ShopifyApp/Middleware/AuthWebhook.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Response;
use OhMyBrew\ShopifyApp\Facades\ShopifyApp;

/**
* Response for ensuring a proper webhook request.
*/
class AuthWebhook
{
/**
Expand All @@ -18,14 +22,14 @@ class AuthWebhook
*/
public function handle(Request $request, Closure $next)
{
$hmac = request()->header('x-shopify-hmac-sha256') ?: '';
$shop = request()->header('x-shopify-shop-domain');
$data = request()->getContent();
$hmac = $request->header('x-shopify-hmac-sha256') ?: '';
$shop = $request->header('x-shopify-shop-domain');
$data = $request->getContent();

$hmacLocal = ShopifyApp::createHmac(['data' => $data, 'raw' => true, 'encode' => true]);
if (!hash_equals($hmac, $hmacLocal) || empty($shop)) {
// Issue with HMAC or missing shop header
abort(401, 'Invalid webhook signature');
return Response::make('Invalid webhook signature.', 401);
}

// All good, process webhook
Expand Down
10 changes: 7 additions & 3 deletions src/ShopifyApp/Middleware/Billable.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Redirect;
use OhMyBrew\ShopifyApp\Facades\ShopifyApp;
use OhMyBrew\ShopifyApp\Models\Charge;

/**
* Responsible for ensuring the shop is being billed.
*/
class Billable
{
/**
Expand All @@ -19,11 +23,11 @@ class Billable
*/
public function handle(Request $request, Closure $next)
{
if (config('shopify-app.billing_enabled') === true) {
if (Config::get('shopify-app.billing_enabled') === true) {
$shop = ShopifyApp::shop();
if (!$shop->isFreemium() && !$shop->isGrandfathered() && !$shop->plan) {
// They're not grandfathered in, and there is no charge or charge was declined... redirect to billing
return redirect()->route('billing');
return Redirect::route('billing');
}
}

Expand Down
Loading