================================================================================ AmiPay / CPay 商户对接接口文档(印度 UPI) 面向:游戏厂商 / 商户技术对接 版本:1.0.3 商户管理后台:https://amipay.net/merchant/ (登录后可查看订单、应用、密钥/白名单等;账号由平台开通时下发) 支付网关:https://amipay.net/gateway 在线签名/验签工具:https://amipay.net/tools/sign-tool.html (纯浏览器本地计算,私钥不上传;含签名、验签、多语言示例) 更新日期:2026-09-05 说明:本文档响应字段以当前网关 Java RS 实际序列化为准;null / 空字符串字段通常不出现在 JSON 中。 ================================================================================ 一、对接前准备 -------------------------------------------------------------------------------- 1. 平台分配: - 商户管理后台地址:https://amipay.net/merchant/ - merchantNo(商户号),如 C1788073687 - appId(应用 ID) - 登录账号 / 初始密码(开通商户时下发,可在后台修改密码) - 平台公钥(用于商户验签平台返回 / 异步通知) - 商户自行生成 RSA2048 密钥对: * 私钥:商户本地保管,用于请求签名(切勿泄露) * 公钥:交给平台,写入商户应用 appSecret 2. IP 白名单: - 商户服务器出口公网 IP 需配置到应用「IP 白名单」 - 未配置或 IP 不匹配将返回:ip not in white list 3. 支付方式(wayCode) - 请求 Body 请传编码:IND_UPI(代收) / IND_UPI_OUT(代付) - 查单 / 回调响应里的 wayCode 通常是展示名,例如 "India upi" / "India upi payout" (不要用响应里的展示名去当下单请求参数) 4. 金额约定: - 单位:分(最小货币单位) - 1 INR = 100 分 - 最低金额:100 INR → amount 最小为 10000 - 响应 / 回调中金额多为带小数的数字(如 20000.00),验签时必须按报文原文保留小数位 二、通用约定 -------------------------------------------------------------------------------- 1. 协议 - HTTP Method:POST - Content-Type:application/json; charset=UTF-8 - 字符集:UTF-8 2. 请求头(必填) --------------------------------------------------------------------------- Header 名 说明 示例 --------------------------------------------------------------------------- Version 接口版本,固定 1.0.0 Sign-Type 签名类型,固定 RSA Req-Time Unix 秒级时间戳 1725000000 Sign 请求体 RSA 签名(Base64) Content-Type application/json --------------------------------------------------------------------------- 说明:参与签名的字段仅为 Body JSON 业务字段(不含 Header、不含 sign)。 3. 统一响应外壳(下单 / 查单 / 余额 / 提现等同步接口均为该结构) { "code": "0", "msg": "SUCCESS", "data": { ... }, "sign": "..." } - code=0 仅表示接口调用成功,不等于业务支付成功 - sign:平台对 data 对象的 RSA 签名;商户用平台公钥验签 - 异步通知不是该外壳,见第七章 4. 订单状态 0 - 订单生成 1 - 处理中 / 支付中 2 - 成功 3 - 失败 4 - 已撤销 5 - 已退款 6 - 已关闭 7 - 拒付 字段名注意: - 同步下单响应:orderState - 查单 / 异步通知:state 入账请以「异步通知 + 主动查单」双确认 state/orderState = 2。 三、签名算法(RSA,必读) -------------------------------------------------------------------------------- 算法:SHA256withRSA 密钥:商户私钥签名请求;平台公钥验签响应 / 回调 编码:签名结果 Base64 3.1 待签名字符串构造(请求签名 / 响应验签 / 异步通知验签共用) 1) 取 Body(或 data / 回调 JSON)中全部字段 2) 去掉 sign、signature、fileData(若有) 3) 跳过值为 null 或空字符串 "" 的字段 4) 按参数名 ASCII 自然序排序(Java TreeMap,区分大小写) 5) 拼成:key1=value1&key2=value2&...(末尾无多余 &) - 数字须与报文原文一致(如 20000.00,不可写成 20000) 6) channelExtra 若为对象/字符串,整段作为 value,不要拆内部字段 3.2 验签 - 同步响应:对 data 内字段拼串,用顶层 sign - 异步通知:对整包扁平 JSON 拼串(去掉 sign) - 用平台公钥做 SHA256withRSA 验签 3.3 在线工具 https://amipay.net/tools/sign-tool.html 四、接口一览 -------------------------------------------------------------------------------- 1) 统一下单 POST /api/order/pay 2) 订单查询 POST /api/order/query 3) 余额查询 POST /api/account/balance 4) 异步通知 商户 notifyUrl(平台主动 POST) 5) 提现申请 POST /api/account/cashout(附录) 6) 提现查询 POST /api/account/cashoutQuery(附录) ================================================================================ 五、统一下单 POST /api/order/pay ================================================================================ 完整 URL:https://amipay.net/gateway/api/order/pay 5.1 请求 Body --------------------------------------------------------------------------- 字段 类型 必填 说明 --------------------------------------------------------------------------- merchantNo String Y 商户号 appId String Y 应用 ID orderNo String Y 商户订单号(商户侧唯一) wayCode String Y IND_UPI / IND_UPI_OUT amount Number Y 商户下单交易金额,单位分(非元);最低 10000(=100 INR) currency String Y INR description String Y 商品 / 订单描述 channelExtra String Y 渠道扩展,JSON 字符串(见下) notifyUrl String N 异步通知地址(强烈建议填) returnUrl String N 支付完成跳转 clientIp String N 玩家端 IP userId String N 商户侧用户 ID,≤50 expiredTime String N 可选;单位秒。可传可不传,不传不影响下单。 当前多数印度通道会忽略本参数(平台侧常固定约 30 分钟仅作记录)。 平台目前不会按该字段自动关闭订单;终态以异步通知 / 查单为准,请勿依赖本字段做关单逻辑。 extParam String N 透传字段,回调原样返回 --------------------------------------------------------------------------- 5.2 代收 channelExtra(IND_UPI)必填:firstName / lastName / email / phoneNumber 建议:name / upi / country / state / city / postalCode 5.3 代付 channelExtra(IND_UPI_OUT) 必填:name / cardNo / ifscCode / bankName / email / phoneNumber 可选:paymentMode / accountType / city / state / postalCode / address 说明:cardNo=玩家银行账号;ifscCode=IFSC;由商户在下单时传入(玩家提现绑卡信息) 5.4 响应 data 字段(代收 IndUpiPayinOrderRS / 代付 IndUpiPayoutOrderRS,外壳相同) --------------------------------------------------------------------------- 字段 类型 说明 --------------------------------------------------------------------------- payOrderId String 平台订单号 mchOrderNo String 商户订单号(= 请求 orderNo) orderState Number 订单状态(见第二节;同步下单用本字段) payDataType String 代收常见 payurl;代付也可能出现该类型,但通常无支付链接 payData String 代收:收银台 / 跳转 URL;代付:一般为空或无此字段 upiUrl String ★ 代收常见;代付通常无 name / upi String ★ 代收扩展;代付通常无 fee Number 商户手续费(分);成功记账后常见;可为非整数分 feeCurrency String 手续费币种 settleAmount Number 结算入账金额(分);同币种常见 amount − fee settleCurrency String 结算币种 serviceFee Number 服务费(分) marginAmount Number 保证金(分,有则返回) currencyPair String 汇率对说明(有则返回) userId String 用户标识(有则返回) walletBrandName String 钱包品牌名(有则返回) billDes String 账单描述(有则返回) checkDate String 对账日 yyyyMMdd(有则返回) channelExtra Object 代收常见 {"payUrl","upiUrl"};代付通常无或较少 errCode / errMsg String 失败时 --------------------------------------------------------------------------- ★ 代付 vs 代收:代付是打款给玩家,同步响应一般只要看 orderState;不要依赖 payData / upiUrl。 正式通道多数同步 orderState=1(处理中),终态以异步通知 / 查单 state=2 为准。 5.5 代收请求示例(IND_UPI,100 INR) { "merchantNo": "C1788116547", "appId": "6a947e438f0872229b1e778c", "orderNo": "GAME_20260901120000_001", "wayCode": "IND_UPI", "amount": 10000, "currency": "INR", "clientIp": "1.2.3.4", "description": "Game diamond recharge", "notifyUrl": "https://your-game.com/pay/notify", "returnUrl": "https://your-game.com/pay/return", "userId": "player_10086", "extParam": "optional_biz_tag", "channelExtra": "{\"firstName\":\"stephen\",\"lastName\":\"curry\",\"email\":\"stephen@gmail.com\",\"phoneNumber\":\"9566778899\",\"name\":\"stephen curry\",\"upi\":\"demo@upi\",\"country\":\"IND\",\"state\":\"Mumbai\",\"city\":\"Bellevue\",\"postalCode\":\"123546\"}" } 5.6 代收成功响应示例(含外壳;玩家需打开 payData / upiUrl 付款) { "code": "0", "msg": "SUCCESS", "data": { "payOrderId": "TSPPI08312094417832285474817", "mchOrderNo": "GAME_20260901120000_001", "orderState": 1, "payDataType": "payurl", "payData": "https://amipay.net/gateway/api/pay/upi/TSPPI08312094417832285474817", "upiUrl": "upi://pay?cu=INR&pa=demo@upi&am=100.00&tn=xxx", "channelExtra": { "payUrl": "https://pi.example.com/pay/xxxx", "upiUrl": "upi://pay?cu=INR&pa=demo@upi&am=100.00&tn=xxx" } }, "sign": "Base64(SHA256withRSA)..." } 说明:测试即时成功通道可能直接 orderState=2,并带 fee / settleAmount / serviceFee / checkDate。 5.7 代付请求示例(IND_UPI_OUT,100 INR → 打到玩家银行卡) { "merchantNo": "C1788116547", "appId": "6a947e438f0872229b1e778c", "orderNo": "WD_20260901120000_001", "wayCode": "IND_UPI_OUT", "amount": 10000, "currency": "INR", "clientIp": "1.2.3.4", "description": "Player withdrawal", "notifyUrl": "https://your-game.com/pay/notify", "returnUrl": "https://your-game.com/pay/return", "userId": "player_10086", "extParam": "optional_biz_tag", "channelExtra": "{\"name\":\"stephen curry\",\"cardNo\":\"123456789012\",\"ifscCode\":\"HDFC0001234\",\"bankName\":\"HDFC Bank\",\"email\":\"stephen@gmail.com\",\"phoneNumber\":\"9566778899\",\"paymentMode\":\"IMPS\",\"accountType\":1,\"city\":\"Mumbai\",\"state\":\"MH\",\"postalCode\":\"400001\",\"address\":\"Andheri West\"}" } channelExtra 字段含义: name 收款人姓名(玩家) cardNo 银行账号(玩家账户,不是信用卡号) ifscCode IFSC bankName 银行名 email 邮箱 phoneNumber 手机号 paymentMode 可选,如 IMPS accountType 可选,如 1=Savings city/state/postalCode/address 可选地址 5.8 代付受理成功响应示例(含外壳;多数正式通道为处理中) { "code": "0", "msg": "SUCCESS", "data": { "payOrderId": "TSPPO09011200001234567890123", "mchOrderNo": "WD_20260901120000_001", "orderState": 1, "payDataType": "payurl", "payData": "" }, "sign": "Base64(SHA256withRSA)..." } 说明: - code=0 仅表示接口受理成功,不等于打款成功 - 代付一般无收银台 / upiUrl;勿引导玩家打开 payData - 终态(成功 state=2 / 失败 state=3)以异步通知 + 查单为准 - 若通道瞬时成功,data 可能直接 orderState=2,并带: fee / feeCurrency / settleAmount / settleCurrency / serviceFee / checkDate 等 - 可能 code=0 但 orderState=3,并带 errCode / errMsg(如余额不足、上游拒单) - 下单前会校验商户余额 ≥ amount + 手续费;不足返回失败 ================================================================================ 六、订单查询 POST /api/order/query ================================================================================ 完整 URL:https://amipay.net/gateway/api/order/query 请求 Body: { "merchantNo": "C1788073687", "appId": "6a93d6d78f08fd1adc3ef1f5", "mchOrderNo": "GAME_20260830120000_001", "payOrderId": "" } 规则:mchOrderNo 与 payOrderId 不能同时为空 响应 data 字段(QueryPayOrderRS) --------------------------------------------------------------------------- 字段 类型 说明 --------------------------------------------------------------------------- payOrderId String 平台订单号 appId String 应用 ID mchOrderNo String 商户订单号 wayCode String 支付方式展示名(如 "India upi",不是 IND_UPI) amount Number 商户下单交易金额,单位分(非元);常带两位小数如 20000.00(=200 INR) currency String 交易币种 state Number 订单状态(查单用 state,不是 orderState);成功为 2 clientIp String 下单 IP(有则返回) channelOrderNo String 渠道订单号 errCode String 错误码 errMsg String 错误信息 extParam String 透传字段 successTime Number 成功时间(毫秒时间戳) createdAt Number 创建时间(毫秒时间戳) signType String 签名类型,如 RSA fee Number 商户手续费,单位分;decimal(20,2),可为非整数分(如 9.50);成功记账后常见 feeCurrency String 手续费币种 settleAmount Number 结算入账金额,单位分;同币种常见 amount − fee(例 20000−1005=18995);成功记账后常见 settleCurrency String 结算 / 记账币种 --------------------------------------------------------------------------- 金额三字段关系(代收成功):amount=交易额(分),fee=手续费(分),settleAmount=结算额(分)。 同币种常见 settleAmount ≈ amount − fee。验签按报文原文小数位,勿改成元或抹小数。 currencyPair String 汇率说明(有则返回) userId String 用户标识(有则返回) walletBrandName String 钱包品牌名(有则返回) marginAmount Number 保证金(有则返回) checkDate String 对账日 yyyyMMdd(有则返回) --------------------------------------------------------------------------- 注意:模型含 merchantNo,但当前实现通常不会返回该字段(请勿依赖)。 查单 data 不含 channelExtra、reqTime、sign(sign 在外壳顶层)。 完整响应示例: { "code": "0", "msg": "SUCCESS", "data": { "payOrderId": "TSPPI08312094417832285474817", "appId": "6a947e438f0872229b1e778c", "mchOrderNo": "P20944178244636221461788183096", "wayCode": "India upi", "amount": 20000.00, "currency": "INR", "state": 2, "clientIp": "127.0.0.1", "channelOrderNo": "fHGoc", "extParam": "P20944178244636221461788183096", "successTime": 1788177514000, "createdAt": 1788177513995, "signType": "RSA", "fee": 1005.00, "feeCurrency": "INR", "settleAmount": 18995.00, "settleCurrency": "INR", "walletBrandName": "India upi", "checkDate": "20260831" }, "sign": "..." } ================================================================================ 七、异步通知(商户 notifyUrl) ================================================================================ 说明:notifyUrl = 【贵方】接收入账通知的地址。Body 为扁平 JSON + sign, 不是 {code,msg,data,sign} 外壳。 1. 平台 → 商户:HTTP POST,Content-Type: application/json; charset=UTF-8 2. 验签:对整包字段(去掉 sign)按第三章规则拼串,用平台公钥 SHA256withRSA 验签 3. 处理成功后 Body 必须返回纯文本 SUCCESS(大小写不敏感) 4. 务必幂等;非 SUCCESS / 超时将重试(约最多 6 次) 7.1 Body 字段(QueryPayOrderRS + reqTime + channelExtra + sign) --------------------------------------------------------------------------- 字段 类型 说明 --------------------------------------------------------------------------- payOrderId String 平台订单号 appId String 应用 ID mchOrderNo String 商户订单号 wayCode String 展示名,如 "India upi" amount Number 商户下单交易金额,单位分(非元);常带两位小数 currency String 交易币种 state Number 订单状态(终态通知;成功为 2) clientIp String 有则返回 channelOrderNo String 渠道订单号 errCode / errMsg String 失败时可能有 extParam String 透传 successTime Number 毫秒时间戳 createdAt Number 毫秒时间戳 signType String 如 RSA fee Number 商户手续费,单位分;可为非整数分;成功记账后常见 feeCurrency String 手续费币种 settleAmount Number 结算入账金额,单位分;同币种常见 amount − fee settleCurrency String 结算 / 记账币种 --------------------------------------------------------------------------- 金额含义与查单相同:amount / fee / settleAmount 均为分,不是元。 currencyPair String 有则返回 userId String 有则返回 walletBrandName String 有则返回 marginAmount Number 有则返回 checkDate String 有则返回 channelExtra Object 来自渠道扩展,如 {"utr":"..." };无则为 null 且通常省略 reqTime Number 本次通知时间(毫秒)★ 回调特有 sign String 平台签名 ★ 回调特有(验签时剔除) --------------------------------------------------------------------------- 注意:merchantNo 通常不出现在回调 JSON 中,请勿依赖。 7.2 Body 示例(代收成功) { "payOrderId": "TSPPI08312094394410113363970", "appId": "6a947e438f0872229b1e778c", "mchOrderNo": "P20943944073414287371788177513", "wayCode": "India upi", "amount": 20000.00, "currency": "INR", "state": 2, "clientIp": "127.0.0.1", "channelOrderNo": "fHGoc", "extParam": "P20943944073414287371788177513", "successTime": 1788177514000, "createdAt": 1788177513995, "signType": "RSA", "fee": 1005.00, "feeCurrency": "INR", "settleAmount": 18995.00, "settleCurrency": "INR", "walletBrandName": "India upi", "checkDate": "20260831", "reqTime": 1788177514646, "channelExtra": { "utr": "422253713113" }, "sign": "Base64..." } 7.3 商户应答(必须) Body 仅:SUCCESS 7.4 处理流程 1. 读 POST JSON 2. 平台公钥验签 3. 校验 appId / amount / mchOrderNo(及本地订单) 4. state==2 且未入账 → 入账(幂等) 5. 返回 SUCCESS ================================================================================ 八、余额查询 POST /api/account/balance ================================================================================ 完整 URL:https://amipay.net/gateway/api/account/balance 请求: { "merchantNo": "...", "appId": "..." } 响应: { "code": "0", "msg": "SUCCESS", "data": { "walltes": [ { "currency": "INR", "balance": 0.00, "freezeBalance": 0.00, "waitSettleBalance": 18995.00, "marginAmount": 0.00, "preBalance": 0, "specialBalance": 0.00 } ] }, "sign": "..." } 说明: - 字段名 walltes 为历史拼写(代码即此,请按此解析,不是 wallets) - 金额单位:分 - specialBalance:专款金额(可用于退款等场景) ================================================================================ 九、错误与联调注意 -------------------------------------------------------------------------------- 1. ip not in white list → 配置出口 IP 白名单 2. 验签失败 → 平台公钥、跳过 null/""、TreeMap 区分大小写、金额小数位、channelExtra 整段 3. Bean Validation → Header;代收 channelExtra 必填 firstName/lastName/email/phoneNumber 4. amount 过小 → amount ≥ 10000 5. code=0 且 orderState/state=3 → 看 errCode/errMsg 6. notifyUrl 填贵方公网地址,不要填上游通道地址 7. 同步看 orderState;查单/回调查 state;wayCode 请求用编码、响应用展示名 十、联调检查清单 -------------------------------------------------------------------------------- [ ] RSA 密钥对已生成,公钥已交给平台 [ ] IP 白名单已配置 [ ] 代收下单 IND_UPI,amount ≥ 10000(分) [ ] 能解析完整外壳 {code,msg,data,sign},并从 data 取 payData / upiUrl [ ] notifyUrl 公网可达,成功返回 SUCCESS [ ] 回调验签通过,幂等入账(按真实字段,勿依赖 merchantNo) [ ] 查单接口可用 附录 A:结算提现 -------------------------------------------------------------------------------- 申请提现 POST /api/account/cashout 请求:merchantNo, appId, currency, mchOrderNo, amount(分), orderType(可选 1/2), remarks(可选) 响应 data:{ "state": } 查询提现 POST /api/account/cashoutQuery 请求:merchantNo, appId, mchOrderNo 响应 data: state / fee / feeCurrency / actualAmount / fxRate 附录 B:常用地址 -------------------------------------------------------------------------------- 商户后台:https://amipay.net/merchant/ 支付网关:https://amipay.net/gateway 签名工具:https://amipay.net/tools/sign-tool.html 本文档:https://amipay.net/ 与 https://amipay.net/docs/merchant-api.txt ================================================================================ 文档结束 ================================================================================