Skip to content

Instantly share code, notes, and snippets.

@mig1098
Last active October 21, 2015 21:28
Show Gist options
  • Save mig1098/0b6148679520d7c43272 to your computer and use it in GitHub Desktop.
Save mig1098/0b6148679520d7c43272 to your computer and use it in GitHub Desktop.
shopify private an public extension php client
<?php
namespace Model;
/**
* SHOPIFY PUBLIC AND PRIVATE APP
* ----------------------------------------------
* @Author : Miglio - [email protected]
* @updated : Miglio 2015
* ----------------------------------------------
* DEVELOPER APP KEYS:
* {@api_key},{@secret}
* ----------------------------------------------
* STORE PUBLIC OWNER KEYS:
* {@shop_domain},{@token}
* ----------------------------------------------
* STORE PRIVATE OWNER KEYS:
* {@api_key} , {@api_password} , {@shop_domain}
* ----------------------------------------------
*/
use Library\Shopify\ShopifyClient;
use Library\Shopify\ShopifyClientPrivate;
class Clients{
const SHOP_PUBLIC = 'public';
const SHOP_PRIVATE = 'private';
private $client = null;
public function __construct($args){
if($args['type'] == self::SHOP_PUBLIC){
$this->client = new ShopifyClient($args['shop_domain'],$args['token'],$args['api_key'],$args['secret']);
}else if($args['type'] == self::SHOP_PRIVATE){
$this->client = new ShopifyClientPrivate($args['api_key'].':'.$args['api_password'].'@'. $args['shop_domain'],null,null,null);
}
}
public function call($method, $path, $params=array()){
return $this->client->call($method, $path, $params);
}
}
class Shopify extends Clients{
public $LIMIT=250;
//
private $SHOPIFY_TOPICS = array(//for webhooks
0 => 'orders/create',
1 => 'orders/delete',
2 => 'orders/updated',
3 => 'orders/paid',
4 => 'orders/cancelled',
5 => 'orders/fulfilled',
6 => 'orders/partially_fulfilled',
7 => 'carts/create',
8 => 'checkouts/create',
9 => 'checkouts/update',
10 => 'checkouts/delete',
11 => 'refunds/create',
12 => 'products/create',
13 => 'products/update',
14 => 'products/delete',
15 => 'collections/create',
16 => 'collections/update',
17 => 'collections/delete',
18 => 'customer_groups/create',
19 => 'customer_groups/update',
20 => 'customer_groups/delete',
21 => 'customers/create',
22 => 'customers/enable',
23 => 'customers/disable',
24 => 'customers/update',
25 => 'customers/delete',
26 => 'fulfillments/create',
27 => 'fulfillments/update',
28 => 'shop/update',
29 => 'app/uninstalled',
30 => 'carts/update'
);
//
public function __construct($args = array('type'=>'public')){
parent::__construct($args);
}
/**
* ------------------------------------------
* PRODUCTS
* ------------------------------------------
**/
public function getAllProducts($page=1){
return parent::call('GET', '/admin/products.json', array('published_status'=>'published','page'=>$page,'limit'=>$this->LIMIT));//
}
public function getAllProductsQuery($query=array()){
return parent::call('GET', '/admin/products.json', $query);//
}
public function getAllProductsSinceId($id){
return parent::call('GET', '/admin/products.json?since_id='.$id, array('published_status'=>'published','limit'=>$this->LIMIT));//
}
public function getAllProductsId($page){
return parent::call('GET', '/admin/products.json?fields=id,variants,title',array('published_status'=>'any','page'=>$page,'limit'=>$this->LIMIT));//, array('published_status'=>'any','limit'=>self::LIMIT_ID)
}
public function getAllProductsIdToDelete($page){
return parent::call('GET', '/admin/products.json?fields=id,title',array('published_status'=>'any','page'=>$page,'limit'=>$this->LIMIT));//, array('published_status'=>'any','limit'=>self::LIMIT_ID)
}
public function getAllCountProducts($query=array()){
return parent::call('GET', '/admin/products/count.json',$query);//
}
public function getAllProductsWithFieldsSelected(/* String by commas */$fields){
/**
* massive quantity of products can affect the performance of this method
* */
$total = $this->getAllCountProducts();
$limit = $this->LIMIT;
$paginate = ($total >= $limit) ? ceil($total/$limit) : 1;
$response = array();
for($i=1; $i<=$paginate; $i++){
$products = $this->getAllProductsQuery(array('fields'=>$fields,'page'=>$i,'limit'=>$limit));
$response = ( count($products) > 0 ) ?array_merge($response, $products) : $response;//merge in 1 array
}
return $response;
}
//PRODUCT
public function getProductById($id){
return parent::call('GET', '/admin/products/'.$id.'.json');//
}
public function searchProductBySku($sku){
return parent::call('GET', '/admin/products/search.json?sku:'.$sku);//
}
public function searchProductByTitle($title){
return parent::call('GET', '/admin/products.json?title='.$title);//
}
public function createNewProduct($arrProduct){
//array("product"=>array("title"=>"Burton Custom Freestlye 151","body_html"=>"qwer","vendor"=>"ddqwer2d","product_type"=>"Snowboard"))
return parent::call('POST', '/admin/products.json',$arrProduct);
}
public function deleteProduct($id){
return parent::call('DELETE ', '/admin/products/'.$id.'.json');
}
public function updateProduct($arrProduct){
return parent::call('PUT', '/admin/products/'.$arrProduct["product"]["id"].'.json',$arrProduct);
}
/**
* ------------------------------------------
* VARIANTS
* ------------------------------------------
**/
public function variantCreate($product_id,$arrVariant){
return parent::call('POST', '/admin/products/'.$product_id.'/variants.json',$arrVariant);
}
public function variantUpdate($arrVariant){
return parent::call('PUT', '/admin/variants/'.$arrVariant['variant']['id'].'.json',$arrVariant);
}
public function variantDelete($product_id,$variant_id){
return parent::call('DELETE ', '/admin/products/'.$product_id.'/variants/'.$variant_id.'.json');
}
public function getVariantsByProductId($product_id){
return parent::call('GET', '/admin/products/'.$product_id.'/variants.json',array('fields'=>'id,sku','limit'=>100));
}
/**
* ------------------------------------------
* USER DATA
* ------------------------------------------
**/
public function adminShop(){
return parent::call('GET', '/admin/shop.json');//
}
/**
* ------------------------------------------
* WEBHOOKS
* ------------------------------------------
**/
public function webhookGetAll(){
return parent::call('GET', '/admin/webhooks.json');
}
public function webhookGetById($id){
return parent::call('GET', '/admin/webhooks/'.$id.'.json');
}
public function webhookCreate($arrWebhook){
return parent::call('POST', '/admin/webhooks.json',$arrWebhook);
}
public function webhookUpdate($arrWebhook){
return parent::call('PUT', '/admin/webhooks/'.$arrWebhook['webhook']['id'].'.json',$arrWebhook);
}
public function webhookDelete($id){
return parent::call('DELETE', '/admin/webhooks/'.$id.'.json');
}
public function topic($index){
return $this->SHOPIFY_TOPICS[$index];
}
/**
* ------------------------------------------
* COLLECTIONS
* ------------------------------------------
**/
public function getAllCollections(){
return parent::call('GET', '/admin/custom_collections.json');
}
public function getCollectionById($id){
return parent::call('GET', '/admin/custom_collections/'.$id.'.json');
}
public function getProductsByCollectionId($id){
return parent::call('GET', '/admin/products.json?collection_id='.$id);
}
public function getCollectionByProductId($id){
return parent::call('GET', '/admin/custom_collections.json?product_id='.$id);
}
public function productInCollection($porduct_id,$collection_id){
return parent::call('POST', '/admin/collects.json',array('collect'=>array('product_id'=>$porduct_id,'collection_id'=>$collection_id)));
}
public function getCollect($id){
return parent::call('GET','/admin/collects/'.$id.'.json');
}
/**
* ------------------------------------------
* SMART COLLECTIONS
* ------------------------------------------
**/
public function getAllSmartCollection(){
return parent::call('GET', '/admin/smart_collections.json', array('published_status'=>'published','limit'=>'250'));//
}
public function getAllSmartCollectionById($id){
return parent::call('GET', '/admin/smart_collections/'.$id.'.json');//
}
public function smartCollectionUpdate($data){
return parent::call('PUT', '/admin/smart_collections/'.$data['smart_collection']['id'].'.json',$data);//
}
/**
* ------------------------------------------
* ORDERS
* ------------------------------------------
**/
public function getOrders($page=1){
return parent::call('GET', '/admin/orders.json', array('limit'=>'250','page'=>$page));
}
public function getOrder($id){
return parent::call('GET', '/admin/orders/'.$id.'.json');
}
public function insertOrder($arrOrder){
return parent::call('POST', '/admin/orders.json',$arrOrder);
}
public function deleteOrder($orderId){
return parent::call('DELETE', '/admin/orders/'.$orderId.'.json');
}
/**
* ------------------------------------------
* RECURRING PAYMENT
* ------------------------------------------
* */
public function getRecurringApplicationCharges(){
return parent::call('GET', '/admin/recurring_application_charges.json');
}
public function createRecurringApplicationCharges($recurring){
return parent::call('POST', '/admin/recurring_application_charges.json',$recurring);
}
public function activateRecurringApplicationCharges($recurringId){
return parent::call('POST', '/admin/recurring_application_charges/'.$recurringId.'/activate.json');
}
public function deleteRecurringApplicationCharges($recurringId){
return parent::call('DELETE', '/admin/recurring_application_charges/'.$recurringId.'.json');
}
//TEST
public function test(){
return 'Shopify Api';
}
}
<?php
namespace Library\Shopify;
class ShopifyClient {
public $shop_domain;
private $token;
private $api_key;
private $secret;
private $last_response_headers = null;
public function __construct($shop_domain, $token, $api_key, $secret) {
$this->name = "ShopifyClient";
$this->shop_domain = $shop_domain;
$this->token = $token;
$this->api_key = $api_key;
$this->secret = $secret;
}
// Get the URL required to request authorization
public function getAuthorizeUrl($scope, $redirect_url='') {
$url = "http://{$this->shop_domain}/admin/oauth/authorize?client_id={$this->api_key}&scope=" . urlencode($scope);
if ($redirect_url != '')
{
$url .= "&redirect_uri=" . urlencode($redirect_url);
}
return $url;
}
// Once the User has authorized the app, call this with the code to get the access token
public function getAccessToken($code) {
// POST to POST https://SHOP_NAME.myshopify.com/admin/oauth/access_token
$url = "https://{$this->shop_domain}/admin/oauth/access_token";
$payload = "client_id={$this->api_key}&client_secret={$this->secret}&code=$code";
$response = $this->curlHttpApiRequest('POST', $url, '', $payload, array());
$response = json_decode($response, true);
if (isset($response['access_token']))
return $response['access_token'];
return '';
}
public function callsMade()
{
return $this->shopApiCallLimitParam(0);
}
public function callLimit()
{
return $this->shopApiCallLimitParam(1);
}
public function callsLeft($response_headers)
{
return $this->callLimit() - $this->callsMade();
}
public function call($method, $path, $params=array())
{
$baseurl = "https://{$this->shop_domain}/";
$url = $baseurl.ltrim($path, '/');
$query = in_array($method, array('GET','DELETE')) ? $params : array();
$payload = in_array($method, array('POST','PUT')) ? stripslashes(json_encode($params)) : array();
$request_headers = in_array($method, array('POST','PUT')) ? array("Content-Type: application/json; charset=utf-8", 'Expect:') : array();
// add auth headers
$request_headers[] = 'X-Shopify-Access-Token: ' . $this->token;
$response = $this->curlHttpApiRequest($method, $url, $query, $payload, $request_headers);
$response = json_decode($response, true);
if (isset($response['errors']) or ($this->last_response_headers['http_status_code'] >= 400))
throw new ShopifyApiException($method, $path, $params, $this->last_response_headers, $response);
return (is_array($response) and (count($response) > 0)) ? array_shift($response) : $response;
}
private function curlHttpApiRequest($method, $url, $query='', $payload='', $request_headers=array())
{
$url = $this->curlAppendQuery($url, $query);
$ch = curl_init($url);
$this->curlSetopts($ch, $method, $payload, $request_headers);
$response = curl_exec($ch);
$errno = curl_errno($ch);
$error = curl_error($ch);
curl_close($ch);
if ($errno) throw new ShopifyCurlException($error, $errno);
list($message_headers, $message_body) = preg_split("/\r\n\r\n|\n\n|\r\r/", $response, 2);
$this->last_response_headers = $this->curlParseHeaders($message_headers);
return $message_body;
}
private function curlAppendQuery($url, $query)
{
if (empty($query)) return $url;
if (is_array($query)) return "$url?".http_build_query($query);
else return "$url?$query";
}
private function curlSetopts($ch, $method, $payload, $request_headers)
{
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_MAXREDIRS, 3);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_USERAGENT, 'ohShopify-php-api-client');
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt ($ch, CURLOPT_CUSTOMREQUEST, $method);
if (!empty($request_headers)) curl_setopt($ch, CURLOPT_HTTPHEADER, $request_headers);
if ($method != 'GET' && !empty($payload))
{
if (is_array($payload)) $payload = http_build_query($payload);
curl_setopt ($ch, CURLOPT_POSTFIELDS, $payload);
}
}
private function curlParseHeaders($message_headers)
{
$header_lines = preg_split("/\r\n|\n|\r/", $message_headers);
$headers = array();
list(, $headers['http_status_code'], $headers['http_status_message']) = explode(' ', trim(array_shift($header_lines)), 3);
foreach ($header_lines as $header_line)
{
list($name, $value) = explode(':', $header_line, 2);
$name = strtolower($name);
$headers[$name] = trim($value);
}
return $headers;
}
private function shopApiCallLimitParam($index)
{
if ($this->last_response_headers == null)
{
throw new \Exception('Cannot be called before an API call.');
}
$params = explode('/', $this->last_response_headers['http_x_shopify_shop_api_call_limit']);
return (int) $params[$index];
}
}
class ShopifyCurlException extends \Exception { }
class ShopifyApiException extends \Exception
{
protected $method;
protected $path;
protected $params;
protected $response_headers;
protected $response;
function __construct($method, $path, $params, $response_headers, $response)
{
$this->method = $method;
$this->path = $path;
$this->params = $params;
$this->response_headers = $response_headers;
$this->response = $response;
parent::__construct($response_headers['http_status_message'], $response_headers['http_status_code']);
}
function getMethod() { return $this->method; }
function getPath() { return $this->path; }
function getParams() { return $this->params; }
function getResponseHeaders() { return $this->response_headers; }
function getResponse() { return $this->response; }
}
<?php
namespace Library\Shopify;
class ShopifyClientPrivate {
public $shop_domain;
private $token;
private $api_key;
private $secret;
private $last_response_headers = null;
public function __construct($shop_domain, $token, $api_key, $secret) {
$this->name = "ShopifyClient";
$this->shop_domain = $shop_domain;
$this->token = $token;
$this->api_key = $api_key;
$this->secret = $secret;
}
// Get the URL required to request authorization
public function getAuthorizeUrl($scope, $redirect_url='') {
$url = "http://{$this->shop_domain}/admin/oauth/authorize?client_id={$this->api_key}&scope=" . urlencode($scope);
if ($redirect_url != '')
{
$url .= "&redirect_uri=" . urlencode($redirect_url);
}
return $url;
}
// Once the User has authorized the app, call this with the code to get the access token
public function getAccessToken($code) {
// POST to POST https://SHOP_NAME.myshopify.com/admin/oauth/access_token
$url = "https://{$this->shop_domain}/admin/oauth/access_token";
$payload = "client_id={$this->api_key}&client_secret={$this->secret}&code=$code";
$response = $this->curlHttpApiRequest('POST', $url, '', $payload, array());
$response = json_decode($response, true);
if (isset($response['access_token']))
return $response['access_token'];
return '';
}
public function callsMade()
{
return $this->shopApiCallLimitParam(0);
}
public function callLimit()
{
return $this->shopApiCallLimitParam(1);
}
public function callsLeft($response_headers)
{
return $this->callLimit() - $this->callsMade();
}
public function call($method, $path, $params=array())
{
$baseurl = "https://{$this->shop_domain}/";
$url = $baseurl.ltrim($path, '/');
//var_dump($url);
$query = in_array($method, array('GET','DELETE')) ? $params : array();
//echo '<br />'.$path;
$payload = in_array($method, array('POST','PUT')) ? stripslashes(json_encode($params)) : array();
$request_headers = in_array($method, array('GET','DELETE','POST','PUT')) ? array("Content-Type: application/json; charset=utf-8", 'Expect:') : array();
// add auth headers
//$request_headers[] = 'X-Shopify-Access-Token: ' . $this->token;
$response = $this->curlHttpApiRequest($method, $url, $query, $payload, $request_headers);
$response = json_decode($response, true);
return $response;
/*if (isset($response['errors']) or ($this->last_response_headers['http_status_code'] >= 400))
throw new ShopifyApiException($method, $path, $params, $this->last_response_headers, $response);
return (is_array($response) and (count($response) > 0)) ? array_shift($response) : $response;*/
}
private function curlHttpApiRequest($method, $url, $query='', $payload='', $request_headers=array()){
$url = $this->curlAppendQuery($url, $query);
$ch = curl_init( $url );
//curl_setopt( $ch, CURLOPT_HTTPHEADER, array("Content-Type: application/json; charset=utf-8", 'Expect:'));
# Return response instead of printing.
//curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
# Send request.
$this->curlSetopts($ch, $method, $payload, $request_headers);
$response = curl_exec($ch);
curl_close($ch);
# Print response.
return $response;
}
private function curlHttpApiRequest2($method, $url, $query='', $payload='', $request_headers=array())
{
$url = $this->curlAppendQuery($url, $query);
$ch = curl_init($url);
$this->curlSetopts($ch, $method, $payload, $request_headers);
$response = curl_exec($ch);
$errno = curl_errno($ch);
$error = curl_error($ch);
curl_close($ch);
/*if ($errno) throw new ShopifyCurlException($error, $errno);
list($message_headers, $message_body) = preg_split("/\r\n\r\n|\n\n|\r\r/", $response, 2);
$this->last_response_headers = $this->curlParseHeaders($message_headers);*/
return $message_body;
}
private function curlAppendQuery($url, $query)
{
if (empty($query)) return $url;
if (is_array($query)) return "$url?".http_build_query($query);
else return "$url?$query";
}
private function curlSetopts($ch, $method, $payload, $request_headers)
{
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_MAXREDIRS, 3);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
//curl_setopt($ch, CURLOPT_USERAGENT, 'ohShopify-php-api-client');
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt ($ch, CURLOPT_CUSTOMREQUEST, $method);
if (!empty($request_headers)) curl_setopt($ch, CURLOPT_HTTPHEADER, $request_headers);
if ($method != 'GET' && !empty($payload))
{
if (is_array($payload)) $payload = http_build_query($payload);
curl_setopt ($ch, CURLOPT_POSTFIELDS, $payload);
}
}
private function curlParseHeaders($message_headers)
{
$header_lines = preg_split("/\r\n|\n|\r/", $message_headers);
$headers = array();
list(, $headers['http_status_code'], $headers['http_status_message']) = explode(' ', trim(array_shift($header_lines)), 3);
foreach ($header_lines as $header_line)
{
list($name, $value) = explode(':', $header_line, 2);
$name = strtolower($name);
$headers[$name] = trim($value);
}
return $headers;
}
private function shopApiCallLimitParam($index)
{
if ($this->last_response_headers == null)
{
throw new Exception('Cannot be called before an API call.');
}
$params = explode('/', $this->last_response_headers['http_x_shopify_shop_api_call_limit']);
return (int) $params[$index];
}
}
/*
class ShopifyCurlException extends \Exception { }
class ShopifyApiException extends \Exception
{
protected $method;
protected $path;
protected $params;
protected $response_headers;
protected $response;
function __construct($method, $path, $params, $response_headers, $response)
{
$this->method = $method;
$this->path = $path;
$this->params = $params;
$this->response_headers = $response_headers;
$this->response = $response;
parent::__construct($response_headers['http_status_message'], $response_headers['http_status_code']);
}
function getMethod() { return $this->method; }
function getPath() { return $this->path; }
function getParams() { return $this->params; }
function getResponseHeaders() { return $this->response_headers; }
function getResponse() { return $this->response; }
}*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment