Full Code of kalvinGit/J12306 for AI

master 69298ea5c070 cached
42 files
281.0 KB
139.2k tokens
247 symbols
1 requests
Download .txt
Showing preview only (335K chars total). Download the full file or copy to clipboard to get everything.
Repository: kalvinGit/J12306
Branch: master
Commit: 69298ea5c070
Files: 42
Total size: 281.0 KB

Directory structure:
gitextract_po6zbghf/

├── README.md
├── lib/
│   ├── activation-1.1.1.jar
│   ├── hutool-all-4.6.6.jar
│   ├── javax.mail-1.5.4.jar
│   └── snakeyaml-1.25.jar
└── src/
    ├── com/
    │   └── kalvin/
    │       └── J12306/
    │           ├── AI/
    │           │   ├── Easy12306AI.java
    │           │   └── ImageAI.java
    │           ├── Go12306.java
    │           ├── Main.java
    │           ├── api/
    │           │   ├── AlternateOrder.java
    │           │   ├── Captcha.java
    │           │   ├── CheckCaptcha.java
    │           │   ├── CheckOrderInfo.java
    │           │   ├── CheckRandCodeAsync.java
    │           │   ├── CheckUser.java
    │           │   ├── ConfirmSingleForQueue.java
    │           │   ├── GetJS.java
    │           │   ├── GetPassCodeNew.java
    │           │   ├── GetQueueCount.java
    │           │   ├── Login.java
    │           │   ├── MyOrder.java
    │           │   ├── PassengerDTOS.java
    │           │   ├── QueryOrderWaitTime.java
    │           │   ├── RepeatSubmitToken.java
    │           │   ├── SubmitOrderRequest.java
    │           │   └── Ticket.java
    │           ├── cache/
    │           │   └── TicketCache.java
    │           ├── config/
    │           │   ├── Constants.java
    │           │   ├── TicketSeatType.java
    │           │   ├── UrlConfig.java
    │           │   ├── Urls.java
    │           │   └── UrlsEnum.java
    │           ├── dto/
    │           │   ├── SubmitTicketInfoDTO.java
    │           │   ├── TicketInfoDTO.java
    │           │   └── UserInfoDTO.java
    │           ├── exception/
    │           │   └── J12306Exception.java
    │           ├── http/
    │           │   └── Session.java
    │           └── utils/
    │               ├── EmailUtil.java
    │               ├── J12306Util.java
    │               ├── StationUtil.java
    │               └── YmlUtil.java
    └── config.yml

================================================
FILE CONTENTS
================================================

================================================
FILE: README.md
================================================
# J12306抢票助手
12306抢票程序JAVA版,自动登录-验证-查票-购票/自动候补。只需简单的配置即可运行进行快捷抢票。

### 使用说明
##### 引入jar依赖
* 手动添加项目lib文件夹中的依赖包
##### 配置文件config.yml
```
# 请修改相关配置

# 12306账号密码配置(暂时没用到)
j12306:
  user: 182xxxx
  password: 123456

  ticket:
    queryspeed: 2000 # 刷票速度(单位毫秒)。默认2秒。温馨提示:刷票频率不要过快,避免封IP(暂未测试过)
    alternate: true # 开启自动候补
    queryp: Z # 查票默认接口(可选值:A、Z)。说明:由于12306官方查票接口经常在A和Z两个接口中变更,所以为了方便,在此处加了默认接口配置。

  # 通知配置
  notice:
    # 电子邮件配置
    email:
      sender:
        from: hutool@yeah.net   # 发件人(必须正确,否则发送失败)
        host: smtp.yeah.net    # 邮件服务器的SMTP地址,可选,默认为smtp.<发件人邮箱后缀>
        port: 25    # 邮件服务器的SMTP端口,可选,默认25
        user: hutool    # 用户名
        pass: qlw2e3    # 密码(注意,某些邮箱需要为SMTP服务单独设置密码,详情查看相关帮助)
      receiver: 1481397688@qq.com   # 接收人邮箱
```

##### 配置抢票信息
* Main.java中,直接配置用户名密码及乘车相关信息即可
##### 开始抢票
* 直接运行Main函数开始抢票。就是这么简单粗暴!

##### 程序运行log
```
[2019-09-22 12:42:33] [INFO] com.kalvin.J12306.api.Login: 进入12306登录页,状态码:200
[2019-09-22 12:42:36] [INFO] com.kalvin.J12306.AI.Easy12306AI: 验证码:3,4
[2019-09-22 12:42:37] [INFO] com.kalvin.J12306.api.Login: 验证码通过,开始密码登录
[2019-09-22 12:42:37] [INFO] com.kalvin.J12306.api.Login: 登录成功
[2019-09-22 12:42:40] [INFO] com.kalvin.J12306.api.Ticket: 进入查询车票页面,开始查票...
[2019-09-22 12:42:42] [INFO] com.kalvin.J12306.Go12306: 可预订车票信息:发车日期:2019-09-26,车次:D2804,出发时间:07:06,到达时间:08:10,座席:一等座1、二等座12、无座有
[2019-09-22 12:42:42] [INFO] com.kalvin.J12306.Go12306: 可预订车票信息:发车日期:2019-09-26,车次:D1849,出发时间:07:23,到达时间:08:37,座席:一等座4、二等座有、无座无
[2019-09-22 12:42:42] [INFO] com.kalvin.J12306.Go12306: 可预订车票信息:发车日期:2019-09-26,车次:D7551,出发时间:09:23,到达时间:11:02,座席:一等座有、二等座有、无座有
[2019-09-22 12:42:42] [INFO] com.kalvin.J12306.Go12306: 可预订车票信息:发车日期:2019-09-26,车次:D2962,出发时间:09:35,到达时间:10:41,座席:一等座8、二等座14、无座有
[2019-09-22 12:42:42] [INFO] com.kalvin.J12306.Go12306: 可预订车票信息:发车日期:2019-09-26,车次:D2812,出发时间:10:05,到达时间:11:11,座席:一等座无、二等座2、无座无
[2019-09-22 12:42:42] [INFO] com.kalvin.J12306.Go12306: 可预订车票信息:发车日期:2019-09-26,车次:D1822,出发时间:11:00,到达时间:12:06,座席:一等座3、二等座无、无座无
[2019-09-22 12:42:42] [INFO] com.kalvin.J12306.Go12306: 可预订车票信息:发车日期:2019-09-26,车次:D2948,出发时间:11:34,到达时间:12:42,座席:一等座无、二等座无、无座有
[2019-09-22 12:42:42] [INFO] com.kalvin.J12306.Go12306: 可预订车票信息:发车日期:2019-09-26,车次:D2834,出发时间:15:15,到达时间:16:27,座席:一等座2、二等座2、无座有
[2019-09-22 12:42:42] [INFO] com.kalvin.J12306.Go12306: 可预订车票信息:发车日期:2019-09-26,车次:D2980,出发时间:17:19,到达时间:18:25,座席:一等座2、二等座20、无座有
[2019-09-22 12:42:46] [INFO] com.kalvin.J12306.api.CheckOrderInfo: 车票提交通过,正在尝试排队...
[2019-09-22 12:42:46] [INFO] com.kalvin.J12306.api.GetQueueCount: 排队成功,你当前排在6位,当前余票还有101张
[2019-09-22 12:42:46] [INFO] com.kalvin.J12306.api.ConfirmSingleForQueue: 不需要订单验证码,直接提交
[2019-09-22 12:42:46] [INFO] com.kalvin.J12306.api.ConfirmSingleForQueue: 开始正式下单...
[2019-09-22 12:42:48] [INFO] com.kalvin.J12306.api.QueryOrderWaitTime: 下单ing...正在第1次排队ing...
[2019-09-22 12:42:48] [INFO] com.kalvin.J12306.api.QueryOrderWaitTime: 订票成功!
[2019-09-22 12:42:48] [INFO] com.kalvin.J12306.api.QueryOrderWaitTime: 恭喜您订票成功,订单号为:EF71508610, 请立即打开浏览器登录12306,访问‘未完成订单’,在30分钟内完成支付!
[2019-09-22 12:42:48] [INFO] com.kalvin.J12306.api.QueryOrderWaitTime: 以邮件方式通知抢票人
[2019-09-22 12:42:48] [INFO] com.kalvin.J12306.Go12306: 抢票程序结束:STOP
```
### 更新日志
##### 2019-12-24
* 新增座席选择,现在支持座席【商务特等座(P)、一等座(M)、二等座(O)、无座(N)、软卧(4)、硬卧(3)、软座(2)、硬座(1)】
* 优化抢票逻辑及代码
##### 2019-12-22 
* 更改刷票频率(config.yml[j12306.ticket.queryspeed])粒度为毫秒(ms), 原秒(s)。
* config.yml新增配置项:[j12306.ticket.queryp];由于12306官方查票接口经常在A和Z两个接口中变更,
现在支持配置默认查票接口(不是必要的),另外程序也会自动识别无法访问的查票接口,并自动切换,如:queryZ -> queryA
* 更新错误日志输出级别
### 问题反馈
如有疑问,可在项目上issues!
### 常见问题解决
* RAIL_EXPIRATION值已失效<br>
有时候网络原因导致的,请务必多重试几次,如果还是这种情况就更新下logdevice接口的参数;更新步骤:
    * 以下顺序一定要对,不然找不到logdevice
    * 1.浏览器访问:https://kyfw.12306.cn/otn/login/init
    * 2.按f12进入调试模式并点击Network选项
    * 3.清除浏览器缓存的有关12306.cn和kyfw.12306.cn的Cookie(谷歌浏览器点击浏览器地址栏的小锁)
    * 4.按f5重新刷新(只有第1次刷新才有出现,所以不要刷新2次)
    * 5.在Network选项下找到logdevice请求,点击它,在Headers选项下拉到最下面就可以找到如下几个参数,复制替换它即可
* 其它情况登录失败或验证码验证失败<br>
可能的解决方案:
    * 请重试登录多次
    * 确保更新到最新的代码
* 线程【main】无法获取车票信息,状态码:302<br>
可能的解决方案:
    * 确保你IP没被封(在浏览器上12306官网是否能正常查票)
    * 更新最新代码




================================================
FILE: src/com/kalvin/J12306/AI/Easy12306AI.java
================================================
package com.kalvin.J12306.AI;

import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.kalvin.J12306.exception.J12306Exception;

import java.io.File;

/**
 * 此图片识别AI由https://github.com/zhaipro/easy12306提供
 * Create by Kalvin on 2019/9/19.
 */
public class Easy12306AI implements ImageAI {

    private static final Log log = LogFactory.get();

    private String aiUrl;
    private String imgPath;

    public Easy12306AI(String aiUrl, String imgPath) {
        this.aiUrl = aiUrl;
        this.imgPath = imgPath;
    }

    @Override
    public String printCode() {
        try {
            // 此AI不支持验证多个标签的图片验证码
            HttpRequest request = HttpUtil.createPost(this.aiUrl);
            request.form("file", new File(this.imgPath));
            String body = request.execute().body(); // text: 辣椒酱 , images: 调色板 , 雨靴 , 绿豆 , 辣椒酱 , 雨靴 , 雨靴 , 档案袋 , 辣椒酱
            body = body.replaceAll(" ", "");
            // log.info("printCode body = {}", body);
            String tagTxt = body.substring(body.indexOf("text:") + 5, body.indexOf(",images"));
            String imagesTxt = body.substring(body.indexOf("images:") + 7);
            String[] imageTxtArr = imagesTxt.split(",");
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < imageTxtArr.length; i++) {
                if (tagTxt.equals(imageTxtArr[i])) {
                    if (sb.length() > 0) {
                        sb.append(",");
                    }
                    sb.append(i + 1);
                }
            }
            log.info("验证码:{}", sb.toString());
            return sb.toString();
        } catch (StringIndexOutOfBoundsException e) {
            log.info("图片验证码识别AI异常,无法为您自动识别验证码,请重试");
            throw new J12306Exception("图片验证码识别AI异常,无法为您自动识别验证码,请重试:" + e.getMessage());
        }

    }
}


================================================
FILE: src/com/kalvin/J12306/AI/ImageAI.java
================================================
package com.kalvin.J12306.AI;

/**
 * 图片验证码识别AI接口
 * Create by Kalvin on 2019/9/19.
 */
public interface ImageAI {

    /**
     * 打码
     * @return 图片识别码(如12306图片识别码:1,3,5。分别代码横排数起图片位置)
     */
    String printCode();

}


================================================
FILE: src/com/kalvin/J12306/Go12306.java
================================================
package com.kalvin.J12306;

import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpException;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONException;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.kalvin.J12306.api.*;
import com.kalvin.J12306.cache.TicketCache;
import com.kalvin.J12306.config.Constants;
import com.kalvin.J12306.config.TicketSeatType;
import com.kalvin.J12306.dto.TicketInfoDTO;
import com.kalvin.J12306.dto.UserInfoDTO;
import com.kalvin.J12306.exception.J12306Exception;
import com.kalvin.J12306.http.Session;
import com.kalvin.J12306.utils.J12306Util;
import com.kalvin.J12306.utils.StationUtil;
import com.kalvin.J12306.utils.YmlUtil;

import java.util.LinkedHashMap;
import java.util.List;

/**
 * 12306抢票程序
 * Create by Kalvin on 2019/9/18.
 */
public class Go12306 {

    private static final Log log = LogFactory.get();

    private Session session;    // 会话保持

    private String username;    // 12306用户账号
    private String password;    // 密码

    private TicketCache ticketCache = TicketCache.getInstance();

    /*乘客订票相关参数*/
    private String trainDate;  // 乘车日期(2019-10-01)
    private String fromStation; // 出发站(IZQ)
    private String toStation;   // 到达站(FAQ)
    private String trainNums;   // 列车编号(D2834)。多个使用英文半角逗号分隔。目前暂时只能人工看列车编号啦
    private String seats;   // 列车座席。M,O,N分别代表:一等座、二等座、无座。目前只支持这三种选择

    private int queryCount = 0; // 刷票次数

    public static Go12306 newInstance() {
        return new Go12306();
    }

    public Go12306 initUser(String username, String password) {
        this.username = username;
        this.password = password;
        return this;
    }

    /**
     * 初始化订票参数信息
     * @param trainDate 乘车日期
     * @param fromStation 始发站
     * @param toStation 终点站
     * @param trainNums 列表车次
     * @param seats 座席类型:M、O、N
     */
    public Go12306 initBookTicketInfo(String trainDate, String fromStation, String toStation, String trainNums, String seats) {
        this.trainDate = J12306Util.formatDateStr(trainDate);
        final String fromStationCode = StationUtil.getStationCode(fromStation);
        if (fromStationCode == null) {
            throw new J12306Exception("无法找到始发站站点【" + fromStation + "】,请确保始发站点名正确。");
        }
        final String toStationCode = StationUtil.getStationCode(toStation);
        if (toStationCode == null) {
            throw new J12306Exception("无法找到到达站站点【" + fromStation + "】,请确保到达站点名正确。");
        }
        this.fromStation = fromStationCode;
        this.toStation = toStationCode;
        this.trainNums = trainNums;
        this.seats = seats;
        return this;
    }

    public void run() {
        // 构建会话
        this.session = new Session();
        // 开始登录
        Login login = new Login(this.session, this.username, this.password);
        UserInfoDTO userInfo = login.send();
        int tryLoginCount = 0;
        while (true) {
            if (userInfo == null) {
                if (tryLoginCount >= 5) {
                    throw new J12306Exception("无法登录,程序已终止,请手动重试登录");
                }
                log.error("登录失败,正在第{}次尝试登录", tryLoginCount++);
                userInfo = login.send();
            } else {
                break;
            }
        }
        // 用户信息保存到缓存中
        this.ticketCache.put(Constants.USER_INFO_KEY, userInfo);

        // 开始查询余票
        Ticket ticket = new Ticket(this.session, this.trainDate, this.fromStation, this.toStation);

        int querySpeed = (Integer) YmlUtil.get("j12306.ticket.queryspeed");

        // 计算刷票粒度
//        int intervalTime = querySpeed / threadPoolSize;
//        ExecutorService executorService = Executors.newFixedThreadPool(threadPoolSize);

        int queryA302Count = 0, queryZ302Count = 0;
        String usingQuery = (String) YmlUtil.get("j12306.ticket.queryp");
        boolean isPutTime = false;
        stopLop: while (true) {
            HttpResponse httpResponse;
            try {
                if ("A".equals(usingQuery)) {
                    httpResponse = ticket.queryA();
                } else if ("Z".equals(usingQuery)) {
                    httpResponse = ticket.queryZ();
                } else {
                    throw new J12306Exception("查票接口异常,请确认config.yml[j12306.ticket.queryp]配置正确");
                }
            } catch (HttpException e) {
                log.error("请求超时,或无法访问,错误信息:{}", e.getMessage());
                continue;
            }

            String body = httpResponse.body();
//            log.info("query tickets status = {},body={}", httpResponse.getStatus(), body);

            if (httpResponse.getStatus() == Constants.REQ_SUCCESS_STATUS) {
                List<TicketInfoDTO> ticketInfoDTOS;
                try {
                    ticketInfoDTOS = J12306Util.parseTicketInfo(body);
                } catch (JSONException e) {
                    log.error("查询车票发生未知异常:{}", e.getMessage());
                    continue;
                }
                for (TicketInfoDTO ticketInfoDTO : ticketInfoDTOS) {
                    if (!ticketInfoDTO.isOnSale()) {
                        continue;
                    }
                    String trainNum = ticketInfoDTO.getTrainNum();
                    String canNotAlternateSeatType = ticketInfoDTO.getCanNotAlternateSeatType();

                    final LinkedHashMap<String, Boolean> seatsTicketInfo = J12306Util.getSeatsTicketInfo(this.seats, ticketInfoDTO);

                    // 先进行一次解码。避免提交后再编码一次导致参数失效
                    String secretStr = J12306Util.urlDecode(ticketInfoDTO.getSecretStr());
                    String leftTicket = J12306Util.urlDecode(ticketInfoDTO.getLeftTicket());
                    String trainNo = ticketInfoDTO.getTrainNo();
                    String fromStationCode = ticketInfoDTO.getFormStationTelecode();
                    String toStationCode = ticketInfoDTO.getToStationTelecode();
                    String trainLocation = ticketInfoDTO.getTrainLocation();

                    if (!J12306Util.noNeedTicket(seatsTicketInfo)) {
                        log.info("可预订车票信息:发车日期【{}】,车次【{}】,出发时间:{},到达时间:{},座席:",
                                trainDate, trainNum, ticketInfoDTO.getGoOffTime(), ticketInfoDTO.getArrivalTime());
                    }

                    // 跳过不是购票意向的车次
                    if (!this.trainNums.contains(trainNum)) {
                        continue;
                    }

                    // 候补订单
                    if (J12306Util.noNeedTicket(seatsTicketInfo)) {
                        if ((boolean) YmlUtil.get("j12306.ticket.alternate")) {
                            // 判断是否能候补订单
                            if (this.ticketCache.get(trainNo) != null) {
                                continue;
                            }
                            if (ticketInfoDTO.isCanAlternate()) {
                                final String allEncStr = new PassengerDTOS(this.session).getPassengerEncStr();
                                for (String seatCode : seatsTicketInfo.keySet()) {
                                    if ("".equals(canNotAlternateSeatType) || !canNotAlternateSeatType.contains(seatCode)) {
                                        try {
                                            log.info("准备提交候补订单:车次【{}】,发车日期【{}】,座席类型:{}", trainNum, trainDate, seatCode);
                                            AlternateOrder alternateOrder = new AlternateOrder(this.session, ticketInfoDTO.getSecretStr(), allEncStr, seatCode, trainNo);
                                            if (alternateOrder.checkFace()) {
                                                alternateOrder.getSuccessRate();
                                            }
                                        } catch (Exception e) {
                                            if (e instanceof J12306Exception) {
                                                log.info("抢票程序结束");
                                                break stopLop;
                                            }
                                            log.error("候补异常:{},列车【】加入小黑屋关闭3分钟", e.getMessage(), trainNum);
                                            ticketCache.put(trainNo, trainNo, Constants.BLACK_ROOM_CACHE_EXP_TIME * 60);
                                        }
                                    }
                                }
                            }
                        }
                        continue;
                    }

                    // 跳过小黑屋中的车次
                    if (ticketCache.get(trainNum) != null) {
                        continue;
                    }

                    try {
                        for (String seatCode : seatsTicketInfo.keySet()) {
                            if (seatsTicketInfo.get(seatCode)) {
                                log.info("提交订单:车次【{}】,发车日期【{}】,座席类型:{}", trainNum, trainDate, TicketSeatType.get(seatCode).getName());
                                new SubmitOrderRequest(this.session, secretStr, seatCode, trainDate, fromStationCode, toStationCode, trainNo, trainNum, trainLocation)
                                        .send();
                            }
                        }
                    } catch (J12306Exception e) {
                        log.info("抢票程序结束:{}", e.getMsg());
                        break stopLop;
                    }
                }
                this.queryCount++;
                log.info("-------线程【{}】已为账号{}刷票{}次,启程日期:{}--------", Thread.currentThread().getName(), this.username, this.queryCount, trainDate);
            } else {
                log.error("-------线程【{}】无法获取车票信息,状态码:{};程序会在{}次访问302后切换到另一个查询接口", Thread.currentThread().getName(), httpResponse.getStatus(), Constants.MAX_302);
                if (httpResponse.getStatus() == 302) {
                    if ("A".equals(usingQuery)) {
                        queryA302Count++;
                    }
                    if ("Z".equals(usingQuery)) {
                        queryZ302Count++;
                    }
                    if (queryA302Count >= Constants.MAX_302) {
                        usingQuery = "Z";
                    }
                    if (queryZ302Count >= Constants.MAX_302) {
                        usingQuery = "A";
                    }
                }
            }
            String puttime = (String) YmlUtil.get("j12306.ticket.puttime");
            if (!StrUtil.isNullOrUndefined(puttime)) {
                if (J12306Util.getCurrAftOneMinuteTime().equals(puttime.replace("-", ":"))) {
                    isPutTime = true;
                    querySpeed = (Integer) YmlUtil.get("j12306.ticket.puttimespeed");
                }
            }
            if (isPutTime && J12306Util.getAfter5MinuteTime(puttime.replace("-", ":")).equals(J12306Util.getCurrTime())) {
                isPutTime = false;
                querySpeed = (Integer) YmlUtil.get("j12306.ticket.queryspeed");
            }
            J12306Util.sleepM(querySpeed);
        }

    }


}


================================================
FILE: src/com/kalvin/J12306/Main.java
================================================
package com.kalvin.J12306;

import com.kalvin.J12306.utils.EmailUtil;
import com.kalvin.J12306.utils.J12306Util;

public class Main {

    public static void main(String[] args) {
        // 测试配置邮件是否能成功发送(收件人能成功接收到测试邮件证明配置正确)
//        EmailUtil.sendTest();
        // 可以在控制台打印指定日期、出发站点、达到站点的所有车次,主要为了方便填写车次信息
        // 你可以启动抢票前执行此方法(不是必要的),获取指定日期车次后,填写抢票信息,再启动抢票
//        J12306Util.printlnLeftTicket("2020-01-21", "广州", "怀集");
        // 开始抢票
        selectTicket1();
    }


    public static void selectTicket1() {
        Go12306.newInstance()
                .initUser("182xxxx", "123456")    // 用户名/密码
                .initBookTicketInfo("2020-01-21", // 乘车日期
                        "广州",   // 始发站
                        "怀集",   // 到达站
                        "D1818,D1822,D2948,D1870,G2904,D2972,D1872,D2936",    // 列车编号(D2834)。多个使用英文半角逗号分隔。目前暂时只能人工看列车编号啦
                        "P,M,O,N,4,3,2,1")    // 列车座席。P,M,O,N,4,3,2,1分别代表:商务特等座(P)、一等座(M)、二等座(O)、无座(N)、软卧(4)、硬卧(3)、软座(2)、硬座(1)。
                .run();
    }

    public static void selectTicket2() {
        Go12306.newInstance()
                .initUser("182xxxx", "123456")    // 用户名/密码
                .initBookTicketInfo("2020-01-22", // 乘车日期
                        "广州",   // 始发站
                        "怀集",   // 到达站
                        "D1882,D7551,D2962,D1818,D1754,D1822",    // 列车编号(D2834)。多个使用英文半角逗号分隔。目前暂时只能人工看列车编号啦
                        "P,M,O,N,4,3,2,1")    // 列车座席。P,M,O,N,4,3,2,1分别代表:商务特等座(P)、一等座(M)、二等座(O)、无座(N)、软卧(4)、硬卧(3)、软座(2)、硬座(1)。
                .run();
    }

}


================================================
FILE: src/com/kalvin/J12306/api/AlternateOrder.java
================================================
package com.kalvin.J12306.api;

import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.kalvin.J12306.cache.TicketCache;
import com.kalvin.J12306.config.Constants;
import com.kalvin.J12306.config.UrlsEnum;
import com.kalvin.J12306.dto.UserInfoDTO;
import com.kalvin.J12306.exception.J12306Exception;
import com.kalvin.J12306.http.Session;
import com.kalvin.J12306.utils.EmailUtil;
import com.kalvin.J12306.utils.J12306Util;

import java.util.HashMap;

/**
 * 候补订单
 * Create by Kalvin on 2019/9/25.
 */
public class AlternateOrder {

    private final static Log log = LogFactory.get();

    private Session session;
    private String secretStr;
    private String allEncStr;
    private String seatType;
    private String trainNo;
    private String jzdhDateE;
    private String jzdhHourE;

    public AlternateOrder(Session session, String secretStr, String allEncStr, String seatType, String trainNo) {
        this.session = session;
        this.secretStr = secretStr;
        this.allEncStr = allEncStr;
        this.seatType = seatType;
        this.trainNo = trainNo;
    }

    public boolean checkFace() {
        TicketCache ticketCache = TicketCache.getInstance();
        HashMap<String, Object> formData = new HashMap<>();
        formData.put("secretList", this.getSecretList());
        formData.put("_json_att", "");
        HttpResponse httpResponse = this.session.httpClient.send(UrlsEnum.CHECK_FACE, formData);
        String body = httpResponse.body();
//        log.info("checkFace body ={}", body);
        JSON parse = JSONUtil.parse(body);
        if ((boolean) parse.getByPath("status") && parse.getByPath("data") != null) {
            if ((boolean) parse.getByPath("data.face_flag")) {
                log.info("已通过人脸核验,可以进行候补车票!");
                return true;
            } else {
                log.info("你未通过人脸核验,通过人证一致性核验的用户及激活的“铁路畅行”会员可以提交候补需求,请您按照操作说明在铁路12306app.上完成人证核验");
                return false;
            }
        } else if (parse.getByPath("messages") != null) {
            ticketCache.put(this.trainNo, this.trainNo, Constants.BLACK_ROOM_CACHE_EXP_TIME * 60);
            log.info(((JSONArray) parse.getByPath("messages")).get(0).toString());
            return false;
        }
        ticketCache.put(this.trainNo, this.trainNo, Constants.BLACK_ROOM_CACHE_EXP_TIME * 60);
        return false;
    }

    public void getSuccessRate() {
        HashMap<String, Object> formData = new HashMap<>();
        formData.put("successSecret", this.getSuccessSecret());
        formData.put("_json_att", "");
        HttpResponse httpResponse = this.session.httpClient.send(UrlsEnum.GET_SUCCESS_RATE, formData);
        String body = httpResponse.body();
//        log.info("getSuccessRate body ={}", body);
        JSON parse = JSONUtil.parse(body);
        if ((boolean) parse.getByPath("status") && parse.getByPath("data") != null) {
//            this.trainNo = (String) parse.getByPath("data.flag[0].train_no");
            String info = (String) parse.getByPath("data.flag[0].info");
            log.info("开始提交候补订单,{}", info);
            this.submitOrderRequestAN();
        } else {
            log.info("getSuccessRate message:{}{}", ((JSONArray) parse.getByPath("messages")).get(0).toString(), parse.getByPath("validateMessages").toString());
        }
    }

    private void submitOrderRequestAN() {
        HashMap<String, Object> formData = new HashMap<>();
        formData.put("secretList", this.getSecretList());
        formData.put("_json_att", "");
        HttpResponse httpResponse = this.session.httpClient.send(UrlsEnum.SUBMIT_ORDER_REQUEST_AN, formData);
        String body = httpResponse.body();
//        log.info("submitOrderRequestAN body ={}", body);
        JSON parse = JSONUtil.parse(body);
        if ((boolean) parse.getByPath("status") && parse.getByPath("data.flag") != null) {
            this.lineUpToPayInit();
            this.passengerInitApi();
            this.confirmHB();
        } else {
            log.info("提交候补订单失败:{}{}", ((JSONArray) parse.getByPath("messages")).get(0).toString(), parse.getByPath("validateMessages").toString());
        }
    }

    private void lineUpToPayInit() {
        this.session.httpClient.send(UrlsEnum.LINE_UP_TO_PAY);
    }

    private void passengerInitApi() {
        HttpResponse httpResponse = this.session.httpClient.send(UrlsEnum.PASSENGER_INIT_API);
        String body = httpResponse.body();
        JSON parse = JSONUtil.parse(body);
        if ((boolean) parse.getByPath("status") && parse.getByPath("data") != null) {
            this.jzdhDateE = (String) parse.getByPath("data.jzdhDateE");
            this.jzdhHourE = (String) parse.getByPath("data.jzdhHourE");
        } else {
            log.info("passengerInitApi message:{}{}", ((JSONArray) parse.getByPath("messages")).get(0).toString(), parse.getByPath("validateMessages").toString());
        }
    }

    private void confirmHB() {
        HashMap<String, Object> formData = this.getConfirmHBParams();
        HttpResponse httpResponse = this.session.httpClient.send(UrlsEnum.CONFIRM_HB, formData);
        String body = httpResponse.body();
//        log.info("confirmHB body ={}", body);
        JSON parse = JSONUtil.parse(body);
        if ((boolean) parse.getByPath("status")) {
            if (parse.getByPath("data.flag") != null) {
                log.info("候补订单排队");
                this.queryQueue();
            } else {
                log.info("confirmHB error:{}", parse.getByPath("data.msg"));
            }
        } else {
            log.info("confirmHB message:{}{}", ((JSONArray) parse.getByPath("messages")).get(0).toString(), parse.getByPath("validateMessages").toString());
        }
    }

    private void queryQueue() {
        int maxNum = 10;
        int i = 0;
        while (i < maxNum) {
            HttpResponse httpResponse = this.session.httpClient.send(UrlsEnum.QUERY_QUEUE);
            String body = httpResponse.body();
            JSON parse = JSONUtil.parse(body);
            if ((boolean) parse.getByPath("status")) {
                log.info("恭喜您候补订单成功,请立即打开浏览器登录12306,访问‘候补订单’,在30分钟内完成支付!");
                EmailUtil.send("12306候补成功", "恭喜您候补订单成功,请立即打开浏览器登录12306,访问‘候补订单’,在30分钟内完成支付!");
                throw new J12306Exception(Constants.THREAD_STOP);
            } else {
                log.info(parse.getByPath("messages") + parse.getByPath("validateMessages").toString());
            }
            i++;
            log.info("正在候补排队{}次", i);
            J12306Util.sleep(1);
        }
    }

    private String getSecretList() {
        String secretList = "{secretStr}#{seatType}|";
        return secretList
                .replace("{secretStr}", this.secretStr)
                .replace("{seatType}", this.seatType);
    }

    private String getSuccessSecret() {
        String successSecret = "{secretStr}#{seatType}";
        return successSecret
                .replace("{secretStr}", this.secretStr)
                .replace("{seatType}", this.seatType);
    }

    private HashMap<String, Object> getConfirmHBParams() {
        HashMap<String, Object> formData = new HashMap<>();
        formData.put("passengerInfo", this.getPassengerInfo());
        formData.put("jzParam", "{0}#{1}"
                .replace("{0}", this.jzdhDateE)
                .replace("{1}", this.jzdhHourE)
                .replace(":", "#"));
        formData.put("hbTrain", "{0},{1}#"
                .replace("{0}", this.trainNo)
                .replace("{1}", this.seatType));
        formData.put("lkParam", "");
        formData.put("sessionId", "");
        formData.put("sig", "");
        formData.put("scene", "nc_login");
        return formData;
    }

    private String getPassengerInfo() {
        TicketCache ticketCache = TicketCache.getInstance();
        UserInfoDTO userInfoDTO = (UserInfoDTO) ticketCache.get(Constants.USER_INFO_KEY);
        String passengerInfo = "1#{name}#1#{idNo}#{encStr};";
        return passengerInfo
                .replace("{name}", userInfoDTO.getName())
                .replace("{idNo}", userInfoDTO.getIdNo())
                .replace("{encStr}", this.allEncStr);
    }
}


================================================
FILE: src/com/kalvin/J12306/api/Captcha.java
================================================
package com.kalvin.J12306.api;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.kalvin.J12306.AI.Easy12306AI;
import com.kalvin.J12306.AI.ImageAI;
import com.kalvin.J12306.config.Constants;
import com.kalvin.J12306.config.UrlConfig;
import com.kalvin.J12306.config.UrlsEnum;
import com.kalvin.J12306.exception.J12306Exception;
import com.kalvin.J12306.http.Session;
import com.kalvin.J12306.utils.J12306Util;

import java.io.File;
import java.util.HashMap;

/**
 * 验证码
 * Create by Kalvin on 2019/9/18.
 */
public class Captcha {

    private Session session;
    private String loginCaptchaImageName;
    private String orderCaptchaImageName;

    public Captcha(Session session) {
        this.session = session;
    }

    /**
     * 登录验证码
     */
    public void getLoginCaptchaImg() {
        UrlConfig urlConfig = UrlsEnum.CAPTCHA.getUrlConfig();
        urlConfig.setUrl(urlConfig.getUrl().replace("{0}", J12306Util.genRandNumber()));
        UrlsEnum.CAPTCHA.setUrlConfig(urlConfig);
        HttpResponse httpResponse = session.httpClient.sendAsync(UrlsEnum.CAPTCHA);
        this.loginCaptchaImageName = this.getNewLoginCaptchaImgFileName();
        httpResponse.writeBody(new File(Constants.CAPTCHA_IMG_PRE_PATH + this.loginCaptchaImageName));
    }

    /**
     * 订单页面验证码
     */
    public String getOrderCaptchaImg() {
        UrlConfig urlConfig = UrlsEnum.GET_PASSCODE_NEW.getUrlConfig();
        urlConfig.setUrl(urlConfig.getUrl().replace("{0}", J12306Util.genRandNumber()));
        UrlsEnum.GET_PASSCODE_NEW.setUrlConfig(urlConfig);
        HttpResponse httpResponse = session.httpClient.sendAsync(UrlsEnum.GET_PASSCODE_NEW);
        this.orderCaptchaImageName = this.getNewOrderCaptchaImgFileName();
        httpResponse.writeBody(new File(Constants.CAPTCHA_IMG_PRE_PATH + this.orderCaptchaImageName));
        return this.orderCaptchaImageName;
    }

    public boolean checkLoginCaptchaImg() {
        J12306Util.sleep(2);
        // 若需要使用其它打码平台AI,在AI包下新增一个类实现ImageAI接口并更换下面图片AI实例即可
        ImageAI imageAI = new Easy12306AI(Constants.IMAGE_AI_URL, Constants.CAPTCHA_IMG_PRE_PATH + this.loginCaptchaImageName);
        String code = imageAI.printCode();
        // 转化为图片坐标点
        String answerCode = J12306Util.getCaptchaPos(code);
//        System.out.println("answerCode = " + answerCode);
        HashMap<String, Object> hashMap = new HashMap<>();
        hashMap.put("answer", answerCode);
        hashMap.put("login_site", "E");
        hashMap.put("rand", "sjrand");
        HttpResponse httpResponse = this.session.httpClient.send(UrlsEnum.CHECK_CAPTCHA, hashMap);
        String body = httpResponse.body();
        if (StrUtil.isBlank(body)) {
            throw new J12306Exception(Constants.UPDATE_LOG_DEVICE_ERROR_MSG);
        }
//        System.out.println("checkLoginCaptchaImg body = " + body);
        JSONObject jsonObject = JSONUtil.parseObj(body);
        String resultCode = jsonObject.get("result_code").toString();
        return "4".equals(resultCode);
    }

    private String getNewLoginCaptchaImgFileName() {
        return "login" + RandomUtil.randomString(5) + ".png";
    }

    private String getNewOrderCaptchaImgFileName() {
        return "order" + RandomUtil.randomString(5) + ".png";
    }
}


================================================
FILE: src/com/kalvin/J12306/api/CheckCaptcha.java
================================================
package com.kalvin.J12306.api;

/**
 * 校验验证码
 * Create by Kalvin on 2019/9/19.
 */
public class CheckCaptcha {
}


================================================
FILE: src/com/kalvin/J12306/api/CheckOrderInfo.java
================================================
package com.kalvin.J12306.api;

import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.kalvin.J12306.config.UrlsEnum;
import com.kalvin.J12306.dto.SubmitTicketInfoDTO;
import com.kalvin.J12306.exception.J12306Exception;
import com.kalvin.J12306.http.Session;

import java.util.HashMap;

/**
 * 检查订单
 * Create by Kalvin on 2019/9/20.
 */
public class CheckOrderInfo {

    private final static Log log = LogFactory.get();

    private Session session;
    private String repeatSubmitToken;
    private String seatType;
    private String passengerTicketStr;
    private String oldPassengerStr;
    private String trainDate;
    private String trainNo;
    private String trainNum;
    private String fromStationCode;
    private String toStationCode;
    private String trainLocation;
    private SubmitTicketInfoDTO submitTicketInfoDTO;

    public CheckOrderInfo(Session session, String repeatSubmitToken, String seatType,
                          String passengerTicketStr, String oldPassengerStr, String trainDate,
                          String trainNo, String trainNum, String fromStationCode, String toStationCode,
                          String trainLocation, SubmitTicketInfoDTO submitTicketInfoDTO) {
        this.session = session;
        this.repeatSubmitToken = repeatSubmitToken;
        this.seatType = seatType;
        this.passengerTicketStr = passengerTicketStr;
        this.oldPassengerStr = oldPassengerStr;
        this.trainDate = trainDate;
        this.trainNo = trainNo;
        this.trainNum = trainNum;
        this.fromStationCode = fromStationCode;
        this.toStationCode = toStationCode;
        this.trainLocation = trainLocation;
        this.submitTicketInfoDTO = submitTicketInfoDTO;
    }

    public void send() {
        HashMap<String, Object> formData = new HashMap<>();
        formData.put("cancel_flag", 2);
        formData.put("bed_level_order_num", "000000000000000000000000000000");
        formData.put("passengerTicketStr", this.passengerTicketStr);
        formData.put("oldPassengerStr", this.oldPassengerStr);
        formData.put("tour_flag", "dc"); // 单程
        formData.put("randCode", "");
        formData.put("whatsSelect", 1);   // 1-成人票 2-学生票
        formData.put("_json_att", "");
        formData.put("REPEAT_SUBMIT_TOKEN", this.repeatSubmitToken);

        try {
            HttpResponse httpResponse = this.session.httpClient.send(UrlsEnum.CHECK_ORDER_INFO, formData);
            String body = httpResponse.body();
            JSON parse = JSONUtil.parse(body);
//            log.info("checkOrderInfo body = {}", body);

            if (parse.getByPath("data.submitStatus") != null && (boolean) parse.getByPath("data.submitStatus")) {
                log.info("车票提交通过,正在尝试排队...");
                int ifShowPassCodeTime = Integer.parseInt((String) parse.getByPath("data.ifShowPassCodeTime"));
                String ifShowPassCode = (String) parse.getByPath("data.ifShowPassCode");
                boolean isNeedCode = "Y".equals(ifShowPassCode);
                // 获取排队队列位置
                new GetQueueCount(
                        this.session,
                        this.repeatSubmitToken,
                        this.trainDate,
                        this.trainNo,
                        this.trainNum,
                        this.passengerTicketStr,
                        this.oldPassengerStr,
                        this.seatType,
                        this.fromStationCode,
                        this.toStationCode,
                        this.trainLocation,
                        ifShowPassCodeTime,
                        isNeedCode,
                        this.submitTicketInfoDTO
                ).send();
            } else {
                log.info("车票提交失败,正在重试...");
            }
        } catch (Exception e) {
            if (e instanceof J12306Exception) {
                throw new J12306Exception(e.getMessage());
            } else {
                log.error("车票提交异常,正在重试...错误信息:{}", e.getMessage());
            }
        }

    }
}


================================================
FILE: src/com/kalvin/J12306/api/CheckRandCodeAsync.java
================================================
package com.kalvin.J12306.api;

import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.kalvin.J12306.config.UrlsEnum;
import com.kalvin.J12306.http.Session;

import java.util.HashMap;

/**
 * 检查订单验证码
 * Create by Kalvin on 2019/9/20.
 */
public class CheckRandCodeAsync {

    private static final Log log = LogFactory.get();

    private Session session;
    private String randCode;
    private String repeatSubmitToken;

    public CheckRandCodeAsync(Session session, String randCode, String repeatSubmitToken) {
        this.session = session;
        this.randCode = randCode;
        this.repeatSubmitToken = repeatSubmitToken;
    }

    public boolean send() {
        HashMap<String, Object> formData = new HashMap<>();
        formData.put("randCode", this.randCode);
        formData.put("rand", "randp");
        formData.put("_json_att", "");
        formData.put("REPEAT_SUBMIT_TOKEN", this.repeatSubmitToken);

        HttpResponse httpResponse = this.session.httpClient.send(UrlsEnum.CHECK_RAND_CODE_ASYNC, formData);
        String body = httpResponse.body();
        JSON parse = JSONUtil.parse(body);
        log.info("CheckRandCodeAsync body = {}", body);
        String checked = (String) parse.getByPath("data.msg");
        return checked.equals("TRUE");
    }
}


================================================
FILE: src/com/kalvin/J12306/api/CheckUser.java
================================================
package com.kalvin.J12306.api;

/**
 * 检查用户状态
 * Create by Kalvin on 2019/9/19.
 */
public class CheckUser {
}


================================================
FILE: src/com/kalvin/J12306/api/ConfirmSingleForQueue.java
================================================
package com.kalvin.J12306.api;

import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.kalvin.J12306.AI.Easy12306AI;
import com.kalvin.J12306.AI.ImageAI;
import com.kalvin.J12306.cache.TicketCache;
import com.kalvin.J12306.config.Constants;
import com.kalvin.J12306.config.UrlsEnum;
import com.kalvin.J12306.dto.SubmitTicketInfoDTO;
import com.kalvin.J12306.exception.J12306Exception;
import com.kalvin.J12306.http.Session;
import com.kalvin.J12306.utils.J12306Util;

import java.util.HashMap;

/**
 * 真正下单
 * Create by Kalvin on 2019/9/20.
 */
public class ConfirmSingleForQueue {

    private final static Log log = LogFactory.get();

    private Session session;
    private String repeatSubmitToken;
    private String passengerTicketStr;
    private String oldPassengerStr;
    private String trainNum;
    private String trainLocation;
    private int ifShowPassCodeTime;
    private boolean isNeedCode;
    private SubmitTicketInfoDTO submitTicketInfoDTO;

    public ConfirmSingleForQueue(Session session, String repeatSubmitToken, String passengerTicketStr,
                                 String oldPassengerStr, String trainNum, String trainLocation, int ifShowPassCodeTime,
                                 boolean isNeedCode, SubmitTicketInfoDTO submitTicketInfoDTO) {
        this.session = session;
        this.repeatSubmitToken = repeatSubmitToken;
        this.passengerTicketStr = passengerTicketStr;
        this.oldPassengerStr = oldPassengerStr;
        this.trainNum = trainNum;
        this.trainLocation = trainLocation;
        this.ifShowPassCodeTime = ifShowPassCodeTime;
        this.isNeedCode = isNeedCode;
        this.submitTicketInfoDTO = submitTicketInfoDTO;
    }

    public void send() {
        TicketCache ticketCache = TicketCache.getInstance();
        String randCode = "";   // 订单验证码,默认空
        try {
            if (this.isNeedCode) {
                log.info("需要订单验证码,正在打印验证码...");
                Captcha captcha = new Captcha(this.session);
                // 获取订单验证码
                String orderCaptchaImg = captcha.getOrderCaptchaImg();
                for (int i = 0; i < 3; i++) {
                    // 若需要使用其它打码平台AI,在AI包下新增一个类实现ImageAI接口并更换下面图片AI实例即可
                    ImageAI imageAI = new Easy12306AI(Constants.IMAGE_AI_URL, Constants.CAPTCHA_IMG_PRE_PATH + orderCaptchaImg);
                    String code = imageAI.printCode();
                    // 转化为图片坐标点
                    randCode = J12306Util.getCaptchaPos(code);
                    // 检查验证码
                    boolean checkCode = new CheckRandCodeAsync(this.session, randCode, this.repeatSubmitToken).send();
                    if (checkCode) {
                        log.info("验证码通过,正在提交订单...");
                        break;
                    } else {
                        log.info("验证码不通过,{}次重试中...", i + 1);
                    }
                }
            } else {
                log.info("不需要订单验证码,直接提交");
            }

            log.info("开始正式下单...");
            J12306Util.sleep(ifShowPassCodeTime / 1000);

            HashMap<String, Object> formData = new HashMap<>();
            formData.put("passengerTicketStr", this.passengerTicketStr);
            formData.put("oldPassengerStr", this.oldPassengerStr);
            formData.put("randCode", randCode);
            formData.put("purpose_codes", this.submitTicketInfoDTO.getPurposeCodes());
            formData.put("key_check_isChange", this.submitTicketInfoDTO.getKeyCheckIsChange());
            formData.put("leftTicketStr", this.submitTicketInfoDTO.getLeftTicketStr());   // 这个参数不需要解码的。
            formData.put("train_location", this.trainLocation);
            formData.put("choose_seats", "");
            formData.put("seatDetailType", "000");   // 选择座位,不选默认000
            formData.put("whatsSelect", 1);    // 1-成人票 2-学生票
            formData.put("roomType", "00");  // 好像是根据一个id来判断选中的,两种 第一种是00,第二种是10,但是我在12306的页面没找到该id,目前写死是00
            formData.put("dwAll", "N");
            formData.put("_json_att", "");
            formData.put("REPEAT_SUBMIT_TOKEN", this.repeatSubmitToken);

            HttpResponse httpResponse = this.session.httpClient.send(UrlsEnum.CONFIRM_SINGLE_FOR_QUEUE, formData);
            String body = httpResponse.body();
//            log.info("confirmSingleForQueue body = {}", body);

            JSON parse = JSONUtil.parse(body);
            if (parse.getByPath("status") != null && (boolean) parse.getByPath("status")) {
                if (parse.getByPath("status") != null && (boolean) parse.getByPath("data.submitStatus")) {
                    new QueryOrderWaitTime(
                            this.session,
                            this.repeatSubmitToken,
                            this.trainNum
                    ).send();
                } else {
                    ticketCache.put(this.trainNum, this.trainNum, Constants.BLACK_ROOM_CACHE_EXP_TIME * 60);
                    log.error("正式下单失败,错误信息:{}。此列车{}加入小黑屋闭关3分钟", parse.getByPath("data.errMsg"), this.trainNum);
                }
            } else {
                ticketCache.put(this.trainNum, this.trainNum, Constants.BLACK_ROOM_CACHE_EXP_TIME * 60);
                log.error("正式下单失败,错误信息:{}。此列车{}加入小黑屋闭关3分钟", parse.getByPath("messages"), this.trainNum);
            }
        } catch (Exception e) {
            if (e instanceof J12306Exception) {
                throw new J12306Exception(e.getMessage());
            } else {
                log.error("正式下单异常:{}", e.getMessage());
            }
        }

    }
}


================================================
FILE: src/com/kalvin/J12306/api/GetJS.java
================================================
package com.kalvin.J12306.api;

import com.kalvin.J12306.config.UrlsEnum;
import com.kalvin.J12306.http.Session;

/**
 * 获取js脚本
 * Create by Kalvin on 2019/9/20.
 */
public class GetJS {

    private Session session;

    public GetJS(Session session) {
        this.session = session;
    }

    public void send() {
        this.session.httpClient.send(UrlsEnum.GET_JS);
    }
}


================================================
FILE: src/com/kalvin/J12306/api/GetPassCodeNew.java
================================================
package com.kalvin.J12306.api;

/**
 * 获取订单页面验证码
 * Create by Kalvin on 2019/9/20.
 */
public class GetPassCodeNew {

}


================================================
FILE: src/com/kalvin/J12306/api/GetQueueCount.java
================================================
package com.kalvin.J12306.api;

import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.kalvin.J12306.cache.TicketCache;
import com.kalvin.J12306.config.Constants;
import com.kalvin.J12306.config.UrlsEnum;
import com.kalvin.J12306.dto.SubmitTicketInfoDTO;
import com.kalvin.J12306.http.Session;
import com.kalvin.J12306.utils.J12306Util;

import java.util.Arrays;
import java.util.HashMap;

/**
 * 获取队列位置
 * Create by Kalvin on 2019/9/20.
 */
public class GetQueueCount {

    private final static Log log = LogFactory.get();

    private Session session;
    private String repeatSubmitToken;
    private String trainDate;
    private String trainNo;
    private String trainNum;
    private String passengerTicketStr;
    private String oldPassengerStr;
    private String seatType;
    private String fromStationCode;
    private String toStationCode;
    private String trainLocation;
    private int ifShowPassCodeTime;
    private boolean isNeedCode;
    private SubmitTicketInfoDTO submitTicketInfoDTO;

    public GetQueueCount(Session session, String repeatSubmitToken, String trainDate, String trainNo,
                         String trainNum, String passengerTicketStr, String oldPassengerStr, String seatType,
                         String fromStationCode, String toStationCode, String trainLocation, int ifShowPassCodeTime,
                         boolean isNeedCode, SubmitTicketInfoDTO submitTicketInfoDTO) {
        this.session = session;
        this.repeatSubmitToken = repeatSubmitToken;
        this.trainDate = trainDate;
        this.trainNo = trainNo;
        this.trainNum = trainNum;
        this.passengerTicketStr = passengerTicketStr;
        this.oldPassengerStr = oldPassengerStr;
        this.seatType = seatType;
        this.fromStationCode = fromStationCode;
        this.toStationCode = toStationCode;
        this.trainLocation = trainLocation;
        this.ifShowPassCodeTime = ifShowPassCodeTime;
        this.isNeedCode = isNeedCode;
        this.submitTicketInfoDTO = submitTicketInfoDTO;
    }

    public void send() {
        HashMap<String, Object> formData = new HashMap<>();
        formData.put("train_date", J12306Util.formatDateGMT(this.trainDate));
        formData.put("train_no", this.trainNo);
        formData.put("stationTrainCode", this.trainNum);
        formData.put("seatType", this.seatType);
        formData.put("fromStationTelecode", this.fromStationCode);
        formData.put("toStationTelecode", this.toStationCode);
        formData.put("leftTicket", submitTicketInfoDTO.getLeftTicketStr()); // todo 是否解码
        formData.put("purpose_codes", submitTicketInfoDTO.getPurposeCodes());
        formData.put("train_location", this.trainLocation);
        formData.put("_json_att", "");
        formData.put("REPEAT_SUBMIT_TOKEN", this.repeatSubmitToken);
        HttpResponse httpResponse = this.session.httpClient.send(UrlsEnum.GET_QUEUE_COUNT, formData);
        String body = httpResponse.body();
//        log.info("getQueueCount body = {}", body);

        TicketCache ticketCache = TicketCache.getInstance();
        // 余票数
        int ticketCount;
        JSONObject object = JSONUtil.parseObj(body);
        JSONObject dataObj = (JSONObject) object.get("data");
        if (object.get("status") != null && (boolean) object.get("status")) {
            String ticket = dataObj.get("ticket").toString();
            if (dataObj.get("count") != null) {
                Integer count = Integer.valueOf(dataObj.get("count").toString());
                if (!ticket.contains(",")) {
                    ticketCount = Integer.parseInt(ticket);
                } else {
                    String[] ticketSplit = ticket.split(",");
                    ticketCount = Arrays.stream(ticketSplit).map(Integer::valueOf).reduce(0, Integer::sum);
                }
                log.info("排队成功,你当前排在{}位,当前余票还有{}张", count, ticketCount);
                // 正式下单
                new ConfirmSingleForQueue(
                        this.session,
                        this.repeatSubmitToken,
                        this.passengerTicketStr,
                        this.oldPassengerStr,
                        this.trainNum,
                        this.trainLocation,
                        this.ifShowPassCodeTime,
                        this.isNeedCode,
                        this.submitTicketInfoDTO
                ).send();
            } else {
                // 将此列车加入小黑屋3分钟
                ticketCache.put(this.trainNum, this.trainNum, Constants.BLACK_ROOM_CACHE_EXP_TIME * 60);
                log.error("排队失败,错误信息:{},将此列车{}加入小黑屋3分钟", object.get("messages"), this.trainNum);
            }
        } else {
            ticketCache.put(this.trainNum, this.trainNum, Constants.BLACK_ROOM_CACHE_EXP_TIME * 60);
            log.error("排队失败,错误信息:{},将此列车{}加入小黑屋3分钟", object.get("messages"), this.trainNum);
        }
    }
            
}


================================================
FILE: src/com/kalvin/J12306/api/Login.java
================================================
package com.kalvin.J12306.api;

import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONException;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.kalvin.J12306.config.Constants;
import com.kalvin.J12306.config.UrlConfig;
import com.kalvin.J12306.config.UrlsEnum;
import com.kalvin.J12306.dto.UserInfoDTO;
import com.kalvin.J12306.exception.J12306Exception;
import com.kalvin.J12306.http.Session;

import java.net.HttpCookie;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;

/**
 * 登录
 * Create by Kalvin on 2019/9/18.
 */
public class Login {

    private static final Log log = LogFactory.get();
    private Session session;
    private String username;
    private String password;

    public Login(Session session, String username, String password) {
        this.session = session;
        this.username = username;
        this.password = password;
    }

    public UserInfoDTO send() {
        HttpResponse initRes = this.session.httpClient.send(UrlsEnum.LOGIN_INIT);
        this.session.setCookie(initRes.getCookies());
        log.info("进入12306登录页,状态码:{}", initRes.getStatus());
        Captcha captcha = new Captcha(this.session);
        // 获取登录验证码
        captcha.getLoginCaptchaImg();
        // 获取deviceId
        this.initLogDevice();
        // 校验登录验证码
        if (captcha.checkLoginCaptchaImg()) {
            log.info("验证码通过,开始密码登录");
            // 开始密码登录
            HashMap<String, Object> formData = new HashMap<>();
            formData.put("username", this.username);
            formData.put("password", this.password);
            formData.put("appid", "otn");
            HttpResponse httpResponse = this.session.httpClient.send(UrlsEnum.LOGIN, formData);
            String body = httpResponse.body();
//            log.info("login body={}", body);
            if (StrUtil.isBlank(body)) {
                throw new J12306Exception(Constants.UPDATE_LOG_DEVICE_ERROR_MSG);
            }

            JSONObject jsonObject = JSONUtil.parseObj(body);
            Integer resultCode = (Integer) jsonObject.get("result_code");
            if (resultCode == 0) {   // 登录成功,获取tk
                log.info("登录成功");
                this.userLogin();
                this.passport();
                new GetJS(this.session).send();
                boolean uamtk = this.postUamTK((String) jsonObject.get("uamtk"));
                if (uamtk) {
                    return this.getUserInfo();
                }
            } else {
                log.info("登录失败,请检查12306账号或密码是否正确。");
                throw new J12306Exception("登录失败,请检查12306账号或密码是否正确。");
            }
        } else {
            log.info("登录失败,验证码不通过,请重试...");
        }
        return null;
    }

    private void initLogDevice() {
        String userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36";
        Session ldSession = new Session();
        UrlConfig urlConfig = UrlsEnum.LOG_DEVICE.getUrlConfig();
        /*urlConfig.setUrl(urlConfig.getUrl()
                .replace("{0}", userAgent)
                .replace("{1}", String.valueOf(System.currentTimeMillis())));*/
        urlConfig.setUrl(this.fillLogDeviceUrlParams(urlConfig.getUrl()));
        UrlsEnum.LOG_DEVICE.setUrlConfig(urlConfig);
        HttpResponse httpResponse = ldSession.httpClient.send(UrlsEnum.LOG_DEVICE);
        String body = httpResponse.body();
//        log.info("deviceInfo body = {}", body);
        String startIdxStr = "{";
        String endIdxStr = "}";
        body = body.substring(body.indexOf(startIdxStr), body.indexOf(endIdxStr) + 1);
        JSONObject jsonObject = JSONUtil.parseObj(body);
        // 设置到session的cookie中
        String railExpiration = jsonObject.get("exp").toString();
        String railDeviceId = jsonObject.get("dfp").toString();
//        log.info("railDeviceId={}", railDeviceId);
        this.session.setCookie("RAIL_EXPIRATION=" + railExpiration);
        this.session.setCookie("RAIL_DEVICEID=" + railDeviceId);
//        this.session.httpClient.setHeader(new HashMap<String, String>() {{put("User-Agent", userAgent);}});
    }

    private String fillLogDeviceUrlParams(String url) {
        final StringBuilder sb = new StringBuilder();
        /**
         * 如果RAIL_DEVICEID失效了,以下参数需要更新(顺序一定要对,不然找不到logdevice)
         * 更新步骤:
         * 1.浏览器访问:https://kyfw.12306.cn/otn/login/init
         * 2.按f12进入调试模式并点击Network选项
         * 3.清除浏览器缓存的有关12306.cn和kyfw.12306.cn的Cookie(谷歌浏览器点击浏览器地址栏的小锁)
         * 4.按f5重新刷新(只有第1次刷新才有出现,所以不要刷新2次)
         * 5.在Network选项下找到logdevice请求,点击它,在Headers选项下拉到最下面就可以找到如下几个参数,复制替换它即可
         */
        final String algID = "PyvGQGRrn7";
        final String hashCode = "zgwkwwmfXov0h0OiTVGEm5O3x8wCUon2_s6JFyCUmFE";
        final String EOQP = "8f58b1186770646318a429cb33977d8c";
        final String jp76 = "52d67b2a5aa5e031084733d5006cc664";
        final String q5aJ = "-8";
        final String Oaew = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36";
        final String E3gR = "662690cce73ebaa8bae40c90cd3a15d5";

        new LinkedHashMap<String, Object>() {{
            put("algID", algID);
            put("hashCode", hashCode);
            put("FMQw", "0");
            put("q4f3", "zh-CN");
            put("VPIf", "1");
            put("custID", "133");
            put("VEek", "unknown");
            put("dzuS", "0");
            put("yD16", "0");
            put("EOQP", EOQP);
            put("jp76", jp76);
            put("hAqN", "Win32");
            put("platform", "WEB");
            put("ks0Q", "d22ca0b81584fbea62237b14bd04c866");
            put("TeRS", "1040x1920");
            put("tOHY", "24xx1080x1920");
            put("Fvje", "i1l1o1s1");
            put("q5aJ", q5aJ);
            put("wNLf", "99115dfb07133750ba677d055874de87");
            put("0aew", Oaew);
            put("E3gR", E3gR);
            put("timestamp", String.valueOf(System.currentTimeMillis()));
        }}.forEach((k, v) -> {
            if (sb.length() == 0) {
                sb.append("?");
            } else {
                sb.append("&");
            }
            sb.append(k).append("=").append(v);
        });
        return url + sb.toString();
    }

    private void userLogin() {
        this.session.httpClient.send(UrlsEnum.USER_LOGIN);
    }

    private void passport() {
        HttpResponse httpResponse = this.session.httpClient.send(UrlsEnum.PASSPORT);
        List<HttpCookie> cookies = httpResponse.getCookies();
        // 设置cookies
        this.session.setCookie(cookies);
    }

    /**
     * 获取登录token
     * @param uamTK uamTK令牌
     */
    private boolean postUamTK(String uamTK) {
        /*if (StrUtil.isNotBlank(uamTK)) {
            HashMap<String, String> headers = new HashMap<String, String>() {{
//                put("uamtk", uamTK);
            }};
            this.session.httpClient.setHeader(headers);
        }*/

        HashMap<String, Object> formData = new HashMap<String, Object>() {{
            put("appid", "otn");
        }};
        HttpResponse httpResponse = this.session.httpClient.send(UrlsEnum.UAM_TK, formData);
        log.info("postUamTK http status = {}", httpResponse.getStatus());
        String body = httpResponse.body();
//        log.info("postUamTK body = {}", body);
        try {
            JSONObject jsonObject = JSONUtil.parseObj(body);
            Integer resultCode = (Integer) jsonObject.get("result_code");
            if (resultCode == 0) {
                this.session.token = (String) jsonObject.get("newapptk");
                return this.postUamAuthClient();
            }
        } catch (JSONException je) {
            return false;
        }
        return false;
    }

    /**
     * 获取权限
     */
    private boolean postUamAuthClient() {
        HashMap<String, Object> formData = new HashMap<>();
        formData.put("tk", this.session.token);
        HttpResponse httpResponse = this.session.httpClient.send(UrlsEnum.UAM_AUTH_CLIENT, formData);
        List<HttpCookie> cookies = httpResponse.getCookies();
        this.session.setCookie(cookies);

        String body = httpResponse.body();
        try {
            JSONObject jsonObject = JSONUtil.parseObj(body);
            Integer resultCode = (Integer) jsonObject.get("result_code");
            return resultCode == 0;
        } catch (JSONException e) {
            return false;
        }
    }

    /**
     * 获取用户信息
     */
    private UserInfoDTO getUserInfo() {
        HttpResponse httpResponse = this.session.httpClient.send(UrlsEnum.GET_USER_INFO);
        String body = httpResponse.body();
//        log.info("queryPassengerInfo body={}", body);
        JSON parse = JSONUtil.parse(body);
        JSONObject object = (JSONObject) parse.getByPath("data.userDTO.loginUserDTO");
        UserInfoDTO userInfo = new UserInfoDTO();
        userInfo.setIdNo(object.get("id_no").toString());
        userInfo.setName(object.get("name").toString());
        userInfo.setUsername(object.get("user_name").toString());
        userInfo.setIdTypeCode(object.get("id_type_code").toString());
        userInfo.setIdTypeName(object.get("id_type_name").toString());
        userInfo.setEmail(parse.getByPath("data.userDTO.email").toString());
        return userInfo;
    }

}


================================================
FILE: src/com/kalvin/J12306/api/MyOrder.java
================================================
package com.kalvin.J12306.api;

import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.kalvin.J12306.config.UrlsEnum;
import com.kalvin.J12306.http.Session;

import java.util.HashMap;

/**
 * 我的订单
 * Create by Kalvin on 2019/9/24.
 */
public class MyOrder {

    private final static Log log = LogFactory.get();

    private Session session;

    public MyOrder(Session session) {
        this.session = session;
    }

    public void init() {
        HashMap<String, Object> formData = new HashMap<>();
        formData.put("_json_att", "");
        this.session.httpClient.send(UrlsEnum.INIT_NO_COMPLETE, formData);
    }

    /**
     * 查询未完成的订单
     * @return httpResponse
     */
    public HttpResponse queryMyNoComplete() {
        HashMap<String, Object> formData = new HashMap<>();
        formData.put("_json_att", "");
        try {
            return this.session.httpClient.send(UrlsEnum.QUERY_MY_ORDER_NO_COMPLETE, formData);
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 检查订单状态
     * @return State
     */
    public State check() {
        HttpResponse httpResponse = this.queryMyNoComplete();
        if (httpResponse == null) {
            return State.fail();
        }
        String body = httpResponse.body();
        JSON parse = JSONUtil.parse(body);
        if (parse.getByPath("data") != null && parse.getByPath("data.orderDBList") != null) {
            JSONArray objects = JSONUtil.parseArray(parse.getByPath("data.orderDBList"));
            JSON parseODB = JSONUtil.parse(objects.get(0));
            String sequenceNo = (String) parseODB.getByPath("sequence_no");
            if (parseODB.getByPath("tickets.ticket_status_code").equals("i")) { // 待支付状态
                return State.noPay(sequenceNo);
            } else {
                return State.queue(sequenceNo);
            }
        }
        return State.fail();
    }

    /**
     * 取消订单
     * @param sequenceNo 订单ID
     */
    public void cancelNoComplete(String sequenceNo) {
        HashMap<String, Object> formData = new HashMap<>();
        formData.put("sequence_no", sequenceNo);
        formData.put("cancel_flag", "cancel_order");
        formData.put("_json_att", "");
        HttpResponse httpResponse = this.session.httpClient.send(UrlsEnum.CANCEL_NO_COMPLETE_MY_ORDER, formData);
        String body = httpResponse.body();
        JSON parse = JSONUtil.parse(body);
        if (parse.getByPath("data") != null && parse.getByPath("data.existError").equals("N")) {
            log.info("订单【{}】取消成功", sequenceNo);
        } else {
            log.info("订单【{}】取消失败", sequenceNo);
        }
    }

    /**
     * 订单状态
     */
    public static class State {
        /**
         * 待支付状态
         */
        public final static String NO_PAY_CODE = "NO_PAY";
        /**
         * 排队状态
         */
        public final static String QUEUE_CODE = "QUEUE";
        /**
         * 失败状态
         */
        public final static String FAIL_CODE = "FAIL";

        private String code;
        private String sequenceNo;

        private State(String code, String sequenceNo) {
            this.code = code;
            this.sequenceNo = sequenceNo;
        }

        private static State noPay(String sequenceNo) {
            return new State(State.NO_PAY_CODE, sequenceNo);
        }

        private static State queue(String sequenceNo) {
            return new State(State.QUEUE_CODE, sequenceNo);
        }

        private static State fail() {
            return new State(State.FAIL_CODE, "");
        }

        public String getCode() {
            return code;
        }

        public String getSequenceNo() {
            return sequenceNo;
        }
    }

}


================================================
FILE: src/com/kalvin/J12306/api/PassengerDTOS.java
================================================
package com.kalvin.J12306.api;

import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.kalvin.J12306.cache.TicketCache;
import com.kalvin.J12306.config.Constants;
import com.kalvin.J12306.config.UrlsEnum;
import com.kalvin.J12306.dto.UserInfoDTO;
import com.kalvin.J12306.http.Session;

import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 乘客信息
 * Create by Kalvin on 2019/9/20.
 */
public class PassengerDTOS {

    private Session session;
    private String repeatSubmitToken;
    private String seatType;

    public PassengerDTOS(Session session) {
        this.session = session;
    }

    public PassengerDTOS(Session session, String repeatSubmitToken, String seatType) {
        this.session = session;
        this.repeatSubmitToken = repeatSubmitToken;
        this.seatType = seatType;
    }

    /**
     * 获取乘客购票信息
     * @return passengerTicketStr
     */
    public String getPassengerTicketStr() {
        String passengerTicketStr = "{seatType},0,1,{name},1,{passengerIdCard},,N,{allEncStr}";
        // 从缓存中获取用户信息
        TicketCache ticketCache = TicketCache.getInstance();
        UserInfoDTO userInfo = (UserInfoDTO) ticketCache.get(Constants.USER_INFO_KEY);
        String idNo = userInfo.getIdNo();
        String name = userInfo.getName();

        HashMap<String, Object> formData = new HashMap<>();
        formData.put("REPEAT_SUBMIT_TOKEN", repeatSubmitToken);
        formData.put("_json_att", "");
        HttpResponse httpResponse = this.session.httpClient.send(UrlsEnum.GET_PASSENGERDTOS, formData);
        String body = httpResponse.body();
        JSON parse = JSONUtil.parse(body);
        JSONArray jsonArray = JSONUtil.parseArray(parse.getByPath("data.normal_passengers"));
        List<Object> list = jsonArray.stream().filter(object ->
                ((JSONObject) object).get("passenger_id_no").equals(idNo))
                .collect(Collectors.toList());
        String allEncStr = ((JSONObject) list.get(0)).get("allEncStr").toString();
        userInfo.setUserEncStr(allEncStr);

        ticketCache.put(Constants.USER_INFO_KEY, userInfo);

        return passengerTicketStr
                .replace("{seatType}", this.seatType)
                .replace("{name}", name)
                .replace("{passengerIdCard}", idNo)
                .replace("{allEncStr}", allEncStr);
    }

    public String getPassengerEncStr() {
        TicketCache ticketCache = TicketCache.getInstance();
        UserInfoDTO userInfo = (UserInfoDTO) ticketCache.get(Constants.USER_INFO_KEY);
        String idNo = userInfo.getIdNo();
        HashMap<String, Object> formData = new HashMap<>();
        formData.put("_json_att", "");
        HttpResponse httpResponse = this.session.httpClient.send(UrlsEnum.GET_PASSENGERDTOS, formData);
        String body = httpResponse.body();
        JSON parse = JSONUtil.parse(body);
        JSONArray jsonArray = JSONUtil.parseArray(parse.getByPath("data.normal_passengers"));
        List<Object> list = jsonArray.stream().filter(object ->
                ((JSONObject) object).get("passenger_id_no").equals(idNo))
                .collect(Collectors.toList());
        return ((JSONObject) list.get(0)).get("allEncStr").toString();
    }

    /**
     * 获取乘客信息
     * @return oldPassengerStr
     */
    public String getOldPassengerStr() {
        String oldPassengerStr = "{name},1,{passengerIdCard},1_";
        // 从缓存中获取用户信息
        TicketCache ticketCache = TicketCache.getInstance();
        UserInfoDTO userInfo = (UserInfoDTO) ticketCache.get(Constants.USER_INFO_KEY);
        String idNo = userInfo.getIdNo();
        String name = userInfo.getName();
        return oldPassengerStr.replace("{name}", name).replace("{passengerIdCard}", idNo);
    }
}


================================================
FILE: src/com/kalvin/J12306/api/QueryOrderWaitTime.java
================================================
package com.kalvin.J12306.api;

import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.kalvin.J12306.cache.TicketCache;
import com.kalvin.J12306.config.Constants;
import com.kalvin.J12306.config.UrlConfig;
import com.kalvin.J12306.config.UrlsEnum;
import com.kalvin.J12306.exception.J12306Exception;
import com.kalvin.J12306.http.Session;
import com.kalvin.J12306.utils.EmailUtil;
import com.kalvin.J12306.utils.J12306Util;

/**
 * 排队获取订单等待信息,每隔3秒请求一次,最高请求次数为20次!
 * Create by Kalvin on 2019/9/20.
 */
public class QueryOrderWaitTime {

    private static final Log log = LogFactory.get();

    private Session session;
    private String repeatSubmitToken;
    private String trainNum;

    public QueryOrderWaitTime(Session session, String repeatSubmitToken, String trainNum) {
        this.session = session;
        this.repeatSubmitToken = repeatSubmitToken;
        this.trainNum = trainNum;
    }

    public void send() {
        int tryTimes = 0;
        boolean success = false;
        String orderId = "";
        TicketCache ticketCache = TicketCache.getInstance();
        while (true) {
            if (tryTimes >= Constants.MAX_TRY_TIMES) {
                // 自动取消订单
                MyOrder myOrder = new MyOrder(this.session);
                myOrder.init();
                MyOrder.State check = myOrder.check();
                switch (check.getCode()) {
                    case MyOrder.State.NO_PAY_CODE:
                        success = true;
                        break;
                    case MyOrder.State.QUEUE_CODE:
                    case MyOrder.State.FAIL_CODE:
                        log.info("排队失败,取消订单");
                        myOrder.cancelNoComplete(check.getSequenceNo());
                }
                ticketCache.put(this.trainNum, this.trainNum, Constants.BLACK_ROOM_CACHE_EXP_TIME * 60);
                log.error("排队20次失败。此列车{}加入小黑屋闭关3分钟", this.trainNum);
                break;
            }
            try {
                tryTimes++;
                log.info("下单ing...正在第{}次排队ing...", tryTimes);

                UrlConfig urlConfig = UrlsEnum.QUERY_ORDER_WAIT_TIME.getUrlConfig();
                urlConfig.setUrl(urlConfig.getUrl()
                        .replace("{0}", String.valueOf(System.currentTimeMillis()))
                        .replace("{1}", this.repeatSubmitToken));
                UrlsEnum.QUERY_ORDER_WAIT_TIME.setUrlConfig(urlConfig);
                HttpResponse httpResponse = session.httpClient.sendAsync(UrlsEnum.QUERY_ORDER_WAIT_TIME);
                String body = httpResponse.body();
//                log.info("queryOrderWaitTime body = {}", body);

                JSON parse = JSONUtil.parse(body);
                if (parse.getByPath("status") != null && (boolean) parse.getByPath("status")) {
                    JSONObject dObj = (JSONObject) parse.getByPath("data");
                    orderId = dObj.get("orderId").toString();
                    String waitCount = dObj.get("waitCount").toString();
//                    LOGGER.info("orderId={}", orderId);
                    if (StrUtil.isNotBlank(orderId) && !"null".equals(orderId) && orderId != null) {
                        log.info("订票成功!");
                        success = true;
                        break;
                    } else if (dObj.get("msg") == null) {
                        log.info("等待提交订单,等待队列:{},时间剩余:{}毫秒", waitCount, dObj.get("waitTime"));
                    } else {
                        log.info("等待提交订单失败:{}", dObj.get("msg"));
                        break;
                    }
                } else {
                    log.info("等待提交订单中,信息:{}", parse.getByPath("messages"));
                }
            } catch (Exception e) {
                log.error("等待提交订单异常,错误信息:{}", e.getMessage());
                break;
            }
            J12306Util.sleep(2);   // 睡眠2秒
        }

        if (success) {
            // 订票成功,使用邮件通知抢票人
            log.info("恭喜您订票成功,订单号为:{}, 请立即打开浏览器登录12306,访问‘未完成订单’,在30分钟内完成支付!", orderId);
            log.info("以邮件方式通知抢票人");
            EmailUtil.send("12306抢票成功", "恭喜您订票成功,订单号为:" + orderId + ", 请立即打开浏览器登录12306,访问‘未完成订单’,在30分钟内完成支付!");
            throw new J12306Exception(Constants.THREAD_STOP);
        }

    }
}


================================================
FILE: src/com/kalvin/J12306/api/RepeatSubmitToken.java
================================================
package com.kalvin.J12306.api;

import cn.hutool.core.util.ReUtil;
import cn.hutool.http.HttpResponse;
import com.kalvin.J12306.config.UrlsEnum;
import com.kalvin.J12306.dto.SubmitTicketInfoDTO;
import com.kalvin.J12306.http.Session;

import java.util.List;

/**
 * RepeatSubmitToken
 * Create by Kalvin on 2019/9/20.
 */
public class RepeatSubmitToken {

    private Session session;

    public RepeatSubmitToken(Session session) {
        this.session = session;
    }

    /**
     * 获取提交订单相关参数
     * @return SubmitTicketInfoDTO
     */
    public SubmitTicketInfoDTO getSubmitTicketInfo() {
        HttpResponse httpResponse = this.session.httpClient.send(UrlsEnum.INIT_DC);
        String body = httpResponse.body();
        List<String> list0 = ReUtil.findAll("globalRepeatSubmitToken = '(.*?)'", body, 1);
        List<String> list1 = ReUtil.findAll("'key_check_isChange':'(.*?)'", body, 1);
        List<String> list2 = ReUtil.findAll("'purpose_codes':'(.*?)'", body, 1);
        List<String> list3 = ReUtil.findAll("'leftTicketStr':'(.*?)'", body, 1);
        SubmitTicketInfoDTO submitTicketInfoDTO = new SubmitTicketInfoDTO();
        submitTicketInfoDTO.setRepeatSubmitToken(list0.get(0));
        submitTicketInfoDTO.setKeyCheckIsChange(list1.get(0));
        submitTicketInfoDTO.setPurposeCodes(list2.get(0));
        submitTicketInfoDTO.setLeftTicketStr(list3.get(0));
        return submitTicketInfoDTO;
    }
}


================================================
FILE: src/com/kalvin/J12306/api/SubmitOrderRequest.java
================================================
package com.kalvin.J12306.api;

import cn.hutool.core.date.DateUtil;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.kalvin.J12306.config.Constants;
import com.kalvin.J12306.config.UrlsEnum;
import com.kalvin.J12306.dto.SubmitTicketInfoDTO;
import com.kalvin.J12306.exception.J12306Exception;
import com.kalvin.J12306.http.Session;
import com.kalvin.J12306.utils.StationUtil;

import java.util.Date;
import java.util.HashMap;

/**
 * 提交订单
 * Create by Kalvin on 2019/9/19.
 */
public class SubmitOrderRequest {

    private static final Log log = LogFactory.get();

    private Session session;
    private String secretStr;
    private String seatType;
    private String trainDate;
    private String formStationCode;
    private String toStationCode;
    private String trainNo;
    private String trainNum;
    private String trainLocation;

    public SubmitOrderRequest(Session session, String secretStr, String seatType, String trainDate, String formStationCode, String toStationCode, String trainNo, String trainNum, String trainLocation) {
        this.session = session;
        this.secretStr = secretStr;
        this.seatType = seatType;
        this.trainDate = trainDate;
        this.formStationCode = formStationCode;
        this.toStationCode = toStationCode;
        this.trainNo = trainNo;
        this.trainNum = trainNum;
        this.trainLocation = trainLocation;
    }

    public void send() {
        HashMap<String, Object> formData = new HashMap<>();
        formData.put("secretStr", this.secretStr);
        formData.put("train_date", this.trainDate);
        formData.put("back_train_date", DateUtil.format(new Date(), "yyyy-MM-dd")); // 返程日
        formData.put("tour_flag", "dc"); // 单程
        formData.put("purpose_codes", "ADULT");  // 成人票
        formData.put("query_from_station_name", StationUtil.getStationName(this.formStationCode));
        formData.put("query_to_station_name", StationUtil.getStationName(this.toStationCode));
        formData.put("undefined", "");
        try {
            HttpResponse httpResponse = this.session.httpClient.send(UrlsEnum.SUBMIT_ORDER_REQUEST, formData);
            if (httpResponse.getStatus() == Constants.REQ_SUCCESS_STATUS) {
                String body = httpResponse.body();
//                log.info("submitOrderRequest body ={}", body);
                JSONObject jsonObject = JSONUtil.parseObj(body);
                boolean status = (boolean) jsonObject.get("status");
                // 提交订单
                if (status && "N".equals(jsonObject.get("data").toString())) {
                    RepeatSubmitToken repeatSubmitToken = new RepeatSubmitToken(this.session);
                    SubmitTicketInfoDTO submitTicketInfo = repeatSubmitToken.getSubmitTicketInfo();
                    // GetJS
                    new GetJS(this.session).send();
                    // 获取乘客信息
                    PassengerDTOS passengerDTOS = new PassengerDTOS(this.session, submitTicketInfo.getRepeatSubmitToken(), this.seatType);
                    final String passengerTicketStr = passengerDTOS.getPassengerTicketStr();
                    final String oldPassengerStr = passengerDTOS.getOldPassengerStr();
                    // 获取订单页面验证码
                    new Captcha(this.session).getOrderCaptchaImg();
                    // 检查订单
                    new CheckOrderInfo(
                            this.session,
                            submitTicketInfo.getRepeatSubmitToken(),
                            this.seatType,
                            passengerTicketStr,
                            oldPassengerStr,
                            this.trainDate,
                            this.trainNo,
                            this.trainNum,
                            this.formStationCode,
                            this.toStationCode,
                            this.trainLocation,
                            submitTicketInfo
                    ).send();
                } else {
                    log.error("订单提交失败,正在重试...错误信息:{}", jsonObject.get("messages"));
                }
            }
        } catch (Exception e) {
            if (e instanceof J12306Exception) {
                throw new J12306Exception(e.getMessage());
            } else {
                log.error("订单提交异常,正在重试...错误信息:{}", e.getMessage());
            }
        }

    }



}


================================================
FILE: src/com/kalvin/J12306/api/Ticket.java
================================================
package com.kalvin.J12306.api;

import cn.hutool.http.HttpResponse;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.kalvin.J12306.config.UrlConfig;
import com.kalvin.J12306.config.UrlsEnum;
import com.kalvin.J12306.exception.J12306Exception;
import com.kalvin.J12306.http.Session;

/**
 * 车票
 * Create by Kalvin on 2019/9/19.
 */
public class Ticket {

    private static final Log log = LogFactory.get();

    private Session session;
    private String trainDate;
    private String fromStation;
    private String toStation;
    private String tempCookie;

    public Ticket(Session session, String trainDate, String fromStation, String toStation) {
        // 进入查询车票页面
        session.httpClient.send(UrlsEnum.INIT_TICKET);
        log.info("进入查询车票页面,开始查票...");

        this.tempCookie = session.getCookie();
        this.session = session;
        this.trainDate = trainDate;
        this.fromStation = fromStation;
        this.toStation = toStation;
    }

    private HttpResponse query(String type) {
        UrlsEnum urlsEnum;
        switch (type) {
            case "A":
                urlsEnum = UrlsEnum.QUERY_A_TICKET;
                break;
            case "Z":
                urlsEnum = UrlsEnum.QUERY_Z_TICKET;
                break;
            default:
                throw new J12306Exception("无效的查票接口");
        }
        this.session = new Session();
        this.session.setCookie(this.tempCookie);
        UrlConfig urlConfig = urlsEnum.getUrlConfig();
        urlConfig.setUrl(urlConfig.getUrl()
                .replace("{0}", trainDate)
                .replace("{1}", this.fromStation)
                .replace("{2}", this.toStation));
        urlsEnum.setUrlConfig(urlConfig);

        return this.session.httpClient.send(urlsEnum);
    }

    public HttpResponse queryA() {
        return this.query("A");
    }

    public HttpResponse queryZ() {
        return this.query("Z");
    }
}


================================================
FILE: src/com/kalvin/J12306/cache/TicketCache.java
================================================
package com.kalvin.J12306.cache;

import java.util.HashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * 自定义车票信息缓存类
 * Create by Kalvin on 2019/9/20.
 */
public class TicketCache {

    private static volatile TicketCache ticketCacheInstance;

    private HashMap<String, Object> cacheMap = new HashMap<>();
    private ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();

    /**
     * 获取缓存实例(单例)
     * @return ticketCacheInstance
     */
    public static TicketCache getInstance() {
        if (ticketCacheInstance == null) {
            synchronized (TicketCache.class) {
                if (ticketCacheInstance == null) {
                    ticketCacheInstance = new TicketCache();
                }
            }
        }
        return ticketCacheInstance;
    }

    public void put(String key, Object value) {
        this.put(key, value, 0);
    }

    public synchronized void put(String key, Object value, long expire) {

        if (expire > 0) {   // 过期缓存
            scheduledExecutorService.schedule(() -> {
                this.cacheMap.remove(key);
            }, expire, TimeUnit.SECONDS);

            this.cacheMap.put(key, value);
        } else {    // 不过期缓存
            this.cacheMap.put(key, value);
        }
    }

    public Object get(String key) {
        return this.cacheMap.get(key);
    }

    public int size() {
        return this.cacheMap.size();
    }

}


================================================
FILE: src/com/kalvin/J12306/config/Constants.java
================================================
package com.kalvin.J12306.config;

import cn.hutool.core.util.ClassUtil;

/**
 * Create by Kalvin on 2019/9/18.
 */
public class Constants {

    public final static String HOST = "kyfw.12306.cn";

    public final static String ORIGIN = "https://kyfw.12306.cn";

    public final static String ACCEPT = "text/javascript, application/javascript, application/ecmascript,application/json, application/x-ecmascript,image/webp,image/apng,image/*,*/*; q=0.01";

    public final static String IMAGE_AI_URL = "http://shell.teachx.cn:12306/predict";

    public final static int REQ_SUCCESS_STATUS = 200;

    public final static String CAPTCHA_IMG_PRE_PATH = ClassUtil.getClassPath() + "captcha/";    // 验证码图片生成保存路径

    public final static String USER_INFO_KEY = "USER_INFO"; // 用户信息
    public final static String STATION_CACHE_KEY = "STATION";   // 站点信息
    public final static String BLACK_ROOM_KEY = "BLACK_ROOM";   // 小黑屋
    public final static String ALTERNATE_BLACK_ROOM_KEY = "ALTERNATE_BLACK_ROOM";   // 候补小黑屋
    public final static String THREAD_LOCK_TRAIN = "THREAD_LOCK_TRAIN";
    public final static int BLACK_ROOM_CACHE_EXP_TIME = 3;  // 默认3分钟


    /*座席代码*/
//    public final static String L1_SEAT_CODE = "M";
//    public final static String L2_SEAT_CODE = "O";
    public final static String NO_SEAT_CODE = "N";

    public final static int MAX_TRY_TIMES = 20;

    public final static int MAX_302 = 10;   //  最大302请求数。如果官方更换了接口,程序会在10次访问302状态的接口自动切换到另一个接口去。如:queryZ -> queryA

    public final static String THREAD_STOP = "STOP";

    public final static String UPDATE_LOG_DEVICE_ERROR_MSG = "请再重试登录多次,如果还报这个错可能RAIL_EXPIRATION值已失效,需要更新获取设备信息的LOG_DEVICE接口参数,请到Login.java类的fillLogDeviceUrlParams方法中更新";

}


================================================
FILE: src/com/kalvin/J12306/config/TicketSeatType.java
================================================
package com.kalvin.J12306.config;

/**
 * 车票座席枚举
 * Create by Kalvin on 2019/9/25.
 */
public enum  TicketSeatType {

    SP_SEAT("P", "特等座"),
    L1_SEAT("M", "一等座"),
    L2_SEAT("O", "二等座"),
    NO_SEAT("O", "无座"),
    BUS_SEAT("9", "商务座"),
    HARD_SEAT("1", "硬座"),
    SOFT_SEAT("2", "软座"),
    HARD_SLEEPER("3", "硬卧"),
    SORT_SLEEPER("4", "软卧");

    private String code;
    private String name;

    TicketSeatType(String code, String name) {
        this.code = code;
        this.name = name;
    }

    public static TicketSeatType get(String code) {
        for (TicketSeatType ticketSeatType : TicketSeatType.values()) {
            if (ticketSeatType.getCode().equals(code)) {
                return ticketSeatType;
            }
        }
        throw new RuntimeException("无效的code:" + code);
    }

    public String getCode() {
        return code;
    }

    public String getName() {
        return name;
    }
}


================================================
FILE: src/com/kalvin/J12306/config/UrlConfig.java
================================================
package com.kalvin.J12306.config;

/**
 * Create by Kalvin on 2019/9/18.
 */
public class UrlConfig {
    private String url;
    private String method;
    private String host;
    private String referer;

    public UrlConfig(String url, String method, String referer) {
        this.url = url;
        this.method = method;
        this.referer = referer;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getMethod() {
        return method;
    }

    public void setMethod(String method) {
        this.method = method;
    }

    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public String getReferer() {
        return referer;
    }

    public void setReferer(String referer) {
        this.referer = referer;
    }
}


================================================
FILE: src/com/kalvin/J12306/config/Urls.java
================================================
package com.kalvin.J12306.config;

/**
 * 接口url
 * Create by Kalvin on 2019/9/18.
 */
@Deprecated
public class Urls {

    // 设备信息
    private static String LOG_DEVICE = "https://kyfw.12306.cn/otn/HttpZF/logdevice?algID=1oMrl2Kf4t&hashCode=NrIjgGA7fXtB_4v4eTDmOPBVxUD08R6x4M7uSypZ14w&FMQw=0&q4f3=zh-CN&VySQ=FGFm2gYQYLbALw8nbWLg6D8wQj4uOWaI&VPIf=1&custID=133&VEek=unknown&dzuS=0&yD16=0&EOQP=8f58b1186770646318a429cb33977d8c&jp76=52d67b2a5aa5e031084733d5006cc664&hAqN=Win32&platform=WEB&ks0Q=d22ca0b81584fbea62237b14bd04c866&TeRS=1040x1920&tOHY=24xx1080x1920&Fvje=i1l1o1s1&q5aJ=-8&wNLf=99115dfb07133750ba677d055874de87&0aew=Mozilla/5.0%20(Windows%20NT%2010.0;%20Win64;%20x64)%20AppleWebKit/537.36%20(KHTML,%20like%20Gecko)%20Chrome/76.0.3809.132%20Safari/537.36&E3gR=05d47ed076f9affcd4517ac2b4fa4223&timestamp={timestamp}";
    // 登录页
    private static String LOGIN_INIT = "https://kyfw.12306.cn/otn/login/init";
    // 生成验证码
    private static String CAPTCHA = "https://kyfw.12306.cn/passport/captcha/captcha-image";
    private static String CAPTCHA_IMAGE64 = "https://kyfw.12306.cn/passport/captcha/captcha-image64";
    // 校验验证码
    private static String CHECK_CAPTCHA = "https://kyfw.12306.cn/passport/captcha/captcha-check";
    // 登录接口
    private static String LOGIN = "https://kyfw.12306.cn/passport/web/login";
    // 获取token
    private static String UAM_TK = "https://kyfw.12306.cn/passport/web/auth/uamtk";
    private static String UAM_AUTH_CLIENT = "https://kyfw.12306.cn/otn/uamauthclient";
    // 查票页
    private static String INIT_TICKET = "https://kyfw.12306.cn/otn/leftTicket/init";
    // 查票接口
    private static String QUERY_TICKET = "https://kyfw.12306.cn/otn/leftTicket/queryA";
    // 检查用户状态
    private static String CHECK_USER = "https://kyfw.12306.cn/otn/login/checkUser";
    // 提交订单
    private static String SUBMIT_ORDER_REQUEST = "https://kyfw.12306.cn/otn/leftTicket/submitOrderRequest";
    // initDc
    private static String INIT_DC = "https://kyfw.12306.cn/otn/confirmPassenger/initDc";
    // GetJS
    private static String GET_JS = "https://kyfw.12306.cn/otn/HttpZF/GetJS";
    // 获取乘客信息列表
    private static String GET_PASSENGERDTOS = "https://kyfw.12306.cn/otn/confirmPassenger/getPassengerDTOs";

    private static String GET_PASSCODE_NEW = "https://kyfw.12306.cn/otn/passcodeNew/getPassCodeNew";
    // 检查订单
    private static String CHECK_ORDER_INFO = "https://kyfw.12306.cn/otn/confirmPassenger/checkOrderInfo";
    // 队列计数(准备进入下单步骤)
    private static String GET_QUEUE_COUNT = "https://kyfw.12306.cn/otn/confirmPassenger/getQueueCount";
    // 正式下单
    private static String CONFIRM_SINGLE_FOR_QUEUE = "https://kyfw.12306.cn/otn/confirmPassenger/confirmSingleForQueue";
    // 下单确认中(调用两次)
    private static String QUERY_ORDER_WAIT_TIME = "https://kyfw.12306.cn/otn/confirmPassenger/queryOrderWaitTime";
    // 结果回执
    private static String RESULT_ORDER_FOR_DC_QUEUE = "https://kyfw.12306.cn/otn/confirmPassenger/resultOrderForDcQueue";

}


================================================
FILE: src/com/kalvin/J12306/config/UrlsEnum.java
================================================
package com.kalvin.J12306.config;

/**
 * url枚举类
 * Create by Kalvin on 2019/9/18.
 */
public enum UrlsEnum {

    LOG_DEVICE(new UrlConfig(   // 设备信息
            "https://kyfw.12306.cn/otn/HttpZF/logdevice",   // url地址
            "get",  // 请求方法
            "https://kyfw.12306.cn/otn/login/init" // referer
    )),
    LOGIN_INIT(new UrlConfig(   // 登录页
            "https://kyfw.12306.cn/otn/login/init",
            "get",
            "https://kyfw.12306.cn/otn/index/init"
    )),
    CAPTCHA(new UrlConfig(  // 登录验证码
            "https://kyfw.12306.cn/passport/captcha/captcha-image?login_site=E&module=login&rand=sjrand&{0}",
            "get",
            "https://kyfw.12306.cn/otn/resources/login.html"
    )),
    CAPTCHA_BASE64(new UrlConfig(  // 登录验证码2
            "https://kyfw.12306.cn/passport/captcha/captcha-image64?login_site=E&module=login&rand=sjrand&{0}&callback=jQuery19108016482864806321_1554298927290&_=1554298927293",
            "get",
            "https://kyfw.12306.cn/otn/resources/login.html"
    )),
    CHECK_CAPTCHA(new UrlConfig(    // 校验登录验证码
            "https://kyfw.12306.cn/passport/captcha/captcha-check",
            "post",
            "https://kyfw.12306.cn/otn/login/init"
    )),
    LOGIN(new UrlConfig(    // 登录接口
            "https://kyfw.12306.cn/passport/web/login",
            "post",
            "https://kyfw.12306.cn/otn/resources/login.html"
    )),
    USER_LOGIN(new UrlConfig(   // 用户登录
            "https://kyfw.12306.cn/otn/login/userLogin",
            "get",
            "https://kyfw.12306.cn/otn/login/init"
    )),
    PASSPORT(new UrlConfig(   // PASSPORT
            "https://kyfw.12306.cn/otn/passport?redirect=/otn/login/userLogin",
            "get",
            "https://kyfw.12306.cn/otn/login/init"
    )),
    UAM_TK(new UrlConfig(   // 获取token
            "https://kyfw.12306.cn/passport/web/auth/uamtk",
            "post",
            "https://kyfw.12306.cn/otn/passport?redirect=/otn/login/userLogin"
    )),
    UAM_AUTH_CLIENT(new UrlConfig(
            "https://kyfw.12306.cn/otn/uamauthclient",
            "post",
            "https://kyfw.12306.cn/otn/passport?redirect=/otn/login/userLogin"
    )),
    GET_USER_INFO(new UrlConfig(    // 获取用户信息
            "https://kyfw.12306.cn/otn/modifyUser/initQueryUserInfoApi",
            "post",
            ""
    )),
    INIT_TICKET(new UrlConfig(  // 查票页
            "https://kyfw.12306.cn/otn/leftTicket/init",
            "get",
            "https://www.12306.cn/index/index.html"
    )),
    QUERY_A_TICKET(new UrlConfig( // 查票接口A
            "https://kyfw.12306.cn/otn/leftTicket/queryA?leftTicketDTO.train_date={0}&leftTicketDTO.from_station={1}&leftTicketDTO.to_station={2}&purpose_codes=ADULT",
            "post",
            "https://kyfw.12306.cn/otn/leftTicket/init"
    )),
    QUERY_Z_TICKET(new UrlConfig( // 查票接口Z
            "https://kyfw.12306.cn/otn/leftTicket/queryZ?leftTicketDTO.train_date={0}&leftTicketDTO.from_station={1}&leftTicketDTO.to_station={2}&purpose_codes=ADULT",
            "post",
            "https://kyfw.12306.cn/otn/leftTicket/init"
    )),
    CHECK_USER(new UrlConfig(   // 检查用户状态
            "https://kyfw.12306.cn/otn/login/checkUser",
            "post",
            "https://kyfw.12306.cn/otn/leftTicket/init"
    )),
    SUBMIT_ORDER_REQUEST(new UrlConfig( // 提交订单
            "https://kyfw.12306.cn/otn/leftTicket/submitOrderRequest",
            "post",
            "https://kyfw.12306.cn/otn/leftTicket/init"
    )),
    INIT_DC(new UrlConfig(  // initDc
            "https://kyfw.12306.cn/otn/confirmPassenger/initDc",
            "get",
            "https://kyfw.12306.cn/otn/leftTicket/init"
    )),
    GET_JS(new UrlConfig(   // GetJS
            "https://kyfw.12306.cn/otn/HttpZF/GetJS",
            "get",
            "https://kyfw.12306.cn/otn/confirmPassenger/initDc"
    )),
    GET_PASSENGERDTOS(new UrlConfig(    // 获取乘客信息列表
            "https://kyfw.12306.cn/otn/confirmPassenger/getPassengerDTOs",
            "post",
            "https://kyfw.12306.cn/otn/confirmPassenger/initDc"
    )),
    GET_PASSCODE_NEW(new UrlConfig( // 订单页面验证码
            "https://kyfw.12306.cn/otn/passcodeNew/getPassCodeNew?module=passenger&rand=randp&{0}",
            "get",
            "https://kyfw.12306.cn/otn/confirmPassenger/initDc"
    )),
    CHECK_ORDER_INFO(new UrlConfig( // 检查订单
            "https://kyfw.12306.cn/otn/confirmPassenger/checkOrderInfo",
            "post",
            "https://kyfw.12306.cn/otn/confirmPassenger/initDc"
    )),
    GET_QUEUE_COUNT(new UrlConfig(  // 队列计数(准备进入下单步骤)
            "https://kyfw.12306.cn/otn/confirmPassenger/getQueueCount",
            "post",
            "https://kyfw.12306.cn/otn/confirmPassenger/initDc"
    )),
    CHECK_RAND_CODE_ASYNC(new UrlConfig(  // 验证订单验证码
            "https://kyfw.12306.cn/otn/passcodeNew/checkRandCodeAnsyn",
            "post",
            "https://kyfw.12306.cn/otn/confirmPassenger/initDc"
    )),
    CONFIRM_SINGLE_FOR_QUEUE(new UrlConfig( // 正式下单
            "https://kyfw.12306.cn/otn/confirmPassenger/confirmSingleForQueue",
            "post",
            "https://kyfw.12306.cn/otn/confirmPassenger/initDc"
    )),
    QUERY_ORDER_WAIT_TIME(new UrlConfig(    // 下单确认中(调用两次)
            "https://kyfw.12306.cn/otn/confirmPassenger/queryOrderWaitTime?random={0}&tourFlag=dc&_json_att=&REPEAT_SUBMIT_TOKEN={1}",
            "post",
            "https://kyfw.12306.cn/otn/confirmPassenger/initDc"
    )),
    RESULT_ORDER_FOR_DC_QUEUE(new UrlConfig(    // 结果回执
            "https://kyfw.12306.cn/otn/confirmPassenger/resultOrderForDcQueue",
            "post",
            ""
    )),
    INIT_NO_COMPLETE(new UrlConfig(    // 初始化用户未完成的订单列表
            "https://kyfw.12306.cn/otn/queryOrder/initNoComplete",
            "get",
            "https://kyfw.12306.cn/otn/passport?redirect=/otn/queryOrder/initNoComplete"
    )),
    INIT_MY12306_API(new UrlConfig(    // 初始化用户基础信息API
            "https://kyfw.12306.cn/otn/index/initMy12306Api",
            "post",
            "https://kyfw.12306.cn/otn/view/index.html"
    )),
    QUERY_MY_ORDER_NO_COMPLETE(new UrlConfig(    // 查询未完成的订单
            "https://kyfw.12306.cn/otn/queryOrder/queryMyOrderNoComplete",
            "post",
            "https://kyfw.12306.cn/otn/queryOrder/initNoComplete"
    )),
    CANCEL_NO_COMPLETE_MY_ORDER(new UrlConfig(    // 查询未完成的订单
            "https://kyfw.12306.cn/otn/queryOrder/cancelNoCompleteMyOrder",
            "post",
            "https://kyfw.12306.cn/otn/queryOrder/initNoComplete"
    )),
    CHECK_FACE(new UrlConfig(    // 人脸验证
            "https://kyfw.12306.cn/otn/afterNate/chechFace",
            "post",
            "https://kyfw.12306.cn/otn/leftTicket/init"
    )),
    GET_SUCCESS_RATE(new UrlConfig(    // 成功添加候补
            "https://kyfw.12306.cn/otn/afterNate/getSuccessRate",
            "post",
            "https://kyfw.12306.cn/otn/leftTicket/init"
    )),
    SUBMIT_ORDER_REQUEST_AN(new UrlConfig(    // 提交候补订单
            "https://kyfw.12306.cn/otn/afterNate/submitOrderRequest",
            "post",
            "https://kyfw.12306.cn/otn/leftTicket/init"
    )),
    LINE_UP_TO_PAY(new UrlConfig(    // 候补页面
            "https://kyfw.12306.cn/otn/view/lineUp_toPay.html",
            "get",
            "https://kyfw.12306.cn/otn/leftTicket/init"
    )),
    PASSENGER_INIT_API(new UrlConfig(    // 乘客信息接口
            "https://kyfw.12306.cn/otn/afterNate/passengerInitApi",
            "post",
            "https://kyfw.12306.cn/otn/view/lineUp_toPay.html"
    )),
    GET_QUEUE_NUM(new UrlConfig(    // 获取候补排队人数
            "https://kyfw.12306.cn/otn/afterNate/getQueueNum",
            "post",
            "https://kyfw.12306.cn/otn/view/lineUp_toPay.html"
    )),
    CONFIRM_HB(new UrlConfig(    // 提交候补订单信息
            "https://kyfw.12306.cn/otn/afterNate/confirmHB",
            "post",
            "https://kyfw.12306.cn/otn/view/lineUp_toPay.html"
    )),
    QUERY_QUEUE(new UrlConfig(    // 候补排队
            "https://kyfw.12306.cn/otn/queryOrder/cancelNoCompleteMyOrder",
            "post",
            "https://kyfw.12306.cn/otn/view/lineUp_toPay.html"
    ));

    private UrlConfig urlConfig;

    UrlsEnum(UrlConfig urlConfig) {
        this.urlConfig = urlConfig;
    }

    public UrlConfig getUrlConfig() {
        return urlConfig;
    }

    public void setUrlConfig(UrlConfig urlConfig) {
        this.urlConfig = urlConfig;
    }
}


================================================
FILE: src/com/kalvin/J12306/dto/SubmitTicketInfoDTO.java
================================================
package com.kalvin.J12306.dto;

/**
 * 提交订单相关参数
 * Create by Kalvin on 2019/9/20.
 */
public class SubmitTicketInfoDTO {

    private String repeatSubmitToken; // 提交订单token
    private String keyCheckIsChange;
    private String purposeCodes;
    private String leftTicketStr;   // 车票标识

    public String getRepeatSubmitToken() {
        return repeatSubmitToken;
    }

    public void setRepeatSubmitToken(String repeatSubmitToken) {
        this.repeatSubmitToken = repeatSubmitToken;
    }

    public String getKeyCheckIsChange() {
        return keyCheckIsChange;
    }

    public void setKeyCheckIsChange(String keyCheckIsChange) {
        this.keyCheckIsChange = keyCheckIsChange;
    }

    public String getPurposeCodes() {
        return purposeCodes;
    }

    public void setPurposeCodes(String purposeCodes) {
        this.purposeCodes = purposeCodes;
    }

    public String getLeftTicketStr() {
        return leftTicketStr;
    }

    public void setLeftTicketStr(String leftTicketStr) {
        this.leftTicketStr = leftTicketStr;
    }

    @Override
    public String toString() {
        return "SubmitTicketInfoDTO{" +
                "repeatSubmitToken='" + repeatSubmitToken + '\'' +
                ", keyCheckIsChange='" + keyCheckIsChange + '\'' +
                ", purposeCodes='" + purposeCodes + '\'' +
                ", leftTicketStr='" + leftTicketStr + '\'' +
                '}';
    }
}


================================================
FILE: src/com/kalvin/J12306/dto/TicketInfoDTO.java
================================================
package com.kalvin.J12306.dto;

/**
 * 车票信息
 * Create by Kalvin on 2019/9/19.
 */
public class TicketInfoDTO {

    private boolean onSale; // 是否开售
    private String secretStr;   // 密钥串
    private String trainNo;     // 列车号
    private String trainNum;    // 车次
    private String formStationName; // 始发站名称
    private String toStationName; // 终点站名称
    private String formStationTelecode; // 12306始发站代码
    private String toStationTelecode;   // 12306终点站代码
    private String goOffTime;   // 出发时间
    private String arrivalTime; // 到达时间
    private String lastTime;    // 历时时间
    private String leftTicket;
    private String trainLocation;

    private String businessSeat;    // 商务特等座
    private String l1Seat;  // 一等座
    private String l2Seat;  // 二等座
    private String l1SoftBerth; // 软卧一等卧
    private String l2HardBerth; // 硬卧二等卧
    private String hardSeat;    // 硬座
    private String softSeat;    // 软座
    private String noSeat;      // 无座
    private boolean canAlternate;   // 是否可候补。1代表能候补
    private String canNotAlternateSeatType; // 不能候补的座席

    public boolean isOnSale() {
        return onSale;
    }

    public void setOnSale(boolean onSale) {
        this.onSale = onSale;
    }

    public String getSecretStr() {
        return secretStr;
    }

    public void setSecretStr(String secretStr) {
        this.secretStr = secretStr;
    }

    public String getTrainNo() {
        return trainNo;
    }

    public void setTrainNo(String trainNo) {
        this.trainNo = trainNo;
    }

    public String getTrainNum() {
        return trainNum;
    }

    public void setTrainNum(String trainNum) {
        this.trainNum = trainNum;
    }

    public String getFormStationName() {
        return formStationName;
    }

    public void setFormStationName(String formStationName) {
        this.formStationName = formStationName;
    }

    public String getToStationName() {
        return toStationName;
    }

    public void setToStationName(String toStationName) {
        this.toStationName = toStationName;
    }

    public String getFormStationTelecode() {
        return formStationTelecode;
    }

    public void setFormStationTelecode(String formStationTelecode) {
        this.formStationTelecode = formStationTelecode;
    }

    public String getToStationTelecode() {
        return toStationTelecode;
    }

    public void setToStationTelecode(String toStationTelecode) {
        this.toStationTelecode = toStationTelecode;
    }

    public String getGoOffTime() {
        return goOffTime;
    }

    public void setGoOffTime(String goOffTime) {
        this.goOffTime = goOffTime;
    }

    public String getArrivalTime() {
        return arrivalTime;
    }

    public void setArrivalTime(String arrivalTime) {
        this.arrivalTime = arrivalTime;
    }

    public String getLastTime() {
        return lastTime;
    }

    public void setLastTime(String lastTime) {
        this.lastTime = lastTime;
    }

    public String getLeftTicket() {
        return leftTicket;
    }

    public void setLeftTicket(String leftTicket) {
        this.leftTicket = leftTicket;
    }

    public String getTrainLocation() {
        return trainLocation;
    }

    public void setTrainLocation(String trainLocation) {
        this.trainLocation = trainLocation;
    }

    public String getBusinessSeat() {
        return businessSeat;
    }

    public void setBusinessSeat(String businessSeat) {
        this.businessSeat = businessSeat;
    }

    public String getL1Seat() {
        return l1Seat;
    }

    public void setL1Seat(String l1Seat) {
        this.l1Seat = l1Seat;
    }

    public String getL2Seat() {
        return l2Seat;
    }

    public void setL2Seat(String l2Seat) {
        this.l2Seat = l2Seat;
    }

    public String getL1SoftBerth() {
        return l1SoftBerth;
    }

    public void setL1SoftBerth(String l1SoftBerth) {
        this.l1SoftBerth = l1SoftBerth;
    }

    public String getL2HardBerth() {
        return l2HardBerth;
    }

    public void setL2HardBerth(String l2HardBerth) {
        this.l2HardBerth = l2HardBerth;
    }

    public String getHardSeat() {
        return hardSeat;
    }

    public void setHardSeat(String hardSeat) {
        this.hardSeat = hardSeat;
    }

    public String getSoftSeat() {
        return softSeat;
    }

    public void setSoftSeat(String softSeat) {
        this.softSeat = softSeat;
    }

    public String getNoSeat() {
        return noSeat;
    }

    public void setNoSeat(String noSeat) {
        this.noSeat = noSeat;
    }

    public boolean isCanAlternate() {
        return canAlternate;
    }

    public void setCanAlternate(boolean canAlternate) {
        this.canAlternate = canAlternate;
    }

    public String getCanNotAlternateSeatType() {
        return canNotAlternateSeatType;
    }

    public void setCanNotAlternateSeatType(String canNotAlternateSeatType) {
        this.canNotAlternateSeatType = canNotAlternateSeatType;
    }

    @Override
    public String toString() {
        return "TicketInfoDTO{" +
                "secretStr='" + secretStr + '\'' +
                ", trainNo='" + trainNo + '\'' +
                ", trainNum='" + trainNum + '\'' +
                ", formStationName='" + formStationName + '\'' +
                ", toStationName='" + toStationName + '\'' +
                ", formStationTelecode='" + formStationTelecode + '\'' +
                ", toStationTelecode='" + toStationTelecode + '\'' +
                ", goOffTime='" + goOffTime + '\'' +
                ", arrivalTime='" + arrivalTime + '\'' +
                ", lastTime='" + lastTime + '\'' +
                ", leftTicket='" + leftTicket + '\'' +
                ", trainLocation='" + trainLocation + '\'' +
                ", businessSeat='" + businessSeat + '\'' +
                ", l1Seat='" + l1Seat + '\'' +
                ", l2Seat='" + l2Seat + '\'' +
                ", l1SoftBerth='" + l1SoftBerth + '\'' +
                ", l2HardBerth='" + l2HardBerth + '\'' +
                ", hardSeat='" + hardSeat + '\'' +
                ", softSeat='" + softSeat + '\'' +
                ", noSeat='" + noSeat + '\'' +
                ", canAlternate=" + canAlternate +
                ", canNotAlternateSeatType='" + canNotAlternateSeatType + '\'' +
                '}';
    }
}


================================================
FILE: src/com/kalvin/J12306/dto/UserInfoDTO.java
================================================
package com.kalvin.J12306.dto;

/**
 * 保存用户基础信息
 * Create by Kalvin on 2019/9/19.
 */
public class UserInfoDTO {

    private String name;    // 用户姓名
    private String username;    // 用户账号
    private String idTypeCode;  // 证件类型代码
    private String idTypeName;  // 证件类型名称
    private String idNo;    // 证件号码
    private String email;   // 用户绑定的邮箱账号
    private String userEncStr;  // 用户密钥串

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getIdTypeCode() {
        return idTypeCode;
    }

    public void setIdTypeCode(String idTypeCode) {
        this.idTypeCode = idTypeCode;
    }

    public String getIdTypeName() {
        return idTypeName;
    }

    public void setIdTypeName(String idTypeName) {
        this.idTypeName = idTypeName;
    }

    public String getIdNo() {
        return idNo;
    }

    public void setIdNo(String idNo) {
        this.idNo = idNo;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getUserEncStr() {
        return userEncStr;
    }

    public void setUserEncStr(String userEncStr) {
        this.userEncStr = userEncStr;
    }

    @Override
    public String toString() {
        return "UserInfoDTO{" +
                "name='" + name + '\'' +
                ", username='" + username + '\'' +
                ", idTypeCode='" + idTypeCode + '\'' +
                ", idTypeName='" + idTypeName + '\'' +
                ", idNo='" + idNo + '\'' +
                ", email='" + email + '\'' +
                ", userEncStr='" + userEncStr + '\'' +
                '}';
    }
}


================================================
FILE: src/com/kalvin/J12306/exception/J12306Exception.java
================================================
package com.kalvin.J12306.exception;

/**
 * 自定义异常类
 * Create by Kalvin on 2019/9/19.
 */
public class J12306Exception extends RuntimeException {
    private String msg;

    public J12306Exception(String message) {
        super(message);
        this.msg = message;
    }

    public J12306Exception(int errorCode, String message) {
        super(message);
        this.msg = message;
    }

    public J12306Exception(String message, Throwable cause) {
        super(message, cause);
        this.msg = message;
    }

    public String getMsg() {
        return msg;
    }
}


================================================
FILE: src/com/kalvin/J12306/http/Session.java
================================================
package com.kalvin.J12306.http;

import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.http.Method;
import com.kalvin.J12306.config.Constants;
import com.kalvin.J12306.config.UrlConfig;
import com.kalvin.J12306.config.UrlsEnum;

import java.net.HttpCookie;
import java.util.HashMap;
import java.util.List;

/**
 * 会话类
 * Create by Kalvin on 2019/9/18.
 */
public class Session {

    public HttpClient httpClient;
    public String token;
    public String cookie;

    public Session() {
        this.httpClient = new HttpClient();
    }

    public String getToken() {
        return token;
    }

    public void setToken(String token) {
        this.token = token;
    }

    public String getCookie() {
        return cookie;
    }

    public void setCookie(String cookie) {
        if (StrUtil.isNotEmpty(this.cookie)) {
            this.cookie += ";";
        } else {
            this.cookie = "";
        }
        this.cookie += cookie;
    }

    public void setCookie(List<HttpCookie> cookies) {
        cookies.forEach(hc -> {
            if (StrUtil.isNotEmpty(this.cookie)) {
                this.cookie += ";";
            } else {
                this.cookie = "";
            }
            this.cookie += hc.toString();
        });
    }

    public class HttpClient {

        private HttpRequest httpRequest;

        private HttpClient() {
        }

        public HttpResponse send(UrlsEnum urlsEnum) {
            return this.send(urlsEnum, null, false);
        }

        public HttpResponse send(UrlsEnum urlsEnum, HashMap<String, Object> formData) {
            return this.send(urlsEnum, formData, false);
        }

        public HttpResponse sendAsync(UrlsEnum urlsEnum) {
            return this.send(urlsEnum, null, true);
        }

        public HttpResponse sendAsync(UrlsEnum urlsEnum, HashMap<String, Object> formData) {
            return this.send(urlsEnum, formData, true);
        }

        public HttpResponse send(UrlsEnum urlsEnum, HashMap<String, Object> formData, boolean async) {
            UrlConfig urlConfig = urlsEnum.getUrlConfig();
            if (this.httpRequest == null) {
                this.httpRequest = HttpUtil.createGet(urlConfig.getUrl());
                this.httpRequest.header("Host", Constants.HOST);
                this.httpRequest.header("Origin", Constants.ORIGIN);
                this.httpRequest.header("Connection", "keep-alive");
                this.httpRequest.header("Accept", Constants.ACCEPT);
            } else {
                this.httpRequest.setUrl(urlConfig.getUrl());
                this.httpRequest.setMethod(this.getMethod(urlConfig.getMethod()));
            }
            if (!"".equals(urlConfig.getReferer())) {
                this.httpRequest.header("Referer", urlConfig.getReferer());
            }
            // 设置cookie
            if (StrUtil.isNotBlank(cookie)) {
                this.httpRequest.header("Cookie", cookie);
            }
//            this.httpRequest.headers().forEach((k, v) -> System.out.println(k + "=" + v));
            // 设置表单参数
            if (formData != null) {
                this.httpRequest.form(formData);
            }
            if (async) {
                return this.httpRequest.executeAsync();
            } else {
                return this.httpRequest.execute();
            }
        }

        private Method getMethod(String methodStr) {
            return methodStr.equalsIgnoreCase("get") ? Method.GET : Method.POST;
        }

        public void setHeader(HashMap<String, String> headers) {
            headers.forEach((k, v) -> this.httpRequest.header(k, v));
        }

        public String getHeader(String name) {
            return this.httpRequest.header(name);
        }
    }

}


================================================
FILE: src/com/kalvin/J12306/utils/EmailUtil.java
================================================
package com.kalvin.J12306.utils;

import cn.hutool.extra.mail.MailAccount;
import cn.hutool.extra.mail.MailUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;

/**
 * 邮件工具类
 * Create by Kalvin on 2019/9/23.
 */
public class EmailUtil {

    private final static Log log = LogFactory.get();

    private static MailAccount account;

    private static void initAccount() {
        account = new MailAccount();
        account.setHost((String) YmlUtil.get("j12306.notice.email.sender.host"));
        account.setPort((Integer) YmlUtil.get("j12306.notice.email.sender.port"));
        account.setAuth(true);
        account.setFrom((String) YmlUtil.get("j12306.notice.email.sender.from"));
        account.setUser((String) YmlUtil.get("j12306.notice.email.sender.user"));
        account.setPass((String) YmlUtil.get("j12306.notice.email.sender.pass"));
    }

    public static void send(String subject, String content) {
        if (account == null) {
            initAccount();
        }
        try {
            MailUtil.send(account, (String) YmlUtil.get("j12306.notice.email.receiver"), subject, content, false);
        } catch (Exception e) {
            log.error("无法通过邮件通知您,请检查config.yml配置文件,确保邮件相关配置正确!error:" + e.getMessage());
        }
    }

    public static void sendTest() {
        EmailUtil.send("J12306邮件配置测试", "测试邮件是否能发送成功!收到邮件证明邮件信息配置正确!");
    }
}


================================================
FILE: src/com/kalvin/J12306/utils/J12306Util.java
================================================
package com.kalvin.J12306.utils;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.kalvin.J12306.api.Ticket;
import com.kalvin.J12306.config.Constants;
import com.kalvin.J12306.config.TicketSeatType;
import com.kalvin.J12306.dto.TicketInfoDTO;
import com.kalvin.J12306.exception.J12306Exception;
import com.kalvin.J12306.http.Session;

import java.io.UnsupportedEncodingException;
import java.math.RoundingMode;
import java.net.URLDecoder;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 工具类
 * Create by Kalvin on 2019/9/19.
 */
public class J12306Util {

    private final static Log log = LogFactory.get();

    public static String genRandNumber() {
        return String.valueOf(RandomUtil.randomDouble(0, 0.9, 17, RoundingMode.HALF_UP));
    }

    public static void sleep(int second) {
        try {
            Thread.sleep(second * 1000);
        } catch (InterruptedException e) {
            System.out.println("Thread.sleep error = " + e.getMessage());
            log.error("Thread.sleep error = {}", e.getMessage());
        }
    }

    public static void sleepM(int millisecond) {
        try {
            Thread.sleep(millisecond);
        } catch (InterruptedException e) {
            log.error("Thread.sleep error = {}", e.getMessage());
        }
    }

    public static String getCaptchaPos(String codeIdx) {
        final List<String> DICT_CODE = Arrays.asList("36,46", "116,46", "188,46", "267,43", "40,118", "113,119", "190,122", "264,115");
        StringBuilder sb = new StringBuilder();
        for (String i : codeIdx.split(",")) {
            if (sb.length() > 0) {
                sb.append(",");
            }
            sb.append(DICT_CODE.get(Integer.parseInt(i) - 1));
        }
        return sb.toString();
    }

    /**
     * 解析车票信息实体
     * @param ticketRes 车票查询结果字符串
     * @return List<TicketInfoDTO>
     */
    public static List<TicketInfoDTO> parseTicketInfo(String ticketRes) {
        JSON parse = JSONUtil.parse(ticketRes);
        JSONObject map = (JSONObject) parse.getByPath("data.map");
        JSONArray result = (JSONArray) parse.getByPath("data.result");
        List<TicketInfoDTO> ticketInfoDTOS = new ArrayList<>();
        TicketInfoDTO ticketInfoDTO;

        for (Object object : result) {
            ticketInfoDTO = new TicketInfoDTO();
            String trainInfo = object.toString();
            String[] split = trainInfo.split("\\|");

            if (StrUtil.isNotEmpty(split[0])) {
                ticketInfoDTO.setSecretStr(split[0]);
                ticketInfoDTO.setOnSale("预订".equals(split[1]));
                ticketInfoDTO.setTrainNo(split[2]);
                ticketInfoDTO.setTrainNum(split[3]);
                ticketInfoDTO.setFormStationTelecode(split[6]);
                ticketInfoDTO.setToStationTelecode(split[7]);
                ticketInfoDTO.setGoOffTime(split[8]);
                ticketInfoDTO.setArrivalTime(split[9]);
                ticketInfoDTO.setLastTime(split[10]);
                ticketInfoDTO.setLeftTicket(split[12]);
                ticketInfoDTO.setTrainLocation(split[15]);
                ticketInfoDTO.setBusinessSeat(split[32]);   // or 5
                ticketInfoDTO.setL1Seat(split[31]);
                ticketInfoDTO.setL2Seat(split[30]);
                ticketInfoDTO.setL1SoftBerth(split[23]);
                ticketInfoDTO.setL2HardBerth(split[28]);
                ticketInfoDTO.setSoftSeat(split[24]);
                ticketInfoDTO.setHardSeat(split[29]);
                ticketInfoDTO.setNoSeat(split[26]);
                ticketInfoDTO.setCanAlternate(split[37].equals("1"));
                if (split.length == 38) {
                    ticketInfoDTO.setCanNotAlternateSeatType("");
                }
                if (split.length == 39) {
                    ticketInfoDTO.setCanNotAlternateSeatType(split[38]);
                }

                ticketInfoDTO.setFormStationName(map.get(split[6]).toString());
                ticketInfoDTO.setToStationName(map.get(split[7]).toString());

                ticketInfoDTOS.add(ticketInfoDTO);
            }
        }
        return ticketInfoDTOS;
    }

    public static String urlDecode(String str) {
        try {
            // 先进行一次解码。避免提交后再编码一次导致参数secretStr失效
            return URLDecoder.decode(str, "utf-8");
        } catch (UnsupportedEncodingException e) {
            log.error(e.getMessage());
        }
        return str;
    }

    public static String formatDateGMT(String dateStr) {
        final DateTime date = DateUtil.parse(dateStr);
        final SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd yyyy '00:00:00' 'GMT'Z '(中国标准时间)'", Locale.ENGLISH);
        return sdf.format(date);
    }

    public static boolean hasTicket(String seatInfo) {
        return (NumberUtil.isNumber(seatInfo) && Integer.parseInt(seatInfo) > 0) || "有".equals(seatInfo);
    }

    public static LinkedHashMap<String, Boolean> getSeatsTicketInfo(String seats, TicketInfoDTO ticketInfo) {
        final LinkedHashMap<String, Boolean> linkedHashMap = new LinkedHashMap<>();
        for (String seat : seats.split(",")) {
            if (TicketSeatType.L2_SEAT.getCode().equals(seat)) {
                linkedHashMap.put(TicketSeatType.L2_SEAT.getCode(), J12306Util.hasTicket(ticketInfo.getL2Seat()));
            }
            if (TicketSeatType.L1_SEAT.getCode().equals(seat)) {
                linkedHashMap.put(TicketSeatType.L1_SEAT.getCode(), J12306Util.hasTicket(ticketInfo.getL1Seat()));
            }
            if (TicketSeatType.SOFT_SEAT.getCode().equals(seat)) {
                linkedHashMap.put(TicketSeatType.SOFT_SEAT.getCode(), J12306Util.hasTicket(ticketInfo.getSoftSeat()));
            }
            if (TicketSeatType.HARD_SEAT.getCode().equals(seat)) {
                linkedHashMap.put(TicketSeatType.HARD_SEAT.getCode(), J12306Util.hasTicket(ticketInfo.getHardSeat()));
            }
            if (TicketSeatType.SORT_SLEEPER.getCode().equals(seat)) {
                linkedHashMap.put(TicketSeatType.SORT_SLEEPER.getCode(), J12306Util.hasTicket(ticketInfo.getL1SoftBerth()));
            }
            if (TicketSeatType.HARD_SLEEPER.getCode().equals(seat)) {
                linkedHashMap.put(TicketSeatType.HARD_SLEEPER.getCode(), J12306Util.hasTicket(ticketInfo.getL2HardBerth()));
            }
            if (TicketSeatType.SP_SEAT.getCode().equals(seat)) {
                linkedHashMap.put(TicketSeatType.SP_SEAT.getCode(), J12306Util.hasTicket(ticketInfo.getBusinessSeat()));
            }
            if (Constants.NO_SEAT_CODE.equals(seat)) {
                linkedHashMap.put(TicketSeatType.NO_SEAT.getCode(), J12306Util.hasTicket(ticketInfo.getNoSeat()));
            }
        }
        return linkedHashMap;
    }

    public static boolean noNeedTicket(LinkedHashMap<String, Boolean> seatsTicketInfo) {
        for (String seatCode : seatsTicketInfo.keySet()) {
            if (seatsTicketInfo.get(seatCode)) {
                return false;
            }
        }
        return true;
    }

    public static String formatDateStr(String dateStr) {
        final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        try {
            Date date = simpleDateFormat.parse(dateStr);
            return simpleDateFormat.format(date);
        } catch (ParseException e) {
            throw new J12306Exception("日期格式不正确");
        }
    }

    public static void printlnLeftTicket(String trainDate, String fromStation, String toStation) {
        HttpResponse httpResponse = new Ticket(new Session(), J12306Util.formatDateStr(trainDate), StationUtil.getStationCode(fromStation), StationUtil.getStationCode(toStation))
                .queryZ();
        if (httpResponse.getStatus() == Constants.REQ_SUCCESS_STATUS) {
            List<TicketInfoDTO> ticketInfoDTOS = J12306Util.parseTicketInfo(httpResponse.body());
            ticketInfoDTOS.forEach(t -> log.info("出发日期【{}】车次【{}】出发时间【{}】到达时间【{}】", trainDate, t.getTrainNum(), t.getGoOffTime(), t.getArrivalTime()));
        } else {
            log.error("无法查询车票信息,状态【{}】", httpResponse.getStatus());
        }
    }

    public static String getCurrAftOneMinuteTime() {
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
        Calendar afterTime = Calendar.getInstance();
        afterTime.add(Calendar.MINUTE, 1);// 1分钟之后的时间
        Date beforeD = afterTime.getTime();
        return sdf.format(beforeD);
    }

    public static String getAfter5MinuteTime(String time) {
        DateTime dateTime = DateUtil.parse(DateUtil.formatDate(DateUtil.date()) + " " + time);
        Calendar calendar = DateUtil.calendar(dateTime);
        calendar.add(Calendar.MINUTE, 5);
        return DateUtil.format(calendar.getTime(), "HH:mm");
    }

    public static String getCurrTime() {
        return DateUtil.format(DateUtil.date(), "HH:mm");
    }

}


================================================
FILE: src/com/kalvin/J12306/utils/StationUtil.java
================================================
package com.kalvin.J12306.utils;

import cn.hutool.core.util.StrUtil;
import com.kalvin.J12306.cache.TicketCache;
import com.kalvin.J12306.config.Constants;

import java.util.HashMap;

/**
 * 12306站点工具
 * Create by Kalvin on 2019/9/20.
 */
public class StationUtil {

//    private final static String stationNames = "@bjb|北京北|VAP|beijingbei|bjb|0@bjd|北京东|BOP|beijingdong|bjd|1@bji|北京|BJP|beijing|bj|2@bjn|北京南|VNP|beijingnan|bjn|3@bjx|北京西|BXP|beijingxi|bjx|4@gzn|广州南|IZQ|guangzhounan|gzn|5@cqb|重庆北|CUW|chongqingbei|cqb|6@cqi|重庆|CQW|chongqing|cq|7@cqn|重庆南|CRW|chongqingnan|cqn|8@cqx|重庆西|CXW|chongqingxi|cqx|9@gzd|广州东|GGQ|guangzhoudong|gzd|10@sha|上海|SHH|shanghai|sh|11@shn|上海南|SNH|shanghainan|shn|12@shq|上海虹桥|AOH|shanghaihongqiao|shhq|13@shx|上海西|SXH|shanghaixi|shx|14@tjb|天津北|TBP|tianjinbei|tjb|15@tji|天津|TJP|tianjin|tj|16@tjn|天津南|TIP|tianjinnan|tjn|17@tjx|天津西|TXP|tianjinxi|tjx|18@xgl|香港西九龙|XJA|hkwestkowloon|xgxjl|19@cch|长春|CCT|changchun|cc|20@ccn|长春南|CET|changchunnan|ccn|21@ccx|长春西|CRT|changchunxi|ccx|22@cdd|成都东|ICW|chengdudong|cdd|23@cdn|成都南|CNW|chengdunan|cdn|24@cdu|成都|CDW|chengdu|cd|25@csh|长沙|CSQ|changsha|cs|26@csn|长沙南|CWQ|changshanan|csn|27@dmh|大明湖|JAK|daminghu|dmh|28@fzh|福州|FZS|fuzhou|fz|29@fzn|福州南|FYS|fuzhounan|fzn|30@gya|贵阳|GIW|guiyang|gy|31@gzh|广州|GZQ|guangzhou|gz|32@gzx|广州西|GXQ|guangzhouxi|gzx|33@heb|哈尔滨|HBB|haerbin|heb|34@hed|哈尔滨东|VBB|haerbindong|hebd|35@hex|哈尔滨西|VAB|haerbinxi|hebx|36@hfe|合肥|HFH|hefei|hf|37@hfx|合肥西|HTH|hefeixi|hfx|38@hhd|呼和浩特东|NDC|huhehaotedong|hhhtd|39@hht|呼和浩特|HHC|huhehaote|hhht|40@hkd|海  口东|KEQ|haikoudong|hkd|41@hkd|海口东|HMQ|haikoudong|hkd|42@hko|海口|VUQ|haikou|hk|43@hzd|杭州东|HGH|hangzhoudong|hzd|44@hzh|杭州|HZH|hangzhou|hz|45@hzn|杭州南|XHH|hangzhounan|hzn|46@jna|济南|JNK|jinan|jn|47@jnx|济南西|JGK|jinanxi|jnx|48@kmi|昆明|KMM|kunming|km|49@kmx|昆明西|KXM|kunmingxi|kmx|50@lsa|拉萨|LSO|lasa|ls|51@lzd|兰州东|LVJ|lanzhoudong|lzd|52@lzh|兰州|LZJ|lanzhou|lz|53@lzx|兰州西|LAJ|lanzhouxi|lzx|54@nch|南昌|NCG|nanchang|nc|55@nji|南京|NJH|nanjing|nj|56@njn|南京南|NKH|nanjingnan|njn|57@nni|南宁|NNZ|nanning|nn|58@sjb|石家庄北|VVP|shijiazhuangbei|sjzb|59@sjz|石家庄|SJP|shijiazhuang|sjz|60@sya|沈阳|SYT|shenyang|sy|61@syb|沈阳北|SBT|shenyangbei|syb|62@syd|沈阳东|SDT|shenyangdong|syd|63@syn|沈阳南|SOT|shenyangnan|syn|64@tyb|太原北|TBV|taiyuanbei|tyb|65@tyd|太原东|TDV|taiyuandong|tyd|66@tyu|太原|TYV|taiyuan|ty|67@wha|武汉|WHN|wuhan|wh|68@wjx|王家营西|KNM|wangjiayingxi|wjyx|69@wlq|乌鲁木齐|WAR|wulumuqi|wlmq|70@xab|西安北|EAY|xianbei|xab|71@xan|西安|XAY|xian|xa|72@xan|西安南|CAY|xiannan|xan|73@xni|西宁|XNO|xining|xn|74@ych|银川|YIJ|yinchuan|yc|75@zzh|郑州|ZZF|zhengzhou|zz|76@aes|阿尔山|ART|aershan|aes|77@aka|安康|AKY|ankang|ak|78@aks|阿克苏|ASR|akesu|aks|79@alh|阿里河|AHX|alihe|alh|80@alk|阿拉山口|AKR|alashankou|alsk|81@api|安平|APT|anping|ap|82@aqi|安庆|AQH|anqing|aq|83@ash|安顺|ASW|anshun|as|84@ash|鞍山|AST|anshan|as|85@aya|安阳|AYF|anyang|ay|86@ban|北安|BAB|beian|ba|87@bbu|蚌埠|BBH|bengbu|bb|88@bch|白城|BCT|baicheng|bc|89@bha|北海|BHZ|beihai|bh|90@bhe|白河|BEL|baihe|bh|91@bji|白涧|BAP|baijian|bj|92@bji|宝鸡|BJY|baoji|bj|93@bji|滨江|BJB|binjiang|bj|94@bkt|博克图|BKX|boketu|bkt|95@bse|百色|BIZ|baise|bs|96@bss|白山市|HJL|baishanshi|bss|97@bta|北台|BTT|beitai|bt|98@btd|包头东|BDC|baotoudong|btd|99@bto|包头|BTC|baotou|bt|100@bts|北屯市|BXR|beitunshi|bts|101@bxi|本溪|BXT|benxi|bx|102@byb|白云鄂博|BEC|baiyunebo|byeb|103@byx|白银西|BXJ|baiyinxi|byx|104@bzh|亳州|BZH|bozhou|bz|105@cbi|赤壁|CBN|chibi|cb|106@cde|常德|VGQ|changde|cd|107@cde|承德|CDP|chengde|cd|108@cdi|长甸|CDT|changdian|cd|109@cfe|赤峰|CFD|chifeng|cf|110@cli|茶陵|CDG|chaling|cl|111@cna|苍南|CEH|cangnan|cn|112@cpi|昌平|CPP|changping|cp|113@cre|崇仁|CRG|chongren|cr|114@ctu|昌图|CTT|changtu|ct|115@ctz|长汀镇|CDB|changtingzhen|ctz|116@cxi|曹县|CXK|caoxian|cx|117@cxn|楚雄南|COM|chuxiongnan|cxn|118@cxt|陈相屯|CXT|chenxiangtun|cxt|119@czb|长治北|CBF|changzhibei|czb|120@czh|池州|IYH|chizhou|cz|121@czh|长征|CZJ|changzheng|cz|122@czh|常州|CZH|changzhou|cz|123@czh|郴州|CZQ|chenzhou|cz|124@czh|长治|CZF|changzhi|cz|125@czh|沧州|COP|cangzhou|cz|126@czu|崇左|CZZ|chongzuo|cz|127@dab|大安北|RNT|daanbei|dab|128@dch|大成|DCT|dacheng|dc|129@ddo|丹东|DUT|dandong|dd|130@dfh|东方红|DFB|dongfanghong|dfh|131@dgd|东莞东|DMQ|dongguandong|dgd|132@dhs|大虎山|DHD|dahushan|dhs|133@dhu|敦化|DHL|dunhua|dh|134@dhu|敦煌|DHJ|dunhuang|dh|135@dhu|德惠|DHT|dehui|dh|136@djc|东京城|DJB|dongjingcheng|djc|137@dji|大涧|DFP|dajian|dj|138@djy|都江堰|DDW|dujiangyan|djy|139@dlb|大连北|DFT|dalianbei|dlb|140@dli|大理|DKM|dali|dl|141@dli|大连|DLT|dalian|dl|142@dna|定南|DNG|dingnan|dn|143@dqi|大庆|DZX|daqing|dq|144@dsh|东胜|DOC|dongsheng|ds|145@dsq|大石桥|DQT|dashiqiao|dsq|146@dto|大同|DTV|datong|dt|147@dyi|东营|DPK|dongying|dy|148@dys|大杨树|DUX|dayangshu|dys|149@dyu|都匀|RYW|duyun|dy|150@dzh|邓州|DOF|dengzhou|dz|151@dzh|达州|RXW|dazhou|dz|152@dzh|德州|DZP|dezhou|dz|153@ejn|额济纳|EJC|ejina|ejn|154@eli|二连|RLC|erlian|el|155@esh|恩施|ESN|enshi|es|156@fdi|福鼎|FES|fuding|fd|157@fhc|凤凰机场|FJQ|fenghuangjichang|fhjc|158@fld|风陵渡|FLV|fenglingdu|fld|159@fli|涪陵|FLW|fuling|fl|160@flj|富拉尔基|FRX|fulaerji|flej|161@fsb|抚顺北|FET|fushunbei|fsb|162@fsh|佛山|FSQ|foshan|fs|163@fxn|阜新南|FXD|fuxinnan|fxn|164@fya|阜阳|FYH|fuyang|fy|165@gem|格尔木|GRO|geermu|gem|166@gha|广汉|GHW|guanghan|gh|167@gji|古交|GJV|gujiao|gj|168@glb|桂林北|GBZ|guilinbei|glb|169@gli|古莲|GRX|gulian|gl|170@gli|桂林|GLZ|guilin|gl|171@gsh|固始|GXN|gushi|gs|172@gsh|广水|GSN|guangshui|gs|173@gta|干塘|GNJ|gantang|gt|174@gyu|广元|GYW|guangyuan|gy|175@gzb|广州北|GBQ|guangzhoubei|gzb|176@gzh|赣州|GZG|ganzhou|gz|177@gzl|公主岭|GLT|gongzhuling|gzl|178@gzn|公主岭南|GBT|gongzhulingnan|gzln|179@han|淮安|AUH|huaian|ha|180@hbe|淮北|HRH|huaibei|hb|181@hbe|鹤北|HMB|hebei|hb|182@hbi|淮滨|HVN|huaibin|hb|183@hbi|河边|HBV|hebian|hb|184@hch|潢川|KCN|huangchuan|hc|185@hch|韩城|HCY|hancheng|hc|186@hda|邯郸|HDP|handan|hd|187@hdz|横道河子|HDB|hengdaohezi|hdhz|188@hga|鹤岗|HGB|hegang|hg|189@hgt|皇姑屯|HTT|huanggutun|hgt|190@hgu|红果|HEM|hongguo|hg|191@hhe|黑河|HJB|heihe|hh|192@hhu|怀化|HHQ|huaihua|hh|193@hko|汉口|HKN|hankou|hk|194@hld|葫芦岛|HLD|huludao|hld|195@hle|海拉尔|HRX|hailaer|hle|196@hll|霍林郭勒|HWD|huolinguole|hlgl|197@hlu|海伦|HLB|hailun|hl|198@hma|侯马|HMV|houma|hm|199@hmi|哈密|HMR|hami|hm|200@hna|淮南|HAH|huainan|hn|201@hna|桦南|HNB|huanan|hn|202@hnx|海宁西|EUH|hainingxi|hnx|203@hqi|鹤庆|HQM|heqing|hq|204@hrb|怀柔北|HBP|huairoubei|hrb|205@hro|怀柔|HRP|huairou|hr|206@hsd|黄石东|OSN|huangshidong|hsd|207@hsh|华山|HSY|huashan|hs|208@hsh|黄山|HKH|huangshan|hs|209@hsh|黄石|HSN|huangshi|hs|210@hsh|衡水|HSP|hengshui|hs|211@hya|衡阳|HYQ|hengyang|hy|212@hze|菏泽|HIK|heze|hz|213@hzh|贺州|HXZ|hezhou|hz|214@hzh|汉中|HOY|hanzhong|hz|215@hzh|惠州|HCQ|huizhou|hz|216@jan|吉安|VAG|jian|ja|217@jan|集安|JAL|jian|ja|218@jbc|江边村|JBG|jiangbiancun|jbc|219@jch|晋城|JCF|jincheng|jc|220@jcj|金城江|JJZ|jinchengjiang|jcj|221@jdz|景德镇|JCG|jingdezhen|jdz|222@jfe|嘉峰|JFF|jiafeng|jf|223@jgq|加格达奇|JGX|jiagedaqi|jgdq|224@jgs|井冈山|JGG|jinggangshan|jgs|225@jhe|蛟河|JHL|jiaohe|jh|226@jhn|金华南|RNH|jinhuanan|jhn|227@jhu|金华|JBH|jinhua|jh|228@jji|九江|JJG|jiujiang|jj|229@jli|吉林|JLL|jilin|jl|230@jme|荆门|JMN|jingmen|jm|231@jms|佳木斯|JMB|jiamusi|jms|232@jni|济宁|JIK|jining|jn|233@jnn|集宁南|JAC|jiningnan|jnn|234@jqu|酒泉|JQJ|jiuquan|jq|235@jsh|江山|JUH|jiangshan|js|236@jsh|吉首|JIQ|jishou|js|237@jta|九台|JTL|jiutai|jt|238@jts|镜铁山|JVJ|jingtieshan|jts|239@jxi|鸡西|JXB|jixi|jx|240@jxx|绩溪县|JRH|jixixian|jxx|241@jyg|嘉峪关|JGJ|jiayuguan|jyg|242@jyo|江油|JFW|jiangyou|jy|243@jzb|蓟州北|JKP|jizhoubei|jzb|244@jzh|金州|JZT|jinzhou|jz|245@jzh|锦州|JZD|jinzhou|jz|246@kel|库尔勒|KLR|kuerle|kel|247@kfe|开封|KFF|kaifeng|kf|248@kla|岢岚|KLV|kelan|kl|249@kli|凯里|KLW|kaili|kl|250@ksh|喀什|KSR|kashi|ks|251@ksn|昆山南|KNH|kunshannan|ksn|252@ktu|奎屯|KTR|kuitun|kt|253@kyu|开原|KYT|kaiyuan|ky|254@lan|六安|UAH|luan|la|255@lba|灵宝|LBF|lingbao|lb|256@lcg|芦潮港|UCH|luchaogang|lcg|257@lch|利川|LCN|lichuan|lc|258@lch|隆昌|LCW|longchang|lc|259@lch|陆川|LKZ|luchuan|lc|260@lch|临川|LCG|linchuan|lc|261@lch|潞城|UTP|lucheng|lc|262@lda|鹿道|LDL|ludao|ld|263@ldi|娄底|LDQ|loudi|ld|264@lfe|临汾|LFV|linfen|lf|265@lgz|良各庄|LGP|lianggezhuang|lgz|266@lhe|临河|LHC|linhe|lh|267@lhe|漯河|LON|luohe|lh|268@lhu|绿化|LWJ|lvhua|lh|269@lhu|隆化|UHP|longhua|lh|270@lji|丽江|LHM|lijiang|lj|271@lji|临江|LQL|linjiang|lj|272@lji|龙井|LJL|longjing|lj|273@lli|吕梁|LHV|lvliang|ll|274@lli|醴陵|LLG|liling|ll|275@lln|柳林南|LKV|liulinnan|lln|276@lpi|滦平|UPP|luanping|lp|277@lps|六盘水|UMW|liupanshui|lps|278@lqi|灵丘|LVV|lingqiu|lq|279@lsh|旅顺|LST|lvshun|ls|280@lxi|兰溪|LWH|lanxi|lx|281@lxi|陇西|LXJ|longxi|lx|282@lxi|澧县|LEQ|lixian|lx|283@lxi|临西|UEP|linxi|lx|284@lya|龙岩|LYS|longyan|ly|285@lya|耒阳|LYQ|leiyang|ly|286@lya|洛阳|LYF|luoyang|ly|287@lyd|连云港东|UKH|lianyungangdong|lygd|288@lyd|洛阳东|LDF|luoyangdong|lyd|289@lyi|临沂|LVK|linyi|ly|290@lym|洛阳龙门|LLF|luoyanglongmen|lylm|291@lyu|柳园|DHR|liuyuan|ly|292@lyu|凌源|LYD|lingyuan|ly|293@lyu|辽源|LYL|liaoyuan|ly|294@lzh|立志|LZX|lizhi|lz|295@lzh|柳州|LZZ|liuzhou|lz|296@lzh|辽中|LZD|liaozhong|lz|297@mch|麻城|MCN|macheng|mc|298@mdh|免渡河|MDX|mianduhe|mdh|299@mdj|牡丹江|MDB|mudanjiang|mdj|300@meg|莫尔道嘎|MRX|moerdaoga|medg|301@mgu|明光|MGH|mingguang|mg|302@mgu|满归|MHX|mangui|mg|303@mhe|漠河|MVX|mohe|mh|304@mmi|茂名|MDQ|maoming|mm|305@mmx|茂名西|MMZ|maomingxi|mmx|306@msh|密山|MSB|mishan|ms|307@msj|马三家|MJT|masanjia|msj|308@mwe|麻尾|VAW|mawei|mw|309@mya|绵阳|MYW|mianyang|my|310@mzh|梅州|MOQ|meizhou|mz|311@mzl|满洲里|MLX|manzhouli|mzl|312@nbd|宁波东|NVH|ningbodong|nbd|313@nbo|宁波|NGH|ningbo|nb|314@nch|南岔|NCB|nancha|nc|315@nch|南充|NCW|nanchong|nc|316@nda|南丹|NDZ|nandan|nd|317@ndm|南大庙|NMP|nandamiao|ndm|318@nfe|南芬|NFT|nanfen|nf|319@nhe|讷河|NHX|nehe|nh|320@nji|嫩江|NGX|nenjiang|nj|321@nji|内江|NJW|neijiang|nj|322@npi|南平|NPS|nanping|np|323@nto|南通|NUH|nantong|nt|324@nya|南阳|NFF|nanyang|ny|325@nzs|碾子山|NZX|nianzishan|nzs|326@pds|平顶山|PEN|pingdingshan|pds|327@pji|盘锦|PVD|panjin|pj|328@pli|平凉|PIJ|pingliang|pl|329@pln|平凉南|POJ|pingliangnan|pln|330@pqu|平泉|PQP|pingquan|pq|331@psh|坪石|PSQ|pingshi|ps|332@pxi|萍乡|PXG|pingxiang|px|333@pxi|凭祥|PXZ|pingxiang|px|334@pxx|郫县西|PCW|pixianxi|pxx|335@pzh|攀枝花|PRW|panzhihua|pzh|336@qch|蕲春|QRN|qichun|qc|337@qcs|青城山|QSW|qingchengshan|qcs|338@qda|青岛|QDK|qingdao|qd|339@qhc|清河城|QYP|qinghecheng|qhc|340@qji|曲靖|QJM|qujing|qj|341@qji|黔江|QNW|qianjiang|qj|342@qjz|前进镇|QEB|qianjinzhen|qjz|343@qqe|齐齐哈尔|QHX|qiqihaer|qqhe|344@qth|七台河|QTB|qitaihe|qth|345@qxi|沁县|QVV|qinxian|qx|346@qzd|泉州东|QRS|quanzhoudong|qzd|347@qzh|泉州|QYS|quanzhou|qz|348@qzh|衢州|QEH|quzhou|qz|349@ran|融安|RAZ|rongan|ra|350@rjg|汝箕沟|RQJ|rujigou|rjg|351@rji|瑞金|RJG|ruijin|rj|352@rzh|日照|RZK|rizhao|rz|353@scp|双城堡|SCB|shuangchengpu|scp|354@sfh|绥芬河|SFB|suifenhe|sfh|355@sgd|韶关东|SGQ|shaoguandong|sgd|356@shg|山海关|SHD|shanhaiguan|shg|357@shu|绥化|SHB|suihua|sh|358@sjf|三间房|SFX|sanjianfang|sjf|359@sjt|苏家屯|SXT|sujiatun|sjt|360@sla|舒兰|SLL|shulan|sl|361@smn|神木南|OMY|shenmunan|smn|362@smx|三门峡|SMF|sanmenxia|smx|363@sna|商南|ONY|shangnan|sn|364@sni|遂宁|NIW|suining|sn|365@spi|四平|SPT|siping|sp|366@sqi|商丘|SQF|shangqiu|sq|367@sra|上饶|SRG|shangrao|sr|368@ssh|韶山|SSQ|shaoshan|ss|369@sso|宿松|OAH|susong|ss|370@sto|汕头|OTQ|shantou|st|371@swu|邵武|SWS|shaowu|sw|372@sxi|涉县|OEP|shexian|sx|373@sya|三亚|SEQ|sanya|sy|374@sya|三  亚|JUQ|sanya|sya|375@sya|邵阳|SYQ|shaoyang|sy|376@sya|十堰|SNN|shiyan|sy|377@syq|三元区|SMS|sanyuanqu|syq|378@sys|双鸭山|SSB|shuangyashan|sys|379@syu|松原|VYT|songyuan|sy|380@szh|苏州|SZH|suzhou|sz|381@szh|深圳|SZQ|shenzhen|sz|382@szh|宿州|OXH|suzhou|sz|383@szh|随州|SZN|suizhou|sz|384@szh|朔州|SUV|shuozhou|sz|385@szx|深圳西|OSQ|shenzhenxi|szx|386@tba|塘豹|TBQ|tangbao|tb|387@teq|塔尔气|TVX|taerqi|teq|388@tgu|潼关|TGY|tongguan|tg|389@tgu|塘沽|TGP|tanggu|tg|390@the|塔河|TXX|tahe|th|391@thu|通化|THL|tonghua|th|392@tla|泰来|TLX|tailai|tl|393@tlf|吐鲁番|TFR|tulufan|tlf|394@tli|通辽|TLD|tongliao|tl|395@tli|铁岭|TLT|tieling|tl|396@tlz|陶赖昭|TPT|taolaizhao|tlz|397@tme|图们|TML|tumen|tm|398@tre|铜仁|RDQ|tongren|tr|399@tsb|唐山北|FUP|tangshanbei|tsb|400@tsf|田师府|TFT|tianshifu|tsf|401@tsh|泰山|TAK|taishan|ts|402@tsh|唐山|TSP|tangshan|ts|403@tsh|天水|TSJ|tianshui|ts|404@typ|通远堡|TYT|tongyuanpu|typ|405@tys|太阳升|TQT|taiyangsheng|tys|406@tzh|泰州|UTH|taizhou|tz|407@tzi|桐梓|TZW|tongzi|tz|408@tzx|通州西|TAP|tongzhouxi|tzx|409@wch|五常|WCB|wuchang|wc|410@wch|武昌|WCN|wuchang|wc|411@wfd|瓦房店|WDT|wafangdian|wfd|412@wha|威海|WKK|weihai|wh|413@whu|芜湖|WHH|wuhu|wh|414@whx|乌海西|WXC|wuhaixi|whx|415@wjt|吴家屯|WJT|wujiatun|wjt|416@wln|乌鲁木齐南|WMR|wulumuqinan|wlmqn|417@wlo|武隆|WLW|wulong|wl|418@wlt|乌兰浩特|WWT|wulanhaote|wlht|419@wna|渭南|WNY|weinan|wn|420@wsh|威舍|WSM|weishe|ws|421@wts|歪头山|WIT|waitoushan|wts|422@wwe|武威|WUJ|wuwei|ww|423@wwn|武威南|WWJ|wuweinan|wwn|424@wxi|无锡|WXH|wuxi|wx|425@wxi|乌西|WXR|wuxi|wx|426@wyl|乌伊岭|WPB|wuyiling|wyl|427@wys|武夷山|WAS|wuyishan|wys|428@wyu|万源|WYY|wanyuan|wy|429@wzh|万州|WYW|wanzhou|wz|430@wzh|梧州|WZZ|wuzhou|wz|431@wzh|温州|RZH|wenzhou|wz|432@wzn|温州南|VRH|wenzhounan|wzn|433@xch|西昌|ECW|xichang|xc|434@xch|许昌|XCF|xuchang|xc|435@xcn|西昌南|ENW|xichangnan|xcn|436@xlt|锡林浩特|XTC|xilinhaote|xlht|437@xmb|厦门北|XKS|xiamenbei|xmb|438@xme|厦门|XMS|xiamen|xm|439@xmq|厦门高崎|XBS|xiamengaoqi|xmgq|440@xwe|宣威|XWM|xuanwei|xw|441@xxi|新乡|XXF|xinxiang|xx|442@xya|信阳|XUN|xinyang|xy|443@xya|咸阳|XYY|xianyang|xy|444@xya|襄阳|XFN|xiangyang|xy|445@xyc|熊岳城|XYT|xiongyuecheng|xyc|446@xyu|新余|XUG|xinyu|xy|447@xzh|徐州|XCH|xuzhou|xz|448@yan|延安|YWY|yanan|ya|449@ybi|宜宾|YBW|yibin|yb|450@ybn|亚布力南|YWB|yabulinan|ybln|451@ybs|叶柏寿|YBD|yebaishou|ybs|452@ycd|宜昌东|HAN|yichangdong|ycd|453@ych|永川|YCW|yongchuan|yc|454@ych|盐城|AFH|yancheng|yc|455@ych|宜昌|YCN|yichang|yc|456@ych|运城|YNV|yuncheng|yc|457@ych|伊春|YCB|yichun|yc|458@yci|榆次|YCV|yuci|yc|459@ycu|杨村|YBP|yangcun|yc|460@ycx|宜春西|YCG|yichunxi|ycx|461@yes|伊尔施|YET|yiershi|yes|462@yga|燕岗|YGW|yangang|yg|463@yji|永济|YIV|yongji|yj|464@yji|延吉|YJL|yanji|yj|465@yko|营口|YKT|yingkou|yk|466@yks|牙克石|YKX|yakeshi|yks|467@yli|玉林|YLZ|yulin|yl|468@yli|阎良|YNY|yanliang|yl|469@yli|榆林|ALY|yulin|yl|470@ylw|亚龙湾|TWQ|yalongwan|ylw|471@ymp|一面坡|YPB|yimianpo|ymp|472@yni|伊宁|YMR|yining|yn|473@ypg|阳平关|YAY|yangpingguan|ypg|474@ypi|玉屏|YZW|yuping|yp|475@ypi|原平|YPV|yuanping|yp|476@yqi|延庆|YNP|yanqing|yq|477@yqq|阳泉曲|YYV|yangquanqu|yqq|478@yqu|玉泉|YQB|yuquan|yq|479@yqu|阳泉|AQP|yangquan|yq|480@ysh|营山|NUW|yingshan|ys|481@ysh|玉山|YNG|yushan|ys|482@ysh|燕山|AOP|yanshan|ys|483@ysh|榆树|YRT|yushu|ys|484@yta|鹰潭|YTG|yingtan|yt|485@yta|烟台|YAK|yantai|yt|486@yth|伊图里河|YEX|yitulihe|ytlh|487@ytx|玉田县|ATP|yutianxian|ytx|488@ywu|义乌|YWH|yiwu|yw|489@yxi|阳新|YON|yangxin|yx|490@yxi|义县|YXD|yixian|yx|491@yya|益阳|AEQ|yiyang|yy|492@yya|岳阳|YYQ|yueyang|yy|493@yzh|崖州|YUQ|yazhou|yz|494@yzh|扬州|YLH|yangzhou|yz|495@yzh|永州|AOQ|yongzhou|yz|496@zbo|淄博|ZBK|zibo|zb|497@zcd|镇城底|ZDV|zhenchengdi|zcd|498@zgo|自贡|ZGW|zigong|zg|499@zha|珠海|ZHQ|zhuhai|zh|500@zhb|珠海北|ZIQ|zhuhaibei|zhb|501@zji|湛江|ZJZ|zhanjiang|zj|502@zji|镇江|ZJH|zhenjiang|zj|503@zjj|张家界|DIQ|zhangjiajie|zjj|504@zjk|张家口|ZMP|zhangjiakou|zjk|505@zko|周口|ZKN|zhoukou|zk|506@zlt|扎兰屯|ZTX|zhalantun|zlt|507@zmd|驻马店|ZDN|zhumadian|zmd|508@zqi|肇庆|ZVQ|zhaoqing|zq|509@zsz|周水子|ZIT|zhoushuizi|zsz|510@zto|昭通|ZDW|zhaotong|zt|511@zwe|中卫|ZWJ|zhongwei|zw|512@zya|资阳|ZYW|ziyang|zy|513@zyx|遵义西|ZIW|zunyixi|zyx|514@zzh|枣庄|ZEK|zaozhuang|zz|515@zzh|资中|ZZW|zizhong|zz|516@zzh|株洲|ZZQ|zhuzhou|zz|517@zzx|枣庄西|ZFK|zaozhuangxi|zzx|518@aax|昂昂溪|AAX|angangxi|aax|519@ach|阿城|ACB|acheng|ac|520@ada|安达|ADX|anda|ad|521@ade|安德|ARW|ande|ad|522@adi|安定|ADP|anding|ad|523@adu|安多|ADO|anduo|ad|524@agu|安广|AGT|anguang|ag|525@aha|敖汉|YED|aohan|ah|526@ahe|艾河|AHP|aihe|ah|527@ahu|安化|PKQ|anhua|ah|528@ajc|艾家村|AJJ|aijiacun|ajc|529@aji|安家|AJB|anjia|aj|530@aji|阿金|AJD|ajin|aj|531@aji|安靖|PYW|anjing|aj|532@akt|阿克陶|AER|aketao|akt|533@aky|安口窑|AYY|ankouyao|aky|534@alg|敖力布告|ALD|aolibugao|albg|535@alo|安龙|AUZ|anlong|al|536@als|阿龙山|ASX|alongshan|als|537@alu|安陆|ALN|anlu|al|538@ame|阿木尔|JTX|amuer|ame|539@anz|阿南庄|AZM|ananzhuang|anz|540@aqx|安庆西|APH|anqingxi|aqx|541@asx|鞍山西|AXT|anshanxi|asx|542@ata|安塘|ATV|antang|at|543@atb|安亭北|ASH|antingbei|atb|544@ats|阿图什|ATR|atushi|ats|545@atu|安图|ATL|antu|at|546@axi|安溪|AXS|anxi|ax|547@bao|博鳌|BWQ|boao|ba|548@bbe|北碚|BPW|beibei|bb|549@bbg|白壁关|BGV|baibiguan|bbg|550@bbn|蚌埠南|BMH|bengbunan|bbn|551@bch|巴楚|BCR|bachu|bc|552@bch|板城|BUP|bancheng|bc|553@bdh|北戴河|BEP|beidaihe|bdh|554@bdi|保定|BDP|baoding|bd|555@bdi|宝坻|BPP|baodi|bd|556@bdl|八达岭|ILP|badaling|bdl|557@bdo|巴东|BNN|badong|bd|558@bfe|宝丰|BFF|baofeng|bf|559@bgu|柏果|BGM|baiguo|bg|560@bha|布海|BUT|buhai|bh|561@bhd|白河东|BIY|baihedong|bhd|562@bhs|宝华山|BWH|baohuashan|bhs|563@bhx|白河县|BEY|baihexian|bhx|564@bjg|白芨沟|BJJ|baijigou|bjg|565@bjg|碧鸡关|BJM|bijiguan|bjg|566@bji|北滘|IBQ|beijiao|bj|567@bji|碧江|BLQ|bijiang|bj|568@bjp|白鸡坡|BBM|baijipo|bjp|569@bjs|笔架山|BSB|bijiashan|bjs|570@bjt|八角台|BTD|bajiaotai|bjt|571@bka|保康|BKD|baokang|bk|572@bkp|白奎堡|BKB|baikuipu|bkp|573@bla|白狼|BAT|bailang|bl|574@bla|百浪|BRZ|bailang|bl|575@ble|博乐|BOR|bole|bl|576@bli|巴林|BLX|balin|bl|577@bli|宝林|BNB|baolin|bl|578@bli|北流|BOZ|beiliu|bl|579@bli|勃利|BLB|boli|bl|580@blk|布列开|BLR|buliekai|blk|581@bls|宝龙山|BND|baolongshan|bls|582@blx|百里峡|AAP|bailixia|blx|583@bmc|八面城|BMD|bamiancheng|bmc|584@bmq|班猫箐|BNM|banmaoqing|bmq|585@bmt|八面通|BMB|bamiantong|bmt|586@bmz|北马圈子|BRP|beimaquanzi|bmqz|587@bpn|北票南|RPD|beipiaonan|bpn|588@bqi|白旗|BQP|baiqi|bq|589@bql|宝泉岭|BQB|baoquanling|bql|590@bqu|白泉|BQL|baiquan|bq|591@bsh|巴山|BAY|bashan|bs|592@bsj|白水江|BSY|baishuijiang|bsj|593@bsp|白沙坡|BPM|baishapo|bsp|594@bss|白石山|BAL|baishishan|bss|595@bsz|白水镇|BUM|baishuizhen|bsz|596@btd|包头 东|FDC|baotoudong|btd|597@bti|坂田|BTQ|bantian|bt|598@bto|泊头|BZP|botou|bt|599@btu|北屯|BYP|beitun|bt|600@bxh|本溪湖|BHT|benxihu|bxh|601@bxi|博兴|BXK|boxing|bx|602@bxt|八仙筒|VXD|baxiantong|bxt|603@byg|白音察干|BYC|baiyinchagan|bycg|604@byh|背荫河|BYB|beiyinhe|byh|605@byi|北营|BIV|beiying|by|606@byl|巴彦高勒|BAC|bayangaole|bygl|607@byl|白音他拉|BID|baiyintala|bytl|608@byq|鲅鱼圈|BYT|bayuquan|byq|609@bys|白银市|BNJ|baiyinshi|bys|610@bys|白音胡硕|BCD|baiyinhushuo|byhs|611@bzh|巴中|IEW|bazhong|bz|612@bzh|霸州|RMP|bazhou|bz|613@bzh|北宅|BVP|beizhai|bz|614@cbb|赤壁北|CIN|chibibei|cbb|615@cbg|查布嘎|CBC|chabuga|cbg|616@cch|长城|CEJ|changcheng|cc|617@cch|长冲|CCM|changchong|cc|618@cdd|承德东|CCP|chengdedong|cdd|619@cfx|赤峰西|CID|chifengxi|cfx|620@cga|嵯岗|CAX|cuogang|cg|621@cga|柴岗|CGT|chaigang|cg|622@cge|长葛|CEF|changge|cg|623@cgp|柴沟堡|CGV|chaigoupu|cgp|624@cgu|城固|CGY|chenggu|cg|625@cgy|陈官营|CAJ|chenguanying|cgy|626@cgz|成高子|CZB|chenggaozi|cgz|627@cha|草海|WBW|caohai|ch|628@che|柴河|CHB|chaihe|ch|629@che|册亨|CHZ|ceheng|ch|630@chk|草河口|CKT|caohekou|chk|631@chk|崔黄口|CHP|cuihuangkou|chk|632@chu|巢湖|CIH|chaohu|ch|633@cjg|蔡家沟|CJT|caijiagou|cjg|634@cjh|成吉思汗|CJX|chengjisihan|cjsh|635@cji|岔江|CAM|chajiang|cj|636@cjp|蔡家坡|CJY|caijiapo|cjp|637@cle|昌乐|CLK|changle|cl|638@clg|超梁沟|CYP|chaolianggou|clg|639@cli|慈利|CUQ|cili|cl|640@cli|昌黎|CLP|changli|cl|641@clz|长岭子|CLT|changlingzi|clz|642@cmi|晨明|CMB|chenming|cm|643@cno|长农|CNJ|changnong|cn|644@cpb|昌平北|VBP|changpingbei|cpb|645@cpi|常平|DAQ|changping|cp|646@cpl|长坡岭|CPM|changpoling|cpl|647@cqi|辰清|CQB|chenqing|cq|648@csh|蔡山|CON|caishan|cs|649@csh|楚山|CSB|chushan|cs|650@csh|长寿|EFW|changshou|cs|651@csh|磁山|CSP|cishan|cs|652@csh|苍石|CST|cangshi|cs|653@csh|草市|CSL|caoshi|cs|654@csq|察素齐|CSC|chasuqi|csq|655@cst|长山屯|CVT|changshantun|cst|656@cti|长汀|CES|changting|ct|657@ctn|朝天南|CTY|chaotiannan|ctn|658@ctx|昌图西|CPT|changtuxi|ctx|659@cwa|春湾|CQQ|chunwan|cw|660@cxi|磁县|CIP|cixian|cx|661@cxi|岑溪|CNZ|cenxi|cx|662@cxi|辰溪|CXQ|chenxi|cx|663@cxi|磁西|CRP|cixi|cx|664@cxn|长兴南|CFH|changxingnan|cxn|665@cya|磁窑|CYK|ciyao|cy|666@cya|春阳|CAL|chunyang|cy|667@cya|城阳|CEK|chengyang|cy|668@cyc|创业村|CEX|chuangyecun|cyc|669@cyc|朝阳川|CYL|chaoyangchuan|cyc|670@cyd|朝阳地|CDD|chaoyangdi|cyd|671@cyn|朝阳南|CYD|chaoyangnan|cyn|672@cyu|长垣|CYF|changyuan|cy|673@cyz|朝阳镇|CZL|chaoyangzhen|cyz|674@czb|滁州北|CUH|chuzhoubei|czb|675@czb|常州北|ESH|changzhoubei|czb|676@czh|滁州|CXH|chuzhou|cz|677@czh|潮州|CKQ|chaozhou|cz|678@czh|常庄|CVK|changzhuang|cz|679@czl|曹子里|CFP|caozili|czl|680@czw|车转湾|CWM|chezhuanwan|czw|681@czx|郴州西|ICQ|chenzhouxi|czx|682@czx|沧州西|CBP|cangzhouxi|czx|683@dan|德安|DAG|dean|da|684@dan|大安|RAT|daan|da|685@dba|大坝|DBJ|daba|db|686@dba|大板|DBC|daban|db|687@dba|大巴|DBD|daba|db|688@dba|电白|NWQ|dianbai|db|689@dba|到保|RBT|daobao|db|690@dbc|达坂城|DCR|dabancheng|dbc|691@dbi|定边|DYJ|dingbian|db|692@dbj|东边井|DBB|dongbianjing|dbj|693@dbs|德伯斯|RDT|debosi|dbs|694@dcg|打柴沟|DGJ|dachaigou|dcg|695@dch|德昌|DVW|dechang|dc|696@dda|滴道|DDB|didao|dd|697@ddg|大磴沟|DKJ|dadenggou|ddg|698@ded|刀尔登|DRD|daoerdeng|ded|699@dee|得耳布尔|DRX|deerbuer|debe|700@det|杜尔伯特|TKX|duerbote|debt|701@dfa|东方|UFQ|dongfang|df|702@dfe|丹凤|DGY|danfeng|df|703@dfe|东丰|DIL|dongfeng|df|704@dge|都格|DMM|duge|dg|705@dgt|大官屯|DTT|daguantun|dgt|706@dgu|大关|RGW|daguan|dg|707@dgu|东光|DGP|dongguang|dg|708@dha|东海|DHB|donghai|dh|709@dhc|大灰厂|DHP|dahuichang|dhc|710@dhq|大红旗|DQD|dahongqi|dhq|711@dht|大禾塘|SOQ|shaodong|dh|712@dhx|德惠西|DXT|dehuixi|dhx|713@dhx|东海县|DQH|donghaixian|dhx|714@djg|达家沟|DJT|dajiagou|djg|715@dji|东津|DKB|dongjin|dj|716@dji|杜家|DJL|dujia|dj|717@dkt|大口屯|DKP|dakoutun|dkt|718@dla|东来|RVD|donglai|dl|719@dlh|德令哈|DHO|delingha|dlh|720@dli|带岭|DLB|dailing|dl|721@dli|大林|DLD|dalin|dl|722@dlq|达拉特旗|DIC|dalateqi|dltq|723@dlt|独立屯|DTX|dulitun|dlt|724@dlu|豆罗|DLV|douluo|dl|725@dlx|达拉特西|DNC|dalatexi|dltx|726@dlx|大连西|GZT|dalianxi|dlx|727@dmc|东明村|DMD|dongmingcun|dmc|728@dmh|洞庙河|DEP|dongmiaohe|dmh|729@dmx|东明县|DNF|dongmingxian|dmx|730@dni|大拟|DNZ|dani|dn|731@dpf|大平房|DPD|dapingfang|dpf|732@dps|大盘石|RPP|dapanshi|dps|733@dpu|大埔|DPI|dapu|dp|734@dpu|大堡|DVT|dapu|dp|735@dqd|大庆东|LFX|daqingdong|dqd|736@dqh|大其拉哈|DQX|daqilaha|dqlh|737@dqi|道清|DML|daoqing|dq|738@dqs|对青山|DQB|duiqingshan|dqs|739@dqx|德清西|MOH|deqingxi|dqx|740@dqx|大庆西|RHX|daqingxi|dqx|741@dsh|东升|DRQ|dongsheng|ds|742@dsh|砀山|DKH|dangshan|ds|743@dsh|独山|RWW|dushan|ds|744@dsh|登沙河|DWT|dengshahe|dsh|745@dsp|读书铺|DPM|dushupu|dsp|746@dst|大石头|DSL|dashitou|dst|747@dsx|东胜西|DYC|dongshengxi|dsx|748@dsz|大石寨|RZT|dashizhai|dsz|749@dta|东台|DBH|dongtai|dt|750@dta|定陶|DQK|dingtao|dt|751@dta|灯塔|DGT|dengta|dt|752@dtb|大田边|DBM|datianbian|dtb|753@dth|东通化|DTL|dongtonghua|dth|754@dtu|丹徒|RUH|dantu|dt|755@dtu|大屯|DNT|datun|dt|756@dwa|东湾|DRJ|dongwan|dw|757@dwk|大武口|DFJ|dawukou|dwk|758@dwp|低窝铺|DWJ|diwopu|dwp|759@dwt|大王滩|DZZ|dawangtan|dwt|760@dwz|大湾子|DFM|dawanzi|dwz|761@dxg|大兴沟|DXL|daxinggou|dxg|762@dxi|大兴|DXX|daxing|dx|763@dxi|定西|DSJ|dingxi|dx|764@dxi|甸心|DXM|dianxin|dx|765@dxi|东乡|DXG|dongxiang|dx|766@dxi|代县|DKV|daixian|dx|767@dxi|定襄|DXV|dingxiang|dx|768@dxu|东戌|RXP|dongxu|dx|769@dxz|东辛庄|DXD|dongxinzhuang|dxz|770@dya|丹阳|DYH|danyang|dy|771@dya|德阳|DYW|deyang|dy|772@dya|大雁|DYX|dayan|dy|773@dya|当阳|DYN|dangyang|dy|774@dyb|丹阳北|EXH|danyangbei|dyb|775@dyd|大英东|IAW|dayingdong|dyd|776@dyd|东淤地|DBV|dongyudi|dyd|777@dyi|大营|DYV|daying|dy|778@dyu|定远|EWH|dingyuan|dy|779@dyu|岱岳|RYV|daiyue|dy|780@dyu|大元|DYZ|dayuan|dy|781@dyz|大营镇|DJP|dayingzhen|dyz|782@dyz|大营子|DZD|dayingzi|dyz|783@dzc|大战场|DTJ|dazhanchang|dzc|784@dzd|德州东|DIP|dezhoudong|dzd|785@dzh|东至|DCH|dongzhi|dz|786@dzh|低庄|DVQ|dizhuang|dz|787@dzh|东镇|DNV|dongzhen|dz|788@dzh|道州|DFZ|daozhou|dz|789@dzh|东庄|DZV|dongzhuang|dz|790@dzh|兑镇|DWV|duizhen|dz|791@dzh|豆庄|ROP|douzhuang|dz|792@dzh|定州|DXP|dingzhou|dz|793@dzy|大竹园|DZY|dazhuyuan|dzy|794@dzz|大杖子|DAP|dazhangzi|dzz|795@dzz|豆张庄|RZP|douzhangzhuang|dzz|796@ebi|峨边|EBW|ebian|eb|797@edm|二道沟门|RDP|erdaogoumen|edgm|798@edw|二道湾|RDX|erdaowan|edw|799@ees|鄂尔多斯|EEC|eerduosi|eeds|800@elo|二龙|RLD|erlong|el|801@elt|二龙山屯|ELA|erlongshantun|elst|802@eme|峨眉|EMW|emei|em|803@emh|二密河|RML|ermihe|emh|804@epi|恩平|PXQ|enping|ep|805@eyi|二营|RYJ|erying|ey|806@ezh|鄂州|ECN|ezhou|ez|807@fan|福安|FAS|fuan|fa|808@fch|丰城|FCG|fengcheng|fc|809@fcn|丰城南|FNG|fengchengnan|fcn|810@fdo|肥东|FIH|feidong|fd|811@fer|发耳|FEM|faer|fe|812@fha|富海|FHX|fuhai|fh|813@fha|福海|FHR|fuhai|fh|814@fhc|凤凰城|FHT|fenghuangcheng|fhc|815@fhe|汾河|FEV|fenhe|fh|816@fhu|奉化|FHH|fenghua|fh|817@fji|富锦|FIB|fujin|fj|818@fjt|范家屯|FTT|fanjiatun|fjt|819@flq|福利区|FLJ|fuliqu|flq|820@flt|福利屯|FTB|fulitun|flt|821@flz|丰乐镇|FZB|fenglezhen|flz|822@fna|阜南|FNH|funan|fn|823@fni|阜宁|AKH|funing|fn|824@fni|抚宁|FNP|funing|fn|825@fqi|福清|FQS|fuqing|fq|826@fqu|福泉|VMW|fuquan|fq|827@fsc|丰水村|FSJ|fengshuicun|fsc|828@fsh|丰顺|FUQ|fengshun|fs|829@fsh|繁峙|FSV|fanshi|fs|830@fsh|抚顺|FST|fushun|fs|831@fsk|福山口|FKP|fushankou|fsk|832@fsu|扶绥|FSZ|fusui|fs|833@ftu|冯屯|FTX|fengtun|ft|834@fty|浮图峪|FYP|futuyu|fty|835@fxd|富县东|FDY|fuxiandong|fxd|836@fxi|凤县|FXY|fengxian|fx|837@fxi|富县|FEY|fuxian|fx|838@fxi|费县|FXK|feixian|fx|839@fya|凤阳|FUH|fengyang|fy|840@fya|汾阳|FAV|fenyang|fy|841@fyb|扶余北|FBT|fuyubei|fyb|842@fyi|分宜|FYG|fenyi|fy|843@fyu|富源|FYM|fuyuan|fy|844@fyu|扶余|FYT|fuyu|fy|845@fyu|富裕|FYX|fuyu|fy|846@fzb|抚州北|FBG|fuzhoubei|fzb|847@fzh|凤州|FZY|fengzhou|fz|848@fzh|丰镇|FZC|fengzhen|fz|849@fzh|范镇|VZK|fanzhen|fz|850@gan|固安|GFP|guan|ga|851@gan|广安|VJW|guangan|ga|852@gbd|高碑店|GBP|gaobeidian|gbd|853@gbz|沟帮子|GBD|goubangzi|gbz|854@gcd|甘草店|GDJ|gancaodian|gcd|855@gch|谷城|GCN|gucheng|gc|856@gch|藁城|GEP|gaocheng|gc|857@gcu|高村|GCV|gaocun|gc|858@gcz|古城镇|GZB|guchengzhen|gcz|859@gde|广德|GRH|guangde|gd|860@gdi|贵定|GTW|guiding|gd|861@gdn|贵定南|IDW|guidingnan|gdn|862@gdo|古东|GDV|gudong|gd|863@gga|贵港|GGZ|guigang|gg|864@gga|官高|GVP|guangao|gg|865@ggm|葛根庙|GGT|gegenmiao|ggm|866@ggo|干沟|GGL|gangou|gg|867@ggu|甘谷|GGJ|gangu|gg|868@ggz|高各庄|GGP|gaogezhuang|ggz|869@ghe|甘河|GAX|ganhe|gh|870@ghe|根河|GEX|genhe|gh|871@gjd|郭家店|GDT|guojiadian|gjd|872@gjz|孤家子|GKT|gujiazi|gjz|873@gla|古浪|GLJ|gulang|gl|874@gla|皋兰|GEJ|gaolan|gl|875@glf|高楼房|GFM|gaoloufang|glf|876@glh|归流河|GHT|guiliuhe|glh|877@gli|关林|GLF|guanlin|gl|878@glu|甘洛|VOW|ganluo|gl|879@glz|郭磊庄|GLP|guoleizhuang|glz|880@gmi|高密|GMK|gaomi|gm|881@gmz|公庙子|GMC|gongmiaozi|gmz|882@gnh|工农湖|GRT|gongnonghu|gnh|883@gnn|广宁寺南|GNT|guangningsinan|gnn|884@gnw|广南卫|GNM|guangnanwei|gnw|885@gpi|高平|GPF|gaoping|gp|886@gqb|甘泉北|GEY|ganquanbei|gqb|887@gqc|共青城|GAG|gongqingcheng|gqc|888@gqk|甘旗卡|GQD|ganqika|gqk|889@gqu|甘泉|GQY|ganquan|gq|890@gqz|高桥镇|GZD|gaoqiaozhen|gqz|891@gsh|灌水|GST|guanshui|gs|892@gsh|赶水|GSW|ganshui|gs|893@gsk|孤山口|GSP|gushankou|gsk|894@gso|果松|GSL|guosong|gs|895@gsz|高山子|GSD|gaoshanzi|gsz|896@gsz|嘎什甸子|GXD|gashidianzi|gsdz|897@gta|高台|GTJ|gaotai|gt|898@gta|高滩|GAY|gaotan|gt|899@gti|古田|GTS|gutian|gt|900@gti|官厅|GTP|guanting|gt|901@gtx|官厅西|KEP|guantingxi|gtx|902@gxi|贵溪|GXG|guixi|gx|903@gya|涡阳|GYH|guoyang|gy|904@gyi|巩义|GXF|gongyi|gy|905@gyi|高邑|GIP|gaoyi|gy|906@gyn|巩义南|GYF|gongyinan|gyn|907@gyn|广元南|GAW|guangyuannan|gyn|908@gyu|固原|GUJ|guyuan|gy|909@gyu|菇园|GYL|guyuan|gy|910@gyz|公营子|GYD|gongyingzi|gyz|911@gze|光泽|GZS|guangze|gz|912@gzh|古镇|GNQ|guzhen|gz|913@gzh|固镇|GEH|guzhen|gz|914@gzh|虢镇|GZY|guozhen|gz|915@gzh|瓜州|GZJ|guazhou|gz|916@gzh|高州|GSQ|gaozhou|gz|917@gzh|盖州|GXT|gaizhou|gz|918@gzj|官字井|GOT|guanzijing|gzj|919@gzs|冠豸山|GSS|guanzhaishan|gzs|920@gzx|盖州西|GAT|gaizhouxi|gzx|921@han|海安|HIH|haian|ha|922@han|淮安南|AMH|huaiannan|han|923@han|红安|HWN|hongan|ha|924@hax|红安西|VXN|honganxi|hax|925@hba|黄柏|HBL|huangbai|hb|926@hbe|海北|HEB|haibei|hb|927@hbi|鹤壁|HAF|hebi|hb|928@hcb|会昌北|XEG|huichangbei|hcb|929@hch|汉川|HCN|hanchuan|hc|930@hch|华城|VCQ|huacheng|hc|931@hch|河唇|HCZ|hechun|hc|932@hch|海城|HCT|haicheng|hc|933@hch|合川|WKW|hechuan|hc|934@hct|黑冲滩|HCJ|heichongtan|hct|935@hcu|黄村|HCP|huangcun|hc|936@hcx|海城西|HXT|haichengxi|hcx|937@hde|化德|HGC|huade|hd|938@hdo|洪洞|HDV|hongtong|hd|939@hes|霍尔果斯|HFR|huoerguosi|hegs|940@hfe|横峰|HFG|hengfeng|hf|941@hfw|韩府湾|HXJ|hanfuwan|hfw|942@hgu|汉沽|HGP|hangu|hg|943@hgy|黄瓜园|HYM|huangguayuan|hgy|944@hgz|红光镇|IGW|hongguangzhen|hgz|945@hhe|浑河|HHT|hunhe|hh|946@hhg|红花沟|VHD|honghuagou|hhg|947@hht|黄花筒|HUD|huanghuatong|hht|948@hjd|贺家店|HJJ|hejiadian|hjd|949@hji|和静|HJR|hejing|hj|950@hji|红江|HFM|hongjiang|hj|951@hji|黑井|HIM|heijing|hj|952@hji|获嘉|HJF|huojia|hj|953@hji|河津|HJV|hejin|hj|954@hji|涵江|HJS|hanjiang|hj|955@hji|华家|HJT|huajia|hj|956@hjq|杭锦后旗|HDC|hangjinhouqi|hjhq|957@hjx|河间西|HXP|hejianxi|hjx|958@hjz|花家庄|HJM|huajiazhuang|hjz|959@hkn|河口南|HKJ|hekounan|hkn|960@hko|湖口|HKG|hukou|hk|961@hko|黄口|KOH|huangkou|hk|962@hla|呼兰|HUB|hulan|hl|963@hlb|葫芦岛北|HPD|huludaobei|hldb|964@hlh|浩良河|HHB|haolianghe|hlh|965@hlh|哈拉海|HIT|halahai|hlh|966@hli|鹤立|HOB|heli|hl|967@hli|桦林|HIB|hualin|hl|968@hli|黄陵|ULY|huangling|hl|969@hli|海林|HRB|hailin|hl|970@hli|虎林|VLB|hulin|hl|971@hli|寒岭|HAT|hanling|hl|972@hlo|和龙|HLL|helong|hl|973@hlo|海龙|HIL|hailong|hl|974@hls|哈拉苏|HAX|halasu|hls|975@hlt|呼鲁斯太|VTJ|hulusitai|hlst|976@hlz|火连寨|HLT|huolianzhai|hlz|977@hme|黄梅|VEH|huangmei|hm|978@hmy|韩麻营|HYP|hanmaying|hmy|979@hnh|黄泥河|HHL|huangnihe|hnh|980@hni|海宁|HNH|haining|hn|981@hno|惠农|HMJ|huinong|hn|982@hpi|和平|VAQ|heping|hp|983@hpz|花棚子|HZM|huapengzi|hpz|984@hqi|花桥|VQH|huaqiao|hq|985@hqi|宏庆|HEY|hongqing|hq|986@hre|怀仁|HRV|huairen|hr|987@hro|华容|HRN|huarong|hr|988@hsb|华山北|HDY|huashanbei|hsb|989@hsd|黄松甸|HDL|huangsongdian|hsd|990@hsg|和什托洛盖|VSR|heshituoluogai|hstlg|991@hsh|红山|VSB|hongshan|hs|992@hsh|汉寿|VSQ|hanshou|hs|993@hsh|衡山|HSQ|hengshan|hs|994@hsh|黑水|HOT|heishui|hs|995@hsh|惠山|VCH|huishan|hs|996@hsh|虎什哈|HHP|hushiha|hsh|997@hsp|红寺堡|HSJ|hongsipu|hsp|998@hst|虎石台|HUT|hushitai|hst|999@hsw|海石湾|HSO|haishiwan|hsw|1000@hsx|衡山西|HEQ|hengshanxi|hsx|1001@hsx|红砂岘|VSJ|hongshaxian|hsx|1002@hta|黑台|HQB|heitai|ht|1003@hta|桓台|VTK|huantai|ht|1004@hti|和田|VTR|hetian|ht|1005@hto|会同|VTQ|huitong|ht|1006@htz|海坨子|HZT|haituozi|htz|1007@hwa|黑旺|HWK|heiwang|hw|1008@hwa|海湾|RWH|haiwan|hw|1009@hxi|红星|VXB|hongxing|hx|1010@hxi|徽县|HYY|huixian|hx|1011@hxl|红兴隆|VHB|hongxinglong|hxl|1012@hxt|换新天|VTB|huanxintian|hxt|1013@hxt|红岘台|HTJ|hongxiantai|hxt|1014@hya|红彦|VIX|hongyan|hy|1015@hya|海晏|HFO|haiyan|hy|1016@hya|合阳|HAY|heyang|hy|1017@hyd|衡阳东|HVQ|hengyangdong|hyd|1018@hyi|华蓥|HUW|huaying|hy|1019@hyi|汉阴|HQY|hanyin|hy|1020@hyt|黄羊滩|HGJ|huangyangtan|hyt|1021@hyu|汉源|WHW|hanyuan|hy|1022@hyu|河源|VIQ|heyuan|hy|1023@hyu|花园|HUN|huayuan|hy|1024@hyu|湟源|HNO|huangyuan|hy|1025@hyz|黄羊镇|HYJ|huangyangzhen|hyz|1026@hzh|湖州|VZH|huzhou|hz|1027@hzh|化州|HZZ|huazhou|hz|1028@hzh|黄州|VON|huangzhou|hz|1029@hzh|霍州|HZV|huozhou|hz|1030@hzx|惠州西|VXQ|huizhouxi|hzx|1031@jba|巨宝|JRT|jubao|jb|1032@jbi|靖边|JIY|jingbian|jb|1033@jbt|金宝屯|JBD|jinbaotun|jbt|1034@jcb|晋城北|JEF|jinchengbei|jcb|1035@jch|金昌|JCJ|jinchang|jc|1036@jch|鄄城|JCK|juancheng|jc|1037@jch|交城|JNV|jiaocheng|jc|1038@jch|建昌|JFD|jianchang|jc|1039@jde|峻德|JDB|junde|jd|1040@jdi|井店|JFP|jingdian|jd|1041@jdo|鸡东|JOB|jidong|jd|1042@jdu|江都|UDH|jiangdu|jd|1043@jgs|鸡冠山|JST|jiguanshan|jgs|1044@jgt|金沟屯|VGP|jingoutun|jgt|1045@jha|静海|JHP|jinghai|jh|1046@jhe|金河|JHX|jinhe|jh|1047@jhe|锦河|JHB|jinhe|jh|1048@jhe|精河|JHR|jinghe|jh|1049@jhn|精河南|JIR|jinghenan|jhn|1050@jhu|江华|JHZ|jianghua|jh|1051@jhu|建湖|AJH|jianhu|jh|1052@jjg|纪家沟|VJD|jijiagou|jjg|1053@jji|晋江|JJS|jinjiang|jj|1054@jji|锦界|JEY|jinjie|jj|1055@jji|姜家|JJB|jiangjia|jj|1056@jji|江津|JJW|jiangjin|jj|1057@jke|金坑|JKT|jinkeng|jk|1058@jli|芨岭|JLJ|jiling|jl|1059@jmc|金马村|JMM|jinmacun|jmc|1060@jmd|江门东|JWQ|jiangmendong|jmd|1061@jme|角美|JES|jiaomei|jm|1062@jna|莒南|JOK|junan|jn|1063@jna|井南|JNP|jingnan|jn|1064@jou|建瓯|JVS|jianou|jo|1065@jpe|经棚|JPC|jingpeng|jp|1066@jqi|江桥|JQX|jiangqiao|jq|1067@jsa|九三|SSX|jiusan|js|1068@jsb|金山北|EGH|jinshanbei|jsb|1069@jsh|建始|JRN|jianshi|js|1070@jsh|嘉善|JSH|jiashan|js|1071@jsh|京山|JCN|jingshan|js|1072@jsh|稷山|JVV|jishan|js|1073@jsh|吉舒|JSL|jishu|js|1074@jsh|建设|JET|jianshe|js|1075@jsh|甲山|JOP|jiashan|js|1076@jsj|建三江|JIB|jiansanjiang|jsj|1077@jsn|嘉善南|EAH|jiashannan|jsn|1078@jst|金山屯|JTB|jinshantun|jst|1079@jst|江所田|JOM|jiangsuotian|jst|1080@jta|景泰|JTJ|jingtai|jt|1081@jtn|九台南|JNL|jiutainan|jtn|1082@jwe|吉文|JWX|jiwen|jw|1083@jxi|进贤|JUG|jinxian|jx|1084@jxi|莒县|JKK|juxian|jx|1085@jxi|嘉祥|JUK|jiaxiang|jx|1086@jxi|介休|JXV|jiexiu|jx|1087@jxi|嘉兴|JXH|jiaxing|jx|1088@jxi|井陉|JJP|jingxing|jx|1089@jxn|嘉兴南|EPH|jiaxingnan|jxn|1090@jxz|夹心子|JXT|jiaxinzi|jxz|1091@jya|简阳|JYW|jianyang|jy|1092@jya|揭阳|JRQ|jieyang|jy|1093@jya|姜堰|UEH|jiangyan|jy|1094@jya|建阳|JYS|jianyang|jy|1095@jye|巨野|JYK|juye|jy|1096@jyo|江永|JYZ|jiangyong|jy|1097@jyu|缙云|JYH|jinyun|jy|1098@jyu|靖远|JYJ|jingyuan|jy|1099@jyu|江源|SZL|jiangyuan|jy|1100@jyu|济源|JYF|jiyuan|jy|1101@jyx|靖远西|JXJ|jingyuanxi|jyx|1102@jzb|胶州北|JZK|jiaozhoubei|jzb|1103@jzd|焦作东|WEF|jiaozuodong|jzd|1104@jzh|金寨|JZH|jinzhai|jz|1105@jzh|荆州|JBN|jingzhou|jz|1106@jzh|蓟州|JIP|jizhou|jz|1107@jzh|靖州|JEQ|jingzhou|jz|1108@jzh|胶州|JXK|jiaozhou|jz|1109@jzh|晋州|JXP|jinzhou|jz|1110@jzn|锦州南|JOD|jinzhounan|jzn|1111@jzu|焦作|JOF|jiaozuo|jz|1112@jzw|旧庄窝|JVP|jiuzhuangwo|jzw|1113@jzz|金杖子|JYD|jinzhangzi|jzz|1114@kan|开安|KAT|kaian|ka|1115@kch|库车|KCR|kuche|kc|1116@kch|康城|KCP|kangcheng|kc|1117@kde|库都尔|KDX|kuduer|kde|1118@kdi|宽甸|KDT|kuandian|kd|1119@kdo|克东|KOB|kedong|kd|1120@kdz|昆都仑召|KDC|kundulunzhao|kdlz|1121@kji|开江|KAW|kaijiang|kj|1122@kjj|康金井|KJB|kangjinjing|kjj|1123@klq|喀喇其|KQX|kalaqi|klq|1124@klu|开鲁|KLC|kailu|kl|1125@kly|克拉玛依|KHR|kelamayi|klmy|1126@kpn|开平南|PVQ|kaipingnan|kpn|1127@kqi|口前|KQL|kouqian|kq|1128@ksh|昆山|KSH|kunshan|ks|1129@ksh|奎山|KAB|kuishan|ks|1130@ksh|克山|KSB|keshan|ks|1131@kxl|康熙岭|KXZ|kangxiling|kxl|1132@kya|昆阳|KAM|kunyang|ky|1133@kyh|克一河|KHX|keyihe|kyh|1134@kyx|开原西|KXT|kaiyuanxi|kyx|1135@kzh|康庄|KZP|kangzhuang|kz|1136@lbi|来宾|UBZ|laibin|lb|1137@lbi|老边|LLT|laobian|lb|1138@lbx|灵宝西|LPF|lingbaoxi|lbx|1139@lch|龙川|LUQ|longchuan|lc|1140@lch|乐昌|LCQ|lechang|lc|1141@lch|黎城|UCP|licheng|lc|1142@lch|聊城|UCK|liaocheng|lc|1143@lcu|蓝村|LCK|lancun|lc|1144@lda|两当|LDY|liangdang|ld|1145@ldo|林东|LRC|lindong|ld|1146@ldu|乐都|LDO|ledu|ld|1147@ldx|梁底下|LDP|liangdixia|ldx|1148@ldz|六道河子|LVP|liudaohezi|ldhz|1149@lfa|鲁番|LVM|lufan|lf|1150@lfa|廊坊|LJP|langfang|lf|1151@lfa|落垡|LOP|luofa|lf|1152@lfb|廊坊北|LFP|langfangbei|lfb|1153@lfu|老府|UFD|laofu|lf|1154@lga|兰岗|LNB|langang|lg|1155@lgd|龙骨甸|LGM|longgudian|lgd|1156@lgo|芦沟|LOM|lugou|lg|1157@lgo|龙沟|LGJ|longgou|lg|1158@lgu|拉古|LGB|lagu|lg|1159@lha|临海|UFH|linhai|lh|1160@lha|林海|LXX|linhai|lh|1161@lha|拉哈|LHX|laha|lh|1162@lha|凌海|JID|linghai|lh|1163@lhe|柳河|LNL|liuhe|lh|1164@lhe|六合|KLH|liuhe|lh|1165@lhu|龙华|LHP|longhua|lh|1166@lhy|滦河沿|UNP|luanheyan|lhy|1167@lhz|六合镇|LEX|liuhezhen|lhz|1168@ljd|亮甲店|LRT|liangjiadian|ljd|1169@ljd|刘家店|UDT|liujiadian|ljd|1170@ljh|刘家河|LVT|liujiahe|ljh|1171@lji|连江|LKS|lianjiang|lj|1172@lji|庐江|UJH|lujiang|lj|1173@lji|李家|LJB|lijia|lj|1174@lji|罗江|LJW|luojiang|lj|1175@lji|廉江|LJZ|lianjiang|lj|1176@lji|两家|UJT|liangjia|lj|1177@lji|龙江|LJX|longjiang|lj|1178@lji|龙嘉|UJL|longjia|lj|1179@ljk|莲江口|LHB|lianjiangkou|ljk|1180@ljl|蔺家楼|ULK|linjialou|ljl|1181@ljp|李家坪|LIJ|lijiaping|ljp|1182@lka|兰考|LKF|lankao|lk|1183@lko|林口|LKB|linkou|lk|1184@lkp|路口铺|LKQ|lukoupu|lkp|1185@lla|老莱|LAX|laolai|ll|1186@lli|拉林|LAB|lalin|ll|1187@lli|陆良|LRM|luliang|ll|1188@lli|龙里|LLW|longli|ll|1189@lli|临澧|LWQ|linli|ll|1190@lli|兰棱|LLB|lanling|ll|1191@lli|零陵|UWZ|lingling|ll|1192@llo|卢龙|UAP|lulong|ll|1193@lmd|喇嘛甸|LMX|lamadian|lmd|1194@lmd|里木店|LMB|limudian|lmd|1195@lme|洛门|LMJ|luomen|lm|1196@lna|龙南|UNG|longnan|ln|1197@lpi|梁平|UQW|liangping|lp|1198@lpi|罗平|LPM|luoping|lp|1199@lpl|落坡岭|LPP|luopoling|lpl|1200@lps|六盘山|UPJ|liupanshan|lps|1201@lps|乐平市|LPG|lepingshi|lps|1202@lqi|临清|UQK|linqing|lq|1203@lqs|龙泉寺|UQJ|longquansi|lqs|1204@lsb|乐山北|UTW|leshanbei|ls|1205@lsc|乐善村|LUM|leshancun|lsc|1206@lsd|冷水江东|UDQ|lengshuijiangdong|lsjd|1207@lsg|连山关|LGT|lianshanguan|lsg|1208@lsg|流水沟|USP|liushuigou|lsg|1209@lsh|丽水|USH|lishui|ls|1210@lsh|陵水|LIQ|lingshui|ls|1211@lsh|罗山|LRN|luoshan|ls|1212@lsh|鲁山|LAF|lushan|ls|1213@lsh|梁山|LMK|liangshan|ls|1214@lsh|灵石|LSV|lingshi|ls|1215@lsh|露水河|LUL|lushuihe|lsh|1216@lsh|庐山|LSG|lushan|ls|1217@lsp|林盛堡|LBT|linshengpu|lsp|1218@lst|柳树屯|LSD|liushutun|lst|1219@lsz|龙山镇|LAS|longshanzhen|lsz|1220@lsz|梨树镇|LSB|lishuzhen|lsz|1221@lsz|李石寨|LET|lishizhai|lsz|1222@lta|黎塘|LTZ|litang|lt|1223@lta|轮台|LAR|luntai|lt|1224@lta|芦台|LTP|lutai|lt|1225@ltb|龙塘坝|LBM|longtangba|ltb|1226@ltu|濑湍|LVZ|laituan|lt|1227@ltx|骆驼巷|LTJ|luotuoxiang|ltx|1228@lwa|李旺|VLJ|liwang|lw|1229@lwd|莱芜东|LWK|laiwudong|lwd|1230@lws|狼尾山|LRJ|langweishan|lws|1231@lwu|灵武|LNJ|lingwu|lw|1232@lwx|莱芜西|UXK|laiwuxi|lwx|1233@lxi|朗乡|LXB|langxiang|lx|1234@lxi|陇县|LXY|longxian|lx|1235@lxi|临湘|LXQ|linxiang|lx|1236@lxi|芦溪|LUG|luxi|lx|1237@lxi|莱西|LXK|laixi|lx|1238@lxi|林西|LXC|linxi|lx|1239@lxi|滦县|UXP|luanxian|lx|1240@lya|莱阳|LYK|laiyang|ly|1241@lya|略阳|LYY|lueyang|ly|1242@lya|辽阳|LYT|liaoyang|ly|1243@lyd|凌源东|LDD|lingyuandong|lyd|1244@lyd|临沂东|UYK|linyidong|lyd|1245@lyg|连云港|UIH|lianyungang|lyg|1246@lyi|临颍|LNF|linying|ly|1247@lyi|老营|LXL|laoying|ly|1248@lyo|龙游|LMH|longyou|ly|1249@lyu|罗源|LVS|luoyuan|ly|1250@lyu|林源|LYX|linyuan|ly|1251@lyu|涟源|LAQ|lianyuan|ly|1252@lyu|涞源|LYP|laiyuan|ly|1253@lyx|耒阳西|LPQ|leiyangxi|lyx|1254@lze|临泽|LEJ|linze|lz|1255@lzg|龙爪沟|LZT|longzhuagou|lzg|1256@lzh|雷州|UAQ|leizhou|lz|1257@lzh|六枝|LIW|liuzhi|lz|1258@lzh|鹿寨|LIZ|luzhai|lz|1259@lzh|来舟|LZS|laizhou|lz|1260@lzh|龙镇|LZA|longzhen|lz|1261@lzh|拉鲊|LEM|lazha|lz|1262@lzq|兰州新区|LQJ|lanzhouxinqu|lzxq|1263@mas|马鞍山|MAH|maanshan|mas|1264@mba|毛坝|MBY|maoba|mb|1265@mbg|毛坝关|MGY|maobaguan|mbg|1266@mcb|麻城北|MBN|machengbei|mcb|1267@mch|渑池|MCF|mianchi|mc|1268@mch|明城|MCL|mingcheng|mc|1269@mch|庙城|MAP|miaocheng|mc|1270@mcn|渑池南|MNF|mianchinan|mcn|1271@mcp|茅草坪|KPM|maocaoping|mcp|1272@mdh|猛洞河|MUQ|mengdonghe|mdh|1273@mds|磨刀石|MOB|modaoshi|mds|1274@mdu|弥渡|MDF|midu|md|1275@mes|帽儿山|MRB|maoershan|mes|1276@mga|明港|MGN|minggang|mg|1277@mhk|梅河口|MHL|meihekou|mhk|1278@mhu|马皇|MHZ|mahuang|mh|1279@mjg|孟家岗|MGB|mengjiagang|mjg|1280@mla|美兰|MHQ|meilan|ml|1281@mld|汨罗东|MQQ|miluodong|mld|1282@mlh|马莲河|MHB|malianhe|mlh|1283@mli|茅岭|MLZ|maoling|ml|1284@mli|庙岭|MLL|miaoling|ml|1285@mli|茂林|MLD|maolin|ml|1286@mli|穆棱|MLB|muling|ml|1287@mli|马林|MID|malin|ml|1288@mlo|马龙|MGM|malong|ml|1289@mlt|木里图|MUD|mulitu|mlt|1290@mlu|汨罗|MLQ|miluo|ml|1291@mnh|玛纳斯湖|MNR|manasihu|mnsh|1292@mni|冕宁|UGW|mianning|mn|1293@mpa|沐滂|MPQ|mupang|mp|1294@mqh|马桥河|MQB|maqiaohe|mqh|1295@mqi|闽清|MQS|minqing|mq|1296@mqu|民权|MQF|minquan|mq|1297@msh|明水河|MUT|mingshuihe|msh|1298@msh|麻山|MAB|mashan|ms|1299@msh|眉山|MSW|meishan|ms|1300@msw|漫水湾|MKW|manshuiwan|msw|1301@msz|茂舍祖|MOM|maoshezu|msz|1302@msz|米沙子|MST|mishazi|msz|1303@mta|马踏|PWQ|mata|mt|1304@mxi|美溪|MEB|meixi|mx|1305@mxi|勉县|MVY|mianxian|mx|1306@mya|麻阳|MVQ|mayang|my|1307@myb|密云北|MUP|miyunbei|myb|1308@myi|米易|MMW|miyi|my|1309@myu|麦园|MYS|maiyuan|my|1310@myu|墨玉|MUR|moyu|my|1311@mzh|庙庄|MZJ|miaozhuang|mz|1312@mzh|米脂|MEY|mizhi|mz|1313@mzh|明珠|MFQ|mingzhu|mz|1314@nan|宁安|NAB|ningan|na|1315@nan|农安|NAT|nongan|na|1316@nbs|南博山|NBK|nanboshan|nbs|1317@nch|南仇|NCK|nanqiu|nc|1318@ncs|南城司|NSP|nanchengsi|ncs|1319@ncu|宁村|NCZ|ningcun|nc|1320@nde|宁德|NES|ningde|nd|1321@ngc|南观村|NGP|nanguancun|ngc|1322@ngd|南宫东|NFP|nangongdong|ngd|1323@ngl|南关岭|NLT|nanguanling|ngl|1324@ngu|宁国|NNH|ningguo|ng|1325@nha|宁海|NHH|ninghai|nh|1326@nhb|南华北|NHS|nanhuabei|nhb|1327@nhc|南河川|NHJ|nanhechuan|nhc|1328@nhz|泥河子|NHD|nihezi|nhz|1329@nji|宁家|NVT|ningjia|nj|1330@nji|南靖|NJS|nanjing|nj|1331@nji|牛家|NJB|niujia|nj|1332@nji|能家|NJD|nengjia|nj|1333@nko|南口|NKP|nankou|nk|1334@nkq|南口前|NKT|nankouqian|nkq|1335@nla|南朗|NNQ|nanlang|nl|1336@nli|乃林|NLD|nailin|nl|1337@nlk|尼勒克|NIR|nileke|nlk|1338@nlu|那罗|ULZ|naluo|nl|1339@nlx|宁陵县|NLF|ninglingxian|nlx|1340@nma|奈曼|NMD|naiman|nm|1341@nmi|宁明|NMZ|ningming|nm|1342@nmu|南木|NMX|nanmu|nm|1343@npn|南平南|NNS|nanpingnan|npn|1344@npu|那铺|NPZ|napu|np|1345@nqi|南桥|NQD|nanqiao|nq|1346@nqu|那曲|NQO|naqu|nq|1347@nqu|暖泉|NQJ|nuanquan|nq|1348@nta|南台|NTT|nantai|nt|1349@nto|南头|NOQ|nantou|nt|1350@nwu|宁武|NWV|ningwu|nw|1351@nwz|南湾子|NWP|nanwanzi|nwz|1352@nxb|南翔北|NEH|nanxiangbei|nxb|1353@nxi|宁乡|NXQ|ningxiang|nx|1354@nxi|内乡|NXF|neixiang|nx|1355@nxt|牛心台|NXT|niuxintai|nxt|1356@nyu|南峪|NUP|nanyu|ny|1357@nzg|娘子关|NIP|niangziguan|nzg|1358@nzh|南召|NAF|nanzhao|nz|1359@nzm|南杂木|NZT|nanzamu|nzm|1360@pan|蓬安|PAW|pengan|pa|1361@pan|平安|PAL|pingan|pa|1362@pay|平安驿|PNO|pinganyi|pay|1363@paz|磐安镇|PAJ|pananzhen|paz|1364@paz|平安镇|PZT|pinganzhen|paz|1365@pcd|蒲城东|PEY|puchengdong|pcd|1366@pch|蒲城|PCY|pucheng|pc|1367@pde|裴德|PDB|peide|pd|1368@pdi|偏店|PRP|piandian|pd|1369@pdx|坡底下|PXJ|podixia|pdx|1370@pet|瓢儿屯|PRT|piaoertun|pet|1371@pfa|平房|PFB|pingfang|pf|1372@pga|平岗|PGL|pinggang|pg|1373@pgu|平果|PGZ|pingguo|pg|1374@pgu|平关|PGM|pingguan|pg|1375@pgu|盘关|PAM|panguan|pg|1376@phb|徘徊北|PHP|paihuaibei|phb|1377@phk|平河口|PHM|pinghekou|phk|1378@phu|平湖|PHQ|pinghu|ph|1379@pjb|盘锦北|PBD|panjinbei|pjb|1380@pjd|潘家店|PDP|panjiadian|pjd|1381@pkn|皮口南|PKT|pikounan|pk|1382@pld|普兰店|PLT|pulandian|pld|1383@pli|偏岭|PNT|pianling|pl|1384@psh|平山|PSB|pingshan|ps|1385@psh|彭山|PSW|pengshan|ps|1386@psh|皮山|PSR|pishan|ps|1387@psh|磐石|PSL|panshi|ps|1388@psh|平社|PSV|pingshe|ps|1389@psh|彭水|PHW|pengshui|ps|1390@pta|平台|PVT|pingtai|pt|1391@pti|平田|PTM|pingtian|pt|1392@pti|莆田|PTS|putian|pt|1393@ptq|葡萄菁|PTW|putaojing|ptq|1394@pwa|普湾|PWT|puwan|pw|1395@pwa|平旺|PWV|pingwang|pw|1396@pxg|平型关|PGV|pingxingguan|pxg|1397@pxi|普雄|POW|puxiong|px|1398@pxi|蓬溪|KZW|pengxi|px|1399@pxi|郫县|PWW|pixian|px|1400@pya|平阳|ARH|pingyang|py|1401@pya|平洋|PYX|pingyang|py|1402@pya|彭阳|PYJ|pengyang|py|1403@pya|平遥|PYV|pingyao|py|1404@pyi|平邑|PIK|pingyi|py|1405@pyp|平原堡|PPJ|pingyuanpu|pyp|1406@pyu|平原|PYK|pingyuan|py|1407@pyu|平峪|PYP|pingyu|py|1408@pze|彭泽|PZG|pengze|pz|1409@pzh|邳州|PJH|pizhou|pz|1410@pzh|平庄|PZD|pingzhuang|pz|1411@pzi|泡子|POD|paozi|pz|1412@pzn|平庄南|PND|pingzhuangnan|pzn|1413@qan|乾安|QOT|qianan|qa|1414@qan|庆安|QAB|qingan|qa|1415@qan|迁安|QQP|qianan|qa|1416@qdb|祁东北|QRQ|qidongbei|qd|1417@qdi|七甸|QDM|qidian|qd|1418@qfd|曲阜东|QAK|qufudong|qfd|1419@qfe|庆丰|QFT|qingfeng|qf|1420@qft|奇峰塔|QVP|qifengta|qft|1421@qfu|曲阜|QFK|qufu|qf|1422@qha|琼海|QYQ|qionghai|qh|1423@qhd|秦皇岛|QTP|qinhuangdao|qhd|1424@qhe|千河|QUY|qianhe|qh|1425@qhe|清河|QIP|qinghe|qh|1426@qhm|清河门|QHD|qinghemen|qhm|1427@qhy|清华园|QHP|qinghuayuan|qhy|1428@qji|全椒|INH|quanjiao|qj|1429@qji|潜江|QJN|qianjiang|qj|1430@qji|渠旧|QJZ|qujiu|qj|1431@qji|秦家|QJB|qinjia|qj|1432@qji|綦江|QJW|qijiang|qj|1433@qjp|祁家堡|QBT|qijiapu|qjp|1434@qjx|清涧县|QNY|qingjianxian|qjx|1435@qjz|秦家庄|QZV|qinjiazhuang|qjz|1436@qlh|七里河|QLD|qilihe|qlh|1437@qli|秦岭|QLY|qinling|ql|1438@qli|渠黎|QLZ|quli|ql|1439@qlo|青龙|QIB|qinglong|ql|1440@qls|青龙山|QGH|qinglongshan|qls|1441@qme|祁门|QIH|qimen|qm|1442@qmt|前磨头|QMP|qianmotou|qmt|1443@qsh|青山|QSB|qingshan|qs|1444@qsh|确山|QSN|queshan|qs|1445@qsh|前山|QXQ|qianshan|qs|1446@qsh|清水|QUJ|qingshui|qs|1447@qsy|戚墅堰|QYH|qishuyan|qsy|1448@qti|青田|QVH|qingtian|qt|1449@qto|桥头|QAT|qiaotou|qt|1450@qtx|青铜峡|QTJ|qingtongxia|qtx|1451@qwe|前卫|QWD|qianwei|qw|1452@qwt|前苇塘|QWP|qianweitang|qwt|1453@qxi|渠县|QRW|quxian|qx|1454@qxi|祁县|QXV|qixian|qx|1455@qxi|青县|QXP|qingxian|qx|1456@qxi|桥西|QXJ|qiaoxi|qx|1457@qxu|清徐|QUV|qingxu|qx|1458@qxy|旗下营|QXC|qixiaying|qxy|1459@qya|千阳|QOY|qianyang|qy|1460@qya|沁阳|QYF|qinyang|qy|1461@qya|泉阳|QYL|quanyang|qy|1462@qyb|祁阳北|QVQ|qiyangbei|qy|1463@qyi|七营|QYJ|qiying|qy|1464@qys|庆阳山|QSJ|qingyangshan|qys|1465@qyu|清远|QBQ|qingyuan|qy|1466@qyu|清原|QYT|qingyuan|qy|1467@qzd|钦州东|QDZ|qinzhoudong|qzd|1468@qzh|钦州|QRZ|qinzhou|qz|1469@qzs|青州市|QZK|qingzhoushi|qzs|1470@ran|瑞安|RAH|ruian|ra|1471@rch|荣昌|RCW|rongchang|rc|1472@rch|瑞昌|RCG|ruichang|rc|1473@rga|如皋|RBH|rugao|rg|1474@rgu|容桂|RUQ|ronggui|rg|1475@rqi|任丘|RQP|renqiu|rq|1476@rsh|乳山|ROK|rushan|rs|1477@rsh|融水|RSZ|rongshui|rs|1478@rsh|热水|RSD|reshui|rs|1479@rxi|容县|RXZ|rongxian|rx|1480@rya|饶阳|RVP|raoyang|ry|1481@rya|汝阳|RYF|ruyang|ry|1482@ryh|绕阳河|RHD|raoyanghe|ryh|1483@rzh|汝州|ROF|ruzhou|rz|1484@sba|石坝|OBJ|shiba|sb|1485@sbc|上板城|SBP|shangbancheng|sbc|1486@sbi|施秉|AQW|shibing|sb|1487@sbn|上板城南|OBP|shangbanchengnan|sbcn|1488@sby|世博园|ZWT|shiboyuan|sby|1489@scb|双城北|SBB|shuangchengbei|scb|1490@sch|舒城|OCH|shucheng|sc|1491@sch|商城|SWN|shangcheng|sc|1492@sch|莎车|SCR|shache|sc|1493@sch|顺昌|SCS|shunchang|sc|1494@sch|神池|SMV|shenchi|sc|1495@sch|沙城|SCP|shacheng|sc|1496@sch|石城|SCT|shicheng|sc|1497@scz|山城镇|SCL|shanchengzhen|scz|1498@sda|山丹|SDJ|shandan|sd|1499@sde|顺德|ORQ|shunde|sd|1500@sde|绥德|ODY|suide|sd|1501@sdo|水洞|SIL|shuidong|sd|1502@sdu|商都|SXC|shangdu|sd|1503@sdu|十渡|SEP|shidu|sd|1504@sdw|四道湾|OUD|sidaowan|sdw|1505@sdy|顺德学院|OJQ|shundexueyuan|sdxy|1506@sfa|绅坊|OLH|shenfang|sf|1507@sfe|双丰|OFB|shuangfeng|sf|1508@sft|四方台|STB|sifangtai|sft|1509@sfu|水富|OTW|shuifu|sf|1510@sgk|三关口|OKJ|sanguankou|sgk|1511@sgl|桑根达来|OGC|sanggendalai|sgdl|1512@sgu|韶关|SNQ|shaoguan|sg|1513@sgz|上高镇|SVK|shanggaozhen|sgz|1514@sha|上杭|JBS|shanghang|sh|1515@sha|沙海|SED|shahai|sh|1516@she|蜀河|SHY|shuhe|sh|1517@she|松河|SBM|songhe|sh|1518@she|沙河|SHP|shahe|sh|1519@shk|沙河口|SKT|shahekou|shk|1520@shl|赛汗塔拉|SHC|saihantala|shtl|1521@shs|沙河市|VOP|shaheshi|shs|1522@shs|沙后所|SSD|shahousuo|shs|1523@sht|山河屯|SHL|shanhetun|sht|1524@shx|三河县|OXP|sanhexian|shx|1525@shy|四合永|OHD|siheyong|shy|1526@shz|三汇镇|OZW|sanhuizhen|shz|1527@shz|双河镇|SEL|shuanghezhen|shz|1528@shz|石河子|SZR|shihezi|shz|1529@shz|三合庄|SVP|sanhezhuang|shz|1530@sjd|三家店|ODP|sanjiadian|sjd|1531@sjh|水家湖|SQH|shuijiahu|sjh|1532@sjh|沈家河|OJJ|shenjiahe|sjh|1533@sjh|松江河|SJL|songjianghe|sjh|1534@sji|尚家|SJB|shangjia|sj|1535@sji|孙家|SUB|sunjia|sj|1536@sji|沈家|OJB|shenjia|sj|1537@sji|双吉|SML|shuangji|sj|1538@sji|松江|SAH|songjiang|sj|1539@sjk|三江口|SKD|sanjiangkou|sjk|1540@sjl|司家岭|OLK|sijialing|sjl|1541@sjn|松江南|IMH|songjiangnan|sjn|1542@sjn|石景山南|SRP|shijingshannan|sjsn|1543@sjt|邵家堂|SJJ|shaojiatang|sjt|1544@sjx|三江县|SOZ|sanjiangxian|sjx|1545@sjz|三家寨|SMM|sanjiazhai|sjz|1546@sjz|十家子|SJD|shijiazi|sjz|1547@sjz|松江镇|OZL|songjiangzhen|sjz|1548@sjz|施家嘴|SHM|shijiazui|sjz|1549@sjz|深井子|SWT|shenjingzi|sjz|1550@sld|什里店|OMP|shilidian|sld|1551@sle|疏勒|SUR|shule|sl|1552@slh|疏勒河|SHJ|shulehe|slh|1553@slh|舍力虎|VLD|shelihu|slh|1554@sli|石磷|SPB|shilin|sl|1555@sli|石林|SLM|shilin|sl|1556@sli|双辽|ZJD|shuangliao|sl|1557@sli|绥棱|SIB|suiling|sl|1558@sli|石岭|SOL|shiling|sl|1559@sln|石林南|LNM|shilinnan|sln|1560@slo|石龙|SLQ|shilong|sl|1561@slq|萨拉齐|SLC|salaqi|slq|1562@slu|索伦|SNT|suolun|sl|1563@slu|商洛|OLY|shangluo|sl|1564@slz|沙岭子|SLP|shalingzi|slz|1565@smb|石门县北|VFQ|shimenxianbei|smxb|1566@smn|三门峡南|SCF|sanmenxianan|smxn|1567@smx|三门县|OQH|sanmenxian|smx|1568@smx|石门县|OMQ|shimenxian|smx|1569@smx|三门峡西|SXF|sanmenxiaxi|smxx|1570@sni|肃宁|SYP|suning|sn|1571@son|宋|SOB|song|son|1572@spa|双牌|SBZ|shuangpai|sp|1573@spb|沙坪坝|CYW|shapingba|spb|1574@spd|四平东|PPT|sipingdong|spd|1575@spi|遂平|SON|suiping|sp|1576@spt|沙坡头|SFJ|shapotou|spt|1577@sqi|沙桥|SQM|shaqiao|sq|1578@sqn|商丘南|SPF|shangqiunan|sqn|1579@squ|水泉|SID|shuiquan|sq|1580@sqx|石泉县|SXY|shiquanxian|sqx|1581@sqz|石桥子|SQT|shiqiaozi|sqz|1582@src|石人城|SRB|shirencheng|src|1583@sre|石人|SRL|shiren|sr|1584@ssh|山市|SQB|shanshi|ss|1585@ssh|神树|SWB|shenshu|ss|1586@ssh|鄯善|SSR|shanshan|ss|1587@ssh|三水|SJQ|sanshui|ss|1588@ssh|泗水|OSK|sishui|ss|1589@ssh|石山|SAD|shishan|ss|1590@ssh|松树|SFT|songshu|ss|1591@ssh|首山|SAT|shoushan|ss|1592@ssj|三十家|SRD|sanshijia|ssj|1593@ssp|三十里堡|SST|sanshilipu|sslp|1594@ssz|双水镇|PQQ|shuangshuizhen|ssz|1595@ssz|松树镇|SSL|songshuzhen|ssz|1596@sta|松桃|MZQ|songtao|st|1597@sth|索图罕|SHX|suotuhan|sth|1598@stj|三堂集|SDH|santangji|stj|1599@sto|石头|OTB|shitou|st|1600@sto|神头|SEV|shentou|st|1601@stu|沙沱|SFM|shatuo|st|1602@swa|上万|SWP|shangwan|sw|1603@swu|孙吴|SKB|sunwu|sw|1604@swx|沙湾县|SXR|shawanxian|swx|1605@sxi|歙县|OVH|shexian|sx|1606@sxi|遂溪|SXZ|suixi|sx|1607@sxi|沙县|SAS|shaxian|sx|1608@sxi|绍兴|SOH|shaoxing|sx|1609@sxi|石岘|SXL|shixian|sx|1610@sxp|上西铺|SXM|shangxipu|sxp|1611@sxz|石峡子|SXJ|shixiazi|sxz|1612@sya|沭阳|FMH|shuyang|sy|1613@sya|绥阳|SYB|suiyang|sy|1614@sya|寿阳|SYV|shouyang|sy|1615@sya|水洋|OYP|shuiyang|sy|1616@syc|三阳川|SYJ|sanyangchuan|syc|1617@syd|上腰墩|SPJ|shangyaodun|syd|1618@syi|三营|OEJ|sanying|sy|1619@syi|顺义|SOP|shunyi|sy|1620@syj|三义井|OYD|sanyijing|syj|1621@syp|三源浦|SYL|sanyuanpu|syp|1622@syu|上虞|BDH|shangyu|sy|1623@syu|三原|SAY|sanyuan|sy|1624@syu|上园|SUD|shangyuan|sy|1625@syu|水源|OYJ|shuiyuan|sy|1626@syz|桑园子|SAJ|sangyuanzi|syz|1627@szb|绥中北|SND|suizhongbei|szb|1628@szb|苏州北|OHH|suzhoubei|szb|1629@szd|宿州东|SRH|suzhoudong|szd|1630@szd|深圳东|BJQ|shenzhendong|szd|1631@szh|深州|OZP|shenzhou|sz|1632@szh|孙镇|OZY|sunzhen|sz|1633@szh|绥中|SZD|suizhong|sz|1634@szh|尚志|SZB|shangzhi|sz|1635@szh|师庄|SNM|shizhuang|sz|1636@szi|松滋|SIN|songzi|sz|1637@szo|师宗|SEM|shizong|sz|1638@szq|苏州园区|KAH|suzhouyuanqu|szyq|1639@szq|苏州新区|ITH|suzhouxinqu|szxq|1640@tan|泰安|TMK|taian|ta|1641@tan|台安|TID|taian|ta|1642@tay|通安驿|TAJ|tonganyi|tay|1643@tba|桐柏|TBF|tongbai|tb|1644@tbe|通北|TBB|tongbei|tb|1645@tch|桐城|TTH|tongcheng|tc|1646@tch|汤池|TCX|tangchi|tc|1647@tch|郯城|TZK|tancheng|tc|1648@tch|铁厂|TCL|tiechang|tc|1649@tcu|桃村|TCK|taocun|tc|1650@tda|通道|TRQ|tongdao|td|1651@tdo|田东|TDZ|tiandong|td|1652@tga|天岗|TGL|tiangang|tg|1653@tgl|土贵乌拉|TGC|tuguiwula|tgwl|1654@tgo|通沟|TOL|tonggou|tg|1655@tgu|太谷|TGV|taigu|tg|1656@tha|塔哈|THX|taha|th|1657@tha|棠海|THM|tanghai|th|1658@the|唐河|THF|tanghe|th|1659@the|泰和|THG|taihe|th|1660@thu|太湖|TKH|taihu|th|1661@tji|团结|TIX|tuanjie|tj|1662@tjj|谭家井|TNJ|tanjiajing|tjj|1663@tjt|陶家屯|TOT|taojiatun|tjt|1664@tjw|唐家湾|PDQ|tangjiawan|tjw|1665@tjz|统军庄|TZP|tongjunzhuang|tjz|1666@tld|吐列毛杜|TMD|tuliemaodu|tlmd|1667@tlh|图里河|TEX|tulihe|tlh|1668@tli|铜陵|TJH|tongling|tl|1669@tli|田林|TFZ|tianlin|tl|1670@tli|亭亮|TIZ|tingliang|tl|1671@tli|铁力|TLB|tieli|tl|1672@tlx|铁岭西|PXT|tielingxi|tlx|1673@tmb|图们北|QSL|tumenbei|tmb|1674@tme|天门|TMN|tianmen|tm|1675@tmn|天门南|TNN|tianmennan|tmn|1676@tms|太姥山|TLS|taimushan|tms|1677@tmt|土牧尔台|TRC|tumuertai|tmet|1678@tmz|土门子|TCJ|tumenzi|tmz|1679@tna|洮南|TVT|taonan|tn|1680@tna|潼南|TVW|tongnan|tn|1681@tpc|太平川|TIT|taipingchuan|tpc|1682@tpz|太平镇|TEB|taipingzhen|tpz|1683@tqi|图强|TQX|tuqiang|tq|1684@tqi|台前|TTK|taiqian|tq|1685@tql|天桥岭|TQL|tianqiaoling|tql|1686@tqz|土桥子|TQJ|tuqiaozi|tqz|1687@tsc|汤山城|TCT|tangshancheng|tsc|1688@tsh|台山|PUQ|taishan|ts|1689@tsh|桃山|TAB|taoshan|ts|1690@tsz|塔石嘴|TIM|tashizui|tsz|1691@ttu|通途|TUT|tongtu|tt|1692@twh|汤旺河|THB|tangwanghe|twh|1693@txi|同心|TXJ|tongxin|tx|1694@txi|土溪|TSW|tuxi|tx|1695@txi|桐乡|TCH|tongxiang|tx|1696@tya|田阳|TRZ|tianyang|ty|1697@tyi|天义|TND|tianyi|ty|1698@tyi|汤阴|TYF|tangyin|ty|1699@tyl|驼腰岭|TIL|tuoyaoling|tyl|1700@tys|太阳山|TYJ|taiyangshan|tys|1701@tyu|通榆|KTT|tongyu|ty|1702@tyu|汤原|TYB|tangyuan|ty|1703@tyy|塔崖驿|TYP|tayayi|tyy|1704@tzd|滕州东|TEK|tengzhoudong|tzd|1705@tzh|台州|TZH|taizhou|tz|1706@tzh|天祝|TZJ|tianzhu|tz|1707@tzh|滕州|TXK|tengzhou|tz|1708@tzh|天镇|TZV|tianzhen|tz|1709@tzl|桐子林|TEW|tongzilin|tzl|1710@tzs|天柱山|QWH|tianzhushan|tzs|1711@wan|文安|WBP|wenan|wa|1712@wan|武安|WAP|wuan|wa|1713@waz|王安镇|WVP|wanganzhen|waz|1714@wbu|吴堡|WUY|wubu|wb|1715@wca|旺苍|WEW|wangcang|wc|1716@wcg|五叉沟|WCT|wuchagou|wcg|1717@wch|文昌|WEQ|wenchang|wc|1718@wch|温春|WDB|wenchun|wc|1719@wdc|五大连池|WRB|wudalianchi|wdlc|1720@wde|文登|WBK|wendeng|wd|1721@wdg|五道沟|WDL|wudaogou|wdg|1722@wdh|五道河|WHP|wudaohe|wdh|1723@wdi|文地|WNZ|wendi|wd|1724@wdo|卫东|WVT|weidong|wd|1725@wds|武当山|WRN|wudangshan|wds|1726@wdu|望都|WDP|wangdu|wd|1727@weh|乌尔旗汗|WHX|wuerqihan|weqh|1728@wfa|潍坊|WFK|weifang|wf|1729@wft|万发屯|WFB|wanfatun|wft|1730@wfu|王府|WUT|wangfu|wf|1731@wfx|瓦房店西|WXT|wafangdianxi|wfdx|1732@wga|王岗|WGB|wanggang|wg|1733@wgo|武功|WGY|wugong|wg|1734@wgo|湾沟|WGL|wangou|wg|1735@wgt|吴官田|WGM|wuguantian|wgt|1736@wha|乌海|WVC|wuhai|wh|1737@whe|苇河|WHB|weihe|wh|1738@whu|卫辉|WHF|weihui|wh|1739@wjc|吴家川|WCJ|wujiachuan|wjc|1740@wji|五家|WUB|wujia|wj|1741@wji|威箐|WAM|weiqing|wj|1742@wji|午汲|WJP|wuji|wj|1743@wji|渭津|WJL|weijin|wj|1744@wjw|王家湾|WJJ|wangjiawan|wjw|1745@wke|倭肯|WQB|woken|wk|1746@wks|五棵树|WKT|wukeshu|wks|1747@wlb|五龙背|WBT|wulongbei|wlb|1748@wle|万乐|WEB|wanle|wl|1749@wlg|瓦拉干|WVX|walagan|wlg|1750@wli|温岭|VHH|wenling|wl|1751@wli|五莲|WLK|wulian|wl|1752@wlq|乌拉特前旗|WQC|wulateqianqi|wltqq|1753@wlt|卧里屯|WLX|wolitun|wlt|1754@wnb|渭南北|WBY|weinanbei|wnb|1755@wne|乌奴耳|WRX|wunuer|wne|1756@wni|万宁|WNQ|wanning|wn|1757@wni|万年|WWG|wannian|wn|1758@wnn|渭南南|WVY|weinannan|wnn|1759@wnz|渭南镇|WNJ|weinanzhen|wnz|1760@wpi|沃皮|WPT|wopi|wp|1761@wqi|吴桥|WUP|wuqiao|wq|1762@wqi|汪清|WQL|wangqing|wq|1763@wqi|武清|WWP|wuqing|wq|1764@wsh|武山|WSJ|wushan|ws|1765@wsh|文水|WEV|wenshui|ws|1766@wsz|魏善庄|WSP|weishanzhuang|wsz|1767@wto|王瞳|WTP|wangtong|wt|1768@wts|五台山|WSV|wutaishan|wts|1769@wtz|王团庄|WZJ|wangtuanzhuang|wtz|1770@wwu|五五|WVR|wuwu|ww|1771@wxd|无锡东|WGH|wuxidong|wxd|1772@wxi|卫星|WVB|weixing|wx|1773@wxi|闻喜|WXV|wenxi|wx|1774@wxi|武乡|WVV|wuxiang|wx|1775@wxq|无锡新区|IFH|wuxixinqu|wxxq|1776@wxu|武穴|WXN|wuxue|wx|1777@wxu|吴圩|WYZ|wuxu|wx|1778@wya|王杨|WYB|wangyang|wy|1779@wyi|武义|RYH|wuyi|wy|1780@wyi|五营|WWB|wuying|wy|1781@wyt|瓦窑田|WIM|wayaotian|wyt|1782@wyu|五原|WYC|wuyuan|wy|1783@wzg|苇子沟|WZL|weizigou|wzg|1784@wzh|韦庄|WZY|weizhuang|wz|1785@wzh|五寨|WZV|wuzhai|wz|1786@wzt|王兆屯|WZB|wangzhaotun|wzt|1787@wzz|微子镇|WQP|weizizhen|wzz|1788@wzz|魏杖子|WKD|weizhangzi|wzz|1789@xan|新安|EAM|xinan|xa|1790@xan|兴安|XAZ|xingan|xa|1791@xax|新安县|XAF|xinanxian|xax|1792@xba|新保安|XAP|xinbaoan|xba|1793@xbc|下板城|EBP|xiabancheng|xbc|1794@xbl|西八里|XLP|xibali|xbl|1795@xch|宣城|ECH|xuancheng|xc|1796@xch|兴城|XCD|xingcheng|xc|1797@xcu|小村|XEM|xiaocun|xc|1798@xcy|新绰源|XRX|xinchuoyuan|xcy|1799@xcz|下城子|XCB|xiachengzi|xcz|1800@xcz|新城子|XCT|xinchengzi|xcz|1801@xde|喜德|EDW|xide|xd|1802@xdj|小得江|EJM|xiaodejiang|xdj|1803@xdm|西大庙|XMP|xidamiao|xdm|1804@xdo|小董|XEZ|xiaodong|xd|1805@xdo|小东|XOD|xiaodong|xd|1806@xfa|香坊|XFB|xiangfang|xf|1807@xfe|信丰|EFG|xinfeng|xf|1808@xfe|襄汾|XFV|xiangfen|xf|1809@xfe|息烽|XFW|xifeng|xf|1810@xga|新干|EGG|xingan|xg|1811@xga|轩岗|XGV|xuangang|xg|1812@xga|孝感|XGN|xiaogan|xg|1813@xgc|西固城|XUJ|xigucheng|xgc|1814@xgu|兴国|EUG|xingguo|xg|1815@xgu|西固|XIJ|xigu|xg|1816@xgy|夏官营|XGJ|xiaguanying|xgy|1817@xgz|西岗子|NBB|xigangzi|xgz|1818@xha|宣汉|XHY|xuanhan|xh|1819@xhe|襄河|XXB|xianghe|xh|1820@xhe|新和|XIR|xinhe|xh|1821@xhe|宣和|XWJ|xuanhe|xh|1822@xhj|斜河涧|EEP|xiehejian|xhj|1823@xht|新华屯|XAX|xinhuatun|xht|1824@xhu|新会|EFQ|xinhui|xh|1825@xhu|新华|XHB|xinhua|xh|1826@xhu|新晃|XLQ|xinhuang|xh|1827@xhu|新化|EHQ|xinhua|xh|1828@xhu|宣化|XHP|xuanhua|xh|1829@xhx|兴和西|XEC|xinghexi|xhx|1830@xhy|小河沿|XYD|xiaoheyan|xhy|1831@xhy|下花园|XYP|xiahuayuan|xhy|1832@xhz|小河镇|EKY|xiaohezhen|xhz|1833@xjd|徐家店|HYK|xujiadian|xjd|1834@xji|徐家|XJB|xujia|xj|1835@xji|峡江|EJG|xiajiang|xj|1836@xji|新绛|XJV|xinjiang|xj|1837@xji|辛集|ENP|xinji|xj|1838@xji|新江|XJM|xinjiang|xj|1839@xjk|西街口|EKM|xijiekou|xjk|1840@xjt|许家屯|XJT|xujiatun|xjt|1841@xjt|许家台|XTJ|xujiatai|xjt|1842@xjz|谢家镇|XMT|xiejiazhen|xjz|1843@xka|兴凯|EKB|xingkai|xk|1844@xla|小榄|EAQ|xiaolan|xl|1845@xla|香兰|XNB|xianglan|xl|1846@xld|兴隆店|XDD|xinglongdian|xld|1847@xle|新乐|ELP|xinle|xl|1848@xli|新林|XPX|xinlin|xl|1849@xli|小岭|XLB|xiaoling|xl|1850@xli|新李|XLJ|xinli|xl|1851@xli|西林|XYB|xilin|xl|1852@xli|西柳|GCT|xiliu|xl|1853@xli|仙林|XPH|xianlin|xl|1854@xlt|新立屯|XLD|xinlitun|xlt|1855@xlx|兴隆县|EXP|xinglongxian|xlx|1856@xlz|兴隆镇|XZB|xinglongzhen|xlz|1857@xlz|新立镇|XGT|xinlizhen|xlz|1858@xmi|新民|XMD|xinmin|xm|1859@xms|西麻山|XMB|ximashan|xms|1860@xmt|下马塘|XAT|xiamatang|xmt|1861@xna|孝南|XNV|xiaonan|xn|1862@xnb|咸宁北|XRN|xianningbei|xnb|1863@xni|兴宁|ENQ|xingning|xn|1864@xni|咸宁|XNN|xianning|xn|1865@xpd|犀浦东|XAW|xipudong|xpd|1866@xpi|西平|XPN|xiping|xp|1867@xpi|兴平|XPY|xingping|xp|1868@xpt|新坪田|XPM|xinpingtian|xpt|1869@xpu|霞浦|XOS|xiapu|xp|1870@xpu|溆浦|EPQ|xupu|xp|1871@xpu|犀浦|XIW|xipu|xp|1872@xqi|新青|XQB|xinqing|xq|1873@xqi|新邱|XQD|xinqiu|xq|1874@xqp|兴泉堡|XQJ|xingquanbu|xqp|1875@xrq|仙人桥|XRL|xianrenqiao|xrq|1876@xsg|小寺沟|ESP|xiaosigou|xsg|1877@xsh|杏树|XSB|xingshu|xs|1878@xsh|浠水|XZN|xishui|xs|1879@xsh|下社|XSV|xiashe|xs|1880@xsh|小市|XST|xiaoshi|xs|1881@xsh|徐水|XSP|xushui|xs|1882@xsh|夏石|XIZ|xiashi|xs|1883@xsh|小哨|XAM|xiaoshao|xs|1884@xsh|秀山|ETW|xiushan|xs|1885@xsp|新松浦|XOB|xinsongpu|xsp|1886@xst|杏树屯|XDT|xingshutun|xst|1887@xsw|许三湾|XSJ|xusanwan|xsw|1888@xta|湘潭|XTQ|xiangtan|xt|1889@xta|邢台|XTP|xingtai|xt|1890@xta|向塘|XTG|xiangtang|xt|1891@xtx|仙桃西|XAN|xiantaoxi|xtx|1892@xtz|下台子|EIP|xiataizi|xtz|1893@xwe|徐闻|XJQ|xuwen|xw|1894@xwp|新窝铺|EPD|xinwopu|xwp|1895@xwu|修武|XWF|xiuwu|xw|1896@xxi|新县|XSN|xinxian|xx|1897@xxi|息县|ENN|xixian|xx|1898@xxi|西乡|XQY|xixiang|xx|1899@xxi|湘乡|XXQ|xiangxiang|xx|1900@xxi|西峡|XIF|xixia|xx|1901@xxi|孝西|XOV|xiaoxi|xx|1902@xxj|小新街|XXM|xiaoxinjie|xxj|1903@xxx|新兴县|XGQ|xinxingxian|xxx|1904@xxz|西小召|XZC|xixiaozhao|xxz|1905@xxz|小西庄|XXP|xiaoxizhuang|xxz|1906@xya|向阳|XDB|xiangyang|xy|1907@xya|旬阳|XUY|xunyang|xy|1908@xyb|旬阳北|XBY|xunyangbei|xyb|1909@xyd|襄阳东|XWN|xiangyangdong|xyd|1910@xye|兴业|SNZ|xingye|xy|1911@xyg|小雨谷|XHM|xiaoyugu|xyg|1912@xyi|新沂|VIH|xinyi|xy|1913@xyi|兴义|XRZ|xingyi|xy|1914@xyi|信宜|EEQ|xinyi|xy|1915@xyj|小月旧|XFM|xiaoyuejiu|xyj|1916@xyq|小扬气|XYX|xiaoyangqi|xyq|1917@xyu|襄垣|EIF|xiangyuan|xy|1918@xyx|夏邑县|EJH|xiayixian|xyx|1919@xyx|祥云西|EXM|xiangyunxi|xyx|1920@xyy|新友谊|EYB|xinyouyi|xyy|1921@xyz|新阳镇|XZJ|xinyangzhen|xyz|1922@xzd|徐州东|UUH|xuzhoudong|xzd|1923@xzf|新帐房|XZX|xinzhangfang|xzf|1924@xzh|悬钟|XRP|xuanzhong|xz|1925@xzh|新肇|XZT|xinzhao|xz|1926@xzh|忻州|XXV|xinzhou|xz|1927@xzi|汐子|XZD|xizi|xz|1928@xzm|西哲里木|XRD|xizhelimu|xzlm|1929@xzz|新杖子|ERP|xinzhangzi|xzz|1930@yan|姚安|YAC|yaoan|ya|1931@yan|依安|YAX|yian|ya|1932@yan|永安|YAS|yongan|ya|1933@yax|永安乡|YNB|yonganxiang|yax|1934@ybl|亚布力|YBB|yabuli|ybl|1935@ybs|元宝山|YUD|yuanbaoshan|ybs|1936@yca|羊草|YAB|yangcao|yc|1937@ycd|秧草地|YKM|yangcaodi|ycd|1938@ych|阳澄湖|AIH|yangchenghu|ych|1939@ych|迎春|YYB|yingchun|yc|1940@ych|叶城|YER|yecheng|yc|1941@ych|盐池|YKJ|yanchi|yc|1942@ych|砚川|YYY|yanchuan|yc|1943@ych|阳春|YQQ|yangchun|yc|1944@ych|宜城|YIN|yicheng|yc|1945@ych|应城|YHN|yingcheng|yc|1946@ych|禹城|YCK|yucheng|yc|1947@ych|晏城|YEK|yancheng|yc|1948@ych|阳城|YNF|yangcheng|yc|1949@ych|阳岔|YAL|yangcha|yc|1950@ych|郓城|YPK|yuncheng|yc|1951@ych|雁翅|YAP|yanchi|yc|1952@ycl|云彩岭|ACP|yuncailing|ycl|1953@ycx|虞城县|IXH|yuchengxian|ycx|1954@ycz|营城子|YCT|yingchengzi|ycz|1955@yde|英德|YDQ|yingde|yd|1956@yde|永登|YDJ|yongdeng|yd|1957@ydi|尹地|YDM|yindi|yd|1958@ydi|永定|YGS|yongding|yd|1959@ydo|阳东|WLQ|yangdong|yd|1960@yds|雁荡山|YGH|yandangshan|yds|1961@ydu|于都|YDG|yudu|yd|1962@ydu|园墩|YAJ|yuandun|yd|1963@ydx|英德西|IIQ|yingdexi|ydx|1964@yfy|永丰营|YYM|yongfengying|yfy|1965@yga|杨岗|YRB|yanggang|yg|1966@yga|阳高|YOV|yanggao|yg|1967@ygu|阳谷|YIK|yanggu|yg|1968@yha|友好|YOB|youhao|yh|1969@yha|余杭|EVH|yuhang|yh|1970@yhc|沿河城|YHP|yanhecheng|yhc|1971@yhu|岩会|AEP|yanhui|yh|1972@yjh|羊臼河|YHM|yangjiuhe|yjh|1973@yji|永嘉|URH|yongjia|yj|1974@yji|阳江|WRQ|yangjiang|yj|1975@yji|营街|YAM|yingjie|yj|1976@yji|盐津|AEW|yanjin|yj|1977@yji|余江|YHG|yujiang|yj|1978@yji|燕郊|AJP|yanjiao|yj|1979@yji|姚家|YAT|yaojia|yj|1980@yjj|岳家井|YGJ|yuejiajing|yjj|1981@yjp|一间堡|YJT|yijianpu|yjp|1982@yjs|英吉沙|YIR|yingjisha|yjs|1983@yjs|云居寺|AFP|yunjusi|yjs|1984@yjz|燕家庄|AZK|yanjiazhuang|yjz|1985@yka|永康|RFH|yongkang|yk|1986@ykd|营口东|YGT|yingkoudong|ykd|1987@yla|银浪|YJX|yinlang|yl|1988@yla|永郎|YLW|yonglang|yl|1989@ylb|宜良北|YSM|yiliangbei|ylb|1990@yld|永乐店|YDY|yongledian|yld|1991@ylh|伊拉哈|YLX|yilaha|ylh|1992@yli|伊林|YLB|yilin|yl|1993@yli|杨陵|YSY|yangling|yl|1994@yli|彝良|ALW|yiliang|yl|1995@yli|杨林|YLM|yanglin|yl|1996@ylp|余粮堡|YLD|yuliangpu|ylp|1997@ylq|杨柳青|YQP|yangliuqing|ylq|1998@ylt|月亮田|YUM|yueliangtian|ylt|1999@yma|义马|YMF|yima|ym|2000@ymb|阳明堡|YVV|yangmingbu|ymb|2001@yme|玉门|YXJ|yumen|ym|2002@yme|云梦|YMN|yunmeng|ym|2003@ymo|元谋|YMM|yuanmou|ym|2004@yms|一面山|YST|yimianshan|yms|2005@yna|沂南|YNK|yinan|yn|2006@yna|宜耐|YVM|yinai|yn|2007@ynd|伊宁东|YNR|yiningdong|ynd|2008@yps|营盘水|YZJ|yingpanshui|yps|2009@ypu|羊堡|ABM|yangpu|yp|2010@yqb|阳泉北|YPP|yangquanbei|yqb|2011@yqi|乐清|UPH|yueqing|yq|2012@yqi|焉耆|YSR|yanqi|yq|2013@yqi|源迁|AQK|yuanqian|yq|2014@yqt|姚千户屯|YQT|yaoqianhutun|yqht|2015@yqu|阳曲|YQV|yangqu|yq|2016@ysg|榆树沟|YGP|yushugou|ysg|2017@ysh|月山|YBF|yueshan|ys|2018@ysh|玉石|YSJ|yushi|ys|2019@ysh|玉舍|AUM|yushe|ys|2020@ysh|偃师|YSF|yanshi|ys|2021@ysh|沂水|YUK|yishui|ys|2022@ysh|榆社|YSV|yushe|ys|2023@ysh|颍上|YVH|yingshang|ys|2024@ysh|窑上|ASP|yaoshang|ys|2025@ysh|元氏|YSP|yuanshi|ys|2026@ysl|杨树岭|YAD|yangshuling|ysl|2027@ysp|野三坡|AIP|yesanpo|ysp|2028@yst|榆树屯|YSX|yushutun|yst|2029@yst|榆树台|YUT|yushutai|yst|2030@ysz|鹰手营子|YIP|yingshouyingzi|ysyz|2031@yta|源潭|YTQ|yuantan|yt|2032@ytp|牙屯堡|YTZ|yatunpu|ytp|2033@yts|烟筒山|YSL|yantongshan|yts|2034@ytt|烟筒屯|YUX|yantongtun|ytt|2035@yws|羊尾哨|YWM|yangweishao|yws|2036@yxi|阳西|WMQ|yangxi|yx|2037@yxi|越西|YHW|yuexi|yx|2038@yxi|攸县|YOG|youxian|yx|2039@yxi|永修|ACG|yongxiu|yx|2040@yxx|玉溪西|YXM|yuxixi|yxx|2041@yya|弋阳|YIG|yiyang|yy|2042@yya|余姚|YYH|yuyao|yy|2043@yya|酉阳|AFW|youyang|yy|2044@yyd|岳阳东|YIQ|yueyangdong|yyd|2045@yyi|阳邑|ARP|yangyi|yy|2046@yyu|鸭园|YYL|yayuan|yy|2047@yyz|鸳鸯镇|YYJ|yuanyangzhen|yyz|2048@yzb|燕子砭|YZY|yanzibian|yzb|2049@yzh|仪征|UZH|yizheng|yz|2050@yzh|宜州|YSZ|yizhou|yz|2051@yzh|兖州|YZK|yanzhou|yz|2052@yzi|迤资|YQM|yizi|yz|2053@yzw|羊者窝|AEM|yangzhewo|yzw|2054@yzz|杨杖子|YZD|yangzhangzi|yzz|2055@zan|镇安|ZEY|zhenan|za|2056@zan|治安|ZAD|zhian|za|2057@zba|招柏|ZBP|zhaobai|zb|2058@zbw|张百湾|ZUP|zhangbaiwan|zbw|2059@zcc|中川机场|ZJJ|zhongchuanjichang|zcjc|2060@zch|枝城|ZCN|zhicheng|zc|2061@zch|子长|ZHY|zichang|zc|2062@zch|诸城|ZQK|zhucheng|zc|2063@zch|邹城|ZIK|zoucheng|zc|2064@zch|赵城|ZCV|zhaocheng|zc|2065@zda|章党|ZHT|zhangdang|zd|2066@zdi|正定|ZDP|zhengding|zd|2067@zdo|肇东|ZDB|zhaodong|zd|2068@zfp|照福铺|ZFM|zhaofupu|zfp|2069@zgt|章古台|ZGD|zhanggutai|zgt|2070@zgu|赵光|ZGB|zhaoguang|zg|2071@zhe|中和|ZHX|zhonghe|zh|2072@zhm|中华门|VNH|zhonghuamen|zhm|2073@zjb|枝江北|ZIN|zhijiangbei|zjb|2074@zjc|钟家村|ZJY|zhongjiacun|zjc|2075@zjg|朱家沟|ZUB|zhujiagou|zjg|2076@zjg|紫荆关|ZYP|zijingguan|zjg|2077@zji|周家|ZOB|zhoujia|zj|2078@zji|诸暨|ZDH|zhuji|zj|2079@zjn|镇江南|ZEH|zhenjiangnan|zjn|2080@zjt|周家屯|ZOD|zhoujiatun|zjt|2081@zjw|褚家湾|CWJ|zhujiawan|zjw|2082@zjx|湛江西|ZWQ|zhanjiangxi|zjx|2083@zjy|朱家窑|ZUJ|zhujiayao|zjy|2084@zjz|曾家坪子|ZBW|zengjiapingzi|zjpz|2085@zla|张兰|ZLV|zhanglan|zl|2086@zla|镇赉|ZLT|zhenlai|zl|2087@zli|枣林|ZIV|zaolin|zl|2088@zlt|扎鲁特|ZLD|zhalute|zlt|2089@zlx|扎赉诺尔西|ZXX|zhalainuoerxi|zlrex|2090@zmt|樟木头|ZOQ|zhangmutou|zmt|2091@zmu|中牟|ZGF|zhongmu|zm|2092@znd|中宁东|ZDJ|zhongningdong|znd|2093@zni|中宁|VNJ|zhongning|zn|2094@znn|中宁南|ZNJ|zhongningnan|znn|2095@zpi|镇平|ZPF|zhenping|zp|2096@zpi|漳平|ZPS|zhangping|zp|2097@zpu|泽普|ZPR|zepu|zp|2098@zqi|枣强|ZVP|zaoqiang|zq|2099@zqi|张桥|ZQY|zhangqiao|zq|2100@zqi|章丘|ZTK|zhangqiu|zq|2101@zrh|朱日和|ZRC|zhurihe|zrh|2102@zrl|泽润里|ZLM|zerunli|zrl|2103@zsb|中山北|ZGQ|zhongshanbei|zsb|2104@zsd|樟树东|ZOG|zhangshudong|zsd|2105@zsh|珠斯花|ZHD|zhusihua|zsh|2106@zsh|中山|ZSQ|zhongshan|zs|2107@zsh|柞水|ZSY|zhashui|zs|2108@zsh|钟山|ZSZ|zhongshan|zs|2109@zsh|樟树|ZSG|zhangshu|zs|2110@zwo|珠窝|ZOP|zhuwo|zw|2111@zwt|张维屯|ZWB|zhangweitun|zwt|2112@zwu|彰武|ZWD|zhangwu|zw|2113@zxi|棕溪|ZOY|zongxi|zx|2114@zxi|钟祥|ZTN|zhongxiang|zx|2115@zxi|资溪|ZXS|zixi|zx|2116@zxi|镇西|ZVT|zhenxi|zx|2117@zxi|张辛|ZIP|zhangxin|zx|2118@zxq|正镶白旗|ZXC|zhengxiangbaiqi|zxbq|2119@zya|紫阳|ZVY|ziyang|zy|2120@zya|枣阳|ZYN|zaoyang|zy|2121@zyb|竹园坝|ZAW|zhuyuanba|zyb|2122@zye|张掖|ZYJ|zhangye|zy|2123@zyu|镇远|ZUW|zhenyuan|zy|2124@zzd|漳州东|GOS|zhangzhoudong|zzd|2125@zzh|漳州|ZUS|zhangzhou|zz|2126@zzh|壮志|ZUX|zhuangzhi|zz|2127@zzh|子洲|ZZY|zizhou|zz|2128@zzh|中寨|ZZM|zhongzhai|zz|2129@zzh|涿州|ZXP|zhuozhou|zz|2130@zzi|咋子|ZAL|zhazi|zz|2131@zzs|卓资山|ZZC|zhuozishan|zzs|2132@zzx|株洲西|ZAQ|zhuzhouxi|zzx|2133@zzx|郑州西|XPF|zhengzhouxi|zzx|2134@abq|阿巴嘎旗|AQC|abagaqi|abgq|2135@acb|阿城北|ABB|achengbei|acb|2136@aeb|阿尔山北|ARX|aershanbei|aesb|2137@ajd|安江东|ADA|anjiangdong|ajd|2138@alt|阿勒泰|AUR|aletai|alt|2139@are|安仁|ARG|anren|ar|2140@asx|安顺西|ASE|anshunxi|asx|2141@atx|安图西|AXL|antuxi|atx|2142@ayd|安阳东|ADF|anyangdong|ayd|2143@bba|博白|BBZ|bobai|bb|2144@bbu|八步|BBE|babu|bb|2145@bch|栟茶|FWH|bencha|bc|2146@bdd|保定东|BMP|baodingdong|bdd|2147@bel|博尔塔拉|BER|boertala|betl|2148@bfs|八方山|FGQ|bafangshan|bfs|2149@bgo|白沟|FEP|baigou|bg|2150@bha|滨海|YKP|binhai|bh|2151@bhb|滨海北|FCP|binhaibei|bhb|2152@bhg|滨海港|BGU|binhaigang|bhg|2153@bhx|滨海西|FHP|binhaixi|bhx|2154@bjn|宝鸡南|BBY|baojinan|bjn|2155@bjz|北井子|BRT|beijingzi|bjz|2156@blz|八里甸子|BLT|balidianzi|bldz|2157@bmj|白马井|BFQ|baimajing|bmj|2158@bpi|北票|BPT|beipiao|bp|2159@bqi|宝清|BUB|baoqing|bq|2160@bsh|璧山|FZW|bishan|bs|2161@bsp|白沙铺|BSN|baishapu|bsp|2162@bsx|白水县|BGY|baishuixian|bsx|2163@bta|板塘|NGQ|bantang|bt|2164@bwd|白文东|BCV|baiwendong|bwd|2165@bxb|宾西北|BBB|binxibei|bxb|2166@bxc|本溪新城|BVT|benxixincheng|bxxc|2167@bxj|步行街|BWW|buxingjie|bxj|2168@bya|宾阳|UKZ|binyang|by|2169@byd|白洋淀|FWP|baiyangdian|byd|2170@byi|百宜|FHW|baiyi|by|2171@byn|白音华南|FNC|baiyinhuanan|byhn|2172@bzd|巴中东|BDE|bazhongdong|bzd|2173@bzh|彬州|BXY|binzhou|bz|2174@bzh|滨州|BIK|binzhou|bz|2175@bzh|宾州|BZB|binzhou|bz|2176@bzx|霸州西|FOP|bazhouxi|bzx|2177@cch|澄城|CUY|chengcheng|cc|2178@cdb|承德县北|IYP|chengdexianbei|cdxb|2179@cdn|承德南|IVP|chengdenan|cdn|2180@cdx|成都西|CMW|chengduxi|cdx|2181@cfd|曹妃甸东|POP|caofeidiandong|cfdd|2182@cfg|曹妃甸港|PGP|caofeidiangang|cfdg|2183@cgb|城固北|CBY|chenggubei|cgb|2184@cgh|查干湖|VAT|chaganhu|cgh|2185@chd|巢湖东|GUH|chaohudong|chd|2186@cji|从江|KNW|congjiang|cj|2187@cjy|蔡家崖|EBV|caijiaya|cjy|2188@cka|茶卡|CVO|chaka|ck|2189@clh|长临河|FVH|changlinhe|clh|2190@cli|长流|CLA|changliu|cl|2191@cln|茶陵南|CNG|chalingnan|cln|2192@cpd|常平东|FQQ|changpingdong|cpd|2193@cpn|常平南|FPQ|changpingnan|cpn|2194@cqq|长庆桥|CQJ|changqingqiao|cqq|2195@csb|长寿北|COW|changshoubei|csb|2196@csh|长寿湖|CSE|changshouhu|csh|2197@csh|常山|CSU|changshan|cs|2198@csh|潮汕|CBQ|chaoshan|cs|2199@csx|长沙西|RXQ|changshaxi|csx|2200@cti|朝天|CTE|chaotian|ct|2201@ctn|长汀南|CNS|changtingnan|ctn|2202@cwu|长武|CWY|changwu|cw|2203@cxi|长兴|CBH|changxing|cx|2204@cxi|苍溪|CXE|cangxi|cx|2205@cxi|楚雄|CUM|chuxiong|cx|2206@cxi|城西|CIA|chengxi|cx|2207@cya|朝阳|VBT|chaoyang|cy|2208@cya|长阳|CYN|changyang|cy|2209@cya|潮阳|CNQ|chaoyang|cy|2210@cyh|朝阳湖|CYE|chaoyanghu|cyh|2211@czh|崇州|CZE|chongzhou|cz|2212@czt|城子坦|CWT|chengzitan|czt|2213@dad|东安东|DCZ|dongandong|dad|2214@dba|德保|RBZ|debao|db|2215@dch|都昌|DCG|duchang|dc|2216@dch|东岔|DCJ|dongcha|dc|2217@dcn|东城南|IYQ|dongchengnan|dcn|2218@ddh|东戴河|RDD|dongdaihe|ddh|2219@ddx|丹东西|RWT|dandongxi|ddx|2220@deh|东二道河|DRB|dongerdaohe|dedh|2221@dfe|大丰|KRQ|dafeng|df|2222@dfn|大方南|DNE|dafangnan|dfn|2223@dgb|东港北|RGT|donggangbei|dgb|2224@dgs|大孤山|RMT|dagushan|dgs|2225@dgu|东莞|RTQ|dongguan|dg|2226@dhd|鼎湖东|UWQ|dinghudong|dhd|2227@dhs|鼎湖山|NVQ|dinghushan|dhs|2228@dji|道滘|RRQ|daojiao|dj|2229@dji|垫江|DJE|dianjiang|dj|2230@dji|洞井|FWQ|dongjing|dj|2231@djk|董家口|DTK|dongjiakou|djk|2232@dju|大苴|DIM|daju|dj|2233@dko|洞口|DKA|dongkou|dk|2234@dlh|达连河|DCB|dalianhe|dlh|2235@dli|大荔|DNY|dali|dl|2236@dlz|大朗镇|KOQ|dalangzhen|dlz|2237@dml|得莫利|DTB|demoli|dml|2238@dqg|大青沟|DSD|daqinggou|dqg|2239@dqi|德清|DRH|deqing|dq|2240@dsd|东胜东|RSC|dongshengdong|dsd|2241@dsn|砀山南|PRH|dangshannan|dsn|2242@dsn|大石头南|DAL|dashitounan|dstn|2243@dtd|当涂东|OWH|dangtudong|dtd|2244@dtx|大通西|DTO|datongxi|dtx|2245@dwa|大旺|WWQ|dawang|dw|2246@dxb|定西北|DNJ|dingxibei|dxb|2247@dxd|德兴东|DDG|dexingdong|dxd|2248@dxi|德兴|DWG|dexing|dx|2249@dxs|丹霞山|IRQ|danxiashan|dxs|2250@dya|大阳|RET|dayang|dy|2251@dyb|大冶北|DBN|dayebei|dyb|2252@dyd|都匀东|KJW|duyundong|dyd|2253@dyi|大邑|DEE|dayi|dy|2254@dyn|东营南|DOK|dongyingnan|dyn|2255@dyu|大余|DYG|dayu|dy|2256@dzd|定州东|DOP|dingzhoudong|dzd|2257@dzh|端州|WZQ|duanzhou|dz|2258@dzn|大足南|FQW|dazunan|dzn|2259@emi|额敏|EMR|emin|em|2260@ems|峨眉山|IXW|emeishan|ems|2261@epg|阿房宫|EGY|epanggong|epg|2262@ezd|鄂州东|EFN|ezhoudong|ezd|2263@fcb|防城港北|FBZ|fangchenggangbei|fcgb|2264@fcd|凤城东|FDT|fengchengdong|fcd|2265@fch|富川|FDZ|fuchuan|fc|2266@fcx|繁昌西|PUH|fanchangxi|fcx|2267@fdu|丰都|FUW|fengdu|fd|2268@flb|涪陵北|FEW|fulingbei|flb|2269@fli|枫林|FLN|fenglin|fl|2270@fnd|阜宁东|FDU|funingdong|fnd|2271@fni|富宁|FNM|funing|fn|2272@fpi|佛坪|FUY|foping|fp|2273@fqi|法启|FQE|faqi|fq|2274@frn|芙蓉南|KCQ|furongnan|frn|2275@fsh|复盛|FAW|fusheng|fs|2276@fso|抚松|FSL|fusong|fs|2277@fsx|佛山西|FOQ|foshanxi|fsx|2278@fsz|福山镇|FZQ|fushanzhen|fsz|2279@fti|福田|NZQ|futian|ft|2280@fxi|阜新|FOT|fuxin|fx|2281@fya|富阳|FYU|fuyang|fy|2282@fyb|富源北|FBM|fuyuanbei|fyb|2283@fyu|抚远|FYB|fuyuan|fy|2284@fzd|抚州东|FDG|fuzhoudong|fzd|2285@fzh|抚州|FZG|fuzhou|fz|2286@fzh|方正|FNB|fangzheng|fz|2287@fzn|福州 南|FXS|fuzhounan|fzn|2288@gan|高安|GCG|gaoan|ga|2289@gan|广安南|VUW|guangannan|gan|2290@gan|贵安|GAE|guian|ga|2291@gbd|高碑店东|GMP|gaobeidiandong|gbdd|2292@gbk|古北口|GKP|gubeikou|gbk|2293@gch|恭城|GCZ|gongcheng|gc|2294@gcn|藁城南|GUP|gaochengnan|gcn|2295@gdb|贵定北|FMW|guidingbei|gdb|2296@gdn|葛店南|GNN|gediannan|gdn|2297@gdx|贵定县|KIW|guidingxian|gdx|2298@ghb|广汉北|GVW|guanghanbei|ghb|2299@ghu|高花|HGD|gaohua|gh|2300@gju|革居|GEM|geju|gj|2301@gle|高楞|GLB|gaoleng|gl|2302@gli|关岭|GLE|guanling|gl|2303@glx|桂林西|GEZ|guilinxi|glx|2304@gmb|高密北|GVK|gaomibei|gmb|2305@gmc|光明城|IMQ|guangmingcheng|gmc|2306@gni|广宁|FBQ|guangning|gn|2307@gns|广宁寺|GQT|guangningsi|gns|2308@gnx|广南县|GXM|guangnanxian|gnx|2309@gpi|桂平|GAZ|guiping|gp|2310@gpz|弓棚子|GPT|gongpengzi|gpz|2311@gsd|赶水东|GDE|ganshuidong|gsd|2312@gsh|光山|GUN|guangshan|gs|2313@gsh|谷山|FFQ|gushan|gs|2314@gsl|观沙岭|FKQ|guanshaling|gsl|2315@gtb|古田北|GBS|gutianbei|gtb|2316@gtb|广通北|GPM|guangtongbei|gtb|2317@gtn|高台南|GAJ|gaotainan|gtn|2318@gtz|古田会址|STS|gutianhuizhi|gthz|2319@gyb|贵阳北|KQW|guiyangbei|gyb|2320@gyd|贵阳东|KEW|guiyangdong|gyd|2321@gyu|赣榆|GYU|ganyu|gy|2322@gyx|高邑西|GNP|gaoyixi|gyx|2323@han|惠安|HNS|huian|ha|2324@hbb|淮北北|PLH|huaibeibei|hbb|2325@hbd|鹤壁东|HFF|hebidong|hbd|2326@hbs|花博山|KBT|huaboshan|hbs|2327@hcg|寒葱沟|HKB|hanconggou|hcg|2328@hch|霍城|SER|huocheng|hc|2329@hch|珲春|HUL|hunchun|hc|2330@hdd|横道河子东|KUX|hengdaohezidong|hdhzd|2331@hdd|邯郸东|HPP|handandong|hdd|2332@hdo|惠东|KDQ|huidong|hd|2333@hdp|哈达铺|HDJ|hadapu|hdp|2334@hdx|洪洞西|HTV|hongtongxi|hdx|2335@hdx|海东西|HDO|haidongxi|hdx|2336@heb|哈尔滨北|HTB|haerbinbei|hebb|2337@hfc|合肥北城|COH|hefeibeicheng|hfbc|2338@hfn|合肥南|ENH|hefeinan|hfn|2339@hga|黄冈|KGN|huanggang|hg|2340@hgd|黄冈东|KAN|huanggangdong|hgd|2341@hgd|横沟桥东|HNN|henggouqiaodong|hgqd|2342@hgx|黄冈西|KXN|huanggangxi|hgx|2343@hhe|洪河|HPB|honghe|hh|2344@hhn|怀化南|KAQ|huaihuanan|hhn|2345@hhq|黄河景区|HCF|huanghejingqu|hhjq|2346@hhu|惠环|KHQ|huihuan|hh|2347@hhu|花湖|KHN|huahu|hh|2348@hhu|后湖|IHN|houhu|hh|2349@hji|怀集|FAQ|huaiji|hj|2350@hkb|河口北|HBM|hekoubei|hkb|2351@hkl|宏克力|OKB|hongkeli|hkl|2352@hlb|海林北|KBX|hailinbei|hlb|2353@hli|黄流|KLQ|huangliu|hl|2354@hln|黄陵南|VLY|huanglingnan|hln|2355@hme|鲘门|KMQ|houmen|hm|2356@hme|海门|HMU|haimen|hm|2357@hme|虎门|IUQ|humen|hm|2358@hmx|侯马西|HPV|houmaxi|hmx|2359@hna|衡南|HNG|hengnan|hn|2360@hnd|淮南东|HOH|huainandong|hnd|2361@hpu|合浦|HVZ|hepu|hp|2362@hqi|霍邱|FBH|huoqiu|hq|2363@hrd|怀仁东|HFV|huairendong|hrd|2364@hrd|华容东|HPN|huarongdong|hrd|2365@hrn|华容南|KRN|huarongnan|hrn|2366@hsb|黑山北|HQT|heishanbei|hsb|2367@hsb|衡水北|IHP|hengshuibei|hsb|2368@hsb|黄山北|NYH|huangshanbei|hsb|2369@hsb|黄石北|KSN|huangshibei|hsb|2370@hsd|贺胜桥东|HLN|heshengqiaodong|hsqd|2371@hsh|和硕|VUR|heshuo|hs|2372@hsn|花山南|KNN|huashannan|hsn|2373@hss|黑山寺|HVP|heishansi|hss|2374@hta|荷塘|KXQ|hetang|ht|2375@htd|黄土店|HKP|huangtudian|htd|2376@hyb|海阳北|HEK|haiyangbei|hyb|2377@hyb|合阳北|HTY|heyangbei|hyb|2378@hyi|槐荫|IYN|huaiyin|hy|2379@hyi|鄠邑|KXY|huyi|hyi|2380@hyk|花园口|HYT|huayuankou|hyk|2381@hzd|霍州东|HWV|huozhoudong|hzd|2382@hzn|惠州南|KNQ|huizhounan|hzn|2383@jan|建安|JUL|jianan|ja|2384@jch|泾川|JAJ|jingchuan|jc|2385@jch|碱厂|JUT|jianchang|jc|2386@jdb|景德镇北|JDG|jingdezhenbei|jdzb|2387@jde|旌德|NSH|jingde|jd|2388@jde|建德|JDU|jiande|jd|2389@jfe|尖峰|PFQ|jianfeng|jf|2390@jha|近海|JHD|jinhai|jh|2391@jhx|蛟河西|JOL|jiaohexi|jhx|2392@jlb|军粮城北|JMP|junliangchengbei|jlcb|2393@jle|将乐|JLS|jiangle|jl|2394@jlh|贾鲁河|JLF|jialuhe|jlh|2395@jls|九郎山|KJQ|jiulangshan|jls|2396@jmb|即墨北|JVK|jimobei|jmb|2397@jmg|剑门关|JME|jianmenguan|jmg|2398@jmx|佳木斯西|JUB|jiamusixi|jmsx|2399@jnb|建宁县北|JCS|jianningxianbei|jnxb|2400@jnd|济南东|MDK|jinandong|jnd|2401@jni|江宁|JJH|jiangning|jn|2402@jnx|江宁西|OKH|jiangningxi|jnx|2403@jox|建瓯西|JUS|jianouxi|jox|2404@jqn|酒泉南|JNJ|jiuquannan|jqn|2405@jrx|句容西|JWH|jurongxi|jrx|2406@jsh|建水|JSM|jianshui|js|2407@jsh|尖山|JPQ|jianshan|js|2408@jss|界首市|JUN|jieshoushi|jss|2409@jxb|绩溪北|NRH|jixibei|jxb|2410@jxd|介休东|JDV|jiexiudong|jxd|2411@jxi|泾县|LOH|jingxian|jx|2412@jxi|靖西|JMZ|jingxi|jx|2413@jxn|进贤南|JXG|jinxiannan|jxn|2414@jyb|江油北|JBE|jiangyoubei|jyb|2415@jyn|简阳南|JOW|jianyangnan|jyn|2416@jyn|嘉峪关南|JBJ|jiayuguannan|jygn|2417@jyt|金银潭|JTN|jinyintan|jyt|2418@jyu|靖宇|JYL|jingyu|jy|2419@jyw|金月湾|PYQ|jinyuewan|jyw|2420@jyx|缙云西|PYH|jinyunxi|jyx|2421@jzh|景州|JEP|jingzhou|jz|2422@jzh|晋中|JZV|jinzhong|jz|2423@kfb|开封北|KBF|kaifengbei|kfb|2424@kfs|开福寺|FLQ|kaifusi|kfs|2425@khu|开化|KHU|kaihua|kh|2426@kln|凯里南|QKW|kailinan|kln|2427@klu|库伦|KLD|kulun|kl|2428@kmn|昆明南|KOM|kunmingnan|kmn|2429@kta|葵潭|KTQ|kuitan|kt|2430@kya|开阳|KVW|kaiyang|ky|2431@kyu|昆玉|ESR|kunyu|ky|2432@kzu|喀左|KZT|kazuo|kz|2433@lad|隆安东|IDZ|longandong|lad|2434@lbb|来宾北|UCZ|laibinbei|lbb|2435@lbi|灵璧|GMH|lingbi|lb|2436@lbu|寮步|LTQ|liaobu|lb|2437@lby|绿博园|LCF|lvboyuan|lby|2438@lcb|隆昌北|NWW|longchangbei|lcb|2439@lcd|乐昌东|ILQ|lechangdong|lcd|2440@lch|临城|UUP|lincheng|lc|2441@lch|罗城|VCZ|luocheng|lc|2442@lch|陵城|LGK|lingcheng|lc|2443@lcz|老城镇|ACQ|laochengzhen|lcz|2444@ldb|龙洞堡|FVW|longdongbao|ldb|2445@ldn|乐都南|LVO|ledunan|ldn|2446@ldn|娄底南|UOQ|loudinan|ldn|2447@ldo|乐东|UQQ|ledong|ld|2448@ldy|离堆公园|INW|liduigongyuan|ldgy|2449@lfa|娄烦|USV|loufan|lf|2450@lfe|陆丰|LLQ|lufeng|lf|2451@lfe|龙丰|KFQ|longfeng|lf|2452@lfn|禄丰南|LQM|lufengnan|lfn|2453@lfx|临汾西|LXV|linfenxi|lfx|2454@lgn|临高南|KGQ|lingaonan|lgn|2455@lgu|麓谷|BNQ|lugu|lg|2456@lhe|滦河|UDP|luanhe|lh|2457@lhn|珞璜南|LNE|luohuangnan|lhn|2458@lhu|隆回|LHA|longhui|lh|2459@lhx|漯河西|LBN|luohexi|lhx|2460@ljd|罗江东|IKW|luojiangdong|ljd|2461@lji|柳江|UQZ|liujiang|lj|2462@ljn|利津南|LNK|lijinnan|ljn|2463@lkn|兰考南|LUF|lankaonan|lkn|2464@lks|龙口市|UKK|longkoushi|lks|2465@llb|龙里北|KFW|longlibei|llb|2466@llb|兰陵北|COK|lanlingbei|llb|2467@llb|沥林北|KBQ|lilinbei|llb|2468@lld|醴陵东|UKQ|lilingdong|lld|2469@lna|陇南|INJ|longnan|ln|2470@lpn|梁平南|LPE|liangpingnan|lpn|2471@lqi|龙桥|LQU|longqiao|lq|2472@lqu|礼泉|LGY|liquan|lq|2473@lsd|灵石东|UDV|lingshidong|lsd|2474@lsh|乐山|IVW|leshan|ls|2475@lsh|龙市|LAG|longshi|ls|2476@lsh|溧水|LDH|lishui|ls|2477@lsn|娄山关南|LSE|loushanguannan|lsgn|2478@lsx|岚山西|UWK|lanshanxi|lsx|2479@lwj|洛湾三江|KRW|luowansanjiang|lwsj|2480@lxb|莱西北|LBK|laixibei|lxb|2481@lxi|岚县|UXV|lanxian|lx|2482@lya|溧阳|LEH|liyang|ly|2483@lyi|临邑|LUK|linyi|ly|2484@lyn|柳园南|LNR|liuyuannan|lyn|2485@lzb|鹿寨北|LSZ|luzhaibei|lzb|2486@lzb|临淄北|UEK|linzibei|lzb|2487@lzh|阆中|LZE|langzhong|lz|2488@lzn|临泽南|LDJ|linzenan|lzn|2489@mad|马鞍山东|OMH|maanshandong|masd|2490@mch|毛陈|MHN|maochen|mc|2491@mex|帽儿山西|MUB|mershanxi|mesx|2492@mgd|明港东|MDN|minggangdong|mgd|2493@mhn|民和南|MNO|minhenan|mhn|2494@mji|闵集|MJN|minji|mj|2495@mla|马兰|MLR|malan|ml|2496@mle|民乐|MBJ|minle|ml|2497@mle|弥勒|MLM|mile|ml|2498@mns|玛纳斯|MSR|manasi|mns|2499@mpi|牟平|MBK|muping|mp|2500@mqb|闽清北|MBS|minqingbei|mqb|2501@mqb|民权北|MIF|minquanbei|mqb|2502@msd|眉山东|IUW|meishandong|msd|2503@msh|名山|MSE|mingshan|ms|2504@msh|庙山|MSN|miaoshan|ms|2505@mxi|岷县|MXJ|minxian|mx|2506@myu|门源|MYO|menyuan|my|2507@myu|暮云|KIQ|muyun|my|2508@mzb|蒙自北|MBM|mengzibei|mzb|2509@mzh|孟庄|MZF|mengzhuang|mz|2510@mzi|蒙自|MZM|mengzi|mz|2511@nbu|南部|NBE|nanbu|nb|2512@nca|南曹|NEF|nancao|nc|2513@ncb|南充北|NCE|nanchongbei|ncb|2514@nch|南城|NDG|nancheng|nc|2515@nch|南 昌|NOG|nanchang|nc|2516@ncx|南昌西|NXG|nanchangxi|ncx|2517@ndn|宁东南|NDJ|ningdongnan|ndn|2518@ndo|宁东|NOJ|ningdong|nd|2519@nfb|南芬北|NUT|nanfenbei|nfb|2520@nfe|南丰|NFG|nanfeng|nf|2521@nhd|南湖东|NDN|nanhudong|nhd|2522@nhl|牛河梁|LKT|niuheliang|nhl|2523@nhu|南华|NAM|nanhua|nh|2524@njb|内江北|NKW|neijiangbei|njb|2525@nji|南江|FIW|nanjiang|nj|2526@njk|南江口|NDQ|nanjiangkou|njk|2527@nlg|奈林皋|NGT|nailingao|nlg|2528@nli|南陵|LLH|nanling|nl|2529@nmu|尼木|NMO|nimu|nm|2530@nnd|南宁东|NFZ|nanningdong|nnd|2531@nnx|南宁西|NXZ|nanningxi|nnx|2532@npb|南平北|NBS|nanpingbei|npb|2533@npb|南堡北|TLP|nanpubei|npb|2534@nqn|宁强南|NOY|ningqiangnan|nqn|2535@nxi|泥溪|NIE|nixi|nxi|2536@nxi|南雄|NCQ|nanxiong|nx|2537@nyo|纳雍|NYE|nayong|ny|2538@nyz|南阳寨|NYF|nanyangzhai|nyz|2539@pan|普安|PAN|puan|pa|2540@pax|普安县|PUE|puanxian|pax|2541@pbi|屏边|PBM|pingbian|pb|2542@pbn|平坝南|PBE|pingbanan|pbn|2543@pch|平昌|PCE|pingchang|pc|2544@pdi|普定|PGW|puding|pd|2545@pdu|平度|PAK|pingdu|pd|2546@pji|蒲江|PJE|pujiang|pj|2547@pko|皮口|PUT|pikou|pk|2548@plc|盘龙城|PNN|panlongcheng|plc|2549@pls|蓬莱市|POK|penglaishi|pls|2550@pni|普宁|PEQ|puning|pn|2551@pnn|平南南|PAZ|pingnannan|pnn|2552@pqb|平泉北|PBP|pingquanbei|pqb|2553@psb|彭山北|PPW|pengshanbei|psb|2554@psh|屏山|PSE|pingshan|psh|2555@psh|盘山|PUD|panshan|ps|2556@psh|坪上|PSK|pingshang|ps|2557@pxb|萍乡北|PBG|pingxiangbei|pxb|2558@pya|鄱阳|PYG|poyang|py|2559@pya|濮阳|PYF|puyang|py|2560@pyc|平遥古城|PDV|pingyaogucheng|pygc|2561@pyd|平原东|PUK|pingyuandong|pyd|2562@pzh|普者黑|PZM|puzhehei|pzh|2563@pzh|盘州|PAE|panzhou|pz|2564@pzh|彭州|PMW|pengzhou|pz|2565@pzn|彭州南|PKW|pengzhounan|pzn|2566@qan|秦安|QGJ|qinan|qa|2567@qbd|青白江东|QFW|qingbaijiangdong|qbjd|2568@qch|青川|QCE|qingchuan|qc|2569@qdb|青岛北|QHK|qingdaobei|qdb|2570@qdh|千岛湖|QDU|qiandaohu|qdh|2571@qdo|祁东|QMQ|qidong|qd|2572@qdo|启东|QOU|qidong|qd|2573@qdu|青堆|QET|qingdui|qd|2574@qdx|青岛西|QUK|qingdaoxi|qdx|2575@qfe|前锋|QFB|qianfeng|qf|2576@qhb|清河门北|QBD|qinghemenbei|qhmb|2577@qhe|齐河|QIK|qihe|qh|2578@qjb|曲靖北|QBM|qujingbei|qjb|2579@qjd|綦江东|QDE|qijiangdong|qjd|2580@qji|曲江|QIM|qujiang|qj|2581@qla|邛崃|QLE|qionglai|ql|2582@qli|青莲|QEW|qinglian|ql|2583@qqn|齐齐哈尔南|QNB|qiqihaernan|qqhen|2584@qsb|清水北|QEJ|qingshuibei|qsb|2585@qsh|青神|QVW|qingshen|qs|2586@qsh|岐山|QAY|qishan|qs|2587@qsh|庆盛|QSQ|qingsheng|qs|2588@qsx|清水县|QIJ|qingshuixian|qsx|2589@qsx|曲水县|QSO|qushuixian|qsx|2590@qwe|犍为|JWE|qianwei|qwe|2591@qxd|祁县东|QGV|qixiandong|qxd|2592@qxi|乾县|QBY|qianxian|qx|2593@qxn|旗下营南|QNC|qixiayingnan|qxyn|2594@qya|祁阳|QWQ|qiyang|qy|2595@qzb|青州市北|QOK|qingzhoushibei|qzsb|2596@qzd|乔庄东|QEP|qiaozhuangdong|qzd|2597@qzn|全州南|QNZ|quanzhounan|qzn|2598@qzw|棋子湾|QZQ|qiziwan|qzw|2599@rbu|仁布|RUO|renbu|rb|2600@rcb|荣昌北|RQW|rongchangbei|rcb|2601@rch|荣成|RCK|rongcheng|rc|2602@rcx|瑞昌西|RXG|ruichangxi|rcx|2603@rdo|如东|RIH|rudong|rd|2604@rji|榕江|RVW|rongjiang|rj|2605@rkz|日喀则|RKO|rikaze|rkz|2606@rpi|饶平|RVQ|raoping|rp|2607@rzx|日照西|KZK|rizhaoxi|rzx|2608@scl|宋城路|SFF|songchenglu|scl|2609@sdh|三道湖|SDL|sandaohu|sdh|2610@sdo|邵东|FIQ|shaodong|sd|2611@sdx|三都县|KKW|sanduxian|sdx|2612@sfa|胜芳|SUP|shengfang|sf|2613@sfb|双峰北|NFQ|shuangfengbei|sfb|2614@she|商河|SOK|shanghe|sh|2615@sho|泗洪|GQH|sihong|sh|2616@shs|双河市|OHR|shuangheshi|shs|2617@shu|四会|AHQ|sihui|sh|2618@sjd|石家庄东|SXP|shijiazhuangdong|sjzd|2619@sjn|三江南|SWZ|sanjiangnan|sjn|2620@sjz|三井子|OJT|sanjingzi|sjz|2621@sks|四棵树|SIR|sikeshu|sks|2622@slc|双流机场|IPW|shuangliujichang|sljc|2623@slh|双龙湖|OHB|shuanglonghu|slh|2624@slx|石林西|SYM|shilinxi|slx|2625@slx|双流西|IQW|shuangliuxi|slx|2626@slz|胜利镇|OLB|shenglizhen|slz|2627@smb|三明北|SHS|sanmingbei|smb|2628@smi|三明|SVS|sanming|sm|2629@smi|嵩明|SVM|songming|sm|2630@sml|树木岭|FMQ|shumuling|sml|2631@smu|神木|HMY|shenmu|sm|2632@snq|苏尼特左旗|ONC|sunitezuoqi|sntzq|2633@spd|山坡东|SBN|shanpodong|spd|2634@sqi|石桥|SQE|shiqiao|sq|2635@sqi|沈丘|SQN|shenqiu|sq|2636@ssb|鄯善北|SMR|shanshanbei|ssb|2637@ssb|狮山北|NSQ|shishanbei|ssb|2638@ssb|三水北|ARQ|sanshuibei|ssb|2639@ssb|松山湖北|KUQ|songshanhubei|sshb|2640@ssh|狮山|KSQ|shishan|ss|2641@ssn|三水南|RNQ|sanshuinan|ssn|2642@ssn|韶山南|INQ|shaoshannan|ssn|2643@ssu|三穗|QHW|sansui|ss|2644@sti|石梯|STE|shiti|st|2645@swe|汕尾|OGQ|shanwei|sw|2646@sxb|歙县北|NPH|shexianbei|sxb|2647@sxb|绍兴北|SLH|shaoxingbei|sxb|2648@sxd|绍兴东|SSH|shaoxingdong|sxd|2649@sxi|泗县|GPH|sixian|sx|2650@sxi|始兴|IPQ|shixing|sx|2651@sya|双洋|SQS|shuangyang|sy|2652@sya|泗阳|MPH|siyang|sy|2653@sya|三阳|SYU|sanyang|sy|2654@sya|射阳|SAU|sheyang|sy|2655@sya|双阳|OYT|shuangyang|sy|2656@syb|邵阳北|OVQ|shaoyangbei|syb|2657@syb|松原北|OCT|songyuanbei|syb|2658@syi|山阴|SNV|shanyin|sy|2659@syx|邵阳西|SXA|shaoyangxi|syx|2660@syx|沈阳西|OOT|shenyangxi|syx|2661@szb|深圳北|IOQ|shenzhenbei|szb|2662@szh|神州|S
Download .txt
gitextract_po6zbghf/

├── README.md
├── lib/
│   ├── activation-1.1.1.jar
│   ├── hutool-all-4.6.6.jar
│   ├── javax.mail-1.5.4.jar
│   └── snakeyaml-1.25.jar
└── src/
    ├── com/
    │   └── kalvin/
    │       └── J12306/
    │           ├── AI/
    │           │   ├── Easy12306AI.java
    │           │   └── ImageAI.java
    │           ├── Go12306.java
    │           ├── Main.java
    │           ├── api/
    │           │   ├── AlternateOrder.java
    │           │   ├── Captcha.java
    │           │   ├── CheckCaptcha.java
    │           │   ├── CheckOrderInfo.java
    │           │   ├── CheckRandCodeAsync.java
    │           │   ├── CheckUser.java
    │           │   ├── ConfirmSingleForQueue.java
    │           │   ├── GetJS.java
    │           │   ├── GetPassCodeNew.java
    │           │   ├── GetQueueCount.java
    │           │   ├── Login.java
    │           │   ├── MyOrder.java
    │           │   ├── PassengerDTOS.java
    │           │   ├── QueryOrderWaitTime.java
    │           │   ├── RepeatSubmitToken.java
    │           │   ├── SubmitOrderRequest.java
    │           │   └── Ticket.java
    │           ├── cache/
    │           │   └── TicketCache.java
    │           ├── config/
    │           │   ├── Constants.java
    │           │   ├── TicketSeatType.java
    │           │   ├── UrlConfig.java
    │           │   ├── Urls.java
    │           │   └── UrlsEnum.java
    │           ├── dto/
    │           │   ├── SubmitTicketInfoDTO.java
    │           │   ├── TicketInfoDTO.java
    │           │   └── UserInfoDTO.java
    │           ├── exception/
    │           │   └── J12306Exception.java
    │           ├── http/
    │           │   └── Session.java
    │           └── utils/
    │               ├── EmailUtil.java
    │               ├── J12306Util.java
    │               ├── StationUtil.java
    │               └── YmlUtil.java
    └── config.yml
Download .txt
SYMBOL INDEX (247 symbols across 36 files)

FILE: src/com/kalvin/J12306/AI/Easy12306AI.java
  class Easy12306AI (line 15) | public class Easy12306AI implements ImageAI {
    method Easy12306AI (line 22) | public Easy12306AI(String aiUrl, String imgPath) {
    method printCode (line 27) | @Override

FILE: src/com/kalvin/J12306/AI/ImageAI.java
  type ImageAI (line 7) | public interface ImageAI {
    method printCode (line 13) | String printCode();

FILE: src/com/kalvin/J12306/Go12306.java
  class Go12306 (line 28) | public class Go12306 {
    method newInstance (line 48) | public static Go12306 newInstance() {
    method initUser (line 52) | public Go12306 initUser(String username, String password) {
    method initBookTicketInfo (line 66) | public Go12306 initBookTicketInfo(String trainDate, String fromStation...
    method run (line 83) | public void run() {

FILE: src/com/kalvin/J12306/Main.java
  class Main (line 6) | public class Main {
    method main (line 8) | public static void main(String[] args) {
    method selectTicket1 (line 19) | public static void selectTicket1() {
    method selectTicket2 (line 30) | public static void selectTicket2() {

FILE: src/com/kalvin/J12306/api/AlternateOrder.java
  class AlternateOrder (line 24) | public class AlternateOrder {
    method AlternateOrder (line 36) | public AlternateOrder(Session session, String secretStr, String allEnc...
    method checkFace (line 44) | public boolean checkFace() {
    method getSuccessRate (line 70) | public void getSuccessRate() {
    method submitOrderRequestAN (line 88) | private void submitOrderRequestAN() {
    method lineUpToPayInit (line 105) | private void lineUpToPayInit() {
    method passengerInitApi (line 109) | private void passengerInitApi() {
    method confirmHB (line 121) | private void confirmHB() {
    method queryQueue (line 139) | private void queryQueue() {
    method getSecretList (line 159) | private String getSecretList() {
    method getSuccessSecret (line 166) | private String getSuccessSecret() {
    method getConfirmHBParams (line 173) | private HashMap<String, Object> getConfirmHBParams() {
    method getPassengerInfo (line 190) | private String getPassengerInfo() {

FILE: src/com/kalvin/J12306/api/Captcha.java
  class Captcha (line 24) | public class Captcha {
    method Captcha (line 30) | public Captcha(Session session) {
    method getLoginCaptchaImg (line 37) | public void getLoginCaptchaImg() {
    method getOrderCaptchaImg (line 49) | public String getOrderCaptchaImg() {
    method checkLoginCaptchaImg (line 59) | public boolean checkLoginCaptchaImg() {
    method getNewLoginCaptchaImgFileName (line 82) | private String getNewLoginCaptchaImgFileName() {
    method getNewOrderCaptchaImgFileName (line 86) | private String getNewOrderCaptchaImgFileName() {

FILE: src/com/kalvin/J12306/api/CheckCaptcha.java
  class CheckCaptcha (line 7) | public class CheckCaptcha {

FILE: src/com/kalvin/J12306/api/CheckOrderInfo.java
  class CheckOrderInfo (line 19) | public class CheckOrderInfo {
    method CheckOrderInfo (line 36) | public CheckOrderInfo(Session session, String repeatSubmitToken, Strin...
    method send (line 54) | public void send() {

FILE: src/com/kalvin/J12306/api/CheckRandCodeAsync.java
  class CheckRandCodeAsync (line 17) | public class CheckRandCodeAsync {
    method CheckRandCodeAsync (line 25) | public CheckRandCodeAsync(Session session, String randCode, String rep...
    method send (line 31) | public boolean send() {

FILE: src/com/kalvin/J12306/api/CheckUser.java
  class CheckUser (line 7) | public class CheckUser {

FILE: src/com/kalvin/J12306/api/ConfirmSingleForQueue.java
  class ConfirmSingleForQueue (line 24) | public class ConfirmSingleForQueue {
    method ConfirmSingleForQueue (line 38) | public ConfirmSingleForQueue(Session session, String repeatSubmitToken...
    method send (line 52) | public void send() {

FILE: src/com/kalvin/J12306/api/GetJS.java
  class GetJS (line 10) | public class GetJS {
    method GetJS (line 14) | public GetJS(Session session) {
    method send (line 18) | public void send() {

FILE: src/com/kalvin/J12306/api/GetPassCodeNew.java
  class GetPassCodeNew (line 7) | public class GetPassCodeNew {

FILE: src/com/kalvin/J12306/api/GetQueueCount.java
  class GetQueueCount (line 22) | public class GetQueueCount {
    method GetQueueCount (line 41) | public GetQueueCount(Session session, String repeatSubmitToken, String...
    method send (line 61) | public void send() {

FILE: src/com/kalvin/J12306/api/Login.java
  class Login (line 27) | public class Login {
    method Login (line 34) | public Login(Session session, String username, String password) {
    method send (line 40) | public UserInfoDTO send() {
    method initLogDevice (line 85) | private void initLogDevice() {
    method fillLogDeviceUrlParams (line 110) | private String fillLogDeviceUrlParams(String url) {
    method userLogin (line 163) | private void userLogin() {
    method passport (line 167) | private void passport() {
    method postUamTK (line 178) | private boolean postUamTK(String uamTK) {
    method postUamAuthClient (line 209) | private boolean postUamAuthClient() {
    method getUserInfo (line 229) | private UserInfoDTO getUserInfo() {

FILE: src/com/kalvin/J12306/api/MyOrder.java
  class MyOrder (line 18) | public class MyOrder {
    method MyOrder (line 24) | public MyOrder(Session session) {
    method init (line 28) | public void init() {
    method queryMyNoComplete (line 38) | public HttpResponse queryMyNoComplete() {
    method check (line 52) | public State check() {
    method cancelNoComplete (line 76) | public void cancelNoComplete(String sequenceNo) {
    class State (line 94) | public static class State {
      method State (line 111) | private State(String code, String sequenceNo) {
      method noPay (line 116) | private static State noPay(String sequenceNo) {
      method queue (line 120) | private static State queue(String sequenceNo) {
      method fail (line 124) | private static State fail() {
      method getCode (line 128) | public String getCode() {
      method getSequenceNo (line 132) | public String getSequenceNo() {

FILE: src/com/kalvin/J12306/api/PassengerDTOS.java
  class PassengerDTOS (line 22) | public class PassengerDTOS {
    method PassengerDTOS (line 28) | public PassengerDTOS(Session session) {
    method PassengerDTOS (line 32) | public PassengerDTOS(Session session, String repeatSubmitToken, String...
    method getPassengerTicketStr (line 42) | public String getPassengerTicketStr() {
    method getPassengerEncStr (line 72) | public String getPassengerEncStr() {
    method getOldPassengerStr (line 92) | public String getOldPassengerStr() {

FILE: src/com/kalvin/J12306/api/QueryOrderWaitTime.java
  class QueryOrderWaitTime (line 23) | public class QueryOrderWaitTime {
    method QueryOrderWaitTime (line 31) | public QueryOrderWaitTime(Session session, String repeatSubmitToken, S...
    method send (line 37) | public void send() {

FILE: src/com/kalvin/J12306/api/RepeatSubmitToken.java
  class RepeatSubmitToken (line 15) | public class RepeatSubmitToken {
    method RepeatSubmitToken (line 19) | public RepeatSubmitToken(Session session) {
    method getSubmitTicketInfo (line 27) | public SubmitTicketInfoDTO getSubmitTicketInfo() {

FILE: src/com/kalvin/J12306/api/SubmitOrderRequest.java
  class SubmitOrderRequest (line 23) | public class SubmitOrderRequest {
    method SubmitOrderRequest (line 37) | public SubmitOrderRequest(Session session, String secretStr, String se...
    method send (line 49) | public void send() {

FILE: src/com/kalvin/J12306/api/Ticket.java
  class Ticket (line 15) | public class Ticket {
    method Ticket (line 25) | public Ticket(Session session, String trainDate, String fromStation, S...
    method query (line 37) | private HttpResponse query(String type) {
    method queryA (line 61) | public HttpResponse queryA() {
    method queryZ (line 65) | public HttpResponse queryZ() {

FILE: src/com/kalvin/J12306/cache/TicketCache.java
  class TicketCache (line 12) | public class TicketCache {
    method getInstance (line 23) | public static TicketCache getInstance() {
    method put (line 34) | public void put(String key, Object value) {
    method put (line 38) | public synchronized void put(String key, Object value, long expire) {
    method get (line 51) | public Object get(String key) {
    method size (line 55) | public int size() {

FILE: src/com/kalvin/J12306/config/Constants.java
  class Constants (line 8) | public class Constants {

FILE: src/com/kalvin/J12306/config/TicketSeatType.java
  type TicketSeatType (line 7) | public enum  TicketSeatType {
    method TicketSeatType (line 22) | TicketSeatType(String code, String name) {
    method get (line 27) | public static TicketSeatType get(String code) {
    method getCode (line 36) | public String getCode() {
    method getName (line 40) | public String getName() {

FILE: src/com/kalvin/J12306/config/UrlConfig.java
  class UrlConfig (line 6) | public class UrlConfig {
    method UrlConfig (line 12) | public UrlConfig(String url, String method, String referer) {
    method getUrl (line 18) | public String getUrl() {
    method setUrl (line 22) | public void setUrl(String url) {
    method getMethod (line 26) | public String getMethod() {
    method setMethod (line 30) | public void setMethod(String method) {
    method getHost (line 34) | public String getHost() {
    method setHost (line 38) | public void setHost(String host) {
    method getReferer (line 42) | public String getReferer() {
    method setReferer (line 46) | public void setReferer(String referer) {

FILE: src/com/kalvin/J12306/config/Urls.java
  class Urls (line 7) | @Deprecated

FILE: src/com/kalvin/J12306/config/UrlsEnum.java
  type UrlsEnum (line 7) | public enum UrlsEnum {
    method UrlsEnum (line 202) | UrlsEnum(UrlConfig urlConfig) {
    method getUrlConfig (line 206) | public UrlConfig getUrlConfig() {
    method setUrlConfig (line 210) | public void setUrlConfig(UrlConfig urlConfig) {

FILE: src/com/kalvin/J12306/dto/SubmitTicketInfoDTO.java
  class SubmitTicketInfoDTO (line 7) | public class SubmitTicketInfoDTO {
    method getRepeatSubmitToken (line 14) | public String getRepeatSubmitToken() {
    method setRepeatSubmitToken (line 18) | public void setRepeatSubmitToken(String repeatSubmitToken) {
    method getKeyCheckIsChange (line 22) | public String getKeyCheckIsChange() {
    method setKeyCheckIsChange (line 26) | public void setKeyCheckIsChange(String keyCheckIsChange) {
    method getPurposeCodes (line 30) | public String getPurposeCodes() {
    method setPurposeCodes (line 34) | public void setPurposeCodes(String purposeCodes) {
    method getLeftTicketStr (line 38) | public String getLeftTicketStr() {
    method setLeftTicketStr (line 42) | public void setLeftTicketStr(String leftTicketStr) {
    method toString (line 46) | @Override

FILE: src/com/kalvin/J12306/dto/TicketInfoDTO.java
  class TicketInfoDTO (line 7) | public class TicketInfoDTO {
    method isOnSale (line 34) | public boolean isOnSale() {
    method setOnSale (line 38) | public void setOnSale(boolean onSale) {
    method getSecretStr (line 42) | public String getSecretStr() {
    method setSecretStr (line 46) | public void setSecretStr(String secretStr) {
    method getTrainNo (line 50) | public String getTrainNo() {
    method setTrainNo (line 54) | public void setTrainNo(String trainNo) {
    method getTrainNum (line 58) | public String getTrainNum() {
    method setTrainNum (line 62) | public void setTrainNum(String trainNum) {
    method getFormStationName (line 66) | public String getFormStationName() {
    method setFormStationName (line 70) | public void setFormStationName(String formStationName) {
    method getToStationName (line 74) | public String getToStationName() {
    method setToStationName (line 78) | public void setToStationName(String toStationName) {
    method getFormStationTelecode (line 82) | public String getFormStationTelecode() {
    method setFormStationTelecode (line 86) | public void setFormStationTelecode(String formStationTelecode) {
    method getToStationTelecode (line 90) | public String getToStationTelecode() {
    method setToStationTelecode (line 94) | public void setToStationTelecode(String toStationTelecode) {
    method getGoOffTime (line 98) | public String getGoOffTime() {
    method setGoOffTime (line 102) | public void setGoOffTime(String goOffTime) {
    method getArrivalTime (line 106) | public String getArrivalTime() {
    method setArrivalTime (line 110) | public void setArrivalTime(String arrivalTime) {
    method getLastTime (line 114) | public String getLastTime() {
    method setLastTime (line 118) | public void setLastTime(String lastTime) {
    method getLeftTicket (line 122) | public String getLeftTicket() {
    method setLeftTicket (line 126) | public void setLeftTicket(String leftTicket) {
    method getTrainLocation (line 130) | public String getTrainLocation() {
    method setTrainLocation (line 134) | public void setTrainLocation(String trainLocation) {
    method getBusinessSeat (line 138) | public String getBusinessSeat() {
    method setBusinessSeat (line 142) | public void setBusinessSeat(String businessSeat) {
    method getL1Seat (line 146) | public String getL1Seat() {
    method setL1Seat (line 150) | public void setL1Seat(String l1Seat) {
    method getL2Seat (line 154) | public String getL2Seat() {
    method setL2Seat (line 158) | public void setL2Seat(String l2Seat) {
    method getL1SoftBerth (line 162) | public String getL1SoftBerth() {
    method setL1SoftBerth (line 166) | public void setL1SoftBerth(String l1SoftBerth) {
    method getL2HardBerth (line 170) | public String getL2HardBerth() {
    method setL2HardBerth (line 174) | public void setL2HardBerth(String l2HardBerth) {
    method getHardSeat (line 178) | public String getHardSeat() {
    method setHardSeat (line 182) | public void setHardSeat(String hardSeat) {
    method getSoftSeat (line 186) | public String getSoftSeat() {
    method setSoftSeat (line 190) | public void setSoftSeat(String softSeat) {
    method getNoSeat (line 194) | public String getNoSeat() {
    method setNoSeat (line 198) | public void setNoSeat(String noSeat) {
    method isCanAlternate (line 202) | public boolean isCanAlternate() {
    method setCanAlternate (line 206) | public void setCanAlternate(boolean canAlternate) {
    method getCanNotAlternateSeatType (line 210) | public String getCanNotAlternateSeatType() {
    method setCanNotAlternateSeatType (line 214) | public void setCanNotAlternateSeatType(String canNotAlternateSeatType) {
    method toString (line 218) | @Override

FILE: src/com/kalvin/J12306/dto/UserInfoDTO.java
  class UserInfoDTO (line 7) | public class UserInfoDTO {
    method getName (line 17) | public String getName() {
    method setName (line 21) | public void setName(String name) {
    method getUsername (line 25) | public String getUsername() {
    method setUsername (line 29) | public void setUsername(String username) {
    method getIdTypeCode (line 33) | public String getIdTypeCode() {
    method setIdTypeCode (line 37) | public void setIdTypeCode(String idTypeCode) {
    method getIdTypeName (line 41) | public String getIdTypeName() {
    method setIdTypeName (line 45) | public void setIdTypeName(String idTypeName) {
    method getIdNo (line 49) | public String getIdNo() {
    method setIdNo (line 53) | public void setIdNo(String idNo) {
    method getEmail (line 57) | public String getEmail() {
    method setEmail (line 61) | public void setEmail(String email) {
    method getUserEncStr (line 65) | public String getUserEncStr() {
    method setUserEncStr (line 69) | public void setUserEncStr(String userEncStr) {
    method toString (line 73) | @Override

FILE: src/com/kalvin/J12306/exception/J12306Exception.java
  class J12306Exception (line 7) | public class J12306Exception extends RuntimeException {
    method J12306Exception (line 10) | public J12306Exception(String message) {
    method J12306Exception (line 15) | public J12306Exception(int errorCode, String message) {
    method J12306Exception (line 20) | public J12306Exception(String message, Throwable cause) {
    method getMsg (line 25) | public String getMsg() {

FILE: src/com/kalvin/J12306/http/Session.java
  class Session (line 20) | public class Session {
    method Session (line 26) | public Session() {
    method getToken (line 30) | public String getToken() {
    method setToken (line 34) | public void setToken(String token) {
    method getCookie (line 38) | public String getCookie() {
    method setCookie (line 42) | public void setCookie(String cookie) {
    method setCookie (line 51) | public void setCookie(List<HttpCookie> cookies) {
    class HttpClient (line 62) | public class HttpClient {
      method HttpClient (line 66) | private HttpClient() {
      method send (line 69) | public HttpResponse send(UrlsEnum urlsEnum) {
      method send (line 73) | public HttpResponse send(UrlsEnum urlsEnum, HashMap<String, Object> ...
      method sendAsync (line 77) | public HttpResponse sendAsync(UrlsEnum urlsEnum) {
      method sendAsync (line 81) | public HttpResponse sendAsync(UrlsEnum urlsEnum, HashMap<String, Obj...
      method send (line 85) | public HttpResponse send(UrlsEnum urlsEnum, HashMap<String, Object> ...
      method getMethod (line 116) | private Method getMethod(String methodStr) {
      method setHeader (line 120) | public void setHeader(HashMap<String, String> headers) {
      method getHeader (line 124) | public String getHeader(String name) {

FILE: src/com/kalvin/J12306/utils/EmailUtil.java
  class EmailUtil (line 12) | public class EmailUtil {
    method initAccount (line 18) | private static void initAccount() {
    method send (line 28) | public static void send(String subject, String content) {
    method sendTest (line 39) | public static void sendTest() {

FILE: src/com/kalvin/J12306/utils/J12306Util.java
  class J12306Util (line 33) | public class J12306Util {
    method genRandNumber (line 37) | public static String genRandNumber() {
    method sleep (line 41) | public static void sleep(int second) {
    method sleepM (line 50) | public static void sleepM(int millisecond) {
    method getCaptchaPos (line 58) | public static String getCaptchaPos(String codeIdx) {
    method parseTicketInfo (line 75) | public static List<TicketInfoDTO> parseTicketInfo(String ticketRes) {
    method urlDecode (line 124) | public static String urlDecode(String str) {
    method formatDateGMT (line 134) | public static String formatDateGMT(String dateStr) {
    method hasTicket (line 140) | public static boolean hasTicket(String seatInfo) {
    method getSeatsTicketInfo (line 144) | public static LinkedHashMap<String, Boolean> getSeatsTicketInfo(String...
    method noNeedTicket (line 175) | public static boolean noNeedTicket(LinkedHashMap<String, Boolean> seat...
    method formatDateStr (line 184) | public static String formatDateStr(String dateStr) {
    method printlnLeftTicket (line 194) | public static void printlnLeftTicket(String trainDate, String fromStat...
    method getCurrAftOneMinuteTime (line 205) | public static String getCurrAftOneMinuteTime() {
    method getAfter5MinuteTime (line 213) | public static String getAfter5MinuteTime(String time) {
    method getCurrTime (line 220) | public static String getCurrTime() {

FILE: src/com/kalvin/J12306/utils/StationUtil.java
  class StationUtil (line 13) | public class StationUtil {
    method getStationNamesStr (line 17) | private static String getStationNamesStr() {
    method getAllStationNames (line 29) | public static HashMap<String, String> getAllStationNames() {
    method getStationName (line 48) | public static String getStationName(String stationCode) {
    method getStationCode (line 59) | public static String getStationCode(String stationName) {

FILE: src/com/kalvin/J12306/utils/YmlUtil.java
  class YmlUtil (line 13) | public class YmlUtil {
    method loadYml (line 27) | private static void loadYml() {
    method getValue (line 32) | private static Object getValue(String key) {
    method get (line 46) | public static Object get(String key) {
Condensed preview — 42 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (334K chars).
[
  {
    "path": "README.md",
    "chars": 4074,
    "preview": "# J12306抢票助手\n12306抢票程序JAVA版,自动登录-验证-查票-购票/自动候补。只需简单的配置即可运行进行快捷抢票。\n\n### 使用说明\n##### 引入jar依赖\n* 手动添加项目lib文件夹中的依赖包\n##### 配置文件"
  },
  {
    "path": "src/com/kalvin/J12306/AI/Easy12306AI.java",
    "chars": 1900,
    "preview": "package com.kalvin.J12306.AI;\n\nimport cn.hutool.http.HttpRequest;\nimport cn.hutool.http.HttpUtil;\nimport cn.hutool.log.L"
  },
  {
    "path": "src/com/kalvin/J12306/AI/ImageAI.java",
    "chars": 222,
    "preview": "package com.kalvin.J12306.AI;\n\n/**\n * 图片验证码识别AI接口\n * Create by Kalvin on 2019/9/19.\n */\npublic interface ImageAI {\n\n    "
  },
  {
    "path": "src/com/kalvin/J12306/Go12306.java",
    "chars": 11016,
    "preview": "package com.kalvin.J12306;\n\nimport cn.hutool.core.util.StrUtil;\nimport cn.hutool.http.HttpException;\nimport cn.hutool.ht"
  },
  {
    "path": "src/com/kalvin/J12306/Main.java",
    "chars": 1564,
    "preview": "package com.kalvin.J12306;\n\nimport com.kalvin.J12306.utils.EmailUtil;\nimport com.kalvin.J12306.utils.J12306Util;\n\npublic"
  },
  {
    "path": "src/com/kalvin/J12306/api/AlternateOrder.java",
    "chars": 8304,
    "preview": "package com.kalvin.J12306.api;\n\nimport cn.hutool.http.HttpResponse;\nimport cn.hutool.json.JSON;\nimport cn.hutool.json.JS"
  },
  {
    "path": "src/com/kalvin/J12306/api/Captcha.java",
    "chars": 3393,
    "preview": "package com.kalvin.J12306.api;\n\nimport cn.hutool.core.util.RandomUtil;\nimport cn.hutool.core.util.StrUtil;\nimport cn.hut"
  },
  {
    "path": "src/com/kalvin/J12306/api/CheckCaptcha.java",
    "chars": 113,
    "preview": "package com.kalvin.J12306.api;\n\n/**\n * 校验验证码\n * Create by Kalvin on 2019/9/19.\n */\npublic class CheckCaptcha {\n}\n"
  },
  {
    "path": "src/com/kalvin/J12306/api/CheckOrderInfo.java",
    "chars": 4163,
    "preview": "package com.kalvin.J12306.api;\n\nimport cn.hutool.http.HttpResponse;\nimport cn.hutool.json.JSON;\nimport cn.hutool.json.JS"
  },
  {
    "path": "src/com/kalvin/J12306/api/CheckRandCodeAsync.java",
    "chars": 1397,
    "preview": "package com.kalvin.J12306.api;\n\nimport cn.hutool.http.HttpResponse;\nimport cn.hutool.json.JSON;\nimport cn.hutool.json.JS"
  },
  {
    "path": "src/com/kalvin/J12306/api/CheckUser.java",
    "chars": 111,
    "preview": "package com.kalvin.J12306.api;\n\n/**\n * 检查用户状态\n * Create by Kalvin on 2019/9/19.\n */\npublic class CheckUser {\n}\n"
  },
  {
    "path": "src/com/kalvin/J12306/api/ConfirmSingleForQueue.java",
    "chars": 5656,
    "preview": "package com.kalvin.J12306.api;\n\nimport cn.hutool.http.HttpResponse;\nimport cn.hutool.json.JSON;\nimport cn.hutool.json.JS"
  },
  {
    "path": "src/com/kalvin/J12306/api/GetJS.java",
    "chars": 381,
    "preview": "package com.kalvin.J12306.api;\n\nimport com.kalvin.J12306.config.UrlsEnum;\nimport com.kalvin.J12306.http.Session;\n\n/**\n *"
  },
  {
    "path": "src/com/kalvin/J12306/api/GetPassCodeNew.java",
    "chars": 120,
    "preview": "package com.kalvin.J12306.api;\n\n/**\n * 获取订单页面验证码\n * Create by Kalvin on 2019/9/20.\n */\npublic class GetPassCodeNew {\n\n}\n"
  },
  {
    "path": "src/com/kalvin/J12306/api/GetQueueCount.java",
    "chars": 5022,
    "preview": "package com.kalvin.J12306.api;\n\nimport cn.hutool.http.HttpResponse;\nimport cn.hutool.json.JSONObject;\nimport cn.hutool.j"
  },
  {
    "path": "src/com/kalvin/J12306/api/Login.java",
    "chars": 9518,
    "preview": "package com.kalvin.J12306.api;\n\nimport cn.hutool.core.util.StrUtil;\nimport cn.hutool.http.HttpResponse;\nimport cn.hutool"
  },
  {
    "path": "src/com/kalvin/J12306/api/MyOrder.java",
    "chars": 3862,
    "preview": "package com.kalvin.J12306.api;\n\nimport cn.hutool.http.HttpResponse;\nimport cn.hutool.json.JSON;\nimport cn.hutool.json.JS"
  },
  {
    "path": "src/com/kalvin/J12306/api/PassengerDTOS.java",
    "chars": 3885,
    "preview": "package com.kalvin.J12306.api;\n\nimport cn.hutool.http.HttpResponse;\nimport cn.hutool.json.JSON;\nimport cn.hutool.json.JS"
  },
  {
    "path": "src/com/kalvin/J12306/api/QueryOrderWaitTime.java",
    "chars": 4432,
    "preview": "package com.kalvin.J12306.api;\n\nimport cn.hutool.core.util.StrUtil;\nimport cn.hutool.http.HttpResponse;\nimport cn.hutool"
  },
  {
    "path": "src/com/kalvin/J12306/api/RepeatSubmitToken.java",
    "chars": 1430,
    "preview": "package com.kalvin.J12306.api;\n\nimport cn.hutool.core.util.ReUtil;\nimport cn.hutool.http.HttpResponse;\nimport com.kalvin"
  },
  {
    "path": "src/com/kalvin/J12306/api/SubmitOrderRequest.java",
    "chars": 4485,
    "preview": "package com.kalvin.J12306.api;\n\nimport cn.hutool.core.date.DateUtil;\nimport cn.hutool.http.HttpResponse;\nimport cn.hutoo"
  },
  {
    "path": "src/com/kalvin/J12306/api/Ticket.java",
    "chars": 1946,
    "preview": "package com.kalvin.J12306.api;\n\nimport cn.hutool.http.HttpResponse;\nimport cn.hutool.log.Log;\nimport cn.hutool.log.LogFa"
  },
  {
    "path": "src/com/kalvin/J12306/cache/TicketCache.java",
    "chars": 1538,
    "preview": "package com.kalvin.J12306.cache;\n\nimport java.util.HashMap;\nimport java.util.concurrent.Executors;\nimport java.util.conc"
  },
  {
    "path": "src/com/kalvin/J12306/config/Constants.java",
    "chars": 1721,
    "preview": "package com.kalvin.J12306.config;\n\nimport cn.hutool.core.util.ClassUtil;\n\n/**\n * Create by Kalvin on 2019/9/18.\n */\npubl"
  },
  {
    "path": "src/com/kalvin/J12306/config/TicketSeatType.java",
    "chars": 934,
    "preview": "package com.kalvin.J12306.config;\n\n/**\n * 车票座席枚举\n * Create by Kalvin on 2019/9/25.\n */\npublic enum  TicketSeatType {\n\n  "
  },
  {
    "path": "src/com/kalvin/J12306/config/UrlConfig.java",
    "chars": 911,
    "preview": "package com.kalvin.J12306.config;\n\n/**\n * Create by Kalvin on 2019/9/18.\n */\npublic class UrlConfig {\n    private String"
  },
  {
    "path": "src/com/kalvin/J12306/config/Urls.java",
    "chars": 2988,
    "preview": "package com.kalvin.J12306.config;\n\n/**\n * 接口url\n * Create by Kalvin on 2019/9/18.\n */\n@Deprecated\npublic class Urls {\n\n "
  },
  {
    "path": "src/com/kalvin/J12306/config/UrlsEnum.java",
    "chars": 8446,
    "preview": "package com.kalvin.J12306.config;\n\n/**\n * url枚举类\n * Create by Kalvin on 2019/9/18.\n */\npublic enum UrlsEnum {\n\n    LOG_D"
  },
  {
    "path": "src/com/kalvin/J12306/dto/SubmitTicketInfoDTO.java",
    "chars": 1428,
    "preview": "package com.kalvin.J12306.dto;\n\n/**\n * 提交订单相关参数\n * Create by Kalvin on 2019/9/20.\n */\npublic class SubmitTicketInfoDTO {"
  },
  {
    "path": "src/com/kalvin/J12306/dto/TicketInfoDTO.java",
    "chars": 6345,
    "preview": "package com.kalvin.J12306.dto;\n\n/**\n * 车票信息\n * Create by Kalvin on 2019/9/19.\n */\npublic class TicketInfoDTO {\n\n    priv"
  },
  {
    "path": "src/com/kalvin/J12306/dto/UserInfoDTO.java",
    "chars": 1892,
    "preview": "package com.kalvin.J12306.dto;\n\n/**\n * 保存用户基础信息\n * Create by Kalvin on 2019/9/19.\n */\npublic class UserInfoDTO {\n\n    pr"
  },
  {
    "path": "src/com/kalvin/J12306/exception/J12306Exception.java",
    "chars": 579,
    "preview": "package com.kalvin.J12306.exception;\n\n/**\n * 自定义异常类\n * Create by Kalvin on 2019/9/19.\n */\npublic class J12306Exception e"
  },
  {
    "path": "src/com/kalvin/J12306/http/Session.java",
    "chars": 3849,
    "preview": "package com.kalvin.J12306.http;\n\nimport cn.hutool.core.util.StrUtil;\nimport cn.hutool.http.HttpRequest;\nimport cn.hutool"
  },
  {
    "path": "src/com/kalvin/J12306/utils/EmailUtil.java",
    "chars": 1383,
    "preview": "package com.kalvin.J12306.utils;\n\nimport cn.hutool.extra.mail.MailAccount;\nimport cn.hutool.extra.mail.MailUtil;\nimport "
  },
  {
    "path": "src/com/kalvin/J12306/utils/J12306Util.java",
    "chars": 9280,
    "preview": "package com.kalvin.J12306.utils;\n\nimport cn.hutool.core.date.DateTime;\nimport cn.hutool.core.date.DateUtil;\nimport cn.hu"
  },
  {
    "path": "src/com/kalvin/J12306/utils/StationUtil.java",
    "chars": 167407,
    "preview": "package com.kalvin.J12306.utils;\n\nimport cn.hutool.core.util.StrUtil;\nimport com.kalvin.J12306.cache.TicketCache;\nimport"
  },
  {
    "path": "src/com/kalvin/J12306/utils/YmlUtil.java",
    "chars": 1195,
    "preview": "package com.kalvin.J12306.utils;\n\nimport org.yaml.snakeyaml.Yaml;\n\nimport java.io.InputStream;\nimport java.util.LinkedHa"
  },
  {
    "path": "src/config.yml",
    "chars": 841,
    "preview": "# 配置\n\n# 12306账号密码配置(暂时没用到)\nj12306:\n  user: 182xxxx\n  password: 123456\n\n  ticket:\n    queryspeed: 2000 # 刷票速度(单位毫秒)。默认2秒。"
  }
]

// ... and 4 more files (download for full content)

About this extraction

This page contains the full source code of the kalvinGit/J12306 GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 42 files (281.0 KB), approximately 139.2k tokens, and a symbol index with 247 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!