shopify / shopify-api-php Goto Github PK
View Code? Open in Web Editor NEWLicense: MIT License
License: MIT License
I get error when OAuth callback
Here is my code
OAuth::callback($cookies, $query, function (OAuthCookie $cookie) {
setcookie(
$cookie->getName(),
$cookie->getValue(),
$cookie->getExpire(),
'',
'',
$cookie->isSecure(),
$cookie->isHttpOnly()
);
return true;
});
I get this error:
Shopify\Exception\CookieNotFoundException
Could not find the current session id in the cookies
Fatal error: Uncaught TypeError: Return value of Shopify\Clients\HttpClientFactory::client() must be an instance of Psr\Http\Client\ClientInterface, instance of GuzzleHttp\Client returned in
This happen in callback method when try to fetchAccessToken, any clue why this happen ?
The API itself will already return the full object if you do a create/update operation. However, the library swallows this response here:
https://github.com/Shopify/shopify-php-api/blob/0556edf274ceb83346533bd22b662d7622e58c66/src/Rest/Base.php#L60-L74
Adding return $response->getDecodedBody();
at the end of the function should suffice. Note that the saveAndUpdate
function would also need to be updated, with return $this->save(true);
. Implementation can be found in my fork: MagicLegend@d43bc94
What inspired this feature request? What problems were you facing?
I would like to verify the saved object myself, without needing to query the API again for data that was already returned in the first place. This also allows immediate access to the ID of the newly created object.
Is there a way to remove created webhook? Now I can only register, but not to remove.
There are cases when you need to remove registered webhooks
Hi
Please clearify in instruction how to start using the library.
for example after autload? how to start using it.
Regards
Will there be support for Laravel 9? Getting this message on installation
osiset/laravel-shopify[v17.1.0, ..., 17.1.x-dev] require laravel/framework ^7.0 || ^8.0 -> found laravel/framework[v7.0.0, ..., 7.x-dev, v8.0.0, ..., 8.x-dev] but it conflicts with your root composer.json require (^9.2).
Error thrown: Call to a member function client() on null in /var/www/vendor/shopify/shopify-api/src/Clients/Http.php on line 164
$client = Context::$HTTP_CLIENT_FACTORY->client();
Should be returning a working Guzzle client however it isnt. Apologies it's late here but Context::initialize()
is never called as far as I can see and so $HTTP_CLIENT_FACTORY
is never populated with the Guzzle client that is relied on.
new \Shopify\Clients\Rest($url, $accessToken)->get('orders');
When i called following code (process method):
$registry = new Registry();
$response = $registry->process($request->headers->toArray(), $request->getRawBody());
Getting following error:
Call to undefined method Symfony\Component\HttpFoundation\HeaderBag::toArray()
Note: Laravel Framework 8.83.2
any solution?
I get a [statusCode:GuzzleHttp\Psr7\Response:private] => 200 in the response.
So it seems to work but it does not reflect in updated inventory. :(
Checking at /admin/products/inventory?location_id=62241177806&query=F11_27781195 does not show the new inventory.
I am using the inventoryid correctly (not product or variantid).
$inventoryItemAdjustments = array();
$inventoryItemAdjustments[] = (object)[
'inventoryItemId' => 'gid://shopify/InventoryItem/43151435235534',
'availableDelta' => 500
];
$inventoryItemAdjustments[] = (object)[
'inventoryItemId' => 'gid://shopify/InventoryItem/43151435268302',
'availableDelta' => 500
];
$variables = array(
'locationId' => ConfigClass::$locationId,
'inventoryItemAdjustments' => $inventoryItemAdjustments
);
$graphqlquery='mutation inventoryBulkAdjustQuantityAtLocation($inventoryItemAdjustments: [InventoryAdjustItemInput!]!, $locationId: ID!)
{inventoryBulkAdjustQuantityAtLocation(inventoryItemAdjustments: $inventoryItemAdjustments, locationId: $locationId) {userErrors { field message }}}';
$response = $client->query(['query' => $graphqlquery, 'variables' => $variables]);
print_r($response);
Deleting a product works (and is a good test if the library is initialized well):
$query = <<<QUERY
mutation {
productDelete(input: {id: "gid://shopify/Product/6975310463182"})
{
deletedProductId
}
}
QUERY;
$response = $client->query(["query" => $query]);
print_r($response);
The documents on how to use the rest client is very poor. You'll get in a endless void of non documented specification:
How can i use this Rest client in laravel? Can someone provide the proper and full infromation on how to use the client in a controller and a command?
We've been using another package for our apps. That package is going to be achieved soon. As our apps are using PHP 7.2, this is our request to you to add PHP 7.2 support as well so we can use this package.
Thanks!
The project could really do with some better documentation in general, although this ticket is more aimed at PHPDocs for functions. There are a lot of undocumented functions, that could do with a quick one-line explanation of what it's doing. For example, the src/Rest/Base.php
file has no useful documentation at all, and not all functions even have the auto-generated function docs.
The library could really use some love!
What inspired this enhancement?
The (in-code) documentation is severely lacking in some places.
Rest/Base.php could use a method to retrieve headers from the response
What inspired this feature request? What problems were you facing?
Need to access X-Request-Id, X-Shopify-Shop-Api-Call-Limit, Retry-After, etc.
I'd like to see the requirement for guzzle/guzzlehttp
loosened to also allow v6, instead of ^7.0
. I have forked the project, and downgraded the package. All tests still succeed, so I'm assuming v6 is fully compatible with this package as well.
I also have loosened doctrine/inflector
to allow v1, which also doesn't break the tests. This is a deeper dependency to two Magento packages as well.
Magento v2.4.3 uses Guzzlehttp v6, and upgrading Magento is simply not an option. In our case:
$ composer2 why guzzlehttp/guzzle
magento/ece-tools 2002.1.10 requires guzzlehttp/guzzle (^6.3||^7.3)
magento/framework 103.0.3-p1 requires guzzlehttp/guzzle (^6.3.3)
magento/module-catalog-sync-admin 1.0.4 requires guzzlehttp/guzzle (~6.0)
magento/module-product-recommendations-admin 3.0.4 requires guzzlehttp/guzzle (~6.0)
magento/module-product-recommendations-sync-admin 1.0.1 requires guzzlehttp/guzzle (~6.0)
magento/product-community-edition 2.4.3-p1 requires guzzlehttp/guzzle (^6.3.3)
magento/product-enterprise-edition 2.4.3-p1 requires guzzlehttp/guzzle (^6.3.3)
magento/product-recommendations-admin 3.0.5 requires guzzlehttp/guzzle (~6.0)
magento/services-connector 1.2.0 requires guzzlehttp/guzzle (6.*)
$ composer2 why doctrine/inflector
illuminate/support v5.8.36 requires doctrine/inflector (^1.1)
$ composer2 why illuminate/support
illuminate/config v5.8.36 requires illuminate/support (5.8.*)
$ composer2 why illuminate/config
magento/ece-tools 2002.1.10 requires illuminate/config (^5.5||^8.77)
magento/magento-cloud-docker 1.3.2 requires illuminate/config (^5.5||^8.77)
Would be great if it'd be allowed to use both packages with a lower version for better compatability.
Currently using this library when connecting to a private app is confusing.
It takes quite a long time to work out what you are doing, when it feels like it could be really simple.
In our usecase, we only want to consume the Shopify admin api via REST, with a private app access token.
Currently to do that you have to have the following code:
Context::initialize(
'xxx', // Not used
'yyy', // Not used
'read_orders, write_orders', // Not used
'http://localhost', // Not used
new FileSessionStorage('/tmp/php_sessions'), // Not used
'latest',
false, // Not used
false, // Needs to (incorrectly) be set to false
);
$rest = new Rest($domain, $storeApiToken);
This is not helped by the fact that there is a bug on this line:
https://github.com/Shopify/shopify-php-api/blob/main/src/Clients/Rest.php#L46
So you actually have to Context::initialize with "privateApp" to to false, so it uses the access token not the secret key.
$headers[HttpHeaders::X_SHOPIFY_ACCESS_TOKEN] =
Context::$IS_PRIVATE_APP ? Context::$API_SECRET_KEY : $this->accessToken;
There is barely any point in having to call Context::initialize, the only reason for doing it is to:
In an ideal situation I would just need to do this:
$rest = new Rest($domain, $storeApiToken);
Happy to contribute these changes, if you are welcome to receive them.
Please add php 8 support as the package cannot be used with the laravel 8 and psr 2.0
run command: composer require shopify/shopify-api:3.0.0
, error:
composer require shopify/shopify-api:3.0.0
, report an error.composer require guzzlehttp/guzzle:7.4.5
, successful installation.composer require shopify/shopify-api:3.0.0
, same error.This 194 line causes error.
Array to string conversion
when checkStatusCode
is not 200 status.
The getDecodedBody
returns array.
I am trying to setup non embedded app with the help shopify cli3 using php template.
I have disabled embedded app from the shopify section but app still not working as non embedded. Please help what change we need to do at script level under the laravel.
shopify-api-php/src/Webhooks/Registry.php
Line 157 in 24515ae
This catch
statement is inappropriate for the following reasons:
$error->getMessage()
, the exception object has useful information which is not even accessible.I want to add app bridge 2.0 to my App . Currently I am using PHP for public app. Is there any way to do so ?
As shown below the graphqlProxy method does not accept access mode as a parameter and there is no way to pass it.
public static function graphqlProxy(array $rawHeaders, array $cookies, string $rawBody): HttpResponse
{
$session = self::loadCurrentSession($rawHeaders, $cookies, true);
if (!$session) {
throw new SessionNotFoundException("Could not find session for GraphQL proxy");
}
$client = new Graphql($session->getShop(), $session->getAccessToken());
return $client->proxy($rawBody);
}
For local development, the fixed https in the redirect_uri is a pain => https://github.com/Shopify/shopify-php-api/blob/main/src/Auth/OAuth.php#L92
i would suggest to have an option to customize that value, at least for local developemnt. i assume in production only https redirect uris are allowed anyhow. I would make a PR if you like.
Hi
I am using this package to integrate Shopify in one of my apps. I would prefer if it were possible to provide custom file (and path) for logging errors, maybe probably through Context object.
Discount code lookup fails due to error handling on redirect.
API returns 303 redirect code, which is handled in the Base.php as error, yet this is expected behavior:
This is due to checking for error code above 300 in the request method of Base.php
https://github.com/Shopify/shopify-api-php/blob/main/src/Rest/Base.php#L189
Follow redirect or return headers to read pricelist and discount code id.
DiscountCode::lookup($session, [], ["code" => "SUMMERSALE10OFF"]);
throws RestResourceRequestException.
Request valid Discount code:
DiscountCode::lookup($session, [], ["code" => "SUMMERSALE10OFF"]);
Create discount code and try to look it up:
use Shopify\Rest\Admin2022_07\DiscountCode;
use Shopify\Utils;
$this->test_session = Utils::loadCurrentSession(
$requestHeaders,
$requestCookies,
$isOnline
);
DiscountCode::lookup(
$this->test_session, // Session
[], // Url Ids
["code" => "SUMMERSALE10OFF"], // Params
);
This will result in a RestResourceRequestException
Exception being thrown.
Hi,
As of today, the library dynamically create class properties, such as here.
This has been deprecated in PHP 8.2. Current version therefore lead to warning errors.
Thanks :)
Do you support Basic HTTP Auth for a Private App?
Building a private app with apiKey + secret should be secure enough.
What inspired this enhancement?
OAuth not needed for private apps, IMHO
Auth
Shopify returns Retry-After
header as a float. So when we run usleep($retryAfter * 1000000);
on Clients/Http.php
Line 204 it throws a TypeError Exception as seen here:
TypeError: usleep(): Argument #1 ($microseconds) must be of type int, float given in /home/user/project/vendor/shopify/shopify-api/src/Clients/Http.php:204
Instead of throw an exception it should work and delays the program's execution for given microseconds.
What actually happens?
Throws a TypeError Exception as seen here:
TypeError: usleep(): Argument #1 ($microseconds) must be of type int, float given in /home/user/project/vendor/shopify/shopify-api/src/Clients/Http.php:204
It appears that if an API deprecation occurs, the SDK attempts to write this deprecation to a file named .last_api_deprecation_warning
. This happens in the Http
class and does not seem to be configurable behavior.
In our case, we (as most container-based environments) prevent write access to an application's directories except for a few selected ones, and /vendor
definitely isn't one of them for obvious reasons. The file_put_contents
call unfortunately doesn't have any error handling so a deprecation is now causing exceptions that then trigger our monitoring.
Would it be possible to remove this logic? If I'm being totally honest I don't see the need to write anything directly to a file; that's what libraries such as Monolog or another PSR-compliant library are meant for.
This library currently doesn't work on PHP 8.1
A TypeError should not be thrown
The setcookie signature is invalid and is throwing a TypeError
This TypeError is thrown:
setcookie(): Argument #3 ($expires_or_options) must be of type array|int, null given
ShopifyOAuth::callback()
It's this that causes the problem:
$cookieSet = setcookie( $signatureCookie->getName(), $signatureCookie->getValue(), $signatureCookie->getExpire(), "", "", $signatureCookie->isSecure(), $signatureCookie->isHttpOnly(), );
And it's when there is no expiry time set on the session, which is the case for offline access.
Change this line:
$sessionExpiration = ($session->getExpires() ? (int)$session->getExpires()->format('U') : null);
To:
$sessionExpiration = ($session->getExpires() ? (int)$session->getExpires()->format('U') : 0);
I can submit a pull request if that's helpful :)
I wanted to test this package for my laravel app and i am very confused on how to define my private app. Which fields do i need? Because the fields in a private app are different from a public app. For example i don't need to get my session etc. because i only want to write products to my store from my Laravel app.
Thanks in advance.
Hi
I have authorized the app and its install but when going on the callback step written send cookies and query
BUT we have not set any cookies then which cookies array need to send in this function.
Shopify\Auth\OAuth::callback
in this callback function which cookies array hash need to send anyone to explain a little bit.
Currently the abstract API calls will not handle rate limiting because $tries is not passed on here:
shopify-api-php/src/Rest/Base.php
Lines 173 to 186 in 582252e
Thus $maxTries
will default to 1
:
shopify-api-php/src/Clients/Http.php
Line 150 in 582252e
We ran into rate limiting issues that weren't handled by the library.
In Base.php
it should take apart the $params
array and take out a tries
value from there, to pass it on to the appropriate function. Another solution would be to simply add an optional parameter up the chain, but that would involve changing every function in this library.
I see cookie set for 1 minute for both access token (online/offline). For offline access token, token is permanent, but cookie expired after 1 minute. Here I see Utility function to load current session with headers and cookie. My app not embedded and If I try to access current access token, there is no cookie after 1 minute.
Can you please explain how I can get access token without re-authenticate after 1 minute. I know I can get access token by shop but then why this utility function ?
I think For offline access token, We can set cookie permanent. Is there any issue if we make cookie permanent ?
I am not expert but This is my opinion. It may be wrong.
Thank you
Why provide the Cookies example using YII? Can you add framework-less examples? Any way to add all the code examples necessary to run everything on the main readme file like other shopify api plugins? Needs to be even more clear and easy for beginners and even intermediates to not waste time trying to figure it out.
The Shopify PHP app template already supports, using the EnsureBilling class, the management of some Billing APIs mutations.
Since the underlying billing mutations already support the usage of "trialDays" parameter to enable a trial period of the app (https://shopify.dev/apps/billing/purchase-adjustments/free-trials), I would like to be able to define its value in the shopify.php config file and use it through the EnsureBilling functions as we can do for all the other billing parameters.
The EnsureBilling class enables setting up easily the Shopify app billing using middleware.
Since the billing API mutations used by EnsureBilling's functions already support for the trial period using the "trialDays" parameter, it would be convenient to be able to use all the mutations' native options also through EnsureBilling's functions which wrap them.
...
Give the option to change the path to this file, or remove it
shopify-api-php/src/Clients/Http.php
Line 247 in 432676a
Hi
Using this package is it possible to query this SHOW sum(pageview_count) OVER month(timestamp) AS month statement?
If yes then how we can execute it programmatically?
Currently, I'm using this package: https://github.com/osiset/laravel-shopify, and using that package I'm trying like this way, But it throwing the error.
Example Code:
$response = $shop->api()->graph("SHOW sum(pageview_count) OVER month(timestamp) AS month");
dd($response);
Error: https://prnt.sc/2005osy
Can anyone help me with this?
Thank you.
When creating a fulfillmentEvent, the return exception does not exist index 'event'
It should return me the normal response as described in the documentation https://shopify.dev/api/admin-rest/2022-10/resources/fulfillmentevent#post-orders-order-id-fulfillments-fulfillment-id-events
What actually happens?
it return exception does not exist index 'event'
After printing in the source code of the composer package, I found that the index in the returned result is 'fulfillment_event'
and the rewritten jsonBodyName of the fufillment is event, so this error occurs. I hope it can be fixed as soon as possible.
Can you remove or update requirements of "psr/log": "^1.1", ?
current psr/log version is 3!
This library should implement a "RestResourceRequestJsonException" that extends ShopifyException, to be thrown when a malformed JSON response is returned by Shopify (yes, it happens).
This would allow for the raw response to be logged, alongside X-Request-ID, so that this can be reported and hopefully fixed.
What inspired this feature request? What problems were you facing?
At times Shopify returns JSON data that causes json_decode() to throw a JsonException.
Error when trying to fetch current webhooks.
It should have returned a JSON response containing a list of webhooks
we get this error:
Fatal error: Uncaught TypeError: Argument 1 passed to Shopify\Utils::loadCurrentSession() must be of the type array, null given, called in /www/doc/www.example.com/www/script/index.php on line 45 and defined in /www/doc/www.example.com/www/script/vendor/shopify/shopify-api/src/Utils.php:158 Stack trace: #0 /www/doc/www.example.com/www/script/index.php(45): Shopify\Utils::loadCurrentSession(NULL, NULL, NULL) #1 {main} thrown in /www/doc/www.example.com/www/script/vendor/shopify/shopify-api/src/Utils.php on line 158
require("vendor/autoload.php");
use Shopify\Auth\FileSessionStorage;
use Shopify\Auth\Session;
use Shopify\Rest\Admin2022_10\Customer;
use Shopify\Rest\Admin2022_10\Webhookv2;
use Shopify\Utils;
Shopify\Context::initialize(
'apiKey',
'apiSecretKey',
'read_analytics, read_assigned_fulfillment_orders, read_customers, read_draft_orders, read_merchant_managed_fulfillment_orders, read_order_edits, read_orders, read_script_tags, read_third_party_fulfillment_orders',
'https://sozialstar.de/script/',
new FileSessionStorage('/tmp/php_sessions'),
'2022-10',
);
$this->test_session = Utils::loadCurrentSession(
$requestHeaders,
$requestCookies,
$isOnline
);
Webhookv2::webhooks(
$this->test_session, // Session
[], // Url Ids
[], // Params
);
I tried to install shopify api in my yii2 project using
composer require shopify/shopify-api --with-all-dependencies
but its conflicting with other packages and geeting error like:
Your requirements could not be resolved to an installable set of packages.
Problem 1
- fedemotta/yii2-aws-sdk is locked to version v2.0 and an update of this package was not requested.
- Root composer.json requires shopify/shopify-api ^3.0 -> satisfiable by shopify/shopify-api[v3.0.0].
- kushy/metrc-php-sdk is locked to version dev-master and an update of this package was not requested.
- Conclusion: install guzzlehttp/guzzle 7.4.5 (conflict analysis result)
- You can only install one version of a package, so only one of these can be installed: guzzlehttp/guzzle[5.3.0, ..., 5.3.4, 6.0.0, ..., 6.5.8, 7.0.0, ..., 7.4.5].
- Conclusion: don't install guzzlehttp/guzzle[7.4.5] | install guzzlehttp/guzzle[6.5.4] (conflict analysis result)
Installation failed, reverting ./composer.json and ./composer.lock to their original content.
so please any help with this?
I'm trying to integrate the api with Codeigniter. While initializing, I'm stuck on SHOPIFY_APP_HOST_NAME and session.
I don't know what is the shopify app host name and where can I get it?
what is the session file or path I should use as I'm using Codeigniter?
Context::initialize(
$_ENV['SHOPIFY_API_KEY'],
$_ENV['SHOPIFY_API_SECRET'],
$_ENV['SHOPIFY_APP_SCOPES'],
$_ENV['SHOPIFY_APP_HOST_NAME'], // what is the shopify app host name? where can I get it?
new FileSessionStorage('/tmp/php_sessions'), // what is the session file or path I should use here?
'2021-04',
true,
false,
);
Is it possible you create example projects for vanila PHP, Codeigniter & Laravel so that developers like me can work on the shopify api.
Hi there , on calling this "begin" function it return with authorization url
but if can check in query parameter
$query = [
'client_id' => Context::$API_KEY,
'scope' => Context::$SCOPES->toString(),
'redirect_uri' => Context::$HOST_SCHEME . '://' . Context::$HOST_NAME . $redirectPath,
'state' => $session->getState(),
'grant_options[]' => $grantOptions,
];
why we are writing Context::$HOST_NAME in redirect uri?
We attached a LoggerInterface to Context but couldn't find how can we enable debug logging so package logs every operation it made. Because even We checked and enabled retries for some requests and they resulted with success responses, some properties of result payload we try to read is throws undefined index exception. We want to log everything with request payloads and responses to take a full look to process.
...
What inspired this feature request? What problems were you facing?
Even We checked and enabled retries for some requests and they resulted with success responses, some properties of result payload we try to read is throws undefined index exception. We want to log everything with request payloads and responses to take a full look to process.
...
Required version of psr/log
can be updated so it won't be a conflict with other packages which uses a newer version of psr/log
What inspired this enhancement?
When I tried to install this package on a Laravel 8 project, composer couldn't install it because my project uses psr/log 2.^
I downgraded psr/log
version on my project since most of packages depends on it also accepts version 1.*
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.