* * This source file is subject to the MIT license that is bundled * with this source code in the file LICENSE. */ namespace EasyWeChat\Payment\Kernel; use EasyWeChat\Kernel\Support; use EasyWeChat\Kernel\Traits\HasHttpRequests; use EasyWeChat\Payment\Application; use GuzzleHttp\MessageFormatter; use GuzzleHttp\Middleware; use Psr\Http\Message\ResponseInterface; /** * Class BaseClient. * * @author overtrue */ class BaseClient { use HasHttpRequests { request as performRequest; } /** * @var \EasyWeChat\Payment\Application */ protected $app; /** * Constructor. */ public function __construct(Application $app) { $this->app = $app; $this->setHttpClient($this->app['http_client']); } /** * Extra request params. * * @return array */ protected function prepends() { return []; } /** * Make a API request. * * @param string $method * @param bool $returnResponse * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException * @throws \GuzzleHttp\Exception\GuzzleException */ protected function request(string $endpoint, array $params = [], $method = 'post', array $options = [], $returnResponse = false) { $base = [ 'mch_id' => $this->app['config']['mch_id'], 'nonce_str' => uniqid(), 'sub_mch_id' => $this->app['config']['sub_mch_id'], 'sub_appid' => $this->app['config']['sub_appid'], ]; $params = array_filter(array_merge($base, $this->prepends(), $params), 'strlen'); $secretKey = $this->app->getKey($endpoint); $encryptMethod = Support\get_encrypt_method(Support\Arr::get($params, 'sign_type', 'MD5'), $secretKey); $params['sign'] = Support\generate_sign($params, $secretKey, $encryptMethod); $options = array_merge([ 'body' => Support\XML::build($params), ], $options); $this->pushMiddleware($this->logMiddleware(), 'log'); $response = $this->performRequest($endpoint, $method, $options); return $returnResponse ? $response : $this->castResponseToType($response, $this->app->config->get('response_type')); } /** * Log the request. * * @return \Closure */ protected function logMiddleware() { $formatter = new MessageFormatter($this->app['config']['http.log_template'] ?? MessageFormatter::DEBUG); return Middleware::log($this->app['logger'], $formatter); } /** * Make a request and return raw response. * * @param string $method * * @return ResponseInterface * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException * @throws \GuzzleHttp\Exception\GuzzleException */ protected function requestRaw(string $endpoint, array $params = [], $method = 'post', array $options = []) { /** @var ResponseInterface $response */ $response = $this->request($endpoint, $params, $method, $options, true); return $response; } /** * Make a request and return an array. * * @param string $method * * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException * @throws \GuzzleHttp\Exception\GuzzleException */ protected function requestArray(string $endpoint, array $params = [], $method = 'post', array $options = []): array { $response = $this->requestRaw($endpoint, $params, $method, $options); return $this->castResponseToType($response, 'array'); } /** * Request with SSL. * * @param string $endpoint * @param string $method * * @return \Psr\Http\Message\ResponseInterface|\EasyWeChat\Kernel\Support\Collection|array|object|string * * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException * @throws \GuzzleHttp\Exception\GuzzleException */ protected function safeRequest($endpoint, array $params, $method = 'post', array $options = []) { $options = array_merge([ 'cert' => $this->app['config']->get('cert_path'), 'ssl_key' => $this->app['config']->get('key_path'), ], $options); return $this->request($endpoint, $params, $method, $options); } /** * Wrapping an API endpoint. */ protected function wrap(string $endpoint): string { return $this->app->inSandbox() ? "sandboxnew/{$endpoint}" : $endpoint; } }