微信小程序支付ApiV3版本java开发的完整案例
时间: 2024-01-13 11:02:14 浏览: 98
以下是微信小程序支付ApiV3版本java开发的完整案例:
1. 首先,你需要在微信商户平台上创建一个应用并获取到以下信息:
- 商户号(mch_id)
- 商户APIv3密钥(api_key)
- 应用ID(appid)
- 商户证书私钥文件(apiclient_key.pem)
- 商户证书文件(apiclient_cert.pem)
- 微信支付平台证书文件(weixinpay_cert.pem)
2. 接下来,你需要使用Java SDK进行开发,包括以下步骤:
- 导入相关的Java SDK依赖包。
- 构建请求参数,包括HTTP请求头和请求体,其中请求体需要使用商户证书进行签名。
- 发送HTTP请求,并处理响应数据。
以下是一个简单的Java代码片段,演示如何使用Java SDK实现微信小程序支付ApiV3版本:
```
import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayConstants;
import com.github.wxpay.sdk.WXPayUtil;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHeaders;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.Map;
public class WxPayApiV3Demo {
private static final String API_KEY = "商户APIv3密钥";
private static final String MCH_ID = "商户号";
private static final String APP_ID = "应用ID";
private static final String API_BASE_URL = "https://api.mch.weixin.qq.com/";
private static final String PRIVATE_KEY_FILE = "apiclient_key.pem";
private static final String CERT_FILE = "apiclient_cert.pem";
private static final String WEIXINPAY_CERT_FILE = "weixinpay_cert.pem";
private static final String CHARSET = StandardCharsets.UTF_8.name();
private static final String API_PAY = "v3/pay/transactions/jsapi";
private static final String API_CERTIFICATE = "v3/certificates";
private static PrivateKey privateKey;
private static X509Certificate certificate;
private static X509Certificate weixinpayCertificate;
static {
try {
privateKey = loadPrivateKey(new File(PRIVATE_KEY_FILE));
certificate = loadCertificate(new File(CERT_FILE));
weixinpayCertificate = loadCertificate(new File(WEIXINPAY_CERT_FILE));
} catch (Exception e) {
throw new RuntimeException("Failed to load certificate.", e);
}
}
public static void main(String[] args) throws Exception {
// 构建请求参数
Map<String, String> params = new HashMap<>();
params.put("appid", APP_ID);
params.put("mchid", MCH_ID);
params.put("description", "测试商品");
params.put("out_trade_no", "1234567890");
params.put("amount", "{\"total\":100,\"currency\":\"CNY\"}");
params.put("payer", "{\"openid\":\"用户openid\"}");
params.put("notify_url", "https://example.com/notify");
// 发送HTTP请求
String response = doPost(API_PAY, params);
System.out.println(response);
}
private static String doPost(String api, Map<String, String> params) throws Exception {
String url = API_BASE_URL + api;
String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
// 构建请求头
Map<String, String> headers = new HashMap<>();
headers.put(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.getMimeType());
headers.put(HttpHeaders.AUTHORIZATION, buildAuthorizationHeader(api, timestamp, params));
// 构建请求体
String requestBody = WXPayUtil.mapToXml(params);
String signature = sign(requestBody, timestamp);
String signedRequestBody = buildSignedRequestBody(requestBody, signature);
// 发送HTTP请求
HttpPost httpPost = new HttpPost(url);
headers.forEach(httpPost::addHeader);
httpPost.setEntity(new StringEntity(signedRequestBody, CHARSET));
try (CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse httpResponse = httpClient.execute(httpPost)) {
HttpEntity entity = httpResponse.getEntity();
return IOUtils.toString(entity.getContent(), CHARSET);
}
}
private static String buildAuthorizationHeader(String api, String timestamp, Map<String, String> params) throws Exception {
String nonceStr = WXPayUtil.generateUUID();
String message = buildMessage(api, timestamp, nonceStr, params);
String signature = sign(message);
return String.format("WECHATPAY2-SHA256-RSA2048 mchid=\"%s\",nonce_str=\"%s\",timestamp=\"%s\",serial_no=\"%s\",signature=\"%s\"",
MCH_ID, nonceStr, timestamp, weixinpayCertificate.getSerialNumber().toString(16), signature);
}
private static String buildMessage(String api, String timestamp, String nonceStr, Map<String, String> params) {
StringBuilder sb = new StringBuilder();
sb.append("POST\n")
.append(API_BASE_URL).append(api).append("\n")
.append(buildQueryString(params)).append("\n")
.append(HttpHeaders.CONTENT_TYPE).append(":").append(ContentType.APPLICATION_JSON.getMimeType()).append("\n")
.append(HttpHeaders.ACCEPT).append(":").append(ContentType.APPLICATION_JSON.getMimeType()).append("\n")
.append(HttpHeaders.AUTHORIZATION).append(":").append(buildAuthorizationHeader(api, timestamp, params)).append("\n")
.append("Wechatpay-Timestamp:").append(timestamp).append("\n")
.append("Wechatpay-Nonce:").append(nonceStr).append("\n")
.append("Wechatpay-Serial:").append(weixinpayCertificate.getSerialNumber().toString(16)).append("\n");
return sb.toString();
}
private static String buildQueryString(Map<String, String> params) {
StringBuilder sb = new StringBuilder();
params.entrySet().stream()
.sorted(Map.Entry.comparingByKey())
.forEach(entry -> {
if (sb.length() > 0) {
sb.append("&");
}
sb.append(entry.getKey()).append("=").append(entry.getValue());
});
return sb.toString();
}
private static String sign(String message) throws Exception {
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initSign(privateKey);
signature.update(message.getBytes(StandardCharsets.UTF_8));
return Base64.encodeBase64String(signature.sign());
}
private static String sign(String requestBody, String timestamp) throws Exception {
StringBuilder sb = new StringBuilder();
sb.append(timestamp).append("\n")
.append(nonceStr()).append("\n")
.append(requestBody).append("\n");
return sign(sb.toString());
}
private static String buildSignedRequestBody(String requestBody, String signature) {
return requestBody.replace("</xml>", String.format("<sign_type><![CDATA[SHA256]]></sign_type><sign><![CDATA[%s]]></sign></xml>", signature));
}
private static String nonceStr() {
return WXPayUtil.generateUUID();
}
private static PrivateKey loadPrivateKey(File file) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
byte[] bytes = FileUtils.readFileToByteArray(file);
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(bytes);
KeyFactory factory = KeyFactory.getInstance("RSA");
return factory.generatePrivate(spec);
}
private static X509Certificate loadCertificate(File file) throws IOException, CertificateException {
byte[] bytes = FileUtils.readFileToByteArray(file);
return WXPayUtil.loadCertificate(bytes);
}
}
```
上述代码中,我们使用了微信提供的Java SDK(https://github.com/wechatpay-apiv3/wechatpay-apache-httpclient),它封装了HTTP请求和签名验证的相关逻辑,并提供了一些实用的工具类。在这个示例中,我们使用了WXPayUtil工具类来进行签名、验签和XML格式的转换。我们还使用了Apache HttpClient来发送HTTP请求。
需要注意的是,该示例中使用的是微信提供的Java SDK中的最新版本,如果你使用的是旧版本,可能会存在一些差异。
此外,该示例中只演示了如何实现支付接口,如果你需要实现其他接口,可以参考微信官方文档(https://wechatpay-api.gitbook.io/wechatpay-api-v3/)。
阅读全文