From ad5db85e540947e82c7a4d5612879b3b3ecdf459 Mon Sep 17 00:00:00 2001
From: liujie <1793218484@qq.com>
Date: 星期五, 21 八月 2026 10:38:07 +0800
Subject: [PATCH] update

---
 backend/src/main/java/com/tourguide/common/huifu/biz/DouGongWithdrawBiz.java |  161 ++++++++++++++++++-----------------------------------
 1 files changed, 55 insertions(+), 106 deletions(-)

diff --git a/backend/src/main/java/com/tourguide/common/huifu/biz/DouGongWithdrawBiz.java b/backend/src/main/java/com/tourguide/common/huifu/biz/DouGongWithdrawBiz.java
index 6c1d780..5b24da8 100644
--- a/backend/src/main/java/com/tourguide/common/huifu/biz/DouGongWithdrawBiz.java
+++ b/backend/src/main/java/com/tourguide/common/huifu/biz/DouGongWithdrawBiz.java
@@ -1,133 +1,82 @@
 package com.tourguide.common.huifu.biz;
 
 import com.alibaba.fastjson.JSONObject;
+import com.huifu.bspay.sdk.opps.core.net.BasePayRequest;
 import com.tourguide.common.huifu.properties.HuiFuProperties;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Qualifier;
-import org.springframework.http.*;
 import org.springframework.stereotype.Component;
-import org.springframework.web.client.RestTemplate;
 
 import java.math.BigDecimal;
-import java.security.KeyFactory;
-import java.security.PrivateKey;
-import java.security.Signature;
-import java.security.spec.PKCS8EncodedKeySpec;
-import java.text.SimpleDateFormat;
-import java.util.Base64;
-import java.util.Date;
+import java.math.RoundingMode;
+import java.util.HashMap;
+import java.util.Map;
 
-/**
- * 斗拱主动提现业务。
- *
- * 备注:该类只向斗拱发起提现,导游余额扣减、提现单状态变更应在本项目业务服务中幂等完成。
- */
+/** 斗拱主动取现和出金交易查询。 */
 @Component
 public class DouGongWithdrawBiz {
     private static final Logger log = LoggerFactory.getLogger(DouGongWithdrawBiz.class);
 
-    @Autowired
-    private HuiFuProperties huiFuProperties;
-    @Autowired
-    @Qualifier("huifuRestTemplate")
-    private RestTemplate restTemplate;
+    private final HuiFuProperties huiFuProperties;
 
-    private static final String ENCASHMENT_URL = "https://api.huifu.com/v2/trade/settlement/encashment";
-    /**
-     * 主动取现接口。
-     *
-     * @param cashAmt 取现金额,单位元
-     * @param huifuId 取现方汇付 ID
-     * @param tokenNo 绑定取现卡后返回的取现卡序列号
-     * @return 斗拱响应结果
-     */
-    public JSONObject encashment(BigDecimal cashAmt, String huifuId, String tokenNo) {
+    public DouGongWithdrawBiz(HuiFuProperties huiFuProperties) {
+        this.huiFuProperties = huiFuProperties;
+    }
+
+    public JSONObject encashment(BigDecimal cashAmt, String huifuId, String tokenNo,
+                                  String requestSequence, String requestDate) {
         try {
-            log.info("开始调用斗拱提现接口,取现方ID: {}, 取现金额: {}", huifuId, cashAmt);
-
-            JSONObject data = new JSONObject();
-            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
-            String reqDate = dateFormat.format(new Date());
-
-            data.put("req_date", reqDate);
-            data.put("req_seq_id", DouGongRequestSupport.generateForHuiFu("TX"));
-            data.put("cash_amt", cashAmt.toString());
-            data.put("huifu_id", huifuId);
-            // 备注:提现到账周期先固定 D1,后续如果后台提供提现规则,再从配置或提现申请中读取。
-            data.put("into_acct_date_type", "D1");
-            data.put("token_no", tokenNo);
-            data.put("notify_url", huiFuProperties.getCallbackPath() + "/base/dougong/encashment");
-
-            String dataStr = data.toJSONString();
-            log.info("业务参数data: {}", dataStr);
-
-            JSONObject requestJson = new JSONObject();
-            requestJson.put("sys_id", huiFuProperties.getSysId());
-            requestJson.put("product_id", huiFuProperties.getProductId());
-            requestJson.put("data", dataStr);
-
-            // 备注:主动提现接口按完整报文签名,不复用支付创建接口只签 data 的逻辑。
-            String signData = requestJson.toJSONString();
-            log.info("待签名报文: {}", signData);
-
-            String signature = sign(signData, huiFuProperties.getRsaPrivateKey());
-            if (signature == null) {
-                log.error("签名生成失败");
-                return createErrorResult("签名生成失败");
-            }
-
-            requestJson.put("sign", signature);
-
-            HttpHeaders headers = new HttpHeaders();
-            headers.setContentType(MediaType.APPLICATION_JSON);
-
-            HttpEntity<String> requestEntity = new HttpEntity<>(requestJson.toJSONString(), headers);
-
-            log.info("发送斗拱提现请求到: {}", ENCASHMENT_URL);
-            ResponseEntity<String> response = restTemplate.exchange(
-                ENCASHMENT_URL,
-                HttpMethod.POST,
-                requestEntity,
-                String.class
-            );
-
-            log.info("斗拱提现接口响应状态: {}, 响应内容: {}", response.getStatusCode(), response.getBody());
-
-            // 解析响应
-            JSONObject result = JSONObject.parseObject(response.getBody());
-            return result;
-
-        } catch (Exception e) {
-            log.error("调用斗拱提现接口异常: {}", e.getMessage(), e);
-            return createErrorResult("调用接口异常: " + e.getMessage());
+            DouGongRequestSupport.initBasePay(huiFuProperties);
+            Map<String, Object> params = new HashMap<>();
+            params.put("req_date", requestDate);
+            params.put("req_seq_id", requestSequence);
+            params.put("cash_amt", cashAmt.setScale(2, RoundingMode.HALF_UP).toString());
+            params.put("huifu_id", huifuId);
+            params.put("into_acct_date_type", "D1");
+            params.put("token_no", tokenNo);
+            params.put("enchashment_channel", "00");
+            params.put("notify_url", callbackBaseUrl() + "/base/dougong/encashment");
+            log.info("调用斗拱取现接口,reqSeqId={},huifuId={},cashAmt={}",
+                    requestSequence, huifuId, cashAmt);
+            return json(BasePayRequest.requestBasePay(
+                    "v2/trade/settlement/encashment", params, null, false));
+        } catch (Exception exception) {
+            log.error("调用斗拱取现接口异常,reqSeqId={},原因={}",
+                    requestSequence, exception.getMessage(), exception);
+            return error(exception.getMessage());
         }
     }
 
+    public JSONObject query(String huifuId, String requestDate, String requestSequence) {
+        try {
+            DouGongRequestSupport.initBasePay(huiFuProperties);
+            Map<String, Object> params = new HashMap<>();
+            params.put("huifu_id", huifuId);
+            params.put("org_req_date", requestDate);
+            params.put("org_req_seq_id", requestSequence);
+            return json(BasePayRequest.requestBasePay(
+                    "v2/trade/settlement/query", params, null, false));
+        } catch (Exception exception) {
+            log.warn("查询斗拱取现状态异常,reqSeqId={},原因={}", requestSequence, exception.getMessage());
+            return error(exception.getMessage());
+        }
+    }
 
-    private JSONObject createErrorResult(String errorMsg) {
+    private JSONObject json(Map<String, Object> response) {
+        return response == null ? null : JSONObject.parseObject(JSONObject.toJSONString(response));
+    }
+
+    private JSONObject error(String message) {
         JSONObject result = new JSONObject();
         result.put("code", "9999");
-        result.put("msg", errorMsg);
+        result.put("msg", message == null ? "斗拱服务调用异常" : message);
         result.put("success", false);
         return result;
     }
-    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;
-        }
+
+    private String callbackBaseUrl() {
+        String value = huiFuProperties.getCallbackPath().trim();
+        while (value.endsWith("/")) value = value.substring(0, value.length() - 1);
+        return value;
     }
 }

--
Gitblit v1.7.1