From f0e738ecd05cba3d71b144433789bc08cb101911 Mon Sep 17 00:00:00 2001
From: 无关风月 <443237572@qq.com>
Date: 星期日, 10 八月 2025 20:00:51 +0800
Subject: [PATCH] 小程序积分支付

---
 ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/controller/TIntegralController.java |  245 +++++++++++++++++++++++++++++++++++++-----------
 1 files changed, 187 insertions(+), 58 deletions(-)

diff --git a/ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/controller/TIntegralController.java b/ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/controller/TIntegralController.java
index c3d4c79..80aa8e5 100644
--- a/ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/controller/TIntegralController.java
+++ b/ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/controller/TIntegralController.java
@@ -27,6 +27,7 @@
 import com.ruoyi.other.util.pay.HttpRequester;
 import com.ruoyi.other.util.pay.HttpRespons;
 import com.ruoyi.other.util.pay.Md5_Sign;
+import com.ruoyi.other.util.payment.wx.WechatPayConfig;
 import com.ruoyi.other.util.payment.wx.WechatPayService;
 import com.ruoyi.other.vo.IntegralListVO;
 import com.ruoyi.other.vo.IntegralVO;
@@ -47,15 +48,18 @@
 import javax.annotation.Resource;
 import javax.imageio.ImageIO;
 import java.awt.image.BufferedImage;
-import java.io.IOException;
+import java.io.*;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.security.KeyFactory;
+import java.security.PrivateKey;
+import java.security.Signature;
+import java.security.spec.PKCS8EncodedKeySpec;
 import java.text.SimpleDateFormat;
 import java.time.LocalDateTime;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 
 /**
  * <p>
@@ -246,9 +250,12 @@
         payDto.setQrCode(rcResult);
         return R.ok(payDto);
     }
+    @Autowired
+    private WechatPayConfig wechatPayConfig;
     @PostMapping("/integralPayApplet")
     @ApiOperation(tags = {"2.0-积分钱包"},value = "小程序积分充值")
-    public R servicePayApplet() throws Exception {
+    public R servicePayApplet(@RequestParam("amount")BigDecimal amount) throws Exception {
+        BigDecimal money = amount.setScale(2, RoundingMode.HALF_UP);
         Long userid = tokenService.getLoginUser().getUserid();
         R<SysUser> sysUser = sysUserClient.getSysUser(userid);
         SysUser data = sysUser.getData();
@@ -270,68 +277,190 @@
         servicePayService.save(servicePay);
 
 
-        return wechatPayService.unifiedOrderApplet(servicePay.getId()+"",code, site.getAnnualServiceFee()+"", "服务费缴纳",data.getOpenId(), "/other/wx/serviceCallback");
+//        return wechatPayService.unifiedOrderApplet(servicePay.getId()+"",code, site.getAnnualServiceFee()+"", "服务费缴纳",data.getOpenId(), "/other/wx/serviceCallback");
+        SimpleDateFormat date = new SimpleDateFormat("yyyyMMdd");
+
+
+        String key = "MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQDAna1TkFL4MRjBiPpGqBbvRy8ojVglU306o01wibafNiE7pvAVjn9aUShSzCA9OkvMld35XLpO4o8ZhetFK5W9mlVGgCVyOSCcApEyadBH8zfRGpL96vQDynhY7QP0Ffgrua5jKXvbIxcqwGO0kdHqQULJFjDoqwknTy+LUWX/IhuViY4hzS79RoQhCmvTM8BaPUY3cGLA7XbRHMgYkkoRrRzfIio2rwEtq+2s2sajPsdM/g0D4ilCOFYUO36+H26uzBWlwBprjEkoPujcdAo93Y3JxkC7ZcVP3ytyFVQTUwNbmeLdK8XPet95ngbmRQyAgN//QItLvIukAJjJp8zNAgMBAAECggEBAJ3QkvKkjVZM47uuP2Ek16W07S6MoGv0u+YPZqOOMdLAxvnZDVycJDwbwq4UEVYZLYGySOzGzN9VQWnoD5vc2hM/IB9jX0r3A4DPmad0ivJolJL+8vCYUNXKTlCN4W9bkLpCqF8W3iPt3E1q1EZeM197mPyo8emwOQ+8EXhUeP1PyJDHGu6EXMApaobGFZy00ggke8h0P7/OZbrf0o9G0u004fH9bfHHREwsa31LsYkQrGBOXXWSO6KGc0wcjK3gIV06DyA9uQNAi8Afd7ga3M/QzTNdg0G5GwVBBIlcg8NA5FFJO6fxmS9kPhWeij7C20iHJfqqc4CEC4ig2w4IgQECgYEA5+tYwnuiFyaiZsdlrSkb7z7NiYPBjtDRz0ZgfT51LMzO3UvegpwpuxZgJFIpL4k5EFfHrkLztUCDzsPdaDFnPKqVzRgBNSFbZ4iTAht9CgX/RSHuBHwiRBZRoWWlL3bKUAIXXHtwpx12nweh+iRE8feGd7VJwrMY3QOqAqtN3YMCgYEA1J2bE2cp0aNZxAYc1CmV6nJxPniQlNV+pCQv3usUaGMJzxqXG1N6ViuB1VxC6WLvy8cp3uMu57Pjae71AcBgjULv5KcCg1cJctwvcv+7ZteJUhg7chr4nLGjdip85UyRqmoTF7EnIPqmDm8aGvWBDCPRTION59G88zgUNEFFa28CgYEAj9JxTtpg4L6Cw/4v3by6qBloWTkuFaUGF+Zq/AB5pfi06KOeL50se+saYCvbgrE0hCALotO+Us7ZbqYkbfMFNKgNEg0q4on3JzOZBxuI5Whmr7ak5n8cuOCmatKgJ9khCZDib+XVLK2m3GRdXMSVRQDdkOsJ/QYYCye0jMczGIUCgYEAlUTtSesErhyr+fZ8qOtlSAr+vGgywXs+BQku3qdWVY8qpM87RUEPQ44aAexbQbVnOz7hg40mMh/WSlosgwVIBAT5nSMvnXwuswgo++jU7ffmfc9rdMnAv2nrpBtiQi3GmskMDHcgTIQMr1eLEWBJMHe5CqnVp+pVaMB3VtR4Y1sCgYEAqg43xBxz6P/3K/PfCMmx4Vh2xpT+V3JLGA7DcnEHOUjG5M9jwkkXBuOp0gdtojEoIlI1c2xd4RFZsl451RKZOc4+YsVS2LzCJQrP0PcMlvMVVCIddm7v//ec7s+hAL5g+VuMyq7YKMXXWfA9a+H2thvrAVagihMho2SNAh+LYn8=";
+
+        // 构建data部分
+        Map<String, Object> dataMap = new LinkedHashMap<String, Object>(); // 使用LinkedHashMap保持顺序
+        dataMap.put("goods_desc", "积分充值");
+        dataMap.put("huifu_id", "6666000174575407");
+        dataMap.put("notify_url", "http://221.182.45.100:8084/other/wx/integralCallback");
+        dataMap.put("req_date", date.format(new Date()));
+        dataMap.put("req_seq_id", code);
+        dataMap.put("trade_type", "T_MINIAPP");
+        dataMap.put("trans_amt", money+"");
+        Map<String, String> wx_data = new LinkedHashMap<String, String>(); // 使用LinkedHashMap保持顺序
+        // todo
+        dataMap.put("sub_appid", wechatPayConfig.getAppId());
+        dataMap.put("sub_openid", data.getOpenId());
+
+        dataMap.put("wx_data", wx_data);
+
+        // 将dataMap转化为json对象
+
+        String signStr = JSON.toJSONString(JSONObject.parseObject(JSON.toJSONString(dataMap), TreeMap.class));
+
+        System.out.println("待签名字符串:" + signStr);
+
+        // 签名 (按照汇付天下规则,使用MD5加签)
+        String sign = sign(signStr, key);
+        System.out.println("签名:" + sign);
+
+        // 构建完整请求JSON
+        Map<String, Object> requestJson = new HashMap<>();
+        requestJson.put("sys_id", "6666000174575407");
+        requestJson.put("product_id", "KAZX");
+        requestJson.put("sign", sign);
+        requestJson.put("data", dataMap);
+
+        String jsonBody = JSON.toJSONString(requestJson);
+        System.out.println("发送JSON:" + jsonBody);
+
+        // 使用原生Java发送请求
+        URL url = new URL("https://api.huifu.com/v3/trade/payment/jspay");
+        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+
+        conn.setRequestMethod("POST");
+        conn.setRequestProperty("Content-Type", "application/json;charset=UTF-8");
+        conn.setRequestProperty("Accept", "application/json");
+        conn.setDoOutput(true);
+
+        // 发送请求体
+        try (OutputStream os = conn.getOutputStream()) {
+            byte[] input = jsonBody.getBytes("utf-8");
+            os.write(input, 0, input.length);
+        }
+
+        // 读取响应
+        int responseCode = conn.getResponseCode();
+        System.out.println("响应码: " + responseCode);
+
+        // 正确处理响应流,无论成功还是失败
+        InputStream inputStream = null;
+        try {
+            inputStream = conn.getInputStream();
+        } catch (IOException e) {
+            inputStream = conn.getErrorStream();
+        }
+
+        StringBuilder response = new StringBuilder();
+        if (inputStream != null) {
+            try (BufferedReader br = new BufferedReader(new InputStreamReader(inputStream, "utf-8"))) {
+                String responseLine;
+                while ((responseLine = br.readLine()) != null) {
+                    response.append(responseLine.trim());
+                }
+            }
+        }
+
+        System.out.println("接收返回参数:" + response.toString());
+        return R.ok(response.toString());
     }
     public static void main(String[] args) throws IOException {
+        SimpleDateFormat date = new SimpleDateFormat("yyyyMMdd");
         SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
         String code = sdf.format(new Date()) + UUIDUtil.getNumberRandom(5);
-//        Map<String, String> res =  wechatPayService.unifiedOrder(code, amount, "积分充值", "/other/wx/integralCallback");
 
-//        TIntegralRule one = integralRuleService.lambdaQuery().eq(TIntegralRule::getSiteId, 0).one();
-//        if (one==null){
-//            return R.fail("获取支付失败,平台未设置充值积分比例");
-//        }
-//        String chargeCredit = one.getChargeCredit();
-//        JSONObject jsonObject = JSONObject.parseObject(chargeCredit);
-//        Integer num1 = jsonObject.getInteger("num1");
-//        BigDecimal bigDecimal = new BigDecimal(amount);
-//        // 向上取整 比如5.1 当作6 5.9也当作6
-//        integralPay.setIntegralCount(bigDecimal.divide(new BigDecimal(num1), RoundingMode.UP).intValue());
-//        int i = bigDecimal.multiply(new BigDecimal(num1)).intValue();
+        String key = "MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQDAna1TkFL4MRjBiPpGqBbvRy8ojVglU306o01wibafNiE7pvAVjn9aUShSzCA9OkvMld35XLpO4o8ZhetFK5W9mlVGgCVyOSCcApEyadBH8zfRGpL96vQDynhY7QP0Ffgrua5jKXvbIxcqwGO0kdHqQULJFjDoqwknTy+LUWX/IhuViY4hzS79RoQhCmvTM8BaPUY3cGLA7XbRHMgYkkoRrRzfIio2rwEtq+2s2sajPsdM/g0D4ilCOFYUO36+H26uzBWlwBprjEkoPujcdAo93Y3JxkC7ZcVP3ytyFVQTUwNbmeLdK8XPet95ngbmRQyAgN//QItLvIukAJjJp8zNAgMBAAECggEBAJ3QkvKkjVZM47uuP2Ek16W07S6MoGv0u+YPZqOOMdLAxvnZDVycJDwbwq4UEVYZLYGySOzGzN9VQWnoD5vc2hM/IB9jX0r3A4DPmad0ivJolJL+8vCYUNXKTlCN4W9bkLpCqF8W3iPt3E1q1EZeM197mPyo8emwOQ+8EXhUeP1PyJDHGu6EXMApaobGFZy00ggke8h0P7/OZbrf0o9G0u004fH9bfHHREwsa31LsYkQrGBOXXWSO6KGc0wcjK3gIV06DyA9uQNAi8Afd7ga3M/QzTNdg0G5GwVBBIlcg8NA5FFJO6fxmS9kPhWeij7C20iHJfqqc4CEC4ig2w4IgQECgYEA5+tYwnuiFyaiZsdlrSkb7z7NiYPBjtDRz0ZgfT51LMzO3UvegpwpuxZgJFIpL4k5EFfHrkLztUCDzsPdaDFnPKqVzRgBNSFbZ4iTAht9CgX/RSHuBHwiRBZRoWWlL3bKUAIXXHtwpx12nweh+iRE8feGd7VJwrMY3QOqAqtN3YMCgYEA1J2bE2cp0aNZxAYc1CmV6nJxPniQlNV+pCQv3usUaGMJzxqXG1N6ViuB1VxC6WLvy8cp3uMu57Pjae71AcBgjULv5KcCg1cJctwvcv+7ZteJUhg7chr4nLGjdip85UyRqmoTF7EnIPqmDm8aGvWBDCPRTION59G88zgUNEFFa28CgYEAj9JxTtpg4L6Cw/4v3by6qBloWTkuFaUGF+Zq/AB5pfi06KOeL50se+saYCvbgrE0hCALotO+Us7ZbqYkbfMFNKgNEg0q4on3JzOZBxuI5Whmr7ak5n8cuOCmatKgJ9khCZDib+XVLK2m3GRdXMSVRQDdkOsJ/QYYCye0jMczGIUCgYEAlUTtSesErhyr+fZ8qOtlSAr+vGgywXs+BQku3qdWVY8qpM87RUEPQ44aAexbQbVnOz7hg40mMh/WSlosgwVIBAT5nSMvnXwuswgo++jU7ffmfc9rdMnAv2nrpBtiQi3GmskMDHcgTIQMr1eLEWBJMHe5CqnVp+pVaMB3VtR4Y1sCgYEAqg43xBxz6P/3K/PfCMmx4Vh2xpT+V3JLGA7DcnEHOUjG5M9jwkkXBuOp0gdtojEoIlI1c2xd4RFZsl451RKZOc4+YsVS2LzCJQrP0PcMlvMVVCIddm7v//ec7s+hAL5g+VuMyq7YKMXXWfA9a+H2thvrAVagihMho2SNAh+LYn8=";
 
+        // 构建data部分
+        Map<String, String> dataMap = new LinkedHashMap<String, String>(); // 使用LinkedHashMap保持顺序
+        dataMap.put("goods_desc", "积分充值");
+        dataMap.put("huifu_id", "6666000174575407");
+        dataMap.put("notify_url", "http://221.182.45.100:8084/other/wx/integralCallback");
+        dataMap.put("req_date", date.format(new Date()));
+        dataMap.put("req_seq_id", code);
+        dataMap.put("trade_type", "T_MINIAPP");
+        dataMap.put("trans_amt", "0.01");
 
-//        String codeUrl = res.get("code_url");
-//        MyQrCodeUtil.createCodeToFile(codeUrl);
-//        BufferedImage blueImage = QRCodeUtil.createImage(codeUrl);
-//        MultipartFile blueFile = convert(blueImage, new Date().getTime() + UUIDUtil.getRandomCode(3) + ".PNG");
-//        String s = ObsUploadUtil.obsUpload(blueFile);
-//        System.err.println(s);
-        String key = "ad273ceb5e1b49e68d5c565d28d1d305";/** md5密钥商户后台-商户中心-商户设置-密钥管理获取 必填!*/
-        Map<String, String> map = new HashMap<String, String>();
-        map.put("p0_Version", "2.5");/** 版本号 */
-        map.put("p1_MerchantNo", "888122400007793");/** 商户编号 */
-        map.put("p2_OrderNo", code); /**商户订单号*/
-        map.put("p3_Amount", String.valueOf(0.01));/**订单金额*/
-        map.put("p4_Cur", "1"); /**交易币种 */
-        map.put("p5_ProductName", "充值"); /** 商品名称 */
-        map.put("p6_ProductDesc", "积分充值"); /** 商品名称 */
-//        map.put("p7_Mp", ""); /** 如果商户请求时传递了该参数,则返回给商户时会原值传 回。 */
-        map.put("p9_NotifyUrl", "http://221.182.45.100:8084/other/wx/integralCallback"); /** 服务器异步通知地址 */
-        map.put("q1_FrpCode", "WEIXIN_NATIVE"); /** 微信扫码(主扫)【注:此为用户主扫,商户被扫】*/
-        map.put("q4_IsShowPic", "1"); /** 是否展示二 维码图片 1表示输出*/
-        map.put("q7_AppId", "wx1a4a7760be53a835"); /** 交易类型*/
-        map.put("qa_TradeMerchantNo", "777165000859101"); /** 777开头的报备商户号   必填!*/
-        map.put("qi_FqSellerPercen", "0"); /** 卖家承担收 费比例 目前仅支持传入 0 ,即用户承 担手续费!*/
-        String Strmap = CreateLinkStringByGet1.createLinkStringByGet(map);
-        // 签名
-        String sign = "";
-        sign = Md5_Sign.SignByMD5(Strmap, key);
-        map.put("hmac", sign);/** 签名数据 */
-        System.out.println("发送:" + JSON.toJSONString(map).toString());
+        // 将dataMap转化为json对象
 
-        // post请求参数内容
-        HttpRequester hr = new HttpRequester();
-        HttpRespons HP = hr.sendPost("https://trade.joinpay.com/tradeRt/uniPay", map);
-        System.out.println("接收返回参数:" + HP.getContent());
-        JSONObject resPay = JSONObject.parseObject(HP.getContent());
-        String rcResult = resPay.getString("rd_Pic");
-        Map<String, Object> map2 = new HashMap<>();
-        map2.put("rcResult", rcResult);
-        PayDto payDto = new PayDto();
-        payDto.setQrCode(rcResult);
-        System.err.println(payDto);
+        String signStr = JSON.toJSONString(JSONObject.parseObject(JSON.toJSONString(dataMap), TreeMap.class));
+
+        System.out.println("待签名字符串:" + signStr);
+
+        // 签名 (按照汇付天下规则,使用MD5加签)
+        String sign = sign(signStr, key);
+        System.out.println("签名:" + sign);
+
+        // 构建完整请求JSON
+        Map<String, Object> requestJson = new HashMap<>();
+        requestJson.put("sys_id", "6666000174575407");
+        requestJson.put("product_id", "KAZX");
+        requestJson.put("sign", sign);
+        requestJson.put("data", dataMap);
+
+        String jsonBody = JSON.toJSONString(requestJson);
+        System.out.println("发送JSON:" + jsonBody);
+
+        // 使用原生Java发送请求
+        URL url = new URL("https://api.huifu.com/v3/trade/payment/jspay");
+        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+
+        conn.setRequestMethod("POST");
+        conn.setRequestProperty("Content-Type", "application/json;charset=UTF-8");
+        conn.setRequestProperty("Accept", "application/json");
+        conn.setDoOutput(true);
+
+        // 发送请求体
+        try (OutputStream os = conn.getOutputStream()) {
+            byte[] input = jsonBody.getBytes("utf-8");
+            os.write(input, 0, input.length);
+        }
+
+        // 读取响应
+        int responseCode = conn.getResponseCode();
+        System.out.println("响应码: " + responseCode);
+
+        // 正确处理响应流,无论成功还是失败
+        InputStream inputStream = null;
+        try {
+            inputStream = conn.getInputStream();
+        } catch (IOException e) {
+            inputStream = conn.getErrorStream();
+        }
+
+        StringBuilder response = new StringBuilder();
+        if (inputStream != null) {
+            try (BufferedReader br = new BufferedReader(new InputStreamReader(inputStream, "utf-8"))) {
+                String responseLine;
+                while ((responseLine = br.readLine()) != null) {
+                    response.append(responseLine.trim());
+                }
+            }
+        }
+
+        System.out.println("接收返回参数:" + response.toString());
     }
 
+
+    /**
+     * RSA私钥签名:签名方式SHA256WithRSA
+     * @param data 待签名字符串
+     * @param privateKeyBase64 私钥(Base64编码)
+     * @return 签名byte[]
+     * @throws Exception
+     */
+    public static String sign(String data, String privateKeyBase64) {
+        // Base64 --> Key
+        try {
+            byte[] bytes = Base64.getDecoder().decode(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;
+        }
+    }
     public static MultipartFile convert(BufferedImage bufferedImage, String fileName) throws IOException {
         // 将 BufferedImage 转换为字节数组
         ByteArrayOutputStream baos = new ByteArrayOutputStream();

--
Gitblit v1.7.1