From 26cb0486f0772b425ab65fa1500c598511970d2e Mon Sep 17 00:00:00 2001
From: KKSU <15274802129@163.com>
Date: Wed, 17 Jan 2024 13:59:02 +0800
Subject: [PATCH] fapiao
---
src/main/java/cc/mrbird/febs/pay/controller/XcxPayController.java | 5
src/main/java/cc/mrbird/febs/pay/service/WxFaPiaoService.java | 6 +
src/main/java/cc/mrbird/febs/pay/service/impl/WxFaPiaoServiceImpl.java | 257 +++++++++++++++++++++++++++++---------------------
3 files changed, 156 insertions(+), 112 deletions(-)
diff --git a/src/main/java/cc/mrbird/febs/pay/controller/XcxPayController.java b/src/main/java/cc/mrbird/febs/pay/controller/XcxPayController.java
index fef552f..71679fa 100644
--- a/src/main/java/cc/mrbird/febs/pay/controller/XcxPayController.java
+++ b/src/main/java/cc/mrbird/febs/pay/controller/XcxPayController.java
@@ -27,6 +27,7 @@
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@@ -249,8 +250,8 @@
*/
@Transactional(rollbackFor = Exception.class)
@RequestMapping(value = "/fapiaoCallBack")
- public Map<String, Object> fapiaoCallBack(HttpServletResponse response, HttpServletRequest request) throws IOException {
- return wxFaPiaoService.fapiaoCallBack(response,request);
+ public Map<String, Object> fapiaoCallBack(HttpServletRequest request, @RequestBody Map<String, Object> requestBody) throws IOException {
+ return wxFaPiaoService.fapiaoCallBack(request,requestBody);
}
diff --git a/src/main/java/cc/mrbird/febs/pay/service/WxFaPiaoService.java b/src/main/java/cc/mrbird/febs/pay/service/WxFaPiaoService.java
index 333cabb..f2a1d16 100644
--- a/src/main/java/cc/mrbird/febs/pay/service/WxFaPiaoService.java
+++ b/src/main/java/cc/mrbird/febs/pay/service/WxFaPiaoService.java
@@ -1,11 +1,15 @@
package cc.mrbird.febs.pay.service;
+import org.springframework.web.bind.annotation.RequestBody;
+
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
+import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
+import java.security.SignatureException;
import java.util.Map;
public interface WxFaPiaoService {
@@ -18,5 +22,5 @@
String sendPost(String url, String params, String token);
- Map<String, Object> fapiaoCallBack(HttpServletResponse response, HttpServletRequest request);
+ Map<String, Object> fapiaoCallBack(HttpServletRequest request, @RequestBody Map<String, Object> requestBody) throws IOException, NoSuchAlgorithmException, InvalidKeyException, SignatureException;
}
diff --git a/src/main/java/cc/mrbird/febs/pay/service/impl/WxFaPiaoServiceImpl.java b/src/main/java/cc/mrbird/febs/pay/service/impl/WxFaPiaoServiceImpl.java
index fecfbbf..f35b58f 100644
--- a/src/main/java/cc/mrbird/febs/pay/service/impl/WxFaPiaoServiceImpl.java
+++ b/src/main/java/cc/mrbird/febs/pay/service/impl/WxFaPiaoServiceImpl.java
@@ -20,6 +20,7 @@
import com.wechat.pay.contrib.apache.httpclient.notification.NotificationHandler;
import com.wechat.pay.contrib.apache.httpclient.notification.NotificationRequest;
import com.wechat.pay.contrib.apache.httpclient.util.AesUtil;
+import com.wechat.pay.java.core.notification.Resource;
import io.undertow.util.Certificates;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
@@ -37,12 +38,15 @@
import org.apache.http.util.EntityUtils;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
+import org.springframework.util.Base64Utils;
+import org.springframework.web.bind.annotation.RequestBody;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.security.*;
+import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
@@ -206,77 +210,162 @@
}
@Override
- public Map<String, Object> fapiaoCallBack(HttpServletResponse response, HttpServletRequest request) {
+ public Map<String, Object> fapiaoCallBack(HttpServletRequest request, @RequestBody Map<String, Object> requestBody) throws IOException, NoSuchAlgorithmException, InvalidKeyException, SignatureException {
Map<String,Object> map = new HashMap<>();
- try {
- BufferedReader br = request.getReader();
- String str = null;
- StringBuilder sb = new StringBuilder();
- while ((str = br.readLine())!=null) {
- sb.append(str);
- }
- // 构建request,传入必要参数
-// NotificationRequest requests = new NotificationRequest.Builder()
-// .withSerialNumber(request.getHeader("Wechatpay-Serial"))
-// .withNonce(request.getHeader("Wechatpay-Nonce"))
-// .withTimestamp(request.getHeader("Wechatpay-Timestamp"))
-// .withSignature(request.getHeader("Wechatpay-Signature"))
-// .withBody(String.valueOf(sb))
-// .build();
- log.info("微信电子发票回调接口...."+request.getHeader("Wechatpay-Serial"));
- log.info("微信电子发票回调接口...."+request.getHeader("Wechatpay-Nonce"));
- log.info("微信电子发票回调接口...."+request.getHeader("Wechatpay-Timestamp"));
- log.info("微信电子发票回调接口...."+request.getHeader("Wechatpay-Signature"));
+ String signature = request.getHeader("Wechatpay-Signature");
+ String timestamp = request.getHeader("Wechatpay-Timestamp");
+ String nonce = request.getHeader("Wechatpay-Nonce");
+ //平台证书序列号不是API证书序列号
+ String serial = request.getHeader("Wechatpay-Serial");
+ String body = com.alibaba.fastjson.JSONObject.toJSONString(requestBody);
+ log.info("头信息---签名:" + signature);
+ log.info("头信息---时间戳:" + timestamp);
+ log.info("头信息---随机字符:" + nonce);
+ log.info("头信息---平台证书序列号:" + serial);
+ log.info("获取到的body信息:" + body);
+ //验签
+ boolean signCheck = verifySign(request, body);
+// boolean signCheck = signCheck(timestamp, nonce, requestBody, signature);
+ log.info("验签结果:" + signCheck);
+ if (signCheck) {
+// //解密参数
+// Resource resource = com.alibaba.fastjson.JSONObject.parseObject(com.alibaba.fastjson.JSONObject.toJSONString(requestBody.get("resource")), Resource.class);
+// AesUtil aesUtil = new AesUtil(CommonParameters.apiV3Key.getBytes("utf-8"));
+// String string = aesUtil.decryptToString(resource.getAssociated_data().getBytes("utf-8"), resource.getNonce().getBytes("utf-8"), resource.getCiphertext());
+// ComplaintInfo complaintInfo = JSONObject.parseObject(string, ComplaintInfo.class);
+// //获取投诉详情
+// ComplaintDetail complaintDetail = CommonUtils.GetComplaintsInfo(complaintInfo.getComplaint_id());
+// data.put("code", "SUCCESS");
+// data.put("message", "成功");
+// return data;
+ try {
+ //解析请求体
+// Resource resource = com.alibaba.fastjson.JSONObject.parseObject(com.alibaba.fastjson.JSONObject.toJSONString(requestBody.get("resource")), Resource.class);
+ Notification notification = com.alibaba.fastjson.JSONObject.parseObject(String.valueOf(body),Notification.class);
+ log.info("微信电子发票回调接口....解析请求体:"+notification.toString());
+ String decryptData = notification.getDecryptData();//可能是支付业务的回调数据
+ log.info("微信电子发票回调接口....decryptData:"+notification.toString());
+ Notification.Resource resource = notification.getResource();//电子发票的回调加密数据
+ log.info("微信电子发票回调接口....resource:"+notification.toString());
- log.info("微信电子发票回调接口....body"+request.getHeader(String.valueOf(sb)));
- //验签
-// NotificationHandler handler = new NotificationHandler(getVerifier(AppContants.WX_CARD_NUM), xcxProperties.getWecharpaySecretV3().getBytes(StandardCharsets.UTF_8));
- //解析请求体
-// Notification notification = handler.parse(requests);
- Notification notification = com.alibaba.fastjson.JSONObject.parseObject(String.valueOf(sb),Notification.class);
- log.info("微信电子发票回调接口....解析请求体:"+notification.toString());
- String decryptData = notification.getDecryptData();//可能是支付业务的回调数据
- log.info("微信电子发票回调接口....decryptData:"+notification.toString());
- Notification.Resource resource = notification.getResource();//电子发票的回调加密数据
- log.info("微信电子发票回调接口....resource:"+notification.toString());
+ if ("FAPIAO.USER_APPLIED".equals(notification.getEventType())//用户发票抬头填写完成类型:FAPIAO.USER_APPLIED
+ && !"encryptresource".equals(notification.getResourceType())) {//通知的资源数据类型,确认成功通知为encryptresource。
+ //解密
+ AesUtil aesUtil = new AesUtil(xcxProperties.getWecharpaySecretV3().getBytes("utf-8"));
+ String decryptToString = aesUtil.decryptToString(
+ resource.getAssociatedData().getBytes("utf-8"),
+ resource.getNonce().getBytes("utf-8"),
+ resource.getCiphertext());
+ log.info("微信电子发票回调接口....resource解密:"+decryptToString);
- if ("FAPIAO.USER_APPLIED".equals(notification.getEventType())//用户发票抬头填写完成类型:FAPIAO.USER_APPLIED
- && !"encryptresource".equals(notification.getResourceType())) {//通知的资源数据类型,确认成功通知为encryptresource。
- //解密
- AesUtil aesUtil = new AesUtil(xcxProperties.getWecharpaySecretV3().getBytes("utf-8"));
- String decryptToString = aesUtil.decryptToString(
- resource.getAssociatedData().getBytes("utf-8"),
- resource.getNonce().getBytes("utf-8"),
- resource.getCiphertext());
- log.info("微信电子发票回调接口....resource解密:"+decryptToString);
+ JSONObject parseObj = JSONUtil.parseObj(decryptToString);
- JSONObject parseObj = JSONUtil.parseObj(decryptToString);
+ log.info("微信电子发票回调接口....resource解密-JSONObject:"+parseObj);
- log.info("微信电子发票回调接口....resource解密-JSONObject:"+parseObj);
-
- String mchid = String.valueOf(parseObj.get("mchid"));
- String fapiao_apply_id = String.valueOf(parseObj.get("fapiao_apply_id"));
- String apply_time = String.valueOf(parseObj.get("apply_time"));
- MallOrderInfo mallOrderInfo = mallOrderInfoMapper.selectByOrderNo(fapiao_apply_id);
- if(ObjectUtil.isNotEmpty(mallOrderInfo)){
- //省略查询订单
- //此处处理业务
- map.put("code","SUCCESS");
- map.put("message","成功");
- //消息推送成功
- return map;
+ String mchid = String.valueOf(parseObj.get("mchid"));
+ String fapiao_apply_id = String.valueOf(parseObj.get("fapiao_apply_id"));
+ String apply_time = String.valueOf(parseObj.get("apply_time"));
+ MallOrderInfo mallOrderInfo = mallOrderInfoMapper.selectByOrderNo(fapiao_apply_id);
+ if(ObjectUtil.isNotEmpty(mallOrderInfo)){
+ //省略查询订单
+ //此处处理业务
+ map.put("code","SUCCESS");
+ map.put("message","成功");
+ //消息推送成功
+ return map;
+ }
}
+ map.put("code","RESOURCE_NOT_EXISTS");
+ map.put("message", "订单不存在");
+ return map;
+ }catch (Exception e) {
+ e.printStackTrace();
}
- map.put("code","RESOURCE_NOT_EXISTS");
- map.put("message", "订单不存在");
- return map;
- }catch (Exception e) {
- e.printStackTrace();
}
map.put("code","FAIL");
map.put("message", "失败");
return map;
}
+
+// /**
+// * 验证签名
+// *
+// * @param timestamp 微信平台传入的时间戳
+// * @param nonce 微信平台传入的随机字符串
+// * @param requestBody 微信平台传入的消息体
+// * @param signature 微信平台传入的签名
+// * @return
+// * @throws NoSuchAlgorithmException
+// * @throws SignatureException
+// * @throws IOException
+// * @throws InvalidKeyException
+// */
+// public static boolean signCheck(String timestamp, String nonce, Map<String, Object> requestBody, String signature) throws NoSuchAlgorithmException, SignatureException, IOException, InvalidKeyException {
+// //构造验签名串
+// String signatureStr = timestamp + "\n" + nonce + "\n" + com.alibaba.fastjson.JSONObject.toJSONString(requestBody) + "\n";
+// // 加载SHA256withRSA签名器
+// Signature signer = Signature.getInstance("SHA256withRSA");
+// // 用微信平台公钥对签名器进行初始化(调上一节中的获取平台证书方法)
+// signer.initVerify(getCertificates());
+// // 把我们构造的验签名串更新到签名器中
+// signer.update(signatureStr.getBytes(StandardCharsets.UTF_8));
+// // 把请求头中微信服务器返回的签名用Base64解码 并使用签名器进行验证
+// boolean result = signer.verify(Base64Utils.decodeFromString(signature));
+// return result;
+// }
+
+
+ /**
+ * 获取平台证书
+ */
+// public static X509Certificate getCertificates() throws IOException, NoSuchAlgorithmException, SignatureException, InvalidKeyException {
+// SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
+// CloseableHttpClient httpClient = CommonUtils.httpClient();
+// //请求URL
+// HttpGet httpGet = new HttpGet("https://api.mch.weixin.qq.com/v3/certificates");
+// httpGet.setHeader("Accept", "application/json");
+// //生成签名
+// httpGet.setHeader("Authorization ", SignUtils.getSign("GET", HttpUrl.parse("https://api.mch.weixin.qq.com/v3/certificates"), ""));
+// httpGet.setHeader("User-Agent", "https://zh.wikipedia.org/wiki/User_agent");
+// //完成签名并执行请求
+// CloseableHttpResponse response = httpClient.execute(httpGet);
+// X509Certificate x509Certificate = null;
+// try {
+// int statusCode = response.getStatusLine().getStatusCode();
+// if (statusCode == 200) { //处理成功
+//// System.out.println("success,return body = " + EntityUtils.toString(response.getEntity()));
+// CertificateVo certificateVo = JSONObject.parseObject(EntityUtils.toString(response.getEntity()), CertificateVo.class);
+// for (Certificates certificates : certificateVo.getData()) {
+// if (format.parse(certificates.getEffective_time()).before(new Date()) && format.parse(certificates.getExpire_time()).after(new Date())) {
+// EncryptCertificate encrypt_certificate = certificates.getEncrypt_certificate();
+// //解密
+// AesUtil aesUtil = new AesUtil(CommonParameters.apiV3Key.getBytes("utf-8"));
+// String pulicKey = aesUtil.decryptToString(encrypt_certificate.getAssociated_data().getBytes("utf-8"), encrypt_certificate.getNonce().getBytes("utf-8"), encrypt_certificate.getCiphertext());
+//
+// //获取平台证书
+// final CertificateFactory cf = CertificateFactory.getInstance("X509");
+//
+// ByteArrayInputStream inputStream = new ByteArrayInputStream(pulicKey.getBytes(StandardCharsets.UTF_8));
+//
+// x509Certificate = (X509Certificate) cf.generateCertificate(inputStream);
+// }
+// }
+// return x509Certificate;
+// } else if (statusCode == 204) { //处理成功,无返回Body
+// System.out.println("success");
+// return x509Certificate;
+// } else {
+// System.out.println("failed,resp code = " + statusCode + ",return body = " + EntityUtils.toString(response.getEntity()));
+// return x509Certificate;
+// }
+// } catch (GeneralSecurityException | ParseException e) {
+// e.printStackTrace();
+// return null;
+// } finally {
+// response.close();
+// CommonUtils.after(httpClient);
+// }
+// }
/**
* 功能描述: 验证签名
@@ -357,56 +446,6 @@
}
return verifier;
}
-
- /**
- * 获取平台证书
- */
-// public static X509Certificate getCertificates() throws IOException, NoSuchAlgorithmException, SignatureException, InvalidKeyException {
-// SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
-// CloseableHttpClient httpClient = HttpClients.createDefault();
-// //请求URL
-// HttpGet httpGet = new HttpGet("https://api.mch.weixin.qq.com/v3/certificates");
-// httpGet.setHeader("Accept", "application/json");
-// //生成签名
-// httpGet.setHeader("Authorization ", SignUtils.getSign("GET", HttpUrl.parse("https://api.mch.weixin.qq.com/v3/certificates"), ""));
-// httpGet.setHeader("User-Agent", "https://zh.wikipedia.org/wiki/User_agent");
-// //完成签名并执行请求
-// CloseableHttpResponse response = httpClient.execute(httpGet);
-// X509Certificate x509Certificate = null;
-// try {
-// int statusCode = response.getStatusLine().getStatusCode();
-// if (statusCode == 200) { //处理成功
-//// System.out.println("success,return body = " + EntityUtils.toString(response.getEntity()));
-// CertificateVo certificateVo = JSONObject.parseObject(EntityUtils.toString(response.getEntity()), CertificateVo.class);
-// for (Certificates certificates : certificateVo.getData()) {
-// if (format.parse(certificates.getEffective_time()).before(new Date()) && format.parse(certificates.getExpire_time()).after(new Date())) {
-// EncryptCertificate encrypt_certificate = certificates.getEncrypt_certificate();
-// //解密
-// AesUtil aesUtil = new AesUtil(CommonParameters.apiV3Key.getBytes("utf-8"));
-// String pulicKey = aesUtil.decryptToString(encrypt_certificate.getAssociated_data().getBytes("utf-8"), encrypt_certificate.getNonce().getBytes("utf-8"), encrypt_certificate.getCiphertext());
-// //获取平台证书 final CertificateFactory cf = CertificateFactory.getInstance("X509");
-//
-// ByteArrayInputStream inputStream = new ByteArrayInputStream(pulicKey.getBytes(StandardCharsets.UTF_8));
-//
-// x509Certificate = (X509Certificate) cf.generateCertificate(inputStream);
-// }
-// }
-// return x509Certificate;
-// } else if (statusCode == 204) { //处理成功,无返回Body
-// System.out.println("success");
-// return x509Certificate;
-// } else {
-// System.out.println("failed,resp code = " + statusCode + ",return body = " + EntityUtils.toString(response.getEntity()));
-// return x509Certificate;
-// }
-// } catch (GeneralSecurityException | ParseException e) {
-// e.printStackTrace();
-// return null;
-// } finally {
-// response.close();
-// CommonUtils.after(httpClient);
-// }
-// }
/**
--
Gitblit v1.9.1