订单状态回调接口规范

# 规范说明

回调接口定义: 即商户后台下单时传入的回调接口地址,并且回调接口接收参数必须按照如下"请求参数"进行实现

回调接口作用: 当订单结束(成功或失败)时,TopPay会通过POST方式向商户后台发送请求,通知订单状态变化等信息

回调接口约束: 商户后台收到请求后,需返回"success"字符串,否则TopPay会认为回调失败

# 特别注意

回调接口验证: 商户后台收到请求后,需要用平台公钥对签名进行验证,能验证通过才是合法请求,才能进行业务处理

验证签名细节: 参数格式化时,需要过滤null和空字符串,详情可查看TopPaySignUtil#paramFormat方法代码实现

下面给出的示例代码,仅供参考,请根据实际情况进行修改

TopPaySignUtil点击获取代码示例

import java.util.HashMap;
import java.util.Map;
// import TopPaySignUtil;

public class CallBack {
    //平台公钥来自商户后台
    private static final String PLAT_PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUACahEnlP3aRj8yCT+WHzR+VvPBTw9S1i7iYWb+MY09CG/HYuHF4+IxshXDJygmndxKf/esuwPybS8mAd//yubHpmZsmBqg1FffT8VH1APa6ZRWASUp4U01ZrbCCp35QA8FuWrJGMJxGx4xk7KUtV2yujxC8noQIDAQAB";  

    //这里使用字典接收参数只是示例,实际开发中请根据实际情况进行修改
    public String callBackMethod(Map<String, String> requestParams) {
        //注意: 格式化请求参数之前 要确保去掉sign字段
        String sign = requestParams.remove("sign");

        //将接收到的参数格式化 并计算签名 并将签名值加入到请求参数中
        String source = TopPaySignUtil.paramFormat(requestParams);

        //签名验证
        boolean validReq = TopPaySignUtil.verify(PLAT_PUBLIC_KEY, source, sign);
        if (!validReq) {
            // ... 签名验证错误
            return "fail";
        }

        // ... 签名验证通过,执行正常的业务逻辑
        
        return "success"; //最后成功处理 一定要返回"success"字符串 否则TopPay会认为回调失败
    }
}

public class TestCallBack {
    public static void main(String[] args) {
        Map<String, String> requestParams = new HashMap<>();
        requestParams.put("platOrderNum", "S820190712000002");
        requestParams.put("merchantCode", "S820211021094748000001");
        requestParams.put("orderType", "1");
        requestParams.put("orderNum", "T1231511321515");
        requestParams.put("orderAmount", "100.00");
        requestParams.put("realAmount", "99.91");
        requestParams.put("status", "30");
        requestParams.put("timestamp", "1745377181");
        requestParams.put("utr", "HDFC1234567890");
        requestParams.put("sign", "Bf8ZfHn7UyHO8TsU8Xkh2sqa0hbpKH1HSPampNXxzBn5PvJoytb8zPkHuQ...");

        // 实例化 CallBack 类
        CallBack newObj = new CallBack();
        // 调用方法并打印结果
        String result = newObj.callBackMethod(requestParams);
        System.out.println(result);
    }
}
<?php
require_once 'TopPaySignUtil.php';

class CallBack
{
    //平台公钥来自商户后台
    private static $PLAT_PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUACahEnlP3aRj8yCT+WHzR+VvPBTw9S1i7iYWb+MY09CG/HYuHF4+IxshXDJygmndxKf/esuwPybS8mAd//yubHpmZsmBqg1FffT8VH1APa6ZRWASUp4U01ZrbCCp35QA8FuWrJGMJxGx4xk7KUtV2yujxC8noQIDAQAB";  

    //这里使用字典接收参数只是示例,实际开发中请根据实际情况进行修改
    public function callBackMethod($requestParams)
    {
        //注意: 格式化请求参数之前 要确保去掉sign字段
        $sign = $requestParams["sign"];
        unset($requestParams["sign"]);

        //将接收到的参数格式化 并计算签名 并将签名值加入到请求参数中
        $source = TopPaySignUtil::paramFormat($requestParams);

        //签名验证
        $validReq = TopPaySignUtil::verify(self::$PLAT_PUBLIC_KEY, $source, $sign);
        if (!$validReq) {
            // ... 签名验证错误
            return "fail";
        }

        // ... 签名验证通过,执行正常的业务逻辑

        return "success"; //最后成功处理 一定要返回"success"字符串 否则TopPay会认为回调失败
    }
}
// 实例化类
$callback = new CallBack();
$requestParams = [
    "platOrderNum" => "S820190712000002",
    "merchantCode"=>"S820211021094748000001",
    "orderType" => "1",
    "orderNum" => "T1231511321515",
    "orderAmount" => "100.00",
    "realAmount"=>"99.91",
    "status"=>"30",
    "timestamp"=>"1745377181",
    "utr"=>"HDFC1234567890",
    "sign" => "Bf8ZfHn7UyHO8TsU8Xkh2sqa0hbpKH1HSPampNXxzBn5PvJoytb8zPkHuQ...",
    ];
// 调用方法
$result = $callback->callBackMethod($requestParams);
// 输出结果给平台
echo $result;
using System;
using System.Collections.Generic;

class CallBack
{
    //平台公钥来自商户后台
    private static readonly string PLAT_PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUACahEnlP3aRj8yCT+WHzR+VvPBTw9S1i7iYWb+MY09CG/HYuHF4+IxshXDJygmndxKf/esuwPybS8mAd//yubHpmZsmBqg1FffT8VH1APa6ZRWASUp4U01ZrbCCp35QA8FuWrJGMJxGx4xk7KUtV2yujxC8noQIDAQAB";  

    //这里使用字典接收参数只是示例,实际开发中请根据实际情况进行修改
    public string CallBackMethod(Dictionary<string, string> requestParams)
    {
        //注意: 格式化请求参数之前 要确保去掉sign字段
        string sign = requestParams["sign"];
        requestParams.Remove("sign");

        //将接收到的参数格式化 并计算签名 并将签名值加入到请求参数中
        var source = TopPaySignUtil.ParamFormat(requestParams);

        //签名验证
        bool validReq = TopPaySignUtil.Verify(PLAT_PUBLIC_KEY, source, sign);
        if (!validReq)
        {
            // ... 签名验证错误
            return "fail";
        }

        // ... 签名验证通过,执行正常的业务逻辑

        return "success"; //最后成功处理 一定要返回"success"字符串 否则TopPay会认为回调失败
    }
}


class Program
{
    static void Main(string[] args)
    {
        // 构造入参字典
        var requestParams = new Dictionary<string, string>
        {
            { "platOrderNum", "S820190712000002" },
            { "merchantCode", "S820211021094748000001" },
            { "orderType", "1" },
            { "orderNum", "T1231511321515" },
            { "orderAmount", "100.00" },
            { "realAmount", "99.91" },
            { "status", "30" },
            { "timestamp", "1745377181" },
            { "utr", "HDFC1234567890" },
            { "sign", "Bf8ZfHn7UyHO8TsU8Xkh2sqa0hbpKH1HSPampNXxzBn5PvJoytb8zPkHuQ..." }
        };

        // 实例化 CallBack 类
        var newObj = new CallBack();

        // 调用方法并打印结果
        string result = newObj.CallBackMethod(requestParams);
        Console.WriteLine(result);
    }
}
package main

import (
    "fmt"
    // 请替换为你自己的工具包路径
    "github.com/your-username/your-top-pay-util-package/toppayutil"
)

// CallBack 定义回调类
type CallBack struct {
    //平台公钥来自商户后台
    PLAT_PUBLIC_KEY string = "MIGfMA0GCSqGSIb3DQEBAQUACahEnlP3aRj8yCT+WHzR+VvPBTw9S1i7iYWb+MY09CG/HYuHF4+IxshXDJygmndxKf/esuwPybS8mAd//yubHpmZsmBqg1FffT8VH1APa6ZRWASUp4U01ZrbCCp35QA8FuWrJGMJxGx4xk7KUtV2yujxC8noQIDAQAB"
}

// callBackMethod 处理回调方法
func (c *CallBack) callBackMethod(requestParams map[string]string) string {
    //注意: 格式化请求参数之前 要确保去掉sign字段
    sign, ok := requestParams["sign"]
    if ok {
        delete(requestParams, "sign")
    }

    //将接收到的参数格式化 并计算签名 并将签名值加入到请求参数中
    source := toppayutil.ParamFormat(requestParams)

    //签名验证
    validReq := toppayutil.Verify(c.PLAT_PUBLIC_KEY, source, sign)
    if!validReq {
        // ... 签名验证错误
        return "fail"
    }

    // ... 签名验证通过,执行正常的业务逻辑

    return "success" //最后成功处理 一定要返回"success"字符串 否则TopPay会认为回调失败
}

func main() {
    // 构造入参 map
    requestParams := map[string]string{
        "platOrderNum": "S820190712000002",
        "merchantCode": "S820211021094748000001",
        "orderType":    "1",
        "orderNum":     "T1231511321515",
        "orderAmount":  "100.00",
        "realAmount":   "99.91",
        "status":       "30",
        "timestamp":    "1745377181",
        "utr":          "HDFC1234567890",
        "sign":         "Bf8ZfHn7UyHO8TsU8Xkh2sqa0hbpKH1HSPampNXxzBn5PvJoytb8zPkHuQ...",
    }

    // 实例化 CallBack
    cb := &CallBack{
        PLAT_PUBLIC_KEY: "MIGfMA0GCSqGSIb3DQEBAQUACahEnlP3aRj8yCT+WHzR+VvPBTw9S1i7iYWb+MY09CG/HYuHF4+IxshXDJygmndxKf/esuwPybS8mAd//yubHpmZsmBqg1FffT8VH1APa6ZRWASUp4U01ZrbCCp35QA8FuWrJGMJxGx4xk7KUtV2yujxC8noQIDAQAB",
    }

    // 调用方法并打印结果
    result := cb.callBackMethod(requestParams)
    fmt.Println("回调处理结果:", result)
}
from TopPaySignUtil import TopPaySignUtil


class CallBack:
    # 平台公钥来自商户后台
    PLAT_PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUACahEnlP3aRj8yCT+WHzR+VvPBTw9S1i7iYWb+MY09CG/HYuHF4+IxshXDJygmndxKf/esuwPybS8mAd//yubHpmZsmBqg1FffT8VH1APa6ZRWASUp4U01ZrbCCp35QA8FuWrJGMJxGx4xk7KUtV2yujxC8noQIDAQAB"

    # 这里使用字典接收参数只是示例,实际开发中请根据实际情况进行修改
    def callBackMethod(self, requestParams):
        # 注意: 格式化请求参数之前 要确保去掉sign字段
        sign = requestParams.pop('sign', None)

        # 将接收到的参数格式化 并计算签名 并将签名值加入到请求参数中
        source = TopPaySignUtil.param_format(requestParams)

        # 签名验证
        validReq = TopPaySignUtil.verify(self.PLAT_PUBLIC_KEY, source, sign)
        if not validReq:
            # ... 签名验证错误
            return "fail"

        # ... 签名验证通过,执行正常的业务逻辑

        return "success"  # 最后成功处理 一定要返回"success"字符串 否则TopPay会认为回调失败

if __name__ == "__main__":
    # 构造入参字典
    requestParams = {
        "platOrderNum": "S820190712000002",
        "merchantCode": "S820211021094748000001",
        "orderType": "1",
        "orderNum": "T1231511321515",
        "orderAmount": "100.00",
        "realAmount": "99.91",
        "status": "30",
        "timestamp": "1745377181",
        "utr": "HDFC1234567890",
        "sign": "Bf8ZfHn7UyHO8TsU8Xkh2sqa0hbpKH1HSPampNXxzBn5PvJoytb8zPkHuQ..."
    }
    # 实例化 CallBack 类
    cb = CallBack()
    # 调用方法并打印结果
    result = cb.callBackMethod(requestParams)
    print("回调处理结果:", result)
const { TopPaySignUtil } = require('./TopPaySignUtil');

class CallBack {
    //平台公钥来自商户后台
    static PLAT_PUBLIC_KEY = `
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAybE+QuZsX5aqpfQTFMqq5HdundWTBDnoSJbI7iDGAcjyOCe5vg0pYUycEreThYYtftSsPePnNpq1R97MrGSLLd2BJ9veCHGAhclSStZo/1VQWvC9H5ANv48quQPgaT06fFRztoyrwDL5PElBQtZHQ54p51fDTVYx6xR3bGjphZN+kv6WyUlDTm9SeCqKfmU2PvgiguyHp6ACK7IGXerdbt0kt0C9zWLUxscu7JuBfmk4K2F2ttQ29TVrOArUHYgBs4wd+AKsiIM0rD76JWikfV7APWVDzWGpPNiGjKmD3ghhtj2LqYrKg2dAuBesKyRIFVKZFfuizciJFJq99OGPswIDAQAB
-----END PUBLIC KEY-----
`;

    //这里使用字典接收参数只是示例,实际开发中请根据实际情况进行修改
    callBackMethod(requestParams) {
        //注意: 格式化请求参数之前 要确保去掉sign字段
        const sign = requestParams.sign;
        delete requestParams.sign;

        //将接收到的参数格式化 并计算签名 并将签名值加入到请求参数中
        const source = TopPaySignUtil.paramFormat(requestParams);

        //签名验证
        const validReq = TopPaySignUtil.verify(CallBack.PLAT_PUBLIC_KEY, source, sign);
        if (!validReq) {
            // ... 签名验证错误
            return "fail";
        }

        // ... 签名验证通过,执行正常的业务逻辑

        return "success"; //最后成功处理 一定要返回"success"字符串 否则TopPay会认为回调失败
    }
}

const newObj = new CallBack();
console.log(newObj.callBackMethod({
    "platOrderNum":"S820190712000002",
    "merchantCode":"S820211021094748000001",
    "orderType":"1",
    "orderNum" : "T1231511321515",
    "orderAmount" : "100.00",
    "realAmount":"99.91",
    "status":"30",
    "timestamp":"1745377181",
    "utr":"HDFC1234567890",
    "sign" :"Bf8ZfHn7UyHO8TsU8Xkh2sqa0hbpKH1HSPampNXxzBn5PvJoytb8zPkHuQ...",
}))

# 请求地址

  • 请求方式 : POST
  • 请求地址 : 自定义

# 请求参数

参数 必填 描述 示例
platOrderNum Y 平台订单号 S820190712000002
merchantCode Y 商户ID S820211021094748000001
orderType Y 订单类型 1:代收 2:代付
orderNum Y 商户订单号 T1231511321515
orderAmount Y 订单金额(单位:1卢比) 100.00 回调金额以此为准
realAmount N 用户实际支付金额(单位:1卢比) 99.01仅需要时使用,几乎用不到
status Y 订单状态 20:处理中 30:成功 40:失败
timestamp Y 时间戳(秒),取系统实时时间戳 1745377181
utr N 统一交易参考号 HDFC1234567890
sign Y 签名 Bf8ZfHn7UyHO8TsU8Xkh2sqa0hbpKH1HSPampNXxzBn5PvJoytb8zPkHuQ

# 请求报文示例

{
  "platOrderNum": "S820190712000002",
  "merchantCode": "S820211021094748000001",
  "orderType": "1",
  "orderNum": "T1231511321515",
  "orderAmount": "100.00",
  "realAmount": "99.01",
  "status": "30",
  "timestamp": "1745377181",
  "utr": "HDFC1234567890",
  "sign": "Bf8ZfHn7UyHO8TsU8Xkh2sqa0hbpKH1HSPampNXxzBn5PvJoytb8zPkHuQ"
}

# 响应参数

成功处理,返回success字符串

# 响应报文示例

"success"