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

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

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

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

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

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

下面是我自己写的流程 

 

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

 按照例程打印不出来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: function () {
// 1.获取临时登录凭证code
        wx.login({
          success: res => {
            if(res.code){
              console.log("code->", res.code)
              wx.setStorageSync('resCode', res.code)
            }
          }
        })
}
})

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

2.由于getPhoneNumber现在不支持自动d出,需要用按钮去拉起,所以我们在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";

    
    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);
    }

    
    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 {
    
    public static String post(String url, MultiValueMap params) throws IOException {
        return  httpRestClient(url, HttpMethod.POST, params);
    }

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

    
    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了,可以获取用户手机号了

后台数据打印如下

 

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5672424.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-16
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存