微信小程序获取用户手机号前后台流程(附代码)

前置条件

1.首先获取手机号需要认证企业资质的小程序

2.获取手机号需要一台服务器编写解密代码

正文

1.首先理一下流程,下面是微信开发文档中的一张图

微信小程序获取用户手机号前后台流程(附代码)_第1张图片

下面是我自己写的流程 

 微信小程序获取用户手机号前后台流程(附代码)_第2张图片

注意

微信官方文档-手机号获取

微信小程序获取用户手机号前后台流程(附代码)_第3张图片

 按照例程打印不出来code,看看答应e.detail的结果

{
errMsg: "getPhoneNumber:ok", 
encryptedData: "/7uD9+GJ7qd0YBVX30Fg0Fj8W/2IXHbUhzZ3TfHv+LyRktBtZw…KKLFhmzK5jyiLxweSspezjVP7EEaifXPaAFeGG4fIl3u4GQ==", 
iv: "jfnSdhGbU4OS3JmwsoxL2Q=="
}

只能获取encryptedData和iv因此我们需要从wx.login()中获取code

2.小程序代码

1.在app.js的onLaunch()或index.js页面的onLoad()下面写wx.login()

App({
  /**
   * 当小程序初始化完成时,会触发 onLaunch(全局只触发一次)
   */
  onLaunch: function () {
// 1.获取临时登录凭证code
        wx.login({
          success: res => {
            if(res.code){
              console.log("code->", res.code)
              wx.setStorageSync('resCode', res.code)
            }
          }
        })
}
})

将获取到的code保存在缓存里

2.由于getPhoneNumber现在不支持自动弹出,需要用按钮去拉起,所以我们在wxml写上

并且在对应的js里写

Page({
// 获取手机号授权
getPhoneNumber (e)  {
    // 用户拒绝授权
    if(e.detail.errMsg == "getPhoneNumber:fail user deny") {
      wx.showToast({
        icon: "none",
        title: '请允许获取手机号,否则功能不可用!',
      })
      return
    }
    /// 用户允许授权
    console.log("e.detail.errMsg="+e.detail.errMsg)
    console.log("e.detail.iv=->", e.detail.iv); //包括敏感数据在内的完整用户信息的加密数据,需要解密
    console.log("e.detail.encryptedData->", e.detail.encryptedData); //加密算法的初始向量,解密需要用到

    /// 获取手机号
    let resCode = wx.getStorageSync('resCode');
    console.log("resCode = " +resCode)
    console.log("  e.detail = " +  e.detail)

    if(resCode){
      this.getphone(resCode, e.detail.encryptedData, e.detail.iv);
      this.triggerEvent("isHiddenPopup");
    }
  },
// 访问登录凭证校验接口获取session_key 并用session_key获取手机号
getphone: function(js_code, encryptedData, iv) {
  wx.request({
    url: globalData.getSessionKeyUrl,//需要填写自己的服务器请求地址
    data: {
        'js_code': js_code,
        'encryptedData' : encryptedData,
        'iv':iv,
        'sign': 'sign',
    },
    method: 'GET', 
    header: {
        'content-type': 'application/json'
    }, // 设置请求的 header
    success: function(data) {
      console.log("获取手机号返回JSON数据 =", data.data)
      console.log("手机号 = "+data.data.phoneNumber)
      if(data.data==undefined){
        wx.showToast({
          icon: "none",
          title: '手机号获取失败,请重新登录!',
        })
        return
      }
      if(data.statusCode == 200) { 
        if(data.data.phoneNumber==undefined){
          // 获取手机号失败 
            console.log("获取手机号失败");
            return
          }
          // 4.跳转web-view页面
          wx.switchTab({
            url: "/pages/mine/mine"
          }) 
        }
    },
    fail: function(err) {
        console.log(err);
        wx.showToast({
          icon: "none",
          title: 'session_key获取失败,请重新登录!',
        })
        return
    }
  })
}
})

至此小程序主要代码写完了

3.后台代码

后台选择SpringBoot搭建,首先建一个基础工程,然后直接贴代码

1.pom.xml



    4.0.0
    
        org.springframework.boot
        spring-boot-starter-parent
        2.6.1
         
    
    com.server
    server
    0.0.1-SNAPSHOT
    server
    server
    
        1.8
    
    
        
            org.springframework.boot
            spring-boot-starter-web
        

        
            org.springframework.boot
            spring-boot-devtools
            runtime
            true
        
        
            org.springframework.boot
            spring-boot-configuration-processor
            true
        
        
            org.projectlombok
            lombok
            true
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
        
        
            org.apache.logging.log4j
            log4j-api
            2.11.1
        
        
            commons-codec
            commons-codec
            1.15
        

        
        
            org.bouncycastle
            bcprov-jdk16
            1.46
        


    


    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
                
                    
                        
                            org.projectlombok
                            lombok
                        
                    
                
            
        
    


2.ServerApplication.java 

package com.server;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.server.data.globalData;
import com.server.httpUtil.PostData;


import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.web.bind.annotation.*;


@RestController
@SpringBootApplication
public class ServerApplication {
    com.server.data.globalData globalData = new globalData();
    public static void main(String[] args) {
        SpringApplication.run(ServerApplication.class, args);
    }
    //解析电话号码
    @GetMapping("/getsessionkey")
    public Object getsessionkey(String js_code,String encryptedData, String iv) throws JsonProcessingException {
        PostData PostData = new PostData();
        String responseData =  PostData.PostData(globalData.url, globalData.appid, globalData.secret,js_code,globalData.grant_type);
        //获取SessionKey 和openid
        ObjectMapper mapper = new ObjectMapper();
        JsonNode resData = mapper.readTree(responseData);
        try{
            if(resData.get("session_key").asText()!=null)
            {
                String SessionKey = resData.get("session_key").asText();
                String openid = resData.get("openid").asText();
                System.out.println("SessionKey="+SessionKey);
                System.out.println("openid="+openid);
                System.out.println("encryptedData="+encryptedData);
                System.out.println("iv="+iv);
                String wxDecrypt = WechatUtils.wxDecrypt(encryptedData,SessionKey,iv);
                System.out.println(wxDecrypt);
                return wxDecrypt;
            }else {
                System.out.println("请求微信服务器异常");
            }

        }catch (Exception e)
        {
            System.out.println("请求微信服务器异常");
        }
        return 0;
    }
}

3.WechatUtils.java解密工具类

package com.server;

import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class WechatUtils {
    public static final String AES = "AES";
    public static final String AES_CBC_PADDING = "AES/CBC/PKCS7Padding";

    /**
     *    * 微信 数据解密
* * 对称解密使用的算法为 AES-128-CBC,数据采用PKCS#7填充
* * 对称解密的目标密文:encrypted=Base64_Decode(encryptData)
* * 对称解密秘钥:key = Base64_Decode(session_key),aeskey是16字节
* * 对称解密算法初始向量:iv = Base64_Decode(iv),同样是16字节
* * * * @param encrypted 目标密文 * * @param session_key 会话ID * * @param iv 加密算法的初始向量 * */ public static String wxDecrypt(String encrypted, String session_key, String iv) { String result = null; byte[] encrypted64 = org.apache.commons.codec.binary.Base64.decodeBase64(encrypted); byte[] key64 = org.apache.commons.codec.binary.Base64.decodeBase64(session_key); byte[] iv64 = org.apache.commons.codec.binary.Base64.decodeBase64(iv); try { init(); result = new String(decrypt(encrypted64, key64, generateIV(iv64))); } catch (Exception e) { e.printStackTrace(); } return result; } /** * * 初始化密钥 * */ public static void init() throws Exception { Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); KeyGenerator.getInstance(AES).init(128); } /** * * 生成iv * */ public static AlgorithmParameters generateIV(byte[] iv) throws Exception { // iv 为一个 16 字节的数组,这里采用和 iOS 端一样的构造方法,数据全为0 // Arrays.fill(iv, (byte) 0x00); AlgorithmParameters params = AlgorithmParameters.getInstance(AES); params.init(new IvParameterSpec(iv)); return params; } /** * * 生成解密 * */ public static byte[] decrypt(byte[] encryptedData, byte[] keyBytes, AlgorithmParameters iv) throws Exception { Key key = new SecretKeySpec(keyBytes, AES); Cipher cipher = Cipher.getInstance(AES_CBC_PADDING); // 设置为解密模式 cipher.init(Cipher.DECRYPT_MODE, key, iv); return cipher.doFinal(encryptedData); } }

4.HttpRestUtils.java http请求工具类

package com.server.httpUtil;
import org.springframework.http.*;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;
import java.io.IOException;
public class HttpRestUtils {
    /**
     * http post
     * */
    public static String post(String url, MultiValueMap params) throws IOException {
        return  httpRestClient(url, HttpMethod.POST, params);
    }

    /**
     * http get
     * */
    public static String get(String url, MultiValueMap params) throws IOException {
        return  httpRestClient(url, HttpMethod.GET, params);
    }

    /**
     * HttpMethod  post/get
     * */
    private static String httpRestClient(String url, HttpMethod method, MultiValueMap params) throws IOException {
        SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
        requestFactory.setConnectTimeout(10*1000);
        requestFactory.setReadTimeout(10*1000);
        RestTemplate client = new RestTemplate(requestFactory);
        HttpHeaders headers = new HttpHeaders();
        // 以表单的方式提交
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
//       headers.setContentType(MediaType.APPLICATION_JSON_UTF8);//不好使,不能用get方法
        HttpEntity> requestEntity = new HttpEntity>(params, headers);
        //  执行HTTP请求
        ResponseEntity response = null;
        try{
            response = client.exchange(url, HttpMethod.POST, requestEntity, String.class);
            System.out.println("response="+response);
            return response.getBody();
        }
        catch (HttpClientErrorException e){
            System.out.println( "------------- 出现异常 HttpClientErrorException -------------");
            System.out.println(e.getMessage());
            System.out.println(e.getStatusText());
            System.out.println( "-------------responseBody-------------");
            System.out.println( e.getResponseBodyAsString());
            e.printStackTrace();
            return "";
        }
        catch (Exception e) {
            System.out.println( "------------- HttpRestUtils.httpRestClient() 出现异常 Exception -------------");
            System.out.println(e.getMessage());
            return "";
        }


    }
}

5.PostData.java http请求业务类

package com.server.httpUtil;
import org.springframework.http.HttpMethod;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;

public class PostData {
    public String PostData(String url ,String appid,String appSecret,String code,String authorization_code) {
        try {
            //post请求
            HttpMethod method = HttpMethod.GET;
            // 封装参数,千万不要替换为Map与HashMap,否则参数无法传递
            MultiValueMap params = new LinkedMultiValueMap();
            params.add("appid",appid);
            params.add("secret",appSecret);
            params.add("js_code",code);
            params.add("grant_type",authorization_code);
            System.out.print("发送数据:" + params.toString()+"\n");
            //发送http请求并返回结果
            String result = HttpRestUtils.get(url, params);
            System.out.print("接收反馈:" + result+"\n");
            return result;
        } catch (Exception e) {
            System.out.println("------------- " + this.getClass().toString() + ".PostData() : 出现异常 Exception -------------");
            System.out.println(e.getMessage());
            return "";
        }
    }
}

6.globalData.java 全局变量

package com.server.data;

public class globalData {
    public String  url = "https://api.weixin.qq.com/sns/jscode2session";//微信服务器接口
    public String  appid = "xxxxxx填自己小程序的xxxxx";
    public String  secret = "xxxxxx填自己小程序的xxxxx";
    public String  grant_type = "authorization_code";//这样写就行
}

至此前后台就ok了,可以获取用户手机号了

后台数据打印如下

 

你可能感兴趣的:(微信小程序,微信小程序,小程序)