package com.zsElectric.boot.security.provider; import cn.binarywang.wx.miniapp.api.WxMaService; import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo; import cn.hutool.core.util.StrUtil; import com.zsElectric.boot.business.model.entity.UserInfo; import com.zsElectric.boot.business.service.UserInfoService; import com.zsElectric.boot.security.model.WxMiniAppPhoneCodeAuthenticationToken; import lombok.extern.slf4j.Slf4j; import me.chanjar.weixin.common.error.WxErrorException; import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.authentication.CredentialsExpiredException; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.userdetails.UsernameNotFoundException; /** * 微信小程序手机号Code认证Provider(新版接口) * * @author Ray.Hao * @since 2.0.0 */ @Slf4j public class WxMiniAppPhoneCodeAuthenticationProvider implements AuthenticationProvider { private final UserInfoService userInfoService; private final WxMaService wxMaService; public WxMiniAppPhoneCodeAuthenticationProvider(UserInfoService userInfoService, WxMaService wxMaService) { this.userInfoService = userInfoService; this.wxMaService = wxMaService; } @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { WxMiniAppPhoneCodeAuthenticationToken authenticationToken = (WxMiniAppPhoneCodeAuthenticationToken) authentication; String phoneCode = (String) authenticationToken.getPrincipal(); // 1. 通过phoneCode获取手机号信息(新版接口) WxMaPhoneNumberInfo phoneNumberInfo; try { phoneNumberInfo = wxMaService.getUserService().getPhoneNoInfo(phoneCode); } catch (WxErrorException e) { log.error("获取微信手机号失败", e); throw new CredentialsExpiredException("获取手机号失败,code无效或已过期"); } if (phoneNumberInfo == null || StrUtil.isBlank(phoneNumberInfo.getPhoneNumber())) { throw new CredentialsExpiredException("获取手机号失败"); } String phoneNumber = phoneNumberInfo.getPhoneNumber(); log.info("通过code获取到手机号: {}", phoneNumber); // 2. 根据手机号注册或更新用户(c_user_info表) UserInfo userInfo = userInfoService.registerOrUpdateUserByPhone(phoneNumber, null); if (userInfo == null) { throw new UsernameNotFoundException("用户注册失败"); } log.info("用户信息获取成功,ID: {}, 手机号: {}", userInfo.getId(), userInfo.getPhone()); // 3. 构建小程序用户详情 AppletUserDetails userDetails = new AppletUserDetails(); userDetails.setUserId(userInfo.getId()); userDetails.setPhone(userInfo.getPhone()); userDetails.setOpenid(userInfo.getOpenid()); userDetails.setNickname(userInfo.getNickName()); userDetails.setEnabled(true); // 4. 创建已认证的Token return WxMiniAppPhoneCodeAuthenticationToken.authenticated( userDetails, userDetails.getAuthorities() ); } @Override public boolean supports(Class authentication) { return WxMiniAppPhoneCodeAuthenticationToken.class.isAssignableFrom(authentication); } }