ソースを参照

易宝信用卡信息创建

light 5 日 前
コミット
d4c0cd5e1c
10 ファイル変更724 行追加1 行削除
  1. BIN
      BankCardBean.class
  2. 84 0
      BankCardBean.java
  3. BIN
      CardApiServer.class
  4. 59 0
      CardApiServer.java
  5. 19 0
      Dockerfile
  6. 202 1
      README.md
  7. 266 0
      VirCardNoUtils.java
  8. 60 0
      docker-deploy.sh
  9. 22 0
      start-server.sh
  10. 12 0
      test-api.sh

BIN
BankCardBean.class


+ 84 - 0
BankCardBean.java

@@ -0,0 +1,84 @@
+public class BankCardBean { 
+    /**
+     * 卡号
+     */
+    private String cardNo;
+    /** 
+     * 银行ID
+     */
+    private String bankId;
+    /**
+     * cvv
+     */
+    private String cvv;
+    
+    private String bankName;
+    /**
+     * VALIDITY_PERIOD
+     */
+    private String validityPeriod;
+    
+    /**
+     * 持卡人姓名
+     */
+    private String holderName;
+    
+    /**
+     * 持卡人身份证号
+     */
+    private String holderIdCardNo;
+    
+    /**
+     * 性别
+     */
+    private String gender;
+
+    public String getCardNo() {
+        return cardNo;
+    }
+    public void setCardNo(String cardNo) {
+        this.cardNo = cardNo;
+    }
+    public String getBankId() {
+        return bankId;
+    }
+    public void setBankId(String bankId) {
+        this.bankId = bankId;
+    }
+    public String getCvv() {
+        return cvv;
+    }
+    public void setCvv(String cvv) {
+        this.cvv = cvv;
+    }
+    public String getValidityPeriod() {
+        return validityPeriod;
+    }
+    public void setValidityPeriod(String validityPeriod) {
+        this.validityPeriod = validityPeriod;
+    }
+    public String getBankName() {
+        return bankName;
+    }
+    public void setBankName(String bankName) {
+        this.bankName = bankName;
+    }
+    public String getHolderName() {
+        return holderName;
+    }
+    public void setHolderName(String holderName) {
+        this.holderName = holderName;
+    }
+    public String getHolderIdCardNo() {
+        return holderIdCardNo;
+    }
+    public void setHolderIdCardNo(String holderIdCardNo) {
+        this.holderIdCardNo = holderIdCardNo;
+    }
+    public String getGender() {
+        return gender;
+    }
+    public void setGender(String gender) {
+        this.gender = gender;
+    }
+}

BIN
CardApiServer.class


+ 59 - 0
CardApiServer.java

@@ -0,0 +1,59 @@
+import com.sun.net.httpserver.HttpServer;
+import com.sun.net.httpserver.HttpHandler;
+import com.sun.net.httpserver.HttpExchange;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.InetSocketAddress;
+import java.nio.charset.StandardCharsets;
+
+public class CardApiServer {
+    public static void main(String[] args) throws IOException {
+        HttpServer server = HttpServer.create(new InetSocketAddress(8666), 0);
+        
+        server.createContext("/api/card", new HttpHandler() {
+            @Override
+            public void handle(HttpExchange exchange) throws IOException {
+                if ("GET".equals(exchange.getRequestMethod())) {
+                    try {
+                        BankCardBean cardBean = VirCardNoUtils.getBankCardBean();
+                        
+                        String json = String.format(
+                            "{\"cardNo\":\"%s\",\"bankId\":\"%s\",\"cvv\":\"%s\",\"bankName\":\"%s\",\"validityPeriod\":\"%s\",\"holderName\":\"%s\",\"gender\":\"%s\",\"holderIdCardNo\":\"%s\"}",
+                            cardBean.getCardNo(),
+                            cardBean.getBankId(),
+                            cardBean.getCvv(),
+                            cardBean.getBankName(),
+                            cardBean.getValidityPeriod(),
+                            cardBean.getHolderName(),
+                            cardBean.getGender(),
+                            cardBean.getHolderIdCardNo()
+                        );
+                        
+                        exchange.getResponseHeaders().set("Content-Type", "application/json; charset=UTF-8");
+                        exchange.getResponseHeaders().set("Access-Control-Allow-Origin", "*");
+                        exchange.sendResponseHeaders(200, json.getBytes(StandardCharsets.UTF_8).length);
+                        OutputStream os = exchange.getResponseBody();
+                        os.write(json.getBytes(StandardCharsets.UTF_8));
+                        os.close();
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                        String error = "{\"error\":\"" + e.getMessage() + "\"}";
+                        exchange.sendResponseHeaders(500, error.getBytes(StandardCharsets.UTF_8).length);
+                        OutputStream os = exchange.getResponseBody();
+                        os.write(error.getBytes(StandardCharsets.UTF_8));
+                        os.close();
+                    }
+                } else {
+                    exchange.sendResponseHeaders(405, -1);
+                }
+            }
+        });
+        
+        server.setExecutor(null);
+        server.start();
+        System.out.println("========================================");
+        System.out.println("信用卡生成 API 服务器已启动!");
+        System.out.println("API 地址: http://localhost:8666/api/card");
+        System.out.println("========================================");
+    }
+}

+ 19 - 0
Dockerfile

@@ -0,0 +1,19 @@
+# 使用 Eclipse Temurin(AdoptOpenJDK 的继任者,更稳定)
+FROM eclipse-temurin:8-jdk-alpine
+
+# 设置工作目录
+WORKDIR /app
+
+# 复制 Java 源文件到容器
+COPY BankCardBean.java .
+COPY VirCardNoUtils.java .
+COPY CardApiServer.java .
+
+# 编译 Java 文件
+RUN javac BankCardBean.java VirCardNoUtils.java CardApiServer.java
+
+# 暴露端口
+EXPOSE 8666
+
+# 启动应用
+CMD ["java", "CardApiServer"]

+ 202 - 1
README.md

@@ -1 +1,202 @@
-11111
+# 信用卡生成 API
+
+一个轻量级的 REST API 服务,用于生成随机的测试用信用卡信息。
+
+## 功能特性
+
+- ✅ 生成随机信用卡号(16位)
+- ✅ 生成 CVV 安全码(3位)
+- ✅ 生成有效期(MM/YY 格式)
+- ✅ 随机银行名称(建设、工商、农业、中国、招商、广发)
+- ✅ 生成持卡人姓名(中文)
+- ✅ 生成性别
+- ✅ 生成身份证号(18位)
+
+## 快速开始
+
+### 方式一:本地运行(推荐,无需 Docker)
+
+#### 1. 启动服务器
+
+```bash
+bash start-server.sh
+```
+
+#### 2. 测试 API
+
+```bash
+# 使用测试脚本
+bash test-api.sh
+
+# 或使用 curl
+curl http://localhost:8666/api/card
+
+# 或在浏览器访问
+http://localhost:8666/api/card
+```
+
+#### 3. 停止服务器
+
+```bash
+pkill -f CardApiServer
+```
+
+---
+
+### 方式二:Docker 部署
+
+**前提条件:** 已安装 Docker
+
+#### 使用 Docker Compose(推荐)
+
+```bash
+# 一键部署
+bash docker-compose-deploy.sh
+
+# 或手动执行
+docker-compose up -d --build
+```
+
+#### 使用 Docker 命令
+
+```bash
+# 一键部署
+bash docker-deploy.sh
+
+# 或手动执行
+docker build -t bankcard-api .
+docker run -d -p 8666:8666 --name bankcard-api bankcard-api
+```
+
+#### Docker 管理命令
+
+```bash
+# 查看日志
+docker logs -f bankcard-api
+
+# 停止服务
+docker stop bankcard-api
+
+# 重启服务
+docker restart bankcard-api
+
+# 删除容器
+docker rm -f bankcard-api
+
+# 使用 Docker Compose
+docker-compose logs -f      # 查看日志
+docker-compose down         # 停止服务
+docker-compose restart      # 重启服务
+```
+
+## API 接口
+
+### 获取信用卡信息
+
+**请求:**
+```
+GET http://localhost:8666/api/card
+```
+
+**响应示例:**
+```json
+{
+  "cardNo": "6227071234567890",
+  "bankId": "CCB",
+  "cvv": "123",
+  "bankName": "建设银行",
+  "validityPeriod": "05/27",
+  "holderName": "张伟",
+  "gender": "男",
+  "holderIdCardNo": "110101199001011234"
+}
+```
+
+## 项目结构
+
+```
+.
+├── BankCardBean.java          # 数据模型
+├── VirCardNoUtils.java        # 工具类(生成随机信息)
+├── CardApiServer.java         # HTTP 服务器
+├── Dockerfile                 # Docker 镜像配置
+├── docker-compose.yml         # Docker Compose 配置
+├── .dockerignore              # Docker 忽略文件
+├── start-server.sh            # 本地启动脚本
+├── docker-deploy.sh           # Docker 部署脚本
+├── docker-compose-deploy.sh   # Docker Compose 部署脚本
+├── test-api.sh                # API 测试脚本
+└── README.md                  # 本文档
+```
+
+## 技术栈
+
+- Java 8+
+- Java 内置 HTTP 服务器 (com.sun.net.httpserver)
+- 零依赖,无需 Maven 或 Spring Boot
+
+## 支持的银行
+
+- 建设银行 (CCB)
+- 工商银行 (ICBC)
+- 农业银行 (ABC)
+- 中国银行 (BOC)
+- 招商银行 (CMBCHINA)
+- 广发银行 (GDB)
+
+## 常见问题
+
+**Q: 如何修改端口?**
+
+A: 
+- 本地运行:编辑 `CardApiServer.java`,修改端口号
+- Docker 运行:修改 `docker-compose.yml` 中的端口映射
+
+```java
+// CardApiServer.java
+HttpServer server = HttpServer.create(new InetSocketAddress(9999), 0);
+```
+
+```yaml
+# docker-compose.yml
+ports:
+  - "9999:8666"  # 主机端口:容器端口
+```
+
+**Q: 如何后台运行?**
+
+A: 
+- 本地运行:`nohup java CardApiServer > server.log 2>&1 &`
+- Docker 运行:默认就是后台运行(-d 参数)
+
+**Q: 如何查看运行状态?**
+
+A: 
+- 本地运行:`ps aux | grep CardApiServer`
+- Docker 运行:`docker ps | grep bankcard-api`
+
+**Q: Docker 构建失败怎么办?**
+
+A: 如果遇到网络问题无法拉取镜像,可以:
+1. 配置 Docker 镜像加速器(推荐)
+2. 使用本地运行方式(bash start-server.sh)
+
+配置镜像加速器(macOS):
+- Docker Desktop → Settings → Docker Engine
+- 添加以下配置:
+```json
+{
+  "registry-mirrors": [
+    "https://docker.mirrors.ustc.edu.cn",
+    "https://registry.docker-cn.com"
+  ]
+}
+```
+
+## 注意事项
+
+⚠️ **重要提示:** 此工具生成的信用卡信息仅供开发测试使用,请勿用于任何非法用途。
+
+## License
+
+仅供学习和测试使用。

+ 266 - 0
VirCardNoUtils.java

@@ -0,0 +1,266 @@
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+public class VirCardNoUtils {
+
+
+    // 获取贷记卡BIN
+    private static List<String> creditCardBins = null;
+    /**
+     * 分割符
+     */
+    public static final String SPLIT_CHARACTER = ",";
+    /**
+     * 月份
+     */
+    public final static String MONTH = "01,02,03,04,05,06,07,08,09,10,11,12";
+
+    public static String DEFAULT_VIR_BINS_CREDIT="CCB:建设银行:622707,CCB:建设银行:625955,CCB:建设银行:625956,CCB:建设银行:436728,CCB:建设银行:453242,CCB:建设银行:491031,CCB:建设银行:628316,CCB:建设银行:628317,CCB:建设银行:622708,CCB:建设银行:622675,"
+            + "ICBC:工商银行:427019,ICBC:工商银行:427020,ICBC:工商银行:427029,ICBC:工商银行:427030,ICBC:工商银行:427039,ICBC:工商银行:438125,ICBC:工商银行:438126,ICBC:工商银行:451804,ICBC:工商银行:427010,ICBC:工商银行:427018,"
+            + "ABC:农业银行:403361,ABC:农业银行:404117,ABC:农业银行:404118,ABC:农业银行:404119,ABC:农业银行:404120,ABC:农业银行:404121,ABC:农业银行:463758,ABC:农业银行:514027,ABC:农业银行:519412,ABC:农业银行:519413,"
+            + "BOC:中国银行:356835,BOC:中国银行:409665,BOC:中国银行:409666,BOC:中国银行:409672,BOC:中国银行:512315,BOC:中国银行:512316,BOC:中国银行:512411,BOC:中国银行:512412,BOC:中国银行:514957,BOC:中国银行:409667"
+            + "CMBCHINA:招商银行:356890,CMBCHINA:招商银行:439188,CMBCHINA:招商银行:439227,CMBCHINA:招商银行:479229,CMBCHINA:招商银行:521302,CMBCHINA:招商银行:356889,CMBCHINA:招商银行:552534,CMBCHINA:招商银行:622575,CMBCHINA:招商银行:622576,CMBCHINA:招商银行:622581"
+            + "GDB:广发银行:406365,GDB:广发银行:406366,GDB:广发银行:487013,GDB:广发银行:491032,GDB:广发银行:491035,GDB:广发银行:491037,GDB:广发银行:491038,GDB:广发银行:518364,GDB:广发银行:622558,GDB:广发银行:622559";
+
+    private static Random strGen = new Random();
+    /**
+     * 随机数据池
+     */
+    private static char[] numbersAndLetters = ("0123456789").toCharArray();
+
+    static {
+        // 加载卡BIN配置
+        creditCardBins = new ArrayList<String>();
+        // 信用卡配置加载
+        String[] banks = DEFAULT_VIR_BINS_CREDIT.split(",");
+        for (String bankinfo : banks) {
+            String[] info = bankinfo.split(":");
+            if (info.length != 3){
+                continue;
+            }
+            creditCardBins.add(bankinfo);
+        }
+    }
+
+
+
+
+    /**
+     * 获取卡bin
+     * @return
+     */
+    private static String[] getCardBinInfo() {
+        List<String> cardBins = creditCardBins;
+        int index = (int) (Math.random() * cardBins.size());
+        String cardbin = cardBins.get(index);
+        return cardbin.split(":");
+    }
+
+    /**
+     * 获取cardbean
+     * @return
+     */
+    public static BankCardBean getBankCardBean(){
+        String[] bin = getCardBinInfo();
+        String cardNo = bin[2] +randomString(10);
+        BankCardBean bankCard = new BankCardBean();
+        bankCard.setCardNo(cardNo);
+        bankCard.setBankId(bin[0]);
+        bankCard.setBankName(bin[1]);
+        bankCard.setCvv(getCvv());
+        bankCard.setValidityPeriod(getMonth() + "/" + getYear());
+
+        //获取持卡人姓名
+        String holderName = getName();
+        // 提取性别
+        String gender = holderName.substring(0, 1);
+        // 去掉性别前缀
+        String name = holderName.substring(2);
+        
+        bankCard.setHolderName(name);
+        bankCard.setGender(gender);
+        
+        //获取身份证号码
+        String idCardNo = getRandomID();
+        bankCard.setHolderIdCardNo(idCardNo);
+
+        return bankCard;
+    }
+
+
+    /**
+     * 获取三位cvv
+     * @return
+     */
+    public static String getCvv(){
+        return randomString(3);
+    }
+
+    /**
+     * 获取明后2年的年份后两位随机数
+     */
+    public static String getYear(){
+        SimpleDateFormat SHORTDATEFORMAT = new SimpleDateFormat("yyyyMMdd");
+        String thisYearStrng = SHORTDATEFORMAT.format(new Date()).substring(2, 4);
+        StringBuilder sb = new StringBuilder();
+        int thisYear = Integer.valueOf(thisYearStrng).intValue();
+        sb.append(thisYear+1)
+                .append(SPLIT_CHARACTER)
+                .append(thisYear+2);
+        return sb.toString().split(SPLIT_CHARACTER)[(int)(Math.random() * 2)];
+
+    }
+
+    /**
+     * 获取随机月份
+     * @return
+     */
+    public static String getMonth(){
+        String[] months = MONTH.split(SPLIT_CHARACTER);
+        return months[(int)(Math.random() * (months.length))];
+    }
+
+    /** * 产生随机字符串 * */
+    public static String randomString(int length) {
+        if (length < 1) {
+            return null;
+        }
+        char[] randBuffer = new char[length];
+        for (int i = 0; i < randBuffer.length; i++) {
+            randBuffer[i] = numbersAndLetters[strGen.nextInt(9)];
+        }
+        return new String(randBuffer);
+    }
+
+    /**
+     * 获取中国人姓名
+     *
+     * @return
+     */
+    public static String getName() {
+        Random random = new Random();
+        String[] Surname = {"赵", "钱", "孙", "李", "周", "吴", "郑", "王", "冯", "陈", "褚", "卫", "蒋", "沈", "韩", "杨", "朱", "秦", "尤", "许",
+                "何", "吕", "施", "张", "孔", "曹", "严", "华", "金", "魏", "陶", "姜", "戚", "谢", "邹", "喻", "柏", "水", "窦", "章", "云", "苏", "潘", "葛", "奚", "范", "彭", "郎",
+                "鲁", "韦", "昌", "马", "苗", "凤", "花", "方", "俞", "任", "袁", "柳", "酆", "鲍", "史", "唐", "费", "廉", "岑", "薛", "雷", "贺", "倪", "汤", "滕", "殷",
+                "罗", "毕", "郝", "邬", "安", "常", "乐", "于", "时", "傅", "皮", "卞", "齐", "康", "伍", "余", "元", "卜", "顾", "孟", "平", "黄", "和",
+                "穆", "萧", "尹", "姚", "邵", "湛", "汪", "祁", "毛", "禹", "狄", "米", "贝", "明", "臧", "计", "伏", "成", "戴", "谈", "宋", "茅", "庞", "熊", "纪", "舒",
+                "屈", "项", "祝", "董", "梁", "杜", "阮", "蓝", "闵", "席", "季"};
+        String girl = "秀娟英华慧巧美娜静淑惠珠翠雅芝玉萍红娥玲芬芳燕彩春菊兰凤洁梅琳素云莲真环雪荣爱妹霞香月莺媛艳瑞凡佳嘉琼勤珍贞莉桂娣叶璧璐娅琦晶妍茜秋珊莎锦黛青倩婷姣婉娴瑾颖露瑶怡婵雁蓓纨仪荷丹蓉眉君琴蕊薇菁梦岚苑婕馨瑗琰韵融园艺咏卿聪澜纯毓悦昭冰爽琬茗羽希宁欣飘育滢馥筠柔竹霭凝晓欢霄枫芸菲寒伊亚宜可姬舒影荔枝思丽 ";
+        String boy = "伟刚勇毅俊峰强军平保东文辉力明永健世广志义兴良海山仁波宁贵福生龙元全国胜学祥才发武新利清飞彬富顺信子杰涛昌成康星光天达安岩中茂进林有坚和彪博诚先敬震振壮会思群豪心邦承乐绍功松善厚庆磊民友裕河哲江超浩亮政谦亨奇固之轮翰朗伯宏言若鸣朋斌梁栋维启克伦翔旭鹏泽晨辰士以建家致树炎德行时泰盛雄琛钧冠策腾楠榕风航弘";
+        int index = random.nextInt(Surname.length - 1);
+        //获得一个随机的姓氏
+        String name = Surname[index];
+        //可以根据这个数设置产生的男女比例
+        int i = random.nextInt(3);
+        if (i == 2) {
+            int j = random.nextInt(girl.length() - 2);
+            if (j % 2 == 0) {
+                name = "女-" + name + girl.substring(j, j + 2);
+            } else {
+                name = "女-" + name + girl.substring(j, j + 1);
+            }
+
+        } else {
+            int j = random.nextInt(girl.length() - 2);
+            if (j % 2 == 0) {
+                name = "男-" + name + boy.substring(j, j + 2);
+            } else {
+                name = "男-" + name + boy.substring(j, j + 1);
+            }
+
+        }
+
+        return name;
+    }
+
+ 
+    public static int getNum(int start, int end) {
+        return (int) (Math.random() * (end - start + 1) + start);
+    }
+
+
+    /**
+     * 获取身份证号
+     * @return
+     */
+    public static String getRandomID() {
+        String id = "420222199204179999";
+        // 随机生成省、自治区、直辖市代码 1-2
+        String provinces[] = { "11", "12", "13", "14", "15", "21", "22", "23",
+                "31", "32", "33", "34", "35", "36", "37", "41", "42", "43",
+                "44", "45", "46", "50", "51", "52", "53", "54", "61", "62",
+                "63", "64", "65", "71", "81", "82" };
+        String province = randomOne(provinces);
+        // 随机生成地级市、盟、自治州代码 3-4
+        String city = randomCityCode(18);
+        // 随机生成县、县级市、区代码 5-6
+        String county = randomCityCode(28);
+        // 随机生成出生年月 7-14
+        String birth = randomBirth(20, 50);
+        // 随机生成顺序号 15-17(随机性别)
+        String no = new Random().nextInt(899) + 100+"";
+        // 随机生成校验码 18
+        String checks[] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
+                "X" };
+        String check = randomOne(checks);
+        // 拼接身份证号码
+        id = province + city + county + birth + no + check;
+        return id;
+    }
+
+    /**
+     * 随机生成minAge到maxAge年龄段的人的生日日期
+     *
+     * @author mingzijian
+     * @param minAge
+     * @param maxAge
+     * @return
+     */
+    public static String randomBirth(int minAge, int maxAge) {
+        SimpleDateFormat dft = new SimpleDateFormat("yyyyMMdd");// 设置日期格式
+        Calendar date = Calendar.getInstance();
+        date.setTime(new Date());// 设置当前日期
+        // 随机设置日期为前maxAge年到前minAge年的任意一天
+        int randomDay = 365 * minAge
+                + new Random().nextInt(365 * (maxAge - minAge));
+        date.set(Calendar.DATE, date.get(Calendar.DATE) - randomDay);
+        return dft.format(date.getTime());
+    }
+
+    /**
+     * 随机生成两位数的字符串(01-max),不足两位的前面补0
+     *
+     * @author mingzijian
+     * @param max
+     * @return
+     */
+    public static String randomCityCode(int max) {
+        int i = new Random().nextInt(max) + 1;
+        return i > 9 ? i + "" : "0" + i;
+    }
+
+
+    /**
+     * 从String[] 数组中随机取出其中一个String字符串
+     *
+     * @author mingzijian
+     * @param s
+     * @return
+     */
+    public  static String randomOne(String s[]) {
+        return s[new Random().nextInt(s.length - 1)];
+    }
+
+
+    public static void main(String[] args) {
+
+        for (int i = 0; i < 3; i++) {
+            BankCardBean bean = getBankCardBean();
+            System.out.println("信用卡卡号:" + bean.getCardNo() + " Cvv:"+bean.getCvv()
+                    + " 有效期: " + bean.getValidityPeriod() + " 银行名:" + bean.getBankName());
+            System.out.println("持卡人姓名:" + bean.getHolderName() + " 身份证号:" + bean.getHolderIdCardNo());
+            System.out.println("----------------------------------------");
+        }
+
+    }
+}

+ 60 - 0
docker-deploy.sh

@@ -0,0 +1,60 @@
+#!/bin/bash
+
+echo "======================================"
+echo "开始构建和部署信用卡生成 API 到 Docker"
+echo "======================================"
+
+# 停止并删除旧容器
+echo "1. 停止旧容器..."
+docker stop yibao-bankcard-api 2>/dev/null || true
+docker rm yibao-bankcard-api 2>/dev/null || true
+
+# 构建 Docker 镜像
+echo "2. 构建 Docker 镜像..."
+docker build -t yibao-bankcard-api .
+
+if [ $? -ne 0 ]; then
+    echo ""
+    echo "❌ Docker 构建失败!"
+    echo ""
+    echo "可能的原因:"
+    echo "  1. 无法连接到 Docker Hub"
+    echo "  2. 网络问题"
+    echo ""
+    echo "解决方案:"
+    echo "  - 配置 Docker 镜像加速器(见 README.md)"
+    echo "  - 或使用本地运行:bash start-server.sh"
+    exit 1
+fi
+
+# 启动容器
+echo "3. 启动容器..."
+docker run -d -p 8666:8666 --name yibao-bankcard-api yibao-bankcard-api
+
+if [ $? -ne 0 ]; then
+    echo "❌ 容器启动失败!"
+    exit 1
+fi
+
+# 等待服务启动
+echo "4. 等待服务启动(5秒)..."
+sleep 5
+
+# 检查容器状态
+echo "5. 检查容器状态..."
+docker ps | grep bankcard-api
+
+echo ""
+echo "======================================"
+echo "✅ 部署完成!"
+echo "======================================"
+echo ""
+echo "API 地址: http://localhost:8666/api/card"
+echo ""
+echo "常用命令:"
+echo "  查看日志: docker logs -f yibao-bankcard-api"
+echo "  停止服务: docker stop yibao-bankcard-api"
+echo "  重启服务: docker restart yibao-bankcard-api"
+echo "  删除容器: docker rm -f yibao-bankcard-api"
+echo "  测试 API: bash test-api.sh"
+echo ""

+ 22 - 0
start-server.sh

@@ -0,0 +1,22 @@
+#!/bin/bash
+
+echo "======================================"
+echo "编译并启动信用卡生成 API 服务器"
+echo "======================================"
+
+# 编译所有 Java 文件
+echo "1. 编译 Java 文件..."
+javac BankCardBean.java VirCardNoUtils.java CardApiServer.java
+
+if [ $? -ne 0 ]; then
+    echo "❌ 编译失败!请检查 Java 环境。"
+    exit 1
+fi
+
+echo "✅ 编译成功!"
+echo ""
+echo "2. 启动服务器..."
+echo ""
+
+# 运行服务器
+java CardApiServer

+ 12 - 0
test-api.sh

@@ -0,0 +1,12 @@
+#!/bin/bash
+
+echo "测试信用卡生成 API..."
+echo "======================================"
+
+for i in {1..3}
+do
+  echo "第 $i 次请求:"
+  curl -s http://localhost:8666/api/card | python3 -m json.tool
+  echo ""
+  echo "--------------------------------------"
+done