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.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.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; @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(), 7 * 24 * 60 * 60); redisUtil.setStrValue("USER_" + appUser.getPhone(), key, 7 * 24 * 60 * 60); return token; } return null; } /** * 微信授权注册登录 * @param signInToRegister * @return * @throws Exception */ @Override public ResultUtil signInToRegister(SignInToRegister signInToRegister) throws Exception { SignInToRegisterWarpper warpper = new SignInToRegisterWarpper(); 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); appUser.setInviterId(signInToRegister.getInviterId()); appUser.setInviterType(signInToRegister.getInviterType()); this.insert(appUser); //发送优惠券 boolean lock = redisUtil.lock(); 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); return ResultUtil.success(warpper); } /** * 发送优惠券 * @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) { UserToCoupon userToCoupon = new UserToCoupon(); userToCoupon.setCouponId(coupon.getId()); userToCoupon.setCreateTime(new Date()); userToCoupon.setUserId(userId); userToCoupon.setStatus(1); userToCoupon.setCouponTotal(coupon.getCouponSendQuantity() > coupon.getRemainingQuantity() ? coupon.getRemainingQuantity() : coupon.getCouponSendQuantity()); userToCoupon.setValidCount(userToCoupon.getCouponTotal()); userToCoupon.setExpireTime(new Date(System.currentTimeMillis() + (coupon.getCouponValidity() * 24 * 60 * 60 * 1000))); userToCouponService.insert(userToCoupon); coupon.setRemainingQuantity(coupon.getCouponSendQuantity() > coupon.getRemainingQuantity() ? 0 : coupon.getRemainingQuantity() - coupon.getCouponSendQuantity()); couponService.updateById(coupon); 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); } 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(3); 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); // ResultUtil weixinpay = payMoneyUtil.weixinpay("余额充值", "", out_trade_no, amount.toString(), "/base/appUser/rechargeBalanceCallback", "JSAPI", appUser.getOpenid()); // return weixinpay; PaymentOrder paymentOrder = new PaymentOrder(); paymentOrder.setBizOrderId(out_trade_no); paymentOrder.setAmount(String.valueOf(amount * 100)); 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(""); 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.getResult())){ return ResultUtil.error(execute.getMsg()); } JSONObject jsonObject = JSON.parseObject(execute.getResult()); String status = jsonObject.getString("status"); if("2".equals(status)){ return ResultUtil.error("失败"); } if("0".equals(status)){ return ResultUtil.error("处理中"); } String payCode = jsonObject.getString("payCode"); 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(3)); accountChangeDetail.setChangeType(3); accountChangeDetail.setType(1); accountChangeDetail.setCreateTime(new Date()); accountChangeDetail.setExplain("余额充值"); accountChangeDetail.setOldData(appUser.getAccountBalance()); appUser.setAccountBalance(appUser.getAccountBalance() + rechargeRecord1.getAmount()); accountChangeDetail.setNewData(appUser.getAccountBalance()); this.updateById(appUser); accountChangeDetailService.saveData(accountChangeDetail); rechargeRecord1.setPayTime(new Date()); rechargeRecord1.setPayStatus(2); rechargeRecord1.setOrderNumber(transaction_id); 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; } }