WxBase.php 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2017~2021 https://www.yiovo.com All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
  8. // +----------------------------------------------------------------------
  9. // | Author: 萤火科技 <admin@yiovo.com>
  10. // +----------------------------------------------------------------------
  11. declare (strict_types=1);
  12. namespace app\common\library\wechat;
  13. use think\facade\Cache;
  14. use app\common\library\helper;
  15. use app\common\exception\BaseException;
  16. /**
  17. * 微信api基类
  18. * Class wechat
  19. * @package app\library
  20. */
  21. class WxBase
  22. {
  23. protected $appId;
  24. protected $appSecret;
  25. protected $error;
  26. /**
  27. * 构造函数
  28. * WxBase constructor.
  29. * @param $appId
  30. * @param $appSecret
  31. */
  32. public function __construct($appId = null, $appSecret = null)
  33. {
  34. $this->setConfig($appId, $appSecret);
  35. }
  36. protected function setConfig($appId = null, $appSecret = null)
  37. {
  38. !empty($appId) && $this->appId = $appId;
  39. !empty($appSecret) && $this->appSecret = $appSecret;
  40. }
  41. /**
  42. * 获取access_token
  43. * @return mixed
  44. * @throws BaseException
  45. */
  46. protected function getAccessToken()
  47. {
  48. $cacheKey = $this->appId . '@access_token';
  49. if (!Cache::instance()->get($cacheKey)) {
  50. // 请求API获取 access_token
  51. $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$this->appId}&secret={$this->appSecret}";
  52. $result = $this->get($url);
  53. $response = $this->jsonDecode($result);
  54. if (array_key_exists('errcode', $response)) {
  55. throwError("access_token获取失败,错误信息:{$result}");
  56. }
  57. // 记录日志
  58. log_record([
  59. 'name' => '获取access_token',
  60. 'url' => $url,
  61. 'appId' => $this->appId,
  62. 'result' => $result
  63. ]);
  64. // 写入缓存
  65. Cache::instance()->set($cacheKey, $response['access_token'], 6000);
  66. }
  67. return Cache::instance()->get($cacheKey);
  68. }
  69. /**
  70. * 模拟GET请求 HTTPS的页面
  71. * @param string $url 请求地址
  72. * @param array $data
  73. * @return string $result
  74. * @throws BaseException
  75. */
  76. protected function get(string $url, array $data = [])
  77. {
  78. // 处理query参数
  79. if (!empty($data)) {
  80. $url = $url . '?' . http_build_query($data);
  81. }
  82. $curl = curl_init();
  83. curl_setopt($curl, CURLOPT_URL, $url);
  84. curl_setopt($curl, CURLOPT_HEADER, 0);
  85. curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
  86. curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE); // https请求 不验证证书和hosts
  87. $result = curl_exec($curl);
  88. if ($result === false) {
  89. throwError(curl_error($curl));
  90. }
  91. curl_close($curl);
  92. return $result;
  93. }
  94. /**
  95. * 模拟POST请求
  96. * @param string $url 请求地址
  97. * @param array $data 请求数据
  98. * @param false $useCert 是否引入微信支付证书
  99. * @param array $sslCert 证书路径
  100. * @return mixed|bool|string
  101. * @throws BaseException
  102. */
  103. protected function post(string $url, $data = [], $useCert = false, $sslCert = [])
  104. {
  105. $header = [
  106. 'Content-type: application/json;'
  107. ];
  108. $curl = curl_init();
  109. curl_setopt($curl, CURLOPT_URL, $url);
  110. curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
  111. curl_setopt($curl, CURLOPT_HEADER, false);
  112. curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
  113. curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
  114. curl_setopt($curl, CURLOPT_POST, TRUE);
  115. curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
  116. if ($useCert == true) {
  117. // 设置证书:cert 与 key 分别属于两个.pem文件
  118. curl_setopt($curl, CURLOPT_SSLCERTTYPE, 'PEM');
  119. curl_setopt($curl, CURLOPT_SSLCERT, $sslCert['certPem']);
  120. curl_setopt($curl, CURLOPT_SSLKEYTYPE, 'PEM');
  121. curl_setopt($curl, CURLOPT_SSLKEY, $sslCert['keyPem']);
  122. }
  123. $result = curl_exec($curl);
  124. if ($result === false) {
  125. throwError(curl_error($curl));
  126. }
  127. curl_close($curl);
  128. return $result;
  129. }
  130. /**
  131. * 模拟POST请求 [第二种方式, 用于兼容微信api]
  132. * @param $url
  133. * @param array $data
  134. * @return mixed
  135. * @throws BaseException
  136. */
  137. protected function post2($url, $data = [])
  138. {
  139. $header = [
  140. 'Content-Type: application/x-www-form-urlencoded'
  141. ];
  142. $ch = curl_init();
  143. curl_setopt($ch, CURLOPT_URL, $url);
  144. curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
  145. curl_setopt($ch, CURLOPT_POST, true);
  146. curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
  147. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  148. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);//这个是重点。
  149. $result = curl_exec($ch);
  150. if ($result === false) {
  151. throwError(curl_error($ch));
  152. }
  153. curl_close($ch);
  154. return $result;
  155. }
  156. /**
  157. * 数组转json
  158. * @param $data
  159. * @return string
  160. */
  161. protected function jsonEncode($data)
  162. {
  163. return helper::jsonEncode($data, JSON_UNESCAPED_UNICODE);
  164. }
  165. /**
  166. * json转数组
  167. * @param $json
  168. * @return mixed
  169. */
  170. protected function jsonDecode($json)
  171. {
  172. return helper::jsonDecode($json);
  173. }
  174. /**
  175. * 返回错误信息
  176. * @return mixed
  177. */
  178. public function getError()
  179. {
  180. return $this->error;
  181. }
  182. }