package com.supersavedriving.user.modular.system.service.impl; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.alipay.api.domain.RechargeDetail; import com.baomidou.mybatisplus.mapper.EntityWrapper; import com.baomidou.mybatisplus.service.impl.ServiceImpl; import com.supersavedriving.user.core.common.constant.JwtConstants; import com.supersavedriving.user.core.shiro.ShiroKit; import com.supersavedriving.user.core.shiro.ShiroUser; import com.supersavedriving.user.core.util.JwtTokenUtil; import com.supersavedriving.user.core.util.ToolUtil; import com.supersavedriving.user.modular.system.dao.AppUserMapper; import com.supersavedriving.user.modular.system.model.*; import com.supersavedriving.user.modular.system.service.*; import com.supersavedriving.user.modular.system.util.MallBook.model.InterfaceResponse; import com.supersavedriving.user.modular.system.util.MallBook.model.PaymentOrder; import com.supersavedriving.user.modular.system.util.MallBook.model.PaymentOrderGood; import com.supersavedriving.user.modular.system.util.MallBook.model.QueryOrder; import com.supersavedriving.user.modular.system.util.MallBook.util.Transfer; import com.supersavedriving.user.modular.system.util.MallBook.util.TrhRequest; import com.supersavedriving.user.modular.system.util.PayMoneyUtil; import com.supersavedriving.user.modular.system.util.RedisUtil; import com.supersavedriving.user.modular.system.util.ResultUtil; import com.supersavedriving.user.modular.system.util.UUIDUtil; import com.supersavedriving.user.modular.system.util.weChat.WXCore; import com.supersavedriving.user.modular.system.util.weChat.WeChatUtil; import com.supersavedriving.user.modular.system.util.weChat.model.Code2Session; import com.supersavedriving.user.modular.system.warpper.*; import org.apache.shiro.authc.SimpleAuthenticationInfo; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.authc.credential.HashedCredentialsMatcher; import org.apache.shiro.crypto.hash.Md5Hash; import org.apache.shiro.util.ByteSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; import java.math.BigDecimal; import java.math.BigInteger; import java.math.RoundingMode; import java.net.InetAddress; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; /** * 用户 */ @Service public class AppUserServiceImpl extends ServiceImpl implements IAppUserService { @Autowired private WeChatUtil weChatUtil; @Autowired private RedisUtil redisUtil; private final String salt = "s5d1"; @Autowired private ICouponService couponService; @Autowired private IUserToCouponService userToCouponService; @Autowired private IRechargeRecordService rechargeRecordService; @Autowired private PayMoneyUtil payMoneyUtil; @Autowired private IAccountChangeDetailService accountChangeDetailService; @Autowired private IDriverService driverService; @Autowired private ISystemConfigService systemConfigService; @Value("${callbackPath}") private String callbackPath;//支付回调网关地址 @Value("${wx.appletsAppid}") private String appletsAppid; @Override public ResultUtil appUserLogin(String jscode) throws Exception { Code2Session code2Session = weChatUtil.code2Session(jscode); if(null != code2Session.getErrcode() && code2Session.getErrcode() != 0){ return ResultUtil.error(code2Session.getErrmsg()); } String openid = code2Session.getOpenid(); AppUser appUser = this.selectOne(new EntityWrapper().eq("openid", openid).eq("status", 1)); if(null == appUser){ return ResultUtil.error("无效的账号"); } String token = getToken(appUser); if(ToolUtil.isEmpty(token)){ return ResultUtil.error("获取身份凭证失败"); } return ResultUtil.success(token); } /** * 获取身份凭证 * @return */ public String getToken(AppUser appUser){ //封装请求账号密码为shiro可验证的token String phone = appUser.getPhone(); UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(phone, phone.toCharArray()); String credentials = ShiroKit.md5(phone, salt); ByteSource credentialsSalt = new Md5Hash(salt); SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo( new ShiroUser(), credentials, credentialsSalt, ""); //校验用户账号密码 HashedCredentialsMatcher md5CredentialsMatcher = new HashedCredentialsMatcher(); md5CredentialsMatcher.setHashAlgorithmName(ShiroKit.hashAlgorithmName); md5CredentialsMatcher.setHashIterations(ShiroKit.hashIterations); boolean passwordTrueFlag = md5CredentialsMatcher.doCredentialsMatch( usernamePasswordToken, simpleAuthenticationInfo); if (passwordTrueFlag) { String token = JwtTokenUtil.generateToken(phone); String key = token; if(token.length() > 16){ key = token.substring(token.length() - 16); } redisUtil.setStrValue(key, appUser.getId().toString(), 94608000); redisUtil.setStrValue("USER_" + appUser.getPhone(), key, 94608000); return token; } return null; } /** * 微信授权注册登录 * @param signInToRegister * @return * @throws Exception */ @Override public ResultUtil signInToRegister(SignInToRegister signInToRegister) throws Exception { SignInToRegisterWarpper warpper = new SignInToRegisterWarpper(); try { if(ToolUtil.isEmpty(signInToRegister.getJscode())){ return ResultUtil.paranErr("jscode"); } if(ToolUtil.isEmpty(signInToRegister.getEncryptedDataPhone())){ return ResultUtil.paranErr("encryptedDataPhone"); } if(ToolUtil.isEmpty(signInToRegister.getIvPhone())){ return ResultUtil.paranErr("ivPhone"); } Code2Session code2Session = weChatUtil.code2Session(signInToRegister.getJscode()); if(null != code2Session.getErrcode() && code2Session.getErrcode() != 0){ return ResultUtil.error(code2Session.getErrmsg()); } String openid = code2Session.getOpenid(); String session_key = code2Session.getSession_key(); String decrypt = WXCore.decrypt(signInToRegister.getEncryptedDataPhone(), session_key, signInToRegister.getIvPhone()); if(ToolUtil.isEmpty(decrypt)){ return ResultUtil.error("获取手机号失败"); } JSONObject phone = JSON.parseObject(decrypt); String purePhoneNumber = phone.getString("purePhoneNumber"); AppUser appUser = this.selectOne(new EntityWrapper().eq("phone", purePhoneNumber).ne("status", 3)); if(null == appUser){ appUser = new AppUser(); appUser.setNickname("亲爱的用户"); appUser.setAvatar("https://csxdj.obs.cn-south-1.myhuaweicloud.com:443/66cc269703a84e4da87fb21e2c21ab1f.png"); appUser.setPhone(purePhoneNumber); appUser.setOpenid(openid); appUser.setUnionid(code2Session.getUnionid()); appUser.setAccountBalance(0D); appUser.setStatus(1); appUser.setCreateTime(new Date()); appUser.setIsException(1); if(null != signInToRegister.getInviterId()){ appUser.setInviterId(signInToRegister.getInviterId()); appUser.setInviterType(signInToRegister.getInviterType()); } this.insert(appUser); //发送优惠券 boolean lock = redisUtil.lock(5); if(!lock){ int num1 = 1; while (num1 <= 10){ Thread.sleep(3000);//等待3秒 lock = redisUtil.lock(5); if(lock){ break; }else{ num1++; } } } if(lock){ List list = pushCoupon(appUser.getId()); redisUtil.unlock(); warpper.setCoupons(list); } } if(appUser.getStatus() == 2){ return ResultUtil.error("账号被冻结"); } String token = getToken(appUser); if(ToolUtil.isEmpty(token)){ return ResultUtil.error("获取身份凭证失败"); } warpper.setToken(token); }catch (Exception e){ e.printStackTrace(); redisUtil.unlock(); } return ResultUtil.success(warpper); } /** * 转账 * @param id * @param merOrderId * @param toUserId * @param amount * @param notifyUrl * @return */ public ResultUtil zhaunzhang(Integer id, String merOrderId, String toUserId, Double amount, String notifyUrl){ Transfer transfer = new Transfer(); transfer.setDepositMerOrderId(merOrderId); transfer.setToUserId(toUserId); transfer.setAmount(new BigDecimal(amount).multiply(new BigDecimal(100)).setScale(0, RoundingMode.HALF_EVEN).longValue() + ""); transfer.setOrderName("补贴"); transfer.setNotifyUrl(notifyUrl); transfer.setParameter1(id.toString()); TrhRequest request = new TrhRequest(); InterfaceResponse execute = request.execute(transfer, Transfer.SERVICE_CODE); if("0000".equals(execute.getCode())){ JSONObject jsonObject = JSON.parseObject(execute.getResult()); Integer status = jsonObject.getInteger("status");//0:待处理;1:成功;2:失败 if(2 == status){ System.err.println("转账失败"); return ResultUtil.error("转账失败"); } return ResultUtil.success(); }else{ System.err.println("转账失败:" + execute.getMsg()); return ResultUtil.error(execute.getMsg()); } } /** * 发送优惠券 * @param userId */ public List pushCoupon(Integer userId){ List coupons = couponService.selectList(new EntityWrapper().eq("coupon_type", 2) .eq("coupon_state", 1).eq("status", 1).gt("remaining_quantity", 0)); List list = new ArrayList<>(); for (Coupon coupon : coupons) { Long num = coupon.getCouponSendQuantity() > coupon.getRemainingQuantity() ? coupon.getRemainingQuantity() : coupon.getCouponSendQuantity(); for (int i = 0; i < num; i++) { UserToCoupon userToCoupon = new UserToCoupon(); userToCoupon.setCouponId(coupon.getId()); userToCoupon.setCreateTime(new Date()); userToCoupon.setUserId(userId); userToCoupon.setStatus(1); userToCoupon.setCouponTotal(1); userToCoupon.setValidCount(1); userToCoupon.setExpireTime(new Date(System.currentTimeMillis() + (coupon.getCouponValidity().longValue() * 24L * 60L * 60L * 1000L))); userToCouponService.insert(userToCoupon); CouponWarpper couponWarpper = new CouponWarpper(); couponWarpper.setCouponConditionalAmount(coupon.getCouponConditionalAmount()); couponWarpper.setCouponPreferentialAmount(coupon.getCouponPreferentialAmount()); couponWarpper.setCouponName(coupon.getCouponName()); couponWarpper.setNumber(userToCoupon.getValidCount()); couponWarpper.setExpirationDate(userToCoupon.getExpireTime().getTime()); list.add(couponWarpper); } coupon.setRemainingQuantity(coupon.getCouponSendQuantity() > coupon.getRemainingQuantity() ? 0 : coupon.getRemainingQuantity() - coupon.getCouponSendQuantity()); couponService.updateById(coupon); } return list; } @Override public Integer getUserByRequest() throws Exception { ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = servletRequestAttributes.getRequest(); String requestHeader = request.getHeader(JwtConstants.AUTH_HEADER); if (ToolUtil.isNotEmpty(requestHeader) && requestHeader.startsWith("Bearer ")) { requestHeader = requestHeader.substring(requestHeader.indexOf(" ") + 1); String key = null; int length = requestHeader.length(); if(length > 16){ key = requestHeader.substring(length - 16); }else{ key = requestHeader; } String value = redisUtil.getValue(key); return null != value ? Integer.valueOf(value) : null; }else{ return null; } } /** * 修改个人信息 * @param userInfo * @return * @throws Exception */ @Override public ResultUtil updateUserInfo(Integer uid, UserInfo userInfo) throws Exception { AppUser appUser = this.selectById(uid); if(ToolUtil.isNotEmpty(userInfo.getAvatar())){ appUser.setAvatar(userInfo.getAvatar()); } if(ToolUtil.isNotEmpty(userInfo.getEmergencyContact())){ appUser.setEmergencyContact(userInfo.getEmergencyContact()); } if(ToolUtil.isNotEmpty(userInfo.getEmergencyPhone())){ appUser.setEmergencyPhone(userInfo.getEmergencyPhone()); } if(ToolUtil.isNotEmpty(userInfo.getNickname())){ appUser.setNickname(userInfo.getNickname()); } if(ToolUtil.isNotEmpty(userInfo.getPhone())){ if(userInfo.getPhone().equals(appUser.getPhone())){ return ResultUtil.error("新手机不能和原手机号相同"); } String value = redisUtil.getValue("+86" + userInfo.getPhone()); if(ToolUtil.isEmpty(value) || !value.equals(userInfo.getCode())){ return ResultUtil.error("验证码无效"); } appUser.setPhone(userInfo.getPhone()); } this.updateById(appUser); return ResultUtil.success(); } /** * 余额充值 * @param uid * @param amount * @return * @throws Exception */ @Override public ResultUtil rechargeBalance(Integer uid, Double amount) throws Exception { if(0 >= amount){ return ResultUtil.error("充值金额必须大于0"); } SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS"); String out_trade_no = sdf.format(new Date()) + UUIDUtil.getNumberRandom(5); AppUser appUser = this.selectById(uid); RechargeRecord rechargeRecord = new RechargeRecord(); rechargeRecord.setType(1); rechargeRecord.setUserId(uid); rechargeRecord.setCode(out_trade_no); rechargeRecord.setAmount(amount); rechargeRecord.setCreateTime(new Date()); rechargeRecord.setPayStatus(1); rechargeRecord.setPayType(1); rechargeRecordService.insert(rechargeRecord); PaymentOrder paymentOrder = new PaymentOrder(); paymentOrder.setBizOrderId(out_trade_no); paymentOrder.setAmount(new BigDecimal(amount).multiply(new BigDecimal(100)).setScale(0, RoundingMode.HALF_EVEN).longValue() + ""); paymentOrder.setOrderName("账户充值"); paymentOrder.setPayType("WX_MINI"); paymentOrder.setTransferType("0"); paymentOrder.setAsynSplitFlag("1"); paymentOrder.setAppid(appletsAppid); paymentOrder.setOpenid(appUser.getOpenid()); paymentOrder.setTerminalIp(InetAddress.getLocalHost().getHostAddress()); List goodsDetail = new ArrayList<>(); PaymentOrderGood paymentOrderGood = new PaymentOrderGood(); paymentOrderGood.setGoodsName("账户充值"); goodsDetail.add(paymentOrderGood); paymentOrder.setGoodsDetail(goodsDetail); paymentOrder.setFrontUrl(callbackPath + "/base/appUser/rechargeBalanceCallback"); paymentOrder.setNotifyUrl(callbackPath + "/base/appUser/rechargeBalanceCallback"); paymentOrder.setParameter1(out_trade_no); TrhRequest request = new TrhRequest(); InterfaceResponse execute = request.execute(paymentOrder, PaymentOrder.SERVICE_CODE); if(!"0000".equals(execute.getCode())){ return ResultUtil.error(execute.getMsg()); } JSONObject jsonObject = JSON.parseObject(execute.getResult()); String status = jsonObject.getString("status"); if("2".equals(status)){ return ResultUtil.error("失败"); } String merOrderId = jsonObject.getString("merOrderId"); String payCode = jsonObject.getString("payCode"); if(ToolUtil.isNotEmpty(payCode)){ new Thread(new Runnable() { @Override public void run() { try { int num = 1; int wait = 0; while (num <= 10){ int min = 5000; wait += (min * num); RechargeRecord rechargeRecord1 = rechargeRecordService.selectOne(new EntityWrapper().eq("code", out_trade_no)); if(rechargeRecord1.getPayStatus() != 1){ return; } QueryOrder queryOrder = new QueryOrder(); queryOrder.setOriginalMerOrderId(merOrderId); queryOrder.setQueryType("1"); TrhRequest request = new TrhRequest(); InterfaceResponse execute1 = request.execute(queryOrder, QueryOrder.SERVICE_CODE); if("0000".equals(execute1.getCode())){ JSONObject jsonObject1 = JSON.parseObject(execute1.getResult()); String status1 = jsonObject1.getString("status"); if("0".equals(status1)){//待处理 Thread.sleep(wait); num++; } if("1".equals(status1)){//成功 String merOrderId = jsonObject1.getString("merOrderId"); AppUser appUser1 = AppUserServiceImpl.this.selectById(rechargeRecord1.getUserId()); AccountChangeDetail accountChangeDetail = new AccountChangeDetail(); accountChangeDetail.setUserType(1); accountChangeDetail.setUserId(appUser1.getId()); accountChangeDetail.setCode(System.currentTimeMillis() + UUIDUtil.getNumberRandom(5)); accountChangeDetail.setChangeType(3); accountChangeDetail.setType(1); accountChangeDetail.setCreateTime(new Date()); accountChangeDetail.setExplain("账户充值"); accountChangeDetail.setOldData(appUser1.getAccountBalance()); appUser1.setAccountBalance(new BigDecimal(appUser1.getAccountBalance()).add(new BigDecimal(rechargeRecord1.getAmount())).setScale(2, RoundingMode.HALF_EVEN).doubleValue()); accountChangeDetail.setNewData(appUser1.getAccountBalance()); accountChangeDetailService.saveData(accountChangeDetail); SystemConfig systemConfig = systemConfigService.selectOne(new EntityWrapper().eq("type", 6)); Double num2 = JSON.parseObject(systemConfig.getContent()).getDouble("num2"); if(appUser1.getHavDiscount() == 0 && rechargeRecord1.getAmount().compareTo(num2) >= 0){ appUser1.setHavDiscount(1); } AppUserServiceImpl.this.updateById(appUser1); rechargeRecord1.setPayTime(new Date()); rechargeRecord1.setPayStatus(2); rechargeRecord1.setOrderNumber(merOrderId); rechargeRecord1.setSurplusDividedAmount(rechargeRecord1.getAmount()); rechargeRecordService.updateById(rechargeRecord1); break; } if("2".equals(status1) || 10 == num){//失败 rechargeRecordService.deleteById(rechargeRecord1.getId()); break; } }else{ Thread.sleep(wait); num++; } } }catch (Exception e){ e.printStackTrace(); } } }).start(); } return ResultUtil.success(payCode); } /** * 余额充值回调 * @param out_trade_no * @param transaction_id * @return * @throws Exception */ @Override public void rechargeBalanceCallback(String out_trade_no, String transaction_id) throws Exception { RechargeRecord rechargeRecord1 = rechargeRecordService.selectOne(new EntityWrapper().eq("code", out_trade_no)); if(rechargeRecord1.getPayStatus() != 1){ return; } AppUser appUser = this.selectById(rechargeRecord1.getUserId()); AccountChangeDetail accountChangeDetail = new AccountChangeDetail(); accountChangeDetail.setUserType(1); accountChangeDetail.setUserId(rechargeRecord1.getUserId()); accountChangeDetail.setCode(System.currentTimeMillis() + UUIDUtil.getNumberRandom(5)); accountChangeDetail.setChangeType(3); accountChangeDetail.setType(1); accountChangeDetail.setCreateTime(new Date()); accountChangeDetail.setExplain("余额充值"); accountChangeDetail.setOldData(appUser.getAccountBalance()); appUser.setAccountBalance(new BigDecimal(appUser.getAccountBalance()).add(new BigDecimal(rechargeRecord1.getAmount())).setScale(2, RoundingMode.HALF_EVEN).doubleValue()); accountChangeDetail.setNewData(appUser.getAccountBalance()); accountChangeDetailService.saveData(accountChangeDetail); SystemConfig systemConfig = systemConfigService.selectOne(new EntityWrapper().eq("type", 6)); Double num2 = JSON.parseObject(systemConfig.getContent()).getDouble("num2"); if(appUser.getHavDiscount() == 0 && rechargeRecord1.getAmount().compareTo(num2) >= 0){ appUser.setHavDiscount(1); } this.updateById(appUser); rechargeRecord1.setPayTime(new Date()); rechargeRecord1.setPayStatus(2); rechargeRecord1.setOrderNumber(transaction_id); rechargeRecord1.setSurplusDividedAmount(rechargeRecord1.getAmount()); rechargeRecordService.updateById(rechargeRecord1); } /** * 获取用户优惠券列表 * @param uid * @param state * @param pageNum * @param pageSize * @return * @throws Exception */ @Override public List queryMyCoupons(Integer uid, Integer state, Integer pageNum, Integer pageSize) throws Exception { return null; } }