diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php index be2a4eca1..249d98718 100644 --- a/vendor/composer/autoload_classmap.php +++ b/vendor/composer/autoload_classmap.php @@ -296,6 +296,7 @@ return array( 'think\\admin\\command\\Database' => $vendorDir . '/zoujingli/think-library/src/command/Database.php', 'think\\admin\\command\\Install' => $vendorDir . '/zoujingli/think-library/src/command/Install.php', 'think\\admin\\command\\Queue' => $vendorDir . '/zoujingli/think-library/src/command/Queue.php', + 'think\\admin\\command\\Replace' => $vendorDir . '/zoujingli/think-library/src/command/Replace.php', 'think\\admin\\command\\Version' => $vendorDir . '/zoujingli/think-library/src/command/Version.php', 'think\\admin\\extend\\CodeExtend' => $vendorDir . '/zoujingli/think-library/src/extend/CodeExtend.php', 'think\\admin\\extend\\DataExtend' => $vendorDir . '/zoujingli/think-library/src/extend/DataExtend.php', diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php index 6e286d15c..a9b87f1a7 100644 --- a/vendor/composer/autoload_static.php +++ b/vendor/composer/autoload_static.php @@ -424,6 +424,7 @@ class ComposerStaticInit4f89fd0e0503ccf740f2fa5757825d7b 'think\\admin\\command\\Database' => __DIR__ . '/..' . '/zoujingli/think-library/src/command/Database.php', 'think\\admin\\command\\Install' => __DIR__ . '/..' . '/zoujingli/think-library/src/command/Install.php', 'think\\admin\\command\\Queue' => __DIR__ . '/..' . '/zoujingli/think-library/src/command/Queue.php', + 'think\\admin\\command\\Replace' => __DIR__ . '/..' . '/zoujingli/think-library/src/command/Replace.php', 'think\\admin\\command\\Version' => __DIR__ . '/..' . '/zoujingli/think-library/src/command/Version.php', 'think\\admin\\extend\\CodeExtend' => __DIR__ . '/..' . '/zoujingli/think-library/src/extend/CodeExtend.php', 'think\\admin\\extend\\DataExtend' => __DIR__ . '/..' . '/zoujingli/think-library/src/extend/DataExtend.php', diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index 5f4bcc518..9c0351c73 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -937,12 +937,12 @@ "source": { "type": "git", "url": "https://github.com/zoujingli/ThinkLibrary.git", - "reference": "f8a4e65cf6b57531c8536462b30892eae49c7809" + "reference": "e1cc4dcb049fc1cedbb99807d235e5bda3dcdf71" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zoujingli/ThinkLibrary/zipball/f8a4e65cf6b57531c8536462b30892eae49c7809", - "reference": "f8a4e65cf6b57531c8536462b30892eae49c7809", + "url": "https://api.github.com/repos/zoujingli/ThinkLibrary/zipball/e1cc4dcb049fc1cedbb99807d235e5bda3dcdf71", + "reference": "e1cc4dcb049fc1cedbb99807d235e5bda3dcdf71", "shasum": "", "mirrors": [ { @@ -959,7 +959,7 @@ "ext-mbstring": "*", "topthink/framework": "^6.0" }, - "time": "2020-12-18T05:04:10+00:00", + "time": "2020-12-26T08:29:41+00:00", "type": "library", "extra": { "think": { @@ -992,17 +992,17 @@ }, { "name": "zoujingli/wechat-developer", - "version": "v1.2.26", - "version_normalized": "1.2.26.0", + "version": "v1.2.27", + "version_normalized": "1.2.27.0", "source": { "type": "git", "url": "https://github.com/zoujingli/WeChatDeveloper.git", - "reference": "5ecafcd810627cd9217c3d7f18c7026612418278" + "reference": "94de6626f1c9e3d12f16640c30fb9319b37ff34c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zoujingli/WeChatDeveloper/zipball/5ecafcd810627cd9217c3d7f18c7026612418278", - "reference": "5ecafcd810627cd9217c3d7f18c7026612418278", + "url": "https://api.github.com/repos/zoujingli/WeChatDeveloper/zipball/94de6626f1c9e3d12f16640c30fb9319b37ff34c", + "reference": "94de6626f1c9e3d12f16640c30fb9319b37ff34c", "shasum": "", "mirrors": [ { @@ -1022,7 +1022,7 @@ "ext-xml": "*", "php": ">=5.4" }, - "time": "2020-09-13T06:01:11+00:00", + "time": "2020-12-24T09:44:04+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -1056,10 +1056,6 @@ "wechat", "wechatpay", "wepay" - ], - "support": { - "issues": "https://github.com/zoujingli/WeChatDeveloper/issues", - "source": "https://github.com/zoujingli/WeChatDeveloper/tree/v1.2.26" - } + ] } ] diff --git a/vendor/services.php b/vendor/services.php index 76ae7cb3d..e65841a8e 100644 --- a/vendor/services.php +++ b/vendor/services.php @@ -1,5 +1,5 @@ 'think\\admin\\Library', diff --git a/vendor/zoujingli/think-library/src/Library.php b/vendor/zoujingli/think-library/src/Library.php index fb9ca5bef..eefb76cc1 100644 --- a/vendor/zoujingli/think-library/src/Library.php +++ b/vendor/zoujingli/think-library/src/Library.php @@ -18,11 +18,12 @@ namespace think\admin; use think\admin\command\Database; use think\admin\command\Install; use think\admin\command\Queue; +use think\admin\command\Replace; use think\admin\command\Version; +use think\admin\multiple\BuildUrl; use think\admin\multiple\command\Build; use think\admin\multiple\command\Clear; use think\admin\multiple\Multiple; -use think\admin\multiple\BuildUrl; use think\admin\service\AdminService; use think\admin\service\SystemService; use think\middleware\LoadLangPack; @@ -41,7 +42,7 @@ class Library extends Service /** * 版本号 */ - const VERSION = '6.0.22'; + const VERSION = '6.0.23'; /** * 启动服务 @@ -62,7 +63,7 @@ class Library extends Service // 替换 ThinkPHP 指令 $this->commands(['build' => Build::class, 'clear' => Clear::class]); // 注册 ThinkAdmin 指令 - $this->commands([Queue::class, Install::class, Version::class, Database::class]); + $this->commands([Queue::class, Install::class, Version::class, Database::class, Replace::class]); // 动态应用运行参数 SystemService::instance()->bindRuntime(); } diff --git a/vendor/zoujingli/think-library/src/command/Replace.php b/vendor/zoujingli/think-library/src/command/Replace.php new file mode 100644 index 000000000..82ff478c4 --- /dev/null +++ b/vendor/zoujingli/think-library/src/command/Replace.php @@ -0,0 +1,89 @@ +setName('xadmin:replace'); + $this->addArgument('search', Argument::OPTIONAL, '查找替换的字符内容', ''); + $this->addArgument('replace', Argument::OPTIONAL, '目标替换的字符内容', ''); + $this->setDescription('Database Character Field Replace for ThinkAdmin'); + } + + /** + * 执行指令 + * @param Input $input + * @param Output $output + * @throws \think\admin\Exception + * @throws \think\db\exception\DbException + */ + protected function execute(Input $input, Output $output) + { + $search = $input->getArgument('search'); + $repalce = $input->getArgument('replace'); + if ($search === '') $this->queue->error('查找替换字符内容不能为空!'); + if ($repalce === '') $this->queue->error('目标替换字符内容不能为空!'); + + [$count, $used] = [count($tables = $this->getTables()), 0]; + foreach ($tables as $table) { + $data = []; + $this->queue->message($count, ++$used, sprintf("准备替换数据表 %s", Str::studly($table))); + foreach ($this->app->db->table($table)->getFields() as $field => $attrs) { + if (preg_match('/char|text/', $attrs['type'])) { + $data[$field] = $this->app->db->raw(sprintf('REPLACE(`%s`,"%s","%s")', $field, $search, $repalce)); + } + } + if (count($data) > 0) { + if ($this->app->db->table($table)->where('1=1')->update($data) !== false) { + $this->queue->message($count, $used, sprintf("成功替换数据表 %s", Str::studly($table)), 1); + } else { + $this->queue->message($count, $used, sprintf("失败替换数据表 %s", Str::studly($table)), 1); + } + } else { + $this->queue->message($count, $used, sprintf("无需替换数据表 %s", Str::studly($table)), 1); + } + } + $this->queue->success('批量替换成功'); + } + + /** + * 获取数据库的数据表 + * @return array + */ + protected function getTables(): array + { + $tables = []; + foreach ($this->app->db->query("show tables") as $item) { + $tables = array_merge($tables, array_values($item)); + } + return $tables; + } +} \ No newline at end of file diff --git a/vendor/zoujingli/wechat-developer/We.php b/vendor/zoujingli/wechat-developer/We.php index f582eb61b..1202b6d85 100644 --- a/vendor/zoujingli/wechat-developer/We.php +++ b/vendor/zoujingli/wechat-developer/We.php @@ -28,6 +28,7 @@ use WeChat\Exceptions\InvalidInstanceException; * @method \AliPay\Bill AliPayBill($options) static 支付宝电子面单下载 * @method \AliPay\Pos AliPayPos($options) static 支付宝刷卡支付 * @method \AliPay\Scan AliPayScan($options) static 支付宝扫码支付 + * @method \AliPay\Trade AliPayTrade($options) static 支付宝标准接口 * @method \AliPay\Transfer AliPayTransfer($options) static 支付宝转账到账户 * @method \AliPay\Wap AliPayWap($options) static 支付宝手机网站支付 * @method \AliPay\Web AliPayWeb($options) static 支付宝网站支付 @@ -86,7 +87,7 @@ class We * 定义当前版本 * @var string */ - const VERSION = '1.2.26'; + const VERSION = '1.2.27'; /** * 静态配置 diff --git a/vendor/zoujingli/wechat-developer/WeChat/Contracts/BasicWeChat.php b/vendor/zoujingli/wechat-developer/WeChat/Contracts/BasicWeChat.php index 6a3b5df30..eec7c6a81 100644 --- a/vendor/zoujingli/wechat-developer/WeChat/Contracts/BasicWeChat.php +++ b/vendor/zoujingli/wechat-developer/WeChat/Contracts/BasicWeChat.php @@ -128,21 +128,21 @@ class BasicWeChat /** * 设置外部接口 AccessToken - * @param string $access_token + * @param string $accessToken * @throws \WeChat\Exceptions\LocalCacheException * @author 高一平 * - * 当用户使用自己的缓存驱动时,直接实例化对象后可直接设置 AccessToekn + * 当用户使用自己的缓存驱动时,直接实例化对象后可直接设置 AccessToken * - 多用于分布式项目时保持 AccessToken 统一 - * - 使用此方法后就由用户来保证传入的 AccessToekn 为有效 AccessToekn + * - 使用此方法后就由用户来保证传入的 AccessToken 为有效 AccessToken */ - public function setAccessToken($access_token) + public function setAccessToken($accessToken) { - if (!is_string($access_token)) { + if (!is_string($accessToken)) { throw new InvalidArgumentException("Invalid AccessToken type, need string."); } $cache = $this->config->get('appid') . '_access_token'; - Tools::setCache($cache, $this->access_token = $access_token); + Tools::setCache($cache, $this->access_token = $accessToken); } /** @@ -169,8 +169,7 @@ class BasicWeChat } catch (InvalidResponseException $exception) { if (isset($this->currentMethod['method']) && empty($this->isTry)) { if (in_array($exception->getCode(), ['40014', '40001', '41001', '42001'])) { - $this->delAccessToken(); - $this->isTry = true; + [$this->delAccessToken(), $this->isTry = true]; return call_user_func_array([$this, $this->currentMethod['method']], $this->currentMethod['arguments']); } } diff --git a/vendor/zoujingli/wechat-developer/WeChat/Contracts/Tools.php b/vendor/zoujingli/wechat-developer/WeChat/Contracts/Tools.php index 69d7c4efb..90b4a4333 100644 --- a/vendor/zoujingli/wechat-developer/WeChat/Contracts/Tools.php +++ b/vendor/zoujingli/wechat-developer/WeChat/Contracts/Tools.php @@ -426,7 +426,7 @@ class Tools return call_user_func_array(self::$cache_callable['get'], func_get_args()); } $file = self::_getCacheName($name); - if (file_exists($file) && ($content = file_get_contents($file))) { + if (file_exists($file) && is_file($file) && ($content = file_get_contents($file))) { $data = unserialize($content); if (isset($data['expired']) && (intval($data['expired']) === 0 || intval($data['expired']) >= time())) { return $data['value']; diff --git a/vendor/zoujingli/wechat-developer/WePay/Refund.php b/vendor/zoujingli/wechat-developer/WePay/Refund.php index e8abbad8f..39ac36a24 100644 --- a/vendor/zoujingli/wechat-developer/WePay/Refund.php +++ b/vendor/zoujingli/wechat-developer/WePay/Refund.php @@ -16,6 +16,7 @@ namespace WePay; use WeChat\Contracts\BasicWePay; use WeChat\Contracts\Tools; +use WeChat\Exceptions\InvalidDecryptException; use WeChat\Exceptions\InvalidResponseException; /** @@ -55,6 +56,7 @@ class Refund extends BasicWePay /** * 获取退款通知 * @return array + * @throws InvalidDecryptException * @throws InvalidResponseException */ public function getNotify() @@ -63,16 +65,14 @@ class Refund extends BasicWePay if (!isset($data['return_code']) || $data['return_code'] !== 'SUCCESS') { throw new InvalidResponseException('获取退款通知XML失败!'); } - if (!class_exists('Prpcrypt', false)) { - include dirname(__DIR__) . '/WeChat/Contracts/Prpcrypt.php'; + try { + $key = md5($this->config->get('mch_key')); + $decrypt = base64_decode($data['req_info']); + $response = openssl_decrypt($decrypt, 'aes-256-ecb', $key, OPENSSL_RAW_DATA); + $data['result'] = Tools::xml2arr($response); + return $data; + } catch (\Exception $exception) { + throw new InvalidDecryptException($exception->getMessage(), $exception->getCode()); } - $pc = new \Prpcrypt(md5($this->config->get('mch_key'))); - $array = $pc->decrypt(base64_decode($data['req_info'])); - if (intval($array[0]) > 0) { - throw new InvalidResponseException($array[1], $array[0]); - } - $data['decode'] = $array[1]; - return $data; } - } \ No newline at end of file diff --git a/vendor/zoujingli/wechat-developer/WePayV3/Cert.php b/vendor/zoujingli/wechat-developer/WePayV3/Cert.php new file mode 100644 index 000000000..2c368aac2 --- /dev/null +++ b/vendor/zoujingli/wechat-developer/WePayV3/Cert.php @@ -0,0 +1,49 @@ +config['mch_v3_key']); + $result = $this->doRequest('GET', '/v3/certificates'); + foreach ($result['data'] as $vo) { + $this->tmpFile($vo['serial_no'], $aes->decryptToString( + $vo['encrypt_certificate']['associated_data'], + $vo['encrypt_certificate']['nonce'], + $vo['encrypt_certificate']['ciphertext'] + )); + } + } catch (\Exception $exception) { + throw new InvalidResponseException($exception->getMessage(), $exception->getCode()); + } + } +} \ No newline at end of file diff --git a/vendor/zoujingli/wechat-developer/WePayV3/Contracts/BasicWePay.php b/vendor/zoujingli/wechat-developer/WePayV3/Contracts/BasicWePay.php new file mode 100644 index 000000000..4f40e1429 --- /dev/null +++ b/vendor/zoujingli/wechat-developer/WePayV3/Contracts/BasicWePay.php @@ -0,0 +1,219 @@ + '', // 微信绑定APPID,需配置 + 'mch_id' => '', // 微信商户编号,需要配置 + 'mch_v3_key' => '', // 微信商户密钥,需要配置 + 'cert_serial' => '', // 商户证书序号,无需配置 + 'cert_public' => '', // 商户公钥内容,需要配置 + 'cert_private' => '', // 商户密钥内容,需要配置 + ]; + + /** + * BasicWePayV3 constructor. + * @param array $options [mch_id, mch_v3_key, cert_public, cert_private] + */ + public function __construct(array $options = []) + { + if (empty($options['mch_id'])) { + throw new InvalidArgumentException("Missing Config -- [mch_id]"); + } + if (empty($options['mch_v3_key'])) { + throw new InvalidArgumentException("Missing Config -- [mch_v3_key]"); + } + if (empty($options['cert_private'])) { + throw new InvalidArgumentException("Missing Config -- [cert_private]"); + } + if (empty($options['cert_public'])) { + throw new InvalidArgumentException("Missing Config -- [cert_public]"); + } + + $this->config['appid'] = isset($options['appid']) ? $options['appid'] : ''; + $this->config['mch_id'] = $options['mch_id']; + $this->config['mch_v3_key'] = $options['mch_v3_key']; + $this->config['cert_public'] = $options['cert_public']; + $this->config['cert_private'] = $options['cert_private']; + $this->config['cert_serial'] = openssl_x509_parse($this->config['cert_public'])['serialNumberHex']; + + if (empty($this->config['cert_serial'])) { + throw new InvalidArgumentException("Failed to parse certificate public key"); + } + } + + /** + * 静态创建对象 + * @param array $config + * @return static + */ + public static function instance(array $config) + { + $key = md5(get_called_class() . serialize($config)); + if (isset(self::$cache[$key])) return self::$cache[$key]; + return self::$cache[$key] = new static($config); + } + + /** + * 模拟发起请求 + * @param string $method 请求访问 + * @param string $pathinfo 请求路由 + * @param string $jsondata 请求数据 + * @param bool $verify 是否验证 + * @return array + * @throws InvalidResponseException + */ + public function doRequest($method, $pathinfo, $jsondata = '', $verify = false) + { + list($time, $nonce) = [time(), uniqid() . rand(1000, 9999)]; + $signstr = join("\n", [$method, $pathinfo, $time, $nonce, $jsondata, '']); + // 生成数据签名TOKEN + $token = sprintf('mchid="%s",nonce_str="%s",timestamp="%d",serial_no="%s",signature="%s"', + $this->config['mch_id'], $nonce, $time, $this->config['cert_serial'], $this->signBuild($signstr) + ); + list($header, $content) = $this->_doRequestCurl($method, $this->base . $pathinfo, [ + 'data' => $jsondata, 'header' => [ + "Accept: application/json", "Content-Type: application/json", + 'User-Agent: https://thinkadmin.top', "Authorization: WECHATPAY2-SHA256-RSA2048 {$token}", + ], + ]); + if ($verify) { + $headers = []; + foreach (explode("\n", $header) as $line) { + if (stripos($line, 'Wechatpay') !== false) { + list($name, $value) = explode(':', $line); + list(, $keys) = explode('wechatpay-', strtolower($name)); + $headers[$keys] = trim($value); + } + } + try { + $string = join("\n", [$headers['timestamp'], $headers['nonce'], $content, '']); + if (!$this->signVerify($string, $headers['signature'], $headers['serial'])) { + throw new InvalidResponseException("验证响应签名失败"); + } + } catch (\Exception $exception) { + throw new InvalidResponseException($exception->getMessage(), $exception->getCode()); + } + } + return json_decode($content, true); + } + + /** + * 通过CURL模拟网络请求 + * @param string $method 请求方法 + * @param string $location 请求方法 + * @param array $options 请求参数 [data, header] + * @return array [header,content] + */ + private function _doRequestCurl($method, $location, $options = []) + { + $curl = curl_init(); + // POST数据设置 + if (strtolower($method) === 'post') { + curl_setopt($curl, CURLOPT_POST, true); + curl_setopt($curl, CURLOPT_POSTFIELDS, $options['data']); + } + // CURL头信息设置 + if (!empty($options['header'])) { + curl_setopt($curl, CURLOPT_HTTPHEADER, $options['header']); + } + curl_setopt($curl, CURLOPT_URL, $location); + curl_setopt($curl, CURLOPT_HEADER, true); + curl_setopt($curl, CURLOPT_TIMEOUT, 60); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); + curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); + $content = curl_exec($curl); + $headerSize = curl_getinfo($curl, CURLINFO_HEADER_SIZE); + curl_close($curl); + return [substr($content, 0, $headerSize), substr($content, $headerSize)]; + } + + /** + * 生成数据签名 + * @param string $data 签名内容 + * @return string + */ + protected function signBuild($data) + { + $pkeyid = openssl_pkey_get_private($this->config['cert_private']); + openssl_sign($data, $signature, $pkeyid, 'sha256WithRSAEncryption'); + return base64_encode($signature); + } + + /** + * 验证内容签名 + * @param string $data 签名内容 + * @param string $sign 原签名值 + * @param string $serial 证书序号 + * @return int + * @throws InvalidResponseException + * @throws LocalCacheException + */ + protected function signVerify($data, $sign, $serial = '') + { + $cert = $this->tmpFile($serial); + if (empty($cert)) { + Cert::instance($this->config)->download(); + $cert = $this->tmpFile($serial); + } + return @openssl_verify($data, base64_decode($sign), openssl_x509_read($cert), 'sha256WithRSAEncryption'); + } + + /** + * 写入或读取临时文件 + * @param string $name + * @param null|string $content + * @return string + * @throws LocalCacheException + */ + protected function tmpFile($name, $content = null) + { + if (is_null($content)) { + return base64_decode(Tools::getCache($name) ?: ''); + } else { + return Tools::setCache($name, base64_encode($content), 7200); + } + } +} \ No newline at end of file diff --git a/vendor/zoujingli/wechat-developer/WePayV3/Contracts/DecryptAes.php b/vendor/zoujingli/wechat-developer/WePayV3/Contracts/DecryptAes.php new file mode 100644 index 000000000..7a5b59796 --- /dev/null +++ b/vendor/zoujingli/wechat-developer/WePayV3/Contracts/DecryptAes.php @@ -0,0 +1,81 @@ +aesKey = $aesKey; + } + + /** + * Decrypt AEAD_AES_256_GCM ciphertext + * @param string $associatedData AES GCM additional authentication data + * @param string $nonceStr AES GCM nonce + * @param string $ciphertext AES GCM cipher text + * @return string|bool Decrypted string on success or FALSE on failure + * @throws InvalidDecryptException + */ + public function decryptToString($associatedData, $nonceStr, $ciphertext) + { + $ciphertext = \base64_decode($ciphertext); + if (strlen($ciphertext) <= self::AUTH_TAG_LENGTH_BYTE) { + return false; + } + try { + // ext-sodium (default installed on >= PHP 7.2) + if (function_exists('\sodium_crypto_aead_aes256gcm_is_available') && \sodium_crypto_aead_aes256gcm_is_available()) { + return \sodium_crypto_aead_aes256gcm_decrypt($ciphertext, $associatedData, $nonceStr, $this->aesKey); + } + // ext-libsodium (need install libsodium-php 1.x via pecl) + if (function_exists('\Sodium\crypto_aead_aes256gcm_is_available') && \Sodium\crypto_aead_aes256gcm_is_available()) { + return \Sodium\crypto_aead_aes256gcm_decrypt($ciphertext, $associatedData, $nonceStr, $this->aesKey); + } + // openssl (PHP >= 7.1 support AEAD) + if (PHP_VERSION_ID >= 70100 && in_array('aes-256-gcm', \openssl_get_cipher_methods())) { + $ctext = substr($ciphertext, 0, -self::AUTH_TAG_LENGTH_BYTE); + $authTag = substr($ciphertext, -self::AUTH_TAG_LENGTH_BYTE); + return \openssl_decrypt($ctext, 'aes-256-gcm', $this->aesKey, \OPENSSL_RAW_DATA, $nonceStr, $authTag, $associatedData); + } + } catch (\Exception $exception) { + throw new InvalidDecryptException($exception->getMessage(), $exception->getCode()); + } catch (\SodiumException $exception) { + throw new InvalidDecryptException($exception->getMessage(), $exception->getCode()); + } + throw new InvalidDecryptException('AEAD_AES_256_GCM 需要 PHP 7.1 以上或者安装 libsodium-php'); + } +} \ No newline at end of file diff --git a/vendor/zoujingli/wechat-developer/WePayV3/Order.php b/vendor/zoujingli/wechat-developer/WePayV3/Order.php new file mode 100644 index 000000000..e22cb59c3 --- /dev/null +++ b/vendor/zoujingli/wechat-developer/WePayV3/Order.php @@ -0,0 +1,106 @@ + '/v3/pay/transactions/h5', + 'app' => '/v3/pay/transactions/app', + 'jsapi' => '/v3/pay/transactions/jsapi', + 'native' => '/v3/pay/transactions/native', + ]; + if (empty($types[$type])) { + throw new InvalidArgumentException("Payment {$type} not defined."); + } else { + // 创建预支付码 + $result = $this->doRequest('POST', $types[$type], json_encode($data, JSON_UNESCAPED_UNICODE), true); + if (empty($result['prepay_id'])) return $result; + // 支付参数签名 + $time = (string)time(); + $appid = $this->config['appid']; + $prepayId = $result['prepay_id']; + $nonceStr = Tools::createNoncestr(); + if ($type === 'app') { + $sign = $this->signBuild(join("\n", [$appid, $time, $nonceStr, $prepayId])); + return ['partnerId' => $this->config['mch_id'], 'prepayId' => $prepayId, 'package' => 'Sign=WXPay', 'nonceStr' => $nonceStr, 'timeStamp' => $time, 'sign' => $sign]; + } elseif ($type === 'jsapi') { + $sign = $this->signBuild(join("\n", [$appid, $time, $nonceStr, "prepay_id={$prepayId}"])); + return ['appId' => $appid, 'timeStamp' => $time, 'nonceStr' => $nonceStr, 'package' => "prepay_id={$prepayId}", 'signType' => 'RSA', 'paySign' => $sign]; + } else { + return $result; + } + } + } + + /** + * 支付订单查询 + * @param string $orderNo 订单单号 + * @return array + * @throws InvalidResponseException + */ + public function query($orderNo) + { + $pathinfo = "/v3/pay/transactions/out-trade-no/{$orderNo}"; + return $this->doRequest('GET', "{$pathinfo}?mchid={$this->config['mch_id']}", '', true); + } + + /** + * 支付通知 + * @return array + * @throws InvalidDecryptException + */ + public function notify() + { + $body = file_get_contents('php://input'); + $data = json_decode($body, true); + if (isset($data['resource'])) { + $aes = new DecryptAes($this->config['mch_v3_key']); + $data['result'] = $aes->decryptToString( + $data['resource']['associated_data'], + $data['resource']['nonce'], + $data['resource']['ciphertext'] + ); + } + return $data; + } + +} \ No newline at end of file diff --git a/vendor/zoujingli/wechat-developer/WePayV3/Refund.php b/vendor/zoujingli/wechat-developer/WePayV3/Refund.php new file mode 100644 index 000000000..809f6e296 --- /dev/null +++ b/vendor/zoujingli/wechat-developer/WePayV3/Refund.php @@ -0,0 +1,75 @@ +doRequest('POST', '/v3/ecommerce/refunds/apply', json_encode($data, JSON_UNESCAPED_UNICODE), true); + } + + /** + * 退款订单查询 + * @param string $refundNo 退款单号 + * @return array + * @throws InvalidResponseException + */ + public function query($refundNo) + { + $pathinfo = "/v3/ecommerce/refunds/out-refund-no/{$refundNo}"; + return $this->doRequest('GET', "{$pathinfo}?sub_mchid={$this->config['mch_id']}", '', true); + } + + /** + * 获取退款通知 + * @return array + * @throws InvalidDecryptException + * @throws InvalidResponseException + */ + public function notify() + { + $data = Tools::xml2arr(file_get_contents("php://input")); + if (!isset($data['return_code']) || $data['return_code'] !== 'SUCCESS') { + throw new InvalidResponseException('获取退款通知XML失败!'); + } + try { + $key = md5($this->config['mch_v3_key']); + $decrypt = base64_decode($data['req_info']); + $response = openssl_decrypt($decrypt, 'aes-256-ecb', $key, OPENSSL_RAW_DATA); + $data['result'] = Tools::xml2arr($response); + return $data; + } catch (\Exception $exception) { + throw new InvalidDecryptException($exception->getMessage(), $exception->getCode()); + } + } + +} \ No newline at end of file diff --git a/vendor/zoujingli/wechat-developer/_test/pay-v3-config-cert.php b/vendor/zoujingli/wechat-developer/_test/pay-v3-config-cert.php new file mode 100644 index 000000000..47883d133 --- /dev/null +++ b/vendor/zoujingli/wechat-developer/_test/pay-v3-config-cert.php @@ -0,0 +1,16 @@ +download(); + +} catch (\Exception $exception) { + // 出错啦,处理下吧 + echo $exception->getMessage() . PHP_EOL; +} \ No newline at end of file diff --git a/vendor/zoujingli/wechat-developer/_test/pay-v3-config.php b/vendor/zoujingli/wechat-developer/_test/pay-v3-config.php new file mode 100644 index 000000000..14d095a98 --- /dev/null +++ b/vendor/zoujingli/wechat-developer/_test/pay-v3-config.php @@ -0,0 +1,17 @@ + '绑定的APPID', + 'mch_id' => '您的商户编号', + 'mch_v3_key' => '您的V3接口密码', + 'cert_public' => << <<create('jsapi', [ + 'appid' => 'wx60a43dd8161666d4', + 'mchid' => $config['mch_id'], + 'description' => '商品描述', + 'out_trade_no' => date("YmdHis"), + 'notify_url' => 'https://thinkadmin.top', + 'payer' => ['openid' => 'o38gps3vNdCqaggFfrBRCRikwlWY'], + 'amount' => ['total' => 1, 'currency' => 'CNY'], + ]); + + echo '
';
+    echo "\n--- 创建支付参数 ---\n";
+    var_export($result);
+
+} catch (\Exception $exception) {
+    // 出错啦,处理下吧
+    echo $exception->getMessage() . PHP_EOL;
+}
\ No newline at end of file
diff --git a/vendor/zoujingli/wechat-developer/readme.md b/vendor/zoujingli/wechat-developer/readme.md
index 21099e3d6..154a87141 100644
--- a/vendor/zoujingli/wechat-developer/readme.md
+++ b/vendor/zoujingli/wechat-developer/readme.md
@@ -11,6 +11,7 @@ WeChatDeveloper for PHP
 * 微信的部分接口需要缓存数据在本地,因此对目录需要有写权限;
 * 我们鼓励大家使用 composer 来管理您的第三方库,方便后期更新操作;
 * WeChatDeveloper 已历经数个线上项目考验,欢迎 fork 或 star 此项目。
+* 微信商户支持已经支持 v2 接口,组件开发版支持 v3 接口。
 
 功能描述
 ----
@@ -260,8 +261,5 @@ try {
 * WeChatDeveloper 基于`MIT`协议发布,任何人可以用在任何地方,不受约束
 * WeChatDeveloper 部分代码来自互联网,若有异议,可以联系作者进行删除
 
-赞助支持
-----
-![赞助](http://static.thinkadmin.top/pay.png)
-
-
+## 赞助打赏
+![赞助](https://thinkadmin.top/static/img/pay.png)