package com.jsowell.service; import com.alibaba.fastjson2.JSONObject; import com.alibaba.fastjson2.TypeReference; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; import com.google.common.collect.ImmutableMap; import com.huifu.adapay.core.exception.BaseAdaPayException; import com.huifu.adapay.model.Payment; import com.jsowell.adapay.common.CreateAdaPaymentParam; import com.jsowell.common.constant.CacheConstants; import com.jsowell.common.constant.Constants; import com.jsowell.common.core.page.PageResponse; import com.jsowell.common.core.redis.RedisCache; import com.jsowell.common.enums.TitleTypeEnum; import com.jsowell.common.enums.uniapp.BalanceChangesEnum; import com.jsowell.common.enums.ykc.ReturnCodeEnum; import com.jsowell.common.enums.ykc.ScenarioEnum; import com.jsowell.common.exception.BusinessException; import com.jsowell.common.util.AdapayUtil; import com.jsowell.common.util.JWTUtils; import com.jsowell.common.util.StringUtils; import com.jsowell.common.util.id.IdUtils; import com.jsowell.pile.domain.MemberBasicInfo; import com.jsowell.pile.domain.MemberInvoiceTitle; import com.jsowell.pile.domain.MemberPlateNumberRelation; import com.jsowell.pile.domain.MemberWalletInfo; import com.jsowell.pile.domain.PileAuthCard; import com.jsowell.pile.dto.BindingCarNoDTO; import com.jsowell.pile.dto.BindingCardDTO; import com.jsowell.pile.dto.InvoiceTitleDTO; import com.jsowell.pile.dto.MemberRegisterAndLoginDTO; import com.jsowell.pile.dto.MemberRegisterDTO; import com.jsowell.pile.dto.PaymentScenarioDTO; import com.jsowell.pile.dto.UniAppQueryMemberBalanceDTO; import com.jsowell.pile.dto.WechatLoginDTO; import com.jsowell.pile.dto.WeixinPayDTO; import com.jsowell.pile.service.IMemberBasicInfoService; import com.jsowell.pile.service.IMemberInvoiceTitleService; import com.jsowell.pile.service.IMemberPlateNumberRelationService; import com.jsowell.pile.service.IPileAuthCardService; import com.jsowell.pile.service.IPileMerchantInfoService; import com.jsowell.pile.transaction.dto.MemberTransactionDTO; import com.jsowell.pile.transaction.service.TransactionService; import com.jsowell.pile.vo.uniapp.InvoiceTitleVO; import com.jsowell.pile.vo.uniapp.MemberVO; import com.jsowell.pile.vo.uniapp.MemberWalletLogVO; import com.jsowell.wxpay.service.WxAppletRemoteService; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.compress.utils.Lists; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cglib.beans.BeanMap; import org.springframework.stereotype.Service; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Objects; @Service public class MemberService { private final Logger log = LoggerFactory.getLogger(this.getClass()); @Autowired private RedisCache redisCache; @Autowired private TransactionService transactionService; @Autowired private IMemberBasicInfoService memberBasicInfoService; @Autowired private IPileMerchantInfoService pileMerchantInfoService; @Autowired private WxAppletRemoteService wxAppletRemoteService; @Autowired private IMemberPlateNumberRelationService memberPlateNumberRelationService; @Autowired private IPileAuthCardService pileAuthCardService; @Autowired private IMemberInvoiceTitleService memberInvoiceTitleService; @Autowired private OrderService orderService; /** * 校验短信验证码 * @param dto */ public void checkVerificationCode(MemberRegisterAndLoginDTO dto) { // 取出缓存中的验证码进行对比,如果缓存中没有,则超时 String captchaCode = redisCache.getCacheObject(CacheConstants.SMS_VERIFICATION_CODE_KEY + dto.getMobileNumber()); if (StringUtils.isEmpty(captchaCode)) { throw new BusinessException(ReturnCodeEnum.CODE_VERIFICATION_CODE_TIMEOUT_ERROR); } // 如果缓存中有,但与实际不一致,则为验证码错误 if (!StringUtils.equals(captchaCode, dto.getVerificationCode())) { throw new BusinessException(ReturnCodeEnum.CODE_VERIFICATION_CODE_ERROR); } } /** * 短信验证码登录注册 * @param dto * @return */ public String memberRegisterAndLogin(MemberRegisterAndLoginDTO dto) { // 校验短信验证码 两种情况不能通过校验,1-验证码错误;2-超时 验证码10分钟有效 checkVerificationCode(dto); String merchantId = ""; return memberRegisterAndLogin(dto.getMobileNumber(), dto.getMerchantId(), dto.getOpenId()); } /** * 公共登陆注册方法 * @param phoneNumber 手机号 * @param merchantId 商户id * @return token返给前端 */ private String memberRegisterAndLogin(String phoneNumber, String merchantId, String openId) { if (StringUtils.isBlank(phoneNumber)) { throw new BusinessException(ReturnCodeEnum.CODE_GET_MOBILE_NUMBER_BY_CODE_ERROR); } // if (Objects.isNull(merchantId)) { // throw new BusinessException(ReturnCodeEnum.CODE_GET_MERCHANT_ID_BY_APP_ID_ERROR); // } // 查询手机号码是否注册过 MemberBasicInfo memberBasicInfo = memberBasicInfoService.selectInfoByMobileNumberAndMerchantId(phoneNumber, merchantId); if (Objects.isNull(memberBasicInfo)) { // 不存在则新增数据 String memberId = generateNewMemberId(); memberBasicInfo = new MemberBasicInfo(); memberBasicInfo.setStatus(Constants.ONE); memberBasicInfo.setMemberId(memberId); memberBasicInfo.setNickName("会员" + memberId); memberBasicInfo.setMobileNumber(phoneNumber); memberBasicInfo.setMerchantId(Long.valueOf(merchantId)); memberBasicInfo.setOpenId(openId); // 首次新建会员,同时新建会员钱包 MemberWalletInfo memberWalletInfo = MemberWalletInfo.builder().memberId(memberId).build(); MemberTransactionDTO memberTransactionDTO = MemberTransactionDTO.builder() .memberBasicInfo(memberBasicInfo) .memberWalletInfo(memberWalletInfo) .build(); transactionService.createMember(memberTransactionDTO); } else { if (StringUtils.isBlank(memberBasicInfo.getOpenId()) && StringUtils.isNotBlank(openId)) { memberBasicInfo.setOpenId(openId); memberBasicInfoService.updateMemberBasicInfo(memberBasicInfo); } } // 服务器生成token返给前端 String memberToken = JWTUtils.createMemberToken(memberBasicInfo.getMemberId(), memberBasicInfo.getNickName()); // log.info("memToken:{}", memberToken); return memberToken; } private String generateNewMemberId() { while (true) { String memberId = IdUtils.getMemberId(); // 通过memberId查询是否已经存在 MemberVO memberVO = memberBasicInfoService.queryMemberInfoByMemberId(memberId); if (memberVO == null) { return memberId; } } } /** * 微信一键登录 * @param dto */ public String wechatLogin(WechatLoginDTO dto) { // 通过微信传的code获取手机号码 String mobileNumber = wxAppletRemoteService.getMobileNumberByCode(dto.getCode()); if (StringUtils.isBlank(mobileNumber)) { throw new BusinessException(ReturnCodeEnum.CODE_GET_MOBILE_NUMBER_BY_CODE_ERROR); } // 通过appid获取运营商id String merchantId = pileMerchantInfoService.getMerchantIdByAppId(dto.getAppId()); // if (Objects.isNull(merchantId)) { // throw new BusinessException(ReturnCodeEnum.CODE_GET_MERCHANT_ID_BY_APP_ID_ERROR); // } // 通过code获取openId String openId = ""; try { openId = getOpenIdByCode(dto.getOpenIdCode()); } catch (Exception e) { log.error("getOpenIdByCode发生异常", e); } // 查询手机号码是否注册过 return memberRegisterAndLogin(mobileNumber, merchantId, openId); } /** * 获取openId * @param code * @return */ public String getOpenIdByCode(String code) { return wxAppletRemoteService.getOpenIdByCode(code); } /** * 处理用户信息 * * @param dto 用户个人信息 */ public void handleUserInfo(MemberRegisterDTO dto) { // 通过用户手机号查询数据库,如果数据库中存在,则更新 MemberBasicInfo memberBasicInfo = memberBasicInfoService.selectInfoByMobileNumber(dto.getMobileNumber()); if (Objects.nonNull(memberBasicInfo)) { MemberBasicInfo memberInfo = MemberBasicInfo.builder() .avatarUrl(dto.getAvatarUrl()) .mobileNumber(dto.getMobileNumber()) .nickName(dto.getNickName()) .build(); memberBasicInfoService.updateMemberBasicInfo(memberInfo); } } /** * 通过memberToken获取用户账户信息 * * @param memberId * @return */ public MemberVO getMemberInfoByMemberId(String memberId) { MemberVO memberVO = memberBasicInfoService.queryMemberInfoByMemberId(memberId); return memberVO; } /** * 查询用户账户余额变动信息 * * @param dto */ public PageResponse getMemberBalanceChanges(UniAppQueryMemberBalanceDTO dto) { // 获取分页信息以及memberId int pageNum = dto.getPageNum() == 0 ? 1 : dto.getPageNum(); int pageSize = dto.getPageSize() == 0 ? 10 : dto.getPageSize(); String memberId = dto.getMemberId(); String type = dto.getType(); if (!StringUtils.equals("1", type) && !StringUtils.equals("2", type)) { type = ""; } // 分页 PageHelper.startPage(pageNum, pageSize); List list = memberBasicInfoService.getMemberBalanceChanges(memberId, type); PageInfo pageInfo = new PageInfo<>(list); for (MemberWalletLogVO walletLogVO : pageInfo.getList()) { String subType = walletLogVO.getSubType(); String subTypeValue = BalanceChangesEnum.getValueByCode(subType); if (StringUtils.isNotBlank(subTypeValue)) { walletLogVO.setSubType(subTypeValue); } // walletLogVO.setTotalAccountAmount(walletLogVO.getPrincipalBalance().add(walletLogVO.getGiftBalance())); } PageResponse pageResponse = PageResponse.builder() .pageSize(pageSize) .pageNum(pageNum) .list(pageInfo.getList()) .pages(pageInfo.getPages()) .total(pageInfo.getTotal()) .build(); return pageResponse; } /** * 用户绑定车牌号 * @param dto */ public void memberBindingCarNo(BindingCarNoDTO dto){ // 校验短信验证码 MemberRegisterAndLoginDTO registerAndLoginDTO = MemberRegisterAndLoginDTO.builder() .mobileNumber(dto.getPhoneNumber()) .verificationCode(dto.getVerificationCode()) .build(); checkVerificationCode(registerAndLoginDTO); // 判断当前车牌号是否已经绑定 MemberPlateNumberRelation relation = new MemberPlateNumberRelation(); relation.setMemberId(dto.getMemberId()); relation.setLicensePlateNumber(dto.getCarNo()); List list = memberPlateNumberRelationService.selectMemberPlateNumberRelationList(relation); if (CollectionUtils.isNotEmpty(list)) { // 不为空说明该用户绑定过此车牌号 throw new BusinessException(ReturnCodeEnum.CODE_THIS_CARNO_HAS_BEEN_BINDING); } relation.setPhoneNumber(dto.getPhoneNumber()); memberPlateNumberRelationService.insertMemberPlateNumberRelation(relation); } /** * 用户绑定鉴权卡 * @param dto */ public int memberBindCard(BindingCardDTO dto){ // 校验短信验证码 MemberRegisterAndLoginDTO registerAndLoginDTO = MemberRegisterAndLoginDTO.builder() .mobileNumber(dto.getPhoneNumber()) .verificationCode(dto.getVerificationCode()) .build(); checkVerificationCode(registerAndLoginDTO); // 判断当前鉴权卡是否被绑定过 PileAuthCard pileAuthCardInfo = pileAuthCardService.selectCardInfoByLogicCard(dto.getLogicCard()); if (pileAuthCardInfo == null){ // 为空说明没查到此卡信息 throw new BusinessException(ReturnCodeEnum.CODE_THIS_CARD_HAS_NO_INFO); } if (StringUtils.isNotBlank(pileAuthCardInfo.getMemberId())) { // memberId 不为空,说明此卡已被绑定 throw new BusinessException(ReturnCodeEnum.CODE_THIS_CARD_HAS_BEEN_BINDING); } if (!StringUtils.equals(pileAuthCardInfo.getSecretKey(), dto.getSecretKey().toUpperCase(Locale.ROOT))) { // 密钥不一致,不能绑定 throw new BusinessException(ReturnCodeEnum.CODE_SECRET_KEY_NOT_SAME); } PileAuthCard authCard = PileAuthCard.builder() .memberId(dto.getMemberId()) .status("1") // 1-正常使用 .createBy(dto.getMemberId()) .id(pileAuthCardInfo.getId()) .build(); return pileAuthCardService.updatePileAuthCard(authCard); } /** * 用户解绑鉴权卡 * @param dto * @return */ public int memberUnbindCard(BindingCardDTO dto) { // 校验短信验证码 MemberRegisterAndLoginDTO registerAndLoginDTO = MemberRegisterAndLoginDTO.builder() .mobileNumber(dto.getPhoneNumber()) .verificationCode(dto.getVerificationCode()) .build(); // checkVerificationCode(registerAndLoginDTO); // 校验身份信息 PileAuthCard authCard = PileAuthCard.builder() .logicCard(dto.getLogicCard()) .memberId(dto.getMemberId()) .build(); PileAuthCard pileAuthCardInfo = pileAuthCardService.selectPileAuthCardInfo(authCard); if (pileAuthCardInfo == null){ // 为空说明没查到此卡信息 throw new BusinessException(ReturnCodeEnum.CODE_THIS_CARD_HAS_NO_INFO); } // 解绑鉴权卡 return pileAuthCardService.unBindingCard(authCard); } public List queryMemberInvoiceTitles(String memberId) { List resultList = Lists.newArrayList(); List memberInvoiceTitles = memberInvoiceTitleService.selectMemberInvoiceTitleList(memberId); if (CollectionUtils.isEmpty(memberInvoiceTitles)) { return resultList; } for (MemberInvoiceTitle memberInvoiceTitle : memberInvoiceTitles) { String reception = StringUtils.isNotEmpty(memberInvoiceTitle.getEmail()) ? memberInvoiceTitle.getEmail() : memberInvoiceTitle.getPhoneNumber(); resultList.add( InvoiceTitleVO.builder() .titleId(memberInvoiceTitle.getId() + "") .titleName(memberInvoiceTitle.getName()) .titleType(TitleTypeEnum.getLabel(memberInvoiceTitle.getTitleType())) .taxId(memberInvoiceTitle.getTaxId()) .unitAddress(memberInvoiceTitle.getUnitAddress()) .phoneNumber(memberInvoiceTitle.getPhoneNumber()) .email(memberInvoiceTitle.getEmail()) .reception(reception) .bankName(memberInvoiceTitle.getBankName()) .bankAccountNumber(memberInvoiceTitle.getBankAccountNumber()) .defaultFlag(memberInvoiceTitle.getDefaultFlag()) .build() ); } return resultList; } public void createMemberInvoiceTitle(InvoiceTitleDTO dto) { MemberInvoiceTitle title = new MemberInvoiceTitle(); BeanUtils.copyProperties(dto, title); title.setName(dto.getTitleName()); if (StringUtils.isEmail(dto.getReception())) { title.setEmail(dto.getReception()); } else { title.setPhoneNumber(dto.getReception()); } int i = memberInvoiceTitleService.insertMemberInvoiceTitle(title); // log.info("新增{}条发票抬头", i); } public void updateMemberInvoiceTitle(InvoiceTitleDTO dto) { MemberInvoiceTitle title = new MemberInvoiceTitle(); BeanUtils.copyProperties(dto, title); title.setId(Long.valueOf(dto.getTitleId())); title.setName(dto.getTitleName()); if (StringUtils.isEmail(dto.getReception())) { title.setEmail(dto.getReception()); } else { title.setPhoneNumber(dto.getReception()); } int i = memberInvoiceTitleService.updateMemberInvoiceTitle(title); } /** * 删除会员发票抬头 * @param dto */ public void deleteMemberInvoiceTitle(InvoiceTitleDTO dto) { memberInvoiceTitleService.deleteMemberInvoiceTitleById(Long.valueOf(dto.getTitleId())); } public Map rechargeBalance(WeixinPayDTO dto) throws Exception { PaymentScenarioDTO paymentScenarioDTO = new PaymentScenarioDTO(); paymentScenarioDTO.setType(ScenarioEnum.BALANCE.getValue()); paymentScenarioDTO.setMemberId(dto.getMemberId()); dto.setAttach(JSONObject.toJSONString(paymentScenarioDTO)); dto.setDescription("会员充值余额"); return orderService.weixinPayV3(dto); } public Map rechargeBalanceWithAdapay(WeixinPayDTO dto) throws Exception { // 封装对象 CreateAdaPaymentParam createAdaPaymentParam = new CreateAdaPaymentParam(); createAdaPaymentParam.setOrder_no(IdUtils.fastSimpleUUID()); createAdaPaymentParam.setPay_amt(AdapayUtil.formatAmount(dto.getAmount())); createAdaPaymentParam.setApp_id("app_d0c80cb1-ffc8-48cb-a030-fe9bec823aaa"); // todo 后面移动到配置文件中 createAdaPaymentParam.setPay_channel("wx_lite"); // todo 如果以后有支付宝等别的渠道,这里需要做修改,判断是什么渠道的请求 createAdaPaymentParam.setGoods_title("充电费用1"); createAdaPaymentParam.setGoods_desc("充电费用2"); createAdaPaymentParam.setDescription("充电费用3"); createAdaPaymentParam.setExpend(JSONObject.toJSONString( ImmutableMap.of("open_id", dto.getOpenId()))); //异步通知地址,url为http/https路径,服务器POST回调,URL 上请勿附带参数 createAdaPaymentParam.setNotify_url("https://api.jsowellcloud.com/uniapp/pay/adapayCallback"); try { log.info("创建汇付支付参数:{}", JSONObject.toJSONString(createAdaPaymentParam)); Map response = Payment.create(BeanMap.create(createAdaPaymentParam)); log.info("创建汇付支付参数反参:{}", JSONObject.toJSONString(response)); if (response != null && !response.isEmpty()) { JSONObject jsonObject = JSONObject.parseObject(response.get("expend").toString()); JSONObject pay_info = jsonObject.getJSONObject("pay_info"); Map resultMap = JSONObject.parseObject(pay_info.toJSONString(), new TypeReference>() {}); return resultMap; } } catch (BaseAdaPayException e) { log.error("汇付-获取支付对象发生异常", e); } return null; } }