跳到主要内容

TOPPay API接入文档

一、概述

本文档是平台服务端API的统一接口规范和开发指南。主要提供SDK服务器CP服务器之间的交互接口规范。

二、接入前准备

参数名称参数说明
AppID平台分配给研发的应用 id
PaySecret平台分配给研发的本地化支付秘钥
参数名称参数说明
充值结果回调接口即充值结果通知地址,当支付成功后,SDK 服务器会将支付结果回调给该接口

三、通信协议

  • 本接口采用HTTP 协议作为通信协议,调用方通过构造HTTP 请求(POST/GET 方式)发起接口请求。

  • 接口域名如下:https://api-gamepay.meetsocial.com

  • 请求与响应内容采用UTF-8字符编码

  • 服务器请求示例

POST https://api-gamepay.meetsocial.com/xxx/xxx
Content-Type: application/json
success
  • 响应数据示例
Content-Type: application/json
{
"code": 0,
"message": "success",
"result": {
"xxx": "xxx",
}
}
  • 响应错误数据示例
Content-Type: application/json
{
"code": 5003,
"message": "parameter_error",
"success": false
}

四、接口列表

1、支付接口

字段名称类型是否必填备注
outTradeCodeStringcp订单号
currencyCodeString货币编号, 目前只支持USD
countryCodeString国家编号(获取地区国家信息接口返回的result-code)(当paymentChannelCode为CHECKOUT_HOSTED_CARD或CHECKOUT_HOSTED_MADA必填)
amountLong订单价格(货币最小单位)例子:1000
productsArray查看products对象
paymentAppIdLong支付应用id(联系平台获取)
paymentChannelCodeString支付方式编号:
Card请传入:CHECKOUT_HOSTED_CARD(此支付通道暂时关闭)
Mada请传入:CHECKOUT_HOSTED_MADA(此支付通道暂时关闭)
AED请传入:PAYBY_HOSTED_AED(需要看下第六的注意点)
tazapay请传入:TAZAPAY
mix pay请传入:MIXPAY
callbackSuccessUrlString支付成功后跳转地址(当paymentChannelCode为CHECKOUT_HOSTED_CARD或CHECKOUT_HOSTED_MADA必填)
callbackFailUrlString支付失败后跳转地址(当paymentChannelCode为CHECKOUT_HOSTED_CARD或CHECKOUT_HOSTED_MADA必填)
callbackCancelUrlString支付取消后跳转地址(当paymentChannelCode为CHECKOUT_HOSTED_CARD或CHECKOUT_HOSTED_MADA必填)
extraParamObject额外参数(当paymentChannelCode为PAYBY_HOSTED_AED必填)
orderSignString密钥(参照下面的加密方式)
ipString用户IP,建议传入,能提高支付成功率和风控准确率
roleIdString角色ID,建议传入,能提高支付成功率和风控准确率
deviceIdString设备ID,建议传入,能提高支付成功率和风控准确率
userAgentString浏览器UserAgent信息,建议传入,能提高支付成功率和风控准确率
emailString用户邮箱,建议传入,能提高支付成功率和风控准确率
paymentMethodObject支付方式参数,当paymentChannelCode为TAZAPAY或MIXPAY时必传
  • extraParam对象:
字段名称类型备注
redirectUrlStringAED通道支付后跳转地址(当paymentChannelCode为PAYBY_HOSTED_AED必填)
  • products对象:
字段名称类型备注
productNameString商品名
productCountInt商品数量
productPriceLong商品单价(货币最小单位)
  • paymentMethod对象:
字段名称类型备注
tazapayObjectpaymentChannelCode为TAZAPAY时必传
mixpayObjectpaymentChannelCode为MIXPAY时必传
  • tazapay对象:
字段名称类型是否必填备注
emailString买家邮箱
countryCodeString买家国家编码,可以从pay/config/countryList获取
firstNameString买家姓氏,长度不能超出250个字符
lastNameString买家名字,长度不能超出250个字符
callbackSuccessUrlString付款后客户重定向到的URL,请确保该网址位于https下
callbackErrorUrlString付款错误时重定向客户的URL,请确保该网址位于https下
  • mixpay对象:
字段名称类型是否必填备注
returnUrlString付款后客户重定向到的URL,请确保该网址位于https下
failedReturnUrlString付款错误时重定向客户的URL,请确保该网址位于https下
  • 加密方式

如amount=aaaa&outTradeCode=xxx¤cyCode=xxx&secretKey=xxx

用此方式拼接以amount、outTradeCode、currencyCode、secretKey这4个字段,最终md5对此字符串加密。计算md5签名时,应以utf-8编码取字符串。

  • 响应结果
字段名称类型备注
urlString支付地址
orderNoString平台服务器订单号
outTradeNoStringCP支付订单号
{
"code": 0,
"message": "success",
"result": {
"url": "https://xxx",
"orderNo":xxx,
"outTradeNo":xxxxxx
}
}
  • 错误Code编码
状态码说明
0成功
999服务器内部错误
5003请求参数错误
5011订单创建失败
5014货币单位错误
5015支付失败
5017签名校验失败
5018国家编号错误
5019支付方式错误

2、获取地区国家信息接口

字段名称类型备注
codeint消息编码
resultArraycode String 地区编号
name String 地区名称
taxPoint double 国家地区税点
messageString消息信息

3、(tazapay支付方式) 获取支持地区国家信息接口

字段名称类型是否必填备注
paymentChannelString支付方式:TAZAPAY
  • 响应结果
字段名称类型备注
codeint消息编码
resultArraycode String 地区编号
name String 地区名称
messageString消息信息

4、查询支付订单接口

字段名称类型是否必填备注
payIdString流水号
  • 响应结果
字段名称类型备注
codeint消息编码
resultObject字段名称类型备注payTimedate支付时间payAmountint支付金额货币最小单位如:5099美分payIdString流水号outTradeNoStringCP厂商支付订单号orderStatusint订单状态:1为已完成; 2为失败;3为处理中notifyStatusint异步通知状态:0:未完成;1:已经完成;2:异步通知失败currencyCodeString货币单位如:USD
messageString消息信息
  • 特殊响应代码说明
代码编号备注
5001订单不存在

5、充值结果回调接口

  • 接口描述:即充值结果通知地址,当支付成功后,平台服务器会将支付结果在notify告诉CP服务器,由CP提供地址。
  • 返回数据支持格式:JSON
  • 版本:1
  • HTTP请求方式 :POST
  • 请求方:CP服务器
  • 响应方:平台服务器
  • 请求地址:cp提供回调地址
  • Data信息
参数必填类型描述
tradeCodeYStringCP支付订单号
orderCodeYString平台服务器订单号
paymentChannelCodeYString支付方式
paymentAmountYLong订单价格(货币最小单位)例子:1000
paymentStatusYbool是否支付
payTimeYLong时间戳
signYStringmd5加密后的签名(参考以下加密方式)
  • 验证充值是否成功,务必在保证sign正确情况下,paymentAmount也要进行对比,保证充值正确性
  • 加密方式

如tradeCode=aaaa&orderCode=xxx&paymentChannelCode=xxx&paymentAmount=xxx&paymentStatus=xxx&payTime=xxx&secretKey=xxx

用此方式拼接以tradeCode、orderCode、paymentChannelCode、paymentAmount、paymentStatus、payTime、secretKey这7个字段,最终md5对此字符串加密。计算md5签名时,应以utf-8编码取字符串。

  • 响应数据说明(如果对应的订单CP已经处理完成,请保持返回"true")
响应内容描述
truetrue表示处理订单成功,平台服务端方收到响应true后不会再通知给cp方(也可返回其他错误信息,SDK服务器方收到true以外的字符串后都会多次重复通知)

五、接口备注

在用户支付订单完成后,平台服务器会向商户方服务器发起通知,并异步不断尝试直到获取结果。以下为异步通知接口说明:

  • 必须保证服务器异步通知页面(nify_url)上无任何字符,如空格、HTML 标签、开发系统自带抛出的异常提示信息等;

  • 平台服务器使用 POST 方式发送通知信息,里面的数据是一个json字符串,json decode以后得到订单数组。

  • 程序执行完后必须打印输出“true”(不包含引号,不能加入换行符,缩进符等不可见字符)。如果商户反馈给平台服务器的字符不是 true 这 4 个字符,平台服务器会不断重发通知,一般情况下, 一共7次通知(再次通知时间从首次通知失败后,按2m、10m、10m、1h、2h、6h、12h时间规则执行)。7次结束之后将不在重试。

  • cookies、session 等在此页面会失效,即无法获取这些数据;

  • 该方式的调试与运行必须在服务器上,即互联网上能访问;

  • CP方不仅要对回调的签名进行验证,还需要对回调的金额进行比对,两方一致方可发货,避免用户造假篡改订单内容

六、注意点

1、如果paymentChannelCode=PAYBY_HOSTED_AED并且网页是WebView或者WKWebView承载,需要特殊处理,具体如下:

  • Android
@Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
try {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
Uri uri = request.getUrl();
if (isPayby(uri) || isTotok(uri) || isBotim(uri)) {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setData(uri);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
view.getContext().startActivity(intent);
return true;
}
}
} catch (Throwable t) {
t.printStackTrace();
}
return super.shouldOverrideUrlLoading(view, request);
}

private boolean isBotim(Uri uri) {
try {
String scheme = uri.getScheme();
String host = uri.getHost();
String path = uri.getPath();
return "https".equalsIgnoreCase(scheme) && "botim.me".equalsIgnoreCase(host) && "/botim/payby/open-iap-cashdesk".equalsIgnoreCase(path);
} catch (Throwable t) {
t.printStackTrace();
}
return false;
}

private boolean isTotok(Uri uri) {
try {
String scheme = uri.getScheme();
String host = uri.getHost();
String path = uri.getPath();
return "totok".equalsIgnoreCase(scheme) && "payby".equalsIgnoreCase(host) && "/open-iap-cashdesk".equalsIgnoreCase(path);
} catch (Throwable t) {
t.printStackTrace();
}
return false;
}

private boolean isPayby(Uri uri) {
try {
String scheme = uri.getScheme();
String host = uri.getHost();
String path = uri.getPath();
return ("payby".equalsIgnoreCase(scheme) && "payment".equalsIgnoreCase(host) && "/open-iap-cashdesk".equalsIgnoreCase(path))
|| ("https".equalsIgnoreCase(scheme) && "app.payby.com".equalsIgnoreCase(host) && "/open-iap-cashdesk".equalsIgnoreCase(path));
} catch (Throwable t) {
t.printStackTrace();
}
return false;
}
  • iOS
- (void)webView:(WKWebView *)webView
decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction
decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
NSString* urlStr = navigationAction.request.URL.absoluteString;
if ([urlStr containsString:@"https://app.payby.com/open-iap-cashdesk"] ||
[urlStr containsString:@"payby://payment/open-iap-cashdesk"] ||
[urlStr containsString:@"https://botim.me/botim/payby/open-iap-cashdesk"] ||
[urlStr containsString:@"totok://payby/open-iap-cashdesk"]) {
NSURL* url = [NSURL URLWithString:urlStr];
if (@available(iOS 10.0, *)) {
[[UIApplication sharedApplication] openURL:url options:@{} completionHandler:^(BOOL success) {
}];
} else {
[[UIApplication sharedApplication] openURL:url];
}
decisionHandler(WKNavigationActionPolicyCancel);
return;
}
decisionHandler(WKNavigationActionPolicyAllow);
}