Skip to content

Commit ac5e1dc

Browse files
committed
Initial commit
0 parents  commit ac5e1dc

File tree

6 files changed

+597
-0
lines changed

6 files changed

+597
-0
lines changed

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/build
2+
/vendor
3+
.env
4+
.php-cs-fixer.cache
5+
.phpunit.result.cache
6+
composer.lock
7+
phpunit.xml

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2024 Arslan Ramay
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
# About
2+
3+
A simple PHP API wrapper for Shopify using Guzzle [Shopify API](https://help.shopify.com/api/getting-started).
4+
5+
## Installation
6+
7+
Install via [Composer](https://getcomposer.org/) by running `composer require arslanramay/php-shopify-api` in your project directory.
8+
9+
## Usage
10+
11+
In order to use this wrapper library you will need to provide credentials to access Shopify's API.
12+
13+
You will either need an access token for the shop you are trying to access (if using a [public application](https://help.shopify.com/api/getting-started/authentication#public-applications)) or an API Key and Secret for a [private application](https://help.shopify.com/api/getting-started/authentication#private-applications).
14+
15+
## Examples
16+
17+
#### Make an API call
18+
```php
19+
use arslanramay\ShopifyPHP\Shopify;
20+
21+
// Initialize the client
22+
$shopify = new Shopify('exampleshop.myshopify.com', 'mysupersecrettoken');
23+
24+
// Get all products
25+
$result = $shopify->call('GET', 'admin/products.json');
26+
27+
// Get the products with ids of '9326553104669' and '9339160002845' with only the 'id', 'images', and 'title' fields
28+
$result = $shopify->call('GET', 'admin/products.json', [
29+
'ids' => '9326553104669,9339160002845',
30+
'fields' => 'id,images,title',
31+
]);
32+
33+
// Create a new product with title "Kerastase Shampoo 150ml"
34+
$result = $shopify->call('POST', 'admin/products.json', [
35+
'product' => [
36+
"title" => "Kerastase Shampoo 150ml",
37+
"body_html" => "<strong>Good shampoo for hair!</strong>",
38+
"vendor" => "Kerastase",
39+
"product_type" => "Snowboard",
40+
"tags" => 'Shampoo, Kerastas, "Hair Care"',
41+
],
42+
]);
43+
```
44+
45+
#### Use Private Application API Credentials to authenticate API requests
46+
```php
47+
use arslanramay\ShopifyPHP\Shopify;
48+
49+
$shopify = new Shopify($data['shop'], [
50+
'api_key' => '...',
51+
'secret' => '...',
52+
]);
53+
```
54+
55+
#### Use an access token to authenticate API requests
56+
```php
57+
use arslanramay\ShopifyPHP\Shopify;
58+
59+
$storedToken = ''; // Retrieve the stored token for the shop in question
60+
$shopify = new Shopify('exampleshop.myshopify.com', $storedToken);
61+
```
62+
63+
#### Request an access_token for a shop
64+
```php
65+
use arslanramay\ShopifyPHP\Shopify;
66+
67+
function make_authorization_attempt($shop, $scopes)
68+
{
69+
$shopify = new Shopify($shop, [
70+
'api_key' => '...',
71+
'secret' => '...',
72+
]);
73+
74+
$nonce = bin2hex(random_bytes(10));
75+
76+
// Store a record of the shop attempting to authenticate and the nonce provided
77+
$storedAttempts = file_get_contents('authattempts.json');
78+
$storedAttempts = $storedAttempts ? json_decode($storedAttempts) : [];
79+
$storedAttempts[] = ['shop' => $shop, 'nonce' => $nonce, 'scopes' => $scopes];
80+
file_put_contents('authattempts.json', json_encode($storedAttempts));
81+
82+
return $shopify->getAuthorizeUrl($scopes, 'https://example.com/handle/shopify/callback', $nonce);
83+
}
84+
85+
header('Location: ' . make_authorization_attempt('exampleshop.myshopify.com', ['read_product']));
86+
die();
87+
```
88+
89+
#### Handle Shopify's response to the authorization request
90+
```php
91+
use arslanramay\ShopifyPHP\Shopify;
92+
93+
function check_authorization_attempt()
94+
{
95+
$data = $_GET;
96+
97+
$shopify = new Shopify($data['shop'], [
98+
'api_key' => '...',
99+
'secret' => '...',
100+
]);
101+
102+
$storedAttempt = null;
103+
$attempts = json_decode(file_get_contents('authattempts.json'));
104+
foreach ($attempts as $attempt) {
105+
if ($attempt->shop === $data['shop']) {
106+
$storedAttempt = $attempt;
107+
break;
108+
}
109+
}
110+
111+
return $shopify->authorizeApplication($storedAttempt->nonce, $data);
112+
}
113+
114+
$response = check_authorization_attempt();
115+
if ($response) {
116+
// Store the access token for later use
117+
$response->access_token;
118+
}
119+
```

composer.json

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
"name": "arslanramay/php-shopify-api",
3+
"description": "A simple PHP API wrapper for Shopify using Guzzle",
4+
"keywords": [
5+
"PHP",
6+
"Shopify",
7+
"API",
8+
"Shopify PHP API"
9+
],
10+
"homepage": "https://github.com/arslanramay/php-shopify-api",
11+
"type": "library",
12+
"require": {
13+
"php": "^8.1",
14+
"guzzlehttp/guzzle": "^7.0"
15+
},
16+
"license": "MIT",
17+
"authors": [
18+
{
19+
"name": "Arslan Ramay",
20+
"email": "arslanramay104@gmail.com"
21+
}
22+
],
23+
"autoload": {
24+
"psr-4": {
25+
"arslanramay\\ShopifyPHP\\": "src/"
26+
}
27+
}
28+
}

index.php

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
<?php
2+
3+
require 'vendor/autoload.php';
4+
5+
use arslanramay\ShopifyPHP\Shopify;
6+
7+
// Load the.env file
8+
$dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
9+
$dotenv->load();
10+
11+
// Define shop domain, API key, and secret
12+
$shop_domain = $_ENV['SHOP_DOMAIN'];
13+
$shop_access_token = $_ENV['SHOP_ACCESS_TOKEN'];
14+
$shop_api_version = $_ENV['SHOP_API_VERSION'];
15+
16+
echo "<pre>";
17+
// var_dump($_ENV);
18+
// var_dump($shop_access_token);
19+
20+
echo "Shop Domain: " . $shop_domain . "\n";
21+
echo "Shop Access Token: " . $shop_access_token;
22+
23+
24+
25+
// Initialize the Shopify client
26+
$shopify = new Shopify($shop_domain, $shop_access_token);
27+
28+
// =====================================
29+
// CODE EXAMPLES
30+
// =====================================
31+
32+
// Example 1: Fetch all Products
33+
$result = $shopify->call('GET', 'admin/products.json');
34+
35+
// echo "<pre>";
36+
// echo var_dump($result->products);
37+
// echo print_r($result->products);
38+
// echo "</pre>";
39+
40+
41+
42+
// Example 2: Fetch products with ids of '9326553104669' and '9339160002845' with only the 'id', 'images', and 'title' fields
43+
$products = $shopify->call('GET', 'admin/products.json', [
44+
'ids' => '9326553104669,9339160002845',
45+
'fields' => 'id,images,title,created_at,status',
46+
]);
47+
48+
echo "<pre>";
49+
// echo var_dump($result->products);
50+
echo print_r($products);
51+
// echo "Products: " . json_encode($products, JSON_PRETTY_PRINT) . "\n";
52+
echo "</pre>";
53+
54+
55+
56+
// Create a new "Burton Custom Freestyle 151" product
57+
// $result123 = $shopify->call('POST', 'admin/products.json', [
58+
// 'product' => [
59+
// "title" => "Burton Custom Freestyle 151",
60+
// "body_html" => "<strong>Good snowboard!</strong>",
61+
// "vendor" => "Burton",
62+
// "product_type" => "Snowboard",
63+
// "tags" => 'Barnes Noble, Johns Fav, "Big Air"',
64+
// ],
65+
// ]);
66+
67+
// print_r($result123);
68+
69+
// Example 3: Create a new Product
70+
71+
// Product data
72+
$productData = [
73+
'product' => [
74+
'title' => 'Kerastase Shampoo 150ml',
75+
'body_html' => '<strong>Kerastase Shampoo</strong> for healthy hair.',
76+
'vendor' => 'Kerastase',
77+
'product_type' => 'Shampoo',
78+
'tags' => 'Shampoo, Kerastas, Hair Care',
79+
'variants' => [
80+
[
81+
'option1' => 'Default Title',
82+
'price' => '29.99',
83+
'sku' => 'KERASTASE-150ML',
84+
]
85+
]
86+
]
87+
];
88+
89+
// Create product
90+
try {
91+
$product = $shopify->call('POST', 'admin/api/2024-01/products.json', $product);
92+
print_r($product);
93+
} catch (Exception $e) {
94+
echo 'Error creating product: ' . $e->getMessage();
95+
}
96+
97+
98+
// Create a new product with title "Kerastase Shampoo 150ml"
99+
// $result = $shopify->call('POST', 'admin/products.json', [
100+
// 'product' => [
101+
// "title" => "Kerastase Shampoo 150ml",
102+
// "body_html" => "<strong>Good shampoo for hair!</strong>",
103+
// "vendor" => "Kerastase",
104+
// "product_type" => "Snowboard",
105+
// "tags" => 'Shampoo, Kerastas, "Hair Care"',
106+
// ],
107+
// ]);
108+
109+
110+
// Fetch orders
111+
// try {
112+
// $orders = $shopify->call('GET', 'admin/api/2024-04/orders.json');
113+
// echo "<pre>";
114+
// echo "Orders: " . json_encode($orders, JSON_PRETTY_PRINT) . "\n";
115+
// echo "</pre>";
116+
// } catch (Exception $e) {
117+
// echo "Error fetching orders: " . $e->getMessage() . "\n";
118+
// }

0 commit comments

Comments
 (0)