C:\Users\qmj\.jdks\graalvm-jdk-21.0.7。updatesql/sql.md 中 pos_order_omg_attempt DDL。pos_store_omg 中录入并启用 OMG stage 凭证。dd_id = parent_dd_id、pay_type='2'、pay_status=0、state IN (0,1,2)、amount>0。omgpay.return-url 是受控 HTTPS 地址,路径精确为 /pay/omg/notify。$env:JAVA_HOME='C:\Users\qmj\.jdks\graalvm-jdk-21.0.7'
$env:Path="$env:JAVA_HOME\bin;$env:Path"
mvn -pl ruoyi-system -am -Dtest='OmgPaymentAttemptServiceTest,OmgIpnAuditServiceTest' -Dsurefire.failIfNoSpecifiedTests=false test
mvn -pl ruoyi-admin -am -Dtest='OmgCheckMacSignerTest,OmgPaymentFormFactoryTest,OmgPaymentCreateServiceTest,OmgPaymentControllerTest,OmgNotifyFormParserTest,OmgNotifyRawBodyFilterTest,OmgPaymentNotifyServiceTest,OmgPaymentNotifyControllerTest' -Dsurefire.failIfNoSpecifiedTests=false test
mvn -pl ruoyi-admin -am -DskipTests package
$headers = @{ token = '<USER_TOKEN>' }
$body = @{ orderId = '<SINGLE_STORE_DD_ID>'; paymentMethod = 'CREDIT' } | ConvertTo-Json
$response = Invoke-RestMethod -Method Post `
-Uri 'https://<API_HOST>/pay/omg/create' `
-Headers $headers -ContentType 'application/json' -Body $body
$response.data
Expected:
status=CREATED。gatewayUrl 精确等于 stage AioCheckOut V5 地址。CREDIT 响应包含 ChoosePayment=Credit、UnionPay=2,且不包含 IgnorePayment。paymentMethod 改为 APPLE_PAY 后,新响应包含 ChoosePayment=ApplePay,且不包含 UnionPay 或 IgnorePayment。ChoosePayment=ALL。CheckMacValue 是 64 位大写十六进制。在客户端当前页面创建 <form method="post">,action 设置为 gatewayUrl,逐一把 formFields 的键和值创建为 hidden input,然后调用 form.submit()。不要设置 iframe target,也不要 window.open()。
Expected: 分别提交 CREDIT 和 APPLE_PAY 表单时,浏览器直接进入对应 OMG stage 付款流程并显示正确金额;不得出现超商快付、AFTEE 或其他渠道选择项。Apple Pay 仍需门店已开通且设备环境支持。
对同一 orderId 再调用创建接口。
Expected:
PAYMENT_ATTEMPT_EXISTS。formFields。dd_id 的 CREATED 行。用两个 PowerShell 作业同时提交同一订单:
$uri = 'https://<API_HOST>/pay/omg/create'
$tokenValue = '<USER_TOKEN>'
$json = (@{ orderId = '<SINGLE_STORE_DD_ID>' } | ConvertTo-Json -Compress)
$jobs = 1..2 | ForEach-Object {
Start-Job -ScriptBlock {
param($u, $t, $b)
Invoke-RestMethod -Method Post -Uri $u -Headers @{ token = $t } `
-ContentType 'application/json' -Body $b
} -ArgumentList $uri, $tokenValue, $json
}
$jobs | Wait-Job | Receive-Job
$jobs | Remove-Job
Expected: 一个请求成功,一个请求返回 PAYMENT_ATTEMPT_EXISTS。手动查询:
SELECT dd_id, COUNT(*) AS active_count
FROM pos_order_omg_attempt
WHERE active_dd_id = '<SINGLE_STORE_DD_ID>'
GROUP BY dd_id;
active_count 必须为 1。
分别验证无效 token、他人订单、多门店子订单、state=3/4、pay_status 非 0、amount<=0、pay_type 非 2、无启用凭证。每项都必须:
确认日志可按 orderId 定位创建开始、校验、成功或拒绝,异常路径含服务端堆栈。全文搜索不得出现:
formFields 或凭证对象序列化内容。使用真实 OMG stage 回调日志中的完整 form-urlencoded 内容重放;不要自行删除空值字段或额外字段:
$body = '<从 ipn_log.ipn_log 或应用日志复制的完整回调内容>'
Invoke-WebRequest -Method Post `
-Uri 'https://foodieapi.waimai-paotui.com/pay/omg/notify' `
-ContentType 'application/x-www-form-urlencoded' `
-Body $body
预期:
1|OK。RtnCode=1(包括 SimulatePaid=1)后,尝试为 PAID、订单 pay_status=1,订单 state/delivery_status 不变。RtnCode!=1 后,尝试为 FAILED、订单仍未付款,下一次 create 可生成新尝试。1|OK,不重复推进任何订单业务状态。0|ERROR,支付和订单事实不变。ipn_log 新增 type=omg 的完整原文,包括验签失败请求。本阶段不验收查询、补单、取号、退款或推送;不得把旧 OMG 回调或旧查询结果作为新流程证据。