showErrorMessage('缺少appid,或appsecret,或token!');
$this->appId = $appId;
$this->appSecret = $appSecret;
$this->token = $token;
$this->timestamp = time();
!empty($jsDomain)&&$this->jsDomain = $jsDomain;
$this->basePath = Yii::$app->params['wxPath'];
dir_create($this->basePath);
$this->acessTokenFile = $this->basePath.$this->appId.'_access_token.json';//文件存储$accessToken
$this->jsApiTicketFile = $this->basePath.$this->appId.'_jsapi_ticket.json';//文件存储js api 凭据
}
//初始化
public function init()
{
$this->getAccessTokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=".$this->appId."&secret=".$this->appSecret;
$this->getIpListUrl = "https://api.weixin.qq.com/cgi-bin/getcallbackip?access_token=%s";
$this->getUserInfoUrl= "https://api.weixin.qq.com/cgi-bin/user/info?access_token=%s&openid=%s&lang=zh_CN";
$this->getJsApiTicketUrl = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=%s&type=jsapi";
$this->addMaterialUrl= "https://api.weixin.qq.com/cgi-bin/material/add_material?access_token=%s";
$this->addNewsUrl = "https://api.weixin.qq.com/cgi-bin/material/add_news?access_token=%s";
$this->uploadImgUrl = "https://api.weixin.qq.com/cgi-bin/media/uploadimg?access_token=%s";
$this->getMediaUrl = "https://api.weixin.qq.com/cgi-bin/material/get_material?access_token=%s";
$this->updateNewsUrl = "https://api.weixin.qq.com/cgi-bin/material/update_news?access_token=%s";
$this->delMediaUrl = "https://api.weixin.qq.com/cgi-bin/material/del_material?access_token=%s";
$this->getMaterialCountUrl = "https://api.weixin.qq.com/cgi-bin/material/get_materialcount?access_token=%s";
$this->batcheGetMaterialUrl = "https://api.weixin.qq.com/cgi-bin/material/batchget_material?access_token=%s";
$this->uploadNewsVideoUrl = "https://file.api.weixin.qq.com/cgi-bin/media/uploadvideo?access_token=%s";
$this->msgSendAllUrl = "https://api.weixin.qq.com/cgi-bin/message/mass/sendall?access_token=%s";
$this->msgSendUrl = "https://api.weixin.qq.com/cgi-bin/message/mass/send?access_token=%s";
$this->msgPreviewUrl = "https://api.weixin.qq.com/cgi-bin/message/mass/preview?access_token=%s";
$this->delMsgUrl = "https://api.weixin.qq.com/cgi-bin/message/mass/delete?access_token=%s";
$this->getMsgStatusUrl = "https://api.weixin.qq.com/cgi-bin/message/mass/get?access_token=%s";
$this->createGroupUrl = "https://api.weixin.qq.com/cgi-bin/groups/create?access_token=%s";
$this->getGroupsUrl = "https://api.weixin.qq.com/cgi-bin/groups/get?access_token=%s";
$this->getGroupIdByOpenIdUrl = "https://api.weixin.qq.com/cgi-bin/groups/getid?access_token=%s";
$this->updateGroupNameUrl = "https://api.weixin.qq.com/cgi-bin/groups/update?access_token=%s";
$this->changeUserGroupUrl = "https://api.weixin.qq.com/cgi-bin/groups/members/update?access_token=%s";
$this->batchChangeUserGroupUrl = "https://api.weixin.qq.com/cgi-bin/groups/members/batchupdate?access_token=%s";
$this->delGroupUrl = "https://api.weixin.qq.com/cgi-bin/groups/delete?access_token=%s";
$this->updateRemarkUrl = "https://api.weixin.qq.com/cgi-bin/user/info/updateremark?access_token=%s";
$this->batchGetUserInfoUrl = "https://api.weixin.qq.com/cgi-bin/user/info/batchget?access_token=%s";
$this->getUserListUrl = "https://api.weixin.qq.com/cgi-bin/user/get?access_token=%s&next_openid=%s";
$this->getWebAuthCodeUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=%s&state=%s#wechat_redirect";
$this->getWebAuthAccessTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code";
$this->getWebAuthUserInfoUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s&lang=zh_CN";
$this->createMenuUrl = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=%s";
$this->getMenuListUrl = "https://api.weixin.qq.com/cgi-bin/menu/get?access_token=%s";
$this->deleteMenuUrl = "https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=%s";
$this->createQrcodeUrl = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=%s";
$this->getQrcodeUrl = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=%s";
$this->getShortUrl = "https://api.weixin.qq.com/cgi-bin/shorturl?access_token=%s";
$this->addOrderUrl = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
$this->qryOrderUrl = 'https://api.mch.weixin.qq.com/pay/orderquery';
$this->redPackUrl = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack';
$this->tplMsgUrl = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=%s";
$this->customerMsgUrl = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=%s";
return $this;
}
//获取短链接
public function createShortUrl($longUrl)
{
$this->getAccessToken();
$this->getShortUrl = sprintf($this->getShortUrl,$this->accessToken);
$postdata = json_encode(array('action'=>'long2short','long_url'=>$longUrl),JSON_UNESCAPED_UNICODE);
$result = $this->httpsRequest($this->getShortUrl, $postdata);
$result = json_decode($result,true);
return $result;
}
//创建二维码 $type 1:永久,2:临时
public function createQrcode($sceneId,$type=1,$expireSeconds=604800)
{
$this->getAccessToken();
$this->createQrcodeUrl = sprintf($this->createQrcodeUrl,$this->accessToken);
if($type==1)
{
$postdata = '{"action_name": "QR_LIMIT_SCENE", "action_info": {"scene": {"scene_id": '.$sceneId.'}}}';
}
if($type==2)
{
$postdata = '{"expire_seconds": '.$expireSeconds.', "action_name": "QR_SCENE", "action_info": {"scene": {"scene_id": '.$sceneId.'}}}';
}
if($type==3)
{
$postdata = '{"expire_seconds": '.$expireSeconds.', "action_name": "QR_STR_SCENE", "action_info": {"scene": {"scene_str": "'.$sceneId.'"}}}';
}
$result = $this->httpsRequest($this->createQrcodeUrl, $postdata);
$result = json_decode($result,true);
$result['codeUrl'] = sprintf($this->getQrcodeUrl,urlencode($result['ticket']));
return $result;
}
//删除自定义菜单
public function deleteMenu()
{
$this->getAccessToken();
$this->deleteMenuUrl = sprintf($this->deleteMenuUrl,$this->accessToken);
$result = json_decode($this->httpGet($this->deleteMenuUrl),true);
return $result;
}
//创建自定义菜单
public function createMenu($buttons)
{
$this->getAccessToken();
$this->createMenuUrl = sprintf($this->createMenuUrl,$this->accessToken);
$array['button'] = $buttons;
$result = $this->httpsRequest($this->createMenuUrl, json_encode($array,JSON_UNESCAPED_UNICODE));
$result = json_decode($result,true);
return $result;
}
//查询自定义菜单
public function getMenuList()
{
$this->getAccessToken();
$this->getMenuListUrl = sprintf($this->getMenuListUrl,$this->accessToken);
$result = json_decode($this->httpGet($this->getMenuListUrl),true);
return $result;
}
/* 第一步:用户同意授权,获取code
* 获取网页授权地址$scope:nsapi_base (不弹出授权页面,直接跳转,只能获取用户openid),
snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且,即使在未关注的情况下,只要用户授权,也能获取其信息)
*/
public function getWebAuthUrl($redirectUrl,$scope='snsapi_userinfo',$state='MR8888')
{
$this->getWebAuthCodeUrl = sprintf($this->getWebAuthCodeUrl,$this->appId,$redirectUrl,$scope,$state);
return $this->getWebAuthCodeUrl;
}
//第二步:通过code换取网页授权access_token
public function getWebAuthAccessToken()
{
try
{
$this->getWebAuthAccessTokenUrl = sprintf($this->getWebAuthAccessTokenUrl,$this->appId,$this->appSecret,$_GET['code']);
$data = json_decode($this->httpGet($this->getWebAuthAccessTokenUrl),true);
$this->webAuthAccessToken = $data['access_token'];
$this->currentOpenId = $data['openid'];
}
catch(\Exception $e)
{
$this->showError($e->getMessage());
}
}
// 第二步:通过code换取网页授权access_token
public function getOauthAccessToken($code)
{
$url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=".$this->appId."&secret=".$this->appSecret."&code=$code&grant_type=authorization_code";
return json_decode($this->httpGet($url),true);
}
//第三步:拉取用户信息(需scope为 snsapi_userinfo)
public function getWebAuthUserInfo()
{
/*$result = $this->getOauthAccessToken($_GET['code']);
$this->webAuthAccessToken = $result['access_token'];
$this->currentOpenId = $result['openid'];*/
$this->getWebAuthAccessToken();
$this->getWebAuthUserInfoUrl = sprintf($this->getWebAuthUserInfoUrl,$this->webAuthAccessToken,$this->currentOpenId);
$result = json_decode($this->httpGet($this->getWebAuthUserInfoUrl),true);
$result['nick_name'] = $result['nickname'];
$result['avatar'] = $result['headimgurl'];
return $result;
}
//获取用户列表
public function getUserList($nextOpenId='')
{
try
{
$this->getAccessToken();
$this->getUserListUrl = sprintf($this->getUserListUrl,$this->accessToken,$nextOpenId);
$result = json_decode($this->httpGet($this->getUserListUrl),true);
return $result;
}
catch(\Exception $e)
{
$this->showError($e->getMessage());
}
}
//批量获取用户基本信息
public function batchGetUserInfo($userList)
{
try
{
$this->getAccessToken();
$this->batchGetUserInfoUrl = sprintf($this->batchGetUserInfoUrl,$this->accessToken);
if(is_array($userList))foreach($userList as $openId)
{
$array['user_list'][] = array('openid'=>$openId,'lang'=>'zh-CN');
}
$result = $this->httpsRequest($this->batchGetUserInfoUrl, json_encode($array,JSON_UNESCAPED_UNICODE));
$result = json_decode($result,true);
return $result;
}
catch(\Exception $e)
{
$this->showError($e->getMessage());
}
}
//修改用户备注
public function updateRemark($openId,$remark)
{
try
{
$this->getAccessToken();
$this->updateRemarkUrl = sprintf($this->updateRemarkUrl,$this->accessToken);
$array = array('openid'=>$openId,'remark'=>$remark);
$result = $this->httpsRequest($this->updateRemarkUrl, json_encode($array,JSON_UNESCAPED_UNICODE));
$result = json_decode($result,true);
return $result;
}
catch(\Exception $e)
{
$this->showError($e->getMessage());
}
}
//创建分组
public function createGroup($groupName)
{
try
{
$this->getAccessToken();
$this->createGroupUrl = sprintf($this->createGroupUrl,$this->accessToken);
$array['group'] = array('name'=>$groupName);
$result = $this->httpsRequest($this->createGroupUrl, json_encode($array,JSON_UNESCAPED_UNICODE));
$result = json_decode($result,true);
return $result;
}
catch(\Exception $e)
{
$this->showError($e->getMessage());
}
}
//查询所有分组信息
public function getGroups()
{
try
{
$this->getAccessToken();
$this->getGroupsUrl = sprintf($this->getGroupsUrl,$this->accessToken);
$result = $this->httpGet($this->getGroupsUrl);
$result = json_decode($result,true);
return $result;
}
catch(\Exception $e)
{
$this->showError($e->getMessage());
}
}
//查询用户所在分组
public function getGroupId($openId)
{
try
{
$this->getAccessToken();
$this->getGroupIdByOpenIdUrl = sprintf($this->getGroupIdByOpenIdUrl,$this->accessToken);
$array['openid'] = $openId;
$result = $this->httpsRequest($this->getGroupIdByOpenIdUrl, json_encode($array,JSON_UNESCAPED_UNICODE));
$result = json_decode($result,true);
return $result;
}
catch(\Exception $e)
{
$this->showError($e->getMessage());
}
}
//修改用户分组名称
public function updateGroupName($groupId,$groupName)
{
try
{
$this->getAccessToken();
$this->updateGroupNameUrl = sprintf($this->updateGroupNameUrl,$this->accessToken);
$array['group'] = array('id'=>$groupId,'name'=>$groupName);
$result = $this->httpsRequest($this->updateGroupNameUrl, json_encode($array,JSON_UNESCAPED_UNICODE));
$result = json_decode($result,true);
return $result;
}
catch(\Exception $e)
{
$this->showError($e->getMessage());
}
}
//修改用户所在分组,支持批量转移
public function changUserGroup($openId,$toGroupId)
{
try
{
$this->getAccessToken();
if(is_array($openId))
{
$requestUrl = sprintf($this->batchChangeUserGroupUrl,$this->accessToken);
$array= array('openid_list'=>$openId,'to_groupid'=>$toGroupId);
}
else
{
$requestUrl = sprintf($this->changeUserGroupUrl,$this->accessToken);
$array= array('openid'=>$openId,'to_groupid'=>$toGroupId);
}
$result = $this->httpsRequest($requestUrl, json_encode($array,JSON_UNESCAPED_UNICODE));
$result = json_decode($result,true);
return $result;
}
catch(\Exception $e)
{
$this->showError($e->getMessage());
}
}
//删除分组
public function deleteGroup($groupId)
{
try
{
$this->getAccessToken();
$this->delGroupUrl = sprintf($this->delGroupUrl,$this->accessToken);
$array['group'] = array('id'=>$groupId);
$result = $this->httpsRequest($this->delGroupUrl, json_encode($array,JSON_UNESCAPED_UNICODE));
$result = json_decode($result,true);
return $result;
}
catch(Exception $e)
{
$this->showError($e->getMessage());
}
}
//根据openid 获取用户基本信息
public function getUserInfo($open_id)
{
try
{
$this->getAccessToken();
$this->getUserInfoUrl = sprintf($this->getUserInfoUrl,$this->accessToken,$open_id);
$result = json_decode($this->httpGet($this->getUserInfoUrl),TRUE);
return $result;
}
catch(\Exception $e)
{
$this->showError($e->getMessage());
}
}
//群发消息
public function msgSend($contentInfo)
{
try
{
$this->getAccessToken();
$msg =array();
$sendUrl = sprintf($this->msgSendAllUrl,$this->accessToken);
extract($contentInfo);
if(is_numeric($groupId))
{
$msg['filter'] = array('is_to_all'=>false,'group_id'=>$groupId);
}
if(!empty($openIds)&&is_array($openIds))
{
$msg['touser'] = $openIds;
$sendUrl = sprintf($this->msgSendUrl,$this->accessToken);
}
$msg['msgtype'] = $msgtype;
if($msgtype=='mpnews')//群发图文
{
$msg['mpnews'] = array('media_id'=>$media_id);
}
if($msgtype=='text')//群发文本
{
$msg['text'] = array('content'=>$content);
}
if($msgtype=='voice')//群发语音
{
$msg['voice'] = array('media_id'=>$media_id);
}
if($msgtype=='image')//群发图片
{
$msg['image'] = array('media_id'=>$media_id);
}
if($msgtype=='mpvideo')//群发视频
{
$msg['mpvideo'] = array('media_id'=>$media_id);
}
if($msgtype=='wxcard')//卡券消息
{
$msg['wxcard'] = array('card_id'=>$card_id);
}
$result = $this->httpsRequest($sendUrl, json_encode($msg,JSON_UNESCAPED_UNICODE));
$result = json_decode($result,true);
return $result;
}
catch(\Exception $e)
{
$this->showError($e->getMessage());
}
}
//消息预览 $contentInfo:
public function msgPreview($contentInfo)
{
try
{
$this->getAccessToken();
$msg =array();
$this->msgPreviewUrl = sprintf($this->msgPreviewUrl,$this->accessToken);
extract($contentInfo);
if(!empty($towxname)) $msg['towxname'] = $towxname;
if(!empty($touser)) $msg['touser'] = $touser;
$msg['msgtype'] = $msgtype;
if($msgtype=='mpnews')//群发图文
{
$msg['mpnews'] = array('media_id'=>$media_id);
}
if($msgtype=='text')//群发文本
{
$msg['text'] = array('content'=>$content);
}
if($msgtype=='voice')//群发语音
{
$msg['voice'] = array('media_id'=>$media_id);
}
if($msgtype=='image')//群发图片
{
$msg['image'] = array('media_id'=>$media_id);
}
if($msgtype=='mpvideo')//群发视频
{
$msg['mpvideo'] = array('media_id'=>$media_id);
}
if($msgtype=='wxcard')//卡券消息
{
$msg['wxcard'] = array('card_id'=>$card_id,'card_ext'=>$card_ext);
}
$result = $this->httpsRequest($this->msgPreviewUrl, json_encode($msg,JSON_UNESCAPED_UNICODE));
$result = json_decode($result,true);
return $result;
}
catch(\Exception $e)
{
$this->showError($e->getMessage());
}
}
//删除群发消息
public function delMsg($msgId)
{
$this->getAccessToken();
$this->delMsgUrl = sprintf($this->delMsgUrl,$this->accessToken);
$array = array('msg_id'=>$msgId);
$result = $this->httpsRequest($this->delMsgUrl, json_encode($array,JSON_UNESCAPED_UNICODE));
$result = json_decode($result,true);
return $result;
}
//获取群发消息状态
public function msgStatus($msgId)
{
$this->getAccessToken();
$this->getMsgStatusUrl = sprintf($this->getMsgStatusUrl,$this->accessToken);
$array = array('msg_id'=>$msgId);
$result = $this->httpsRequest($this->getMsgStatusUrl, json_encode($array,JSON_UNESCAPED_UNICODE));
$result = json_decode($result,true);
return $result;
}
//客服消息
public function sendCustomermsg($type,$openid,$data)
{
$this->getAccessToken();
$this->customerMsgUrl = sprintf($this->customerMsgUrl,$this->accessToken);
if($type=='text')
{
$msgcontent = '{ "touser" : "'.$openid.'",
"msgtype" : "text",
"text" : {
"content" : "'.$data['content'].'"
}
}';
}
if($type=='image'||$type=='voice'||$type=='mpnews')
{
$msgcontent = '{ "touser" : "'.$openid.'",
"msgtype" : "'.$type.'",
"'.$type.'" : {
"media_id" : "'.$data['media_id'].'"
}
}';
}
if($type=='news')
{
$msgcontent = '{"touser":"'.$openid.'",
"msgtype":"news",
"news":{
"articles": [
{
"title":"'.$data['title'].'",
"description":"'.$data['description'].'",
"url":"'.$data['url'].'",
"picurl":"'.getFileUrl($data['picurl']).'"
}
]
}
}';
}
if($type=='video')
{
$msgcontent = '{
"touser":"'.$openid.'",
"msgtype":"video",
"video":
{
"media_id":"'.$data['media_id'].'",
"thumb_media_id":"'.$data['thumb_media_id'].'",
"title":"'.$data['title'].'",
"description":"'.$data['description'].'",
}
}';
}
$result = $this->httpsRequest($this->customerMsgUrl, $msgcontent);
$result = json_decode($result,true);
return $result;
}
//自动回复消息
public function responseMsg($array,$articles=array())
{
try
{
$receive = $this->receiveMsg();
if (!empty($receive)){
$fromUsername = $receive['fromUsername'];
$toUsername = $receive['toUsername'];
$time = TIMESTAMP;
extract($array);
if($type=='text')
{
$tpl = "
%s
0
";
$resultStr = sprintf($tpl, $fromUsername, $toUsername, $time, $type, $content);
}
if($type=='image')
{
$tpl="
%s
";
$resultStr = sprintf($tpl, $fromUsername, $toUsername, $time, $type, $media_id);
}
if($type=='voice')
{
$tpl = "
%s
";
$resultStr = sprintf($tpl, $fromUsername, $toUsername, $time, $type, $media_id);
}
if($type=='video')
{
$tpl="
%s
";
$resultStr = sprintf($tpl, $fromUsername, $toUsername, $time, $type, $media_id,$title,$description);
}
if($type=='news')
{
$tpl="
%s
%s";
$tpl.="";
if(!empty($articles))foreach($articles as $article){
$tpl.="-
";
}
$tpl.="";
$tpl.="";
$resultStr = sprintf($tpl, $fromUsername, $toUsername, $time, $type, $count);
}
echo $resultStr;
}else {
echo "";
exit;
}
}
catch(\Exception $e)
{
$this->showError($e->getMessage());
}
}
//解析接收到的用户信息
public function receiveMsg()
{
try
{
//$postStr = $GLOBALS["HTTP_RAW_POST_DATA"];
$postStr = file_get_contents("php://input");//支持PHP7
file_put_contents(BASE_PATH.'components/WeiXin/test.txt',$postStr);
if (!empty($postStr)){
$msg = array();
/* libxml_disable_entity_loader is to prevent XML eXternal Entity Injection,
the best way is to check the validity of xml by yourself */
libxml_disable_entity_loader(true);
$postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
//file_put_contents(BASE_PATH.'components/WeiXin/test.txt',$postObj->FromUserName);
$fromUsername = $postObj->FromUserName;
$this->getUserInfo($fromUsername);
$this->currentOpenId = $fromUsername;
$toUsername = $postObj->ToUserName;
$msgType = $postObj->MsgType;
$event = $postObj->Event;
$msgID = $postObj->MsgID;
$createTime = $postObj->CreateTime;
if($msgType=='text')
{
$msg['content'] = $postObj->Content;
}
if($msgType=='image')
{
$msg['picUrl'] = $postObj->PicUrl;
$msg['mediaId'] = $postObj->MediaId;
}
if($msgType=='voice')
{
$msg['format'] = $postObj->Format;
$msg['mediaId'] = $postObj->MediaId;
}
if($msgType=='video')
{
$msg['thumbMediaId'] = $postObj->ThumbMediaId;
$msg['mediaId'] = $postObj->MediaId;
}
if($msgType=='shortvideo')
{
$msg['thumbMediaId'] = $postObj->ThumbMediaId;
$msg['mediaId'] = $postObj->MediaId;
}
if($msgType=='event')
{
if($postObj->TotalCount)//群发消息后,微信推送过来的
{
}
if($event=='LOCATION')//上报地理位置
{
$msg['latitude'] = $postObj->Latitude;
$msg['longitude'] = $postObj->Longitude;
$msg['precision'] = $postObj->Precision;
}
if($event=='subscribe')//订阅
{
$postObj->EventKey&&$msg['eventKey'] = $postObj->EventKey;//未关注:事件KEY值,qrscene_为前缀,后面为二维码的参数值
$postObj->Ticket&&$msg['ticket'] = $postObj->Ticket;//二维码的ticket,可用来换取二维码图片
}
if($event=='SCAN')//已关注,扫描二维码
{
$postObj->EventKey&&$msg['eventKey'] = $postObj->EventKey;//事件KEY值,是一个32位无符号整数,即创建二维码时的二维码scene_id
$postObj->Ticket&&$msg['ticket'] = $postObj->Ticket;//二维码的ticket,可用来换取二维码图片
}
if($event=='unsubscribe'){}//取消订阅
if($event=='click')//点击菜单
{
$postObj->EventKey&&$msg['eventKey'] = $postObj->EventKey;//与自定义菜单接口中KEY值对应
}
if($event=='VIEW')//菜单跳转
{
$postObj->EventKey&&$msg['eventKey'] = $postObj->EventKey;//EventKey 是一个连接地址
}
if($event=='scancode_push')//扫码推事件的事件推送
{
$msg['eventKey'] = $postObj->EventKey;//EventKey 是一个连接地址
$msg['ScanType'] = $postObj->ScanCodeInfo->ScanType;
$msg['ScanResult'] = $postObj->ScanCodeInfo->ScanResult;
}
if($event=='scancode_waitmsg')//扫码推事件且弹出“消息接收中”提示框的事件推送
{
$msg['eventKey'] = $postObj->EventKey;//EventKey 是一个连接地址
$msg['ScanType'] = $postObj->ScanCodeInfo->ScanType;
$msg['ScanResult'] = $postObj->ScanCodeInfo->ScanResult;
}
if($event=='pic_sysphoto')//弹出系统拍照发图的事件推送
{
$msg['eventKey'] = $postObj->EventKey;//EventKey 是一个连接地址
$msg['Count'] = $postObj->SendPicsInfo->Count;
$msg['PicList'] = $postObj->SendPicsInfo->PicList;
}
if($event=='pic_photo_or_album')//弹出拍照或者相册发图的事件推送
{
$msg['eventKey'] = $postObj->EventKey;//EventKey 是一个连接地址
$msg['Count'] = $postObj->SendPicsInfo->Count;
$msg['PicList'] = $postObj->SendPicsInfo->PicList;
}
if($event=='pic_weixin')//弹出微信相册发图器的事件推送
{
$msg['eventKey'] = $postObj->EventKey;//EventKey 是一个连接地址
$msg['Count'] = $postObj->SendPicsInfo->Count;
$msg['PicList'] = $postObj->SendPicsInfo->PicList;
}
if($event=='location_select')//弹出地理位置选择器的事件推送
{
$msg['eventKey'] = $postObj->EventKey;//EventKey 是一个连接地址
$msg['Location_X'] = $postObj->SendLocationInfo->Location_X;
$msg['Location_Y'] = $postObj->SendLocationInfo->Location_Y;
$msg['Scale'] = $postObj->SendLocationInfo->Scale;
$msg['Label'] = $postObj->SendLocationInfo->Label;
$msg['Poiname'] = $postObj->SendLocationInfo->Poiname;
}
}
if($msgType=='link')
{
$msg['title'] = $postObj->Title;
$msg['description'] = $postObj->Description;
$msg['url'] = $postObj->Url;
}
$msg['fromUsername']=$fromUsername;
$msg['toUsername']=$toUsername;
$msg['msgType']=$msgType;
$msg['event']=$event;
$msg['msgID']=$msgID;
$msg['createTime']=$createTime;
return $msg;
}
else
{
return array();
}
}
catch(\Exception $e)
{
$this->showError($e->getMessage());
}
}
//上传永久素材
public function addMaterial($type,$filepath,$title='',$introduction='')
{
try
{
$this->getAccessToken();
$ext = $this->fileext($filepath);
$filesize = filesize($filepath);
$voiceFatmat = array('mp3','wma','wav','amr');
$voiceMaxSize = 5;//5mb
$voiceTimeLenth = "60秒";
$imageFatmat = array('bmp','png','jpeg','jpg','gif');
$imageMaxSize = 2;//2MB
$newsImageFatmat = array('jpg','png');
$newsImageMaxSize = 1;//1MB
if($type=='voice')
{
if(!in_array($ext,$voiceFatmat))$this->showErrorMessage('不支持该语音格式');
if($filesize>$voiceMaxSize*1014*1024)$this->showErrorMessage('语音超出大小');
}
if($type=='image')
{
if(!in_array($ext,$imageFatmat))$this->showErrorMessage('不支持该图片格式');
if($filesize>$imageMaxSize*1014*1024)$this->showErrorMessage('图片超出大小');
}
if($type=='video'||$type=='newsvideo')
{
$description='{"title":"'.$title.'","introduction":"'.$introduction.'"}';
if(!empty($description))$data['description'] = $description;
}
if($type=='newsimage')//图文消息图片时候用到
{
if(!in_array($ext,$newsImageFatmat))$this->showErrorMessage('不支持该图片格式');
if($filesize>$newsImageMaxSize*1014*1024)$this->showErrorMessage('图片超出大小');
$this->addMaterialUrl = sprintf($this->uploadImgUrl,$this->accessToken);
}
else
{
$this->addMaterialUrl = sprintf($this->addMaterialUrl,$this->accessToken);
}
$data['media'] = new \CURLFile(realpath($filepath));
$result = $this->httpsRequest($this->addMaterialUrl, $data);
$result = json_decode($result,true);
if($type=='newsvideo')//图文消息中的视频素材
{
$this->uploadNewsVideoUrl = sprintf($this->uploadNewsVideoUrl,$this->accessToken);
$array = array('media_id'=>$result['media_id'],'title'=>$title,'description'=>$description);
$result = $this->httpsRequest($this->uploadNewsVideoUrl, json_encode($array,JSON_UNESCAPED_UNICODE));
$result = json_decode($result,true);
}
return $result;
}
catch(\Exception $e)
{
$this->showError($e->getMessage());
}
}
//上传永久图文素材
public function addNews($articles)
{
try
{
$this->getAccessToken();
$this->addNewsUrl = sprintf($this->addNewsUrl,$this->accessToken);
$result = $this->httpsRequest($this->addNewsUrl, json_encode($articles,JSON_UNESCAPED_UNICODE));
$result = json_decode($result,true);
return $result;
}
catch(\Exception $e)
{
$this->showError($e->getMessage());
}
}
//修改图文素材 index:多图文时候的单篇图文索引
public function updateNews($media_id,$data,$index=0)
{
try
{
$this->getAccessToken();
$this->updateNewsUrl = sprintf($this->updateNewsUrl,$this->accessToken);
$data['media_id'] = $media_id;
$data['index'] = $index;
$result = $this->httpsRequest($this->updateNewsUrl, json_encode($data,JSON_UNESCAPED_UNICODE));
$result = json_decode($result,true);
return $result;
}
catch(\Exception $e)
{
$this->showError($e->getMessage());
}
}
//根据media_id 获取素材
public function getMedia($media_id)
{
try
{
$this->getAccessToken();
$this->getMediaUrl = sprintf($this->getMediaUrl,$this->accessToken);
$result = json_decode($this->httpsRequest($this->getMediaUrl,json_encode(array('media_id'=>$media_id))),TRUE);
return $result;
}
catch(\Exception $e)
{
$this->showError($e->getMessage());
}
}
//删除素材
public function delMedia($media_id)
{
try
{
$this->getAccessToken();
$this->delMediaUrl = sprintf($this->delMediaUrl,$this->accessToken);
$result = json_decode($this->httpsRequest($this->delMediaUrl,json_encode(array('media_id'=>$media_id))),TRUE);
return $result;
}
catch(\Exception $e)
{
$this->showError($e->getMessage());
}
}
//获取接口凭据 $type:1 文件存储 2 数据库存储
public function getAccessToken($type=1)
{
try
{
if(file_exists($this->acessTokenFile))
{
$data = json_decode(file_get_contents($this->acessTokenFile));
if($data->expire_timeaccessToken = $data->access_token;
}
}
else
{
$refresh = true;
}
if($refresh)
{
$data = json_decode($this->httpGet($this->getAccessTokenUrl));
$data->expire_time = TIMESTAMP+3600;
file_put_contents($this->acessTokenFile,json_encode($data));
$this->accessToken = $data->access_token;
}
}
catch(\Exception $e)
{
$this->showError($e->getMessage());
}
}
//获取js api ticket type 1:文件 2:数据库
public function getJsApiTicket($type=1,$url='')
{
try
{
if(file_exists($this->jsApiTicketFile))
{
$data = json_decode(file_get_contents($this->jsApiTicketFile));
if($data->expire_timeticket;
}
}
else
{
$refresh = true;
}
if($refresh)
{
$this->getAccessToken();
$this->getJsApiTicketUrl = sprintf($this->getJsApiTicketUrl,$this->accessToken);
$data = json_decode($this->httpGet($this->getJsApiTicketUrl));
$data->expire_time = TIMESTAMP+7000;
file_put_contents($this->jsApiTicketFile,json_encode($data));
$ticket = $data->ticket;
}
$timestamp = TIMESTAMP;
$noncestr = $this->createNonceStr();
if(empty($url))$url = $this->getUrl();
$string = "jsapi_ticket=".$ticket."&noncestr=".$noncestr."×tamp=".$timestamp."&url=".$url;
$signature = sha1($string);
return array('appid'=>$this->appId,'ticket'=>$ticket,'noncestr'=>$noncestr,'timestamp'=>$timestamp,'url'=>$url,'signature'=>$signature);
}
catch(\Exception $e)
{
$this->showError($e->getMessage());
}
}
//获取微信服务器IP列表
public function getWeiXinIpList()
{
try
{
$this->getIpListUrl = sprintf($this->getIpListUrl,$this->accessToken);
$result = $this->httpGet($this->getIpListUrl);
$result = json_decode($result,TRUE);
$this->wxIpList = $result['ip_list'];
return $this->wxIpList;
}
catch(\Exception $e)
{
$this->showError($e->getMessage());
}
}
//获取素材总数
public function getMaterialCount()
{
try
{
$this->getAccessToken();
$this->getMaterialCountUrl = sprintf($this->getMaterialCountUrl,$this->accessToken);
return $result = json_decode($this->httpGet($this->getMaterialCountUrl),TRUE);
}
catch(\Exception $e)
{
$this->showError($e->getMessage());
}
}
//批量获取素材
public function batcheGetMaterial($type,$offset,$count)
{
try
{
$this->getAccessToken();
$this->batcheGetMaterialUrl = sprintf($this->batcheGetMaterialUrl,$this->accessToken);
$result = json_decode($this->httpsRequest($this->batcheGetMaterialUrl,json_encode(array('type'=>$type,'offset'=>$offset,'count'=>$count))),TRUE);
return $result;
}
catch(\Exception $e)
{
$this->showError($e->getMessage());
}
}
//发送模板消息
public function sendTemplateMsg($openid,$templateid,$data,$url=''){
/*
$data = array(
'name'=>array('value'=>'Lucy','color'=>"#173177") ,
'money'=>array('value'=>'1000000','color'=>"#173177") ,
'date'=>array('value'=>date('Y-m-d H:i:s'),'color'=>"#173177") ,
)
*/
try
{
$this->getAccessToken();
$this->tplMsgUrl = sprintf($this->tplMsgUrl,$this->accessToken);
$arr = array(
'touser'=>$openid ,
'template_id'=>$templateid,
'url'=>$url,
'data'=>$data
) ;
$result = json_decode($this->httpsRequest($this->tplMsgUrl,json_encode($arr)),TRUE);
return $result;
}
catch(\Exception $e)
{
$this->showError($e->getMessage());
}
}
// 发送红包
function sendRedPack($parameter)
{
$money = max($parameter['money'], 0.01);
$money = intval($money * 100);
$mch_billno = $this->mchId.date('YmdHis',$this->timestamp).$this->num_rand(4);
$ip = $parameter['ip'];
$openid = $parameter['openid'];
if (!$openid) {
$this->echo_json('openid获取失败');
}
$this->parameters = array();
$this->setParameter('nonce_str', $this->createNonceStr());
$this->setParameter('mch_billno', $mch_billno);
$this->setParameter('mch_id', $this->mchId);
$this->setParameter('wxappid', $this->appId);
$this->setParameter('nick_name', $parameter['nick_name']);
$this->setParameter('send_name', $parameter['send_name']);
$this->setParameter('re_openid', $openid);
$this->setParameter('total_amount', $money);
$this->setParameter('min_value', $money);
$this->setParameter('max_value', $money);
$this->setParameter('total_num', 1);
$this->setParameter('wishing', $parameter['wishing']);
$this->setParameter('client_ip', $ip);
$this->setParameter('act_name', $parameter['act_name']);
$this->setParameter('remark', $parameter['remark']);
$this->setParameter('sign', $this->getSign());
$xml = $this->arrayToXml($this->parameters);
$res = $this->wxHttpsRequestPem($this->redPackUrl, $xml);
$resObj = simplexml_load_string($res, 'SimpleXMLElement', LIBXML_NOCDATA);
if ($resObj->return_code != 'SUCCESS') {
return array('code'=>-1, 'msg'=>$resObj->return_msg);
}
if ($resObj->result_code != 'SUCCESS') {
return array('code'=>-1, 'msg'=>$resObj->err_code_des);
}
return array('code'=>1, 'order_no'=>$mch_billno, 'openid'=>$openid);
}
//验证签名
public function valid()
{
$echoStr = $_GET["echostr"];
if($this->checkSignature()){
echo $echoStr;
exit;
}
}
public function checkSignature()
{
if (empty($this->token)) {
$this->showError('错误token!');
}
$signature = $_GET["signature"];
$timestamp = $_GET["timestamp"];
$nonce = $_GET["nonce"];
$tmpArr = array($this->token, $timestamp, $nonce);
// use SORT_STRING rule
sort($tmpArr, SORT_STRING);
$tmpStr = implode( $tmpArr );
$tmpStr = sha1( $tmpStr );
if( $tmpStr == $signature ){
return true;
}else{
return false;
}
}
// 设置参数
public function setParameter($parameter, $parameterValue)
{
$this->parameters[trim($parameter)] = trim($parameterValue);
}
// 获取参数
public function getParameter($parameter)
{
return $this->parameters[$parameter];
}
/**
* 获取随机数
*
* @param int $length 长度
* @return string
*/
function num_rand($length) {
mt_srand((double) microtime() * 1000000);
$randVal = mt_rand(1, 9);
for ($i = 1; $i < $length; $i++) {
$randVal .= mt_rand(0, 9);
}
return $randVal;
}
function echo_json_callback($results) { //ajax输出
if ($_GET['callback']=='') $_GET['callback']='wzcallback';
if (is_string($results)) $results=array('code'=>-1,'msg'=>$results);
header("Content-type: text/html; charset=utf-8");
header("Cache-Control: no-cache");
echo $_GET['callback']."(".json_encode($results).")";
exit;
}
function echo_json($arr=array(), $code = -1){
$arr = is_array($arr)?$arr:array("msg"=>$arr, 'code'=>$code);
header('Content-type: application/json');
echo json_encode($arr);exit;
}
//抛出异常
public function showError($msg)
{
throw new \Exception($msg);
}
//显示错误
public function showErrorMessage($msg)
{
echo $msg;
exit;
}
private function httpGet($url) {
$curl = curl_init();
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_TIMEOUT, 500);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($curl, CURLOPT_URL, $url);
$res = curl_exec($curl);
curl_close($curl);
return $res;
}
// POST请求
public function wxHttpsRequestPem($url, $vars, $second=30,$aHeader=array()){
$ch = curl_init();
//超时时间
curl_setopt($ch,CURLOPT_TIMEOUT,$second);
curl_setopt($ch,CURLOPT_RETURNTRANSFER, 1);
//这里设置代理,如果有的话
//curl_setopt($ch,CURLOPT_PROXY, '10.206.30.98');
//curl_setopt($ch,CURLOPT_PROXYPORT, 8080);
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false);
curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,false);
//以下两种方式需选择一种
//第一种方法,cert 与 key 分别属于两个.pem文件
//默认格式为PEM,可以注释
curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
curl_setopt($ch,CURLOPT_SSLCERT,$this->basePath.'cert/apiclient_cert.pem');
//默认格式为PEM,可以注释
curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
curl_setopt($ch,CURLOPT_SSLKEY,$this->basePath.'cert/apiclient_key.pem');
curl_setopt($ch,CURLOPT_CAINFO,'PEM');
curl_setopt($ch,CURLOPT_CAINFO,$this->basePath.'cert/rootca.pem');
//第二种方式,两个文件合成一个.pem文件
//curl_setopt($ch,CURLOPT_SSLCERT,getcwd().'/all.pem');
if( count($aHeader) >= 1 ){
curl_setopt($ch, CURLOPT_HTTPHEADER, $aHeader);
}
curl_setopt($ch,CURLOPT_POST, 1);
curl_setopt($ch,CURLOPT_POSTFIELDS,$vars);
$data = curl_exec($ch);
if($data){
curl_close($ch);
return $data;
}
else {
$error = curl_errno($ch);
echo "call faild, errorCode:$error\n";
curl_close($ch);
return false;
}
}
private function httpsRequest($url, $data = null)
{
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
if (!empty($data)){
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
}
curl_setopt($curl, CURLOPT_TIMEOUT, 3000);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($curl);
curl_close($curl);
return $output;
}
private function fileext($filepath)
{
return strtolower(trim(substr(strrchr($filepath, '.'), 1, 10)));
}
/*
* 获取当前页面完整URL地址
*/
private function getUrl() {
$sys_protocal = isset($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == '443' ? 'https://' : 'http://';
$php_self = $_SERVER['PHP_SELF'] ? $this->safe_replace($_SERVER['PHP_SELF']) : $this->safe_replace($_SERVER['SCRIPT_NAME']);
$path_info = isset($_SERVER['PATH_INFO']) ? $this->safe_replace($_SERVER['PATH_INFO']) : '';
$relate_url = isset($_SERVER['REQUEST_URI']) ? $this->safe_replace($_SERVER['REQUEST_URI']) : $php_self.(isset($_SERVER['QUERY_STRING']) ? '?'.$this->safe_replace($_SERVER['QUERY_STRING']) : $path_info);
return $sys_protocal.(isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '').$relate_url;
}
/*
* 安全过滤函数
* @parame $string
* @return string
*/
function safe_replace($string)
{
$string = str_replace('%20','',$string);
$string = str_replace('%27','',$string);
$string = str_replace('%2527','',$string);
$string = str_replace('*','',$string);
$string = str_replace('"','"',$string);
$string = str_replace("'",'',$string);
$string = str_replace('"','',$string);
$string = str_replace(';','',$string);
$string = str_replace('>','>',$string);
$string = str_replace('<','<',$string);
$string = str_replace('{','',$string);
$string = str_replace('}','',$string);
$string = str_replace('\\','',$string);
return $string;
}
// 生成随机字符串
public 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;
}
// 数组转XML
public function arrayToXml($arr)
{
$xml = "";
foreach ($arr as $key=>$val) {
$xml.="<".$key.">".$key.">";
}
$xml.="";
return $xml;
}
// 获取签名
public function getSign($arr)
{
$arr = $arr ? $arr : $this->parameters;
// 参数按字典排序
unset($arr['sign']);
ksort($arr);
$str = '';
foreach ($arr as $key => $val) {
if ($val != null) {
//$key = $lower ? strtolower($key) : $key;
$str .= $key . '=' . $val . '&';
}
}
// 加上partnerKey, md5加密
$str .= 'key='.$this->partnerKey;
return strtoupper(md5($str));
}
}