瀏覽代碼

fix 支付回调验证

Jim 11 月之前
父節點
當前提交
9f750562ea

+ 1 - 1
build.gradle

@@ -24,5 +24,5 @@ dependencies {
     compile group: 'com.google.code.gson', name: 'gson', version: '2.2.4'
     // https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient
     compile group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.5.6'
-
+    compile("org.apache.thrift:libthrift:0.9.2")
 }

+ 22 - 2
src/main/java/com/ljsd/channel/Mock361YXSDK.java

@@ -24,10 +24,12 @@ import org.slf4j.LoggerFactory;
 
 import javax.servlet.http.HttpServletRequest;
 import java.io.UnsupportedEncodingException;
+import java.math.BigDecimal;
 import java.net.URLEncoder;
 import java.nio.charset.StandardCharsets;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
+import java.text.DecimalFormat;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -204,17 +206,35 @@ public class Mock361YXSDK {
 
         List<DBObject> payInfoList = BaseGlobal.getInstance().mongoDBPool.find(_COLLECTION_PAY, payInfo);
         if (payInfoList.size() != 1) {
+            LOGGER.error("payInfoList.size() = {}", payInfoList.size());
             return null;
         }
+        payInfo = payInfoList.get(0);
+
+        // 比较订单金额
+        // 比较订单金额
+        BigDecimal money = new BigDecimal( request.getParameter("amount"));
+        int processedMoney = money.multiply(BigDecimal.valueOf(100))
+                .intValueExact();
+
+        int amount = (int) payInfo.get("money");
+        boolean isEqual = processedMoney == amount;
+        LOGGER.info("处理后的金额(100倍)= {}", processedMoney);
+        LOGGER.info("与目标金额对比结果= {}, 订单金额 = {}", isEqual, amount);
+        if(!isEqual) {
+            LOGGER.error("金额不一致,请检查!");
+            return null;
+        }
+
         payInfo.put("billno", request.getParameter("order_id"));
 
-        payInfo.put("uid", request.getParameter("role_id"));
+//        payInfo.put("uid", request.getParameter("role_id"));
         payInfo.put("openId", request.getParameter("open_id"));
         payInfo.put("region", request.getParameter("server_id"));
         payInfo.put("channel", "361yx");
 //        payInfo.put("gameorderId", request.getParameter("game_order"));
 //            dbObject.put("cporderId", platform);
-        payInfo.put("creattime",request.getParameter("pay_time"));
+//        payInfo.put("creattime",request.getParameter("pay_time"));
         payInfo.put("callbaktime", TimeUtil.getTimeNow());
         BaseGlobal.getInstance().mongoDBPool.save(_COLLECTION_PAY, payInfo);
         return payInfo;

+ 80 - 9
src/main/java/com/ljsd/channel/MockQuickSDK.java

@@ -12,14 +12,20 @@ import org.apache.http.client.utils.URIBuilder;
 import org.apache.http.impl.client.CloseableHttpClient;
 import org.apache.http.impl.client.HttpClients;
 import org.apache.http.util.EntityUtils;
+import org.slf4j.ILoggerFactory;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.math.BigDecimal;
 import java.nio.charset.StandardCharsets;
 import java.security.MessageDigest;
+import java.text.DecimalFormat;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 import java.util.Properties;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 import static javax.management.Query.eq;
 
@@ -28,6 +34,7 @@ public class MockQuickSDK {
     private static final Logger LOGGER = LoggerFactory.getLogger(MockQuickSDK.class);
     private static final String QUICK_SDK_PRODUCT_CODE="74323196251398220690098816635773";
     private static final String QUICK_SDK_PRODUCT_KEY="20562534";
+    private static final String QUICK_SDK_MD5KEY = "h801bjmrbjdovgaoytebqyt3inub0e9h";
     private static final String QUICK_SDK_CALLBACK_KEY="05803023623721638274057263988239";
     private static final String QUICK_SDK_VERIFY_API_URL="https://checkuser.gamedachen.com/v2/checkUserInfo";
     private static final CloseableHttpClient httpClient = HttpClients.createDefault();
@@ -59,7 +66,8 @@ public class MockQuickSDK {
             LOGGER.error("参数不可为空,nt_data={}, sign={}, md5Sign={}", nt_data, sign, md5Sign);
             return false;
         }
-        String rawString = nt_data + sign + QUICK_SDK_CALLBACK_KEY;
+        String rawString = nt_data + sign + QUICK_SDK_MD5KEY;
+        LOGGER.info("rawString = {}", rawString);
 
         try {
             MessageDigest md = MessageDigest.getInstance("MD5");
@@ -74,10 +82,7 @@ public class MockQuickSDK {
                 }
                 hexString.append(hex);
             }
-            boolean success = hexString.toString().equals(md5Sign);
-            if (success) {
-
-            }
+            LOGGER.info("hexString.toString() = {}", hexString);
             return hexString.toString().equals(md5Sign);
         } catch (Exception e) {
             e.printStackTrace();
@@ -87,7 +92,10 @@ public class MockQuickSDK {
     }
 
     public static DBObject saveDB(String nt_data) throws Exception {
-        Map<String, String> fields = XmlParser.parseNtData(nt_data);
+        String decoded = decode(nt_data, QUICK_SDK_CALLBACK_KEY);
+        LOGGER.info("解码结果 = {}", decoded);
+
+        Map<String, String> fields = XmlParser.parseNtData(decoded);
         String param = fields.get("extras_params");
         LOGGER.info("param = {}", param);
 
@@ -97,23 +105,86 @@ public class MockQuickSDK {
 
         List<DBObject> payInfoList = BaseGlobal.getInstance().mongoDBPool.find(_COLLECTION_PAY, payInfo);
         if (payInfoList.size() != 1) {
+            LOGGER.error("payInfoList.size() = {}", payInfoList.size());
+            return null;
+        }
+        payInfo = payInfoList.get(0);
+
+        // 比较订单金额
+        BigDecimal money = new BigDecimal(fields.get("amount"));
+        int processedMoney = money.multiply(BigDecimal.valueOf(100))
+                .intValueExact();
+
+        int amount = (int) payInfo.get("money");
+        boolean isEqual = processedMoney == amount;
+        LOGGER.info("处理后的金额(100倍)= {}", processedMoney);
+        LOGGER.info("与目标金额对比结果= {}, 订单金额 = {}", isEqual, amount);
+        if(!isEqual) {
+            LOGGER.error("金额不一致,请检查!");
             return null;
         }
-        payInfo = new BasicDBObject();
         payInfo.put("billno", fields.get("order_no"));
 
-        payInfo.put("uid", fields.get("channel_uid"));
+//        payInfo.put("uid", fields.get("channel_uid"));
 //        payInfo.put("openId", uid);
 //            dbObject.put("region", serverId);
         payInfo.put("channel", "quick");
 //        payInfo.put("gameorderId", fields.get("game_order"));
 //            dbObject.put("cporderId", platform);
-        payInfo.put("creattime", fields.get("pay_time"));
+//        payInfo.put("creattime", fields.get("pay_time"));
         payInfo.put("callbaktime", TimeUtil.getTimeNow());
         BaseGlobal.getInstance().mongoDBPool.save(_COLLECTION_PAY, payInfo);
         return payInfo;
     }
 
+    private static String decode(String strEncode, String keyStr) {
+        if (strEncode == null || strEncode.isEmpty()) {
+            return strEncode;
+        }
+
+        List<Long> numberList = extractNumbers(strEncode); // 使用 long 避免大数溢出
+
+        if (numberList.isEmpty()) {
+            return strEncode;
+        }
+
+        byte[] keyBytes = keyStr.getBytes(StandardCharsets.UTF_8);
+        if (keyBytes.length == 0) {
+            return strEncode;
+        }
+
+        byte[] decodedBytes = new byte[numberList.size()];
+        for (int i = 0; i < numberList.size(); i++) {
+            int keyIndex = i % keyBytes.length;
+            byte key = keyBytes[keyIndex];
+
+            long rawValue = numberList.get(i);
+            int unsignedKey = key & 0xFF;
+            long decodedValue = rawValue - unsignedKey;
+
+            decodedBytes[i] = (byte) decodedValue;
+        }
+
+        return new String(decodedBytes, StandardCharsets.UTF_8);
+    }
+
+
+    private static List<Long> extractNumbers(String input) {
+        List<Long> numbers = new ArrayList<>();
+        Pattern pattern = Pattern.compile("\\d+");
+        Matcher matcher = pattern.matcher(input);
+
+        while (matcher.find()) {
+            String numStr = matcher.group();
+            try {
+                numbers.add(Long.parseLong(numStr));
+            } catch (NumberFormatException e) {
+                LOGGER.error("NumberFormatException: ", e);
+            }
+        }
+        return numbers;
+    }
+
     private static String generateSign(String appId, String appSecret, String userId) {
         String raw = appId + appSecret + userId;
         return raw.hashCode() + "";

+ 3 - 3
src/main/java/com/ljsd/controller/CreateOrderController.java

@@ -66,10 +66,10 @@ public class CreateOrderController extends HttpServlet {
         payInfo.put("pay_item", payItem);
         payInfo.put("region", serverId);
         payInfo.put("channel", channel);
-        payInfo.put("cp_order_id", orderId);
+        payInfo.put("cporderId", orderId);
         payInfo.put("openid", openId);
-        payInfo.put("creattime", TimeUtil.getTimeNow());
-        payInfo.put("money", price);
+        payInfo.put("creattime", String.valueOf(TimeUtil.getTimeNow()));
+        payInfo.put("money", Integer.valueOf(price));
         BaseGlobal.getInstance().mongoDBPool.save(_COLLECTION_PAY, payInfo);
 
         Map<String,String> parms = new HashMap<>();

+ 15 - 4
src/main/java/com/ljsd/controller/PayCallbackController.java

@@ -55,7 +55,8 @@ public class PayCallbackController extends HttpServlet {
         String sign = request.getParameter("sign");
         String nt_data = request.getParameter("nt_data");
         String md5Sign = request.getParameter("md5Sign");
-        LOGGER.info("PayCallbackController request = {}", request);
+        LOGGER.info("PayCallbackController sign = {}, nt_data = {}, md5Sign = {}, app_id = {}", sign, nt_data,
+                md5Sign, request.getParameter("app_id"));
         ResMsg resMsg = new ResMsg();
         resMsg.setCode(1);
         DBObject payInfo = new BasicDBObject();
@@ -73,12 +74,21 @@ public class PayCallbackController extends HttpServlet {
                 }
             } else {
                 resMsg.setMsg("不支持该渠道");
+                LOGGER.error("不支持该渠道");
                 out.print(gson.toJson(resMsg));
                 return;
             }
 
             if (!ok) {
                 resMsg.setMsg("支付sign验证失败");
+                LOGGER.error("支付sign验证失败");
+                out.print(gson.toJson(resMsg));
+                return;
+            }
+
+            if (payInfo == null) {
+                resMsg.setMsg("订单验证失败");
+                LOGGER.error("订单验证失败");
                 out.print(gson.toJson(resMsg));
                 return;
             }
@@ -90,13 +100,14 @@ public class PayCallbackController extends HttpServlet {
 
             // todo 通知发货
             // todo 各区服分配端口
-            URIBuilder uriBuilder = new URIBuilder("127.0.0.1:7915/deliveryRecharge");
+            LOGGER.info("通知发货, payInfo = {}", payInfo);
+            URIBuilder uriBuilder = new URIBuilder("http://127.0.0.1:7915/deliveryRecharge");
             uriBuilder.addParameter("uid", (String) payInfo.get("uid"));
             uriBuilder.addParameter("goodsId", (String) payInfo.get("pay_item"));
             uriBuilder.addParameter("openId", (String) payInfo.get("open_id"));
             uriBuilder.addParameter("orderId", (String) payInfo.get("cporderId"));
-            uriBuilder.addParameter("orderTime", String.valueOf((long) payInfo.get("creattime")));
-            uriBuilder.addParameter("amount", String.valueOf((int) payInfo.get("amount")));
+            uriBuilder.addParameter("orderTime", (String) payInfo.get("creattime"));
+            uriBuilder.addParameter("amount", String.valueOf((int) payInfo.get("money")));
 
             HttpGet httpGet = new HttpGet(uriBuilder.build().toString());
             CloseableHttpResponse resp = httpClient.execute(httpGet);