将菜鸟身份码、淘宝和拼多多身份码与待取包裹、京东身份码与商城订单取件码集中到一个 Android 应用中。应用在系统 WebView 中使用各平台的官方登录与数据更新流程。
HandyCode is an unofficial Android app for viewing Cainiao identity codes, Taobao and Pinduoduo pickup information, and JD identity codes and pickup codes available in JD orders.
最新正式版 0.8.1,支持 Android 8.0(API 26)及以上,目标 API 35。
安装包随 GitHub Releases 分发,仓库不跟踪构建产物。下载站是独立项目,不随本仓库发布。
| 平台 | 身份码 | 待取包裹 | 添加手机号 | 运单号查询 |
|---|---|---|---|---|
| 菜鸟 | 官方身份码,与淘宝共用登录状态 | — | — | — |
| 淘宝 | 官方身份码,支持旋转放大 | 官方待取列表 | 官方号码管理与验证 | 官方查询表单 |
| 拼多多 | 官方身份码,支持旋转放大 | 官方待取列表 | 官方绑定收件手机号 | 官方查询表单 |
| 京东 | 官方身份码,支持旋转放大 | 商城订单中返回的取件码 | 当前入口未提供 | 当前入口未提供 |
四个平台的入口固定为「菜鸟 → 淘宝 → 拼多多 → 京东」。身份码、包裹各自刷新;支持点击和横向滑动切换、记忆上次标签、玻璃昼夜开关、可见条码自动提亮,以及卡片下方的当前平台退出入口。
0.8.1 新增京东身份码,统一加载和刷新过渡,补齐登录、验证码、号码管理及运单号查询页的深浅配色,并修复淘宝启动与昼夜切换时的闪白。详情和验证边界见更新说明。
本项目为独立开发的非官方客户端,平台服务由菜鸟、淘宝、拼多多和京东各自提供。
应用只在本机系统 WebView 中加载各平台官方页面,不自建账号服务、不代理业务接口、不采集或保存账号密码、验证码、Cookie 与码值。使用前请自行确认是否符合你所在地区的法律及各平台服务条款;因使用本应用产生的账号风险、风控或数据问题由使用者自行承担。
- 菜鸟身份码使用淘宝登录状态,首次开通按菜鸟官方页面完成授权。淘宝、拼多多和京东可在各自官方网页完成登录与验证。
- 淘宝、拼多多和京东的身份码在上、待取包裹在下,整页一起滚动。菜鸟展示官方身份码,京东的包裹区展示商城订单中实际返回的取件码。
- 点击底部标签,或在内容区横向拖动切换平台。超过半屏或短距离快速滑动可完成切换。
- 每张卡片可单独刷新。登录后可在卡片下方点「退出登录」,结束该平台会话。淘宝退出后,菜鸟会提示先登录淘宝。
- 拼多多未登录时可直接打开官方 App 的身份码。若要在 HandyCode 内查看,建议用小号网页登录,再在「待取包裹」添加并验证大号的收件手机号。同一账号在网页和官方 App 重新登录时可能互相挤下线。
- 应用会记住上次停留的平台,重新打开时直接回到该平台;从桌面快捷方式进入时,以快捷方式指定的平台为准。
- 点身份码卡片中的条码可在原卡片里旋转放大,再点一次恢复。放大时待取包裹卡片移到屏幕下方,向上滚动仍可查看。
- 在「待取包裹」标题旁点「添加手机号」,可打开平台官方号码管理。淘宝的号码管理和填写页嵌在应用中间,用系统返回逐级退出。
- 淘宝和拼多多的「添加包裹」入口位于同一标题栏,打开中间区域内的官方运单号查询表单。表单适配深浅外观,保留查询所需的站点选择、验证和结果,隐藏图片上传和推广内容。京东当前接入的订单页面未提供此入口。
首次使用在 HandyCode 内的官方页面登录。 无需在外部浏览器登录后搬运凭据;应用中显示的手机号、短信验证码和滑块验证页面由平台提供,凭据由系统 WebView 与平台服务器处理。登录按钮下方的协议文字保持展示,协议链接不在应用内跳转,确认圈保留官方勾选与校验行为,不会自动代勾。
应用如何处理登录与取件信息
- 只申请网络权限(
android.permission.INTERNET),不申请存储、位置、通讯录、相机、短信、电话等权限 - 不读取、不保存、不上传账号、密码、验证码与登录令牌
- 不读取 Cookie 内容,也不在原生层代发携带登录态的业务请求;原生层只按白名单下载拼多多官方公开的页面脚本做兼容适配(见下文「拼多多」章节),不带 Cookie 或令牌。登录状态由系统 WebView 自身的 Cookie 存储维护,应用只在退出登录时按站点清除
- 没有自建服务器、统计 SDK 或崩溃上报服务,不接入任何埋点
- 应用用布尔值记录页面是否已登录,据此显示退出入口
- 展示层使用官方身份码与包裹信息,不主动将码值、原始响应或页面截图写入独立文件、导出或上传;网页资源与登录存储仍由系统 WebView 按官方页面规则缓存
- 昼夜渐变临时在内存中保留旧界面截图,可能包含当时可见的身份码或包裹,过渡结束后释放引用,不保存截图文件
- 本地保存上次停留的平台、主题模式,以及菜鸟页面是否需要先登录淘宝的状态
- 按站点清除 WebView 登录数据。淘宝和菜鸟共用会话,拼多多和京东各自管理登录状态
卸载应用或清除应用数据后,需要在官方页面重新登录。
原生 Java 负责页面容器、手势、动画、会话界面状态和 WebView 生命周期;HTML / JavaScript 负责将官方页面内容投影成统一布局。项目没有自建账号服务器或业务 API 服务。
flowchart TD
A[MainActivity 原生界面] --> B[淘宝 WebView]
A --> C[PddPage / 拼多多 WebView]
A --> L[CainiaoPage / 菜鸟官方身份码]
A --> M[JdPage / 京东订单]
M --> N[JdIdentityCard / 京东官方身份码]
B --> D[官方登录与身份码页面]
D --> E[本地双卡片 HTML + 官方来源 iframe]
C --> F[官方 m.pinduoduo.net 网页]
F --> G[官方同源 proxy/api 路由]
G --> H[官方 React 状态与 DOM]
H --> I[同文档双卡片 DOM 投影]
J[官方公开 CDN JavaScript] --> K[限定范围的兼容适配]
K --> F
图中的同源代理是拼多多已有的官方路由,不由 HandyCode 提供;登录、验证码和业务请求仍在系统 WebView 中执行。
底部从左到右为菜鸟、淘宝、拼多多、京东,支持液态玻璃底栏与滑动切换。标题栏的玻璃开关可切换深色和浅色,应用会记住所选外观。
标题栏开关由 Zsolt Kacso 的 Glass Light Toggle 独立组件适配而来,在本机离线运行。 渲染中断时显示由同一着色器生成的静态帧,并尝试恢复渲染。拖动过程随滑块预览页面配色,松手后保存所选外观。
菜鸟使用官方身份码网页的默认淘宝入口,与淘宝页共用本机 WebView 登录会话。首次开通请在菜鸟官方页面阅读并确认授权。出码后,身份码卡片在同一 WebView 内展示官方生成的条码,支持刷新和点击放大。共用会话的退出由淘宝页管理。
菜鸟刷新时只在内存保留卡片的布局尺寸和放大状态,让加载卡片与刷新前的卡片重合;新文档完成布局后再淡入,放大状态下刷新也不会先缩小。不截图或缓存身份码图像用于过渡。
身份码入口为 京东官方身份码网页。JdIdentityCard 在独立 WebView 中保留官方 Vue 页面及其身份码请求、验证码和到期更新逻辑,jd-identity.js 仅在此 HTTPS 来源与路径运行,将实时生成的 SVG、脱敏手机号和更新周期投影到卡片。展示条码来自官方 SVG,不根据截图重绘或自行编造码值。点击条码可在卡片内旋转放大,再点恢复;深浅外观使用相同尺寸,条码保持黑白对比。
身份码与订单共用系统 WebView 的京东 Cookie 存储,能否直接复用取决于官方会话是否有效。需要验证时,在应用中间区域打开京东官方登录页;不会自动提交账号、验证码或协议。身份码和包裹分别刷新,切换标签保留文档。刷新完成检查仅针对官方 /generateIdentityCode 请求,不改请求地址、参数、凭据;失败时不将旧码视为刷新成功。原生层仅接收就绪、失败和布局尺寸等状态,不接收或记录身份码原始值。
京东刷新按钮为文字状态预留固定宽度并保持右对齐,标题栏不参与内容过渡。加载反馈至少保持 320 毫秒,避免快速请求让文字只闪一帧。
京东在本机 WebView 中打开官方登录和订单页面,识别页面订单响应及订单卡片中的数字/字母取件码,以原生列表展示。提供卡片内刷新及按 jd.com 站点单独退出登录;不新增短信、通知读取、无障碍或存储权限,不抽取或另存 Cookie,不记录原始订单响应。
包裹区范围仅为当前京东商城账号订单中实际返回的取件码,身份码不代表账号一定有待取包裹,也不将京东快递的全部运单当作商城订单。上游页面改版、验证码或风控可能使识别暂时不可用。
回归覆盖 JD HTTPS 导航白名单、退出站点隔离、订单识别、取消订单过滤、去重和取码。身份码已在真机确认官方真实 SVG 展示、复用已有登录状态、分区刷新、失败重试、旋转放大和切页保留;深浅模式下布局尺寸一致。没有清除真实账号数据重测首次登录,也未等待完整到期周期。本次订单区真机验收使用没有待取订单的京东账号,真实订单取件码仍待验证。
菜鸟、淘宝、拼多多和京东的身份条码加载完成且完整显示在当前窗口内时,临时将本应用窗口亮度提高至最大。切换页面、码移出可视区域、打开弹窗或应用失去焦点后恢复先前亮度;不修改系统亮度,也不申请系统设置权限。京东数字取件码列表本身不触发身份码提亮。
底栏标题使用单层固定坐标绘制,选中颜色随滑动进度过渡,玻璃背景独立动画。
MainActivity先加载固定官方身份码入口。official-identity.js检查实际码内容、登录输入控件及跨域认证 iframe;只有官方页面已能显示有效内容,才切入合并布局,避免用空壳覆盖登录页。taobao.html在一个文档中展示身份码、待取包裹。官方来源 iframe 保留在后台,读取可访问的来源 DOM,并复制展示节点;卡片里的必要操作转发给原官方元素。refresh-controller.js将主动刷新和来源 iframe 的被动load/ DOM 更新分开。主动刷新只让对应卡片进入加载状态,重复点击合并;相同可见内容保留节点、更新事件引用,避免“刷新 / 刷新中”与加载动画反复闪烁。- 原始身份码未生成时,仅在非登录状态下有界触发官方刷新控件;输入手机号、验证码或显示认证 iframe 时暂停,不自行提交表单。
taobao-login-chrome.js只隐藏“您需要登录才能继续访问 / 关闭”这一外层标题,回收 iframe 顶部占位。官方 iframe 的节点和src不变,输入与验证流程继续由官方处理。taobao-login-theme.js适配官方手机号输入页和短信验证码格子。支持的 WebView 会在限定的官方来源文档启动时注入样式,覆盖跨域登录 iframe;已打开的登录 iframe 通过限定来源与父窗口的主题消息同步昼夜模式,不读取或提交输入内容。- 切换昼夜模式时,保留旧画面的截图,等待淘宝登录 iframe 确认目标主题并经过 WebView 绘制屏障后再渐变。拖动松手或取消时也会等待最终主题绘制完成,避免外层已变色、登录页面仍停留在另一主题而闪白。
- 官方入口等待超时后会提供恢复操作。检测到需要先开通身份码时,应用提供打开淘宝 App 身份码页的入口。
- 号码管理与新增号码表单使用淘宝官方网页和现有 WebView 会话。应用在中间区域显示它们,返回取件页后刷新待取包裹。
完整细节见 拼多多 H5 实现说明。
入口是 https://m.pinduoduo.net/mdkd/package?tab=ID_CODE。排查时发现:身份码页的浏览器业务请求发往 https://api.pinduoduo.com/api/...,而普通网页登录使用当前官方站点已有的 /proxy/api/ 路由。
.net 页面与 .com API 属于跨站访问,Cookie 的作用域、SameSite 及浏览器跨站规则都会影响会话是否被服务端接受。曾观察到页面短暂显示框架、前置检查报告未登录,随后回到登录页。单独一条 api_uid 的 SameSite 警告不能证明它就是登录凭据,也不能说明所有跳转都由它造成。
PddPage 只拦截严格匹配的官方公开 CDN _app-<hash>.js,正常 HTTPS 下载后,在前面加入兼容脚本。pdd-same-origin.js 在原应用脚本执行前包装 XMLHttpRequest.open 和 fetch,只映射指定来源:
https://api.pinduoduo.com/api/express_trackbox/...
↓
https://m.pinduoduo.net/proxy/api/api/express_trackbox/...
这里的 /proxy/api/api/ 两段 api 是有意保留的:官方代理前缀为 /proxy/api,原 API 路径仍以 /api/ 开头。
脚本保留原方法、请求体、请求头、查询参数与调用选项;Request 输入按原对象重建。认证仍由 WebView 按官方站点规则管理。应用不读取或搬运 Cookie / Token,不在原生层代发业务请求,也不修改 SameSite、证书验证或伪装官方客户端。登录页和验证页不应用这段 API 映射。
-
WebView 内部只允许
https://m.pinduoduo.net的正常 HTTPS 导航,阻止其他域名和任意协议接管页面。 -
官方登录验证偶尔会落到
/index.html,丢失身份码返回目标。应用在确实经过登录后,最多自动返回身份码入口一次;仍失败则保留官方页面,避免强制重定向循环。 -
未登录时直接展示官方登录页,账号互斥与小号使用建议以普通文字放在登录内容下方,不再增加选择提示页。官方页面的「打开拼多多 App」按钮可直达官方 App 身份码,网页触发需满足官方登录页、主框架、用户手势和目标精确匹配条件。
pinduoduo://com.xunmeng.pinduoduo/mdkd/package?tab=ID_CODE直达入口使用拼多多 App 自身的会话。网页登录则由 WebView 单独保存会话,同一账号在两端登录时可能触发平台替换旧会话。
- 启用 WebView 的 Cookie 和 DOM Storage,复用同一应用的默认 WebView 数据目录,不在启动、切页、退出 Activity 或覆盖更新时清空它。
- 页面完成和应用进入后台时执行
CookieManager.flush(),让 Cookie 存储及时落盘;localStorage等仍由浏览器按来源管理。拼多多不依赖放开第三方 Cookie,而使用上述第一方官方代理。京东订单识别只在本机 WebView 和原生卡片之间传递展示所需的信息。 - 各平台首次打开后保留各自 WebView 与当前文档。切页只是移动、裁剪视图,停止非当前页的加载圆点动画;应用进入后台时暂停 WebView,回来后恢复。京东切到后台标签时也暂停订单及身份码的原生状态检查。
- Release 沿用相同包名与签名,使用
adb install -r覆盖安装,继续使用原沙箱数据。
flush() 不会延长官方 Cookie 的过期时间,也不会把会话 Cookie 变成永久凭据。卸载、清除应用数据、主动退出、服务端会话失效或风控要求重新验证时,仍需要登录;电脑浏览器和官方 App 的会话也不会自动同步给本应用。
pdd-layout.js 保留原始 #__next 根节点,将它移到屏幕外;另外创建 #hc-pdd-shell 展示身份码与待取包裹。不会搬走 React 原节点,也不另造一个带独立滚动条的可见 iframe。
身份码复用官方生成的图片或 SVG,默认横向居中,点击后由展示层旋转放大。待取区只投影当前待取列表或空状态,隐藏推荐商品、已取记录和原始底栏。已列出的包裹信息供直接查看。进入官方号码管理前保留当前卡片,待目标页面准备后再切换。
PddBundleAdapter 对身份码组件(1235-<hash>.js)和包裹组件(8905-<hash>.js 或 5709-<hash>.js)进行唯一锚点匹配,在组件生命周期内注册官方查询回调。响应处理只报告成功布尔值。
pdd-section-refresh.js 按分区去重,允许两个分区并行,12 秒超时;pdd-layout.js 固定所点卡片高度、隐藏旧显示、等待官方状态更新后替换这一块,另一块 DOM 不变。失败只在当前卡片显示重试。上游脚本结构不匹配时不勉强替换、不误绑回调,也不退回整页刷新。
- 原生
PickupLoadingView先遮住未整理的原页。合并页面建立后,应用读取卡片尺寸,等待postVisualStateCallback确认绘制,再淡出加载层。 - 脚本执行早于
#__next挂载时,等待根节点出现;即使超过提示时间,也允许晚到节点继续初始化。 - 除提交回调外,文档完成回调也能启动交接;遮罩期间每 500ms 检查就绪,最多 60 次。已准备好但缺少新 console 阶段时仍可恢复。不会因此自动重载网页或重复业务请求。
- 内容默认不透明,短暂入场效果在隐藏时取消。已访问页保持附着,避免返回时只剩有标题的空白卡片。
SwitchMotion 用一个 0—1 进度同时驱动中间页面横移、顶部图标标题纵向切换和底部选中背景移动。松手时按半屏距离判断;速度达到 600dp/s 且移动至少 24dp 时支持短距离快滑。SwipeFrameLayout 区分横向意图和竖向滚动,取消时回到已选平台;未访问页预览只有静态加载指示,落定后才创建并加载 WebView。
四个平台统一使用圆点加载指示,不按未知内容绘制骨架灯条。身份码内容区按屏宽预留固定高度,原生加载盒与网页卡片共用尺寸,从首次加载到出码保持同高;点击放大时才展开。待取包裹卡片可按真实内容平滑调整高度,再淡入内容。拼多多的合并页使用设备宽度视口,进入官方表单时恢复原视口配置。淘宝空包裹状态单独整理为整体居中的图片和提示文字。淘宝和拼多多等待两区展示层就绪及动画结束;等待超时仍可展示局部错误与重试入口。
键盘只缩减网页可用区域,底栏保持物理位置。登录状态提示使用固定阶段 / 布尔值;这只是界面状态,不作为认证凭据。
退出时关闭当前平台旧网页,再用 AndroidX WebKit 的按站点删除能力清理其 Cookie、JS 存储和缓存,完成后打开登录入口。淘宝范围为项目允许的五个登录站点,拼多多为 pinduoduo.net,京东为 jd.com。不会调用全局 Cookie / WebStorage 清理来退出单个平台。WebView 不支持该能力时提示更新。
需要 JDK 17+、Android SDK Platform 35、Build Tools 36.0.0、Node.js 24+。不依赖 Gradle:aapt2 → javac → D8 → zipalign → apksigner。
npm ci --ignore-scripts
.\build-android.ps1 -Configuration Release -AndroidSdk 'D:\path\to\SDK' -JavaHome 'D:\path\to\JDK'默认即为 Release;-Configuration Debug 可单独生成开发产物。Release 显式 android:debuggable="false",WebView 调试也始终关闭。产物同步到根目录与 dist/,并生成 SHA256 与 release.json。
签名延续原调试期证书,用于兼容已有安装;本机密钥仍位于 .local/debug.keystore,不进入 Git 或 APK。Release 构建在缺少该密钥时会停止,避免悄悄生成另一把密钥。应用商店发布需另行规划生产签名与迁移。
AndroidX WebKit 精简库随仓库提供并在构建前校验 SHA256;其来源、Apache 许可和离线重建方式见 依赖说明。
图标采用奶油色圆角底板、深红描边与角色抱快递箱的设计。源图位于 design/icon-candidates/icon-02.png。
采用 Android 自适应图标:mipmap-anydpi-v26/ic_launcher.xml 组合背景色 #FCF6E7 与前景位图,前景用 <inset> 内缩 13%。这个比例是按「底板描边正好落在 72dp 可见视口边缘」算出来的,使深红描边贴住图标边界;背景与底板同色,遮罩裁切不会露出接缝。
一套资源即可适配所有密度与桌面图标尺寸,不需要多套 mipmap-*dpi。但遮罩形状由桌面决定,红框只能对齐圆角方形遮罩,圆形遮罩桌面上四角描边会被裁掉一部分。换算方式、重新生成步骤和验收记录见 应用图标原理。
构建会运行导航域名限制、同源映射、组件适配、独立刷新、登录保护、DOM 投影、加载恢复、切换及退出隔离等回归,再检查 DEX、对齐、签名与包信息。真机安装与无线调试见 无线调试说明,逐版本验证记录见 内嵌网页版本验证记录。
已在真机验证官方真实身份码显示、双卡片布局、分区刷新、切换保留及遗漏就绪回调恢复。退出隔离测试只使用虚构站点,不代替真实账号退出 / 重登验收;有实际待取件时的全部详情、长时间保活和码过期更新仍需实际场景验证。
曾出现拼多多偶发长时间加载、随后自行恢复;已修复可复现的晚挂载缺口并补充遮罩恢复,但当时完整状态未捕获,不能保证排除所有网络或上游变更因素。H5 和公开脚本结构受平台更新影响,适配不匹配时会停止对应操作并提示重试。
应用只申请网络权限,不实现拍照 / 文件上传验证。不在独立文件或日志中保存账号、验证码、Cookie、接口响应或码值;网页登录数据由系统 WebView 持有,应用禁用系统备份。
| 文件 | 职责 |
|---|---|
MainActivity.java |
原生容器、淘宝集成、标题与底栏、键盘和生命周期 |
CainiaoPage.java / assets/cainiao-layout.js |
菜鸟官方身份码、授权与淘宝会话衔接 |
JdPage.java / JdIdentityCard.java |
京东订单与官方身份码的独立加载、刷新及登录 |
GlassThemeSwitch.java / ThemeTransition.java |
离线玻璃开关、拖动预览与绘制同步 |
TaobaoLoginTheme.java / assets/taobao-login-theme.js |
官方登录 iframe 的配色与绘制就绪 |
assets/login-agreements.js |
限定登录来源的协议跳转拦截,保留确认圈 |
PddPage.java |
拼多多 WebView、公开脚本适配、登录返回及绘制交接 |
UrlPolicy.java |
官方 HTTPS 导航、公开脚本及固定深链范围 |
SwitchMotion.java / SwipeFrameLayout.java |
联动进度、拖动识别与落定规则 |
SiteDataClearer.java / LogoutSites.java |
当前平台按站点退出 |
assets/taobao.html |
淘宝双来源投影与卡片布局 |
assets/pdd-same-origin.js |
官方同源 API 路由映射 |
assets/pdd-layout.js |
拼多多投影、表单返回及加载恢复 |
PddBundleAdapter.java / assets/pdd-section-refresh.js |
官方组件回调与独立刷新协调 |
Java 文件均位于 app/src/main/java/com/fairycrane/handycode/,网页资源位于 app/src/main/assets/。
本项目自行编写的源码以 MIT 许可 发布。玻璃开关改编自 Zsolt Kacso 的 Glass Light Toggle,来源保留在组件源码中;第三方代码和素材的权属不因本项目的 MIT 许可而改变。随仓库提供的 AndroidX WebKit 精简库为 Apache License 2.0,来源与许可文本见 third_party/androidx-webkit-1.13.0。
应用图标由作者提供的参考图生成,仅作本项目标识使用;若其中涉及第三方角色形象,其权利归原权利人,MIT 许可不涵盖该图形。