cache->set(self::editHistoryPrefix . $this->group_id, $history, 3600*365);
return \PhalApi\DI()->cache->get(self::editHistoryPrefix . $this->group_id);
*/
namespace App\Api\WeChat;
use PhalApi\Api;
use PhalApi\Exception\BadRequestException;
/**
* 用户相关
* 实现教程:https://www.tpxhm.com/adetail/127.html
* @author cygm 20181210
*/
class CURD extends Api{
private $richFitCfg;
private $appId = "";
private $appSecret = "";
private $richFitProxy = "";
const WE_CHAT_CACHE_PREFIX = "WE_CHAT";
const WE_CHAT_CACHE_JSAPI_TICKT_KEY = "_JSAPI_TICKT";
const WE_CHAT_CACHE_ACCESS_TOKEN_KEY = "_ACCESS_TOKEN";
const WE_CHAT_API_URL_TOKEN = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s";
const WE_CHAT_API_URL_TICKET = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token=%s";
function __construct() {
//session_start();
//return parent::__construct();
$this->appId = "xxx";
$this->appSecret = "xxx";
//http curl 代理地址 ip:port
$this->richFitProxy = "xxx";
}
public function getRules() {
return array(
'getSignPackage' => array(
'share_url' => array('name' => 'share_url',
'desc' => '用作分享的URL',
'require' => true
)
),
);
}
public function getSignPackage(){
$jsapiTicket = $this->getJsApiTicket();
$url = $this->share_url;
$timestamp = time();
$nonceStr = $this->createNonceStr();
// 这里参数的顺序要按照 key 值 ASCII 码升序排序
$string = "jsapi_ticket=$jsapiTicket&noncestr=$nonceStr×tamp=$timestamp&url=$url";
$signature = sha1($string);
$signPackage = array(
"appId" => $this->appId,
"nonceStr" => $nonceStr,
"timestamp" => $timestamp,
"url" => $url,
"signature" => $signature,
"rawString" => $string
);
return $signPackage;
}
/**
* getJsApiTicket
* @return type
* @throws BadRequestException
*/
private function getJsApiTicket() {
$data = \PhalApi\DI()->cache->get(self::WE_CHAT_CACHE_PREFIX . self::WE_CHAT_CACHE_JSAPI_TICKT_KEY);
// jsapi_ticket 应该全局存储与更新,以下代码以写入到文件中做示例
if (empty($data) || ($data['expire_time'] ?? 0) < time()) {
$accessToken = $this->getAccessToken();
// 如果是企业号用以下 URL 获取 ticket
$url = sprintf(self::WE_CHAT_API_URL_TICKET, $accessToken);
\PhalApi\DI()->logger->Debug('Wechat.getJsApiTicket', [
'url' => $url,
]);
// 先实例
$curl = $this->getCurl();
// 第二个参数,表示超时时间,单位为毫秒
$rs = $curl->post( $url, http_build_query(array()
), getenv('RX_CURL_TIMEOUT'));
$rs = json_decode($rs, true);
\PhalApi\DI()->logger->Debug('Wechat.getJsApiTicket', $rs);
if (empty($rs['ticket'])) {
\PhalApi\DI()->logger->Error('Wechat.getJsApiTicket', [
'url' => $url,
]);
throw new BadRequestException("微信服务器响应失败.");
}
$rs['expire_time'] = time() + $rs['expires_in'] ?? 7000;
\PhalApi\DI()->cache->set(self::WE_CHAT_CACHE_PREFIX . self::WE_CHAT_CACHE_JSAPI_TICKT_KEY, $rs, $rs['expires_in']);
$data = $rs;
}
return $data['ticket'] ?? "";
}
/**
* access_token 应该全局存储与更新,以下代码以写入到文件中做示例
* @return type
*/
private function getAccessToken() {
// access_token 应该全局存储与更新,以下代码以写入到文件中做示例
// \PhalApi\DI()->cache->set(self::WE_CHAT_CACHE_PREFIX . self::WE_CHAT_CACHE_ACCESS_TOKEN_KEY, [], $rs['expires_in']);
$cache = \PhalApi\DI()->cache->get(self::WE_CHAT_CACHE_PREFIX . self::WE_CHAT_CACHE_ACCESS_TOKEN_KEY);
$access_token = "";
if (empty($cache) || ($cache['expire_time'] ?? 0) < time()) {
$url = sprintf(SELF::WE_CHAT_API_URL_TOKEN, $this->appId, $this->appSecret);
// 先实例
$curl = $this->getCurl();
// 第二个参数,表示超时时间,单位为毫秒
$rs = $curl->get( $url, http_build_query(array()
), getenv('RX_CURL_TIMEOUT'));
\PhalApi\DI()->logger->Debug('Wechat.getAccessToken', [
'url' => $url,
]);
$rs = json_decode($rs, true);
\PhalApi\DI()->logger->Debug('Wechat.getAccessToken', $rs);
if (!empty($rs['access_token'])) {
$rs['expire_time'] = time() + $rs['expires_in'] ?? 7000;
}else{
\PhalApi\DI()->logger->Error('Wechat.getAccessToken', [
'url' => $url,
]);
throw new BadRequestException("微信服务器响应失败.");
}
$access_token = $rs['access_token'];
\PhalApi\DI()->cache->set(self::WE_CHAT_CACHE_PREFIX . self::WE_CHAT_CACHE_ACCESS_TOKEN_KEY, $rs, $rs['expires_in']);
} else {
$access_token = $cache['access_token'];
}
return $access_token;
}
private 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;
}
private function getCurl(){
// 先实例
$curl = new \PhalApi\CUrl();
// 忽略证书验证
$curl->setOption([
CURLOPT_PROXY => $this->richFitProxy,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
CURLOPT_HTTPHEADER => array('Content-Type: application/x-www-form-urlencoded')
]);
return $curl;
}
}
网页端js
$(document).ready(function(){
var URL = location.href.split('#')[0];
//alert(location.href.split('#')[0]);
function __wechat_project(wechatInfos){
wx.config({
debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: wechatInfos.result_data.appId, // 必填,公众号的唯一标识
timestamp: wechatInfos.result_data.timestamp, // 必填,生成签名的时间戳
nonceStr: wechatInfos.result_data.nonceStr, // 必填,生成签名的随机串
signature: wechatInfos.result_data.signature,// 必填,签名
jsApiList: [
'onMenuShareAppMessage',
'onMenuShareTimeline',
'onMenuShareQQ'
] // 必填,需要使用的JS接口列表
});
/**
* 分享至好友
*/
wx.ready(function () {
/**
* 分享至朋友圈
*/
wx.onMenuShareTimeline({
title: rx_title, // 分享标题
link: URL, // 分享链接
imgUrl: rx_img_url, // 分享图标
success: function () {}
});
wx.onMenuShareAppMessage({
title: rx_title, // 分享标题
desc: rx_summary, // 分享描述
link: URL, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
imgUrl: rx_img_url, // 分享图标
type: '', // 分享类型,music、video或link,不填默认为link
dataUrl: '', // 如果type是music或video,则要提供数据链接,默认为空
success: function () {}
// 用户点击了分享后执行的回调函数
});
wx.error(function(res){
alert("errorMSG:"+res);
});
/**
* 分享至qq
*/
wx.onMenuShareQQ({
title: rx_title, // 分享标题
link: URL, // 分享链接
imgUrl: rx_img_url, // 分享图标
success: function () {
// 用户确认分享后执行的回调函数
},
cancel: function () {
// 用户取消分享后执行的回调函数
}
});
});
}
$.post("?service=App.WeChat_CURD.GetSignPackage",{ share_url : URL }, function (wechatInfos) {
if(wechatInfos.success == true){
__wechat_project(wechatInfos);
}else{
console.log(wechatInfos);
}
});
});