From 86e7119cfb6d592b82387c05a8e2d5f2eb4a88aa Mon Sep 17 00:00:00 2001 From: xupei Date: Fri, 31 May 2024 16:28:23 +0800 Subject: [PATCH] =?UTF-8?q?AlipayHK=20=E5=9B=9E=E8=B0=83=E5=8F=8A=E7=9B=B8?= =?UTF-8?q?=E5=85=B3=E6=95=B0=E6=8D=AE=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- files/COD-public-key.txt | 9 ++++ .../common/utils/AlipayHKEncryptionUtil.java | 35 +++++++------- .../da/common/utils/AlipayHKRequestUtil.java | 4 +- .../ai/da/controller/AlipayHKController.java | 6 +-- .../da/mapper/primary/entity/PaymentInfo.java | 2 +- .../ai/da/model/dto/AlipayHKCallbackDTO.java | 2 +- .../com/ai/da/service/AlipayHKService.java | 4 +- .../com/ai/da/service/CreditsService.java | 2 +- .../ai/da/service/impl/AliPayServiceImpl.java | 4 +- .../da/service/impl/AlipayHKServiceImpl.java | 46 +++++++++++-------- .../da/service/impl/CreditsServiceImpl.java | 2 +- .../impl/PayPalCheckoutServiceImpl.java | 4 +- .../service/impl/PaymentInfoServiceImpl.java | 14 +++--- src/main/resources/alipay-sandbox.properties | 4 +- src/main/resources/application-dev.properties | 6 ++- 15 files changed, 84 insertions(+), 60 deletions(-) create mode 100644 files/COD-public-key.txt diff --git a/files/COD-public-key.txt b/files/COD-public-key.txt new file mode 100644 index 00000000..ec172ee3 --- /dev/null +++ b/files/COD-public-key.txt @@ -0,0 +1,9 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAymkBAWixxUi9IAeMWgsq + K92AzFbe0qzzYPdkoh15ymL2A5MkYH7asnhFwclgdiFmd9a0TbZP+t/SzWW8UUzN + 1pXoEp48R+eguGTt5xkJwb10+H6quVXF/Ezzid5yzVW3dcYRp8qUlFr0XBpvkK9l + FpPzh2+mwVEAsgBMXq/K50ZiX2dlkPZ7ffkVPWaK2ESIo3YgfM6dmiiza0hPWJ35 + UgTH5rwJ7vN3IdOJTlkQOvrIrj2ocPcrudeEwqybIbCGhgRBwQSBsXQOO4U//rE4 + VU+0LF/3uQgXkvVY1+a1JLiTncZYKGEQ/NtxM+dGtYWV2gPhQRyJ7Z77OX0XCbcn + zwIDAQAB +-----END PUBLIC KEY----- \ No newline at end of file diff --git a/src/main/java/com/ai/da/common/utils/AlipayHKEncryptionUtil.java b/src/main/java/com/ai/da/common/utils/AlipayHKEncryptionUtil.java index a26d60a0..3b706563 100644 --- a/src/main/java/com/ai/da/common/utils/AlipayHKEncryptionUtil.java +++ b/src/main/java/com/ai/da/common/utils/AlipayHKEncryptionUtil.java @@ -50,6 +50,9 @@ public class AlipayHKEncryptionUtil { @Value("${alipayHK.rsaPublicKey}") private String publicKeyPath; + @Value("${alipayHK.CODPublicKey}") + private String CODPublicKeyPath; + /** * 加密 @@ -70,7 +73,8 @@ public class AlipayHKEncryptionUtil { // The path to the rsa private key file, DO NOT save this key to a publicly accessible location // 使用私钥创建数字签名 // Mode, aes-128-cbc for 128bit key - String mode = "aes-128-cbc"; +// String mode = "aes-128-cbc"; + String mode = "aes-256-cbc"; // Padding mode String padding = "pkcs7"; // signature alogrithm @@ -84,14 +88,6 @@ public class AlipayHKEncryptionUtil { requestMessage.setRequest_uuid(UUID.randomUUID().toString()); // HashMap param = new HashMap<>(); requestMessage.setParameters(param); - /*String orderRef = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")); - param.put("order_ref", orderRef); - param.put("amount", 208.12); - param.put("subject", "四月帳單 April Bill"); - param.put("wallet", "ALIPAYHK"); - param.put("segment_id", segmentId); - param.put("payment_solution", "WAP");*/ - // Serialize message body Gson gson = new GsonBuilder().disableHtmlEscaping().create(); @@ -342,18 +338,25 @@ public class AlipayHKEncryptionUtil { Base64.Decoder decoder = Base64.getDecoder(); // Verify key try { -// PublicKey publicKey = readPublicKey(new File(publicKeyPath)); - InputStreamReader isrPub = new InputStreamReader(new FileInputStream(publicKeyPath)); + // 从指定的路径读取公钥文件 + InputStreamReader isrPub = new InputStreamReader(new FileInputStream(CODPublicKeyPath)); PEMParser pemParserPub = new PEMParser(isrPub); + // 使用 PEMParser 解析公钥文件 SubjectPublicKeyInfo pubInfo = (SubjectPublicKeyInfo) pemParserPub.readObject(); + // 从 SubjectPublicKeyInfo 创建 AsymmetricKeyParameter 对象 AsymmetricKeyParameter pubKey = PublicKeyFactory.createKey(pubInfo); - // Verifying + // Verifying; 创建 RSADigestSigner 对象并使用 SHA-256 作为摘要算法 RSADigestSigner verifier = new RSADigestSigner(new SHA256Digest()); + // 初始化 RSADigestSigner,设置为验证模式并提供公钥参数 verifier.init(false, pubKey); - byte[] signMessageForVerifing = data.getBytes(); - byte[] signatureBase64ForVerifing = decoder.decode(signatureBase64); - verifier.update(signMessageForVerifing, 0, signMessageForVerifing.length); - Boolean verifyResult = verifier.verifySignature(signatureBase64ForVerifing); + // 将要验证的数据转换为字节数组 + byte[] signMessageForVerifying = data.getBytes(); + // 将 Base64 编码的签名转换为字节数组 + byte[] signatureBase64ForVerifying = decoder.decode(signatureBase64); + // 使用签名器更新要验证的数据 + verifier.update(signMessageForVerifying, 0, signMessageForVerifying.length); + // 验证签名并返回结果 + Boolean verifyResult = verifier.verifySignature(signatureBase64ForVerifying); return verifyResult; } catch (Exception e) { throw new RuntimeException(e); diff --git a/src/main/java/com/ai/da/common/utils/AlipayHKRequestUtil.java b/src/main/java/com/ai/da/common/utils/AlipayHKRequestUtil.java index 3bfcf9a4..a7246492 100644 --- a/src/main/java/com/ai/da/common/utils/AlipayHKRequestUtil.java +++ b/src/main/java/com/ai/da/common/utils/AlipayHKRequestUtil.java @@ -17,7 +17,7 @@ import org.springframework.stereotype.Component; @Component public class AlipayHKRequestUtil { - public String requestAlipayHK(AlipayHKRequestDTO alipayHKRequestDTO) throws IOException { + public String requestAlipayHK(AlipayHKRequestDTO alipayHKRequestDTO) { OkHttpClient client = new OkHttpClient().newBuilder() .connectTimeout(30, TimeUnit.SECONDS) .pingInterval(5, TimeUnit.SECONDS)//websocket轮训间隔(单位:秒) @@ -29,7 +29,7 @@ public class AlipayHKRequestUtil { log.info("Alipay-HK send request unix timestamp: {}", epochMilli); String jsonString = JSONObject.toJSONString(alipayHKRequestDTO, SerializerFeature.WriteMapNullValue); - log.info(jsonString); +// log.info(jsonString); RequestBody body = RequestBody.create(mediaType, jsonString); diff --git a/src/main/java/com/ai/da/controller/AlipayHKController.java b/src/main/java/com/ai/da/controller/AlipayHKController.java index 602096a6..006c00b9 100644 --- a/src/main/java/com/ai/da/controller/AlipayHKController.java +++ b/src/main/java/com/ai/da/controller/AlipayHKController.java @@ -8,7 +8,6 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; -import java.util.Map; @CrossOrigin @RestController @@ -29,8 +28,9 @@ public class AlipayHKController { @ApiOperation("支付通知") @PostMapping("/trade/notify") - public String callback(@RequestParam Map params){ - return alipayHKService.callback(params); + public String callback(@RequestBody String paramString){ + log.info("alipay-hk callback parameter : {}", paramString); + return alipayHKService.callback(paramString); } @ApiOperation("订单查询") diff --git a/src/main/java/com/ai/da/mapper/primary/entity/PaymentInfo.java b/src/main/java/com/ai/da/mapper/primary/entity/PaymentInfo.java index 2d7cf881..c3876106 100644 --- a/src/main/java/com/ai/da/mapper/primary/entity/PaymentInfo.java +++ b/src/main/java/com/ai/da/mapper/primary/entity/PaymentInfo.java @@ -17,7 +17,7 @@ public class PaymentInfo extends BaseEntity{ private String tradeState;//交易状态 - private Long payerTotal;//支付金额(元) + private Float payerTotal;//支付金额(元) private String content;//通知参数 } diff --git a/src/main/java/com/ai/da/model/dto/AlipayHKCallbackDTO.java b/src/main/java/com/ai/da/model/dto/AlipayHKCallbackDTO.java index d1e40107..560aaeb7 100644 --- a/src/main/java/com/ai/da/model/dto/AlipayHKCallbackDTO.java +++ b/src/main/java/com/ai/da/model/dto/AlipayHKCallbackDTO.java @@ -7,7 +7,7 @@ public class AlipayHKCallbackDTO { private String transaction_id; - private Long amount; + private Float amount; private String currency; diff --git a/src/main/java/com/ai/da/service/AlipayHKService.java b/src/main/java/com/ai/da/service/AlipayHKService.java index e0aad9c4..13495fe2 100644 --- a/src/main/java/com/ai/da/service/AlipayHKService.java +++ b/src/main/java/com/ai/da/service/AlipayHKService.java @@ -2,13 +2,11 @@ package com.ai.da.service; import com.ai.da.model.dto.AlipayHKCallbackDTO; -import java.util.Map; - public interface AlipayHKService { String createOrder(Integer amount, String wallet); - String callback(Map params); + String callback(String paramString); void processOrder(AlipayHKCallbackDTO alipayHKCallbackDTO); diff --git a/src/main/java/com/ai/da/service/CreditsService.java b/src/main/java/com/ai/da/service/CreditsService.java index a9d35d17..e6179e22 100644 --- a/src/main/java/com/ai/da/service/CreditsService.java +++ b/src/main/java/com/ai/da/service/CreditsService.java @@ -11,7 +11,7 @@ public interface CreditsService extends IService { void initCredits(); - Boolean buyCredits(Long accountId, Integer quantity); + Boolean buyCredits(Long accountId, Float quantity); void creditsIncrease(Long accountId, String event); diff --git a/src/main/java/com/ai/da/service/impl/AliPayServiceImpl.java b/src/main/java/com/ai/da/service/impl/AliPayServiceImpl.java index 2d886b2d..75c93eb6 100644 --- a/src/main/java/com/ai/da/service/impl/AliPayServiceImpl.java +++ b/src/main/java/com/ai/da/service/impl/AliPayServiceImpl.java @@ -216,7 +216,7 @@ public class AliPayServiceImpl implements AliPayService { CreditsEventsEnum.BUY_CREDITS.getValue(), "positive"); // 更新积分 - creditsService.buyCredits(orderByOrderNo.getAccountId(),Integer.parseInt(totalAmount) / Integer.parseInt(CreditsEventsEnum.PRICE.getValue())); + creditsService.buyCredits(orderByOrderNo.getAccountId(),Float.parseFloat(totalAmount) / Float.parseFloat(CreditsEventsEnum.PRICE.getValue())); } finally { //要主动释放锁 lock.unlock(); @@ -318,7 +318,7 @@ public class AliPayServiceImpl implements AliPayService { CreditsEventsEnum.BUY_CREDITS.getValue(), "positive"); // 更新积分 - creditsService.buyCredits(orderByOrderNo.getAccountId(),(int)(orderByOrderNo.getTotalFee() / Float.parseFloat(CreditsEventsEnum.PRICE.getValue()))); + creditsService.buyCredits(orderByOrderNo.getAccountId(),orderByOrderNo.getTotalFee() / Float.parseFloat(CreditsEventsEnum.PRICE.getValue())); } } diff --git a/src/main/java/com/ai/da/service/impl/AlipayHKServiceImpl.java b/src/main/java/com/ai/da/service/impl/AlipayHKServiceImpl.java index 038168ec..14515580 100644 --- a/src/main/java/com/ai/da/service/impl/AlipayHKServiceImpl.java +++ b/src/main/java/com/ai/da/service/impl/AlipayHKServiceImpl.java @@ -71,7 +71,8 @@ public class AlipayHKServiceImpl implements AlipayHKService { // ALIPAYHK 或者 ALIPAYCN param.put("wallet", wallet); param.put("segment_id", segmentId); - param.put("payment_solution", "WAP"); +// param.put("payment_solution", "WAP"); + param.put("payment_solution", "PC2MOBILE"); log.info("alipay-hk 创建订单,参数信息: {}", param); // 生成订单 log.info("创建订单"); @@ -125,44 +126,46 @@ public class AlipayHKServiceImpl implements AlipayHKService { } - /** * 异步回调 * @return */ - public String callback(Map params){ - log.info("支付通知正在执行"); - log.info("通知参数 ===> {}", params); + public String callback(String paramString){ + log.info("支付宝(HK)通知正在执行"); + Map params = JSONObject.parseObject(paramString, Map.class); String result = "failure"; - String data = params.get("data"); String signature = params.get("signature"); try { // 异步回调验签 Boolean verification = alipayHKEncryptionUtil.signatureVerification(data, signature); - if (!verification){ - log.error("alipay-hk 验签失败"); + log.error("Alipay-hk 验签失败"); return result; } + log.info("Alipay-HK 验签成功"); - AlipayHKCallbackDTO alipayHKCallbackDTO = JSONObject.parseObject(data, AlipayHKCallbackDTO.class); + String dataString = data.replace("\\\"", "\"") + .replace("\"{", "{") + .replace("}\"", "}"); + + AlipayHKCallbackDTO alipayHKCallbackDTO = JSONObject.parseObject(dataString, AlipayHKCallbackDTO.class); //按照支付结果异步通知中的描述,对支付结果中的业务内容进行二次校验, //1 商户需要验证该通知数据中的 out_trade_no 是否为商户系统中创建的订单号 String outTradeNo = alipayHKCallbackDTO.getOut_trade_no(); OrderInfo order = orderInfoService.getOrderByOrderNo(outTradeNo); if(order == null){ - log.error("订单不存在"); + log.error("订单:{} 不存在",outTradeNo); return result; } //2 判断 total_amount 是否确实为该订单的实际金额(即商户订单创建时的金额) - Long totalAmount = alipayHKCallbackDTO.getAmount(); - Long totalFee = order.getTotalFee().longValue(); + Float totalAmount = alipayHKCallbackDTO.getAmount(); + Float totalFee = order.getTotalFee(); if(!Objects.equals(totalAmount, totalFee)){ - log.error("金额校验失败"); + log.error("金额校验失败,回调中金额为:{},实际金额为:{}", totalAmount, totalFee); return result; } @@ -170,7 +173,7 @@ public class AlipayHKServiceImpl implements AlipayHKService { String sellerId = alipayHKCallbackDTO.getMerchant_id(); String sellerIdProperty = merchantId; if(!sellerId.equals(sellerIdProperty)){ - log.error("商家pid校验失败"); + log.error("商家merchantId校验失败,回调中merchantId为:{},实际merchantId为:{}", sellerId, sellerIdProperty); return result; } @@ -178,7 +181,7 @@ public class AlipayHKServiceImpl implements AlipayHKService { String segId = alipayHKCallbackDTO.getSegment_id(); String segmentIdProperty = segmentId; if(!segId.equals(segmentIdProperty)){ - log.error("segmentId校验失败"); + log.error("segmentId校验失败,回调中segmentId为:{},实际segmentId为:{}", segId, segmentIdProperty); return result; } @@ -190,13 +193,14 @@ public class AlipayHKServiceImpl implements AlipayHKService { return result; } + log.info("Alipay-HK参数二次校验成功,进入数据处理与存储"); processOrder(alipayHKCallbackDTO); result = "success"; }catch (Exception e){ log.error(e.getMessage()); } - + log.info("Alipay-HK 回调处理结果:{}", result); return result; } @@ -226,21 +230,25 @@ public class AlipayHKServiceImpl implements AlipayHKService { // String orderStatus = orderInfoService.getOrderStatus(orderNo); OrderInfo orderByOrderNo = orderInfoService.getOrderByOrderNo(orderNo); String orderStatus = orderByOrderNo.getOrderStatus(); - // 当订单状态处于未支付或超时已关闭时,更新订单状态 - if (!OrderStatusEnum.NOT_PAY.getType().equals(orderStatus) || !OrderStatusEnum.TIMEOUT_CLOSED.getType().equals(orderStatus)) { + // 当订单状态处于未支付或超时已关闭时,更新订单状态,其他状态均不更新订单状态 + if (!OrderStatusEnum.NOT_PAY.getType().equals(orderStatus) && !OrderStatusEnum.TIMEOUT_CLOSED.getType().equals(orderStatus)) { + log.info("订单状态 : {}", orderStatus); return; } //更新订单状态 orderInfoService.updateStatusByOrderNo(orderNo, OrderStatusEnum.SUCCESS); + log.info("Alipay-HK 订单:{} 状态更新成功",orderNo); //记录支付日志 paymentInfoService.createPaymentInfoForAliPayHK(alipayHKCallbackDTO); + log.info("Alipay-HK 订单:{} 支付信息状态更新成功",orderNo); // 添加积分变更记录 creditsService.insertToCreditsDetail(orderByOrderNo.getAccountId(), CreditsEventsEnum.BUY_CREDITS.getName() + "--AlipayHK", CreditsEventsEnum.BUY_CREDITS.getValue(), "positive"); // 更新积分 - creditsService.buyCredits(orderByOrderNo.getAccountId(),Integer.parseInt(totalAmount) / Integer.parseInt(CreditsEventsEnum.PRICE.getValue())); + creditsService.buyCredits(orderByOrderNo.getAccountId(),Float.parseFloat(totalAmount) / Float.parseFloat(CreditsEventsEnum.PRICE.getValue())); + log.info("用户:{} 积分信息更新成功",orderByOrderNo.getAccountId()); } finally { //要主动释放锁 lock.unlock(); diff --git a/src/main/java/com/ai/da/service/impl/CreditsServiceImpl.java b/src/main/java/com/ai/da/service/impl/CreditsServiceImpl.java index c947ac97..13f380ce 100644 --- a/src/main/java/com/ai/da/service/impl/CreditsServiceImpl.java +++ b/src/main/java/com/ai/da/service/impl/CreditsServiceImpl.java @@ -48,7 +48,7 @@ public class CreditsServiceImpl extends ServiceImpl