<?php
namespace app\index\controller;
use think\Exception;
use app\common\controller\Frontend;
class Pay extends Frontend{
protected $noNeedLogin = '*';
protected $noNeedRight = '*';
protected $apiurl="https://api.dpweixin.com/payment/do.html";
protected $pid="20-----";
protected $hashkey="f9a7bdb3fd---";
public function _initialize()
{
parent::_initialize();
// $this->apiurl=$apiurl;
// $this->pid=$pid;
// $this->hashkey=$hashkey;
}
//$param=["type"=>"","sn"=>"","price"=>"","title"=>"","notify_url"=>"","return_url"=>""];
public function pay()
{
$param=$this->request->param();
if(!in_array($param["type"], ["wechat","alipay"])){
$this->error("type参数错误");
}
if(empty($param["price"])){
$this->error("价格不能为空!");
}
if(empty($param["title"])){
$this->error("订单名称不能为空!");
}
if(empty($param["sn"])){
$this->error("订单号不能为空!");
}
$paytxt=["wechat"=>"微信","alipay"=>"支付宝"];
$data=array(
'version' => '1.1',//固定值,api 版本,目前暂时是1.1
'appid' => $this->pid, //必须的,APPID
'trade_order_id'=> $param["sn"], //必须的,网站订单ID,唯一的,匹配[a-zA-Z\d\-_]+
'total_fee' => $param['price'],//人民币,单位精确到分(测试账户只支持0.1元内付款)
'title' => $param['title'], //必须的,订单标题,长度32或以内
'time' => time(),//必须的,当前时间戳,根据此字段判断订单请求是否已超时,防止第三方攻击服务器
'notify_url'=> $param['notify_url'], //必须的,支付成功异步回调接口
'return_url'=> $param['return_url'], //支付成功返回地址
'nonce_str' => str_shuffle(time())//必须的,随机字符串,作用:1.避免服务器缓存,2.防止安全密钥被猜测出来
);
//微信h5
if($param['type']=='wechat' && $this->isWebApp()){
$data['type'] = "WAP";
}
//签名
$data['hash'] = $this->generate_xh_hash($data,$this->hashkey);
try {
$response = $this->http_post($this->apiurl, json_encode($data));
$result = $response?json_decode($response,true):null;
if(empty($result)){
throw new Exception($response,500);
}
if ($result['errcode'] != 0) {
throw new Exception($result['errmsg']);
}
if ($this->isWebApp()) {
$pay_url =$result['url'];
header("Location: $pay_url");
exit;
}
$qrcode=$result['url_qrcode'];
} catch (\Exception $e) {
$this->error($e->getMessage());
}
$this->view->assign("paytxt",$paytxt[$param['type']]);
$this->view->assign("type",$param['type']);
$this->view->assign("data",$data);
$this->view->assign("qrcode",$qrcode);
$this->view->assign("param",$param);
return $this->view->fetch();
}
public function notifyx()
{
$data = $this->request->post();
$uid = $this->request->param("uid");
$paytype = $this->request->param("paytype");
foreach ($data as $k=>$v){
$data[$k] = stripslashes($v);
}
if(!isset($data['hash'])||!isset($data['trade_order_id'])){
trace($data,'参数错误');
echo 'failed';exit;
}
// if($data['plugins']=='wechat'){
// $appid = '201906130470';
// $appsecret = 'd6031f0c7debcc61d486cad77468ae46';
// }else{
// $appid = '';
// $appsecret = '';
// }
// //APP SECRET
// $appkey =$appsecret;
unset($data['paytype']);
unset($data['sn']);
unset($data['uid']);
$hash =$this->generate_xh_hash($data,$this->hashkey);
if($data['hash']!=$hash){
//签名验证失败
trace($data,'签名验证失败:'.$hash);
echo 'failed';exit;
}
//商户订单ID
$trade_order_id =$data['trade_order_id'];
if($data['status']=='OD'){
$this->CreateBaoGao($uid,$data['transaction_id'],$data['total_fee'],$trade_order_id);
/************商户业务处理******************/
//TODO:此处处理订单业务逻辑,支付平台会多次调用本接口(防止网络异常导致回调失败等情况)
// 请避免订单被二次更新而导致业务异常!!!
// if(订单未处理){
// 处理订单....
// }
//....
//...
/*************商户业务处理 END*****************/
}else{
//处理未支付的情况
}
//以下是处理成功后输出,当支付平台接收到此消息后,将不再重复回调当前接口
echo 'success';
exit;
}
public function query()
{
$order_id=$this->request->param("order_id");
$request=array(
'appid' => $this->pid, //必须的,APPID
'out_trade_order'=> $order_id, //网站订单号(out_trade_order,open_order_id 二选一)
'time' => time(),//必须的,当前时间戳,根据此字段判断订单请求是否已超时,防止第三方攻击服务器
'nonce_str' => str_shuffle(time())//必须的,随机字符串,作用:1.避免服务器缓存,2.防止安全密钥被猜测出来
);
$request['hash'] = $this->generate_xh_hash($request,$this->hashkey);
$url = 'https://api.dpweixin.com/payment/query.html';
try {
$response = $this->http_post($url, http_build_query($request));
// dump($response);
$result = $response?json_decode($response,true):null;
if(!$result){
throw new Exception('Internal server error:'.$response,500);
}
if($result['data']['status']=='OD'){
echo 'complete';
exit;
}else{
echo 'paidding';
exit;
}
} catch (Exception $e) {
$this->error($e->getMessage());
}
}
protected function CreateBaoGao($user_id,$transaction_id,$payamount,$out_trade_no)
{
$site=config("site");
if(empty(db('baogao')->where("sn",$out_trade_no)->find())){
db("baogao")->insert([
"uid"=>$user_id,
"sn"=>$out_trade_no,
"title"=>$site["ordername"],
"syts"=>$this->getQujian($site["syts"]),
"nqsj"=>$this->getQujian($site["nqsj"]),
"fsxx"=>$this->getQujian($site["fsxx"]),
"cghybl"=>$this->getQujian($site["cghybl"]),
"bscs"=>$this->getQujian($site["bscs"]),
"bhyzd"=>$this->getQujian($site["bhyzd"]),
"ckzpdthys"=>$this->getQujian($site["ckzpdthys"]),
"hybzrs"=>$this->getQujian($site["hybzrs"]),
"hybznr"=>$this->getQujian($site["hybznr"]),
"pyqfwcs"=>$this->getQujian($site["pyqfwcs"]),
"bzcs"=>$this->getQujian($site["bzcs"]),
"zbs"=>$this->getQujian($site["zbs"]),
"nzgjc"=>$this->getQujian($site["nzgjc"]),
"pyqtlsc"=>$this->getQujian($site["pyqtlsc"]),
"amount"=>$site["price"],
"zfmoney"=>$payamount,
"zfstatus"=>"ok",
"zfsn"=>$out_trade_no,
"zftime"=>time(),
"createtime"=>time(),
"status"=>"normal",
]);
}
}
protected function getQujian($str){
$arr1=explode(",",$str);
$arr2=explode("-",$str);
if(count($arr1)>1){
return $arr1[array_rand($arr1)];
}elseif(count($arr2)==2){
if(intval(trim($arr2[0]))>0 && intval(trim($arr2[1]))>0){
return rand(intval(trim($arr2[0])),intval(trim($arr2[1])));
}
}else{
return $str;
}
}
protected function http_post($url,$data){
if(!function_exists('curl_init')){
throw new Exception('php未安装curl组件',500);
}
$protocol = (! empty ( $_SERVER ['HTTPS'] ) && $_SERVER ['HTTPS'] !== 'off' || $_SERVER ['SERVER_PORT'] == 443) ? "https://" : "http://";
$siteurl= $protocol.$_SERVER['HTTP_HOST'];
$ch = curl_init();
curl_setopt($ch, CURLOPT_TIMEOUT, 60);
curl_setopt($ch,CURLOPT_URL, $url);
curl_setopt($ch,CURLOPT_REFERER,$siteurl);
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE);
curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,FALSE);
curl_setopt($ch, CURLOPT_HEADER, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$response = curl_exec($ch);
$httpStatusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error=curl_error($ch);
curl_close($ch);
if($httpStatusCode!=200){
throw new Exception("invalid httpstatus:{$httpStatusCode} ,response:$response,detail_error:".$error,$httpStatusCode);
}
return $response;
}
protected function isWebApp(){
if(!isset($_SERVER['HTTP_USER_AGENT'])){
return false;
}
$u=strtolower($_SERVER['HTTP_USER_AGENT']);
if($u==null||strlen($u)==0){
return false;
}
preg_match('/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/',$u,$res);
if($res&&count($res)>0){
return true;
}
if(strlen($u)<4){
return false;
}
preg_match('/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/',substr($u,0,4),$res);
if($res&&count($res)>0){
return true;
}
$ipadchar = "/(ipad|ipad2)/i";
preg_match($ipadchar,$u,$res);
return $res&&count($res)>0;
}
protected function generate_xh_hash(array $datas,$hashkey){
ksort($datas);
reset($datas);
$arg = '';
foreach ($datas as $key=>$val){
if($key=='hash'||is_null($val)||$val===''){continue;}
if($arg){$arg.='&';}
$arg.="$key=$val";
}
return md5($arg.$hashkey);
}
protected function is_wechat_app(){
return strripos($_SERVER['HTTP_USER_AGENT'],'micromessenger');
}
}
?>
发表评论 取消回复