1
0

WeChatOaService.php 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | likeadmin快速开发前后端分离管理后台(PHP版)
  4. // +----------------------------------------------------------------------
  5. // | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
  6. // | 开源版本可自由商用,可去除界面版权logo
  7. // | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
  8. // | github下载:https://github.com/likeshop-github/likeadmin
  9. // | 访问官网:https://www.likeadmin.cn
  10. // | likeadmin团队 版权所有 拥有最终解释权
  11. // +----------------------------------------------------------------------
  12. // | author: likeadminTeam
  13. // +----------------------------------------------------------------------
  14. namespace app\common\service\wechat;
  15. use app\common\enum\notice\NoticeEnum;
  16. use app\common\logic\NoticeLogic;
  17. use app\common\model\notice\NoticeSetting;
  18. use EasyWeChat\Kernel\Exceptions\Exception;
  19. use EasyWeChat\OfficialAccount\Application;
  20. use think\facade\Log;
  21. /**
  22. * 公众号相关
  23. * Class WeChatOaService
  24. * @package app\common\service\wechat
  25. */
  26. class WeChatOaService
  27. {
  28. protected $app;
  29. protected $config;
  30. public function __construct()
  31. {
  32. $this->config = $this->getConfig();
  33. $this->app = new Application($this->config);
  34. }
  35. /**
  36. * @notes easywechat服务端
  37. * @return \EasyWeChat\Kernel\Contracts\Server|\EasyWeChat\OfficialAccount\Server
  38. * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
  39. * @throws \ReflectionException
  40. * @throws \Throwable
  41. * @author 段誉
  42. * @date 2023/2/27 14:22
  43. */
  44. public function getServer()
  45. {
  46. return $this->app->getServer();
  47. }
  48. /**
  49. * @notes 配置
  50. * @return array
  51. * @throws Exception
  52. * @author 段誉
  53. * @date 2023/2/27 12:03
  54. */
  55. protected function getConfig()
  56. {
  57. $config = WeChatConfigService::getOaConfig();
  58. if (empty($config['app_id']) || empty($config['secret'])) {
  59. throw new Exception('请先设置公众号配置');
  60. }
  61. return $config;
  62. }
  63. /**
  64. * @notes 公众号-根据code获取微信信息
  65. * @param string $code
  66. * @return mixed
  67. * @throws Exception
  68. * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
  69. * @author 段誉
  70. * @date 2023/2/27 11:04
  71. */
  72. public function getOaResByCode(string $code)
  73. {
  74. $response = $this->app->getOAuth()
  75. ->scopes(['snsapi_userinfo'])
  76. ->userFromCode($code)
  77. ->getRaw();
  78. if (!isset($response['openid']) || empty($response['openid'])) {
  79. throw new Exception('获取openID失败');
  80. }
  81. return $response;
  82. }
  83. /**
  84. * @notes 公众号跳转url
  85. * @param string $url
  86. * @return mixed
  87. * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
  88. * @author 段誉
  89. * @date 2023/2/27 10:35
  90. */
  91. public function getCodeUrl(string $url)
  92. {
  93. return $this->app->getOAuth()
  94. ->scopes(['snsapi_userinfo'])
  95. ->redirect($url);
  96. }
  97. /**
  98. * @notes 创建公众号菜单
  99. * @param array $buttons
  100. * @param array $matchRule
  101. * @return \EasyWeChat\Kernel\HttpClient\Response|\Symfony\Contracts\HttpClient\ResponseInterface
  102. * @throws \Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface
  103. * @author 段誉
  104. * @date 2023/2/27 12:07
  105. */
  106. public function createMenu(array $buttons, array $matchRule = [])
  107. {
  108. if (!empty($matchRule)) {
  109. return $this->app->getClient()->postJson('cgi-bin/menu/addconditional', [
  110. 'button' => $buttons,
  111. 'matchrule' => $matchRule,
  112. ]);
  113. }
  114. return $this->app->getClient()->postJson('cgi-bin/menu/create', ['button' => $buttons]);
  115. }
  116. /**
  117. * @notes 获取jssdkConfig
  118. * @param $url
  119. * @param $jsApiList
  120. * @param array $openTagList
  121. * @param false $debug
  122. * @return mixed[]
  123. * @throws \EasyWeChat\Kernel\Exceptions\HttpException
  124. * @throws \Psr\SimpleCache\InvalidArgumentException
  125. * @throws \Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface
  126. * @throws \Symfony\Contracts\HttpClient\Exception\DecodingExceptionInterface
  127. * @throws \Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface
  128. * @throws \Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface
  129. * @throws \Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface
  130. * @author 段誉
  131. * @date 2023/3/1 11:46
  132. */
  133. public function getJsConfig($url, $jsApiList, $openTagList = [], $debug = false)
  134. {
  135. return $this->app->getUtils()->buildJsSdkConfig($url, $jsApiList, $openTagList, $debug);
  136. }
  137. public function contentFormat($noticeSetting, $params)
  138. {
  139. $content = $noticeSetting['oa_notice']['content'];
  140. foreach($params['params'] as $k => $v) {
  141. $search = '${' . $k . '}';
  142. $content = str_replace($search, $v, $content);
  143. }
  144. return $content;
  145. }
  146. public function getTemplateMessageParams($noticeSetting, $params)
  147. {
  148. $arr = [];
  149. $content = $noticeSetting['oa_notice']['content'];
  150. foreach ($params['params'] as $item => $val) {
  151. $search = '${' . $item . '}';
  152. if(strpos($content, $search) !== false && !in_array($item, $arr)) {
  153. $arr[] = $item;
  154. }
  155. }
  156. $arr2 = [];
  157. if (!empty($arr)) {
  158. foreach ($arr as $v) {
  159. $key = strpos($content, $v);
  160. $arr2[$key] = $v;
  161. }
  162. }
  163. ksort($arr2);
  164. $arr3 = array_values($arr2);
  165. $arr4 = [];
  166. foreach ($arr3 as $v2) {
  167. if(isset($params['params'][$v2])) {
  168. $arr4[$v2]['value'] = $params['params'][$v2] . "";
  169. }
  170. }
  171. return $arr4;
  172. }
  173. public function sendTemplateMessage(array $params)
  174. {
  175. try {
  176. // 通知设置
  177. $noticeSetting = NoticeSetting::where('scene_id', $params['scene_id'])->findOrEmpty()->toArray();
  178. Log::info('WeChatOa-sendTemplateMessage:'.json_encode([$noticeSetting,$params,$this->getTemplateMessageParams($noticeSetting, $params)]));
  179. // 发送
  180. $wx_data = [
  181. 'touser' => $params['params']['openid'],
  182. 'template_id' => $noticeSetting['oa_notice']['template_id'],
  183. 'url' => (isset($params['url']) && !empty($params['url']))?$params['url']:'',
  184. 'data' => $this->getTemplateMessageParams($noticeSetting, $params)
  185. ];
  186. // 可跳小程序
  187. if(isset($params['page']) && !empty($params['page'])) {
  188. $wx_data["miniprogram"]=[
  189. "appid" => 'wx8e44db3741ea212c',
  190. "pagepath" => $params['page']
  191. ];
  192. }
  193. $result = $this->app->getClient()->postJson('cgi-bin/message/template/send', $wx_data);
  194. if (intval($result["errcode"]) > 0) {
  195. throw new \Exception('微信通知发送失败:'.$result["errmsg"]);
  196. }
  197. // 替换通知模板参数
  198. $content = $this->contentFormat($noticeSetting, $params);
  199. // 添加通知记录
  200. NoticeLogic::addNotice($params, $noticeSetting, NoticeEnum::OA, $content);
  201. return true;
  202. } catch (\Exception $e) {
  203. Log::info('WeChatOa-sendTemplateMessage:'.$e->getMessage());
  204. throw new \Exception($e->getMessage());
  205. }
  206. }
  207. public function getUserInfo($openid)
  208. {
  209. $response =$this->app->getClient()->get("/cgi-bin/user/info?openid={$openid}&lang=zh_CN");
  210. return $response->toArray();
  211. }
  212. }