Skip to content

开发前必读

测试环境API网关

BASE_URL: http://stag.q-yd.cn

接口使用 AppID + APP Secret 通过 HMAC SHA1 加密鉴权

  • App ID:渠道唯一性标示符,由系统分配。
  • App Secret: 接口秘钥,系统分配。
  • HMAC:是基于散列的消息认证码(Hash-based MessageAuthentication Code)。

签名原串生成规则:

样例代码 api.php
php
<?php
require "helper.php";

error_reporting(0);

function buildRequestPara($para_temp, $app_id, $app_secret) {
  //除去待签名参数数组中的空值和签名参数
  $para_filter = paraFilter($para_temp);
  //对待签名参数数组排序
  $para_sort = argSort($para_filter);
  //生成签名结果
  $mysign = buildRequestSign($para_sort, $app_id, $app_secret);
  //签名结果与签名方式加入请求提交参数组中
  $para_sort['sign'] = $mysign;
  foreach ($para_sort as $key => $value) {
      $para_sort[$key] = $value;
  }
  return $para_sort;
}

/**
 * 生成签名结果
 * @param $para_sort 已排序要签名的数组
 * return 签名结果字符串
 */
function buildRequestSign($para_sort, $app_id, $app_secret) {
  $prestr = createLinkstring($para_sort);
  // echo $prestr . "\n";
  return hash_hmac("sha1", $prestr, $app_secret, false);
}

function buildRequestJSON($request_data,$url) {
  $sResult = '';
  //远程获取数据
  $sResult = getHttpResponseJSON($url, $request_data);
  return $sResult;
}

$app_id = "****";

$app_secret = "****";

$bank_data = array(
  'app_id' => $app_id,
  'nonce_str' => genLetterDigitRandom(16),
  'time_stamp' => time() . "",
  'card_number' => '6216261000000000018',
  'account_name' => '张三',
  'phone' => '15698238449',
  'branch_bank_name' => '中国银行',
  'identity_card_number' => '441283195508011086',
  'amount' => '0.1',
  'out_order_no' => "20190918384748" . rand(100, 999)
);

$alipay_data = array(
  'app_id' => $app_id,
  'nonce_str' => genLetterDigitRandom(16),
  'time_stamp' => time() . "",
  'alipay_account' => '15017898739',
  'account_name' => '张三',
  'phone' => '15698238449',
  'identity_card_number' => '441283195508011086',
  'amount' => '0.1',
  'order_info' => '代付服务费',
  'remark' => '代付服务费',
  'out_order_no' => "20190918384748" . rand(100, 999) 
);

$query_data = array(
  'app_id' => $app_id,
  'nonce_str' => genLetterDigitRandom(16),
  'time_stamp' => time() . "",
  'order_no' => "9adbb6ab58774f078266a43617b11271"
);


$sortPara = buildRequestPara($query_data, $app_id, $app_secret);
// echo json_encode($sortPara);
$html_text = buildRequestJSON($sortPara, 'http://stag.tsing-pay.com/api/platform/payment_results');

echo $html_text;
样例代码 helper.php
php
<?php

/**
 * 把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串
 * @param $para 需要拼接的数组
 * return 拼接完成以后的字符串
 */
function createLinkstring($para) {
	$arg  = "";
	while (list ($key, $val) = each ($para)) {
		$arg.=$key."=".$val."&";
	}
	//去掉最后一个&字符
	$arg = substr($arg,0,count($arg)-2);
	//file_put_contents("log.txt","转义前:".$arg."\n", FILE_APPEND);
	//如果存在转义字符,那么去掉转义
	if(get_magic_quotes_gpc()){$arg = stripslashes($arg);}
	//file_put_contents("log.txt","转义后:".$arg."\n", FILE_APPEND);
	return $arg;
}
/**
 * 把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串,并对字符串做urlencode编码
 * @param $para 需要拼接的数组
 * return 拼接完成以后的字符串
 */
function createLinkstringUrlencode($para) {
	$arg  = "";
	while (list ($key, $val) = each ($para)) {
		$arg.=$key."=".urlencode($val)."&";
	}
	//去掉最后一个&字符
	$arg = substr($arg,0,count($arg)-2);
	
	//如果存在转义字符,那么去掉转义
	if(get_magic_quotes_gpc()){$arg = stripslashes($arg);}
	return $arg;
}
/**
 * 除去数组中的空值和签名参数
 * @param $para 签名参数组
 * return 去掉空值与签名参数后的新签名参数组
 */
function paraFilter($para) {
	$para_filter = array();
	while (list ($key, $val) = each ($para)) {
		if($key == "sign" || $val == "")continue;
		else	$para_filter[$key] = $para[$key];
	}
	return $para_filter;
}
/**
 * 对数组排序
 * @param $para 排序前的数组
 * return 排序后的数组
 */
function argSort($para) {
	ksort($para);
	reset($para);
	return $para;
}
/**
 * 写日志,方便测试(看网站需求,也可以改成把记录存入数据库)
 * 注意:服务器需要开通fopen配置
 * @param $word 要写入日志里的文本内容 默认值:空值
 */
function logResult($word='') {
	$fp = fopen("log.txt","a");
	flock($fp, LOCK_EX) ;
	fwrite($fp,"执行日期:".strftime("%Y%m%d%H%M%S",time())."\n".$word."\n");
	flock($fp, LOCK_UN);
	fclose($fp);
}

/**
 * 远程获取数据,POST模式
 * 注意:
 * @param $url 指定URL完整路径地址
 * @param $para 请求的数据
 * return 远程输出的数据
 */
function getHttpResponseJSON($url, $para) {
  $json = json_encode($para);     
  $curl = curl_init($url);
  curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "POST");                          
  curl_setopt($curl, CURLOPT_POSTFIELDS, $json);
  curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($curl,CURLOPT_RETURNTRANSFER, 1);// 显示输出结果

  curl_setopt($curl, CURLOPT_HTTPHEADER, array(                 
      'Content-Type: application/json',
      'Content-Length: ' . strlen($json))
  );
  $responseText = curl_exec($curl);
  file_put_contents("log.txt","返回值:".$responseText."\n", FILE_APPEND);  
  curl_close($curl);
  return $responseText;
}

/**
 * 实现多种字符解码方式
 * @param $input 需要解码的字符串
 * @param $_output_charset 输出的解码格式
 * @param $_input_charset 输入的解码格式
 * return 解码后的字符串
 */
function charsetDecode($input,$_input_charset ,$_output_charset) {
	$output = "";
	if(!isset($_input_charset) )$_input_charset  = $_input_charset ;
	if($_input_charset == $_output_charset || $input ==null ) {
		$output = $input;
	} elseif (function_exists("mb_convert_encoding")) {
		$output = mb_convert_encoding($input,$_output_charset,$_input_charset);
	} elseif(function_exists("iconv")) {
		$output = iconv($_input_charset,$_output_charset,$input);
	} else die("sorry, you have no libs support for charset changes.");
	return $output;
}

//格式化时间戳
function local_date($format, $time = NULL) {
  if ($time === NULL) {
    $time = gmtime();
  } elseif ($time <= 0) {
    return '';
  }
  return date($format, $time);
}

function genLetterDigitRandom($size) {
	$allLetterDigit = array("0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z");
	$randomSb = "";
	$digitSize = count($allLetterDigit)-1;
	for($i = 0; $i < $size; $i ++){
		$randomSb .= $allLetterDigit[rand(0,$digitSize)];
	}
	return $randomSb;
}
?>

将已有json数组中的参数按照key_1=value_1&key_2=value2的形式进行排列;
参数的排放顺序按照首字母 ASCII 码进行升序排列,
值不为空的参数均需参与签名, url 地址需要进行 urlencode 编码后传入接口。

得到加密原串 s:

account_name=张胜男&amount=1223.56&app_id=2019071516330002&branch_bank_name=中国银行&card_number=6216261000000000018&identity_card_number=441283195508011086&nonce_str=MI7X1BMGJJNCOJQS&out_order_no=20190918384748&phone=15698238449&time_stamp=1563852246

生成16进制 sign

php
// php 样例代码
hash_hmac("sha1", $s, $secret_key, false);
go
// golang 样例代码
func Hmac5Sign(secretKey, s string) []byte {
  m := hmac.New(sha1.New, []byte(secretKey))
  m.Write([]byte(s))
  return m.Sum(nil)
}

返回码

返回码
说明
0000交易成功
42207数据解析失败
42208请求数据已过期
42209签名验证失败
42210AppID 不存在,或应用状态异常