详情

首页手游攻略 微信支付 API v3 下单和退款怎样分阶段测试?

微信支付 API v3 下单和退款怎样分阶段测试?

佚名 2026-11-06 16:00:02

先查预支付标识,再确认付款,然后发起退款并等待退款单终态。下面用固定金额测试本地处理。

把下面脚本保存为 flow.py。它验证本地状态流转。接口响应和已解密事件均为样例,未发送真实请求。

import sqlite3
import sys

db = sqlite3.connect(":memory:")
db.execute("CREATE TABLE refund (id TEXT PRIMARY KEY, status TEXT NOT NULL)")
order_id, refund_id, total, refund = "ORDER-1", "REFUND-1", 100, 30
mode = sys.argv[1]

if mode == "order":
    response = {"prepay_id": "fixture-prepay"}
    assert response["prepay_id"] and total == 100
    print(order_id, "PREPAY_READY", total)
elif mode == "refund":
    payment = {"trade_state": "SUCCESS"}
    assert payment["trade_state"] == "SUCCESS" and 0 < refund <= total
    with db:
        db.execute("INSERT INTO refund VALUES (?, ?)", (refund_id, "PROCESSING"))
    print(refund_id, db.execute("SELECT status FROM refund").fetchone()[0])
elif mode == "notify":
    # A test fixture stands in for a verified and decrypted notification.
    event = {"id": refund_id, "status": "SUCCESS", "refund": 30}
    with db:
        db.execute("INSERT INTO refund VALUES (?, ?)", (refund_id, "PROCESSING"))
    for _ in range(2):
        assert event["id"] == refund_id and event["refund"] == refund
        assert event["status"] == "SUCCESS"
        with db:
            count = db.execute(
                "UPDATE refund SET status=? WHERE id=? AND status=?",
                ("SUCCESS", refund_id, "PROCESSING"),
            ).rowcount
        print(refund_id, "updated=" + str(count))
    assert db.execute("SELECT status FROM refund").fetchone() == ("SUCCESS",)
else:
    raise ValueError(mode)

1. 下单后检查预支付标识

调用 POST /v3/pay/transactions/jsapi 后记录商户订单号与 prepay_id。

python3 flow.py order
# ORDER-1 PREPAY_READY 100

prepay_id 用于客户端发起支付。用验签后的支付通知或查询单笔订单确认 trade_state 为 SUCCESS,再进入退款。

2. 申请退款后保留待确认状态

支付确认后调用 POST /v3/refund/domestic/refunds,记录 out_refund_no 和退款金额。

python3 flow.py refund
# REFUND-1 PROCESSING

申请被受理时仍需核对退款单状态。遇到同一笔申请超时,先按 out_refund_no 查询,再按原编号重试。查询路径为 GET /v3/refund/domestic/refunds/{out_refund_no}。

3. 重复通知只更新一次

以相同退款单号重放已验证的成功样例,检查第一次更新和第二次重放。

python3 flow.py notify
# REFUND-1 updated=1
# REFUND-1 updated=0

真实请求应使用原始请求体及 Wechatpay 请求头验签,按平台公钥或证书标识选择验签材料,然后用 APIv3 密钥解密 resource。核对商户、原订单、退款单号和金额。将通知持久化后按接口约定返回 200 或 204,异步处理时确保可恢复。

回调联调时再补验签失败、解密失败、重复发送、通知迟到和查询补偿。已确认成功的退款保持终态。本地样例覆盖状态与去重,商户联调还需核对产品权限、真实签名、回调可达性与实际退款状态。

点击查看更多
推荐专题
热门阅读