背景介绍

众所周知的背景:

  1. 苏康码打开很慢,在支付宝中如果没有快捷键,需要以下步骤:点击打开支付宝 -> 点击健康码 -> 点击立即查看,如果设置了长按图标打开健康码,也得至少两步;其他 APP 比如“苏周到”,可以实现长按快捷键后一步访问,但是其中存在三个步骤:APP 启动 -> 健康码小程序启动 -> 加载网页,这种不可理喻的框架,在某些低端机上冷启动,可能需要长达数十秒的时间;
  2. 行程卡打开也很慢,在微信小程序中打开,不知道为什么每次都让我确认一下“同意并授权运营商查询”,严重影响效率;
  3. 很多地方两个码都要查,于是慢*2,话说我也不知道为什么有关部门不把这两个码合二为一……

所以干脆 DIY 一个。

开发流程

我想做出这样的效果:打开 APP 后,直接显示苏康码,滑动屏幕可切换到行程码,不需要任何多余的点击动作。

技术栈选择

我没有任何 APP 开发经验,所以相当于新手。因为最近用 C# 和 .NET 框架比较多,经 V2EX 网友提醒,我选择了 Xamarin 框架。据说如果新手想快速尝试跨平台 APP 开发,用 flutter 比较好,但是……whatever,支持一下微软,及其宇宙第一 IDE。

获取苏康码直链

既然苏康码本质上是网页,而且我在朋友圈了解到,可以获取到直链而且是不需要认证的,只要 token 对就行了,那就简单了。

于是我决定使用 Fiddler 抓包,大致步骤就是:配好 Fiddler 的监听端口,然后保证电脑和手机在同一个局域网内,手机在 WiFi 设置里配置好 Fiddler 的代理。

测试的 APP 是苏周到,不出所料,苏康码链接是 HTTPS 的,想解密只能在手机上安装一个证书然后中间人了。

导出 Fiddler 的证书并复制到手机上,MIUI 安装证书的步骤也很简单,记得在抓完包之后删除这个证书就好。

然后就可以解密 HTTPS 流量。理论上,对于现在的 Android 版本,APP 可以选择不信任用户安装的证书,但还好,苏康码并没有采取这样的机制。

解析出来的苏康码的直链很简单,就是 https://jsstm.jszwfw.gov.cn/jkmIndex.html?token=xxxxxxxxxxxxxxxx&uuid=xxxxxxxxxxxxxxx 这样的格式,直接访问就可以看到自己的苏康码界面。

获取行程码直链

行程码直链更简单,直接就可以搜到: https://xc.caict.ac.cn/ 。有趣的是,行程码居然是用 Vue 框架做的,如果只是普通的 HTML 表单页面的话,我也许会做一个自动发验证码查询的功能。

APP 开发

安装移动端开发相关 SDK 后,启动宇宙最强 IDE,新建一个空项目叫 ShuangShuangMa (随便起一个名字,双双码),然后面向 Google 编程……基本上只要查一下怎么使用 WebView 以及如何实现滑动切换页面就好了。

代码非常简单,xaml 页面如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?xml version="1.0" encoding="utf-8" ?>
<CarouselPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ShuangShuangMa.MainPage">

<ContentPage>
<StackLayout>
<WebView x:Name="WebView_SuKangMa" VerticalOptions="FillAndExpand" />
<Button Text="点击刷新" Margin="50,10" Clicked="Button_RefreshSuKangMa_Clicked" />
</StackLayout>
</ContentPage>
<ContentPage>
<StackLayout>
<WebView x:Name="WebView_XingChengMa" VerticalOptions="FillAndExpand" />
</StackLayout>
</ContentPage>

</CarouselPage>

C# 逻辑如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
using System;
using Xamarin.Forms;

namespace ShuangShuangMa
{
public partial class MainPage : CarouselPage
{
public MainPage()
{
InitializeComponent();
WebView_SuKangMa.Source = "https://jsstm.jszwfw.gov.cn/jkmIndex.html?token=xxxxxx&uuid=xxxxxx";
WebView_XingChengMa.Source = "https://xc.caict.ac.cn/";
}

private void Button_RefreshSuKangMa_Clicked(object sender, EventArgs e)
{
WebView_SuKangMa.Reload();
}
}
}

部分解释:

  1. 添加刷新按钮是因为,WebView 在后台不会运行,而苏康码上的时间又是在前端运算的,所以防止再次打开应用后,苏康码的时间不对;
  2. 行程码网页在重新加载后就必须重新认证手机号,而 Android 应用在触发返回按钮后,会关闭所有的 WebView,所以需要在 MainActivity.cs 中添加以下代码以便把返回按钮当 Home 键用:
1
2
3
4
public override void OnBackPressed()
{
MoveTaskToBack(true);
}

当然,应用安装后得关闭电池优化、锁在后台,毕竟被清理掉之后又得重新认证行程码。

至此,APP 完成。

效果展示

效果见下面的视频:

话说,本来想着 Xamarin 是跨平台的,准备给玲玲的 iPhone 也整一个的,但无奈意识到自己没有 Mac,作罢。