123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625 |
- <?php
- namespace app\adminapi\controller\v1\merchant;
- use app\adminapi\controller\AuthController;
- use app\lib\wx_encode\WXBizMsgCrypt;
- use app\models\merchant\MerchantCodeAudit;
- use app\models\merchant\MerchantMiniprogram;
- use app\models\merchant\Merchant;
- use app\Request;
- use crmeb\basic\BaseModel;
- use crmeb\services\CacheService;
- use crmeb\services\UtilService;
- use Psr\SimpleCache\InvalidArgumentException;
- use SimpleXMLElement;
- use think\db\exception\DbException;
- use think\Exception;
- use think\facade\Log;
- class Open extends AuthController
- {
- protected $encodingAesKey = ''; //第三方平台解密key
- protected $appId = ''; //第三方平台appid
- protected $appSecret = ''; //第三方平台appSecret
- protected $token = ''; //第三方平台消息验证token
- public function __construct(\think\facade\App $app, $escape = false)
- {
- if (!$escape) {
- parent::__construct($app);
- } else {
- $this->app = $app;
- $this->request = app('request');
- $this->initialize($escape);
- }
- }
- public function initialize($escape = false)
- {
- if (!($this->request->action() == 'wxTicketCallback') && !($this->request->action() == 'wxCallback') && !$escape) {
- parent::initialize();
- }
- $this->encodingAesKey = config('third.encodingAesKey');
- $this->appId = config('third.appId');
- $this->appSecret = config('third.appSecret');
- $this->token = config('third.token');
- }
- /**
- * 票据获取接口
- * @param Request $request
- * @throws InvalidArgumentException
- */
- public function wxTicketCallback(Request $request)
- {
- $msg = '';
- $timeStamp = $request->param('timestamp', '');
- $nonce = $request->param('nonce', '');
- $msg_sign = $request->param('msg_signature', '');
- $encryptMsg = file_get_contents('php://input');
- $pc = new WXBizMsgCrypt($this->token, $this->encodingAesKey, $this->appId);
- $errCode = $pc->decryptMsg($msg_sign, $timeStamp, $nonce, $encryptMsg, $msg);
- if ($errCode == 0) {
- $data = $this->_xmlToArr($msg);
- switch ($data['InfoType']) {
- case'component_verify_ticket':
- //接收验证票据
- CacheService::redisHandler()->set('component_verify_ticket', $data['ComponentVerifyTicket']);
- break;
- case 'unauthorized';
- //todo 发送授权取消通知
- break;
- case 'updateauthorized':
- //todo 发送授权更新通知
- break;
- case 'authorized':
- //todo 发送授权成功通知
- break;
- default:
- break;
- }
- echo 'success';
- } else {
- echo '解密失败' . $errCode;
- }
- }
- /**
- * 消息与事件接受接口
- * @param $appid
- * @param Request $request
- */
- public function wxCallback($appid, Request $request)
- {
- $msg = '';
- $timeStamp = $request->param('timestamp', '');
- $nonce = $request->param('nonce', '');
- $msg_sign = $request->param('msg_signature', '');
- $encryptMsg = file_get_contents('php://input');
- $pc = new WXBizMsgCrypt($this->token, $this->encodingAesKey, $this->appId);
- Log::error('77777777777');
- Log::error($msg_sign);
- Log::error($timeStamp);
- Log::error($nonce);
- Log::error($encryptMsg);
- Log::error($msg);
- $errCode = $pc->decryptMsg($msg_sign, $timeStamp, $nonce, $encryptMsg, $msg);
- Log::error($errCode);
- Log::error($this->_xmlToArr($msg));
- @file_put_contents('call_back_log.txt', '[' . date('Y-m-d H:i:s') . ']' . json_encode($data) . PHP_EOL, FILE_APPEND);
- if ($errCode == 0) {
- $data = $this->_xmlToArr($msg);
- @file_put_contents('call_back_log.txt', '[' . date('Y-m-d H:i:s') . ']' . json_encode($data) . PHP_EOL, FILE_APPEND);
- $mer_id = MerchantMiniprogram::where(['appid' => $appid])->value('mer_id');
- BaseModel::beginTrans();
- try {
- switch ($data['Event']) {
- case'weapp_audit_success':
- $info = MerchantCodeAudit::where('mer_id', $mer_id)->where('status', 2)->order('commit_time', 'desc')->find();
- $info->save(['success_time' => $data['SuccTime'], 'status' => 0]);
- //todo 某小程序代码审核通过
- break;
- case 'weapp_audit_fail';
- $info = MerchantCodeAudit::where('mer_id', $mer_id)->where('status', 2)->order('commit_time', 'desc')->find();
- $info->save(['fail_time' => $data['FailTime'], 'status' => 1, 'reason' => $data['Reason'], 'screenshot' => $data['ScreenShot']]);
- //todo 某小程序代码审核不通过
- break;
- case 'weapp_audit_delay':
- $info = MerchantCodeAudit::where('mer_id', $mer_id)->where('status', 2)->order('commit_time', 'desc')->find();
- $info->save(['delay_time' => $data['DelayTime'], 'status' => 4, 'reason' => $data['Reason']]);
- //todo 某小程序代码核延后
- break;
- default:
- break;
- }
- BaseModel::commitTrans();
- echo 'success';
- } catch (Exception $e) {
- BaseModel::rollbackTrans();
- echo $e->getMessage();
- } catch (DbException $e) {
- BaseModel::rollbackTrans();
- echo $e->getMessage();
- }
- } else {
- BaseModel::rollbackTrans();
- echo '解密失败' . $errCode;
- }
- }
- /**
- * @param $xml
- * @return mixed|SimpleXMLElement
- */
- protected function _xmlToArr($xml)
- {
- $res = @simplexml_load_string($xml, NULL, LIBXML_NOCDATA);
- $res = json_decode(json_encode($res), true);
- return $res;
- }
- /**
- * 获取令牌
- * @return mixed
- * @throws \Exception
- * @throws InvalidArgumentException
- */
- public function getComponentAccessToken()
- {
- try {
- if (CacheService::redisHandler()->get('component_access_token')) {
- return CacheService::redisHandler()->get('component_access_token');
- }
- $url = 'https://api.weixin.qq.com/cgi-bin/component/api_component_token';
- $data = [
- 'component_appid' => $this->appId,
- 'component_appsecret' => $this->appSecret,
- 'component_verify_ticket' => CacheService::redisHandler()->get('component_verify_ticket'),
- ];
- // $data['component_verify_ticket'] = 'ticket@@@iWDHjOTCGw8wIGeopp1Nux6gbi7KYD-MtFroWBw6WkEReGbCQWBesNMd-c3LlaR07J1cx4AQF48LYDMmcmdqZQ';
- $res = json_decode(doRequest($url, $data, null, true, true), true);
- if (isset($res['component_access_token'])) {
- CacheService::redisHandler()->set('component_access_token', $res['component_access_token'], $res['expires_in']);
- return $res['component_access_token'];
- } else {
- throw exception($res['errmsg'] ?? $res['msg'] ?? '请求错误');
- }
- } catch (Exception $e) {
- throw exception($e->getMessage());
- }
- }
- /**
- * 获取预授权码
- * @return mixed
- * @throws \Exception
- * @throws InvalidArgumentException
- */
- protected function getPreAuthCode()
- {
- try {
- if (CacheService::redisHandler()->get('pre_auth_code')) {
- return CacheService::redisHandler()->get('pre_auth_code');
- }
- $component_access_token = $this->getComponentAccessToken();
- $url = 'https://api.weixin.qq.com/cgi-bin/component/api_create_preauthcode?component_access_token=' . $component_access_token;
- $data = [
- 'component_appid' => $this->appId,
- ];
- $res = json_decode(doRequest($url, $data, null, true, true), true);
- if (isset($res['pre_auth_code'])) {
- CacheService::redisHandler()->set('pre_auth_code', $res['pre_auth_code'], $res['expires_in']);
- return $res['pre_auth_code'];
- } else {
- throw exception($res['errmsg'] ?? $res['msg'] ?? '请求错误');
- }
- } catch (Exception $e) {
- throw exception($e->getMessage());
- }
- }
- /**
- * 生成授权地址
- * @param string $re_url 回调地址
- * @param int $type 授权地址类型:1桌面端,其他移动端
- * @return mixed
- * @throws InvalidArgumentException
- */
- public function createAuthUrl($type = 1)
- {
- try {
- $re_url = $this->request->get('re_url');
- if (!$re_url) {
- return app('json')->fail('请传入回调地址');
- }
- $url_base = $type == 1 ? 'https://mp.weixin.qq.com/cgi-bin/componentloginpage?component_appid=' : 'https://mp.weixin.qq.com/safe/bindcomponent?action=bindcomponent&auth_type=3&no_scan=1&component_appid=';
- $pre_auth_code = $this->getPreAuthCode();
- $url = $url_base . $this->appId
- . '&pre_auth_code=' . $pre_auth_code
- . '&redirect_uri=' . $re_url;//todo 改成前端的接收页面
- if ($type != 1) {
- $url .= '#wechat_redirect';
- }
- return app('json')->success('ok', ['url' => $url]);
- } catch (Exception $e) {
- return app('json')->fail($e->getMessage(), ['file' => $e->getFile(), 'line' => $e->getLine()]);
- }
- }
- /**
- * 接收授权码
- * @param $mer_id
- * @param Request $request
- * @return mixed
- * @throws InvalidArgumentException
- */
- public function wxAuthRedirect(Request $request, $mer_id)
- {
- $auth_code = $request->post('authorization_code');
- $expires_in = $request->post('expires_in');
- if ($auth_code && $expires_in) {
- try {
- CacheService::redisHandler()->set($mer_id . '_authorization_code', $auth_code, $expires_in);
- //return $this->getAuthInfo(['mer_id' => $mer_id]);
- return app('json')->success('获取授权码成功');
- } catch (Exception $e) {
- return app('json')->fail($e->getMessage(), ['file' => $e->getFile(), 'line' => $e->getLine()]);
- }
- } else {
- return app('json')->fail('获取授权码失败');
- }
- }
- /**
- *使用授权码获取授权信息
- * @param array $param
- * @return mixed
- * @throws \Exception
- * @throws InvalidArgumentException
- */
- protected function getAuthInfo($param = ['mer_id' => ''])
- {
- BaseModel::beginTrans();
- try {
- $mer_id = $param['mer_id'] ?? '';
- if (!$mer_id) {
- BaseModel::rollbackTrans();
- throw exception('未找到商家');
- }
- $mer_info = Merchant::get($mer_id);
- if (!$mer_info) {
- BaseModel::rollbackTrans();
- throw exception('未找到商家');
- }
- $authorization_code = CacheService::redisHandler()->get($param['mer_id'] . '_authorization_code');
- if (!$authorization_code) {
- BaseModel::rollbackTrans();
- throw exception('请先获取授权码');
- }
- $component_access_token = $this->getComponentAccessToken();
- $url = 'https://api.weixin.qq.com/cgi-bin/component/api_query_auth?component_access_token=' . $component_access_token;
- $data = [
- 'component_appid' => $this->appId,
- 'authorization_code' => $authorization_code,
- ];
- $res = json_decode(doRequest($url, $data, null, true, true), true);
- if (isset($res['authorization_info'])) {
- //保存/更新内容到商户小程序表
- if (MerchantMiniprogram::vaildWhere()->where(['mer_id' => $mer_id])->find()) {
- MerchantMiniprogram::vaildWhere()->where('mer_id', $mer_id)->update([
- 'appid' => $res['authorization_info']['authorizer_appid'],
- 'authorizer_refresh_token' => $res['authorization_info']['authorizer_refresh_token'],
- 'func_info' => json_encode($res['authorization_info']),
- 'update' => time(),
- ]);
- BaseModel::commitTrans();
- } else {
- $app_secret = self::createAppSecret();
- MerchantMiniprogram::create([
- 'mer_id' => $mer_id,
- 'appid' => $res['authorization_info']['authorizer_appid'],
- 'authorizer_refresh_token' => $res['authorization_info']['authorizer_refresh_token'],
- 'func_info' => json_encode($res['authorization_info']),
- 'add_time' => time(),
- 'update' => time(),
- 'boofly_app_secret' => $app_secret,
- ]);
- BaseModel::commitTrans();
- }
- //保存authorizer_access_token到redis,过期时间为expires_in
- CacheService::redisHandler()->set($mer_id . '_authorizer_access_token', $res['authorization_info']['authorizer_access_token'], $res['authorization_info']['expires_in']);
- return array_merge($res['authorization_info'], ['boofly_app_secret' => $app_secret ?? '']);
- } else {
- BaseModel::rollbackTrans();
- throw exception($res['errmsg'] ?? $res['msg'] ?? '请求错误');
- }
- } catch (Exception $e) {
- BaseModel::rollbackTrans();
- throw exception($e->getMessage());
- } catch (DbException $e) {
- BaseModel::rollbackTrans();
- throw exception($e->getMessage());
- }
- }
- /**
- * 创建app_secret
- * @return string
- * @throws \Exception
- */
- private static function createAppSecret()
- {
- return md5(bin2hex(random_bytes(8)));
- }
- /**
- *获取/刷新商户接口调用令牌
- * @param array $param
- * @return mixed
- * @throws InvalidArgumentException
- * @throws \Exception
- */
- public function getAuthorizerAccessToken($param = ['mer_id' => '', 'get_token' => 1, 'return_array' => false])
- {
- BaseModel::beginTrans();
- try {
- $mer_id = $param['mer_id'] ?? '';
- $get_token = isset($param['get_token']) ? $param['get_token'] : 1;
- $return_array = isset($param['return_array']) ? $param['return_array'] : false;
- if (!$mer_id) {
- throw exception('未找到商家');
- }
- if (CacheService::redisHandler()->get($mer_id . '_authorizer_access_token') && $get_token == 1) {
- BaseModel::commitTrans();
- return CacheService::redisHandler()->get($mer_id . '_authorizer_access_token');
- }
- // 根据商户id从商户表获取authorizer_appid和authorizer_refresh_token
- $authorizer_info = MerchantMiniprogram::vaildWhere()->where(['mer_id' => $mer_id])->find();
- if (!$authorizer_info) {
- throw exception('未找到商家');
- }
- $component_access_token = $this->getComponentAccessToken();
- $url = 'https://api.weixin.qq.com/cgi-bin/component/api_authorizer_token?component_access_token=' . $component_access_token;
- $data = [
- 'component_appid' => $this->appId,
- 'authorizer_appid' => $authorizer_info['appid'],
- 'authorizer_refresh_token' => $authorizer_info['authorizer_refresh_token'],
- ];
- $res = json_decode(doRequest($url, $data, null, true, true), true);
- if (isset($res['authorizer_access_token'])) {
- MerchantMiniprogram::vaildWhere()->where('mer_id', $mer_id)->update([
- 'authorizer_refresh_token' => $res['authorizer_refresh_token'],
- 'update' => time(),
- ]);
- BaseModel::commitTrans();
- //保存新的authorizer_access_token到redis,过期时间为expires_in
- CacheService::redisHandler()->set($mer_id . '_authorizer_access_token', $res['authorizer_access_token'], $res['expires_in']);
- return $return_array ? ['access_token' => $res['authorizer_access_token'], 'expires_in' => $res['expires_in']] : $res['authorizer_access_token'];
- } else {
- BaseModel::rollbackTrans();
- throw exception($res['errmsg'] ?? $res['msg'] ?? '请求错误');
- }
- } catch (Exception $e) {
- BaseModel::rollbackTrans();
- throw exception($e->getMessage());
- } catch (DbException $e) {
- BaseModel::rollbackTrans();
- throw exception($e->getMessage());
- }
- }
- /**
- * 获取授权方的帐号基本信息
- * 包括头像、昵称、帐号类型、认证类型、微信号、原始ID和二维码图片URL
- * 具体参数详见https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/api/api_get_authorizer_info.html#%E5%85%AC%E4%BC%97%E5%8F%B7%E5%B8%90%E5%8F%B7%E4%BF%A1%E6%81%AF
- * @param array $param
- * @return mixed
- * @throws InvalidArgumentException
- * @throws \Exception
- */
- protected function getAuthorizerInfo($param = ['mer_id' => ''])
- {
- BaseModel::beginTrans();
- try {
- $mer_id = $param['mer_id'] ?? '';
- if (!$mer_id) {
- BaseModel::rollbackTrans();
- throw exception('未找到商家');
- }
- //根据商户id从商户表获取authorizer_appid和authorizer_refresh_token
- $authorizer_info = MerchantMiniprogram::vaildWhere()->where(['mer_id' => $mer_id])->find();
- if (!$authorizer_info) {
- BaseModel::rollbackTrans();
- throw exception('未找到商家');
- }
- $component_access_token = $this->getComponentAccessToken();
- $url = 'https://api.weixin.qq.com/cgi-bin/component/api_get_authorizer_info?component_access_token=' . $component_access_token;
- $data = [
- 'component_appid' => $this->appId,
- 'authorizer_appid' => $authorizer_info['appid'],
- ];
- $res = json_decode(doRequest($url, $data, null, true, true), true);
- if (isset($res['authorizer_info'])) {
- //更新商户信息到商户表
- MerchantMiniprogram::vaildWhere()->where('mer_id', $mer_id)->update([
- 'nick_name' => $res['authorizer_info']['nick_name'],
- 'head_img' => $res['authorizer_info']['head_img'],
- 'signature' => $res['authorizer_info']['signature'],
- 'principal_name' => $res['authorizer_info']['principal_name'],
- 'categories' => $res['authorizer_info']['nick_name'],
- 'business_info' => json_encode($res['authorizer_info']['business_info']),
- 'service_type_info' => $res['authorizer_info']['service_type_info']['id'],
- 'user_name' => $res['authorizer_info']['user_name'],
- 'qrcode_url' => $res['authorizer_info']['qrcode_url'],
- 'update' => time(),
- ]);
- BaseModel::commitTrans();
- // CacheService::redisHandler()->set($mer_id . '_authorizer_access_token', $res['authorizer_access_token'], $res['expires_in']);
- return $res;
- } else {
- BaseModel::rollbackTrans();
- throw exception($res['errmsg'] ?? $res['msg'] ?? '请求错误');
- }
- } catch (Exception $e) {
- BaseModel::rollbackTrans();
- throw exception($e->getMessage());
- } catch (DbException $e) {
- BaseModel::rollbackTrans();
- throw exception($e->getMessage());
- }
- }
- /**
- *获取授权方选项信息(可能不常用)
- * 如:地理位置上报,语音识别开关,多客服开关
- * @param array $param
- * @return mixed
- * @throws InvalidArgumentException
- * @throws \Exception
- */
- protected function getAuthorizerOption($param = ['mer_id' => '', 'option_name' => ''])
- {
- try {
- $mer_id = $param['mer_id'] ?? '';
- $option_name = $param['option_name'] ?? '';
- if (!$mer_id) {
- throw exception('未找到商家');
- }
- //根据商户id从商户表获取authorizer_appid和authorizer_refresh_token
- $authorizer_info = MerchantMiniprogram::vaildWhere()->where(['mer_id' => $mer_id])->find();
- if (!$authorizer_info) {
- throw exception('未找到商家');
- }
- $component_access_token = $this->getComponentAccessToken();
- $url = 'https://api.weixin.qq.com/cgi-bin/component/api_get_authorizer_option?component_access_token=' . $component_access_token;
- $data = [
- 'component_appid' => $this->appId,
- 'authorizer_appid' => $authorizer_info['appid'],
- 'option_name' => $option_name,
- ];
- $res = json_decode(doRequest($url, $data, null, true, true), true);
- if (isset($res['option_value'])) {
- return $res['option_value'];
- } else {
- throw exception($res['errmsg'] ?? $res['msg'] ?? '请求错误');
- }
- } catch (Exception $e) {
- throw exception($e->getMessage());
- }
- }
- /**
- * 设置授权方选项信息
- * @param $mer_id
- * @param $option_name
- * @param $option_value
- * @return mixed
- * @throws InvalidArgumentException
- * @throws \Exception
- */
- public function setAuthorizerOption($mer_id, $option_name, $option_value)
- {
- try {
- if (!$mer_id) {
- return app('json')->fail('未找到商家');
- }
- //根据商户id从商户表获取authorizer_appid和authorizer_refresh_token
- $authorizer_info = MerchantMiniprogram::vaildWhere()->where(['mer_id' => $mer_id])->find();
- if (!$authorizer_info) {
- throw exception('未找到商家');
- }
- $component_access_token = $this->getComponentAccessToken();
- $url = 'https://api.weixin.qq.com/cgi-bin/component/api_set_authorizer_option?component_access_token=' . $component_access_token;
- $data = [
- 'component_appid' => $this->appId,
- 'authorizer_appid' => $authorizer_info['appid'],
- 'option_name' => $option_name,
- 'option_value' => $option_value,
- ];
- $res = json_decode(doRequest($url, $data, null, true, true), true);
- if (isset($res['errcode'])) {
- if ($res['errcode'] == 0) {
- return app('json')->success('设置成功');
- } else {
- return app('json')->fail($res['errmsg']);
- }
- } else {
- return app('json')->fail($res['errmsg'] ?? $res['msg'] ?? '请求错误');
- }
- } catch (Exception $e) {
- return app('json')->fail($e->getMessage(), ['file' => $e->getFile(), 'line' => $e->getLine()]);
- }
- }
- /**
- * 拉取所有已授权的帐号信息
- * @param array $page
- * @return mixed
- * @throws InvalidArgumentException
- * @throws \Exception
- */
- protected function getAuthorizerList($page = ['offset' => 1, 'count' => 10])
- {
- $offset = $page['offset'] ?? 1;
- $count = $page['count'] ?? 10;
- BaseModel::beginTrans();
- try {
- $component_access_token = $this->getComponentAccessToken();
- $url = 'https://api.weixin.qq.com/cgi-bin/component/api_get_authorizer_list?component_access_token=' . $component_access_token;
- $data = [
- 'component_appid' => $this->appId,
- 'offset' => $offset,
- 'count' => $count,
- ];
- $res = json_decode(doRequest($url, $data, null, true, true), true);
- if (isset($res['total_count'])) {
- foreach ($res['list'] as $v) {
- MerchantMiniprogram::vaildWhere()->where('appid', $v['authorizer_appid'])->update(['authorizer_refresh_token' => $v['refresh_token'], 'update' => time()]);
- }
- BaseModel::commitTrans();
- return $res;
- } else {
- BaseModel::rollbackTrans();
- throw exception($res['errmsg'] ?? '请求错误');
- }
- } catch (Exception $e) {
- BaseModel::rollbackTrans();
- throw exception($e->getMessage());
- } catch (DbException $e) {
- BaseModel::rollbackTrans();
- throw exception($e->getMessage());
- }
- }
- /**
- * 前端获取某些信息
- * @param Request $request
- * @param string $info_type 获取的信息类型
- * @return mixed
- */
- public function getInfoForFront(Request $request, $info_type = 'AuthorizerAccessToken')
- {
- try {
- $function = 'get' . $info_type;
- if (method_exists($this, $function)) {
- if (!$request->param()) {
- $res = $this->$function();
- } else {
- $res = $this->$function($request->param());
- }
- return app('json')->success('ok', ['res' => $res]);
- } else {
- return app('json')->fail('获取失败');
- }
- } catch (Exception $e) {
- return app('json')->fail($e->getMessage(), ['file' => $e->getFile(), 'line' => $e->getLine()]);
- }
- }
- }
|