聚合支付 - 接口开发文档 SDK示例下载

支付下单接口

请求API地址

主选:http://18pay.net/pay.html

备用:http://www.18pay.net/pay.html

提示:安全起见,提交方式推荐使用 POST ,请不要用 GET 方式提交。
请求参数列表
参数名称 参数含义 类型 示例值 是否必填 参与签名 描述
appid 商户编号 string 20206491 是 是 平台分配商户编号
payid 唯一标识 string 202305310100203715872 是 是 订单编号或者用户ID(必须确保是唯一的)
money 订单金额 string 10 是 是 订单提交的金额(单位:元)
type 支付方式 string 1 是 是 传入数字(1为支付宝,2为微信支付)
notify_url 异步通知地址 string http://296o.com/notify_url.php 是 是 接收平台通知的URL,需给绝对路径,并确保平台能通过互联网访问该地址
return_url 同步跳转地址 string http://296o.com/return_url.php 是 是 前端页面跳转的URL(支付成功后会跳转到这个地址),
该地址只作为前端页面的一个跳转,须使用notify_url通知作为支付最终结果
subject 商品名称 string 购买商品 是 是 商品说明,游戏充值可传玩家账号或者角色名
client_ip 客户端IP string 114.114.114.114 是 是 请正确提交用户的真实IP,否则会出现"支付IP地址异常"问题
param 自定义参数 string 没有请留空 否 是 原封返回,避免特殊字符
account 充值账号 string qq1234 否 是 接口用于游戏充值时,可传入玩家账号
contact 联系方式 string 79899080 否 是 接口用于游戏充值时,可传入玩家联系方式
native 原生接口 string true 否 是 native不为空时,接口返回原生支付结果,比如支付宝和微信的官方二维码链接
hidetitle 隐藏标题 string true 否 是 hidetitle不为空时,自动隐藏支付页面上的"支付中心"标题栏
codesize 二维码大小 int 150 否 是 二维码大小默认200px
agent 代理账号 string 88888 否 是 支持三级代理分销,直接传入代理的登录账号
sign 数据签名 string fa7337122f6082b6ac14433ecf8ec73a 是 否 对数据进行签名,请参考签名算法
sign_type 签名类型 string rsa 否 否 默认md5(V1.0),可选rsa(V2.0)
charset 编码 string utf-8 否 否 utf-8或gb2312,默认utf-8
签名算法
重要提示:平台现已支持两种签名算法版本!
  • MD5签名(V1.0):传统签名方式,默认使用;
  • RSA签名(V2.0):强烈推荐使用,更安全、更高效;
  使用V2.0需要在基本资料中配置RSA密钥,并将 sign_type 参数设为 rsa

▍ MD5签名算法(V1.0 - 默认)

  • 第一步

    设所有发送或者接收到的数据为集合,将集合内非空参数值的参数按照参数名从小到大排序(ASCII码字典序),使用 URL 键值对的格式(即key1=value1&key2=value2…)拼接成字符串 str 。

    
    $postDatas = array(
        "appid" => '20206491',
        "money" => '10',
        "payid" => '202305310100203715872',
        "type" => '1',
        "subject" => '购买商品',
        "notify_url" => 'http://296o.com/notify_url.php',
        "return_url" => 'http://296o.com/return_url.php'
    );
    //ksort()对数组按照键名进行升序排序
    ksort($postDatas);
    //reset()内部指针指向数组中的第一个元素
    reset($postDatas);
    $str = ASCII($postDatas);
    function ASCII($postDatas = array()){
    	$str = '';//初始化
    	foreach ($postDatas AS $key => $val) { //遍历参数数组
    		if ($val == ''||$key == 'sign'||$key == 'sign_type') continue; //跳过这些不签名
    		if ($str) $str .= '&'; //第一个字符串签名不加& 其他加&连接起来参数
    		$str .= "$key=$val"; //拼接为url参数形式
    	}
    	return $str;
    }
    
  • 第二步

    然后在字符串 str 后面拼接上 appkey(平台商户密钥),得到 stringSignTemp 字符串,最后对stringSignTemp 进行 MD5 运算,得到 sign 值

    
    $str = "appid=20206491&money=10&notify_url=http://296o.com/notify_url.php&payid=202305310100203715872&return_url=http://296o.com/return_url.php&subject=购买商品&type=1";
    $stringSignTemp = $str.$appkey;
    $sign = md5($stringSignTemp);
    

▍ RSA签名算法(V2.0 - 强烈推荐)

RSA签名流程(双密钥模式):
1. 商户自行生成RSA密钥对,将商户公钥配置到平台,商户私钥自己保管;
2. 从平台"基本资料"获取平台RSA公钥,用于验证异步通知签名;
3. 发起请求时,用商户私钥进行RSA签名;
4. 异步通知时,平台用平台私钥签名,商户用平台公钥验签;
5. 私钥各自保管,安全性更高。
  • 第一步:生成商户RSA密钥对

    推荐方式:在平台"基本资料"页面点击 "生成商户RSA密钥对" 按钮,一键生成:

    • 商户私钥:弹窗展示,请立即复制保存(平台不保存,丢失无法找回)

    • 商户公钥:自动保存到平台,无需手动配置

    • 平台公钥:从平台"基本资料"复制,用于验证异步通知签名

    也可使用OpenSSL命令自行生成:

    
    # 使用OpenSSL生成商户RSA密钥对(可选)
    openssl genpkey -algorithm RSA -out merchant_private_key.pem -pkeyopt rsa_keygen_bits:2048
    openssl rsa -pubout -in merchant_private_key.pem -out merchant_public_key.pem
    
  • 第二步:使用商户私钥签名(PHP示例)

    
    //构造待签名字符串(与MD5签名第一步相同)
    $postDatas = array(
        "appid" => '20206491',
        "money" => '10',
        "payid" => '202305310100203715872',
        "type" => '1',
        "subject" => '购买商品',
        "notify_url" => 'http://296o.com/notify_url.php',
        "return_url" => 'http://296o.com/return_url.php'
    );
    ksort($postDatas);
    reset($postDatas);
    $str = ASCII($postDatas);
    //获取商户RSA私钥(从平台基本资料页面复制)
    $privateKey = "";
    $res = openssl_get_privatekey($privateKey);
    openssl_sign($str, $sign, $res, OPENSSL_ALGO_SHA256);
    openssl_free_key($res);
    $sign = base64_encode($sign);
    //将sign和sign_type=rsa一起提交到支付接口
    $postDatas["sign"] = $sign;
    $postDatas["sign_type"] = 'rsa';
    
  • 第三步:验证异步通知签名(PHP示例)

    异步通知时,平台使用平台私钥签名,商户用平台公钥验签:

    
    //获取平台RSA公钥(从平台基本资料页面复制)
    $platformPublicKey = "";
    
    //接收异步通知参数
    $postDatas = $_POST;
    ksort($postDatas);
    reset($postDatas);
    $str = ASCII($postDatas);
    $sign = base64_decode($_POST['sign']);
    
    //使用平台RSA公钥验证签名
    $res = openssl_get_publickey($platformPublicKey);
    $verifyResult = openssl_verify($str, $sign, $res, OPENSSL_ALGO_SHA256);
    openssl_free_key($res);
    
    if($verifyResult === 1 && !empty($_POST['pay_no'])){
        //签名验证通过,处理业务逻辑
        exit('success');
    }else{
        exit('fail');
    }
    
签名失败怎么办?
  • 常见问题排查

    1、可以使用signArray参数,提交参与签名的数组字符串,然后对比前后计算签名的数组参数有什么区别;

    2、param参数值里包含逗号(,)等符号,http请求提交到平台时,会被检测层过滤掉符号,从而导致签名不一致;

    解决方案:
    如果你的param参数里必须携带符号,那么可以先进行base64编码转换,异步通知和同步跳转接收param参数时,再转换回来即可。

    3、如果参与签名的数组字符串里存在转义字符,那么要先去掉转义,再进行签名,参考代码如下:

    
    /**
     * 把数组所有元素,进行ASCII码字典排序,然后按照"参数=参数值"的模式用"&"字符拼接成字符串,并对字符串做urlencode编码
     * @param $postDatas 需要拼接的数组
     * return 拼接完成以后的字符串
     */
    function createSignArray($postDatas) {
        //ksort()对数组按照键名进行升序排序
        ksort($postDatas);
        //reset()内部指针指向数组中的第一个元素
        reset($postDatas);
    	$str  = "";
    	while (list ($key, $val) = each ($postDatas)) {
    		$str.=$key."=".urlencode($val)."&";
    	}
    	//去掉最后一个&字符
    	$str = substr($str,0,count($str)-2);
    	//如果存在转义字符,那么去掉转义
    	if(get_magic_quotes_gpc()){
    	    $str = stripslashes($str);
    	}
    	return $str;
    }
    

支付回调通知

提交native参数时,以json格式返回原生支付结果:
参数名称 参数含义 参数说明
status 返回状态 status为1表示成功,status为0表示失败
pay_no 交易流水号 平台生成的交易流水号
pay_money 支付金额 买家需要支付的实际金额
pay_url 支付链接 商户可用此参数自定义创建支付页面,或者跳转到支付宝、微信等第三方平台
code_url 二维码链接 商户可用此参数自定义去生成二维码后展示出来进行扫码支付
code_img 二维码图片 此参数的值即是根据code_url生成的可以扫码支付的二维码图片地址
订单支付成功时,系统会以POST请求方式通知到异步通知地址(notify_url),以GET请求方式跳转到同步跳转地址(return_url),通知结果参数如下表:
参数名称 参数含义 类型 示例值 参与签名 参数说明
pay_id 唯一标识 string admin 是 商户提交的的唯一标识(订单编号或者用户ID)
pay_money 订单金额 string 100.00 是 实际付款金额
pay_no 交易流水号 string 20200217200042408995 是 平台生成的交易流水号
pay_time 交易时间 int 1487597795 是 付款的时间戳
pay_type 支付方式 int 1 是 1:支付宝 2:微信支付 3:QQ钱包
param 扩展返回 string 没有则不返回 是 商户附加数据,原封返回,提交什么就返回什么。注意:值为空时不参与签名
sign 数据签名 string c47f3cba123456b6b24542110a8928af 否 加密签名,验证订单是否为合法,请参考签名算法
sign_type 签名类型 string rsa 否 RSA签名(V2.0)会返回该sign_type参数,sign_type值等于rsa

通知返回的参数示例如下:

MD5签名(V1.0)通知示例:


pay_id=admin&pay_money=100.00&pay_no=20200217200042408995&pay_time=1487597795&pay_type=1&sign=c47f3cba123456b6b24542110a8928af

RSA签名(V2.0)通知示例:


pay_id=admin&pay_money=100.00&pay_no=20200217200042408995&pay_time=1487597795&pay_type=1&sign_type=rsa&sign=e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855...
业务处理返回
返回类型 返回数据
业务处理完成返回 ok 或者 success
业务处理失败还需要下次继续通知返回 fail

1、业务处理完成返回:ok 或者 success

2、业务处理失败还需要下次继续通知返回:fail

3、注意:一定要验证是否有pay_no参数值,因为只有该值存在,才是付款成功 。

  • notify_url异步通知示例(Thinkphp):

    
    //签名类型:md5(V1.0)或 rsa(V2.0)
    $sign_type="md5";
    //平台商户密钥(使用MD5签名时需要,V1.0版本)
    $appkey="";
    //平台RSA公钥(使用RSA签名时需要,V2.0版本)
    $platformPublicKey = "";
    
    if (empty($_POST)) $_POST = $_GET; //如果为GET方式访问 
    //ksort()对数组按照键名进行升序排序 
    ksort($_POST); 
    //reset()内部指针指向数组中的第一个元素 
    reset($_POST); 
    $sign = '';//初始化 
    foreach ($_POST AS $key => $val) { //遍历POST参数 
    if ($val == ''||$key == 'sign'||$key == 'sign_type') continue; //跳过这些不签名 
    if ($sign) $sign .= '&'; //第一个字符串签名不加& 其他加&连接起来参数 
    $sign .= "$key=$val"; //拼接为url参数形式 
    } 
    $pay_id = $_POST['pay_id']; //需要充值的ID 或订单号 或用户名 
    $pay_money = (float)$_POST['pay_money']; //实际付款金额
    $pay_no = $_POST['pay_no']; //交易流水号 
    $pay_time = $_POST['pay_time']; //付款的时间戳 
    $pay_type = (int)$_POST['pay_type']; //支付方式 1:支付宝 2:微信支付 3:QQ钱包 
    $param = isset($_POST['param'])?$_POST['param']:'';//自定义参数 
    
    //验证签名(根据sign_type选择验证方式)
    $signValid = false;
    if(strtolower($sign_type) == 'rsa'){
        //RSA签名验证(V2.0)
        $res = openssl_get_publickey($platformPublicKey);
        $signValid = openssl_verify($sign, base64_decode($_POST['sign']), $res, OPENSSL_ALGO_SHA256) === 1;
        openssl_free_key($res);
    }else{
        //MD5签名验证(V1.0)
        $signValid = (md5($sign . $appkey) == $_POST['sign']);
    }
    
    if (!$_POST['pay_no'] || !$signValid) { //不合法的数据 
    exit('fail'); //返回失败 继续补单 
    } else { //合法的数据 
    /** 
    * 业务处理在这里写 
    */ 
    exit('success'); //返回成功,业务处理完成,下面不再执行了
     } 
    
  • return_url同步跳转示例(Thinkphp):

    
    //签名类型:md5(V1.0)或 rsa(V2.0)
    $sign_type="md5";
    //平台商户密钥(使用MD5签名时需要,V1.0版本)
    $appkey="";
    //平台RSA公钥(使用RSA签名时需要,V2.0版本)
    $platformPublicKey = "";
    
    if (empty($_POST)) $_POST = $_GET; //如果为GET方式访问 
    //ksort()对数组按照键名进行升序排序 
    ksort($_POST); 
    //reset()内部指针指向数组中的第一个元素 
    reset($_POST); 
    $sign = '';//初始化 
    foreach ($_POST AS $key => $val) { //遍历POST参数 
    if ($val == ''||$key == 'sign'||$key == 'sign_type') continue; //跳过这些不签名 
    if ($sign) $sign .= '&'; //第一个字符串签名不加& 其他加&连接起来参数 
    $sign .= "$key=$val"; //拼接为url参数形式 
    } 
    $pay_id = $_POST['pay_id']; //需要充值的ID 或订单号 或用户名 
    $pay_money = (float)$_POST['pay_money']; //实际付款金额 
    $pay_no = $_POST['pay_no']; //交易流水号 
    $pay_time = $_POST['pay_time']; //付款的时间戳 
    $pay_type = (int)$_POST['pay_type']; //支付方式 1:支付宝 2:微信支付 3:QQ钱包
    $param = isset($_POST['param'])?$_POST['param']:'';//自定义参数 
    
    //验证签名(根据sign_type选择验证方式)
    $signValid = false;
    if(strtolower($sign_type) == 'rsa'){
        $res = openssl_get_publickey($platformPublicKey);
        $signValid = openssl_verify($sign, base64_decode($_POST['sign']), $res, OPENSSL_ALGO_SHA256) === 1;
        openssl_free_key($res);
    }else{
        $signValid = (md5($sign . $appkey) == $_POST['sign']);
    }
    
    if (!$_POST['pay_no'] || !$signValid) { //不合法的数据 
    $result = '支付失败';
    } else { //合法的数据 
    /** 
    * 业务处理在这里写 
    */ 
    $result = '支付成功'; 
    } 
    $this->assign('pay_id',$pay_id);
    $this->assign('pay_no',$pay_no);
    $this->assign('pay_money',$pay_money);
    $this->assign('pay_type',$pay_type);
    $this->assign('pay_time',date("Y-m-d H:i:s",$pay_time));
    $this->assign('param',$param);
    $this->assign('result',$result);
    return view();
    

订单查询接口

查询API地址
http://18pay.net/pay/query.html
查询参数列表
参数名称 参数含义 类型 示例值 是否必填 参与签名 参数说明
appid 商户编号 string 20206491 是 是 平台分配商户编号
pay_no 交易流水号 string 20200217200042408995 否 是 平台生成的交易流水号,pay_no和pay_id必须提交其中一个,否则查询不到订单,同时提交2个参数时,pay_no优先
pay_id 唯一标识 string admin 否 是 商户提交的的唯一标识(订单编号或者用户ID)
sign 数据签名 string d7242db1748f4baef9ecec43b4106553 是 否 对数据进行签名,请参考签名算法
sign_type 签名类型 string rsa 否 否 默认md5,可选rsa(推荐)
charset 编码 string utf-8 否 否 utf-8或gb2312,默认utf-8
查询结果返回

系统会以json格式返回查询的结果(数据签名类型和提交的一样),可根据code的值来判断订单是否支付成功

返回类型 返回数据
支付成功 {"code":1,"type":"success","pay_no":"平台订单交易流水号","msg":"订单支付成功","sign_type":"md5","sign":"c47f3cba123456b6b24542110a8928af"}
未支付 {"code":0,"type":"error","pay_no":"平台订单交易流水号","msg":"订单未支付","sign_type":"md5","sign":"c47f3cba123456b6b24542110a8928af"}
其他情况 {"code":0,"type":"error","title":"提示","msg":"订单不存在","sign_type":"md5","sign":"c47f3cba123456b6b24542110a8928af"}

SDK接口示例

语言类型 接口介绍 SDK下载
易支付 彩虹易支付的接口插件 点击下载
发货100 发货100系统的接口示例 点击下载
Java Java的聚合支付接口示例 点击下载
ASP ASP的聚合支付接口示例 点击下载
PHP PHP的聚合支付接口示例 点击下载
Thinkphp5 Thinkphp5的聚合支付接口示例 点击下载