From 11e778f72b830a4050c293d78694417d32055727 Mon Sep 17 00:00:00 2001
From: puzhibing <393733352@qq.com>
Date: 星期五, 20 十月 2023 20:39:55 +0800
Subject: [PATCH] 对接第三方分账接口

---
 ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/util/HuiFuTianXiaUtil.java |  172 +++++++++++++++++++++++++++++++++++++++++++++-----------
 1 files changed, 137 insertions(+), 35 deletions(-)

diff --git a/ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/util/HuiFuTianXiaUtil.java b/ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/util/HuiFuTianXiaUtil.java
index f226c79..8a71058 100644
--- a/ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/util/HuiFuTianXiaUtil.java
+++ b/ruoyi-modules/ruoyi-shop/src/main/java/com/ruoyi/shop/util/HuiFuTianXiaUtil.java
@@ -6,6 +6,7 @@
 import com.alibaba.fastjson.JSONObject;
 import com.ruoyi.common.core.domain.R;
 import com.ruoyi.common.core.utils.uuid.IdUtils;
+import com.ruoyi.shop.domain.dto.MerchantBasicDataNotifyDto;
 import com.ruoyi.shop.domain.dto.MgtShopHFTXAuthDto;
 import com.ruoyi.shop.domain.pojo.shop.ShopAuthenticationHftx;
 import com.ruoyi.shop.domain.vo.MerchantBasicdataSettlementVo;
@@ -23,7 +24,6 @@
 
 import java.io.File;
 import java.io.IOException;
-import java.io.InputStream;
 import java.nio.charset.Charset;
 import java.security.KeyFactory;
 import java.security.PrivateKey;
@@ -31,7 +31,6 @@
 import java.security.Signature;
 import java.security.spec.PKCS8EncodedKeySpec;
 import java.security.spec.X509EncodedKeySpec;
-import java.text.NumberFormat;
 import java.text.SimpleDateFormat;
 import java.util.*;
 
@@ -49,15 +48,24 @@
     private static String publicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAral1nmqS1vswaeFp3dAfUY4a/ql07382AMH4NOwewtf9iuiZa608hDVzGYIXYAr+mxj1WwJpSCp9Sn+zSJs4+9iGodMa9qfUQ4oi32zGKR1ND7OZwpXYZudqQrUfC8/0j1DjOWBlKWyqwIh2JLXOiJLrU+dbDJxCqyHv+rO55egjD5yVLEJLkB/n1peIsfbqozKu7rpkx4bUAP1PvMmP913np2gYKsTrjGo7B/NqzkQ98mtL/VMOIbha0qN+MpEWImT/mOlgxvmr7YnTr3e7Iu/gSm8HR/5kLqmO4WmHALnoq7vDnOWpyM7c+awIxRTwoT8mwCuxPTLBUZ5UEmpIYwIDAQAB";
     //商户号
     private static String huifu_id = "6666000141279152";
+    //控制台地址https://dashboard.huifu.com/customers/login,用户名为hh_hrt,最新密码为xw123456
+
+    //私钥(Base64编码)
+    private static String channel_privateKeyBase64 = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCB7Flp+4FuRBvW4FLx5FoR/Hbj1UWJbgt9JAgO5iCFR9MhxXu783hvP88STFWyNkCeAh9EIwVcJxm80Kmt87KH4Nwo1ejfqF8kUkK02byVby39fqTJlyqeDYKjqqc04GpnL7vi4iD4rKGvjyJIFxekCcOSTFWVl879fbPn9+ljsVrrjoyzbPMvPJHPuc2dzkWP98C+y5QFDIdjyS8NrVOpJcwVFrcxkmCmK6azTi6LJeI/wH9MsJHmnF9ZilqY1x00XbTMxE4EfTgXgmv6dvRac6VrqQowUCqIrHpVJIdet1w56vmz3IpxORIOPzU2nY9ziZrMIgGkJ1bLQRbLK2RXAgMBAAECggEAKA4i/u7AV6t93cBpMhRRxIvOZ61/87/OoPUz2swOKKkdKaNF44tLjRjiEWUhYoEhaNWEqDAX3fJcF/9I4M1qNEQZ/Cj+072IH52Q3UrnvjZ5ulaKHXCSfgnyRd0+EapCg6+OwIMw4Rnv+z0ot4sPCc7M0dTg6e7UrQhNJ+4hsU8yZAMzmQyUu7pE6tvbE+u5QdRZRMQIYPgzwpy5Yta0gtRSmMQ9jneUYwEJ5eu8ZhAXRzEWqAA9GgOLgAwC2Ma1xkVyiBS/7pfd0fwbxapzMZMQMbCsv+UrYGYkXDp/1XwrpNWavfHpSCc9fkK2auEqYJtYlhELoa87+WrBOHhkkQKBgQDMi73gDw47XH0T6zuJn2ieDDc7IU1DV9RXXNJNxgcB0yBM8HaI8lv27eThphlEU13KWKTHAylm/q7v4dp88aC+iA3GhIbmE1sWxiSJvwGR2xqmWvIHTadJtQFdXJN+/GmG1fJuCRwkZSyGdUXUdmx3PBATEqUwuSQQDQkMvxYjrwKBgQCimxdXNEZrZKHCbHWTHx0nUu0lF7skgi8x+xLbDT096WvqpeNxOZXVZVhU7yHn2ePF9iFipg8uHviUIJyB2Rzr1M2busY3yoRutXlugZJ9ZVUlxpIpNI94ntcOZUctgfd1quhlgqEwcF1PJ5lkogrKHvLoV30fvgkYpA763ZNr2QKBgDgDkKS6GsCgzFPXGD/Q2pplZ/6WWQ03ERw3fBP2Rdb3FSJcu2k3TX3qmcI9dS/j0IxoB//D2uOsnQVuCSIsHUPwCC2z/ykkZc5vxnO+TdS+dqbVwu/DESu7GLuTbYTZ5KAbGL+PWRiSaEYN+Wh8YampVhGTCo+0M679ktvdvFdbAoGACtCz+bnhYS09URgzrchpAP+UBF6StPfvuaxQcb9srlyDMAU+nn5NB/eIq4WIRMqKStV3HP+cjN3EfN26ayyMrublkhEXNAjFTDPH0uDNZIfD5RJTEGiNjmFKPovf8xfs5Kesc2v/2p/upOAmZLoea5kpYOjIyr6yDjCDSo5ISukCgYBtOo2AgFXyzW1ti8MCsz77BtCJ9MgVoPF4y4Ah8l/6Dwe+cevdlWuOYckIAJqJ9g2FYwp9AAevK7k17xsgBgrdqlI77p3wQb7p/znJnNU6qz78FwUzd8t5WvqFh+3mTxjG7Iyj6brLzEUt8McdmGlwbFJqKgUxBKS4mY7T399L5Q==";
+    //公钥(Base64编码)
+    private static String channel_publicKeyBase64 = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgexZafuBbkQb1uBS8eRaEfx249VFiW4LfSQIDuYghUfTIcV7u/N4bz/PEkxVsjZAngIfRCMFXCcZvNCprfOyh+DcKNXo36hfJFJCtNm8lW8t/X6kyZcqng2Co6qnNOBqZy+74uIg+Kyhr48iSBcXpAnDkkxVlZfO/X2z5/fpY7Fa646Ms2zzLzyRz7nNnc5Fj/fAvsuUBQyHY8kvDa1TqSXMFRa3MZJgpiums04uiyXiP8B/TLCR5pxfWYpamNcdNF20zMROBH04F4Jr+nb0WnOla6kKMFAqiKx6VSSHXrdcOer5s9yKcTkSDj81Np2Pc4mazCIBpCdWy0EWyytkVwIDAQAB";
+    //汇付公钥
+    private static String channel_publicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgmGZVY0i5r17BnHiLeL7TbqojpuOmR947JIUB5zYcc/TTYijkCsjtshmvxWslZBdkV6K8/1CmHRAY92+4GZnem6MVO34xn1wTCq65+wMC1oypjJy9T6N0WXoGaf+Wn0nxPdJLvnwpOo6epEES3kQKx+i/Qar7oDwlXMQ6b2QwR/id9cYudN0RmdRLzkmrwEOkjv+WcWCQdoAXv4JWJwU+iwJffoJrWn5pGeVFWFrH1fRJ0IB4YdaL9aWMn2YM5pu+/mcOKQogmNYzsHkZDapX3AF+es0TN+v/qOCgU3OVTVa7ltDAiLuPtMeu/72pQiM0nxunRVnAJDo2BQ5mu6z4wIDAQAB";
     //渠道号
     private static String channel_id = "6666000140729384";
+    //控制台地址https://dashboard.huifu.com/partners/login,用户名为hongrt,最新密码为xw123456
+
     //产品号
     private static String product_id = "KAZX";
     //微信小程序appid
     private static String sub_appid = "wxb7f0ea286fc4e535";
     //本地文件存储位置
     private static String path = "D:\\file";
-    //控制台地址https://dashboard.huifu.com/customers/login,用户名为hongruitang,最新密码为xw123456
     //接口文档https://paas.huifu.com/partners/api/#/
 
 
@@ -70,11 +78,8 @@
      * @param sub_openid    微信小程序用户openid
      * @param notify_url    异步通知回调地址
      */
-    public static R weixinPayment(String req_seq_id, String goods_desc, Double trans_amt, String sub_openid, String notify_url){
+    public static R<JSONObject> weixinPayment(String req_seq_id, String goods_desc, Double trans_amt, String sub_openid, String notify_url){
         SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
-        NumberFormat numberInstance = NumberFormat.getInstance();
-        //最大两位小数
-        numberInstance.setMaximumFractionDigits(2);
         String url = "https://api.huifu.com/v2/trade/payment/jspay";
         JSONObject data = new JSONObject();
         data.put("req_date", sdf.format(new Date()));
@@ -82,7 +87,7 @@
         data.put("huifu_id", huifu_id);
         data.put("goods_desc", goods_desc);
         data.put("trade_type", "T_MINIAPP");
-        data.put("trans_amt", numberInstance.format(trans_amt));
+        data.put("trans_amt", String.format("%.2f", trans_amt));
 
         JSONObject wx_data = new JSONObject();
         wx_data.put("sub_appid", sub_appid);
@@ -96,7 +101,7 @@
         body.put("product_id", product_id);
         body.put("sign", sign(data.toJSONString()));
         body.put("data", data);
-        System.out.print(JSON.toJSONString(body));
+        System.err.println(JSON.toJSONString(body));
         HttpRequest post = HttpUtil.createPost(url);
         Map<String, String> headers = new HashMap<>();
         headers.put("Content-type","application/json; charset=utf-8");
@@ -108,12 +113,6 @@
         execute.close();
         if(StringUtils.hasLength(result1)){
             JSONObject result = JSONObject.parseObject(result1);
-            String result_data = result.getString("data");
-            String result_sign = result.getString("sign");
-            boolean verify = verify(result_data, result_sign);
-            if(!verify){
-                return R.fail("结果验签失败");
-            }
             JSONObject resultData = result.getJSONObject("data");
             String resp_code = resultData.getString("resp_code");
             String resp_desc = resultData.getString("resp_desc");
@@ -121,7 +120,8 @@
             String success1 = "00000000";
             String success2 = "00000100";
             if(success1.equals(resp_code) || success2.equals(resp_code)){
-
+                JSONObject pay_info = resultData.getJSONObject("pay_info");
+                return R.ok(pay_info);
             }
             return R.fail(resp_desc);
         }
@@ -140,15 +140,12 @@
      */
     public static R<String> weixinPaymentRefund(String req_seq_id, Double ord_amt, String org_req_date, String org_party_order_id, String notify_url){
         SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
-        NumberFormat numberInstance = NumberFormat.getInstance();
-        //最大两位小数
-        numberInstance.setMaximumFractionDigits(2);
         String url = "https://api.huifu.com/v2/trade/payment/scanpay/refund";
         JSONObject data = new JSONObject();
         data.put("req_date", sdf.format(new Date()));
         data.put("req_seq_id", req_seq_id);
         data.put("huifu_id", huifu_id);
-        data.put("ord_amt", ord_amt);
+        data.put("ord_amt", String.format("%.2f", ord_amt));
         data.put("org_req_date", org_req_date);
         data.put("org_party_order_id", org_party_order_id);
         data.put("notify_url", notify_url);
@@ -246,6 +243,33 @@
     }
 
 
+    /**
+     * RSA私钥签名:签名方式SHA256WithRSA
+     * @param data 待签名字符串
+     * @return 签名byte[]
+     * @throws Exception
+     */
+    public static String channel_sign(String data) {
+        //先对该json对象数据按照参数字典顺序(参数名ASCII码从小到大排序,参数名区分大小写)排序生成字符串,再进行加签和验签。
+        data = JSON.toJSONString(JSONObject.parseObject(data, TreeMap.class));
+        // Base64 --> Key
+        try {
+            byte[] bytes = Base64.getDecoder().decode(channel_privateKeyBase64);
+            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(bytes);
+            KeyFactory keyFactory;
+            keyFactory = KeyFactory.getInstance("RSA");
+            PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
+            // Sign
+            Signature signature = Signature.getInstance("SHA256WithRSA");
+            signature.initSign(privateKey);
+            signature.update(data.getBytes("UTF-8"));
+            return Base64.getEncoder().encodeToString(signature.sign());
+        } catch (Exception e) {
+            return null;
+        }
+    }
+
+
 
     /**
      * 使用汇付RSA公钥验签
@@ -272,7 +296,34 @@
             e.printStackTrace();
             return false;
         }
+    }
 
+
+    /**
+     * 使用汇付RSA公钥验签
+     * @param data 待签名字符串
+     * @return 验签结果
+     * @throws Exception
+     */
+    public static boolean channel_verify(String data, String sign) {
+        //先对该json对象数据按照参数字典顺序(参数名ASCII码从小到大排序,参数名区分大小写)排序生成字符串,再进行加签和验签。
+        data = JSON.toJSONString(JSONObject.parseObject(data, TreeMap.class));
+        // Base64 --> Key
+        try {
+            byte[] bytes = Base64.getDecoder().decode(channel_publicKeyBase64);
+            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(bytes);
+            KeyFactory keyFactory;
+            keyFactory = KeyFactory.getInstance("RSA");
+            PublicKey publicKey = keyFactory.generatePublic(keySpec);
+            // verify
+            Signature signature = Signature.getInstance("SHA256WithRSA");
+            signature.initVerify(publicKey);
+            signature.update(data.getBytes("UTF-8"));
+            return signature.verify(Base64.getDecoder().decode(sign));
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
     }
 
 
@@ -376,12 +427,14 @@
         }else{
             return R.fail(r.getMsg());
         }
-        r = supplementaryPicture(dto.getSettleCardFrontPic(), IdUtils.simpleUUID(), "F13");
-        if(r.getCode() == 200){
-            data.put("settle_card_front_pic", r.getData());
-            shopAuthenticationHftx.setSettleCardFrontPicNo(r.getData());
-        }else{
-            return R.fail(r.getMsg());
+        if(!"0".equals(dto.getCardType())){
+            r = supplementaryPicture(dto.getSettleCardFrontPic(), IdUtils.simpleUUID(), "F13");
+            if(r.getCode() == 200){
+                data.put("settle_card_front_pic", r.getData());
+                shopAuthenticationHftx.setSettleCardFrontPicNo(r.getData());
+            }else{
+                return R.fail(r.getMsg());
+            }
         }
         r = supplementaryPicture(dto.getSettleCertBackPic(), IdUtils.simpleUUID(), "F56");
         if(r.getCode() == 200){
@@ -425,7 +478,7 @@
         }else{
             return R.fail(r.getMsg());
         }
-        if(!dto.getLegalName().equals(dto.getCardName())){
+        if(!"0".equals(dto.getCardType()) && !dto.getLegalName().equals(dto.getCardName())){
             r = supplementaryPicture(dto.getAuthEnturstPic(), IdUtils.simpleUUID(), "F15");
             if(r.getCode() == 200){
                 data.put("auth_enturst_pic", r.getData());
@@ -473,7 +526,7 @@
         headers.put("Accept", "application/json");
         post.addHeaders(headers);
         post.body(body.toJSONString());
-        System.out.println(JSON.toJSONString(body));
+        System.err.println(JSON.toJSONString(body));
         HttpResponse execute = post.execute();
         String result = execute.body();
         execute.close();
@@ -504,15 +557,14 @@
 
     /**
      * 企业进件通知回调处理
-     * @param jsonObject
      * @return
      */
-    public static R<MerchantBasicdataVo> merchantBasicDataNotify(JSONObject jsonObject){
+    public static R<MerchantBasicdataVo> merchantBasicDataNotify(MerchantBasicDataNotifyDto dto){
         String ok = "200";
         String success = "10000";
-        String resp_code = jsonObject.getString("resp_code");
+        String resp_code = dto.getResp_code();
         if(ok.equals(resp_code) || success.equals(resp_code)){
-            JSONObject data = jsonObject.getJSONObject("data");
+            JSONObject data = JSON.parseObject(dto.getData());
             String sub_resp_code = data.getString("sub_resp_code");
             String sub_resp_desc = data.getString("sub_resp_desc");
             //处理成功
@@ -534,7 +586,7 @@
             }
             return R.fail(sub_resp_desc);
         }
-        return R.fail(jsonObject.getString("resp_desc"));
+        return R.fail(dto.getResp_desc());
     }
 
 
@@ -664,7 +716,7 @@
         body.put("product_id", product_id);
         body.put("sign", sign(data.toJSONString()));
         body.put("data", data);
-        System.out.println(JSON.toJSONString(body));
+        System.err.println(JSON.toJSONString(body));
         HttpRequest post = HttpUtil.createPost(url);
         Map<String, String> headers = new HashMap<>();
         headers.put("Content-type","application/json; charset=utf-8");
@@ -699,6 +751,56 @@
     }
 
 
+    /**
+     * 查询商户信息
+     * @param huifuId
+     * @return
+     */
+    public static R<MerchantBasicdataVo> queryMerchantBasicdata(String req_seq_id, String huifuId){
+        String url = "https://api.huifu.com/v2/merchant/basicdata/query";
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
+        JSONObject data = new JSONObject();
+        data.put("req_seq_id", req_seq_id);
+        data.put("req_date", sdf.format(new Date()));
+        data.put("huifu_id", huifuId);
+
+        JSONObject body = new JSONObject();
+        body.put("sys_id", channel_id);
+        body.put("product_id", product_id);
+        body.put("sign", channel_sign(data.toJSONString()));
+        body.put("data", data);
+        HttpRequest post = HttpUtil.createPost(url);
+        Map<String, String> headers = new HashMap<>();
+        headers.put("Content-type","application/json; charset=utf-8");
+        headers.put("Accept", "application/json");
+        post.addHeaders(headers);
+        post.body(body.toJSONString());
+        System.err.println(JSON.toJSONString(body));
+        HttpResponse execute = post.execute();
+        String result = execute.body();
+        execute.close();
+        if(!StringUtils.hasLength(result)){
+            return R.fail("请求异常");
+        }
+        JSONObject jsonObject = JSON.parseObject(result);
+        JSONObject resultData = jsonObject.getJSONObject("data");
+        String resp_code = resultData.getString("resp_code");
+        String resp_desc = resultData.getString("resp_desc");
+        //处理成功
+        String success1 = "00000000";
+        //交易正在处理中
+        String success2 = "00000100";
+        //审核中
+        String success3 = "90000000";
+        MerchantBasicdataVo vo = new MerchantBasicdataVo();
+        if(success1.equals(resp_code) || success2.equals(resp_code) || success3.equals(resp_code)){
+            JSONArray qry_cash_card_info_list = resultData.getJSONArray("qry_cash_card_info_list");
+            JSONObject jsonObject1 = qry_cash_card_info_list.getJSONObject(0);
+            vo.setTokenNo(jsonObject1.getString("token_no"));
+            return R.ok(vo);
+        }
+        return R.fail(resp_desc);
+    }
 
 
 
@@ -740,7 +842,7 @@
             if (statusCode == org.apache.http.HttpStatus.SC_OK) {
                 HttpEntity resEntity = response.getEntity();
                 result = EntityUtils.toString(resEntity);
-                System.out.print(result);
+                System.err.println(result);
             }
             if(!StringUtils.hasLength(result)){
                 return R.fail("请求异常");

--
Gitblit v1.7.1