From 15d223c549e0d94316db344f2f6337b605fffbae Mon Sep 17 00:00:00 2001
From: KKSU <15274802129@163.com>
Date: Tue, 16 Jan 2024 10:56:38 +0800
Subject: [PATCH] fapiao

---
 src/main/java/cc/mrbird/febs/common/properties/XcxProperties.java       |    2 
 src/main/java/cc/mrbird/febs/pay/service/WxFaPiaoService.java           |   11 +
 src/main/java/cc/mrbird/febs/mall/controller/ViewSystemController.java  |   15 ++
 src/test/java/cc/mrbird/febs/ProfitTest.java                            |   96 ++++++++++++-
 src/main/resources/application-prod.yml                                 |    1 
 src/main/resources/application-test.yml                                 |    1 
 pom.xml                                                                 |    5 
 src/main/java/cc/mrbird/febs/mall/controller/AdminSystemController.java |   57 +++++++
 src/main/java/cc/mrbird/febs/pay/controller/XcxPayController.java       |   23 +-
 src/main/resources/templates/febs/views/modules/system/faPiao.html      |   75 ++++++++++
 src/main/java/cc/mrbird/febs/common/enumerates/DataDictionaryEnum.java  |    3 
 src/main/java/cc/mrbird/febs/mall/dto/FaPiaoDto.java                    |   10 +
 src/main/java/cc/mrbird/febs/pay/model/HeaderDto.java                   |   12 +
 src/main/java/cc/mrbird/febs/common/configure/WebMvcConfigure.java      |    1 
 src/main/java/cc/mrbird/febs/pay/service/impl/WxFaPiaoServiceImpl.java  |  108 +++++++++++++++
 src/main/resources/wxP12/apiclient_cert.p12                             |    0 
 16 files changed, 396 insertions(+), 24 deletions(-)

diff --git a/pom.xml b/pom.xml
index d38c03a..3f7a5b4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -28,6 +28,11 @@
     </properties>
 
     <dependencies>
+        <dependency>
+            <groupId>com.github.wechatpay-apiv3</groupId>
+            <artifactId>wechatpay-java</artifactId>
+            <version>0.2.12</version>
+        </dependency>
         <!--        图片压缩-->
         <dependency>
             <groupId>net.coobird</groupId>
diff --git a/src/main/java/cc/mrbird/febs/common/configure/WebMvcConfigure.java b/src/main/java/cc/mrbird/febs/common/configure/WebMvcConfigure.java
index f640c22..4d0b4b3 100644
--- a/src/main/java/cc/mrbird/febs/common/configure/WebMvcConfigure.java
+++ b/src/main/java/cc/mrbird/febs/common/configure/WebMvcConfigure.java
@@ -31,5 +31,6 @@
         registration.excludePathPatterns("/api/leader/noLoginLeaderTitle");
         registration.excludePathPatterns("/api/xcxPay/wxpayCallback");
         registration.excludePathPatterns("/api/xcxPay/rechargeCallBack");
+        registration.excludePathPatterns("/api/xcxPay/fapiaoCallBack");
     }
 }
diff --git a/src/main/java/cc/mrbird/febs/common/enumerates/DataDictionaryEnum.java b/src/main/java/cc/mrbird/febs/common/enumerates/DataDictionaryEnum.java
index f8125d8..31e3827 100644
--- a/src/main/java/cc/mrbird/febs/common/enumerates/DataDictionaryEnum.java
+++ b/src/main/java/cc/mrbird/febs/common/enumerates/DataDictionaryEnum.java
@@ -5,6 +5,9 @@
 
 @Getter
 public enum DataDictionaryEnum {
+
+    // 发票的通知回调路径
+    FP_CALLBACK_URL("FP_CALLBACK_URL", "FP_CALLBACK_URL"),
     //微信订阅模板ID,
     // 微信订单通知
 //    WX_TEMPLATE_ID_ONE("WX_TEMPLATE", "WX_TEMPLATE_ID_ONE"),
diff --git a/src/main/java/cc/mrbird/febs/common/properties/XcxProperties.java b/src/main/java/cc/mrbird/febs/common/properties/XcxProperties.java
index 6393808..ca1b5e0 100644
--- a/src/main/java/cc/mrbird/febs/common/properties/XcxProperties.java
+++ b/src/main/java/cc/mrbird/febs/common/properties/XcxProperties.java
@@ -26,6 +26,8 @@
     private String wecharpayMchid;
     //支付秘钥
     private String wecharpaySecret;
+    //支付秘钥V3
+    private String wecharpaySecretV3;
     //高德KEY
     private String gaodeKey;
     //高德serviceName
diff --git a/src/main/java/cc/mrbird/febs/mall/controller/AdminSystemController.java b/src/main/java/cc/mrbird/febs/mall/controller/AdminSystemController.java
index f6444ee..bef7b04 100644
--- a/src/main/java/cc/mrbird/febs/mall/controller/AdminSystemController.java
+++ b/src/main/java/cc/mrbird/febs/mall/controller/AdminSystemController.java
@@ -3,18 +3,22 @@
 import cc.mrbird.febs.common.annotation.ControllerEndpoint;
 import cc.mrbird.febs.common.entity.FebsResponse;
 import cc.mrbird.febs.common.enumerates.DataDictionaryEnum;
-import cc.mrbird.febs.mall.dto.AdminAgentAmountDto;
-import cc.mrbird.febs.mall.dto.AdminAgentDetailDto;
-import cc.mrbird.febs.mall.dto.AdminIndexVideoDto;
-import cc.mrbird.febs.mall.dto.CashOutSettingDto;
+import cc.mrbird.febs.mall.dto.*;
 import cc.mrbird.febs.mall.entity.DataDictionaryCustom;
 import cc.mrbird.febs.mall.mapper.DataDictionaryCustomMapper;
 import cc.mrbird.febs.mall.service.ICommonService;
 import cc.mrbird.febs.mall.service.ISystemService;
+import cc.mrbird.febs.pay.model.HeaderDto;
+import cc.mrbird.febs.pay.service.WxFaPiaoService;
 import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.json.JSONUtil;
 import com.alibaba.fastjson.JSONObject;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.commons.httpclient.methods.RequestEntity;
+import org.apache.commons.httpclient.methods.StringRequestEntity;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.PostMapping;
@@ -22,7 +26,9 @@
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
+import java.io.IOException;
 import java.math.BigDecimal;
+import java.security.KeyPair;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
@@ -39,6 +45,7 @@
 
     private final ICommonService commonService;
     private final DataDictionaryCustomMapper dataDictionaryCustomMapper;
+    private final WxFaPiaoService wxFaPiaoService;
 
     @PostMapping(value = "/bonusSystemSetting")
     public FebsResponse bonusSystemSetting(@RequestBody Map<String, Object> map) {
@@ -122,6 +129,48 @@
         return new FebsResponse().success().message("操作成功");
     }
 
+    @PostMapping(value = "/faPiaoSet")
+    public FebsResponse faPiaoSet(FaPiaoDto faPiaoDto) {
+        dataDictionaryCustomMapper.updateDicValueByTypeAndCode(
+                DataDictionaryEnum.FP_CALLBACK_URL.getType(),
+                DataDictionaryEnum.FP_CALLBACK_URL.getCode(),
+                faPiaoDto.getCallbackUrl()
+        );
+        KeyPair privateKey = wxFaPiaoService.getPrivateKey();
+        HeaderDto headerDto = new HeaderDto();
+        headerDto.setCallback_url(faPiaoDto.getCallbackUrl());
+        headerDto.setShow_fapiao_cell(false);
+        String parseObj = JSONUtil.parseObj(headerDto).toString();
+        String baseUrl = "https://api.mch.weixin.qq.com";
+        String canonicalUrl = "/v3/new-tax-control-fapiao/merchant/development-config";
+        String postStr = wxFaPiaoService.createAuthorization(
+                "POST",
+                canonicalUrl,
+                parseObj,
+                privateKey
+        );
+        // 创建httppost
+        try {
+            HttpClient httpClient = new HttpClient();
+            PostMethod post = new PostMethod(baseUrl+canonicalUrl);
+            post.setRequestHeader("Accept", "application/json");
+            post.setRequestHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36");
+            post.setRequestHeader("Content-Type", "application/json");
+            post.setRequestHeader("Connection", "keep-alive");
+            post.setRequestHeader("Authorization",  "WECHATPAY2-SHA256-RSA2048 "+postStr);
+            RequestEntity entity = new StringRequestEntity(parseObj, "text/html", "utf-8");
+            post.setRequestEntity(entity);
+            httpClient.executeMethod(post);
+            String responseBodyAsString = post.getResponseBodyAsString();
+            cn.hutool.json.JSONObject maps = JSONUtil.parseObj(responseBodyAsString);
+            System.out.println(maps);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+        return new FebsResponse().success().message("操作成功");
+    }
+
     @PostMapping(value = "/agentDetail")
     public FebsResponse agentDetail(AdminAgentDetailDto adminAgentDetailDto) {
         DataDictionaryCustom dic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
diff --git a/src/main/java/cc/mrbird/febs/mall/controller/ViewSystemController.java b/src/main/java/cc/mrbird/febs/mall/controller/ViewSystemController.java
index ff3fdea..e678562 100644
--- a/src/main/java/cc/mrbird/febs/mall/controller/ViewSystemController.java
+++ b/src/main/java/cc/mrbird/febs/mall/controller/ViewSystemController.java
@@ -99,4 +99,19 @@
         model.addAttribute("indexVideoSet", adminIndexVideoDto);
         return FebsUtil.view("modules/system/indexVideo");
     }
+
+
+
+    @GetMapping("faPiao")
+    @RequiresPermissions("faPiao:update")
+    public String faPiao(Model model) {
+        FaPiaoDto faPiaoDto = new FaPiaoDto();
+        DataDictionaryCustom dic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(DataDictionaryEnum.FP_CALLBACK_URL.getType(),
+                DataDictionaryEnum.FP_CALLBACK_URL.getCode());
+        if (dic != null) {
+            faPiaoDto.setCallbackUrl(dic.getValue());
+        }
+        model.addAttribute("faPiaoDto", faPiaoDto);
+        return FebsUtil.view("modules/system/faPiao");
+    }
 }
diff --git a/src/main/java/cc/mrbird/febs/mall/dto/FaPiaoDto.java b/src/main/java/cc/mrbird/febs/mall/dto/FaPiaoDto.java
new file mode 100644
index 0000000..e13c2b4
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/mall/dto/FaPiaoDto.java
@@ -0,0 +1,10 @@
+package cc.mrbird.febs.mall.dto;
+
+import io.swagger.annotations.ApiModel;
+import lombok.Data;
+
+@Data
+@ApiModel(value = "DeliverGoodsDto", description = "接收参数类")
+public class FaPiaoDto {
+    private String callbackUrl;
+}
diff --git a/src/main/java/cc/mrbird/febs/pay/controller/XcxPayController.java b/src/main/java/cc/mrbird/febs/pay/controller/XcxPayController.java
index 2dcefa6..6830a9f 100644
--- a/src/main/java/cc/mrbird/febs/pay/controller/XcxPayController.java
+++ b/src/main/java/cc/mrbird/febs/pay/controller/XcxPayController.java
@@ -12,12 +12,7 @@
 import cc.mrbird.febs.mall.service.IApiMallMemberWalletService;
 import cc.mrbird.febs.mall.service.IMallMoneyFlowService;
 import cc.mrbird.febs.pay.model.NotifyData;
-import cc.mrbird.febs.pay.model.OrderStateDto;
-import cc.mrbird.febs.pay.model.OrderStateMsgVo;
-import cc.mrbird.febs.pay.model.WxTemplateData;
-import cc.mrbird.febs.pay.service.IPayService;
 import cc.mrbird.febs.pay.service.IXcxPayService;
-import cc.mrbird.febs.pay.util.PayThreadPool;
 import cc.mrbird.febs.pay.util.Signature;
 import cc.mrbird.febs.pay.util.Util;
 import cc.mrbird.febs.pay.util.WechatConfigure;
@@ -26,17 +21,12 @@
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.json.JSONObject;
 import cn.hutool.json.JSONUtil;
-import io.swagger.annotations.ApiOperation;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.ResponseEntity;
 import org.springframework.transaction.annotation.Transactional;
-import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
-import org.springframework.web.client.RestTemplate;
-import org.thymeleaf.engine.TemplateData;
 
 import javax.servlet.ServletOutputStream;
 import javax.servlet.http.HttpServletRequest;
@@ -247,6 +237,19 @@
 //        System.out.println(rechargeNo);
 //    }
     /**
+     * 微信电子发票回调接口
+     * @return
+     */
+    @Transactional(rollbackFor = Exception.class)
+    @RequestMapping(value = "/fapiaoCallBack")
+    public Map<Object, Object> fapiaoCallBack(HttpServletResponse response, HttpServletRequest request) throws IOException {
+        log.info("微信电子发票回调接口....");
+        Map<Object, Object> objectObjectHashMap = new HashMap<>();
+        objectObjectHashMap.put("code","SUCCESS");
+        objectObjectHashMap.put("message","");
+        return objectObjectHashMap;
+    }
+    /**
      * 微信支付回调接口
      */
     @Transactional(rollbackFor = Exception.class)
diff --git a/src/main/java/cc/mrbird/febs/pay/model/HeaderDto.java b/src/main/java/cc/mrbird/febs/pay/model/HeaderDto.java
new file mode 100644
index 0000000..9a0712a
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/pay/model/HeaderDto.java
@@ -0,0 +1,12 @@
+package cc.mrbird.febs.pay.model;
+
+import com.sun.org.apache.xpath.internal.operations.Bool;
+import lombok.Data;
+
+@Data
+public class HeaderDto {
+
+    private String callback_url;
+
+    private boolean show_fapiao_cell;
+}
diff --git a/src/main/java/cc/mrbird/febs/pay/service/WxFaPiaoService.java b/src/main/java/cc/mrbird/febs/pay/service/WxFaPiaoService.java
new file mode 100644
index 0000000..960e8e2
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/pay/service/WxFaPiaoService.java
@@ -0,0 +1,11 @@
+package cc.mrbird.febs.pay.service;
+
+import java.security.KeyPair;
+
+public interface WxFaPiaoService {
+
+    String createAuthorization(String method, String canonicalUrl, String body, KeyPair keyPair);//生成Token
+
+    KeyPair getPrivateKey();//通过证书获取私钥公钥
+
+}
diff --git a/src/main/java/cc/mrbird/febs/pay/service/impl/WxFaPiaoServiceImpl.java b/src/main/java/cc/mrbird/febs/pay/service/impl/WxFaPiaoServiceImpl.java
new file mode 100644
index 0000000..a35aa8d
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/pay/service/impl/WxFaPiaoServiceImpl.java
@@ -0,0 +1,108 @@
+package cc.mrbird.febs.pay.service.impl;
+
+import cc.mrbird.febs.common.properties.XcxProperties;
+import cc.mrbird.febs.common.utils.SpringContextHolder;
+import cc.mrbird.febs.pay.service.WxFaPiaoService;
+import cc.mrbird.febs.pay.util.RandomStringGenerator;
+import lombok.RequiredArgsConstructor;
+import lombok.SneakyThrows;
+import lombok.extern.slf4j.Slf4j;
+import okhttp3.HttpUrl;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.stereotype.Service;
+import org.springframework.util.Base64Utils;
+
+import java.io.*;
+import java.nio.charset.StandardCharsets;
+import java.security.*;
+import java.security.cert.X509Certificate;
+import java.util.Map;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class WxFaPiaoServiceImpl implements WxFaPiaoService {
+
+    private final XcxProperties xcxProperties = SpringContextHolder.getBean(XcxProperties.class);
+
+    @Override
+    public String createAuthorization(String method, String canonicalUrl, String body, KeyPair keyPair) {
+        String nonceStr = RandomStringGenerator.getRandomStringByLength(32);//随机字符串
+        long timestamp = System.currentTimeMillis() / 1000;//时间戳
+        String signature = sign(method, canonicalUrl, timestamp, nonceStr, body, keyPair);//签名加密
+        return "mchid=\"" + xcxProperties.getWecharpayMchid() + "\","
+                + "nonce_str=\"" + nonceStr + "\","
+                + "timestamp=\"" + timestamp + "\","
+                + "serial_no=\"" + "50F37206347BCC9E6AC9860DAACE52AC035F7C24" + "\","//证书序列号
+                + "signature=\"" + signature + "\"";
+    }
+
+    @Override
+    public KeyPair getPrivateKey() {
+        return createPKCS12("Tenpay Certificate", "1658958205");
+    }
+    /**
+     * V3  SHA256withRSA 签名.
+     *
+     * @param method       请求方法  GET  POST PUT DELETE 等
+     * @param canonicalUrl 例如  https://api.mch.weixin.qq.com/v3/pay/transactions/app?version=1 ——> /v3/pay/transactions/app?version=1
+     * @param timestamp    当前时间戳   因为要配置到TOKEN 中所以 签名中的要跟TOKEN 保持一致
+     * @param nonceStr     随机字符串  要和TOKEN中的保持一致
+     * @param body         请求体 GET 为 "" POST 为JSON
+     * @param keyPair      商户API 证书解析的密钥对  实际使用的是其中的私钥
+     * @return the string
+     */
+    @SneakyThrows
+    public String sign(String method, String canonicalUrl, long timestamp, String nonceStr, String body, KeyPair keyPair)  {
+        String signatureStr = Stream.of(method, canonicalUrl, String.valueOf(timestamp), nonceStr, body)
+                .collect(Collectors.joining("\n", "", "\n"));
+        Signature sign = Signature.getInstance("SHA256withRSA");
+        sign.initSign(keyPair.getPrivate());
+        sign.update(signatureStr.getBytes(StandardCharsets.UTF_8));
+        return Base64Utils.encodeToString(sign.sign());
+    }
+
+    /**
+     * 获取公私钥.通过证书
+     */
+    private KeyStore store;
+    private final Object lock = new Object();
+    public KeyPair createPKCS12(String keyAlias, String keyPass) {
+        ClassPathResource resource = new ClassPathResource(xcxProperties.getCertLocalPath());
+//        File file = new File("src/main/resources/wxP12/apiclient_cert.p12");
+        char[] pem = keyPass.toCharArray();
+        try {
+            synchronized (lock) {
+                if (store == null) {
+                    synchronized (lock) {
+                        store = KeyStore.getInstance("PKCS12");
+                        store.load(resource.getInputStream(), pem);
+//                        store.load(new FileInputStream(file), pem);
+                    }
+                }
+            }
+            X509Certificate certificate = (X509Certificate) store.getCertificate(keyAlias);
+            certificate.checkValidity();
+            // 证书的序列号 也有用 50F37206347BCC9E6AC9860DAACE52AC035F7C24
+            String serialNumber = certificate.getSerialNumber().toString(16).toUpperCase();
+            // 证书的 公钥
+            PublicKey publicKey = certificate.getPublicKey();
+            // 证书的私钥
+            PrivateKey storeKey = (PrivateKey) store.getKey(keyAlias, pem);
+            return new KeyPair(publicKey, storeKey);
+        } catch (Exception e) {
+            throw new IllegalStateException("Cannot load keys from store: " , e);
+        }
+    }
+
+    public static void main(String[] args) {
+        try {
+            System.out.println(new ClassPathResource("wxP12/apiclient_cert.p12").getFile().exists());
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+}
diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml
index d5cbbf0..af5002d 100644
--- a/src/main/resources/application-prod.yml
+++ b/src/main/resources/application-prod.yml
@@ -69,6 +69,7 @@
   certLocalPath: /home/blnkaCert/apiclient_cert.p12
   wecharpayMchid: 1658958205
   wecharpaySecret: daL341aN5orDt13puXadsAf2rpuXdq4r
+  wecharpaySecretV3: daL341aN5orDt13puXadsAf2rpuX12v3
   gaodeKey: 95ede7157929f5f6b6c758971be924b1
   serviceName: yiyuanshucai
 
diff --git a/src/main/resources/application-test.yml b/src/main/resources/application-test.yml
index 3e54b1d..0b43a6e 100644
--- a/src/main/resources/application-test.yml
+++ b/src/main/resources/application-test.yml
@@ -78,6 +78,7 @@
   certLocalPath: /home/blnkaCert/apiclient_cert.p12
   wecharpayMchid: 1658958205
   wecharpaySecret: daL341aN5orDt13puXadsAf2rpuXdq4r
+  wecharpaySecretV3: daL341aN5orDt13puXadsAf2rpuX12v3
   gaodeKey: 95ede7157929f5f6b6c758971be924b1
   serviceName: yiyuanshucai
 
diff --git a/src/main/resources/templates/febs/views/modules/system/faPiao.html b/src/main/resources/templates/febs/views/modules/system/faPiao.html
new file mode 100644
index 0000000..d12dcaf
--- /dev/null
+++ b/src/main/resources/templates/febs/views/modules/system/faPiao.html
@@ -0,0 +1,75 @@
+<div class="layui-fluid layui-anim febs-anim" id="fa-piao-set" lay-title="发票回调地址设置">
+    <div class="layui-row layui-col-space8 febs-container">
+        <form class="layui-form" action="" lay-filter="fa-piao-set-form">
+            <div class="layui-card">
+                <div class="layui-card-body">
+<!--                    <div class="layui-form-item">-->
+<!--                        <blockquote class="layui-elem-quote blue-border">是否</blockquote>-->
+<!--                        <label class="layui-form-label">充值送金额:</label>-->
+<!--                        <div class="layui-input-block">-->
+<!--                            <input type="radio" name="giveState" value="1" title="开启" lay-filter="giveStateOpen" />-->
+<!--                            <input type="radio" name="giveState" value="2" title="关闭" lay-filter="giveStateOpen" checked/>-->
+<!--                        </div>-->
+<!--                    </div>-->
+                    <div class="layui-form-item activityBulletin-input  febs-hide">
+                        <label class="layui-form-label">回调地址:</label>
+                        <div class="layui-input-block">
+                            <input id="callbackUrl" type="text" name="callbackUrl" placeholder="" autocomplete="off" class="layui-input">
+                            <div class="layui-form-mid layui-word-aux">收取微信的授权通知、开票通知、插卡通知等相关通知。</div>
+                        </div>
+                    </div>
+                </div>
+                <div class="layui-card-footer">
+                    <button class="layui-btn layui-btn-normal" lay-submit="" lay-filter="fa-piao-set-form-submit" id="submit">保存</button>
+                </div>
+            </div>
+        </form>
+    </div>
+</div>
+<style>
+    .layui-form-label {
+        width: 120px;
+    }
+
+    .layui-form-item .layui-input-block {
+        margin-left: 150px;
+    }
+
+    .layui-table-form .layui-form-item {
+        margin-bottom: 20px !important;
+    }
+</style>
+<script data-th-inline="javascript" type="text/javascript">
+    layui.use(['dropdown', 'jquery', 'validate', 'febs', 'form', 'eleTree'], function () {
+        var $ = layui.jquery,
+            febs = layui.febs,
+            form = layui.form,
+            faPiaoDto = [[${faPiaoDto}]],
+            validate = layui.validate,
+            $view = $('#fa-piao-set');
+
+        form.verify(validate);
+
+        initFPValue();
+
+        form.render();
+
+        function initFPValue() {
+            form.val("fa-piao-set-form", {
+                "callbackUrl": faPiaoDto.callbackUrl,
+            });
+        }
+        form.on('submit(fa-piao-set-form-submit)', function (data) {
+            console.log(data);
+            febs.post(ctx + 'admin/system/faPiaoSet', data.field, function (res) {
+                if (res.code == 200) {
+                    febs.alert.success(res.message);
+                } else {
+                    febs.alert.warn(res.message);
+                }
+            });
+            // window.location.reload();
+            return false;
+        });
+    });
+</script>
\ No newline at end of file
diff --git a/src/main/resources/wxP12/apiclient_cert.p12 b/src/main/resources/wxP12/apiclient_cert.p12
new file mode 100644
index 0000000..bf33845
--- /dev/null
+++ b/src/main/resources/wxP12/apiclient_cert.p12
Binary files differ
diff --git a/src/test/java/cc/mrbird/febs/ProfitTest.java b/src/test/java/cc/mrbird/febs/ProfitTest.java
index 93719a9..817e62a 100644
--- a/src/test/java/cc/mrbird/febs/ProfitTest.java
+++ b/src/test/java/cc/mrbird/febs/ProfitTest.java
@@ -12,8 +12,11 @@
 import cc.mrbird.febs.mall.mapper.*;
 import cc.mrbird.febs.mall.service.*;
 import cc.mrbird.febs.mall.vo.MallMemberCouponVo;
+import cc.mrbird.febs.pay.configure.WxPayUtil;
 import cc.mrbird.febs.pay.model.BrandWCPayRequestData;
+import cc.mrbird.febs.pay.model.HeaderDto;
 import cc.mrbird.febs.pay.service.IXcxPayService;
+import cc.mrbird.febs.pay.service.WxFaPiaoService;
 import cc.mrbird.febs.pay.util.WechatConfigure;
 import cc.mrbird.febs.rabbit.consumer.AgentConsumer;
 import cn.hutool.core.collection.CollUtil;
@@ -22,10 +25,17 @@
 import cn.hutool.json.JSONUtil;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
+import okhttp3.HttpUrl;
 import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.httpclient.HttpClient;
 import org.apache.commons.httpclient.HttpStatus;
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.commons.httpclient.methods.RequestEntity;
+import org.apache.commons.httpclient.methods.StringRequestEntity;
 import org.apache.http.HttpEntity;
 import org.apache.http.HttpResponse;
+import org.apache.http.client.methods.CloseableHttpResponse;
 import org.apache.http.client.methods.HttpPost;
 import org.apache.http.entity.StringEntity;
 import org.apache.http.impl.client.CloseableHttpClient;
@@ -33,6 +43,8 @@
 import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.ResourceLoader;
 import org.springframework.web.client.RestTemplate;
 
 import javax.annotation.Resource;
@@ -40,6 +52,7 @@
 import java.math.BigDecimal;
 import java.net.URLConnection;
 import java.nio.charset.Charset;
+import java.security.KeyPair;
 import java.util.*;
 import java.io.ByteArrayOutputStream;
 import java.io.InputStream;
@@ -89,18 +102,81 @@
     private MallGoodsMapper mallGoodsMapper;
     @Autowired
     private CouponGoodsMapper couponGoodsMapper;
+    @Autowired
+    private WxFaPiaoService wxFaPiaoService;
+    @Autowired
+    ResourceLoader resourceLoader;
     @Test
-    public void rankProfit() {
-//        memberProfitService.rankProfit();
-        MallMemberCouponDto mallMemberCouponDto = new MallMemberCouponDto();
-        mallMemberCouponDto.setMemberId(72L);
-        mallMemberCouponDto.setExpireTime(DateUtil.date());
-        List<Long> couponIds = couponGoodsMapper.selectByGoodId(10L);
-        List<MallMemberCouponVo> mallMemberCouponVos = new ArrayList<>();
-        if(CollUtil.isNotEmpty(couponIds)){
-            mallMemberCouponVos = mallMemberCouponMapper.selectListCreateInPage(mallMemberCouponDto,couponIds);
-            System.out.println(mallMemberCouponVos);
+    public void rankProfit() throws IOException {
+//        System.out.println(new ClassPathResource("wxP12/apiclient_cert.p12").getFile().exists());
+//        System.out.println(new File("src/main/resources/wxP12/apiclient_cert.p12").exists());
+//
+//        InputStream inputStream = new FileInputStream(file);
+//        System.out.println(resourceLoader.getResource("classpath:/wxP12/apiclient_cert.p12").exists());
+        KeyPair privateKey = wxFaPiaoService.getPrivateKey();
+        HeaderDto headerDto = new HeaderDto();
+        headerDto.setCallback_url("https://api.blnka.cn/api/xcxPay/fapiaoCallBack");
+        headerDto.setShow_fapiao_cell(true);
+        String parseObj = JSONUtil.parseObj(headerDto).toString();
+        String baseUrl = "https://api.mch.weixin.qq.com";
+        String canonicalUrl = "/v3/new-tax-control-fapiao/merchant/development-config";
+        String postStr = wxFaPiaoService.createAuthorization(
+                "POST",
+                canonicalUrl,
+                parseObj,
+                privateKey
+
+        );
+        // 创建httppost
+        try {
+            HttpClient httpClient = new HttpClient();
+            PostMethod post = new PostMethod("https://api.mch.weixin.qq.com/v3/new-tax-control-fapiao/merchant/development-config");
+            post.setRequestHeader("Accept", "application/json");
+            post.setRequestHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36");
+            post.setRequestHeader("Content-Type", "application/json; charset=UTF-8");
+            post.setRequestHeader("Connection", "keep-alive");
+            post.setRequestHeader("Authorization",  "WECHATPAY2-SHA256-RSA2048 "+postStr);
+            RequestEntity entity = new StringRequestEntity(parseObj, "text/html", "utf-8");
+            post.setRequestEntity(entity);
+            httpClient.executeMethod(post);
+            String responseBodyAsString = post.getResponseBodyAsString();
+            cn.hutool.json.JSONObject maps = JSONUtil.parseObj(responseBodyAsString);
+            System.out.println(maps);
+        } catch (IOException e) {
+            e.printStackTrace();
         }
+
+    }
+
+    @Test
+    public void rankProfit2() throws IOException {
+        KeyPair privateKey = wxFaPiaoService.getPrivateKey();
+        String baseUrl = "https://api.mch.weixin.qq.com";
+        String canonicalUrl = "/v3/new-tax-control-fapiao/merchant/development-config";
+        String postStr = wxFaPiaoService.createAuthorization(
+                "GET",
+                canonicalUrl,
+                "",
+                privateKey
+
+        );
+        try {
+            HttpClient httpClient = new HttpClient();
+            GetMethod method = new GetMethod(baseUrl+canonicalUrl);
+            method.setRequestHeader("Accept", "application/json");
+            method.setRequestHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36");
+            method.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
+            method.setRequestHeader("Connection", "keep-alive");
+            method.setRequestHeader("Authorization", "WECHATPAY2-SHA256-RSA2048 "+postStr);
+            httpClient.executeMethod(method);
+            System.out.println(method);
+            String responseBodyAsString = method.getResponseBodyAsString();
+            cn.hutool.json.JSONObject maps = JSONUtil.parseObj(responseBodyAsString);
+            System.out.println(maps);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
     }
 
 

--
Gitblit v1.9.1