wlzboy
2025-12-04 af8cab142a6b15c06e131a8474574dd5b00df982
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
package com.ruoyi.payment.infrastructure.channel.alipay;
 
import com.ruoyi.payment.infrastructure.config.AlipayConfig;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
 
import java.math.BigDecimal;
 
/**
 * 支付宝第三方接口客户端
 * 调用旧系统的支付宝当面付接口
 * 
 * @author ruoyi
 */
@Slf4j
@Component
public class AlipayThirdPartyClient {
 
    @Autowired
    private AlipayConfig alipayConfig;
    /**
     * 第三方支付宝当面付接口地址
     */
//    private  String THIRD_PARTY_ALIPAY_URL = "https://sys.966120.com.cn/alipay_pay_QR_NotifyUrl.php";
 
    /**
     * 第三方支付宝查询接口地址
     */
    private static final String THIRD_PARTY_QUERY_URL = "https://sys.966120.com.cn/alipay_pay_query.php";
 
    /**
     * 调用第三方接口生成支付宝当面付URL
     * 
     * @param notifyUrl 异步回调通知地址
     * @param outTradeNo 商户订单号
     * @param totalFee 订单金额(单位:分)
     * @param serviceOrdId 业务订单ID
     * @return 支付宝当面付URL
     * @throws Exception 调用异常
     */
    public String createQrCodeUrl(String notifyUrl, String outTradeNo, Integer totalFee, String serviceOrdId) 
            throws Exception {
        log.info("调用第三方支付宝当面付接口,订单号: {}, 金额: {}分, 业务订单ID: {}", 
                outTradeNo, totalFee, serviceOrdId);
 
        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpPost httpPost = new HttpPost(this.alipayConfig.getThirdParty().getUrl());
            
            // 设置Cookie头
            httpPost.setHeader("Cookie", "CAMEName=");
            BigDecimal totalFeeYuan = BigDecimal.valueOf(totalFee / 100f);
            // 构建multipart/form-data请求体
            HttpEntity entity = MultipartEntityBuilder.create()
                    .addTextBody("notify_url", notifyUrl)
                    .addTextBody("out_trade_no", outTradeNo)
                    .addTextBody("total_fee", String.valueOf(totalFeeYuan))
                    .addTextBody("ServiceOrdID", serviceOrdId)
                    .build();
            
            httpPost.setEntity(entity);
            
            log.info("发送请求到第三方接口: {}", this.alipayConfig.getThirdParty().getUrl());
            
            // 发送请求
            try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
                int statusCode = response.getStatusLine().getStatusCode();
                String responseBody = EntityUtils.toString(response.getEntity(), "UTF-8");
                
                log.info("第三方接口响应,状态码: {}, 响应内容: {}", statusCode, responseBody);
                
                if (statusCode >= 200 && statusCode < 300) {
                    // 响应成功,解析返回的URL
                    String qrCodeUrl = parseQrCodeUrl(responseBody);
                    
                    if (qrCodeUrl == null || qrCodeUrl.isEmpty()) {
                        throw new Exception("第三方接口未返回有效的支付URL,响应: " + responseBody);
                    }
                    
                    log.info("第三方支付宝当面付URL生成成功: {}", qrCodeUrl);
                    return qrCodeUrl;
                } else {
                    throw new Exception("第三方接口调用失败,状态码: " + statusCode + ", 响应: " + responseBody);
                }
            }
        } catch (Exception e) {
            log.error("调用第三方支付宝当面付接口失败", e);
            throw new Exception("调用第三方支付宝当面付接口失败: " + e.getMessage(), e);
        }
    }
 
    /**
     * 解析第三方接口响应,提取支付URL
     * 根据实际返回格式调整解析逻辑
     * 
     * @param responseBody 响应内容
     * @return 支付URL
     */
    private String parseQrCodeUrl(String responseBody) {
        // TODO: 根据实际返回格式调整解析逻辑
        // 这里假设直接返回URL字符串,或者返回JSON格式
        
        if (responseBody == null || responseBody.isEmpty()) {
            return null;
        }
        
        // 去除可能的引号和空白字符
        String url = responseBody.trim();
        if (url.startsWith("\"") && url.endsWith("\"")) {
            url = url.substring(1, url.length() - 1);
        }
        
        // 如果是JSON格式,可以使用FastJSON解析
        // 示例:{"status": "success", "qr_code": "https://..."}
        // JSONObject json = JSON.parseObject(responseBody);
        // return json.getString("qr_code");
        
        return url;
    }
 
    /**
     * 查询支付宝交易状态
     * 
     * @param outTradeNo 商户订单号
     * @return 交易状态(SUCCESS-成功,其他-失败或处理中)
     * @throws Exception 调用异常
     */
    public String queryTradeStatus(String outTradeNo) throws Exception {
        log.info("调用第三方支付宝查询接口,订单号: {}", outTradeNo);
 
        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpPost httpPost = new HttpPost(THIRD_PARTY_QUERY_URL);
            
            // 设置Cookie头
            httpPost.setHeader("Cookie", "CAMEName=");
            
            // 构建multipart/form-data请求体
            HttpEntity entity = MultipartEntityBuilder.create()
                    .addTextBody("out_trade_no", outTradeNo)
                    .build();
            
            httpPost.setEntity(entity);
            
            log.info("发送查询请求到第三方接口: {}", THIRD_PARTY_QUERY_URL);
            
            // 发送请求
            try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
                int statusCode = response.getStatusLine().getStatusCode();
                String responseBody = EntityUtils.toString(response.getEntity(), "UTF-8");
                
                log.info("第三方查询接口响应,状态码: {}, 响应内容: {}", statusCode, responseBody);
                
                if (statusCode >= 200 && statusCode < 300) {
                    // 响应成功,解析交易状态
                    String tradeStatus = parseTradeStatus(responseBody);
                    
                    log.info("第三方支付宝交易查询成功,订单号: {}, 状态: {}", outTradeNo, tradeStatus);
                    return tradeStatus;
                } else {
                    throw new Exception("第三方查询接口调用失败,状态码: " + statusCode + ", 响应: " + responseBody);
                }
            }
        } catch (Exception e) {
            log.error("调用第三方支付宝查询接口失败", e);
            throw new Exception("调用第三方支付宝查询接口失败: " + e.getMessage(), e);
        }
    }
 
    /**
     * 解析交易状态
     * 
     * @param responseBody 响应内容
     * @return 交易状态
     */
    private String parseTradeStatus(String responseBody) {
        if (responseBody == null || responseBody.isEmpty()) {
            return "UNKNOWN";
        }
        
        // 去除空白字符
        String status = responseBody.trim();
        
        // 去除可能的引号
        if (status.startsWith("\"") && status.endsWith("\"")) {
            status = status.substring(1, status.length() - 1);
        }
        
        // 转换为大写
        status = status.toUpperCase();
        
        log.info("解析交易状态: {}", status);
        
        return status;
    }
}