java对接支付宝小程序登录
支付宝小程序登录和微信小程序登录有点不太一样
具体可以看这一篇微信小程序登录的文章
✅ 支付宝小程序没有 phoneCode 机制
✅ 必须通过服务端解密 encryptedData 获取手机号
前端代码
通过my.getAuthCode()方法拿到authCode(也是一个入参)通过my.getPhoneNumber()方法拿到下面的JSON出参用户手机号密文(只用到了encryptedData)
{
"encryptedData": "5SR8/SmdDDwaXjJSncBG4FPZ1HtBvpnx/RMYXFBFm2tRNiWBGhur21nbT5CR7Mes3595QXoI9cCJ4GctsAnxMw==",
"errMsg": "getPhoneNumber:ok",
"sign": "e7rhAA2LE/qREXcOXz8BV3ChKRpvUk8nze2LatvJl1BIRGg0ugJXGrDu6vTePABmRcOgx6an0aP/OZOj8c9GGEEZzDL7eVzoRhVLwse23+DJS2vUtFKLdh/WvEFCcii+VGiB7vabzMfOKvx9nRJ9b67DxeZmGg93RwmYs4XTm+zF8wJ4z/fZw056YXksyGRS8DGIvSHJobDmrTweALxcM3g/FE84PxWmrw+Paxd5qA2D5rGjKk+T0U/3xZWq0g7/KIZA8SXocI5RLm6lAkw43CIL/SzDO7dKduLtTKYo0WFxrYdQIGMRLgaRUuHlnIcbW0iMdPEHaVjnNaM97LiAzg=="
}
引入支付宝的SDK
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>4.40.523.ALL</version>
</dependency>
java后端代码
支付宝配置文件
package com.boboboom.pro.module.system.config;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import lombok.Getter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@Getter
public class AlipayMiniConfig {
@Value("${alipay.app-id}")
private String alipayAppId; // 你的应用ID
@Value("${alipay.private-key}")
private String alipayPrivateKey; //你的应用私钥
@Value("${alipay.server-url:https://openapi.alipay.com/gateway.do}")
private String alipayServerUrl;
@Value("${alipay.public-key}") // 你的支付宝公钥(验签用)
private String alipayPublicKey;
@Value("${alipay.aes-key}") // 加密敏感数据的AES密钥
private String alipayAesKey;
@Bean
public AlipayClient alipayClient() {
return new DefaultAlipayClient(
alipayServerUrl,
alipayAppId,
alipayPrivateKey,
"json",
"UTF-8",
alipayPublicKey,
"RSA2"
);
}
}
支付宝小程序登录入参
public class LoginMobileParam {
private String code; // authCode
private String encryptedData; // 手机号加密数据
}
支付宝登录响应出参
package com.boboboom.pro.api.system.user.result;
import lombok.AllArgsConstructor;
import lombok.Data;
// 支付宝登录响应 DTO
@Data
@AllArgsConstructor
public class AlipayOpenDTO {
private String openId;
private String accessToken;
}
public LoginMobileResult loginAlipay(LoginMobileParam param) {
String authCode = param.getCode(); // 支付宝登录凭证authCode
String encryptedData = param.getEncryptedData();// 加密后的数据
//String sign = param.getSign(); // 支付宝签名
AssertUtil.notEmpty(authCode, "authCode不能为空");
AssertUtil.notEmpty(encryptedData, "encryptedData不能为空");
return sysUserApi.loginAlipay(param);
}

@Autowired
private AlipayClient alipayClient;
@Autowired
private AlipayMiniConfig alipayMiniConfig;
/**
* 支付宝小程序登录
*
* @param param
* @return
*/
@Override
@Transactional(rollbackFor = Exception.class)
public LoginMobileResult loginAlipay(LoginMobileParam param) {
log.info("【支付宝】小程序登录入参: {}", JSONUtil.toJsonStr(param));
// === Step 1: 用 code 换取 alipayOpenid + alipayUnionid + accessToken ===
AlipayOpenDTO alipayDTO = getAlipayOpenIdByCode(param.getCode());
String alipayOpenid = alipayDTO.getOpenId();
String accessToken = alipayDTO.getAccessToken();
log.info("【支付宝】获取到 alipayDTO: {}", JSONUtil.toJsonStr(alipayDTO));
param.setOpenid(alipayOpenid);
// === Step 2: 获取手机号(若用户已授权)===
String phone = getAlipayPhoneNumber(param.getEncryptedData());
param.setPhone(phone);
log.info("【支付宝】获取到手机号: {}", phone);
// === Step 3: 查询用户是否存在
LoginMobileResult existingResult = getLoginResultByAlipayOpenid(param.getPhone(), alipayOpenid);
if (existingResult != null) {
existingResult.setOpenId(alipayOpenid);
return existingResult;
}
// === Step 4: 新用户注册(写入 alipayOpenid/alipayUnionid)===
Long userId = handleAlipayUserLogin(param, alipayOpenid);
LoginMobileResult result = generateLoginResult(userId, param.getPhone(), param.getNickName());
result.setOpenId(alipayOpenid);
return result;
}
```java
/**
* 支付宝:用小程序 code 换取 openId / unionId / accessToken
*/
private AlipayOpenDTO getAlipayOpenIdByCode(String code) {
AlipaySystemOauthTokenRequest request = new AlipaySystemOauthTokenRequest();
request.setGrantType("authorization_code");
request.setCode(code);
try {
AlipaySystemOauthTokenResponse response = alipayClient.execute(request);
log.info("【支付宝】换取 openId 结果: {}", JSONUtil.toJsonStr(response));
if (!response.isSuccess()) {
log.warn("支付宝登录失败: code={}, msg={}, sub_code={}, sub_msg={}",
response.getCode(), response.getMsg(),
response.getSubCode(), response.getSubMsg());
throw new ServerException("支付宝登录失败: " + response.getSubMsg());
}
return new AlipayOpenDTO(
response.getOpenId(),
response.getAccessToken()
);
} catch (Exception e) {
log.error("【支付宝】换取 openId 异常", e);
throw new ServerException("系统异常,请稍后重试");
}
}
/**
* 支付宝:使用SDK内置方法解密手机号
*/
private String getAlipayPhoneNumber(String encryptedData) {
try {
// 1. 直接使用SDK内置方法解密
String decryptedPhoneInfo = AlipayEncrypt.decryptContent(
encryptedData,
"AES",
alipayMiniConfig.getAlipayAesKey(),
"UTF-8"
);
// 2. 解析手机号
JSONObject jsonObject = JSONObject.parseObject(decryptedPhoneInfo);
log.info("【支付宝】解密手机号结果: {}", JSONUtil.toJsonStr(jsonObject));
String phone = jsonObject.getString("mobile");
if (StringUtils.isBlank(phone)) {
phone = jsonObject.getString("phoneNumber");
if (StringUtils.isBlank(phone)) {
throw new ServerException("解密数据中未找到手机号: " + decryptedPhoneInfo);
}
}
log.info("【支付宝】解密手机号成功: {}", phone);
return phone;
} catch (Exception e) {
log.error("【支付宝】解密手机号异常", e);
throw new ServerException("解密手机号失败,请重试");
}
}
<h1>返回的实体类参考</h1>
```java
package com.boboboom.pro.api.system.user.result;
import lombok.Data;
import java.io.Serializable;
@Data
public class LoginMobileResult implements Serializable {
private Long userId; //用户ID
private String token; //用户登录token默认30天有效期
private String openId; //用户登录openId
}
JWT方法参考
/**
* 生成登录结果(含JWT令牌生成和Redis存储)
*/
private LoginMobileResult generateLoginResult(Long userId, String userName, String nickName) {
// 生成JWT
long expireTime = System.currentTimeMillis() + MobileConsent.TOKEN_EXPIRETIME_VERIFIED;
JwtUserInfo jwtUserInfo = new JwtUserInfo();
jwtUserInfo.setUserId(userId);
jwtUserInfo.setUserName(userName);
jwtUserInfo.setNickName(nickName);
jwtUserInfo.setSource(UserSourceEnum.MOBILE.getCode());
String token = jwtTokenUtil.generateToken(jwtUserInfo, expireTime);
// 以token为key存入Redis
RedisUtil.setEx(RedisKeyUtil.getMobileTokenKey(token), jwtUserInfo,
MobileConsent.TOKEN_EXPIRETIME_VERIFIED, TimeUnit.MILLISECONDS);
// 以jwtUserInfo为key存入Redis
RedisUtil.setEx(RedisKeyUtil.getMobileUserIdKey(userId), token,
MobileConsent.TOKEN_EXPIRETIME_VERIFIED, TimeUnit.MILLISECONDS);
// 构建结果
LoginMobileResult result = new LoginMobileResult();
result.setUserId(userId);
result.setToken(token);
return result;
}


浙公网安备 33010602011771号