For agentic workers: REQUIRED SUB-SKILL: Use superpowers:executing-plans for native execution, or superpowers:subagent-driven-development only if the user explicitly chooses delegation. Steps use checkbox syntax. Do not implement before this written plan is reviewed.
Goal: 用户在骑手接单后通过该骑手的 LINE Pay 付款,支付成功才可取件,取件前取消全额退款,任意站已取后禁止取消。
Architecture: 骑手凭证、闪送支付尝试与退款分别持久化,不复用外卖流水关联。复用 LINE Pay v4 客户端;网络副作用采用持久化意图、独立外部请求及条件更新,订单行锁仅保护短事务。闪送入口接入独立支付服务,保持普通外卖及现金/转账收款流程。
Tech Stack: JDK 21、Spring Boot、MyBatis/MyBatis-Plus、MySQL、Redisson;Vue 2、Element UI、四语 i18n。
Spec: rider-flash-online-spec.md,原 LINE Pay 规格第 17 节及闪送 FR-111 至 FR-115。
test-202609v2 原地实施;不创建或切换分支/工作树。不自动提交或推送,等待用户指令。ruoyi-admin -> ruoyi-system;外部 HTTP 编排在 admin,持久化与闸门在 system。Controller 明确 DTO、请求注解及权限,不用 Map 入参或 Bean Validation。updatesql/sql.md,包括表、索引、字段说明和菜单权限;不执行数据库迁移或回写历史资金事实。info_rider_line_pay:不可变凭证版本;可空唯一 current_rider_id 保证一个当前版本。环境来自服务器,界面只读;轮换时只变更当前标记,不覆盖旧密钥。新支付要求用户类型 2、账号有效及当前凭证启用且环境匹配。flash_delivery_line_payment:订单 ID、riderId、credentialId、服务端金额/TWD、唯一 lineOrderId/transactionId、可空唯一 activeOrderId、状态、版本、租约及下次核实/截止时间。订单 1:N 尝试;未知结果阻断新尝试。flash_delivery_line_refund:paymentId 唯一、全额金额、状态、网关退款交易号、版本、租约及恢复时间;支付 PAID 事实不被退款覆盖。CREATED/REQUESTING/WAITING_AUTH/CONFIRMING/REQUEST_UNKNOWN/CONFIRM_UNKNOWN/PAID/FAILED/CANCELLED/EXPIRED/MANUAL_REVIEW;只有网关明确证明的终止尝试可释放活跃键,浏览器取消不是证据。CREATED/PROCESSING/UNKNOWN/REFUNDED/FAILED/MANUAL_REVIEW;UNKNOWN 与过期 PROCESSING 只读核实,不盲重发退款。不能证明结果时进入人工核对,不伪造成功。paymentStatus:现金/转账保持 0/1;LINE Pay 0=未核实到账、1=已支付、2=已全额退款。SQL 修改列说明,不根据旧收款标记伪造 LINE 支付流水;历史 payType=3 无可信流水时禁止取件并提示核对。FlashLinePayPaymentView:Long orderId/paymentId、String status/refundStatus、String paymentUrl;无尝试返回 status=NOT_STARTED,refundStatus 无退款时为空。paymentUrl 只返回寄件付款人,骑手查询仅返回状态;敏感流水/密钥不进 App 响应。POST /system/flashDelivery/orders/{id}/linePay/create(明确空业务 DTO,不接收金额);GET /system/flashDelivery/orders/{id}/linePay/status。仅寄件人发起付款;寄件人及本单骑手可读取状态,不返回其他人订单。GET /pay/line/flash/confirm 与 /cancel,显式 orderId(LINE 订单号)、transactionId 字符串参数;仅定位已绑定尝试并触发核实,不信任浏览器支付结果。App 回链沿用既有 payment/result,加 orderSource=FLASH,orderId 为闪送 ID,文档要求前端重新查询。LinePayClient.request(credential, request, confirmUrl, cancelUrl) 重载允许服务端指定闪送回跳;原双参数签名继续使用原配置。新增 line-pay.flash-confirm-url/flash-cancel-url 部署配置,无有效 HTTPS 回跳时阻止新闪送支付,不改变外卖配置。Files: 新增 system 下 domain/InfoRiderLinePay.java、domain/dto/RiderLinePayCredentialDto.java、domain/dto/RiderLinePayToggleDto.java、domain/vo/InfoRiderLinePayVo.java、mapper/InfoRiderLinePayMapper.java、resources/mapper/infouser/InfoRiderLinePayMapper.xml、service/IInfoRiderLinePayService.java、service/impl/InfoRiderLinePayServiceImpl.java;admin 下新增 com/ruoyi/app/pay/RiderLinePayController.java。平台新增 src/api/infouser/riderLinePay.js、src/views/infouser/riderPayment/index.vue、tests/rider-line-pay.test.cjs;迁移与菜单登记至 updatesql/sql.md,四个 src/api/language 文件新增同名 key。
Interfaces: getCurrent(Long riderId)、getEnabledCurrent(Long riderId)、getById(Long credentialId) 返回 InfoRiderLinePay;saveVerifiedCredential(RiderLinePayCredentialDto dto, String environment, String returnCode, String returnMessage) 返回版本;setCurrentEnabled(Long riderId, boolean enabled) 返回 int。列表/详情沿用门店分页 VO 模式。平台路径 /system/riderLinePay,list/detail/saveCredentials/toggleEnable 分别采用 GET/GET/PUT/PUT;权限 infouser:riderLinePay:list/query/saveCredentials/toggleEnable。
InfoRiderLinePayServiceTest 与 RiderLinePayControllerTest:nonRiderRejectedBeforeProbe 验证非骑手 0 网关调用;invalidProbePreservesCurrent 验证原版本不变;rotationKeepsOldVersion 验证旧凭证可查;listDoesNotExposeSecret 验证列表无 Secret;environmentMismatchNotEnabled 验证环境错配不可新收款。node --test tests/rider-line-pay.test.cjs,核对配置列表、保存、禁用、权限按钮及环境只读;保留可独立演示的平台配置闭环,暂不开放真实闪送支付。Files: 新增 system domain/flash/FlashDeliveryLinePayment.java、mapper/flash/FlashDeliveryLinePaymentMapper.java、resources/mapper/flash/FlashDeliveryLinePaymentMapper.xml;admin com/ruoyi/app/flashdelivery/payment/FlashLinePayService.java、FlashLinePayFactService.java、FlashLinePayController.java、FlashLinePayReturnController.java、FlashLinePayReturnPageRenderer.java,DTO FlashLinePayCreateRequest.java、FlashLinePayPaymentView.java。修改 LinePayClient.java、LinePayProperties.java,应用非敏感配置、updatesql/sql.md 及 i18n。
Interfaces: FlashLinePayService.create(Long userId, Long orderId)、query(Long callerId, Long orderId) 返回 FlashLinePayPaymentView;reconcile(Long paymentId, String source) 返回 void;findByLineOrderId(String lineOrderId, String transactionId) 返回持久化尝试。FlashLinePayFactService.applyPaidFact(Long paymentId, String transactionId, long paidAmount, Date paidAt) 返回 boolean,事务内先锁订单再更新尝试与 paymentStatus。
FlashLinePayServiceTest、FlashLinePayControllerTest、FlashLinePayFactServiceTest 和 LinePayClientTest 增量:unacceptedOrderCannotPay、crossUserCannotPay、serverAmountAndRiderAreUsed、serverAmountOverflowRejected、duplicateCreateUsesExistingAttempt、requestTimeoutDoesNotCreateSecondAttempt、confirmTimeoutOnlyRetrieves、forgedReturnCannotMarkPaid、transactionIdRetainsExactDigits、riderQueryDoesNotExposePaymentUrl;断言未经核实 paymentStatus 不为 1,客户端金额/骑手不能覆盖后端,金额溢出时无网关调用,重复网关 Request/Confirm 至多一次。Files: 新增 system domain/flash/FlashDeliveryLineRefund.java、mapper/flash/FlashDeliveryLineRefundMapper.java、resources/mapper/flash/FlashDeliveryLineRefundMapper.xml;admin com/ruoyi/app/flashdelivery/payment/FlashLinePayRefundService.java、com/ruoyi/app/task/FlashLinePayReconcileTask.java。修改任务 2 的支付事实服务及 updatesql/sql.md。
Interfaces: FlashLinePayFactService.ensureCancellationRefundIntent(Long orderId) 返回 void,在订单锁内创建唯一退款意图或登记未决付款补偿;FlashLinePayRefundService.reconcile(Long refundId, String source) 返回 void。定时任务 reconcile() 分批处理支付与退款,使用独立 Redisson 任务锁和行租约,沿用既有 LINE 恢复批量/租约配置,不更改外卖任务。
FlashLinePayRefundServiceTest、FlashLinePayReconcileTaskTest:paidCancellationCreatesOneFullRefund 验证 paymentId 唯一;latePaymentOnCancelledOrderCreatesRefund 验证取消不恢复、真实扣款自动补偿;refundTimeoutOnlyRetrieves 验证 UNKNOWN 不二次 Refund;rotatedCredentialRefundUsesOriginalVersion 验证原密钥;expiredLeaseRequiresReadOnlyRecovery 验证崩溃后不重扣;refundFactDoesNotErasePaidFact 验证支付仍 PAID,订单收款状态仅退款证实后为 2。Files: 修改 system PaymentMethodGateService.java、domain/flash/FlashDeliveryOrder.java、mapper/flash/FlashDeliveryOrderMapper.java/XML;admin FlashDeliveryApplicationService.java、FlashDeliveryStateMachine.java、DTO FlashDeliveryAdminOrderDetailView.java/FlashDeliveryOrderView.java。平台修改 src/views/flashDelivery/shared.js、orders/index.vue、orders/OrderDetail.vue、multiPickup.js 及相关四语/测试。
Interfaces: 闸门 RIDER_FLASH 在 payeeUserId 非空时检查任务 1 凭证,未知骑手仅服从平台开关;保留现有支付选择。新增 FlashLinePayFactService.assertPickupPaid(FlashDeliveryOrder order) 返回 void,只验证可信 PAID 流水并无退款阻断,不仅检查 paymentStatus。平台列表订单返回只读非持久化 Boolean canAdminCancel,详情同名字段;资格计算复用短方法 canCancelBeforePickup(FlashDeliveryOrder order, List<FlashDeliveryOrderStop> stops)。
partiallyPickedOrderCannotAdminCancel、legacyPickedStatusCannotCancel、noStationFactsCannotDefaultToCancellable、linePayWithoutVerifiedPaymentCannotPickupAnyStop、manualReceiptCannotMarkLinePayPaid、riderWithoutCredentialCannotListOrAccept、cancelAndPickupConditionFailureDoesNotApplySideEffects;断言取消拒绝无写入、任一取件入口不绕过付款、现金/转账原收款流程不变。acceptedButPartlyPickedHidesCancel、missingEligibilityHidesCancel、staleDialogCannotSubmitCancel、allUnpickedCanCancel 断言;新增 API状态字段/注释同步 Entity、XML、DTO、Controller、i18n 与 SQL 列说明。Files: 新增 docs/flash-delivery-line-pay-app-integration.md;更新 specs/019-line-pay/spec.md、plan.md、tasks.md、quickstart.md、本增量规格/计划;更新 specs/024-flash-delivery 与 specs/031-pay-method-config 的 spec.md/plan.md/tasks.md 兼容说明。新增/更新测试保持任务 1 至 4 的实际类名,不另建重复测试框架。
C:/Users/99029/.jdks/graalvm-jdk-21.0.12+7.1 并将 bin 加入 PATH;先验证 java -version。每任务定向命令统一采用 mvn -pl ruoyi-admin -am '-Dtest=<该任务全部测试类名,逗号分隔>' -Dsurefire.failIfNoSpecifiedTests=false test,system 类也随 reactor 执行,不改全局环境。mvn -pl ruoyi-admin -am test 和 mvn -pl ruoyi-admin -am -DskipTests package,要求 BUILD SUCCESS、新鲜报告 0 失败/错误;记录实际项数,不沿用历史数字。平台目录执行 node --test tests/rider-line-pay.test.cjs tests/flash-delivery.test.cjs tests/flash-multi-pickup.test.cjs、改动 Vue/脚本及四语解析检查;有依赖时执行 npm run build:stage,依赖缺失则明确未执行,不擅自安装升级。T061 → T062 → T063 → T064 → T065,采用一次原地实施闭环,不将未完成的接单后付款路径视为已交付;计划未要求创建 Agent。主流程、凭证、App边界及注释覆盖 US-R1 至 US-R4;五项 Review Focus 均对应定向测试。
执行方式已确认:本会话原地执行,不创建分支,不自动提交。T061–T065 本地实现及验证已收口,仍未提交/推送。后端全量 1140 项、平台 16 项及两端构建通过,最终独立只读审查 5 项 Important 均用失败→通过回归修复;没有启动实现分工或重复审查。实际结果见 tasks.md;不执行数据库迁移或真实资金调用,真实 MySQL 竞争及 App 联调另行验收。