GET
GET = 'get'
Class AbstractAPI.
$http : \EasyWeChat\Core\Http
Http instance.
$accessToken : \EasyWeChat\Core\AccessToken
The request token.
__construct(\EasyWeChat\Core\AccessToken  $accessToken) 
                Constructor.
| \EasyWeChat\Core\AccessToken | $accessToken | 
getHttp() : \EasyWeChat\Core\Http
Return the http instance.
setHttp(\EasyWeChat\Core\Http  $http) : $this
                Set the http instance.
| \EasyWeChat\Core\Http | $http | 
getAccessToken() : \EasyWeChat\Core\AccessToken
Return the current accessToken.
setAccessToken(\EasyWeChat\Core\AccessToken  $accessToken) : $this
                Set the request token.
| \EasyWeChat\Core\AccessToken | $accessToken | 
parseJSON(string $method, array $args) : \EasyWeChat\Support\Collection
Parse JSON from response and check error.
| string | $method | |
| array | $args | 
| null
<?php
/*
 * This file is part of the overtrue/wechat.
 *
 * (c) overtrue <i@overtrue.me>
 *
 * This source file is subject to the MIT license that is bundled
 * with this source code in the file LICENSE.
 */
/**
 * AbstractAPI.php.
 *
 * This file is part of the wechat-components.
 *
 * (c) overtrue <i@overtrue.me>
 *
 * This source file is subject to the MIT license that is bundled
 * with this source code in the file LICENSE.
 */
namespace EasyWeChat\Core;
use EasyWeChat\Core\Exceptions\HttpException;
use EasyWeChat\Support\Collection;
use EasyWeChat\Support\Log;
use GuzzleHttp\Middleware;
use GuzzleHttp\Psr7\Uri;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
/**
 * Class AbstractAPI.
 */
abstract class AbstractAPI
{
    /**
     * Http instance.
     *
     * @var \EasyWeChat\Core\Http
     */
    protected $http;
    /**
     * The request token.
     *
     * @var \EasyWeChat\Core\AccessToken
     */
    protected $accessToken;
    const GET = 'get';
    const POST = 'post';
    const JSON = 'json';
    /**
     * @var int
     */
    protected static $maxRetries = 2;
    /**
     * Constructor.
     *
     * @param \EasyWeChat\Core\AccessToken $accessToken
     */
    public function __construct(AccessToken $accessToken)
    {
        $this->setAccessToken($accessToken);
    }
    /**
     * Return the http instance.
     *
     * @return \EasyWeChat\Core\Http
     */
    public function getHttp()
    {
        if (is_null($this->http)) {
            $this->http = new Http();
        }
        if (0 === count($this->http->getMiddlewares())) {
            $this->registerHttpMiddlewares();
        }
        return $this->http;
    }
    /**
     * Set the http instance.
     *
     * @param \EasyWeChat\Core\Http $http
     *
     * @return $this
     */
    public function setHttp(Http $http)
    {
        $this->http = $http;
        return $this;
    }
    /**
     * Return the current accessToken.
     *
     * @return \EasyWeChat\Core\AccessToken
     */
    public function getAccessToken()
    {
        return $this->accessToken;
    }
    /**
     * Set the request token.
     *
     * @param \EasyWeChat\Core\AccessToken $accessToken
     *
     * @return $this
     */
    public function setAccessToken(AccessToken $accessToken)
    {
        $this->accessToken = $accessToken;
        return $this;
    }
    /**
     * @param int $retries
     */
    public static function maxRetries($retries)
    {
        self::$maxRetries = abs($retries);
    }
    /**
     * Parse JSON from response and check error.
     *
     * @param string $method
     * @param array  $args
     *
     * @return \EasyWeChat\Support\Collection | null
     * @throws \EasyWeChat\Core\Exceptions\HttpException
     */
    public function parseJSON($method, array $args)
    {
        $http = $this->getHttp();
        $contents = $http->parseJSON(call_user_func_array([$http, $method], $args));
        if (empty($contents)) {
            return null;
        }
        $this->checkAndThrow($contents);
        return new Collection($contents);
    }
    /**
     * Register Guzzle middlewares.
     */
    protected function registerHttpMiddlewares()
    {
        // log
        $this->http->addMiddleware($this->logMiddleware());
        // retry
        $this->http->addMiddleware($this->retryMiddleware());
        // access token
        $this->http->addMiddleware($this->accessTokenMiddleware());
    }
    /**
     * Attache access token to request query.
     *
     * @return \Closure
     */
    protected function accessTokenMiddleware()
    {
        return function (callable $handler) {
            return function (RequestInterface $request, array $options) use ($handler) {
                if (!$this->accessToken) {
                    return $handler($request, $options);
                }
                $field = $this->accessToken->getQueryName();
                $token = $this->accessToken->getToken();
                $request = $request->withUri(Uri::withQueryValue($request->getUri(), $field, $token));
                return $handler($request, $options);
            };
        };
    }
    /**
     * Log the request.
     *
     * @return \Closure
     */
    protected function logMiddleware()
    {
        return Middleware::tap(function (RequestInterface $request, $options) {
            Log::debug("Request: {$request->getMethod()} {$request->getUri()} ".json_encode($options));
            Log::debug('Request headers:'.json_encode($request->getHeaders()));
        });
    }
    /**
     * Return retry middleware.
     *
     * @return \Closure
     */
    protected function retryMiddleware()
    {
        return Middleware::retry(function (
                                          $retries,
                                          RequestInterface $request,
                                          ResponseInterface $response = null
                                       ) {
            // Limit the number of retries to 2
            if ($retries <= self::$maxRetries && $response && $body = $response->getBody()) {
                // Retry on server errors
                if (false !== stripos($body, 'errcode') && (false !== stripos($body, '40001') || false !== stripos($body, '42001'))) {
                    $field = $this->accessToken->getQueryName();
                    $token = $this->accessToken->getToken(true);
                    $request = $request->withUri($newUri = Uri::withQueryValue($request->getUri(), $field, $token));
                    Log::debug("Retry with Request Token: {$token}");
                    Log::debug("Retry with Request Uri: {$newUri}");
                    return true;
                }
            }
            return false;
        });
    }
    /**
     * Check the array data errors, and Throw exception when the contents contains error.
     *
     * @param array $contents
     *
     * @throws \EasyWeChat\Core\Exceptions\HttpException
     */
    protected function checkAndThrow(array $contents)
    {
        if (isset($contents['errcode']) && 0 !== $contents['errcode']) {
            if (empty($contents['errmsg'])) {
                $contents['errmsg'] = 'Unknown';
            }
            throw new HttpException($contents['errmsg'], $contents['errcode']);
        }
    }
}