重发回调通知接口

更新时间:2026-07-10

接口说明

重发异步回调通知接口,支持通过平台订单号transactionNo)或商户订单号orderNo)重新发送支付成功的异步回调消息给商户。

适用对象
间连商户
请求 URL
https://openapi.shuhuipay.com/v1/order/notify
请求方法
POST
💡
使用场景:
  • 商户未收到异步通知或通知处理失败,需要重发
  • 商户主动请求重发通知以更新订单状态
  • 仅对支付成功(status=2)的订单有效
⚠️
频率限制:
  • 每个商户每分钟最多调用 60 次,超过限制将返回错误码 9000
  • 建议商户端做好请求频率控制,避免频繁调用

请求参数(bizContent)

ℹ️ transactionNoorderNo 二者必须提供其中一个。推荐使用 transactionNo(平台订单号)进行查询,效率更高。
参数名 类型 必填 参数说明
transactionNo String 二选一 平台订单号,与 orderNo 二选一
orderNo String 二选一 商户订单号,与 transactionNo 二选一

请求示例

通过 transactionNo 查询(推荐)

JSON
{
  "appId": "you_system_appid",
  "subMerchantNo": "your_user_id",
  "bizContent": "{\"transactionNo\":\"SHPAY_202607021507077387091\"}",
  "version": "1.0",
  "nonce": "49d55020fa3adf6ed67b253c583ccdaa",
  "contentHash": "95772c8a0c74e52b707e2ace5963e0eae956e8b1ae26e86a6cde5469247d0382",
  "timestamp": "2026-07-10 14:33:11",
  "sign": "your_sign"
}

通过 orderNo 查询

JSON
{
  "appId": "you_system_appid",
  "subMerchantNo": "your_user_id",
  "bizContent": "{\"orderNo\":\"TEST202607021506596406\"}",
  "version": "1.0",
  "nonce": "49d55020fa3adf6ed67b253c583ccdaa",
  "contentHash": "95772c8a0c74e52b707e2ace5963e0eae956e8b1ae26e86a6cde5469247d0382",
  "timestamp": "2026-07-10 14:33:11",
  "sign": "your_sign"
}

响应参数

公共返回参数

参数 类型 必须 参数说明
code String Y 响应状态码,成功 0000
message String Y 响应描述
timestamp String Y 响应时间戳,UTC 时间,ISO 8601 格式
data Object Y 业务数据,无数据时返回空对象 {}

响应附加参数(data)

参数名 类型 必填 参数说明
transactionNo String Y 平台订单号
orderNo String Y 商户订单号
notifyStatus Integer Y 通知状态,1 表示通知发送成功

错误码说明

错误码 说明
0000 成功
4001 参数错误(transactionNo 和 orderNo 同时为空)
4000 业务错误(订单未支付、未配置通知地址等)
4004 订单不存在
5000 系统异常或通知发送失败

响应示例

成功响应:

JSON
{
  "code": "0000",
  "message": "通知发送成功",
  "timestamp": "2026-07-10T10:30:00.000Z",
  "data": {
    "transactionNo": "SHPAY_202607021507077387091",
    "orderNo": "TEST202607021506596406",
    "notifyStatus": 1
  }
}

失败响应:

JSON
// 订单未支付,无法发送通知
{
  "code": "4000",
  "message": "订单未支付,无法发送通知",
  "timestamp": "2026-07-10T10:30:00.000Z",
  "data": {}
}

// 参数缺失
{
  "code": "4001",
  "message": "transactionNo 和 orderNo 不能同时为空",
  "timestamp": "2026-07-10T10:30:00.000Z",
  "data": {}
}

// 订单不存在
{
  "code": "4004",
  "message": "订单号 ORDER202501150001 不存在或不属于当前商户",
  "timestamp": "2026-07-10T10:30:00.000Z",
  "data": {}
}

代码示例

Java
import java.util.HashMap;
import java.util.Map;
import com.alibaba.fastjson.JSON;

public class ReplayNotifyExample {
    public static void main(String[] args) {
        // 方式一:通过平台订单号重发通知
        Map<String, String> notifyByTransactionNo = new HashMap<>();
        notifyByTransactionNo.put("transactionNo", "SHPAY_202607021507077387091");
        String result1 = replayNotify(notifyByTransactionNo);
        System.out.println("重发结果:" + result1);

        // 方式二:通过商户订单号重发通知
        Map<String, String> notifyByOrderNo = new HashMap<>();
        notifyByOrderNo.put("orderNo", "TEST202607021506596406");
        String result2 = replayNotify(notifyByOrderNo);
        System.out.println("重发结果:" + result2);
    }

    public static String replayNotify(Map<String, String> queryParams) {
        String appId = "your_app_id";
        String subMerchantNo = "your_user_id";
        String signKey = "your_sign_key";
        String apiUrl = "https://openapi.shuhuipay.com/v1/order/notify";

        Map<String, String> requestData = new HashMap<>();
        requestData.put("appId", appId);
        requestData.put("subMerchantNo", subMerchantNo);
        requestData.put("bizContent", JSON.toJSONString(queryParams));
        requestData.put("version", "1.0");
        requestData.put("nonce", "49d55020fa3adf6ed67b253c583ccdaa");
        requestData.put("contentHash", "95772c8a0c74e52b707e2ace5963e0eae956e8b1ae26e86a6cde5469247d0382");
        requestData.put("timestamp", "2026-07-10 14:33:11");

        String sign = SignUtil.generateSign(requestData, signKey);
        requestData.put("sign", sign);

        String response = HttpUtil.post(apiUrl, requestData);
        return response;
    }
}
Python
import requests
import json
import hashlib

def replay_notify(query_params):
    """重发异步回调通知"""
    sys_appid = "your_sys_appid"
    open_subMerchantNo = "your_open_subMerchantNo"
    sign_key = "your_sign_key"
    api_url = "https://openapi.shuhuipay.com/v1/order/notify"

    request_data = {
        "sys_appid": sys_appid,
        "open_subMerchantNo": open_subMerchantNo,
        "version": "1.0",
        "timestamp": "2026-07-10 14:33:11",
        "replay": "49d55020fa3adf6ed67b253c583ccdaa",
        "bizContent": json.dumps(query_params),
        "data_hash": "95772c8a0c74e52b707e2ace5963e0eae956e8b1ae26e86a6cde5469247d0382",
    }

    sign = generate_sign(request_data, sign_key)
    request_data["sign"] = sign

    try:
        response = requests.post(api_url, json=request_data, timeout=30)
        return response.json()
    except Exception as e:
        print(f"重发通知失败: {e}")
        return None

def generate_sign(params, sign_key):
    sorted_params = sorted(params.items())
    sign_str = "&".join([f"{k}={v}" for k, v in sorted_params if v])
    sign_str += f"&key={sign_key}"
    return hashlib.md5(sign_str.encode()).hexdigest().upper()

# 方式一:通过平台订单号重发通知
result1 = replay_notify({"transactionNo": "SHPAY_202607021507077387091"})

# 方式二:通过商户订单号重发通知
result2 = replay_notify({"orderNo": "TEST202607021506596406"})

# 处理返回结果
if result1 and result1.get("code") == "0000":
    data = result1.get("data", {})
    print("通知发送成功")
    print(f"平台订单号: {data.get('transactionNo')}")
    print(f"商户订单号: {data.get('orderNo')}")
else:
    print(f"通知发送失败: {result1.get('message')}")
PHP
<?php

class ReplayNotify {
    private $appId = 'your_app_id';
    private $subMerchantNo = 'your_user_id';
    private $signKey = 'your_sign_key';
    private $apiUrl = 'https://openapi.shuhuipay.com/v1/order/notify';

    public function replayNotify($queryParams) {
        $requestData = [
            'appId'       => $this->appId,
            'subMerchantNo'      => $this->subMerchantNo,
            'bizContent'  => json_encode($queryParams),
            'version'     => '1.0',
            'nonce'       => '49d55020fa3adf6ed67b253c583ccdaa',
            'contentHash' => '95772c8a0c74e52b707e2ace5963e0eae956e8b1ae26e86a6cde5469247d0382',
            'timestamp'   => '2026-07-10 14:33:11',
        ];

        $requestData['sign'] = $this->generateSign($requestData);
        $response = $this->httpPost($this->apiUrl, $requestData);
        return json_decode($response, true);
    }

    private function generateSign($params) {
        ksort($params);
        $signStr = '';
        foreach ($params as $key => $value) {
            if ($value !== '') {
                $signStr .= "{$key}={$value}&";
            }
        }
        $signStr .= "key={$this->signKey}";
        return strtoupper(md5($signStr));
    }

    private function httpPost($url, $data) {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
        $response = curl_exec($ch);
        curl_close($ch);
        return $response;
    }
}

// 方式一:通过平台订单号重发通知
$result1 = (new ReplayNotify())->replayNotify([
    'transactionNo' => 'SHPAY_202607021507077387091'
]);

// 方式二:通过商户订单号重发通知
$result2 = (new ReplayNotify())->replayNotify([
    'orderNo' => 'TEST202607021506596406'
]);

// 处理返回结果
if ($result1 && $result1['code'] === '0000') {
    $data = $result1['data'] ?? [];
    echo "通知发送成功\n";
    echo "平台订单号: " . ($data['transactionNo'] ?? '') . "\n";
    echo "商户订单号: " . ($data['orderNo'] ?? '') . "\n";
} else {
    echo "通知发送失败: " . ($result1['message'] ?? '未知错误') . "\n";
}

注意事项

⚠️
调用限制:
  • 仅对支付成功(status=2)的订单有效,其他状态会返回错误码 4000
  • 订单必须配置了 notify_url,否则无法发送通知
  • 每个商户每分钟最多调用 60 次,超过限制将返回错误码 9000
💡
使用建议:
  • 推荐使用 transactionNo(平台订单号)进行调用,效率更高
  • 通知会重新签名并发送到订单的 notify_url
  • 发送结果会记录到通知日志表,可通过管理后台查看
最佳实践:
  • 仅在商户确认未收到通知或通知处理失败时调用此接口
  • 调用后请检查返回的 notifyStatus 字段确认通知是否发送成功
  • 建议在调用前先使用订单查询接口确认订单状态