Files
2026-03-15 01:27:05 +08:00

370 lines
9.5 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
define('USEDCHARSET', 'utf-8');
/// 这里定义公共变量
$app_id = '14992192722868'; /// appid
$dev_key = '14915485974028'; /// 开发者key
$market_key = '0000'; /// 门店key
$sign_key = '0000'; /// 签名key(暂时支付时不校验签名, 但是退款时将校验这个签名)
/// 接口返回用的信息类
class ResultObject
{
public $error; /// 返回值: 0成功; 非0失败;
public $error_code; /// 错误号
public $msg; /// 错误信息
public $data; /// 返回的数据
public function ResultObject($string)
{
$this->error = 0;
$this->error_code = 0;
$this->msg = null;
$this->data = null;
$this->from_string($string);
}
public function to_array()
{
return (array)$this;
}
public function to_string()
{
return json_encode($this, JSON_UNESCAPED_UNICODE);
}
public function from_array($array)
{
foreach ($array as $key => $value)
{
if (property_exists($this, $key))
{
$this->$key = $value;
}
}
return true;
}
public function from_string($string)
{
return $this->from_array((array)json_decode($string));
}
}
/**
* @note 获取当前页面的完整连接
* @return string
*/
function getLocaleUrl()
{
$is_https =
(isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ||
(isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') ||
(isset($_SERVER['REQUEST_SCHEME']) && $_SERVER['REQUEST_SCHEME'] == 'https');
$request_scheme = $is_https ? 'https://' : 'http://';
$hostname = $_SERVER['SERVER_NAME'];
$hostport = (($is_https && '443' == $_SERVER['SERVER_PORT']) || (!$is_https && '80' == $_SERVER['SERVER_PORT'])) ? '' : ':' . intval($_SERVER['SERVER_PORT']);
return $request_scheme . $hostname . $hostport . $_SERVER['PHP_SELF'];
}
/**
* @date 2017-03-04
* @note 给参数按key的顺序排序。支持递归
* @param mixed $parameter 要排序的参数
* @return array
* @auth 应俊
*/
function SortParam($parameter)
{
$parameter = (array)$parameter;
foreach ($parameter as $k => $v)
{
if (is_array($v) || is_object($v))
{
$parameter[$k] = SortParam($v);
}
}
// 调用strcmp函数来排序该函数区分大小写。
uksort($parameter, 'strcmp');
return $parameter;
}
/**
* @date 2017-03-06
* @note 转换参数成字符串形式按key=value的形式用&分隔)。
* @param mixed $parameter 要转换的参数
* @return string
* @auth 应俊
*/
function ConvertParam($parameter)
{
$parameter = (array)$parameter;
$return = '';
foreach ($parameter as $k => $v)
{
if (is_array($v) || is_object($v))
{
$return .= sprintf('&%s={%s}', $k, ConvertParam($v));
}
else
{
$return .= sprintf('&%s=%s', $k, $v);
}
}
$sublen = mb_strlen('&', USEDCHARSET);
$retlen = mb_strlen($return, USEDCHARSET);
$return = mb_substr($return, $sublen, $retlen - $sublen, USEDCHARSET);
return $return;
}
/**
* @date 2017-03-04
* @note 为参数生成签名
* @param mixed $parameter 要签名的参数
* @param string $signkey 签名key
* @return string
* @auth 应俊
*/
function SignParameter($parameter, $signkey = '')
{
// 1先把参数按参数名key从小到大排序
$parameter = SortParam($parameter);
// 2连接参数成一个字符串按key=value的形式用&分隔)。
$return = ConvertParam($parameter);
// 3结尾加上key=签名key
$return .= '&key=' . $signkey;
// 4md5加密这个字符串
return md5($return);
}
/**
* @param mixed $data
* @return array|mixed
*/
function ChangePostData($data)
{
switch (gettype($data))
{
case 'array':
{
foreach ($data as $key => $value)
{
$data[$key] = ChangePostData($value);
}
break;
}
case 'object':
{
$array = (array)$data;
foreach ($array as $key => $value)
{
$data->$key = ChangePostData($value);
}
break;
}
default:
{
$data = preg_replace_callback('/\+/', function ($r) { return '%2B'; }, $data);
$data = preg_replace_callback('/\&/', function ($r) { return '%26'; }, $data);
break;
}
}
return $data;
}
/**
* @note 发送post请求
* @param string $url
* @param mixed $data
* @return string
*/
function SendPost($url, $data)
{
$data = http_build_query(ChangePostData($data));
$opts = array(
'http' => array(
'method' => 'POST',
'header' => "Content-type: application/x-www-form-urlencoded\r\n" . "Content-Length: " . strlen($data) . "\r\n",
'content' => $data,
),
);
$context = stream_context_create($opts);
$ret = file_get_contents($url, false, $context);
$ret = trim($ret, "\xEF\xBB\xBF");
return $ret;
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>支付测试</title>
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<link href="css/style.css" rel="stylesheet">
<script src="js/jquery-2.1.4.min.js"></script>
<script src="js/common.js"></script>
</head>
<body id="mainbody">
<?php
/// 尝试获取sid和scode
$sid = isset($_REQUEST['sid']) ? $_REQUEST['sid'] : '';
$scode = isset($_REQUEST['scode']) ? $_REQUEST['scode'] : '';
/// 判断是否有sid和scode, 什么数据都没有则先跳转到登录页面授权
if (empty($sid) || empty($scode))
{
$url = "https://api.tscce.cn/source/login/login.php?app_id={$app_id}&dev_key={$dev_key}&market_key={$market_key}&redirect_uri=" . rawurlencode(getLocaleUrl());
header("Location: {$url}");
exit;
}
elseif (!isset($_REQUEST['fee'])) /// 有sid和scode 但是 没有fee 则要求页面输入并提交fee参数
{
$html = <<<EOL
<script>
function submit() {
var fee = document.getElementById('fee').value;
if ('' == fee || undefined == fee) {
alert('请输入要支付的金额(单位为分)');
return;
}
var script =
"<form style='display:none;' id='frm' name='frm' method='post' action=''>" +
" <input name='fee' type='text' value='" + fee + "' />" + /// 支付金额(单位分)
"</form>";
$('#mainbody').append(script);
$('#frm').submit();
}
</script>
<section>
<header class="header"><span>支付测试</span></header>
<div class="neirong">
<ul>
<li><span class="name">总金额:</span><input id="fee" type="text" autofocus placeholder="单位:分 整型" class="input"> <sapn class="red">*</sapn></li>
</ul>
<footer class="text-center"><a href="javascript:;" onclick="submit();" class="btn btn-blue foot_btn">确定</a></footer>
</div>
</section>
EOL;
}
else /// 有fee参数表示已提交页面中输入的支付金额
{
/// 通过接口获取门店所支援的支付方式
$data = array(
'appid' => $app_id, /// appid
'devkey' => $dev_key, /// 开发者key
'market_key' => $market_key, /// 门店key
'level' => 1, /// 支付类型(1: 线上, 2: 扫码, 3: app)
'version' => 1, /// 版本号
);
$data['sign'] = SignParameter($data, $sign_key);
$result = new ResultObject(rawurldecode(SendPost('https://api.tscce.cn/api/newpay/querylist', $data)));
if (0 == $result->error && count($result->data) > 0) /// 成功
{
/// 这里为了演示, 只判断了第一个支付方式, 实际应该先判断当前用户的运行环境, 然后才去决定使用哪种支付通道(微信或支付宝等)
$pay_type = $result->data[0]->type_id;
$order_id = date('YmdHis') . rand(1000, 9999); /// 随机生成一个订单号
$notice_url = dirname(getLocaleUrl()) . '/notice.php'; /// 通知页面地址
$return_url = getLocaleUrl() . "?sid={$sid}&scode={$scode}"; /// 回调地址
$fee = $_REQUEST['fee'];
$data = array(
'appid' => $app_id, /// appid
'devkey' => $dev_key, /// 开发者key
'sid' => $sid, /// sid
'scode' => $scode, /// scode
'orderid' => $order_id, /// 订单号
'fee' => $fee, /// 支付金额(单位分)
'title' => 'test', /// 支付标题
'notice_url' => $notice_url, /// 回调页面地址(异步)
'return_url' => $return_url, /// 回调页面地址(同步)
'paytype' => $pay_type, /// 支付类型(可通过接口获取所有支持的类型列表)
'p1' => 'p1', /// 附加的其他参数, 回调时会原样返回, 参数名可自定义
'p2' => 'p2', /// 附加的其他参数, 回调时会原样返回, 参数名可自定义
'version' => 1, /// 接口版本号, 整型, 目前只支持1
);
$data['sign'] = SignParameter($data, $sign_key);
$html = <<<EOF
<form style="display:none;" id="frm" name="frm" method="post" action="https://api.tscce.cn/api/newpay/pay/online/">
<input name="appid" type="text" value="{$data['appid']}" />
<input name="devkey" type="text" value="{$data['devkey']}" />
<input name="sid" type="text" value="{$data['sid']}" />
<input name="scode" type="text" value="{$data['scode']}" />
<input name="orderid" type="text" value="{$data['orderid']}" />
<input name="fee" type="text" value="{$data['fee']}" />
<input name="title" type="text" value="{$data['title']}" />
<input name="notice_url" type="text" value="{$data['notice_url']}" />
<input name="return_url" type="text" value="{$data['return_url']}" />
<input name="paytype" type="text" value="{$data['paytype']}"/>
<input name="p1" type="text" value="{$data['p1']}"/>
<input name="p2" type="text" value="{$data['p2']}"/>
<input name="version" type="text" value="{$data['version']}"/>
<input name="sign" type="text" value="{$data['sign']}"/>
</form>
<script>
frm.submit();
</script>
EOF;
}
elseif (0 != $result->error) /// 有错误发生
{
$html = <<<EOL
<script>
alert('{$result->msg}');
</script>
EOL;
}
else
{
$html = <<<EOL
<script>
alert('该门店不支援任何的支付方式!');
</script>
EOL;
}
}
echo $html;
?>
</body>
</html>