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