开发文档:https://open.work.weixin.qq.com/api/doc/90000/90135/90664
一、效果图
二、开发流程
1、创建应用
2、配置应用
三、简单代码
1、授权登录
2、回调
helper.php
/**
* GET 请求
* @param string $url
*/
function http_get($url){
$oCurl = curl_init();
if(stripos($url,"https://")!==FALSE){
curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($oCurl, CURLOPT_SSLVERSION, 1); //CURL_SSLVERSION_TLSv1
}
curl_setopt($oCurl, CURLOPT_URL, $url);
curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, 1 );
curl_setopt($oCurl, CURLOPT_VERBOSE, 1);
curl_setopt($oCurl, CURLOPT_HEADER, 1);
// $sContent = curl_exec($oCurl);
// $aStatus = curl_getinfo($oCurl);
$sContent = execCURL($oCurl);
curl_close($oCurl);
return $sContent;
}
/**
* POST 请求
* @param string $url
* @param array $param
* @param boolean $post_file 是否文件上传
* @return string content
*/
function http_post($url,$param,$post_file=false){
$oCurl = curl_init();
if(stripos($url,"https://")!==FALSE){
curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($oCurl, CURLOPT_SSLVERSION, 1); //CURL_SSLVERSION_TLSv1
}
if(PHP_VERSION_ID >= 50500 && class_exists('\CURLFile')){
$is_curlFile = true;
}else {
$is_curlFile = false;
if (defined('CURLOPT_SAFE_UPLOAD')) {
curl_setopt($oCurl, CURLOPT_SAFE_UPLOAD, false);
}
}
if($post_file) {
if($is_curlFile) {
foreach ($param as $key => $val) {
if(isset($val["tmp_name"])){
$param[$key] = new \CURLFile(realpath($val["tmp_name"]),$val["type"],$val["name"]);
}else if(substr($val, 0, 1) == '@'){
$param[$key] = new \CURLFile(realpath(substr($val,1)));
}
}
}
$strPOST = $param;
}else{
$strPOST = json_encode($param);
}
curl_setopt($oCurl, CURLOPT_URL, $url);
curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, 1 );
curl_setopt($oCurl, CURLOPT_POST,true);
curl_setopt($oCurl, CURLOPT_POSTFIELDS,$strPOST);
curl_setopt($oCurl, CURLOPT_VERBOSE, 1);
curl_setopt($oCurl, CURLOPT_HEADER, 1);
// $sContent = curl_exec($oCurl);
// $aStatus = curl_getinfo($oCurl);
$sContent = execCURL($oCurl);
curl_close($oCurl);
return $sContent;
}
/**
* 执行CURL请求,并封装返回对象
*/
function execCURL($ch){
$response = curl_exec($ch);
$error = curl_error($ch);
$result = array( 'header' => '',
'content' => '',
'curl_error' => '',
'http_code' => '',
'last_url' => '');
if ($error != ""){
$result['curl_error'] = $error;
return $result;
}
$header_size = curl_getinfo($ch,CURLINFO_HEADER_SIZE);
$result['header'] = str_replace(array("\r\n", "\r", "\n"), "<br/>", substr($response, 0, $header_size));
$result['content'] = substr( $response, $header_size );
$result['http_code'] = curl_getinfo($ch,CURLINFO_HTTP_CODE);
$result['last_url'] = curl_getinfo($ch,CURLINFO_EFFECTIVE_URL);
$result["base_resp"] = array();
$result["base_resp"]["ret"] = $result['http_code'] == 200 ? 0 : $result['http_code'];
$result["base_resp"]["err_msg"] = $result['http_code'] == 200 ? "ok" : $result["curl_error"];
return $result;
}
//给URL地址追加参数
function appendParamter($url,$key,$value){
return strrpos($url,"?",0) > -1 ? "$url&$key=$value" : "$url?$key=$value";
}
//生成指定长度的随机字符串
function createNonceStr($length = 16) {
$chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
$str = "";
for ($i = 0; $i < $length; $i++) {
$str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
}
return $str;
}
//读取本地文件
function get_php_file($filename) {
if(file_exists($filename)){
return trim(substr(file_get_contents($filename), 15));
}else{
return '{"expire_time":0}';
}
}
//写入本地文件
function set_php_file($filename, $content) {
$fp = fopen($filename, "w");
fwrite($fp, "<?php exit();?>" . $content);
fclose($fp);
}
//加载本地的应用配置文件
function loadConfig(){
return json_decode(get_php_file("../config.php"));
}
//根据应用ID获取应用配置
function getConfigByAgentId($id){
$configs = loadConfig();
foreach ($configs->AppsConfig as $key => $value) {
if($value->AgentId == $id){
$config = $value;
break;
}
}
return $config;
}
/**
* 日志函数
* @param $msg
* @param string $filename
*/
function write_log($msg, $filename='msg')
{
$file = fopen("./$filename.log", "a");
$msg = "[" . date("Y-m-d H:i:s") . "] - " . $msg;
fwrite($file, $msg . "\n");
fclose($file);
}
/**
* 设置缓存,按需重载
* @param string $cachename
* @param mixed $value
* @param int $expired
* @return boolean
*/
function setCache($cachename, $value, $expired)
{
//TODO: set cache implementation
$content = var_export(array('access_token' => $value, 'expires_in' => $expired), true);
file_put_contents($cachename.".php", "<?php return " . $content . ";");
return false;
}
/**
* 获取缓存,按需重载
* @param string $cachename
* @return mixed
*/
function getCache($cachename, $expired = 7100)
{
if(!file_exists($cachename.".php")){
return false;
}
$access_token_array = include($cachename.".php");
if (filemtime($cachename.".php") + $expired > time()) {
return $access_token_array['access_token'];
}
return false;
}
//=======================================后端函数=====================================================
/**
* 获取第三方应用凭证(suite_access_token)。
* @param $suite_id
* @param $suite_secret
* @param $suite_ticket
*/
function getSuiteAccessToken($suite_id, $suite_secret, $suite_ticket) {
$cachename = './cache/suite_access_token';
$access_token = getCache($cachename);
if (!$access_token){
$url = "https://qyapi.weixin.qq.com/cgi-bin/service/get_suite_token";
$data = array(
'suite_id' => trim($suite_id),
'suite_secret' => trim($suite_secret),
'suite_ticket' => trim($suite_ticket)
);
$response = http_post($url, $data);
if ($response['base_resp']['ret'] == 0) {
$data = json_decode($response['content'], true);
$access_token = $data['suite_access_token'];
setCache($cachename, $access_token, $data['expires_in']);
}
}
return $access_token;
}
/**
* 发送消息
* @param $corpId
* @param $secret
* @param $touser
* @param $msgtype
* @param $agentid
* @param $content
*/
function sendAgentMessage($corpId, $secret,$agentid, $touser, $msgtype, $title, $content, $urls)
{
$access_token = getAccessToken($corpId, $secret);
$url = "https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=".$access_token;
$data = array(
'touser' => $touser,
'msgtype' => $msgtype,
'agentid' => $agentid,
'textcard' => array(
'title' => $title,
'description' => $content,
'url' => $urls,
'btntxt' => '查看详情'
)
);
$response = http_post($url, $data);
return $response['base_resp'];
}
/**
* 获取预授权码。预授权码用于企业授权时的第三方服务商安全验证。
* @param $suite_access_token
* @return mixed
*/
function getPreAuthCode($suite_access_token) {
$cachename = './cache/pre_auth_code';
$access_token = getCache($cachename, 3500);
if (!$access_token){
$url = "https://qyapi.weixin.qq.com/cgi-bin/service/get_pre_auth_code?suite_access_token=".$suite_access_token;
$response = http_get($url);
if ($response['base_resp']['ret'] == 0) {
write_log($response['content'], 'api');
$data = json_decode($response['content'], true);
$access_token = $data['pre_auth_code'];
setCache($cachename, $access_token, $data['expires_in']);
}
}
return $access_token;
}
/**
* 获取企业永久授权码
* @param $auth_code 临时授权码
* @return null
*/
function getPermanentCode($auth_code){
$cachename = './cache/suite_access_token';
$access_token = getCache($cachename);
if ($access_token){
$url = "https://qyapi.weixin.qq.com/cgi-bin/service/get_permanent_code?suite_access_token=".$access_token;
$data = array(
'auth_code' => $auth_code
);
$response = http_post($url, $data);
if ($response['base_resp']['ret'] == 0) {
return $response['content'];
}
}
return null;
}
//=======================================后端函数=====================================================
//=======================================前端函数=====================================================
/**
* 获取企业自建应用用户信息
* @param $code
*/
function getUserInfo($corpId, $secret, $code) {
$access_token = getAccessToken($corpId, $secret);
$url = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?access_token=$access_token&code=$code";
$response = http_get($url);
if ($response['base_resp']['ret'] == 0) {
$data = json_decode($response['content'], true);
return $data;
}
return null;
}
/**
* 获取企业自建应用用户详细信息
* @param $corpId
* @param $secret
* @param $userid
* @return mixed
*/
function getUserDetail($corpId, $secret, $userid) {
$access_token = getAccessToken($corpId, $secret);
$url = "https://qyapi.weixin.qq.com/cgi-bin/user/get?access_token=$access_token&userid=$userid";
$response = http_get($url);
if ($response['base_resp']['ret'] == 0){
//保存access_token
return json_decode($response['content'], true);
}
}
/**
* jssdk获取
* @param $corpid
* @param $secret
* @return array
*/
function getAgentConfigSignPackage($corpid, $secret) {
$jsapiTicket = getAgentConfigJsApiTicket($corpid, $secret);
// 注意 URL 一定要动态获取,不能 hardcode.
$protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
$url = "$protocol$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
$timestamp = time();
$nonceStr = createNonceStr();
//这里参数的顺序要按照 key 值 ASCII 码升序排序
$string = "jsapi_ticket=$jsapiTicket&noncestr=$nonceStr×tamp=$timestamp&url=$url";
$signature = sha1($string);
$signPackage = array(
"appId" => $corpid,
"nonceStr" => $nonceStr,
"timestamp" => $timestamp,
"url" => $url,
"signature" => $signature,
"rawString" => $string
);
return $signPackage;
}
/**
* jssdk获取
* @param $corpid
* @param $secret
* @return array
*/
function getSignPackage($corpid, $secret) {
$jsapiTicket = getJsApiTicket($corpid, $secret);
// 注意 URL 一定要动态获取,不能 hardcode.
$protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
$url = "$protocol$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
$timestamp = time();
$nonceStr = createNonceStr();
//这里参数的顺序要按照 key 值 ASCII 码升序排序
$string = "jsapi_ticket=$jsapiTicket&noncestr=$nonceStr×tamp=$timestamp&url=$url";
$signature = sha1($string);
$signPackage = array(
"appId" => $corpid,
"nonceStr" => $nonceStr,
"timestamp" => $timestamp,
"url" => $url,
"signature" => $signature,
"rawString" => $string
);
return $signPackage;
}
function getJsApiTicket($corpid,$secret) {
// jsapi_ticket 应该全局存储与更新,以下代码以写入到文件中做示例
$path = "./cache/{$corpid}_jsapi_ticket.php";
$data = json_decode(get_php_file($path));
if($data->expire_time < time()){
$app_access_token = getAccessToken($corpid,$secret);
$url = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token=$app_access_token";
$res = json_decode(http_get($url)["content"]);
$ticket = $res->ticket;
if ($ticket) {
$data->expire_time = time() + 7000;
$data->jsapi_ticket = $ticket;
set_php_file($path, json_encode($data));
}
} else {
$ticket = $data->jsapi_ticket;
}
return $ticket;
}
function getAgentConfigJsApiTicket($corpid,$secret) {
// jsapi_ticket 应该全局存储与更新,以下代码以写入到文件中做示例
$path = "./cache/{$corpid}_ticket.php";
$data = json_decode(get_php_file($path));
if($data->expire_time < time()){
$app_access_token = getAccessToken($corpid,$secret);
$url = "https://qyapi.weixin.qq.com/cgi-bin/ticket/get?access_token=$app_access_token&type=agent_config";
$res = json_decode(http_get($url)["content"]);
$ticket = $res->ticket;
if ($ticket) {
$data->expire_time = time() + 7000;
$data->jsapi_ticket = $ticket;
set_php_file($path, json_encode($data));
}
} else {
$ticket = $data->jsapi_ticket;
}
return $ticket;
}
/**
* 获取企业自建应用access_token
* @param $corpId
* @param $secret
* @return mixed
*/
function getAccessToken($corpId, $secret){
$cachename = './cache/'.$corpId.'_access_token';
$access_token = getCache($cachename);
if (!$access_token) {
$url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=$corpId&corpsecret=$secret";
$response = http_get($url);
if ($response['base_resp']['ret'] == 0){
//保存access_token
$data = json_decode($response['content'], true);
$access_token = $data['access_token'];
setCache($cachename, $access_token, $data['expires_in']);
}
}
return $access_token;
}
/**
* 获取访问用户身份
* @param $code
*/
function getUserInfo3rd($code) {
$cachename = './cache/suite_access_token';
$access_token = getCache($cachename);
$url = "https://qyapi.weixin.qq.com/cgi-bin/service/getuserinfo3rd?suite_access_token=$access_token&code=$code";
$response = http_get($url);
if ($response['base_resp']['ret'] == 0) {
$data = json_decode($response['content'], true);
return $data;
}
return null;
}
/**
* 获取授权企业的access_token
* @param $auth_corpid
* @return mixed
*/
function getCorpToken($auth_corpid) {
//判断是否过期
$access_token_filename = "./cache/{$auth_corpid}_access_token";
$access_token = getCache($access_token_filename);
if (!$access_token) {
$permanent_code = getCache("./cache/{$auth_corpid}_permanent_code", 3 * 365 * 24 * 3600);
$suite_access_token = getCache("./cache/suite_access_token");
$url = "https://qyapi.weixin.qq.com/cgi-bin/service/get_corp_token?suite_access_token=".$suite_access_token;
$data = array(
'auth_corpid' => $auth_corpid,
'permanent_code' => $permanent_code
);
$response = http_post($url, $data);
if ($response['base_resp']['ret'] == 0){
//保存access_token
$data = json_decode($response['content'], true);
$access_token = $data['access_token'];
setCache($access_token_filename, $access_token, $data['expires_in']);
}
}
return $access_token;
}
/**
* 获取用户信息
* @param $corpId
* @param $userId
*/
function getUserById($corpId, $userId){
//获取授权企业access_token
$access_token = getCorpToken($corpId);
$url = "https://qyapi.weixin.qq.com/cgi-bin/user/get?access_token=$access_token&userid=$userId";
$response = http_get($url);
if ($response['base_resp']['ret'] == 0){
$data = json_decode($response['content'], true);
return $data;
}
return null;
}
/**
* 获取访问用户敏感信息
* @param $corpId
* @param $user_ticket
* @return mixed|null
*/
function getUserDetail3rd($user_ticket){
$cachename = './cache/suite_access_token';
$suite_access_token = getCache($cachename);
$url = "https://qyapi.weixin.qq.com/cgi-bin/service/getuserdetail3rd?suite_access_token=$suite_access_token";
$response = http_post($url, array('user_ticket' => $user_ticket));
if ($response['base_resp']['ret'] == 0){
$data = json_decode($response['content'], true);
return $data;
}
return null;
}