| | |
| | | columns.put("capability_response_code", "varchar(32) default null"); |
| | | columns.put("capability_response_message", "varchar(512) default null"); |
| | | columns.put("capability_verified_at", "datetime default null"); |
| | | // 商户端「立即核实」的冷却时间戳,见 V148。 |
| | | columns.put("capability_sync_until", "datetime default null"); |
| | | // 法人手机号:微信实名认证走法人时的必填项,实名接口的 name/mobile/id_card_number |
| | | // 都必须是法人本人的,不能用联系人手机号顶替。见 V145 的说明。 |
| | | columns.put("legal_mobile", "varchar(20) default null"); |
| | | columns.put("realname_status", "varchar(16) not null default 'not_started'"); |
| | | columns.put("realname_request_no", "varchar(32) default null"); |
| | | columns.put("realname_apply_no", "varchar(32) default null"); |
| | | columns.put("realname_response_code", "varchar(32) default null"); |
| | | columns.put("realname_response_message", "varchar(512) default null"); |
| | | // 门店照片:线下经营的门店材料是**一组三张**(门头照 F22、内景照 F24、收银台 F105), |
| | | // 通道在进件这一步就按 F-code 逐张核对,企业与个人主体都要交。见 V146 与 V156 的说明。 |
| | | columns.put("store_header_url", "varchar(512) default null"); |
| | | columns.put("store_indoor_url", "varchar(512) default null"); |
| | | columns.put("store_cashier_url", "varchar(512) default null"); |
| | | // 经营详细地址:线下进件的 detail_addr 是通道必填项,与证件地址分开存。见 V155 的说明。 |
| | | columns.put("business_address", "varchar(255) default null"); |
| | | // 进件来源(自助进件 / 后台纳管):决定进度刷新是否允许下发通道改动。见 V158 的说明。 |
| | | // 开发库(flyway 关闭)靠这里补列,否则纳管的 INSERT 会报 Unknown column。 |
| | | columns.put("source", "varchar(16) not null default 'self'"); |
| | | for (Map.Entry<String, String> column : columns.entrySet()) { |
| | | if (!hasColumn("merchant_onboarding_application", column.getKey())) addColumn("merchant_onboarding_application", column.getKey(), column.getValue()); |
| | | } |
| | |
| | | jdbc.execute("alter table " + tableName + " add column " + columnName + " " + definition); |
| | | log.info("Merchant onboarding schema: added {}.{}", tableName, columnName); |
| | | } catch (Exception exception) { |
| | | log.warn("Merchant onboarding schema: could not add {}.{} within {}s (table busy); it will be retried on the next restart. cause={}", |
| | | tableName, columnName, DDL_LOCK_WAIT_TIMEOUT_SECONDS, exception.getClass().getSimpleName()); |
| | | // 这里必须是 error 而不是 warn:进件的 INSERT/UPDATE 都显式列出列名,缺列不是"只影响重试功能", |
| | | // 而是商户一提交进件就报 Unknown column。原先只记 warn、应用照常启动,于是症状变成 |
| | | // "重启了还是报错、又看不出原因"(2026-09-16 在开发库的 legal_mobile 上实际发生过: |
| | | // 同一轮循环里它后面的列都加成功了,只有它抢锁失败)。日志里直接给出补救语句。 |
| | | log.error("Merchant onboarding schema: could not add {}.{} within {}s (table busy); the column is" |
| | | + " referenced by the onboarding INSERT, so onboarding submissions will fail until it" |
| | | + " exists. Retried on the next restart, or run manually: alter table {} add column {} {}." |
| | | + " cause={}", |
| | | tableName, columnName, DDL_LOCK_WAIT_TIMEOUT_SECONDS, tableName, columnName, definition, |
| | | exception.getClass().getSimpleName()); |
| | | } |
| | | } |
| | | |