diff --git a/dating-agency-mall-event/pom.xml b/dating-agency-mall-event/pom.xml index daaf667..5973371 100644 --- a/dating-agency-mall-event/pom.xml +++ b/dating-agency-mall-event/pom.xml @@ -17,4 +17,21 @@ UTF-8 + + + com.qniao + ddd-event + 0.0.1-SNAPSHOT + + + com.qniao + dating-agency-uec-constant + 0.0.1-SNAPSHOT + + + com.qniao + dating-agency-mall-constant + 0.0.1-SNAPSHOT + + \ No newline at end of file diff --git a/dating-agency-mall-event/src/main/java/com/qniao/dam/domian/aggregate/paymentchannelorder/event/PaymentChannelOrderPaidEvent.java b/dating-agency-mall-event/src/main/java/com/qniao/dam/domian/aggregate/paymentchannelorder/event/PaymentChannelOrderPaidEvent.java new file mode 100644 index 0000000..06a5afd --- /dev/null +++ b/dating-agency-mall-event/src/main/java/com/qniao/dam/domian/aggregate/paymentchannelorder/event/PaymentChannelOrderPaidEvent.java @@ -0,0 +1,27 @@ +package com.qniao.dam.domian.aggregate.paymentchannelorder.event; + +import com.qniao.dam.domian.aggregate.paymentorder.constant.PaymentMethodEnum; +import com.qniao.domain.BaseDomainEvent; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class PaymentChannelOrderPaidEvent extends BaseDomainEvent { + + private static final long serialVersionUID = 1L; + + private Long id; + + private Long txnOrderId; + + private PaymentMethodEnum paymentMethod; + + private LocalDateTime paidTime; +} diff --git a/dating-agency-mall-server/pom.xml b/dating-agency-mall-server/pom.xml index 6b3ee33..a24e455 100644 --- a/dating-agency-mall-server/pom.xml +++ b/dating-agency-mall-server/pom.xml @@ -72,6 +72,11 @@ weixin-java-pay 3.3.4.B + + com.qniao + dating-agency-mall-event + 0.0.1-SNAPSHOT + diff --git a/dating-agency-mall-server/src/main/java/com/qniao/dam/api/command/notify/user/NotifyUserCommandController.java b/dating-agency-mall-server/src/main/java/com/qniao/dam/api/command/notify/user/NotifyUserCommandController.java new file mode 100644 index 0000000..74c2cd3 --- /dev/null +++ b/dating-agency-mall-server/src/main/java/com/qniao/dam/api/command/notify/user/NotifyUserCommandController.java @@ -0,0 +1,34 @@ +package com.qniao.dam.api.command.notify.user; + +import cn.hutool.core.util.StrUtil; +import com.qniao.dam.application.service.notify.NotifyApplicationService; +import com.qniao.framework.annotation.IgnoreResponseAdvice; +import com.qniao.framework.exception.BizException; +import io.swagger.annotations.Api; +import org.apache.commons.io.IOUtils; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; + +@Api(tags = "应用支付通知") +@RestController +@RequestMapping("user") +public class NotifyUserCommandController { + + @Resource + private NotifyApplicationService notifyApplicationService; + + @RequestMapping("/notify/wx") + @IgnoreResponseAdvice + public String wx(HttpServletRequest request) throws IOException { + String xmlResult = IOUtils.toString(request.getInputStream(), request.getCharacterEncoding()); + if (StrUtil.isBlank(xmlResult)) { + throw new BizException("回调内容不能为空"); + } + return notifyApplicationService.wx(xmlResult); + } + +} \ No newline at end of file diff --git a/dating-agency-mall-server/src/main/java/com/qniao/dam/application/service/notify/NotifyApplicationService.java b/dating-agency-mall-server/src/main/java/com/qniao/dam/application/service/notify/NotifyApplicationService.java new file mode 100644 index 0000000..4a3ccd3 --- /dev/null +++ b/dating-agency-mall-server/src/main/java/com/qniao/dam/application/service/notify/NotifyApplicationService.java @@ -0,0 +1,104 @@ +package com.qniao.dam.application.service.notify; + +import cn.hutool.core.date.DateUtil; +import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult; +import com.github.binarywang.wxpay.config.WxPayConfig; +import com.github.binarywang.wxpay.exception.WxPayException; +import com.github.binarywang.wxpay.service.WxPayService; +import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl; +import com.qniao.dam.domain.aggregate.paymentchannelorder.PaymentChannelOrderAggregate; +import com.qniao.dam.domain.aggregate.paymentchannelorder.entity.PaymentChannelOrder; +import com.qniao.dam.domian.aggregate.paymentchannelorder.constant.PaymentChannelOrderStatusEnum; +import com.qniao.dam.infrastructure.persistent.dao.domain.PaymentChannelOrderDao; +import com.qniao.domain.BaseApplicationService; +import com.qniao.domain.BaseDomainEvent; +import com.qniao.framework.exception.BizException; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.util.Assert; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.math.RoundingMode; + +@Service +@Slf4j +public class NotifyApplicationService extends BaseApplicationService { + + @Value("${weixin.mchid}") + private String mchId; + @Value("${weixin.mchkey}") + private String mchKey; + private static final String WX_SUCCESS_RTN = ""; + private static final String WX_FAIL_RTN = ""; + public static final String RETURN_VALUE_SUCCESS = "SUCCESS"; + + @Resource + private PaymentChannelOrderDao paymentChannelOrderDao; + @Resource + private PaymentChannelOrderAggregate paymentChannelOrderAggregate; + + public String wx(String xmlResult) { + try { + WxPayOrderNotifyResult result = parseOrderNotifyResult(xmlResult); + // 查询订单 + PaymentChannelOrder paymentChannelOrder = paymentChannelOrderDao.selectById(result.getOutTradeNo()); + Assert.notNull(paymentChannelOrder, "支付订单不存在"); + // 验证业务数据是否正确 + checkWxPayParams(result, paymentChannelOrder); + // 更新订单信息 + paymentChannelOrder.setPaidTime(DateUtil.parseLocalDateTime(result.getTimeEnd(), "yyyyMMddHHmmss")); + paymentChannelOrder.setExtOrderNo(result.getTransactionId()); + BaseDomainEvent event = paymentChannelOrderAggregate.paid(paymentChannelOrder); + this.sendEvent(event); + return WX_SUCCESS_RTN; + } catch (WxPayException e) { + log.error("微信回调结果异常,异常原因", e); + } + return WX_FAIL_RTN; + } + + private WxPayOrderNotifyResult parseOrderNotifyResult(String xmlResult) throws WxPayException { + WxPayService wxPayService = new WxPayServiceImpl(); + WxPayOrderNotifyResult result = null; + WxPayConfig wxPayConfig = new WxPayConfig(); + wxPayConfig.setMchId(mchId); + wxPayConfig.setMchKey(mchKey); + wxPayService.setConfig(wxPayConfig); + // 解析并校验参数 + try { + result = wxPayService.parseOrderNotifyResult(xmlResult); + } catch (Exception e) { + e.printStackTrace(); + } + return result; + } + + /** + * 验证微信参数 + */ + private void checkWxPayParams(WxPayOrderNotifyResult params, PaymentChannelOrder paymentChannelOrder) { + //校验结果是否成功 + if (!RETURN_VALUE_SUCCESS.equalsIgnoreCase(params.getResultCode()) + && RETURN_VALUE_SUCCESS.equalsIgnoreCase(params.getReturnCode())) { + String err = "returnCode=" + params.getReturnCode() + ",resultCode=" + params.getResultCode() + + ",errCode={}" + params.getErrCode() + ",errCodeDes={}" + params.getErrCodeDes(); + log.error(err); + throw new BizException("支付结果为失败"); + } + checkCommonParams(new BigDecimal(params.getTotalFee()), paymentChannelOrder); + } + + /** + * 验证订单数据 + */ + private void checkCommonParams(BigDecimal amount, PaymentChannelOrder paymentChannelOrder) { + if (!PaymentChannelOrderStatusEnum.UNPAID.equals(paymentChannelOrder.getStatus())) { + throw new BizException("支付订单状态不正确"); + } + if (!(paymentChannelOrder.getAmount().multiply(new BigDecimal(100)).setScale(0, RoundingMode.HALF_UP).compareTo(amount) == 0)) { + throw new BizException("支付金额错误"); + } + } +} diff --git a/dating-agency-mall-server/src/main/java/com/qniao/dam/domain/aggregate/paymentchannelorder/PaymentChannelOrderAggregate.java b/dating-agency-mall-server/src/main/java/com/qniao/dam/domain/aggregate/paymentchannelorder/PaymentChannelOrderAggregate.java index d4abef3..9c95c27 100644 --- a/dating-agency-mall-server/src/main/java/com/qniao/dam/domain/aggregate/paymentchannelorder/PaymentChannelOrderAggregate.java +++ b/dating-agency-mall-server/src/main/java/com/qniao/dam/domain/aggregate/paymentchannelorder/PaymentChannelOrderAggregate.java @@ -3,6 +3,9 @@ package com.qniao.dam.domain.aggregate.paymentchannelorder; import com.qniao.dam.domain.aggregate.paymentchannelorder.entity.PaymentChannelOrder; import com.qniao.dam.domain.aggregate.paymentchannelorder.repository.PaymentChannelOrderRepository; import com.qniao.dam.domian.aggregate.paymentchannelorder.constant.PaymentChannelOrderStatusEnum; +import com.qniao.dam.domian.aggregate.paymentchannelorder.event.PaymentChannelOrderPaidEvent; +import com.qniao.domain.BaseDomainEvent; +import com.qniao.framework.utils.TypeConvertUtils; import org.springframework.stereotype.Service; import javax.annotation.Resource; @@ -17,4 +20,10 @@ public class PaymentChannelOrderAggregate { paymentChannelOrder.setStatus(PaymentChannelOrderStatusEnum.UNPAID); paymentChannelOrderRepository.save(paymentChannelOrder); } + + public BaseDomainEvent paid(PaymentChannelOrder paymentChannelOrder) { + paymentChannelOrder.setStatus(PaymentChannelOrderStatusEnum.PAID); + paymentChannelOrderRepository.save(paymentChannelOrder); + return TypeConvertUtils.convert(paymentChannelOrder, PaymentChannelOrderPaidEvent.class); + } }