package com.doumee.service.business.impl; import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.doumee.core.constants.ResponseStatus; import com.doumee.core.exception.BusinessException; import com.doumee.core.model.LoginUserInfo; import com.doumee.core.utils.Constants; import com.doumee.core.wx.WxJsapiPayUtil; import com.doumee.dao.business.*; import com.doumee.dao.business.dto.YwCustomerRechargeConditionerDTO; import com.doumee.dao.business.dto.YwCustomerRechargeElectricalDTO; import com.doumee.dao.business.dto.h5.CustomerPayCreateDTO; import com.doumee.dao.business.model.*; import com.doumee.service.business.YwContractRevenueService; import com.doumee.service.business.YwCustomerH5BizService; import com.doumee.service.business.YwCustomerH5AuthService; import com.doumee.service.business.YwCustomerRechargeBizService; import com.doumee.service.business.YwCustomerWxPayService; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; import java.util.*; @Service @Slf4j public class YwCustomerWxPayServiceImpl implements YwCustomerWxPayService { @Autowired private YwWxPayOrderMapper ywWxPayOrderMapper; @Autowired private YwContractBillMapper ywContractBillMapper; @Autowired private YwContractMapper ywContractMapper; @Autowired private YwAccountMapper ywAccountMapper; @Autowired private YwElectricalChargeMapper ywElectricalChargeMapper; @Autowired private WxJsapiPayUtil wxJsapiPayUtil; @Autowired private YwCustomerRechargeBizService ywCustomerRechargeBizService; @Autowired private YwContractRevenueService ywContractRevenueService; @Autowired private YwCustomerH5BizService ywCustomerH5BizService; @Autowired private YwCustomerH5AuthService ywCustomerH5AuthService; @Override @Transactional(rollbackFor = Exception.class) public Map createOrder(CustomerPayCreateDTO dto, LoginUserInfo user, String clientIp) { if (user == null || user.getCustomerId() == null) { throw new BusinessException(ResponseStatus.NO_ALLOW_LOGIN); } if (dto.getAmount() == null || dto.getAmount().compareTo(BigDecimal.ZERO) <= 0) { throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "金额须大于0"); } if (StringUtils.isBlank(dto.getOpenid())) { throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "openid不能为空"); } Integer orderType = dto.getOrderType(); Integer bizRefId = resolveBizRefId(dto, user.getCustomerId()); validateBiz(orderType, bizRefId, user.getCustomerId(), dto.getAmount()); String orderNo = "WX" + System.currentTimeMillis() + user.getCustomerId() + new Random().nextInt(1000); YwWxPayOrder order = new YwWxPayOrder(); order.setCreator(user.getId()); order.setCreateDate(new Date()); order.setEditor(user.getId()); order.setEditDate(new Date()); order.setIsdeleted(Constants.ZERO); order.setOrderNo(orderNo); order.setCustomerId(user.getCustomerId()); order.setMemberId(user.getMemberId()); order.setOrderType(orderType); order.setBizRefId(bizRefId); order.setAmount(dto.getAmount()); order.setStatus(YwWxPayOrder.STATUS_WAIT); order.setOpenid(dto.getOpenid()); order.setRemark(dto.getRemark()); order.setRequestSnapshot(JSON.toJSONString(dto)); ywWxPayOrderMapper.insert(order); String body = orderType == YwWxPayOrder.TYPE_BILL ? "账单缴费" : (orderType == YwWxPayOrder.TYPE_CONDITIONER ? "空调充值" : "电费充值"); Map payParams = wxJsapiPayUtil.createJsapiOrder(orderNo, dto.getOpenid(), body, dto.getAmount(), clientIp); payParams.put("orderNo", orderNo); return payParams; } @Override public YwWxPayOrder queryOrder(String orderNo, Integer customerId) { return ywWxPayOrderMapper.selectOne(new QueryWrapper().lambda() .eq(YwWxPayOrder::getOrderNo, orderNo) .eq(YwWxPayOrder::getCustomerId, customerId) .eq(YwWxPayOrder::getIsdeleted, Constants.ZERO) .last("limit 1")); } @Override @Transactional(rollbackFor = Exception.class) public String handleNotify(String xmlBody) { Map data = wxJsapiPayUtil.parseNotifyXml(xmlBody); if (!wxJsapiPayUtil.verifyNotifySign(data)) { return failXml("签名失败"); } if (!"SUCCESS".equals(data.get("return_code")) || !"SUCCESS".equals(data.get("result_code"))) { return successXml(); } String orderNo = data.get("out_trade_no"); YwWxPayOrder order = ywWxPayOrderMapper.selectOne(new QueryWrapper().lambda() .eq(YwWxPayOrder::getOrderNo, orderNo) .eq(YwWxPayOrder::getIsdeleted, Constants.ZERO) .last("limit 1")); if (order == null) { return successXml(); } if (Objects.equals(order.getStatus(), YwWxPayOrder.STATUS_SUCCESS)) { return successXml(); } LoginUserInfo user = buildCustomerUser(order); try { Integer bizRecordId = fulfillBiz(order, user); order.setStatus(YwWxPayOrder.STATUS_SUCCESS); order.setWxTransactionId(data.get("transaction_id")); order.setPayTime(new Date()); order.setBizRecordId(bizRecordId); order.setEditDate(new Date()); ywWxPayOrderMapper.updateById(order); } catch (Exception e) { log.error("wx pay fulfill failed orderNo={}", orderNo, e); order.setStatus(YwWxPayOrder.STATUS_FAIL); order.setStatusInfo(e.getMessage()); order.setEditDate(new Date()); ywWxPayOrderMapper.updateById(order); } return successXml(); } private Integer fulfillBiz(YwWxPayOrder order, LoginUserInfo user) { CustomerPayCreateDTO dto = JSON.parseObject(order.getRequestSnapshot(), CustomerPayCreateDTO.class); if (order.getOrderType() == YwWxPayOrder.TYPE_BILL) { return createBillRevenue(order, user); } ywCustomerH5BizService.applyFirstRechargeIfNeeded(order.getCustomerId(), user); if (order.getOrderType() == YwWxPayOrder.TYPE_ELECTRICAL) { YwCustomerRechargeElectricalDTO req = new YwCustomerRechargeElectricalDTO(); req.setCustomerId(order.getCustomerId()); req.setElectricalId(order.getBizRefId()); req.setMoney(order.getAmount()); req.setRemark(StringUtils.defaultIfBlank(dto != null ? dto.getRemark() : null, "微信H5充值")); ywCustomerRechargeBizService.rechargeElectrical(req, user); return findLatestChargeId(order.getCustomerId(), Constants.ZERO, order.getBizRefId(), order.getOrderNo()); } YwCustomerRechargeConditionerDTO req = new YwCustomerRechargeConditionerDTO(); req.setCustomerId(order.getCustomerId()); req.setMoney(order.getAmount()); req.setRemark(StringUtils.defaultIfBlank(dto != null ? dto.getRemark() : null, "微信H5充值")); ywCustomerRechargeBizService.rechargeConditioner(req, user); return findLatestChargeId(order.getCustomerId(), Constants.ONE, order.getCustomerId(), order.getOrderNo()); } private Integer createBillRevenue(YwWxPayOrder order, LoginUserInfo user) { YwContractBill bill = ywContractBillMapper.selectById(order.getBizRefId()); if (bill == null) { throw new BusinessException(ResponseStatus.DATA_EMPTY.getCode(), "账单不存在"); } YwAccount account = ywAccountMapper.selectOne(new QueryWrapper().lambda() .eq(YwAccount::getCompanyId, bill.getCompanyId()) .eq(YwAccount::getIsdeleted, Constants.ZERO) .eq(YwAccount::getStatus, Constants.ZERO) .orderByAsc(YwAccount::getId) .last("limit 1")); if (account == null) { throw new BusinessException(ResponseStatus.DATA_EMPTY.getCode(), "未配置收支账户"); } YwContractRevenue revenue = new YwContractRevenue(); revenue.setBillId(bill.getId()); revenue.setCompanyId(bill.getCompanyId()); revenue.setAccountId(account.getId()); revenue.setActReceivableFee(order.getAmount()); revenue.setActPayDate(new Date()); revenue.setPayType(4); revenue.setWxOrderNo(order.getOrderNo()); revenue.setRemark("微信H5支付 orderNo=" + order.getOrderNo()); revenue.setLoginUserInfo(user); return ywContractRevenueService.create(revenue); } private Integer findLatestChargeId(Integer customerId, int type, Integer objId, String orderNo) { YwElectricalCharge charge = ywElectricalChargeMapper.selectOne(new QueryWrapper().lambda() .eq(YwElectricalCharge::getCustomerId, customerId) .eq(YwElectricalCharge::getType, type) .eq(type == Constants.ZERO, YwElectricalCharge::getObjId, objId) .eq(YwElectricalCharge::getIsdeleted, Constants.ZERO) .orderByDesc(YwElectricalCharge::getCreateDate) .last("limit 1")); if (charge != null && StringUtils.isBlank(charge.getWxOrderNo())) { ywElectricalChargeMapper.update(null, new UpdateWrapper().lambda() .set(YwElectricalCharge::getWxOrderNo, orderNo) .eq(YwElectricalCharge::getId, charge.getId())); return charge.getId(); } return charge != null ? charge.getId() : null; } private void validateBiz(Integer orderType, Integer bizRefId, Integer customerId, BigDecimal amount) { if (orderType == YwWxPayOrder.TYPE_BILL) { YwContractBill bill = ywContractBillMapper.selectById(bizRefId); if (bill == null || Objects.equals(bill.getIsdeleted(), Constants.ONE)) { throw new BusinessException(ResponseStatus.DATA_EMPTY.getCode(), "账单不存在"); } YwContract contract = ywContractMapper.selectById(bill.getContractId()); if (contract == null || !Objects.equals(contract.getRenterId(), customerId)) { throw new BusinessException(ResponseStatus.NOT_ALLOWED); } } } private Integer resolveBizRefId(CustomerPayCreateDTO dto, Integer customerId) { if (dto.getOrderType() == YwWxPayOrder.TYPE_ELECTRICAL) { if (dto.getElectricalId() == null) { throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "电表ID不能为空"); } return dto.getElectricalId(); } if (dto.getOrderType() == YwWxPayOrder.TYPE_CONDITIONER) { return customerId; } if (dto.getOrderType() == YwWxPayOrder.TYPE_BILL) { if (dto.getBillId() == null) { throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "账单ID不能为空"); } return dto.getBillId(); } throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "订单类型无效"); } private LoginUserInfo buildCustomerUser(YwWxPayOrder order) { if (order == null || order.getCustomerId() == null) { return null; } return ywCustomerH5AuthService.buildLoginUserInfo(order.getCustomerId(), order.getMemberId()); } private String successXml() { return ""; } private String failXml(String msg) { return ""; } }