Installation:
composer require kyon147/laravel-shopify
Publish the config and migrations:
php artisan vendor:publish --provider="Kyon147\Shopify\ShopifyServiceProvider"
php artisan migrate
Configuration:
Add your Shopify app credentials to .env:
SHOPIFY_API_KEY=your_api_key
SHOPIFY_API_SECRET=your_api_secret
SHOPIFY_REDIRECT_URI=http://your-app.test/api/auth/callback
SHOPIFY_SCOPES=write_products,write_orders,read_themes
First Use Case:
Set up OAuth routes in routes/web.php:
Route::get('/auth/shopify', [ShopifyController::class, 'install'])->name('shopify.install');
Route::get('/auth/shopify/callback', [ShopifyController::class, 'callback']);
Use the ShopifyController to handle OAuth flow and store shop data.
Create a controller to handle Shopify webhooks:
use Kyon147\Shopify\Facades\Shopify;
class ShopifyWebhookController extends Controller
{
public function handleWebhook(Request $request)
{
$topic = $request->header('X-Shopify-Topic');
$hmac = $request->header('X-Shopify-Hmac-Sha256');
return Shopify::webhook($topic, $hmac, $request->getContent());
}
}
Installation Route: Redirect users to Shopify for OAuth:
public function install()
{
return Shopify::install();
}
Callback Handling: Process the OAuth response and store the shop data:
public function callback(Request $request)
{
$shop = Shopify::callback($request, 'your_store_callback_url');
// Store $shop->id in your database
}
Shop Context:
Use the Shopify facade with a shop ID:
$shop = Shopify::findShopById($shopId);
$products = $shop->callApi('GET', '/admin/api/2023-01/products.json');
Resource Management: Fetch and update resources (e.g., products, orders):
$product = $shop->callApi('GET', '/admin/api/2023-01/products/123456789.json');
$product->title = 'Updated Title';
$shop->callApi('PUT', '/admin/api/2023-01/products/123456789.json', $product);
Register Webhooks: Subscribe to Shopify events during OAuth callback:
$shop->subscribeWebhook('orders/create', 'your_webhook_url');
Handle Incoming Webhooks: Verify and process webhook payloads:
public function handleWebhook(Request $request)
{
$topic = $request->header('X-Shopify-Topic');
$data = Shopify::verifyWebhook($topic, $request->getContent());
// Process $data (e.g., create an order in your DB)
}
Track Usage:
Use the Billable trait to log API calls for billing:
use Kyon147\Shopify\Traits\Billable;
class MyShopifyService
{
use Billable;
public function fetchProducts()
{
$this->increment('products_fetched');
return Shopify::callApi(...);
}
}
Retrieve Metrics: Fetch usage data for a shop:
$metrics = Shopify::getBillableMetrics($shopId);
API Versioning:
/admin/api/2023-01/products.json). Mismatches cause 404 Not Found.Webhook Verification:
Shopify::verifyWebhook() to avoid spoofing:
$data = Shopify::verifyWebhook($topic, $rawBody, $hmac);
Rate Limiting:
429 Too Many Requests gracefully:
try {
$response = $shop->callApi('GET', '/admin/api/2023-01/products.json');
} catch (RateLimitExceededException $e) {
// Retry with exponential backoff
}
Session Management:
$shop->refreshAccessToken();
Enable Logging:
Configure logging in .env:
SHOPIFY_LOG_LEVEL=debug
Logs appear in storage/logs/shopify.log.
Inspect Responses:
Use dd() to debug API responses:
$response = $shop->callApi('GET', '/admin/api/2023-01/products.json');
dd($response->body);
Test Locally: Use ngrok to expose local endpoints for webhook testing:
ngrok http 8000
Configure Shopify to send webhooks to your ngrok URL.
Custom API Clients:
Extend the Shopify facade for reusable logic:
class CustomShopify extends \Kyon147\Shopify\Facades\Shopify
{
public function getCustomProducts()
{
return $this->callApi('GET', '/admin/api/2023-01/custom_products.json');
}
}
Middleware for Shop Context: Attach a middleware to inject the current shop into requests:
Shopify::middleware(function ($request, $next) {
$shop = Shopify::findShopByRequest($request);
$request->merge(['shop' => $shop]);
return $next($request);
});
Event Listeners: Listen for Shopify events (e.g., after webhook processing):
Shopify::listen('webhook.processed', function ($topic, $data) {
// Custom logic (e.g., send Slack notification)
});
Scopes:
SHOPIFY_SCOPES in .env match the scopes requested during OAuth. Missing scopes cause 403 Forbidden.Redirect URI:
SHOPIFY_REDIRECT_URI must exactly match the URI configured in your Shopify Partners dashboard. Use absolute URLs (e.g., https://your-app.com/auth/callback).Environment-Specific Settings:
Use Laravel’s .env files to manage different environments:
# .env.production
SHOPIFY_API_KEY=prod_key
SHOPIFY_API_SECRET=prod_secret
# .env.local
SHOPIFY_API_KEY=local_key
SHOPIFY_API_SECRET=local_secret
Batch API Calls: Use pagination for large datasets:
$limit = 250; // Max allowed by Shopify
$products = $shop->callApi('GET', "/admin/api/2023-01/products.json?limit=$limit");
Cache Responses: Cache frequent API calls (e.g., shop themes):
$theme = Cache::remember("shop_{$shopId}_theme", now()->addHours(1), function () use ($shop) {
return $shop->callApi('GET', '/admin/api/2023-01/themes.json');
});
Async Webhook Processing: Offload webhook processing to a queue (e.g., Laravel Queues):
Shopify::listen('webhook.processed', function ($topic, $data) {
dispatch(new ProcessWebhook($topic, $data));
});
How can I help you explore Laravel packages today?