微信小程序获取open_id与手机号教程

Gary Chen
微信小程序获取open_id与手机号教程

好的,以下是微信小程序获取 openid 和手机号的前后端完整实现,基于 Spring Boot 和微信小程序的开发框架。

一、微信小程序前端实现

1. 获取 openid

微信小程序通过 wx.login() 获取临时登录凭证(code),然后将 code 发送到后端,后端通过 code 换取 openid

前端代码示例:

// 在小程序的登录页面
wx.login({
  success(res) {
    if (res.code) {
      // 将 code 发送到后端
      wx.request({
        url: 'https://your-backend-domain.com/minapp/login', // 替换为你的后端接口地址
        method: 'POST',
        data: {
          code: res.code
        },
        success(res) {
          console.log('获取openid成功', res.data);
          // 保存 openid 或其他返回的数据
        },
        fail(err) {
          console.error('获取openid失败', err);
        }
      });
    } else {
      console.error('登录失败!' + res.errMsg);
    }
  }
});

2. 获取手机号

微信小程序通过 wx.getPhoneNumber() 获取手机号,但需要用户授权。用户授权后,前端会收到一个加密的手机号信息(encryptedDataiv),需要将这些数据发送到后端进行解密。

前端代码示例:

// 在小程序的页面中
wx.getPhoneNumber({
  success(res) {
    if (res.encryptedData && res.iv) {
      // 将 encryptedData 和 iv 发送到后端
      wx.request({
        url: 'https://your-backend-domain.com/minapp/getPhoneNumber', // 替换为你的后端接口地址
        method: 'POST',
        data: {
          encryptedData: res.encryptedData,
          iv: res.iv
        },
        success(res) {
          console.log('获取手机号成功', res.data);
          // 保存手机号或其他返回的数据
        },
        fail(err) {
          console.error('获取手机号失败', err);
        }
      });
    } else {
      console.error('获取手机号失败,用户未授权');
    }
  },
  fail(err) {
    console.error('获取手机号失败', err);
  }
});

二、Spring Boot 后端实现

1. 添加依赖

pom.xml 文件中添加以下依赖:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.78</version>
    </dependency>
    <dependency>
        <groupId>org.bouncycastle</groupId>
        <artifactId>bcprov-jdk15on</artifactId>
        <version>1.68</version>
    </dependency>
</dependencies>

2. 配置文件

application.yml 文件中配置微信小程序的 appidsecret

wx:
  miniapp:
    appid: your_app_id
    secret: your_app_secret

3. 后端代码实现

3.1 获取 openid

Controller:

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
public class WechatController {

    @Value("${wx.miniapp.appid}")
    private String appId;

    @Value("${wx.miniapp.secret}")
    private String appSecret;

    private final RestTemplate restTemplate = new RestTemplate();

    @PostMapping("/minapp/login")
    public String getOpenId(@RequestBody Map<String, String> request) {
        String code = request.get("code");
        String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + appId +
                "&secret=" + appSecret +
                "&js_code=" + code +
                "&grant_type=authorization_code";

        String response = restTemplate.getForObject(url, String.class);
        return response; // 返回 openid 和 session_key 等信息
    }
}
3.2 获取手机号

Controller:

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.security.AlgorithmParameters;
import java.security.spec.IVParameterSpec;
import java.util.Base64;
import java.util.Map;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

@RestController
public class WechatController {

    @Value("${wx.miniapp.appid}")
    private String appId;

    @PostMapping("/minapp/getPhoneNumber")
    public String getPhoneNumber(@RequestBody Map<String, String> request) {
        String encryptedData = request.get("encryptedData");
        String iv = request.get("iv");
        String sessionKey = request.get("sessionKey"); // sessionKey 需要从前端传递或从数据库获取

        try {
            // 解密手机号
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
            SecretKeySpec keySpec = new SecretKeySpec(Base64.getDecoder().decode(sessionKey), "AES");
            AlgorithmParameters params = AlgorithmParameters.getInstance("AES");
            params.init(new IVParameterSpec(Base64.getDecoder().decode(iv)));
            cipher.init(Cipher.DECRYPT_MODE, keySpec, params);

            byte[] result = cipher.doFinal(Base64.getDecoder().decode(encryptedData));
            String phoneNumber = new String(result, "UTF-8");

            return phoneNumber; // 返回解密后的手机号
        } catch (Exception e) {
            e.printStackTrace();
            return "解密失败";
        }
    }
}

三、完整流程说明

  1. 前端流程:
    • 用户点击登录按钮,调用 wx.login() 获取 code
    • code 发送到后端接口 /minapp/login
    • 后端通过 code 换取 openidsession_key,返回给前端。
    • 用户点击获取手机号按钮,调用 wx.getPhoneNumber()
    • 将返回的 encryptedDataiv 发送到后端接口 /minapp/getPhoneNumber
    • 后端使用 session_key 解密 encryptedData,获取手机号。
  2. 后端流程:
    • 接收前端发送的 code,通过微信接口换取 openidsession_key
    • 接收前端发送的 encryptedDataiv,使用 session_key 解密,获取手机号。

四、注意事项

  1. 安全性:
    • session_key 是敏感信息,不要直接存储在前端,应存储在服务器端。
    • 解密手机号的操作应在服务器端完成,避免将 session_key 暴露给前端。
  2. 微信限制:
    • 每个 session_key 有效期为 2 小时,建议在用户登录时重新获取 session_key
  3. 错误处理:
    • 前端和后端都需要处理可能出现的错误,如用户未授权、解密失败等。

通过以上代码和流程,你可以实现微信小程序获取 openid 和手机号的功能。如果有其他问题,欢迎继续提问!