// +---------------------------------------------------------------------- declare (strict_types=1); namespace app\api\service; use EasyWeChat\Factory; use EasyWeChat\Kernel\Exceptions\InvalidArgumentException; use EasyWeChat\Kernel\Exceptions\InvalidConfigException; use EasyWeChat\Kernel\Exceptions\RuntimeException; use EasyWeChat\OfficialAccount\Application; use app\api\model\wxofficial\Setting as WxofficialSetting; use app\common\service\BaseService; use app\common\library\helper; use app\common\library\wechat\WXBizDataCrypt; use cores\exception\BaseException; use think\db\exception\DataNotFoundException; use think\db\exception\DbException; use think\db\exception\ModelNotFoundException; /** * 服务类:微信公众号 * Class Wxofficial * @package app\api\service */ class Wxofficial extends BaseService { /** * 微信SDK应用类 * @var Application|null */ private ?Application $app = null; /** * 获取授权登录地址 * @param string $callbackUrl 回调的h5页面 * @return string * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ public function getOauthUrl(string $callbackUrl): string { return $this->getApp()->oauth->redirect($callbackUrl)->getTargetUrl(); } /** * 获取微信公众号基础设置 * @return array * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ private function getWxofficialSetting(): array { $setting = WxofficialSetting::getItem('basic'); return [ 'app_id' => $setting['appId'], 'secret' => $setting['appSecret'] ]; } /** * 获取微信用户信息 * @return array * @throws BaseException */ public function getOauthUserInfo(): array { try { // 获取微信用户信息 $userInfo = $this->getApp()->oauth->user(); // 将敏感信息加密 $encrypted = $this->encryptData([ 'openid' => $userInfo['original']['openid'], 'unionid' => $userInfo['original']['unionid'] ?? '', ]); return [ 'userInfo' => [ 'nickName' => $userInfo['original']['nickname'], 'avatarUrl' => $userInfo['original']['headimgurl'], 'gender' => $userInfo['original']['sex'] ], 'encryptedData' => $encrypted['encryptedData'], 'iv' => $encrypted['iv'], ]; } catch (\Throwable $e) { throwError('获取微信用户信息失败:' . $e->getMessage()); } } /** * 获取微信公众号jssdk配置参数 * @param string $url 用户端完整的url * @return array * @throws InvalidArgumentException * @throws InvalidConfigException * @throws RuntimeException * @throws \Psr\SimpleCache\InvalidArgumentException * @throws DataNotFoundException * @throws DbException * @throws ModelNotFoundException */ public function getJssdkConfig(string $url): array { return $this->getApp()->jssdk->buildConfig([ 'checkJsApi', 'updateAppMessageShareData', 'updateTimelineShareData', 'onMenuShareAppMessage', 'onMenuShareTimeline', 'onMenuShareQQ', 'onMenuShareWeibo', 'onMenuShareQZone', 'hideOptionMenu', ], false, false, false, [], $url); } /** * 微信SDK应用类 * @return Application * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException */ private function getApp(): ?Application { if (!$this->app) { $setting = $this->getWxofficialSetting(); $this->app = Factory::officialAccount($setting); } return $this->app; } /** * 加密敏感信息 * @param array $plainData * @return array */ private function encryptData(array $plainData): array { $WXBizDataCrypt = new WXBizDataCrypt; $iv = $WXBizDataCrypt->createIv(); $encryptedData = ''; $plaintext = helper::jsonEncode($plainData); $WXBizDataCrypt->encryptData($plaintext, $iv, $encryptedData); return compact('iv', 'encryptedData'); } }