php 微信公众号签名signature生成方法
因为要做网页的微信分享,分享的时候想自定义 分享标题 分享摘要 和分享缩略图,所以要用到微信公众号的jssdk,必然就牵扯到微信签名。
以thinkphp5为例,展示整个生成和使用的过程。
步骤:
1、获取微信access_token : 自定义函数 getWxAccessToken();
2、根据1 的access_token,获取ticket: 自定义函数 getWxTicket();
3、根据2 的ticket,自己拼装字符串,并生成签名sign: 自定义函数 makeWxSha1Sign();
后台php代码如下:
/**
* 生成微信公众号签名
* @param string url 前端微信分享页面的url全地址
*/
public function getWxShareSign()
{
$signData = input('');
if( !$signData['url'] ){
$this->_error('参数错误');
}
$ticket = '';
if($redis_ticket = cache::get('wx_share_ticket')){
$ticket = $redis_ticket;
}else{
$access_token = $this->getWxAccessToken(); //获取微信access_token
$ticket = $this->getWxTicket($access_token); //获取微信ticket
}
$signData['jsapi_ticket'] = $ticket;
$signData['noncestr'] = 'abs1004';
$signData['timestamp'] = time();
$sign = $this->makeWxSha1Sign($signData); // 生成微信签名
$signData['sign'] = $sign;
$this->_success($signData); // jsapi_ticket, noncestr, timestamp, sign 都返回给前端,供前端页面微信验签使用
}
//生成 sha1 签名
private function makeWxSha1Sign($arr){
$str = "";
//升序数组的键
$keyArr = [];
foreach ($arr as $k => $v) {
array_push($keyArr,$k);
}
sort($keyArr);
reset($keyArr);
//升序数组的字符串拼接,删除signature
foreach ($keyArr as $key => $value) {
$linker = '';
if($key!=0){
$linker = '&';
}
$str .= $linker.$value.'='.$arr[$value];
}
log_result('wxshare signStr='.$str);
//字符串SHA1
$signature = sha1($str);
return $signature;
}
//微信公众号 票据
private function getWxTicket($access_token){
$ticketUrl = 'https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token='.$access_token.'&type=jsapi';
$ticketResp = file_get_contents($ticketUrl);
if(!$ticketResp) $this->_error('ticket 获取失败');
$ticketData = json_decode($ticketResp, true);
if( isset($ticketData['ticket']) ){
$ticket = $ticketData['ticket'];
cache::set('wx_share_ticket',$ticket,7200);
log_result('ticket='.$ticket);
return $ticket;
}else{
$this->_error('ticket 解析错误');
}
}
//微信公众号 token
private function getWxAccessToken(){
$tokeUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=".config('wxgzh_appid')."&secret=".config('wxgzh_secret');
$tokenResp = file_get_contents($tokeUrl);
if(!$tokenResp) $this->_error('token 服务器返回失败');
$tokenData = json_decode($tokenResp, true);
if( !isset($tokenData['access_token']) ) $this->_error($tokenData['errmsg']);
return $tokenData['access_token'];
}
// 成功返回封装 json格式的数据给前端
protected function _success ($data=null, $info='操作成功', $status=1000)
{
$result = array(
'status' => $status,
'msg' => $info,
'data' => $data,
);
die( json_encode($result) );
}
// 失败返回封装 json格式的数据给前端
protected function _error ($info='系统错误', $status=-1004)
{
$result = array(
'status' => $status,
'msg' => $info,
);
die( json_encode($result) );
}
前端代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge" >
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0,user-scalable=no" >
<meta name="description" content="正方形口腔 ">
<meta name="keywords" content="正方形口腔 ">
<title>正方形口腔 - 送牙币</title>
<link rel="stylesheet" href="/res/css/bootstrap.css">
<link rel="stylesheet" href="/res/css/font-awesome.css">
<script src="/res/js/jquery.min.js"></script>
<script src="/res/js/bootstrap.min.js"></script>
<script type="text/javascript" src="https://res.wx.qq.com/open/js/jweixin-1.4.0.js"></script>
<style>
body{
background:#fc471e url("/res/img/share/bg@2x.png") no-repeat 100% 100%;
font-weight: 200;
}
#content {
background: transparent;
}
::-webkit-input-placeholder { /* WebKit browsers */
color: #F06D4A;
}
:-moz-placeholder { /* Mozilla Firefox 4 to 18 */
color: #F06D4A;
}
::-moz-placeholder { /* Mozilla Firefox 19+ */
color: #F06D4A;
}
:-ms-input-placeholder { /* Internet Explorer 10+ */
color: #F06D4A;
}
header{
height: 48px;
width:100%;
background: #fff;
color: #333;
text-align: center;
line-height: 48px;
font-size: 17px;
}
.quan {
vertical-align: middle;
border: 0;
width: 100%;
height: auto;
}
.form-control{
/*height: 48px;*/
border:none;
font-size: 14px;
padding-right: 0;
}
input{
}
.abs-input-box{
width: 90%;
margin: 1px 5%;
}
.btn-code{
height: 38px;
padding: 0;
font-weight: 200;
width:100%;
background: #fad142;
}
.input-mobile-box{
border-radius: 5px;
background: #fff;
background-image: url('/res/img/share/icon_username@2x.png');
background-repeat: no-repeat;
background-size: 20px 20px;
background-position: 8px 8px;
overflow: hidden;
height: 40px;
line-height: 40px;
padding: 0 0;
}
.input-mobile{
height: 30px;
width: 100%;
border:none;
line-height: 30px;
color: #262626;
margin-left: 40px;
font-weight: 300;
margin-top:5px ;
}
.input-code-box{
border-radius: 5px;
background: #fff;
width:60%;
float:left;
background-image: url('/res/img/share/icon_yanzhengma@2x.png');
background-repeat: no-repeat;
background-size: 20px 20px;
background-position: 8px 8px;
overflow: hidden;
height: 38px;
line-height: 38px;
}
.input-code{
color: #262626;
width: 100%;
border:none;
height: 30px;
line-height: 30px;
margin-top: 4px;
margin-left: 40px;
font-weight: 300;
padding: 0 0;
}
.btn-quan{
height: 48px;
border-radius: 5px;
background: #feec34;
width:100%;
font-weight: 400;
font-size: 18px;
}
.mt-35{
margin-top: 35px;
}
.btn.focus, .btn:focus, .btn:hover{
color:inherit;
}
.bg-gray{
background: #999;
color:#f3f3f3;
}
.bg-red{
background: #fa6262;
}
.color-white{
color:#fff;
}
.color-red{
color:rgb(219,43,19);
}
.test-before:before{
content: 'abs';
}
td{line-height: 180%;}
</style>
</head>
<body>
<div class="container">
<!-- 优惠券券 -->
<div class="row mt-35">
<img class="quan" src="/res/img/share/pic_lihe@2x.png" alt="正方形口腔-分享领券">
</div>
<!-- 手机号 -->
<div class="row ">
<div class="abs-input-box">
<form role="form">
<div class="form-group">
<div class="input-mobile-box">
<input type="text" required class="input-mobile" id="mobile" placeholder="请输入11位中国大陆手机号">
</div>
</div>
<div class="form-group">
<div style="height: 40px;">
<div class="input-code-box" >
<input type="text" required class=" input-code" id="code" placeholder="输入短信验证码">
</div >
<div style="width:30%;float:right;height:40px;">
<button class="btn btn-code color-red" type="button" id="btn_get_code">获取验证码</button>
</div>
</div>
</div>
<div class="form-group">
<button type="button" class=" btn btn-quan color-red" id="btn_download">下载领币</button>
</div>
</form>
</div>
</div>
<div class="mt-35 color-white">
<p>
活动规则:<br />
</p>
<table>
<tr>
<td style="vertical-align: top">1、</td>
<td>活动时间:2018年11月1日-2019年6月30日。</td>
</tr>
<tr>
<td style="vertical-align: top">2、</td>
<td>已在正方形口腔建档的用户(以下简称“老用户”)可以通过此链接邀请好友下载注册正方形口腔APP,并参照以下规则获得相应牙币:</td>
</tr>
<tr>
<td style="vertical-align: top">a、</td>
<td>老用户每邀请一名未在正方形口腔建档的用户(以下简称“新用户”)注册登录正方形APP后,老用户即可获得50牙币;</td>
</tr>
<tr>
<td style="vertical-align: top">b、</td>
<td>被邀请的新用户注册登录正方形口腔APP后,即可获得100牙币。</td>
</tr>
<tr>
<td style="vertical-align: top">3、</td>
<td>1牙币=1元人民币,牙币可用于诊费支付及礼品兑换。</td>
</tr>
<tr>
<td style="vertical-align: top">4、</td>
<td>活动过程中凡是以恶意手段(包括但不限于作弊、攻击系统等)参与的用户,正方形口腔有权利终止其参与活动并取消获取牙币的资格。</td>
</tr>
<tr>
<td style="vertical-align: top">5、</td>
<td>在法律范围内正方形口腔拥有本活动解释权。</td>
</tr>
</table>
</div>
</div>
</body>
<script>
var domain = "{$Think.config.site_url}"; // 域名 https://www.zhipur.com
var curUrl = window.location.href;
//微信设置
var shareLink = curUrl;
var shareIcon = domain+"/logo.png";
var shareDesc = "微信分享内容摘要";
// ajax请求后台接口,获取微信签名
$.ajax({
url: domain+"/api/webview/getWxShareSign",
data:{
url: curUrl
},
type: 'POST',
dataType: 'json',
success: function (res) {
if(res.status===1000){
wx.config({
debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: 'wx112312312321312312', // 必填,换成你公众号里的appid
timestamp: res.data.timestamp, // 必填,生成签名的时间戳
nonceStr: res.data.noncestr, // 必填,生成签名的随机串
signature: res.data.sign,// 必填,签名
jsApiList: ['onMenuShareTimeline','onMenuShareAppMessage'] // 必填,需要使用的JS接口列表
});
}else{
console.log(res.msg);
}
},
error: function (e) {
console.log(e);
}
});
wx.ready(function(){
wx.onMenuShareAppMessage({
title: '微信分享标题文字', // 分享标题
desc: shareDesc, // 分享描述
link: shareLink, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
imgUrl: shareIcon, // 分享图标
success: function () {
// 用户点击了分享后执行的回调函数
console.log('用户点击了分享');
}
});
});
wx.error(function(res){
console.log('wx jsapi fail');
});
</script>
</html>