|
|
@@ -0,0 +1,207 @@
|
|
|
+package shop.alien.gateway.service;
|
|
|
+
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
+import lombok.RequiredArgsConstructor;
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
+import shop.alien.entity.result.R;
|
|
|
+import shop.alien.entity.store.LifeUser;
|
|
|
+import shop.alien.entity.store.LifeUserThirdBind;
|
|
|
+import shop.alien.entity.store.vo.LifeUserThirdBindInfoVo;
|
|
|
+import shop.alien.gateway.config.LifeUserThirdBindProperties;
|
|
|
+import shop.alien.gateway.mapper.LifeUserGatewayMapper;
|
|
|
+import shop.alien.gateway.thirdparty.WeChatMobileOAuthClient;
|
|
|
+import shop.alien.mapper.LifeUserThirdBindMapper;
|
|
|
+
|
|
|
+import java.util.Date;
|
|
|
+
|
|
|
+@Service
|
|
|
+@RequiredArgsConstructor
|
|
|
+public class LifeUserThirdBindService {
|
|
|
+
|
|
|
+ private final LifeUserGatewayMapper lifeUserMapper;
|
|
|
+ private final LifeUserThirdBindMapper thirdBindMapper;
|
|
|
+ private final LifeUserThirdBindProperties thirdBindProperties;
|
|
|
+ private final WeChatMobileOAuthClient weChatMobileOAuthClient;
|
|
|
+
|
|
|
+ public Integer resolveLifeUserId(JSONObject sub) {
|
|
|
+ if (sub == null) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ String userType = sub.getString("userType");
|
|
|
+ if (!"user".equals(userType) && !"miniprogram_user".equals(userType)) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ String userIdStr = sub.getString("userId");
|
|
|
+ if (StringUtils.isNotBlank(userIdStr)) {
|
|
|
+ try {
|
|
|
+ return Integer.parseInt(userIdStr);
|
|
|
+ } catch (NumberFormatException ignored) {
|
|
|
+ // fall through
|
|
|
+ }
|
|
|
+ }
|
|
|
+ String phone = sub.getString("phone");
|
|
|
+ if (StringUtils.isNotBlank(phone)) {
|
|
|
+ LifeUser u = lifeUserMapper.selectOne(
|
|
|
+ new LambdaQueryWrapper<LifeUser>().eq(LifeUser::getUserPhone, phone).last("LIMIT 1"));
|
|
|
+ return u != null ? u.getId() : null;
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ public LifeUserThirdBindInfoVo getThirdBindInfo(Integer lifeUserId) {
|
|
|
+ LifeUserThirdBindInfoVo vo = new LifeUserThirdBindInfoVo();
|
|
|
+ vo.setLifeUserId(lifeUserId);
|
|
|
+ LifeUser user = lifeUserMapper.selectById(lifeUserId);
|
|
|
+ if (user != null) {
|
|
|
+ vo.setLifeUserPhone(user.getUserPhone());
|
|
|
+ }
|
|
|
+ LifeUserThirdBind wechat = latestRow(lifeUserId, LifeUserThirdBind.PLATFORM_WECHAT);
|
|
|
+ LifeUserThirdBind alipay = latestRow(lifeUserId, LifeUserThirdBind.PLATFORM_ALIPAY);
|
|
|
+ vo.setWechat(toWechat(wechat));
|
|
|
+ vo.setAlipay(toAlipay(alipay));
|
|
|
+ return vo;
|
|
|
+ }
|
|
|
+
|
|
|
+ private LifeUserThirdBind latestRow(Integer lifeUserId, String platform) {
|
|
|
+ return thirdBindMapper.selectOne(
|
|
|
+ new LambdaQueryWrapper<LifeUserThirdBind>()
|
|
|
+ .eq(LifeUserThirdBind::getLifeUserId, lifeUserId)
|
|
|
+ .eq(LifeUserThirdBind::getPlatform, platform)
|
|
|
+ .orderByDesc(LifeUserThirdBind::getUpdatedTime)
|
|
|
+ .last("LIMIT 1"));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public R<LifeUserThirdBindInfoVo> bindWechat(Integer lifeUserId, String code,
|
|
|
+ String nickName, String bindPhone) {
|
|
|
+ if (!thirdBindProperties.isEnabled()) {
|
|
|
+ return R.fail("第三方绑定功能已关闭");
|
|
|
+ }
|
|
|
+ String guard = assertUserBindableOrMsg(lifeUserId);
|
|
|
+ if (guard != null) {
|
|
|
+ return R.fail(guard);
|
|
|
+ }
|
|
|
+ WeChatMobileOAuthClient.OAuthExchangeResult session = weChatMobileOAuthClient.exchangeCode(code);
|
|
|
+ if (!session.isSuccess()) {
|
|
|
+ String msg = session.getErrmsg();
|
|
|
+ if (session.getErrcode() != null) {
|
|
|
+ msg = StringUtils.defaultString(msg) + "(errcode=" + session.getErrcode() + ")";
|
|
|
+ }
|
|
|
+ return R.fail(StringUtils.defaultIfBlank(msg, "微信授权失败"));
|
|
|
+ }
|
|
|
+ String openid = session.getOpenid();
|
|
|
+ if (isWechatOpenidBoundToOtherUser(openid, lifeUserId)) {
|
|
|
+ return R.fail("该微信已绑定其他账号");
|
|
|
+ }
|
|
|
+ String label = StringUtils.trimToNull(nickName);
|
|
|
+ String phone = StringUtils.trimToNull(bindPhone);
|
|
|
+ upsertWechatRow(lifeUserId, openid, session.getUnionid(), label, phone);
|
|
|
+ return R.data(getThirdBindInfo(lifeUserId));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public R<LifeUserThirdBindInfoVo> unbindWechat(Integer lifeUserId) {
|
|
|
+ if (!thirdBindProperties.isEnabled()) {
|
|
|
+ return R.fail("第三方绑定功能已关闭");
|
|
|
+ }
|
|
|
+ String guard = assertUserBindableOrMsg(lifeUserId);
|
|
|
+ if (guard != null) {
|
|
|
+ return R.fail(guard);
|
|
|
+ }
|
|
|
+ LifeUserThirdBind row = latestRow(lifeUserId, LifeUserThirdBind.PLATFORM_WECHAT);
|
|
|
+ if (row == null) {
|
|
|
+ return R.fail("当前未绑定微信");
|
|
|
+ }
|
|
|
+ thirdBindMapper.deleteById(row.getId());
|
|
|
+ return R.data(getThirdBindInfo(lifeUserId));
|
|
|
+ }
|
|
|
+
|
|
|
+ private String assertUserBindableOrMsg(Integer lifeUserId) {
|
|
|
+ LifeUser user = lifeUserMapper.selectById(lifeUserId);
|
|
|
+ if (user == null) {
|
|
|
+ return "用户不存在";
|
|
|
+ }
|
|
|
+ if (user.getLogoutFlag() != null && user.getLogoutFlag() == 1) {
|
|
|
+ return "账号已注销,无法操作绑定";
|
|
|
+ }
|
|
|
+ if (user.getIsBanned() != null && user.getIsBanned() == 1) {
|
|
|
+ return "账号已被封禁,无法操作绑定";
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean isWechatOpenidBoundToOtherUser(String openid, Integer lifeUserId) {
|
|
|
+ if (StringUtils.isBlank(openid)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ long n = thirdBindMapper.selectCount(
|
|
|
+ new LambdaQueryWrapper<LifeUserThirdBind>()
|
|
|
+ .eq(LifeUserThirdBind::getPlatform, LifeUserThirdBind.PLATFORM_WECHAT)
|
|
|
+ .eq(LifeUserThirdBind::getOpenid, openid)
|
|
|
+ .ne(LifeUserThirdBind::getLifeUserId, lifeUserId));
|
|
|
+ return n > 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void upsertWechatRow(Integer lifeUserId, String openid, String unionid, String accountLabel, String bindPhone) {
|
|
|
+ Date now = new Date();
|
|
|
+ LifeUserThirdBind existing = latestRow(lifeUserId, LifeUserThirdBind.PLATFORM_WECHAT);
|
|
|
+ if (existing != null) {
|
|
|
+ existing.setOpenid(openid);
|
|
|
+ existing.setUnionid(unionid);
|
|
|
+ if (accountLabel != null) {
|
|
|
+ existing.setAccountLabel(accountLabel);
|
|
|
+ }
|
|
|
+ if (bindPhone != null) {
|
|
|
+ existing.setBindPhone(bindPhone);
|
|
|
+ }
|
|
|
+ existing.setUpdatedTime(now);
|
|
|
+ thirdBindMapper.updateById(existing);
|
|
|
+ } else {
|
|
|
+ LifeUserThirdBind row = new LifeUserThirdBind();
|
|
|
+ row.setLifeUserId(lifeUserId);
|
|
|
+ row.setPlatform(LifeUserThirdBind.PLATFORM_WECHAT);
|
|
|
+ row.setOpenid(openid);
|
|
|
+ row.setUnionid(unionid);
|
|
|
+ row.setAccountLabel(accountLabel);
|
|
|
+ row.setBindPhone(bindPhone);
|
|
|
+ row.setDeleteFlag(0);
|
|
|
+ row.setCreatedTime(now);
|
|
|
+ row.setUpdatedTime(now);
|
|
|
+ thirdBindMapper.insert(row);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private static LifeUserThirdBindInfoVo.WechatBindItem toWechat(LifeUserThirdBind row) {
|
|
|
+ LifeUserThirdBindInfoVo.WechatBindItem it = new LifeUserThirdBindInfoVo.WechatBindItem();
|
|
|
+ if (row == null) {
|
|
|
+ it.setBound(false);
|
|
|
+ return it;
|
|
|
+ }
|
|
|
+ it.setBound(true);
|
|
|
+ String label = row.getAccountLabel();
|
|
|
+ it.setNickName(label);
|
|
|
+ it.setAccountLabel(label);
|
|
|
+ it.setOpenid(row.getOpenid());
|
|
|
+ it.setUnionid(row.getUnionid());
|
|
|
+ it.setBindPhone(row.getBindPhone());
|
|
|
+ return it;
|
|
|
+ }
|
|
|
+
|
|
|
+ private static LifeUserThirdBindInfoVo.AlipayBindItem toAlipay(LifeUserThirdBind row) {
|
|
|
+ LifeUserThirdBindInfoVo.AlipayBindItem it = new LifeUserThirdBindInfoVo.AlipayBindItem();
|
|
|
+ if (row == null) {
|
|
|
+ it.setBound(false);
|
|
|
+ return it;
|
|
|
+ }
|
|
|
+ it.setBound(true);
|
|
|
+ String label = row.getAccountLabel();
|
|
|
+ it.setNickName(label);
|
|
|
+ it.setAccountLabel(label);
|
|
|
+ it.setAlipayUserId(row.getAlipayUserId());
|
|
|
+ it.setBindPhone(row.getBindPhone());
|
|
|
+ return it;
|
|
|
+ }
|
|
|
+}
|