From 18118188e370e45f6e1bd43e5b33fd4c4a156655 Mon Sep 17 00:00:00 2001
From: lin <sbla5888@163.com>
Date: Mon, 08 Apr 2024 16:01:44 +0800
Subject: [PATCH] 微信支付+获取用户的openid
---
src/main/java/org/springblade/common/config/WxMiniConfig.java | 21
src/main/java/org/springblade/modules/pay/entity/RefundInfoEntity.java | 102 +
src/main/java/org/springblade/modules/property/mapper/PropertyChargeRecordMapper.xml | 79 +
src/main/java/org/springblade/common/config/WxPayConfig.java | 39
src/main/java/org/springblade/common/enums/wxpay/WxNotifyType.java | 13
src/main/java/org/springblade/modules/wechat/service/WechatService.java | 12
src/main/java/org/springblade/modules/pay/service/IRefundInfoService.java | 46
src/main/java/org/springblade/modules/pay/mapper/RefundInfoMapper.java | 60 +
src/main/java/org/springblade/modules/pay/controller/RefundInfoController.java | 125 ++
src/main/java/org/springblade/modules/pay/service/IWxPayService.java | 31
src/main/java/org/springblade/modules/pay/controller/WxPayController.java | 139 +-
src/main/java/org/springblade/modules/pay/vo/RefundInfoVO.java | 34
src/main/java/org/springblade/modules/property/mapper/PropertyChargeRecordMapper.java | 18
src/main/java/org/springblade/modules/pay/entity/WeChatMiniAuthorizeVo.java | 39
src/main/java/org/springblade/modules/pay/service/impl/RefundInfoServiceImpl.java | 118 ++
src/main/java/org/springblade/modules/pay/wrapper/PaymentInfoWrapper.java | 51
src/main/java/org/springblade/modules/pay/controller/OrderInfoController.java | 135 ++
src/main/java/org/springblade/modules/pay/mapper/OrderInfoMapper.java | 44
src/main/java/org/springblade/modules/wechat/service/impl/WechatServiceImpl.java | 59 +
src/main/java/org/springblade/modules/pay/dto/PaymentInfoDTO.java | 34
src/main/java/org/springblade/modules/pay/mapper/OrderInfoMapper.xml | 15
src/main/java/org/springblade/modules/pay/vo/PaymentInfoVO.java | 34
src/main/java/org/springblade/modules/property/dto/PropertyChargeRecordDTO.java | 18
src/main/java/org/springblade/modules/pay/vo/OrderInfoVO.java | 34
src/main/java/org/springblade/modules/pay/service/impl/PaymentInfoServiceImpl.java | 88 +
src/main/java/org/springblade/modules/pay/wrapper/RefundInfoWrapper.java | 51
src/main/java/org/springblade/modules/pay/service/impl/WxPayServiceImpl.java | 732 +++++++++++--
src/main/java/org/springblade/modules/pay/controller/PaymentInfoController.java | 125 ++
src/main/java/org/springblade/modules/pay/mapper/PaymentInfoMapper.java | 59 +
src/main/java/org/springblade/modules/pay/service/IPaymentInfoService.java | 45
src/main/java/org/springblade/modules/pay/dto/OrderInfoDTO.java | 34
src/main/java/org/springblade/modules/pay/mapper/RefundInfoMapper.xml | 71 +
src/main/java/org/springblade/modules/pay/entity/PaymentInfoEntity.java | 95 +
src/main/java/org/springblade/modules/system/entity/User.java | 4
src/main/java/org/springblade/modules/pay/service/IOrderInfoService.java | 59 +
src/main/java/org/springblade/modules/pay/wrapper/OrderInfoWrapper.java | 51
src/main/java/org/springblade/modules/property/service/impl/PropertyChargeRecordServiceImpl.java | 3
src/main/java/org/springblade/modules/pay/dto/RefundInfoDTO.java | 34
src/main/java/org/springblade/modules/property/entity/PropertyChargeRecord.java | 108 +
src/main/java/org/springblade/modules/pay/entity/OrderInfoEntity.java | 100 +
src/main/java/org/springblade/modules/pay/mapper/PaymentInfoMapper.xml | 64 +
src/main/java/org/springblade/modules/wechat/controller/WechatController.java | 33
src/main/java/org/springblade/modules/property/service/IPropertyChargeRecordService.java | 3
src/main/resources/application.yml | 15
src/main/java/org/springblade/modules/pay/service/impl/OrderInfoServiceImpl.java | 207 +++
45 files changed, 3,071 insertions(+), 210 deletions(-)
diff --git a/src/main/java/org/springblade/common/config/WxMiniConfig.java b/src/main/java/org/springblade/common/config/WxMiniConfig.java
new file mode 100644
index 0000000..9972e29
--- /dev/null
+++ b/src/main/java/org/springblade/common/config/WxMiniConfig.java
@@ -0,0 +1,21 @@
+package org.springblade.common.config;
+
+import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@ConfigurationProperties(prefix = "wxmini") //读取wxmini节点
+@Data //使用set方法将wxpay节点中的值填充到当前类的属性中
+@Slf4j
+public class WxMiniConfig {
+
+ // appid
+ private String appid;
+
+ // 小程序appSecret key
+ private String secret;
+
+ private String jscode2sessionUrl;
+}
diff --git a/src/main/java/org/springblade/common/config/WxPayConfig.java b/src/main/java/org/springblade/common/config/WxPayConfig.java
index 1c018b4..3d7edf1 100644
--- a/src/main/java/org/springblade/common/config/WxPayConfig.java
+++ b/src/main/java/org/springblade/common/config/WxPayConfig.java
@@ -18,9 +18,9 @@
import java.security.PrivateKey;
-//@Configuration
+@Configuration
// @PropertySource("classpath:wxpay.properties") //读取配置文件
-//@ConfigurationProperties(prefix = "wxpay") //读取wxpay节点
+@ConfigurationProperties(prefix = "wxpay") //读取wxpay节点
@Data //使用set方法将wxpay节点中的值填充到当前类的属性中
@Slf4j
public class WxPayConfig {
@@ -111,8 +111,8 @@
*
* @return
*/
-// @Bean
- public ScheduledUpdateCertificatesVerifier getVerifier(String privateKeyPath, String mchSerialNo, String mchId, String apiV3Key) {
+ @Bean
+ public ScheduledUpdateCertificatesVerifier getVerifier() {
log.info("获取签名验证器");
@@ -140,8 +140,8 @@
* @param verifier
* @return
*/
-// @Bean(name = "wxPayClient")
- public CloseableHttpClient getWxPayClient(String privateKeyPath, String mchSerialNo, String mchId, String apiV3Key) {
+ @Bean(name = "wxPayClient")
+ public CloseableHttpClient getWxPayClient(ScheduledUpdateCertificatesVerifier verifier) {
log.info("获取httpClient");
@@ -150,7 +150,7 @@
WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
.withMerchant(mchId, mchSerialNo, privateKey)
- .withValidator(new WechatPay2Validator(getVerifier(privateKeyPath, mchSerialNo, mchId, apiV3Key)));
+ .withValidator(new WechatPay2Validator(verifier));
// ... 接下来,你仍然可以通过builder设置各种参数,来配置你的HttpClient
// 通过WechatPayHttpClientBuilder构造的HttpClient,会自动的处理签名和验签,并进行证书自动更新
@@ -159,5 +159,30 @@
return httpClient;
}
+ /**
+ * 获取HttpClient,无需进行应答签名验证,跳过验签的流程
+ */
+ @Bean(name = "wxPayNoSignClient")
+ public CloseableHttpClient getWxPayNoSignClient() {
+
+ //获取商户私钥
+ PrivateKey privateKey = getPrivateKey(privateKeyPath);
+
+ //用于构造HttpClient
+ WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
+ //设置商户信息
+ .withMerchant(mchId, mchSerialNo, privateKey)
+ //无需进行签名验证、通过withValidator((response) -> true)实现
+ .withValidator((response) -> true);
+
+ // 通过WechatPayHttpClientBuilder构造的HttpClient,会自动的处理签名和验签,并进行证书自动更新
+ CloseableHttpClient httpClient = builder.build();
+
+ log.info("== getWxPayNoSignClient END ==");
+
+ return httpClient;
+ }
+
}
+
diff --git a/src/main/java/org/springblade/common/enums/wxpay/WxNotifyType.java b/src/main/java/org/springblade/common/enums/wxpay/WxNotifyType.java
index b0f4825..2eed92e 100644
--- a/src/main/java/org/springblade/common/enums/wxpay/WxNotifyType.java
+++ b/src/main/java/org/springblade/common/enums/wxpay/WxNotifyType.java
@@ -21,7 +21,18 @@
/**
* 退款结果通知
*/
- REFUND_NOTIFY("/wxPay/refunds/notify");
+ REFUND_NOTIFY("/wxPay/refunds/notify"),
+
+ /**
+ * 添加分账接收方API
+ */
+ RECEIVERS_ADD("/v3/profitsharing/receivers/add"),
+
+ /**
+ * 创建分账订单API
+ *
+ */
+ PROFITSHARING_ORDERS("/v3/profitsharing/orders");
/**
* 类型
diff --git a/src/main/java/org/springblade/modules/pay/controller/OrderInfoController.java b/src/main/java/org/springblade/modules/pay/controller/OrderInfoController.java
new file mode 100644
index 0000000..99bca25
--- /dev/null
+++ b/src/main/java/org/springblade/modules/pay/controller/OrderInfoController.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the dreamlu.net developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.modules.pay.controller;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import lombok.AllArgsConstructor;
+import javax.validation.Valid;
+
+import org.springblade.core.mp.support.Condition;
+import org.springblade.core.mp.support.Query;
+import org.springblade.core.tool.api.R;
+import org.springblade.core.tool.utils.Func;
+import org.springblade.modules.pay.entity.OrderInfoEntity;
+import org.springframework.web.bind.annotation.*;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import org.springblade.modules.pay.vo.OrderInfoVO;
+import org.springblade.modules.pay.wrapper.OrderInfoWrapper;
+import org.springblade.modules.pay.service.IOrderInfoService;
+import org.springblade.core.boot.ctrl.BladeController;
+
+/**
+ * 订单信息 控制器
+ *
+ * @author BladeX
+ * @since 2024-04-07
+ */
+@RestController
+@AllArgsConstructor
+@RequestMapping("blade-orderInfo/orderInfo")
+@Api(value = "订单信息", tags = "订单信息接口")
+public class OrderInfoController extends BladeController {
+
+ private final IOrderInfoService orderInfoService;
+
+ /**
+ * 订单信息 详情
+ */
+ @GetMapping("/detail")
+ @ApiOperationSupport(order = 1)
+ @ApiOperation(value = "详情", notes = "传入orderInfo")
+ public R<OrderInfoVO> detail(OrderInfoEntity orderInfo) {
+ OrderInfoEntity detail = orderInfoService.getOne(Condition.getQueryWrapper(orderInfo));
+ return R.data(OrderInfoWrapper.build().entityVO(detail));
+ }
+ /**
+ * 订单信息 分页
+ */
+ @GetMapping("/list")
+ @ApiOperationSupport(order = 2)
+ @ApiOperation(value = "分页", notes = "传入orderInfo")
+ public R<IPage<OrderInfoVO>> list(OrderInfoEntity orderInfo, Query query) {
+ IPage<OrderInfoEntity> pages = orderInfoService.page(Condition.getPage(query), Condition.getQueryWrapper(orderInfo));
+ return R.data(OrderInfoWrapper.build().pageVO(pages));
+ }
+
+ /**
+ * 订单信息 自定义分页
+ */
+ @GetMapping("/page")
+ @ApiOperationSupport(order = 3)
+ @ApiOperation(value = "分页", notes = "传入orderInfo")
+ public R<IPage<OrderInfoVO>> page(OrderInfoVO orderInfo, Query query) {
+ IPage<OrderInfoVO> pages = orderInfoService.selectOrderInfoPage(Condition.getPage(query), orderInfo);
+ return R.data(pages);
+ }
+
+ /**
+ * 订单信息 新增
+ */
+ @PostMapping("/save")
+ @ApiOperationSupport(order = 4)
+ @ApiOperation(value = "新增", notes = "传入orderInfo")
+ public R save(@Valid @RequestBody OrderInfoEntity orderInfo) {
+ return R.status(orderInfoService.save(orderInfo));
+ }
+
+ /**
+ * 创建订单信息
+ */
+ @PostMapping("/save")
+ @ApiOperationSupport(order = 4)
+ @ApiOperation(value = "新增", notes = "传入orderInfo")
+ public R save(@RequestParam Long propertyChargeRecordId) {
+ return R.data(orderInfoService.createOrderByPropertyChargeRecordId(propertyChargeRecordId));
+ }
+
+ /**
+ * 订单信息 修改
+ */
+ @PostMapping("/update")
+ @ApiOperationSupport(order = 5)
+ @ApiOperation(value = "修改", notes = "传入orderInfo")
+ public R update(@Valid @RequestBody OrderInfoEntity orderInfo) {
+ return R.status(orderInfoService.updateById(orderInfo));
+ }
+
+ /**
+ * 订单信息 新增或修改
+ */
+ @PostMapping("/submit")
+ @ApiOperationSupport(order = 6)
+ @ApiOperation(value = "新增或修改", notes = "传入orderInfo")
+ public R submit(@Valid @RequestBody OrderInfoEntity orderInfo) {
+ return R.status(orderInfoService.saveOrUpdate(orderInfo));
+ }
+
+ /**
+ * 订单信息 删除
+ */
+ @PostMapping("/remove")
+ @ApiOperationSupport(order = 7)
+ @ApiOperation(value = "逻辑删除", notes = "传入ids")
+ public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
+ return R.status(orderInfoService.removeBatchByIds(Func.toLongList(ids)));
+ }
+
+
+}
diff --git a/src/main/java/org/springblade/modules/pay/controller/PaymentInfoController.java b/src/main/java/org/springblade/modules/pay/controller/PaymentInfoController.java
new file mode 100644
index 0000000..0c13196
--- /dev/null
+++ b/src/main/java/org/springblade/modules/pay/controller/PaymentInfoController.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the dreamlu.net developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.modules.pay.controller;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import lombok.AllArgsConstructor;
+import javax.validation.Valid;
+
+import org.springblade.core.mp.support.Condition;
+import org.springblade.core.mp.support.Query;
+import org.springblade.core.tool.api.R;
+import org.springblade.core.tool.utils.Func;
+import org.springblade.modules.pay.entity.PaymentInfoEntity;
+import org.springblade.modules.pay.vo.PaymentInfoVO;
+import org.springframework.web.bind.annotation.*;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import org.springblade.modules.pay.wrapper.PaymentInfoWrapper;
+import org.springblade.modules.pay.service.IPaymentInfoService;
+import org.springblade.core.boot.ctrl.BladeController;
+
+/**
+ * 支付信息 控制器
+ *
+ * @author BladeX
+ * @since 2024-04-07
+ */
+@RestController
+@AllArgsConstructor
+@RequestMapping("blade-paymentInfo/paymentInfo")
+@Api(value = "支付信息", tags = "支付信息接口")
+public class PaymentInfoController extends BladeController {
+
+ private final IPaymentInfoService paymentInfoService;
+
+ /**
+ * 支付信息 详情
+ */
+ @GetMapping("/detail")
+ @ApiOperationSupport(order = 1)
+ @ApiOperation(value = "详情", notes = "传入paymentInfo")
+ public R<PaymentInfoVO> detail(PaymentInfoEntity paymentInfo) {
+ PaymentInfoEntity detail = paymentInfoService.getOne(Condition.getQueryWrapper(paymentInfo));
+ return R.data(PaymentInfoWrapper.build().entityVO(detail));
+ }
+ /**
+ * 支付信息 分页
+ */
+ @GetMapping("/list")
+ @ApiOperationSupport(order = 2)
+ @ApiOperation(value = "分页", notes = "传入paymentInfo")
+ public R<IPage<PaymentInfoVO>> list(PaymentInfoEntity paymentInfo, Query query) {
+ IPage<PaymentInfoEntity> pages = paymentInfoService.page(Condition.getPage(query), Condition.getQueryWrapper(paymentInfo));
+ return R.data(PaymentInfoWrapper.build().pageVO(pages));
+ }
+
+ /**
+ * 支付信息 自定义分页
+ */
+ @GetMapping("/page")
+ @ApiOperationSupport(order = 3)
+ @ApiOperation(value = "分页", notes = "传入paymentInfo")
+ public R<IPage<PaymentInfoVO>> page(PaymentInfoVO paymentInfo, Query query) {
+ IPage<PaymentInfoVO> pages = paymentInfoService.selectPaymentInfoPage(Condition.getPage(query), paymentInfo);
+ return R.data(pages);
+ }
+
+ /**
+ * 支付信息 新增
+ */
+ @PostMapping("/save")
+ @ApiOperationSupport(order = 4)
+ @ApiOperation(value = "新增", notes = "传入paymentInfo")
+ public R save(@Valid @RequestBody PaymentInfoEntity paymentInfo) {
+ return R.status(paymentInfoService.save(paymentInfo));
+ }
+
+ /**
+ * 支付信息 修改
+ */
+ @PostMapping("/update")
+ @ApiOperationSupport(order = 5)
+ @ApiOperation(value = "修改", notes = "传入paymentInfo")
+ public R update(@Valid @RequestBody PaymentInfoEntity paymentInfo) {
+ return R.status(paymentInfoService.updateById(paymentInfo));
+ }
+
+ /**
+ * 支付信息 新增或修改
+ */
+ @PostMapping("/submit")
+ @ApiOperationSupport(order = 6)
+ @ApiOperation(value = "新增或修改", notes = "传入paymentInfo")
+ public R submit(@Valid @RequestBody PaymentInfoEntity paymentInfo) {
+ return R.status(paymentInfoService.saveOrUpdate(paymentInfo));
+ }
+
+ /**
+ * 支付信息 删除
+ */
+ @PostMapping("/remove")
+ @ApiOperationSupport(order = 7)
+ @ApiOperation(value = "逻辑删除", notes = "传入ids")
+ public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
+ return R.status(paymentInfoService.removeBatchByIds(Func.toLongList(ids)));
+ }
+
+
+}
diff --git a/src/main/java/org/springblade/modules/pay/controller/RefundInfoController.java b/src/main/java/org/springblade/modules/pay/controller/RefundInfoController.java
new file mode 100644
index 0000000..9a88bd8
--- /dev/null
+++ b/src/main/java/org/springblade/modules/pay/controller/RefundInfoController.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the dreamlu.net developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.modules.pay.controller;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import lombok.AllArgsConstructor;
+import javax.validation.Valid;
+
+import org.springblade.core.mp.support.Condition;
+import org.springblade.core.mp.support.Query;
+import org.springblade.core.tool.api.R;
+import org.springblade.core.tool.utils.Func;
+import org.springblade.modules.pay.entity.RefundInfoEntity;
+import org.springblade.modules.pay.service.IRefundInfoService;
+import org.springblade.modules.pay.vo.RefundInfoVO;
+import org.springblade.modules.pay.wrapper.RefundInfoWrapper;
+import org.springframework.web.bind.annotation.*;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import org.springblade.core.boot.ctrl.BladeController;
+
+/**
+ * 退款信息 控制器
+ *
+ * @author BladeX
+ * @since 2024-04-07
+ */
+@RestController
+@AllArgsConstructor
+@RequestMapping("blade-refundInfo/refundInfo")
+@Api(value = "退款信息", tags = "退款信息接口")
+public class RefundInfoController extends BladeController {
+
+ private final IRefundInfoService refundInfoService;
+
+ /**
+ * 退款信息 详情
+ */
+ @GetMapping("/detail")
+ @ApiOperationSupport(order = 1)
+ @ApiOperation(value = "详情", notes = "传入refundInfo")
+ public R<RefundInfoVO> detail(RefundInfoEntity refundInfo) {
+ RefundInfoEntity detail = refundInfoService.getOne(Condition.getQueryWrapper(refundInfo));
+ return R.data(RefundInfoWrapper.build().entityVO(detail));
+ }
+ /**
+ * 退款信息 分页
+ */
+ @GetMapping("/list")
+ @ApiOperationSupport(order = 2)
+ @ApiOperation(value = "分页", notes = "传入refundInfo")
+ public R<IPage<RefundInfoVO>> list(RefundInfoEntity refundInfo, Query query) {
+ IPage<RefundInfoEntity> pages = refundInfoService.page(Condition.getPage(query), Condition.getQueryWrapper(refundInfo));
+ return R.data(RefundInfoWrapper.build().pageVO(pages));
+ }
+
+ /**
+ * 退款信息 自定义分页
+ */
+ @GetMapping("/page")
+ @ApiOperationSupport(order = 3)
+ @ApiOperation(value = "分页", notes = "传入refundInfo")
+ public R<IPage<RefundInfoVO>> page(RefundInfoVO refundInfo, Query query) {
+ IPage<RefundInfoVO> pages = refundInfoService.selectRefundInfoPage(Condition.getPage(query), refundInfo);
+ return R.data(pages);
+ }
+
+ /**
+ * 退款信息 新增
+ */
+ @PostMapping("/save")
+ @ApiOperationSupport(order = 4)
+ @ApiOperation(value = "新增", notes = "传入refundInfo")
+ public R save(@Valid @RequestBody RefundInfoEntity refundInfo) {
+ return R.status(refundInfoService.save(refundInfo));
+ }
+
+ /**
+ * 退款信息 修改
+ */
+ @PostMapping("/update")
+ @ApiOperationSupport(order = 5)
+ @ApiOperation(value = "修改", notes = "传入refundInfo")
+ public R update(@Valid @RequestBody RefundInfoEntity refundInfo) {
+ return R.status(refundInfoService.updateById(refundInfo));
+ }
+
+ /**
+ * 退款信息 新增或修改
+ */
+ @PostMapping("/submit")
+ @ApiOperationSupport(order = 6)
+ @ApiOperation(value = "新增或修改", notes = "传入refundInfo")
+ public R submit(@Valid @RequestBody RefundInfoEntity refundInfo) {
+ return R.status(refundInfoService.saveOrUpdate(refundInfo));
+ }
+
+ /**
+ * 退款信息 删除
+ */
+ @PostMapping("/remove")
+ @ApiOperationSupport(order = 7)
+ @ApiOperation(value = "逻辑删除", notes = "传入ids")
+ public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
+ return R.status(refundInfoService.removeBatchByIds(Func.toLongList(ids)));
+ }
+
+
+}
diff --git a/src/main/java/org/springblade/modules/pay/controller/WxPayController.java b/src/main/java/org/springblade/modules/pay/controller/WxPayController.java
index 016e4c6..22df1f0 100644
--- a/src/main/java/org/springblade/modules/pay/controller/WxPayController.java
+++ b/src/main/java/org/springblade/modules/pay/controller/WxPayController.java
@@ -1,35 +1,32 @@
package org.springblade.modules.pay.controller;
import com.google.gson.Gson;
-import com.wechat.pay.contrib.apache.httpclient.auth.ScheduledUpdateCertificatesVerifier;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
-import lombok.AllArgsConstructor;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springblade.common.config.WxPayConfig;
+import lombok.extern.slf4j.Slf4j;
import org.springblade.common.utils.HttpUtils;
import org.springblade.common.utils.WechatPay2ValidatorForRequest;
-import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.tool.api.R;
import org.springblade.modules.pay.entity.WxPayInfo;
import org.springblade.modules.pay.service.IWxPayService;
import org.springframework.web.bind.annotation.*;
+import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;
+@CrossOrigin //跨域
@RestController
-@AllArgsConstructor
-@RequestMapping("/wxpay")
-@Api(value = "微信支付接口", tags = "微信支付接口")
-public class WxPayController extends BladeController {
+@RequestMapping("/wxPay")
+@Api(tags = "网站微信支付APIv3")
+@Slf4j
+public class WxPayController {
- private static final Logger logger = LoggerFactory.getLogger(WxPayController.class);
-
+ @Resource
private IWxPayService wxPayService;
+
@PostMapping("/save")
public R save(@RequestBody WxPayInfo wxPayInfo) {
@@ -57,21 +54,22 @@
return R.data(wxPayService.getOpenId(code));
}
+
/**
* jsapi下单
*
- * @param productId
+ * @param properChargeRecordId
* @return
* @throws Exception
*/
@ApiOperation("调用jsapi统一下单API")
@GetMapping("/jsapiPay")
- public R jsapiPay(@RequestParam("productId") Long productId) throws Exception {
+ public R jsapiPay(@RequestParam("properChargeRecordId") Long properChargeRecordId) throws Exception {
- logger.info("发起支付请求 v3");
+ log.info("发起支付请求 v3");
//返回支付二维码连接和订单号
- Map<String, String> map = wxPayService.jsapiPay(productId);
+ Map<String, String> map = wxPayService.jsapiPay(properChargeRecordId);
return R.data(map);
}
@@ -83,55 +81,82 @@
@ApiOperation("支付通知")
@PostMapping("/native/notify")
public String nativeNotify(HttpServletRequest request, HttpServletResponse response) {
+ return wxPayService.nativeNotify(request, response);
+ }
- Gson gson = new Gson();
- Map<String, String> map = new HashMap<>();//应答对象
+ /**
+ * 用户取消订单
+ *
+ * @param orderNo
+ * @return
+ * @throws Exception
+ */
+ @ApiOperation("用户取消订单")
+ @PostMapping("/cancel/{orderNo}")
+ public R cancel(@PathVariable String orderNo) throws Exception {
- try {
+ log.info("取消订单");
- //处理通知参数
- String body = HttpUtils.readData(request);
- Map<String, Object> bodyMap = gson.fromJson(body, HashMap.class);
- String requestId = (String) bodyMap.get("id");
- logger.info("支付通知的id ===> {}", requestId);
- logger.info("支付通知的完整数据 ===> {}", body);
- //int a = 9 / 0;
- ScheduledUpdateCertificatesVerifier verifier = new WxPayConfig().getVerifier("111", "111", "111", "111");
- //签名的验证
- WechatPay2ValidatorForRequest wechatPay2ValidatorForRequest
- = new WechatPay2ValidatorForRequest(verifier, requestId, body);
- if (!wechatPay2ValidatorForRequest.validate(request)) {
- logger.error("通知验签失败");
- //失败应答
- response.setStatus(500);
- map.put("code", "ERROR");
- map.put("message", "通知验签失败");
- return gson.toJson(map);
- }
- logger.info("通知验签成功");
+ wxPayService.cancelOrder(orderNo);
+ return R.data("订单已取消");
+ }
- //处理订单
- wxPayService.processOrder(bodyMap);
+ /**
+ * 查询订单
+ *
+ * @param orderNo
+ * @return
+ * @throws Exception
+ */
+ @ApiOperation("查询订单")
+ @GetMapping("/query/{orderNo}")
+ public R queryOrder(@PathVariable String orderNo) throws Exception {
- //应答超时
- //模拟接收微信端的重复通知
- // TimeUnit.SECONDS.sleep(5);
+ log.info("查询订单");
- //成功应答
- response.setStatus(200);
- map.put("code", "SUCCESS");
- map.put("message", "成功");
- return gson.toJson(map);
+ String result = wxPayService.queryOrder(orderNo);
+ return R.data("result", result);
- } catch (Exception e) {
- e.printStackTrace();
- //失败应答
- response.setStatus(500);
- map.put("code", "ERROR");
- map.put("message", "失败");
- return gson.toJson(map);
- }
+ }
+
+ @ApiOperation("申请退款")
+ @PostMapping("/refunds/{orderNo}/{reason}")
+ public R refunds(@PathVariable String orderNo, @PathVariable String reason) throws Exception {
+
+ log.info("申请退款");
+ wxPayService.refund(orderNo, reason);
+ return R.success("退款申请成功");
+ }
+
+ /**
+ * 查询退款
+ *
+ * @param refundNo
+ * @return
+ * @throws Exception
+ */
+ @ApiOperation("查询退款")
+ @GetMapping("/query-refund/{refundNo}")
+ public R queryRefund(@PathVariable String refundNo) throws Exception {
+
+ log.info("查询退款");
+
+ String result = wxPayService.queryRefund(refundNo);
+ return R.data("result", result);
+ }
+
+
+ /**
+ * 退款结果通知
+ * 退款状态改变后,微信会把相关退款结果发送给商户。
+ */
+ @ApiOperation("退款结果通知")
+ @PostMapping("/refunds/notify")
+ public String refundsNotify(HttpServletRequest request, HttpServletResponse response) {
+
+ log.info("退款通知执行");
+ return wxPayService.refundsNotify(request, response);
}
diff --git a/src/main/java/org/springblade/modules/pay/dto/OrderInfoDTO.java b/src/main/java/org/springblade/modules/pay/dto/OrderInfoDTO.java
new file mode 100644
index 0000000..de45776
--- /dev/null
+++ b/src/main/java/org/springblade/modules/pay/dto/OrderInfoDTO.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the dreamlu.net developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.modules.pay.dto;
+
+import org.springblade.modules.pay.entity.OrderInfoEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 订单信息 数据传输对象实体类
+ *
+ * @author BladeX
+ * @since 2024-04-07
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class OrderInfoDTO extends OrderInfoEntity {
+ private static final long serialVersionUID = 1L;
+
+}
diff --git a/src/main/java/org/springblade/modules/pay/dto/PaymentInfoDTO.java b/src/main/java/org/springblade/modules/pay/dto/PaymentInfoDTO.java
new file mode 100644
index 0000000..0eca252
--- /dev/null
+++ b/src/main/java/org/springblade/modules/pay/dto/PaymentInfoDTO.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the dreamlu.net developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.modules.pay.dto;
+
+import org.springblade.modules.pay.entity.PaymentInfoEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 支付信息 数据传输对象实体类
+ *
+ * @author BladeX
+ * @since 2024-04-07
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class PaymentInfoDTO extends PaymentInfoEntity {
+ private static final long serialVersionUID = 1L;
+
+}
diff --git a/src/main/java/org/springblade/modules/pay/dto/RefundInfoDTO.java b/src/main/java/org/springblade/modules/pay/dto/RefundInfoDTO.java
new file mode 100644
index 0000000..41b82ac
--- /dev/null
+++ b/src/main/java/org/springblade/modules/pay/dto/RefundInfoDTO.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the dreamlu.net developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.modules.pay.dto;
+
+import org.springblade.modules.pay.entity.RefundInfoEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 退款信息 数据传输对象实体类
+ *
+ * @author BladeX
+ * @since 2024-04-07
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class RefundInfoDTO extends RefundInfoEntity {
+ private static final long serialVersionUID = 1L;
+
+}
diff --git a/src/main/java/org/springblade/modules/pay/entity/OrderInfoEntity.java b/src/main/java/org/springblade/modules/pay/entity/OrderInfoEntity.java
new file mode 100644
index 0000000..7e6e1d1
--- /dev/null
+++ b/src/main/java/org/springblade/modules/pay/entity/OrderInfoEntity.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the dreamlu.net developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.modules.pay.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.EqualsAndHashCode;
+import org.springblade.core.tenant.mp.TenantEntity;
+
+import java.util.Date;
+
+/**
+ * 订单信息 实体类
+ *
+ * @author BladeX
+ * @since 2024-04-07
+ */
+@Data
+@TableName("jczz_order_info")
+@ApiModel(value = "OrderInfo对象", description = "订单信息")
+public class OrderInfoEntity {
+
+
+ /** id */
+ @ApiModelProperty(value = "主键ID", example = "")
+ @TableId(value = "id", type = IdType.ASSIGN_ID)
+ private Long id;
+
+ /** 订单标题 */
+ @ApiModelProperty(value = "订单标题", example = "")
+ @TableField("title")
+ private String title;
+
+ /** 商户订单编号 */
+ @ApiModelProperty(value = "商户订单编号", example = "")
+ @TableField("order_no")
+ private String orderNo;
+
+ /** 用户id */
+ @ApiModelProperty(value = "用户id", example = "")
+ @TableField("user_id")
+ private Long userId;
+
+ /** 支付产品id */
+ @ApiModelProperty(value = "支付产品id", example = "")
+ @TableField("proper_charge_record_id")
+ private Long properChargeRecordId;
+
+ /** 订单二维码连接 */
+ @ApiModelProperty(value = "订单二维码连接", example = "")
+ @TableField("code_url")
+ private String codeUrl;
+
+ /** 订单金额(分) */
+ @ApiModelProperty(value = "订单金额(分)", example = "")
+ @TableField("total_fee")
+ private Integer totalFee;
+
+ /** 订单状态 */
+ @ApiModelProperty(value = "订单状态", example = "")
+ @TableField("order_status")
+ private String orderStatus;
+
+ /** 创建时间 */
+ @ApiModelProperty(value = "创建时间", example = "")
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+ @TableField("create_time")
+ private Date createTime;
+
+ /** 更新时间 */
+ @ApiModelProperty(value = "更新时间", example = "")
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+ @TableField("update_time")
+ private Date updateTime;
+
+ /** 物业id */
+ @ApiModelProperty(value = "物业id", example = "")
+ @TableId("proper_id")
+ private Long properId;
+}
diff --git a/src/main/java/org/springblade/modules/pay/entity/PaymentInfoEntity.java b/src/main/java/org/springblade/modules/pay/entity/PaymentInfoEntity.java
new file mode 100644
index 0000000..46c08d3
--- /dev/null
+++ b/src/main/java/org/springblade/modules/pay/entity/PaymentInfoEntity.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the dreamlu.net developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.modules.pay.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.EqualsAndHashCode;
+import org.springblade.core.tenant.mp.TenantEntity;
+
+import java.util.Date;
+
+/**
+ * 支付信息 实体类
+ *
+ * @author BladeX
+ * @since 2024-04-07
+ */
+@Data
+@TableName("jczz_payment_info")
+@ApiModel(value = "PaymentInfo对象", description = "支付信息")
+public class PaymentInfoEntity {
+
+
+ /** id */
+ @ApiModelProperty(value = "主键ID", example = "")
+ @TableId(value = "id", type = IdType.ASSIGN_ID)
+ private Long id;
+
+ /** 订单编号 */
+ @ApiModelProperty(value = "订单编号", example = "")
+ @TableField("order_no")
+ private String orderNo;
+
+ /** 支付系统交易编号 */
+ @ApiModelProperty(value = "支付系统交易编号", example = "")
+ @TableField("transaction_id")
+ private String transactionId;
+
+ /** 支付类型 */
+ @ApiModelProperty(value = "支付类型", example = "")
+ @TableField("payment_type")
+ private String paymentType;
+
+ /** 交易类型 */
+ @ApiModelProperty(value = "交易类型", example = "")
+ @TableField("trade_type")
+ private String tradeType;
+
+ /** 交易状态 */
+ @ApiModelProperty(value = "交易状态", example = "")
+ @TableField("trade_state")
+ private String tradeState;
+
+ /** 支付金额(分) */
+ @ApiModelProperty(value = "支付金额(分)", example = "")
+ @TableField("payer_total")
+ private Integer payerTotal;
+
+ /** 通知参数 */
+ @ApiModelProperty(value = "通知参数", example = "")
+ @TableField("content")
+ private String content;
+
+ /** 创建时间 */
+ @ApiModelProperty(value = "创建时间", example = "")
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+ @TableField("create_time")
+ private Date createTime;
+
+ /** 更新时间 */
+ @ApiModelProperty(value = "更新时间", example = "")
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+ @TableField("update_time")
+ private Date updateTime;
+}
diff --git a/src/main/java/org/springblade/modules/pay/entity/RefundInfoEntity.java b/src/main/java/org/springblade/modules/pay/entity/RefundInfoEntity.java
new file mode 100644
index 0000000..ec28d2e
--- /dev/null
+++ b/src/main/java/org/springblade/modules/pay/entity/RefundInfoEntity.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the dreamlu.net developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.modules.pay.entity;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.EqualsAndHashCode;
+import org.springblade.core.tenant.mp.TenantEntity;
+
+import java.util.Date;
+
+/**
+ * 退款信息 实体类
+ *
+ * @author BladeX
+ * @since 2024-04-07
+ */
+@Data
+@TableName("jczz_refund_info")
+@ApiModel(value = "RefundInfo对象", description = "退款信息")
+public class RefundInfoEntity {
+
+ /** id */
+ @ApiModelProperty(value = "主键ID", example = "")
+ @TableId(value = "id", type = IdType.ASSIGN_ID)
+ private Long id;
+
+ /** 订单编号 */
+ @ApiModelProperty(value = "订单编号", example = "")
+ @TableField("order_no")
+ private String orderNo;
+
+ /** 退款单编号 */
+ @ApiModelProperty(value = "退款单编号", example = "")
+ @TableField("refund_no")
+ private String refundNo;
+
+ /** 支付系统退款单号 */
+ @ApiModelProperty(value = "支付系统退款单号", example = "")
+ @TableField("refund_id")
+ private String refundId;
+
+ /** 原订单金额(分) */
+ @ApiModelProperty(value = "原订单金额(分)", example = "")
+ @TableField("total_fee")
+ private Integer totalFee;
+
+ /** 退款金额(分) */
+ @ApiModelProperty(value = "退款金额(分)", example = "")
+ @TableField("refund")
+ private Integer refund;
+
+ /** 退款原因 */
+ @ApiModelProperty(value = "退款原因", example = "")
+ @TableField("reason")
+ private String reason;
+
+ /** 退款单状态 */
+ @ApiModelProperty(value = "退款单状态", example = "")
+ @TableField("refund_status")
+ private String refundStatus;
+
+ /** 申请退款返回参数 */
+ @ApiModelProperty(value = "申请退款返回参数", example = "")
+ @TableField("content_return")
+ private String contentReturn;
+
+ /** 退款结果通知参数 */
+ @ApiModelProperty(value = "退款结果通知参数", example = "")
+ @TableField("content_notify")
+ private String contentNotify;
+
+ /** 创建时间 */
+ @ApiModelProperty(value = "创建时间", example = "")
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+ @TableField(value = "create_time",fill = FieldFill.INSERT)
+ private Date createTime;
+
+ /** 更新时间 */
+ @ApiModelProperty(value = "更新时间", example = "")
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+ @TableField(value = "update_time",fill = FieldFill.UPDATE)
+ private Date updateTime;
+
+}
diff --git a/src/main/java/org/springblade/modules/pay/entity/WeChatMiniAuthorizeVo.java b/src/main/java/org/springblade/modules/pay/entity/WeChatMiniAuthorizeVo.java
new file mode 100644
index 0000000..13625aa
--- /dev/null
+++ b/src/main/java/org/springblade/modules/pay/entity/WeChatMiniAuthorizeVo.java
@@ -0,0 +1,39 @@
+package org.springblade.modules.pay.entity;
+
+import com.alibaba.fastjson.annotation.JSONField;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@ApiModel(value="WeChatMiniAuthorizeVo对象", description="微信小程序用户授权返回数据")
+public class WeChatMiniAuthorizeVo implements Serializable {
+
+ private static final long serialVersionUID=1L;
+
+ @ApiModelProperty(value = "会话密钥")
+ @JSONField(name = "session_key")
+ private String sessionKey;
+
+ @ApiModelProperty(value = "用户唯一标识")
+ @JSONField(name = "openid")
+ private String openId;
+
+ @ApiModelProperty(value = "用户在开放平台的唯一标识符,若当前小程序已绑定到微信开放平台帐号下会返回")
+ @JSONField(name = "unionid")
+ private String unionId;
+
+ @ApiModelProperty(value = "错误码")
+ @JSONField(name = "errcode")
+ private String errCode;
+
+ @ApiModelProperty(value = "错误信息")
+ @JSONField(name = "errmsg")
+ private String errMsg;
+}
diff --git a/src/main/java/org/springblade/modules/pay/mapper/OrderInfoMapper.java b/src/main/java/org/springblade/modules/pay/mapper/OrderInfoMapper.java
new file mode 100644
index 0000000..a6c5f59
--- /dev/null
+++ b/src/main/java/org/springblade/modules/pay/mapper/OrderInfoMapper.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the dreamlu.net developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.modules.pay.mapper;
+
+import org.springblade.modules.pay.entity.OrderInfoEntity;
+import org.springblade.modules.pay.vo.OrderInfoVO;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+
+import java.util.List;
+
+/**
+ * 订单信息 Mapper 接口
+ *
+ * @author BladeX
+ * @since 2024-04-07
+ */
+public interface OrderInfoMapper extends BaseMapper<OrderInfoEntity> {
+
+ /**
+ * 自定义分页
+ *
+ * @param page
+ * @param orderInfo
+ * @return
+ */
+ List<OrderInfoVO> selectOrderInfoPage(IPage page, OrderInfoVO orderInfo);
+
+
+}
diff --git a/src/main/java/org/springblade/modules/pay/mapper/OrderInfoMapper.xml b/src/main/java/org/springblade/modules/pay/mapper/OrderInfoMapper.xml
new file mode 100644
index 0000000..cfda60f
--- /dev/null
+++ b/src/main/java/org/springblade/modules/pay/mapper/OrderInfoMapper.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="org.springblade.modules.pay.mapper.OrderInfoMapper">
+
+ <!-- 通用查询映射结果 -->
+ <resultMap id="orderInfoResultMap" type="org.springblade.modules.pay.entity.OrderInfoEntity">
+ </resultMap>
+
+
+ <select id="selectOrderInfoPage" resultMap="orderInfoResultMap">
+ select * from jczz_order_info where is_deleted = 0
+ </select>
+
+
+</mapper>
diff --git a/src/main/java/org/springblade/modules/pay/mapper/PaymentInfoMapper.java b/src/main/java/org/springblade/modules/pay/mapper/PaymentInfoMapper.java
new file mode 100644
index 0000000..875b7c5
--- /dev/null
+++ b/src/main/java/org/springblade/modules/pay/mapper/PaymentInfoMapper.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the dreamlu.net developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.modules.pay.mapper;
+
+import org.springblade.modules.pay.dto.PaymentInfoDTO;
+import org.springblade.modules.pay.entity.PaymentInfoEntity;
+import org.springblade.modules.pay.vo.PaymentInfoVO;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import java.util.List;
+
+/**
+ * 支付信息 Mapper 接口
+ *
+ * @author BladeX
+ * @since 2024-04-07
+ */
+public interface PaymentInfoMapper extends BaseMapper<PaymentInfoEntity> {
+
+ /**
+ * 自定义分页
+ *
+ * @param page
+ * @param paymentInfo
+ * @return
+ */
+ List<PaymentInfoVO> selectPaymentInfoPage(IPage page, PaymentInfoVO paymentInfo);
+
+
+ /**
+ * 查询支付信息
+ *
+ * @param id 支付信息ID
+ * @return 支付信息
+ */
+ public PaymentInfoDTO selectPaymentInfoById(Long id);
+
+ /**
+ * 查询支付信息列表
+ *
+ * @param paymentInfoDTO 支付信息
+ * @return 支付信息集合
+ */
+ public List<PaymentInfoDTO> selectPaymentInfoList(PaymentInfoDTO paymentInfoDTO);
+}
diff --git a/src/main/java/org/springblade/modules/pay/mapper/PaymentInfoMapper.xml b/src/main/java/org/springblade/modules/pay/mapper/PaymentInfoMapper.xml
new file mode 100644
index 0000000..266d878
--- /dev/null
+++ b/src/main/java/org/springblade/modules/pay/mapper/PaymentInfoMapper.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="org.springblade.modules.pay.mapper.PaymentInfoMapper">
+
+ <!-- 通用查询映射结果 -->
+ <resultMap id="paymentInfoResultMap" type="org.springblade.modules.pay.entity.PaymentInfoEntity">
+ </resultMap>
+
+
+ <select id="selectPaymentInfoPage" resultMap="paymentInfoResultMap">
+ select * from jczz_payment_info where is_deleted = 0
+ </select>
+
+ <resultMap type="org.springblade.modules.pay.dto.PaymentInfoDTO" id="PaymentInfoDTOResult">
+ <result property="id" column="id" />
+ <result property="orderNo" column="order_no" />
+ <result property="transactionId" column="transaction_id" />
+ <result property="paymentType" column="payment_type" />
+ <result property="tradeType" column="trade_type" />
+ <result property="tradeState" column="trade_state" />
+ <result property="payerTotal" column="payer_total" />
+ <result property="content" column="content" />
+ <result property="createTime" column="create_time" />
+ <result property="updateTime" column="update_time" />
+ </resultMap>
+
+ <sql id="selectPaymentInfo">
+ select
+ id,
+ order_no,
+ transaction_id,
+ payment_type,
+ trade_type,
+ trade_state,
+ payer_total,
+ content,
+ create_time,
+ update_time
+ from
+ jczz_payment_info
+ </sql>
+
+ <select id="selectPaymentInfoById" parameterType="long" resultMap="PaymentInfoDTOResult">
+ <include refid="selectPaymentInfo"/>
+ where
+ id = #{id}
+ </select>
+
+ <select id="selectPaymentInfoList" parameterType="org.springblade.modules.pay.dto.PaymentInfoDTO" resultMap="PaymentInfoDTOResult">
+ <include refid="selectPaymentInfo"/>
+ <where>
+ <if test="id != null "> and id = #{id}</if>
+ <if test="orderNo != null and orderNo != ''"> and order_no = #{orderNo}</if>
+ <if test="transactionId != null and transactionId != ''"> and transaction_id = #{transactionId}</if>
+ <if test="paymentType != null and paymentType != ''"> and payment_type = #{paymentType}</if>
+ <if test="tradeType != null and tradeType != ''"> and trade_type = #{tradeType}</if>
+ <if test="tradeState != null and tradeState != ''"> and trade_state = #{tradeState}</if>
+ <if test="payerTotal != null and payerTotal != ''"> and payer_total = #{payerTotal}</if>
+ <if test="content != null and content != ''"> and content = #{content}</if>
+ <if test="createTime != null "> and create_time = #{createTime}</if>
+ <if test="updateTime != null "> and update_time = #{updateTime}</if>
+ </where>
+ </select>
+</mapper>
diff --git a/src/main/java/org/springblade/modules/pay/mapper/RefundInfoMapper.java b/src/main/java/org/springblade/modules/pay/mapper/RefundInfoMapper.java
new file mode 100644
index 0000000..f42ae01
--- /dev/null
+++ b/src/main/java/org/springblade/modules/pay/mapper/RefundInfoMapper.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the dreamlu.net developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.modules.pay.mapper;
+
+import org.springblade.modules.pay.dto.RefundInfoDTO;
+import org.springblade.modules.pay.entity.RefundInfoEntity;
+import org.springblade.modules.pay.vo.RefundInfoVO;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import java.util.List;
+
+/**
+ * 退款信息 Mapper 接口
+ *
+ * @author BladeX
+ * @since 2024-04-07
+ */
+public interface RefundInfoMapper extends BaseMapper<RefundInfoEntity> {
+
+ /**
+ * 自定义分页
+ *
+ * @param page
+ * @param refundInfo
+ * @return
+ */
+ List<RefundInfoVO> selectRefundInfoPage(IPage page, RefundInfoVO refundInfo);
+
+ /**
+ * 查询退款信息
+ *
+ * @param id 退款信息ID
+ * @return 退款信息
+ */
+ public RefundInfoDTO selectRefundInfoById(Long id);
+
+ /**
+ * 查询退款信息列表
+ *
+ * @param refundInfoDTO 退款信息
+ * @return 退款信息集合
+ */
+ public List<RefundInfoDTO> selectRefundInfoList(RefundInfoDTO refundInfoDTO);
+
+
+}
diff --git a/src/main/java/org/springblade/modules/pay/mapper/RefundInfoMapper.xml b/src/main/java/org/springblade/modules/pay/mapper/RefundInfoMapper.xml
new file mode 100644
index 0000000..511768f
--- /dev/null
+++ b/src/main/java/org/springblade/modules/pay/mapper/RefundInfoMapper.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="org.springblade.modules.pay.mapper.RefundInfoMapper">
+
+ <!-- 通用查询映射结果 -->
+ <resultMap id="refundInfoResultMap" type="org.springblade.modules.pay.entity.RefundInfoEntity">
+ </resultMap>
+
+
+ <select id="selectRefundInfoPage" resultMap="refundInfoResultMap">
+ select * from jczz_refund_info where is_deleted = 0
+ </select>
+ <resultMap type="org.springblade.modules.pay.dto.RefundInfoDTO" id="RefundInfoDTOResult">
+ <result property="id" column="id" />
+ <result property="orderNo" column="order_no" />
+ <result property="refundNo" column="refund_no" />
+ <result property="refundId" column="refund_id" />
+ <result property="totalFee" column="total_fee" />
+ <result property="refund" column="refund" />
+ <result property="reason" column="reason" />
+ <result property="refundStatus" column="refund_status" />
+ <result property="contentReturn" column="content_return" />
+ <result property="contentNotify" column="content_notify" />
+ <result property="createTime" column="create_time" />
+ <result property="updateTime" column="update_time" />
+ </resultMap>
+
+ <sql id="selectRefundInfo">
+ select
+ id,
+ order_no,
+ refund_no,
+ refund_id,
+ total_fee,
+ refund,
+ reason,
+ refund_status,
+ content_return,
+ content_notify,
+ create_time,
+ update_time
+ from
+ jczz_refund_info
+ </sql>
+
+ <select id="selectRefundInfoById" parameterType="long" resultMap="RefundInfoDTOResult">
+ <include refid="selectRefundInfo"/>
+ where
+ id = #{id}
+ </select>
+
+ <select id="selectRefundInfoList" parameterType="org.springblade.modules.pay.dto.RefundInfoDTO" resultMap="RefundInfoDTOResult">
+ <include refid="selectRefundInfo"/>
+ <where>
+ <if test="id != null "> and id = #{id}</if>
+ <if test="orderNo != null "> and order_no = #{orderNo}</if>
+ <if test="refundNo != null "> and refund_no = #{refundNo}</if>
+ <if test="refundId != null "> and refund_id = #{refundId}</if>
+ <if test="totalFee != null and totalFee != ''"> and total_fee = #{totalFee}</if>
+ <if test="refund != null and refund != ''"> and refund = #{refund}</if>
+ <if test="reason != null and reason != ''"> and reason = #{reason}</if>
+ <if test="refundStatus != null and refundStatus != ''"> and refund_status = #{refundStatus}</if>
+ <if test="contentReturn != null and contentReturn != ''"> and content_return = #{contentReturn}</if>
+ <if test="contentNotify != null and contentNotify != ''"> and content_notify = #{contentNotify}</if>
+ <if test="createTime != null "> and create_time = #{createTime}</if>
+ <if test="updateTime != null "> and update_time = #{updateTime}</if>
+ </where>
+ </select>
+
+
+</mapper>
diff --git a/src/main/java/org/springblade/modules/pay/service/IOrderInfoService.java b/src/main/java/org/springblade/modules/pay/service/IOrderInfoService.java
new file mode 100644
index 0000000..1ded657
--- /dev/null
+++ b/src/main/java/org/springblade/modules/pay/service/IOrderInfoService.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the dreamlu.net developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.modules.pay.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import org.springblade.common.enums.OrderStatus;
+import org.springblade.modules.pay.entity.OrderInfoEntity;
+import org.springblade.modules.pay.vo.OrderInfoVO;
+import org.springblade.core.mp.base.BaseService;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+
+import java.util.List;
+
+/**
+ * 订单信息 服务类
+ *
+ * @author BladeX
+ * @since 2024-04-07
+ */
+public interface IOrderInfoService extends IService<OrderInfoEntity> {
+
+ /**
+ * 自定义分页
+ *
+ * @param page
+ * @param orderInfo
+ * @return
+ */
+ IPage<OrderInfoVO> selectOrderInfoPage(IPage<OrderInfoVO> page, OrderInfoVO orderInfo);
+
+
+ OrderInfoEntity createOrderByPropertyChargeRecordId(Long propertyChargeRecordId);
+
+ void saveCodeUrl(String orderNo, String codeUrl);
+
+ List<OrderInfoEntity> listOrderByCreateTimeDesc();
+
+ void updateStatusByOrderNo(String orderNo, OrderStatus orderStatus);
+
+ String getOrderStatus(String orderNo);
+
+ List<OrderInfoEntity> getNoPayOrderByDuration(int minutes);
+
+ OrderInfoEntity getOrderByOrderNo(String orderNo);
+}
diff --git a/src/main/java/org/springblade/modules/pay/service/IPaymentInfoService.java b/src/main/java/org/springblade/modules/pay/service/IPaymentInfoService.java
new file mode 100644
index 0000000..f2501c2
--- /dev/null
+++ b/src/main/java/org/springblade/modules/pay/service/IPaymentInfoService.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the dreamlu.net developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.modules.pay.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import org.springblade.modules.pay.entity.PaymentInfoEntity;
+import org.springblade.modules.pay.vo.PaymentInfoVO;
+import org.springblade.core.mp.base.BaseService;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+
+/**
+ * 支付信息 服务类
+ *
+ * @author BladeX
+ * @since 2024-04-07
+ */
+public interface IPaymentInfoService extends IService<PaymentInfoEntity> {
+
+ /**
+ * 自定义分页
+ *
+ * @param page
+ * @param paymentInfo
+ * @return
+ */
+ IPage<PaymentInfoVO> selectPaymentInfoPage(IPage<PaymentInfoVO> page, PaymentInfoVO paymentInfo);
+
+ void createPaymentInfo(String plainText);
+
+
+}
diff --git a/src/main/java/org/springblade/modules/pay/service/IRefundInfoService.java b/src/main/java/org/springblade/modules/pay/service/IRefundInfoService.java
new file mode 100644
index 0000000..a1eab06
--- /dev/null
+++ b/src/main/java/org/springblade/modules/pay/service/IRefundInfoService.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the dreamlu.net developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.modules.pay.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import org.springblade.modules.pay.entity.RefundInfoEntity;
+import org.springblade.modules.pay.vo.RefundInfoVO;
+import org.springblade.core.mp.base.BaseService;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+
+/**
+ * 退款信息 服务类
+ *
+ * @author BladeX
+ * @since 2024-04-07
+ */
+public interface IRefundInfoService extends IService<RefundInfoEntity> {
+
+ /**
+ * 自定义分页
+ *
+ * @param page
+ * @param refundInfo
+ * @return
+ */
+ IPage<RefundInfoVO> selectRefundInfoPage(IPage<RefundInfoVO> page, RefundInfoVO refundInfo);
+
+
+ RefundInfoEntity createRefundByOrderNo(String orderNo, String reason);
+
+ void updateRefund(String plainText);
+}
diff --git a/src/main/java/org/springblade/modules/pay/service/IWxPayService.java b/src/main/java/org/springblade/modules/pay/service/IWxPayService.java
index bac42f4..dc12258 100644
--- a/src/main/java/org/springblade/modules/pay/service/IWxPayService.java
+++ b/src/main/java/org/springblade/modules/pay/service/IWxPayService.java
@@ -3,20 +3,35 @@
import com.baomidou.mybatisplus.extension.service.IService;
import org.springblade.modules.pay.entity.WxPayInfo;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Map;
public interface IWxPayService extends IService<WxPayInfo> {
- /**
- * 获取openId
- * @param code
- * @return
- */
- Object getOpenId(String code);
-
- Map<String, String> jsapiPay(Long productId) throws IOException;
+ Object getOpenId(String code);
void processOrder(Map<String, Object> bodyMap) throws GeneralSecurityException;
+
+ void cancelOrder(String orderNo) throws Exception;
+
+ String queryOrder(String orderNo) throws Exception;
+
+ void checkOrderStatus(String orderNo) throws Exception;
+
+ void refund(String orderNo, String reason) throws Exception;
+
+ String queryRefund(String orderNo) throws Exception;
+
+ void checkRefundStatus(String refundNo) throws Exception;
+
+ void processRefund(Map<String, Object> bodyMap) throws Exception;
+
+ Map<String, String> jsapiPay(Long productId) throws IOException, Exception;
+
+ String refundsNotify(HttpServletRequest request, HttpServletResponse response);
+
+ String nativeNotify(HttpServletRequest request, HttpServletResponse response);
}
diff --git a/src/main/java/org/springblade/modules/pay/service/impl/OrderInfoServiceImpl.java b/src/main/java/org/springblade/modules/pay/service/impl/OrderInfoServiceImpl.java
new file mode 100644
index 0000000..e3cfef6
--- /dev/null
+++ b/src/main/java/org/springblade/modules/pay/service/impl/OrderInfoServiceImpl.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the dreamlu.net developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.modules.pay.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springblade.common.enums.OrderStatus;
+import org.springblade.modules.pay.entity.OrderInfoEntity;
+import org.springblade.modules.pay.vo.OrderInfoVO;
+import org.springblade.modules.pay.mapper.OrderInfoMapper;
+import org.springblade.modules.pay.service.IOrderInfoService;
+import org.springblade.modules.property.entity.PropertyChargeRecord;
+import org.springblade.modules.property.service.IPropertyChargeRecordService;
+import org.springframework.stereotype.Service;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+
+import javax.annotation.Resource;
+import java.text.SimpleDateFormat;
+import java.time.Duration;
+import java.time.Instant;
+import java.util.Date;
+import java.util.List;
+import java.util.Random;
+
+/**
+ * 订单信息 服务实现类
+ *
+ * @author BladeX
+ * @since 2024-04-07
+ */
+@Service
+public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfoEntity> implements IOrderInfoService {
+
+ private static Logger logger = LoggerFactory.getLogger(OrderInfoServiceImpl.class);
+
+
+ @Resource
+ private IPropertyChargeRecordService iPropertyChargeRecordService;
+
+ @Override
+ public IPage<OrderInfoVO> selectOrderInfoPage(IPage<OrderInfoVO> page, OrderInfoVO orderInfo) {
+ return page.setRecords(baseMapper.selectOrderInfoPage(page, orderInfo));
+ }
+
+
+ @Override
+ public OrderInfoEntity createOrderByPropertyChargeRecordId(Long propertyChargeRecordId) {
+
+ //查找已存在但未支付的订单
+ OrderInfoEntity orderInfo = this.getNoPayOrderByPropertyChargeRecordId(propertyChargeRecordId);
+ if( orderInfo != null){
+ return orderInfo;
+ }
+ //获取商品信息
+ PropertyChargeRecord propertyChargeRecord = iPropertyChargeRecordService.getById(propertyChargeRecordId);
+ //生成订单
+ orderInfo = new OrderInfoEntity();
+ orderInfo.setTitle(propertyChargeRecord.getPayContent());
+ orderInfo.setOrderNo(getOrderNoStr()); //订单号
+ orderInfo.setProperChargeRecordId(propertyChargeRecordId);
+ orderInfo.setTotalFee(propertyChargeRecord.getPayPrice().intValue()); //分
+ orderInfo.setOrderStatus(OrderStatus.NOTPAY.getType());
+ baseMapper.insert(orderInfo);
+ return orderInfo;
+ }
+
+ /**
+ * 存储订单二维码
+ * @param orderNo
+ * @param codeUrl
+ */
+ @Override
+ public void saveCodeUrl(String orderNo, String codeUrl) {
+
+ QueryWrapper<OrderInfoEntity> queryWrapper = new QueryWrapper<>();
+ queryWrapper.eq("order_no", orderNo);
+
+ OrderInfoEntity orderInfo = new OrderInfoEntity();
+ orderInfo.setCodeUrl(codeUrl);
+
+ baseMapper.update(orderInfo, queryWrapper);
+ }
+
+ /**
+ * 查询订单列表,并倒序查询
+ * @return
+ */
+ @Override
+ public List<OrderInfoEntity> listOrderByCreateTimeDesc() {
+
+ QueryWrapper<OrderInfoEntity> queryWrapper = new QueryWrapper<OrderInfoEntity>().orderByDesc("create_time");
+ return baseMapper.selectList(queryWrapper);
+ }
+
+ /**
+ * 根据订单号更新订单状态
+ * @param orderNo
+ * @param orderStatus
+ */
+ @Override
+ public void updateStatusByOrderNo(String orderNo, OrderStatus orderStatus) {
+
+ logger.info("更新订单状态 ===> {}", orderStatus.getType());
+
+ QueryWrapper<OrderInfoEntity> queryWrapper = new QueryWrapper<>();
+ queryWrapper.eq("order_no", orderNo);
+
+ OrderInfoEntity orderInfo = new OrderInfoEntity();
+ orderInfo.setOrderStatus(orderStatus.getType());
+
+ baseMapper.update(orderInfo, queryWrapper);
+ }
+
+ /**
+ * 根据订单号获取订单状态
+ * @param orderNo
+ * @return
+ */
+ @Override
+ public String getOrderStatus(String orderNo) {
+
+ QueryWrapper<OrderInfoEntity> queryWrapper = new QueryWrapper<>();
+ queryWrapper.eq("order_no", orderNo);
+ OrderInfoEntity orderInfo = baseMapper.selectOne(queryWrapper);
+ if(orderInfo == null){
+ return null;
+ }
+ return orderInfo.getOrderStatus();
+ }
+
+ /**
+ * 查询创建超过minutes分钟并且未支付的订单
+ * @param minutes
+ * @return
+ */
+ @Override
+ public List<OrderInfoEntity> getNoPayOrderByDuration(int minutes) {
+
+ Instant instant = Instant.now().minus(Duration.ofMinutes(minutes));
+
+ QueryWrapper<OrderInfoEntity> queryWrapper = new QueryWrapper<>();
+ queryWrapper.eq("order_status", OrderStatus.NOTPAY.getType());
+ queryWrapper.le("create_time", instant);
+
+ List<OrderInfoEntity> orderInfoList = baseMapper.selectList(queryWrapper);
+
+ return orderInfoList;
+ }
+
+ /**
+ * 根据订单号获取订单
+ * @param orderNo
+ * @return
+ */
+ @Override
+ public OrderInfoEntity getOrderByOrderNo(String orderNo) {
+
+ QueryWrapper<OrderInfoEntity> queryWrapper = new QueryWrapper<>();
+ queryWrapper.eq("order_no", orderNo);
+ OrderInfoEntity orderInfo = baseMapper.selectOne(queryWrapper);
+
+ return orderInfo;
+ }
+
+
+ /**
+ * 根据商品id查询未支付订单
+ * 防止重复创建订单对象
+ * @param propertyChargeRecordId
+ * @return
+ */
+ private OrderInfoEntity getNoPayOrderByPropertyChargeRecordId(Long propertyChargeRecordId) {
+
+ QueryWrapper<OrderInfoEntity> queryWrapper = new QueryWrapper<>();
+ queryWrapper.eq("product_id", propertyChargeRecordId);
+ queryWrapper.eq("order_status", OrderStatus.NOTPAY.getType());
+// queryWrapper.eq("user_id", userId);
+ OrderInfoEntity orderInfo = baseMapper.selectOne(queryWrapper);
+ return orderInfo;
+ }
+
+ //生成订单号
+ public static String getOrderNoStr() {
+ String order = "pay" + new SimpleDateFormat("yyyyMMdd").format(new Date());
+ Random r = new Random();
+ for (int i = 0; i < 10; i++) {
+ order += r.nextInt(9);
+ }
+ return order;
+ }
+}
diff --git a/src/main/java/org/springblade/modules/pay/service/impl/PaymentInfoServiceImpl.java b/src/main/java/org/springblade/modules/pay/service/impl/PaymentInfoServiceImpl.java
new file mode 100644
index 0000000..a42515e
--- /dev/null
+++ b/src/main/java/org/springblade/modules/pay/service/impl/PaymentInfoServiceImpl.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the dreamlu.net developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.modules.pay.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.google.gson.Gson;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springblade.common.enums.PayType;
+import org.springblade.modules.pay.entity.PaymentInfoEntity;
+import org.springblade.modules.pay.mapper.PaymentInfoMapper;
+import org.springblade.modules.pay.vo.PaymentInfoVO;
+import org.springblade.modules.pay.service.IPaymentInfoService;
+import org.springblade.core.mp.base.BaseServiceImpl;
+import org.springframework.stereotype.Service;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 支付信息 服务实现类
+ *
+ * @author BladeX
+ * @since 2024-04-07
+ */
+@Service
+public class PaymentInfoServiceImpl extends ServiceImpl<PaymentInfoMapper, PaymentInfoEntity> implements IPaymentInfoService {
+
+ private static Logger logger = LoggerFactory.getLogger(PaymentInfoServiceImpl.class);
+
+ @Override
+ public IPage<PaymentInfoVO> selectPaymentInfoPage(IPage<PaymentInfoVO> page, PaymentInfoVO paymentInfo) {
+ return page.setRecords(baseMapper.selectPaymentInfoPage(page, paymentInfo));
+ }
+
+ /**
+ * 记录支付日志
+ * @param plainText
+ */
+ @Override
+ public void createPaymentInfo(String plainText) {
+
+ logger.info("记录支付日志");
+
+ Gson gson = new Gson();
+ HashMap plainTextMap = gson.fromJson(plainText, HashMap.class);
+
+ //订单号
+ String orderNo = (String)plainTextMap.get("out_trade_no");
+ //业务编号
+ String transactionId = (String)plainTextMap.get("transaction_id");
+ //支付类型
+ String tradeType = (String)plainTextMap.get("trade_type");
+ //交易状态
+ String tradeState = (String)plainTextMap.get("trade_state");
+ //用户实际支付金额
+ Map<String, Object> amount = (Map)plainTextMap.get("amount");
+ Integer payerTotal = ((Double) amount.get("payer_total")).intValue();
+
+ PaymentInfoEntity paymentInfo = new PaymentInfoEntity();
+ paymentInfo.setOrderNo(orderNo);
+ paymentInfo.setPaymentType(PayType.WXPAY.getType());
+ paymentInfo.setTransactionId(transactionId);
+ paymentInfo.setTradeType(tradeType);
+ paymentInfo.setTradeState(tradeState);
+ paymentInfo.setPayerTotal(payerTotal);
+ paymentInfo.setContent(plainText);
+
+ baseMapper.insert(paymentInfo);
+ }
+
+
+}
diff --git a/src/main/java/org/springblade/modules/pay/service/impl/RefundInfoServiceImpl.java b/src/main/java/org/springblade/modules/pay/service/impl/RefundInfoServiceImpl.java
new file mode 100644
index 0000000..be4852f
--- /dev/null
+++ b/src/main/java/org/springblade/modules/pay/service/impl/RefundInfoServiceImpl.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the dreamlu.net developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.modules.pay.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.google.gson.Gson;
+import org.springblade.modules.pay.entity.OrderInfoEntity;
+import org.springblade.modules.pay.entity.RefundInfoEntity;
+import org.springblade.modules.pay.mapper.RefundInfoMapper;
+import org.springblade.modules.pay.service.IOrderInfoService;
+import org.springblade.modules.pay.service.IRefundInfoService;
+import org.springblade.modules.pay.vo.RefundInfoVO;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Random;
+
+/**
+ * 退款信息 服务实现类
+ *
+ * @author BladeX
+ * @since 2024-04-07
+ */
+@Service
+public class RefundInfoServiceImpl extends ServiceImpl<RefundInfoMapper, RefundInfoEntity> implements IRefundInfoService {
+
+
+ @Resource
+ private IOrderInfoService orderInfoService;
+ @Override
+ public IPage<RefundInfoVO> selectRefundInfoPage(IPage<RefundInfoVO> page, RefundInfoVO refundInfo) {
+ return page.setRecords(baseMapper.selectRefundInfoPage(page, refundInfo));
+ }
+
+ @Override
+ public RefundInfoEntity createRefundByOrderNo(String orderNo, String reason) {
+
+ //根据订单号获取订单信息
+ OrderInfoEntity orderInfo = orderInfoService.getOne(Wrappers.<OrderInfoEntity>lambdaQuery()
+ .eq(OrderInfoEntity::getOrderNo, orderNo));
+
+ //根据订单号生成退款订单
+ RefundInfoEntity refundInfo = new RefundInfoEntity();
+ refundInfo.setOrderNo(orderNo);//订单编号
+ refundInfo.setRefundNo(getOrderNoStr());//退款单编号
+ refundInfo.setTotalFee(orderInfo.getTotalFee());//原订单金额(分)
+ refundInfo.setRefund(orderInfo.getTotalFee());//退款金额(分)
+ refundInfo.setReason(reason);//退款原因
+
+ //保存退款订单
+ baseMapper.insert(refundInfo);
+
+ return refundInfo;
+ }
+
+
+ @Override
+ public void updateRefund(String content) {
+ //将json字符串转换成Map
+ Gson gson = new Gson();
+ Map<String, String> resultMap = gson.fromJson(content, HashMap.class);
+
+ //根据退款单编号修改退款单
+ QueryWrapper<RefundInfoEntity> queryWrapper = new QueryWrapper<>();
+ queryWrapper.eq("refund_no", resultMap.get("out_refund_no"));
+
+ //设置要修改的字段
+ RefundInfoEntity refundInfo = new RefundInfoEntity();
+
+ refundInfo.setRefundId(resultMap.get("refund_id"));//微信支付退款单号
+
+ //查询退款和申请退款中的返回参数
+ if(resultMap.get("status") != null){
+ refundInfo.setRefundStatus(resultMap.get("status"));//退款状态
+ refundInfo.setContentReturn(content);//将全部响应结果存入数据库的content字段
+ }
+ //退款回调中的回调参数
+ if(resultMap.get("refund_status") != null){
+ refundInfo.setRefundStatus(resultMap.get("refund_status"));//退款状态
+ refundInfo.setContentNotify(content);//将全部响应结果存入数据库的content字段
+ }
+
+ //更新退款单
+ baseMapper.update(refundInfo, queryWrapper);
+ }
+
+
+ //生成订单号
+ public static String getOrderNoStr() {
+ String order = "refund" + new SimpleDateFormat("yyyyMMdd").format(new Date());
+ Random r = new Random();
+ for (int i = 0; i < 10; i++) {
+ order += r.nextInt(9);
+ }
+ return order;
+ }
+}
diff --git a/src/main/java/org/springblade/modules/pay/service/impl/WxPayServiceImpl.java b/src/main/java/org/springblade/modules/pay/service/impl/WxPayServiceImpl.java
index 08b67fe..dfc021c 100644
--- a/src/main/java/org/springblade/modules/pay/service/impl/WxPayServiceImpl.java
+++ b/src/main/java/org/springblade/modules/pay/service/impl/WxPayServiceImpl.java
@@ -1,26 +1,48 @@
package org.springblade.modules.pay.service.impl;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.wxpay.sdk.WXPayUtil;
import com.google.gson.Gson;
import com.wechat.pay.contrib.apache.httpclient.util.AesUtil;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.springblade.common.config.WxPayConfig;
import org.springblade.common.enums.OrderStatus;
import org.springblade.common.enums.wxpay.WxApiType;
import org.springblade.common.enums.wxpay.WxNotifyType;
-import org.springblade.modules.pay.controller.WxPayController;
+import org.springblade.common.enums.wxpay.WxRefundStatus;
+import org.springblade.common.enums.wxpay.WxTradeState;
+import org.springblade.common.utils.HttpUtils;
+import org.springblade.common.utils.SpringUtils;
+import org.springblade.common.utils.WechatPay2ValidatorForRequest;
+import org.springblade.core.secure.utils.AuthUtil;
+import org.springblade.modules.pay.entity.OrderInfoEntity;
+import org.springblade.modules.pay.entity.RefundInfoEntity;
import org.springblade.modules.pay.entity.WxPayInfo;
import org.springblade.modules.pay.mapper.WxPayMapper;
+import org.springblade.modules.pay.service.IOrderInfoService;
+import org.springblade.modules.pay.service.IPaymentInfoService;
+import org.springblade.modules.pay.service.IRefundInfoService;
import org.springblade.modules.pay.service.IWxPayService;
-import org.springframework.beans.factory.annotation.Value;
+import org.springblade.modules.property.entity.PropertyChargeRecord;
+import org.springblade.modules.property.service.IPropertyChargeService;
+import org.springblade.modules.system.entity.User;
+import org.springblade.modules.system.service.IUserService;
import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.StringUtils;
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
@@ -31,100 +53,37 @@
@Service
public class WxPayServiceImpl extends ServiceImpl<WxPayMapper,WxPayInfo> implements IWxPayService {
+ private static Logger logger = LoggerFactory.getLogger(WxPayServiceImpl.class);
- private final String MINI_PROGRAM_APP_ID = "wx41aa8a5d2e565a05";
- private static final Logger logger = LoggerFactory.getLogger(WxPayServiceImpl.class);
+
+ @Resource
+ private WxPayConfig wxPayConfig;
+
+ @Resource
+ private IPropertyChargeService iPropertyChargeService;
+
+
+ @Resource
+ private CloseableHttpClient wxPayClient;
+
+ @Resource
+ private IOrderInfoService orderInfoService;
+
+ @Resource
+ private IPaymentInfoService paymentInfoService;
+
+ @Resource
+ private IRefundInfoService refundsInfoService;
private final ReentrantLock lock = new ReentrantLock();
+
@Override
public Object getOpenId(String code) {
return null;
}
- @Override
- public Map<String, String> jsapiPay(Long productId) throws IOException {
-
- String prepayId = "";
- //生成订单
-// OrderInfo orderInfo = orderInfoService.createOrderByProductId(productId);
-
-
- logger.info("调用统一下单API");
-
-// //调用统一下单API
-// HttpPost httpPost = new HttpPost(wxPayConfig.getDomain().concat(WxApiType.JSAPI_PAY.getType()));
-//
-// // 请求body参数
-//
-// Gson gson = new Gson();
-// Map paramsMap = new HashMap();
-// paramsMap.put("appid", wxPayConfig.getAppid());
-// paramsMap.put("mchid", wxPayConfig.getMchId());
-// paramsMap.put("description", orderInfo.getTitle());
-// paramsMap.put("out_trade_no", orderInfo.getOrderNo());
-// paramsMap.put("notify_url", wxPayConfig.getNotifyDomain().concat(WxNotifyType.NATIVE_NOTIFY.getType()));
-//
-// Map amountMap = new HashMap();
-// amountMap.put("total", orderInfo.getTotalFee());
-// amountMap.put("currency", "CNY");
-//
-// paramsMap.put("amount", amountMap);
-//
-// Map payerMap = new HashMap();
-// payerMap.put("openid", "oSX3G6OUuGaKJbWzSHUpPbzgtDXo");
-//
-// paramsMap.put("payer", payerMap);
-//
-// //将参数转换成json字符串
-// String jsonParams = gson.toJson(paramsMap);
-// logger.info("请求参数 ===> {}" + jsonParams);
-//
-// StringEntity entity = new StringEntity(jsonParams, "utf-8");
-// entity.setContentType("application/json");
-// httpPost.setEntity(entity);
-// httpPost.setHeader("Accept", "application/json");
-//
-// //完成签名并执行请求
-// CloseableHttpResponse response = wxPayClient.execute(httpPost);
-//
-// try {
-// String bodyAsString = EntityUtils.toString(response.getEntity());//响应体
-// int statusCode = response.getStatusLine().getStatusCode();//响应状态码
-// if (statusCode == 200) { //处理成功
-// logger.info("成功, 返回结果 = " + bodyAsString);
-// } else if (statusCode == 204) { //处理成功,无返回Body
-// logger.info("成功");
-// } else {
-// logger.info("jszpi下单失败,响应码 = " + statusCode + ",返回结果 = " + bodyAsString);
-// throw new IOException("request failed");
-// }
-// //响应结果
-// Map<String, String> resultMap = gson.fromJson(bodyAsString, HashMap.class);
-// //预支付交易会话标识
-// prepayId = resultMap.get("prepay_id");
-//
-// //返回预支付交易会话标识
-// // 组装前端预下单参数
-// /** 返回给前端所需要的数据 */
-// SortedMap<String, String> payMap = new TreeMap<>();
-// String nonceStr = WXPayUtil.generateNonceStr();
-// String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
-// payMap.put("appId", wxPayConfig.getAppid());
-// payMap.put("timeStamp", timestamp);
-// payMap.put("nonceStr", nonceStr);
-// payMap.put("signType", "RSA");
-// payMap.put("package", "prepay_id=" + prepayId);
-// String paySign = getSign(wxPayConfig.getAppid(), prepayId, timestamp, nonceStr);
-// payMap.put("paySign", paySign);
-// logger.info("返回参数 ===> {}" + gson.toJson(payMap));
-// return payMap;
-// } finally {
-// response.close();
-// }
- return null;
- }
-
+ @Transactional(rollbackFor = Exception.class)
@Override
public void processOrder(Map<String, Object> bodyMap) throws GeneralSecurityException {
logger.info("处理订单");
@@ -143,32 +102,410 @@
以避免函数重入造成的数据混乱*/
//尝试获取锁:
// 成功获取则立即返回true,获取失败则立即返回false。不必一直等待锁的释放
-// if (lock.tryLock()) {
-// try {
-// //处理重复的通知
-// //接口调用的幂等性:无论接口被调用多少次,产生的结果是一致的。
-// String orderStatus = orderInfoService.getOrderStatus(orderNo);
-// if (!OrderStatus.NOTPAY.getType().equals(orderStatus)) {
-// return;
-// }
-//
-// //模拟通知并发
-// try {
-// TimeUnit.SECONDS.sleep(5);
-// } catch (InterruptedException e) {
-// e.printStackTrace();
-// }
-//
-// //更新订单状态
-// orderInfoService.updateStatusByOrderNo(orderNo, OrderStatus.SUCCESS);
-//
-// //记录支付日志
-// paymentInfoService.createPaymentInfo(plainText);
-// } finally {
-// //要主动释放锁
-// lock.unlock();
-// }
-// }
+ if (lock.tryLock()) {
+ try {
+ //处理重复的通知
+ //接口调用的幂等性:无论接口被调用多少次,产生的结果是一致的。
+ String orderStatus = orderInfoService.getOrderStatus(orderNo);
+ if (!OrderStatus.NOTPAY.getType().equals(orderStatus)) {
+ return;
+ }
+
+ //模拟通知并发
+ try {
+ TimeUnit.SECONDS.sleep(5);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+
+ //更新订单状态
+ orderInfoService.updateStatusByOrderNo(orderNo, OrderStatus.SUCCESS);
+
+ //记录支付日志
+ paymentInfoService.createPaymentInfo(plainText);
+ } finally {
+ //要主动释放锁
+ lock.unlock();
+ }
+ }
+ }
+
+ /**
+ * 用户取消订单
+ *
+ * @param orderNo
+ */
+ @Override
+ public void cancelOrder(String orderNo) throws Exception {
+
+ //调用微信支付的关单接口
+ this.closeOrder(orderNo);
+
+ //更新商户端的订单状态
+ orderInfoService.updateStatusByOrderNo(orderNo, OrderStatus.CANCEL);
+ }
+
+ @Override
+ public String queryOrder(String orderNo) throws Exception {
+
+ logger.info("查单接口调用 ===> {}", orderNo);
+
+ String url = String.format(WxApiType.ORDER_QUERY_BY_NO.getType(), orderNo);
+ url = wxPayConfig.getDomain().concat(url).concat("?mchid=").concat(wxPayConfig.getMchId());
+
+ HttpGet httpGet = new HttpGet(url);
+ httpGet.setHeader("Accept", "application/json");
+
+ //完成签名并执行请求
+ CloseableHttpResponse response = wxPayClient.execute(httpGet);
+
+ try {
+ String bodyAsString = EntityUtils.toString(response.getEntity());//响应体
+ int statusCode = response.getStatusLine().getStatusCode();//响应状态码
+ if (statusCode == 200) { //处理成功
+ logger.info("成功, 返回结果 = " + bodyAsString);
+ } else if (statusCode == 204) { //处理成功,无返回Body
+ logger.info("成功");
+ } else {
+ logger.info("查单接口调用,响应码 = " + statusCode + ",返回结果 = " + bodyAsString);
+ throw new IOException("request failed");
+ }
+
+ return bodyAsString;
+
+ } finally {
+ response.close();
+ }
+
+ }
+
+ /**
+ * 根据订单号查询微信支付查单接口,核实订单状态
+ * 如果订单已支付,则更新商户端订单状态,并记录支付日志
+ * 如果订单未支付,则调用关单接口关闭订单,并更新商户端订单状态
+ *
+ * @param orderNo
+ */
+ @Transactional(rollbackFor = Exception.class)
+ @Override
+ public void checkOrderStatus(String orderNo) throws Exception {
+
+ logger.info("根据订单号核实订单状态 ===> {}", orderNo);
+
+ //调用微信支付查单接口
+ String result = this.queryOrder(orderNo);
+
+ Gson gson = new Gson();
+ Map<String, String> resultMap = gson.fromJson(result, HashMap.class);
+
+ //获取微信支付端的订单状态
+ String tradeState = resultMap.get("trade_state");
+
+ //判断订单状态
+ if (WxTradeState.SUCCESS.getType().equals(tradeState)) {
+
+ logger.info("核实订单已支付 ===> {}", orderNo);
+
+ //如果确认订单已支付则更新本地订单状态
+ orderInfoService.updateStatusByOrderNo(orderNo, OrderStatus.SUCCESS);
+ //记录支付日志
+ paymentInfoService.createPaymentInfo(result);
+ }
+
+ if (WxTradeState.NOTPAY.getType().equals(tradeState)) {
+ logger.info("核实订单未支付 ===> {}", orderNo);
+
+ //如果订单未支付,则调用关单接口
+ this.closeOrder(orderNo);
+
+ //更新本地订单状态
+ orderInfoService.updateStatusByOrderNo(orderNo, OrderStatus.CLOSED);
+ }
+
+ }
+
+ /**
+ * 退款
+ *
+ * @param orderNo
+ * @param reason
+ * @throws IOException
+ */
+ @Transactional(rollbackFor = Exception.class)
+ @Override
+ public void refund(String orderNo, String reason) throws Exception {
+
+ logger.info("创建退款单记录");
+ //根据订单编号创建退款单
+ RefundInfoEntity refundsInfo = refundsInfoService.createRefundByOrderNo(orderNo, reason);
+
+ logger.info("调用退款API");
+
+ //调用统一下单API
+ String url = wxPayConfig.getDomain().concat(WxApiType.DOMESTIC_REFUNDS.getType());
+ HttpPost httpPost = new HttpPost(url);
+
+ // 请求body参数
+ Gson gson = new Gson();
+ Map paramsMap = new HashMap();
+ paramsMap.put("out_trade_no", orderNo);//订单编号
+ paramsMap.put("out_refund_no", refundsInfo.getRefundNo());//退款单编号
+ paramsMap.put("reason", reason);//退款原因
+ paramsMap.put("notify_url", wxPayConfig.getNotifyDomain().concat(WxNotifyType.REFUND_NOTIFY.getType()));//退款通知地址
+
+ Map amountMap = new HashMap();
+ amountMap.put("refund", refundsInfo.getRefund());//退款金额
+ amountMap.put("total", refundsInfo.getTotalFee());//原订单金额
+ amountMap.put("currency", "CNY");//退款币种
+ paramsMap.put("amount", amountMap);
+
+ //将参数转换成json字符串
+ String jsonParams = gson.toJson(paramsMap);
+ logger.info("请求参数 ===> {}" + jsonParams);
+
+ StringEntity entity = new StringEntity(jsonParams, "utf-8");
+ entity.setContentType("application/json");//设置请求报文格式
+ httpPost.setEntity(entity);//将请求报文放入请求对象
+ httpPost.setHeader("Accept", "application/json");//设置响应报文格式
+
+ //完成签名并执行请求,并完成验签
+ CloseableHttpResponse response = wxPayClient.execute(httpPost);
+
+ try {
+
+ //解析响应结果
+ String bodyAsString = EntityUtils.toString(response.getEntity());
+ int statusCode = response.getStatusLine().getStatusCode();
+ if (statusCode == 200) {
+ logger.info("成功, 退款返回结果 = " + bodyAsString);
+ } else if (statusCode == 204) {
+ logger.info("成功");
+ } else {
+ throw new RuntimeException("退款异常, 响应码 = " + statusCode + ", 退款返回结果 = " + bodyAsString);
+ }
+
+ //更新订单状态
+ orderInfoService.updateStatusByOrderNo(orderNo, OrderStatus.REFUND_PROCESSING);
+
+ //更新退款单
+ refundsInfoService.updateRefund(bodyAsString);
+
+ } finally {
+ response.close();
+ }
+ }
+
+
+ /**
+ * 查询退款接口调用
+ *
+ * @param refundNo
+ * @return
+ */
+ @Override
+ public String queryRefund(String refundNo) throws Exception {
+
+ logger.info("查询退款接口调用 ===> {}", refundNo);
+
+ String url = String.format(WxApiType.DOMESTIC_REFUNDS_QUERY.getType(), refundNo);
+ url = wxPayConfig.getDomain().concat(url);
+
+ //创建远程Get 请求对象
+ HttpGet httpGet = new HttpGet(url);
+ httpGet.setHeader("Accept", "application/json");
+
+ //完成签名并执行请求
+ CloseableHttpResponse response = wxPayClient.execute(httpGet);
+
+ try {
+ String bodyAsString = EntityUtils.toString(response.getEntity());
+ int statusCode = response.getStatusLine().getStatusCode();
+ if (statusCode == 200) {
+ logger.info("成功, 查询退款返回结果 = " + bodyAsString);
+ } else if (statusCode == 204) {
+ logger.info("成功");
+ } else {
+ throw new RuntimeException("查询退款异常, 响应码 = " + statusCode + ", 查询退款返回结果 = " + bodyAsString);
+ }
+
+ return bodyAsString;
+
+ } finally {
+ response.close();
+ }
+ }
+
+ /**
+ * 根据退款单号核实退款单状态
+ *
+ * @param refundNo
+ * @return
+ */
+ @Transactional(rollbackFor = Exception.class)
+ @Override
+ public void checkRefundStatus(String refundNo) throws Exception {
+
+ logger.info("根据退款单号核实退款单状态 ===> {}", refundNo);
+
+ //调用查询退款单接口
+ String result = this.queryRefund(refundNo);
+
+ //组装json请求体字符串
+ Gson gson = new Gson();
+ Map<String, String> resultMap = gson.fromJson(result, HashMap.class);
+
+ //获取微信支付端退款状态
+ String status = resultMap.get("status");
+
+ String orderNo = resultMap.get("out_trade_no");
+
+ if (WxRefundStatus.SUCCESS.getType().equals(status)) {
+
+ logger.info("核实订单已退款成功 ===> {}", refundNo);
+
+ //如果确认退款成功,则更新订单状态
+ orderInfoService.updateStatusByOrderNo(orderNo, OrderStatus.REFUND_SUCCESS);
+
+ //更新退款单
+ refundsInfoService.updateRefund(result);
+ }
+
+ if (WxRefundStatus.ABNORMAL.getType().equals(status)) {
+
+ logger.info("核实订单退款异常 ===> {}", refundNo);
+
+ //如果确认退款成功,则更新订单状态
+ orderInfoService.updateStatusByOrderNo(orderNo, OrderStatus.REFUND_ABNORMAL);
+
+ //更新退款单
+ refundsInfoService.updateRefund(result);
+ }
+ }
+
+ /**
+ * 处理退款单
+ */
+ @Transactional(rollbackFor = Exception.class)
+ @Override
+ public void processRefund(Map<String, Object> bodyMap) throws Exception {
+
+ logger.info("退款单");
+
+ //解密报文
+ String plainText = decryptFromResource(bodyMap);
+
+ //将明文转换成map
+ Gson gson = new Gson();
+ HashMap plainTextMap = gson.fromJson(plainText, HashMap.class);
+ String orderNo = (String) plainTextMap.get("out_trade_no");
+
+ if (lock.tryLock()) {
+ try {
+
+ String orderStatus = orderInfoService.getOrderStatus(orderNo);
+ if (!OrderStatus.REFUND_PROCESSING.getType().equals(orderStatus)) {
+ return;
+ }
+
+ //更新订单状态
+ orderInfoService.updateStatusByOrderNo(orderNo, OrderStatus.REFUND_SUCCESS);
+
+ //更新退款单
+ refundsInfoService.updateRefund(plainText);
+
+ } finally {
+ //要主动释放锁
+ lock.unlock();
+ }
+ }
+ }
+
+
+
+ @Override
+ public Map<String, String> jsapiPay(Long properChargeRecordId) throws Exception {
+
+ String prepayId = "";
+ //生成订单
+ OrderInfoEntity orderInfo = orderInfoService.getOne(Wrappers.<OrderInfoEntity>lambdaQuery().eq(OrderInfoEntity::getProperChargeRecordId,properChargeRecordId));
+ IUserService userService = SpringUtils.getBean(IUserService.class);
+ User serviceOne = userService.getOne(Wrappers.<User>lambdaQuery().eq(User::getId, AuthUtil.getUserId()));
+
+ logger.info("调用统一下单API");
+
+ //调用统一下单API
+ HttpPost httpPost = new HttpPost(wxPayConfig.getDomain().concat(WxApiType.JSAPI_PAY.getType()));
+
+ // 请求body参数
+
+ Gson gson = new Gson();
+ Map paramsMap = new HashMap();
+ paramsMap.put("appid", wxPayConfig.getAppid());
+ paramsMap.put("mchid", wxPayConfig.getMchId());
+ paramsMap.put("description", orderInfo.getTitle());
+ paramsMap.put("out_trade_no", orderInfo.getOrderNo());
+ paramsMap.put("notify_url", wxPayConfig.getNotifyDomain().concat(WxNotifyType.NATIVE_NOTIFY.getType()));
+
+ Map amountMap = new HashMap();
+ amountMap.put("total", orderInfo.getTotalFee());
+ amountMap.put("currency", "CNY");
+
+ paramsMap.put("amount", amountMap);
+
+ Map payerMap = new HashMap();
+ payerMap.put("openid", serviceOne.getMiniOpenId());
+
+ paramsMap.put("payer", payerMap);
+
+ // 是否指定分账,枚举值 true:是 false:否
+ paramsMap.put("profit_sharing", true);
+
+ //将参数转换成json字符串
+ String jsonParams = gson.toJson(paramsMap);
+ logger.info("请求参数 ===> {}" + jsonParams);
+
+ StringEntity entity = new StringEntity(jsonParams, "utf-8");
+ entity.setContentType("application/json");
+ httpPost.setEntity(entity);
+ httpPost.setHeader("Accept", "application/json");
+
+ //完成签名并执行请求
+ CloseableHttpResponse response = wxPayClient.execute(httpPost);
+
+ try {
+ String bodyAsString = EntityUtils.toString(response.getEntity());//响应体
+ int statusCode = response.getStatusLine().getStatusCode();//响应状态码
+ if (statusCode == 200) { //处理成功
+ logger.info("成功, 返回结果 = " + bodyAsString);
+ } else if (statusCode == 204) { //处理成功,无返回Body
+ logger.info("成功");
+ } else {
+ logger.info("jszpi下单失败,响应码 = " + statusCode + ",返回结果 = " + bodyAsString);
+ throw new IOException("request failed");
+ }
+ //响应结果
+ Map<String, String> resultMap = gson.fromJson(bodyAsString, HashMap.class);
+ //预支付交易会话标识
+ prepayId = resultMap.get("prepay_id");
+
+ //返回预支付交易会话标识
+ // 组装前端预下单参数
+ /** 返回给前端所需要的数据 */
+ SortedMap<String, String> payMap = new TreeMap<>();
+ String nonceStr = WXPayUtil.generateNonceStr();
+ String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
+ payMap.put("appId", wxPayConfig.getAppid());
+ payMap.put("timeStamp", timestamp);
+ payMap.put("nonceStr", nonceStr);
+ payMap.put("signType", "RSA");
+ payMap.put("package", "prepay_id=" + prepayId);
+ String paySign = getSign(wxPayConfig.getAppid(), prepayId, timestamp, nonceStr);
+ payMap.put("paySign", paySign);
+ logger.info("返回参数 ===> {}" + gson.toJson(payMap));
+ return payMap;
+ } finally {
+ response.close();
+ }
}
/**
@@ -196,7 +533,7 @@
//签名方式
Signature sign = Signature.getInstance("SHA256withRSA");
//私钥,通过MyPrivateKey来获取,这是个静态类可以接调用方法 ,需要的是_key.pem文件的绝对路径配上文件名
-// sign.initSign(getPrivateKey(wxPayConfig.getPrivateKeyPath()));
+ sign.initSign(getPrivateKey(wxPayConfig.getPrivateKeyPath()));
sign.update(message);
return Base64.getEncoder().encodeToString(sign.sign());
@@ -227,6 +564,52 @@
}
}
+
+ /**
+ * 关单接口的调用
+ *
+ * @param orderNo
+ */
+ private void closeOrder(String orderNo) throws Exception {
+
+ logger.info("关单接口的调用,订单号 ===> {}", orderNo);
+ //创建远程请求对象
+ String url = String.format(WxApiType.CLOSE_ORDER_BY_NO.getType(), orderNo);
+ url = wxPayConfig.getDomain().concat(url);
+ HttpPost httpPost = new HttpPost(url);
+
+ //组装json请求体
+ Gson gson = new Gson();
+ Map<String, String> paramsMap = new HashMap<>();
+ paramsMap.put("mchid", wxPayConfig.getMchId());
+ String jsonParams = gson.toJson(paramsMap);
+ logger.info("请求参数 ===> {}", jsonParams);
+
+ //将请求参数设置到请求对象中
+ StringEntity entity = new StringEntity(jsonParams, "utf-8");
+ entity.setContentType("application/json");
+ httpPost.setEntity(entity);
+ httpPost.setHeader("Accept", "application/json");
+
+ //完成签名并执行请求
+ CloseableHttpResponse response = wxPayClient.execute(httpPost);
+
+ try {
+ int statusCode = response.getStatusLine().getStatusCode();//响应状态码
+ if (statusCode == 200) { //处理成功
+ logger.info("成功200");
+ } else if (statusCode == 204) { //处理成功,无返回Body
+ logger.info("成功204");
+ } else {
+ logger.info("Native下单失败,响应码 = " + statusCode);
+ throw new IOException("request failed");
+ }
+
+ } finally {
+ response.close();
+ }
+ }
+
/**
* 对称解密
*
@@ -247,15 +630,122 @@
String associatedData = resourceMap.get("associated_data");
logger.info("密文 ===> {}", ciphertext);
-// AesUtil aesUtil = new AesUtil(wxPayConfig.getApiV3Key().getBytes(StandardCharsets.UTF_8));
-// String plainText = aesUtil.decryptToString(associatedData.getBytes(StandardCharsets.UTF_8),
-// nonce.getBytes(StandardCharsets.UTF_8),
-// ciphertext);
+ AesUtil aesUtil = new AesUtil(wxPayConfig.getApiV3Key().getBytes(StandardCharsets.UTF_8));
+ String plainText = aesUtil.decryptToString(associatedData.getBytes(StandardCharsets.UTF_8),
+ nonce.getBytes(StandardCharsets.UTF_8),
+ ciphertext);
-// logger.info("明文 ===> {}", plainText);
+ logger.info("明文 ===> {}", plainText);
-// return plainText;
- return null;
+ return plainText;
}
+ @Override
+ public String nativeNotify(HttpServletRequest request, HttpServletResponse response) {
+ Gson gson = new Gson();
+ Map<String, String> map = new HashMap<>();//应答对象
+
+ try {
+
+ //处理通知参数
+ String body = HttpUtils.readData(request);
+ Map<String, Object> bodyMap = gson.fromJson(body, HashMap.class);
+ String requestId = (String) bodyMap.get("id");
+ logger.info("支付通知的id ===> {}", requestId);
+ logger.info("支付通知的完整数据 ===> {}", body);
+ //int a = 9 / 0;
+
+ //签名的验证
+ WechatPay2ValidatorForRequest wechatPay2ValidatorForRequest
+ = new WechatPay2ValidatorForRequest(wxPayConfig.getVerifier(), requestId, body);
+ if (!wechatPay2ValidatorForRequest.validate(request)) {
+
+ logger.error("通知验签失败");
+ //失败应答
+ response.setStatus(500);
+ map.put("code", "ERROR");
+ map.put("message", "通知验签失败");
+ return gson.toJson(map);
+ }
+ logger.info("通知验签成功");
+
+ //处理订单
+ processOrder(bodyMap);
+
+ //成功应答
+ response.setStatus(200);
+ map.put("code", "SUCCESS");
+ map.put("message", "成功");
+ return gson.toJson(map);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ //失败应答
+ response.setStatus(500);
+ map.put("code", "ERROR");
+ map.put("message", "失败");
+ return gson.toJson(map);
+ }
+ }
+
+ @Override
+ public String refundsNotify(HttpServletRequest request, HttpServletResponse response) {
+ Gson gson = new Gson();
+ Map<String, String> map = new HashMap<>();//应答对象
+
+ try {
+ //处理通知参数
+ String body = HttpUtils.readData(request);
+ Map<String, Object> bodyMap = gson.fromJson(body, HashMap.class);
+ String requestId = (String) bodyMap.get("id");
+ logger.info("支付通知的id ===> {}", requestId);
+
+ //签名的验证
+ WechatPay2ValidatorForRequest wechatPay2ValidatorForRequest
+ = new WechatPay2ValidatorForRequest(wxPayConfig.getVerifier(), requestId, body);
+ if (!wechatPay2ValidatorForRequest.validate(request)) {
+
+ logger.error("通知验签失败");
+ //失败应答
+ response.setStatus(500);
+ map.put("code", "ERROR");
+ map.put("message", "通知验签失败");
+ return gson.toJson(map);
+ }
+ logger.info("通知验签成功");
+
+ //处理退款单
+ processRefund(bodyMap);
+
+ //成功应答
+ response.setStatus(200);
+ map.put("code", "SUCCESS");
+ map.put("message", "成功");
+ return gson.toJson(map);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ //失败应答
+ response.setStatus(500);
+ map.put("code", "ERROR");
+ map.put("message", "失败");
+ return gson.toJson(map);
+ }
+ }
+
+
+ //创建签名所需要的参数xml格式
+// public static String createXML(Map<String, Object> map) {
+// String xml = "<xml>";
+// Set<String> set = map.keySet();
+// Iterator<String> i = set.iterator();
+// while (i.hasNext()) {
+// String str = i.next();
+// xml += "<" + str + ">" + "<![CDATA[" + map.get(str) + "]]>" + "</" + str + ">";
+// }
+// xml += "</xml>";
+// return xml;
+// }
+
+
}
diff --git a/src/main/java/org/springblade/modules/pay/vo/OrderInfoVO.java b/src/main/java/org/springblade/modules/pay/vo/OrderInfoVO.java
new file mode 100644
index 0000000..7a1129c
--- /dev/null
+++ b/src/main/java/org/springblade/modules/pay/vo/OrderInfoVO.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the dreamlu.net developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.modules.pay.vo;
+
+import org.springblade.modules.pay.entity.OrderInfoEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 订单信息 视图实体类
+ *
+ * @author BladeX
+ * @since 2024-04-07
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class OrderInfoVO extends OrderInfoEntity {
+ private static final long serialVersionUID = 1L;
+
+}
diff --git a/src/main/java/org/springblade/modules/pay/vo/PaymentInfoVO.java b/src/main/java/org/springblade/modules/pay/vo/PaymentInfoVO.java
new file mode 100644
index 0000000..f137d6d
--- /dev/null
+++ b/src/main/java/org/springblade/modules/pay/vo/PaymentInfoVO.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the dreamlu.net developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.modules.pay.vo;
+
+import org.springblade.modules.pay.entity.PaymentInfoEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 支付信息 视图实体类
+ *
+ * @author BladeX
+ * @since 2024-04-07
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class PaymentInfoVO extends PaymentInfoEntity {
+ private static final long serialVersionUID = 1L;
+
+}
diff --git a/src/main/java/org/springblade/modules/pay/vo/RefundInfoVO.java b/src/main/java/org/springblade/modules/pay/vo/RefundInfoVO.java
new file mode 100644
index 0000000..d519c32
--- /dev/null
+++ b/src/main/java/org/springblade/modules/pay/vo/RefundInfoVO.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the dreamlu.net developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.modules.pay.vo;
+
+import org.springblade.modules.pay.entity.RefundInfoEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 退款信息 视图实体类
+ *
+ * @author BladeX
+ * @since 2024-04-07
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class RefundInfoVO extends RefundInfoEntity {
+ private static final long serialVersionUID = 1L;
+
+}
diff --git a/src/main/java/org/springblade/modules/pay/wrapper/OrderInfoWrapper.java b/src/main/java/org/springblade/modules/pay/wrapper/OrderInfoWrapper.java
new file mode 100644
index 0000000..962a6f3
--- /dev/null
+++ b/src/main/java/org/springblade/modules/pay/wrapper/OrderInfoWrapper.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the dreamlu.net developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.modules.pay.wrapper;
+
+import org.springblade.core.mp.support.BaseEntityWrapper;
+import org.springblade.core.tool.utils.BeanUtil;
+import org.springblade.modules.pay.entity.OrderInfoEntity;
+import org.springblade.modules.pay.vo.OrderInfoVO;
+
+import java.util.Objects;
+
+/**
+ * 订单信息 包装类,返回视图层所需的字段
+ *
+ * @author BladeX
+ * @since 2024-04-07
+ */
+public class OrderInfoWrapper extends BaseEntityWrapper<OrderInfoEntity, OrderInfoVO> {
+
+ public static OrderInfoWrapper build() {
+ return new OrderInfoWrapper();
+ }
+
+ @Override
+ public OrderInfoVO entityVO(OrderInfoEntity orderInfo) {
+ OrderInfoVO orderInfoVO = Objects.requireNonNull(BeanUtil.copy(orderInfo, OrderInfoVO.class));
+
+ //User createUser = UserCache.getUser(orderInfo.getCreateUser());
+ //User updateUser = UserCache.getUser(orderInfo.getUpdateUser());
+ //orderInfoVO.setCreateUserName(createUser.getName());
+ //orderInfoVO.setUpdateUserName(updateUser.getName());
+
+ return orderInfoVO;
+ }
+
+
+}
diff --git a/src/main/java/org/springblade/modules/pay/wrapper/PaymentInfoWrapper.java b/src/main/java/org/springblade/modules/pay/wrapper/PaymentInfoWrapper.java
new file mode 100644
index 0000000..0cc7cfb
--- /dev/null
+++ b/src/main/java/org/springblade/modules/pay/wrapper/PaymentInfoWrapper.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the dreamlu.net developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.modules.pay.wrapper;
+
+import org.springblade.core.mp.support.BaseEntityWrapper;
+import org.springblade.core.tool.utils.BeanUtil;
+import org.springblade.modules.pay.entity.PaymentInfoEntity;
+import org.springblade.modules.pay.vo.PaymentInfoVO;
+
+import java.util.Objects;
+
+/**
+ * 支付信息 包装类,返回视图层所需的字段
+ *
+ * @author BladeX
+ * @since 2024-04-07
+ */
+public class PaymentInfoWrapper extends BaseEntityWrapper<PaymentInfoEntity, PaymentInfoVO> {
+
+ public static PaymentInfoWrapper build() {
+ return new PaymentInfoWrapper();
+ }
+
+ @Override
+ public PaymentInfoVO entityVO(PaymentInfoEntity paymentInfo) {
+ PaymentInfoVO paymentInfoVO = Objects.requireNonNull(BeanUtil.copy(paymentInfo, PaymentInfoVO.class));
+
+ //User createUser = UserCache.getUser(paymentInfo.getCreateUser());
+ //User updateUser = UserCache.getUser(paymentInfo.getUpdateUser());
+ //paymentInfoVO.setCreateUserName(createUser.getName());
+ //paymentInfoVO.setUpdateUserName(updateUser.getName());
+
+ return paymentInfoVO;
+ }
+
+
+}
diff --git a/src/main/java/org/springblade/modules/pay/wrapper/RefundInfoWrapper.java b/src/main/java/org/springblade/modules/pay/wrapper/RefundInfoWrapper.java
new file mode 100644
index 0000000..2ef166e
--- /dev/null
+++ b/src/main/java/org/springblade/modules/pay/wrapper/RefundInfoWrapper.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the dreamlu.net developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.modules.pay.wrapper;
+
+import org.springblade.core.mp.support.BaseEntityWrapper;
+import org.springblade.core.tool.utils.BeanUtil;
+import org.springblade.modules.pay.entity.RefundInfoEntity;
+import org.springblade.modules.pay.vo.RefundInfoVO;
+
+import java.util.Objects;
+
+/**
+ * 退款信息 包装类,返回视图层所需的字段
+ *
+ * @author BladeX
+ * @since 2024-04-07
+ */
+public class RefundInfoWrapper extends BaseEntityWrapper<RefundInfoEntity, RefundInfoVO> {
+
+ public static RefundInfoWrapper build() {
+ return new RefundInfoWrapper();
+ }
+
+ @Override
+ public RefundInfoVO entityVO(RefundInfoEntity refundInfo) {
+ RefundInfoVO refundInfoVO = Objects.requireNonNull(BeanUtil.copy(refundInfo, RefundInfoVO.class));
+
+ //User createUser = UserCache.getUser(refundInfo.getCreateUser());
+ //User updateUser = UserCache.getUser(refundInfo.getUpdateUser());
+ //refundInfoVO.setCreateUserName(createUser.getName());
+ //refundInfoVO.setUpdateUserName(updateUser.getName());
+
+ return refundInfoVO;
+ }
+
+
+}
diff --git a/src/main/java/org/springblade/modules/property/dto/PropertyChargeRecordDTO.java b/src/main/java/org/springblade/modules/property/dto/PropertyChargeRecordDTO.java
new file mode 100644
index 0000000..7762b9a
--- /dev/null
+++ b/src/main/java/org/springblade/modules/property/dto/PropertyChargeRecordDTO.java
@@ -0,0 +1,18 @@
+package org.springblade.modules.property.dto;
+
+import io.swagger.annotations.ApiModel;
+import lombok.Data;
+import org.springblade.modules.property.entity.PropertyChargeRecord;
+
+/**
+ * 缴费记录表对象 jczz_property_charge_record
+ *
+ * @author ${context.author}
+ * @date 2024-04-07 15:44:09
+ */
+@ApiModel(value = "PropertyChargeRecordDTO对象")
+@Data
+public class PropertyChargeRecordDTO extends PropertyChargeRecord
+{
+
+}
diff --git a/src/main/java/org/springblade/modules/property/entity/PropertyChargeRecord.java b/src/main/java/org/springblade/modules/property/entity/PropertyChargeRecord.java
index 9767dc7..bb97fac 100644
--- a/src/main/java/org/springblade/modules/property/entity/PropertyChargeRecord.java
+++ b/src/main/java/org/springblade/modules/property/entity/PropertyChargeRecord.java
@@ -1,47 +1,127 @@
package org.springblade.modules.property.entity;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springblade.core.mp.base.BaseEntity;
import org.springframework.format.annotation.DateTimeFormat;
+import java.math.BigDecimal;
import java.util.Date;
@Data
@TableName("jczz_property_charge_record")
@ApiModel(value = "PropertyChargeRecord", description = "物业缴费记录")
-public class PropertyChargeRecord extends BaseEntity {
+public class PropertyChargeRecord {
- //物业公司的deptId
+ /** 主键 */
+ @ApiModelProperty(value = "主键ID", example = "")
+ @TableId(value = "id", type = IdType.ASSIGN_ID)
+ private Long id;
+
+ /** 物业公司id */
+ @ApiModelProperty(value = "物业公司id", example = "")
+ @TableField("property_id")
private String propertyId;
+ /** 订单号 */
+ @ApiModelProperty(value = "订单号", example = "")
+ @TableField("order_no")
+ private String orderNo;
- //缴费项id
+ /** 缴费项id */
+ @ApiModelProperty(value = "缴费项id", example = "")
+ @TableField("charge_id")
private String chargeId;
- //编号
+ /** 缴费单号 */
+ @ApiModelProperty(value = "缴费单号", example = "")
+ @TableField("no")
private String no;
- //付款人id
+ /** 付款人id */
+ @ApiModelProperty(value = "付款人id", example = "")
+ @TableField("pay_user")
private String payUser;
- //付款时间
- @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
- @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ /** 付费时间 */
+ @ApiModelProperty(value = "付费时间", example = "")
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+ @TableField("pay_time")
private Date payTime;
- //缴费方式
+ /** 付款方式 */
+ @ApiModelProperty(value = "付款方式", example = "")
+ @TableField("pay_func")
private String payFunc;
- //付款金额
- private String payPrice;
+ /** 付款金额 */
+ @ApiModelProperty(value = "付款金额(分)", example = "")
+ @TableField("pay_price")
+ private BigDecimal payPrice;
- //付款房屋的houseCode
- private String payHouse;
+ /** 房屋编码 */
+ @ApiModelProperty(value = "房屋编码", example = "")
+ @TableField("house_code")
+ private String houseCode;
- //缴费内容
+ /** 缴费内容 */
+ @ApiModelProperty(value = "缴费内容", example = "")
+ @TableField("pay_content")
private String payContent;
+
+ /** 创建时间 */
+ @ApiModelProperty(value = "创建时间", example = "")
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+ @TableField("create_time")
+ private Date createTime;
+
+ /** 创建人 */
+ @ApiModelProperty(value = "创建人", example = "")
+ @TableField("create_user")
+ private Long createUser;
+
+ /** 创建部门 */
+ @ApiModelProperty(value = "创建部门", example = "")
+ @TableField("create_dept")
+ private Long createDept;
+
+ /** 修改人 */
+ @ApiModelProperty(value = "修改人", example = "")
+ @TableField("update_user")
+ private Long updateUser;
+
+ /** 修改时间 */
+ @ApiModelProperty(value = "修改时间", example = "")
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+ @TableField("update_time")
+ private Date updateTime;
+
+ /** 状态(1、待支付;2、已支付;99取消支付) */
+ @ApiModelProperty(value = "状态(1、待支付;2、已支付;99取消支付)", example = "")
+ @TableField("status")
+ private Integer status;
+
+ /** 是否已删除 */
+ @ApiModelProperty(value = "是否已删除", example = "")
+ @TableField("is_deleted")
+ private Integer isDeleted;
+
+ /** 开始时间 */
+ @ApiModelProperty(value = "开始时间", example = "")
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+ @TableField("start_time")
+ private Date startTime;
+
+ /** 到期时间 */
+ @ApiModelProperty(value = "到期时间", example = "")
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+ @TableField("end_time")
+ private Date endTime;
}
diff --git a/src/main/java/org/springblade/modules/property/mapper/PropertyChargeRecordMapper.java b/src/main/java/org/springblade/modules/property/mapper/PropertyChargeRecordMapper.java
index 0b3cac5..bda5a80 100644
--- a/src/main/java/org/springblade/modules/property/mapper/PropertyChargeRecordMapper.java
+++ b/src/main/java/org/springblade/modules/property/mapper/PropertyChargeRecordMapper.java
@@ -19,6 +19,7 @@
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.apache.ibatis.annotations.Param;
+import org.springblade.modules.property.dto.PropertyChargeRecordDTO;
import org.springblade.modules.property.entity.PropertyCharge;
import org.springblade.modules.property.entity.PropertyChargeRecord;
import org.springblade.modules.property.vo.PropertyChargeRecordVO;
@@ -36,4 +37,21 @@
List<PropertyChargeRecordVO> getPage(IPage<PropertyChargeRecordVO> page, @Param("vo") PropertyChargeRecordVO vo);
+
+
+ /**
+ * 查询缴费记录表
+ *
+ * @param id 缴费记录表ID
+ * @return 缴费记录表
+ */
+ public PropertyChargeRecordDTO selectPropertyChargeRecordById(Long id);
+
+ /**
+ * 查询缴费记录表列表
+ *
+ * @param propertyChargeRecordDTO 缴费记录表
+ * @return 缴费记录表集合
+ */
+ public List<PropertyChargeRecordDTO> selectPropertyChargeRecordList(PropertyChargeRecordDTO propertyChargeRecordDTO);
}
diff --git a/src/main/java/org/springblade/modules/property/mapper/PropertyChargeRecordMapper.xml b/src/main/java/org/springblade/modules/property/mapper/PropertyChargeRecordMapper.xml
index a43ab38..ae8081d 100644
--- a/src/main/java/org/springblade/modules/property/mapper/PropertyChargeRecordMapper.xml
+++ b/src/main/java/org/springblade/modules/property/mapper/PropertyChargeRecordMapper.xml
@@ -6,4 +6,83 @@
<select id="getPage" resultType="org.springblade.modules.property.vo.PropertyChargeRecordVO">
SELECT * FROM jczz_property_charge_record where is_deleted = 0
</select>
+
+
+ <resultMap type="org.springblade.modules.property.dto.PropertyChargeRecordDTO" id="PropertyChargeRecordDTOResult">
+ <result property="id" column="id" />
+ <result property="propertyId" column="property_id" />
+ <result property="chargeId" column="charge_id" />
+ <result property="no" column="no" />
+ <result property="payUser" column="pay_user" />
+ <result property="payTime" column="pay_time" />
+ <result property="payFunc" column="pay_func" />
+ <result property="payPrice" column="pay_price" />
+ <result property="houseCode" column="house_code" />
+ <result property="payContent" column="pay_content" />
+ <result property="createTime" column="create_time" />
+ <result property="createUser" column="create_user" />
+ <result property="createDept" column="create_dept" />
+ <result property="updateUser" column="update_user" />
+ <result property="updateTime" column="update_time" />
+ <result property="status" column="status" />
+ <result property="isDeleted" column="is_deleted" />
+ <result property="startTime" column="start_time" />
+ <result property="endTime" column="end_time" />
+ </resultMap>
+
+ <sql id="selectPropertyChargeRecord">
+ select
+ id,
+ property_id,
+ charge_id,
+ no,
+ pay_user,
+ pay_time,
+ pay_func,
+ pay_price,
+ house_code,
+ pay_content,
+ create_time,
+ create_user,
+ create_dept,
+ update_user,
+ update_time,
+ status,
+ is_deleted,
+ start_time,
+ end_time
+ from
+ jczz_property_charge_record
+ </sql>
+
+ <select id="selectPropertyChargeRecordById" parameterType="long" resultMap="PropertyChargeRecordDTOResult">
+ <include refid="selectPropertyChargeRecord"/>
+ where
+ id = #{id}
+ </select>
+
+ <select id="selectPropertyChargeRecordList" parameterType="org.springblade.modules.property.dto.PropertyChargeRecordDTO" resultMap="PropertyChargeRecordDTOResult">
+ <include refid="selectPropertyChargeRecord"/>
+ <where>
+ <if test="id != null "> and id = #{id}</if>
+ <if test="propertyId != null and propertyId != ''"> and property_id = #{propertyId}</if>
+ <if test="chargeId != null and chargeId != ''"> and charge_id = #{chargeId}</if>
+ <if test="no != null and no != ''"> and no = #{no}</if>
+ <if test="payUser != null and payUser != ''"> and pay_user = #{payUser}</if>
+ <if test="payTime != null "> and pay_time = #{payTime}</if>
+ <if test="payFunc != null and payFunc != ''"> and pay_func = #{payFunc}</if>
+ <if test="payPrice != null "> and pay_price = #{payPrice}</if>
+ <if test="houseCode != null and houseCode != ''"> and house_code = #{houseCode}</if>
+ <if test="payContent != null and payContent != ''"> and pay_content = #{payContent}</if>
+ <if test="createTime != null "> and create_time = #{createTime}</if>
+ <if test="createUser != null "> and create_user = #{createUser}</if>
+ <if test="createDept != null "> and create_dept = #{createDept}</if>
+ <if test="updateUser != null "> and update_user = #{updateUser}</if>
+ <if test="updateTime != null "> and update_time = #{updateTime}</if>
+ <if test="status != null "> and status = #{status}</if>
+ <if test="isDeleted != null "> and is_deleted = #{isDeleted}</if>
+ <if test="startTime != null "> and start_time = #{startTime}</if>
+ <if test="endTime != null "> and end_time = #{endTime}</if>
+ </where>
+ </select>
</mapper>
diff --git a/src/main/java/org/springblade/modules/property/service/IPropertyChargeRecordService.java b/src/main/java/org/springblade/modules/property/service/IPropertyChargeRecordService.java
index 9ece75c..6dffd84 100644
--- a/src/main/java/org/springblade/modules/property/service/IPropertyChargeRecordService.java
+++ b/src/main/java/org/springblade/modules/property/service/IPropertyChargeRecordService.java
@@ -17,6 +17,7 @@
package org.springblade.modules.property.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.service.IService;
import org.springblade.core.mp.base.BaseService;
import org.springblade.modules.property.entity.PropertyCharge;
import org.springblade.modules.property.entity.PropertyChargeRecord;
@@ -29,7 +30,7 @@
* @author BladeX
* @since 2023-11-23
*/
-public interface IPropertyChargeRecordService extends BaseService<PropertyChargeRecord> {
+public interface IPropertyChargeRecordService extends IService<PropertyChargeRecord> {
IPage<PropertyChargeRecordVO> getPage(IPage<PropertyChargeRecordVO> page, PropertyChargeRecordVO vo);
diff --git a/src/main/java/org/springblade/modules/property/service/impl/PropertyChargeRecordServiceImpl.java b/src/main/java/org/springblade/modules/property/service/impl/PropertyChargeRecordServiceImpl.java
index 28af099..5aedd34 100644
--- a/src/main/java/org/springblade/modules/property/service/impl/PropertyChargeRecordServiceImpl.java
+++ b/src/main/java/org/springblade/modules/property/service/impl/PropertyChargeRecordServiceImpl.java
@@ -1,6 +1,7 @@
package org.springblade.modules.property.service.impl;
import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.modules.property.entity.PropertyCharge;
import org.springblade.modules.property.entity.PropertyChargeRecord;
@@ -13,7 +14,7 @@
import org.springframework.stereotype.Service;
@Service
-public class PropertyChargeRecordServiceImpl extends BaseServiceImpl<PropertyChargeRecordMapper, PropertyChargeRecord> implements IPropertyChargeRecordService {
+public class PropertyChargeRecordServiceImpl extends ServiceImpl<PropertyChargeRecordMapper, PropertyChargeRecord> implements IPropertyChargeRecordService {
@Override
public IPage<PropertyChargeRecordVO> getPage(IPage<PropertyChargeRecordVO> page, PropertyChargeRecordVO vo) {
return page.setRecords(baseMapper.getPage(page, vo));
diff --git a/src/main/java/org/springblade/modules/system/entity/User.java b/src/main/java/org/springblade/modules/system/entity/User.java
index 0984744..cb87321 100644
--- a/src/main/java/org/springblade/modules/system/entity/User.java
+++ b/src/main/java/org/springblade/modules/system/entity/User.java
@@ -104,6 +104,10 @@
@TableField("lat")
private String lat;
+ @ApiModelProperty(value = "小程序openid", example = "")
+ @TableField("mini_open_id")
+ private String miniOpenId;
+
}
diff --git a/src/main/java/org/springblade/modules/wechat/controller/WechatController.java b/src/main/java/org/springblade/modules/wechat/controller/WechatController.java
new file mode 100644
index 0000000..82b571f
--- /dev/null
+++ b/src/main/java/org/springblade/modules/wechat/controller/WechatController.java
@@ -0,0 +1,33 @@
+package org.springblade.modules.wechat.controller;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.springblade.core.tool.api.R;
+import org.springblade.modules.pay.entity.WeChatMiniAuthorizeVo;
+import org.springblade.modules.wechat.service.WechatService;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+
+@Slf4j
+@RestController
+@RequestMapping("blade-wechat/wechat/")
+@Api(tags = "用户 -- 登录注册")
+public class WechatController {
+ @Resource
+ private WechatService wechatService;
+
+ @ApiOperation(value = "微信小程序授权")
+ @RequestMapping(value = "/getOpenId", method = RequestMethod.GET)
+ public R<WeChatMiniAuthorizeVo> wechatRoutineLogin(String code) throws Exception {
+ return R.data(wechatService.miniAuthCode(code));
+ }
+
+
+}
+
+
+
diff --git a/src/main/java/org/springblade/modules/wechat/service/WechatService.java b/src/main/java/org/springblade/modules/wechat/service/WechatService.java
new file mode 100644
index 0000000..dcb1fb0
--- /dev/null
+++ b/src/main/java/org/springblade/modules/wechat/service/WechatService.java
@@ -0,0 +1,12 @@
+package org.springblade.modules.wechat.service;
+
+import org.springblade.modules.pay.entity.WeChatMiniAuthorizeVo;
+
+public interface WechatService {
+ /**
+ * 小程序登录凭证校验
+ *
+ * @return 小程序登录校验对象
+ */
+ WeChatMiniAuthorizeVo miniAuthCode(String code) throws Exception;
+}
diff --git a/src/main/java/org/springblade/modules/wechat/service/impl/WechatServiceImpl.java b/src/main/java/org/springblade/modules/wechat/service/impl/WechatServiceImpl.java
new file mode 100644
index 0000000..013e175
--- /dev/null
+++ b/src/main/java/org/springblade/modules/wechat/service/impl/WechatServiceImpl.java
@@ -0,0 +1,59 @@
+package org.springblade.modules.wechat.service.impl;
+
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.StrUtil;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springblade.common.config.WxMiniConfig;
+import org.springblade.common.utils.HttpClientUtils;
+import org.springblade.common.utils.SpringUtils;
+import org.springblade.core.secure.utils.AuthUtil;
+import org.springblade.modules.pay.entity.WeChatMiniAuthorizeVo;
+import org.springblade.modules.system.entity.User;
+import org.springblade.modules.system.service.IUserService;
+import org.springblade.modules.wechat.service.WechatService;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+
+@Service
+public class WechatServiceImpl implements WechatService {
+
+ private static final Logger logger = LoggerFactory.getLogger(WechatServiceImpl.class);
+
+ @Resource
+ private WxMiniConfig wxMiniConfig;
+
+ /**
+ * 小程序登录凭证校验
+ *
+ * @return 小程序登录校验对象
+ */
+ @Override
+ public WeChatMiniAuthorizeVo miniAuthCode(String code) throws Exception {
+ String url = StrUtil.format(wxMiniConfig.getJscode2sessionUrl(), wxMiniConfig.getAppid(), wxMiniConfig.getSecret(), code);
+ JSONObject data = JSON.parseObject(HttpClientUtils.doGet(url));
+ if (ObjectUtil.isNull(data)) {
+ logger.error("微信平台接口异常,没任何数据返回!");
+ throw new Exception("微信平台接口异常,没任何数据返回!");
+ }
+ if (data.containsKey("errcode") && !data.getString("errcode").equals("0")) {
+ if (data.containsKey("errmsg")) {
+ logger.error("微信接口调用失败:" + data.getString("errcode") + data.getString("errmsg"));
+ throw new Exception("微信接口调用失败:" + data.getString("errcode") + data.getString("errmsg"));
+ }
+ }
+ WeChatMiniAuthorizeVo weChatMiniAuthorizeVo = JSONObject.parseObject(data.toJSONString(), WeChatMiniAuthorizeVo.class);
+ // 绑定用户openid
+ Long userId = AuthUtil.getUserId();
+ IUserService userService = SpringUtils.getBean(IUserService.class);
+ userService.update(Wrappers.<User>lambdaUpdate().set(User::getMiniOpenId, weChatMiniAuthorizeVo.getOpenId()).eq(User::getId, userId));
+ return weChatMiniAuthorizeVo;
+ }
+
+
+}
+
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
index 55f16f6..a45e5b6 100644
--- a/src/main/resources/application.yml
+++ b/src/main/resources/application.yml
@@ -316,3 +316,18 @@
appId: 202403288666059313538996533
privateKey: MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCCL4tz9BbUz+z3vs/eFwmUmQhsTiP3ZLwruTMJuEhsTEsT58PrdUOKGipwhKF88zj8SCk/Tn8izvDXj5IzqHEWjSEkfivYHx/6cE3VdHc6vvpvpeC06264d5NN4T6hwYH9CYz9iSmx9HFxADlg5zxj0lHqLSFf25cmEPF3F7PvAzj1cmYrKjet1HtCKaAyKADD+ojHHRjNLXZg3E5CINUqRYlLi+OKQph3VdrfokkO8efe8CR2wdiGU78mV1/UtTaiSYOEwv7pkbGECkqIXp+xYzaAVNCxikIWkc+qKmvvJXKsQVOKqv5b7/FQ/ag8trWPe8JLcQCN/Zg7DXSTc9YHAgMBAAECggEAENI73punZ5AGOmy5RyUK49xyLixakVi+x5eCdLsPAI9LFCNaOU5Jj8qZuTgp9Y8nydE5IyjtXH4IuJGgfnRBSHyrz59N4vsCksV4CSCnVzvd+Bci1b2l7MfmjKWSBiyOszdMtGXIsWm4TrWMtGysbOl8FBoIue4RtaVyzcSOR0+gDCIkn2XGqh3FhSIIApYm+eTOPDLZuSOsrgoTrppTOVUCXGN+/cSBAegWQnCES0b49F2EIRCAtSybc52N7zFPB9f8Kzzmgozilf00uS27HLZplwyLA6FMargdOi619x3T/XY52a55r4ldu/aZF2EbD1RpvMi9aGH/O77HtmLfAQKBgQC/32H0ibR5BgqfUjOWS0v+GRqG0gXr4x2R/oY9Pym16F5gEFKDYauBfEK4GYDtTEahB0Wo0n57StSZ3fX6yy9uBsPxywy0yUvzkxwe2th8fBg5czEBbLzHz4RMqo7LkfwKBatKMJLCOLdecSV2uJlDt/AIRFx5ymypiVLyYHb4IQKBgQCtsjv0ThHMM861CEfe9FZ2B4LFGfCptcek95ilARc7r3RpZpSSi+K0mF2992JVen+dkPh3FuG5NM5VSJeFyReNj5RxVz8A+4d9w3fxrqi2qfC1TFHR7IRv4JzPeZ+7wkMSc7rwkJ9UBSOdecXm2FV7BOivtnf7bGWIGLJNUb7pJwKBgCu0ZkudUk5+4cyInNePLzAh57jt/gtNIF8w6sLosEePNnALR8BFbxt/gnMM3CExTqU/Us6xo73RvbuOo4kM3zDguaFJ7wr/Dx3cVHtyvf0dByeO5Yq9igK5chlEgGI+Tnq579pmVgeHg70vaKkyQzb5nuNDLw1O3pF/hjVPY8oBAoGAFLW5nElqqdRLgx43o4eyf2Qp3WJYZYO9CBhVZOcaZA1pbd/DOy3em/XGx42lddejO6A7X8ekpjZ7m4OKPXNakZBa/KCQbIeRAhe6R2Cx0QW2I4e0AbmXmNdJGxu/Rd3FrX+K/H/h31y1gGMyi3Gjz4UoUTsKVzn3aSC4satbfeUCgYEAmpIo2ZO4hQ9THCOdgR5udXRG5s5JjGEct2QSxXntRyJm3RAkPA3/mEDVlI6X5UNIn7BKeThCFo5eM2bbFFF4sFeNV0W4uP8p9dsOnpwU7FzT++16WNiBopQpff72MNzjnt/k/KLlX/zV60zbMJ1R6McYsv0LP9Zuv9RAo8v8ZDU=
sopCreateBy: 106575361457
+
+wxpay:
+ api-v3-key: qqwuMJcCPRhcNcmFlqb6ucxdHKqVxp9U
+ appid: wxeeab25f4f176f1fc
+ domain: https://api.mch.weixin.qq.com
+ mch-id: 1600701071
+ mch-serial-no: 4C19EAFA9E0AD598DDE3D7399B47C3D5C85EB7C9
+ notify-domain: https://wx.nkjj88.com
+ partnerKey: qqwuMJcCPRhcNcmFlqb6ucxdHKqVxp9U
+ private-key-path: /www/wwwroot/apiclient_key.pem
+ private-cert-path: /www/wwwroot/apiclient_cert.p12
+wxmini:
+ appid: wxeeab25f4f176f1fc
+ secret: 0a0e0d0a0c0b0a09080706050403020100
+ jscode2sessionUrl: https://api.weixin.qq.com/sns/jscode2session?appid={}&secret={}&js_code={}&grant_type=authorization_code
--
Gitblit v1.9.3