优化微信支付和支付宝支付的配置文件的结构
This commit is contained in:
parent
1c5b40771d
commit
bbceb171eb
@ -58,7 +58,7 @@ public class AliPayConfig {
|
||||
}
|
||||
|
||||
@Bean
|
||||
protected Config config() throws Exception {
|
||||
protected Config alipayBaseConfig() throws Exception {
|
||||
// 设置参数(全局只需设置一次)
|
||||
Config config = new Config();
|
||||
config.protocol = "https";
|
||||
|
@ -64,7 +64,6 @@ public class AliPayController {
|
||||
Map<String, String[]> requestParams = request.getParameterMap();
|
||||
for (String name : requestParams.keySet()) {
|
||||
params.put(name, request.getParameter(name));
|
||||
// System.out.println(name + " = " + request.getParameter(name));
|
||||
}
|
||||
|
||||
String orderNumber = params.get("out_trade_no");
|
||||
|
@ -25,10 +25,10 @@ import org.apache.http.ssl.SSLContextBuilder;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
|
||||
public class HttpUtil {
|
||||
public static String httpPostWithoutException(String url, String string,String sign,String sn) {
|
||||
public static String httpPostWithoutException(String url, String string, String sign, String sn) {
|
||||
String xmlRes = "{}";
|
||||
try {
|
||||
xmlRes = httpPost(url, string,sign,sn);
|
||||
xmlRes = httpPost(url, string, sign, sn);
|
||||
} catch (UnrecoverableKeyException e) {
|
||||
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
@ -40,36 +40,33 @@ public class HttpUtil {
|
||||
}
|
||||
return xmlRes;
|
||||
}
|
||||
|
||||
/**
|
||||
* http POST 请求
|
||||
*
|
||||
* @param url:请求地址
|
||||
* @param body: body实体字符串
|
||||
* @param sign:签名
|
||||
* @param sn: 序列号
|
||||
* @return
|
||||
*/
|
||||
public static String httpPost(String url, String body,String sign,String sn) throws UnrecoverableKeyException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
|
||||
public static String httpPost(String url, String body, String sign, String sn)
|
||||
throws UnrecoverableKeyException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
|
||||
String xmlRes = "{}";
|
||||
HttpClient client = createSSLClientDefault();
|
||||
HttpPost httpost = new HttpPost(url);
|
||||
try {
|
||||
System.out.println("Request string: " + body);
|
||||
//所有请求的body都需采用UTF-8编码
|
||||
StringEntity entity = new StringEntity(body,"UTF-8");//
|
||||
// 所有请求的body都需采用UTF-8编码
|
||||
StringEntity entity = new StringEntity(body, "UTF-8");//
|
||||
entity.setContentType("application/json");
|
||||
httpost.setEntity(entity);
|
||||
|
||||
//支付平台所有的API仅支持JSON格式的请求调用,HTTP请求头Content-Type设为application/json
|
||||
httpost.addHeader("Content-Type","application/json");
|
||||
|
||||
//支付平台所有的API调用都需要签名验证,签名首部: Authorization: sn + " " + sign
|
||||
httpost.addHeader("Authorization",sn + " " + sign);
|
||||
System.out.println("Authorization" + sn + " " + sign);
|
||||
// 支付平台所有的API仅支持JSON格式的请求调用,HTTP请求头Content-Type设为application/json
|
||||
httpost.addHeader("Content-Type", "application/json");
|
||||
// 支付平台所有的API调用都需要签名验证,签名首部: Authorization: sn + " " + sign
|
||||
httpost.addHeader("Authorization", sn + " " + sign);
|
||||
HttpResponse response = client.execute(httpost);
|
||||
|
||||
//所有响应也采用UTF-8编码
|
||||
// 所有响应也采用UTF-8编码
|
||||
xmlRes = EntityUtils.toString(response.getEntity(), "UTF-8");
|
||||
System.out.println("Response string: " + xmlRes);
|
||||
} catch (ClientProtocolException e) {
|
||||
|
||||
} catch (IOException e) {
|
||||
@ -81,7 +78,7 @@ public class HttpUtil {
|
||||
public static CloseableHttpClient createSSLClientDefault() {
|
||||
try {
|
||||
SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
|
||||
//信任所有
|
||||
// 信任所有
|
||||
public boolean isTrusted(X509Certificate[] chain,
|
||||
String authType) throws CertificateException {
|
||||
return true;
|
||||
@ -99,23 +96,20 @@ public class HttpUtil {
|
||||
return HttpClients.createDefault();
|
||||
}
|
||||
|
||||
public static String doGet(String url,String parameter)
|
||||
{
|
||||
String uriAPI =url+"?"+parameter ; //"http://XX?str=I+am+get+String";
|
||||
String result= "";
|
||||
public static String doGet(String url, String parameter) {
|
||||
String uriAPI = url + "?" + parameter; // "http://XX?str=I+am+get+String";
|
||||
String result = "";
|
||||
HttpClient client = createSSLClientDefault();
|
||||
HttpGet httpRequst = new HttpGet(uriAPI);
|
||||
try {
|
||||
|
||||
HttpResponse httpResponse = client.execute(httpRequst);//其中HttpGet是HttpUriRequst的子类
|
||||
if(httpResponse.getStatusLine().getStatusCode() == 200)
|
||||
{
|
||||
HttpResponse httpResponse = client.execute(httpRequst);// 其中HttpGet是HttpUriRequst的子类
|
||||
if (httpResponse.getStatusLine().getStatusCode() == 200) {
|
||||
HttpEntity httpEntity = httpResponse.getEntity();
|
||||
result = EntityUtils.toString(httpEntity);//取出应答字符串
|
||||
result = EntityUtils.toString(httpEntity);// 取出应答字符串
|
||||
// 一般来说都要删除多余的字符
|
||||
result.replaceAll("\r", "");//去掉返回结果中的"\r"字符,否则会在结果字符串后面显示一个小方格
|
||||
}
|
||||
else
|
||||
result.replaceAll("\r", "");// 去掉返回结果中的"\r"字符,否则会在结果字符串后面显示一个小方格
|
||||
} else
|
||||
httpRequst.abort();
|
||||
} catch (ClientProtocolException e) {
|
||||
e.printStackTrace();
|
||||
|
@ -1,17 +1,27 @@
|
||||
package com.ruoyi.pay.wx.config;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.io.Resource;
|
||||
|
||||
import lombok.Data;
|
||||
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
|
||||
import com.wechat.pay.java.core.notification.NotificationParser;
|
||||
import com.wechat.pay.java.service.payments.nativepay.NativePayService;
|
||||
|
||||
/**
|
||||
* 配置我们自己的信息
|
||||
*
|
||||
* @author ZlH
|
||||
*/
|
||||
@Data
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "wechat")
|
||||
public class WxPayAppConfig {
|
||||
@ -20,6 +30,7 @@ public class WxPayAppConfig {
|
||||
private String wxchantId;
|
||||
@Value("${pay.wechat.merchantSerialNumber}")
|
||||
private String wxchantSerialNumber;
|
||||
|
||||
@Value("${pay.wechat.apiV3Key}")
|
||||
private String wxapiV3Key;
|
||||
@Value("${pay.wechat.privateKeyPath}")
|
||||
@ -29,4 +40,81 @@ public class WxPayAppConfig {
|
||||
@Value("${pay.wechat.notifyUrl}")
|
||||
private String notifyUrl;
|
||||
|
||||
@Bean
|
||||
public RSAAutoCertificateConfig wxpayBaseConfig() throws Exception {
|
||||
return new RSAAutoCertificateConfig.Builder()
|
||||
.merchantId(getWxchantId())
|
||||
.privateKeyFromPath(getWxcertPath())
|
||||
.merchantSerialNumber(getWxchantSerialNumber())
|
||||
.apiV3Key(getWxapiV3Key())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public NativePayService nativePayService() throws Exception {
|
||||
return new NativePayService.Builder().config(wxpayBaseConfig()).build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public NotificationParser notificationParser() throws Exception {
|
||||
return new NotificationParser(wxpayBaseConfig());
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
public String getWxcertPath() throws Exception {
|
||||
if (wxcertPath.startsWith("classpath:")) {
|
||||
Resource resource = applicationContext.getResource(wxcertPath);
|
||||
String tempFilePath = System.getProperty("java.io.tmpdir") + "/temp_wxcert.pem";
|
||||
try (InputStream inputStream = resource.getInputStream()) {
|
||||
Files.copy(inputStream, Paths.get(tempFilePath), StandardCopyOption.REPLACE_EXISTING);
|
||||
wxcertPath = tempFilePath;
|
||||
} catch (Exception e) {
|
||||
Files.deleteIfExists(Paths.get(tempFilePath));
|
||||
throw new RuntimeException("微信支付证书文件读取失败", e);
|
||||
}
|
||||
}
|
||||
return wxcertPath;
|
||||
}
|
||||
|
||||
public String getWxchantId() {
|
||||
return wxchantId;
|
||||
}
|
||||
|
||||
public void setWxchantId(String wxchantId) {
|
||||
this.wxchantId = wxchantId;
|
||||
}
|
||||
|
||||
public String getWxchantSerialNumber() {
|
||||
return wxchantSerialNumber;
|
||||
}
|
||||
|
||||
public void setWxchantSerialNumber(String wxchantSerialNumber) {
|
||||
this.wxchantSerialNumber = wxchantSerialNumber;
|
||||
}
|
||||
|
||||
public String getWxapiV3Key() {
|
||||
return wxapiV3Key;
|
||||
}
|
||||
|
||||
public void setWxapiV3Key(String wxapiV3Key) {
|
||||
this.wxapiV3Key = wxapiV3Key;
|
||||
}
|
||||
|
||||
public String getAppId() {
|
||||
return appId;
|
||||
}
|
||||
|
||||
public void setAppId(String appId) {
|
||||
this.appId = appId;
|
||||
}
|
||||
|
||||
public String getNotifyUrl() {
|
||||
return notifyUrl;
|
||||
}
|
||||
|
||||
public void setNotifyUrl(String notifyUrl) {
|
||||
this.notifyUrl = notifyUrl;
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,13 @@
|
||||
package com.ruoyi.pay.wx.controller;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.util.StreamUtils;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@ -12,18 +17,26 @@ import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.pay.domain.PayOrder;
|
||||
import com.ruoyi.pay.service.IPayOrderService;
|
||||
import com.ruoyi.pay.wx.config.WxPayAppConfig;
|
||||
import com.wechat.pay.java.core.Config;
|
||||
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
|
||||
import com.wechat.pay.java.core.exception.ValidationException;
|
||||
import com.wechat.pay.java.core.notification.NotificationParser;
|
||||
import com.wechat.pay.java.core.notification.RequestParam;
|
||||
import com.wechat.pay.java.service.payments.nativepay.NativePayService;
|
||||
import com.wechat.pay.java.service.payments.nativepay.model.Amount;
|
||||
import com.wechat.pay.java.service.payments.nativepay.model.PrepayRequest;
|
||||
import com.wechat.pay.java.service.payments.nativepay.model.PrepayResponse;
|
||||
import com.wechat.pay.java.service.wexinpayscoreparking.model.Transaction;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.Parameters;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* @author zlh
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/wxPay")
|
||||
public class WxAppPayController extends BaseController {
|
||||
@ -31,22 +44,18 @@ public class WxAppPayController extends BaseController {
|
||||
private WxPayAppConfig wxPayAppConfig;
|
||||
@Autowired
|
||||
private IPayOrderService payOrderService;
|
||||
@Anonymous
|
||||
|
||||
@Autowired
|
||||
private NativePayService nativePayService;
|
||||
@Autowired
|
||||
private NotificationParser notificationParser;
|
||||
|
||||
@Operation(summary = "微信支付")
|
||||
@Parameters({
|
||||
@Parameter(name = "orderNumber", description = "订单号", required = true)
|
||||
})
|
||||
@GetMapping("/pay/{orderNumber}")
|
||||
public AjaxResult pay(@PathVariable String orderNumber) {
|
||||
// 使用自动更新平台证书的RSA配置
|
||||
// 一个商户号只能初始化一个配置,否则会因为重复的下载任务报错
|
||||
Config config =
|
||||
new RSAAutoCertificateConfig.Builder()
|
||||
.merchantId(wxPayAppConfig.getWxchantId())
|
||||
.privateKeyFromPath(wxPayAppConfig.getWxcertPath())
|
||||
.merchantSerialNumber(wxPayAppConfig.getWxchantSerialNumber())
|
||||
.apiV3Key(wxPayAppConfig.getWxapiV3Key())
|
||||
.build();
|
||||
// 构建service
|
||||
NativePayService service = new NativePayService.Builder().config(config).build();
|
||||
// request.setXxx(val)设置所需参数,具体参数可见Request定义
|
||||
public AjaxResult pay(@PathVariable String orderNumber) throws Exception {
|
||||
PayOrder aliPay = payOrderService.selectPayOrderByOrderNumber(orderNumber);
|
||||
String amountStr = aliPay.getTotalAmount();
|
||||
double amountDouble = Double.parseDouble(amountStr);
|
||||
@ -60,48 +69,44 @@ public class WxAppPayController extends BaseController {
|
||||
request.setDescription(aliPay.getOrderContent());
|
||||
request.setNotifyUrl(wxPayAppConfig.getNotifyUrl());
|
||||
request.setOutTradeNo(aliPay.getOrderNumber());
|
||||
// 调用下单方法,得到应答
|
||||
PrepayResponse response = service.prepay(request);
|
||||
// 使用微信扫描 code_url 对应的二维码,即可体验Native支付
|
||||
PrepayResponse response = nativePayService.prepay(request);
|
||||
return AjaxResult.success(response.getCodeUrl());
|
||||
}
|
||||
|
||||
// @Anonymous
|
||||
// @Operation(summary = "微信支付查询订单")
|
||||
// @GetMapping("/notify")
|
||||
// public AjaxResult WxPayList() {
|
||||
// System.out.println("=========支付宝异步回调========");
|
||||
// // 构造 RequestParam
|
||||
// RequestParam requestParam = new RequestParam.Builder()
|
||||
// .serialNumber("wechatPaySerial")
|
||||
// .nonce("wechatpayNonce")
|
||||
// .signature("wechatSignature")
|
||||
// .timestamp("wechatTimestamp")
|
||||
// .body("requestBody")
|
||||
// .build();
|
||||
//
|
||||
//// 如果已经初始化了 RSAAutoCertificateConfig,可直接使用
|
||||
//// 没有的话,则构造一个
|
||||
// NotificationConfig config = new RSAAutoCertificateConfig.Builder()
|
||||
// .merchantId(merchantId)
|
||||
// .privateKeyFromPath(privateKeyPath)
|
||||
// .merchantSerialNumber(merchantSerialNumber)
|
||||
// .apiV3Key(apiV3Key)
|
||||
// .build();
|
||||
//
|
||||
//// 初始化 NotificationParser
|
||||
// NotificationParser parser = new NotificationParser(config);
|
||||
//
|
||||
// try {
|
||||
// // 以支付通知回调为例,验签、解密并转换成 Transaction
|
||||
// Transaction transaction = parser.parse(requestParam, Transaction.class);
|
||||
// } catch (ValidationException e) {
|
||||
// // 签名验证失败,返回 401 UNAUTHORIZED 状态码
|
||||
// logger.error("sign verification failed", e);
|
||||
// return AjaxResult.success(HttpStatus.UNAUTHORIZED);
|
||||
// }
|
||||
//// 处理成功,返回 200 OK 状态码
|
||||
// return AjaxResult.success(HttpStatus.OK);
|
||||
// }
|
||||
@Anonymous
|
||||
@Operation(summary = "微信支付查询订单")
|
||||
@PostMapping("/notify")
|
||||
public AjaxResult WxPayList(HttpServletRequest servletRequest, HttpServletResponse response)
|
||||
throws Exception {
|
||||
log.info("=========微信异步回调========");
|
||||
|
||||
String timeStamp = servletRequest.getHeader("Wechatpay-Timestamp");
|
||||
String nonce = servletRequest.getHeader("Wechatpay-Nonce");
|
||||
String signature = servletRequest.getHeader("Wechatpay-Signature");
|
||||
String certSn = servletRequest.getHeader("Wechatpay-Serial");
|
||||
|
||||
try {
|
||||
String requestBody = StreamUtils.copyToString(servletRequest.getInputStream(), StandardCharsets.UTF_8);
|
||||
RequestParam requestParam = new RequestParam.Builder()
|
||||
.serialNumber(certSn)
|
||||
.nonce(nonce)
|
||||
.signature(signature)
|
||||
.timestamp(timeStamp)
|
||||
.body(requestBody)
|
||||
.build();
|
||||
|
||||
try {
|
||||
Transaction transaction = notificationParser.parse(requestParam, Transaction.class);
|
||||
String orderNumber = transaction.getOutTradeNo();
|
||||
payOrderService.updateStatus(orderNumber, "已支付");
|
||||
return success();
|
||||
} catch (ValidationException e) {
|
||||
return error();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.error("Error reading request body", e);
|
||||
throw new RuntimeException("Error reading request body", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user