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;
|
}
|
}
|