微信小程序開發——微信授權登錄

開發工具

前端 微信小程序開發工具
後端 idea 2018.3 +mysql8.0

後端技術棧 ----Springboot+mybatis

ps:因爲我是後端開發 所以只能寫後端。。

開發階段

一 準備賬號

郵箱註冊微信公衆平臺小程序 !!! 着重強調 是小程序註冊 !!!
註冊鏈接:微信公衆平臺

註冊完成之後 ,在開發-開發設置裏邊可以看到appid和secret,註冊的目的就是爲了獲取這兩個參數,以爲了向微信服務器發送請求

在這裏插入圖片描述

二 準備域名

因爲微信平臺的要求,需要用http:或者https:開頭的合法域名,我這裏採用的是natapp 購買的隧道,類似於服務器+域名(9RMB一個月,作爲調試開發還是可以的) ,然後將域名配置到微信的開發-開發設置裏邊
在這裏插入圖片描述
這裏需要注意的是:前端訪問的域名不能是服務器ip+端口號+接口名的方式,是要以這個request合法域名+接口名發送請求,否則請求不能發送到微信服務器端

三 代碼實現

因爲前端的同學跟我是第一次開發微信小程序,登錄獲取用戶授權頁面有點簡陋,就不發wxml了(微信版html)

前端js代碼

// pages/indxe/login/login.js
Page({

  /**
   * 頁面的初始數據
   */
  data: {

  },
  getUserInfoBtn:function(){
  
    wx.login({
      success:function(data){
          var code=data.code
        wx.getUserInfo({
          success:function(res){
           var userInfor=res
            var rawData=res.rawData
            var iv=res.iv
            var encryptedData = res.encryptedData
            console.log(encryptedData)
            wx.request({
              url:'//微信要求的合法域名+後端請求接口'
              data: {
              
                iv:         iv,
                encryptedData: encryptedData,
                code:      code
              },
              header: {
                'content-type': 'application/json' //默認值
              },
              success: function (res) {
                console.log(res.data)
              }
            })
            
          }
        })
      }
    })
  },

  /**
   * 生命週期函數--監聽頁面加載
   */
  onLoad: function (options) {

  },

  /**
   * 生命週期函數--監聽頁面初次渲染完成
   */
  onReady: function () {

  },

  /**
   * 生命週期函數--監聽頁面顯示
   */
  onShow: function () {

  },

  /**
   * 生命週期函數--監聽頁面隱藏
   */
  onHide: function () {

  },

  /**
   * 生命週期函數--監聽頁面卸載
   */
  onUnload: function () {

  },

  /**
   * 頁面相關事件處理函數--監聽用戶下拉動作
   */
  onPullDownRefresh: function () {
http://wechatapptest.natapp1.cc/takeaway/user/login',
  },

  /**
   * 頁面上拉觸底事件的處理函數
   */
  onReachBottom: function () {

  },

  /**
   * 用戶點擊右上角分享
   */
  onShareAppMessage: function () {

  }
})

後端yml文件配置

spring:
  datasource:
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/takeaway_applet?useSSL=false&characterEncoding=utf-8
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      # 初始化大小,最小,最大
      initial-size: 5
      min-idle: 5
      max-active: 50
      # 獲取連接等待超時的時間
      max-wait: 60000
      # 配置間隔多久才進行一次檢測,檢測需要關閉的空閒連接,單位是毫秒
      time-between-eviction-runs-millis: 60000
      # 配置一個連接在池中最小生存的時間,單位是毫秒
      min-evictable-idle-time-millis: 300000

mybatis:
  mapper-locations: classpath:mappers/*.xml
  type-aliases-package: com.swpu.uchain.takeawayapplet.entity
  configuration:
    map-underscore-to-camel-case: true
    use-generated-keys: true

file:
  upload-dir: "/home/hobo/testFile"


#微信端配置
wechat:
  appid: wx08cbe6a7723b4059
  secret: 184d33fb3de278d49a1411cd111eeaa2

配置文件對應類

/**
 * @ClassName WeChatAccountConfig
 * @Author hobo
 * @Date 19-3-8 下午9:49
 * @Description
 **/
@Data
@ConfigurationProperties(prefix = "wechat")
@Component
public class WeChatProperties {


    /**
     * 微信小程序appId
     */
    private String appid;

    /**
     * 微信小程序的Secret
     */
    private String secret;

    /**
     * 微信小程序消息服務器配置的token
     */
    private String token;

    /**
     * 設置微信小程序消息服務器配置的EncodingAESKey
     */
    private String aesKey;

    /**
     * 消息格式,XML或者JSON
     */
    private String msgDataFormat;

    /**
     * 開放平臺id
     */
    private String openAppId;

    /***
     * 開放平臺祕鑰
     */
    private String openAppSecret;
    /**
     * 商戶號
     */
    private String mchId;

    /**
     * 商戶密鑰
     */
    private String mchKey;

    /**
     * 商戶證書路徑
     */
    private String keyPath;

    /**
     * 微信異步通知地址
     */
    private String notifyUrl;

    /**
     * 商品簡單描述
     */
    private String title;

    /**
     * 支付類型 小程序爲JSAPI
     */
    private String tradeType;

}

WXController

PS: 微信小程序登錄分爲兩種,一種是前端在發送登錄請求時,隨機發送code,不需要用戶授權,這種方式只獲得用戶的openId,另一種方式是從微信端發來iv,encryptedData,code。後端經過算法解密處理得到用戶的一些信息,包括微信暱稱及頭像等等,我這次是採用了後者。根據前端代碼大家也可以看出前端是傳了這三個參數的。

    @ApiOperation("普通用戶登錄授權接口")
    @GetMapping(value = "/login", name = "普通用戶登錄")
    public Object getUserInfo(String encryptedData, String iv, String code) {
        Map map = new HashMap();
        if (code == null) {
            return ResultUtil.error(ResultEnum.CODE_EMPTY);
        }
        //微信登錄請求URL
        String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + weChatProperties.getAppid() + "&secret=" + weChatProperties.getSecret() + "&js_code=" + code + "&grant_type=authorization_code";
        RestTemplate restTemplate = new RestTemplate();
        String response = restTemplate.getForObject(url, String.class);
        //將Json對象轉換爲Java對象
        WeChatVO weChatVO = JSONObject.parseObject(response, WeChatVO.class);
        String openId = weChatVO.getOpenId();
        String sessionKey = weChatVO.getSessionKey();

        //解密用戶信息
        String result = AesCbcUtil.decrypt(encryptedData, sessionKey, iv, "UTF-8");
        if (null != result && result.length() > 0) {
            //ResultUtil是我自定義的Json化工具類
            return ResultUtil.success(result);

        }
        return ResultUtil.error(ResultEnum.DECRYPTION_FAILURE);
    }

解密工具類

需要引入bcprov-ext-jdk16的依賴

       <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcprov-ext-jdk16</artifactId>
            <version>1.46</version>
            <type>jar</type>
        </dependency>
import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.*;
import java.security.spec.InvalidParameterSpecException;

/**
 * @ClassName AesCbcUtil
 * @Author hobo
 * @Date 19-3-15 下午3:15
 * @Description 用於用戶解密
 **/
public class AesCbcUtil {

    static {
        Security.addProvider(new BouncyCastleProvider());
    }

    /**
     * @return java.security.Security
     * @Author hobo
     * @Description :   AES解密
     * @Param data             //密文 加密的數據
     * @Param key              //祕鑰
     * @Param iv               //偏移量
     * @Param encodingFormat   //解密後結果的編碼格式
     **/
    public static String decrypt(String data, String key, String iv, String encodingFormat) {

        byte[] dataByte = Base64.decodeBase64(data);
        byte[] keyByte = Base64.decodeBase64(key);
        byte[] ivByte = Base64.decodeBase64(iv);

        try {
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
            SecretKeySpec spec = new SecretKeySpec(keyByte, "AES");

            AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");
            parameters.init(new IvParameterSpec(ivByte));

            cipher.init(Cipher.DECRYPT_MODE, spec, parameters);
            byte[] resultByte = cipher.doFinal(dataByte);
            if (null != resultByte && resultByte.length > 0) {
                String result = new String(resultByte, encodingFormat);
                return result;
            }

            return null;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidParameterSpecException e) {
            e.printStackTrace();
        } catch (InvalidAlgorithmParameterException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return null;
    }
}

效果展示

在這裏插入圖片描述

{"openId":"oFVAK4_iFtKuKDMpzEfAfjeI6ysQ","nickName":"菜逼玉","gender":1,"language":"zh_CN","city":"Chengdu","province":"Sichuan","country":"China","avatarUrl":"https://wx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTL94p6V7YgKUP2r9X4mLibwblyib3YAicRG54qAw2EEz0dO2ibMBLSnMqcm2CichAd3yZ36ZjBbMAdh7Wg/132","watermark":{"timestamp":1553434671,"appid":"wx08cbe6a7723b4059"}}

可以看到 我的微信的個人信息已經獲得

四 小白踩坑記錄

github上邊有sdk可以用微信開發者聯盟,但發現自己能力不足,只能用原生的方法。

大家在開發前一定要看小程序開發Api,不然會踩大坑。

新人第一篇博客 QQ:1056024860 敬候志同道合的同學跟我一起探討微信開發

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章