增加支付宝小程序登录
This commit is contained in:
6
pom.xml
6
pom.xml
@ -228,6 +228,12 @@
|
||||
<artifactId>bcprov-jdk15on</artifactId>
|
||||
<version>1.68</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.alipay.sdk</groupId>
|
||||
<artifactId>alipay-sdk-java</artifactId>
|
||||
<version>4.22.110.ALL</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<!-- Build Configuration -->
|
||||
|
||||
@ -1,12 +1,16 @@
|
||||
package com.sczx.user.controller;
|
||||
|
||||
import com.sczx.user.common.Result;
|
||||
import com.sczx.user.dto.AlipayLoginRequest;
|
||||
import com.sczx.user.dto.AlipayMiniProgramRegRequest;
|
||||
import com.sczx.user.dto.LoginResponse;
|
||||
import com.sczx.user.dto.WxMiniProgramRegRequest;
|
||||
import com.sczx.user.exception.BizException;
|
||||
import com.sczx.user.service.IUserService;
|
||||
import com.sczx.user.util.JwtUtil;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@ -42,18 +46,36 @@ public class AuthController {
|
||||
return Result.ok(result);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "微信小程序登录", notes = "通过微信code登录")
|
||||
@PostMapping("/mini-program/wechat/login")
|
||||
public Result<LoginResponse> wechatLogin(@RequestParam("code") String code) {
|
||||
return Result.ok(userService.miniProgramLogin(code));
|
||||
@ApiOperation(value = "获取支付宝手机号", notes = "获取支付宝手机号")
|
||||
@PostMapping("/mini-program/alipay/getPhoneNumber")
|
||||
public Result<String> getAlipayPhoneNumber(@RequestParam("authCode") String authCode) {
|
||||
String phoneNumber = userService.getAlipayPhoneNumber(authCode);
|
||||
return Result.ok(phoneNumber);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "支付宝小程序注册", notes = "支付宝小程序注册")
|
||||
@PostMapping("/mini-program/alipay/register")
|
||||
public Result<LoginResponse> alipayRegister(
|
||||
@RequestBody AlipayMiniProgramRegRequest alipayMiniProgramRegRequest) {
|
||||
LoginResponse result = userService.alipayMiniProgramRegister(alipayMiniProgramRegRequest);
|
||||
return Result.ok(result);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "支付宝小程序登录", notes = "通过支付宝userId登录")
|
||||
@ApiOperation(value = "支付宝小程序登录", notes = "通过支付宝userId或authCode登录")
|
||||
@PostMapping("/mini-program/alipay/login")
|
||||
public Result<String> alipayLogin(@RequestParam("userId") String userId) {
|
||||
String token = userService.alipayMiniProgramLogin(userId);
|
||||
return Result.ok(token);
|
||||
public Result<LoginResponse> alipayLogin(@RequestBody AlipayLoginRequest request) {
|
||||
String userId = request.getUserId();
|
||||
String authCode = request.getAuthCode();
|
||||
|
||||
if (StringUtils.isNotBlank(authCode)) {
|
||||
// 使用授权码登录
|
||||
return Result.ok(userService.alipayMiniProgramLoginByAuthCode(authCode));
|
||||
} else if (StringUtils.isNotBlank(userId)) {
|
||||
// 使用userId登录
|
||||
return Result.ok(userService.alipayMiniProgramLoginByUserId(userId));
|
||||
} else {
|
||||
throw new BizException("缺少必要的登录参数");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
16
src/main/java/com/sczx/user/dto/AlipayLoginRequest.java
Normal file
16
src/main/java/com/sczx/user/dto/AlipayLoginRequest.java
Normal file
@ -0,0 +1,16 @@
|
||||
package com.sczx.user.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
@ApiModel("支付宝小程序登录请求")
|
||||
@Data
|
||||
public class AlipayLoginRequest {
|
||||
|
||||
@ApiModelProperty(value = "用户ID")
|
||||
private String userId;
|
||||
|
||||
@ApiModelProperty(value = "授权码")
|
||||
private String authCode;
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
package com.sczx.user.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@ApiModel("支付宝小程序注册请求")
|
||||
public class AlipayMiniProgramRegRequest {
|
||||
|
||||
@ApiModelProperty(value = "授权码", required = true)
|
||||
private String authCode;
|
||||
|
||||
@ApiModelProperty(value = "用户ID")
|
||||
private String userId;
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
package com.sczx.user.service;
|
||||
|
||||
import com.sczx.user.dto.AlipayMiniProgramRegRequest;
|
||||
import com.sczx.user.dto.LoginResponse;
|
||||
import com.sczx.user.dto.SimpleUserInfoDTO;
|
||||
import com.sczx.user.dto.WxMiniProgramRegRequest;
|
||||
@ -41,11 +42,32 @@ public interface IUserService {
|
||||
|
||||
|
||||
/**
|
||||
* 支付宝小程序登录
|
||||
* @param userId 支付宝用户ID
|
||||
* @return token
|
||||
* 支付宝小程序注册
|
||||
* @param alipayMiniProgramRegRequest 注册请求
|
||||
* @return 登录响应
|
||||
*/
|
||||
String alipayMiniProgramLogin(String userId);
|
||||
LoginResponse alipayMiniProgramRegister(AlipayMiniProgramRegRequest alipayMiniProgramRegRequest);
|
||||
|
||||
/**
|
||||
* 支付宝小程序登录
|
||||
* @param userId 用户ID
|
||||
* @return 登录响应
|
||||
*/
|
||||
LoginResponse alipayMiniProgramLoginByUserId(String userId);
|
||||
|
||||
/**
|
||||
* 支付宝小程序登录
|
||||
* @param authCode 授权码
|
||||
* @return 登录响应
|
||||
*/
|
||||
LoginResponse alipayMiniProgramLoginByAuthCode(String authCode);
|
||||
|
||||
/**
|
||||
* 获取支付宝用户手机号
|
||||
* @param authCode 授权码
|
||||
* @return 手机号
|
||||
*/
|
||||
String getAlipayPhoneNumber(String authCode);
|
||||
|
||||
|
||||
|
||||
|
||||
@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.sczx.user.common.enums.ApiErrorCode;
|
||||
import com.sczx.user.common.enums.MiniProgramTypeEnum;
|
||||
import com.sczx.user.convert.UserInfoConvert;
|
||||
import com.sczx.user.dto.AlipayMiniProgramRegRequest;
|
||||
import com.sczx.user.dto.LoginResponse;
|
||||
import com.sczx.user.dto.SimpleUserInfoDTO;
|
||||
import com.sczx.user.dto.WxMiniProgramRegRequest;
|
||||
@ -14,12 +15,12 @@ import com.sczx.user.repository.BaseUserRepo;
|
||||
import com.sczx.user.service.IUserService;
|
||||
import com.sczx.user.thirdpart.dto.WechatDecryptedPhoneInfo;
|
||||
import com.sczx.user.thirdpart.dto.WechatMiniProgramResponse;
|
||||
import com.sczx.user.thirdpart.integration.AlipayInteg;
|
||||
import com.sczx.user.thirdpart.integration.WeichatInteg;
|
||||
import com.sczx.user.util.JwtUtil;
|
||||
import com.sczx.user.util.RedisUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.tomcat.util.security.MD5Encoder;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@ -60,6 +61,9 @@ public class UserServiceImpl implements IUserService {
|
||||
@Autowired
|
||||
private WeichatInteg weichatInteg;
|
||||
|
||||
@Autowired
|
||||
private AlipayInteg alipayInteg;
|
||||
|
||||
|
||||
@Override
|
||||
public String getWxOpenId(String code) {
|
||||
@ -140,17 +144,122 @@ public class UserServiceImpl implements IUserService {
|
||||
return getLoginResponse(openid,MiniProgramTypeEnum.WECHAT.getType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public LoginResponse alipayMiniProgramRegister(AlipayMiniProgramRegRequest alipayMiniProgramRegRequest) {
|
||||
try {
|
||||
// 1. 通过authCode获取用户信息
|
||||
Map<String, Object> userInfo = null;
|
||||
String userId = null;
|
||||
|
||||
if (StringUtils.isNotBlank(alipayMiniProgramRegRequest.getAuthCode())) {
|
||||
userInfo = alipayInteg.getUserInfoByAuthCode(alipayMiniProgramRegRequest.getAuthCode());
|
||||
userId = (String) userInfo.get("userId");
|
||||
} else if (StringUtils.isNotBlank(alipayMiniProgramRegRequest.getUserId())) {
|
||||
userId = alipayMiniProgramRegRequest.getUserId();
|
||||
userInfo = alipayInteg.getUserInfoByUserId(userId);
|
||||
} else {
|
||||
throw new BizException("缺少必要的用户标识");
|
||||
}
|
||||
|
||||
if (StringUtils.isBlank(userId)) {
|
||||
throw new BizException("获取支付宝用户信息失败");
|
||||
}
|
||||
|
||||
// 2. 获取手机号
|
||||
String phoneNumber = (String) userInfo.get("mobile");
|
||||
if (StringUtils.isBlank(phoneNumber)) {
|
||||
throw new BizException("支付宝小程序注册失败,无法获取用户真实手机号");
|
||||
}
|
||||
|
||||
// 3. 查询用户是否存在
|
||||
LambdaQueryWrapper<BaseUserPO> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(BaseUserPO::getPhoneNumber, phoneNumber);
|
||||
BaseUserPO baseUserPO = baseUserRepo.getOne(queryWrapper);
|
||||
|
||||
// 4. 创建或更新用户
|
||||
BaseUserPO newUserPO = new BaseUserPO();
|
||||
if (Objects.isNull(baseUserPO)) {
|
||||
// 新用户注册
|
||||
newUserPO.setAlipayUserid(userId);
|
||||
newUserPO.setUserName(phoneNumber);
|
||||
newUserPO.setPhoneNumber(phoneNumber);
|
||||
newUserPO.setPassword(MD5Utils.md5Hex(phoneNumber, StandardCharsets.UTF_8.name()));
|
||||
newUserPO.setNickName((String) userInfo.get("nickName"));
|
||||
newUserPO.setAvatarUrl((String) userInfo.get("avatar"));
|
||||
newUserPO.setRoleId(1);
|
||||
} else {
|
||||
// 已存在用户,更新支付宝信息
|
||||
newUserPO.setId(baseUserPO.getId());
|
||||
newUserPO.setAlipayUserid(userId);
|
||||
// if (StringUtils.isNotBlank((String) userInfo.get("nickName"))) {
|
||||
// newUserPO.setNickName((String) userInfo.get("nickName"));
|
||||
// }
|
||||
// if (StringUtils.isNotBlank((String) userInfo.get("avatar"))) {
|
||||
// newUserPO.setAvatarUrl((String) userInfo.get("avatar"));
|
||||
// }
|
||||
}
|
||||
|
||||
baseUserRepo.saveOrUpdate(newUserPO);
|
||||
|
||||
// 5. 返回登录信息
|
||||
return getLoginResponse(userId, MiniProgramTypeEnum.ALIPAY.getType());
|
||||
} catch (Exception e) {
|
||||
log.error("支付宝小程序注册失败", e);
|
||||
throw new BizException("支付宝小程序注册失败");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String alipayMiniProgramLogin(String userId) {
|
||||
String realUserId = ALIPAY_ID_TO_USERID.get(userId);
|
||||
if (realUserId == null) {
|
||||
throw new BizException("无效的支付宝用户ID");
|
||||
}
|
||||
// 模拟登录逻辑
|
||||
SimpleUserInfoDTO simpleUserInfoDTO = getUserInfoByProgramId(realUserId, MiniProgramTypeEnum.ALIPAY.getType());
|
||||
public LoginResponse alipayMiniProgramLoginByUserId(String userId) {
|
||||
try {
|
||||
// 1. 验证用户ID有效性
|
||||
if (StringUtils.isBlank(userId)) {
|
||||
throw new BizException("用户ID不能为空");
|
||||
}
|
||||
|
||||
return jwtUtil.generateToken(simpleUserInfoDTO, simpleUserInfoDTO.getUserName());
|
||||
// 2. 查询数据库验证用户是否存在
|
||||
LambdaQueryWrapper<BaseUserPO> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(BaseUserPO::getAlipayUserid, userId);
|
||||
BaseUserPO userPO = baseUserRepo.getOne(queryWrapper);
|
||||
|
||||
if (userPO == null) {
|
||||
throw new BizException("无效的支付宝用户ID");
|
||||
}
|
||||
|
||||
// 3. 返回登录信息
|
||||
return getLoginResponse(userId, MiniProgramTypeEnum.ALIPAY.getType());
|
||||
} catch (Exception e) {
|
||||
log.error("支付宝小程序按userId登录失败", e);
|
||||
throw new BizException("支付宝小程序登录失败");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public LoginResponse alipayMiniProgramLoginByAuthCode(String authCode) {
|
||||
try {
|
||||
// 1. 验证授权码有效性
|
||||
if (StringUtils.isBlank(authCode)) {
|
||||
throw new BizException("授权码不能为空");
|
||||
}
|
||||
|
||||
// 2. 通过授权码获取用户信息
|
||||
Map<String, Object> userInfo = alipayInteg.getUserInfoByAuthCode(authCode);
|
||||
String userId = (String) userInfo.get("userId");
|
||||
|
||||
if (StringUtils.isBlank(userId)) {
|
||||
throw new BizException("获取支付宝用户信息失败");
|
||||
}
|
||||
return alipayMiniProgramLoginByUserId(userId);
|
||||
} catch (Exception e) {
|
||||
log.error("支付宝小程序按authCode登录失败", e);
|
||||
throw new BizException("支付宝小程序登录失败");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getAlipayPhoneNumber(String authCode) {
|
||||
return alipayInteg.getPhoneNumber(authCode);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,120 @@
|
||||
|
||||
package com.sczx.user.thirdpart.integration;
|
||||
|
||||
import com.alipay.api.AlipayClient;
|
||||
import com.alipay.api.DefaultAlipayClient;
|
||||
import com.alipay.api.request.AlipaySystemOauthTokenRequest;
|
||||
import com.alipay.api.request.AlipayUserInfoShareRequest;
|
||||
import com.alipay.api.response.AlipaySystemOauthTokenResponse;
|
||||
import com.alipay.api.response.AlipayUserInfoShareResponse;
|
||||
import com.sczx.user.exception.BizException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class AlipayInteg {
|
||||
|
||||
@Value("${alipay.miniapp.appid}")
|
||||
private String appId;
|
||||
|
||||
@Value("${alipay.miniapp.privateKey}")
|
||||
private String privateKey;
|
||||
|
||||
@Value("${alipay.miniapp.publicKey}")
|
||||
private String publicKey;
|
||||
|
||||
@Value("${alipay.miniapp.gatewayUrl}")
|
||||
private String gatewayUrl;
|
||||
|
||||
@Value("${alipay.miniapp.format}")
|
||||
private String format;
|
||||
|
||||
@Value("${alipay.miniapp.charset}")
|
||||
private String charset;
|
||||
|
||||
@Value("${alipay.miniapp.signType}")
|
||||
private String signType;
|
||||
|
||||
/**
|
||||
* 通过授权码获取用户信息
|
||||
* @param authCode 授权码
|
||||
* @return 用户信息
|
||||
*/
|
||||
public Map<String, Object> getUserInfoByAuthCode(String authCode) {
|
||||
try {
|
||||
AlipayClient alipayClient = new DefaultAlipayClient(
|
||||
gatewayUrl, appId, privateKey, format, charset, publicKey, signType);
|
||||
|
||||
// 1. 通过authCode获取access_token
|
||||
AlipaySystemOauthTokenRequest tokenRequest = new AlipaySystemOauthTokenRequest();
|
||||
tokenRequest.setGrantType("authorization_code");
|
||||
tokenRequest.setCode(authCode);
|
||||
|
||||
AlipaySystemOauthTokenResponse tokenResponse = alipayClient.execute(tokenRequest);
|
||||
|
||||
if (!tokenResponse.isSuccess()) {
|
||||
log.error("获取支付宝access_token失败: {}", tokenResponse.getSubMsg());
|
||||
throw new BizException("获取支付宝用户信息失败");
|
||||
}
|
||||
|
||||
// 2. 通过access_token获取用户信息
|
||||
AlipayUserInfoShareRequest userInfoRequest = new AlipayUserInfoShareRequest();
|
||||
AlipayUserInfoShareResponse userInfoResponse = alipayClient.execute(userInfoRequest, tokenResponse.getAccessToken());
|
||||
|
||||
if (!userInfoResponse.isSuccess()) {
|
||||
log.error("获取支付宝用户信息失败: {}", userInfoResponse.getSubMsg());
|
||||
throw new BizException("获取支付宝用户信息失败");
|
||||
}
|
||||
|
||||
// 3. 构造返回结果
|
||||
Map<String, Object> userInfo = new HashMap<>();
|
||||
userInfo.put("userId", userInfoResponse.getUserId());
|
||||
userInfo.put("nickName", userInfoResponse.getNickName());
|
||||
userInfo.put("avatar", userInfoResponse.getAvatar());
|
||||
userInfo.put("mobile", userInfoResponse.getMobile());
|
||||
|
||||
return userInfo;
|
||||
} catch (Exception e) {
|
||||
log.error("获取支付宝用户信息异常", e);
|
||||
throw new BizException("获取支付宝用户信息异常");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过userId获取用户信息(简化版,适用于已授权用户)
|
||||
* @param userId 用户ID
|
||||
* @return 用户信息
|
||||
*/
|
||||
public Map<String, Object> getUserInfoByUserId(String userId) {
|
||||
try {
|
||||
// 这里可以调用支付宝的用户信息接口获取用户详情
|
||||
// 为简化实现,直接返回基础信息
|
||||
Map<String, Object> userInfo = new HashMap<>();
|
||||
userInfo.put("userId", userId);
|
||||
return userInfo;
|
||||
} catch (Exception e) {
|
||||
log.error("获取支付宝用户信息异常", e);
|
||||
throw new BizException("获取支付宝用户信息异常");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户手机号(通过支付宝接口)
|
||||
* @param authCode 授权码
|
||||
* @return 手机号
|
||||
*/
|
||||
public String getPhoneNumber(String authCode) {
|
||||
try {
|
||||
Map<String, Object> userInfo = getUserInfoByAuthCode(authCode);
|
||||
return (String) userInfo.get("mobile");
|
||||
} catch (Exception e) {
|
||||
log.error("获取支付宝手机号异常", e);
|
||||
throw new BizException("获取支付宝手机号异常");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -69,4 +69,14 @@ wechat:
|
||||
apiurl: https://api.weixin.qq.com
|
||||
appid: wx25e1ad1a70c326de
|
||||
secret: e0633b08d915a844f7ae7e4495d9e854
|
||||
grantType: authorization_code
|
||||
grantType: authorization_code
|
||||
|
||||
alipay:
|
||||
miniapp:
|
||||
appid: your_alipay_appid
|
||||
privateKey: your_private_key
|
||||
publicKey: your_public_key
|
||||
gatewayUrl: https://openapi.alipay.com/gateway.do
|
||||
format: JSON
|
||||
charset: UTF-8
|
||||
signType: RSA2
|
||||
Reference in New Issue
Block a user