小程序授權(quán)登陸

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


登陸提示

授權(quán)

登陸成功

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


授權(quán)手機(jī)端

解決的問(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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容