1. Go to this page and download the library: Download esign/laravel-shopify library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
esign / laravel-shopify example snippets
'routes' => [
'enabled' => true, // false = the package registers no routes at all
'app_home' => true, // false = skip only the "GET /" app home route
'app_home_path' => '/', // relocate the app home, e.g. '/shopify-app'
'prefix' => 'shopify', // prefix for the auth routes
'webhooks_prefix' => 'webhooks',
],
use Esign\LaravelShopify\Http\Controllers\AppController;
use Esign\LaravelShopify\Http\Controllers\AuthController;
Route::get('/shopify/auth/token-refresh', [AuthController::class, 'tokenRefresh'])
->name('shopify.auth.token-refresh');
Route::middleware('shopify.verify.embedded-app')
->get('/my-app', [AppController::class, 'home'])
->name('shopify.app.home');
namespace App\GraphQL\Queries;
use Esign\LaravelShopify\GraphQL\Contracts\Query;
use Shopify\App\Types\GQLResult;
class GetProductQuery implements Query
{
public function __construct(private string $productId) {}
public function query(): string
{
return <<<'GQL'
query getProduct($id: ID!) {
product(id: $id) {
id
title
description
}
}
GQL;
}
public function variables(): array
{
return ['id' => $this->productId];
}
public function mapFromResponse(GQLResult $response): mixed
{
return $response->data['product'];
}
}
use Esign\LaravelShopify\Facades\Shopify;
use App\GraphQL\Queries\GetProductQuery;
// In a controller or job (a shop must be authenticated via Auth::user())
$product = Shopify::query(new GetProductQuery('gid://shopify/Product/123'));
namespace App\GraphQL\Mutations;
use Esign\LaravelShopify\GraphQL\Contracts\Mutation;
use Shopify\App\Types\GQLResult;
class CreateProductMutation implements Mutation
{
public function __construct(
private string $title,
private string $description
) {}
public function query(): string
{
return <<<'GQL'
mutation createProduct($input: ProductInput!) {
productCreate(input: $input) {
product { id title }
userErrors { field message }
}
}
GQL;
}
public function variables(): array
{
return [
'input' => [
'title' => $this->title,
'descriptionHtml' => $this->description,
],
];
}
public function mapFromResponse(GQLResult $response): mixed
{
return $response->data['productCreate']['product'];
}
}
namespace App\GraphQL\Queries;
use Esign\LaravelShopify\GraphQL\Contracts\PaginatedQuery;
use Shopify\App\Types\GQLResult;
class GetAllProductsQuery implements PaginatedQuery
{
private ?string $cursor = null;
public function query(): string
{
return <<<'GQL'
query getAllProducts($cursor: String) {
products(first: 50, after: $cursor) {
edges { node { id title } }
pageInfo { hasNextPage endCursor }
}
}
GQL;
}
public function variables(): array
{
return ['cursor' => $this->cursor];
}
// Must return an array; every page's array is merged into the final result.
public function mapFromResponse(GQLResult $response): array
{
return $response->data['products']['edges'];
}
public function hasNextPage(GQLResult $response): bool
{
$pageInfo = $response->data['products']['pageInfo'];
$this->cursor = $pageInfo['endCursor'] ?? null;
return $pageInfo['hasNextPage'] ?? false;
}
}
// Executes every page and returns the merged array of edges
$allProducts = Shopify::queryPaginated(new GetAllProductsQuery());
use Esign\ShopifyData\Inputs\CustomerInput;
use Esign\ShopifyData\Inputs\MailingAddressInput;
$customerInput = new CustomerInput(
email: '[email protected]',
firstName: 'John',
lastName: 'Doe',
addresses: [
new MailingAddressInput(
address1: '123 Main St',
city: 'Toronto',
countryCode: 'CA',
provinceCode: 'ON',
zip: 'M5H 2N2',
),
],
);
// Use in your mutation
$variables = [
'input' => $customerInput->toArray(), // null properties are omitted
];
use Esign\ShopifyData\DTOs\ProductDto;
public function mapFromResponse(GQLResult $response): ProductDto
{
return ProductDto::from($response->data['product']);
}
namespace App\Jobs\Shopify;
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\Log;
class OrdersCreateJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public function __construct(
public string $shopDomain,
public array $webhookData,
) {}
public function handle(): void
{
Log::info('Order created', [
'shop' => $this->shopDomain,
'order_id' => $this->webhookData['id'],
]);
// Process order data
// YourOrder::create([...]);
}
}
// In EventServiceProvider or via Event::listen()
use Esign\LaravelShopify\Events\AppInstalledEvent;
use Esign\LaravelShopify\Events\AppUninstalledEvent;
Event::listen(AppInstalledEvent::class, function (AppInstalledEvent $event) {
// $event->shop contains the Shop model
Log::info('New shop installed', ['domain' => $event->shop->domain]);
// Dispatch a job if heavy processing is needed
dispatch(new SetupNewShopJob($event->shop));
});
Event::listen(AppUninstalledEvent::class, function (AppUninstalledEvent $event) {
// Clean up external resources, notify team, etc.
});
use Esign\LaravelShopify\Models\Shop;
// Get authenticated shop
$shop = Auth::user(); // Returns Shop model
// Check installation status
if ($shop->isInstalled()) {
// Shop is currently installed
}
// Mark as uninstalled (soft delete)
$shop->markAsUninstalled();
// Mark as reinstalled (restore from soft delete); the access token is set
// separately via token exchange on the next embedded-app request.
$shop->markAsReinstalled();
// Access token (encrypted in database)
$token = $shop->access_token;