package com.sunvitek.application.creditdata.controller;
import java.io.File;
import java.io.FileInputStream;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import com.github.wxpay.sdk.WXPayUtil;
import okhttp3.HttpUrl;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
public class WeChatRefund {
private static final String API_URL = "https://api.mch.weixin.qq.com/v3/refund/domestic/refunds";
private static final String MCH_ID = ""; // 商户号
private static final String PRIVATE_KEY_PATH = "F:\\项目文件\\配置文件\\001\\apiclient_key.pem"; // 私钥路径
private static final String CERT_SERIAL_NO = ""; // 证书序列号
public static String refund(String transactionId, String outTradeNo, String outRefundNo, String reason, String notifyUrl, int refundAmount, int totalAmount, String currency) throws Exception {
// 创建退款请求参数
Map<String, Object> data = new HashMap<>();
data.put("out_trade_no", "");
data.put("out_refund_no", ""); // 这里需要的是字符串
// 构建 amount 字段
Map<String, Object> amount = new HashMap<>();
amount.put("refund", 2); // 应为整数
amount.put("total", 2); // 应为整数
amount.put("currency", "CNY");
data.put("amount", amount);
// 将参数转换为JSON
ObjectMapper objectMapper = new ObjectMapper();
String jsonParams = objectMapper.writeValueAsString(data);
// 创建HTTP客户端
CloseableHttpClient httpClient = HttpClients.createDefault();
try {
HttpPost httpPost = new HttpPost(API_URL);
httpPost.setHeader("Accept", "application/json");
httpPost.setHeader("Content-Type", "application/json");
httpPost.setHeader("Authorization", "WECHATPAY2-SHA256-RSA2048 " + generateAuthorizationHeader("POST", API_URL, jsonParams));
StringEntity entity = new StringEntity(jsonParams, "UTF-8");
httpPost.setEntity(entity);
// 执行请求
HttpResponse response = httpClient.execute(httpPost);
String responseString = EntityUtils.toString(response.getEntity(), "UTF-8");
return responseString;
} finally {
httpClient.close();
}
}
private static String generateAuthorizationHeader(String method, String url, String body) throws Exception {
HttpUrl httpUrl = HttpUrl.parse(url);
String nonceStr = WXPayUtil.generateNonceStr();
long timestamp = System.currentTimeMillis() / 1000;
String message = buildMessage(method, httpUrl, timestamp, nonceStr, body);
String signature = sign(message.getBytes("utf-8"));
return "mchid=\"" + MCH_ID + "\","
+ "nonce_str=\"" + nonceStr + "\","
+ "timestamp=\"" + timestamp + "\","
+ "serial_no=\"" + CERT_SERIAL_NO + "\","
+ "signature=\"" + signature + "\"";
}
private static String sign(byte[] message) throws Exception {
PrivateKey privateKey = loadPrivateKey(PRIVATE_KEY_PATH);
Signature sign = Signature.getInstance("SHA256withRSA");
sign.initSign(privateKey);
sign.update(message);
return Base64.getEncoder().encodeToString(sign.sign());
}
private static PrivateKey loadPrivateKey(String privateKeyPath) throws Exception {
// 加载私钥文件
try (FileInputStream fis = new FileInputStream(privateKeyPath)) {
byte[] keyBytes = new byte[fis.available()];
fis.read(keyBytes);
String privateKeyPem = new String(keyBytes)
.replace("-----BEGIN PRIVATE KEY-----", "")
.replace("-----END PRIVATE KEY-----", "")
.replaceAll("\\s", "");
byte[] decoded = Base64.getDecoder().decode(privateKeyPem);
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(decoded);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
return keyFactory.generatePrivate(spec);
}
}
private static String buildMessage(String method, HttpUrl url, long timestamp, String nonceStr, String body) {
String canonicalUrl = url.encodedPath();
if (url.encodedQuery() != null) {
canonicalUrl += "?" + url.encodedQuery();
}
return method + "\n"
+ canonicalUrl + "\n"
+ timestamp + "\n"
+ nonceStr + "\n"
+ body + "\n";
}
public static void main(String[] args) {
try {
String result = refund("your_transaction_id", null, "your_out_refund_no", "Refund Reason", "your_notify_url", 2, 2, "CNY");
System.out.println(result);
} catch (Exception e) {
e.printStackTrace();
}
}
}
03-28
02-27
3928
04-02