Commit 14e33da5 authored by 王源's avatar 王源
Browse files

[功能]添加shopify相关公共库文件

parent cb8c5d2e
Loading
Loading
Loading
Loading
+73 −0
Original line number Original line Diff line number Diff line
<?php
/**
 * Created by PhpStorm.
 * User: Zero
 * Date: 2020/8/18
 * Time: 8:13
 */

namespace Meibuyu\Micro\Shopify;

use Meibuyu\Micro\Shopify\lib\AbstractShopify;
use Meibuyu\Micro\Shopify\lib\Webhook;

/**
 * Class ShopifyApp
 * @package Meibuyu\Shopify
 *
 * @property-read Webhook $Webhook
 */
class ShopifyApp
{

    protected $resources = [
        'Webhook',
    ];

    public $config = [];

    public $defaultApiVersion = '2020-07';

    public $timeAllowedForEachApiCall = .5;

    /**
     * ShopifyApp constructor.
     * @param array $config
     */
    public function __construct($config)
    {
        $this->config = [
            'api_version' => $this->defaultApiVersion
        ];
        foreach ($config as $key => $value) {
            $this->config[$key] = $value;
        }
        if (isset($config['shop_url'])) {
            $this->setApiUrl();
        }
    }

    /**
     * 返回AbstractShopify实例
     * @param string $className 实现的类名
     * @return AbstractShopify
     * @throws \Exception
     */
    public function __get($className)
    {
        if (!in_array($className, $this->resources)) {
            throw new \Exception("未知方法 $className");
        }
        $resourceClassName = __NAMESPACE__ . "\\lib\\$className";
        return new $resourceClassName($this->config);
    }

    public function setApiUrl()
    {
        $shopUrl = $this->config['shop_url'];
        $shopUrl = preg_replace('#^https?://|/$#', '', $shopUrl);
        $apiVersion = $this->config['api_version'];
        $this->config['api_url'] = "https://$shopUrl/admin/api/$apiVersion/";
    }

}
+35 −0
Original line number Original line Diff line number Diff line
<?php
/**
 * Created by PhpStorm.
 * User: Zero
 * Date: 2020/8/19
 * Time: 9:25
 */

namespace Meibuyu\Micro\Shopify;

use Hyperf\Contract\ContainerInterface;

class ShopifyFactory
{

    /**
     * @var ContainerInterface
     */
    private $container;

    public function __construct(ContainerInterface $container)
    {
        $this->container = $container;
    }

    public function create(array $config = []): ShopifyApp
    {
        if (method_exists($this->container, 'make')) {
            // Create by DI for AOP.
            return $this->container->make(ShopifyApp::class, ['config' => $config]);
        }
        return new ShopifyApp($config);
    }

}
+256 −0
Original line number Original line Diff line number Diff line
<?php
/**
 * Created by PhpStorm.
 * User: Zero
 * Date: 2020/8/18
 * Time: 8:18
 */

namespace Meibuyu\Micro\Shopify\lib;

use Meibuyu\Micro\Tools\HttpRequestJson;
use Psr\Http\Message\ResponseInterface;

abstract class AbstractShopify
{

    protected $httpHeaders = [];

    protected $resourceUrl;

    protected $resourceKey;
    protected $pluralizeKey;

    /**
     * 无count方法
     * @var boolean
     */
    public $countEnabled = true;

    /**
     * List of custom GET / POST / PUT / DELETE actions
     *
     * Custom actions can be used without calling the get(), post(), put(), delete() methods directly
     * @example: ['enable', 'disable', 'remove','default' => 'makeDefault']
     * Methods can be called like enable(), disable(), remove(), makeDefault() etc.
     * If any array item has an associative key => value pair, value will be considered as the method name
     * and key will be the associated path to be used with the action.
     *
     * @var array $customGetActions
     * @var array $customPostActions
     * @var array $customPutActions
     * @var array $customDeleteActions
     */
    protected $customGetActions = [];
    protected $customPostActions = [];
    protected $customPutActions = [];
    protected $customDeleteActions = [];

    /**
     * AbstractShopify constructor.
     * @param $config
     * @throws \Exception
     */
    public function __construct($config)
    {
        $this->pluralizeKey = $this->resourceKey . 's';
        $this->resourceUrl = $config['api_url'] . $this->pluralizeKey;

        if (isset($config['api_password'])) {
            $this->httpHeaders['X-Shopify-Access-Token'] = $config['api_password'];
        } elseif (!isset($config['api_password'])) {
            throw new \Exception("请设置api_password值");
        }
    }

    /**
     * 调用自定义方法
     * @param $name
     * @param $arguments
     * @return mixed
     * @throws \Exception
     */
    public function __call($name, $arguments)
    {
        $actionMaps = array(
            'post' => 'customPostActions',
            'put' => 'customPutActions',
            'get' => 'customGetActions',
            'delete' => 'customDeleteActions',
        );
        //Get the array key for the action in the actions array
        foreach ($actionMaps as $httpMethod => $actionArrayKey) {
            $actionKey = array_search($name, $this->$actionArrayKey);
            if ($actionKey !== false) break;
        }
        if ($actionKey === false) {
            throw new \Exception("No action named $name is defined for " . $this->getResourceName());
        }
        //If any associative key is given to the action, then it will be considered as the method name,
        //otherwise the action name will be the method name
        $customAction = !is_numeric($actionKey) ? $actionKey : $name;
        //Get the first argument if provided with the method call
        $methodArgument = !empty($arguments) ? $arguments[0] : [];
        //Url parameters
        $urlParams = [];
        //Data body
        $dataArray = [];
        //Consider the argument as url parameters for get and delete request
        //and data array for post and put request
        if ($httpMethod == 'post' || $httpMethod == 'put') {
            $dataArray = $methodArgument;
        } else {
            $urlParams = $methodArgument;
        }
        $url = $this->generateUrl($urlParams, null, $customAction);
        if ($httpMethod == 'post' || $httpMethod == 'put') {
            return $this->$httpMethod($dataArray, $url, false);
        } else {
            return $this->$httpMethod($dataArray, $url);
        }
    }

    private function getResourceName()
    {
        return substr(get_called_class(), strrpos(get_called_class(), '\\') + 1);
    }

    public function generateUrl($urlParams = [], $id = null, $customAction = null)
    {
        return $this->resourceUrl . ($id ? "/$id" : '') . ($customAction ? "/$customAction" : '') . '.json' . (!empty($urlParams) ? '?' . http_build_query($urlParams) : '');
    }

    /**
     * @param array $urlParams
     * @param null $url
     * @param null $dataKey
     * @return mixed
     * @throws \Exception
     */
    public function get($urlParams = [], $url = null, $dataKey = null)
    {
        if (!$url) $url = $this->generateUrl($urlParams);

        $response = HttpRequestJson::get($url, $this->httpHeaders);

        if (!$dataKey) $dataKey = $this->pluralizeKey;
        return $this->processResponse($response, $dataKey);
    }

    /**
     * 根据id获取一条数据
     * @param $id
     * @param array $urlParams
     * @return mixed
     * @throws \Exception
     */
    public function show($id, $urlParams = [])
    {
        $url = $this->generateUrl($urlParams, $id);
        $response = HttpRequestJson::get($url, $this->httpHeaders);
        return $this->processResponse($response, $this->resourceKey);
    }

    /**
     * 获取数量
     * @param array $urlParams
     * @return mixed
     * @throws \Exception
     */
    public function count($urlParams = [])
    {
        if (!$this->countEnabled) {
            throw new \Exception("当前类{$this->getResourceName()}不支持count()方法");
        }
        $url = $this->generateUrl($urlParams, null, 'count');
        return $this->get([], $url, 'count');
    }

    /**
     * @param $dataArray
     * @param null $url
     * @param bool $wrapData
     * @return mixed
     * @throws \Exception
     */
    public function post($dataArray, $url = null, $wrapData = true)
    {
        if (!$url) $url = $this->generateUrl();
        if ($wrapData && !empty($dataArray)) $dataArray = $this->wrapData($dataArray);
        $response = HttpRequestJson::post($url, $dataArray, $this->httpHeaders);
        return $this->processResponse($response, $this->resourceKey);
    }

    /**
     * @param int|string $id
     * @param $dataArray
     * @param null $url
     * @param bool $wrapData
     * @return mixed
     * @throws \Exception
     */
    public function put($id, $dataArray, $url = null, $wrapData = true)
    {
        if (!$url) $url = $this->generateUrl([], $id);
        if ($wrapData && !empty($dataArray)) $dataArray = $this->wrapData($dataArray);
        $response = HttpRequestJson::put($url, $dataArray, $this->httpHeaders);
        return $this->processResponse($response, $this->resourceKey);
    }

    /**
     * @param int|string $id
     * @param array $urlParams
     * @param null $url
     * @return mixed
     * @throws \Exception
     */
    public function delete($id, $urlParams = [], $url = null)
    {
        if (!$url) $url = $this->generateUrl($urlParams, $id);
        $response = HttpRequestJson::delete($url, $this->httpHeaders);
        return $this->processResponse($response);
    }

    protected function wrapData($dataArray, $dataKey = null)
    {
        if (!$dataKey) $dataKey = $this->resourceKey;
        return array($dataKey => $dataArray);
    }

    protected function castString($array)
    {
        if (!is_array($array)) return (string)$array;
        $string = '';
        $i = 0;
        foreach ($array as $key => $val) {
            $string .= ($i === $key ? '' : "$key - ") . $this->castString($val) . ', ';
            $i++;
        }
        $string = rtrim($string, ', ');
        return $string;
    }

    /**
     * 处理响应
     * @param ResponseInterface $response
     * @param null $dataKey
     * @return mixed
     * @throws \Exception
     */
    public function processResponse($response, $dataKey = null)
    {
        $httpCode = $response->getStatusCode();
        $content = $response->getBody()->getContents();
        $content = json_decode($content, true);

        if (isset($content['errors'])) {
            throw new \Exception($this->castString($content['errors']), $httpCode);
        }
        if ($dataKey && isset($content[$dataKey])) {
            return $content[$dataKey];
        } else {
            return $content;
        }
    }

}
+16 −0
Original line number Original line Diff line number Diff line
<?php
/**
 * Created by PhpStorm.
 * User: Zero
 * Date: 2020/8/18
 * Time: 8:13
 */

namespace Meibuyu\Micro\Shopify\lib;

class Webhook extends AbstractShopify
{

    protected $resourceKey = 'webhook';

}
+72 −0
Original line number Original line Diff line number Diff line
<?php
/**
 * Created by PhpStorm.
 * User: Zero
 * Date: 2020/8/19
 * Time: 9:06
 */

namespace Meibuyu\Micro\Tools;

use GuzzleHttp\Client;
use Psr\Http\Message\ResponseInterface;

/**
 * json格式请求(非协程)
 * Class HttpRequestJson
 * @package Meibuyu\Micro\Tools
 */
class HttpRequestJson
{

    /**
     * get请求
     * @param $url
     * @param array $httpHeaders
     * @return ResponseInterface
     */
    public static function get($url, $httpHeaders = [])
    {
        $client = new Client();
        return $client->get($url, ['headers' => $httpHeaders]);
    }

    /**
     * post请求
     * @param $url
     * @param $dataArray
     * @param array $httpHeaders
     * @return ResponseInterface
     */
    public static function post($url, $dataArray, $httpHeaders = [])
    {
        $client = new Client();
        return $client->post($url, ['headers' => $httpHeaders, 'json' => $dataArray]);
    }

    /**
     * put请求
     * @param $url
     * @param $dataArray
     * @param array $httpHeaders
     * @return ResponseInterface
     */
    public static function put($url, $dataArray, $httpHeaders = [])
    {
        $client = new Client();
        return $client->put($url, ['headers' => $httpHeaders, 'json' => $dataArray]);
    }

    /**
     * delete请求
     * @param $url
     * @param array $httpHeaders
     * @return ResponseInterface
     */
    public static function delete($url, $httpHeaders = [])
    {
        $client = new Client();
        return $client->delete($url, ['headers' => $httpHeaders]);
    }

}