1:需求 在开发电商的微信小程序中,需要实现花呗支付功能,包括信用额度的申请,支付,还款,查看还款记录,支付记录的功能。
实现步骤:第一步设计数据库表结构
CREATE TABLE `eb_credit_amount` (
`id` varchar(64) NOT NULL COMMENT 'id',
`uid` int unsigned NOT NULL COMMENT '用户ID',
`credit_amount` decimal(10,2) unsigned NOT NULL DEFAULT '0.00' COMMENT '授信额度',
`credit_pay_amount` decimal(10,2) unsigned NOT NULL DEFAULT '0.00' COMMENT '已使用额度',
`credit_repayment_amount` decimal(10,2) DEFAULT NULL COMMENT '已还款额度',
`credit_remain_amount` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '剩余额度',
`contract_type` varchar(8) DEFAULT '0' COMMENT '合同类型',
`contract_code` varchar(255) DEFAULT '1' COMMENT '合同编号',
`settle_term` int DEFAULT NULL COMMENT '结算期限(天)',
`credit_status` int NOT NULL COMMENT '授信状态 0:关闭,1-开启',
`credit_time` datetime DEFAULT NULL COMMENT '授信开启时间',
`contract_start_date` date DEFAULT NULL COMMENT '合同开始时间',
`contract_end_date` date DEFAULT NULL COMMENT '合同结束时间',
`agreement_pic` varchar(255) DEFAULT NULL COMMENT '协议图片',
`audit_status` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '审核状态0:待审核,1审核通过,2:审核拒绝',
`audit_by` varchar(255) DEFAULT NULL COMMENT '审核人',
`audit_remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '审核意见',
`create_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '提交人',
`create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`task_start_time` timestamp NULL DEFAULT NULL COMMENT '任务执行时间',
`status` int DEFAULT NULL COMMENT '启用状态,0:冻结;1:正常',
`cron_expression` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '结算cron表达式',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE KEY `user_id` (`uid`) USING BTREE,
KEY `search_id` (`id`,`uid`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=COMPACT COMMENT='授信用户表';
SET FOREIGN_KEY_CHECKS = 1;
DROP TABLE IF EXISTS `eb_credit_bill`;
CREATE TABLE `eb_credit_bill` (
`id` varchar(64) NOT NULL COMMENT 'id',
`uid` int unsigned DEFAULT NULL COMMENT '用户ID',
`credit_amount` decimal(10,2) unsigned DEFAULT '0.00' COMMENT '授信额度',
`credit_pay_amount` decimal(10,2) unsigned DEFAULT '0.00' COMMENT '已使用额度',
`credit_repayment_amount` decimal(10,2) DEFAULT NULL COMMENT '已还款额度',
`credit_remain_amount` decimal(10,2) DEFAULT '0.00' COMMENT '剩余额度',
`contract_type` varchar(8) DEFAULT '0' COMMENT '合同类型',
`contract_code` varchar(255) DEFAULT '1' COMMENT '合同编号',
`create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`) USING BTREE,
KEY `user_id` (`uid`) USING BTREE,
KEY `search_id` (`id`,`uid`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=COMPACT COMMENT='授信流水表';
SET FOREIGN_KEY_CHECKS = 1;
CREATE TABLE `eb_credit_order_bill` (
`id` varchar(64) NOT NULL COMMENT 'id',
`uid` int unsigned NOT NULL COMMENT '用户ID',
`order_no` varchar(255) NOT NULL COMMENT '订单号',
`pay_price` decimal(10,2) DEFAULT NULL COMMENT '支付金额',
`pay_type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '支付类型',
`pay_time` datetime DEFAULT NULL COMMENT '交易时间',
`credit_repayment_amount` decimal(10,2) DEFAULT NULL COMMENT '还款金额',
`credit_repayment_type` varchar(255) DEFAULT NULL COMMENT '还款方式',
`credit_repayment_time` datetime DEFAULT NULL COMMENT '还款时间',
`credit_repayment_flag` int DEFAULT NULL COMMENT '是否还款',
`out_trade_no` varchar(255) DEFAULT NULL COMMENT '还款订单号',
`year` int DEFAULT NULL COMMENT '年份',
`month` int DEFAULT NULL COMMENT '月份',
`pay_channel` varchar(255) DEFAULT NULL COMMENT '支付渠道',
`create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`credit_repayment_no` varchar(255) DEFAULT NULL COMMENT '还款订单号',
`payid` int DEFAULT NULL COMMENT '是否支付',
`order_type` int DEFAULT NULL COMMENT '交易类型',
`task_start_time` timestamp NULL DEFAULT NULL COMMENT '任务执行开始时间',
`task_end_time` timestamp NULL DEFAULT NULL COMMENT '任务执行结束时间',
`task_status` int DEFAULT NULL COMMENT '任务是否执行:0:未执行,1已执行',
`is_update` int DEFAULT NULL COMMENT '是否修改',
PRIMARY KEY (`id`) USING BTREE,
KEY `user_id` (`uid`) USING BTREE,
KEY `search_id` (`id`,`uid`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=COMPACT COMMENT='授信用户账单表';
SET FOREIGN_KEY_CHECKS = 1;
CREATE TABLE `eb_credit_order_bill_record` (
`id` varchar(64) NOT NULL COMMENT 'id',
`uid` int unsigned NOT NULL COMMENT '用户ID',
`order_no` varchar(255) NOT NULL COMMENT '订单号',
`pay_price` decimal(10,2) NOT NULL COMMENT '支付金额',
`update_user` varchar(255) NOT NULL COMMENT '更新人',
`update_time` datetime NOT NULL COMMENT '更新时间',
`create_time` datetime NOT NULL COMMENT '创建时间',
`create_user` varchar(255) NOT NULL COMMENT '创建人',
`remark` varchar(255) NOT NULL COMMENT '备注',
`bill_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '账单id',
PRIMARY KEY (`id`) USING BTREE,
KEY `user_id` (`uid`) USING BTREE,
KEY `search_id` (`id`,`uid`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=COMPACT COMMENT='授信用户账单表';
SET FOREIGN_KEY_CHECKS = 1;
CREATE TABLE `eb_credit_repay_order` (
`id` varchar(255) NOT NULL COMMENT 'id',
`order_no` varchar(255) NOT NULL COMMENT '订单号',
`out_trade_no` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '商户订单号',
`pay_price` decimal(10,2) DEFAULT NULL COMMENT '支付金额',
`pay_type` varchar(255) DEFAULT NULL COMMENT '支付类型',
`pay_channel` varchar(255) DEFAULT NULL COMMENT '支付渠道',
`pay_time` datetime DEFAULT NULL COMMENT '支付时间',
`is_paid` int DEFAULT NULL COMMENT '是否支付',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
`uid` int DEFAULT NULL COMMENT '用户id',
`year` int DEFAULT NULL COMMENT '还款年份',
`month` int DEFAULT NULL COMMENT '还款月份',
`is_all` int DEFAULT NULL COMMENT '是否全部还款',
PRIMARY KEY (`id`,`order_no`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='授信支付订单表';
SET FOREIGN_KEY_CHECKS = 1;
CREATE TABLE `eb_credit_bill_info` (
`id` varchar(64) NOT NULL COMMENT 'id',
`uid` int unsigned DEFAULT NULL COMMENT '用户ID',
`credit_pay_amount` decimal(10,2) unsigned DEFAULT '0.00' COMMENT '已使用额度',
`credit_remain_amount` decimal(10,2) DEFAULT '0.00' COMMENT '剩余额度',
`create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`credit_type` int NOT NULL COMMENT '消费类型:0:消费:1还款,2:退款;3:额度增加;4:额度减少'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='授信流水详情表';
SET FOREIGN_KEY_CHECKS = 1;
第二步骤:在平台新增额度管理功能,给用户新增额度管理,
package com.zbkj.admin.controller.platform.credit;
import com.zbkj.common.model.admin.SystemAdmin;
import com.zbkj.common.model.credit.CreditAmount;
import com.zbkj.common.model.credit.CreditBillInfo;
import com.zbkj.common.page.CommonPage;
import com.zbkj.common.request.PageParamRequest;
import com.zbkj.common.request.credit.CreditAmountCheckRequest;
import com.zbkj.common.request.credit.CreditAmountCreditStatusRequest;
import com.zbkj.common.request.credit.CreditAmountRequest;
import com.zbkj.common.request.credit.CreditAmountSearchRequest;
import com.zbkj.common.response.credit.CreditAmountResponse;
import com.zbkj.common.response.credit.CreditOrderBillResponse;
import com.zbkj.common.result.CommonResult;
import com.zbkj.common.utils.SecurityUtil;
import com.zbkj.common.vo.LoginUserVo;
import com.zbkj.service.service.UserService;
import com.zbkj.service.service.credit.CreditAmountService;
import com.zbkj.service.service.credit.CreditBillInfoService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.math.BigDecimal;
/**
* 用户授信信息 前端控制器
*/
@Slf4j
@RestController
@RequestMapping("api/admin/platform/credit/amount")
@Api(tags = "用户授信信息") //配合swagger使用
public class CreditAmountController {
@Autowired
private CreditAmountService creditAmountService;
@Autowired
private CreditBillInfoService creditBillInfoService;
/**
* 分页显示用户授信信息
* @param request 搜索条件
* @param pageParamRequest 分页参数
* @author dudianlong
* @since 2024-11-21
*/
@ApiOperation(value = "分页列表") //配合swagger使用
@RequestMapping(value = "/list", method = RequestMethod.GET)
public CommonResult<CommonPage<CreditAmountResponse>> getList(@Validated CreditAmountSearchRequest request, @Validated PageParamRequest pageParamRequest) {
CommonPage<CreditAmountResponse> creditAmountCommonPage = CommonPage.restPage(creditAmountService.getList(request, pageParamRequest));
return CommonResult.success(creditAmountCommonPage);
}
/**
* 新增用户授信信息
* @param creditAmountRequest 新增参数
* @author dudianlong
* @since 2024-11-21
*/
@PreAuthorize("hasAuthority('platform:creditAmount:save')")
@ApiOperation(value = "新增用户授信")
@RequestMapping(value = "/save", method = RequestMethod.POST)
public CommonResult<String> save(@RequestBody @Validated CreditAmountRequest creditAmountRequest) {
SystemAdmin systemAdmin = SecurityUtil.getLoginUserVo().getUser();
creditAmountRequest.setCreateBy(systemAdmin.getRealName());
if(creditAmountService.saveCreditAmount(creditAmountRequest)) {
return CommonResult.success();
} else {
return CommonResult.failed();
}
}
/**
* 删除用户授信信息
* @param id Integer
* @author dudianlong
* @since 2024-11-21
*/
@ApiOperation(value = "删除用户授信")
@RequestMapping(value = "/delete", method = RequestMethod.GET)
public CommonResult<String> delete(@RequestParam(value = "id") Integer id) {
if(creditAmountService.removeById(id)) {
return CommonResult.success();
} else {
return CommonResult.failed();
}
}
/**
* 修改用户授信信息
* @param creditAmountRequest 修改参数
* @author dudianlong
* @since 2024-11-21
*/
@PreAuthorize("hasAuthority('platform:creditAmount:edit')")
@ApiOperation(value = "修改用户授信")
@RequestMapping(value = "/update", method = RequestMethod.POST)
public CommonResult<String> update(@RequestBody @Validated CreditAmountRequest creditAmountRequest) {
if(creditAmountService.updateCreditAmount(creditAmountRequest)){
return CommonResult.success();
} else {
return CommonResult.failed();
}
}
@PreAuthorize("hasAuthority('platform:creditAmount:check')")
@ApiOperation(value = "审核用户授信")
@RequestMapping(value = "/check", method = RequestMethod.POST)
public CommonResult<String> check(@RequestBody @Validated CreditAmountCheckRequest creditAmountCheckRequest) {
SystemAdmin systemAdmin = SecurityUtil.getLoginUserVo().getUser();
creditAmountCheckRequest.setAuditBy(systemAdmin.getRealName());
if(creditAmountService.checkCreditAmount(creditAmountCheckRequest)) {
return CommonResult.success();
} else {
return CommonResult.failed();
}
}
@ApiOperation(value = "开启/关闭账期")
@RequestMapping(value = "/operatorCreditStatus", method = RequestMethod.POST)
public CommonResult<String> operatorCreditStatus(@RequestBody @Validated CreditAmountCreditStatusRequest creditAmountCreditStatusRequest) {
if(creditAmountService.operatorCreditStatus(creditAmountCreditStatusRequest)) {
return CommonResult.success();
} else {
return CommonResult.failed();
}
}
/**
* 查询用户授信信息
* @param id Integer
* @author dudianlong
* @since 2024-11-21
*/
@ApiOperation(value = "详情用户授信")
@RequestMapping(value = "/info", method = RequestMethod.GET)
public CommonResult<CreditAmountResponse> info(@RequestParam(value = "id") String id) {
CreditAmountResponse creditAmountResponse = creditAmountService.getDetail(id);
return CommonResult.success(creditAmountResponse);
}
/**
* 分页显示授信流水
* @param request 搜索条件
* @param pageParamRequest 分页参数
* @author dudianlong
* @since 2024-11-21
*/
@ApiOperation(value = "分页列表") //配合swagger使用
@RequestMapping(value = "/page", method = RequestMethod.GET)
public CommonResult<CommonPage<CreditAmountResponse>> list(@Validated CreditAmountSearchRequest request, @Validated PageParamRequest pageParamRequest) {
CommonPage<CreditAmountResponse> creditBillCommonPage = CommonPage.restPage(creditAmountService.getList(request, pageParamRequest));
return CommonResult.success(creditBillCommonPage);
}
@ApiOperation(value = "列表统计") //配合swagger使用
@RequestMapping(value = "/listStatistics", method = RequestMethod.GET)
public CommonResult<CreditAmountResponse> listStatistics(@Validated CreditAmountSearchRequest request) {
CreditAmountResponse creditBillReponse = creditAmountService.getListStatistics(request);
return CommonResult.success(creditBillReponse);
}
/**
* 查询用户授信流水
* @param uid Integer
* @author dudianlong
* @since 2024-11-21
*/
@ApiOperation(value = "用户授信流水")
@RequestMapping(value = "/getCreditBillInfoList", method = RequestMethod.GET)
public CommonResult<CommonPage<CreditBillInfo>> getCreditBillInfoList(@RequestParam(value = "uid") Integer uid, @Validated PageParamRequest pageParamRequest) {
CreditBillInfo creditBillInfo = new CreditBillInfo();
creditBillInfo.setUid(uid);
CommonPage<CreditBillInfo> page = CommonPage.restPage(creditBillInfoService.getList(creditBillInfo, pageParamRequest));
return CommonResult.success(page);
}
}
package com.zbkj.service.service.credit;
import com.baomidou.mybatisplus.extension.service.IService;
import com.zbkj.common.model.credit.CreditAmount;
import com.zbkj.common.model.order.Order;
import com.zbkj.common.request.PageParamRequest;
import com.zbkj.common.request.credit.CreditAmountCheckRequest;
import com.zbkj.common.request.credit.CreditAmountCreditStatusRequest;
import com.zbkj.common.request.credit.CreditAmountRequest;
import com.zbkj.common.request.credit.CreditAmountSearchRequest;
import com.zbkj.common.response.credit.CreditAmountResponse;
import com.zbkj.common.response.credit.CreditOrderBillResponse;
import java.math.BigDecimal;
import java.util.List;
/**
* @author dudianlong
* @description CreditAmountService 接口
* @date 2024-11-21
*/
public interface CreditAmountService extends IService<CreditAmount> {
List<CreditAmountResponse> getList(CreditAmountSearchRequest request, PageParamRequest pageParamRequest);
CreditAmountResponse getDetail(String id);
boolean saveCreditAmount(CreditAmountRequest creditAmountRequest);
boolean updateCreditAmount(CreditAmountRequest creditAmountRequest);
boolean checkCreditAmount(CreditAmountCheckRequest creditAmountCheckRequest);
boolean operatorCreditStatus(CreditAmountCreditStatusRequest creditAmountCreditStatusRequest);
CreditAmount getByUserId(Integer uid);
Boolean updateNowMoney(Integer uid, BigDecimal payPrice, String operationTypeSubtract);
Boolean updateRemainMoney(Integer uid, BigDecimal payPrice, String operationTypeSubtract);
Boolean updateCreditRepaymentAmounty(Integer uid, BigDecimal payPrice, String operationTypeSubtract);
Boolean updateUserCredit(Order order);
List<CreditAmount> getActiveCreditAmounts();
List<CreditAmountResponse> getPageList(CreditAmountSearchRequest request, PageParamRequest pageParamRequest);
CreditAmountResponse getListStatistics(CreditAmountSearchRequest request);
void updateCronExpression(String id, String cronExpression);
void disableUserCredit(Integer uid);
void updateStatus();
List<CreditAmount> getUserAmountInfo(List<Integer> uidList);
}
package com.zbkj.service.service.credit;
import com.baomidou.mybatisplus.extension.service.IService;
import com.zbkj.common.model.credit.CreditBillInfo;
import com.zbkj.common.model.credit.CreditRepayOrder;
import com.zbkj.common.page.CommonPage;
import com.zbkj.common.request.PageParamRequest;
import java.math.BigDecimal;
import java.util.List;
/**
* @author dudianlong
* @description CreditBillInfoService 接口
* @date 2024-11-22
*/
public interface CreditBillInfoService extends IService<CreditBillInfo> {
List<CreditBillInfo> getList(CreditBillInfo creditBillInfo, PageParamRequest pageParamRequest);
/**
* 还款 新增记录
*/
boolean addRecord(BigDecimal payPrice, Integer uid, Integer type);
}
package com.zbkj.service.service.impl.credit;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.pagehelper.PageHelper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zbkj.common.constants.Constants;
import com.zbkj.common.exception.CrmebException;
import com.zbkj.common.model.credit.CreditAmount;
import com.zbkj.common.model.credit.CreditBillInfo;
import com.zbkj.common.model.credit.CreditOrderBill;
import com.zbkj.common.model.order.Order;
import com.zbkj.common.model.user.User;
import com.zbkj.common.request.PageParamRequest;
import com.zbkj.common.request.credit.CreditAmountCheckRequest;
import com.zbkj.common.request.credit.CreditAmountCreditStatusRequest;
import com.zbkj.common.request.credit.CreditAmountRequest;
import com.zbkj.common.request.credit.CreditAmountSearchRequest;
import com.zbkj.common.response.credit.CreditAmountResponse;
import com.zbkj.common.response.credit.CreditOrderBillResponse;
import com.zbkj.common.result.CommonResultCode;
import com.zbkj.service.dao.credit.CreditAmountDao;
import com.zbkj.service.dao.credit.CreditBillInfoDao;
import com.zbkj.service.service.UserService;
import com.zbkj.service.service.credit.CreditAmountService;
import com.zbkj.service.service.credit.CreditOrderBillService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import cn.hutool.core.util.StrUtil;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Objects;
/**
* @author dudianlong
* @description CreditAmountServiceImpl 接口实现
* @date 2024-11-21
*/
@Slf4j
@Service
public class CreditAmountServiceImpl extends ServiceImpl<CreditAmountDao, CreditAmount> implements CreditAmountService {
@Resource
private CreditAmountDao dao;
@Resource
private UserService userService;
@Resource
private CreditAmountDao creditAmountDao;
@Resource
private CreditOrderBillService creditOrderBillService;
@Resource
private CreditBillInfoDao creditBillInfoDao;
/**
* 列表
* @param request 请求参数
* @param pageParamRequest 分页类参数
* @author dudianlong
* @since 2024-11-21
* @return List<CreditAmount>
*/
@Override
public List<CreditAmountResponse> getList(CreditAmountSearchRequest request, PageParamRequest pageParamRequest) {
if(pageParamRequest != null){
PageHelper.startPage(pageParamRequest.getPage(), pageParamRequest.getLimit());
}
List<CreditAmountResponse> list = creditAmountDao.getList(request);
return list;
}
/**
* 列表
* @param request 请求参数
* @param pageParamRequest 分页类参数
* @author dudianlong
* @since 2024-11-21
* @return List<CreditAmount>
*/
@Override
public List<CreditAmountResponse> getPageList(CreditAmountSearchRequest request, PageParamRequest pageParamRequest) {
if(pageParamRequest != null){
PageHelper.startPage(pageParamRequest.getPage(), pageParamRequest.getLimit());
}
List<CreditAmountResponse> list = creditAmountDao.getPageList(request);
return list;
}
/**
* 列表
* @param request 请求参数
* @author dudianlong
* @since 2024-11-21
* @return List<CreditAmount>
*/
@Override
public CreditAmountResponse getListStatistics(CreditAmountSearchRequest request) {
CreditAmountResponse res = dao.getListStatistics(request);
return res;
}
/**
* 禁用用户授信功能
* @param uid 用户ID
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void disableUserCredit(Integer uid) {
try {
// 查询用户当前授信信息
LambdaQueryWrapper<CreditAmount> lqw = new LambdaQueryWrapper<>();
lqw.eq(CreditAmount::getUid, uid)
.last("LIMIT 1");
CreditAmount creditAmount = creditAmountDao.selectOne(lqw);
if (creditAmount == null) {
log.warn("未找到用户{}的授信记录", uid);
return;
}
// 更新授信状态为禁用
CreditAmount updateAmount = new CreditAmount();
updateAmount.setId(creditAmount.getId());
updateAmount.setStatus(0);
// updateAmount.setCreditStatus(0); // 0表示禁用
updateAmount.setUpdateTime(new Date());
// updateAmount.setDisableReason("订单逾期未还款");
int rows = creditAmountDao.updateById(updateAmount);
if (rows > 0) {
log.info("用户{}授信功能已禁用,原因:订单逾期未还款", uid);
} else {
log.error("禁用用户{}授信功能失败", uid);
throw new CrmebException("禁用授信功能失败");
}
} catch (Exception e) {
log.error("禁用用户{}授信功能时发生错误", uid, e);
throw new CrmebException("禁用授信功能失败: " + e.getMessage());
}
}
@Override
public void updateStatus() {
User info = userService.getInfo();
if(Objects.isNull(info)) {
return;
}
LambdaQueryWrapper<CreditAmount> lqw = new LambdaQueryWrapper<>();
lqw.eq(CreditAmount::getUid, info.getId());
CreditAmount creditAmount = creditAmountDao.selectOne(lqw);
if(Objects.isNull(creditAmount)){
return;
}
if(creditAmount.getStatus() == 0){
creditAmount.setStatus(1);
}
creditAmountDao.updateById(creditAmount);
}
@Override
public List<CreditAmount> getUserAmountInfo(List<Integer> uidList) {
if(CollectionUtils.isNotEmpty(uidList)){
return creditAmountDao.selectList(new LambdaQueryWrapper<CreditAmount>().in(CreditAmount::getUid, uidList));
}
return Collections.emptyList();
}
@Override
public CreditAmountResponse getDetail(String id) {
CreditAmountSearchRequest request = new CreditAmountSearchRequest();
request.setId(id);
List<CreditAmountResponse> list = getList(request, null);
if(CollectionUtils.isNotEmpty(list)){
return list.get(0);
}
return null;
}
@Override
@Transactional
public boolean saveCreditAmount(CreditAmountRequest creditAmountRequest) {
CreditAmount creditAmount = new CreditAmount();
BeanUtils.copyProperties(creditAmountRequest, creditAmount);
//用户
List<CreditAmount> exists = this.list(new LambdaQueryWrapper<CreditAmount>().eq(CreditAmount::getUid, creditAmountRequest.getUid()));
if(CollectionUtils.isNotEmpty(exists)){
throw new CrmebException(CommonResultCode.VALIDATE_FAILED, "该用户已存在授信记录");
}
creditAmount.setCreditPayAmount(BigDecimal.ZERO);
creditAmount.setCreditRepaymentAmount(BigDecimal.ZERO);
creditAmount.setCreditRemainAmount(BigDecimal.ZERO);
creditAmount.setCreditStatus(0);
creditAmount.setAuditStatus("0");
creditAmount.setStatus(0);
creditAmount.setTaskStartTime(DateUtil.date());
this.save(creditAmount);
User user = userService.getById(creditAmountRequest.getUid());
user.setCreditStatus("1"); //用户置为开启授信
userService.updateById(user);
return true;
}
@Override
@Transactional
public boolean updateCreditAmount(CreditAmountRequest creditAmountRequest) {
CreditAmount creditAmount = this.getById(creditAmountRequest.getId());
BigDecimal sourceCreditAmount = creditAmount.getCreditAmount();
BeanUtils.copyProperties(creditAmountRequest, creditAmount, "creditStatus");
if(creditAmount.getAuditStatus().equals("2")){
//拒绝审核的记录,编辑后置为待审核
creditAmount.setAuditStatus("0");
}else if(creditAmount.getAuditStatus().equals("1")){
//已审核的授信用户,判断额度是否增减
if(creditAmountRequest.getCreditAmount() != null){
BigDecimal changeCreditAmount = creditAmountRequest.getCreditAmount().subtract(sourceCreditAmount);
if(changeCreditAmount.compareTo(BigDecimal.ZERO) != 0){
//授信额度调整
saveCreditBillInfo(creditAmount, changeCreditAmount);
}
}
}
//判断当前合同期限时间,过期则置为冻结状态
if(creditAmount.getContractEndDate()!=null){
String contractEndDate = DateUtil.format(creditAmount.getContractEndDate(), "yyyy-MM-dd");
String curDateStr = DateUtil.format(DateUtil.date(), "yyyy-MM-dd");
if(contractEndDate.compareTo(curDateStr) < 0){
creditAmount.setStatus(0); //冻结
}
else if(contractEndDate.compareTo(curDateStr) >= 0){
creditAmount.setStatus(1); //正常
}
}
String cronExpression = generateCronExpression(creditAmount.getSettleTerm());
creditAmount.setCronExpression(cronExpression);
return this.updateById(creditAmount);
}
public void saveCreditBillInfo(CreditAmount creditAmount, BigDecimal changeCreditAmount){
//修改用户授信额度
creditAmount.setCreditRemainAmount(creditAmount.getCreditRemainAmount().add(changeCreditAmount));
//新增授信流水
CreditBillInfo creditBillInfo = new CreditBillInfo();
creditBillInfo.setUid(creditAmount.getUid());
creditBillInfo.setCreditPayAmount(changeCreditAmount.abs());
creditBillInfo.setCreditRemainAmount(creditAmount.getCreditRemainAmount());
creditBillInfo.setCreateTime(new Date());
creditBillInfo.setCreditType(changeCreditAmount.compareTo(BigDecimal.ZERO.stripTrailingZeros())>=0 ? 3 : 4);
creditBillInfoDao.insert(creditBillInfo);
}
@Override
public boolean checkCreditAmount(CreditAmountCheckRequest creditAmountCheckRequest) {
CreditAmount creditAmount = this.getById(creditAmountCheckRequest.getId());
if(!creditAmount.getAuditStatus().equals("0")){
throw new CrmebException(CommonResultCode.VALIDATE_FAILED, "只有待审核的授信记录才能进行审核");
}
creditAmount.setAuditStatus(creditAmountCheckRequest.getAuditStatus());
creditAmount.setAuditBy(creditAmountCheckRequest.getAuditBy());
creditAmount.setAuditRemark(creditAmountCheckRequest.getAuditRemark());
if(creditAmount.getAuditStatus().equals("1")){
//审核通过
creditAmount.setCreditStatus(1);
creditAmount.setCreditRemainAmount(creditAmount.getCreditAmount());
//判断当前合同期限时间,过期则置为冻结状态
if(creditAmount.getContractEndDate()!=null){
String contractEndDate = DateUtil.format(creditAmount.getContractEndDate(), "yyyy-MM-dd");
String curDateStr = DateUtil.format(DateUtil.date(), "yyyy-MM-dd");
if(contractEndDate.compareTo(curDateStr) < 0){
creditAmount.setStatus(0); //冻结
}else{
//设置状态
creditAmount.setStatus(1); //正常
String cronExpression = generateCronExpression(creditAmount.getSettleTerm());
creditAmount.setCronExpression(cronExpression);
}
}
}
return this.updateById(creditAmount);
}
@Override
public boolean operatorCreditStatus(CreditAmountCreditStatusRequest creditAmountCreditStatusRequest) {
CreditAmount creditAmount = this.getById(creditAmountCreditStatusRequest.getId());
if(!creditAmount.getAuditStatus().equals("1")){
throw new CrmebException(CommonResultCode.VALIDATE_FAILED, "只有审核通过的授信用户才能操作账期开关");
}
creditAmount.setCreditStatus(creditAmountCreditStatusRequest.getCreditStatus());
return this.updateById(creditAmount);
}
@Override
public CreditAmount getByUserId(Integer uid) {
return this.getOne(new LambdaQueryWrapper<CreditAmount>().eq(CreditAmount::getUid, uid));
}
/**
* 授信已使用额度 剩余额度额度变动
* @param uid
* @param price
* @param type
* @return
*/
@Override
public Boolean updateNowMoney(Integer uid, BigDecimal price, String type) {
UpdateWrapper<CreditAmount> wrapper = Wrappers.update();
if (type.equals(Constants.OPERATION_TYPE_ADD)) {
wrapper.setSql(StrUtil.format("credit_remain_amount = credit_remain_amount + {}", price));
} else {
wrapper.setSql(StrUtil.format("credit_remain_amount = credit_remain_amount - {}", price));
}
wrapper.eq("uid", uid);
if (type.equals(Constants.OPERATION_TYPE_SUBTRACT)) {
wrapper.apply(StrUtil.format(" credit_remain_amount - {} >= 0", price));
}
return update(wrapper);
}
/**
* 更新已还款额度
* @param uid
* @param price
* @param type
* @return
*/
@Override
public Boolean updateCreditRepaymentAmounty(Integer uid, BigDecimal price, String type) {
UpdateWrapper<CreditAmount> wrapper = Wrappers.update();
if (type.equals(Constants.OPERATION_TYPE_ADD)) {
wrapper.setSql(StrUtil.format("credit_repayment_amount = credit_repayment_amount + {}", price));
} else {
wrapper.setSql(StrUtil.format("credit_repayment_amount = credit_remain_amount - {}", price));
}
wrapper.eq("uid", uid);
if (type.equals(Constants.OPERATION_TYPE_SUBTRACT)) {
wrapper.apply(StrUtil.format(" credit_repayment_amount - {} >= 0", price));
}
return update(wrapper);
}
/**
* 授信已使用额度 已使用额度额度变动
* @param uid
* @param price
* @param type
* @return
*/
@Override
public Boolean updateRemainMoney(Integer uid, BigDecimal price, String type) {
UpdateWrapper<CreditAmount> wrapper = Wrappers.update();
if (type.equals(Constants.OPERATION_TYPE_ADD)) {
wrapper.setSql(StrUtil.format("credit_pay_amount = credit_pay_amount + {}", price));
} else {
wrapper.setSql(StrUtil.format("credit_pay_amount = credit_pay_amount - {}", price));
}
wrapper.eq("uid", uid);
if (type.equals(Constants.OPERATION_TYPE_SUBTRACT)) {
wrapper.apply(StrUtil.format(" credit_pay_amount - {} >= 0", price));
}
return update(wrapper);
}
@Override
public Boolean updateUserCredit(Order order) {
String platOrderNo = order.getPlatOrderNo();
//查询授信订单
CreditOrderBill creditOrderBill = creditOrderBillService.getByOrderNo(platOrderNo);
if(Objects.nonNull(creditOrderBill)){
if(creditOrderBill.getCreditRepaymentFlag()==0){
//更新用户的授信额度
updateNowMoney(order.getUid(), creditOrderBill.getPayPrice(), Constants.OPERATION_TYPE_ADD);
updateRemainMoney(order.getUid(), creditOrderBill.getPayPrice(), Constants.OPERATION_TYPE_SUBTRACT);
}
creditOrderBill.setCreditRepaymentFlag(1);
creditOrderBill.setCreditRepaymentAmount(order.getPayPrice());
creditOrderBill.setCreditRepaymentTime(DateUtil.date());
creditOrderBill.setPayType(order.getPayType());
creditOrderBill.setPayChannel(order.getPayChannel());
creditOrderBill.setOutTradeNo(order.getOutTradeNo());
creditOrderBill.setOrderType(1);
creditOrderBillService.updateById(creditOrderBill);
}
return true;
}
@Override
public List<CreditAmount> getActiveCreditAmounts(){
LambdaQueryWrapper<CreditAmount> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(CreditAmount::getStatus, 1); // 启用状态
// wrapper.le(CreditAmount::getContractEndDate, DateUtil.date());
return dao.selectList(wrapper);
}
/**
* 更新cron表达式
*/
@Transactional(rollbackFor = Exception.class)
public void updateCronExpression(String id, String cronExpression) {
CreditAmount update = new CreditAmount();
update.setId(id);
update.setCronExpression(cronExpression);
// 更新任务执行时间+7天
update.setTaskStartTime(DateUtil.offsetDay(new Date(), 7));
update.setUpdateTime(new Date());
creditAmountDao.updateById(update);
}
/**
* 生成cron表达式
*/
private String generateCronExpression(Integer settlementPeriod) {
if (settlementPeriod == null || settlementPeriod <= 0) {
settlementPeriod = 7; // 默7天
}
// 生成每隔N天执行一次的cron表达式,默认凌晨1点执行
return String.format("0 0 1 */%d * ?", settlementPeriod);
}
/**
* 初始化所有用户的cron表达式
*/
@PostConstruct // 项目启动时自动执行
public void initCronExpressions() {
try {
// 查询所有没有cron表达式的记录
LambdaQueryWrapper<CreditAmount> lqw = new LambdaQueryWrapper<>();
lqw.isNull(CreditAmount::getCronExpression)
.or()
.eq(CreditAmount::getCronExpression, "");
List<CreditAmount> list = creditAmountDao.selectList(lqw);
if (CollUtil.isNotEmpty(list)) {
for (CreditAmount creditAmount : list) {
// 生成并更新cron表达式
String cronExpression = generateCronExpression(creditAmount.getSettleTerm());
updateCronExpression(creditAmount.getId(), cronExpression);
log.info("已为用户{}生成结算cron表达式: {}",
creditAmount.getUid(), cronExpression);
}
}
} catch (Exception e) {
log.error("初始化cron表达式时发生错误", e);
}
}
}
package com.zbkj.service.service.impl.credit;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.zbkj.common.model.credit.CreditAmount;
import com.zbkj.common.model.credit.CreditBillInfo;
import com.zbkj.common.request.PageParamRequest;
import com.zbkj.service.dao.credit.CreditBillInfoDao;
import com.zbkj.service.service.credit.CreditAmountService;
import com.zbkj.service.service.credit.CreditBillInfoService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* @author dudianlong
* @description CreditBillInfoServiceImpl 接口实现
* @date 2024-11-22
*/
@Service
public class CreditBillInfoServiceImpl extends ServiceImpl<CreditBillInfoDao, CreditBillInfo> implements CreditBillInfoService {
@Resource
private CreditBillInfoDao dao;
@Resource
private CreditAmountService creditAmountService;
@Override
public List<CreditBillInfo> getList(CreditBillInfo creditBillInfo, PageParamRequest pageParamRequest) {
if(pageParamRequest != null){
Page<CreditBillInfo> page = PageHelper.startPage(pageParamRequest.getPage(), pageParamRequest.getLimit());
}
LambdaQueryWrapper<CreditBillInfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
if(creditBillInfo.getUid() != null){
lambdaQueryWrapper.eq(CreditBillInfo::getUid, creditBillInfo.getUid());
}
lambdaQueryWrapper.orderByDesc(CreditBillInfo::getCreateTime);
List<CreditBillInfo> list = dao.selectList(lambdaQueryWrapper);
return list;
}
@Override
public boolean addRecord(BigDecimal payPrice, Integer uid,Integer type) {
CreditAmount creditAmount = creditAmountService.getByUserId(uid);
//创建授信流水
if(Objects.nonNull(creditAmount)){
CreditBillInfo creditBillInfo=new CreditBillInfo();
creditBillInfo.setUid(uid);
creditBillInfo.setCreditType(type);
creditBillInfo.setCreditPayAmount(payPrice);
//剩余授信额度
creditBillInfo.setCreditRemainAmount(creditAmount.getCreditRemainAmount());
creditBillInfo.setCreateTime(DateUtil.date());
creditBillInfo.setUpdateTime(DateUtil.date());
this.save(creditBillInfo);
}
return true;
}
}
功能展示:
3:实现花呗支付功能:
package com.zbkj.front.controller;
import com.zbkj.common.request.OrderPayRequest;
import com.zbkj.common.request.WechatPaymentQueryRequest;
import com.zbkj.common.response.CashierInfoResponse;
import com.zbkj.common.response.OrderPayResultResponse;
import com.zbkj.common.response.PayConfigResponse;
import com.zbkj.common.result.CommonResult;
import com.zbkj.service.service.PayService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
/**
* 支付控制器
* +----------------------------------------------------------------------
* +----------------------------------------------------------------------
*/
@Slf4j
@RestController
@RequestMapping("api/front/pay")
@Api(tags = "支付管理")
public class PayController {
@Autowired
private PayService payService;
@ApiOperation(value = "获取支付配置")
@RequestMapping(value = "/get/config", method = RequestMethod.GET)
public CommonResult<PayConfigResponse> getPayConfig() {
return CommonResult.success(payService.getPayConfig());
}
@ApiOperation(value = "订单支付")
@RequestMapping(value = "/payment", method = RequestMethod.POST)
public CommonResult<OrderPayResultResponse> payment(@RequestBody @Validated OrderPayRequest orderPayRequest) {
return CommonResult.success(payService.payment(orderPayRequest));
}
@ApiOperation(value = "查询订单微信支付结果")
@RequestMapping(value = "/query/wechat/pay/result/{orderNo}", method = RequestMethod.GET)
public CommonResult<Boolean> queryPayResult(@PathVariable(value = "orderNo") String orderNo) {
return CommonResult.success(payService.queryWechatPayResult(orderNo));
}
@ApiOperation(value = "查询订单支付宝支付结果")
@RequestMapping(value = "/query/ali/pay/result/{orderNo}", method = RequestMethod.GET)
public CommonResult<Boolean> queryAliPayResult(@PathVariable(value = "orderNo") String orderNo) {
return CommonResult.success(payService.queryAliPayResult(orderNo));
}
@ApiOperation(value = "获取收银台信息")
@RequestMapping(value = "/get/cashier/{orderNo}", method = RequestMethod.GET)
public CommonResult<CashierInfoResponse> getCashierIno(@PathVariable(value = "orderNo") String orderNo) {
return CommonResult.success(payService.getCashierIno(orderNo));
}
@ApiOperation(value = "查询微信支付结果")
@RequestMapping(value = "/query/wechat/payment/result", method = RequestMethod.GET)
public CommonResult<Boolean> queryWechatPaymentResult(@Validated WechatPaymentQueryRequest request) {
return CommonResult.success(payService.queryWechatPaymentResult(request));
}
}
package com.zbkj.service.service;
import com.zbkj.common.request.OrderPayRequest;
import com.zbkj.common.request.WechatPaymentQueryRequest;
import com.zbkj.common.response.CashierInfoResponse;
import com.zbkj.common.response.OrderPayResultResponse;
import com.zbkj.common.response.PayConfigResponse;
import com.zbkj.common.vo.MyRecord;
/**
* PayService 接口
* +----------------------------------------------------------------------
* +----------------------------------------------------------------------
*/
public interface PayService {
/**
* 获取支付配置
*/
PayConfigResponse getPayConfig();
/**
* 订单支付
* @param orderPayRequest 订单支付参数
* @return OrderPayResultResponse
*/
OrderPayResultResponse payment(OrderPayRequest orderPayRequest);
/**
* 查询订单微信支付结果
* @param orderNo 订单编号
*/
Boolean queryWechatPayResult(String orderNo);
/**
* 查询订单支付宝支付结果
* @param orderNo 订单编号
*/
Boolean queryAliPayResult(String orderNo);
/**
* 支付成功后置处理(临时)
* @param orderNo 订单编号
*/
Boolean payAfterProcessingTemp(String orderNo);
/**
* 获取收银台信息
*
* @param orderNo 订单号
*/
CashierInfoResponse getCashierIno(String orderNo);
/**
* 查询微信支付结果
*/
Boolean queryWechatPaymentResult(WechatPaymentQueryRequest request);
}
package com.zbkj.service.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeQueryModel;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.zbkj.common.config.CrmebConfig;
import com.zbkj.common.constants.*;
import com.zbkj.common.exception.CrmebException;
import com.zbkj.common.model.admin.SystemAdmin;
import com.zbkj.common.model.alipay.AliPayInfo;
import com.zbkj.common.model.bill.Bill;
import com.zbkj.common.model.bill.MerchantBill;
import com.zbkj.common.model.coupon.CouponUser;
import com.zbkj.common.model.credit.CreditAmount;
import com.zbkj.common.model.credit.CreditBillInfo;
import com.zbkj.common.model.credit.CreditOrderBill;
import com.zbkj.common.model.member.PaidMemberOrder;
import com.zbkj.common.model.merchant.Merchant;
import com.zbkj.common.model.merchant.MerchantBalanceRecord;
import com.zbkj.common.model.order.*;
import com.zbkj.common.model.product.ProductCoupon;
import com.zbkj.common.model.sales.XsSales;
import com.zbkj.common.model.system.SystemNotification;
import com.zbkj.common.model.user.*;
import com.zbkj.common.model.wechat.WechatPayInfo;
import com.zbkj.common.model.wechat.video.PayComponentProduct;
import com.zbkj.common.request.OrderPayRequest;
import com.zbkj.common.request.WechatPaymentQueryRequest;
import com.zbkj.common.response.CashierInfoResponse;
import com.zbkj.common.response.OrderPayResultResponse;
import com.zbkj.common.response.PayConfigResponse;
import com.zbkj.common.result.CommonResultCode;
import com.zbkj.common.result.MemberResultCode;
import com.zbkj.common.result.OrderResultCode;
import com.zbkj.common.result.UserResultCode;
import com.zbkj.common.utils.*;
import com.zbkj.common.vo.*;
import com.zbkj.common.vo.wxvedioshop.ShopOrderAddResultVo;
import com.zbkj.common.vo.wxvedioshop.order.*;
import com.zbkj.service.service.*;
import com.zbkj.service.service.credit.CreditAmountService;
import com.zbkj.service.service.credit.CreditBillInfoService;
import com.zbkj.service.service.credit.CreditOrderBillService;
import com.zbkj.service.service.sales.IXsSalesService;
import jodd.util.StringUtil;
import kong.unirest.HttpResponse;
import kong.unirest.Unirest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLDecoder;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
* PayServiceImpl 接口实现
* +----------------------------------------------------------------------
* +----------------------------------------------------------------------
*/
@Service
public class PayServiceImpl implements PayService {
private static final Logger logger = LoggerFactory.getLogger(PayServiceImpl.class);
@Autowired
private SystemConfigService systemConfigService;
@Autowired
private OrderService orderService;
@Autowired
private UserService userService;
@Autowired
private TransactionTemplate transactionTemplate;
@Autowired
private UserTokenService userTokenService;
@Autowired
private WechatService wechatService;
@Autowired
private WechatPayInfoService wechatPayInfoService;
@Autowired
private AliPayService aliPayService;
@Autowired
private MerchantOrderService merchantOrderService;
@Autowired
private OrderStatusService orderStatusService;
@Autowired
private UserIntegralRecordService userIntegralRecordService;
@Autowired
private SystemNotificationService systemNotificationService;
@Autowired
private SmsService smsService;
@Autowired
private TemplateMessageService templateMessageService;
@Autowired
private OrderDetailService orderDetailService;
@Autowired
private ProductCouponService productCouponService;
@Autowired
private CouponUserService couponUserService;
@Autowired
private CouponService couponService;
@Autowired
private UserBrokerageRecordService userBrokerageRecordService;
@Autowired
private UserBalanceRecordService userBalanceRecordService;
@Autowired
private MerchantService merchantService;
@Autowired
private MerchantBillService merchantBillService;
@Autowired
private OrderProfitSharingService orderProfitSharingService;
@Autowired
private BillService billService;
@Autowired
private WechatVideoOrderService wechatVideoOrderService;
@Autowired
private AsyncService asyncService;
@Autowired
private PayComponentOrderService payComponentOrderService;
@Autowired
private PayComponentProductService payComponentProductService;
@Autowired
private AliPayInfoService aliPayInfoService;
@Autowired
private RechargeOrderService rechargeOrderService;
@Autowired
private MerchantBalanceRecordService merchantBalanceRecordService;
@Autowired
private MerchantPrintService merchantPrintService;
@Autowired
private CrmebConfig crmebConfig;
@Autowired
private SystemAdminService systemAdminService;
@Autowired
private PaidMemberOrderService paidMemberOrderService;
@Autowired
private IXsSalesService xsSalesService;
@Autowired
private RedisUtil redisUtil;
@Autowired
private CreditAmountService creditAmountService;
@Autowired
private CreditOrderBillService creditOrderBillService;
@Autowired
private CreditBillInfoService creditBillInfoService;
/**
* 获取支付配置
*/
@Override
public PayConfigResponse getPayConfig() {
String payWxOpen = systemConfigService.getValueByKey(SysConfigConstants.CONFIG_PAY_WECHAT_OPEN);
String yuePayStatus = systemConfigService.getValueByKey(SysConfigConstants.CONFIG_YUE_PAY_STATUS);
String creditPayStatus = systemConfigService.getValueByKey(SysConfigConstants.CONFIG_CREDIT_PAY_STATUS);
String aliPayStatus = systemConfigService.getValueByKey(SysConfigConstants.CONFIG_ALI_PAY_STATUS);
PayConfigResponse response = new PayConfigResponse();
response.setYuePayStatus(Constants.CONFIG_FORM_SWITCH_OPEN.equals(yuePayStatus));
response.setCreditPayStatus(Constants.CONFIG_FORM_SWITCH_OPEN.equals(yuePayStatus));
response.setPayWechatOpen(Constants.CONFIG_FORM_SWITCH_OPEN.equals(payWxOpen));
response.setAliPayStatus(Constants.CONFIG_FORM_SWITCH_OPEN.equals(aliPayStatus));
if (Constants.CONFIG_FORM_SWITCH_OPEN.equals(yuePayStatus)) {
User user = userService.getInfo();
response.setUserBalance(user.getNowMoney());
}
if (Constants.CONFIG_FORM_SWITCH_OPEN.equals(creditPayStatus)) {
User user = userService.getInfo();
//查询授信余额
CreditAmount creditAmount=creditAmountService.getByUserId(user.getId());
if(Objects.nonNull(creditAmount)){
response.setCreditRemainAmount(creditAmount.getCreditRemainAmount());
}else{
response.setCreditRemainAmount(BigDecimal.ZERO);
}
}
return response;
}
/**
* 订单支付
*
* @param orderPayRequest 订单支付参数
* @return OrderPayResultResponse
*/
@Override
public OrderPayResultResponse payment(OrderPayRequest orderPayRequest) {
logger.info("订单支付 START orderPayRequest:{}", JSON.toJSONString(orderPayRequest));
Order order = orderService.getByOrderNo(orderPayRequest.getOrderNo());
logger.info("订单支付 当前操作的订单信息:{}", JSON.toJSONString(order));
if (order.getCancelStatus() > OrderConstants.ORDER_CANCEL_STATUS_NORMAL) {
throw new CrmebException(OrderResultCode.ORDER_CANCEL);
}
if (order.getPaid()) {
throw new CrmebException(OrderResultCode.ORDER_PAID);
}
if (order.getStatus() > OrderConstants.ORDER_STATUS_WAIT_PAY) {
throw new CrmebException(OrderResultCode.ORDER_STATUS_ABNORMAL);
}
User user = userService.getInfo();
// 根据支付类型进行校验,更换支付类型
order.setPayType(orderPayRequest.getPayType());
order.setPayChannel(orderPayRequest.getPayChannel());
// 获取过期时间
DateTime cancelTime = DateUtil.offset(order.getCreateTime(), DateField.MINUTE, crmebConfig.getOrderCancelTime());
long between = DateUtil.between(cancelTime, DateUtil.date(), DateUnit.SECOND, false);
if (between > 0) {
throw new CrmebException(CommonResultCode.VALIDATE_FAILED, "订单已过期");
}
// 授信支付
if (orderPayRequest.getPayType().equals(PayConstants.PAY_TYPE_CREDIT)) {
//查询用户的授信额度
CreditAmount creditAmount=creditAmountService.getByUserId(user.getId());
if (creditAmount.getCreditRemainAmount().compareTo(order.getPayPrice()) < 0) {
throw new CrmebException(UserResultCode.USER_REDIT_INSUFFICIENT);
}
}
// 余额支付
if (orderPayRequest.getPayType().equals(PayConstants.PAY_TYPE_YUE)) {
if (user.getNowMoney().compareTo(order.getPayPrice()) < 0) {
throw new CrmebException(UserResultCode.USER_BALANCE_INSUFFICIENT);
}
}
OrderPayResultResponse response = new OrderPayResultResponse();
response.setOrderNo(order.getOrderNo());
response.setPayType(order.getPayType());
response.setPayChannel(order.getPayChannel());
if (order.getPayPrice().compareTo(BigDecimal.ZERO) <= 0) {
throw new CrmebException(CommonResultCode.VALIDATE_FAILED, "支付金额不能低于等于0元");
}
// 余额支付
if (order.getPayType().equals(PayConstants.PAY_TYPE_YUE)) {
Boolean yueBoolean = yuePay(order, user);
response.setStatus(yueBoolean);
logger.info("余额支付 response : {}", JSON.toJSONString(response));
return response;
}
// 授信支付
if (order.getPayType().equals(PayConstants.PAY_TYPE_CREDIT)) {
Boolean yueBoolean = creditPay(order, user);
response.setStatus(yueBoolean);
logger.info("授信支付 response : {}", JSON.toJSONString(response));
return response;
}
// 微信视频号下单 需要额外调用支付参数
if (order.getPayChannel().equals(PayConstants.PAY_CHANNEL_WECHAT_MINI_VIDEO)) {
WxPayJsResultVo vo = new WxPayJsResultVo();
UserToken tokenByUser = userTokenService.getTokenByUserId(user.getId(), UserConstants.USER_TOKEN_TYPE_ROUTINE);
List<OrderDetail> orderDetailList = orderDetailService.getByOrderNo(order.getOrderNo());
logger.info("视频号下单,订单详情:{}", JSON.toJSONString(orderDetailList));
// 视频号下单都是单品
PayComponentProduct payComponentProduct = payComponentProductService.getById(orderDetailList.get(0).getProductId());
logger.info("视频号下单,当前视频号商品:{}", JSON.toJSONString(payComponentProduct));
//组装商品信息
ShopOrderDetailAddVo shopOrderDetailAddVo = new ShopOrderDetailAddVo();
List<ShopOrderProductInfoAddVo> shopOrderProductInfoAddVoList = new ArrayList<>();
for (OrderDetail orderDetail : orderDetailList) {
ShopOrderProductInfoAddVo shopOrderProductInfoAddVo = new ShopOrderProductInfoAddVo();
shopOrderProductInfoAddVo.setOutProductId(orderDetail.getProductId().toString());
shopOrderProductInfoAddVo.setOutSkuId(orderDetail.getAttrValueId().toString());
shopOrderProductInfoAddVo.setProductCnt(orderDetail.getPayNum());
shopOrderProductInfoAddVo.setSalePrice(orderDetail.getPrice().multiply(new BigDecimal("100")).longValue());
shopOrderProductInfoAddVo.setSkuRealPrice(orderDetail.getPayPrice().multiply(new BigDecimal("100")).longValue());
shopOrderProductInfoAddVo.setPath(payComponentProduct.getPath());
shopOrderProductInfoAddVo.setTitle(payComponentProduct.getTitle());
shopOrderProductInfoAddVo.setHeadImg(payComponentProduct.getHeadImg());
shopOrderProductInfoAddVoList.add(shopOrderProductInfoAddVo);
}
shopOrderDetailAddVo.setProductInfos(shopOrderProductInfoAddVoList);
// 组装支付方式
ShopOrderPayInfoAddVo payInfoAddVo = new ShopOrderPayInfoAddVo();
payInfoAddVo.setPayMethodType(0);
payInfoAddVo.setPayMethod("微信支付"); // 视频号暂时只有微信支付
shopOrderDetailAddVo.setPayInfo(payInfoAddVo);
// 组装支付详细信息
ShopOrderPriceInfoVo shopOrderPriceInfoVo = new ShopOrderPriceInfoVo();
shopOrderPriceInfoVo.setOrderPrice(order.getPayPrice().multiply(new BigDecimal("100")).longValue());
// 视频号商品暂时面部免运费
shopOrderPriceInfoVo.setFreight(0L);
shopOrderPriceInfoVo.setDiscountedPrice(0L);
shopOrderPriceInfoVo.setAdditionalPrice(0L);
shopOrderPriceInfoVo.setAdditional_remarks(null);
shopOrderDetailAddVo.setPriceInfo(shopOrderPriceInfoVo);
// 组装自定义交易组件主体数据
ShopOrderAddVo shopOrderAddVo = new ShopOrderAddVo();
shopOrderAddVo.setOrderDetail(shopOrderDetailAddVo);
shopOrderAddVo.setFund_type(1);
shopOrderAddVo.setTrace_id(null);
shopOrderAddVo.setOutOrderId(order.getOrderNo());
shopOrderAddVo.setOpenid(tokenByUser.getToken());
shopOrderAddVo.setOutUserId(user.getId());
shopOrderAddVo.setMerId(order.getMerId());
// 订单路由地址
shopOrderAddVo.setPath("/pages/users/order_details/index?orderNo=" + orderPayRequest.getOrderNo());
// 组装订单信息 视频号都是单品 最多是多量
List<MerchantOrder> merchantOrderList = merchantOrderService.getByOrderNo(orderPayRequest.getOrderNo());
if (ObjectUtil.isNull(merchantOrderList) || merchantOrderList.size() == 0) {
throw new CrmebException(CommonResultCode.VALIDATE_FAILED, "未找到视频号商品订单");
}
MerchantOrder CurrentMerchantOrder = merchantOrderList.get(0);
ShopOrderAddressInfoAddVo shopOrderAddressInfoAddVo = new ShopOrderAddressInfoAddVo();
shopOrderAddressInfoAddVo.setReceiverName(CurrentMerchantOrder.getRealName());
shopOrderAddressInfoAddVo.setDetailedAddress(CurrentMerchantOrder.getUserAddress());
shopOrderAddressInfoAddVo.setTelNumber(CurrentMerchantOrder.getUserPhone());
shopOrderAddVo.setAddressInfo(shopOrderAddressInfoAddVo);
// 1: 正常快递, 2: 无需快递, 3: 线下配送, 4: 用户自提,视频号场景目前只支持 1,正常快递
ShopOrderDeliveryDetailAddVo shopOrderDeliveryDetailAddVo = new ShopOrderDeliveryDetailAddVo();
shopOrderDeliveryDetailAddVo.setDeliveryType(1);
shopOrderAddVo.setDeliveryDetail(shopOrderDeliveryDetailAddVo);
shopOrderAddVo.setExpire_time(WxPayUtil.getCurrentTimestamp().intValue() + 900);
shopOrderAddVo.setCreateTime(CrmebDateUtil.nowDateTimeStr());
ShopOrderAddResultVo shopOrderAddResultVo = payComponentOrderService.create(shopOrderAddVo);
ShopOrderGetPaymentParamsRequestVo videoPaymentRequestVo = new ShopOrderGetPaymentParamsRequestVo(
shopOrderAddResultVo.getOutOrderId(), order.getOrderNo(), tokenByUser.getToken()
);
logger.info("视频号下单时 支付接口参数:{}", JSON.toJSONString(videoPaymentRequestVo));
ShopOrderGetPaymentParamsRersponseVo shopOrderGetPaymentParamsRersponseVo = wechatVideoOrderService.shopOrderGetPaymentParams(videoPaymentRequestVo);
logger.info("视频号下单时 获取的支付参数 {}", JSON.toJSONString(shopOrderGetPaymentParamsRersponseVo));
response.setStatus(true);
vo.setTimeStamp(WxPayUtil.getCurrentTimestamp() + "");
vo.setNonceStr(shopOrderGetPaymentParamsRersponseVo.getNonceStr());
vo.setPackages(shopOrderGetPaymentParamsRersponseVo.get_package());
vo.setPaySign(shopOrderGetPaymentParamsRersponseVo.getPaySign());
vo.setSignType(shopOrderGetPaymentParamsRersponseVo.getSignType());
response.setJsConfig(vo);
logger.info("订单支付 视频号下单 response:{}", JSON.toJSONString(response));
return response;
}
// 微信支付,调用微信预下单,返回拉起微信支付需要的信息
if (order.getPayType().equals(PayConstants.PAY_TYPE_WE_CHAT)) {
//查询redis支付有支付订单
WxPayJsResultVo vo = redisUtil.get(order.getOrderNo());
if(Objects.isNull(vo)){
logger.info("订单支付 微信下单");
vo = wechatPayment(order);
redisUtil.set(order.getOrderNo(),vo,1l, TimeUnit.MINUTES);
}
logger.info("订单支付 微信下单的商户订单号:{}",vo.getOutTradeNo());
order.setOutTradeNo(vo.getOutTradeNo());
orderService.updateById(order);
response.setStatus(true);
response.setJsConfig(vo);
response.setOutTradeNo(vo.getOutTradeNo());
logger.info("订单支付 微信下单 response :{}", JSON.toJSONString(response));
return response;
}
if (order.getPayType().equals(PayConstants.PAY_TYPE_ALI_PAY)) {
logger.info("订单支付 支付宝");
String result = aliPayment(order);
order.setOutTradeNo(order.getOrderNo());
orderService.updateById(order);
response.setStatus(true);
response.setAlipayRequest(result);
logger.info("订单支付 支付宝 response :{}", JSON.toJSONString(response));
return response;
}
response.setStatus(false);
logger.info("订单支付 END response:{}", JSON.toJSONString(response));
return response;
}
private Boolean creditPay(Order order, User user) {
Boolean execute = transactionTemplate.execute(e -> {
Boolean update = Boolean.TRUE;
// 订单修改
order.setPaid(true);
order.setPayTime(DateUtil.date());
order.setStatus(OrderConstants.ORDER_STATUS_WAIT_SHIPPING);
orderService.updateById(order);
// 这里只扣除金额,账单记录在task中处理
if (order.getPayPrice().compareTo(BigDecimal.ZERO) > 0) {
update = creditAmountService.updateNowMoney(order.getUid(), order.getPayPrice(), Constants.OPERATION_TYPE_SUBTRACT);
if (!update) {
logger.error("授信支付,扣除用户授信额度失败,orderNo = {}", order.getOrderNo());
e.setRollbackOnly();
return update;
}
update = creditAmountService.updateRemainMoney(order.getUid(), order.getPayPrice(), Constants.OPERATION_TYPE_ADD);
if (!update) {
logger.error("授信支付,扣除用户授信额度失败,orderNo = {}", order.getOrderNo());
e.setRollbackOnly();
return update;
}
//创建授信订单记录
if (!saveOrCreditOrderBill(order, user)) throw new CrmebException("授信余额支付订单失败");
//创建用户授信记录
if (!saveCreditBillInfo(order, user)) throw new CrmebException("授信余额支付订单失败");
}
return update;
});
if (!execute) throw new CrmebException("授信余额支付订单失败");
//通知万物
noticeWw(order.getWwOrderNo(), order.getOrderNo());
asyncService.orderPaySuccessSplit(order.getOrderNo());
return true;
}
/**
* 支付成功,回调通知万物平台
* */
public void noticeWw(Integer wwOrderId, String billNo){
HttpResponse<String> res = Unirest.put("https://hk-gateway.demo.starytech.cn/v1/mall/oms-order/"+wwOrderId+"/payment")
.header("Authorization", "Bearer LrVErbgIkXysTMUihxxMK61iO7koYJ4yavZr5wLVgadiFvVgyqv6as4XarM7TGzh")
.header("User-Agent", "Apifox/1.0.0 (https://apifox.com)")
.field("bill_no", billNo)
.asString();
System.out.println(String.format("万物OMS支付通知请求参数==wwOrderId:%d,BillNo:%s",wwOrderId,billNo));
System.out.println("万物OMS支付通知返回结果============================");
System.out.println(res.getBody());
}
private boolean saveOrCreditOrderBill(Order order, User user){
CreditAmount creditAmount = creditAmountService.getByUserId(user.getId());
//创建授信订单记录
CreditOrderBill creditOrderBill=creditOrderBillService.getByOrderNo(order.getOrderNo());
if(Objects.nonNull(creditOrderBill)){
creditOrderBill.setPayid(1);
creditOrderBill.setPayTime(DateUtil.date());
creditOrderBill.setOrderType(0);
creditOrderBill.setPayChannel(order.getPayChannel());
creditOrderBill.setPayType(order.getPayType());
creditOrderBill.setPayPrice(order.getPayPrice());
creditOrderBill.setCreditRepaymentAmount(order.getPayPrice());
creditOrderBill.setCreditRepaymentFlag(0);
//合同开始时间加7天
creditOrderBill.setTaskEndTime(DateUtil.date().offset(DateField.DAY_OF_MONTH,creditAmount.getSettleTerm()));
creditOrderBill.setTaskStartTime(DateUtil.date().offset(DateField.DAY_OF_MONTH,creditAmount.getSettleTerm()));
creditOrderBill.setTaskStatus(0);
creditOrderBillService.updateById(creditOrderBill);
}else{
this.saveOrUdate(order,user);
}
return true;
}
private boolean saveCreditBillInfo(Order order, User user){
CreditAmount creditAmount = creditAmountService.getByUserId(user.getId());
//创建授信流水
if(Objects.nonNull(creditAmount)){
BigDecimal creditRemainAmount = creditAmount.getCreditRemainAmount();
//创建流程记录
CreditBillInfo creditBillInfo=new CreditBillInfo();
creditBillInfo.setUid(user.getId());
creditBillInfo.setCreditType(Constants.BILL_TYPE_PAY);
creditBillInfo.setCreditPayAmount(order.getPayPrice());
creditBillInfo.setCreditRemainAmount(creditRemainAmount);
creditBillInfo.setCreateTime(DateUtil.date());
creditBillInfo.setUpdateTime(DateUtil.date());
creditBillInfo.setId(IdWorker.getIdStr());
creditBillInfoService.save(creditBillInfo);
}
return true;
}
public boolean saveOrUdate(Order order,User user) {
CreditOrderBill creditOrderBill = new CreditOrderBill();
creditOrderBill.setUid(user.getId());
creditOrderBill.setOrderNo(order.getOrderNo());
creditOrderBill.setPayType(PayConstants.PAY_TYPE_CREDIT);
creditOrderBill.setPayChannel(order.getPayChannel());
creditOrderBill.setPayPrice(order.getPayPrice());
creditOrderBill.setCreateTime(DateUtil.date());
//获取当月是几月
int month = DateUtil.month(DateUtil.date())+1;
int year = DateUtil.year(DateUtil.date());
creditOrderBill.setMonth(month);
creditOrderBill.setYear(year);
creditOrderBill.setCreditRepaymentAmount(order.getPayPrice());
creditOrderBill.setCreditRepaymentFlag(0);
creditOrderBill.setId(IdWorker.getIdStr());
creditOrderBill.setPayid(1);
creditOrderBill.setOrderType(0);
creditOrderBill.setPayTime(DateUtil.date());
creditOrderBill.setTaskEndTime(DateUtil.date().offset(DateField.DAY_OF_MONTH,7));
creditOrderBill.setTaskStartTime(DateUtil.date());
creditOrderBill.setTaskStatus(0);
creditOrderBillService.save(creditOrderBill);
return true;
}
/**
* 支付成功,给万物平台发送支付消息
* */
public void sendPayment(Integer wwOrderId, String billNo){
HttpResponse<String> res = Unirest.put("https://hk-gateway.demo.starytech.cn/v1/mall/oms-order/"+wwOrderId+"/payment")
.header("Authorization", "Bearer LrVErbgIkXysTMUihxxMK61iO7koYJ4yavZr5wLVgadiFvVgyqv6as4XarM7TGzh")
.header("User-Agent", "Apifox/1.0.0 (https://apifox.com)")
.field("bill_no", billNo)
.asString();
System.out.println(String.format("万物OMS支付通知请求参数==wwOrderId:%d,BillNo:%s",wwOrderId,billNo));
System.out.println("万物OMS支付通知返回结果============================");
System.out.println(res.getBody());
}
/**
* 查询支付结果
*
* @param orderNo 订单编号
*/
@Override
public Boolean queryWechatPayResult(String orderNo) {
Order order = orderService.getByOrderNo(orderNo);
if (ObjectUtil.isNull(order)) {
throw new CrmebException(OrderResultCode.ORDER_NOT_EXIST);
}
if (order.getCancelStatus() > OrderConstants.ORDER_CANCEL_STATUS_NORMAL) {
throw new CrmebException(OrderResultCode.ORDER_CANCEL);
}
if (!order.getPayType().equals(PayConstants.PAY_TYPE_WE_CHAT)) {
throw new CrmebException(CommonResultCode.VALIDATE_FAILED, "不是微信支付类型订单");
}
if (order.getPaid()) {
//支付成功推送万物
logger.info("订单支付 支付成功推送万物");
if(Objects.nonNull(order.getWwOrderNo())){
sendPayment(order.getWwOrderNo(), orderNo);
}
return Boolean.TRUE;
}
WechatPayInfo wechatPayInfo = wechatPayInfoService.getByNo(order.getOutTradeNo());
if (ObjectUtil.isNull(wechatPayInfo)) {
throw new CrmebException(CommonResultCode.VALIDATE_FAILED, "未找到对应微信订单");
}
Map<String, String> payVo = getWechatQueryPayVo(order.getOutTradeNo(), order.getPayChannel());
MyRecord myRecord = wechatService.payOrderQuery(payVo);
if (myRecord.getInt("payStatus") < 1) {
return Boolean.FALSE;
}
wechatPayInfo.setIsSubscribe(myRecord.getStr("is_subscribe"));
wechatPayInfo.setTradeState(myRecord.getStr("trade_state"));
wechatPayInfo.setBankType(myRecord.getStr("bank_type"));
wechatPayInfo.setCashFee(myRecord.getInt("cash_fee"));
wechatPayInfo.setCouponFee(myRecord.getInt("coupon_fee"));
wechatPayInfo.setTransactionId(myRecord.getStr("transaction_id"));
wechatPayInfo.setTimeEnd(myRecord.getStr("time_end"));
wechatPayInfo.setTradeStateDesc(myRecord.getStr("trade_state_desc"));
Boolean updatePaid = transactionTemplate.execute(e -> {
orderService.updatePaid(orderNo);
wechatPayInfoService.updateById(wechatPayInfo);
logger.info("微信查询支付结果 订单支付 支付成功推送万物"+order.getWwOrderNo());
if(Objects.nonNull(order.getWwOrderNo())){
sendPayment(order.getWwOrderNo(), orderNo);
}
return Boolean.TRUE;
});
if (!updatePaid) {
throw new CrmebException("支付成功更新订单失败");
}
asyncService.orderPaySuccessSplit(order.getOrderNo());
// 添加支付成功task
redisUtil.lPush(TaskConstants.ORDER_TASK_PAY_SUCCESS_AFTER, orderNo);
return Boolean.TRUE;
}
/**
* 查询订单支付宝支付结果
*
* @param orderNo 订单编号
*/
@Override
public Boolean queryAliPayResult(String orderNo) {
AliPayInfo aliPayInfo = aliPayInfoService.getByOutTradeNo(orderNo);
if (ObjectUtil.isNull(aliPayInfo)) {
throw new CrmebException(CommonResultCode.VALIDATE_FAILED, "支付宝订单信息不存在");
}
String passbackParams = aliPayInfo.getPassbackParams();
if (StrUtil.isBlank(passbackParams)) {
throw new CrmebException(CommonResultCode.VALIDATE_FAILED, "未知的支付宝订单类型");
}
String decode;
try {
decode = URLDecoder.decode(passbackParams, "utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
throw new CrmebException("ali pay query error : 订单支付类型解码失败==》" + orderNo);
}
String[] split = decode.split("=");
String orderType = split[1];
if (PayConstants.PAY_SERVICE_TYPE_RECHARGE.equals(orderType)) {// 充值订单
RechargeOrder rechargeOrder = rechargeOrderService.getByOutTradeNo(orderNo);
if (ObjectUtil.isNull(rechargeOrder)) {
throw new CrmebException(StrUtil.format("ali pay query error : 充值订单后置处理,没有找到对应订单,支付服务方订单号:{}", orderNo));
}
if (rechargeOrder.getPaid()) {
return Boolean.TRUE;
}
aliPayQuery(orderNo);
// 支付成功处理
Boolean rechargePayAfter = rechargeOrderService.paySuccessAfter(rechargeOrder);
if (!rechargePayAfter) {
throw new CrmebException(StrUtil.format("ali pay recharge pay after error : 数据保存失败==》" + orderNo));
}
return Boolean.TRUE;
}
if (PayConstants.PAY_SERVICE_TYPE_SVIP.equals(orderType)) {// 充值订单
PaidMemberOrder paidMemberOrder = paidMemberOrderService.getByOutTradeNo(orderNo);
if (ObjectUtil.isNull(paidMemberOrder)) {
throw new CrmebException(StrUtil.format("ali pay query error : SVIP订单后置处理,没有找到对应订单,支付服务方订单号:{}", orderNo));
}
if (paidMemberOrder.getPaid()) {
return Boolean.TRUE;
}
aliPayQuery(orderNo);
// 支付成功处理
// 支付成功处理
Boolean svipPayAfter = paidMemberOrderService.paySuccessAfter(paidMemberOrder);
if (!svipPayAfter) {
logger.error("ali pay svip pay after error : 数据保存失败==》" + paidMemberOrder);
throw new CrmebException(StrUtil.format("ali pay svip pay after error : 数据处理失败==》" + orderNo));
}
return Boolean.TRUE;
}
Order order = orderService.getByOrderNo(orderNo);
if (ObjectUtil.isNull(order)) {
throw new CrmebException(OrderResultCode.ORDER_NOT_EXIST);
}
if (order.getCancelStatus() > OrderConstants.ORDER_CANCEL_STATUS_NORMAL) {
throw new CrmebException(OrderResultCode.ORDER_CANCEL);
}
if (!order.getPayType().equals(PayConstants.PAY_TYPE_ALI_PAY)) {
throw new CrmebException(CommonResultCode.VALIDATE_FAILED, "不是支付宝支付类型订单");
}
if (order.getPaid()) {
return Boolean.TRUE;
}
aliPayQuery(orderNo);
Boolean execute = transactionTemplate.execute(e -> {
Boolean updatePaid = orderService.updatePaid(orderNo);
if (!updatePaid) {
logger.warn("商品订单更新支付状态失败,orderNo = {}", orderNo);
e.setRollbackOnly();
}
return Boolean.TRUE;
});
if (!execute) {
throw new CrmebException("支付成功更新订单失败");
}
asyncService.orderPaySuccessSplit(order.getOrderNo());
// // 添加支付成功task
// redisUtil.lPush(TaskConstants.ORDER_TASK_PAY_SUCCESS_AFTER, orderNo);
return Boolean.TRUE;
}
private AlipayTradeQueryResponse aliPayQuery(String orderNo) {
//支付宝交易号
// SDK 公共请求类,包含公共请求参数,以及封装了签名与验签,开发者无需关注签名与验签
String aliPayAppid = systemConfigService.getValueByKey(AlipayConfig.APPID);
String aliPayPrivateKey = systemConfigService.getValueByKey(AlipayConfig.RSA_PRIVATE_KEY);
String aliPayPublicKey = systemConfigService.getValueByKey(AlipayConfig.ALIPAY_PUBLIC_KEY);
AlipayClient client = new DefaultAlipayClient(AlipayConfig.URL, aliPayAppid, aliPayPrivateKey, AlipayConfig.FORMAT, AlipayConfig.CHARSET, aliPayPublicKey, AlipayConfig.SIGNTYPE);
AlipayTradeQueryRequest alipay_request = new AlipayTradeQueryRequest();
AlipayTradeQueryModel model = new AlipayTradeQueryModel();
// 商户订单号,商户网站订单系统中唯一订单号,必填
model.setOutTradeNo(orderNo);
alipay_request.setBizModel(model);
logger.info("alipay_request = " + alipay_request);
AlipayTradeQueryResponse alipay_response = null;
try {
alipay_response = client.execute(alipay_request);
} catch (AlipayApiException e) {
e.printStackTrace();
logger.error("支付宝支付查询异常," + e.getMessage());
throw new CrmebException("支付宝支付查询异常");
}
if (ObjectUtil.isNull(alipay_response)) {
logger.error("支付宝支付结果异常,查询结果为空");
throw new CrmebException("支付宝支付结果异常,查询结果为空");
}
logger.info("alipay_response = " + JSONObject.toJSONString(alipay_response));
if (ObjectUtil.isNull(alipay_response.getTradeStatus()) || !alipay_response.getTradeStatus().equals("TRADE_SUCCESS")) {
logger.error("支付宝支付结果异常,tradeStatus = " + alipay_response.getTradeStatus());
throw new CrmebException("支付宝支付结果异常");
}
return alipay_response;
}
/**
* 支付成功后置处理(临时)
*
* @param orderNo 订单编号
*/
@Override
public Boolean payAfterProcessingTemp(String orderNo) {
Order platOrder = orderService.getByOrderNo(orderNo);
// if(platOrder.getPaid()){
// logger.info("订单支付 支付成功推送万物");
// if(Objects.nonNull(platOrder.getWwOrderNo())){
// sendPayment(platOrder.getWwOrderNo(), orderNo);
// }
// }
if (ObjectUtil.isNull(platOrder)) {
logger.error("OrderTaskServiceImpl.orderPaySuccessAfter | 订单不存在,orderNo: {}", orderNo);
throw new CrmebException("订单不存在,orderNo: " + orderNo);
}
User user = userService.getById(platOrder.getUid());
// 获取拆单后订单
List<Order> orderList = orderService.getByPlatOrderNo(platOrder.getOrderNo());
if (CollUtil.isEmpty(orderList)) {
logger.error("OrderTaskServiceImpl.orderPaySuccessAfter | 商户订单信息不存在,orderNo: {}", orderNo);
throw new CrmebException("商户订单信息不存在,orderNo: " + orderNo);
}
List<UserIntegralRecord> integralList = CollUtil.newArrayList();
List<UserBrokerageRecord> brokerageRecordList = CollUtil.newArrayList();
List<OrderProfitSharing> profitSharingList = CollUtil.newArrayList();
List<MerchantBill> merchantBillList = CollUtil.newArrayList();
List<Bill> billList = CollUtil.newArrayList();
List<MerchantOrder> merchantOrderList = CollUtil.newArrayList();
List<MerchantOrder> merchantOrderListForPrint = CollUtil.newArrayList();
List<OrderDetail> orderDetailList = CollUtil.newArrayList();
for (Order order : orderList) {
// 拆单后,一个主订单只会对应一个商户订单
MerchantOrder merchantOrder = merchantOrderService.getOneByOrderNo(order.getOrderNo());
// 排除核销订单,核销订单在具体核销步骤再打印小票
if (merchantOrder.getShippingType().equals(OrderConstants.ORDER_SHIPPING_TYPE_EXPRESS)) {
merchantOrderListForPrint.add(merchantOrder);
}
if (order.getGainIntegral() > 0) {
// 生成赠送积分记录
UserIntegralRecord integralRecord = integralRecordGainInit(user.getId(), order.getOrderNo(), order.getGainIntegral());
integralList.add(integralRecord);
}
List<OrderDetail> merOrderDetailList = orderDetailService.getByOrderNo(order.getOrderNo());
// 佣金处理
List<UserBrokerageRecord> broRecordList = assignCommission(merchantOrder, merOrderDetailList);
if (CollUtil.isNotEmpty(broRecordList)) {
brokerageRecordList.addAll(broRecordList);
merchantOrderList.add(merchantOrder);
orderDetailList.addAll(merOrderDetailList);
}
// 商户帐单流水、分账
OrderProfitSharing orderProfitSharing = initOrderProfitSharing(merchantOrder);
MerchantBill merchantBill = initPayMerchantBill(merchantOrder, orderProfitSharing.getProfitSharingMerPrice());
List<Bill> platBillList = initPlatformBill(order, merchantOrder, orderProfitSharing);
profitSharingList.add(orderProfitSharing);
merchantBillList.add(merchantBill);
billList.addAll(platBillList);
}
// 商户余额记录
List<MerchantBalanceRecord> merchantBalanceRecordList = profitSharingList.stream().map(sharing -> {
MerchantBalanceRecord merchantBalanceRecord = new MerchantBalanceRecord();
merchantBalanceRecord.setMerId(sharing.getMerId());
merchantBalanceRecord.setLinkNo(sharing.getOrderNo());
merchantBalanceRecord.setLinkType("order");
merchantBalanceRecord.setType(1);
merchantBalanceRecord.setAmount(sharing.getProfitSharingMerPrice().add(sharing.getFreightFee()));
merchantBalanceRecord.setTitle(StrUtil.format("订单支付,商户预计分账金额{}元", merchantBalanceRecord.getAmount()));
merchantBalanceRecord.setBalance(BigDecimal.ZERO);
merchantBalanceRecord.setStatus(1);
return merchantBalanceRecord;
}).collect(Collectors.toList());
// 分销员逻辑
if (!user.getIsPromoter()) {
String funcStatus = systemConfigService.getValueByKey(SysConfigConstants.RETAIL_STORE_SWITCH);
if (funcStatus.equals("1")) {
String broQuota = systemConfigService.getValueByKey(SysConfigConstants.RETAIL_STORE_LINE);
if (!broQuota.equals("-1") && platOrder.getPayPrice().compareTo(new BigDecimal(broQuota)) >= 0) {// -1 不成为分销员
user.setIsPromoter(true);
}
}
} else {
user.setIsPromoter(false);
}
Boolean execute = transactionTemplate.execute(e -> {
// 订单、佣金
if (CollUtil.isNotEmpty(brokerageRecordList)) {
merchantOrderService.updateBatchById(merchantOrderList);
orderDetailService.updateBatchById(orderDetailList);
userBrokerageRecordService.saveBatch(brokerageRecordList);
}
// 订单日志
orderList.forEach(o -> orderStatusService.createLog(o.getOrderNo(), OrderStatusConstants.ORDER_STATUS_PAY_SPLIT, StrUtil.format(OrderStatusConstants.ORDER_LOG_MESSAGE_PAY_SPLIT, platOrder.getOrderNo())));
// 用户信息变更
userService.paySuccessChange(user.getId(), user.getIsPromoter());
// 积分记录
if (CollUtil.isNotEmpty(integralList)) {
userIntegralRecordService.saveBatch(integralList);
}
billService.saveBatch(billList);
merchantBillService.saveBatch(merchantBillList);
orderProfitSharingService.saveBatch(profitSharingList);
// profitSharingList.forEach(p -> {
// merchantService.operationBalance(p.getMerId(), p.getProfitSharingMerPrice(), Constants.OPERATION_TYPE_ADD);
// });
merchantBalanceRecordService.saveBatch(merchantBalanceRecordList);
return Boolean.TRUE;
});
if (execute) {
SystemNotification payNotification = systemNotificationService.getByMark(NotifyConstants.PAY_SUCCESS_MARK);
// 发送短信
if (StrUtil.isNotBlank(user.getPhone()) && payNotification.getIsSms().equals(1)) {
try {
smsService.sendPaySuccess(user.getPhone(), platOrder.getOrderNo(), platOrder.getPayPrice());
} catch (Exception e) {
logger.error("支付成功短信发送异常", e);
}
}
if (payNotification.getIsWechat().equals(1) || payNotification.getIsRoutine().equals(1)) {
//下发模板通知
try {
pushMessageOrder(platOrder, user, payNotification);
} catch (Exception e) {
logger.error("支付成功发送微信通知失败", e);
}
}
// 购买成功后根据配置送优惠券
autoSendCoupons(platOrder);
List<String> orderNoList = orderList.stream().map(Order::getOrderNo).collect(Collectors.toList());
asyncService.orderPayAfterFreezingOperation(orderNoList);
SystemNotification merchantPayNotification = systemNotificationService.getByMark(NotifyConstants.MERCHANT_PAY_SUCCESS_REMINDER);
if (merchantPayNotification.getIsSms().equals(1)) {
try {
orderList.forEach(order -> {
List<SystemAdmin> smsAdminList = systemAdminService.findReceiveSmsAdminListByMerId(order.getMerId());
smsService.sendPaySuccessToMerchant(smsAdminList, order.getOrderNo());
});
} catch (Exception e) {
logger.error("支付成功商户管理员短信发送异常", e);
}
}
try {
// 打印小票 op=1 为方法调用这里也就是支付后自动打印小票的场景
logger.info("小票打印开始调用");
merchantPrintService.printReceipt(merchantOrderListForPrint, 3);
} catch (Exception e) {
logger.error(StrUtil.format("小票打印异常,Exception:{}", e.getMessage()), e);
}
orderList.forEach(order -> {
if (order.getType().equals(OrderConstants.ORDER_TYPE_CLOUD) || order.getType().equals(OrderConstants.ORDER_TYPE_CDKEY)) {
orderService.virtualShipment(order);
}
});
}
return execute;
}
/**
* 获取收银台信息
*
* @param orderNo 订单号
*/
@Override
public CashierInfoResponse getCashierIno(String orderNo) {
Order order = orderService.getByOrderNo(orderNo);
if (order.getCancelStatus() > OrderConstants.ORDER_CANCEL_STATUS_NORMAL) {
throw new CrmebException(OrderResultCode.ORDER_CANCEL);
}
if (order.getPaid()) {
throw new CrmebException(OrderResultCode.ORDER_PAID);
}
if (order.getStatus() > OrderConstants.ORDER_STATUS_WAIT_PAY) {
throw new CrmebException(OrderResultCode.ORDER_STATUS_ABNORMAL);
}
MerchantOrder merchantOrder = merchantOrderService.getOneByOrderNo(orderNo);
CashierInfoResponse response = new CashierInfoResponse();
response.setPayPrice(order.getPayPrice());
response.setTotalNum(order.getTotalNum());
response.setConsigneeName(merchantOrder.getRealName());
response.setConsigneePhone(merchantOrder.getUserPhone());
response.setConsigneeAddress(merchantOrder.getUserAddress());
DateTime cancelDate = DateUtil.offsetMinute(order.getCreateTime(), crmebConfig.getOrderCancelTime());
response.setCancelDateTime(cancelDate.getTime());
return response;
}
/**
* 查询微信支付结果
*/
@Override
public Boolean queryWechatPaymentResult(WechatPaymentQueryRequest request) {
if (request.getOrderType().equals(PayConstants.PAY_SERVICE_TYPE_ORDER)) {
return queryWechatPayResult(request.getOrderNo());
}
if (request.getOrderType().equals(PayConstants.PAY_SERVICE_TYPE_SVIP)) {
return querySvipWechatPayResult(request.getOrderNo());
}
return queryRechargeWechatPayResult(request.getOrderNo());
}
private Boolean queryRechargeWechatPayResult(String orderNo) {
RechargeOrder rechargeOrder = rechargeOrderService.getByOrderNo(orderNo);
if (ObjectUtil.isNull(rechargeOrder)) {
throw new CrmebException(OrderResultCode.ORDER_NOT_EXIST);
}
if (!rechargeOrder.getPayType().equals(PayConstants.PAY_TYPE_WE_CHAT)) {
throw new CrmebException(CommonResultCode.VALIDATE_FAILED, "不是微信支付类型订单");
}
if (rechargeOrder.getPaid()) {
return Boolean.TRUE;
}
WechatPayInfo wechatPayInfo = wechatPayInfoService.getByNo(rechargeOrder.getOutTradeNo());
if (ObjectUtil.isNull(wechatPayInfo)) {
throw new CrmebException(CommonResultCode.VALIDATE_FAILED, "未找到对应微信订单");
}
Map<String, String> payVo = getWechatQueryPayVo(rechargeOrder.getOutTradeNo(), rechargeOrder.getPayChannel());
MyRecord myRecord = wechatService.payOrderQuery(payVo);
if (myRecord.getInt("payStatus") < 1) {
return Boolean.FALSE;
}
wechatPayInfo.setIsSubscribe(myRecord.getStr("is_subscribe"));
wechatPayInfo.setTradeState(myRecord.getStr("trade_state"));
wechatPayInfo.setBankType(myRecord.getStr("bank_type"));
wechatPayInfo.setCashFee(myRecord.getInt("cash_fee"));
wechatPayInfo.setCouponFee(myRecord.getInt("coupon_fee"));
wechatPayInfo.setTransactionId(myRecord.getStr("transaction_id"));
wechatPayInfo.setTimeEnd(myRecord.getStr("time_end"));
wechatPayInfo.setTradeStateDesc(myRecord.getStr("trade_state_desc"));
Boolean updatePaid = transactionTemplate.execute(e -> {
Boolean update = rechargeOrderService.paySuccessAfter(rechargeOrder);
if (!update) {
logger.error("充值订单支付处理结果失败,orderNo = {}", rechargeOrder.getOrderNo());
e.setRollbackOnly();
return false;
}
wechatPayInfoService.updateById(wechatPayInfo);
return Boolean.TRUE;
});
if (!updatePaid) {
throw new CrmebException("充值支付成功更新订单失败");
}
return Boolean.TRUE;
}
/**
* 查询svip订单微信支付结果
*/
private Boolean querySvipWechatPayResult(String orderNo) {
PaidMemberOrder order = paidMemberOrderService.getByOrderNo(orderNo);
if (ObjectUtil.isNull(order)) {
throw new CrmebException(MemberResultCode.PAID_MEMBER_ORDER_NOT_EXIST);
}
if (!order.getPayType().equals(PayConstants.PAY_TYPE_WE_CHAT)) {
throw new CrmebException(CommonResultCode.VALIDATE_FAILED, "不是微信支付类型订单");
}
if (order.getPaid()) {
return Boolean.TRUE;
}
WechatPayInfo wechatPayInfo = wechatPayInfoService.getByNo(order.getOutTradeNo());
if (ObjectUtil.isNull(wechatPayInfo)) {
throw new CrmebException(CommonResultCode.VALIDATE_FAILED, "未找到对应微信订单");
}
Map<String, String> payVo = getWechatQueryPayVo(order.getOutTradeNo(), order.getPayChannel());
MyRecord myRecord = wechatService.payOrderQuery(payVo);
if (myRecord.getInt("payStatus") < 1) {
return Boolean.FALSE;
}
wechatPayInfo.setIsSubscribe(myRecord.getStr("is_subscribe"));
wechatPayInfo.setTradeState(myRecord.getStr("trade_state"));
wechatPayInfo.setBankType(myRecord.getStr("bank_type"));
wechatPayInfo.setCashFee(myRecord.getInt("cash_fee"));
wechatPayInfo.setCouponFee(myRecord.getInt("coupon_fee"));
wechatPayInfo.setTransactionId(myRecord.getStr("transaction_id"));
wechatPayInfo.setTimeEnd(myRecord.getStr("time_end"));
wechatPayInfo.setTradeStateDesc(myRecord.getStr("trade_state_desc"));
Boolean updatePaid = transactionTemplate.execute(e -> {
Boolean update = paidMemberOrderService.paySuccessAfter(order);
if (!update) {
logger.error("svip订单支付处理结果失败,orderNo = {}", order.getOrderNo());
e.setRollbackOnly();
return false;
}
wechatPayInfoService.updateById(wechatPayInfo);
return Boolean.TRUE;
});
if (!updatePaid) {
throw new CrmebException("svip支付成功更新订单失败");
}
return Boolean.TRUE;
}
/**
* 发送消息通知
* 根据用户类型发送
* 公众号模板消息
* 小程序订阅消息
*/
private void pushMessageOrder(Order order, User user, SystemNotification payNotification) {
logger.info("发送微信模板消息,订单编号:" + order.getOrderNo());
if (order.getPayChannel().equals(PayConstants.PAY_CHANNEL_H5)) {// H5
return;
}
UserToken userToken;
HashMap<String, String> temMap = new HashMap<>();
if (!order.getPayType().equals(PayConstants.PAY_TYPE_WE_CHAT)) {
return;
}
List<OrderDetail> orderDetailList = orderDetailService.getByOrderNo(order.getOrderNo());
// 公众号模板消息
if (order.getPayChannel().equals(PayConstants.PAY_CHANNEL_WECHAT_PUBLIC) && payNotification.getIsWechat().equals(1) && user.getIsWechatPublic()) {
userToken = userTokenService.getTokenByUserId(user.getId(), UserConstants.USER_TOKEN_TYPE_WECHAT);
if (ObjectUtil.isNull(userToken)) {
return;
}
// 发送微信模板消息
/**
* {{first.DATA}}
* 订单号:{{keyword1.DATA}}
* 商品名称:{{keyword2.DATA}}
* 支付金额:{{keyword3.DATA}}
* 下单人:{{keyword4.DATA}}
* 订单支付时间:{{keyword5.DATA}}
* {{remark.DATA}}
*/
temMap.put(Constants.WE_CHAT_TEMP_KEY_FIRST, "订单支付成功通知!");
temMap.put("keyword1", order.getOrderNo());
temMap.put("keyword2", orderDetailList.stream().map(OrderDetail::getProductName).collect(Collectors.joining(",")));
temMap.put("keyword3", order.getPayPrice().toString());
temMap.put("keyword4", user.getNickname());
temMap.put("keyword5", order.getPayTime().toString());
temMap.put(Constants.WE_CHAT_TEMP_KEY_END, "欢迎下次再来!");
templateMessageService.pushTemplateMessage(payNotification.getWechatId(), temMap, userToken.getToken());
return;
}
if (order.getPayChannel().equals(PayConstants.PAY_CHANNEL_WECHAT_MINI) && payNotification.getIsRoutine().equals(1)) {
// 小程序发送订阅消息
userToken = userTokenService.getTokenByUserId(user.getId(), UserConstants.USER_TOKEN_TYPE_ROUTINE);
if (ObjectUtil.isNull(userToken)) {
return;
}
// 组装数据
// temMap.put("character_string1", storeOrder.getOrderId());
// temMap.put("amount2", storeOrder.getPayPrice().toString() + "元");
// temMap.put("thing7", "您的订单已支付成功");
temMap.put("character_string3", order.getOrderNo());
temMap.put("amount9", order.getPayPrice().toString() + "元");
temMap.put("thing6", "您的订单已支付成功");
templateMessageService.pushMiniTemplateMessage(payNotification.getRoutineId(), temMap, userToken.getToken());
}
}
/**
* 佣金处理
*
* @param merchantOrder 商户订单部分
* @param orderDetailList 订单详情列表
* @return 佣金记录列表
*/
private List<UserBrokerageRecord> assignCommission(MerchantOrder merchantOrder, List<OrderDetail> orderDetailList) {
// 秒杀订单不参与分佣
if (merchantOrder.getType().equals(OrderConstants.ORDER_TYPE_SECKILL)) {
return CollUtil.newArrayList();
}
// 检测商城是否开启分销功能
String isOpen = systemConfigService.getValueByKey(SysConfigConstants.RETAIL_STORE_SWITCH);
if (StrUtil.isBlank(isOpen) || isOpen.equals("0")) {
return CollUtil.newArrayList();
}
long count = orderDetailList.stream().filter(e -> e.getSubBrokerageType() > 0).count();
if (count == 0L) {
return CollUtil.newArrayList();
}
// 查找订单所属人信息
User user = userService.getById(merchantOrder.getUid());
// 当前用户不存在 没有上级 或者 当用用户上级时自己 直接返回
if (ObjectUtil.isNull(user.getSpreadUid()) || user.getSpreadUid() < 1 || user.getSpreadUid().equals(merchantOrder.getUid())) {
return CollUtil.newArrayList();
}
// 获取参与分佣的人(两级)
List<MyRecord> spreadRecordList = getSpreadRecordList(user.getSpreadUid());
if (CollUtil.isEmpty(spreadRecordList)) {
return CollUtil.newArrayList();
}
// 获取佣金冻结期
String freezingTime = systemConfigService.getValueByKey(SysConfigConstants.RETAIL_STORE_BROKERAGE_FREEZING_TIME);
List<UserBrokerageRecord> brokerageRecordList = new ArrayList<>();
// 计算两级佣金金额
if (spreadRecordList.size() == 1) {
BigDecimal firstBrokerage = BigDecimal.ZERO;
for (OrderDetail orderDetail : orderDetailList) {
if (orderDetail.getSubBrokerageType().equals(0)) {
continue;
}
BigDecimal detailPrice = (orderDetail.getIsSvip() && orderDetail.getIsPaidMemberProduct()) ? orderDetail.getVipPrice() : orderDetail.getPrice();
BigDecimal brokerage = detailPrice.multiply(new BigDecimal(orderDetail.getPayNum().toString()))
.subtract(orderDetail.getMerCouponPrice())
.multiply(new BigDecimal(orderDetail.getBrokerage().toString()))
.divide(new BigDecimal("100"), 2, BigDecimal.ROUND_DOWN);
orderDetail.setFirstBrokerageFee(brokerage);
firstBrokerage = firstBrokerage.add(brokerage);
}
merchantOrder.setFirstBrokerage(firstBrokerage);
UserBrokerageRecord brokerageRecord = new UserBrokerageRecord();
brokerageRecord.setUid(spreadRecordList.get(0).getInt("spreadUid"));
brokerageRecord.setSubUid(merchantOrder.getUid());
brokerageRecord.setLinkNo(merchantOrder.getOrderNo());
brokerageRecord.setLinkType(BrokerageRecordConstants.BROKERAGE_RECORD_LINK_TYPE_ORDER);
brokerageRecord.setType(BrokerageRecordConstants.BROKERAGE_RECORD_TYPE_ADD);
brokerageRecord.setTitle(BrokerageRecordConstants.BROKERAGE_RECORD_TITLE_ORDER);
brokerageRecord.setPrice(firstBrokerage);
brokerageRecord.setMark(StrUtil.format("获得推广佣金,分佣{}", firstBrokerage));
brokerageRecord.setStatus(BrokerageRecordConstants.BROKERAGE_RECORD_STATUS_CREATE);
brokerageRecord.setFrozenTime(Integer.valueOf(Optional.ofNullable(freezingTime).orElse("0")));
brokerageRecord.setCreateTime(CrmebDateUtil.nowDateTime());
brokerageRecord.setBrokerageLevel(spreadRecordList.get(0).getInt("index"));
brokerageRecordList.add(brokerageRecord);
return brokerageRecordList;
}
BigDecimal firstBrokerage = BigDecimal.ZERO;
BigDecimal secondBrokerage = BigDecimal.ZERO;
for (OrderDetail orderDetail : orderDetailList) {
if (orderDetail.getSubBrokerageType().equals(0)) {
continue;
}
BigDecimal detailPrice = (orderDetail.getIsSvip() && orderDetail.getIsPaidMemberProduct()) ? orderDetail.getVipPrice() : orderDetail.getPrice();
BigDecimal brokerage = detailPrice.multiply(new BigDecimal(orderDetail.getPayNum().toString()))
.subtract(orderDetail.getMerCouponPrice())
.multiply(new BigDecimal(orderDetail.getBrokerage().toString()))
.divide(new BigDecimal("100"), 2, BigDecimal.ROUND_DOWN);
BigDecimal brokerageTwo = detailPrice.multiply(new BigDecimal(orderDetail.getPayNum().toString()))
.subtract(orderDetail.getMerCouponPrice())
.multiply(new BigDecimal(orderDetail.getBrokerageTwo().toString()))
.divide(new BigDecimal("100"), 2, BigDecimal.ROUND_DOWN);
orderDetail.setFirstBrokerageFee(brokerage);
orderDetail.setSecondBrokerageFee(brokerageTwo);
firstBrokerage = firstBrokerage.add(brokerage);
secondBrokerage = secondBrokerage.add(brokerageTwo);
}
merchantOrder.setFirstBrokerage(firstBrokerage);
merchantOrder.setSecondBrokerage(secondBrokerage);
// 生成佣金记录
brokerageRecordList = spreadRecordList.stream().map(record -> {
UserBrokerageRecord brokerageRecord = new UserBrokerageRecord();
brokerageRecord.setUid(record.getInt("spreadUid"));
brokerageRecord.setSubUid(merchantOrder.getUid());
brokerageRecord.setLinkNo(merchantOrder.getOrderNo());
brokerageRecord.setLinkType(BrokerageRecordConstants.BROKERAGE_RECORD_LINK_TYPE_ORDER);
brokerageRecord.setType(BrokerageRecordConstants.BROKERAGE_RECORD_TYPE_ADD);
brokerageRecord.setTitle(BrokerageRecordConstants.BROKERAGE_RECORD_TITLE_ORDER);
BigDecimal price = record.getInt("index") == 1 ? merchantOrder.getFirstBrokerage() : merchantOrder.getSecondBrokerage();
brokerageRecord.setPrice(price);
brokerageRecord.setMark(StrUtil.format("获得推广佣金,分佣{}", price));
brokerageRecord.setStatus(BrokerageRecordConstants.BROKERAGE_RECORD_STATUS_CREATE);
brokerageRecord.setFrozenTime(Integer.valueOf(Optional.ofNullable(freezingTime).orElse("0")));
brokerageRecord.setCreateTime(CrmebDateUtil.nowDateTime());
brokerageRecord.setBrokerageLevel(record.getInt("index"));
return brokerageRecord;
}).collect(Collectors.toList());
return brokerageRecordList;
}
/**
* 获取参与分佣人员(两级)
*
* @param spreadUid 一级分佣人Uid
* @return List<MyRecord>
*/
private List<MyRecord> getSpreadRecordList(Integer spreadUid) {
List<MyRecord> recordList = CollUtil.newArrayList();
// 第一级
User spreadUser = userService.getById(spreadUid);
if (ObjectUtil.isNull(spreadUser) || !spreadUser.getIsPromoter()) {
return recordList;
}
MyRecord firstRecord = new MyRecord();
firstRecord.set("index", 1);
firstRecord.set("spreadUid", spreadUid);
recordList.add(firstRecord);
// 第二级
User spreadSpreadUser = userService.getById(spreadUser.getSpreadUid());
if (ObjectUtil.isNull(spreadSpreadUser) || !spreadSpreadUser.getIsPromoter()) {
return recordList;
}
MyRecord secondRecord = new MyRecord();
secondRecord.set("index", 2);
secondRecord.set("spreadUid", spreadSpreadUser.getId());
recordList.add(secondRecord);
return recordList;
}
/**
* 初始化订单分帐表
*
* @param merchantOrder 商户部分订单
* @return 分账记录
*/
private OrderProfitSharing initOrderProfitSharing(MerchantOrder merchantOrder) {
// 获取商户信息
Merchant merchant = merchantService.getByIdException(merchantOrder.getMerId());
// 分账计算
// 商户收入 = 订单应付 - 商户优惠 -平台手续费 - 佣金
BigDecimal orderPrice = merchantOrder.getPayPrice().add(merchantOrder.getIntegralPrice()).add(merchantOrder.getPlatCouponPrice()).subtract(merchantOrder.getPayPostage());
// 平台手续费
BigDecimal platFee = orderPrice.multiply(new BigDecimal(merchant.getHandlingFee())).divide(new BigDecimal(100), 2, BigDecimal.ROUND_UP);
// 商户收入金额
BigDecimal merchantFee = orderPrice.subtract(platFee).subtract(merchantOrder.getFirstBrokerage()).subtract(merchantOrder.getSecondBrokerage());
OrderProfitSharing orderProfitSharing = new OrderProfitSharing();
orderProfitSharing.setOrderNo(merchantOrder.getOrderNo());
orderProfitSharing.setMerId(merchantOrder.getMerId());
//查询attr
Order order = orderService.getByOrderNo(merchantOrder.getOrderNo());
if(Objects.nonNull(order)){
BigDecimal costTotalPrice = order.getCostTotalPrice();
orderProfitSharing.setOrderCostPrice(costTotalPrice);
}else{
orderProfitSharing.setOrderCostPrice(BigDecimal.ZERO);
}
orderProfitSharing.setOrderPrice(merchantOrder.getPayPrice());
orderProfitSharing.setIntegralNum(merchantOrder.getUseIntegral());
orderProfitSharing.setIntegralPrice(merchantOrder.getIntegralPrice());
orderProfitSharing.setProfitSharingPlatPrice(platFee);
orderProfitSharing.setProfitSharingMerPrice(merchantFee);
orderProfitSharing.setFirstBrokerageFee(merchantOrder.getFirstBrokerage());
orderProfitSharing.setSecondBrokerageFee(merchantOrder.getSecondBrokerage());
orderProfitSharing.setPlatCouponPrice(merchantOrder.getPlatCouponPrice());
orderProfitSharing.setFreightFee(merchantOrder.getPayPostage());
return orderProfitSharing;
}
/**
* 初始化订单支付商户账单表
*
* @param merchantOrder 商户订单部分
* @param merchantFee 商户分账金额
*/
private MerchantBill initPayMerchantBill(MerchantOrder merchantOrder, BigDecimal merchantFee) {
MerchantBill merchantBill = new MerchantBill();
merchantBill.setMerId(merchantOrder.getMerId());
merchantBill.setType(BillConstants.BILL_TYPE_PAY_ORDER);
merchantBill.setOrderNo(merchantOrder.getOrderNo());
merchantBill.setUid(merchantOrder.getUid());
merchantBill.setPm(BillConstants.BILL_PM_ADD);
BigDecimal merFee = merchantOrder.getPayPostage().add(merchantFee);
merchantBill.setAmount(merFee);
merchantBill.setMark(StrUtil.format("订单{}支付{}元,商户收入{}元", merchantOrder.getOrderNo(), merchantOrder.getPayPrice(), merFee));
return merchantBill;
}
/**
* 初始化订单支付平台账单表
*
* @param order 订单
* @param merchantOrder 商户订单部分
* @param orderProfitSharing 分账数据
* @return List
*/
private List<Bill> initPlatformBill(Order order, MerchantOrder merchantOrder, OrderProfitSharing orderProfitSharing) {
List<Bill> billList = CollUtil.newArrayList();
Bill payBill = new Bill();
payBill.setUid(order.getUid());
payBill.setOrderNo(order.getOrderNo());
payBill.setAmount(order.getPayPrice());
if (order.getPayType().equals(PayConstants.PAY_TYPE_YUE)) {
payBill.setPm(BillConstants.BILL_PM_SUB);
payBill.setType(BillConstants.BILL_TYPE_YUE_PAY);
payBill.setMark(StrUtil.format("余额支付成功,扣除用户余额{}元", order.getPayPrice()));
} else {
payBill.setPm(BillConstants.BILL_PM_ADD);
payBill.setType(BillConstants.BILL_TYPE_PAY_ORDER);
payBill.setMark(StrUtil.format("订单支付成功,支付金额{}元", order.getPayPrice()));
}
billList.add(payBill);
// Bill collectBill = new Bill();
// collectBill.setMerId(merchantOrder.getMerId());
// collectBill.setOrderNo(order.getOrderNo());
// collectBill.setAmount(orderProfitSharing.getProfitSharingMerPrice().add(merchantOrder.getPayPostage()));
// collectBill.setPm(BillConstants.BILL_PM_SUB);
// collectBill.setType(BillConstants.BILL_TYPE_MERCHANT_COLLECT);
// collectBill.setMark(StrUtil.format("订单支付成功,商户分账{}元", orderProfitSharing.getProfitSharingMerPrice().add(merchantOrder.getPayPostage())));
// billList.add(collectBill);
// Bill platBill = new Bill();
// platBill.setOrderNo(order.getOrderNo());
// platBill.setAmount(orderProfitSharing.getProfitSharingPlatPrice());
// platBill.setPm(BillConstants.BILL_PM_ADD);
// platBill.setType(BillConstants.BILL_TYPE_PAY_ORDER);
// platBill.setMark(StrUtil.format("订单支付成功,平台手续费{}元", orderProfitSharing.getProfitSharingPlatPrice()));
// billList.add(platBill);
if (ObjectUtil.isNotNull(orderProfitSharing.getFirstBrokerageFee()) && orderProfitSharing.getFirstBrokerageFee().compareTo(BigDecimal.ZERO) > 0) {
Bill firstBill = new Bill();
firstBill.setOrderNo(order.getOrderNo());
firstBill.setAmount(orderProfitSharing.getFirstBrokerageFee());
firstBill.setPm(BillConstants.BILL_PM_SUB);
firstBill.setType(BillConstants.BILL_TYPE_BROKERAGE);
firstBill.setMark(StrUtil.format("订单支付成功,分配一级佣金{}元", orderProfitSharing.getFirstBrokerageFee()));
billList.add(firstBill);
if (orderProfitSharing.getSecondBrokerageFee().compareTo(BigDecimal.ZERO) > 0) {
Bill secondBill = new Bill();
secondBill.setOrderNo(order.getOrderNo());
secondBill.setAmount(orderProfitSharing.getSecondBrokerageFee());
secondBill.setPm(BillConstants.BILL_PM_SUB);
secondBill.setType(BillConstants.BILL_TYPE_BROKERAGE);
secondBill.setMark(StrUtil.format("订单支付成功,分配二级佣金{}元", orderProfitSharing.getSecondBrokerageFee()));
billList.add(secondBill);
}
}
if (orderProfitSharing.getIntegralNum() > 0) {
Bill integralBill = new Bill();
integralBill.setOrderNo(order.getOrderNo());
integralBill.setAmount(order.getIntegralPrice());
integralBill.setPm(BillConstants.BILL_PM_SUB);
integralBill.setType(BillConstants.BILL_TYPE_PAY_ORDER);
integralBill.setMark(StrUtil.format("订单支付成功,用户使用{}积分抵扣{}元,平台扣除", orderProfitSharing.getIntegralNum(), orderProfitSharing.getIntegralPrice()));
billList.add(integralBill);
}
return billList;
}
/**
* 初始化积分赠送记录
*/
private UserIntegralRecord integralRecordGainInit(Integer uid, String orderNo, Integer gainIntegral) {
UserIntegralRecord integralRecord = new UserIntegralRecord();
integralRecord.setUid(uid);
integralRecord.setLinkId(orderNo);
integralRecord.setLinkType(IntegralRecordConstants.INTEGRAL_RECORD_LINK_TYPE_ORDER);
integralRecord.setType(IntegralRecordConstants.INTEGRAL_RECORD_TYPE_ADD);
integralRecord.setTitle(IntegralRecordConstants.INTEGRAL_RECORD_TITLE_ORDER);
integralRecord.setIntegral(gainIntegral);
// integralRecord.setBalance(balance);
integralRecord.setMark(StrUtil.format("订单支付成功奖励{}积分", gainIntegral));
integralRecord.setStatus(IntegralRecordConstants.INTEGRAL_RECORD_STATUS_CREATE);
// 获取积分冻结期
String freezeTime = systemConfigService.getValueByKey(SysConfigConstants.CONFIG_KEY_STORE_INTEGRAL_EXTRACT_TIME);
integralRecord.setFrozenTime(Integer.valueOf(Optional.ofNullable(freezeTime).orElse("0")));
integralRecord.setCreateTime(CrmebDateUtil.nowDateTime());
return integralRecord;
}
private Map<String, String> getWechatQueryPayVo(String outTradeNo, String payChannel) {
// 获取appid、mch_id
// 微信签名key
String appId = "";
String mchId = "";
String signKey = "";
switch (payChannel) {
case PayConstants.PAY_CHANNEL_WECHAT_PUBLIC:
case PayConstants.PAY_CHANNEL_H5:// H5使用公众号的信息
case PayConstants.PAY_CHANNEL_WECHAT_NATIVE:// H5使用公众号的信息
appId = systemConfigService.getValueByKeyException(WeChatConstants.WECHAT_PUBLIC_APPID);
mchId = systemConfigService.getValueByKeyException(WeChatConstants.WECHAT_PAY_PUBLIC_MCHID);
signKey = systemConfigService.getValueByKeyException(WeChatConstants.WECHAT_PAY_PUBLIC_KEY);
break;
case PayConstants.PAY_CHANNEL_WECHAT_MINI:
appId = systemConfigService.getValueByKeyException(WeChatConstants.WECHAT_MINI_APPID);
mchId = systemConfigService.getValueByKeyException(WeChatConstants.WECHAT_PAY_MINI_MCHID);
signKey = systemConfigService.getValueByKeyException(WeChatConstants.WECHAT_PAY_MINI_KEY);
break;
case PayConstants.PAY_CHANNEL_WECHAT_APP_IOS:
case PayConstants.PAY_CHANNEL_WECHAT_APP_ANDROID:
appId = systemConfigService.getValueByKeyException(WeChatConstants.WECHAT_APP_APPID);
mchId = systemConfigService.getValueByKeyException(WeChatConstants.WECHAT_PAY_APP_MCHID);
signKey = systemConfigService.getValueByKeyException(WeChatConstants.WECHAT_PAY_APP_KEY);
break;
}
// 生成查询订单对象
Map<String, String> map = CollUtil.newHashMap();
map.put("appid", appId);
map.put("mch_id", mchId);
map.put("out_trade_no", outTradeNo);
map.put("nonce_str", WxPayUtil.getNonceStr());
map.put("sign_type", PayConstants.WX_PAY_SIGN_TYPE_MD5);
map.put("sign", WxPayUtil.getSign(map, signKey));
return map;
}
/**
* 支付宝支付
*
* @param order 订单
* @return result
*/
private String aliPayment(Order order) {
DateTime cancelTime = DateUtil.offset(order.getCreateTime(), DateField.MINUTE, crmebConfig.getOrderCancelTime());
String cancelStr = cancelTime.toString(DateConstants.DATE_FORMAT);
return aliPayService.pay(order.getOrderNo(), order.getPayPrice(), "order", order.getPayChannel(), cancelStr);
}
/**
* 微信支付
*
* @param order 订单
* @return WxPayJsResultVo
*/
private WxPayJsResultVo wechatPayment(Order order) {
// 预下单
Map<String, String> unifiedorder = unifiedorder(order);
WxPayJsResultVo vo = new WxPayJsResultVo();
vo.setAppId(unifiedorder.get("appId"));
vo.setNonceStr(unifiedorder.get("nonceStr"));
vo.setPackages(unifiedorder.get("package"));
vo.setSignType(unifiedorder.get("signType"));
vo.setTimeStamp(unifiedorder.get("timeStamp"));
vo.setPaySign(unifiedorder.get("paySign"));
if (order.getPayChannel().equals(PayConstants.PAY_CHANNEL_H5)) {
vo.setMwebUrl(unifiedorder.get("mweb_url"));
}
if (order.getPayChannel().equals(PayConstants.PAY_CHANNEL_WECHAT_APP_IOS) ||
order.getPayChannel().equals(PayConstants.PAY_CHANNEL_WECHAT_APP_ANDROID)) {// App
vo.setPartnerid(unifiedorder.get("partnerid"));
}
if (order.getPayChannel().equals(PayConstants.PAY_CHANNEL_WECHAT_NATIVE)) {
vo.setMwebUrl(unifiedorder.get("code_url"));
}
order.setOutTradeNo(unifiedorder.get("outTradeNo"));
// 更新商户订单号
vo.setOutTradeNo(unifiedorder.get("outTradeNo"));
return vo;
}
/**
* 余额支付
*
* @param order 订单
* @return Boolean Boolean
*/
private Boolean yuePay(Order order, User user) {
// 用户余额扣除
Boolean execute = transactionTemplate.execute(e -> {
Boolean update = Boolean.TRUE;
// 订单修改
order.setPaid(true);
order.setPayTime(DateUtil.date());
order.setStatus(OrderConstants.ORDER_STATUS_WAIT_SHIPPING);
orderService.updateById(order);
// 这里只扣除金额,账单记录在task中处理
if (order.getPayPrice().compareTo(BigDecimal.ZERO) > 0) {
update = userService.updateNowMoney(order.getUid(), order.getPayPrice(), Constants.OPERATION_TYPE_SUBTRACT);
if (!update) {
logger.error("余额支付,扣除用户余额失败,orderNo = {}", order.getOrderNo());
e.setRollbackOnly();
return update;
}
sendPayment(order.getWwOrderNo(),order.getOrderNo());
// 用户余额记录
UserBalanceRecord userBalanceRecord = new UserBalanceRecord();
userBalanceRecord.setUid(user.getId());
userBalanceRecord.setLinkId(order.getOrderNo());
userBalanceRecord.setLinkType(BalanceRecordConstants.BALANCE_RECORD_LINK_TYPE_ORDER);
userBalanceRecord.setType(BalanceRecordConstants.BALANCE_RECORD_TYPE_SUB);
userBalanceRecord.setAmount(order.getPayPrice());
userBalanceRecord.setBalance(user.getNowMoney().subtract(order.getPayPrice()));
userBalanceRecord.setRemark(StrUtil.format(BalanceRecordConstants.BALANCE_RECORD_REMARK_ORDER, order.getPayPrice()));
userBalanceRecordService.save(userBalanceRecord);
}
return update;
});
if (!execute) throw new CrmebException("余额支付订单失败");
//通知万物
noticeWw(order.getWwOrderNo(), order.getOrderNo());
asyncService.orderPaySuccessSplit(order.getOrderNo());
return true;
}
/**
* 预下单
*
* @param order 订单
* @return 预下单返回对象
*/
private Map<String, String> unifiedorder(Order order) {
// 获取用户openId
// 根据订单支付类型来判断获取公众号openId还是小程序openId
UserToken userToken = new UserToken();
userToken.setToken("");
if (order.getPayChannel().equals(PayConstants.PAY_CHANNEL_WECHAT_PUBLIC)) {// 公众号
userToken = userTokenService.getTokenByUserId(order.getUid(), UserConstants.USER_TOKEN_TYPE_WECHAT);
}
if (order.getPayChannel().equals(PayConstants.PAY_CHANNEL_WECHAT_MINI)
|| order.getPayChannel().equals(PayConstants.PAY_CHANNEL_WECHAT_MINI_VIDEO)) {// 小程序
userToken = userTokenService.getTokenByUserId(order.getUid(), UserConstants.USER_TOKEN_TYPE_ROUTINE);
}
// 获取appid、mch_id、微信签名key
String appId = "";
String mchId = "";
String signKey = "";
switch (order.getPayChannel()) {
case PayConstants.PAY_CHANNEL_WECHAT_PUBLIC:
case PayConstants.PAY_CHANNEL_H5:// H5使用公众号的信息
case PayConstants.PAY_CHANNEL_WECHAT_NATIVE:// H5使用公众号的信息
appId = systemConfigService.getValueByKeyException(WeChatConstants.WECHAT_PUBLIC_APPID);
mchId = systemConfigService.getValueByKeyException(WeChatConstants.WECHAT_PAY_PUBLIC_MCHID);
signKey = systemConfigService.getValueByKeyException(WeChatConstants.WECHAT_PAY_PUBLIC_KEY);
break;
case PayConstants.PAY_CHANNEL_WECHAT_MINI:
case PayConstants.PAY_CHANNEL_WECHAT_MINI_VIDEO:
appId = systemConfigService.getValueByKeyException(WeChatConstants.WECHAT_MINI_APPID);
mchId = systemConfigService.getValueByKeyException(WeChatConstants.WECHAT_PAY_MINI_MCHID);
signKey = systemConfigService.getValueByKeyException(WeChatConstants.WECHAT_PAY_MINI_KEY);
break;
case PayConstants.PAY_CHANNEL_WECHAT_APP_IOS:
case PayConstants.PAY_CHANNEL_WECHAT_APP_ANDROID:
appId = systemConfigService.getValueByKeyException(WeChatConstants.WECHAT_APP_APPID);
mchId = systemConfigService.getValueByKeyException(WeChatConstants.WECHAT_PAY_APP_MCHID);
signKey = systemConfigService.getValueByKeyException(WeChatConstants.WECHAT_PAY_APP_KEY);
break;
}
// 获取微信预下单对象
CreateOrderRequestVo unifiedorderVo = getUnifiedorderVo(order, userToken.getToken(), appId, mchId, signKey);
// 预下单(统一下单)
CreateOrderResponseVo responseVo = wechatService.payUnifiedorder(unifiedorderVo);
// 组装前端预下单参数
Map<String, String> map = new HashMap<>();
map.put("appId", unifiedorderVo.getAppid());
map.put("nonceStr", unifiedorderVo.getAppid());
map.put("package", "prepay_id=".concat(responseVo.getPrepayId()));
map.put("signType", unifiedorderVo.getSign_type());
Long currentTimestamp = WxPayUtil.getCurrentTimestamp();
map.put("timeStamp", Long.toString(currentTimestamp));
String paySign = WxPayUtil.getSign(map, signKey);
map.put("paySign", paySign);
map.put("prepayId", responseVo.getPrepayId());
map.put("prepayTime", CrmebDateUtil.nowDateTimeStr());
map.put("outTradeNo", unifiedorderVo.getOut_trade_no());
if (order.getPayChannel().equals(PayConstants.PAY_CHANNEL_H5)) {
map.put("mweb_url", responseVo.getMWebUrl());
}
if (order.getPayChannel().equals(PayConstants.PAY_CHANNEL_WECHAT_APP_IOS) ||
order.getPayChannel().equals(PayConstants.PAY_CHANNEL_WECHAT_APP_ANDROID)) {// App
map.put("partnerid", mchId);
map.put("package", responseVo.getPrepayId());
Map<String, Object> appMap = new HashMap<>();
appMap.put("appid", unifiedorderVo.getAppid());
appMap.put("partnerid", mchId);
appMap.put("prepayid", responseVo.getPrepayId());
appMap.put("package", "Sign=WXPay");
appMap.put("noncestr", unifiedorderVo.getAppid());
appMap.put("timestamp", currentTimestamp);
logger.info("================================================app支付签名,map = " + appMap);
String sign = WxPayUtil.getSignObject(appMap, signKey);
logger.info("================================================app支付签名,sign = " + sign);
map.put("paySign", sign);
}
if (order.getPayChannel().equals(PayConstants.PAY_CHANNEL_WECHAT_NATIVE)) {
map.put("code_url", responseVo.getCodeUrl());
}
return map;
}
/**
* 获取微信预下单对象
*
* @return 微信预下单对象
*/
private CreateOrderRequestVo getUnifiedorderVo(Order order, String openid, String appId, String mchId, String signKey) {
// 获取域名
String domain = systemConfigService.getValueByKeyException(SysConfigConstants.CONFIG_KEY_SITE_URL);
String apiDomain = systemConfigService.getValueByKeyException(SysConfigConstants.CONFIG_KEY_API_URL);
AttachVo attachVo = new AttachVo(PayConstants.PAY_SERVICE_TYPE_ORDER, order.getUid());
CreateOrderRequestVo vo = new CreateOrderRequestVo();
vo.setAppid(appId);
vo.setMch_id(mchId);
vo.setNonce_str(WxPayUtil.getNonceStr());
vo.setSign_type(PayConstants.WX_PAY_SIGN_TYPE_MD5);
String siteName = systemConfigService.getValueByKeyException(SysConfigConstants.CONFIG_KEY_SITE_NAME);
// 因商品名称在微信侧超长更换为网站名称
vo.setBody(siteName);
vo.setAttach(JSONObject.toJSONString(attachVo));
vo.setOut_trade_no(CrmebUtil.getOrderNo(OrderConstants.ORDER_PREFIX_WECHAT));
// 订单中使用的是BigDecimal,这里要转为Integer类型
vo.setTotal_fee(order.getPayPrice().multiply(BigDecimal.TEN).multiply(BigDecimal.TEN).intValue());
vo.setSpbill_create_ip(RequestUtil.getClientIp());
vo.setNotify_url(apiDomain + PayConstants.WX_PAY_NOTIFY_API_URI);
switch (order.getPayChannel()) {
case PayConstants.PAY_CHANNEL_H5:
vo.setTrade_type(PayConstants.WX_PAY_TRADE_TYPE_H5);
vo.setOpenid(null);
break;
case PayConstants.PAY_CHANNEL_WECHAT_APP_IOS:
case PayConstants.PAY_CHANNEL_WECHAT_APP_ANDROID:
vo.setTrade_type(PayConstants.WX_PAY_TRADE_TYPE_APP);
vo.setOpenid(null);
break;
case PayConstants.PAY_CHANNEL_WECHAT_NATIVE:
vo.setTrade_type(PayConstants.WX_PAY_TRADE_TYPE_NATIVE);
vo.setProduct_id(order.getOrderNo());
vo.setOpenid(null);
break;
default:
vo.setTrade_type(PayConstants.WX_PAY_TRADE_TYPE_JS);
vo.setOpenid(openid);
}
CreateOrderH5SceneInfoVo createOrderH5SceneInfoVo = new CreateOrderH5SceneInfoVo(
new CreateOrderH5SceneInfoDetailVo(
domain,
systemConfigService.getValueByKeyException(SysConfigConstants.CONFIG_KEY_SITE_NAME)
)
);
vo.setScene_info(JSONObject.toJSONString(createOrderH5SceneInfoVo));
vo.setTime_start(DateUtil.date().toString(DateConstants.DATE_TIME_FORMAT_NUM));
DateTime cancelTime = DateUtil.offset(order.getCreateTime(), DateField.MINUTE, crmebConfig.getOrderCancelTime());
String cancelStr = cancelTime.toString(DateConstants.DATE_TIME_FORMAT_NUM);
vo.setTime_expire(cancelStr);
String sign = WxPayUtil.getSign(vo, signKey);
vo.setSign(sign);
return vo;
}
/**
* 商品购买后根据配置送券
*/
private void autoSendCoupons(Order order) {
List<OrderDetail> orderDetailList = orderDetailService.getByOrderNo(order.getOrderNo());
if (CollUtil.isEmpty(orderDetailList)) {
return;
}
List<CouponUser> couponUserList = CollUtil.newArrayList();
Map<Integer, Boolean> couponMap = CollUtil.newHashMap();
List<Integer> proIdList = orderDetailList.stream().map(OrderDetail::getProductId).distinct().collect(Collectors.toList());
for (Integer proId : proIdList) {
List<ProductCoupon> couponsForGiveUser = productCouponService.getListByProductId(proId);
for (int i = 0; i < couponsForGiveUser.size(); ) {
ProductCoupon productCoupon = couponsForGiveUser.get(i);
MyRecord record = couponUserService.paySuccessGiveAway(productCoupon.getCouponId(), order.getUid());
if (record.getStr("status").equals("fail")) {
logger.error(StrUtil.format("支付成功领取优惠券失败,失败原因:{}", record.getStr("errMsg")));
couponsForGiveUser.remove(i);
continue;
}
CouponUser couponUser = record.get("couponUser");
couponUserList.add(couponUser);
couponMap.put(couponUser.getCouponId(), record.getBoolean("isLimited"));
i++;
}
}
Boolean execute = transactionTemplate.execute(e -> {
if (CollUtil.isNotEmpty(couponUserList)) {
couponUserService.saveBatch(couponUserList);
couponUserList.forEach(i -> couponService.deduction(i.getCouponId(), 1, couponMap.get(i.getCouponId())));
}
return Boolean.TRUE;
});
if (!execute) {
logger.error(StrUtil.format("支付成功领取优惠券,更新数据库失败,订单编号:{}", order.getOrderNo()));
}
}
}
package com.zbkj.service.service.credit;
import com.zbkj.common.model.credit.CreditOrderBill;
import com.zbkj.common.model.credit.CreditRepayOrder;
import com.zbkj.common.request.PageParamRequest;
import com.zbkj.common.request.credit.CreditOrderBillRequest;
import com.zbkj.common.request.credit.CreditOrderBillSearchRequest;
import com.baomidou.mybatisplus.extension.service.IService;
import com.zbkj.common.response.OrderPayResultResponse;
import com.zbkj.common.response.credit.CreditAmountInfoReponse;
import com.zbkj.common.response.credit.CreditOrderBillResponse;
import com.zbkj.common.response.credit.CreditOrderBillStaticReponse;
import com.zbkj.common.vo.MyRecord;
import java.util.List;
/**
* @author dudianlong
* @description CreditOrderBillService 接口
* @date 2024-11-21
*/
public interface CreditOrderBillService extends IService<CreditOrderBill> {
List<CreditOrderBillResponse> getList(CreditOrderBillSearchRequest request, PageParamRequest pageParamRequest);
CreditOrderBillResponse getDetail(String id);
CreditOrderBillStaticReponse monthAmountInfo(CreditOrderBillRequest request);
OrderPayResultResponse menthPayment(CreditOrderBillRequest request);
CreditOrderBill getByOrderNo(String orderNo);
CreditAmountInfoReponse getUserAmountInfo(Integer uid);
CreditRepayOrder create(CreditOrderBillRequest request);
Boolean updateCreditAmountAndCreditOrderBill(CreditRepayOrder order, Integer uid);
List<CreditOrderBill> getNoStartTask();
void updateRefundStatus(String wwOrderNo);
List<CreditOrderBill> getCreditRepaymentFlag();
boolean updateInfo(CreditOrderBillRequest creditOrderBillRequest);
}
package com.zbkj.service.service.impl.credit;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.github.pagehelper.PageHelper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zbkj.common.config.CrmebConfig;
import com.zbkj.common.constants.*;
import com.zbkj.common.exception.CrmebException;
import com.zbkj.common.model.admin.SystemAdmin;
import com.zbkj.common.model.bill.Bill;
import com.zbkj.common.model.credit.*;
import com.zbkj.common.model.order.OrderDetail;
import com.zbkj.common.model.user.User;
import com.zbkj.common.model.user.UserBalanceRecord;
import com.zbkj.common.model.user.UserToken;
import com.zbkj.common.request.PageParamRequest;
import com.zbkj.common.request.credit.CreditOrderBillRequest;
import com.zbkj.common.request.credit.CreditOrderBillSearchRequest;
import com.zbkj.common.response.OrderInfoFrontDataResponse;
import com.zbkj.common.response.OrderPayResultResponse;
import com.zbkj.common.response.credit.CreditAmountInfoReponse;
import com.zbkj.common.response.credit.CreditAmountResponse;
import com.zbkj.common.response.credit.CreditOrderBillResponse;
import com.zbkj.common.response.credit.CreditOrderBillStaticReponse;
import com.zbkj.common.utils.*;
import com.zbkj.common.vo.*;
import com.zbkj.service.dao.credit.CreditOrderBillDao;
import com.zbkj.service.dao.credit.CreditOrderBillRecordDao;
import com.zbkj.service.service.*;
import com.zbkj.service.service.credit.*;
import kong.unirest.HttpResponse;
import kong.unirest.Unirest;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate;
import javax.annotation.Resource;
import java.util.List;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
/**
* @author dudianlong
* @description CreditOrderBillServiceImpl 接口实现
* @date 2024-11-21
*/
@Service
public class CreditOrderBillServiceImpl extends ServiceImpl<CreditOrderBillDao, CreditOrderBill> implements CreditOrderBillService {
@Resource
private CreditOrderBillDao dao;
private static final Logger logger = LoggerFactory.getLogger(CreditOrderBillServiceImpl.class);
@Autowired
private CreditRepayOrderService creditRepayOrderService;
@Autowired
private RedisUtil redisUtil;
@Autowired
private UserService userService;
@Autowired
private TransactionTemplate transactionTemplate;
@Autowired
private UserBalanceRecordService userBalanceRecordService;
@Autowired
private UserTokenService userTokenService;
@Autowired
private WechatService wechatService;
@Autowired
private SystemConfigService systemConfigService;
@Autowired
private CrmebConfig crmebConfig;
@Autowired
private OrderDetailService orderDetailService;
@Autowired
private CreditAmountService creditAmountService;
@Autowired
private CreditBillInfoService creditBillInfoService;
@Autowired
private CreditOrderBillService creditOrderBillService;
@Autowired
private CreditOrderBillRecordDao creditOrderBillRecordDao;
@Autowired
private BillService billService;
/**
* 列表
* @param request 请求参数
* @param pageParamRequest 分页类参数
* @author dudianlong
* @since 2024-11-21
* @return List<CreditOrderBill>
*/
@Override
public List<CreditOrderBillResponse> getList(CreditOrderBillSearchRequest request, PageParamRequest pageParamRequest) {
if(pageParamRequest != null){
PageHelper.startPage(pageParamRequest.getPage(), pageParamRequest.getLimit());
}
List<CreditOrderBillResponse> list = dao.getList(request);
return list;
}
@Override
public CreditOrderBillResponse getDetail(String id) {
CreditOrderBillSearchRequest request = new CreditOrderBillSearchRequest();
request.setId(id);
List<CreditOrderBillResponse> list = getList(request, null);
if(CollectionUtils.isNotEmpty(list)){
CreditOrderBillResponse response = list.get(0);
List<OrderDetail> orderDetailList = orderDetailService.getByOrderNo(response.getOrderNo());
List<OrderInfoFrontDataResponse> orderInfoList = orderDetailList.stream().map(e -> {
OrderInfoFrontDataResponse dataResponse = new OrderInfoFrontDataResponse();
BeanUtils.copyProperties(e, dataResponse);
return dataResponse;
}).collect(Collectors.toList());
response.setOrderDetailList(orderInfoList);
//查询修改记录
LambdaQueryWrapper<CreditOrderBillRecord> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(CreditOrderBillRecord::getBillId, id);
List<CreditOrderBillRecord> recordList = creditOrderBillRecordDao.selectList(lambdaQueryWrapper);
response.setRecords(recordList);
return response;
}
return null;
}
@Override
public CreditOrderBillStaticReponse monthAmountInfo(CreditOrderBillRequest request) {
CreditOrderBillStaticReponse reponse=new CreditOrderBillStaticReponse();
LambdaQueryWrapper<CreditOrderBill> lambdaQueryWrapper = new LambdaQueryWrapper<>();
Integer uid = userService.getUserIdException();
//查询授信用户信息
CreditAmount creditAmount = creditAmountService.getByUserId(uid);
BeanUtils.copyProperties(creditAmount, reponse);
lambdaQueryWrapper.eq(CreditOrderBill::getUid, uid);
if(Objects.nonNull(request.getYear())){
//根据创建时间查询年的账单
lambdaQueryWrapper.eq(CreditOrderBill::getYear, request.getYear());
}
if(Objects.nonNull(request.getMonth())){
lambdaQueryWrapper.eq(CreditOrderBill::getMonth, request.getMonth());
}
if(Objects.nonNull(request.getCreditRepaymentFlag())){
lambdaQueryWrapper.eq(CreditOrderBill::getCreditRepaymentFlag, request.getCreditRepaymentFlag());
}
if(Objects.nonNull(request.getOrderNo())){
lambdaQueryWrapper.like(CreditOrderBill::getOrderNo, request.getOrderNo());
}
List<CreditOrderBill> list = this.dao.selectList(lambdaQueryWrapper);
//统计待还款金额
BigDecimal noAmount = list.stream().filter(e -> e.getCreditRepaymentFlag() == 0).map(CreditOrderBill::getPayPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
//统计已还款金额
BigDecimal paidAmount = list.stream().filter(e -> e.getCreditRepaymentFlag() == 1).map(CreditOrderBill::getPayPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
reponse.setFinishTotal(paidAmount);
reponse.setNoTotal(noAmount);
reponse.setCreditOrderBillList(list);
reponse.setContractStartDate(creditAmount.getContractStartDate());
reponse.setContractEndDate(creditAmount.getContractEndDate());
reponse.setSettle_term(creditAmount.getSettleTerm());
return reponse;
}
@Override
public OrderPayResultResponse menthPayment(CreditOrderBillRequest request) {
OrderPayResultResponse response = new OrderPayResultResponse();
response.setPayType(request.getPayType());
response.setPayChannel(request.getPayChannel());
User user = userService.getInfo();
String orderNo = request.getOrderNo();
CreditRepayOrder order = creditRepayOrderService.getByOrderNo(orderNo);
order.setPayChannel(request.getPayChannel());
order.setPayType(request.getPayType());
if(Objects.nonNull(order)){
Integer isPaid = order.getIsPaid();
if(isPaid==1){
throw new CrmebException("该订单已还款");
}
}
// 余额支付
if (request.getPayType().equals(PayConstants.PAY_TYPE_YUE)) {
Boolean yueBoolean = yuePay(order, user);
response.setStatus(yueBoolean);
logger.info("余额还款 response : {}", JSON.toJSONString(response));
return response;
}
// 微信支付,调用微信预下单,返回拉起微信支付需要的信息
if (request.getPayType().equals(PayConstants.PAY_TYPE_WE_CHAT)) {
//查询redis支付有支付订单
WxPayJsResultVo vo = wechatPayment(order);
logger.info("还款信息 微信下单的商户订单号:{}",vo.getOutTradeNo());
order.setOutTradeNo(vo.getOutTradeNo());
creditRepayOrderService.updateById(order);
response.setStatus(true);
response.setJsConfig(vo);
response.setOutTradeNo(vo.getOutTradeNo());
logger.info("还款信息 微信下单 response :{}", JSON.toJSONString(response));
return response;
}
response.setStatus(false);
logger.info("还款信息 END response:{}", JSON.toJSONString(response));
return response;
}
@Override
public CreditOrderBill getByOrderNo(String orderNo) {
CreditOrderBill orderBill = this.getOne(new LambdaQueryWrapper<CreditOrderBill>().eq(CreditOrderBill::getOrderNo, orderNo));
return orderBill;
}
@Override
public CreditAmountInfoReponse getUserAmountInfo(Integer uid) {
//查询用户授信的基本信息
CreditAmount creditAmount=creditAmountService.getByUserId(uid);
if(Objects.nonNull(creditAmount)){
CreditAmountInfoReponse creditAmountInfoReponse=new CreditAmountInfoReponse();
BeanUtils.copyProperties(creditAmount,creditAmountInfoReponse);
//查询用户的所有账单信息
LambdaQueryWrapper<CreditOrderBill> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(CreditOrderBill::getUid,uid);
//计算每个月需要还款的总金额是多少
List<CreditOrderBillStaticReponse> list = this.dao.monthAmountInfo(uid);
if(CollUtil.isNotEmpty(list)){
creditAmountInfoReponse.setReponse(list);
}
return creditAmountInfoReponse;
}
return null;
}
@Override
public CreditRepayOrder create(CreditOrderBillRequest request) {
User user = userService.getInfo();
CreditRepayOrder order= creditRepayOrderService.getByOrderNo(request.getOrderNo());
String orderNo= CrmebUtil.getOrderNo(PayConstants.PAY_TYPE_CREDIT_REPAYMENT);
if(StringUtils.isNotEmpty(request.getOrderNo())){
orderNo=request.getOrderNo();
}
if(Objects.isNull(order)){
order=new CreditRepayOrder();
order.setId(IdWorker.getIdStr());
}
order.setOrderNo(orderNo);
order.setUid(user.getId());
order.setPayType(request.getPayType());
order.setPayChannel(request.getPayChannel());
order.setPayPrice(request.getPayPrice());
order.setIsPaid(0);
order.setYear(request.getYear());
order.setMonth(request.getMonth());
order.setIsAll(request.getIsAll()==1?1:0);
order.setCreateTime(DateUtil.date());
order.setUpdateTime(DateUtil.date());
creditRepayOrderService.saveOrUpdate(order);
return order;
}
/**
* 微信支付
*
* @param order 订单
* @return WxPayJsResultVo
*/
private WxPayJsResultVo wechatPayment(CreditRepayOrder order) {
// 预下单
Map<String, String> unifiedorder = unifiedorder(order);
WxPayJsResultVo vo = new WxPayJsResultVo();
vo.setAppId(unifiedorder.get("appId"));
vo.setNonceStr(unifiedorder.get("nonceStr"));
vo.setPackages(unifiedorder.get("package"));
vo.setSignType(unifiedorder.get("signType"));
vo.setTimeStamp(unifiedorder.get("timeStamp"));
vo.setPaySign(unifiedorder.get("paySign"));
if (order.getPayChannel().equals(PayConstants.PAY_CHANNEL_H5)) {
vo.setMwebUrl(unifiedorder.get("mweb_url"));
}
if (order.getPayChannel().equals(PayConstants.PAY_CHANNEL_WECHAT_APP_IOS) ||
order.getPayChannel().equals(PayConstants.PAY_CHANNEL_WECHAT_APP_ANDROID)) {// App
vo.setPartnerid(unifiedorder.get("partnerid"));
}
if (order.getPayChannel().equals(PayConstants.PAY_CHANNEL_WECHAT_NATIVE)) {
vo.setMwebUrl(unifiedorder.get("code_url"));
}
order.setOutTradeNo(unifiedorder.get("outTradeNo"));
// 更新商户订单号
vo.setOutTradeNo(unifiedorder.get("outTradeNo"));
return vo;
}
/**
* 预下单
*
* @param order 订单
* @return 预下单返回对象
*/
private Map<String, String> unifiedorder(CreditRepayOrder order) {
// 获取用户openId
// 根据订单支付类型来判断获取公众号openId还是小程序openId
UserToken userToken = new UserToken();
userToken.setToken("");
if (order.getPayChannel().equals(PayConstants.PAY_CHANNEL_WECHAT_PUBLIC)) {// 公众号
userToken = userTokenService.getTokenByUserId(order.getUid(), UserConstants.USER_TOKEN_TYPE_WECHAT);
}
if (order.getPayChannel().equals(PayConstants.PAY_CHANNEL_WECHAT_MINI)
|| order.getPayChannel().equals(PayConstants.PAY_CHANNEL_WECHAT_MINI_VIDEO)) {// 小程序
userToken = userTokenService.getTokenByUserId(order.getUid(), UserConstants.USER_TOKEN_TYPE_ROUTINE);
}
// 获取appid、mch_id、微信签名key
String appId = "";
String mchId = "";
String signKey = "";
switch (order.getPayChannel()) {
case PayConstants.PAY_CHANNEL_WECHAT_PUBLIC:
case PayConstants.PAY_CHANNEL_H5:// H5使用公众号的信息
case PayConstants.PAY_CHANNEL_WECHAT_NATIVE:// H5使用公众号的信息
appId = systemConfigService.getValueByKeyException(WeChatConstants.WECHAT_PUBLIC_APPID);
mchId = systemConfigService.getValueByKeyException(WeChatConstants.WECHAT_PAY_PUBLIC_MCHID);
signKey = systemConfigService.getValueByKeyException(WeChatConstants.WECHAT_PAY_PUBLIC_KEY);
break;
case PayConstants.PAY_CHANNEL_WECHAT_MINI:
case PayConstants.PAY_CHANNEL_WECHAT_MINI_VIDEO:
appId = systemConfigService.getValueByKeyException(WeChatConstants.WECHAT_MINI_APPID);
mchId = systemConfigService.getValueByKeyException(WeChatConstants.WECHAT_PAY_MINI_MCHID);
signKey = systemConfigService.getValueByKeyException(WeChatConstants.WECHAT_PAY_MINI_KEY);
break;
case PayConstants.PAY_CHANNEL_WECHAT_APP_IOS:
case PayConstants.PAY_CHANNEL_WECHAT_APP_ANDROID:
appId = systemConfigService.getValueByKeyException(WeChatConstants.WECHAT_APP_APPID);
mchId = systemConfigService.getValueByKeyException(WeChatConstants.WECHAT_PAY_APP_MCHID);
signKey = systemConfigService.getValueByKeyException(WeChatConstants.WECHAT_PAY_APP_KEY);
break;
}
// 获取微信预下单对象
CreateOrderRequestVo unifiedorderVo = getUnifiedorderVo(order, userToken.getToken(), appId, mchId, signKey);
// 预下单(统一下单)
CreateOrderResponseVo responseVo = wechatService.payUnifiedorder(unifiedorderVo);
// 组装前端预下单参数
Map<String, String> map = new HashMap<>();
map.put("appId", unifiedorderVo.getAppid());
map.put("nonceStr", unifiedorderVo.getAppid());
map.put("package", "prepay_id=".concat(responseVo.getPrepayId()));
map.put("signType", unifiedorderVo.getSign_type());
Long currentTimestamp = WxPayUtil.getCurrentTimestamp();
map.put("timeStamp", Long.toString(currentTimestamp));
String paySign = WxPayUtil.getSign(map, signKey);
map.put("paySign", paySign);
map.put("prepayId", responseVo.getPrepayId());
map.put("prepayTime", CrmebDateUtil.nowDateTimeStr());
map.put("outTradeNo", unifiedorderVo.getOut_trade_no());
if (order.getPayChannel().equals(PayConstants.PAY_CHANNEL_H5)) {
map.put("mweb_url", responseVo.getMWebUrl());
}
if (order.getPayChannel().equals(PayConstants.PAY_CHANNEL_WECHAT_APP_IOS) ||
order.getPayChannel().equals(PayConstants.PAY_CHANNEL_WECHAT_APP_ANDROID)) {// App
map.put("partnerid", mchId);
map.put("package", responseVo.getPrepayId());
Map<String, Object> appMap = new HashMap<>();
appMap.put("appid", unifiedorderVo.getAppid());
appMap.put("partnerid", mchId);
appMap.put("prepayid", responseVo.getPrepayId());
appMap.put("package", "Sign=WXPay");
appMap.put("noncestr", unifiedorderVo.getAppid());
appMap.put("timestamp", currentTimestamp);
logger.info("================================================app支付签名,map = " + appMap);
String sign = WxPayUtil.getSignObject(appMap, signKey);
logger.info("================================================app支付签名,sign = " + sign);
map.put("paySign", sign);
}
if (order.getPayChannel().equals(PayConstants.PAY_CHANNEL_WECHAT_NATIVE)) {
map.put("code_url", responseVo.getCodeUrl());
}
return map;
}
/**
* 获取微信预下单对象
*
* @return 微信预下单对象
*/
private CreateOrderRequestVo getUnifiedorderVo(CreditRepayOrder order, String openid, String appId, String mchId, String signKey) {
// 获取域名
String domain = systemConfigService.getValueByKeyException(SysConfigConstants.CONFIG_KEY_SITE_URL);
String apiDomain = systemConfigService.getValueByKeyException(SysConfigConstants.CONFIG_KEY_API_URL);
AttachVo attachVo = new AttachVo(PayConstants.PAY_SERVICE_TYPE_ORDER, order.getUid());
CreateOrderRequestVo vo = new CreateOrderRequestVo();
vo.setAppid(appId);
vo.setMch_id(mchId);
vo.setNonce_str(WxPayUtil.getNonceStr());
vo.setSign_type(PayConstants.WX_PAY_SIGN_TYPE_MD5);
String siteName = systemConfigService.getValueByKeyException(SysConfigConstants.CONFIG_KEY_SITE_NAME);
// 因商品名称在微信侧超长更换为网站名称
vo.setBody(siteName);
vo.setAttach(JSONObject.toJSONString(attachVo));
vo.setOut_trade_no(CrmebUtil.getOrderNo(OrderConstants.ORDER_PREFIX_WECHAT));
// 订单中使用的是BigDecimal,这里要转为Integer类型
vo.setTotal_fee(order.getPayPrice().multiply(BigDecimal.TEN).multiply(BigDecimal.TEN).intValue());
vo.setSpbill_create_ip(RequestUtil.getClientIp());
vo.setNotify_url(apiDomain + PayConstants.WX_PAY_NOTIFY_API_URI);
switch (order.getPayChannel()) {
case PayConstants.PAY_CHANNEL_H5:
vo.setTrade_type(PayConstants.WX_PAY_TRADE_TYPE_H5);
vo.setOpenid(null);
break;
case PayConstants.PAY_CHANNEL_WECHAT_APP_IOS:
case PayConstants.PAY_CHANNEL_WECHAT_APP_ANDROID:
vo.setTrade_type(PayConstants.WX_PAY_TRADE_TYPE_APP);
vo.setOpenid(null);
break;
case PayConstants.PAY_CHANNEL_WECHAT_NATIVE:
vo.setTrade_type(PayConstants.WX_PAY_TRADE_TYPE_NATIVE);
vo.setProduct_id(order.getOrderNo());
vo.setOpenid(null);
break;
default:
vo.setTrade_type(PayConstants.WX_PAY_TRADE_TYPE_JS);
vo.setOpenid(openid);
}
CreateOrderH5SceneInfoVo createOrderH5SceneInfoVo = new CreateOrderH5SceneInfoVo(
new CreateOrderH5SceneInfoDetailVo(
domain,
systemConfigService.getValueByKeyException(SysConfigConstants.CONFIG_KEY_SITE_NAME)
)
);
vo.setScene_info(JSONObject.toJSONString(createOrderH5SceneInfoVo));
vo.setTime_start(DateUtil.date().toString(DateConstants.DATE_TIME_FORMAT_NUM));
DateTime cancelTime = DateUtil.offset(order.getCreateTime(), DateField.MINUTE, crmebConfig.getOrderCancelTime());
String cancelStr = cancelTime.toString(DateConstants.DATE_TIME_FORMAT_NUM);
vo.setTime_expire(cancelStr);
String sign = WxPayUtil.getSign(vo, signKey);
vo.setSign(sign);
return vo;
}
private Boolean yuePay(CreditRepayOrder order, User user) {
// 用户余额扣除
Boolean execute = transactionTemplate.execute(e -> {
Boolean update = Boolean.TRUE;
// 订单修改
order.setIsPaid(1);
order.setPayTime(DateUtil.date());
order.setPayChannel(order.getPayChannel());
order.setPayType(PayConstants.PAY_TYPE_YUE);
order.setUpdateTime(DateUtil.date());
creditRepayOrderService.updateById(order);
// 这里只扣除金额,账单记录在task中处理
if (order.getPayPrice().compareTo(BigDecimal.ZERO) > 0) {
update = userService.updateNowMoney(user.getId(), order.getPayPrice(), Constants.OPERATION_TYPE_SUBTRACT);
if (!update) {
logger.error("余额支付授信还款,扣除用户余额失败,orderNo = {}", order.getOrderNo());
e.setRollbackOnly();
return update;
}
update = creditAmountService.updateNowMoney(order.getUid(), order.getPayPrice(), Constants.OPERATION_TYPE_ADD);
if (!update) {
logger.error("余额支付授信还款,剩余额度额度变动失败,orderNo = {}", order.getOrderNo());
e.setRollbackOnly();
return update;
}
update = creditAmountService.updateRemainMoney(order.getUid(), order.getPayPrice(), Constants.OPERATION_TYPE_SUBTRACT);
if (!update) {
logger.error("余额支付授信还款, 授信已使用额度 已使用额度额度变动,orderNo = {}", order.getOrderNo());
e.setRollbackOnly();
return update;
}
update = creditAmountService.updateCreditRepaymentAmounty(order.getUid(), order.getPayPrice(), Constants.OPERATION_TYPE_ADD);
if (!update) {
logger.error("余额支付授信还款,更新已还款额度,orderNo = {}", order.getOrderNo());
e.setRollbackOnly();
return update;
}
// 用户余额记录
UserBalanceRecord userBalanceRecord = new UserBalanceRecord();
userBalanceRecord.setUid(user.getId());
userBalanceRecord.setLinkId(order.getOrderNo());
userBalanceRecord.setLinkType(BalanceRecordConstants.BALANCE_RECORD_LINK_TYPE_ORDER);
userBalanceRecord.setType(BalanceRecordConstants.BALANCE_RECORD_TYPE_SUB);
userBalanceRecord.setAmount(order.getPayPrice());
userBalanceRecord.setBalance(user.getNowMoney().subtract(order.getPayPrice()));
userBalanceRecord.setRemark(StrUtil.format(BalanceRecordConstants.BALANCE_RECORD_REMARK_ORDER, order.getPayPrice()));
userBalanceRecordService.save(userBalanceRecord);
}
// 授信账单
Boolean b = updateCreditAmountAndCreditOrderBill(order, user.getId());
if(!b) throw new CrmebException("余额还款订单失败");
//用户授信流水
if(!saveOrCreditBill(order,user)) throw new CrmebException("余额还款订单失败");
if (!b) throw new CrmebException("余额还款订单失败");
//查询是否存在超出还款时间待还款订单
List<CreditOrderBill> list = creditOrderBillService.getCreditRepaymentFlag();
if (CollUtil.isEmpty(list)) {
creditAmountService.updateStatus();
}
return update;
});
if (!execute) throw new CrmebException("余额还款订单失败");
// 平台分账返还
Bill platBill = new Bill();
platBill.setOrderNo(order.getOrderNo());
platBill.setUid(order.getUid());
platBill.setPm(BillConstants.BILL_PM_ADD);
platBill.setAmount(order.getPayPrice());
platBill.setType(BillConstants.BILL_TYPE_YUE_PAY_REFUND);
platBill.setMark(StrUtil.format("余额还款,平台返还分账金额{}元", order.getPayPrice()));
billService.save(platBill);
//余额还款
Bill yueBill = new Bill();
yueBill.setOrderNo(order.getOrderNo());
yueBill.setUid(order.getUid());
yueBill.setPm(BillConstants.BILL_PM_ADD);
yueBill.setAmount(order.getPayPrice());
yueBill.setType(BillConstants.BILL_TYPE_YUE_PAY_REFUND);
yueBill.setMark(StrUtil.format("用户余额减少金额{}元", order.getPayPrice()));
billService.save(platBill);
return true;
}
private boolean saveOrCreditBill(CreditRepayOrder order, User user){
//创建授信流水
return creditBillInfoService.addRecord(order.getPayPrice(),user.getId(),1);
}
@Override
public Boolean updateCreditAmountAndCreditOrderBill( CreditRepayOrder order,Integer uid) {
//更新账单信息 判断是否为全部还款
if(order.getIsAll()==1){
//查询当年月份的账单 全部List<CreditOrderBill> creditOrderBillList =
LambdaQueryWrapper<CreditOrderBill> lqw = new LambdaQueryWrapper<CreditOrderBill>();
lqw.eq(CreditOrderBill::getUid, uid);
lqw.eq(CreditOrderBill::getYear, order.getYear());
lqw.eq(CreditOrderBill::getMonth, order.getMonth());
lqw.eq(CreditOrderBill::getCreditRepaymentFlag, 0);
List<CreditOrderBill> creditOrderBillList = this.list(lqw);
if(CollUtil.isNotEmpty(creditOrderBillList)){
for (CreditOrderBill creditOrderBill : creditOrderBillList) {
creditOrderBill.setCreditRepaymentFlag(1);
creditOrderBill.setPayType(order.getPayType());
creditOrderBill.setPayChannel(order.getPayChannel());
creditOrderBill.setOrderType(2);
creditOrderBill.setCreditRepaymentAmount(creditOrderBill.getPayPrice());
creditOrderBill.setCreditRepaymentTime(DateUtil.date());
this.updateById(creditOrderBill);
}
}
}
else{
LambdaQueryWrapper<CreditOrderBill> lqw = new LambdaQueryWrapper<CreditOrderBill>();
lqw.eq(CreditOrderBill::getUid, uid);
lqw.eq(CreditOrderBill::getOrderNo, order.getOrderNo());
lqw.eq(CreditOrderBill::getCreditRepaymentFlag, 0);
CreditOrderBill creditOrderBill = this.getOne(lqw);
if(Objects.nonNull(creditOrderBill)){
logger.info("查询到的还款单:"+creditOrderBill.getOrderNo());
creditOrderBill.setCreditRepaymentFlag(1);
creditOrderBill.setOrderType(2);
creditOrderBill.setPayType(order.getPayType());
creditOrderBill.setPayChannel(order.getPayChannel());
creditOrderBill.setCreditRepaymentAmount(creditOrderBill.getPayPrice());
creditOrderBill.setCreditRepaymentTime(DateUtil.date());
return this.updateById(creditOrderBill);
}
}
return true;
}
@Override
public List<CreditOrderBill> getNoStartTask() {
LambdaQueryWrapper<CreditOrderBill> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(CreditOrderBill::getTaskStatus, 0);
lambdaQueryWrapper.eq(CreditOrderBill::getCreditRepaymentFlag, 0);
// //查询当前时间大于等于任务执行时间
lambdaQueryWrapper.ge(CreditOrderBill::getTaskStartTime, DateUtil.date());
return this.list(lambdaQueryWrapper);
}
@Override
public void updateRefundStatus(String orderNo) {
LambdaQueryWrapper<CreditOrderBill> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(CreditOrderBill::getOrderNo, orderNo);
CreditOrderBill creditOrderBill = this.getOne(lambdaQueryWrapper);
creditOrderBill.setCreditRepaymentFlag(1);
this.updateById(creditOrderBill);
}
@Override
public List<CreditOrderBill> getCreditRepaymentFlag() {
LambdaQueryWrapper<CreditOrderBill> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(CreditOrderBill::getCreditRepaymentFlag, 0);
//还款时间是否大于当前时间
lambdaQueryWrapper.gt(CreditOrderBill::getTaskEndTime, DateUtil.date());
return this.list(lambdaQueryWrapper);
}
@Override
public boolean updateInfo(CreditOrderBillRequest creditOrderBillRequest) {
CreditOrderBill creditOrderBill = this.getById(creditOrderBillRequest.getId());
//判断creditOrderBillRequest.creditOrderBillRequest.getPayPrice()不能大于等于creditOrderBill.getPayPrice()
if(creditOrderBillRequest.getPayPrice().compareTo(creditOrderBill.getPayPrice())==1){
throw new CrmebException("还款金额不能大于订单金额");
}
// creditOrderBillRequest.getPayPrice()减去creditOrderBill.getPayPrice()
BigDecimal creditRepaymentAmount =creditOrderBill.getCreditRepaymentAmount().subtract(creditOrderBillRequest.getPayPrice());
creditOrderBill.setPayPrice(creditOrderBillRequest.getPayPrice());
creditOrderBill.setCreditRepaymentAmount(creditOrderBillRequest.getPayPrice());
creditOrderBill.setIsUpdate(1);
this.dao.updateById(creditOrderBill);
//更新已使用额度
CreditAmount creditAmount = creditAmountService.getByUserId(creditOrderBill.getUid());
creditAmount.setCreditPayAmount(creditAmount.getCreditPayAmount().subtract(creditRepaymentAmount));
//更新creditRemainAmount
creditAmount.setCreditRemainAmount(creditAmount.getCreditRemainAmount().add(creditRepaymentAmount));
creditAmountService.updateById(creditAmount);
//生成一条流水详情
CreditBillInfo billInfo = new CreditBillInfo();
billInfo.setCreditPayAmount(creditRepaymentAmount);
billInfo.setCreditRemainAmount(creditAmount.getCreditRemainAmount());
billInfo.setUid(creditAmount.getUid());
billInfo.setCreditType(5);
billInfo.setCreateTime(DateUtil.date());
billInfo.setUpdateTime(DateUtil.date());
billInfo.setId(IdWorker.getIdStr());
creditBillInfoService.save(billInfo);
//生成修改记录
CreditOrderBillRecord record=new CreditOrderBillRecord();
record.setBillId(creditOrderBill.getId());
record.setOrderNo(creditOrderBill.getOrderNo());
record.setPayPrice(creditOrderBillRequest.getPayPrice());
record.setUid(creditOrderBill.getUid());
SystemAdmin systemAdmin = SecurityUtil.getLoginUserVo().getUser();
record.setCreateTime(DateUtil.date());
record.setCreateUser(systemAdmin.getRealName());
record.setRemark(creditOrderBillRequest.getRemark());
record.setUpdateTime(DateUtil.date());
record.setUpdateUser(systemAdmin.getRealName());
record.setId(IdWorker.getIdStr());
creditOrderBillRecordDao.insert(record);
return true;
}
}
4:实现花呗还款
package com.zbkj.front.controller.credit;
import com.zbkj.common.model.credit.CreditRepayOrder;
import com.zbkj.common.request.credit.CreditOrderBillRequest;
import com.zbkj.common.response.OrderPayResultResponse;
import com.zbkj.common.response.credit.CreditAmountInfoReponse;
import com.zbkj.common.response.credit.CreditOrderBillStaticReponse;
import com.zbkj.common.result.CommonResult;
import com.zbkj.service.service.credit.CreditOrderBillService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 授信流水表 前端控制器
*/
@Slf4j
@RestController
@RequestMapping("api/front/credit/order/bill")
@Api(tags = "授信账单流水表") //配合swagger使用
public class CreditOrderBillController {
@Autowired
private CreditOrderBillService creditOrderBillService;
@ApiOperation(value = "根据年月查看用户账单详情")
@RequestMapping(value = "/month/amount/info", method = RequestMethod.GET)
public CommonResult<CreditOrderBillStaticReponse> monthAmountInfo(CreditOrderBillRequest request) {
return CommonResult.success(creditOrderBillService.monthAmountInfo(request));
}
@ApiOperation(value = "账单还款支付")
@RequestMapping(value = "/month/amount/payment", method = RequestMethod.POST)
public CommonResult<OrderPayResultResponse> menthPayment(@RequestBody CreditOrderBillRequest request) {
return CommonResult.success(creditOrderBillService.menthPayment(request));
}
@ApiOperation(value = "还款创建订单号")
@RequestMapping(value = "/month/amount/create/order", method = RequestMethod.POST)
public CommonResult<CreditRepayOrder> create(@RequestBody CreditOrderBillRequest request) {
return CommonResult.success(creditOrderBillService.create(request));
}
@ApiOperation(value = "根据当前用户查看账单详情")
@RequestMapping(value = "/user/amount/info/{uid}", method = RequestMethod.GET)
public CommonResult<CreditAmountInfoReponse> getUserAmountInfo(@PathVariable(value = "uid") Integer uid) {
return CommonResult.success(creditOrderBillService.getUserAmountInfo(uid));
}
}
package com.zbkj.service.service.credit;
import com.baomidou.mybatisplus.extension.service.IService;
import com.zbkj.common.model.credit.CreditRepayOrder;
import java.util.List;
/**
* @author dudianlong
* @description CreditRepayOrderService 接口
* @date 2024-11-21
*/
public interface CreditRepayOrderService extends IService<CreditRepayOrder> {
CreditRepayOrder getByOrderNo(String orderNo);
CreditRepayOrder getByOutTradeNo(String outTradeNo);
String wechatPayCallback(String xmlInfo);
}
package com.zbkj.service.service.impl.credit;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zbkj.common.constants.*;
import com.zbkj.common.exception.CrmebException;
import com.zbkj.common.model.bill.Bill;
import com.zbkj.common.model.credit.*;
import com.zbkj.common.model.user.User;
import com.zbkj.common.model.wechat.WechatPayInfo;
import com.zbkj.common.utils.CrmebDateUtil;
import com.zbkj.common.utils.CrmebUtil;
import com.zbkj.common.utils.RedisUtil;
import com.zbkj.common.utils.WxPayUtil;
import com.zbkj.common.vo.AttachVo;
import com.zbkj.common.vo.WechatPayCallbackVo;
import com.zbkj.service.dao.credit.CreditRepayOrderDao;
import com.zbkj.service.service.*;
import com.zbkj.service.service.credit.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/**
* @author dudianlong
* @description CreditRepayOrderServiceImpl 接口实现
* @date 2024-11-21
*/
@Service
public class CreditRepayOrderServiceImpl extends ServiceImpl<CreditRepayOrderDao, CreditRepayOrder> implements CreditRepayOrderService {
private static final Logger logger = LoggerFactory.getLogger(CreditRepayOrderServiceImpl.class);
@Resource
private CreditRepayOrderDao dao;
@Autowired
private WechatPayInfoService wechatPayInfoService;
@Autowired
private SystemConfigService systemConfigService;
@Autowired
private UserService userService;
@Autowired
private AsyncService asyncService;
@Autowired
private TransactionTemplate transactionTemplate;
@Autowired
private RedisUtil redisUtil;
@Autowired
private CreditOrderBillService creditOrderBillService;
@Autowired
private CreditBillInfoService creditBillInfoService;
@Autowired
private CreditAmountService creditAmountService;
@Autowired
private BillService billService;
@Override
public CreditRepayOrder getByOrderNo(String orderNo) {
LambdaQueryWrapper<CreditRepayOrder> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(CreditRepayOrder::getOrderNo, orderNo);
return dao.selectOne(queryWrapper);
}
@Override
public CreditRepayOrder getByOutTradeNo(String outTradeNo) {
LambdaQueryWrapper<CreditRepayOrder> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(CreditRepayOrder::getOutTradeNo, outTradeNo);
return dao.selectOne(queryWrapper);
}
@Override
public String wechatPayCallback(String xmlInfo) {
StringBuffer sb = new StringBuffer();
sb.append("<xml>");
if (StrUtil.isBlank(xmlInfo)) {
sb.append("<return_code><![CDATA[FAIL]]></return_code>");
sb.append("<return_msg><![CDATA[xmlInfo is blank]]></return_msg>");
sb.append("</xml>");
logger.error("wechat callback error : " + sb);
return sb.toString();
}
try {
HashMap<String, Object> map = WxPayUtil.processResponseXml(xmlInfo);
// 通信是否成功
String returnCode = (String) map.get("return_code");
if (!returnCode.equals(Constants.SUCCESS)) {
sb.append("<return_code><![CDATA[SUCCESS]]></return_code>");
sb.append("<return_msg><![CDATA[OK]]></return_msg>");
sb.append("</xml>");
logger.error("wechat callback error : wx pay return code is fail returnMsg : " + map.get("return_msg"));
return sb.toString();
}
// 交易是否成功
String resultCode = (String) map.get("result_code");
if (!resultCode.equals(Constants.SUCCESS)) {
sb.append("<return_code><![CDATA[SUCCESS]]></return_code>");
sb.append("<return_msg><![CDATA[OK]]></return_msg>");
sb.append("</xml>");
logger.error("wechat callback error : wx pay result code is fail");
return sb.toString();
}
//解析xml
WechatPayCallbackVo callbackVo = CrmebUtil.mapToObj(map, WechatPayCallbackVo.class);
AttachVo attachVo = JSONObject.toJavaObject(JSONObject.parseObject(callbackVo.getAttach()), AttachVo.class);
//判断openid
User user = userService.getById(attachVo.getUserId());
if (ObjectUtil.isNull(user)) {
//用户信息错误
throw new CrmebException("用户信息错误!");
}
//根据类型判断是订单或者充值
if (!PayConstants.PAY_SERVICE_TYPE_ORDER.equals(attachVo.getType()) && !PayConstants.PAY_SERVICE_TYPE_RECHARGE.equals(attachVo.getType())
&& !PayConstants.PAY_SERVICE_TYPE_SVIP.equals(attachVo.getType())) {
logger.error("wechat pay err : 未知的支付类型==》" + callbackVo.getOutTradeNo());
throw new CrmebException("未知的支付类型!");
}
// 订单
if (PayConstants.PAY_SERVICE_TYPE_ORDER.equals(attachVo.getType())) {
CreditRepayOrder order = this.getByOutTradeNo(callbackVo.getOutTradeNo());
if (ObjectUtil.isNull(order) || !order.getUid().equals(attachVo.getUserId())) {
logger.error("还款订单 wechat pay error : 还款订单订单信息不存在==》" + callbackVo.getOutTradeNo());
throw new CrmebException("wechat pay error : 还款订单订单信息不存在==》" + callbackVo.getOutTradeNo());
}
if (order.getIsPaid()==1) {
sb.append("<return_code><![CDATA[SUCCESS]]></return_code>");
sb.append("<return_msg><![CDATA[OK]]></return_msg>");
sb.append("</xml>");
return sb.toString();
}
String signKey = "";
String payChannel = order.getPayChannel();
if (payChannel.equals(PayConstants.PAY_CHANNEL_H5) || payChannel.equals(PayConstants.PAY_CHANNEL_WECHAT_NATIVE)) {
String source = systemConfigService.getValueByKey(SysConfigConstants.WECHAT_PAY_SOURCE_H5_PC);
if (StrUtil.isNotBlank(source) && source.equals(PayConstants.WECHAT_PAY_SOURCE_MINI)) {
payChannel = PayConstants.PAY_CHANNEL_WECHAT_MINI;
} else {
payChannel = PayConstants.PAY_CHANNEL_WECHAT_PUBLIC;
}
}
switch (payChannel) {
case PayConstants.PAY_CHANNEL_WECHAT_PUBLIC:
signKey = systemConfigService.getValueByKeyException(WeChatConstants.WECHAT_PAY_PUBLIC_KEY);
break;
case PayConstants.PAY_CHANNEL_WECHAT_MINI:
case PayConstants.PAY_CHANNEL_WECHAT_MINI_VIDEO:
signKey = systemConfigService.getValueByKeyException(WeChatConstants.WECHAT_PAY_MINI_KEY);
break;
case PayConstants.PAY_CHANNEL_WECHAT_APP_IOS:
case PayConstants.PAY_CHANNEL_WECHAT_APP_ANDROID:
signKey = systemConfigService.getValueByKeyException(WeChatConstants.WECHAT_PAY_APP_KEY);
break;
}
Map<String, String> stringMap = WxPayUtil.xmlToMap(xmlInfo);
String sign = WxPayUtil.getSign(stringMap, signKey);
if (!sign.equals(stringMap.get(PayConstants.FIELD_SIGN))) {
logger.error("wechat pay error : 微信订单回调验签失败 ==> {}", xmlInfo);
throw new CrmebException(StrUtil.format("wechat pay error : 微信订单回调验签失败 ==> {}", xmlInfo));
}
WechatPayInfo wechatPayInfo = wechatPayInfoService.getByNo(order.getOutTradeNo());
if (ObjectUtil.isNull(wechatPayInfo)) {
logger.error("wechat pay error : 微信订单信息不存在==》" + callbackVo.getOutTradeNo());
throw new CrmebException("wechat pay error : 微信订单信息不存在==》" + callbackVo.getOutTradeNo());
}
wechatPayInfo.setIsSubscribe(callbackVo.getIsSubscribe());
wechatPayInfo.setBankType(callbackVo.getBankType());
wechatPayInfo.setCashFee(callbackVo.getCashFee());
wechatPayInfo.setCouponFee(callbackVo.getCouponFee());
wechatPayInfo.setTransactionId(callbackVo.getTransactionId());
wechatPayInfo.setTimeEnd(callbackVo.getTimeEnd());
// 添加支付成功redis队列
Boolean execute = transactionTemplate.execute(e -> {
logger.error("微信还款。执行execute方法" + order.getOrderNo());
order.setIsPaid(1);
order.setPayTime(CrmebDateUtil.nowDateTime());
this.updateById(order);
wechatPayInfoService.updateById(wechatPayInfo);
//更新授信信息
Boolean update = creditAmountService.updateNowMoney(order.getUid(), order.getPayPrice(), Constants.OPERATION_TYPE_ADD);
if (!update) {
logger.error("微信支付授信还款,剩余额度额度变动失败,orderNo = {}", order.getOrderNo());
e.setRollbackOnly();
return update;
}
update = creditAmountService.updateRemainMoney(order.getUid(), order.getPayPrice(), Constants.OPERATION_TYPE_SUBTRACT);
if (!update) {
logger.error("微信支付授信还款, 授信已使用额度 已使用额度额度变动,orderNo = {}", order.getOrderNo());
e.setRollbackOnly();
return update;
}
update = creditAmountService.updateCreditRepaymentAmounty(order.getUid(), order.getPayPrice(), Constants.OPERATION_TYPE_ADD);
if (!update) {
logger.error("微信支付授信还款,更新已还款额度,orderNo = {}", order.getOrderNo());
e.setRollbackOnly();
return update;
}
creditOrderBillService.updateCreditAmountAndCreditOrderBill(order,order.getUid());
if(!saveOrCreditBill(order,user)) throw new CrmebException("微信还款订单失败");
//查询是否存在超出还款时间待还款订单
List<CreditOrderBill> list = creditOrderBillService.getCreditRepaymentFlag();
if (CollUtil.isEmpty(list)) {
creditAmountService.updateStatus();
}
// 平台分账返还
Bill platBill = new Bill();
platBill.setOrderNo(order.getOrderNo());
platBill.setUid(order.getUid());
platBill.setPm(BillConstants.BILL_PM_ADD);
platBill.setAmount(order.getPayPrice());
platBill.setType(BillConstants.BILL_TYPE_WEIXIN_PAY_REFUND);
platBill.setMark(StrUtil.format("微信还款,平台返还分账金额{}元", order.getPayPrice()));
billService.save(platBill);
return Boolean.TRUE;
});
if (!execute) {
logger.error("wechat pay error : 订单更新失败==》" + callbackVo.getOutTradeNo());
sb.append("<return_code><![CDATA[SUCCESS]]></return_code>");
sb.append("<return_msg><![CDATA[OK]]></return_msg>");
sb.append("</xml>");
return sb.toString();
}
asyncService.orderPaySuccessSplit(order.getOrderNo());
// redisUtil.lPush(TaskConstants.ORDER_TASK_PAY_SUCCESS_AFTER, order.getOrderNo());
}
sb.append("<return_code><![CDATA[SUCCESS]]></return_code>");
sb.append("<return_msg><![CDATA[OK]]></return_msg>");
} catch (Exception e) {
sb.append("<return_code><![CDATA[FAIL]]></return_code>");
sb.append("<return_msg><![CDATA[").append(e.getMessage()).append("]]></return_msg>");
logger.error("wechat pay error : 业务异常==》" + e.getMessage());
}
sb.append("</xml>");
return sb.toString();
}
private boolean saveOrCreditBill(CreditRepayOrder order, User user){
return creditBillInfoService.addRecord(order.getPayPrice(),user.getId(),1);
}
}
这样就实现啦花呗支付,使用微信还款,