diff --git a/nxhs-service/pom.xml b/nxhs-service/pom.xml index 4de1c4f..a1ff981 100644 --- a/nxhs-service/pom.xml +++ b/nxhs-service/pom.xml @@ -48,6 +48,7 @@ de.codecentric spring-boot-admin-starter-client + @@ -71,6 +72,29 @@ + + + + src/main/resources + + application.yml + application-${environment}.yml + logback-${environment}.xml + + true + + + + src/main/resources + + apiclient_cert.pem + apiclient_key.pem + wxpay_v3.properties + nxhs.jks + + false + + \ No newline at end of file diff --git a/nxhs-service/src/main/java/cc/yunxi/controller/TestController.java b/nxhs-service/src/main/java/cc/yunxi/controller/TestController.java index 02e67f8..13a9dad 100644 --- a/nxhs-service/src/main/java/cc/yunxi/controller/TestController.java +++ b/nxhs-service/src/main/java/cc/yunxi/controller/TestController.java @@ -2,10 +2,26 @@ package cc.yunxi.controller; import cc.yunxi.common.domain.CommonResult; import cc.yunxi.common.exception.BadRequestException; +import cc.yunxi.common.exception.BizIllegalException; +import cc.yunxi.config.props.WxPayV3Properties; import cc.yunxi.domain.query.TestQuery; import cc.yunxi.enums.UserTypeEnum; import cc.yunxi.service.ITestService; +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONUtil; import cn.hutool.log.Log; +import com.ijpay.core.IJPayHttpResponse; +import com.ijpay.core.enums.RequestMethodEnum; +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.TransferApiEnum; +import com.ijpay.wxpay.model.TransferModel; +import com.ijpay.wxpay.model.v3.BatchTransferModel; +import com.ijpay.wxpay.model.v3.TransferDetailInput; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.RequiredArgsConstructor; @@ -14,6 +30,9 @@ import org.springframework.scheduling.annotation.Async; import org.springframework.util.concurrent.ListenableFuture; import org.springframework.web.bind.annotation.*; +import javax.annotation.Resource; +import java.security.cert.X509Certificate; +import java.util.Collections; import java.util.concurrent.ExecutionException; @Api(tags = "测试接口") @@ -25,6 +44,9 @@ public class TestController { private final ITestService testService; + @Resource + private WxPayV3Properties wxPayV3Properties; + @ApiOperation("测试接口成功") @GetMapping("/test01") public CommonResult success() { @@ -71,4 +93,58 @@ public class TestController { } return CommonResult.success("数据处理完成"); } + + @ApiOperation(value = "测试支付", hidden = true) + @GetMapping("/tQ7lA2mG9f") + public CommonResult wxCash(@RequestParam("openid") String openid, @RequestParam("amount") Integer amount) throws Exception { +// String openId = "oYkV86-mE9DakrcP5us474KscefQ"; + BatchTransferModel batchTransferModel = new BatchTransferModel() + .setAppid(wxPayV3Properties.getAppId()) + .setOut_batch_no(PayKit.generateStr()) + .setBatch_name("测试商户转账到零钱") + .setBatch_remark("测试商户转账到零钱") + .setTotal_amount(amount) + .setTotal_num(1) + .setTransfer_detail_list(Collections.singletonList( + new TransferDetailInput() + .setOut_detail_no(PayKit.generateStr()) + .setTransfer_amount(amount) + .setTransfer_remark("测试商户转账到零钱") + .setOpenid(openid))); + + log.info("发起商家转账请求参数 {}", JSONUtil.toJsonStr(batchTransferModel)); + // 删除 + IJPayHttpResponse response = WxPayApi.v3( + RequestMethodEnum.POST, + WxDomainEnum.CHINA.toString(), + TransferApiEnum.TRANSFER_BATCHES.toString(), + wxPayV3Properties.getMchId(), + getSerialNumber(), + null, + wxPayV3Properties.getKeyPath(), + JSONUtil.toJsonStr(batchTransferModel) + ); + log.info("发起商家转账响应 {}", response); + if (response.getStatus() != 200) { + log.warn("提现失败: {}", response.getBody()); + throw new BizIllegalException("提现失败"); + } + return CommonResult.success(response.getBody()); + } + + + // 商户API证书序列号 + private String getSerialNumber() { + // 获取证书序列号 + X509Certificate certificate = PayKit.getCertificate(wxPayV3Properties.getCertPath()); + if (certificate == null) { + throw new BizIllegalException("商户证书序列号获取失败!"); + } + String serialNo = certificate.getSerialNumber().toString(16).toUpperCase(); + // 提前两天检查证书是否有效 + boolean isValid = PayKit.checkCertificateIsValid(certificate, wxPayV3Properties.getMchId(), -2); + log.info("证书是否可用 {} 证书有效期为 {}", isValid, DateUtil.format(certificate.getNotAfter(), DatePattern.NORM_DATETIME_PATTERN)); + return serialNo; + } + } diff --git a/nxhs-service/src/main/java/cc/yunxi/service/impl/ClientServiceImpl.java b/nxhs-service/src/main/java/cc/yunxi/service/impl/ClientServiceImpl.java index 83e80f4..01fe79b 100644 --- a/nxhs-service/src/main/java/cc/yunxi/service/impl/ClientServiceImpl.java +++ b/nxhs-service/src/main/java/cc/yunxi/service/impl/ClientServiceImpl.java @@ -177,22 +177,23 @@ public class ClientServiceImpl extends ServiceImpl impleme @Override @Transactional(rollbackFor = Exception.class) public void cashBalance(String openId, Integer amount) throws Exception { - // 模拟提现成功 this.changeBalance(openId, new BigDecimal(amount), null, null, BalanceChangeTypeEnum.CASH_OUT); - /* BatchTransferModel batchTransferModel = new BatchTransferModel() + // 微信提现(单位:分) + amount = amount * 100; + BatchTransferModel batchTransferModel = new BatchTransferModel() .setAppid(wxPayV3Properties.getAppId()) .setOut_batch_no(PayKit.generateStr()) - .setBatch_name("测试商户转账到零钱") - .setBatch_remark("测试商户转账到零钱") + .setBatch_name("提现到零钱") + .setBatch_remark("提现到零钱") .setTotal_amount(amount) .setTotal_num(1) .setTransfer_detail_list(Collections.singletonList( new TransferDetailInput() .setOut_detail_no(PayKit.generateStr()) - .setTransfer_amount(1) - .setTransfer_remark("测试商户转账到零钱") - .setOpenid(openId))); - + .setTransfer_amount(amount) + .setTransfer_remark("提现到零钱") + .setOpenid(openId)) + ); log.info("发起商家转账请求参数 {}", JSONUtil.toJsonStr(batchTransferModel)); // 删除 IJPayHttpResponse response = WxPayApi.v3( @@ -206,8 +207,8 @@ public class ClientServiceImpl extends ServiceImpl impleme JSONUtil.toJsonStr(batchTransferModel) ); log.info("发起商家转账响应 {}", response); -// 根据证书序列号查询对应的证书来验证签名结果 - boolean verifySignature = WxPayKit.verifySignature(response, wxPayV3Properties.getPlatformCertPath()); +// 验证签名不校验 +// boolean verifySignature = WxPayKit.verifySignature(response, wxPayV3Properties.getPlatformCertPath()); // log.info("verifySignature: {}", verifySignature); // if (response.getStatus() == OK && verifySignature) { // return response.getBody(); @@ -215,7 +216,7 @@ public class ClientServiceImpl extends ServiceImpl impleme if (response.getStatus() != OK) { throw new BizIllegalException("提现失败"); } -// return response.getBody(); */ +// return response.getBody(); } @@ -282,7 +283,7 @@ public class ClientServiceImpl extends ServiceImpl impleme accountBill.setAccountBalance(fund); accountBill.setPayoutAmount(amount); accountBill.setOrderNumber(orderNo); - accountBill.setRemark("支付给散户"+ amountStr + "元"); + accountBill.setRemark("支付给散户" + amountStr + "元"); accountBill.setCreatorTime(now); accountBillMapper.insert(accountBill); @@ -291,7 +292,7 @@ public class ClientServiceImpl extends ServiceImpl impleme throw new BizIllegalException("余额不足"); } balance = balance.subtract(amount); - remark = "微信提现" + amountStr + "元"; + remark = "微信提现" + amountStr + "元"; } // 更新散户余额 client.setBanlance(balance); diff --git a/nxhs-service/src/main/resources/application-dev.yml b/nxhs-service/src/main/resources/application-dev.yml index 24e8843..1125462 100644 --- a/nxhs-service/src/main/resources/application-dev.yml +++ b/nxhs-service/src/main/resources/application-dev.yml @@ -12,3 +12,12 @@ spring: host: 222.71.165.188 port: 6379 password: qweasd,.123 # 密码为空时,请将本行注释 + +logging: + config: classpath:logback-dev.xml + level: + cc.yunxi: debug + pattern: + dateformat: yyyy-MM-dd HH:mm:ss:SSS + file: + path: "${user.dir}/logs/${spring.application.name}" diff --git a/nxhs-service/src/main/resources/application-pro.yml b/nxhs-service/src/main/resources/application-prod.yml similarity index 67% rename from nxhs-service/src/main/resources/application-pro.yml rename to nxhs-service/src/main/resources/application-prod.yml index 71eb02f..426488a 100644 --- a/nxhs-service/src/main/resources/application-pro.yml +++ b/nxhs-service/src/main/resources/application-prod.yml @@ -12,3 +12,12 @@ spring: host: 127.0.0.1 port: 6379 password: yx0818 # 密码为空时,请将本行注释 + +logging: + config: classpath:logback-prod.xml + level: + cc.yunxi: debug + pattern: + dateformat: yyyy-MM-dd HH:mm:ss:SSS + file: + path: "${user.dir}/logs/${spring.application.name}" diff --git a/nxhs-service/src/main/resources/application.yml b/nxhs-service/src/main/resources/application.yml index e5f8874..c03791a 100644 --- a/nxhs-service/src/main/resources/application.yml +++ b/nxhs-service/src/main/resources/application.yml @@ -27,13 +27,13 @@ info: spring: application: name: nxhs-service + profiles: + active: '@environment@' servlet: multipart: #文件传输配置 max-file-size: 100MB #单个数据大小限制 max-request-size: 100MB #请求总数据大小限制 enabled: true #是否启用分段上传支持 - profiles: - active: dev boot: admin: client: @@ -71,15 +71,6 @@ mybatis-plus: id-type: auto type-aliases-package: cc.yunxi.domain.po # 指定实体对象扫描包, 简化xml中resultType路径 -logging: - level: - cc.yunxi: debug - pattern: - dateformat: yyyy-MM-dd HH:mm:ss:SSS - file: - path: "${user.dir}/logs/${spring.application.name}" - name: "${logging.file.path}/log_debug.log" - knife4j: enable: true openapi: diff --git a/nxhs-service/src/main/resources/logback-spring.xml b/nxhs-service/src/main/resources/logback-dev.xml similarity index 92% rename from nxhs-service/src/main/resources/logback-spring.xml rename to nxhs-service/src/main/resources/logback-dev.xml index 568d2fc..a767c42 100644 --- a/nxhs-service/src/main/resources/logback-spring.xml +++ b/nxhs-service/src/main/resources/logback-dev.xml @@ -179,29 +179,16 @@ - - - - + - - - - - - - - - - - - - - - - - - - + + + + + + + + + diff --git a/nxhs-service/src/main/resources/logback-prod.xml b/nxhs-service/src/main/resources/logback-prod.xml new file mode 100644 index 0000000..a767c42 --- /dev/null +++ b/nxhs-service/src/main/resources/logback-prod.xml @@ -0,0 +1,194 @@ + + + + + + + logback + + + + + + + + + debug + + + ${CONSOLE_LOG_PATTERN} + + UTF-8 + + + + + + + + + + ${log.path}/log_debug.log + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n + UTF-8 + + + + + + + + ${log.path}/debug/log-debug-%d{yyyy-MM-dd_HH-mm}.%i.log + + + 100MB + + 30 + + 20GB + + + + debug + ACCEPT + DENY + + + + + + + ${log.path}/log_info.log + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n + UTF-8 + + + + + + + ${log.path}/info/log-info-%d{yyyy-MM-dd}.%i.log + + + 100MB + + 30 + + 20GB + + + + + + info + ACCEPT + DENY + + + + + + + ${log.path}/log_warn.log + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n + UTF-8 + + + + + + + ${log.path}/warn/log-warn-%d{yyyy-MM-dd}.%i.log + + + 100MB + + 30 + + 20GB + + + + warn + ACCEPT + DENY + + + + + + + + ${log.path}/log_error.log + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n + UTF-8 + + + + + + + ${log.path}/error/log-error-%d{yyyy-MM-dd}.%i.log + + + 100MB + + 30 + + 20GB + + + + ERROR + ACCEPT + DENY + + + + + + + + + + + + + + + + + + diff --git a/pom.xml b/pom.xml index 92826f1..2673241 100644 --- a/pom.xml +++ b/pom.xml @@ -98,6 +98,28 @@ + + + + + dev + + + true + + + dev + + + + + prod + + prod + + + +