MpService.php 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. <?php
  2. namespace app\common\library\xmwechat\miniprogram;
  3. use app\common\library\xmwechat\SingletonTrait;
  4. use app\common\library\xmwechat\WechatService;
  5. use EasyWeChat\MiniApp\Application;
  6. use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
  7. use Symfony\Contracts\HttpClient\Exception\DecodingExceptionInterface;
  8. use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
  9. use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
  10. use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
  11. /**
  12. * 小程序服务
  13. */
  14. class MpService extends WechatService
  15. {
  16. protected ?Application $app = null;
  17. protected string $accessToken;
  18. use SingletonTrait;
  19. public function __construct()
  20. {
  21. parent::__construct();
  22. if (empty($this->miniProgramConfig['app_id']) || empty($this->miniProgramConfig['secret'])) {
  23. $this->result('请配置小程序appid或secret');
  24. }
  25. $this->app = new Application([
  26. 'app_id' => $this->miniProgramConfig['app_id'],
  27. 'secret' => $this->miniProgramConfig['secret'],
  28. ]);
  29. $accessToken = $this->app->getAccessToken();
  30. $this->accessToken = $accessToken->getToken();
  31. }
  32. /**
  33. * @param $params
  34. * @return array
  35. * @throws ClientExceptionInterface
  36. * @throws DecodingExceptionInterface
  37. * @throws RedirectionExceptionInterface
  38. * @throws ServerExceptionInterface
  39. * @throws TransportExceptionInterface
  40. * @throws \Exception
  41. * @author jsjxsz
  42. */
  43. public function getOpenidAndUnionid($params): array
  44. {
  45. try {
  46. $utils = $this->app->getUtils();
  47. // code需前端获取 传给api
  48. $wxData = $utils->codeToSession($params['code']);
  49. $openid = $wxData['openid'];
  50. // 小程序若未绑定微信开放平台(不是公众号),将获取不到unionid
  51. isset($wxData['unionid']) && !empty($wxData['unionid']) ? $unionid = $wxData['unionid'] : $unionid = '';
  52. return [
  53. 'openid' => $openid,
  54. 'unionid' => $unionid
  55. ];
  56. } catch (\Exception $e) {
  57. $this->result($e->getMessage());
  58. }
  59. }
  60. /**
  61. * @param $params
  62. * @return array
  63. * @throws ClientExceptionInterface
  64. * @throws DecodingExceptionInterface
  65. * @throws RedirectionExceptionInterface
  66. * @throws ServerExceptionInterface
  67. * @throws TransportExceptionInterface
  68. * @throws \Exception
  69. * @author jsjxsz
  70. */
  71. public function getPhoneNumber($params): array
  72. {
  73. try {
  74. // code需前端获取 传给api
  75. $result = $this->app->getClient()->postJson('/wxa/business/getuserphonenumber?access_token=' . $this->accessToken, [
  76. 'code' => (string)$params['code'],
  77. ]);
  78. $result = $result->toArray();
  79. if ($result['errcode'] == 0 && $result['errmsg'] == 'ok') {
  80. return $result;
  81. }
  82. } catch (\Exception $e) {
  83. $this->result($e->getMessage());
  84. }
  85. return [];
  86. }
  87. /**
  88. * 微信文本安全内容检测 单个appid调用上限为2000次/分钟,1,000,000次/天
  89. * scene 场景枚举值(1 资料;2 评论;3 论坛;4 社交日志)
  90. * @param array $params
  91. * @return bool
  92. * @throws ClientExceptionInterface
  93. * @throws DecodingExceptionInterface
  94. * @throws RedirectionExceptionInterface
  95. * @throws ServerExceptionInterface
  96. * @throws TransportExceptionInterface
  97. * @throws \Exception
  98. * @author jsjxsz
  99. */
  100. public function checkText(array $params): bool
  101. {
  102. try {
  103. isset($params['scene']) && !empty($params['scene']) ? $scene = $params['scene'] : $scene = 3;
  104. $api = $this->app->getClient();
  105. $response = $api->postJson('/wxa/msg_sec_check?access_token=' . $this->accessToken, [
  106. "content" => utf8_encode($params['content']),
  107. "version" => 2, // 接口版本号,2.0版本为固定值2
  108. "scene" => $scene,
  109. "openid" => $params['openid']
  110. ]);
  111. $result = $response->toArray();
  112. if (isset($result['result']['label']) && $result['result']['label'] == 100) {
  113. // 具体查看 https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/sec-center/sec-check/msgSecCheck.html
  114. return true;
  115. }
  116. } catch (\Exception $exception) {
  117. $this->result($exception->getMessage());
  118. }
  119. return false;
  120. }
  121. /**
  122. * 检查音频、图片
  123. * 频率限制:单个 appId 调用上限为 2000 次/分钟,200,000 次/天;文件大小限制:单个文件大小不超过10M
  124. * @param $params
  125. * @return bool|array
  126. * @throws ClientExceptionInterface
  127. * @throws DecodingExceptionInterface
  128. * @throws RedirectionExceptionInterface
  129. * @throws ServerExceptionInterface
  130. * @throws TransportExceptionInterface
  131. * @throws \Exception
  132. * @author jsjxsz
  133. */
  134. public function checkMedia($params): bool|array
  135. {
  136. try {
  137. isset($params['media_type']) && !empty($params['media_type']) ? $media_type = $params['media_type'] : $media_type = 2;
  138. isset($params['scene']) && !empty($params['scene']) ? $scene = $params['scene'] : $scene = 3;
  139. $media_url = $params['media_url'];
  140. $api = $this->app->getClient();
  141. $response = $api->postJson('/wxa/media_check_async?access_token=' . $this->accessToken, [
  142. "media_url" => $media_url,
  143. "media_type" => $media_type,
  144. "version" => 2, // 接口版本号,2.0版本为固定值2
  145. "scene" => $scene,
  146. "openid" => $params['openid']
  147. ]);
  148. $result = $response->toArray();
  149. if (isset($result['trace_id']) && !empty($result['trace_id'])) {
  150. // 请求成功
  151. // 检测结果需要异步推送(需先配置微信小程序消息推送相关参数)
  152. // trace_id 唯一请求标识,标记单次请求,用于匹配异步推送结果
  153. // 具体查看 https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/sec-center/sec-check/mediaCheckAsync.html
  154. return $result;
  155. }
  156. } catch (\Exception $exception) {
  157. $this->result($exception->getMessage());
  158. }
  159. return false;
  160. }
  161. /**
  162. * @param array $params
  163. * @return bool
  164. * @author jsjxsz
  165. */
  166. public function checkSignature(array $params): bool
  167. {
  168. $server_token = $this->miniProgramConfig['server_token'];
  169. $tmpArr = array($server_token, $params['timestamp'], $params['nonce']);
  170. sort($tmpArr, SORT_STRING);
  171. $tmpStr = implode($tmpArr);
  172. $tmpStr = sha1($tmpStr);
  173. if ($tmpStr == $params['signature']) {
  174. return true;
  175. } else {
  176. return false;
  177. }
  178. }
  179. }