From 8e2885684576861643e1bca3cb0d540d933780e1 Mon Sep 17 00:00:00 2001 From: quyixiao <2621048238@qq.com> Date: Thu, 6 Nov 2025 12:46:35 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/heyu/api/jsapi/JsapiPrepay.java | 1 - .../com/heyu/api/config}/JSAPIConfig.java | 11 ++- .../api/controller/vv/AppOrderController.java | 8 ++ .../vv/AppWeiXinPayNotifyController.java | 88 +++++++++++++++++++ .../src/main/resources/bootstrap-dev.yml | 5 +- .../src/main/resources/bootstrap-online.yml | 11 ++- .../src/main/resources/bootstrap.yml | 4 + 7 files changed, 121 insertions(+), 7 deletions(-) rename {api-third/src/main/java/com/heyu/api/jsapi => api-web/api-interface/src/main/java/com/heyu/api/config}/JSAPIConfig.java (68%) create mode 100644 api-web/api-interface/src/main/java/com/heyu/api/controller/vv/AppWeiXinPayNotifyController.java diff --git a/api-third/src/main/java/com/heyu/api/jsapi/JsapiPrepay.java b/api-third/src/main/java/com/heyu/api/jsapi/JsapiPrepay.java index 7d0693e..2b63c20 100644 --- a/api-third/src/main/java/com/heyu/api/jsapi/JsapiPrepay.java +++ b/api-third/src/main/java/com/heyu/api/jsapi/JsapiPrepay.java @@ -36,7 +36,6 @@ public class JsapiPrepay { public JsapiPrepay() { } - public JsapiPrepay(String mchid, String certificateSerialNo, String privateKeyFilePath, String wechatPayPublicKeyId, String wechatPayPublicKeyFilePath) { this.mchid = mchid; this.certificateSerialNo = certificateSerialNo; diff --git a/api-third/src/main/java/com/heyu/api/jsapi/JSAPIConfig.java b/api-web/api-interface/src/main/java/com/heyu/api/config/JSAPIConfig.java similarity index 68% rename from api-third/src/main/java/com/heyu/api/jsapi/JSAPIConfig.java rename to api-web/api-interface/src/main/java/com/heyu/api/config/JSAPIConfig.java index 226de57..4515c0b 100644 --- a/api-third/src/main/java/com/heyu/api/jsapi/JSAPIConfig.java +++ b/api-web/api-interface/src/main/java/com/heyu/api/config/JSAPIConfig.java @@ -1,5 +1,6 @@ -package com.heyu.api.jsapi; +package com.heyu.api.config; +import com.heyu.api.jsapi.JsapiPrepay; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; @@ -9,13 +10,19 @@ import org.springframework.context.annotation.Configuration; @Slf4j public class JSAPIConfig { - @Bean public JsapiPrepay jsapiPrepay(@Value("${eb.config.weixin.pay.mchid}") String mchid, @Value("${eb.config.weixin.pay.certificateSerialNo}") String certificateSerialNo, @Value("${eb.config.weixin.pay.privateKeyFilePath}") String privateKeyFilePath, @Value("${eb.config.weixin.pay.wechatPayPublicKeyId}") String wechatPayPublicKeyId, @Value("${eb.config.weixin.pay.wechatPayPublicKeyFilePath}") String wechatPayPublicKeyFilePath) { + + log.info("JSAPIConfig jsapiPrepay init mchid:{}," + + "certificateSerialNo:{}," + + "privateKeyFilePath:{}," + + "wechatPayPublicKeyId:{}," + + "wechatPayPublicKeyFilePath:{}", + mchid, certificateSerialNo, privateKeyFilePath, wechatPayPublicKeyId, wechatPayPublicKeyFilePath); return new JsapiPrepay(mchid, certificateSerialNo, privateKeyFilePath, wechatPayPublicKeyId, wechatPayPublicKeyFilePath); } diff --git a/api-web/api-interface/src/main/java/com/heyu/api/controller/vv/AppOrderController.java b/api-web/api-interface/src/main/java/com/heyu/api/controller/vv/AppOrderController.java index f4ea187..fee11ec 100644 --- a/api-web/api-interface/src/main/java/com/heyu/api/controller/vv/AppOrderController.java +++ b/api-web/api-interface/src/main/java/com/heyu/api/controller/vv/AppOrderController.java @@ -267,6 +267,7 @@ public class AppOrderController { VvTradeOrderEntity vvTradeOrderEntity = new VvTradeOrderEntity(); VvBuyerEntity vvBuyerEntity = vvBuyerDao.selectVvBuyerById(vvOrderRequest.getBuyerId()); + //创建时间 vvTradeOrderEntity.setCreateTime(new Date()); vvTradeOrderEntity.setModifyTime(new Date()); @@ -286,6 +287,7 @@ public class AppOrderController { vvTradeOrderEntity.setBuyerId(vvOrderRequest.getBuyerId()); vvTradeOrderEntity.setCreateTimestamp(System.currentTimeMillis()); vvTradeOrderEntity.setModifyTimestamp(System.currentTimeMillis()); + vvTradeOrderDao.insertVvTradeOrder(vvTradeOrderEntity); for (VvTradeOrderLineEntity tradeOrderLineEntity : vvTradeOrderLineEntityList) { tradeOrderLineEntity.setTradeOrderId(vvTradeOrderEntity.getId()); @@ -299,6 +301,12 @@ public class AppOrderController { for (Map.Entry map : productNumMap.entrySet()) { vvProductDao.updateShowSaleCountAndSaleCount(map.getValue(), map.getValue(), map.getKey()); } + + + + + + return R.ok("订单创建成功"); } diff --git a/api-web/api-interface/src/main/java/com/heyu/api/controller/vv/AppWeiXinPayNotifyController.java b/api-web/api-interface/src/main/java/com/heyu/api/controller/vv/AppWeiXinPayNotifyController.java new file mode 100644 index 0000000..dcfe2d4 --- /dev/null +++ b/api-web/api-interface/src/main/java/com/heyu/api/controller/vv/AppWeiXinPayNotifyController.java @@ -0,0 +1,88 @@ +package com.heyu.api.controller.vv; + + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.heyu.api.common.annotation.Describe; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.crypto.Cipher; +import javax.crypto.spec.GCMParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import java.nio.charset.StandardCharsets; +import java.security.Key; +import java.util.Base64; + +@Slf4j +@RestController +@RequestMapping("/app/weixin") +public class AppWeiXinPayNotifyController { + + + // 微信支付APIv3密钥 + @Value("${eb.config.weixin.pay.apiv3key}") + private String apiv3key; + + @Describe("微信支付回调") + @PostMapping("/payNotify") + public String handleWeChatPayCallback(@RequestBody String requestBody) { + try { + // Step 1: 解析微信支付回调通知的JSON + ObjectMapper objectMapper = new ObjectMapper(); + JsonNode rootNode = objectMapper.readTree(requestBody); + + // 获取加密数据 + String ciphertext = rootNode.get("resource").get("ciphertext").asText(); + String associatedData = rootNode.get("resource").get("associated_data").asText(); + String nonce = rootNode.get("resource").get("nonce").asText(); + // Step 2: 解密加密数据,使用AES-GCM解密 + String decryptedData = decrypt(ciphertext, associatedData, nonce); + + // Step 3: 处理解密后的数据 + JsonNode resultData = objectMapper.readTree(decryptedData); + String transactionId = resultData.get("transaction_id").asText(); // 微信支付订单号 + String outTradeNo = resultData.get("out_trade_no").asText(); // 商户订单号 + String tradeState = resultData.get("trade_state").asText(); // 支付状态 + // 根据支付结果处理商户业务逻辑 + if ("SUCCESS".equals(tradeState)) { + // 支付成功的逻辑,更新订单状态 + updateOrderStatus(outTradeNo, transactionId); + } + // Step 4: 返回处理结果,通知微信支付停止回调 + return "{\"code\":\"SUCCESS\",\"message\":\"OK\"}"; + + } catch (Exception e) { + e.printStackTrace(); + // 如果处理失败,返回错误信息 + return "{\"code\":\"FAIL\",\"message\":\"Server Error\"}"; + } + } + + // AES-GCM解密方法 + private String decrypt(String ciphertext, String associatedData, String nonce) throws Exception { + // 将APIv3密钥转为字节数组 + byte[] key = apiv3key.getBytes(StandardCharsets.UTF_8); + Key secretKey = new SecretKeySpec(key, "AES"); + + // 使用AES-GCM解密 + Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); + GCMParameterSpec spec = new GCMParameterSpec(128, nonce.getBytes(StandardCharsets.UTF_8)); + cipher.init(Cipher.DECRYPT_MODE, secretKey, spec); + cipher.updateAAD(associatedData.getBytes(StandardCharsets.UTF_8)); + byte[] decodedCiphertext = Base64.getDecoder().decode(ciphertext); + byte[] decryptedData = cipher.doFinal(decodedCiphertext); + + return new String(decryptedData, StandardCharsets.UTF_8); + } + + private void updateOrderStatus(String outTradeNo, String transactionId) { + // 这里是更新商户订单状态的逻辑,例如标记订单已支付 + System.out.println("订单 " + outTradeNo + " 已支付,交易号:" + transactionId); + } + +} diff --git a/api-web/api-interface/src/main/resources/bootstrap-dev.yml b/api-web/api-interface/src/main/resources/bootstrap-dev.yml index 64722f7..71531aa 100644 --- a/api-web/api-interface/src/main/resources/bootstrap-dev.yml +++ b/api-web/api-interface/src/main/resources/bootstrap-dev.yml @@ -66,11 +66,12 @@ eb: pay: mchid: 1731491745 certificateSerialNo: 793D48CCEB62C6B227E0A4F46AD90279B149A7BE - privateKey: /Users/quyixiao/Desktop/weixincert/apiclient_key.pem + privateKeyFilePath: /Users/quyixiao/Desktop/weixincert/apiclient_key.pem wechatPayPublicKeyId: PUB_KEY_ID_0117314917452025110400382304001401 - wechatPayPublicKey: /Users/quyixiao/Desktop/weixincert/wxp_pub.pem + wechatPayPublicKeyFilePath: /Users/quyixiao/Desktop/weixincert/wxp_pub.pem appid: wx75fa59c097bd3dfd notifyUrl: https://api.1024api.com/api-interface/app/weixin/payNotify + apiv3key: E938F17ABF6843743F49688269F73B7D diff --git a/api-web/api-interface/src/main/resources/bootstrap-online.yml b/api-web/api-interface/src/main/resources/bootstrap-online.yml index 7b54842..7d486b3 100644 --- a/api-web/api-interface/src/main/resources/bootstrap-online.yml +++ b/api-web/api-interface/src/main/resources/bootstrap-online.yml @@ -61,10 +61,17 @@ eb: pay: mchid: 1731491745 certificateSerialNo: 793D48CCEB62C6B227E0A4F46AD90279B149A7BE - privateKey: /Users/quyixiao/Desktop/weixincert/apiclient_key.pem + privateKeyFilePath: /mnt/admin/weixincert/apiclient_key.pem wechatPayPublicKeyId: PUB_KEY_ID_0117314917452025110400382304001401 - wechatPayPublicKey: /Users/quyixiao/Desktop/weixincert/wxp_pub.pem + wechatPayPublicKeyFilePath: /mnt/admin/weixincert/wxp_pub.pem appid: wx75fa59c097bd3dfd notifyUrl: https://api.1024api.com/api-interface/app/weixin/payNotify + apiv3key: E938F17ABF6843743F49688269F73B7D + + + + + + diff --git a/api-web/api-interface/src/main/resources/bootstrap.yml b/api-web/api-interface/src/main/resources/bootstrap.yml index 217ee86..68c7f79 100644 --- a/api-web/api-interface/src/main/resources/bootstrap.yml +++ b/api-web/api-interface/src/main/resources/bootstrap.yml @@ -64,6 +64,9 @@ eb: delayExchangeName: DELAY_EXCHANGE_NAME_TEST + + + tencent: face: ak: AKIDCxZyA9xZx8D6lFZfcLsBHH3e1A8uTqzu @@ -74,6 +77,7 @@ aliyun: alibaba_cloud_access_key_id: LTAI5tP6oAnNbbxJ357o28Hp alibaba_cloud_access_key_secret: 60LMF88f52wzviDfcpjuZEouZImGO6 + oss: config: endpoint: oss-cn-hangzhou.aliyuncs.com