diff --git a/pom.xml b/pom.xml index 54367f9..a4d53b5 100644 --- a/pom.xml +++ b/pom.xml @@ -36,7 +36,7 @@ 1.12.1 1.9.1 4.2.0 - 9.4.47.v20220610 + 9.4.56.v20240826 https://budwk.com @@ -53,6 +53,12 @@ + + com.github.javen205 + IJPay-All + 2.9.10 + + com.xingyuv captcha-plus diff --git a/src/main/java/io/v/nutz/zhgh/memberCost/controller/payment/MemberPaymentConfigController.java b/src/main/java/io/v/nutz/zhgh/memberCost/controller/MemberPaymentConfigController.java similarity index 93% rename from src/main/java/io/v/nutz/zhgh/memberCost/controller/payment/MemberPaymentConfigController.java rename to src/main/java/io/v/nutz/zhgh/memberCost/controller/MemberPaymentConfigController.java index 1059c3d..6b11307 100644 --- a/src/main/java/io/v/nutz/zhgh/memberCost/controller/payment/MemberPaymentConfigController.java +++ b/src/main/java/io/v/nutz/zhgh/memberCost/controller/MemberPaymentConfigController.java @@ -1,10 +1,9 @@ -package io.v.nutz.zhgh.memberCost.controller.payment; +package io.v.nutz.zhgh.memberCost.controller; import io.v.nutz.base.annontation.ViReturn; import io.v.nutz.base.dao.CndPlus; import io.v.nutz.base.query.PageForm; import io.v.nutz.zhgh.memberCost.model.MemberPaymentConfig; -import io.v.nutz.zhgh.memberCost.model.MemberPaymentProject; import io.v.nutz.zhgh.memberCost.service.MemberPaymentService; import lombok.extern.slf4j.Slf4j; import org.apache.shiro.authz.annotation.RequiresPermissions; @@ -30,7 +29,7 @@ public class MemberPaymentConfigController { private MemberPaymentService memberPaymentService; @At("") - @Ok("beetl:/platform/memberCost/payment/config.html") + @Ok("beetl:/platform/membercost/config.html") @RequiresPermissions("member.payment.config") public void index() {} diff --git a/src/main/java/io/v/nutz/zhgh/memberCost/controller/MemberPaymentMineController.java b/src/main/java/io/v/nutz/zhgh/memberCost/controller/MemberPaymentMineController.java new file mode 100644 index 0000000..84b8f67 --- /dev/null +++ b/src/main/java/io/v/nutz/zhgh/memberCost/controller/MemberPaymentMineController.java @@ -0,0 +1,40 @@ +package io.v.nutz.zhgh.memberCost.controller; + +import io.v.nutz.zhgh.memberCost.payment.wxpay.service.WxPayCommonService; +import io.v.nutz.zhgh.memberCost.service.MemberPaymentService; +import lombok.extern.slf4j.Slf4j; +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; + +/** + * @version 1.0 + * @Author zzr + * @name:MemberPaymentMineController + * @Date 2025/3/10 8:44 + * @注释 我的缴费列表 + */ +@Slf4j +@IocBean +@Ok("json:full") +@At("/platform/member/payment/mine") +public class MemberPaymentMineController { + + @Inject + private WxPayCommonService wxPayCommonService; + @Inject + private MemberPaymentService memberPaymentService; + + @At("") + @Ok("beetl:/platform/membercost/mine/index.html") + @RequiresPermissions("member.payment.project") + public void index() { + } + + + public Object pageData(){ + return null; + } +} diff --git a/src/main/java/io/v/nutz/zhgh/memberCost/controller/payment/MemberPaymentProjectController.java b/src/main/java/io/v/nutz/zhgh/memberCost/controller/MemberPaymentProjectController.java similarity index 98% rename from src/main/java/io/v/nutz/zhgh/memberCost/controller/payment/MemberPaymentProjectController.java rename to src/main/java/io/v/nutz/zhgh/memberCost/controller/MemberPaymentProjectController.java index 5d23841..4a42247 100644 --- a/src/main/java/io/v/nutz/zhgh/memberCost/controller/payment/MemberPaymentProjectController.java +++ b/src/main/java/io/v/nutz/zhgh/memberCost/controller/MemberPaymentProjectController.java @@ -1,4 +1,4 @@ -package io.v.nutz.zhgh.memberCost.controller.payment; +package io.v.nutz.zhgh.memberCost.controller; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.date.DateTime; @@ -30,7 +30,6 @@ import org.nutz.mvc.annotation.Param; import java.util.ArrayList; import java.util.List; -import java.util.Optional; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -50,7 +49,7 @@ public class MemberPaymentProjectController { private MemberPaymentService memberPaymentService; @At("") - @Ok("beetl:/platform/memberCost/payment/project.html") + @Ok("beetl:/platform/membercost/project.html") @RequiresPermissions("member.payment.project") public void index() { } diff --git a/src/main/java/io/v/nutz/zhgh/memberCost/controller/payment/MemberPaymentSummaryController.java b/src/main/java/io/v/nutz/zhgh/memberCost/controller/MemberPaymentSummaryController.java similarity index 99% rename from src/main/java/io/v/nutz/zhgh/memberCost/controller/payment/MemberPaymentSummaryController.java rename to src/main/java/io/v/nutz/zhgh/memberCost/controller/MemberPaymentSummaryController.java index 4fdd028..d7e61c9 100644 --- a/src/main/java/io/v/nutz/zhgh/memberCost/controller/payment/MemberPaymentSummaryController.java +++ b/src/main/java/io/v/nutz/zhgh/memberCost/controller/MemberPaymentSummaryController.java @@ -1,4 +1,4 @@ -package io.v.nutz.zhgh.memberCost.controller.payment; +package io.v.nutz.zhgh.memberCost.controller; import cn.afterturn.easypoi.excel.ExcelExportUtil; import cn.afterturn.easypoi.excel.ExcelImportUtil; @@ -66,7 +66,7 @@ public class MemberPaymentSummaryController { private MsgApi msgApi; @At("") - @Ok("beetl:/platform/memberCost/payment/summary.html") + @Ok("beetl:/platform/membercost/summary.html") @RequiresPermissions("member.payment.summary") public void index() { } diff --git a/src/main/java/io/v/nutz/zhgh/memberCost/controller/payment/MemberPaymentUserController.java b/src/main/java/io/v/nutz/zhgh/memberCost/controller/MemberPaymentUserController.java similarity index 64% rename from src/main/java/io/v/nutz/zhgh/memberCost/controller/payment/MemberPaymentUserController.java rename to src/main/java/io/v/nutz/zhgh/memberCost/controller/MemberPaymentUserController.java index 1cbec5d..3eaa205 100644 --- a/src/main/java/io/v/nutz/zhgh/memberCost/controller/payment/MemberPaymentUserController.java +++ b/src/main/java/io/v/nutz/zhgh/memberCost/controller/MemberPaymentUserController.java @@ -1,4 +1,4 @@ -package io.v.nutz.zhgh.memberCost.controller.payment; +package io.v.nutz.zhgh.memberCost.controller; import io.v.nutz.base.annontation.ViReturn; @@ -6,28 +6,19 @@ import io.v.nutz.base.dao.CndPlus; import io.v.nutz.base.query.PageForm; import io.v.nutz.web.commons.utils.ShiroUtil; import io.v.nutz.zhgh.memberCost.model.MemberPaymentInfo; -import io.v.nutz.zhgh.memberCost.model.MemberPaymentProject; import io.v.nutz.zhgh.memberCost.service.MemberPaymentService; import lombok.extern.slf4j.Slf4j; -import org.apache.shiro.SecurityUtils; import org.apache.shiro.authz.annotation.RequiresPermissions; -import org.nutz.dao.Chain; import org.nutz.dao.Cnd; import org.nutz.dao.Sqls; import org.nutz.dao.sql.Sql; -import org.nutz.dao.util.cri.Static; import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.IocBean; -import org.nutz.lang.Lang; import org.nutz.lang.Strings; import org.nutz.mvc.annotation.At; import org.nutz.mvc.annotation.Ok; import org.nutz.mvc.annotation.Param; -import java.util.Arrays; -import java.util.Date; -import java.util.List; - /** * 个人缴费管理 * @author hpf @@ -42,7 +33,7 @@ public class MemberPaymentUserController { private MemberPaymentService memberPaymentService; @At("") - @Ok("beetl:/platform/memberCost/payment/user.html") + @Ok("beetl:/platform/membercost/user.html") @RequiresPermissions("member.payment.user") public void index() { } @@ -51,23 +42,26 @@ public class MemberPaymentUserController { @ViReturn @RequiresPermissions("member.payment.user") public Object pageData(PageForm pageForm,@Param(value = "year", required = false) String year,@Param(value = "projectName", required = false) String projectName){ - Sql sql = Sqls.create("SELECT" + - " mpi.*," + - " mpp.`year`," + - " mpp.projectName," + - " mpp.startTime," + - " mpp.endTime," + - " mpp.configId," + - " mpc.payStandards," + - " mpc.paymentStartMonth," + - " mpc.paymentEndMonth" + - " FROM" + - " member_payment_info mpi" + - " LEFT JOIN member_payment_project mpp ON mpi.paymentProjectId = mpp.id " + - " LEFT JOIN member_payment_config mpc ON mpc.id = mpp.configId $condition"); + Sql sql = Sqls.create(""" + SELECT + mpi.*, + mpp.`year`, + mpp.projectName, + mpp.startTime, + mpp.endTime, + mpp.configId, + mpc.payStandards, + mpc.paymentStartMonth, + mpc.paymentEndMonth + FROM + member_payment_info mpi + LEFT JOIN member_payment_project mpp ON mpi.paymentProjectId = mpp.id + LEFT JOIN member_payment_config mpc ON mpc.id = mpp.configId + $condition + """); CndPlus cnd = CndPlus.create(); - cnd.andEX("mpp.isDisabled", "=", '0'); + cnd.andEX("mpp.isDisabled", "=", false); cnd.andEX("mpp.year", "=", year); cnd.and("mpi.userId", "=", ShiroUtil.getUserId()); if (Strings.isNotBlank(projectName)) { diff --git a/src/main/java/io/v/nutz/zhgh/memberCost/controller/mobile/MobileMemberCostListController.java b/src/main/java/io/v/nutz/zhgh/memberCost/h5controller/MobileMemberCostListController.java similarity index 97% rename from src/main/java/io/v/nutz/zhgh/memberCost/controller/mobile/MobileMemberCostListController.java rename to src/main/java/io/v/nutz/zhgh/memberCost/h5controller/MobileMemberCostListController.java index 6907302..d2ddeba 100644 --- a/src/main/java/io/v/nutz/zhgh/memberCost/controller/mobile/MobileMemberCostListController.java +++ b/src/main/java/io/v/nutz/zhgh/memberCost/h5controller/MobileMemberCostListController.java @@ -1,4 +1,4 @@ -package io.v.nutz.zhgh.memberCost.controller.mobile; +package io.v.nutz.zhgh.memberCost.h5controller; import io.v.nutz.base.annontation.ViReturn; import io.v.nutz.web.commons.utils.ShiroUtil; diff --git a/src/main/java/io/v/nutz/zhgh/memberCost/controller/AlipayClientController.java b/src/main/java/io/v/nutz/zhgh/memberCost/payment/alipay/controller/AlipayClientController.java similarity index 93% rename from src/main/java/io/v/nutz/zhgh/memberCost/controller/AlipayClientController.java rename to src/main/java/io/v/nutz/zhgh/memberCost/payment/alipay/controller/AlipayClientController.java index 7270989..abc1f68 100644 --- a/src/main/java/io/v/nutz/zhgh/memberCost/controller/AlipayClientController.java +++ b/src/main/java/io/v/nutz/zhgh/memberCost/payment/alipay/controller/AlipayClientController.java @@ -1,6 +1,6 @@ -package io.v.nutz.zhgh.memberCost.controller; +package io.v.nutz.zhgh.memberCost.payment.alipay.controller; -import io.v.nutz.zhgh.memberCost.service.AlipayService; +import io.v.nutz.zhgh.memberCost.payment.alipay.service.AlipayService; import lombok.extern.slf4j.Slf4j; import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.IocBean; diff --git a/src/main/java/io/v/nutz/zhgh/memberCost/controller/AlipayClientConfig.java b/src/main/java/io/v/nutz/zhgh/memberCost/payment/alipay/service/AlipayClientConfig.java similarity index 98% rename from src/main/java/io/v/nutz/zhgh/memberCost/controller/AlipayClientConfig.java rename to src/main/java/io/v/nutz/zhgh/memberCost/payment/alipay/service/AlipayClientConfig.java index 7819815..0594c7c 100644 --- a/src/main/java/io/v/nutz/zhgh/memberCost/controller/AlipayClientConfig.java +++ b/src/main/java/io/v/nutz/zhgh/memberCost/payment/alipay/service/AlipayClientConfig.java @@ -1,4 +1,4 @@ -package io.v.nutz.zhgh.memberCost.controller; +package io.v.nutz.zhgh.memberCost.payment.alipay.service; /** * @ClassName AlipayClientConfig diff --git a/src/main/java/io/v/nutz/zhgh/memberCost/service/AlipayService.java b/src/main/java/io/v/nutz/zhgh/memberCost/payment/alipay/service/AlipayService.java similarity index 85% rename from src/main/java/io/v/nutz/zhgh/memberCost/service/AlipayService.java rename to src/main/java/io/v/nutz/zhgh/memberCost/payment/alipay/service/AlipayService.java index 32da08e..f0fe4d8 100644 --- a/src/main/java/io/v/nutz/zhgh/memberCost/service/AlipayService.java +++ b/src/main/java/io/v/nutz/zhgh/memberCost/payment/alipay/service/AlipayService.java @@ -1,4 +1,4 @@ -package io.v.nutz.zhgh.memberCost.service; +package io.v.nutz.zhgh.memberCost.payment.alipay.service; import io.v.nutz.base.service.ViService; diff --git a/src/main/java/io/v/nutz/zhgh/memberCost/service/impl/AlipayNewServiceImpl.java b/src/main/java/io/v/nutz/zhgh/memberCost/payment/alipay/service/impl/AlipayNewServiceImpl.java similarity index 96% rename from src/main/java/io/v/nutz/zhgh/memberCost/service/impl/AlipayNewServiceImpl.java rename to src/main/java/io/v/nutz/zhgh/memberCost/payment/alipay/service/impl/AlipayNewServiceImpl.java index 0dd726e..b78cd14 100644 --- a/src/main/java/io/v/nutz/zhgh/memberCost/service/impl/AlipayNewServiceImpl.java +++ b/src/main/java/io/v/nutz/zhgh/memberCost/payment/alipay/service/impl/AlipayNewServiceImpl.java @@ -1,4 +1,4 @@ -package io.v.nutz.zhgh.memberCost.service.impl; +package io.v.nutz.zhgh.memberCost.payment.alipay.service.impl; import com.alipay.api.AlipayApiException; import com.alipay.api.AlipayConstants; @@ -9,9 +9,9 @@ import com.alipay.api.request.AlipayTradeWapPayRequest; import com.alipay.api.response.AlipayTradeWapPayResponse; import io.v.nutz.base.service.impl.ViServiceImpl; import io.v.nutz.web.commons.utils.ShiroUtil; -import io.v.nutz.zhgh.memberCost.controller.AlipayClientConfig; +import io.v.nutz.zhgh.memberCost.payment.alipay.service.AlipayClientConfig; import io.v.nutz.zhgh.memberCost.model.MemberPaymentInfo; -import io.v.nutz.zhgh.memberCost.service.AlipayService; +import io.v.nutz.zhgh.memberCost.payment.alipay.service.AlipayService; import lombok.extern.slf4j.Slf4j; import org.nutz.dao.Chain; import org.nutz.dao.Cnd; diff --git a/src/main/java/io/v/nutz/zhgh/memberCost/payment/enums/RefundStateEnum.java b/src/main/java/io/v/nutz/zhgh/memberCost/payment/enums/RefundStateEnum.java new file mode 100644 index 0000000..3e54d0a --- /dev/null +++ b/src/main/java/io/v/nutz/zhgh/memberCost/payment/enums/RefundStateEnum.java @@ -0,0 +1,22 @@ +package io.v.nutz.zhgh.memberCost.payment.enums; + +import io.v.nutz.base.annontation.SelectEnum; + +/** + * 退款状态枚举 + */ +@Getter +@SelectEnum +@AllArgsConstructor +public enum RefundStateEnum { + + INITIATE_REFUND("发起退款"), + REFUNDING("退款中"), + REFUND_SUCCESS("退款成功"), + REFUND_FAILED("退款失败"); + + /** + * 避免和枚举类的name冲突 + */ + public final String refundStateName; +} diff --git a/src/main/java/io/v/nutz/zhgh/memberCost/payment/enums/TradingChannelEnum.java b/src/main/java/io/v/nutz/zhgh/memberCost/payment/enums/TradingChannelEnum.java new file mode 100644 index 0000000..2f1ea6c --- /dev/null +++ b/src/main/java/io/v/nutz/zhgh/memberCost/payment/enums/TradingChannelEnum.java @@ -0,0 +1,23 @@ +package io.v.nutz.zhgh.memberCost.payment.enums; + +import io.v.nutz.base.annontation.SelectEnum; + +/** + * 交易渠道枚举 + */ +@Getter +@SelectEnum +@AllArgsConstructor +public enum TradingChannelEnum { + + QQ_PAY("QQ"), + WX_PAY("微信"), + JD_PAY("京东"), + ALI_PAY("支付宝"), + UNION_PAY("云闪付"); + + /** + * 避免和枚举类的name冲突 + */ + public final String trdingChannelName; +} diff --git a/src/main/java/io/v/nutz/zhgh/memberCost/payment/enums/TradingStateEnum.java b/src/main/java/io/v/nutz/zhgh/memberCost/payment/enums/TradingStateEnum.java new file mode 100644 index 0000000..17c7c9f --- /dev/null +++ b/src/main/java/io/v/nutz/zhgh/memberCost/payment/enums/TradingStateEnum.java @@ -0,0 +1,22 @@ +package io.v.nutz.zhgh.memberCost.payment.enums; + +import io.v.nutz.base.annontation.SelectEnum; + + +/** + * 支付状态枚举 + */ +@Getter +@SelectEnum +@AllArgsConstructor +public enum TradingStateEnum { + + WAITING_FOR_PAYMENT("等待支付"), + PAY_SUCCESS("支付成功"), + CANCEL_PAYMENT("取消支付"); + + /** + * 避免和枚举类的name冲突 + */ + public final String trdingStateName; +} diff --git a/src/main/java/io/v/nutz/zhgh/memberCost/payment/enums/TradingTypeEnum.java b/src/main/java/io/v/nutz/zhgh/memberCost/payment/enums/TradingTypeEnum.java new file mode 100644 index 0000000..31865e4 --- /dev/null +++ b/src/main/java/io/v/nutz/zhgh/memberCost/payment/enums/TradingTypeEnum.java @@ -0,0 +1,20 @@ +package io.v.nutz.zhgh.memberCost.payment.enums; + +import io.v.nutz.base.annontation.SelectEnum; + +/** + * 交易类型枚举 + */ +@Getter +@SelectEnum +@AllArgsConstructor +public enum TradingTypeEnum { + + PAYMENT("付款"), + REFUND("退款"); + + /** + * 避免和枚举类的name冲突 + */ + public final String trdingTypeName; +} diff --git a/src/main/java/io/v/nutz/zhgh/memberCost/payment/model/PaymentTransaction.java b/src/main/java/io/v/nutz/zhgh/memberCost/payment/model/PaymentTransaction.java new file mode 100644 index 0000000..1a9c092 --- /dev/null +++ b/src/main/java/io/v/nutz/zhgh/memberCost/payment/model/PaymentTransaction.java @@ -0,0 +1,107 @@ +package io.v.nutz.zhgh.memberCost.payment.model; + +import io.v.nutz.base.model.BaseModel; + +import java.math.BigDecimal; + +/** + * 交易单表 + */ +@Data +@Table +@Comment("交易订单表") +@EqualsAndHashCode(callSuper = true) +public class PaymentTransaction extends BaseModel { + + @Column + @Name + @Comment("ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + @PrevInsert(uu32 = true) + private String id; + + @Column + @Comment("商户号") + @ColDefine(type = ColType.VARCHAR,width = 128) + private String mchId; + + @Column + @Comment("订单号,传递给交易系统,交易系统订单号") + @ColDefine(type = ColType.VARCHAR,width = 128) + private String outTradeNo; + + @Column + @Comment("交易系统交易号") + @ColDefine(type = ColType.VARCHAR,width = 128) + private String tradingOrderNo; + + @Column + @Comment("交易渠道") + @ColDefine(type = ColType.VARCHAR,width = 50) + private String tradingChannel; + + @Column + @Comment("交易类型") + @ColDefine(type = ColType.VARCHAR,width = 30) + private String tradingType; + + @Column + @Comment("用户ID") + @ColDefine(type = ColType.VARCHAR,width = 32) + private String userId; + + @Column + @Comment("用户工号") + @ColDefine(type = ColType.VARCHAR,width = 50) + private String loginName; + + @Column + @Comment("用户姓名") + @ColDefine(type = ColType.VARCHAR,width = 50) + private String userName; + + @Column + @Comment("用户工会") + @ColDefine(type = ColType.VARCHAR,width = 50) + private String unionName; + + @Column + @Comment("用户单位") + @ColDefine(type = ColType.VARCHAR,width = 50) + private String unitName; + + @Column + @Comment("交易金额") + @ColDefine(customType = "decimal") + private BigDecimal tradingAmount; + + @Column + @Comment("是否退款") + @ColDefine(type = ColType.BOOLEAN) + private Boolean isRefund; + + @Column + @Comment("退款金额") + @ColDefine(customType = "decimal") + private String refundAmount; + + @Column + @Comment("订单描述") + @ColDefine(type = ColType.VARCHAR,width = 128) + private String description; + + @Column + @Comment("附加详细描述") + @ColDefine(type = ColType.TEXT) + private String attach; + + @Column + @Comment("微信支付用户openId") + @ColDefine(type = ColType.VARCHAR,width = 50) + private String openId; + + @Column + @Comment("交易返回数据") + @ColDefine(type = ColType.MYSQL_JSON) + private String resultJson; +} diff --git a/src/main/java/io/v/nutz/zhgh/memberCost/payment/model/RefundRecord.java b/src/main/java/io/v/nutz/zhgh/memberCost/payment/model/RefundRecord.java new file mode 100644 index 0000000..d65049f --- /dev/null +++ b/src/main/java/io/v/nutz/zhgh/memberCost/payment/model/RefundRecord.java @@ -0,0 +1,57 @@ +package io.v.nutz.zhgh.memberCost.payment.model; + +import io.v.nutz.base.model.BaseModel; + +import java.math.BigDecimal; + +/** + * 退款记录表 + */ +@Data +@Table +@Comment("退款记录表") +@EqualsAndHashCode(callSuper = true) +public class RefundRecord extends BaseModel { + + @Column + @Name + @Comment("ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + @PrevInsert(uu32 = true) + private String id; + + @Column + @Comment("关联系统交易订单表Id") + @ColDefine(type = ColType.VARCHAR,width = 32) + private String paymentTransactionId; + + @Column + @Comment("本次退款订单号") + @ColDefine(type = ColType.VARCHAR,width = 128) + private String outRefundTradeNo; + + @Column + @Comment("第三方支付的退款单号") + @ColDefine(type = ColType.VARCHAR,width = 128) + private String refundNo; + + @Column + @Comment("退款状态") + @ColDefine(type = ColType.VARCHAR,width = 30) + private String refundState; + + @Column + @Comment("本次退款金额") + @ColDefine(customType = "decimal") + private BigDecimal refundAmount; + + @Column + @Comment("原订单金额") + @ColDefine(customType = "decimal") + private BigDecimal total; + + @Column + @Comment("交易返回数据") + @ColDefine(type = ColType.MYSQL_JSON) + private String resultJson; +} diff --git a/src/main/java/io/v/nutz/zhgh/memberCost/payment/wxpay/bean/WxPayV3Bean.java b/src/main/java/io/v/nutz/zhgh/memberCost/payment/wxpay/bean/WxPayV3Bean.java new file mode 100644 index 0000000..4999027 --- /dev/null +++ b/src/main/java/io/v/nutz/zhgh/memberCost/payment/wxpay/bean/WxPayV3Bean.java @@ -0,0 +1,47 @@ +package io.v.nutz.zhgh.memberCost.payment.wxpay.bean; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @version 1.0 + * @Author zzr + * @name:WxPayV3Bean + * @Date 2025/3/6 9:54 + * @注释 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +public class WxPayV3Bean { + + private String appId; + private String keyPath; + private String publicKeyPath; + private String certPath; + private String certP12Path; + private String platformCertPath; + private String mchId; + private String apiKey; + private String apiKey3; + private String domain; + private String publicKeyId; + + @Override + public String toString() { + return "WxPayV3Bean{" + + "appId='" + appId + '\'' + + ", keyPath='" + keyPath + '\'' + + ", publicKeyPath='" + publicKeyPath + '\'' + + ", certPath='" + certPath + '\'' + + ", certP12Path='" + certP12Path + '\'' + + ", platformCertPath='" + platformCertPath + '\'' + + ", mchId='" + mchId + '\'' + + ", apiKey='" + apiKey + '\'' + + ", apiKey3='" + apiKey3 + '\'' + + ", domain='" + domain + '\'' + + ", publicKeyId='" + publicKeyId + '\'' + + '}'; + } +} diff --git a/src/main/java/io/v/nutz/zhgh/memberCost/payment/wxpay/pem/apiclient_cert.pem b/src/main/java/io/v/nutz/zhgh/memberCost/payment/wxpay/pem/apiclient_cert.pem new file mode 100644 index 0000000..ee557fe --- /dev/null +++ b/src/main/java/io/v/nutz/zhgh/memberCost/payment/wxpay/pem/apiclient_cert.pem @@ -0,0 +1,25 @@ +-----BEGIN CERTIFICATE----- +MIIEKDCCAxCgAwIBAgIUONYpzvxVfV/RrWnLGPlL6/nb/AcwDQYJKoZIhvcNAQEL +BQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsT +FFRlbnBheS5jb20gQ0EgQ2VudGVyMRswGQYDVQQDExJUZW5wYXkuY29tIFJvb3Qg +Q0EwHhcNMjUwMzA2MTQwNDAzWhcNMzAwMzA1MTQwNDAzWjCBgTETMBEGA1UEAwwK +MTY2NjkzMDk4MDEbMBkGA1UECgwS5b6u5L+h5ZWG5oi357O757ufMS0wKwYDVQQL +DCTmrabmsYnlnLDlpKfkuInmgJ3np5HmioDmnInpmZDlhazlj7gxCzAJBgNVBAYT +AkNOMREwDwYDVQQHDAhTaGVuWmhlbjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC +AQoCggEBALlDML+FJEW+m2hXp/qUH1cU6xlwFllLU4LjFusJkxwyzzcZO4nY0mOi +3woz8xIJipvUWj2Y413WYwMkfcJcRgghupZkfYwdQtSyPfUu7xQBUm8TLWGH88Re +kyyVABEB5T+ne6r3LesXS4IuZknm5N/iaa4z9mbbscGqF0GLvMUqZCRNyTkyfK9r +Bkvs/vspi+Jcjx9I7aU++h/vwzsGB6Bf/uB3kLMb+lj/i3xY20sdrrW8JD2sqONQ +NcRIKmNXSp4zsNy+d6kIKWE3P5609ZTta1ogkeGBNdGXMRNNy6vLIudQc7zny/9H +S4LxGsIrsYmZNhGljRng56X+PG3w1CUCAwEAAaOBuTCBtjAJBgNVHRMEAjAAMAsG +A1UdDwQEAwID+DCBmwYDVR0fBIGTMIGQMIGNoIGKoIGHhoGEaHR0cDovL2V2Y2Eu +aXRydXMuY29tLmNuL3B1YmxpYy9pdHJ1c2NybD9DQT0xQkQ0MjIwRTUwREJDMDRC +MDZBRDM5NzU0OTg0NkMwMUMzRThFQkQyJnNnPUhBQ0M0NzFCNjU0MjJFMTJCMjdB +OUQzM0E4N0FEMUNERjU5MjZFMTQwMzcxMA0GCSqGSIb3DQEBCwUAA4IBAQBQ5e8U +1pQ40gfRoZyO0s+QF16L8pAcVLVwHffo0mmJpIRB4bu8W5IJ9kKhksJ0CzZ0YEwB +Yv7/LTC1qpi7PE73nZ4Ytm9oZeH1Kk5KIlQS+2H3IwOpoV4wucMc34y6MVQJjC7E +u5OnglBPSAopwNP4p+Us9A3ah7Ks48XCw+LCEWpA/setJwo9C13Qq2AQm8qLpogK +pNBwm/oylxb8/kZK1lLPgcXd7geLDhl/Str+aOzBXyd7YSEMxS8zWiZhWozu6rCq +dg10QFKicPGDkDzNQwBz7cDXvlJXSWRDBK5r1li1YgX+QD5WJYPchATo5SlvF4Lr +5/V/dZzI7BJTinr1 +-----END CERTIFICATE----- diff --git a/src/main/java/io/v/nutz/zhgh/memberCost/payment/wxpay/pem/apiclient_key.pem b/src/main/java/io/v/nutz/zhgh/memberCost/payment/wxpay/pem/apiclient_key.pem new file mode 100644 index 0000000..36b4b67 --- /dev/null +++ b/src/main/java/io/v/nutz/zhgh/memberCost/payment/wxpay/pem/apiclient_key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC5QzC/hSRFvpto +V6f6lB9XFOsZcBZZS1OC4xbrCZMcMs83GTuJ2NJjot8KM/MSCYqb1Fo9mONd1mMD +JH3CXEYIIbqWZH2MHULUsj31Lu8UAVJvEy1hh/PEXpMslQARAeU/p3uq9y3rF0uC +LmZJ5uTf4mmuM/Zm27HBqhdBi7zFKmQkTck5MnyvawZL7P77KYviXI8fSO2lPvof +78M7BgegX/7gd5CzG/pY/4t8WNtLHa61vCQ9rKjjUDXESCpjV0qeM7DcvnepCClh +Nz+etPWU7WtaIJHhgTXRlzETTcuryyLnUHO858v/R0uC8RrCK7GJmTYRpY0Z4Oel +/jxt8NQlAgMBAAECggEBAKGQqTi9Ii741Ysftsze1J4bDhS3HaZt/LyO0vPS+8qB +vRiuFrBWuNRPu/en6nl2fLz9al2Bsfep+dtJvar80c5Rq+lwZdUFx7y6XTIv5iwq +IvvfW5pM+Bfu6qbcopwybP0gUMd+nTsCq8UyNd6JUFy3lbZodqCpQ9JDRdjRxqSi +oMonve36Q9kJyDs0mS2F0w+Y9oYFtpE9WvGMBthwT7VfzWuDa+YC/Gh0RhT2V9OG +uDC8kxmfaIbk0IITDVFWVMMhScXiqmJL1II9yQWsCHH73dZS+dDxwwH0ObRD3kOx +hHptxpRzhtuNxLjCOZDGhneyvUHIftpqf4wdOgQ8iUECgYEA6TDo36s3XDFIs8SH +lpVYrhie0nmaNET50CtOc5C2M1OotrkMUrQTMoa4F263UloJfqweW9AKZX11wPp2 +8h7af2sZsGawjuwv7mMthZJoi0fc5J2+z6BnVGgFo7uZbcs1Y/+B0tNrDKIHVrqb +Lywmh18iKDXrMiMDMRp8mtiNyU0CgYEAy2Im0oGb1rmAh9gPvQIENmNEgRsyIU4x +WPAFb5KO7jnseO9KrC9uiRSO5JuwZu/QNGlga2w77Gu7n+Q4HfSU2KFlNhR6pKjb +mqXzPq1quryzbtWay520VsRKz3F/Tfp1FUpIuZvj8x7FrL8z8vjbLkbW4p+Z7HE4 +heYdmk2KCjkCgYBC6xU48pJtc3swk2pxjSQoucoCDoFxFIY39eWKhnGy4wQcg5gE +t8Z2jnCP0ObszAfDgTMpF9eT7l/3ZCj0LGR5gkuZ8q4iJadPmsh6d1xm89VxCc+z +F43vi/ZqWTCbcGA+9RjVXnRu6KSAgAZ+kAXyfRt5PJflCGUnFznA2fo+VQKBgG6s +n7Gno/UKBv5lPdM9mKs8A5g6A2KKWWIrYtnfJ/ZNAPiiRsFCImVoEYYnjqvFTkhn +G3f5cvZpfbU5jKwIX0MvOJNgO4kE9lPGgIKX/d9WNlJW3KB21h7tPER8X6lAZJxM +SxztzvKKyUkC1zMd5q/dDqxN64X16qs6mNtR3I9JAoGBAJbqQtg59Szi2m4jZ9Xo +0cKvP7+PSKgysdWsemTkU0ji1rcMpGRTtcUGRWlawLjRSInQS+xNdL6GVU5mHZWe +gNwXIXEpape4IJta0B1PYAhNcIvOSh5CzcUnVTeo6q0CTSVQPdsivlrObLKZ4uGQ +eewDw82Ej6YoSgczjf99ug0x +-----END PRIVATE KEY----- diff --git a/src/main/java/io/v/nutz/zhgh/memberCost/payment/wxpay/pem/wechatpay.pem b/src/main/java/io/v/nutz/zhgh/memberCost/payment/wxpay/pem/wechatpay.pem new file mode 100644 index 0000000..aaa6938 --- /dev/null +++ b/src/main/java/io/v/nutz/zhgh/memberCost/payment/wxpay/pem/wechatpay.pem @@ -0,0 +1,24 @@ +-----BEGIN CERTIFICATE----- +MIIEFDCCAvygAwIBAgIUKN05Gm0Q9n9mLPPltUh8qjKKegQwDQYJKoZIhvcNAQEL +BQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsT +FFRlbnBheS5jb20gQ0EgQ2VudGVyMRswGQYDVQQDExJUZW5wYXkuY29tIFJvb3Qg +Q0EwHhcNMjUwMzA2MTQwNDAzWhcNMzAwMzA1MTQwNDAzWjBuMRgwFgYDVQQDDA9U +ZW5wYXkuY29tIHNpZ24xEzARBgNVBAoMClRlbnBheS5jb20xHTAbBgNVBAsMFFRl +bnBheS5jb20gQ0EgQ2VudGVyMQswCQYDVQQGEwJDTjERMA8GA1UEBwwIU2hlblpo +ZW4wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDbMenF0GNlcUYErPpj +Aj+WOuzRFz+PJcrtgkI81S0WDh8flMtq1A2nwKARNyPXx+UPd9it657nH5G8E9kL +Ea5u5rENpn+JZc4cAIvZqazteSAUg2pfQH9ewW+/CxNOWarjXPNRYa0OjZWf+5F8 +ZBOT/x8sJ2+jou9lxKNe1skha+jzmiQ8m3B2vPXqR87qgL/fyQjjpLvBGpvearh/ +hxTMBEfGeB4F6Fu52Fz3/VCWe38ubxwj8EMcRSPp4xsl2BTaRVMMT525Hul2N49C +vXCSVsCNt3ND8UDffXnb19Zgpir4KqpECTbfqcT7YX+U34P1Av8gcDl6rRm+7Wpj +PY4RAgMBAAGjgbkwgbYwCQYDVR0TBAIwADALBgNVHQ8EBAMCA/gwgZsGA1UdHwSB +kzCBkDCBjaCBiqCBh4aBhGh0dHA6Ly9ldmNhLml0cnVzLmNvbS5jbi9wdWJsaWMv +aXRydXNjcmw/Q0E9MUJENDIyMEU1MERCQzA0QjA2QUQzOTc1NDk4NDZDMDFDM0U4 +RUJEMiZzZz1IQUNDNDcxQjY1NDIyRTEyQjI3QTlEMzNBODdBRDFDREY1OTI2RTE0 +MDM3MTANBgkqhkiG9w0BAQsFAAOCAQEAUAvXCx55ZGmd3ATi28W4mirnUHQb2RAw +X5/0OC2SkuBdzxI5RbY4YAuugP6nQIAU8TXCANzno2oqZ6vmFZ4dBnJmLewVFMoM +qp18A4RWmnsGnmEIgMm6N1kB+RbM11oLCLdy2KK0SvmqDmTBFJyjyUGqEmRshnV/ +QfKn4UUzJ4suDFAolGX4DyDIOtM0D+SCHwwxGI4yf2+nj4IB8XgmmOeschxoSvu9 +T3E6BgQ271YVDwg+3r9CiFVI5JdyftvQagOEQmZJMPINEKgFn5LzrZJW7mH42+N+ +i4RFz04wpGUsrSFDESh3JxYSNhq/HulpMLinntWxEBHFhpkjyyGDGg== +-----END CERTIFICATE----- \ No newline at end of file diff --git a/src/main/java/io/v/nutz/zhgh/memberCost/payment/wxpay/service/WxPayCommonService.java b/src/main/java/io/v/nutz/zhgh/memberCost/payment/wxpay/service/WxPayCommonService.java new file mode 100644 index 0000000..60d8689 --- /dev/null +++ b/src/main/java/io/v/nutz/zhgh/memberCost/payment/wxpay/service/WxPayCommonService.java @@ -0,0 +1,68 @@ +package io.v.nutz.zhgh.memberCost.payment.wxpay.service; + +import io.v.nutz.zhgh.memberCost.payment.wxpay.vo.WxPayNeedParamVo; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * @version 1.0 + * @Author zzr + * @name:WxPayCommonService + * @Date 2025/3/6 11:40 + * @注释 + */ +public interface WxPayCommonService { + + + /** + * 二维码统一下单,返回支付二维码链接 + * @param paramVo 需要传递的信息,请自定义付款金额Amount 和 付款描述Description,其他关键信息请勿修改 + * 注意Amount的总价total是int类型,会自动乘以0.01,例如传递100元,会自动转换为1元 + * @return + */ + String nativePay(WxPayNeedParamVo paramVo); + + + /** + * JSAPI支付,返回支付参数 + * @param paramVo 需要传递的信息,请自定义付款金额Amount 和 付款描述Description,其他关键信息请勿修改 + * 注意Amount的总价total是int类型,会自动乘以0.01,例如传递100元,会自动转换为1元 + * JsAPI支付,需要传递openId,请自行获取 + * @return + */ + String jsApiPay(WxPayNeedParamVo paramVo); + + /** + * WAP支付,返回支付参数 + * @param paramVo 需要传递的信息,请自定义付款金额Amount 和 付款描述Description,其他关键信息请勿修改 + * 注意Amount的总价total是int类型,会自动乘以0.01,例如传递100元,会自动转换为1元 + * @return + */ + String wapPay(WxPayNeedParamVo paramVo); + + + /** + * 支付回调,验证是否支付成功 + * @param request 请求 + * @param response 响应 + */ + void payNotify(HttpServletRequest request, HttpServletResponse response); + + + /** + * 退款 + * @param transactionId 微信订单号 + * @param outTradeNo 商户订单号 + * @return + */ + String refund(String transactionId, String outTradeNo); + + + /** + * 退款回调 + * @param request 请求 + * @param response 响应 + */ + void refundNotify(HttpServletRequest request, HttpServletResponse response); +} diff --git a/src/main/java/io/v/nutz/zhgh/memberCost/payment/wxpay/service/impl/WxPayCommonServiceImpl.java b/src/main/java/io/v/nutz/zhgh/memberCost/payment/wxpay/service/impl/WxPayCommonServiceImpl.java new file mode 100644 index 0000000..8d2a0a0 --- /dev/null +++ b/src/main/java/io/v/nutz/zhgh/memberCost/payment/wxpay/service/impl/WxPayCommonServiceImpl.java @@ -0,0 +1,479 @@ +package io.v.nutz.zhgh.memberCost.payment.wxpay.service.impl; + +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.http.ContentType; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import com.ijpay.core.IJPayHttpResponse; +import com.ijpay.core.enums.AuthTypeEnum; +import com.ijpay.core.enums.RequestMethodEnum; +import com.ijpay.core.kit.AesUtil; +import com.ijpay.core.kit.HttpKit; +import com.ijpay.core.kit.PayKit; +import com.ijpay.core.kit.WxPayKit; +import com.ijpay.wxpay.WxPayApi; +import com.ijpay.wxpay.enums.WxDomainEnum; +import com.ijpay.wxpay.enums.v3.BasePayApiEnum; +import com.ijpay.wxpay.model.v3.*; +import io.v.nutz.zhgh.memberCost.payment.wxpay.bean.WxPayV3Bean; +import io.v.nutz.zhgh.memberCost.payment.wxpay.service.WxPayCommonService; +import io.v.nutz.zhgh.memberCost.payment.wxpay.vo.WxPayNeedParamVo; +import lombok.extern.slf4j.Slf4j; +import org.nutz.ioc.loader.annotation.IocBean; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.ByteArrayInputStream; +import java.io.FileWriter; +import java.nio.charset.StandardCharsets; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @version 1.0 + * @Author zzr + * @name:WxPayCommonServiceImpl + * @Date 2025/3/6 11:41 + * @注释 + */ +@Slf4j +@IocBean +public class WxPayCommonServiceImpl implements WxPayCommonService { + + // 判断下单接口成功返回码 + private final static int OK = 200; + + // 微信V3必要的支付参数,后期优化 + private final static WxPayV3Bean WX_PAY_V3_BEAN = new WxPayV3Bean( + "ww3eda050a1b5ad96e", + "src/main/java/io/v/nutz/zhgh/memberCost/wxpay/pem/apiclient_key.pem", + "src/main/java/io/v/nutz/zhgh/memberCost/wxpay/pem/apiclient_key.pem", + "src/main/java/io/v/nutz/zhgh/memberCost/wxpay/pem/apiclient_cert.pem", + "src/main/java/io/v/nutz/zhgh/memberCost/wxpay/pem/apiclient_cert.pem", + "src/main/java/io/v/nutz/zhgh/memberCost/wxpay/pem/wechatpay.pem", + "1666930980", + "", + "4ebd020883285d698c44ec50939c0967", + "https://schoolhd.top/platform", + ""); + + // 自定义参数,内容是统一的,但会被多次调用,直接声明 + String serialNo; + String platSerialNo; + String payNotifyUrl = WX_PAY_V3_BEAN.getDomain().concat("/wxPay/notifyMessage"); + + /** + * 微信扫描二维码支付 + * @param paramVo 需要传递的信息,请自定义付款金额Amount 和 付款描述Description,其他关键信息请勿修改 + * 注意Amount的总价total是int类型,会自动乘以0.01,例如传递100元,会自动转换为1元 + * @return + */ + @Override + public String nativePay(WxPayNeedParamVo paramVo) { + try { + // 商户订单号,存储当前用户的订单 + String outTradeNo = PayKit.generateStr(); + + String timeExpire = getNowTimeExpire(); + UnifiedOrderModel unifiedOrderModel = new UnifiedOrderModel() + .setAppid(WX_PAY_V3_BEAN.getAppId()) + .setMchid(WX_PAY_V3_BEAN.getMchId()) + // 描述信息 + .setDescription(paramVo.getDescription()) + .setOut_trade_no(outTradeNo) + .setTime_expire(timeExpire) + .setAttach(paramVo.getAttach()) + .setNotify_url(payNotifyUrl) + // 订单金额 + .setAmount(paramVo.getAmount()); + + log.info("二维码支付统一下单参数 {}", JSONUtil.toJsonStr(unifiedOrderModel)); + IJPayHttpResponse response = WxPayApi.v3( + RequestMethodEnum.POST, + WxDomainEnum.CHINA.toString(), + BasePayApiEnum.NATIVE_PAY.toString(), + WX_PAY_V3_BEAN.getMchId(), + getSerialNumber(), + null, + WX_PAY_V3_BEAN.getKeyPath(), + JSONUtil.toJsonStr(unifiedOrderModel), + AuthTypeEnum.RSA.getCode() + ); + log.info("统一下单响应 {}", response); + // 根据证书序列号查询对应的证书来验证签名结果 + boolean verifySignature = WxPayKit.verifySignature(response, WX_PAY_V3_BEAN.getPlatformCertPath()); + log.info("verifySignature: {}", verifySignature); + // 下单返回数据 + String result = response.getBody(); + + if (result != null) { + // 向数据库插入订单记录 + } + + return result; + } catch (Exception e) { + log.error("系统异常", e); + return e.getMessage(); + } + } + + + @Override + public String jsApiPay(WxPayNeedParamVo paramVo) { + try { + // 商户订单号,存储当前用户的订单 + String outTradeNo = PayKit.generateStr(); + // 订单关闭时间 + String timeExpire = getNowTimeExpire(); + UnifiedOrderModel unifiedOrderModel = new UnifiedOrderModel() + .setAppid(WX_PAY_V3_BEAN.getAppId()) + .setMchid(WX_PAY_V3_BEAN.getMchId()) + .setDescription(paramVo.getDescription()) + .setOut_trade_no(outTradeNo) + .setTime_expire(timeExpire) + .setAttach(paramVo.getAttach()) + .setNotify_url(payNotifyUrl) + .setAmount(paramVo.getAmount()) + .setPayer(paramVo.getPayer()); + + log.info("统一下单参数 {}", JSONUtil.toJsonStr(unifiedOrderModel)); + IJPayHttpResponse response = WxPayApi.v3( + RequestMethodEnum.POST, + WxDomainEnum.CHINA.toString(), + BasePayApiEnum.JS_API_PAY.toString(), + WX_PAY_V3_BEAN.getMchId(), + getSerialNumber(), + null, + WX_PAY_V3_BEAN.getKeyPath(), + JSONUtil.toJsonStr(unifiedOrderModel) + ); + log.info("统一下单响应 {}", response); + // 根据证书序列号查询对应的证书来验证签名结果 + boolean verifySignature = WxPayKit.verifySignature(response, WX_PAY_V3_BEAN.getPlatformCertPath()); + log.info("verifySignature: {}", verifySignature); + if (response.getStatus() == OK && verifySignature) { + String body = response.getBody(); + JSONObject jsonObject = JSONUtil.parseObj(body); + String prepayId = jsonObject.getStr("prepay_id"); + Map map = WxPayKit.jsApiCreateSign(WX_PAY_V3_BEAN.getAppId(), prepayId, WX_PAY_V3_BEAN.getKeyPath()); + log.info("唤起支付参数:{}", map); + // 唤起支付成功,向数据库插入订单参数 + + return JSONUtil.toJsonStr(map); + } + return JSONUtil.toJsonStr(response); + } catch (Exception e) { + log.error("系统异常", e); + return e.getMessage(); + } + } + + + @Override + public String wapPay(WxPayNeedParamVo paramVo) { + try { + // 商户订单号,存储当前用户的订单 + String outTradeNo = PayKit.generateStr(); + // 订单关闭时间 + String timeExpire = getNowTimeExpire(); + UnifiedOrderModel unifiedOrderModel = new UnifiedOrderModel() + .setAppid(WX_PAY_V3_BEAN.getAppId()) + .setMchid(WX_PAY_V3_BEAN.getMchId()) + .setDescription(paramVo.getDescription()) + .setOut_trade_no(outTradeNo) + .setTime_expire(timeExpire) + .setAttach(paramVo.getAttach()) + .setNotify_url(payNotifyUrl) + .setAmount(paramVo.getAmount()) + .setScene_info( + new SceneInfo() + .setPayer_client_ip(""). + setH5_info(new H5Info() + .setType("Wap"))); + + log.info("统一下单参数 {}", JSONUtil.toJsonStr(unifiedOrderModel)); + IJPayHttpResponse response = WxPayApi.v3( + RequestMethodEnum.POST, + WxDomainEnum.CHINA.toString(), + BasePayApiEnum.H5_PAY.toString(), + WX_PAY_V3_BEAN.getMchId(), + getSerialNumber(), + null, + WX_PAY_V3_BEAN.getKeyPath(), + JSONUtil.toJsonStr(unifiedOrderModel) + ); + log.info("统一下单响应 {}", response); + // 根据证书序列号查询对应的证书来验证签名结果 + boolean verifySignature = WxPayKit.verifySignature(response, WX_PAY_V3_BEAN.getPlatformCertPath()); + log.info("verifySignature: {}", verifySignature); + if (response.getStatus() == OK && verifySignature) { + String body = response.getBody(); + return JSONUtil.toJsonStr(body); + } + return JSONUtil.toJsonStr(response); + } catch (Exception e) { + log.error("系统异常", e); + return e.getMessage(); + } + } + + + /** + * 支付回调 + * @param request + * @param response + */ + @Override + public void payNotify(HttpServletRequest request, HttpServletResponse response) { + Map map = new HashMap<>(12); + try { + String timestamp = request.getHeader("Wechatpay-Timestamp"); + String nonce = request.getHeader("Wechatpay-Nonce"); + String serialNo = request.getHeader("Wechatpay-Serial"); + String signature = request.getHeader("Wechatpay-Signature"); + + log.info("timestamp:{} nonce:{} serialNo:{} signature:{}", timestamp, nonce, serialNo, signature); + String result = HttpKit.readData(request); + log.info("支付通知密文 {}", result); +// String plainText = null; + // 需要通过证书序列号查找对应的证书,verifyNotify 中有验证证书的序列号 + String plainText = WxPayKit.verifyNotify(serialNo, result, signature, nonce, timestamp, + WX_PAY_V3_BEAN.getApiKey3(), WX_PAY_V3_BEAN.getPlatformCertPath()); + // 微信公钥验证签名并解密 +// if (ObjectUtil.equals(serialNo, WX_PAY_V3_BEAN.getPublicKeyId())) { +// plainText = WxPayKit.verifyPublicKeyNotify(result, signature, nonce, timestamp, +// WX_PAY_V3_BEAN.getApiKey3(), WX_PAY_V3_BEAN.getPlatformCertPath()); +// } + log.info("支付通知明文 {}", plainText); + + if (StrUtil.isNotEmpty(plainText)) { + response.setStatus(200); + map.put("code", "SUCCESS"); + map.put("message", "SUCCESS"); + } else { + response.setStatus(500); + map.put("code", "ERROR"); + map.put("message", "签名错误"); + } + response.setHeader("Content-type", ContentType.JSON.toString()); + response.getOutputStream().write(JSONUtil.toJsonStr(map).getBytes(StandardCharsets.UTF_8)); + response.flushBuffer(); + } catch (Exception e) { + log.error("系统异常", e); + } + } + + + /** + * 退款 + * @param transactionId 微信订单号 + * @param outTradeNo 商户订单号 + * @return + */ + @Override + public String refund(String transactionId, String outTradeNo) { + try { + String outRefundNo = PayKit.generateStr(); + log.info("商户退款单号: {}", outRefundNo); + + List list = new ArrayList<>(); + RefundGoodsDetail refundGoodsDetail = new RefundGoodsDetail() + .setMerchant_goods_id("123") + .setGoods_name("IJPay 测试") + .setUnit_price(1) + .setRefund_amount(1) + .setRefund_quantity(1); + list.add(refundGoodsDetail); + + RefundModel refundModel = new RefundModel() + .setOut_refund_no(outRefundNo) + .setReason("IJPay 测试退款") + .setNotify_url(WX_PAY_V3_BEAN.getDomain().concat("/v3/refundNotify")) + .setAmount(new RefundAmount().setRefund(1).setTotal(1).setCurrency("CNY")) + .setGoods_detail(list); + + if (StrUtil.isNotEmpty(transactionId)) { + refundModel.setTransaction_id(transactionId); + } + if (StrUtil.isNotEmpty(outTradeNo)) { + refundModel.setOut_trade_no(outTradeNo); + } + log.info("退款参数 {}", JSONUtil.toJsonStr(refundModel)); + IJPayHttpResponse response = WxPayApi.v3( + RequestMethodEnum.POST, + WxDomainEnum.CHINA.toString(), + BasePayApiEnum.REFUND.toString(), + WX_PAY_V3_BEAN.getMchId(), + getSerialNumber(), + null, + WX_PAY_V3_BEAN.getKeyPath(), + JSONUtil.toJsonStr(refundModel) + ); + // 根据证书序列号查询对应的证书来验证签名结果 + boolean verifySignature = WxPayKit.verifySignature(response, WX_PAY_V3_BEAN.getPlatformCertPath()); + // 微信支付公钥验证签名 +// boolean verifySignature = WxPayKit.verifyPublicKeySignature(response, WX_PAY_V3_BEAN.getPlatformCertPath()); + log.info("verifySignature: {}", verifySignature); + log.info("退款响应 {}", response); + + if (verifySignature) { + return response.getBody(); + } + } catch (Exception e) { + log.error("系统异常", e); + return e.getMessage(); + } + return null; + } + + + /** + * 退款回调 + * @param request + * @param response + */ + @Override + public void refundNotify(HttpServletRequest request, HttpServletResponse response) { + Map map = new HashMap<>(12); + try { + String timestamp = request.getHeader("Wechatpay-Timestamp"); + String nonce = request.getHeader("Wechatpay-Nonce"); + String serialNo = request.getHeader("Wechatpay-Serial"); + String signature = request.getHeader("Wechatpay-Signature"); + + log.info("退款通知 timestamp:{} nonce:{} serialNo:{} signature:{}", timestamp, nonce, serialNo, signature); + String result = HttpKit.readData(request); + log.info("退款通知密文 {}", result); +// String plainText = null; + // 需要通过证书序列号查找对应的证书,verifyNotify 中有验证证书的序列号 + String plainText = WxPayKit.verifyNotify(serialNo, result, signature, nonce, timestamp, + WX_PAY_V3_BEAN.getApiKey3(), WX_PAY_V3_BEAN.getPlatformCertPath()); + // 微信公钥验证签名并解密 +// if (ObjectUtil.equals(serialNo, WX_PAY_V3_BEAN.getPublicKeyId())) { +// plainText = WxPayKit.verifyPublicKeyNotify(result, signature, nonce, timestamp, +// WX_PAY_V3_BEAN.getApiKey3(), WX_PAY_V3_BEAN.getPlatformCertPath()); +// } + log.info("退款通知明文 {}", plainText); + + if (StrUtil.isNotEmpty(plainText)) { + response.setStatus(200); + map.put("code", "SUCCESS"); + map.put("message", "SUCCESS"); + } else { + response.setStatus(500); + map.put("code", "ERROR"); + map.put("message", "签名错误"); + } + response.setHeader("Content-type", ContentType.JSON.toString()); + response.getOutputStream().write(JSONUtil.toJsonStr(map).getBytes(StandardCharsets.UTF_8)); + response.flushBuffer(); + } catch (Exception e) { + log.error("系统异常", e); + } + } + + + /** + * 公共方法,获取证书序列号 + * @return + */ + private String getSerialNumber() { + if (StrUtil.isEmpty(serialNo)) { + // 获取证书序列号 + X509Certificate certificate = PayKit.getCertificate(WX_PAY_V3_BEAN.getCertPath()); + if (null != certificate) { + serialNo = certificate.getSerialNumber().toString(16).toUpperCase(); + // 提前两天检查证书是否有效 + boolean isValid = PayKit.checkCertificateIsValid(certificate, WX_PAY_V3_BEAN.getMchId(), -2); + log.info("证书是否可用 {} 证书有效期为 {}", isValid, DateUtil.format(certificate.getNotAfter(), DatePattern.NORM_DATETIME_PATTERN)); + } +// System.out.println("输出证书信息:\n" + certificate.toString()); +// // 输出关键信息,截取部分并进行标记 +// System.out.println("证书序列号:" + certificate.getSerialNumber().toString(16)); +// System.out.println("版本号:" + certificate.getVersion()); +// System.out.println("签发者:" + certificate.getIssuerDN()); +// System.out.println("有效起始日期:" + certificate.getNotBefore()); +// System.out.println("有效终止日期:" + certificate.getNotAfter()); +// System.out.println("主体名:" + certificate.getSubjectDN()); +// System.out.println("签名算法:" + certificate.getSigAlgName()); +// System.out.println("签名:" + certificate.getSignature().toString()); + } + System.out.println("serialNo:" + serialNo); + return serialNo; + } + + + /** + * 公共方法,获取平台证书序列号 + * @return + */ + private String getPlatSerialNumber() { + if (StrUtil.isEmpty(platSerialNo)) { + // 获取平台证书序列号 + X509Certificate certificate = PayKit.getCertificate(FileUtil.getInputStream(WX_PAY_V3_BEAN.getPlatformCertPath())); + platSerialNo = certificate.getSerialNumber().toString(16).toUpperCase(); + } + System.out.println("platSerialNo:" + platSerialNo); + return platSerialNo; + } + + + /** + * 公共方法,保存平台证书 + * @param associatedData + * @param nonce + * @param cipherText + * @param algorithm + * @param certPath + * @return + */ + private String savePlatformCert(String associatedData, String nonce, String cipherText, String algorithm, String certPath) { + try { + String key3 = WX_PAY_V3_BEAN.getApiKey3(); + String publicKey; + if (StrUtil.equals(algorithm, AuthTypeEnum.SM2.getPlatformCertAlgorithm())) { + publicKey = PayKit.sm4DecryptToString(key3, cipherText, nonce, associatedData); + } else { + AesUtil aesUtil = new AesUtil(WX_PAY_V3_BEAN.getApiKey3().getBytes(StandardCharsets.UTF_8)); + // 平台证书密文解密 + // encrypt_certificate 中的 associated_data nonce ciphertext + publicKey = aesUtil.decryptToString( + associatedData.getBytes(StandardCharsets.UTF_8), + nonce.getBytes(StandardCharsets.UTF_8), + cipherText + ); + } + if (StrUtil.isNotEmpty(publicKey)) { + // 保存证书 + FileWriter writer = new FileWriter(certPath); + writer.write(publicKey); + // 获取平台证书序列号 + X509Certificate certificate = PayKit.getCertificate(new ByteArrayInputStream(publicKey.getBytes())); + return certificate.getSerialNumber().toString(16).toUpperCase(); + } + return ""; + } catch (Exception e) { + log.error("保存平台证书异常", e); + return e.getMessage(); + } + } + + + /** + * 公共方法,构建订单关闭时间,默认3分钟 + * @return + */ + private String getNowTimeExpire() { + long currentTimeMillis = System.currentTimeMillis() + 1000 * 60 * 3; + // 将时间戳转换为 DateTime 对象 + DateTime dateTime = DateUtil.date(currentTimeMillis); + return DateUtil.format(dateTime, "yyyy-MM-dd'T'HH:mm:ssXXX"); + } +} diff --git a/src/main/java/io/v/nutz/zhgh/memberCost/payment/wxpay/vo/WxPayNeedParamVo.java b/src/main/java/io/v/nutz/zhgh/memberCost/payment/wxpay/vo/WxPayNeedParamVo.java new file mode 100644 index 0000000..58977a1 --- /dev/null +++ b/src/main/java/io/v/nutz/zhgh/memberCost/payment/wxpay/vo/WxPayNeedParamVo.java @@ -0,0 +1,39 @@ +package io.v.nutz.zhgh.memberCost.payment.wxpay.vo; + +import com.ijpay.wxpay.model.v3.Amount; +import com.ijpay.wxpay.model.v3.Payer; +import lombok.Data; + +/** + * @version 1.0 + * @Author zzr + * @name:WxPayNeedParamVo + * @Date 2025/3/7 18:43 + * @注释 + */ +@Data +public class WxPayNeedParamVo { + + /** + * 订单描述,会显示在支付界面的标题,最大长度127,必填 + */ + private String description; + + /** + * 附加数据,订单的详细描述信息,不必填 + */ + private String attach; + + /** + * 金额对象,对象中的 total 是金额,必填; + * 其余参数可不传递也可不填 + */ + private Amount amount; + + /** + * 支付者对象,JsApi支付是必填,其他支付方式忽略; + * openid 微信绑定的用户openid和小程序的openid相同,必填; + * 其余参数可忽略 + */ + private Payer payer; +} diff --git a/src/main/java/io/v/nutz/zhgh/welfare/controller/WelfareProjectMangeController.java b/src/main/java/io/v/nutz/zhgh/welfare/controller/WelfareProjectMangeController.java index e16ec82..f28dd4e 100644 --- a/src/main/java/io/v/nutz/zhgh/welfare/controller/WelfareProjectMangeController.java +++ b/src/main/java/io/v/nutz/zhgh/welfare/controller/WelfareProjectMangeController.java @@ -1,5 +1,7 @@ package io.v.nutz.zhgh.welfare.controller; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import io.v.nutz.base.annontation.ViReturn; import io.v.nutz.base.dao.CndPlus; @@ -32,7 +34,6 @@ import org.nutz.ioc.loader.annotation.IocBean; import org.nutz.lang.Lang; import org.nutz.lang.Strings; import org.nutz.lang.random.R; -import org.nutz.lang.util.NutMap; import org.nutz.mvc.annotation.At; import org.nutz.mvc.annotation.Ok; import org.nutz.mvc.annotation.Param; @@ -94,7 +95,7 @@ public class WelfareProjectMangeController { Sql sql = Sqls.create("SELECT project.*,IF((SELECT count(1) FROM welfare_list WHERE projectId = project.id)>0,TRUE,FALSE) created FROM `welfare_project` project $condition"); CndPlus cnd = CndPlus.create(); - pageForm.defaultSortDesc("createdAt"); + pageForm.defaultSortDesc("opAt"); cnd.andEx("year", "=", year); if (Strings.isNotBlank(name)) { @@ -117,13 +118,14 @@ public class WelfareProjectMangeController { Trans.exec(() -> { + project.setYear(DateUtil.thisYear()); + project.setIsDisabled(false); if (project.getConditionStructure() != null) { project.setConditionStructureId(matchConditionStructureService.save(project.getConditionStructure()).getId()); } if (StrUtil.isBlank(project.getId())) { WelfareProject insertProject = dao.insertWith(project, "welfareProjectSubjects"); - if (Lang.isNotEmpty(insertProject.getWelfareProjectSubjects())) { insertProject.getWelfareProjectSubjects().forEach(v -> { dao.insertLinks(v, "options"); @@ -235,10 +237,8 @@ public class WelfareProjectMangeController { dao.update(project); } -// if (project.getIsPushHome() != 0) { -// mobileHomeService.handle(project, "welfare", "/mobile/welfare/list/receive?projectId=" + project.getId(), project.getIsPushHome()); -// } Sys_home_activity sysHomeActivity = project.covertToSysHomeActivity(); + sysHomeActivity.setEnable(true); dao.insertOrUpdate(sysHomeActivity); }); return null; @@ -256,7 +256,9 @@ public class WelfareProjectMangeController { projectService.dao().delete(MatchConditionStructure.class, project.getConditionStructureId()); } projectService.dao().clear(WelfareProjectSubject.class, Cnd.where("projectId", "=", id)); - projectService.dao().clear(WelfareProjectSubjectOption.class, Cnd.where("subjectId", "=", welfareProjectSubject.getId())); + if (ObjectUtil.isNotEmpty(welfareProjectSubject)) { + projectService.dao().clear(WelfareProjectSubjectOption.class, Cnd.where("subjectId", "=", welfareProjectSubject.getId())); + } projectService.dao().clear(WelfareUserSelection.class, Cnd.where("welfareId", "=", id)); projectService.delete(id); mobileHomeService.delete(id); @@ -292,7 +294,7 @@ public class WelfareProjectMangeController { public Object sendMsgToNotWelfareUsers(String projectId, String sendMsgValue) { Sql sql = Sqls.create(""" SELECT - u.loginname as userId + u.loginname FROM welfare_list wl left join sys_user u on u.id = wl.userId @@ -308,8 +310,13 @@ public class WelfareProjectMangeController { ) """); sql.setParam("projectId", projectId); - List userList = listService.listMap(sql); -// msgApi.sendMsg(sendMsgValue, "福利选择链接", "", "https://zhgh.jiangnan.edu.cn/mobile/welfare/list/receive?projectId=4fa233704ddb41bc8e34e966efeda0a4", "4", userList); +// List userList = listService.listMap(sql); +// Set loginNameList = userList.stream().map(user -> user.getString("loginname")).collect(Collectors.toSet()); +// String loginNames = loginNameList.stream().collect(Collectors.joining(",")); +// WelfareProject project = dao.fetch(WelfareProject.class, projectId); +// String link = Globals.AppDomain + "/mobile/welfare/list/receive?projectId=%s".formatted(projectId); +// String imageUrl = Globals.AppDomain + "/file_server/fileStreamPreview?id=" + project.getCover(); +// msgApi.sendMsg(List.of("DingTalk"), loginNames, 2, "职工福利", sendMsgValue, "", link); return null; } @@ -321,9 +328,11 @@ public class WelfareProjectMangeController { */ @At @ViReturn + @Aop(TransAop.READ_COMMITTED) @RequiresPermissions("welfare.list.mange") public Object projectStatusChange(String id, boolean val) { dao.update(WelfareProject.class, Chain.make("isDisabled", !val), Cnd.where("id", "=", id)); + dao.update(Sys_home_activity.class, Chain.make("enable", val), Cnd.where("id", "=", id)); return null; } diff --git a/src/main/java/io/v/nutz/zhgh/welfare/controller/WelfareUserChooseController.java b/src/main/java/io/v/nutz/zhgh/welfare/controller/WelfareUserChooseController.java index be6e065..eedf43e 100644 --- a/src/main/java/io/v/nutz/zhgh/welfare/controller/WelfareUserChooseController.java +++ b/src/main/java/io/v/nutz/zhgh/welfare/controller/WelfareUserChooseController.java @@ -55,27 +55,29 @@ public class WelfareUserChooseController { @ViReturn @RequiresPermissions("welfare.user.choose") public Object pageData(PageForm pageForm, Integer year) { + Sql sql = Sqls.create(""" SELECT - wp.*, - CASE - WHEN wus.selectUserId IS NOT NULL THEN 1 - ELSE 0 - END AS isChoose, - wus.selectTime, - GROUP_CONCAT(DISTINCT wuso.optionName ,'(',wus.selectNum,'份)') AS gist_list, - wus.receiveAddress + wp.*, + CASE + WHEN wus.selectUserId IS NOT NULL THEN 1 + ELSE 0 + END AS isChoose, + wus.selectTime, + GROUP_CONCAT(DISTINCT wuso.optionName ,'(',wus.selectNum,'份)') AS gist_list, + wus.receiveAddress FROM - welfare_project wp - LEFT JOIN welfare_project_user_selection wus ON wp.id = wus.welfareId AND wus.selectUserId = @selectUserId - INNER JOIN welfare_list wl ON wp.id = wl.projectId AND wl.userId = @selectUserId - LEFT JOIN welfare_project_subject_option wuso ON wus.selectOptionId = wuso.id + welfare_project wp + LEFT JOIN welfare_project_user_selection wus ON wp.id = wus.welfareId AND wus.selectUserId = @selectUserId + LEFT JOIN welfare_list wl ON wp.id = wl.projectId AND wl.userId = @selectUserId + LEFT JOIN welfare_project_subject_option wuso ON wus.selectOptionId = wuso.id $condition """); sql.setParam("selectUserId", ShiroUtil.getUserId()); Cnd cnd = Cnd.NEW(); cnd.and("wp.provideMode", "in", "2,3"); + cnd.and("wl.userId", "=", ShiroUtil.getUserId()); cnd.andEX("YEAR(wp.choiceTimeStart)", "in", year); cnd.and("wp.isDisabled", "=", 0); cnd.groupBy("wp.id"); diff --git a/src/main/java/io/v/nutz/zhgh/welfare/model/WelfareProject.java b/src/main/java/io/v/nutz/zhgh/welfare/model/WelfareProject.java index ab3e5c8..d012ecc 100644 --- a/src/main/java/io/v/nutz/zhgh/welfare/model/WelfareProject.java +++ b/src/main/java/io/v/nutz/zhgh/welfare/model/WelfareProject.java @@ -1,6 +1,6 @@ package io.v.nutz.zhgh.welfare.model; -import io.v.nutz.base.model.ViBaseModel; +import cn.wizzer.framework.base.model.BaseModel; import io.v.nutz.sys.models.Sys_home_activity; import io.v.nutz.sys.services.SysHomeConvert; import io.v.nutz.zhgh.data.model.MatchConditionStructure; @@ -29,7 +29,7 @@ import java.util.List; @Accessors(chain = true) @Table("welfare_project") @Comment("福利项目") -public class WelfareProject extends ViBaseModel implements Serializable, SysHomeConvert { +public class WelfareProject extends BaseModel implements Serializable, SysHomeConvert { private static final long serialVersionUID = 1L; @@ -43,9 +43,6 @@ public class WelfareProject extends ViBaseModel implements Serializable, SysHome @Column @Comment("年度") @ColDefine(type = ColType.INT, width = 4) - @PrevInsert( - els = {@EL("$me.nowYear()")} - ) private Integer year; @Column diff --git a/src/main/java/io/v/nutz/zhgh/welfare/service/impl/WelfareSingleServiceImpl.java b/src/main/java/io/v/nutz/zhgh/welfare/service/impl/WelfareSingleServiceImpl.java index d6e3490..c1a8fa7 100644 --- a/src/main/java/io/v/nutz/zhgh/welfare/service/impl/WelfareSingleServiceImpl.java +++ b/src/main/java/io/v/nutz/zhgh/welfare/service/impl/WelfareSingleServiceImpl.java @@ -1,10 +1,10 @@ package io.v.nutz.zhgh.welfare.service.impl; -import cn.afterturn.easypoi.excel.ExcelExportUtil; import cn.afterturn.easypoi.excel.annotation.Excel; import cn.afterturn.easypoi.excel.entity.ExportParams; import cn.afterturn.easypoi.excel.entity.enmus.ExcelType; import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity; +import cn.afterturn.easypoi.excel.export.ExcelExportService; import cn.hutool.core.convert.Convert; import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSON; @@ -21,6 +21,7 @@ import io.v.nutz.zhgh.welfare.model.WelfareProject; import io.v.nutz.zhgh.welfare.model.template.WelfareExportEntityTc; import io.v.nutz.zhgh.welfare.service.WelfareSingleService; import lombok.Data; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.hssf.util.HSSFColor; import org.apache.poi.ss.usermodel.*; import org.apache.poi.ss.util.CellRangeAddress; @@ -46,9 +47,7 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.stream.Collectors; /** @@ -671,23 +670,25 @@ public class WelfareSingleServiceImpl extends ViServiceImpl impl SELECT u.loginname, u.username, - vwl.welfareUnitId as unionid, - gh.unionname as unionname, + IF(staffUnion.id IS NOT NULL, staffUnion.id, vwl.welfareUnitId) AS unionid, + IF(staffUnion.id IS NOT NULL, staffUnion.unionname, gh.unionname) AS unionname, vwl.welfareSecondLevelUnitId as unitid, dw.`name` as unitname, wpus.userSign, wpus.selectOptionId, - wpus.selectNum\s + wpus.selectNum FROM welfare_list vwl - LEFT join sys_user u on u.id = vwl.userId - left join sys_union gh on gh.id = vwl.welfareUnitId - left join sys_unit dw on dw.id = vwl.welfareSecondLevelUnitId - LEFT JOIN welfare_project_user_selection wpus ON wpus.selectUserId = vwl.userId\s - AND wpus.welfareId = @projectId\s + LEFT JOIN special_staff staff ON staff.userId = vwl.userId + LEFT JOIN sys_union staffUnion ON staff.unionRelationUnionId = staffUnion.id + LEFT JOIN sys_user u ON u.id = vwl.userId + LEFT JOIN sys_union gh ON gh.id = vwl.welfareUnitId + LEFT JOIN sys_unit dw ON dw.id = vwl.welfareSecondLevelUnitId + LEFT JOIN welfare_project_user_selection wpus ON wpus.selectUserId = vwl.userId + AND wpus.welfareId = @projectId WHERE projectId = @projectId - AND vwl.welfareUnitId = @unionId + AND (vwl.welfareUnitId = @unionId OR staffUnion.id = @unionId) order by vwl.welfareUnitId,vwl.welfareSecondLevelUnitId """); @@ -712,18 +713,21 @@ public class WelfareSingleServiceImpl extends ViServiceImpl impl }); List exportEntities = new ArrayList<>(); - exportEntities.add(new ExcelExportEntity("序号", "no", 20)); - exportEntities.add(new ExcelExportEntity("姓名", "username", 20)); - exportEntities.add(new ExcelExportEntity("工号", "loginname", 20)); - exportEntities.add(new ExcelExportEntity("所在基层工会", "unionname", 20)); - exportEntities.add(new ExcelExportEntity("所在单位", "unitname", 20)); + exportEntities.add(new ExcelExportEntity("序号", "no", 10)); + exportEntities.add(new ExcelExportEntity("姓名", "username", 10)); + exportEntities.add(new ExcelExportEntity("工号", "loginname", 15)); +// exportEntities.add(new ExcelExportEntity("所在分工会", "unionname", 20)); + ExcelExportEntity excelExportEntity1 = new ExcelExportEntity("所在单位", "unitname", 20); + excelExportEntity1.setWrap(true); + exportEntities.add(excelExportEntity1); for (NutMap option : options) { - exportEntities.add(new ExcelExportEntity(option.getString("optionName"), option.getString("id"), 20)); + exportEntities.add(new ExcelExportEntity(option.getString("optionName"), option.getString("id"), 10)); } ExcelExportEntity excelExportEntity = new ExcelExportEntity(); excelExportEntity.setName("签字"); excelExportEntity.setKey("qzBytes"); + excelExportEntity.setHeight(12); excelExportEntity.setWidth(20); excelExportEntity.setType(2); excelExportEntity.setExportImageType(2); @@ -764,9 +768,16 @@ public class WelfareSingleServiceImpl extends ViServiceImpl impl totalMap.put(option.getString("id"), selectNum); } dataList.add(totalMap); - ExportParams exportParams = new ExportParams(); + /*ExportParams exportParams = new ExportParams(); exportParams.setType(ExcelType.XSSF); Workbook workbook = ExcelExportUtil.exportExcel(exportParams, exportEntities, dataList); + workbook.write(outputStream);*/ + + Workbook workbook = new HSSFWorkbook(); + ExportParams exportParams = new ExportParams(); + exportParams.setType(ExcelType.HSSF); + ExcelExportService service = new ExcelExportService(); + service.createSheetForMap(workbook, exportParams, exportEntities, dataList); workbook.write(outputStream); // List result = new ArrayList<>(); @@ -1023,7 +1034,6 @@ public class WelfareSingleServiceImpl extends ViServiceImpl impl sheet.setColumnWidth(0, 1000 * 2); sheet.setColumnWidth(1, 1500 * 2); sheet.setColumnWidth(2, 3000 * 2); - sheet.setColumnWidth(2, 3000 * 2); sheet.setColumnWidth(3, 2000 * 2); sheet.setColumnWidth(4, 2000 * 2); sheet.setColumnWidth(5, 1500 * 2); @@ -1180,18 +1190,43 @@ public class WelfareSingleServiceImpl extends ViServiceImpl impl } else { v.setQzBytes(null); } - } + + Map addressMap = new HashMap<>(); + String receiveAddress = v.getReceiveAddress(); + if (StrUtil.isNotBlank(receiveAddress)) { + List addressList = Arrays.stream(receiveAddress.split("[,,]")).collect(Collectors.toList()); + for (String pair : addressList) { + // 2. 根据冒号分割键和值 + String[] keyValue = pair.split("[::]", 2); + if (keyValue.length == 2) { + String key = keyValue[0].trim(); + String value = keyValue[1].trim(); + addressMap.put(key, value); + } + } +// v.setRecipient(addressMap.get("收件人")); +// v.setPhone(addressMap.get("联系方式")); +// v.setAddress(addressMap.get("收货地址")); + } + }); ExportParams exportParams = new ExportParams(); - exportParams.setType(ExcelType.XSSF); + exportParams.setType(ExcelType.HSSF); exportParams.setSheetName(project.getName()); try { - Workbook workbook = ExcelExportUtil.exportExcel(exportParams, WelfareExportEntityTc.class, welfareExportEntityTcList); - ViTool.excelResponse(response, (project.getName() + (flag ? "已选名单" : "未选名单")) + ".xlsx"); + ViTool.excelResponse(response, (project.getName() + (flag ? "已选名单" : "未选名单")) + ".xls"); + Workbook workbook = new HSSFWorkbook(); + ExcelExportService service = new ExcelExportService(); + service.createSheet(workbook, exportParams, WelfareExportEntityTc.class, welfareExportEntityTcList); ServletOutputStream outputStream = response.getOutputStream(); workbook.write(outputStream); - outputStream.close(); + + +// Workbook workbook = ExcelExportUtil.exportExcel(exportParams, WelfareExportEntityTc.class, welfareExportEntityTcList); +// ServletOutputStream outputStream = response.getOutputStream(); +// workbook.write(outputStream); +// outputStream.close(); } catch (IOException e) { e.printStackTrace(); } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index c530690..551a601 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -47,7 +47,7 @@ jdbc.defaultAutoCommit=true xsssql.ignore.urls=/platform/cms/content/article/addDo,/platform/sys/app/conf/addDo,/platform/sys/app/conf/editDo,\ /platform/member/change/mange/userPageData,/platform/welfare/member/mange/userPageData,/platform/sys/task/cronExp,\ /platform/sys/task/editDo,/platform/sys/task/addDo,/platform/fellowship/manage/activity/doHandle,/platform/sys/menu/editMenuDo,\ - /platform/trainSingUp/manage/activity/doHandle + /platform/trainSingUp/manage/activity/doHandle,/platform/activity/school/info/mange/doAdd,/platform/activity/school/info/mange/doEdit #环境 dev/prod v.environment=dev v.loginUrl=/sso/login @@ -78,7 +78,7 @@ shiro.url.login=/platform shiro.url.logout_redirect=/platform shiro.url.unauth=/platform #开发时设置本地路径,便于调试 -beetl.RESOURCE.rootLocal=G:/zhgh/zhgh_hrbnu/src/main/resources/views/ +beetl.RESOURCE.rootLocal=G:/zhgh/ /src/main/resources/views/ beetl.RESOURCE.root=views/ beetl.DELIMITER_STATEMENT_START= @@ -143,5 +143,15 @@ logback.exts.loglevel.enabled=true #心跳间隔(单位:秒) logback.exts.loglevel.heartbeat=15 +wxpay.appId=\u5E94\u7528\u7F16\u53F7 +wxpay.keyPath=key.pem +wxpay.certPath=cert.pem +wxpay.certP12Path=cert.p12 +wxpay.platformCertPath=wx_cert.pem +wxpay.mchId=\u5FAE\u4FE1\u5546\u6237\u53F7 +wxpay.apiKey3=Api-v3 \u5BC6\u94A5 +wxpay.apiKey=Api \u5BC6\u94A5 +wxpay.domain=https://ijpay.javen.com + diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml index 8128e03..86e2312 100644 --- a/src/main/resources/logback.xml +++ b/src/main/resources/logback.xml @@ -32,9 +32,9 @@ - + - \ No newline at end of file + diff --git a/src/main/resources/static/components/sign/sign.vue b/src/main/resources/static/components/sign/sign.vue index 0e15416..25aa749 100644 --- a/src/main/resources/static/components/sign/sign.vue +++ b/src/main/resources/static/components/sign/sign.vue @@ -84,8 +84,17 @@ module.exports = { clearInterval(signatureInterval) const ts = new Date().getTime() + (Math.floor(Math.random() * (1000 - 1 + 1)) + 1).toString() console.log(ts) - // this.postAddress = location.protocol + '//' + location.host + '/signature?prefix=' + this.prefix + '&id=' + ts + "&is_value_base64=" + this.is_value_base64 - this.postAddress = "https://zhgh.hrbnu.edu.cn/signature?prefix=" + this.prefix + "&id=" + ts + "&is_value_base64=" + this.is_value_base64 + this.postAddress = + location.protocol + + "//" + + location.host + + "/signature?prefix=" + + this.prefix + + "&id=" + + ts + + "&is_value_base64=" + + this.is_value_base64 + // this.postAddress = "https://zhgh.hrbnu.edu.cn/signature?prefix=" + this.prefix + "&id=" + ts + "&is_value_base64=" + this.is_value_base64 this.showQrCode = true diff --git a/src/main/resources/views/layouts/platform.html b/src/main/resources/views/layouts/platform.html index 03123ce..95ec4c3 100644 --- a/src/main/resources/views/layouts/platform.html +++ b/src/main/resources/views/layouts/platform.html @@ -101,7 +101,6 @@ - @@ -109,6 +108,7 @@ + diff --git a/src/main/resources/views/mobile/memberCost/query/index.html b/src/main/resources/views/mobile/memberCost/query/index.html new file mode 100644 index 0000000..6f61605 --- /dev/null +++ b/src/main/resources/views/mobile/memberCost/query/index.html @@ -0,0 +1,16 @@ + +
+ + diff --git a/src/main/resources/views/mobile/welfare/list/receive.html b/src/main/resources/views/mobile/welfare/list/receive.html index 63d0f47..f871108 100644 --- a/src/main/resources/views/mobile/welfare/list/receive.html +++ b/src/main/resources/views/mobile/welfare/list/receive.html @@ -16,11 +16,13 @@ layout("/mobile/platform.html"){ border-bottom: 1px dashed lightgrey; } - .selection .van-checkbox-group .van-cell, .selection .van-radio-group .van-cell { + .selection .van-checkbox-group .van-cell, + .selection .van-radio-group .van-cell { flex-direction: row-reverse; } - .selection .van-checkbox-group .van-cell .van-cell__title, .selection .van-radio-group .van-cell .van-cell__title { + .selection .van-checkbox-group .van-cell .van-cell__title, + .selection .van-radio-group .van-cell .van-cell__title { padding-left: 20px; } @@ -41,7 +43,6 @@ layout("/mobile/platform.html"){ } .van-collapse-item .van-collapse-item__title { - } .selection .van-radio { @@ -59,7 +60,9 @@ layout("/mobile/platform.html"){ height: 80px; } - .welfare_img .van-image__error, .welfare_img .van-image__img, .welfare_img .van-image__loading { + .welfare_img .van-image__error, + .welfare_img .van-image__img, + .welfare_img .van-image__loading { border-radius: 10px; margin-left: -35px; } @@ -115,7 +118,7 @@ layout("/mobile/platform.html"){ padding-left: 20px; padding-right: 10px; position: relative; - height: 100px + height: 100px; } .optionDesc { @@ -132,142 +135,143 @@ layout("/mobile/platform.html"){ border: 1pt solid #000000 !important; } + .van-submit-bar__button { + width: 150px; + } + + .custom-cell { + font-size: 18px; + font-weight: bold; + }
- + - +
-
- 配送至 -
+
配送至
- - - + + - + + :options="dzOptions" + :props="{ expandTrigger: 'hover' }" + @change="handleChange" + clearable + placeholder="请选择地址信息" + style="width: 100%" + v-model="formData.addressList" + > - - + + - - + + - - + + + + + + + + - 取 消 - 保存 - + 取 消 + 保存 + -
- - diff --git a/src/main/resources/views/platform/welfare/mine.html b/src/main/resources/views/platform/welfare/mine.html index 3b1dc3f..a58078a 100644 --- a/src/main/resources/views/platform/welfare/mine.html +++ b/src/main/resources/views/platform/welfare/mine.html @@ -25,26 +25,24 @@ layout("/layouts/platform.html"){ font-size: 13px; color: #868282; } - -
- - + - + - - + + {{item.optionName}} - 未评价 + 未评价 - -
- +
+
- - + 关 闭 - 提 交 - + 提 交 + - +
- + + :color="item.color" + :key="index" + :timestamp="moment().format('YYYY-MM-DD HH:mm:ss')" + v-for="(item, index) in logisticsTrace.logisticsTraceDetailList" + > {{item.desc}} - - @@ -353,7 +296,7 @@ layout("/layouts/platform.html"){
diff --git a/src/main/resources/views/platform/welfare/statistics/single.html b/src/main/resources/views/platform/welfare/statistics/single.html index 390ae0c..5ad2182 100644 --- a/src/main/resources/views/platform/welfare/statistics/single.html +++ b/src/main/resources/views/platform/welfare/statistics/single.html @@ -65,6 +65,20 @@ layout("/layouts/platform.html"){
+
+
人员类型:
+
+ +
+
+
搜索
@@ -86,7 +100,7 @@ layout("/layouts/platform.html"){ type="primary" v-if="judgmentAuthority" > - 导出各基层工会福利签领表 + 导出各分工会福利签领表 按品牌导出全部(蛋糕券) --> -