法币代收异步通知
# 代收异步通知
本接口由商户提供,当代收成功平台请求该接口 接收到HTTP请求时,请响应httpcode=200(HTTP 响应状态码) ,否则会在5小时内重复发送16次通知.
⚠️⚠️注意:用户支付有可能会只支付部分金额,需校对“实际支付金额”⚠️⚠️
# 最佳实践
- 对于支付成功的判定,orderStatus是1
- 对于部分支付的判定:orderStatus是3。请商户根据自身业务逻辑处理
- 对于退款的判定:orderStatus是2。这种情况一般是出现在用户投诉以及银行风控退回,请商户做好相关记录并根据自身业务逻辑进行处理(收到此回调状态之前会先收到回调成功)
- 若是商户业务逻辑上处理失败,请将响应的HTTP状态码改为400或者500(非200)
- Cheezeepay可能会多次发送相同状态的回调,请商户做好相关兼容处理,如商户自身业务已经处理完成,请务必返回响应HTTP状态码200
- 请务必校验回调IP➕验证签名
| 参数 | 类型 | 必填 | 描述 | 示例 |
|---|---|---|---|---|
| merchantId | string | Y | 商户ID | CH10001165 |
| mchOrderNo | string | Y | 商户订单号 | C202401090023 |
| platOrderNo | string | Y | 平台订单号 | 1746060142200229888 |
| orderStatus | int | Y | 订单状态 | 1-成功 2-退款 3-部分支付(暂时没有3这个状态) |
| payAmount | string | Y | 订单实付金额 | 800 |
| amountCurrency | string | Y | 订单金额币种 | INR |
| fee | string | Y | 手续费 | 88 |
| feeCurrency | string | Y | 手续费币种 | INR |
| gmtEnd | long | Y | 完结时间(时间戳:毫秒) | 1705128180000 |
| utr | string | N | UTR(银行流水参考号);无可为空字符串或不下发 | 923238912091 |
| paymentInfo | object | N | 收付款方式类型及收款侧明细;结构与 paymentMethodType 对应,见下文 paymentInfo,无数据时可省略 | — |
| payerUpiId | string | N | 付款人 UPI Id;可无、为空字符串或 null | xxxxxx1@iob |
| kycPass | Boolean | N | 是否通过KYC校验 | true |
| kycInfo | String | N | KYC校验信息 | KYC name verification passed |
| sign | string | Y | 签名 | EcCs7GlN1UzEAflgpyJ4lKIHe9+lS/gdkcEvWI +nSlcvvz1c+Dg4Zi8sFmpYaoOMGxS3/BY66F Gq2TXzVGhAciq2kFmwZFtYbFvr7xPTaNf/n0R u7ZtV/jo3uBnfc9/JI6XlEWlIbPtGsVpH7CLhzgh dqIT+YbPEdhX2ZKETFTTfIj6PzctY9eOsZ51Yb HYnXv0jTWn1hdPoDofAF9RmoNaXK4FGYibQ BSvVA6w4rM6hCXlbTeHdMc4askrZlrHeG3uhyD 34VlXs74cdzAZ+oROMXBcgXR4ObsJVDFz9tsJ H92iaxlKTF0lEFZa/To5ezLpHvTOAK0uY/K6IxvO AAg== |
# paymentInfo 字段说明
paymentInfo 承载当前订单相关的 收款方式类型及信息。一般由 paymentMethodType 标明渠道(目前有以下几种收款方式类型:[UPI]、[PhonePe]、[Paytm]、[IMPS]、[Bank Transfer(India)] 等,以服务端实际返回文案为准)。不需要该数据的商户,paymentInfo 不下发,非必传。异步回调与 代收查询接口 中的 paymentInfo 结构与含义一致;验签若涉及嵌套对象,请按平台约定的序列化规则处理。
# UPI-支付方式示例参数
| 字段 | 类型 | 必填 | 说明(业务含义) |
|---|---|---|---|
| paymentMethodType | String | N | 支付方式类型;示例取值:[UPI] |
| name | String | N | Name |
| upiId | String | N | UPI Id(接口字段常见为 upiId,以服务端为准) |
# PhonePe-支付方式示例参数
| 字段 | 类型 | 必填 | 说明(业务含义) |
|---|---|---|---|
| paymentMethodType | String | N | 支付方式类型;示例取值:[PhonePe] |
| name | String | N | Name |
| phoneNumber | String | N | Phone Number |
# Paytm-支付方式示例参数
| 字段 | 类型 | 必填 | 说明(业务含义) |
|---|---|---|---|
| paymentMethodType | String | N | 支付方式类型;示例取值:[Paytm] |
| name | String | N | Name |
| phoneNumber | String | N | Phone Number |
# IMPS-支付方式示例参数
| 字段 | 类型 | 必填 | 说明(业务含义) |
|---|---|---|---|
| paymentMethodType | String | N | 支付方式类型;示例取值:[IMPS] |
| name | String | N | Name |
| accountNumber | String | N | Account Number / Card Number |
| ifscCode | String | N | IFSC code |
| bankName | String | N | Bank name |
| accountType | String | N | Account Type(可选) |
| branchName | String | N | Branch name |
# Bank Transfer (India)-支付方式示例参数
| 字段 | 类型 | 必填 | 说明(业务含义) |
|---|---|---|---|
| paymentMethodType | String | N | 支付方式类型;示例取值:[Bank Transfer(India)] |
| name | String | N | Name |
| accountNumber | String | N | Account Number / Card Number |
| ifscCode | String | N | IFSC code |
| bankName | String | N | Bank name |
| accountType | String | N | Account Type(可选) |
| branchName | String | N | Branch name |
# 异步通知报文示例
{
"merchantId": "CH10001201",
"mchOrderNo": "20260520181913",
"platOrderNo": "2057043474855759872",
"orderStatus": 1,
"payAmount": "1000.1",
"amountCurrency": "INR",
"fee": "0.5022599",
"feeCurrency": "USDT",
"gmtEnd": 1779272767000,
"utr": "923238912091",
"paymentInfo": {
"paymentMethodType": "[PhonePe]",
"name": "KLAS LL HU",
"phoneNumber": "319712389127@phone"
},
"payerUpiId": "",
"kycPass": true,
"kycInfo": "KYC name verification passed",
"sign": "ZhCW+JRABhkeEpo5mvp9xjU1OoSd6y4Mj4t/586gcJNyyBzApMK/HM9ZP+7eo4tPi4n6AVKlTnFTKs8Lpu51ahRXHdfim8ZPx+ulzoYYyqyDT6KMSQ4hn5Fp+YqLZr5CEBjdh1IPffP3tJB/OWc7RNRMAeuh3m7GhHdcbC1GiKqy4rfb3DyXNnabke/lkfbvmpi33YmcrosUcXOOfr8dc8sOqZHSUAwPwcsaGAkTDdq3wFundWC/EI0HBOjXdDcyUDvAGXx7brZdBJoL602V6SW12HOmumm+x3smYP0HG0ZbYvABHTRXZAIziCgi9V137uziDwd1X5ej8QCIgU+hNg=="
}
# 异步通知代码实现Demo
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
@RestController
@RequestMapping("callback")
public class TestCallbackController {
/**
* 平台公钥
*/
public static String PLATFORM_PUB_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1dad35S74jfLPbHJh8P0jDHiTvkxwrtITK97ovVu19B24UdiHyHoEZgtNlS6alFQj1ULQ71d6EPh2rWCNkS2b5HGQXwDYBtwvesVQ8h4Sf3eVPTTLGw3BS7Os4vtDEN6BezMdv3sUG2N5i6JF+5H4CQTq3MD2Cx6u/Cv7oFOdFqeDT0AH+TR7uyZxn69OtkJaHHr834EUcdShJKKMQtbC11WCcut7ilDUgdvZnThiVTq7cfl8mcC9FDKcQ9bMWamScWIB5cJQdUW23Kr0c1NvZlpgPS8U5VODM4Uc4muHJPD2cJmquuJ+4AGP36rEk27lUB3h7B6JI1QGiuh1yyPDwIDAQAB";
/**
* 代收回调
* @param paramMap
* @param response
*/
@PostMapping("payIn")
public void payInCallback(@RequestBody Map<String, Object> paramMap, HttpServletResponse response) throws Exception{
boolean verifyResult = CheeseTradeRSAUtil.verifySign(paramMap, PLATFORM_PUB_KEY);
if (verifyResult) {
//签名验证成功
//订单通知业务处理逻辑
String merchantId = (String)paramMap.get("merchantId");
String mchOrderNo = (String)paramMap.get("mchOrderNo");
String platOrderNo = (String)paramMap.get("platOrderNo");
Integer orderStatus = (Integer)paramMap.get("orderStatus");
String payAmount = (String)paramMap.get("payAmount");
String amountCurrency = (String)paramMap.get("amountCurrency");
String fee = (String)paramMap.get("fee");
String feeCurrency = (String)paramMap.get("feeCurrency");
Long gmtEnd = (Long)paramMap.get("gmtEnd");
// utr——非必传,可能为空
String utr = paramMap.containsKey("utr") ? String.valueOf(paramMap.get("utr")) : null;
// paymentInfo——非必传(嵌套 Map),结构与支付方式有关
Object paymentInfoObj = paramMap.get("paymentInfo");
// payerUpiId——请注意该参数非必传,可能为空字符串
String payerUpiId = paramMap.containsKey("payerUpiId") ? (paramMap.get("payerUpiId") != null ? String.valueOf(paramMap.get("payerUpiId")) : "") : "";
// kycPass——请注意该参数非必传,可能为null
Boolean kycPass = paramMap.containsKey("kycPass") ? (Boolean) paramMap.get("kycPass") : null;
// kycInfo——请注意该参数非必传,可能为null
String kycInfo = paramMap.containsKey("kycInfo") ? String.valueOf(paramMap.get("kycInfo")) : null;
if (paymentInfoObj instanceof Map) {
@SuppressWarnings("unchecked")
Map<String, Object> paymentInfo = (Map<String, Object>) paymentInfoObj;
// 按需读取,例如 Wallet:paymentMethodType / name / phoneNumber
// String phoneNumber = paymentInfo.get("phoneNumber") != null ? String.valueOf(paymentInfo.get("phoneNumber")) : null;
}
} else {
//签名认证失败
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
}
}
}