Java 后端与 Vue 前端对接微信支付 API v3,按需覆盖 JSAPI、H5、Native,下单、调起、回调验签、查单关单、退款、幂等及业务履约,包含数据库注释、完整测试和中文联调步骤。
## 任务目标 请在现有 Java 后端与 Vue 前端工程中,完成微信支付 API v3 对接。直接实现从业务订单发起支付、前端调起、服务端确认、业务履约,到关闭未支付订单、申请与查询退款的完整流程,交付可运行代码、数据库变更、配置示例、测试和中文使用步骤。不要只给 SDK 调用片段、演示按钮或没有接入真实订单的支付 Demo。 在现有授权范围内完成实际改动和验证;缺少外部条件时先完成可独立实现的部分,不能只停留在计划。 ## 输入信息(选填) 两项均可留空,也可直接用一句话说明目标并附上已有资料。无需自行整理版本、配置或完整需求表;能读取的内容由执行者补齐。 支付业务:从当前对话和现有订单页面、订单服务中识别需要接入的收款业务,沿该订单的创建、支付、履约和退款链路实施;支付入口按工程已有终端和已开通产品确定,不因留空实现全部场景。 工程与接入资料:从当前工作区识别关联的 Java 后端和 Vue 前端,读取依赖、订单模型、权限、配置项定义及已有测试;商户资料只确认受控配置的来源和完整性,不要求粘贴秘密。 ## 信息不完整时 先使用本次对话中已经说明的信息;用户留空、写“暂无/不清楚”或未替换输入标记,都按缺失处理,不当作真实路径、参数或业务值。已能从资料确定的内容不重复询问,不编造文件、日志、接口、业务值或执行结果。在用户已授权的范围内读取相关工程和材料,不为补齐输入擅自扩大操作范围。 ### 优先确认 - 追踪订单金额计算、状态更新、库存或权益履约、退款资格,以及对应表结构和唯一约束。 - 读取构建文件、支付依赖、SDK 封装、通知入口、Vue 支付路由及浏览器或小程序入口证据。 - 核对商户模式、AppID 与商户关系、公钥或平台证书方案、固定回调地址和已有配置校验。 - 查找测试配置、模拟微信适配层、迁移工具及可在隔离环境执行的测试命令。 ### 可采用的默认处理 - 先完成工程接入和无真实资金操作的隔离测试;缺商户材料时保留受控配置入口和明确的不可用状态,不伪造收款结果。 - 复用现有订单、权限、UI、数据库和支付库边界,不默认更换技术栈,也不增加分账、转账或合单产品。 - 支付场景不明时先完成公共订单、金额、幂等和通知基础,场景适配保持未启用,不凭 Vue 或浏览器标识猜商户能力。 ### 必须有依据的事项 - 无法从业务资料确定应付金额、合法收款对象、订单权限、履约或退款资格时,不能自行制定会改变资金或权益的规则。 - 商户模式、应用绑定或已开通产品不明时不启用对应真实接口;真实支付与退款所需的测试订单和金额授权缺失时不执行资金操作。 只有缺口会改变业务结果、权限边界或关键实现,且无法从现有资料确认时,才集中提出最多 3 个关键问题;说明影响,并继续完成不依赖答案的部分。一般命名、排版和可逆实现细节按现有约定决定,不逐项等待确认。 ### 资料仍不足时的交付 - 没有工程时交付订单与支付退款关系、接口契约、状态及额度不变量、配置项说明和隔离测试样例,明确尚未完成项目接入。 - 缺真实商户环境时完成可执行的本地编译、模拟 SDK 交互及签名通知测试,列出按场景剩余的真实联调条件。 ## 执行要求 ### 确认范围和接入前提 读取当前分支、未提交改动、订单模型、金额计算、登录、租户与组织权限、接口风格、异常处理、数据库迁移和前端路由。保留无关改动,复用现有订单、支付与退款能力,不因本次接入重建全部交易系统。 确认普通直连商户或服务商模式,核对商户号、应用 AppID 及其绑定关系、已开通的支付产品和交易场景。服务商模式使用对应官方接口与 sp/sub 身份字段,不能把普通商户代码简单替换商户号后使用。没有分账、转账、合单或订阅扣费需求时不引入这些产品。 Vue 是技术框架,不决定微信支付方式:微信内网页通常对应 JSAPI;手机外部浏览器按已开通能力接入 H5;PC 网页采用 Native 二维码。只有目标包含真正的小程序时才接入 wx.requestPayment,普通 Vue 网页不能直接把它当成浏览器 API。 先核对所选场景的授权域名、支付目录或域名配置、应用与商户关系及回调地址要求,不将不同用途的域名配置混为一项。未确认的场景列为待确认,只实现选定范围;不要为了“完整”强行开通和实现所有支付产品。 商户资料不足时继续完成接口边界、代码、数据结构和隔离测试,明确尚不能执行的真实联调步骤。不得伪造商户号、OpenID、预支付单、支付成功或退款记录。 ### 使用官方 API v3 SDK,明确证书和密钥职责 优先采用官方 Java SDK com.github.wechatpay-apiv3:wechatpay-java;检查官方发布记录与工程 Java、Spring、依赖版本兼容性,在构建文件中锁定具体版本。禁止填写 LATEST 或臆造不存在的方法;已有支付库需要先评估迁移影响,不重复接入两套签名和回调处理逻辑。 商户 API 私钥用于商户请求及所需调起参数的签名,商户 API 证书序列号用于标识商户签名身份;微信支付公钥及其 ID,或微信支付平台证书,用于验证微信响应与通知。API v3 密钥用于相关密文解密,不是商户私钥。AppSecret、API v2 密钥、API v3 密钥不能混用;网站 HTTPS 证书也不是商户 API 证书。 根据商户实际接入方式选择微信支付公钥模式或平台证书模式。核对当前 SDK 的 RSAPublicKeyConfig、RSAAutoCertificateConfig,以及 RSAPublicKeyNotificationConfig 等通知配置能力,选择匹配的实现;不能把 PUB_KEY_ID 当成商户证书序列号,也不能通过关闭验签解决未知密钥或证书问题。 沿用配置注入方式管理 merchantId、appId、商户证书序列号、私钥文件位置、API v3 密钥、公钥 ID 与文件位置或平台证书方案、支付与退款 notifyUrl、业务超时和查询参数。校验必填项和格式,输出可定位但不含秘密的配置错误。 私钥、API v3 密钥和 AppSecret 只在后端受控配置中使用,不进入 Vue 环境变量、浏览器存储、前端构建产物、数据库普通配置表、源码仓库或日志。示例文件只写占位符与来源说明,不要求用户把真实秘密贴到聊天中。 按 SDK 生命周期管理并复用配置与客户端,避免每次下单重新下载平台证书或初始化配置。处理密钥标识不匹配、证书有效性与响应验签失败,不接受“开发环境先永久跳过验签”的实现。 ### 先设计订单、支付单和退款单的关系 业务订单、支付尝试、微信交易和退款单分开建模。业务订单可以经历多次支付尝试,但每次尝试有明确身份与有效状态;同一笔成功支付不能重复履约。保留已有模型,确有缺口才新增表或字段。 本地支付单至少能表达:所属业务订单、用户与租户、支付渠道和场景、服务端选择的商户配置标识、商户订单号 out_trade_no、微信交易号 transaction_id、AppID、订单金额及币种、状态、有效期、支付成功时间、必要的预支付信息、幂等键、版本及创建更新时间。 退款单至少能表达:原支付单、业务退款单、商户退款单号 out_refund_no、微信退款单号 refund_id、申请金额与币种、原因、申请人和权限来源、退款状态、退款完成时间、幂等键及创建更新时间。字段按实际业务和官方响应确定,不凭示例增加无用字段。 为商户范围内的 out_trade_no、微信交易标识、out_refund_no 等建立合适的唯一约束,按当前数据库的空值和索引行为设计;业务幂等键结合订单、用户或租户及操作类型确定范围,防止跨用户复用。不能只依靠 Redis 锁或 synchronized 保证支付唯一性。 设计通知接收与处理记录,以及可靠业务事件或待处理任务。区分通知 ID、交易 ID、支付单 ID 与业务履约唯一键,重复通知去重不能只看通知 ID;同一交易的查单与回调必须进入同一套状态收敛逻辑。 新增任何表的所有字段都写详细中文注释,说明业务含义、金额单位、枚举值、空值与默认值,必要时标注时区、关联关系和敏感等级。按 MySQL、PostgreSQL 等实际数据库提供正确的建表和字段注释语法,不写跨数据库不能执行的通用 SQL。 业务状态集中使用枚举或字典,明确代码与数据库值的对应,不散落魔法值。分别定义支付未完成、结果未知、已支付和已关闭,以及退款申请、处理中、成功、失败或异常等状态;本地名称可沿用项目约定,微信状态按官方当前枚举做显式映射,不能把未知状态默认当成成功或失败。 ### 金额和下单必须由后端控制 前端提交业务订单标识、允许的场景及必要幂等标识,后端验证登录身份、订单归属、租户、订单是否可支付、库存或有效期,并从可信业务数据计算应付金额。不能使用浏览器传来的金额、折扣、商品描述、商户号或 AppID 直接下单。 微信接口的金额按所选接口要求使用整数最小货币单位,人民币通常为分。项目使用元时以 BigDecimal 进行精确转换并验证小数位和范围;不使用 float/double 计算金额,不通过静默四舍五入掩盖非法金额,防止整数溢出和非正数下单。 同一逻辑支付请求重复到达时返回已有有效支付尝试或当前支付状态。以业务订单为边界,通过条件更新、短事务锁或合适的唯一约束控制尝试创建与切换;不同幂等键、多个标签页和不同支付场景也不能同时创建多个可收款的有效尝试。创建中或结果未知的旧尝试仍需占用该位置;确需换号前先确认旧微信单不可继续支付,履约去重不能代替防重复收款。 二维码或预支付信息失效后,先按微信订单状态与官方规则处理旧尝试,再决定是否可重新下单;不能每次点击按钮都创建一个新订单。支付链接或预支付 ID 失效也不能直接当作微信订单已关闭。 对下单超时、连接中断、响应验签失败等结果未知情况,保存本地状态和原 out_trade_no,先查单或按该接口允许的相同参数重试,不能直接生成新商户订单号以规避错误。明确“微信已受理、本地未拿到响应”的恢复路径。 返回前端的调起参数按场景区分,使用明确 DTO,禁止混合返回所有字段让前端猜测。用户状态查询只返回该用户有权查看的金额、状态、有效期与必要动作,不透传整个微信响应或商户配置。 ### 实现完整的 Java 支付服务 按已有分层实现配置、Controller、业务 Service、微信支付适配层、DTO/VO、枚举和持久层。控制层做输入与协议处理,业务层处理状态和一致性,适配层封装 SDK 调用;不要用一个静态 util 承担全部支付业务。 按选定场景使用 SDK 中真实存在的服务,例如 JsapiService 或 JsapiServiceExtension、H5Service、NativePayService;需要调起签名参数时优先核对扩展服务能力。普通商户 SDK 的下单、查询与关闭方法以当前类型和官方示例为准,不混入 API v2 的 XML、MD5 签名或 unifiedorder 写法。 提供发起支付、查询支付状态、关闭符合条件的未支付单、申请退款、查询退款,以及支付和退款通知入口。路径、响应结构与项目现状一致;下面仅是职责示例,不是微信支付官方路径: - POST /api/payments:基于业务订单创建或复用支付尝试,返回场景及调起数据。 - GET /api/payments/{paymentNo}:核验访问权限后返回状态,必要时按节奏向微信查单并收敛本地状态。 - POST /api/payments/{paymentNo}/close:核验订单状态与操作权限,按查单、关单结果处理,不把本地取消当成微信已关单。 - POST /api/refunds:基于允许退款的业务记录和权限创建退款申请。 - GET /api/refunds/{refundNo}:返回经过权限过滤的退款状态。 - POST /api/payments/wechat/notify 与 /api/payments/wechat/refund-notify:按微信通知协议处理,不使用普通业务响应包装。 微信回调入口按需要精确放行普通登录鉴权,并以微信签名和业务核验确认来源;不能为回调放开整个 API 命名空间。业务下单、查询、关单和退款接口继续执行原有认证、权限和防越权规则。 支付和退款 notifyUrl 使用后端固定配置、微信能够访问的 HTTPS 接收地址,不接受前端指定任意回调地址。核对路径、POST 请求、代理转发和原始请求体保持完整,不能被登录跳转或统一响应包装截获;本机 localhost 地址不能直接接收公网微信通知。 使用 MyBatis 时,SQL 统一放 Mapper XML,不在 Java 注解、字符串或 Service 中编写 SQL;XML、Mapper 方法和实体字段对应清楚。使用其他持久层时沿用现有规范,不为这一项强行更换框架。 外部微信网络请求不要放在长时间持有数据库行锁的事务中。先保存本地操作意图,调用微信,再用短事务合并结果;失败和重启后根据持久化状态恢复。涉及一致性时说明事务边界,不以“加了 @Transactional”宣称外部支付与本地数据库能原子提交。 ### 正确处理 JSAPI、H5 与 Native 前端 Vue 沿用已有版本、UI 库、路由、请求封装和状态管理。支付页面展示订单摘要、可信金额、有效期和明确按钮;保持中文界面清楚、布局规整,不引入无关宣传、装饰图或额外 UI 框架。 JSAPI:先处理当前 AppID 下的支付用户身份。网页 OAuth 的 code 换取和 AppSecret 使用在后端完成;校验 state 并绑定登录用户和原支付流程,限制回跳目标。不能将其他 AppID 的 OpenID、UnionID 或前端随意填写的 OpenID 直接用于下单。 JSAPI 调起参数由后端根据本次预支付单生成,例如 appId、timeStamp、nonceStr、package、signType、paySign。timeStamp 为 Unix 秒数字符串,package 对应 prepay_id=实际值;前端不重算商户签名,不自行改写已签名字段。优先核对 JsapiServiceExtension.prepayWithRequestPayment 的参数生成能力。WeixinJSBridge 的调起方法与微信 JS-SDK 的 chooseWXPay 按选定方案分别映射字段,不能混用 timestamp 与 timeStamp;wx.config 的权限签名与支付 paySign 分别实现,不混成一套。 等待相应桥接或 SDK 就绪后再调起支付,处理不在微信内、能力不可用、用户取消、调起失败与回到页面。浏览器环境识别只用于选择交互路径,不能作为支付身份或权限依据。取消支付界面不等于订单已关闭,允许的再次支付依据后端订单状态判断。 H5:由后端使用 H5 下单并返回完整 h5_url,前端从已配置的商户页面按官方流程跳转,检查 Referer 没有被策略或中间跳转丢失。需要 redirect_url 时仅编码该参数值,保留原链接其余参数;发起域名和回跳域名按当前官方要求与商户配置匹配,不能认为任意子域名自动可用。回跳不携带可信支付成功结论。核对场景信息与用户终端地址来源,后端只信任受控代理链传递的客户端 IP,不能随意采用前端提交值、服务器自身 IP 或任意 X-Forwarded-For。 Native:后端返回 code_url,Vue 在本地使用适合工程的二维码库生成清晰二维码,不把支付链接交给无关第三方图片服务。显示订单金额和有效期,二维码过期、刷新、关闭弹窗和切换订单时清理旧状态;“刷新二维码”不能绕过后端重复支付控制。 嵌入小程序 web-view 的 Vue 页面单独识别,不能直接按公众号网页调 JSAPI 或 H5 支付;如该入口确有支付需求,按小程序实际开放能力设计原生页面承接,核对小程序 AppID、OpenID 与签名。识别到 MicroMessenger 不足以证明当前页面可直接使用某一种支付方式。 前端任何 success 回调、URL 参数、支付完成按钮和截图都不能更新后端为已支付。调起结束后向本系统查询状态;服务端用已验签的通知或可信微信查单结果确认支付。页面分别展示待支付、确认中、成功、失败或已关闭,等待通知期间不误报支付失败。 封装合适的支付流程与状态查询能力,处理组件卸载、路由切换、重复点击、多个窗口和再次进入。查询间隔、最长等待、退避与恢复条件配置化;前端停止轮询不代表业务放弃支付结果,后端仍要处理回调和必要补偿。 ### 支付回调先验真,再持久化和履约 读取通知原始请求体和 Wechatpay-Serial、Wechatpay-Signature、Wechatpay-Timestamp、Wechatpay-Nonce 等官方签名头,按实际 SDK 构造 RequestParam 并使用匹配的 NotificationParser 完成验签和解密。不能先重新序列化 JSON 再验签,不能只解密不验签,也不能假定签名头中的标识就是可信的商户身份。 密钥选择只能在后端受控配置中完成。未知标识、签名探测或验签失败不放行;按 SDK 与官方要求核对时间和防重放能力,不能把通知 create_time 简单当成首次支付时间或拒绝所有延迟通知。 验签解密后核验事件类型、支付结果、商户号、AppID、out_trade_no、transaction_id、金额、币种和本地订单关系。区分订单金额、用户实付及优惠字段,按官方含义比对,不能把优惠造成的实付差异误判为订单金额错误。通知中的附加字段只能用于受约束的关联,不能覆盖本地金额与身份。 重复通知、并发回调和主动查单共用一套幂等更新入口,采用数据库唯一约束、状态条件更新或必要的锁控制竞争。支付成功事实不能被随后到达的旧查询覆盖为未支付;退款也不能抹掉原支付成功事实。 先在短事务中提交支付事实与必要的业务状态或可重试履约任务,再应答成功。发货、开通权益、积分和外部调用等副作用通过可靠任务处理并有业务唯一键;不能先返回成功再只放进内存线程池,也不能在事务提交前发送不可回收的业务结果。 成功通知应答采用当前 API v3 要求的 HTTP 200 或 204,不返回 API v2 的 XML;优先使用明确的空响应实现。验签、解密或必要持久化失败时返回符合协议的失败响应,不用统一异常处理器把失败包装为 HTTP 200。合法重复通知在确认已可靠处理后可正常应答。 按官方时限尽快完成可靠接收,避免在回调里执行长耗时履约。商户、金额或订单关系不匹配的事件不得推动支付成功,保留受限的排查记录并进行可信查单;不要通过吞异常消除通知重试。 ### 查询、关单和履约的一致性 不能只依赖通知。对下单结果未知、长时间待支付、前端已返回但本地未确认、通知落库后履约失败等情况,使用持久化记录驱动有边界的查单和处理重试。复用现有调度或任务能力,记录次数、下次执行时间与处理结果,避免无限高频查询。 关单前后都处理支付竞争:本地超时或用户点取消不能证明微信未收款。对微信返回已支付、状态变化或关单结果未知的情况查单确认,不覆盖支付成功;订单是否释放库存或终止权益由业务规则决定。 实际支付发生在业务订单关闭边界时,保存支付事实并进入明确的异常业务处理,按已确认规则选择履约或退款,不能丢弃回调,也不能未经业务规则自动退款。 履约任务在重试、服务重启和多实例并发时只能产生一份有效业务结果。若外部系统不支持幂等,写清确认结果和人工核对路径,不宣称天然“恰好一次”。 需要核对账款时,按所选产品提供交易、退款记录与官方账单的业务核对入口,明确金额、优惠和时间口径。差异先记录和核实,不仅凭一行账单直接重复扣款、退款或强改订单;不把前端显示成功作为对账证据。 ### 退款覆盖受理、处理中和最终结果 退款必须验证操作角色、订单归属、支付成功事实、退款原因和业务资格。退款金额由已授权的业务退款记录确定;不允许前端任意指定他人交易号、商户号或超额金额直接退款。 明确支持全额退款、部分退款及多次退款的范围。每一笔逻辑退款使用稳定且唯一的 out_refund_no;重复点击和网络重试复用该退款单。申请结果未知时用原退款单号查单,不立即换号重新退款。 并发退款需在数据库中控制可退余额:已成功退款以及处理中、结果未知等尚未确定释放的申请都要按规则占用额度,不能只减去成功退款就允许并发超退。终态释放或调整额度必须有可信结果;金额始终使用精确整数单位。 使用当前官方 RefundService 及真实接口完成申请、按商户退款单号查询和退款通知处理。申请接口成功只代表受理或返回了当时状态,不能无条件把本地标为退款成功。依据响应、通知与后续查询识别 PROCESSING、SUCCESS、CLOSED、ABNORMAL 等官方状态,并明确异常后续动作。 退款通知使用独立业务入口或明确事件分发,但同样执行验签、解密、商户和原交易核验、退款单号、退款金额与原订单金额核验。通知与查询并发时复用幂等入口,退款成功不会被旧的处理中结果覆盖。 核对所用 SDK 通知模型的字段是否完整。例如 v0.2.17 的 RefundNotification 使用 getRefundStatus(),没有 getMchid();需要核验官方退款通知中的 mchid 等字段时,可定义匹配官方报文的完整 DTO,并交给 NotificationParser 验签解密后解析,不能臆造 getter、拿支付 Transaction 代替退款通知,或为方便读取而绕过验签。 退款完成后的库存、权益、优惠券及业务状态按原业务规则处理。支付退款和业务补偿分别记录,部分退款不能简单关闭全部权益;需要异步处理时用可靠任务和唯一业务键。 Vue 展示申请中、退款处理中、已退款与需处理的异常等准确状态。到账时间依据实际渠道说明,不写死承诺;用户点击“退款”或接口返回受理不能立即显示“已到账”。 ### 日志、异常和代码规范 日志关联业务订单号、支付单号、商户订单号、退款单号、通知 ID 和必要的微信请求标识,便于定位一次交易。保留必要的错误码和上下文,避免直接输出完整 SDK 响应、通知明文、OpenID、令牌、签名和秘密配置;需要留存原始通知时明确访问控制和最小留存范围。 区分参数错误、商户权限错误、签名或解密错误、业务状态冲突、限流、网络失败与结果未知。只对允许的错误进行有边界重试,保持原逻辑操作身份;不得把所有异常统一视为“支付失败,可以重新创建订单”。 后端采用清楚的业务命名与中文注释,重点解释金额、状态、幂等、权限和事务边界;不堆重复代码、无用工具类和魔法常量。前端遵守当前 ESLint、类型和格式规则,空格、缩进与换行一致。 时间和有效期以服务端及可信支付结果为准,正确保存带时区的支付与退款时间;前端倒计时用于展示,不能决定财务状态。验证长整型 ID、金额、枚举与日期在 Java、JSON、Vue 和数据库之间没有精度或含义变化。 ### 必须完成的验证 先运行不产生真实资金操作的本地单元、集成与前端测试。模拟微信客户端与通知适配层,使用隔离的测试密钥和带真实签名验证过程的测试报文;不能让测试绕过验签,也不能让测试构造的通知进入真实商户订单。 测试至少覆盖: - 后端金额计算、精确单位转换、非法金额、订单归属与跨租户访问。 - 重复下单、不同幂等键或跨场景并发下单、已有成功支付、过期支付信息和同一业务订单多支付尝试;验证无法通过切换入口绕过有效尝试唯一性。 - 微信已受理但本地下单超时、接口验签失败、查单返回未支付或成功,以及未知状态处理。 - 通知正常、重复、并发、乱序、伪造签名、原始体被修改、解密失败、错误商户或 AppID、金额或订单不匹配。 - 回调与查单同时更新、数据库提交失败、持久化后任务未执行、重试履约与多实例重复消费。 - 本地关闭与支付成功并发、关单结果未知、业务已取消后确认收款。 - 全额及部分退款、重复退款、并发超退、申请超时、处理中、成功、失败或异常,以及退款通知与查询乱序。 - Vue 支付取消、调起失败、桥接未就绪、H5 返回、Native 二维码过期、重复点击、刷新恢复、离开页面和轮询超时。 列出实际执行命令、环境、样例、预期与实际结果。没有执行的测试写明原因,不能把代码编译、前端模拟成功或手工改数据库当作支付联调通过。 不要假定所有 API v3 产品都有可用沙箱。核对所选产品当前提供的测试能力,明确本地模拟与微信真实联调的区别。真实扣款和退款只用于用户已明确授权的测试商户、订单、金额与退款范围,不自动进行额外资金操作。 联调时核对真实支付单、通知接收、可信查单、本地订单与履约结果;退款另行核对最终状态。分场景记录实际浏览器、微信环境和验证范围,不能通过一个场景就宣称全部场景可用。 ## 交付与验收 ### 交付内容和完成标准 交付完整后端支付与退款代码、Vue 页面或业务组件、数据库迁移及全部字段注释、配置示例、必要依赖、接口请求响应示例、通知处理实现与测试。示例中的文件路径、接口路径和命令必须与实际工程一致,不能留下伪代码和等待用户自行补全的关键方法。 给出简洁的支付和退款时序,以及状态允许如何转换;说明通知、查单、关闭、退款与履约如何汇合,不只罗列类名。保留必要的接入条件清单,区分开发者已完成的代码和仍需商户平台配置的项目。 中文使用步骤写清:配置来自哪里及放到哪里、安装依赖、执行数据库变更、启动 Java 与 Vue、打开支付入口、运行本地测试,以及在授权范围内完成真实联调的方法。优先更新已有说明或在回复中给出,不随意新增总结类 Markdown 文档。 最终说明改动文件、启用场景、实际测试与联调结果、未验证事项,以及缺少商户配置造成的具体边界。只完成代码与模拟测试时就按这个范围交付,不宣称真实扣款、退款、到账或全链路已验证。 ### 本条完成检查 - 实际交付订单级有效支付尝试控制、服务端金额与权限校验、通知查单收敛、可靠履约和并发退款占额实现。 - 后端与 Vue 按选定场景贯通,新增表全部字段具详细中文注释,通知失败不能被包装为 HTTP 200。 - 记录编译、隔离测试和获授权的真实联调结果,明确尚未验证的场景,不以模拟成功宣称扣款或到账成功。 按本条要求组织结果,使用简洁中文和一致的编号、术语、缩进及空行;已有项目格式优先。只说明实际完成的内容,将采用的假设、未完成项和缺少的条件写在相关位置,不额外生成无关文档。未执行、无法复现或缺少证据的检查如实标注,不宣称已通过或已有性能收益。 ## 参考资料与适用边界 本提示词结合微信支付 API v3 官方资料与工程一致性要求整理。商户接入条件、字段和 SDK 方法以实际锁定版本及当前官方文档为准;数据库结构、接口示例、幂等、事务和测试要求属于项目实现建议,不代表微信支付官方完整业务规范或认证。资料核验日期:2026-09-08;本提示词未代替具体商户的真实支付与退款联调。 [官方 Java SDK 与 v0.2.17 发布记录](https://github.com/wechatpay-apiv3/wechatpay-java/releases/tag/v0.2.17) [SDK 接入、调用与通知处理](https://github.com/wechatpay-apiv3/wechatpay-java/blob/v0.2.17/README.md) [证书与密钥职责](https://pay.wechatpay.cn/doc/v3/merchant/4024350132) [JSAPI 开发指引](https://pay.wechatpay.cn/doc/v3/merchant/4012791870) [JSAPI 调起支付签名](https://pay.wechatpay.cn/doc/v3/merchant/4012365339) [公众号网页授权](https://developers.weixin.qq.com/doc/service/guide/h5/auth.html) [微信 JS-SDK 接入与权限校验](https://developers.weixin.qq.com/doc/service/guide/h5/jssdk.html) [H5 调起与回跳](https://pay.wechatpay.cn/doc/v3/merchant/4012791835) [H5 支付场景与域名问题](https://pay.wechatpay.cn/doc/v3/merchant/4012791845) [Native 开发指引](https://pay.wechatpay.cn/doc/v3/merchant/4012791891) [小程序与 web-view 支付边界](https://pay.wechatpay.cn/doc/v3/merchant/4012791910) [支付成功通知](https://pay.wechatpay.cn/doc/v3/merchant/4012791861) [回调和查单配合](https://pay.wechatpay.cn/doc/v3/merchant/4012075249) [退款申请](https://pay.wechatpay.cn/doc/v3/merchant/4013071036) [查询单笔退款](https://pay.wechatpay.cn/doc/v3/merchant/4012791863) [退款结果通知](https://pay.wechatpay.cn/doc/v3/merchant/4013071196) [SDK 退款通知模型](https://github.com/wechatpay-apiv3/wechatpay-java/blob/v0.2.17/service/src/main/java/com/wechat/pay/java/service/refund/model/RefundNotification.java)
从真实负载和故障证据出发,完成批量访问、幂等、事务、重试与外部副作用优化,同时落实编码与XML SQL规范。
## 任务目标 请在当前目标工程中,完成本次范围内的 Java 性能、幂等与可靠性优化。必须先查证瓶颈,再完成代码修改和验证;不能只提出缓存、异步或加线程的建议。资料可从工程获得时自行读取,仅对影响正确性的关键缺口提问,继续完成其余已授权工作。 在现有授权范围内完成实际改动和验证;缺少外部条件时先完成可独立实现的部分,不能只停留在计划。 ## 输入信息(选填) 两项均可留空,也可直接用一句话说明目标并附上已有资料。无需自行整理版本、配置或完整需求表;能读取的内容由执行者补齐。 优化链路:优先选择当前对话指出的慢接口或重复执行问题;未指定时从当前 Java 工程的已有慢调用证据、循环访问和写操作中识别一条可定位、可验证的链路,说明选择依据后先完成该链路。 工程与性能资料:读取当前仓库的模块依赖、入口、SQL、事务、重试、已有测试和可用性能记录,自动确认版本、格式规则与验证命令,不要求用户重新填写这些信息。 ## 信息不完整时 先使用本次对话中已经说明的信息;用户留空、写“暂无/不清楚”或未替换输入标记,都按缺失处理,不当作真实路径、参数或业务值。已能从资料确定的内容不重复询问,不编造文件、日志、接口、业务值或执行结果。在用户已授权的范围内读取相关工程和材料,不为补齐输入擅自扩大操作范围。 ### 优先确认 - 沿入口追踪 SQL 与远程调用次数、循环取数、事务和锁范围,以及下游连接与线程资源。 - 读取业务幂等键、唯一约束、处理中记录、重试接管和结果查询实现,核对权限与租户范围。 - 检查实际 Maven 或 Gradle、MyBatis XML、数据库迁移、静态检查和格式配置。 - 查找代表性测试数据、已有压测结果、延迟与资源指标;没有实测时识别能够本地复现的访问模式。 ### 可采用的默认处理 - 沿用现有版本、接口契约与中间件;先修正有代码或测试证据的重复工作,不默认加缓存、异步或线程。 - 缺负载数据时先记录调用次数、批量边界和可测指标,性能收益保留待测,不编造吞吐或最优参数。 - 保留稳定数据库编码与旧数据语义,XML SQL 和局部格式规则按原约束实施,限制本轮改动范围。 ### 必须有依据的事项 - 同一业务意图的判定、同键异参处理或处理中接管规则没有可信依据时,不自行改变幂等业务结果。 - 批量改造会改变事务原子性、顺序、权限或外部副作用,而其业务容忍度无法确定时,暂停该项语义变更。 只有缺口会改变业务结果、权限边界或关键实现,且无法从现有资料确认时,才集中提出最多 3 个关键问题;说明影响,并继续完成不依赖答案的部分。一般命名、排版和可逆实现细节按现有约定决定,不逐项等待确认。 ### 资料仍不足时的交付 - 无工程时交付循环批量化与幂等状态的可执行示例、测量清单和故障用例,标明示例假设及尚未实施到项目。 - 缺运行环境时完成可执行的编译、静态检查和隔离回归,给出按同一数据与负载比较前后的测量步骤。 ## 执行要求 以实际运行版本和部署约束为准,不默认升级框架或引入中间件。SQL全部放XML、编码与字典分工等是本项目硬约束;MyBatis支持SQL注解,本项目明确禁用。 1. 只读确定范围和基线。确认仓库分支、未提交改动、真实入口及调用链,记录权限租户、返回字段、顺序分页、事务原子性和错误语义。保护无关改动,先运行已有相关检查,区分原有故障。用代表性数据和请求记录SQL/远程调用次数、延迟分位、吞吐、错误、连接等待、CPU与内存,写明并发、样本、冷热状态和时间窗口。缺少监控只能标记假设,不能虚构瓶颈或收益。 2. 按证据选择最小改动。区分数据库扫描、N+1、远程等待、锁竞争、重复计算和大对象分配,列出根因证据、候选方案、代价和可回退点。优先修正错误访问模式与重复工作,不为局部变快改变业务结果或降低权限校验,不一次叠加多个难以归因的优化。涉及架构或接口变化时明确新旧兼容,先完成范围内可验证的修改。 3. 优化for中的数据访问。定位循环查库、远程调用、懒加载和对象转换暗含的请求,按租户及业务键去重批量取数,再使用有界映射组装;没有批量接口时评估有界并发及下游限制,不能改成无界并行。控制单批参数量、页大小、事务时长和内存,避免巨大IN与全表加载。保留重复项、顺序、缺失关联和错误语义;联表注意行数膨胀与分页计数,跨页修改要考虑稳定游标与并发变化。for清晰就保留,不一律改Stream或parallelStream。 4. SQL统一落在XML Mapper。MyBatis的全部SQL从Java业务层、SQL注解、Provider、字符串或SQL Builder/Wrapper中迁入XML,Mapper接口只留契约和必要参数绑定;核对namespace、参数、resultMap、主键回填和加载。值使用#{参数}绑定,动态列、表和排序方向须服务端白名单并由XML选择固定片段,禁止将用户值送入美元符文本替换。空集合、全空更新和条件缺失不能变成全表操作。依据真实执行计划和数据分布调整查询及索引,不能仅以语法或扫描告警判断性能。 5. 将幂等设计落实到持久化。明确“同一次业务意图”的业务键、租户与操作范围、参数摘要和保留期,用数据库唯一约束或等效原子条件及事务争用执行资格,先查后插只能辅助。区分首次执行、处理中、成功、确定失败和结果不明;同键同内容按契约返回既有结果,同键不同内容拒绝冲突。并发唯一冲突须查询归属正确的记录,先核对当前事务是否仍可用,不吞异常后假成功;缓存锁和前端防抖都不能替代业务唯一性。 6. 处理超时、重试及接管。客户端超时不证明服务端未提交,优先用业务键查询最终状态,未经确认不得换新键重做。按失败类型定义可重试项、次数、退避和总时限;死锁等重试要重建正确事务边界,状态不明先对账。处理中记录须有合法接管条件,避免超时后旧执行者仍能写入;必要时用版本或执行令牌拒绝过期持有者。跨租户查询及结果回放都要重新验证权限。 7. 验证事务和外部副作用。核对代理方式、传播、事务管理器、锁范围及回滚规则;默认代理模式下自调用不会触发被调方法的事务语义,但可能仍处于外层事务。受检异常是否回滚按配置验证,不让catch吞掉失败。数据库事务不覆盖远程扣款、发信或消息投递;按已有能力使用下游业务幂等键、结果查询、可靠事件或补偿,并覆盖本地提交与外部成功不同步的窗口。afterCommit回调不等于可靠投递,不能承诺跨系统天然恰好一次。 8. 控制资源和失败放大。避免持数据库锁等待慢远程响应;减少事务范围前先保持业务原子性,不能随意拆批提交。线程池、队列、连接池、超时和并发上限按负载及下游容量设界,正确传播并清理租户和追踪上下文,处理中断与取消。缓存必须说明权限维度、更新失效与一致性要求,不能把数据库故障降级成成功空结果;优化不能把压力转嫁给下游而掩盖本地指标。 9. 同步完成编码与结构标准化。消除状态、类型、阈值和业务字符串魔法值;稳定有限的数据库编码用显式code的enum,核对序列化和TypeHandler,禁止ordinal持久化及随名称变化改库值。可配置字典数据库为唯一来源,不手工重复维护enum加字典;常量和配置各按语义归属。保留旧值、停用值和未知编码,读取可标未知但不篡改原值,写入或状态迁移需受控校验。Controller管协议入口,Service管领域和事务,Mapper管持久化;DTO、DO、VO明确转换,禁止越权批量赋值。 10. 复用、清理与防御并行。只抽取已证实共性,纯通用函数才入Util,领域逻辑留领域Service,不建万能Util或无必要的泛型框架。检查null拆箱、空集合、重复键、金额精度、时间边界与不可信参数;异常保留原因和业务标识,脱敏记录且不假成功。删除无用及重复代码前核对反射、XML、SPI、扫描、序列化和配置引用。规整命名结构,为类、关键字段、枚举及方法写清晰Javadoc和业务原因注释;新增表全部字段及新增字段须用COMMENT或对应语法补齐中文数据库注释,详细说明含义、单位、编码、空值和默认值。格式仅用既有规则及单一工具处理本轮文件,禁止整仓无关格式化,不生成无关Markdown。 11. 用实际结果验收。运行编译、现有检查和必要回归,在隔离验证环境覆盖重复提交、同键异参、多线程争用、越权租户、未知编码、空输入、批量边界、事务回滚、提交后响应丢失、外部成功但本地未确认、重试及过期接管。既核对响应也核对业务记录、金额和副作用次数,禁止仅断言HTTP成功。记录实际执行与未覆盖项;没有执行条件时完成可执行检查,不填写通过。 ## 交付与验收 对比并交付。在相同数据、并发、负载与观测窗口下对比修改前后延迟、吞吐、错误、查询次数和资源,不只报一次平均耗时;确认业务结果一致、尾延迟和下游未恶化。输出已改文件及原因、基线与证据、批量边界、幂等状态与唯一约束方案、事务及外部副作用矩阵、验证记录、回退和剩余风险。新增持久化结构使用项目既有迁移方式并验证历史重复数据与兼容回退;未实测不能声称性能提升,交付实际完成的修改而非待办方案。 格式落地补充:工程缺少成文配置时,以同模块稳定风格制定一套最小规则,明确空格、缩进、换行、空行、导入顺序及成员组织,用兼容的格式化或静态检查工具固化到现有构建。列出实际采用的规则和检查入口,不能只口头要求代码整齐,也不能额外引入相互冲突的格式工具。 ### 本条完成检查 - 交付实际修改及证据,说明 SQL/远程调用、批量内存、事务和幂等约束如何变化。 - 验证同键异参、并发争用、超时未知、过期接管、租户越权和外部副作用次数,不仅检查 HTTP 成功。 - 有实测才比较延迟、吞吐和资源;没有实测则明确未证实收益,并保留回退与历史数据兼容说明。 按本条要求组织结果,使用简洁中文和一致的编号、术语、缩进及空行;已有项目格式优先。只说明实际完成的内容,将采用的假设、未完成项和缺少的条件写在相关位置,不额外生成无关文档。未执行、无法复现或缺少证据的检查如实标注,不宣称已通过或已有性能收益。 ## 参考资料与适用边界 官方依据(2026-09-08核验,具体能力按项目版本确认,不代表完整企业内部规范): - 阿里巴巴《P3C-PMD 公开编码规则》:https://github.com/alibaba/p3c/blob/master/p3c-pmd/README.md - MyBatis《MyBatis 3:Mapper XML Files》:https://mybatis.org/mybatis-3/sqlmap-xml.html - MyBatis《MyBatis 3:Dynamic SQL》:https://mybatis.org/mybatis-3/dynamic-sql.html - Spring《Spring Framework:Using @Transactional》:https://docs.spring.io/spring-framework/reference/data-access/transaction/declarative/annotations.html - Spring《Spring Framework:Rolling Back a Declarative Transaction》:https://docs.spring.io/spring-framework/reference/data-access/transaction/declarative/rolling-back.html 收录核验(2026-09-08):已核对公开资料和本次项目要求的覆盖范围;尚未使用真实项目执行本模板或进行模型效果评测。具体改动、性能和回归结果须在目标工程中验证。
用于网络波动、主备切换和写命令超时,明确结果未知、可重试边界及重复执行后果。
## 任务目标 请审查 Redis 客户端的超时重试策略,并设计符合业务语义的幂等处理。 以核查和评审为主,给出有证据的判断及可复核的修改建议;本次用户另有明确实现要求时,按其授权范围执行。 ## 输入信息(选填) 两项均可留空,也可直接用一句话说明目标并附上已有资料。无需自行整理版本、配置或完整需求表;能读取的内容由执行者补齐。 重试业务:从当前问题或代码中识别使用 Redis 重试的业务操作;留空时优先检查递增、入队或带过期语义的写入,选一条有客户端和业务双层重试的完整链路。 代码与故障资料:读取 Redis 客户端依赖、连接与命令超时、业务重试封装、请求总时限和已有异常样本,版本与方法语义从实际工程确定。 ## 信息不完整时 先使用本次对话中已经说明的信息;用户留空、写“暂无/不清楚”或未替换输入标记,都按缺失处理,不当作真实路径、参数或业务值。已能从资料确定的内容不重复询问,不编造文件、日志、接口、业务值或执行结果。在用户已授权的范围内读取相关工程和材料,不为补齐输入擅自扩大操作范围。 ### 优先确认 - 追踪客户端、Service、网关与任务层的重试入口及次数。 - 识别命令执行、响应接收和业务确认的边界,找结果未知的处理代码。 - 核对业务请求标识、判重记录、保留期、结果查询及并发覆盖条件。 - 读取现有故障测试和每层超时配置,计算最坏请求次数及总耗时。 ### 可采用的默认处理 - 默认只读形成命令重试决策,不直接调整重试次数或扰动 Redis 连接。 - 无法判断是否执行的写操作归为结果未知,不按连接异常一律重发。 - 缺负载数据时按已知总时限列预算公式与停止条件,不指定所谓通用最优退避值。 ### 必须有依据的事项 - 重复执行对计数、队列、费用或过期时间的业务后果不明时,不认定该写操作可以安全重试。 - 业务请求唯一性、判重有效期或超时后的合法恢复动作缺少依据时,不承诺端到端幂等。 只有缺口会改变业务结果、权限边界或关键实现,且无法从现有资料确认时,才集中提出最多 3 个关键问题;说明影响,并继续完成不依赖答案的部分。一般命名、排版和可逆实现细节按现有约定决定,不逐项等待确认。 ### 资料仍不足时的交付 - 无代码时交付按命令语义分类的重试决策样例,以及多层放大和时间预算的计算模板。 - 无故障环境时提供发送前断开、执行后丢响应和并发旧值覆盖的隔离桩测试方案。 ## 执行要求 适用范围:Redis客户端重连与业务重试;先确认客户端及版本,连接重试和命令重试分开处理。厂商示例参数不能当作本项目推荐值。 将命令已执行但响应超时纳入分析,审查重试的幂等性,并防止多层重试放大请求。 检查步骤: 1. 列出哪些异常发生在连接、发送、执行或接收阶段,按现有证据区分确定未执行、确定执行和结果未知;网络超时本身不能证明写操作没有成功。 2. 逐条按业务结果审查命令重复执行的影响,特别检查递增、入队、计费和带过期语义的写入;即使命令形式相同,也要评估并发新值被旧请求覆盖的风险。 3. 追踪客户端、业务方法、接口网关和任务调度层是否各自重试,计算最坏请求次数与总耗时;为每个操作指定唯一的重试责任层。 4. 为可重试操作定义总期限、次数、退避及随机扰动,结合剩余预算和业务重要性决定何时停止;参数待压测时给出推导方式,不编造固定最优数值。 5. 对非幂等或结果未知的操作,设计业务请求标识、状态查询或对账路径,说明判重记录的生命周期与故障边界;不得仅套一把锁就宣称端到端恰好执行一次。 6. 仅在隔离测试环境或已明确授权的生产演练中验证发送前断开、执行后丢响应、主备切换及连续失败;优先使用代理或桩模拟故障,不扰动普通生产连接,记录业务动作次数、最终状态、请求耗时和重试放大量;验证恢复后积压不会再次冲击系统。 ## 交付与验收 输出要求:交付命令重试决策表、重试责任与预算、最小代码或配置、结果未知处理流程及故障用例。决策表写明“可重试条件|重复后果|停止条件|人工或自动对账入口”。 只报告有证据支持的问题;区分“已验证”“推测”和“待验证”,涉及变更时给出受影响文件或对象、最小修改和复核方法。代码与操作示例使用占位符,不写入真实密码。 ### 本条完成检查 - 每类操作明确可重试条件、重复后果、责任层、总预算和停止条件。 - 结果未知有业务标识与查询或核对路径,不能仅以锁或重连成功证明幂等。 - 测试核对业务动作次数、最终状态和重试放大量;未执行的故障注入不写已验证。 按本条要求组织结果,使用简洁中文和一致的编号、术语、缩进及空行;已有项目格式优先。只说明实际完成的内容,将采用的假设、未完成项和缺少的条件写在相关位置,不额外生成无关文档。未执行、无法复现或缺少证据的检查如实标注,不宣称已通过或已有性能收益。 ## 参考资料与适用边界 来源(核验日期:2026-09-08): [阿里云《Tair:客户端重试指南》](https://help.aliyun.com/zh/redis/use-cases/retry-mechanisms-for-redis-clients) 整理范围:仅依据上述公开文档的相关建议,业务场景、变量、检查流程与验收格式均为独立改写,不代表相关企业完整内部规范。