写了几个常用的微信接口,项目时间过于紧迫,未经整理,留待有空时再来整理或者扩展吧。
建议大家使用前,先去微信官方文档那边看一看,虽然微信的文档着实有点坑,但是总归还是能了解大概的业务逻辑以及找到一些排错手段来使用。
'', 用户openid
'url' => '', 跳转链接
'template_id' => '', 模板id
'data' => [ // 消息模板数据
'first' => ['value' => urlencode('黄旭辉'),'color' => "#743A3A"],
'keyword1' => ['value' => urlencode('男'),'color'=>'blue'],
'keyword2' => ['value' => urlencode('1993-10-23'),'color' => 'blue'],
'remark' => ['value' => urlencode('我的模板'),'color' => '#743A3A']
]
];
* @param string $topcolor 模板内容字体颜色,不填默认为黑色
* @return array
*/
public static function pushMessage($data = [],$topcolor = '#0000',$code=''){
$weiwei_token = self::getToken(); // 获取微信token
// $user_info = self::getUserInfo($code, $weiwei_token);
// $openid = $user_info['openid'];
$template = [
'touser' => $data['openid'],
'template_id' => $data['template_id'],
'pagepath' => $data['url'],
'topcolor' => $topcolor,
'data' => $data['data']
];
$json_template = json_encode($template);
$url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" . $weiwei_token;
$result = self::curlPost($url, urldecode($json_template));
$resultData = json_decode($result, true);
return $resultData;
}
/*
* 小程序发送模板消息
* */
public static function send_msg($data = []){
$weiwei_token = self::get_Token(); // 获取微信token
$template = [
'touser' => $data['openid'],
'template_id' => $data['template_id'],
'page' => $data['page'],
'data' => $data['data']
];
$json_template = json_encode($template);
$url = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=" . $weiwei_token;
$result = self::curlPost($url, urldecode($json_template));
$resultData = json_decode($result, true);
return $resultData;
}
/*
* 发送站内信
* */
public static function send_message($id='',$touser='',$fromuser=1,$type=''){
$msgtemplate = Db('msgtemplate')->where(array('id' => $id))->find();
$data['createtime'] = $data['updatetime'] = time();
$data['title'] = $msgtemplate['name'];
$data['content'] = $msgtemplate['content'];
$data['touser'] = $touser;
$data['fromuser'] = $fromuser;
$data['type'] = $type;
$data['temid'] = $id;
$data['image'] = $msgtemplate['image'];
if(Db('message')->insert($data)){
return true;
}else{
return false;
}
}
/*
* 是否关注
* */
public static function can_push(){
$access_token = self::getToken(); // 获取微信token
var_dump($access_token);
$subscribe_msg = 'https://api.weixin.qq.com/cgi-bin/user/info?access_token='.$access_token.'&openid=oifrh1QtOleXgUwheISByEgaI_Fo';
$subscribe = json_decode(self::curlGet($subscribe_msg));var_dump($subscribe);
}
/**
* addLog 日志记录
* @param string $log_content 日志内容
*/
public static function addLog($log_content = ''){
$data = "";
$data .= "DATE: [ " . date('Y-m-d H:i:s') . " ]\r\n";
$data .= "INFO: " . $log_content . "\r\n\r\n";
file_put_contents('/wechat.log', $data, FILE_APPEND);
}
/**
* 发送get请求
* @param string $url 链接
* @return bool|mixed
*/
private static function curlGet($url){
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($curl);
if(curl_errno($curl)){
return 'ERROR ' . curl_error($curl);
}
curl_close($curl);
return $output;
}
/**
* 发送post请求
* @param string $url 链接
* @param string $data 数据
* @return bool|mixed
*/
private static function curlPost($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_RETURNTRANSFER, 1);
$output = curl_exec($curl);
curl_close($curl);
return $output;
}
public static function getSignPackage($url='') {
$appId = config('site.app_id')?config('site.app_id'):''; // 开发者ID(AppID)
$appSecret = config('site.app_secret')?config('site.app_secret'):''; // 开发者密码(AppSecret)
$jsapiTicket = self::getJsApiTicket($appId,$appSecret);
// 注意 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 = self::createNonceStr();
// 这里参数的顺序要按照 key 值 ASCII 码升序排序
$string = "jsapi_ticket={$jsapiTicket}&noncestr={$nonceStr}×tamp={$timestamp}&url={$url}";
//var_dump($url);
// var_dump($string);
$signature = sha1($string);
// var_dump($signature);die;
$signPackage = array(
"nonceStr" => $nonceStr,
"timestamp" => $timestamp,
"url" => $url,
"signature" => $signature,
"rawString" => $string
);
return $signPackage;
}
public static 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;
}
public static function getJsApiTicket($appId,$appSecret) {
// jsapi_ticket 应该全局存储与更新,以下代码以写入到文件中做示例
$jsapi_ticket = Cache::get('jsapi_ticket'.$appId);
if(!$jsapi_ticket || empty($jsapi_ticket)){
$accessToken = self::getAccessToken($appId,$appSecret);
// 如果是企业号用以下 URL 获取 ticket
// $url = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token=$accessToken";
$url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token={$accessToken}";
$res = json_decode(self::httpGet($url));
$ticket = $res->ticket;
$jsapi_tickets['expire_time'] = time() + 7000;
$jsapi_tickets['jsapi_ticket'] = $ticket;
Cache::set('jsapi_ticket'.$appId,$jsapi_tickets);
}else{
if($jsapi_ticket['expire_time'] <= time()){//缓存失效
$accessToken = self::getAccessToken($appId,$appSecret);
// 如果是企业号用以下 URL 获取 ticket
// $url = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token=$accessToken";
$url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token={$accessToken}";
$res = json_decode(self::httpGet($url));
$ticket = $res->ticket;
$jsapi_tickets['expire_time'] = time() + 7000;
$jsapi_tickets['jsapi_ticket'] = $ticket;
Cache::set('jsapi_ticket'.$appId,$jsapi_tickets);
}else{
$jsapi_tickets = $jsapi_ticket;
}
}
// $accessToken = self::getAccessToken($appId,$appSecret);
// // 如果是企业号用以下 URL 获取 ticket
// // $url = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token=$accessToken";
// $url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token={$accessToken}";
// $res = json_decode(self::httpGet($url));
// $ticket = $res->ticket;
// $jsapi_tickets['expire_time'] = time() + 7000;
// $jsapi_tickets['jsapi_ticket'] = $ticket;
// Cache::set('jsapi_ticket'.$appId,$jsapi_tickets);
return $jsapi_tickets['jsapi_ticket'];
}
public static function getAccessToken($appId,$appSecret) {
// access_token 应该全局存储与更新,以下代码以写入到文件中做示例
$data = Cache::get('access_token'.$appId);
if(!$data || empty($data)){
$url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$appId}&secret={$appSecret}";
$res = json_decode(self::httpGet($url));
$access_token = $res->access_token;
$datas['expire_time'] = time() + 7000;
$datas['access_token'] = $access_token;
Cache::set('access_token'.$appId,$datas);
}else{
if($data['expire_time'] <= time()){//缓存失效
$url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$appId}&secret={$appSecret}";
$res = json_decode(self::httpGet($url));
$access_token = $res->access_token;
$datas['expire_time'] = time() + 7000;
$datas['access_token'] = $access_token;
Cache::set('access_token'.$appId,$datas);
}else{
$datas = $data;
}
}
// $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$appId}&secret={$appSecret}";
// $res = json_decode(self::httpGet($url));
// $access_token = $res->access_token;
// $datas['expire_time'] = time() + 7000;
// $datas['access_token'] = $access_token;
// Cache::set('access_token'.$appId,$datas);
return $datas['access_token'];
}
public static 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;
}
}
使用方式:
//引入微信操作类
use think\Wechatmsg;
//发送小程序模板消息
$data['openid'] = '你的微信小程序appid';
$data['template_id'] = '小程序模板id';
$data['page'] = '需要跳转的小程序页面路径';
$data['data'] = array(
'keyword1' => array("value" => '123', "color" => "#4a4a4a"),
'phrase1' => array("value" => '审核'),
'thing2' => array("value" => '审核结果'),
'date3' => array("value" => date('Y-m-d', time())),
'date4' => array("value" => date('Y-m-d', time())),
'thing7' => array("value" => '审核结果'),
);
WeChatmsg::send_msg($data);
//发送公众号模板消息
$data['openid'] = '你的公众号appid';
$data['template_id'] = '你的公众号模板id';
$data['url'] = '需要跳转的路径';
$data['data'] = array(
'keyword1' => array("value" => date('Y-m-d', time()), "color" => "#4a4a4a"),//提现时间
'keyword2' => array("value" => date('Y-m-d', time())),//到账时间
'keyword3' => array("value" => 100),//到账金额
'keyword4' => array("value" => 111),//账户余额
'remark' => array('value' => '测试推送')
);
WeChatmsg::pushMessage($data);
//获取地理位置
//此处要说明一下,后端的微信地理位置的获取并不能直接获取到地址,只是获取到前端所需的jsapi_ticket和签名等信息,前端拿到后再请求微信接口即可拿到经纬度信息。注意:拿到jsapi_ticket和access_token的时候,一定要做缓存的操作,这两个东西微信都有调用次数限制,微信那边的有效时长为7200s,本地可根据此时间做一定的缓存操作。
//$url指的是当前页面所在地址,具体是使用后端动态获取还是由前端传入,要看具体项目情况,我使用的是前端传入的方式,之所以使用了urldecode是因为项目过程中发生了个奇怪现象,url在传输过程中出现了被转义的情况,使用时根据自己的情况选择一下就OK。
Wechatmsg::getSignPackage(urldecode($url))
总结: 第一、以上代码亲测可用 第二、细看文档 第三、相信微信,出问题了绝对是自己的锅 第四、相信微信,出问题了绝对是自己的锅 第五、相信微信,出问题了绝对是自己的锅 重要的事情说三遍。 出现报错的时候不要慌,报错复制出来百度,或者去微信官方文档查看错误代码,我在调试过程中调用以上代码时也是报错无数,但每次都是我背锅,不是微信小程序或者公众号配置有问题,就是签名或者其他奇葩的地方有问题 最后,微信真坑。