From 0b6c174db343bb3b76c5deec566749f721997a74 Mon Sep 17 00:00:00 2001
From: lin <sbla5888@163.com>
Date: Tue, 12 Mar 2024 17:59:58 +0800
Subject: [PATCH] 从业人员信息录入
---
src/main/java/org/springblade/modules/pay/service/impl/WxPayServiceImpl.java | 248 ++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 242 insertions(+), 6 deletions(-)
diff --git a/src/main/java/org/springblade/modules/pay/service/impl/WxPayServiceImpl.java b/src/main/java/org/springblade/modules/pay/service/impl/WxPayServiceImpl.java
index 206c764..08b67fe 100644
--- a/src/main/java/org/springblade/modules/pay/service/impl/WxPayServiceImpl.java
+++ b/src/main/java/org/springblade/modules/pay/service/impl/WxPayServiceImpl.java
@@ -1,25 +1,261 @@
package org.springblade.modules.pay.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.github.wxpay.sdk.WXPayUtil;
+import com.google.gson.Gson;
+import com.wechat.pay.contrib.apache.httpclient.util.AesUtil;
+import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.util.EntityUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springblade.common.enums.OrderStatus;
+import org.springblade.common.enums.wxpay.WxApiType;
+import org.springblade.common.enums.wxpay.WxNotifyType;
+import org.springblade.modules.pay.controller.WxPayController;
import org.springblade.modules.pay.entity.WxPayInfo;
import org.springblade.modules.pay.mapper.WxPayMapper;
import org.springblade.modules.pay.service.IWxPayService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.security.*;
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.ReentrantLock;
+
@Service
public class WxPayServiceImpl extends ServiceImpl<WxPayMapper,WxPayInfo> implements IWxPayService {
private final String MINI_PROGRAM_APP_ID = "wx41aa8a5d2e565a05";
+ private static final Logger logger = LoggerFactory.getLogger(WxPayServiceImpl.class);
+
+ private final ReentrantLock lock = new ReentrantLock();
@Override
public Object getOpenId(String code) {
-
-
-
-
-
-
return null;
}
+
+ @Override
+ public Map<String, String> jsapiPay(Long productId) throws IOException {
+
+ String prepayId = "";
+ //生成订单
+// OrderInfo orderInfo = orderInfoService.createOrderByProductId(productId);
+
+
+ logger.info("调用统一下单API");
+
+// //调用统一下单API
+// HttpPost httpPost = new HttpPost(wxPayConfig.getDomain().concat(WxApiType.JSAPI_PAY.getType()));
+//
+// // 请求body参数
+//
+// Gson gson = new Gson();
+// Map paramsMap = new HashMap();
+// paramsMap.put("appid", wxPayConfig.getAppid());
+// paramsMap.put("mchid", wxPayConfig.getMchId());
+// paramsMap.put("description", orderInfo.getTitle());
+// paramsMap.put("out_trade_no", orderInfo.getOrderNo());
+// paramsMap.put("notify_url", wxPayConfig.getNotifyDomain().concat(WxNotifyType.NATIVE_NOTIFY.getType()));
+//
+// Map amountMap = new HashMap();
+// amountMap.put("total", orderInfo.getTotalFee());
+// amountMap.put("currency", "CNY");
+//
+// paramsMap.put("amount", amountMap);
+//
+// Map payerMap = new HashMap();
+// payerMap.put("openid", "oSX3G6OUuGaKJbWzSHUpPbzgtDXo");
+//
+// paramsMap.put("payer", payerMap);
+//
+// //将参数转换成json字符串
+// String jsonParams = gson.toJson(paramsMap);
+// logger.info("请求参数 ===> {}" + jsonParams);
+//
+// StringEntity entity = new StringEntity(jsonParams, "utf-8");
+// entity.setContentType("application/json");
+// httpPost.setEntity(entity);
+// httpPost.setHeader("Accept", "application/json");
+//
+// //完成签名并执行请求
+// CloseableHttpResponse response = wxPayClient.execute(httpPost);
+//
+// try {
+// String bodyAsString = EntityUtils.toString(response.getEntity());//响应体
+// int statusCode = response.getStatusLine().getStatusCode();//响应状态码
+// if (statusCode == 200) { //处理成功
+// logger.info("成功, 返回结果 = " + bodyAsString);
+// } else if (statusCode == 204) { //处理成功,无返回Body
+// logger.info("成功");
+// } else {
+// logger.info("jszpi下单失败,响应码 = " + statusCode + ",返回结果 = " + bodyAsString);
+// throw new IOException("request failed");
+// }
+// //响应结果
+// Map<String, String> resultMap = gson.fromJson(bodyAsString, HashMap.class);
+// //预支付交易会话标识
+// prepayId = resultMap.get("prepay_id");
+//
+// //返回预支付交易会话标识
+// // 组装前端预下单参数
+// /** 返回给前端所需要的数据 */
+// SortedMap<String, String> payMap = new TreeMap<>();
+// String nonceStr = WXPayUtil.generateNonceStr();
+// String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
+// payMap.put("appId", wxPayConfig.getAppid());
+// payMap.put("timeStamp", timestamp);
+// payMap.put("nonceStr", nonceStr);
+// payMap.put("signType", "RSA");
+// payMap.put("package", "prepay_id=" + prepayId);
+// String paySign = getSign(wxPayConfig.getAppid(), prepayId, timestamp, nonceStr);
+// payMap.put("paySign", paySign);
+// logger.info("返回参数 ===> {}" + gson.toJson(payMap));
+// return payMap;
+// } finally {
+// response.close();
+// }
+ return null;
+ }
+
+ @Override
+ public void processOrder(Map<String, Object> bodyMap) throws GeneralSecurityException {
+ logger.info("处理订单");
+
+ //解密报文
+ String plainText = decryptFromResource(bodyMap);
+
+ //将明文转换成map
+ Gson gson = new Gson();
+ HashMap plainTextMap = gson.fromJson(plainText, HashMap.class);
+ String orderNo = (String) plainTextMap.get("out_trade_no");
+
+
+ /*在对业务数据进行状态检查和处理之前,
+ 要采用数据锁进行并发控制,
+ 以避免函数重入造成的数据混乱*/
+ //尝试获取锁:
+ // 成功获取则立即返回true,获取失败则立即返回false。不必一直等待锁的释放
+// if (lock.tryLock()) {
+// try {
+// //处理重复的通知
+// //接口调用的幂等性:无论接口被调用多少次,产生的结果是一致的。
+// String orderStatus = orderInfoService.getOrderStatus(orderNo);
+// if (!OrderStatus.NOTPAY.getType().equals(orderStatus)) {
+// return;
+// }
+//
+// //模拟通知并发
+// try {
+// TimeUnit.SECONDS.sleep(5);
+// } catch (InterruptedException e) {
+// e.printStackTrace();
+// }
+//
+// //更新订单状态
+// orderInfoService.updateStatusByOrderNo(orderNo, OrderStatus.SUCCESS);
+//
+// //记录支付日志
+// paymentInfoService.createPaymentInfo(plainText);
+// } finally {
+// //要主动释放锁
+// lock.unlock();
+// }
+// }
+ }
+
+ /**
+ * 通过prepay_id获取签名
+ *
+ * @param appid
+ * @param prepay_id
+ * @param timestamp
+ * @param nonceStr
+ * @return
+ * @throws IOException
+ * @throws SignatureException
+ * @throws NoSuchAlgorithmException
+ * @throws InvalidKeyException
+ */
+ String getSign(String appid, String prepay_id, String timestamp, String nonceStr) throws IOException, SignatureException, NoSuchAlgorithmException, InvalidKeyException {
+ //从下往上依次生成
+ String message = getSignStr(appid, timestamp, nonceStr, "prepay_id=" + prepay_id);
+ //签名
+ String signature = sign(message.getBytes("utf-8"));
+ return signature;
+ }
+
+ String sign(byte[] message) throws NoSuchAlgorithmException, SignatureException, IOException, InvalidKeyException {
+ //签名方式
+ Signature sign = Signature.getInstance("SHA256withRSA");
+ //私钥,通过MyPrivateKey来获取,这是个静态类可以接调用方法 ,需要的是_key.pem文件的绝对路径配上文件名
+// sign.initSign(getPrivateKey(wxPayConfig.getPrivateKeyPath()));
+ sign.update(message);
+
+ return Base64.getEncoder().encodeToString(sign.sign());
+ }
+
+ /**
+ * 按照前端签名文档规范进行排序
+ *
+ * @param appId
+ * @param timeStamp
+ * @param nonceStr
+ * @param packageValue
+ * @return
+ */
+ private String getSignStr(String appId, String timeStamp, String nonceStr, String packageValue) {
+ return String.format("%s\n%s\n%s\n%s\n", appId, timeStamp, nonceStr, packageValue);
+ }
+
+ private PrivateKey getPrivateKey(String filename) {
+
+ try {
+ FileInputStream fileInputStream = new FileInputStream(filename);
+ logger.info("文件内容:" + fileInputStream);
+ return PemUtil.loadPrivateKey(fileInputStream);
+ } catch (Exception e) {
+ logger.info("私钥文件不存在", e);
+ throw new RuntimeException("私钥文件不存在", e);
+ }
+ }
+
+ /**
+ * 对称解密
+ *
+ * @param bodyMap
+ * @return
+ */
+ private String decryptFromResource(Map<String, Object> bodyMap) throws GeneralSecurityException {
+
+ logger.info("密文解密");
+
+ //通知数据
+ Map<String, String> resourceMap = (Map) bodyMap.get("resource");
+ //数据密文
+ String ciphertext = resourceMap.get("ciphertext");
+ //随机串
+ String nonce = resourceMap.get("nonce");
+ //附加数据
+ String associatedData = resourceMap.get("associated_data");
+
+ logger.info("密文 ===> {}", ciphertext);
+// AesUtil aesUtil = new AesUtil(wxPayConfig.getApiV3Key().getBytes(StandardCharsets.UTF_8));
+// String plainText = aesUtil.decryptToString(associatedData.getBytes(StandardCharsets.UTF_8),
+// nonce.getBytes(StandardCharsets.UTF_8),
+// ciphertext);
+
+// logger.info("明文 ===> {}", plainText);
+
+// return plainText;
+ return null;
+ }
+
}
--
Gitblit v1.9.3