以下是 uni-app(前端) + Spring Boot(后端) 获取微信小程序用户的唯一标识(openidunionid)的完整实现方案,包含详细的代码和注释。
在这里插入图片描述


✅ 一、前端:uni-app 获取 code

📄 文件路径:pages/login/login.vue

<template>
  <view class="login-container">
    <button @click="weChatLogin">微信登录</button>
  </view>
</template>

<script>
export default {
  methods: {
    async weChatLogin() {
      try {
        // 调用微信登录接口,获取临时登录凭证 code
        const [err, res] = await uni.login({
          provider: 'weixin', // 微信登录
        });

        if (err) {
          uni.showToast({ title: '登录失败', icon: 'none' });
          console.error('登录失败:', err);
          return;
        }

        const code = res.code;
        console.log('获取到的登录凭证 code:', code);

        // 将 code 发送到后端服务
        const response = await uni.request({
          url: 'https://yourdomain.com/api/wechat/login', // 替换为你的后端地址
          method: 'POST',
          data: {
            code,
          },
        });

        const { openid, unionid } = response.data;
        console.log('获取到的用户标识:', { openid, unionid });

        uni.showToast({ title: '登录成功' });
        // TODO: 可以将 openid 存入本地缓存或跳转页面
      } catch (e) {
        uni.showToast({ title: '系统异常', icon: 'none' });
        console.error('发生异常:', e);
      }
    },
  },
};
</script>

<style scoped>
.login-container {
  padding: 20px;
}
</style>

✅ 二、后端:Spring Boot 接收 code 并请求微信服务器

📁 项目结构建议:

com.example.wechatdemo
├── controller
│   └── WeChatController.java
├── service
│   └── WeChatService.java
├── config
│   └── WeChatConfig.java
└── dto
    └── WeChatResponse.java

📄 1. 配置类:WeChatConfig.java

@Component
@Configuration
public class WeChatConfig {

    // 微信小程序 AppID(在微信公众平台申请)
    @Value("${wechat.appid}")
    private String appId;

    // 微信小程序 AppSecret(在微信公众平台申请)
    @Value("${wechat.secret}")
    private String appSecret;

    // 微信登录凭证校验接口 URL
    public static final String LOGIN_URL = "https://api.weixin.qq.com/sns/jscode2session";

    public String getAppId() {
        return appId;
    }

    public String getAppSecret() {
        return appSecret;
    }
}

💡 在 application.yml 中配置:

wechat:
  appid: your_appid_here
  secret: your_appsecret_here

📄 2. 响应对象:WeChatResponse.java

@Data
@NoArgsConstructor
@AllArgsConstructor
public class WeChatResponse {
    private String openid;     // 用户唯一标识
    private String unionid;    // 跨应用统一标识(需绑定开放平台)
    private String session_key; // 会话密钥
    private Integer errcode;   // 错误码
    private String errmsg;     // 错误信息
}

📄 3. 服务类:WeChatService.java

@Service
public class WeChatService {

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private WeChatConfig weChatConfig;

    /**
     * 根据 code 获取微信用户的 openid 和 unionid
     */
    public WeChatResponse getWeChatUserInfo(String code) {
        String url = String.format("%s?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code",
                WeChatConfig.LOGIN_URL,
                weChatConfig.getAppId(),
                weChatConfig.getAppSecret(),
                code);

        ResponseEntity<String> responseEntity = restTemplate.getForEntity(url, String.class);
        String responseBody = responseEntity.getBody();

        ObjectMapper mapper = new ObjectMapper();
        try {
            return mapper.readValue(responseBody, WeChatResponse.class);
        } catch (Exception e) {
            throw new RuntimeException("解析微信返回数据失败", e);
        }
    }
}

📄 4. 控制器类:WeChatController.java

@RestController
@RequestMapping("/api/wechat")
public class WeChatController {

    @Autowired
    private WeChatService weChatService;

    /**
     * 接收前端传来的 code,并返回微信用户信息
     */
    @PostMapping("/login")
    public ResponseEntity<?> login(@RequestBody Map<String, String> payload) {
        String code = payload.get("code");

        if (code == null || code.isEmpty()) {
            return ResponseEntity.badRequest().body(Map.of("error", "缺少登录凭证"));
        }

        WeChatResponse response = weChatService.getWeChatUserInfo(code);

        if (response.getErrcode() != null && response.getErrcode() != 0) {
            return ResponseEntity.status(500).body(Map.of("error", response.getErrmsg()));
        }

        return ResponseEntity.ok()
                .body(Map.of(
                        "openid", response.getOpenid(),
                        "unionid", response.getUnionid()
                ));
    }
}

📊 三、总结对比表

步骤 使用 API 是否必须 作用说明
前端调用 uni.login() ✅ 是 获取临时登录凭证 code
前端发送 code 到后端 ✅ 是 安全性要求,防止敏感操作暴露在前端
后端调用微信接口 jscode2session ✅ 是 获取 openidunionid
获取 openid ✅ 是 每个小程序内的用户唯一标识
获取 unionid ❌ 否(可选) 多应用之间识别同一用户(需绑定开放平台)

🧭 四、注意事项

项目 说明
微信 AppID 和 AppSecret 必须在微信公众平台注册并配置
微信开放平台绑定 如需跨小程序/公众号识别用户,需绑定开放平台
code 的时效性 有效期为 5 分钟,且只能使用一次
后端安全处理 不要在前端直接调用微信接口,避免泄露 AppSecret
返回字段安全性 session_key 不能暴露给前端,用于后续加密解密操作

✅ 最佳实践建议

  • 前端使用 uni.getUserProfile 获取用户昵称头像等公开信息
  • 使用 uni.login() 获取 code,并由后端换取 openid / unionid
  • 不要在前端直接调用微信的 jscode2session 接口
  • 后端验证 openid 是否已存在数据库,进行登录或注册逻辑

如需进一步实现 解密用户敏感数据(如手机号)JWT 登录态管理,请继续提问,我可以为你提供完整扩展方案。

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐