Files
jsowell-charger-web/jsowell-admin/src/main/java/com/jsowell/service/MemberService.java
jsowell fa641a8563 update
2026-05-14 17:12:04 +08:00

1174 lines
47 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package com.jsowell.service;
import cn.hutool.core.util.PageUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.TypeReference;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.request.AlipaySystemOauthTokenRequest;
import com.alipay.api.response.AlipaySystemOauthTokenResponse;
import com.alipay.easysdk.factory.Factory;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.huifu.adapay.core.exception.BaseAdaPayException;
import com.huifu.adapay.model.Payment;
import com.jsowell.adapay.common.CreateAdaPaymentParam;
import com.jsowell.adapay.config.AbstractAdapayConfig;
import com.jsowell.adapay.factory.AdapayConfigFactory;
import com.jsowell.alipay.factory.AlipayClientFactory;
import com.jsowell.alipay.service.AliAppletRemoteService;
import com.jsowell.common.constant.CacheConstants;
import com.jsowell.common.constant.Constants;
import com.jsowell.common.constant.UserConstants;
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.adapay.AdapayPayChannelEnum;
import com.jsowell.common.enums.adapay.MerchantDelayModeEnum;
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.common.util.id.SnowflakeIdWorker;
import com.jsowell.pile.domain.*;
import com.jsowell.pile.dto.*;
import com.jsowell.pile.service.*;
import com.jsowell.pile.transaction.dto.MemberTransactionDTO;
import com.jsowell.pile.transaction.service.TransactionService;
import com.jsowell.pile.util.MerchantUtils;
import com.jsowell.pile.vo.base.MemberWalletVO;
import com.jsowell.pile.vo.uniapp.customer.InvoiceTitleVO;
import com.jsowell.pile.vo.uniapp.customer.MemberVO;
import com.jsowell.pile.vo.uniapp.customer.MemberWalletInfoVO;
import com.jsowell.pile.vo.uniapp.customer.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.beans.factory.annotation.Value;
import org.springframework.cglib.beans.BeanMap;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.text.ParseException;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
@Service
public class MemberService {
private static final int MAX_MEMBER_ID_GENERATE_RETRY_TIMES = 20;
private static final int MAX_MEMBER_REGISTER_RETRY_TIMES = 5;
private final Logger log = LoggerFactory.getLogger(this.getClass());
@Autowired
private RedisCache redisCache;
@Autowired
private TransactionService transactionService;
@Autowired
private MemberBasicInfoService memberBasicInfoService;
@Autowired
private PileMerchantInfoService pileMerchantInfoService;
@Autowired
private WxAppletRemoteService wxAppletRemoteService;
@Autowired
private AliAppletRemoteService aliAppletRemoteService;
@Autowired
private MemberPlateNumberRelationService memberPlateNumberRelationService;
@Autowired
private PileAuthCardService pileAuthCardService;
@Autowired
private MemberInvoiceTitleService memberInvoiceTitleService;
@Autowired
private MemberWalletInfoService memberWalletInfoService;
@Autowired
private PileRemoteService pileRemoteService;
@Autowired
private OrderBasicInfoService orderBasicInfoService;
@Autowired
private OrderService orderService;
@Value("${adapay.jsowell.appId}")
private String ADAPAY_APP_ID;
@Value("${adapay.callback}")
private String ADAPAY_CALLBACK_URL;
@Value("${weixin.login.appid}")
private String APP_ID;
private final AlipayClient alipayClient;
@Autowired
public MemberService(AlipayClientFactory alipayClientFactory) {
this.alipayClient = alipayClientFactory.getAlipayClient();
}
/**
* 校验短信验证码
* @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);
// }
// 获取通用验证码
String commonCaptchaCode = redisCache.getCacheObject(CacheConstants.SMS_COMMON_VERIFICATION_CODE_KEY + dto.getMobileNumber());
// 缓存中的验证码或者通用验证码, 两个都不匹配, 则抛出异常
if (!StringUtils.equals(captchaCode, dto.getVerificationCode()) && !StringUtils.equals(commonCaptchaCode, dto.getVerificationCode())) {
throw new BusinessException(ReturnCodeEnum.CODE_VERIFICATION_CODE_ERROR);
}
// 如果缓存中有,但与实际不一致,则为验证码错误
// if (!StringUtils.equals(captchaCode, dto.getVerificationCode())) {
// throw new BusinessException(ReturnCodeEnum.CODE_VERIFICATION_CODE_ERROR);
// }
}
/**
* 短信验证码登录注册
* @param dto
* @return
*/
public String memberRegisterAndLoginBySMS(MemberRegisterAndLoginDTO dto) {
// 校验短信验证码 两种情况不能通过校验1-验证码错误2-超时 验证码10分钟有效
checkVerificationCode(dto);
return memberRegisterAndLoginV2(dto); // 短信验证码登录
}
/**
* 公共登录注册方法
*
* <p>该方法已废弃,当前会员注册/登录主流程统一走
* {@link #memberRegisterAndLoginV2(MemberRegisterAndLoginDTO)}。</p>
*
* <p>保留该方法的原因:</p>
* <p>1. 便于和 V2 做逻辑对照,确认重构前后行为一致。</p>
* <p>2. 作为短期回溯参考,降低生产切换风险。</p>
* <p>3. 避免在一次重构中直接删除旧实现,影响排查问题时的可读性。</p>
*
* @return token返给前端
*/
@Deprecated
protected String memberRegisterAndLogin(MemberRegisterAndLoginDTO dto) {
String phoneNumber = dto.getMobileNumber();
String firstLevelMerchantId = dto.getFirstLevelMerchantId();
String openId = dto.getOpenId();
String buyerId = dto.getBuyerId();
log.info("公共登录注册方法, phoneNumber:{}, firstLevelMerchantId:{}, openId:{}", phoneNumber, firstLevelMerchantId, openId);
if (StringUtils.isBlank(phoneNumber)) {
throw new BusinessException(ReturnCodeEnum.CODE_GET_MOBILE_NUMBER_BY_CODE_ERROR);
}
if (StringUtils.isBlank(firstLevelMerchantId)) {
throw new BusinessException(ReturnCodeEnum.CODE_GET_MERCHANT_ID_BY_APP_ID_ERROR);
}
// 2024年6月11日15点37分 支付宝没有openid改为不校验openid
// 2024年6月14日17点03分请求来源为微信校验openId
if (AdapayPayChannelEnum.WX_LITE.getValue().equals(dto.getRequestSource()) && StringUtils.isBlank(openId)) {
throw new BusinessException(ReturnCodeEnum.CODE_OPEN_ID_IS_NULL_ERROR);
}
// 锁键包含手机号和运营商ID确保同一运营商下的同一手机号串行处理不同运营商互不影响
String lockKey = CacheConstants.USER_APP_REGISTER + phoneNumber + ":" + firstLevelMerchantId;
String requestId = IdUtils.fastUUID();
Boolean isLock = false;
try {
// 获取锁防止注册创建重复账户锁超时时间60秒足够覆盖业务执行时间
isLock = redisCache.lock(lockKey, requestId, 60);
if (!isLock) {
// 获取锁失败,说明有其他请求正在处理,提示用户稍候
log.warn("获取注册锁失败,可能有并发请求正在处理, phoneNumber:{}, merchantId:{}", phoneNumber, firstLevelMerchantId);
throw new BusinessException(ReturnCodeEnum.CODE_MEMBER_REGISTER_AND_LOGIN_PROCESSING);
}
// 查询手机号码是否注册过
MemberBasicInfo memberBasicInfo = memberBasicInfoService.selectInfoByMobileNumber(phoneNumber, firstLevelMerchantId);
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(firstLevelMerchantId));
if (AdapayPayChannelEnum.WX_LITE.getValue().equals(dto.getRequestSource()) && StringUtils.isNotBlank(openId)) {
memberBasicInfo.setOpenId(openId);
}
if (AdapayPayChannelEnum.ALIPAY_LITE.getValue().equals(dto.getRequestSource()) && StringUtils.isNotBlank(buyerId)) {
memberBasicInfo.setBuyerId(buyerId);
}
MemberTransactionDTO memberTransactionDTO = new MemberTransactionDTO();
memberTransactionDTO.setMemberBasicInfo(memberBasicInfo);
// 首次新建会员,同时新建会员钱包
if (MerchantUtils.isXiXiaoMerchant(firstLevelMerchantId)) {
MemberWalletInfo memberWalletInfo = MemberWalletInfo.builder()
.memberId(memberId)
.merchantId(MerchantUtils.XIXIAO_MERCHANT_ID)
.walletCode(memberBasicInfoService.generateWalletCode())
.build();
memberTransactionDTO.setMemberWalletInfo(memberWalletInfo);
}
try {
// 插入会员数据
transactionService.createMember(memberTransactionDTO);
} catch (DuplicateKeyException e) {
// 捕获数据库唯一索引冲突异常(极端并发情况下的兜底机制)
// 说明该手机号在该运营商下已经被其他并发请求注册了,重新查询获取已存在的会员信息
log.warn("会员注册时检测到唯一索引冲突,重新查询已存在的会员, phoneNumber:{}, merchantId:{}", phoneNumber, firstLevelMerchantId);
memberBasicInfo = memberBasicInfoService.selectInfoByMobileNumber(phoneNumber, firstLevelMerchantId);
if (memberBasicInfo == null) {
// 理论上不应该走到这里,如果走到这里说明数据被删除了,抛出异常
log.error("唯一索引冲突后重新查询会员信息为空, phoneNumber:{}, merchantId:", phoneNumber, firstLevelMerchantId);
throw new BusinessException(ReturnCodeEnum.CODE_MEMBER_REGISTER_AND_LOGIN_ERROR);
}
}
} else {
boolean updateFlag = false;
if (AdapayPayChannelEnum.WX_LITE.getValue().equals(dto.getRequestSource()) && !StringUtils.equals(memberBasicInfo.getOpenId(), openId)) {
// openId变化就更新
memberBasicInfo.setOpenId(openId);
updateFlag = true;
}
if (AdapayPayChannelEnum.ALIPAY_LITE.getValue().equals(dto.getRequestSource()) && !StringUtils.equals(memberBasicInfo.getBuyerId(), buyerId)) {
memberBasicInfo.setBuyerId(buyerId);
updateFlag = true;
}
if (updateFlag) {
memberBasicInfoService.updateMemberBasicInfo(memberBasicInfo);
}
}
// 服务器生成token返给前端
String memberToken = JWTUtils.createMemberToken(memberBasicInfo.getMemberId(), memberBasicInfo.getNickName());
// log.info("memToken:{}", memberToken);
return memberToken;
} finally {
// 释放锁
if (isLock) {
try {
Object lockValue = redisCache.getCacheObject(lockKey);
if (lockValue != null && requestId.equals(lockValue.toString())) {
redisCache.unLock(lockKey);
}
} catch (Exception e) {
log.error("释放注册锁失败, phoneNumber:{}, merchantId:{}, error:{}", phoneNumber, firstLevelMerchantId, e.getMessage());
}
}
}
}
/**
* 公共登录注册方法 V2
*
* <p>该方法与 {@link #memberRegisterAndLogin(MemberRegisterAndLoginDTO)} 保持相同业务逻辑,
* 但将流程拆成更清晰的几个步骤:校验请求、获取锁、查找或创建会员、同步第三方身份、生成 token。</p>
*
* @param dto 登录/注册入参
* @return 服务端生成的会员 token
*/
protected String memberRegisterAndLoginV2(MemberRegisterAndLoginDTO dto) {
String phoneNumber = dto.getMobileNumber();
String firstLevelMerchantId = dto.getFirstLevelMerchantId();
log.info("公共登录注册方法V2, phoneNumber:{}, firstLevelMerchantId:{}, openId:{}", phoneNumber, firstLevelMerchantId, dto.getOpenId());
// 1. 先做参数校验,尽早拦截无效请求。
validateMemberRegisterAndLoginV2Request(dto);
// 2. 使用“手机号 + 一级运营商”作为锁粒度,串行化同一会员的注册/登录流程。
String lockKey = buildMemberRegisterAndLoginLockKey(phoneNumber, firstLevelMerchantId);
String requestId = IdUtils.fastUUID();
Boolean isLock = false;
try {
// 3. 获取锁,防止并发下重复注册或重复创建钱包。
isLock = acquireMemberRegisterAndLoginLock(lockKey, requestId, phoneNumber, firstLevelMerchantId);
// 4. 会员不存在就静默注册,已存在则按请求来源同步 openId / buyerId。
MemberBasicInfo memberBasicInfo = findOrCreateMemberForRegisterAndLoginV2(dto);
// 5. 最终统一生成会员 token 返回前端。
return JWTUtils.createMemberToken(memberBasicInfo.getMemberId(), memberBasicInfo.getNickName());
} finally {
releaseMemberRegisterAndLoginLock(lockKey, requestId, phoneNumber, firstLevelMerchantId, isLock);
}
}
/**
* 校验 V2 登录/注册请求中的关键参数。
*
* @param dto 登录/注册入参
*/
private void validateMemberRegisterAndLoginV2Request(MemberRegisterAndLoginDTO dto) {
if (StringUtils.isBlank(dto.getMobileNumber())) {
throw new BusinessException(ReturnCodeEnum.CODE_GET_MOBILE_NUMBER_BY_CODE_ERROR);
}
if (StringUtils.isBlank(dto.getFirstLevelMerchantId())) {
throw new BusinessException(ReturnCodeEnum.CODE_GET_MERCHANT_ID_BY_APP_ID_ERROR);
}
if (isWechatLiteRequest(dto) && StringUtils.isBlank(dto.getOpenId())) {
throw new BusinessException(ReturnCodeEnum.CODE_OPEN_ID_IS_NULL_ERROR);
}
}
/**
* 生成登录/注册流程使用的分布式锁 key。
*
* @param phoneNumber 手机号
* @param firstLevelMerchantId 一级运营商 ID
* @return 分布式锁 key
*/
private String buildMemberRegisterAndLoginLockKey(String phoneNumber, String firstLevelMerchantId) {
return CacheConstants.USER_APP_REGISTER + phoneNumber + ":" + firstLevelMerchantId;
}
/**
* 获取登录/注册流程的分布式锁,避免同一会员并发注册。
*
* @param lockKey 锁 key
* @param requestId 当前请求唯一标识
* @param phoneNumber 手机号
* @param firstLevelMerchantId 一级运营商 ID
* @return 是否成功获取锁
*/
private boolean acquireMemberRegisterAndLoginLock(String lockKey, String requestId, String phoneNumber, String firstLevelMerchantId) {
boolean isLock = redisCache.lock(lockKey, requestId, 60);
if (!isLock) {
log.warn("获取注册锁失败,可能有并发请求正在处理, phoneNumber:{}, merchantId:{}", phoneNumber, firstLevelMerchantId);
throw new BusinessException(ReturnCodeEnum.CODE_MEMBER_REGISTER_AND_LOGIN_PROCESSING);
}
return true;
}
/**
* 释放登录/注册流程的分布式锁。
*
* @param lockKey 锁 key
* @param requestId 当前请求唯一标识
* @param phoneNumber 手机号
* @param firstLevelMerchantId 一级运营商 ID
* @param isLock 是否持有锁
*/
private void releaseMemberRegisterAndLoginLock(String lockKey, String requestId, String phoneNumber, String firstLevelMerchantId, Boolean isLock) {
if (!Boolean.TRUE.equals(isLock)) {
return;
}
try {
Object lockValue = redisCache.getCacheObject(lockKey);
if (lockValue != null && requestId.equals(lockValue.toString())) {
redisCache.unLock(lockKey);
}
} catch (Exception e) {
log.error("释放注册锁失败, phoneNumber:{}, merchantId:{}, error:{}", phoneNumber, firstLevelMerchantId, e.getMessage());
}
}
/**
* 根据手机号和运营商查询会员,不存在则静默注册,存在则同步第三方身份信息。
*
* @param dto 登录/注册入参
* @return 已存在或新创建的会员信息
*/
private MemberBasicInfo findOrCreateMemberForRegisterAndLoginV2(MemberRegisterAndLoginDTO dto) {
MemberBasicInfo memberBasicInfo = memberBasicInfoService.selectInfoByMobileNumber(dto.getMobileNumber(), dto.getFirstLevelMerchantId());
if (Objects.isNull(memberBasicInfo)) {
return registerMemberForRegisterAndLoginV2(dto);
}
syncMemberThirdPartyIdentityForRegisterAndLoginV2(memberBasicInfo, dto);
return memberBasicInfo;
}
/**
* 执行静默注册流程,并在唯一索引冲突时回查已创建的会员。
*
* @param dto 登录/注册入参
* @return 注册完成后的会员信息
*/
private MemberBasicInfo registerMemberForRegisterAndLoginV2(MemberRegisterAndLoginDTO dto) {
for (int attempt = 1; attempt <= MAX_MEMBER_REGISTER_RETRY_TIMES; attempt++) {
MemberBasicInfo memberBasicInfo = buildNewMemberForRegisterAndLoginV2(dto);
MemberTransactionDTO memberTransactionDTO = buildMemberTransactionForRegisterAndLoginV2(memberBasicInfo, dto.getFirstLevelMerchantId());
try {
transactionService.createMember(memberTransactionDTO);
return memberBasicInfo;
} catch (DuplicateKeyException e) {
MemberBasicInfo existedMember = reloadMemberAfterDuplicateKeyForRegisterAndLoginV2(dto, memberBasicInfo.getMemberId(), attempt);
if (existedMember != null) {
return existedMember;
}
}
}
log.error("会员注册重试多次后仍失败, phoneNumber:{}, merchantId:{}", dto.getMobileNumber(), dto.getFirstLevelMerchantId());
throw new BusinessException(ReturnCodeEnum.CODE_MEMBER_REGISTER_AND_LOGIN_ERROR);
}
/**
* 构造一个新的会员基础信息对象。
*
* @param dto 登录/注册入参
* @return 待入库的会员基础信息
*/
private MemberBasicInfo buildNewMemberForRegisterAndLoginV2(MemberRegisterAndLoginDTO dto) {
String memberId = generateNewMemberId();
MemberBasicInfo memberBasicInfo = new MemberBasicInfo();
memberBasicInfo.setStatus(Constants.ONE);
memberBasicInfo.setMemberId(memberId);
memberBasicInfo.setNickName("会员" + memberId);
memberBasicInfo.setMobileNumber(dto.getMobileNumber());
memberBasicInfo.setMerchantId(Long.valueOf(dto.getFirstLevelMerchantId()));
fillMemberThirdPartyIdentityForRegisterAndLoginV2(memberBasicInfo, dto);
return memberBasicInfo;
}
/**
* 组装会员注册事务对象,必要时附带创建钱包信息。
*
* @param memberBasicInfo 会员基础信息
* @param firstLevelMerchantId 一级运营商 ID
* @return 注册事务对象
*/
private MemberTransactionDTO buildMemberTransactionForRegisterAndLoginV2(MemberBasicInfo memberBasicInfo, String firstLevelMerchantId) {
MemberTransactionDTO memberTransactionDTO = new MemberTransactionDTO();
memberTransactionDTO.setMemberBasicInfo(memberBasicInfo);
if (MerchantUtils.isXiXiaoMerchant(firstLevelMerchantId)) {
MemberWalletInfo memberWalletInfo = MemberWalletInfo.builder()
.memberId(memberBasicInfo.getMemberId())
.merchantId(MerchantUtils.XIXIAO_MERCHANT_ID)
.walletCode(memberBasicInfoService.generateWalletCode())
.build();
memberTransactionDTO.setMemberWalletInfo(memberWalletInfo);
}
return memberTransactionDTO;
}
/**
* 在注册发生唯一索引冲突时,回查已经被并发请求创建好的会员。
*
* @param dto 登录/注册入参
* @return 已存在的会员信息
*/
private MemberBasicInfo reloadMemberAfterDuplicateKeyForRegisterAndLoginV2(MemberRegisterAndLoginDTO dto, String memberId, int attempt) {
log.warn("会员注册时检测到唯一索引冲突,重新查询已存在的会员, phoneNumber:{}, merchantId:{}, candidateMemberId:{}, attempt:{}",
dto.getMobileNumber(), dto.getFirstLevelMerchantId(), memberId, attempt);
MemberBasicInfo memberBasicInfo = memberBasicInfoService.selectInfoByMobileNumber(dto.getMobileNumber(), dto.getFirstLevelMerchantId());
if (memberBasicInfo == null) {
log.warn("唯一索引冲突后未查询到手机号对应会员准备重新生成memberId重试, phoneNumber:{}, merchantId:{}, candidateMemberId:{}, attempt:{}",
dto.getMobileNumber(), dto.getFirstLevelMerchantId(), memberId, attempt);
return null;
}
return memberBasicInfo;
}
/**
* 同步已有会员的第三方身份标识。
*
* @param memberBasicInfo 已存在会员
* @param dto 登录/注册入参
*/
private void syncMemberThirdPartyIdentityForRegisterAndLoginV2(MemberBasicInfo memberBasicInfo, MemberRegisterAndLoginDTO dto) {
boolean needUpdate = false;
if (isWechatLiteRequest(dto) && !StringUtils.equals(memberBasicInfo.getOpenId(), dto.getOpenId())) {
memberBasicInfo.setOpenId(dto.getOpenId());
needUpdate = true;
}
if (isAlipayLiteRequest(dto) && !StringUtils.equals(memberBasicInfo.getBuyerId(), dto.getBuyerId())) {
memberBasicInfo.setBuyerId(dto.getBuyerId());
needUpdate = true;
}
if (needUpdate) {
memberBasicInfoService.updateMemberBasicInfo(memberBasicInfo);
}
}
/**
* 在新建会员时,根据请求来源写入第三方身份标识。
*
* @param memberBasicInfo 待入库会员
* @param dto 登录/注册入参
*/
private void fillMemberThirdPartyIdentityForRegisterAndLoginV2(MemberBasicInfo memberBasicInfo, MemberRegisterAndLoginDTO dto) {
if (isWechatLiteRequest(dto) && StringUtils.isNotBlank(dto.getOpenId())) {
memberBasicInfo.setOpenId(dto.getOpenId());
}
if (isAlipayLiteRequest(dto) && StringUtils.isNotBlank(dto.getBuyerId())) {
memberBasicInfo.setBuyerId(dto.getBuyerId());
}
}
/**
* 判断当前请求是否来自微信小程序。
*
* @param dto 登录/注册入参
* @return 是否为微信小程序请求
*/
private boolean isWechatLiteRequest(MemberRegisterAndLoginDTO dto) {
return AdapayPayChannelEnum.WX_LITE.getValue().equals(dto.getRequestSource());
}
/**
* 判断当前请求是否来自支付宝小程序。
*
* @param dto 登录/注册入参
* @return 是否为支付宝小程序请求
*/
private boolean isAlipayLiteRequest(MemberRegisterAndLoginDTO dto) {
return AdapayPayChannelEnum.ALIPAY_LITE.getValue().equals(dto.getRequestSource());
}
private String generateNewMemberId() {
for (int attempt = 1; attempt <= MAX_MEMBER_ID_GENERATE_RETRY_TIMES; attempt++) {
String memberId = IdUtils.getMemberId();
if (!memberBasicInfoService.existsByMemberId(memberId)) {
return memberId;
}
log.warn("生成memberId命中已存在记录准备重试, memberId:{}, attempt:{}", memberId, attempt);
}
throw new BusinessException(ReturnCodeEnum.CODE_MEMBER_REGISTER_AND_LOGIN_ERROR);
}
/**
* 微信一键登录
* @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);
}
// 通过code获取openId
String openId = "";
try {
openId = wxAppletRemoteService.getOpenIdByCode(dto.getOpenIdCode());
} catch (Exception e) {
log.error("getOpenIdByCode发生异常", e);
}
// 根据appid查询merchantId
String firstLevelMerchantId = pileMerchantInfoService.getFirstLevelMerchantIdByWxAppId(dto.getAppId());
// 通过手机号获取openid
MemberBasicInfo memberBasicInfo = memberBasicInfoService.selectInfoByMobileNumber(mobileNumber, firstLevelMerchantId);
if (memberBasicInfo != null && StringUtils.isBlank(openId)) {
openId = memberBasicInfo.getOpenId();
}
// 查询手机号码是否注册过
MemberRegisterAndLoginDTO loginDTO = MemberRegisterAndLoginDTO.builder()
.openId(openId)
.firstLevelMerchantId(firstLevelMerchantId)
.mobileNumber(mobileNumber)
.requestSource(dto.getRequestSource())
.build();
return memberRegisterAndLoginV2(loginDTO); // 微信小程序一键登录
}
/**
* 支付宝 通过密文解密 获取手机号码
*/
// private String decryptMobileNumberCiphertext(String mobileNumberCiphertext) throws Exception {
// String decrypt = Factory.Util.AES().decrypt(mobileNumberCiphertext);
// String mobileNumber = JSON.parseObject(decrypt).getString("mobile");
// return mobileNumber;
// }
/**
* 支付宝 通过密文解密 获取手机号码
*/
private void decryptMobileNumberCiphertext(AlipayLoginDTO dto) throws Exception {
String decrypt = Factory.Util.AES().decrypt(dto.getMobileNumberCiphertext());
String mobileNumber = JSON.parseObject(decrypt).getString("mobile");
dto.setMobileNumber(mobileNumber);
}
public String alipayLogin(AlipayLoginDTO dto) throws Exception {
// 获取AccessToken
getAccessToken(dto);
// 解密手机号
decryptMobileNumberCiphertext(dto);
// 获取buyer_id
// AlipayUserInfoShareRequest request = new AlipayUserInfoShareRequest();
// AlipayUserInfoShareResponse response = alipayClient.execute(request, dto.getAccessToken());
// if(response.isSuccess()){
// log.info("调用成功:" + JSON.toJSONString(response));
// } else {
// log.info("调用失败:" + JSON.toJSONString(response));
// }
// String userId = response.getOpenId();
// String mobile = response.getMobile();
// 根据appid查询merchantId
String firstLevelMerchantId = pileMerchantInfoService.getFirstLevelMerchantIdByAliAppId(dto.getAppId());
log.info("支付宝登录,手机号:{}, openId:{}", dto.getMobileNumber(), dto.getOpenId());
// 查询手机号码是否注册过
MemberRegisterAndLoginDTO loginDTO = MemberRegisterAndLoginDTO.builder()
.requestSource(dto.getRequestSource())
.firstLevelMerchantId(firstLevelMerchantId)
.mobileNumber(dto.getMobileNumber())
.buyerId(dto.getUserId())
.build();
return memberRegisterAndLoginV2(loginDTO); // 支付宝小程序一键登录
}
/**
* 获取 auth_code用户授权码后应尽快调用 alipay.system.oauth.token换取授权访问令牌接口换取 access_token访问令牌
*/
private void getAccessToken(AlipayLoginDTO dto) throws AlipayApiException {
if (StringUtils.isBlank(dto.getAuthCode())) {
log.info("换取授权访问令牌接口, authCode为空");
}
AlipaySystemOauthTokenRequest request = new AlipaySystemOauthTokenRequest();
// 设置授权码
request.setCode(dto.getAuthCode());
// 设置授权方式
request.setGrantType("authorization_code");
AlipaySystemOauthTokenResponse response = alipayClient.execute(request);
if (!response.isSuccess()) {
throw new BusinessException(ReturnCodeEnum.CODE_ALIPAY_ACCESS_TOKEN_ERROR);
}
log.info("支付宝getAccessToken:{}", JSON.toJSONString(response));
dto.setAccessToken(response.getAccessToken());
dto.setOpenId(response.getOpenId());
dto.setUserId(response.getUserId());
}
/**
* 获取openId
* @param code
* @return
*/
// public String getOpenIdByCode(String code) {
// return wxAppletRemoteService.getOpenIdByCode(code);
// }
/**
* 处理用户信息
*
* @param memberId
* @param dto 用户个人信息
*/
public void handleUserInfo(String memberId, MemberRegisterDTO dto) {
// 通过用户手机号查询数据库,如果数据库中存在,则更新
// MemberBasicInfo memberBasicInfo = memberBasicInfoService.selectInfoByMobileNumber(dto.getMobileNumber());
MemberBasicInfo memberBasicInfo = memberBasicInfoService.selectInfoByMemberId(memberId);
if (Objects.nonNull(memberBasicInfo)) {
if (StringUtils.isNotBlank(dto.getAvatarUrl())) {
memberBasicInfo.setAvatarUrl(dto.getAvatarUrl());
}
if (StringUtils.isNotBlank(dto.getMobileNumber())) {
memberBasicInfo.setMobileNumber(dto.getMobileNumber());
}
if (StringUtils.isNotBlank(dto.getNickName())) {
memberBasicInfo.setNickName(dto.getNickName());
}
memberBasicInfoService.updateMemberBasicInfo(memberBasicInfo);
}
}
/**
* 通过memberToken获取用户账户信息
*
* @param memberId
* @return
*/
public MemberVO getMemberInfoByMemberId(String memberId) {
MemberVO memberVO = memberBasicInfoService.queryMemberInfoByMemberId(memberId);
return memberVO;
}
public MemberVO getMemberInfoByMemberId(String memberId, String merchantId) {
MemberVO memberVO = memberBasicInfoService.queryMemberInfoByMemberId(memberId, merchantId);
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<MemberWalletLogVO> list = memberBasicInfoService.getMemberBalanceChanges(memberId, type);
PageInfo<MemberWalletLogVO> 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;
}
public MemberWalletInfoVO getMemberWalletInfo(UniAppQueryMemberBalanceDTO dto) throws ParseException {
log.info("查询用户余额信息 service方法 start");
MemberWalletInfoVO vo = new MemberWalletInfoVO();
vo.setMemberId(dto.getMemberId());
// 查询会员钱包信息表,获取 本金余额
MemberWalletVO memberWalletVO = memberWalletInfoService.selectMemberWalletInfo(dto.getWalletCode());
if (memberWalletVO == null) {
// 用户未注册小程序
throw new BusinessException(ReturnCodeEnum.CODE_AUTHENTICATION_ERROR);
}
// 本金 sql处理为空返回0
vo.setPrincipalBalance(memberWalletVO.getPrincipalBalance());
// 赠金 sql处理为空返回0
vo.setGiftBalance(memberWalletVO.getGiftBalance());
// 当前余额
vo.setCurrentBalance(vo.getPrincipalBalance().add(vo.getGiftBalance()));
// 累计充值本金
vo.setAccumulatedRechargePrincipal(memberWalletVO.getAccumulatedRechargePrincipal());
// 累计赠送金额
vo.setAccumulatedRechargeGift(memberWalletVO.getAccumulatedRechargeGift());
// 累计充值金额
vo.setAccumulatedRechargeAmount(memberWalletVO.getTotalRechargeAmount());
// 累计消费金额
vo.setAccumulatedConsumptionAmount(memberWalletVO.getAccumulatedConsumptionAmount());
// 根据日期查询会员钱包变动明细 分页
// 获取分页信息
long pageNum = dto.getPageNum() == 0 ? 1L : dto.getPageNum();
long pageSize = dto.getPageSize() == 0 ? 10L : dto.getPageSize();
String tradeDate = dto.getTradeDate() + " 00:00:00";;
String endDate = dto.getEndDate() + " 23:59:59";
// 获取年、月
// String[] split = StringUtils.split(tradeDate, "-");
// int year = Integer.parseInt(split[0]);
// int month = Integer.parseInt(split[1]);
// 根据年月获取当月第一天和最后一天
// tradeDate = DateUtils.getFirstDay(year, month, DateUtils.YYYY_MM_DD);
// String lastDay = DateUtils.getLastDay(year, month, DateUtils.YYYY_MM_DD);
// sql语句查询日期需要多加一天
// Date date = DateUtils.addDays(DateUtils.parseDate(lastDay, DateUtils.YYYY_MM_DD), 1);
// lastDay = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, date);
dto.setTradeDate(tradeDate);
dto.setEndDate(endDate);
// PageHelper.startPage(pageNum, pageSize);
// List<MemberWalletLogVO> list = memberBasicInfoService.getMemberWalletDetail(dto);
List<MemberWalletLogVO> list = memberBasicInfoService.getMemberWalletDetailV2(dto);
// 总支出
BigDecimal totalConsumption = list.stream()
.map(MemberWalletLogVO::getOrderAmount)
.filter(Objects::nonNull)
.reduce(BigDecimal.ZERO, BigDecimal::add);
vo.setTotalConsumption(totalConsumption);
// 总充值
BigDecimal totalRechargeAmount = list.stream()
.filter(x -> StringUtils.equals(x.getType(), "1"))
.filter(x -> StringUtils.equals(x.getSubType(), "10") || StringUtils.equals(x.getSubType(), "11"))
.map(MemberWalletLogVO::getAmount)
.reduce(BigDecimal.ZERO, BigDecimal::add);
vo.setTotalRechargeAmount(totalRechargeAmount);
// PageInfo<MemberWalletLogVO> pageInfo = new PageInfo<>(list);
// 获取 type 和 subType 的对应信息
for (MemberWalletLogVO walletLogVO : list) {
// 将负数转为正数
walletLogVO.setAmount(BigDecimal.valueOf(Math.abs(walletLogVO.getAmount().doubleValue())).setScale(2, BigDecimal.ROUND_HALF_UP));
String subType = walletLogVO.getSubType();
String subTypeValue = BalanceChangesEnum.getValueByCode(subType);
if (StringUtils.isNotBlank(subTypeValue)) {
walletLogVO.setSubType(subTypeValue);
}
// walletLogVO.setTotalAccountAmount(walletLogVO.getPrincipalBalance().add(walletLogVO.getGiftBalance()));
}
// log.info("查询用户余额信息 service方法 开始处理分页----");
List<MemberWalletLogVO> collect = list.stream()
.skip((pageNum - 1) * pageSize)
.limit(pageSize)
.collect(Collectors.toList());
int total = list.size();
int pages = PageUtil.totalPage(total, dto.getPageSize());
// 返回结果集
PageResponse pageResponse = PageResponse.builder()
.pageNum(Integer.parseInt(String.valueOf(pageNum)))
.pageSize(Integer.parseInt(String.valueOf(pageSize)))
.list(collect)
.pages(pages)
.total(total)
.build();
vo.setPageResponse(pageResponse);
// log.info("查询用户余额信息 service方法 end");
return vo;
}
/**
* 获取会员钱包明细
* @return
*/
// public PageResponse getMemberWalletLog (UniAppQueryMemberBalanceDTO dto) throws ParseException {
// // 获取分页信息以及memberId
// int pageNum = dto.getPageNum() == 0 ? 1 : dto.getPageNum();
// int pageSize = dto.getPageSize() == 0 ? 10 : dto.getPageSize();
// String tradeDate = dto.getTradeDate();
// // 获取年、月
// String[] split = StringUtils.split(tradeDate, "-");
// int year = Integer.parseInt(split[0]);
// int month = Integer.parseInt(split[1]);
// // 根据年月获取当月第一天和最后一天
// tradeDate = DateUtils.getFirstDay(year, month, DateUtils.YYYY_MM_DD);
// String lastDay = DateUtils.getLastDay(year, month, DateUtils.YYYY_MM_DD);
// // sql语句查询日期需要多加一天
// Date date = DateUtils.addDays(DateUtils.parseDate(lastDay, DateUtils.YYYY_MM_DD), 1);
// lastDay = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, date);
// dto.setTradeDate(tradeDate);
// dto.setEndDate(lastDay);
// // 根据日期查询会员钱包变动明细
// // 分页
// PageHelper.startPage(pageNum, pageSize);
// List<MemberWalletLogVO> list = memberBasicInfoService.getMemberWalletDetail(dto);
// PageInfo<MemberWalletLogVO> pageInfo = new PageInfo<>(list);
// // 获取 type 和 subType 的对应信息
// for (MemberWalletLogVO walletLogVO : pageInfo.getList()) {
// // 将负数转为正数
// walletLogVO.setAmount(BigDecimal.valueOf(Math.abs(walletLogVO.getAmount().doubleValue())).setScale(2, BigDecimal.ROUND_HALF_UP));
// 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){
// 校验短信验证码(2023.8.24 不做校验)
// MemberRegisterAndLoginDTO registerAndLoginDTO = MemberRegisterAndLoginDTO.builder()
// .mobileNumber(dto.getPhoneNumber())
// .verificationCode(dto.getVerificationCode())
// .build();
// checkVerificationCode(registerAndLoginDTO);
// 判断当前车牌号是否已经绑定 (2023.8.24 不做校验)
MemberPlateNumberRelation relation = new MemberPlateNumberRelation();
relation.setMemberId(dto.getMemberId());
relation.setLicensePlateNumber(dto.getCarNo());
// 判断当前车牌号是否被绑定
// if (UserConstants.NOT_UNIQUE.equals(memberPlateNumberRelationService.checkPlateNumberUnique(dto.getCarNo()))) {
// // 不为空说明该用户绑定过此车牌号
// throw new BusinessException(ReturnCodeEnum.CODE_THIS_CARNO_HAS_BEEN_BINDING);
// }
// 校验该车牌号是否为新能源车牌
relation.setPhoneNumber(dto.getPhoneNumber());
if (StringUtils.isNotBlank(dto.getVinCode())) {
// 判断当前vin是否被绑定
if (UserConstants.NOT_UNIQUE.equals(memberPlateNumberRelationService.checkVinCodeUnique(dto.getVinCode()))) {
throw new BusinessException(ReturnCodeEnum.CODE_THIS_VIN_HAS_BEEN_BINDING);
}
relation.setVinCode(dto.getVinCode().toUpperCase(Locale.ROOT).trim());
relation.setVinStatus(Constants.ONE); // 1-正常使用
}
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<InvoiceTitleVO> queryMemberInvoiceTitles(String memberId) {
List<InvoiceTitleVO> resultList = Lists.newArrayList();
List<MemberInvoiceTitle> 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<String, Object> rechargeBalance(WeixinPayDTO dto) throws Exception {
// PaymentScenarioDTO paymentScenarioDTO = new PaymentScenarioDTO();
// paymentScenarioDTO.setType(ScenarioEnum.BALANCE.getValue());
// paymentScenarioDTO.setMemberId(dto.getMemberId());
// dto.setAttach(JSON.toJSONString(paymentScenarioDTO));
// dto.setDescription("会员充值余额");
// return orderService.weixinPayV3(dto);
// }
/**
* 使用汇付支付充值余额
* @param dto
* @return
*/
public Map<String, Object> rechargeBalanceWithAdapay(WeixinPayDTO dto) {
// 获取支付配置
AbstractAdapayConfig config = AdapayConfigFactory.getConfig(dto.getWechatAppId());
if (config == null) {
throw new BusinessException(ReturnCodeEnum.CODE_ADAPAY_CONFIG_IS_NULL_ERROR);
}
log.info("使用汇付支付充值余额 支付配置参数:{}", JSON.toJSONString(config));
// 查询延时支付模式,由一级运营商配置决定
String delayMode = pileMerchantInfoService.getDelayModeByWechatAppId(dto.getWechatAppId());
String payMode = MerchantDelayModeEnum.getAdapayPayMode(delayMode);
// 封装对象
// String payMode = Constants.ADAPAY_PAY_MODE_DELAY; // 汇付延时分账
CreateAdaPaymentParam createAdaPaymentParam = new CreateAdaPaymentParam();
createAdaPaymentParam.setOrder_no(SnowflakeIdWorker.getSnowflakeId());
createAdaPaymentParam.setPay_amt(AdapayUtil.formatAmount(dto.getAmount()));
// createAdaPaymentParam.setApp_id(ADAPAY_APP_ID); // 移动到配置文件中
createAdaPaymentParam.setApp_id(config.getAdapayAppId()); // 移动到配置文件中
createAdaPaymentParam.setPay_channel("wx_lite"); // todo 如果以后有支付宝等别的渠道,这里需要做修改,判断是什么渠道的请求
createAdaPaymentParam.setGoods_title("充值余额");
createAdaPaymentParam.setGoods_desc("会员充值余额");
createAdaPaymentParam.setExpend(JSON.toJSONString( ImmutableMap.of("open_id", dto.getOpenId())));
//异步通知地址url为http/https路径服务器POST回调URL 上请勿附带参数
createAdaPaymentParam.setNotify_url(ADAPAY_CALLBACK_URL);
Map<String, String> map = Maps.newHashMap();
map.put("type", ScenarioEnum.BALANCE.getValue());
map.put("payMode", payMode);
map.put("memberId", dto.getMemberId());
createAdaPaymentParam.setDescription(JSON.toJSONString(map));
// 延时分账
if (StringUtils.isNotBlank(payMode)) {
createAdaPaymentParam.setPay_mode(payMode);
}
try {
log.info("创建汇付支付参数:{}", JSON.toJSONString(createAdaPaymentParam));
Map<String, Object> response = Payment.create(BeanMap.create(createAdaPaymentParam), config.getWechatAppId());
log.info("创建汇付支付参数反参:{}", JSON.toJSONString(response));
if (response != null && !response.isEmpty()) {
JSONObject jsonObject = JSONObject.parseObject(response.get("expend").toString());
JSONObject pay_info = jsonObject.getJSONObject("pay_info");
return JSONObject.parseObject(pay_info.toJSONString(), new TypeReference<Map<String, Object>>() {});
}
} catch (BaseAdaPayException e) {
log.error("汇付-获取支付对象发生异常", e);
}
return null;
}
/**
* 充值订单金额
*/
// public void rechargeOrderAmount(RechargeOrderAmountDTO dto) throws ParseException {
// // 根据memberId查询出当前用户正在充电的 vin启动订单 或 卡启动订单
// UniAppQueryOrderDTO orderDTO = new UniAppQueryOrderDTO();
// orderDTO.setOrderStatus("4"); // 4-正在充电中
// PageResponse pageResponse = orderService.getListByMemberIdAndOrderStatus(dto.getMemberId(), orderDTO);
// if (pageResponse == null) {
// return;
// }
// List<OrderVO> list = (List<OrderVO>) pageResponse.getList();
// List<OrderVO> chargingList = list.stream()
// .filter(orderVO -> orderVO.getOrderStatus().equals(OrderStatusEnum.IN_THE_CHARGING.getValue()))
// .collect(Collectors.toList());
// for (OrderVO orderVO : chargingList) {
// if (StringUtils.equals(orderVO.getStartMode(), StartModeEnum.AUTH_CARD.getValue())
// || StringUtils.equals(orderVO.getStartMode(), StartModeEnum.OFFLINE_CARD.getValue())
// || StringUtils.equals(orderVO.getStartMode(), StartModeEnum.VIN_CODE.getValue())) {
// // 将充值后的余额计算出来
// BigDecimal rechargeAmount = new BigDecimal(dto.getRechargeAmount());
// BigDecimal payAmount = orderVO.getPayAmount().add(rechargeAmount);
// orderVO.setPayAmount(payAmount);
// // 发送0x41指令更新账户余额
// RemoteAccountBalanceUpdateDTO remoteDTO = new RemoteAccountBalanceUpdateDTO();
// remoteDTO.setPileSn(orderVO.getPileSn());
// remoteDTO.setConnectorCode(orderVO.getConnectorCode());
// remoteDTO.setAccountBalance(String.valueOf(orderVO.getPayAmount()));
//
// pileRemoteService.remoteAccountBalanceUpdate(remoteDTO);
//
// // 将支付金额修改数据库
// OrderBasicInfo basicInfo = new OrderBasicInfo();
// basicInfo.setId(Integer.parseInt(orderVO.getId()));
// basicInfo.setPayAmount(payAmount);
//
// orderBasicInfoService.updateOrderBasicInfo(basicInfo);
// }
// }
// }
public List<MemberWalletVO> queryMemberWalletList(String memberId) {
return memberWalletInfoService.selectByMemberWalletList(memberId);
}
}