-- 支付与 SIM 套餐续费基础。执行前请先备份生产数据库。 ALTER TABLE traffic_order ADD COLUMN total_fee_fen BIGINT NOT NULL DEFAULT 0 COMMENT '固定支付金额(分)' AFTER total_price, ADD COLUMN payment_provider VARCHAR(32) DEFAULT '' COMMENT '支付渠道' AFTER pay_status, ADD COLUMN provider_trade_no VARCHAR(128) DEFAULT '' COMMENT '第三方交易号' AFTER payment_provider, ADD COLUMN credit_attempt_count INT NOT NULL DEFAULT 0 COMMENT '入账尝试次数' AFTER credit_status, ADD COLUMN next_credit_at DATETIME NULL COMMENT '下次入账时间' AFTER credit_attempt_count, ADD COLUMN closed_at DATETIME NULL COMMENT '关闭时间' AFTER paid_at, ADD UNIQUE KEY uk_traffic_order_provider_trade (payment_provider, provider_trade_no), ADD KEY idx_traffic_order_credit_retry (pay_status, credit_status, next_credit_at); UPDATE traffic_order SET total_fee_fen = ROUND(total_price * 100) WHERE total_fee_fen = 0 AND total_price IS NOT NULL; CREATE TABLE IF NOT EXISTS sim_package ( id BIGINT PRIMARY KEY COMMENT '主键 ID', code VARCHAR(64) NOT NULL COMMENT '平台套餐编码', name VARCHAR(128) NOT NULL COMMENT '套餐名称', carrier VARCHAR(16) NOT NULL COMMENT '运营商', provider_rate_plan_id BIGINT NOT NULL COMMENT 'SIMBOSS 套餐标识', amount_gb INT NOT NULL COMMENT '流量额度 GB', validity_months INT NOT NULL COMMENT '有效月数', cost_fee_fen BIGINT NOT NULL COMMENT '采购成本(分)', sale_fee_fen BIGINT NOT NULL COMMENT '销售价格(分)', status VARCHAR(16) NOT NULL DEFAULT 'active' COMMENT 'active/inactive', created_at DATETIME NULL COMMENT '创建时间', updated_at DATETIME NULL COMMENT '更新时间', UNIQUE KEY uk_sim_package_code (code), UNIQUE KEY uk_sim_package_provider_plan (carrier, provider_rate_plan_id), KEY idx_sim_package_status (status) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; CREATE TABLE IF NOT EXISTS sim_recharge_order ( id BIGINT PRIMARY KEY COMMENT '主键 ID', user_id BIGINT NOT NULL COMMENT '所属用户 ID', sim_card_id BIGINT NOT NULL COMMENT 'SIM 卡 ID', package_id BIGINT NOT NULL COMMENT '套餐 ID', package_code VARCHAR(64) NOT NULL COMMENT '套餐编码快照', provider_rate_plan_id BIGINT NOT NULL COMMENT 'SIMBOSS 套餐标识快照', iccid_snapshot VARCHAR(32) NOT NULL COMMENT 'ICCID 快照,仅供履约', amount_gb INT NOT NULL COMMENT '流量额度 GB', validity_months INT NOT NULL COMMENT '有效月数', total_fee_fen BIGINT NOT NULL COMMENT '固定支付金额(分)', payment_status VARCHAR(16) NOT NULL DEFAULT 'unpaid' COMMENT 'unpaid/processing/paid/failed/closed', fulfillment_status VARCHAR(16) NOT NULL DEFAULT 'pending' COMMENT 'pending/submitting/retrying/success/failed', external_order_no VARCHAR(128) NOT NULL COMMENT '平台稳定外部订单号', provider_order_no VARCHAR(128) DEFAULT '' COMMENT '运营商流水号', attempt_count INT NOT NULL DEFAULT 0 COMMENT '履约尝试次数', next_attempt_at DATETIME NULL COMMENT '下次履约时间', last_error_code VARCHAR(64) DEFAULT '' COMMENT '最后错误代码', last_error_message VARCHAR(256) DEFAULT '' COMMENT '最后错误信息', created_at DATETIME NULL COMMENT '创建时间', paid_at DATETIME NULL COMMENT '支付时间', fulfilled_at DATETIME NULL COMMENT '履约时间', updated_at DATETIME NULL COMMENT '更新时间', UNIQUE KEY uk_sim_recharge_external (external_order_no), KEY idx_sim_recharge_user_created (user_id, created_at), KEY idx_sim_recharge_fulfillment_retry (payment_status, fulfillment_status, next_attempt_at) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; CREATE TABLE IF NOT EXISTS payment_transaction ( id BIGINT PRIMARY KEY COMMENT '主键 ID', user_id BIGINT NOT NULL COMMENT '付款用户 ID', business_type VARCHAR(32) NOT NULL COMMENT 'traffic_order/sim_recharge_order', business_order_id BIGINT NOT NULL COMMENT '业务订单 ID', provider VARCHAR(32) NOT NULL COMMENT '支付渠道', merchant_order_no VARCHAR(128) NOT NULL COMMENT '商户订单号', provider_trade_no VARCHAR(128) DEFAULT '' COMMENT '第三方交易号', total_fee_fen BIGINT NOT NULL COMMENT '固定金额(分)', status VARCHAR(16) NOT NULL DEFAULT 'unpaid' COMMENT 'unpaid/processing/paid/failed/closed', created_at DATETIME NULL COMMENT '创建时间', paid_at DATETIME NULL COMMENT '支付时间', updated_at DATETIME NULL COMMENT '更新时间', UNIQUE KEY uk_payment_merchant_order (provider, merchant_order_no), UNIQUE KEY uk_payment_provider_trade (provider, provider_trade_no), KEY idx_payment_business (business_type, business_order_id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; CREATE TABLE IF NOT EXISTS payment_callback_event ( id BIGINT PRIMARY KEY COMMENT '主键 ID', provider VARCHAR(32) NOT NULL COMMENT '支付渠道', event_key VARCHAR(128) NOT NULL COMMENT '回调事件幂等键', payload_hash VARCHAR(64) NOT NULL COMMENT '载荷哈希', verified TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否通过验签', processed_at DATETIME NULL COMMENT '处理时间', result_code VARCHAR(64) DEFAULT '' COMMENT '处理结果', created_at DATETIME NULL COMMENT '创建时间', UNIQUE KEY uk_payment_callback_event (provider, event_key) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;