appId = $this->config['appid']; $this->secret = $this->config['secret']; } /** * @link https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/login/auth.code2Session.html * @desc 使用授权code换取openid * @param string $code * @return array */ public function code2Openid(string $code): array { $url = 'https://api.weixin.qq.com/sns/jscode2session'; $res = Curl::requestCurl($url, 'GET', [], http_build_query([ 'appid' => $this->appId, 'secret' => $this->secret, 'js_code' => $code, 'grant_type' => 'authorization_code' ])); return $res ? json_decode($res, true) : []; } /** * @link https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/signature.html * @desc 解密小程序信息 * @param string $sessionKey session_key * @param string $encryptedData 加密字符 * @param string $iv 偏移量 * @return array */ public function decrypt($sessionKey, $encryptedData, $iv): array { if (strlen($iv) != 24) { // 偏移量错误 return ['code' => 41002, 'data' => '', 'msg' => 'iv解密失败']; } if (strlen($sessionKey) != 24) { // sessionkey 错误 return ['code' => 41001, 'data' => '', 'msg' => 'sessionKey解密失败']; } $data = openssl_decrypt(base64_decode($encryptedData), 'AES-128-CBC', base64_decode($sessionKey), OPENSSL_RAW_DATA, base64_decode($iv)); if (!$data) { return ['code' => 41001, 'data' => '', 'msg' => '解密失败']; } $userInfo = json_decode($data, true); if ($userInfo['watermark']['appid'] != $this->appId) { return ['code' => 41003, 'data' => '', 'msg' => 'appid不匹配']; } $userInfo['nickName'] = !empty($userInfo['nickName']) ? $userInfo['nickName'] : ''; return ['code' => 0, 'data' => $userInfo, 'msg' => 'success']; } /** * @link https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/qr-code/wxacode.createQRCode.html * @desc 获取小程序码(限量) * @param string $path 页面路径 * @param int $width 二维码宽度 * */ public function qrcode(string $path, $width = 430) { $params = ['path' => $path, 'width' => $width]; $url = 'https://api.weixin.qq.com/cgi-bin/wxaapp/createwxaqrcode?access_token=' . $this->accessToken(); return Curl::requestCurl($url, 'POST', [], json_encode($params)); } /** * @link https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/qr-code/wxacode.getUnlimited.html * @desc 获取小程序码(不限量) * @param string $scene 场景值 * @param array $extra 额外参数,详见 * @return bool|mixed|string */ public function qrcodeUnlimited(string $scene, $extra = []) { $params = array_merge($extra, ['scene' => $scene]); $url = 'https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=' . $this->accessToken(); return Curl::requestCurl($url, 'POST', [], json_encode($params)); } /** * @link https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/url-link/urllink.generate.html * @desc 生成短链接 * @param array $params * @return bool|string */ public function urlLink(array $params) { $url = 'https://api.weixin.qq.com/wxa/generate_urllink?access_token=' . $this->accessToken(); return Curl::requestCurl($url, 'POST', [], json_encode($params)); } /** * @link https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/subscribe-message/subscribeMessage.send.html * @desc 发送模板消息 * @param string $openid 小程序openid * @param string $template 模板ID * @param array $data 小程序数据 * @param string $page 跳转页面 * @param string $state 小程序状态 * @return bool|mixed */ public function sendMiniMsg(string $openid, string $template, array $data, string $page = null, string $state = 'normal'): array { $params = [ 'touser' => $openid, 'template_id' => $template, 'miniprogram_state' => $state, 'data' => $data ]; if ($page) { $params['page'] = $page; } $url = 'https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=' . $this->accessToken(); $res = Curl::requestCurl($url, 'POST', [], json_encode($params)); return $res ? json_decode($res, true) : []; } /** * @link https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/access-token/auth.getAccessToken.html * @desc 获取全局唯一接口调用凭据 * @param int $repeatCnt * @return string */ public function accessToken(&$repeatCnt = 0) { $drive = $this->config['token_drive'] ?? 'redis'; $key = 'mini_' . $this->appId . '_accessToken'; switch ($drive) { case 'redis': $redis = Redis::instance(); $redis->select(15); $token = $redis->get($key); break; case 'db': default: $token = Db::table('configs')->where('c_key', $key)->where('c_expired > ' . time())->value('c_value'); break; } var_dump($token); if ($token) { return $token; } var_dump('jinru'); $url = 'https://api.weixin.qq.com/cgi-bin/token'; $res = Curl::requestCurl($url, 'GET', [], http_build_query([ 'grant_type' => 'client_credential', 'appid' => $this->appId, 'secret' => $this->secret ])); $data = json_decode($res, true); if (isset($data['access_token'])) { $token = $data['access_token']; switch ($drive) { case 'redis': $redis->setex($key, 7000, $token); break; case 'db': default: $isWin = Db::table('configs')->where('c_key',$key)->value('c_value'); if ($isWin){ Db::table('configs') ->where('c_key', $key) ->update([ 'c_value' => $token, 'c_expired' => time() + 7000, 'c_updated' => date('Y-m-d H:i:s') ]); }else{ Db::table('configs') ->insert([ 'c_key' => $key, 'c_value' => $token, 'c_expired' => time() + 7000, 'c_updated' => date('Y-m-d H:i:s') ]); } break; } return $token; } else { if ($repeatCnt <= 3) { $repeatCnt++; return $this->accessToken($repeatCnt); } else { return $data['errcode']; } } } }