
以下为我观察到的行为,不保证正确。
接口 https://wlx.tenpay.com/cgi-bin/wx/hce/ccm_hce_account_info.cgi 返回的数据存在 retcode: "912320107",也就是 DEVICE_IS_ROOT: "912320107"
节选自 pages/index/index.js
{ var e = require("../../utils/config.js"), t = require("../../utils/util.js"), o = require("../../common/request.js"), a = require("../../utils/lib.js"), n = requirePlugin("vfcPlugin").vfc, i = require("../../logic/login.js"), c = require("../../logic/uiHelper.js"), r = require("../../logic/uiShare.js"), s = require("../../logic/report"), d = require("../../common/token.js"), l = require("../../logic/location.js"), u = require("../../logic/elementData.js"), g = require("../../utils/thirdparty/aes.js").CryptoJS, _ = require("../../utils/thirdparty/rsa.js"), f = require("../../utils/thirdparty/md5.js"), p = getApp(), request = o.request, h = { RIGHT: "/img/right.png", FALSE: "/img/false.png" }, w = { BAL: "余额不足", FAIL: "该城市暂不支持使用乘车卡" }, y = { normal: "刷新", refresh: "已刷新" }, C = {}; Page({ requestCardInfo: function() { arguments.length > 0 && void 0 !== arguments[0] && arguments[0]; var e = this; t.compare(C.SDKVersion, "2.6.2", !0) >= 0 ? wx.getWxSecData({ complete: function(t) { e.qryAccInfo({ sec_data_enc: t.encryptedData, sec_data_enc_iv: t.iv }); } }) : e.qryAccInfo({ sec_data_enc: "", sec_data_enc_iv: "", wx_version: C.version, sdk_version: C.SDKVersion }); }, qryAccInfo: function() { var request_raw_data = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {}, o = this, request_data = Object.assign( { ykt_id: o.data.ykt_id, city_code: o.data.city_code, card_id: i.getCardId() || "" }, request_raw_data ); request({ url: e.GET_CARD_INFO, showLoading: !0, data: request_data, success: function(resp) { var resp_data = resp.data; if ((console.log(resp), "0" === resp_data.retcode)) if ("0" === resp_data.open_state) { var n = { cloud_card_id: resp_data.cloud_card_id, vfc_card_id: resp_data.vfc_card_id, vfc_user_id: resp_data.vfc_user_id, vfc_user_name: resp_data.vfc_user_name, acc_no: resp_data.acc_no, card_id: resp_data.card_id }; wx.setStorageSync(e.USER_INFO_KEY, n); var i = resp_data.cloud_card_id || ""; o.setData({ loading: !1, acc_no: resp_data.acc_no, cloudCardId: i, formatCloudCardId: i.replace(/(\d{4})/g, "$1 ") }), p.setGlobalData({ acc_no: resp_data.acc_no }), wx.getStorageSync(e.HCETOKEN) ? wx.getStorageSync(e.CERT_NO) ? o.updateCardInfo() : o.reqCertNo() : o.requestToken(); } else wx.redirectTo({ url: "/pages/card/pre/pre?cardImg=" + o.data.cardImg }); else switch (resp_data.retcode) { case e.RETCODE.USER_NOT_EXIST: case e.RETCODE.USER_STOPPED: case e.RETCODE.NEW_USER_NOT_NEED_PHONE_AUTH: wx.redirectTo({ url: "/pages/card/pre/pre?retcode=" + resp_data.retcode + "&cardImg=" + o.data.cardImg }); break; case e.RETCODE.OPEN_NOT_IN_WHITELIST: case e.RETCODE.OPEN_NOT_ALLOWED: o.setData({ loading: !1, InWhiteList: !1 }); break; case e.RETCODE.DEVICE_IS_ROOT: wx.redirectTo({ url: "/pages/notSupport/notSupport?type=isRoot" }); break; default: c.commonModal({ confirmText: "重试", retcode: resp_data.retcode, success: function(e) { e.confirm && o.render(); } }); } }, fail: function(e) { wx.showModal({ title: "提示", content: "系统繁忙,请重试", confirmText: "重试", success: function(e) { e.confirm && o.render(); } }); } }); } }); } 节选自 common/request.js
function request(user_query) { function isLoginUrl() { return real_query.url === n.LOGIN_CGI; } var real_query = Object.assign( { retry: !0, method: "POST", header: { "content-type": "application/x-www-form-urlencoded" }, isReport: !0 }, user_query ); real_query.data || (real_query.data = {}), (real_query.data.s_tk = token.getSysInfoToken()), (real_query.data.g_tk = token.getACSRFToken()), (real_query.data.version = n.APP_VERSION); var l = new Date().getTime().toString(); (real_query.data.timestamp = l.substr(0, 10)), real_query.showLoading && wx.showLoading({ title: "加载中..." }); var login_data = logic_login.getLoginData(); if (login_data && "POST" == real_query.method) for (var d in login_data) ("wlx_app_id" !== d && "wlx_open_id" !== d && "wlx_skey" !== d && "wlx_skey_type" !== d) || (real_query.data[d] = login_data[d]); real_query.success = function(resp) { console.log(resp); var a = resp.data || {}; 200 == resp.statusCode ? !1 === isLoginUrl() && real_query.retry && "object" == (void 0 === a ? "undefined" : t(a)) && logic_login.needAutoLogin(a.retcode) ? !0 !== request.retryMap[user_query.url] ? ((request.retryMap[user_query.url] = !0), o({ fromCache: !1, showLoading: user_query.showLoading, success: function(o) { request(user_query); } })) : wx.showModal({ title: "提示", content: "登录失效,请重新登录?", showCancel: !0, success: function(t) { t.confirm ? o({ fromCache: !1, success: function(o) { request(user_query); } }) : wx.navigateBack({ delta: 5 }); } }) : (!1 === isLoginUrl() && !0 === request.retryMap[user_query.url] && (request.retryMap[user_query.url] = !1), user_query.success(resp)) : user_query.fail && user_query.fail(); }; (real_query.complete = function(e) { real_query.showLoading && wx.hideLoading(), user_query.complete && user_query.complete(e); }), console.log(real_query), wx.request(real_query); } 节选自 logic/login.js
function getLoginData() { try { var e = wx.getStorageSync(r.LOGIN_DATA_KEY); if ( "" !== e.wlx_app_id && "" !== e.wlx_open_id && "" !== e.wlx_skey && "" !== e.wlx_skey_type ) { var n = getApp(); return n && n.globalData && (n.globalData.wlx_open_id = e.wlx_open_id), e; } return null; } catch (e) { return null; } } 节选自 common/token.js
{ function e() { try { var e = wx.getSystemInfoSync(), t = { model: e.model, pixelRatio: e.pixelRatio, screenWidth: e.screenWidth, screenHeight: e.screenHeight }; return r(JSON.stringify(t)); } catch (e) { console.log("getSysInfoMd5Old"); } } function t() { var e = o.getOpenIdFromStorage(); return e ? r(e + n.SYSINFO_SALT) : (console.log("getSysInfoMd5"), ""); } var r = require("../utils/thirdparty/md5.js"), n = require("../utils/config.js"), o = require("../logic/login.js"); module.exports = { getSysInfoToken: function() { return e().substr(-4); }, getACSRFToken: function() { try { var e = wx.getStorageSync(n.LOGIN_DATA_KEY); if (e) { for (var t = 5381, r = e.wlx_skey, o = 0, i = r.length; o < i; ++o) t += (t << 5) + r.charAt(o).charCodeAt(); return 2147483647 & t; } } catch (e) { return ""; } return ""; }, getSysInfoMd5: t, getGuidMd5: function() { return t(); }, md5: r }; } 这判断很有趣,清空数据后第一次打开就能用,再次打开就不行了。
腾讯能不能因为我 ROOT 了设备就不让我用呢?
四 服务中止 /终止
1、财付通有权基于业务调整或风险管控的需要,暂停、中断或终止向您提供本服务的全部或部分功能。
----- 乘车卡使用协议
1 lpd0155 2019-04-12 23:26:22 +08:00 via Android 小白问一句,压缩包里的东西怎么打开? |
2 azh7138m OP |
3 tony601818 2019-04-13 04:00:33 +08:00 via Android 安卓系统有 SafetyNet |
4 lpd0155 2019-04-13 07:53:47 +08:00 via Android @tony601818 没用的,实测过了 SAFETY NET 依然被检测到 ROOT |
5 kokutou 2019-04-13 09:38:56 +08:00 via Android magisk+edxposed。。。 乘车码我昨天试了下开通了,今天还是可以打开。。。 |
6 azh7138m OP @kokutou 我清空数据后第一次也是可以用的,过一会就不行了,不知道微信是怎么判断的,这里只是说乘车卡是怎么判断用户是否 root,这个接口的数据是怎么来的就不清楚了。 |
7 kokutou 2019-04-13 11:51:17 +08:00 via Android |
10 fyooo 2019-05-29 09:22:47 +08:00 @tony601818 国内的手机不支持 GMS,应该是没有 SafetyNet API 的。估计是小程序调用微信的接口检查是否 root 的,https://stackoverflow.com/questions/27291676/root-detection-methodology-in-android-which-cannot-be-bypassed |
11 UchihaJay 2019-08-23 13:17:55 +08:00 绝对坑,用之前不说,充值开通了告诉我不能用,我为你个乘车吗换手机?行我不要了,告诉我哪里退钱 |