寫了幾個常用的微信接口,項目時間過於緊迫,未經整理,留待有空時再來整理或者擴展吧。
建議大家使用前,先去微信官方文檔那邊看一看,雖然微信的文檔着實有點坑,但是總歸還是能瞭解大概的業務邏輯以及找到一些排錯手段來使用。
<?php
namespace think;
use think\Cache;
// 字符編碼
header("Content-Type:text/html; charset=utf-8");
// 微信接口類
class Wechatmsg{
private static $appid;//公衆號appid
private static $appsecret;//公衆號secret
private static $app_id;//小程序appid
private static $app_secret;//小程序secret
public function __construct()
{
}
// 微信授權地址
public static function getAuthorizeUrl($url){
self::$appid = config('site.app_id')?config('site.app_id'):''; // 開發者ID(AppID)
self::$appsecret = config('site.app_secret')?config('site.app_secret'):''; // 開發者密碼(AppSecret)
self::$app_id = config('site.miniapp_id')?config('site.miniapp_id'):''; // 開發者ID(AppID)
self::$app_secret = config('site.miniapp_secret')?config('site.miniapp_secret'):''; // 開發者密碼(AppSecret)
$url_link = urlencode($url);
return "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" . self::$appid . "&redirect_uri={$url_link}&response_type=code&scope=snsapi_base&state=1#wechat_redirect";
}
// 獲取TOKEN
public static function getToken(){
self::$appid = config('site.app_id')?config('site.app_id'):''; // 開發者ID(AppID)
self::$appsecret = config('site.app_secret')?config('site.app_secret'):''; // 開發者密碼(AppSecret)
self::$app_id = config('site.miniapp_id')?config('site.miniapp_id'):''; // 開發者ID(AppID)
self::$app_secret = config('site.miniapp_secret')?config('site.miniapp_secret'):''; // 開發者密碼(AppSecret)
// $urla = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" . self::$appid . "&secret=" . self::$appsecret;
$urla = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=".config('site.app_id')."&secret=".config('site.app_secret');
$outputa = self::curlGet($urla);
$result = json_decode($outputa, true);
return $result['access_token'];
}
// 獲取TOKEN
public static function get_Token(){
self::$appid = config('site.app_id')?config('site.app_id'):''; // 開發者ID(AppID)
self::$appsecret = config('site.app_secret')?config('site.app_secret'):''; // 開發者密碼(AppSecret)
self::$app_id = config('site.miniapp_id')?config('site.miniapp_id'):''; // 開發者ID(AppID)
self::$app_secret = config('site.miniapp_secret')?config('site.miniapp_secret'):''; // 開發者密碼(AppSecret)
$urla = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" . self::$app_id . "&secret=" . self::$app_secret;
$outputa = self::curlGet($urla);
$result = json_decode($outputa, true);
return $result['access_token'];
}
/**
* getUserInfo 獲取用戶信息
* @param string $code 微信授權code
* @param string $weiwei_token Token
* @return array
*/
public static function getUserInfo($code, $weiwei_token){
self::$appid = config('site.app_id')?config('site.app_id'):''; // 開發者ID(AppID)
self::$appsecret = config('site.app_secret')?config('site.app_secret'):''; // 開發者密碼(AppSecret)
self::$app_id = config('site.miniapp_id')?config('site.miniapp_id'):''; // 開發者ID(AppID)
self::$app_secret = config('site.miniapp_secret')?config('site.miniapp_secret'):''; // 開發者密碼(AppSecret)
$access_token_url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" . self::$appid . "&secret=" . self::$appsecret . "&code={$code}&grant_type=authorization_code";
$access_token_json = self::curlGet($access_token_url);
$access_token_array = json_decode($access_token_json, true);
$openid = $access_token_array['openid'];
$new_access_token = $weiwei_token;
//全局access token獲得用戶基本信息
$userinfo_url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token={$new_access_token}&openid={$openid}";
$userinfo_json = self::curlGet($userinfo_url);
$userinfo_array = json_decode($userinfo_json, true);
return $userinfo_array;
}
/**
* pushMessage 發送自定義的模板消息
* @param array $data 模板數據
$data = [
'openid' => '', 用戶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))
總結: 第一、以上代碼親測可用 第二、細看文檔 第三、相信微信,出問題了絕對是自己的鍋 第四、相信微信,出問題了絕對是自己的鍋 第五、相信微信,出問題了絕對是自己的鍋 重要的事情說三遍。 出現報錯的時候不要慌,報錯複製出來百度,或者去微信官方文檔查看錯誤代碼,我在調試過程中調用以上代碼時也是報錯無數,但每次都是我背鍋,不是微信小程序或者公衆號配置有問題,就是簽名或者其他奇葩的地方有問題 最後,微信真坑。