2020.02新版

This commit is contained in:
Blokura
2020-02-21 16:20:55 +08:00
parent 45e2415d71
commit a2f29a310b
755 changed files with 95144 additions and 0 deletions

62
paypage/ajax.php Normal file
View File

@@ -0,0 +1,62 @@
<?php
include("./inc.php");
$act=isset($_GET['act'])?daddslashes($_GET['act']):null;
if(strpos($_SERVER['HTTP_REFERER'],$_SERVER['HTTP_HOST'])===false)exit('{"code":403}');
@header('Content-Type: application/json; charset=UTF-8');
$uid=intval($_POST['uid']);
$money=daddslashes($_POST['money']);
$payer=daddslashes($_POST['payer']);
$paytype=$_POST['paytype'];
$direct=intval($_POST['direct']);
if($_POST['token']!=$_SESSION['paypage_token'])exit('{"code":-1,"msg":"CSRF TOKEN ERROR"}');
if(!$uid || $uid!=$_SESSION['paypage_uid'])exit('{"code":-1,"msg":"收款方信息无效"}');
if($money<=0 || !is_numeric($money) || !preg_match('/^[0-9.]+$/', $money))exit('{"code":-1,"msg":"金额不合法"}');
if($conf['pay_maxmoney']>0 && $money>$conf['pay_maxmoney'])exit('{"code":-1,"msg":"最大支付金额是'.$conf['pay_maxmoney'].'元"}');
if($conf['pay_minmoney']>0 && $money<$conf['pay_minmoney'])exit('{"code":-1,"msg":"最小支付金额是'.$conf['pay_minmoney'].'元"}');
$trade_no=date("YmdHis").rand(11111,99999);
$return_url=$siteurl.'paypage/success.php?trade_no='.$trade_no;
$domain=getdomain($return_url);
if(!$DB->exec("INSERT INTO `pre_order` (`trade_no`,`out_trade_no`,`uid`,`tid`,`addtime`,`name`,`money`,`notify_url`,`return_url`,`domain`,`ip`,`status`) VALUES (:trade_no, :out_trade_no, :uid, 3, NOW(), :name, :money, :notify_url, :return_url, :domain, :clientip, 0)", [':trade_no'=>$trade_no, ':out_trade_no'=>$trade_no, ':uid'=>$uid, ':name'=>'在线收款', ':money'=>$money, ':notify_url'=>$return_url, ':return_url'=>$return_url, ':domain'=>$domain, ':clientip'=>$clientip]))exit('{"code":-1,"msg":"创建订单失败,请返回重试!"}');
$_SESSION['paypage_trade_no'] = $trade_no;
$result=[];
$result['code']=0;
$result['msg']='succ';
$result['trade_no']=$trade_no;
$result['direct']=$direct;
if(!empty($paytype) && isset($_SESSION['paypage_typeid']) && isset($_SESSION['paypage_channel']) && isset($_SESSION['paypage_rate'])){
$typeid = intval($_SESSION['paypage_typeid']);
$channel = intval($_SESSION['paypage_channel']);
if($direct==1){
if($userrow['mode']==1){
$realmoney = round($money*(100+100-$_SESSION['paypage_rate'])/100,2);
$getmoney = $money;
}else{
$realmoney = $money;
$getmoney = round($money*$_SESSION['paypage_rate']/100,2);
}
$DB->exec("UPDATE pre_order SET type='$typeid',channel='$channel',realmoney='$realmoney',getmoney='$getmoney' WHERE trade_no='$trade_no'");
$ordername = 'onlinepay'.time();
$ordername = !empty($conf['ordername'])?ordername_replace($conf['ordername'],$ordername,$uid):$ordername;
if($paytype=='alipay'){
$paydata = alipay_jspay($channel,$trade_no,$realmoney,$ordername,$payer);
}elseif($paytype=='wxpay'){
$paydata = wxpay_jspay($channel,$trade_no,$realmoney,$ordername,$payer);
}elseif($paytype=='qqpay'){
$paydata = qqpay_jspay($channel,$trade_no,$realmoney,$ordername);
}
$result['paydata'] = $paydata;
}else{
$result['url'] = '/submit2.php?typeid='.$typeid.'&trade_no='.$trade_no;
}
}else{
$result['url'] = '/cashier.php?trade_no='.$trade_no;
}
exit(json_encode($result));

77
paypage/css/default.css Normal file
View File

@@ -0,0 +1,77 @@
@charset "UTF-8";
html {font-size:62.5%;-webkit-font-smoothing:antialiased;}
body {text-align:center;font-family: 'PingFang SC', 'Helvetica Neue', Helvetica, Arial, 'Hiragino Sans GB', 'Microsoft Yahei', , STHeiti, , sans-serif; -webkit-text-size-adjust:none; font-size:1.4rem;background:#f4f6f9;color:#000;-webkit-user-select:none;}
* {margin:0; padding:0;list-style:none; }
i, em, b {font-style:normal; font-weight:normal;}
input::-webkit-input-placeholder,textarea::-webkit-input-placeholder{color:#ccc;}
img{width:100%;vertical-align:top;}
input,textarea,select,button{font-size:1.4rem;border:0; outline:none;font-family:"微软雅黑","Microsoft YaHei","Helvetica Neue",Helvetica,STHeiTi,sans-serif;}
*{-webkit-tap-highlight-color: rgba(0,0,0,0);}
.clear{ clear:both;}
.none{ display:none !important;}
.hide{ display:none;}
.height100{ height:100%;}
/*flex*/
html,body{height:100%;}
.container{height:100%;}
.layout-flex{display:-webkit-box;-webkit-box-orient:vertical;height:100%;}
.layout-flex .content{-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1;overflow:auto;-webkit-overflow-scrolling:touch;position:relative;height:100%;}
.m-title{padding: 0.42rem 0.54rem 0.5rem;}
.m-title dl{overflow: hidden;}
.m-title dl dt{float: left; width: 0.66rem; height: 0.66rem; margin-right: 0.2rem;}
.m-title dl dt img{width: 100%; height: 100%; display: block;}
.m-title dl dd{float: left; font-size: 0.28rem; color: #161213; padding-top: 0.13rem;}
/*pop*/
.pop-wrap{position:fixed;left:0;top:0;width:100%;height:100%;background:rgba(0,0,0,0.6);display:table;z-index:99999;}
.pop-outer{display:table-cell;vertical-align:middle;}
/*loading*/
.circle-box{width: 100%;height: 100%;position: fixed;left: 0;top: 0;}
.circle_animate{position: absolute; left: 50%; top: 43%; width: 9rem; height: 9rem; margin-left: -4.5rem; margin-top: -4.5rem; background: rgba(0, 10, 24, 0.6); border-radius: 8px; box-shadow: 0 0 4px rgba(0, 10, 24, 0.4);}
.circle_animate .circle{width: 3.6rem; height: 3.6rem; margin: 1.6rem auto 1rem; background: url(../images/loading.gif) no-repeat; background-size: 100% 100%; }
@-webkit-keyframes animate_circle{100%{-webkit-transform: rotate(360deg);}}
.circle_animate p{color: rgba(255, 255, 255, 0.7);}
/*pop*/
.pop_wrapper{position:fixed;left:0;top:0;width:100%;height:100%;background:rgba(0,0,0,0.6);display:table;z-index:99999;}
.pop_outer{display:table-cell;vertical-align:middle;}
.pop_obtm{display:table-cell;vertical-align:bottom;}
.pop_pintip{margin: 0 2rem;}
.pop_cont{margin: 0 2rem;background-color: rgba(255,255,255,1);border-radius: 1rem;overflow: hidden;}
.pop_tip{font-size: 1.8rem;padding: 2rem 2.4rem 2rem 2.4rem;line-height: 2.8rem;word-break: break-all;border-bottom:1px solid #e5e5e5;color:#000}
.pop_wbtn{display: block;height: 4.4rem;line-height: 4.4rem;font-size: 1.7rem;color: #007FFF;
}
.pop_wbtn a{background:#0187e8}
.pop_wbtn:active{color: rgba(0,127,255,0.5);}
/*.b_top{padding:1.5rem 0.6rem;background:#0187e8;border-radius: 6px;color:#fff;margin:20px;.b_top{margin:20px 0}}*/
.b_top{padding:1.2rem 0.6rem;border-radius: 6px;color:#0076fe;font-size:2rem}
/*.pop_btn{background:#0187e8;border-radius: 6px;padding:1rem 0;color:#fff;display:block;width:85%;margin:0 auto}
.pop_btn{padding:1em;height:2.5em}*/
.pop_wrapper_white{position:fixed;left:0;top:0;width:100%;height:100%;background:rgba(0,0,0,0);display:table;z-index:99999;}
.pop_intips{display: inline-block;border-radius: 8px;background-color: rgba(0,0,0,0.8);font-size: 1.5rem;color: #fff;padding: 1.5rem 2rem;word-break: break-all;}
@media (max-device-width: 320px){
html{font-size: 52%;}
}

190
paypage/css/style.css Normal file
View File

@@ -0,0 +1,190 @@
@charset "utf-8";
/*date:2018-03-13*/
/* add====================== */
.mar10{margin:10px}
.marLeft5{margin-left:5px}
.marLeft10{margin-left:10px}
.mar20{margin:20px}
.fl{float:left}
.selTitle{font-size: 1.95rem;color:#666}
.fontGray{color:#8e8e8e}
.money{font-size:2rem;font-family: "Microsoft YaHei";}
.grayico_pay{display:inline-block;width: 3.34rem;height: 2.6rem;margin: 0 auto;overflow-y: hidden;}
.copyRight{color:#afafaf;font-size:1.5rem;margin-bottom:10px;font-family: Microsoft YaHei;}
/* 按钮====================== */
.btn{ width:100%; height:4.5rem; border-radius:6px; font-size:1.7rem;}
.btn:after{ border-radius:9px;}
.btn_blue{ background:#4182E2; color:#fff;}
.btn_blue:active{ background:#2167CD;}
.btn_blue.disable{ background: #ddd}
.btn_white{ background:#fff; color:#000;}
.btn_white:active{ background:#ddd;}
/* 1像素边框====================== */
.border{ position:relative;}
.border:after{ content:""; position:absolute; left:0; top:0; right:-100%; bottom:-100%; -webkit-transform:scale(0.5); -webkit-transform-origin:0 0; pointer-events:none;}
/*.b_all:after{ border:1px solid #4182e2;}
.b_all2:after{ border:1px solid #ddd;}*/
.b_btm:after{ border-bottom:1px solid #d5d5d5;}
/*.b_lft:after{ border-left:1px solid #ddd;}*/
.b_rgt:after{ border-right:1px solid #d5d5d5;}
/*.b_top:after{ border-top:1px solid #ddd;}*/
.b_rgt_btm:after{ border-right:1px solid #d5d5d5; border-bottom:1px solid #d5d5d5;}
/* 付款金额====================== */
.payMoney{text-align: left;color:#b7b7b7;font-size:1.8rem;margin-bottom:10px;}
/* 设置支付金额====================== */
.amount_title{padding: 0 1.5rem; font-size: 1.7rem;color: #333;line-height: 2.8rem;}
.set_amount{padding:1rem 1rem 0.5rem 1rem; margin: 2rem 1.5rem 0 1.5rem; background: #fff; position: relative;border-radius:6px;box-shadow: 0 0 1px #ebebeb;}
.set_amount .amount_hd{font-size: 1.5rem; color: #666; text-align: left;height: 2.4rem;line-height: 2.4rem;}
.set_amount .amount_bd{ height: 50px;line-height: 50px; margin: 0; text-align: left; }
.set_amount .amount_bd input{width: 100%; height: 100%; font-family: arial; font-size: 4rem;}
.set_amount .amount_bd .int_place{display: inline-block; height: 5rem; line-height: 5rem; vertical-align: middle; font-family: arial; font-size: 4rem;color: #999;}
/* .set_amount .amount_bd .input_simu{font-family: HelveticaNeue; font-size: 4.4rem;display: inline-block;color:#444;position:absolute;left:3.6rem;height:50px;bottom:10px;}
.set_amount .amount_bd .line_simu{margin-top:0.5rem;width: 1px; height: 3rem; background: #4182E2; vertical-align: middle; opacity: 0; -webkit-animation: animate_flash 1s ease-in-out infinite;}
*/
.set_amount .amount_bd .input_simu{font-family: HelveticaNeue; font-size: 34px; color:#444;height:50px; float:left;}
.set_amount .amount_bd .line_simu{margin-top:0.5rem;width: 1px; height: 40px; background: #4182E2; opacity: 0; -webkit-animation: animate_flash 1s ease-in-out infinite;float:left;}
.i_money{padding:0rem 0.5rem 0 0; font-size:24px;color: #444;font-family: arial;height:50px; float:left;}
@-webkit-keyframes animate_flash{
50%{opacity:1;}
}
.amount_bd .clearBtn{width: 3rem;height: 100%;position: absolute;right: 0;top:0;background: #fff;}
.set_amount .amount_bd .btn_clear{
position: absolute; right: 0.5rem; top: 1.5rem; width: 2rem; height: 2rem; background: url(../images/btn_clear.png) center center no-repeat; background-size: 1.4rem 1.4rem;
}
.error_tips{position: absolute; left: 50%; top: 18.2rem; width: 16rem; height: 3.2rem; line-height: 3.2rem; margin-left: -8rem; color: #fff; background: rgba(15,15,30,0.5); border-radius: 8px; display: none;}
.remark{padding: 0 1.6rem; color: #4081e1; text-align: right;height: 3.7rem;line-height: 3.7rem;}
.btn_row{padding: 0 2rem 1rem;}
/* .i_money{padding:0rem 0.5rem 0 0; font-size:23px;color: #444;font-family: arial;position:absolute;height:50px;bottom:5px;} */
.sico_pay_p{padding: 3rem 0 1.5rem 0;}
.sico_pay{display: block;width:40px;height:40px;background: url(../images/sellerLogo.png) no-repeat;background-size:40px 40px;margin: 0 auto;overflow-y: hidden;}
/*.keyboard{background: #fff;}*/
.key_table{width: 100%;border-collapse:collapse;border-spacing:1;border-spacing:0;list-style: none;padding: 0;margin: 0;}
.key_table td{width: 25%;height: 6.2rem;text-align: center;color:#444}
.key_table td.disable{background-color: #a0d7fe;}
.keyboard .key{line-height: 6.2rem; font-family:HelveticaNeue; font-size: 3.6rem;}
.keyboard .key.clear{background: url(../images/clear.png) center no-repeat; background-size:2.95rem 2.95rem;width: 2.95rem;height:2.95rem}
.keyboard .key:active{background-color: #D5D8DB;}
.keyboard{background: #fff;}
.keyboard .pay_btn{background-color: #0076fe;font-size: 2rem;color: #fff;line-height: 2.3rem;}
.pay_btn:active{background-color: #54b8ff;}
.pay_btn em{display: block;}
.pop_remark{background: rgba(255, 255, 255, 0.95); border-radius: 10px; margin: 8rem 4rem; overflow: hidden;}
.pop_remark .pop_title{padding: 1.8rem 1.5rem 0; font-size: 1.7rem;}
.pop_remark .input_wrap{margin: 1.6rem 1.5rem 2rem;}
.pop_remark .input_wrap input{width: 100%; height: 4rem; background: #fff; text-indent: 1rem;}
.pop_remark .btn_wrap{display: -webkit-box;}
.pop_remark .btn_wrap span{display: block; -webkit-box-flex: 1; width: 1px; height: 5rem; line-height: 5rem; font-size: 1.7rem; color: #007FFF;}
/* 支付确认====================== */
.pay_amount{font-size: 5rem; margin: 3.5rem 0 0.8rem;}
.remark2{font-size: 1.5rem; color: #666;}
.btn_row2{margin: 5rem 2rem 2rem;}
/* 支付成功====================== */
.bg_wt{background-color: #fff;margin-bottom: 1rem;}
.pay_stop{padding: 4rem 0 1rem 0;}
.pay_stop .ico_success{display: block;width: 6rem; height: 6rem; background: url(../images/icoSuccess.png) center no-repeat; background-size: 100% 100%;margin: 0 auto;}
.pay_suc1{font-size: 1.7rem; color: #4182e2;height: 2.6rem;line-height: 2.6rem;overflow: hidden;}
.pay_suc2{font-size: 3rem; color: #333;height: 3.9rem;line-height: 3.9rem;overflow: hidden;}
.pay_suc2 i{font-size: 1.5rem;}
.pay_suc3{font-size: 1.5rem;color: #999;height: 3.7rem;line-height: 3.7rem;overflow: hidden;}
.btn_p{padding: 2rem 0 2.4rem 0;}
.btn_wt{width: 12.5rem;color: #4182e2;background-color: #fff;}
.btn_wt:active{ background-color:#eee;}
/*discount*/
.discount{padding-bottom: 2rem;}
.discount-tit{
font-size: 2.5rem;
padding: 2.5rem 0;
color:#4182e2;
text-align: center;
}
.discount-box{
margin: 0 2rem;
background: #fff;
-wekkit-border-radius: 5px;
border-radius: 5px;
}
.discount-box img{
max-width: 18.15rem;
display: block;
margin: 0 auto;
padding: 3rem 0 1rem 0;
}
.discount-box .t1{
color:#999;
font-size: 1.4rem;
padding: 0.5rem 0;
}
.discount-box .t2{
color:#000;
font-size: 2.5rem;
}
.discount-box .t2 span{font-size: 4rem;}
.discount-box .t3{
margin: 2.5rem 1rem 0 1rem;
border-top: 1px dashed #ddd;
padding: 1rem 1rem 2.6rem 1rem;
line-height: 2.8rem;
color:#999;
}
.discount-box .clear{
overflow: hidden;
}
.discount-box .fl{
float: left;
}
.discount-box .fr{
float: right;
}
.discount-box .grey{
color:#666;
text-decoration: line-through;
}
.discount-box .orange{
color:#ff9742;
}
.discount-box .btn{
margin-top: 2.5rem;
-webkit-border-radius: 5px;
border-radius: 5px;
color:#fff;
font-size: 1.7rem;
line-height: 4.5rem;
background: #4182e2;
}
.discount-box .btn:active{
background:#2667c7;
}
.discount-box .disable,.discount-box .disable:active{
background:#ddd;
}
.tdVerTop{vertical-align:top;}
@media (max-width:340px){
.set_amount .amount_bd .input_simu {
font-family: HelveticaNeue;
font-size: 30px;
}
.keyboard .key {
line-height: 5rem;
font-size: 3rem;
}
.key_table td {
height: 5rem;
}
}

34
paypage/error.php Normal file
View File

@@ -0,0 +1,34 @@
<!DOCTYPE html>
<html>
<head>
<title>错误提示</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta name="format-detection" content="telephone=no">
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<link href="//cdn.staticfile.org/ionic/1.3.2/css/ionic.min.css" rel="stylesheet" />
<style>
body,input,button,h1{font-size:16px;font-family: 'PingFang SC', 'Helvetica Neue', Helvetica, Arial, 'Hiragino Sans GB', 'Microsoft Yahei', 微软雅黑, STHeiti, 华文细黑, sans-serif; padding:0;margin:0}
</style>
</head>
<body>
<div class="bar bar-header bar-light" align-title="center">
<h1 class="title">错误提示</h1>
</div>
<div class="has-header" style="padding: 5px;position: absolute;width: 100%;">
<div class="text-center" style="color: #ff5757;">
<i class="icon ion-close-circled" style="font-size: 80px;"></i><br>
</div>
<div class="text-center" style="margin-top: 30px;">
<span style="font-size: 18px;color: #666;"><?php echo $msg?></span>
</div>
</div>
<script>
document.querySelector('body').addEventListener('touchmove', function (event) {
event.preventDefault();
});
</script>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 387 B

BIN
paypage/images/clear.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

BIN
paypage/images/loading.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

156
paypage/inc.php Normal file
View File

@@ -0,0 +1,156 @@
<?php
include("../includes/common.php");
function showerror($msg){
include ROOT.'paypage/error.php';
exit;
}
function showerrorjson($msg){
$result = ['code'=>-1, 'msg'=>$msg];
exit(json_encode($result));
}
function check_paytype(){
if(strpos($_SERVER['HTTP_USER_AGENT'], 'MicroMessenger/')!==false){
$type='wxpay';
}elseif(strpos($_SERVER['HTTP_USER_AGENT'], 'AlipayClient/')!==false){
$type='alipay';
}elseif(strpos($_SERVER['HTTP_USER_AGENT'], 'QQ/')!==false){
$type='qqpay';
}
return $type;
}
function alipayOpenId($channel){
global $DB,$siteurl;
$channel = \lib\Channel::get($channel);
if(!$channel)showerror('支付通道不存在');
define("PAY_ROOT", PLUGIN_ROOT.$channel['plugin'].'/');
require_once(PAY_ROOT."inc/AlipayOauthService.php");
$config['redirect_uri'] = $siteurl.'paypage/';
$oauth = new AlipayOauthService($config);
if(isset($_GET['auth_code'])){
$result = $oauth->getToken($_GET['auth_code']);
if($result['user_id']){
return $result['user_id'];
}else{
showerror('支付宝快捷登录失败!['.$result['sub_code'].']'.$result['sub_msg']);
}
}else{
$oauth->oauth();
}
}
function weixinOpenId($channel){
global $DB;
$channel = \lib\Channel::get($channel);
if(!$channel)showerror('支付通道不存在');
define("PAY_ROOT", PLUGIN_ROOT.$channel['plugin'].'/');
require_once PAY_ROOT."inc/WxPay.Api.php";
require_once PAY_ROOT."inc/WxPay.JsApiPay.php";
$tools = new JsApiPay();
$openId = $tools->GetOpenid();
if(!$openId)showerror('OpenId获取失败');
return $openId;
}
function alipay_jspay($channel,$trade_no,$money,$name,$openid){
global $DB,$conf;
$channel = \lib\Channel::get($channel);
if(!$channel)showerrorjson('支付通道不存在');
define("PAY_ROOT", PLUGIN_ROOT.$channel['plugin'].'/');
define("TRADE_NO", $trade_no);
require_once(PAY_ROOT."inc/model/builder/AlipayTradeCreateContentBuilder.php");
require_once(PAY_ROOT."inc/AlipayTradeService.php");
// 创建请求builder设置请求参数
$qrPayRequestBuilder = new AlipayTradeCreateContentBuilder();
$qrPayRequestBuilder->setOutTradeNo(TRADE_NO);
$qrPayRequestBuilder->setTotalAmount($money);
$qrPayRequestBuilder->setSubject($name);
$qrPayRequestBuilder->setBuyerId($openid);
// 调用qrPay方法获取当面付应答
$qrPay = new AlipayTradeService($config);
$qrPayResult = $qrPay->create($qrPayRequestBuilder);
// 根据状态值进行业务处理
$status = $qrPayResult->getTradeStatus();
$response = $qrPayResult->getResponse();
if($status == 'SUCCESS'){
$trade_no = $response->trade_no;
return $trade_no;
}elseif($status == 'FAILED'){
showerrorjson('支付宝创建订单失败!['.$response->sub_code.']'.$response->sub_msg);
}else{
showerrorjson('系统异常,状态未知!');
}
}
function wxpay_jspay($channel,$trade_no,$money,$name,$openid){
global $DB,$conf;
$channel = \lib\Channel::get($channel);
if(!$channel)showerrorjson('支付通道不存在');
define("PAY_ROOT", PLUGIN_ROOT.$channel['plugin'].'/');
define("TRADE_NO", $trade_no);
require_once PAY_ROOT."inc/WxPay.Api.php";
require_once PAY_ROOT."inc/WxPay.JsApiPay.php";
$input = new WxPayUnifiedOrder();
$input->SetBody($name);
$input->SetOut_trade_no(TRADE_NO);
$input->SetTotal_fee($money*100);
$input->SetTime_start(date("YmdHis"));
$input->SetTime_expire(date("YmdHis", time() + 600));
$input->SetNotify_url($conf['localurl'].'pay/wxpay/notify/'.TRADE_NO.'/');
$input->SetTrade_type("JSAPI");
$input->SetProduct_id("01001");
$input->SetOpenid($openid);
$order = WxPayApi::unifiedOrder($input);
if($order["result_code"]=='SUCCESS'){
$tools = new JsApiPay();
$jsApiParameters = $tools->GetJsApiParameters($order);
return $jsApiParameters;
}else{
showerrorjson('微信支付下单失败!['.$order["return_code"].'] '.$order["return_msg"].'['.$order["err_code"].'] '.$order["err_code_des"]);
}
}
function qqpay_jspay($channel,$trade_no,$money,$name){
global $DB,$conf;
$channel = \lib\Channel::get($channel);
if(!$channel)showerrorjson('支付通道不存在');
define("PAY_ROOT", PLUGIN_ROOT.$channel['plugin'].'/');
define("TRADE_NO", $trade_no);
require_once (PAY_ROOT.'inc/qpayMchAPI.class.php');
//入参
$params = array();
$params["out_trade_no"] = TRADE_NO;
$params["body"] = $name;
$params["fee_type"] = "CNY";
$params["notify_url"] = $conf['localurl'].'pay/qqpay/notify/'.TRADE_NO.'/';
$params["spbill_create_ip"] = real_ip();
$params["total_fee"] = $money*100;
$params["trade_type"] = "JSAPI";
//api调用
$qpayApi = new QpayMchAPI('https://qpay.qq.com/cgi-bin/pay/qpay_unified_order.cgi', null, 10);
$ret = $qpayApi->reqQpay($params);
$result = QpayMchUtil::xmlToArray($ret);
//print_r($result);
if($result['return_code']=='SUCCESS' && $result['result_code']=='SUCCESS'){
$prepay_id = $result['prepay_id'];
return $prepay_id;
}elseif(isset($result["err_code"])){
showerrorjson('QQ钱包支付下单失败['.$result["err_code"].'] '.$result["err_code_des"]);
}else{
showerrorjson('QQ钱包支付下单失败['.$result["return_code"].'] '.$result["return_msg"]);
}
}

136
paypage/index.php Normal file
View File

@@ -0,0 +1,136 @@
<?php
include("./inc.php");
if(isset($_GET['merchant'])){
$merchant=isset($_GET['merchant'])?trim($_GET['merchant']):showerror('参数不完整');
$uid = authcode($merchant, 'DECODE', SYS_KEY);
if(!$uid || !is_numeric($uid))showerror('参数错误');
}elseif(isset($_SESSION['paypage_uid'])){
$uid = intval($_SESSION['paypage_uid']);
}else{
showerror('参数错误');
}
$userrow=$DB->getRow("select * from pre_user where uid='$uid' limit 1");
if(!$userrow || $userrow['status']==0 || $userrow['pay']==0)showerror('当前商户不存在或已被封禁');
if($conf['cert_force']==1 && $userrow['cert']==0){
showerror('当前商户未完成实名认证,无法收款');
}
$_SESSION['paypage_uid'] = $uid;
$direct = '0';
$type = check_paytype();
if($type){
$submitData = \lib\Channel::submit($type, $userrow['gid']);
$apptype = explode(',',$submitData['apptype']);
if($type == 'alipay' && in_array('4',$apptype)){
$openId = alipayOpenId($submitData['channel']);
$direct = '1';
}elseif($type == 'wxpay' && in_array('2',$apptype)){
$openId = weixinOpenId($submitData['channel']);
$direct = '1';
}elseif($type == 'qqpay' && in_array('2',$apptype)){
$direct = '1';
}
$_SESSION['paypage_typeid'] = $submitData['typeid'];
$_SESSION['paypage_channel'] = $submitData['channel'];
$_SESSION['paypage_rate'] = $submitData['rate'];
}
$codename = !empty($userrow['codename'])?$userrow['codename']:$userrow['username'];
$csrf_token = md5(mt_rand(0,999).time());
$_SESSION['paypage_token'] = $csrf_token;
?>
<html lang="zh-cn">
<head>
<title>向商户付款</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta name="format-detection" content="telephone=no">
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<link rel="stylesheet" href="css/default.css">
<link rel="stylesheet" href="css/style.css?version=1.0.0">
</head>
<body>
<div class="layout-flex wrap">
<!-- content start -->
<div class="content">
<div class="mar20">
<table>
<tbody>
<tr>
<td><span class="sico_pay" style="margin:5px 5px 10px 5px"></span></td>
<td class="selTitle"><?php echo $codename?></td>
</tr>
</tbody>
</table>
</div>
<form name="payForm" action="dopay" method="post">
<input type="hidden" name="uid" id="uid" value="<?php echo $uid?>">
<input type="hidden" name="token" id="token" value="<?php echo $csrf_token?>">
<input type="hidden" name="paytype" id="paytype" value="<?php echo $type?>">
<input type="hidden" name="direct" id="direct" value="<?php echo $direct?>">
<input type="hidden" name="payer" id="payer" value="<?php echo $openId?>">
<input type="hidden" name="trade_no" id="trade_no" value="">
<div class="set_amount">
<div class="payMoney marLeft10">请输入付款金额</div>
<div class="amount_bd">
<i class="i_money marLeft10" style="">¥</i>
<span class="input_simu " id="amount"></span>
<!-- 模拟input -->
<em class="line_simu" id="line"></em>
<!-- 模拟闪烁的光标 -->
<div id="clearBtn" style="touch-action: pan-y; user-select: none; -webkit-user-drag: none; -webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></div>
<!-- 清除按钮 -->
</div>
</div>
</form>
</div>
<!-- content end -->
<div class="copyRight">由 <span style="font-weight:bold"><?php echo $conf['sitename']?></span> 提供服务支持</div>
<!-- 键盘 -->
<div class="keyboard">
<table class="key_table" id="keyboard" style="touch-action:pan-y; user-select: none; -webkit-user-drag: none; -webkit-tap-highlight-color: rgba(0, 0, 0, 0);">
<tbody>
<tr>
<td class="key border b_rgt_btm" data-value="1">1</td>
<td class="key border b_rgt_btm" data-value="2">2</td>
<td class="key border b_rgt_btm" data-value="3">3</td>
<td class="key border b_btm clear" data-value="delete"></td>
</tr>
<tr>
<td class="key border b_rgt_btm" data-value="4">4</td>
<td class="key border b_rgt_btm" data-value="5">5</td>
<td class="key border b_rgt_btm" data-value="6">6</td>
<td class="pay_btn" rowspan="3" id="payBtn" style="touch-action: pan-y; user-select: none; -webkit-user-drag: none; -webkit-tap-highlight-color: rgba(0, 0, 0, 0);"><em>确认</em>支付</td>
</tr>
<tr>
<td class="key border b_rgt_btm" data-value="7">7</td>
<td class="key border b_rgt_btm" data-value="8">8</td>
<td class="key border b_rgt_btm" data-value="9">9</td>
</tr>
<tr>
<td colspan="2" class="key border b_rgt" data-value="0">0</td>
<td class="key border b_rgt" data-value="dot">.</td>
</tr>
</tbody>
</table>
</div>
</div>
<script src="//cdn.staticfile.org/jquery/3.4.1/jquery.min.js"></script>
<script src="//open.mobile.qq.com/sdk/qqapi.js?_bid=152"></script>
<script src="js/hammer.js"></script>
<script src="js/common.js"></script>
<script src="js/pay.js?v=1002"></script>
<script>
var tips = new Tips();
</script>
</body>
</html>

122
paypage/js/common.js Normal file
View File

@@ -0,0 +1,122 @@
function getId(value){
return document.getElementById(value);
}
//ajax post
function Post(option){
var url = option.url || "";
var data = (function(){
var text = '';
if(option.data && option.data.constructor == Object){
var arr = [];
for(var key in option.data){
arr.push(key+'='+option.data[key]);
}
text = arr.join('&');
}
return text;
})();
var toJson = option.dataType == 'text' ? false : true;
var success = option.success || function(){};
var error = option.error || function(){};
var timeout = option.timeout || 30000;
var isTimeout = false;
var http = new XMLHttpRequest();
var timer = setTimeout(function(){
isTimeout = true;
http.abort();
error();
},timeout);
http.open("POST",url,true);
http.setRequestHeader("Content-type","application/x-www-form-urlencoded");
http.onreadystatechange = function(){
if(http.readyState != 4 || isTimeout){return;}
clearTimeout(timer);
if(http.status == 200){
var response = toJson ? JSON.parse(http.responseText) : http.responseText;
success(response);
}else{
error();
}
};
http.send(data);
}
//loading
function Loading(){
var obj = document.createElement('div');
var box = document.createElement('div');
var img = document.createElement('div');
var txt = document.createElement('p');
obj.className = 'circle-box none';
box.className = 'circle_animate';
img.className = 'circle';
box.appendChild(img);
box.appendChild(txt);
obj.appendChild(box);
if(script){
script.parentNode.insertBefore(obj,script);
}else{
document.body.appendChild(obj);
}
this.show = function(value){
txt.innerHTML = value || '加载中...';
obj.classList.remove('none');
};
this.hide = function(){
obj.classList.add('none');
txt.innerHTML = '';
};
}
//tips
function Tips(){
var obj = document.createElement('div');
var box = document.createElement('div');
var con = document.createElement('div');
var txt = document.createElement('div');
var p = document.createElement('p');
var btnBox = document.createElement('p');
var btn = document.createElement('span');
obj.className = 'pop_wrapper none';
box.className = 'pop_outer';
con.className = 'pop_cont';
txt.className = 'pop_tip';
p.className = 'border b_top';
btnBox.className = 'pop_wbtn';
btn.className='pop_btn'
btn.innerHTML = '我知道了';
p.appendChild(btn);
con.appendChild(txt);
con.appendChild(p);
box.appendChild(con);
obj.appendChild(box);
if(script){
script.parentNode.insertBefore(obj,script);
}else{
document.body.appendChild(obj);
}
function hideFun(){
obj.classList.add('none');
}
this.show = function(value,callback){
var fun = callback || hideFun;
txt.innerHTML = value || ' ';
p.onclick = callback || hideFun;
obj.classList.remove('none');
};
this.hide = hideFun;
}
document.body.addEventListener('touchstart',function(){},false);
var script = document.body.getElementsByTagName('script')[0];
var loading = new Loading();

7
paypage/js/hammer.js Normal file

File diff suppressed because one or more lines are too long

223
paypage/js/pay.js Normal file
View File

@@ -0,0 +1,223 @@
//insert
function keypress(e){
e.preventDefault();
var target = e.target;
var value = target.getAttribute('data-value');
var dot = valueCur.match(/\.\d{2,}$/);
if(!value || (value !== 'delete' && dot)){
return;
}
switch(value){
case '0' :
valueCur = valueCur === '0' ? valueCur : valueCur + value;
break;
case 'dot' :
valueCur = valueCur === '' ? valueCur : valueCur.indexOf('.') > -1 ? valueCur : valueCur + '.';
break;
case 'delete' :
valueCur = valueCur.slice(0,valueCur.length-1);
break;
default :
valueCur = valueCur === '0' ? value : valueCur + value;
}
if(!!valueCur && value !== 'delete' && value !== 'dot') {
var re = /^\d{1,9}(\.\d{0,2})?$/;
var limitLen = re.test(valueCur);
if (!limitLen) {
valueCur = valueCur.slice(0,valueCur.length-1);
return;
}
}
format();
}
//format
function format(){
var arr = valueCur.split('.');
var right = arr.length === 2 ? '.'+arr[1] : '';
var num = arr[0];
var left = '';
while(num.length > 3){
left = ',' + num.slice(-3) + left;
num = num.slice(0,num.length - 3);
}
left = num + left;
valueFormat = left+right;
valueFinal = valueCur === '' ? 0 : parseFloat(valueCur);
check();
}
//check
function check(){
amount.innerHTML = valueFormat;
if(valueFormat.length > 0){
clearBtn.classList.remove('none');
}else{
clearBtn.classList.add('none');
}
if(valueFinal === 0 || valueCur.match(/\.$/)){
payBtn.classList.add('disable');
}else{
payBtn.classList.remove('disable');
}
}
//clear
function clearFun(){
valueCur = '';
valueFormat = '';
valueFinal = 0;
amount.innerHTML = '';
clearBtn.classList.add('none');
payBtn.classList.add('disable');
}
//submit
function submitFun(){
if(!submitAble || payBtn.classList.contains('disable')){
return;
}
var txAmount = $("#txAmount").val();
if (!!txAmount && txAmount > 0) {
valueFinal = txAmount;
}
if(valueFinal == 0){
tips.show('请输入金额!');
return;
}
var amount = valueFinal;
var uid = $("#uid").val();
var paytype = $("#paytype").val();
var token = $("#token").val();
var direct = $("#direct").val();
var payer = $("#payer").val();
submitAble = false;
loading.show();
new Post({
url : 'ajax.php',
dataType : 'json',
data : {"money":amount,"payer":payer,"uid":uid,"paytype":paytype,"direct":direct,
"token":token},
error : function(){
loading.hide();
submitAble = true;
//update by yuwm 2018.03.14
tips.show('<span style="color:#959595;margin-top:5px">网络异常,请重新发起支付</span>');
},
success : function(data){
loading.hide();
if(data.code=="0"){//success
$("#trade_no").val(data.trade_no);
if (data.direct==1) {
if (paytype == 'wxpay') {
WxpayJsPay(data.paydata);
} else if (paytype == 'alipay') {
AlipayJsPay(data.paydata);
} else if (paytype == 'qqpay') {
QQJsPay(data.paydata);
}
}else{
window.location.href= data.url;
}
}else{
tips.show(data.msg);
}
submitAble = true;
}
});
}
//region WX JS
function WxpayJsPay(payStr){
var jsonPayStr = eval("("+payStr+")");
WeixinJSBridge.invoke(
'getBrandWCPayRequest',
jsonPayStr,
function(res){
// 使用以上方式判断前端返回,微信团队郑重提示res.err_msg将在用户支付成功后返回 ok但并不保证它绝对可靠。
if(res.err_msg == "get_brand_wcpay_request:ok" ) {
// 支付成功则关闭窗口
// tips.show("支付成功");
//WeixinJSBridge.call('closeWindow');
window.location.href="./success.php?trade_no="+$("#trade_no").val();
} else if(res.err_msg == "get_brand_wcpay_request:cancel") {
// tips.show("支付过程中用户取消");
} else if(res.err_msg == "get_brand_wcpay_request:fail") {
tips.show("支付失败");
}else{
tips.show("支付失败");
}
}
);
}
//endregion
//region ALI JS
function AlipayJsPay(payStr) {
var trade_no = $("#trade_no").val();
Alipayready(function(){
AlipayJSBridge.call("tradePay",{
tradeNO: payStr
}, function(result){
var msg = "";
if(result.resultCode == "9000"){
//AlipayJSBridge.call('closeWebview');
window.location.href="./success.php?trade_no="+$("#trade_no").val();
}else if(result.resultCode == "8000"){
msg = "正在处理中";
}else if(result.resultCode == "4000"){
msg = "订单支付失败";
}else if(result.resultCode == "6002"){
msg = "网络连接出错";
}
if (msg!="") {
tips.show(msg);
}
});
});
}
function Alipayready(callback) {
// 如果jsbridge已经注入则直接调用
if (window.AlipayJSBridge) {
callback && callback();
} else {
// 如果没有注入则监听注入的事件
document.addEventListener('AlipayJSBridgeReady', callback, false);
}
}
//endregion
//region QQ JS
function QQJsPay(payStr){
var trade_no = $("#trade_no").val();
var jsonPayStr = eval("("+payStr+")");
mqq.tenpay.pay({
tokenId: jsonPayStr.tokenId,
appInfo: "appid#"+jsonPayStr.appid+"|bargainor_id#"+jsonPayStr.bargainor_id+"|channel#wallet"
}, function(result, resultCode){
if(resultCode == 0){ //支付成功
//mqq.ui.popBack();
window.location.href="./success.php?trade_no="+$("#trade_no").val();
}else{
tips.show("支付失败");
}
});
}
//endregion
var keyboard = getId('keyboard');
var clearBtn = getId('clearBtn');
var payBtn = getId('payBtn');
var valueCur = '';
var valueFormat = '';
var submitAble = true;
var valueFinal = 0;
new Hammer(keyboard).on('tap',keypress);
new Hammer(payBtn).on('tap',submitFun);
new Hammer(clearBtn).on('tap',clearFun);

48
paypage/success.php Normal file
View File

@@ -0,0 +1,48 @@
<?php
include("./inc.php");
@header('Content-Type: text/html; charset=UTF-8');
$trade_no=daddslashes($_GET['trade_no']);
$row=$DB->getRow("SELECT * FROM pre_order WHERE trade_no='{$trade_no}' limit 1");
if(!$row)showerror('订单号不存在');
if($row['status']!=1)showerror('订单未完成支付');
if(!isset($_SESSION['paypage_trade_no']) || $_SESSION['paypage_trade_no']!=$trade_no)showerror('订单校验失败');
$userrow=$DB->getRow("select codename,username from pre_user where uid='{$row['uid']}' limit 1");
$codename = !empty($userrow['codename'])?$userrow['codename']:$userrow['username'];
?>
<!DOCTYPE html>
<html>
<head>
<title>支付成功页面</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta name="format-detection" content="telephone=no">
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<link href="//cdn.staticfile.org/ionic/1.3.2/css/ionic.min.css" rel="stylesheet" />
<style>
body,input,button,h1{font-size:16px;font-family: 'PingFang SC', 'Helvetica Neue', Helvetica, Arial, 'Hiragino Sans GB', 'Microsoft Yahei', 微软雅黑, STHeiti, 华文细黑, sans-serif; padding:0;margin:0}
</style>
</head>
<body>
<div class="bar bar-header bar-light" align-title="center">
<h1 class="title">支付成功页面</h1>
</div>
<div class="has-header" style="padding: 5px;position: absolute;width: 100%;">
<div class="text-center" style="color: #22ac38;">
<i class="icon ion-checkmark-circled" style="font-size: 80px;"></i><br>
</div>
<div class="text-center" style="margin-top: 30px;">
<p><span style="font-size: 18px;color: #666;"><?php echo $codename?></span></p>
<p><span style="font-size: 18px;color: #666;">支付金额:<span style="font-size:24px;font-weight:700;color:#f40;">¥<?php echo $row['money']?></span></span></p>
<p><span style="font-size: 14px;color: #666;">支付时间:<?php echo $row['endtime']?></span></p>
<p><span style="font-size: 14px;color: #666;">订单号:<?php echo $trade_no?></span></p>
</div>
</div>
<script>
document.querySelector('body').addEventListener('touchmove', function (event) {
event.preventDefault();
});
</script>
</body>
</html>