| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189 |
- <?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.
- */
- namespace EasyWeChat\Payment\Notify;
- use Closure;
- use EasyWeChat\Kernel\Exceptions\Exception;
- use EasyWeChat\Kernel\Support;
- use EasyWeChat\Kernel\Support\XML;
- use EasyWeChat\Payment\Kernel\Exceptions\InvalidSignException;
- use Symfony\Component\HttpFoundation\Response;
- abstract class Handler
- {
- public const SUCCESS = 'SUCCESS';
- public const FAIL = 'FAIL';
- /**
- * @var \EasyWeChat\Payment\Application
- */
- protected $app;
- /**
- * @var array
- */
- protected $message;
- /**
- * @var string|null
- */
- protected $fail;
- /**
- * @var array
- */
- protected $attributes = [];
- /**
- * Check sign.
- * If failed, throws an exception.
- *
- * @var bool
- */
- protected $check = true;
- /**
- * Respond with sign.
- *
- * @var bool
- */
- protected $sign = false;
- /**
- * @param \EasyWeChat\Payment\Application $app
- */
- public function __construct($app)
- {
- $this->app = $app;
- }
- /**
- * Handle incoming notify.
- *
- * @return \Symfony\Component\HttpFoundation\Response
- */
- abstract public function handle(Closure $closure);
- public function fail(string $message)
- {
- $this->fail = $message;
- }
- /**
- * @return $this
- */
- public function respondWith(array $attributes, bool $sign = false)
- {
- $this->attributes = $attributes;
- $this->sign = $sign;
- return $this;
- }
- /**
- * Build xml and return the response to WeChat.
- *
- * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
- */
- public function toResponse(): Response
- {
- $base = [
- 'return_code' => is_null($this->fail) ? static::SUCCESS : static::FAIL,
- 'return_msg' => $this->fail,
- ];
- $attributes = array_merge($base, $this->attributes);
- if ($this->sign) {
- $attributes['sign'] = Support\generate_sign($attributes, $this->app->getKey());
- }
- return new Response(XML::build($attributes));
- }
- /**
- * Return the notify message from request.
- *
- * @throws \EasyWeChat\Kernel\Exceptions\Exception
- */
- public function getMessage(): array
- {
- if (!empty($this->message)) {
- return $this->message;
- }
- try {
- $message = XML::parse(strval($this->app['request']->getContent()));
- } catch (\Throwable $e) {
- throw new Exception('Invalid request XML: '.$e->getMessage(), 400);
- }
- if (!is_array($message) || empty($message)) {
- throw new Exception('Invalid request XML.', 400);
- }
- if ($this->check) {
- $this->validate($message);
- }
- return $this->message = $message;
- }
- /**
- * Decrypt message.
- *
- * @return string|null
- *
- * @throws \EasyWeChat\Kernel\Exceptions\Exception
- */
- public function decryptMessage(string $key)
- {
- $message = $this->getMessage();
- if (empty($message[$key])) {
- return null;
- }
- return Support\AES::decrypt(
- base64_decode($message[$key], true),
- md5($this->app['config']->key),
- '',
- OPENSSL_RAW_DATA,
- 'AES-256-ECB'
- );
- }
- /**
- * Validate the request params.
- *
- * @throws \EasyWeChat\Payment\Kernel\Exceptions\InvalidSignException
- * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
- */
- protected function validate(array $message)
- {
- $sign = $message['sign'];
- unset($message['sign']);
- if (Support\generate_sign($message, $this->app->getKey()) !== $sign) {
- throw new InvalidSignException();
- }
- }
- /**
- * @param mixed $result
- */
- protected function strict($result)
- {
- if (true !== $result && is_null($this->fail)) {
- $this->fail(strval($result));
- }
- }
- }
|