Mock361YXSDK.java 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. package com.ljsd.channel;
  2. import com.google.gson.Gson;
  3. import com.google.gson.JsonObject;
  4. import com.google.gson.JsonParser;
  5. import com.ljsd.util.BaseGlobal;
  6. import com.ljsd.util.TimeUtil;
  7. import com.ljsd.util.XmlParser;
  8. import com.mongodb.BasicDBObject;
  9. import com.mongodb.DBObject;
  10. import org.apache.http.HttpEntity;
  11. import org.apache.http.NameValuePair;
  12. import org.apache.http.client.entity.UrlEncodedFormEntity;
  13. import org.apache.http.client.methods.CloseableHttpResponse;
  14. import org.apache.http.client.methods.HttpGet;
  15. import org.apache.http.client.methods.HttpPost;
  16. import org.apache.http.client.utils.URIBuilder;
  17. import org.apache.http.impl.client.CloseableHttpClient;
  18. import org.apache.http.impl.client.HttpClients;
  19. import org.apache.http.message.BasicNameValuePair;
  20. import org.apache.http.util.EntityUtils;
  21. import org.slf4j.Logger;
  22. import org.slf4j.LoggerFactory;
  23. import javax.servlet.http.HttpServletRequest;
  24. import java.io.UnsupportedEncodingException;
  25. import java.math.BigDecimal;
  26. import java.net.URLEncoder;
  27. import java.nio.charset.StandardCharsets;
  28. import java.security.MessageDigest;
  29. import java.security.NoSuchAlgorithmException;
  30. import java.text.DecimalFormat;
  31. import java.util.ArrayList;
  32. import java.util.HashMap;
  33. import java.util.List;
  34. import java.util.Map;
  35. import java.util.stream.Collectors;
  36. public class Mock361YXSDK {
  37. private static final Logger LOGGER = LoggerFactory.getLogger(Mock361YXSDK.class);
  38. private static final String APP_ID="39bee2c821834c32";
  39. private static final String LOGIN_KEY="3dc60d6756c04f4ca23c6addba1e400e";
  40. private static final String PAY_KEY="befa74b8ed734b01afb34b64f56c8cc2";
  41. private static final String VERIFY_API_URL="http://sdk.361yx.com/tools/gamefactor.ashx?action=factor_login";
  42. private static final CloseableHttpClient httpClient = HttpClients.createDefault();
  43. private final static String _COLLECTION_PAY = "pay";
  44. private static final Gson GSON = new Gson();
  45. public static boolean verifyUser(String uid) {
  46. try {
  47. Map<String, String> params = new HashMap<>();
  48. params.put("app_id",APP_ID);
  49. params.put("uid",uid);
  50. params.put("timestamp",String.valueOf(TimeUtil.getTimeNow()));
  51. params.put("pay_key", PAY_KEY);
  52. // 构建排序后的查询字符串
  53. String sortedQuery = buildSortedQuery(params);
  54. LOGGER.info("排序后的查询字符串:{}", sortedQuery);
  55. String sign = md5(sortedQuery);
  56. // 域名+/tools/gamefactor.ashx?action=factor_login
  57. List<NameValuePair> formParams = new ArrayList<>();
  58. formParams.add(new BasicNameValuePair("app_id", APP_ID)); // app_id 参数
  59. formParams.add(new BasicNameValuePair("uid", uid)); // uid 参数
  60. formParams.add(new BasicNameValuePair("timestamp", params.get("timestamp"))); // timestamp 参数
  61. formParams.add(new BasicNameValuePair("sign", sign));
  62. HttpPost httpPost = new HttpPost(VERIFY_API_URL);
  63. UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(formParams, StandardCharsets.UTF_8);
  64. httpPost.setEntity(formEntity);
  65. CloseableHttpResponse response = httpClient.execute(httpPost);
  66. String responseStr = EntityUtils.toString(response.getEntity(), "UTF-8");
  67. JsonObject jsonObject = GSON.fromJson(responseStr, JsonObject.class);
  68. int status = jsonObject.get("status").getAsInt();
  69. String realname = jsonObject.has("realname") ? jsonObject.get("realname").getAsString() : null;
  70. String idcard = jsonObject.has("idcard") ? jsonObject.get("idcard").getAsString() : null;
  71. String msg = jsonObject.has("msg") ? jsonObject.get("msg").getAsString() : null;
  72. response.close();
  73. if (status == 1) {
  74. LOGGER.info("验证成功!真实姓名:{},身份证号:{}", realname, idcard);
  75. return true;
  76. } else {
  77. LOGGER.error("验证失败,原因:{}", msg);
  78. return false;
  79. }
  80. } catch (Exception e) {
  81. e.printStackTrace();
  82. LOGGER.error("361yx 验证异常:", e);
  83. return false;
  84. }
  85. }
  86. public static String md5(String input) throws NoSuchAlgorithmException {
  87. MessageDigest md = MessageDigest.getInstance("MD5");
  88. byte[] hashBytes = md.digest(input.getBytes(StandardCharsets.UTF_8));
  89. StringBuilder hexString = new StringBuilder();
  90. for (byte b : hashBytes) {
  91. String hex = Integer.toHexString(0xFF & b);
  92. if (hex.length() == 1) {
  93. hexString.append('0'); // 补前导零(如 0x0A → "0a")
  94. }
  95. hexString.append(hex);
  96. }
  97. return hexString.toString();
  98. }
  99. public static boolean verifyCallback(Map<String, String> params, String sign) throws NoSuchAlgorithmException {
  100. params.put("pay_key", PAY_KEY); // 包含特殊字符
  101. // 构建排序后的查询字符串
  102. String sortedQuery = buildSortedQuery(params);
  103. LOGGER.info("排序后的查询字符串:{}", sortedQuery);
  104. String signCheck = md5(sortedQuery);
  105. LOGGER.info("signCheck:{}", signCheck);
  106. return signCheck.equals(sign.toLowerCase());
  107. }
  108. public static String buildSortedQuery(Map<String, String> params) {
  109. // 1. 分离 pay_key 和其他参数(其他参数需非空)
  110. Map<String, String> otherParams = new HashMap<>();
  111. String payKeyValue = params.get("pay_key");
  112. // 过滤其他参数(非 pay_key 且值非空)
  113. for (Map.Entry<String, String> entry : params.entrySet()) {
  114. String key = entry.getKey();
  115. String value = entry.getValue();
  116. if (!"pay_key".equals(key) && value != null && !value.trim().isEmpty()) {
  117. otherParams.put(key, value);
  118. }
  119. }
  120. // 2. 对其他参数按键的 ASCII 字典序排序
  121. List<String> sortedOtherKeys = otherParams.keySet().stream()
  122. .sorted() // 按 String 自然顺序(ASCII 字典序)排序
  123. .collect(Collectors.toList());
  124. // 3. 拼接其他参数(已排序)
  125. StringBuilder otherParamsStr = new StringBuilder();
  126. for (String key : sortedOtherKeys) {
  127. String value = otherParams.get(key);
  128. try {
  129. String encodedValue = URLEncoder.encode(value, StandardCharsets.UTF_8.name());
  130. otherParamsStr.append(key).append("=").append(encodedValue).append("&");
  131. } catch (UnsupportedEncodingException e) {
  132. // 理论上不会触发,此处处理异常
  133. otherParamsStr.append(key).append("=").append(value).append("&");
  134. }
  135. }
  136. // 移除末尾多余的 &
  137. if (otherParamsStr.length() > 0) {
  138. otherParamsStr.deleteCharAt(otherParamsStr.length() - 1);
  139. }
  140. // 4. 拼接 pay_key(始终在最后)
  141. StringBuilder finalQuery = new StringBuilder(otherParamsStr); // 初始化为其他参数的拼接结果
  142. // 拼接 pay_key(如果有值)
  143. if (payKeyValue != null && !payKeyValue.trim().isEmpty()) {
  144. try {
  145. String encodedPayKey = URLEncoder.encode(payKeyValue, StandardCharsets.UTF_8.name());
  146. if (finalQuery.length() > 0) {
  147. finalQuery.append("&").append("pay_key=").append(encodedPayKey);
  148. } else {
  149. finalQuery.append("pay_key=").append(encodedPayKey);
  150. }
  151. } catch (UnsupportedEncodingException e) {
  152. if (finalQuery.length() > 0) {
  153. finalQuery.append("&").append("pay_key=").append(payKeyValue);
  154. } else {
  155. finalQuery.append("pay_key=").append(payKeyValue);
  156. }
  157. }
  158. }
  159. return finalQuery.toString();
  160. }
  161. public static DBObject saveDB(Map<String, String> params) throws Exception {
  162. LOGGER.info("params = {}", params);
  163. String orderId = params.get("cp_order_id");
  164. DBObject payInfo = new BasicDBObject();
  165. payInfo.put("cporderId", orderId);
  166. List<DBObject> payInfoList = BaseGlobal.getInstance().mongoDBPool.find(_COLLECTION_PAY, payInfo);
  167. if (payInfoList.size() != 1) {
  168. LOGGER.error("payInfoList.size() = {}", payInfoList.size());
  169. return null;
  170. }
  171. payInfo = payInfoList.get(0);
  172. // 比较订单金额
  173. BigDecimal money = new BigDecimal(params.get("order_amount"));
  174. int processedMoney = money.multiply(BigDecimal.valueOf(100))
  175. .intValueExact();
  176. int amount = (int) payInfo.get("money");
  177. boolean isEqual = processedMoney == amount;
  178. LOGGER.info("处理后的金额(100倍)= {}", processedMoney);
  179. LOGGER.info("与目标金额对比结果= {}, 订单金额 = {}", isEqual, amount);
  180. if(!isEqual) {
  181. LOGGER.error("金额不一致,请检查!");
  182. return null;
  183. }
  184. payInfo.put("billno", orderId);
  185. // payInfo.put("uid", request.getParameter("role_id"));
  186. payInfo.put("openId", params.get("open_id"));
  187. payInfo.put("region", params.get("server_id"));
  188. payInfo.put("channel", "361yx");
  189. payInfo.put("gameorderId", params.get("order_id"));
  190. // dbObject.put("cporderId", platform);
  191. // payInfo.put("creattime",request.getParameter("pay_time"));
  192. payInfo.put("callbaktime", TimeUtil.getTimeNow());
  193. BaseGlobal.getInstance().mongoDBPool.save(_COLLECTION_PAY, payInfo);
  194. return payInfo;
  195. }
  196. private static String generateSign(String appId, String appSecret, String userId) {
  197. String raw = appId + appSecret + userId;
  198. return raw.hashCode() + "";
  199. }
  200. }