本文目录导读:

我来为您详细介绍Java小程序对接的实操案例,由于“小程序”通常指微信小程序,这里以Java后端对接微信小程序为例。
核心流程概述
微信小程序的登录流程:
- 小程序端获取
code(临时登录凭证) - 将
code发送给Java后端 - Java后端调用微信接口(
code2Session)换取openid和session_key - 后端生成自定义登录态返回给小程序
环境准备
依赖配置(Maven)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.32</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.14</version>
</dependency>
配置文件(application.yml)
wechat:
miniapp:
appid: your_appid_here
secret: your_secret_here
grant-type: authorization_code
login-url: https://api.weixin.qq.com/sns/jscode2session
核心代码实现
配置类
@Component
@ConfigurationProperties(prefix = "wechat.miniapp")
public class WechatConfig {
private String appid;
private String secret;
private String grantType;
private String loginUrl;
// getter/setter 省略
}
微信工具类
@Component
public class WechatUtil {
@Autowired
private WechatConfig wechatConfig;
/**
* 获取微信session信息
*/
public JSONObject getSessionInfo(String code) {
String url = String.format("%s?appid=%s&secret=%s&js_code=%s&grant_type=%s",
wechatConfig.getLoginUrl(),
wechatConfig.getAppid(),
wechatConfig.getSecret(),
code,
wechatConfig.getGrantType());
return HttpClientUtil.doGet(url);
}
/**
* 解密用户信息(获取手机号等敏感数据)
*/
public JSONObject decryptUserInfo(String encryptedData, String sessionKey, String iv) {
try {
byte[] result = AESDecryptUtil.decrypt(
Base64.decodeBase64(encryptedData),
Base64.decodeBase64(sessionKey),
Base64.decodeBase64(iv)
);
return JSON.parseObject(new String(result, "UTF-8"));
} catch (Exception e) {
throw new BusinessException("解密用户信息失败");
}
}
}
用户服务层
@Service
public class UserService {
@Autowired
private WechatUtil wechatUtil;
@Autowired
private UserMapper userMapper;
/**
* 小程序登录
*/
public LoginResponse login(LoginRequest request) {
// 1. 获取微信session
JSONObject sessionInfo = wechatUtil.getSessionInfo(request.getCode());
if (sessionInfo.containsKey("errcode") && sessionInfo.getInteger("errcode") != 0) {
throw new BusinessException("登录失败:" + sessionInfo.getString("errmsg"));
}
String openid = sessionInfo.getString("openid");
String sessionKey = sessionInfo.getString("session_key");
// 2. 查询或创建用户
User user = userMapper.selectByOpenid(openid);
if (user == null) {
user = new User();
user.setOpenid(openid);
user.setCreateTime(new Date());
userMapper.insert(user);
}
// 3. 生成自定义登录态(JWT Token)
String token = generateToken(user.getId(), openid);
// 4. 返回结果
LoginResponse response = new LoginResponse();
response.setToken(token);
response.setUserId(user.getId());
response.setSessionKey(sessionKey); // 注意:session_key不要返回给前端,仅在解密时使用
return response;
}
/**
* 获取用户手机号
*/
public String getUserPhone(DecryptRequest request) {
// 从session中获取session_key(实际项目中可以存入Redis)
String sessionKey = getSessionKeyByToken(request.getToken());
JSONObject userInfo = wechatUtil.decryptUserInfo(
request.getEncryptedData(),
sessionKey,
request.getIv()
);
// 更新用户手机号
String phone = userInfo.getString("phoneNumber");
userMapper.updatePhoneByOpenid(request.getOpenid(), phone);
return phone;
}
}
控制器层
@RestController
@RequestMapping("/api/wx")
public class WechatController {
@Autowired
private UserService userService;
/**
* 小程序登录
*/
@PostMapping("/login")
public Result<LoginResponse> login(@RequestBody LoginRequest request) {
LoginResponse response = userService.login(request);
return Result.success(response);
}
/**
* 获取手机号
*/
@PostMapping("/decrypt")
public Result<String> decryptPhone(@RequestBody DecryptRequest request) {
String phone = userService.getUserPhone(request);
return Result.success(phone);
}
}
请求/响应实体类
public class LoginRequest {
private String code; // 小程序端获取的code
// getter/setter
}
public class LoginResponse {
private String token;
private Long userId;
private String sessionKey;
// getter/setter
}
public class DecryptRequest {
private String token;
private String openid;
private String encryptedData;
private String iv;
// getter/setter
}
小程序端对接代码(示例)
登录流程
// app.js
wx.login({
success(res) {
if (res.code) {
// 将code发送到后端
wx.request({
url: 'https://your-domain.com/api/wx/login',
method: 'POST',
data: { code: res.code },
success(response) {
// 存储token到本地
wx.setStorageSync('token', response.data.data.token)
// 存储sessionKey(用于后续解密)
wx.setStorageSync('sessionKey', response.data.data.sessionKey)
}
})
}
}
})
获取手机号
// 用户点击"获取手机号"按钮
<button open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber">获取手机号</button>
Page({
getPhoneNumber(e) {
if (e.detail.errMsg === 'getPhoneNumber:ok') {
// 发送加密数据到后端解密
wx.request({
url: 'https://your-domain.com/api/wx/decrypt',
method: 'POST',
data: {
token: wx.getStorageSync('token'),
openid: '', // 从登录返回中保存
encryptedData: e.detail.encryptedData,
iv: e.detail.iv
},
success(res) {
console.log('手机号:', res.data.data)
}
})
}
}
})
关键注意事项
安全性
- session_key 绝对不能传输给前端或存储到客户端,仅在后端使用
- 使用 JWT 生成自定义token,有效期建议2小时
- 重要接口需校验JWT有效性
code 有效期
- 每个code只能使用一次,有效期5分钟
- 重新登录需要获取新的code
用户身份持久化
// 使用Redis缓存session_key
@Autowired
private RedisTemplate redisTemplate;
public void saveSessionKey(String token, String sessionKey) {
redisTemplate.opsForValue().set("session:" + token, sessionKey, 2, TimeUnit.HOURS);
}
数据解密(AES工具类)
public class AESDecryptUtil {
public static byte[] decrypt(byte[] content, byte[] keyByte, byte[] ivByte) {
try {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
SecretKeySpec keySpec = new SecretKeySpec(keyByte, "AES");
IvParameterSpec ivSpec = new IvParameterSpec(ivByte);
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
return cipher.doFinal(content);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
异常处理
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(BusinessException.class)
@ResponseBody
public Result handleBusinessException(BusinessException e) {
return Result.error(e.getMessage());
}
}
调试建议
- 使用微信开发者工具:可模拟真实环境
- 检查参数:确保appid和secret正确
- 域名配置:微信小程序后台配置request合法域名
- 日志记录:记录code和返回结果便于排查
- 测试工具:使用Postman测试后端接口
完整项目结构
src/main/java/com/example/wxapp/
├── config/
│ └── WechatConfig.java
├── controller/
│ └── WechatController.java
├── service/
│ └── UserService.java
├── util/
│ ├── WechatUtil.java
│ └── AESDecryptUtil.java
├── model/
│ ├── LoginRequest.java
│ ├── LoginResponse.java
│ └── DecryptRequest.java
├── mapper/
│ └── UserMapper.java
└── common/
├── Result.java
└── BusinessException.java
通过以上实现,您就完成了Java后端与微信小程序的完整对接,如果对接的是其他平台(如支付宝、抖音),核心流程类似,只是API地址和参数不同。
版权声明:足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播