所要實(shí)現(xiàn)效果如下圖



圖二在手機(jī)端顯示的效果其實(shí)是下面這樣的

解決的問(wèn)題其實(shí)是官方現(xiàn)在不可以使用wx.getUserInfo(OBJECT)來(lái)彈出授權(quán)窗口了,須使用button按鈕來(lái)獲取,文檔說(shuō)明在這。
如果要寫(xiě)個(gè)按鈕給用戶主動(dòng)去點(diǎn)估計(jì)不大可能,所以采用組件來(lái)實(shí)現(xiàn)進(jìn)入頁(yè)面引導(dǎo)用戶去點(diǎn)。官方有對(duì)組件的使用介紹:https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/。
具體操作如下:
一、新建組件目錄
在你想把組件內(nèi)容放的位置文件夾右擊-》新建Component,建議單獨(dú)建一個(gè)文件夾。新建后開(kāi)發(fā)者工具自動(dòng)建立了js,wxss,json,wxml。我這里建立的四個(gè)文件命名為:dologin.js 、dologin.wxss、dologin.json、dologin.wxml
二、代碼實(shí)現(xiàn)
dologin.js
// template/dologin.js
var util = require('../../utils/util.js');
var config = require('../../utils/config.js');
var app = getApp();
Component({
options: {
mutipleSlots: true
},
/**
* 組件的屬性列表
*/
properties: {
//彈窗標(biāo)題
title:{
type: String,
value: '標(biāo)題' //默認(rèn)值
},
//彈窗內(nèi)容
content: {
type: String,
value:'彈窗內(nèi)容'
},
//彈窗確認(rèn)按鈕文字
confirmText: {
type: String,
value: '確定'
}
},
/**
* 組件的初始數(shù)據(jù)
*/
data: {
//彈窗顯示控制
isShow:true
},
/**
* 組件的方法列表
*/
methods: {
//隱藏彈窗
hideDologin(){
this.setData({
isShow: false
})
},
//展示彈窗
showDologin(){
this.setData({
isShow: true
})
},
/*
*triggerEvent組件之間通信
*/
confirmEvent() {
this.triggerEvent("confirmEvent");
},
bindGetUserInfo(e) {
this.triggerEvent("bindGetUserInfo",{event:e});
}
},
})
dologin.json
{
"component": true,
"usingComponents": {}
}
dologin.wxss
/* template/dologin.wxss */
.dialog-mask{
position: fixed;
z-index: 1000;
top: 0;
right: 0;
left: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.3);
} .dialog-info{
position: fixed;
z-index: 5000;
width: 80%;
max-width: 600rpx;
top: 50%;
left: 50%;
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
background-color: #FFFFFF;
text-align: center;
border-radius: 3px;
overflow: hidden;
} .dialog-title{
font-size: 36rpx;
padding: 30rpx 30rpx 10rpx;
} .dialog-content{
padding: 10rpx 30rpx 20rpx;
min-height: 80rpx;
font-size: 32rpx;
line-height: 1.3;
word-wrap: break-word;
word-break: break-all;
color: #999999;
} .dialog-footer{
display: flex;
align-items: center;
position: relative;
line-height: 90rpx;
font-size: 34rpx;
} .dialog-btn{
display: block;
-webkit-flex: 1;
flex: 1;
position: relative;
color: #3CC51F;
}
dologin.wxml
<!--template/dologin.wxml-->
<view class='dialog-container' hidden="{{!isShow}}">
<view class='dialog-mask'></view>
<view class='dialog-info'>
<view class='dialog-title'>{{ title }}</view>
<view class='dialog-content'>{{ content }}</view>
<view class='dialog-footer'>
<button class='dialog-btn' open-type="getUserInfo" bindgetuserinfo='bindGetUserInfo' catchtap='confirmEvent'>{{ confirmText }}</button>
</view>
</view>
</view>
然后在需要使用的地方進(jìn)行如下代碼操作:
我是在進(jìn)入home就給出授權(quán)登陸的,所以
- 我在home.json中首先引入組件
{
"navigationBarTitleText": "首頁(yè)",
"enablePullDownRefresh": true,
"backgroundTextStyle": "dark",
"usingComponents":{
"dialog": "../../template/dialog"
}
}
- 接著在home.wxml中寫(xiě)
<dialog id='dialog'
title='登錄提示'
content='小程序需要您的授權(quán)才能提供更好的服務(wù)哦'
confirmText='知道了'
bind:confirmEvent='confirmEvent'
bind:bindGetUserInfo='bindGetUserInfo'>
</dialog>
- 最后在home.js中的onReady函數(shù)中寫(xiě)
//獲得dialog組件
this.dialog = this.selectComponent("#dialog");
},
showDologin: function () {
this.dialog.showDialog();
},
confirmEvent: function () {
this.dialog.hideDologin();
},
bindGetUserInfo: function (e) {
// 用戶點(diǎn)擊授權(quán)后,這里可以做一些登陸操作 this.login();
this.wxlogin(e.detail.event)
},
代碼分析
首先我們進(jìn)入頁(yè)面首頁(yè)后,觸發(fā)onReady函數(shù)對(duì)頁(yè)面初次渲染,引入組件,顯示彈窗,然后我們點(diǎn)擊彈窗中的“”我知道了“”,這個(gè)按鈕里綁定的是bindGetUserInfo授權(quán)參數(shù),open-type="getUserInfo",事件是confirmEvent,點(diǎn)擊后跳轉(zhuǎn)到授權(quán)的選擇,在組件的js文件中的組件交互里,使用triggerEvent來(lái)進(jìn)行交互,作為登陸,需要傳參,所以在后面可接入?yún)?shù)的傳遞{event:e}。最后在home.js中的bindGetUserInfo方法里進(jìn)行登陸操作。
微信登陸
wxlogin: function (e) {
if (e.detail.errMsg == 'getUserInfo:fail auth deny') {
wx.showModal({
title: '提示',
content: '您已拒絕授權(quán),請(qǐng)點(diǎn)擊確定后換手機(jī)號(hào)碼登錄或者重新允許授權(quán)',
success: function (res) { }
})
return false
}
wx.login({
success: function (res) { //使用encodeURI解決再次調(diào)用的時(shí)候解密失敗錯(cuò)誤-41003
var code = encodeURI(res.code)
var AppID = config.AppID
var AppSecret = config.AppSecret
var encrypted =encodeURI( e.detail.encryptedData)
var iv = encodeURI(e.detail.iv)
try {
var cross_sn = wx.getStorageSync('cross_sn')
} catch (e) {
var cross_sn = ''
}
app.reqPost("login", "wxlogin", {
code: code,
encrypted: encrypted,
iv: iv,
appID: AppID,
appSecret: AppSecret,
cross_sn: cross_sn,
cur_store: config.cur_store
}, function (res) {
wx.setStorageSync('token', res.data.datas.token)
wx.setStorageSync('meReload', true)
wx.setStorageSync('cartReload', true)
wx.setStorageSync('goodsReload', true)
wx.navigateBack()
})
}
})
},
后臺(tái)代碼
public function wxloginOp(){
if($_REQUEST['platform']=='wxmini'){
$json=$this->_getUserInfo();
}
else{
$json=$this->get_access_tokenOp();
}
try{
Model()->beginTransaction();
$data=array();
$data['openid']=empty($json->openid)?$json->openId:$json->openid;
$data['nickname']=empty($json->nickname)?$json->nickName:$json->nickname;
$data['headimgurl']=empty($json->avatarUrl)?$json->avatarUrl:$json->avatarurl;
···
$data['unionid']=empty($json->unionid)?$json->unionId:$json->unionid;
$data['add_time']=TIMESTAMP;
$r=Model("wxlogin_userinfo")->addData($data);
if(!$r)
throw new Exception("網(wǎng)絡(luò)繁忙");
$model_member=Model("member");
$unionId=empty($json->unionid)?$json->unionId:$json->unionid;
$memberInfo=$model_member->getMemberInfo(array("unionid"=>$unionId));
if(empty($memberInfo)){
//此處業(yè)務(wù)代碼省略
$member_id=$model_member->addMember($memberInsert);
if(!$member_id)
throw new Exception("網(wǎng)絡(luò)繁忙");
$memberInfo=$model_member->getMemberInfo(array("member_id"=>$member_id));
}
//此處業(yè)務(wù)代碼省略
if(empty($token)) {
throw new Exception('網(wǎng)絡(luò)繁忙');
}
Model()->commit();
output_data(array("token"=>$token,"data"=>$data,"send_data"=>$send_data));
}
catch(Exception $e){
Model()->rollback();
output_error($e->getMessage());
}
}
private function _getUserInfo(){
require_once(dirname(dirname(__FILE__)).DS."resource".DS.'wxBizDataCrypt.php');
$code = $_REQUEST['code'];
$appId = $_REQUEST['appID'];
$appSecret = $_REQUEST['appSecret'];
$grant_type="authorization_code";
$url_get = 'https://api.weixin.qq.com/sns/jscode2session?appid='.$appId.'&secret='.$appSecret.'&js_code='.$code.'&grant_type='.$grant_type;
try{
$json=json_decode($this->curlGet($url_get));
if (!$json->errmsg){
$sessionKey = $json->session_key;
$encryptedData=$_REQUEST['encrypted'];
$iv=$_REQUEST['iv'];
$appID=$_REQUEST['appID'];
$pc = new WXBizDataCrypt($appID, $sessionKey);
$errCode = $pc->decryptData($encryptedData, $iv, $data );
if ($errCode == 0) {
return json_decode($data);
} else {
throw new Exception($errCode);
}
}else {
throw new Exception('獲取session_key發(fā)生錯(cuò)誤:錯(cuò)誤代碼'.$json->errcode.',微信返回錯(cuò)誤信息:'.$json->errmsg);
}
}
catch(Exception $e){
output_error($e->getMessage());
}
}
private function curlGet($url,$method='get',$data=''){
$ch = curl_init();
$header=array();
$header[] = "Accept-Charset: utf-8";
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, strtoupper($method));
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (compatible; MSIE 5.01; Windows NT 5.0)');
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_AUTOREFERER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$temp = curl_exec($ch);
curl_close($ch);
return $temp;
}
<?php
/**
* 對(duì)微信小程序用戶加密數(shù)據(jù)的解密示例代碼.
*
* @copyright Copyright (c) 1998-2014 Tencent Inc.
*/
include_once "errorCode.php";
class WXBizDataCrypt
{
private $appid;
private $sessionKey;
/**
* 構(gòu)造函數(shù)
* @param $sessionKey string 用戶在小程序登錄后獲取的會(huì)話密鑰
* @param $appid string 小程序的appid
*/
public function __construct( $appid, $sessionKey)
{
$this->sessionKey = $sessionKey;
$this->appid = $appid;
}
/**
* 檢驗(yàn)數(shù)據(jù)的真實(shí)性,并且獲取解密后的明文.
* @param $encryptedData string 加密的用戶數(shù)據(jù)
* @param $iv string 與用戶數(shù)據(jù)一同返回的初始向量
* @param $data string 解密后的原文
*
* @return int 成功0,失敗返回對(duì)應(yīng)的錯(cuò)誤碼
*/
public function decryptData( $encryptedData, $iv, &$data )
{
if (strlen($this->sessionKey) != 24) {
return ErrorCode::$IllegalAesKey;
}
$aesKey=base64_decode($this->sessionKey);
if (strlen($iv) != 24) {
return ErrorCode::$IllegalIv;
}
$aesIV=base64_decode($iv);
$aesCipher=base64_decode($encryptedData);
$result=openssl_decrypt( $aesCipher, "AES-128-CBC", $aesKey, 1, $aesIV);
$dataObj=json_decode( $result );
if( $dataObj == NULL )
{
return ErrorCode::$IllegalBuffer;
}
if( $dataObj->watermark->appid != $this->appid )
{
return ErrorCode::$IllegalBuffer;
}
$data = $result;
return ErrorCode::$OK;
}
}
至此,實(shí)現(xiàn)完成。在開(kāi)發(fā)者工具中測(cè)試的時(shí)候,每測(cè)試一次需要清理緩存。下一篇總結(jié)小程序消息推送功能的實(shí)現(xiàn)。
//使用encodeURI解決再次調(diào)用的時(shí)候解密失敗錯(cuò)誤-41003
在小程序前端:
var code = encodeURI(res.code)
var AppID = config.AppID
var AppSecret = config.AppSecret
var encrypted =encodeURI( e.detail.encryptedData)
var iv = encodeURI(e.detail.iv)
更新:2019-5-7
參考鏈接:
https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/
https://blog.csdn.net/YZ0826/article/details/80371132#commentsedit
https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/events.html