class PayController extends Yaf_Controller_Abstract { //微信接口API URL前缀 const API_URL_PREFIX = 'https://api.mch.weixin.qq.com'; //下单地址URL const UNIFIEDORDER_URL = "/pay/unifiedorder"; //支付秘钥 protected $key; /** * @GetUrl 快捷支付请求HTML * ================================================ * @GET * @Type 登录类型 AliPay:支付宝, * @Money 充值金额 */ public function GetOrderAction($name = "Stringer") { // 传入值过滤 if (preg_match("/^\d{1,9}(\.\d{1,2})?$/", trim($_POST['Money'])) && in_array($_POST['Type'], ['WeiXin', 'AliPay'])) { // 获取用户登录数据 $UserID = true; //$UserID = HostID(); // 判断用户是否登录 if ($UserID) { // 初始化 $Time = time(); $IntIP = IntIp(); $Type = $_POST['Type']; $Category = $_POST['Category']; $Key = RandomStr(32, 2); $Money = trim($_POST['Money']); $HostID = HostID(); if (!$HostID) { $HostID = $_POST['UserID']; } $SaveMoney = (int)($Money * 100); $Session = Yaf_Session::getInstance(); $OverTime = (int)Yaconf::get("TaskYun.AliPay.OverTime"); $AliOver = ceil($OverTime / 60); $SQlTile = $Time + $OverTime; // 生成订单号 $OrderID = OrderGenerate($HostID, 1); // 保存该Key $Session->{$Key} = json_encode(array( "IP" => IntIp(), "Money" => $Money, "Name" => $Type, "Time" => $Time, )); $Title = "落地达人网支付宝充值"; // 支付宝描述 $Comment = "落地达人网钱包支付宝充值" . $Money . "元"; if ($Type == "WeiXin") { $ChannelID = 2; } else { $ChannelID = 1; } //获取余额 $PayWallete = UserWallete($HostID); $balance=$PayWallete['Balance']; // 保存相关数据到数据库中 $PayOrder = new MySqlModel("INSERT INTO `PayOrder` VALUES ('$OrderID', '1', '$IntIP','$HostID','0','$Time','$balance', '$ChannelID', '1')"); $PayOrder->WrRrows(); // 保存充值订单 $PayRecharge = new MySqlModel("INSERT INTO `PayRecharge` VALUES ('$OrderID', '$ChannelID', '', '0', '$HostID', '$SaveMoney', '1', '$Time', '0', '$SQlTile', '')"); $auto_id = $PayRecharge->WrRrows();; if (!$auto_id) { exit(json_encode(array("Status" => "false", "Content" => "写入充值订单表失败"))); } //Category等于2时为项目押金 if ((int)$Category == 2) { //执行人ID $ExecuteUserID = $_POST["ExecuteUserID"]; //项目ID $ProjectID = $_POST['ProjectID']; //查询项目详情 //查看是不是自己的项目在项目发布表中查找; $Project_obj = new MySqlModel("SELECT `FounderID`,`ProjectName` FROM `PublishProject`WHERE `ProjectID`=$ProjectID AND `FounderID` = $HostID"); $Project_obj = $Project_obj->WrOneAssoc(); if ($ExecuteUserID && is_numeric($ExecuteUserID) && $Project_obj ) { $Remark="项目【".$Project_obj['ProjectName']."】启动款"; // 保存项目款订单 $PayInside = new MySqlModel("INSERT INTO `PayInside` VALUES ('$OrderID', '$HostID', '$ExecuteUserID', '0', '$SaveMoney', '$SaveMoney', '$Time', '1', '$ProjectID', '$Remark')"); $auto_id = $PayInside->WrRrows(); if (!$auto_id) { exit(json_encode(array("Status" => "200", "Content" => "写入资金流水表失败"))); } } else { exit(json_encode(array("Status" => "false", "Content" => "项目执行人能为空"))); } } switch ($Type) { case "AliPay": // 请求支付宝支付 echo $this->UnifiedOrderAliPay($OrderID, $Title, $Comment, $Money, $Category, $AliOver); // 结束 return true; break; case "WeiXin": echo $this->UnifiedOrderWeiXin($OrderID, $Title, $Comment, $Money, $Category, $OverTime); return true; break; default: // 其余的 $ReturnText = "充值类型暂不支持"; } } else { $ReturnText = "请登录后再执行充值操作"; } } else { $ReturnText = "传入参数有误或您输入了一亿及以上的金额"; } return $ReturnText; } //支付宝统一下单方法 public function UnifiedOrderAliPay($OrderID, $Title, $Comment, $Money, $Key, $OverTime) { // 自动加载类 $Path = Yaconf::get("TaskYun.Home") . "AppButll/library/AliPay/"; require_once $Path . "AopClient.php"; require_once $Path . "request/AlipayTradeAppPayRequest.php"; $AppID = Yaconf::get("TaskYun.AliPay"); $aop = new AopClient; $aop->gatewayUrl = "https://openapi.alipay.com/gateway.do"; $aop->appId = $AppID['AppID']; $aop->rsaPrivateKey = $AppID['PrivateKey']; $aop->format = "json"; $aop->charset = "UTF-8"; $aop->signType = "RSA2"; $aop->alipayrsaPublicKey = $AppID['PublicKey']; //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay $request = new AlipayTradeAppPayRequest(); //SDK已经封装掉了公共参数,这里只需要传入业务参数 $bizcontent = json_encode([ 'body' => $Comment, 'subject' => $Title, 'out_trade_no' => $OrderID,//此订单号为商户唯一订单号 'total_amount' => $Money,//保留两位小数 'product_code' => 'QUICK_MSECURITY_PAY', "passback_params" => urlencode($Key), "timeout_express" => $OverTime . "m", ]); //设置回调地址 //$request->setNotifyUrl("https://chenlongzhen.cn/ceshi.php"); $request->setNotifyUrl("https://www.rw.cn/App/Pay/NotifyAliPay.html"); $request->setBizContent($bizcontent); //这里和普通的接口调用不同,使用的是sdkExecute $response = $aop->sdkExecute($request); //htmlspecialchars是为了输出到页面时防止被浏览器将关键参数html转义,实际打印到日志以及http传输不会有这个问题 ReturnEcho("true", $response); } /** * 微信下单方法 * @param $params 下单参数 */ public function UnifiedOrderWeiXin($OrderID, $Title, $Comment, $Money, $Key, $OverTime) { $WeiXinPay = Yaconf::get("TaskYun.WeiXinPay"); $this->key = $WeiXinPay['key']; $this->params['appid'] = $WeiXinPay['appid']; $this->params['mch_id'] = $WeiXinPay['mch_id']; $this->params['nonce_str'] = $this->genRandomString(); $this->params['body'] = $Title; $this->params['out_trade_no'] = $OrderID; $this->params['total_fee'] = $Money * 100; $this->params['spbill_create_ip'] = $_SERVER['REMOTE_ADDR']; $this->params['notify_url'] = "https://www.rw.cn/App/Pay/NotifyWeixin.html"; //$this->params['notify_url'] = "https://chenlongzhen.cn/ceshi.php"; $this->params['trade_type'] = "APP"; $this->params['detail'] = $Comment; $this->params['attach'] = "$Key"; //获取签名数据 $this->params['sign'] = $this->MakeSign($this->params); $xml = $this->data_to_xml($this->params); $response = $this->postXmlCurl($xml, self::API_URL_PREFIX . self::UNIFIEDORDER_URL); if (!$response) { return false; } $result = $this->xml_to_data($response); if (!empty($result['result_code']) && !empty($result['err_code'])) { $result['err_msg'] = $this->error_code($result['err_code']); } //将返回的数据二次签名 $resignData = array( 'appid' => $result['appid'], 'partnerid' => $result['mch_id'], 'prepayid' => $result['prepay_id'], 'noncestr' => $this->genRandomString(), 'timestamp' => time(), 'package' => 'Sign=WXPay' ); $sign = $this->MakeSign($resignData); $resignData['sign'] = $sign; $resignData['return_code'] = $result['return_code']; return json_encode($resignData); } //支付宝异步通知方法 public function NotifyAliPayAction($name = "Stringer") { //$data = json_decode($_POST['name'], true); // 自动加载类 $Path = Yaconf::get("TaskYun.Home") . "AppButll/library/AliPay/"; require_once $Path . "AopClient.php"; require_once $Path . "request/AlipayTradeAppPayRequest.php"; // 初始化 $Time = time(); $SavarIP = getIP(); $aop = new AopClient(); $AliPay = Yaconf::get("TaskYun.AliPay"); // 载入公钥 $aop->alipayrsaPublicKey = $AliPay['PublicKey']; // 校验支付宝传入数据 $Result = $aop->rsaCheckV1($_POST, "", "RSA2"); // 判断数据是否正确 if ($Result) { // 校验无误,查询是否有此订单 $AliNo = $_POST['trade_no']; $Status = $_POST['trade_status']; $LddrNo = $_POST['out_trade_no']; $ToMoney = $_POST['buyer_pay_amount'] * 100; // 查询目标渠道是否有该交易 $NewRecharge = new MySqlModel("SELECT `UserID`, `Money`, `Type`, `OverTime` FROM `PayRecharge` WHERE `OrderID` = '$LddrNo' LIMIT 1"); $PayRecharge = $NewRecharge->WrOneAssoc(); // 判断订单是否存在 if ($PayRecharge) { // 提取详情 $Money = $PayRecharge['Money']; $Type = (int)$PayRecharge['Type']; $HostID = $PayRecharge['UserID']; // 判断金额是否正确 if ($ToMoney == $Money) { // 判断状态是否 switch ($Status) { case 'WAIT_BUYER_PAY': // 等待卖家付款中,无处理 break; case 'TRADE_CLOSED': // 未付款交易超时关闭,或支付完成后全额退款,判断原本是什么状态 if ($Type == 2) { // 判断是否为退款,本系统不支持退款!!警报 if (isset($_POST['out_biz_no'])) { // 获取警报数据 $LDRRUrl = yaconf::get("TaskYun.LddrHost"); $PhoneList = yaconf::get("TaskYun.RootPhone"); // 保存日志 $NewPay = new MySqlModel("INSERT INTO `PayErrorLog` VALUES ('', '$HostID', '$LddrNo', '$SavarIP', '非法退款,本系统没置退款功能', '<{[Log]}>')", array( "Log" => json_encode($_POST) )); $LogID = $NewPay->InsertId(); // 发送警报信息 $SMSReturn = new MessageModel("SMS_82780011"); $MaileError = $SMSReturn->send_verify($PhoneList, array( "Url" => $LDRRUrl . "Pay/PayLog.html?ID=" . $LogID, "Name" => "非法退款", "Time" => $Time, )); return false; } } // 修改订单为超时终止状态 $NewUpdate = new MySqlModel("UPDATE `PayRecharge` SET `Type` = '3' WHERE `OrderID` = '$LddrNo' LIMIT 1"); $NewUpdate->WrRrows(); break; case 'TRADE_SUCCESS': if ((int)$Type == 2) { //exit("此订单已完成过支付!"); } $NewUpdate = new MySqlModel("UPDATE `PayRecharge` SET `Type` = '2',`ChannelOrder`='$AliNo' WHERE `OrderID` = '$LddrNo'"); $NewUpdate->WrRrows(); // 获取用户余额 $PayWallete = UserWallete($HostID); //print_r($PayWallete); // 添加用户余额,并保存 $category = urldecode($_POST['passback_params']); switch ((int)$category) { case 1: UpUserWallete($HostID, (int)$PayWallete['Balance'] + (int)$ToMoney, $PayWallete['Freeze']); //将交易流水号写入数据库跟新订单状态 break; case 2: $Project_id = new MySqlModel("SELECT `Link` FROM `PayInside` WHERE `OrderID` = '$LddrNo' LIMIT 1"); $Project_id = $Project_id->WrAssoc(); RunProject($HostID, $PayWallete['Freeze'], $PayWallete['Balance'], $Time, $Project_id, 1); //将交易流水号写入数据库跟新订单状态 $NewUpdate = new MySqlModel("UPDATE `PayInside` SET `Type` = '2' WHERE `OrderID` ='$LddrNo'"); $NewUpdate->WrRrows(); } //计算充值后的余额 $Balance=$PayWallete['Balance']+$ToMoney; // 为用户账户添加资金 $NewUpdate = new MySqlModel("UPDATE `PayOrder` SET `Diversity` = '$ToMoney',`Balance` = '$Balance', `Type` = '2' WHERE `OrderID` ='$LddrNo'"); $NewUpdate->WrRrows(); break; case 'TRADE_FINISHED': // 交易结束,不可退款 $NewUpdate = new MySqlModel("UPDATE `PayRecharge` SET `Type` = '4' WHERE `OrderID` = '$LddrNo'"); $NewUpdate->WrRrows(); break; default: // 其他 ReturnEcho(189); } echo "success"; } else { // 链接有误 ReturnEcho(1); } } else { // 订单不存在 ReturnEcho(187); } } else { // 校验有误 ReturnEcho(186); } } //微信支付异步通知方法 public function NotifyWeixinAction() { //$postXml = $GLOBALS["HTTP_RAW_POST_DATA"]; // 接受通知参数; $postXml = file_get_contents("php://input"); //$postXml = $_POST['name']; if (empty($postXml)) { return false; } $postObj = $this->xml_to_data($postXml); // 调用解析方法,将xml数据解析成对象 if ($postObj === false) { return false; } if (!empty($postObj['return_code'])) { if ($postObj["return_code"] == 'FAIL') { return false; } } $WeiXinPay = Yaconf::get("TaskYun.WeiXinPay"); $this->key = $WeiXinPay['key']; $data = $this->object2array($postObj);//对象转成数组 unset($data['sign']); // 拼装数据进行第三次签名 $sign = $this->MakeSign($data); // 获取签名 /** 将签名得到的sign值和微信传过来的sign值进行比对,如果一致,则证明数据是微信返回的。 */ if ($sign == $postObj["sign"]) { //$HostID = HostID(); //查看订单信息 $NewRecharge = new MySqlModel("SELECT `UserID`, `Money`, `Type`, `OverTime` FROM `PayRecharge` WHERE `OrderID` = " . $postObj["out_trade_no"] . " LIMIT 1"); $PayRecharge = $NewRecharge->WrOneAssoc(); if ($PayRecharge) { $HostID = $PayRecharge['UserID']; $Money = $PayRecharge['Money']; $Type = $PayRecharge['Type']; $out_trade_no = $postObj["out_trade_no"]; $total_fee = $postObj["total_fee"]; if ((int)$Type == 2) { exit("此订单已完成过支付!"); } if ((int)$Money !== (int)$postObj["total_fee"]) { exit("金额异常!"); } $NewUpdate = new MySqlModel("UPDATE `PayRecharge` SET `Type` = '2',`ChannelOrder`=" . $postObj["transaction_id"] . " WHERE `OrderID` = '$out_trade_no'"); $NewUpdate->WrRrows(); // 获取用户余额 $PayWallete = UserWallete($HostID); // 添加用户余额,并保存 switch ((int)$postObj['attach']) { case 1: UpUserWallete($HostID, (int)$PayWallete['Balance'] + (int)$postObj["total_fee"], $PayWallete['Freeze']); //将交易流水号写入数据库跟新订单状态 break; case 2: $Time = time(); $Project_id = new MySqlModel("SELECT `Link` FROM `PayInside` WHERE `OrderID` = '$out_trade_no' LIMIT 1"); $Project_id = $Project_id->WrAssoc(); RunProject($HostID, $PayWallete['Freeze'], $PayWallete['Balance'], $Time, $Project_id, 1); //将交易流水号写入数据库跟新订单状态 $NewUpdate = new MySqlModel("UPDATE `PayInside` SET `Type` = '2' WHERE `OrderID` = '$out_trade_no'"); $NewUpdate->WrRrows(); } //计算充值后的余额 $Balance=$PayWallete['Balance']+$postObj["total_fee"]; // 为用户账户添加资金 $NewUpdate = new MySqlModel("UPDATE `PayOrder` SET `Diversity` ='$total_fee',`Balance`='$Balance', `Type` = '2' WHERE `OrderID` ='$out_trade_no'"); $NewUpdate->WrRrows(); $reply = "<xml> <return_code><![CDATA[SUCCESS]]></return_code> <return_msg><![CDATA[OK]]></return_msg> </xml>"; echo $reply; // 向微信后台返回结果。 exit; } else { exit("订单不存在!"); } } else { exit("数据异常!"); } } /** * 产生一个指定长度的随机字符串,并返回给用户 * @param type $len 产生字符串的长度 * @return string 随机字符串 */ private function genRandomString($len = 32) { $chars = array( "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", "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", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" ); $charsLen = count($chars) - 1; // 将数组打乱 shuffle($chars); $output = ""; for ($i = 0; $i < $len; $i++) { $output .= $chars[mt_rand(0, $charsLen)]; } return $output; } /** * 生成签名 * @return 签名 */ public function MakeSign($params) { //签名步骤一:按字典序排序数组参数 ksort($params); $string = $this->ToUrlParams($params); //签名步骤二:在string后加入KEY $string = $string . "&key=" . $this->key; //签名步骤三:MD5加密 $string = md5($string); //签名步骤四:所有字符转为大写 $result = strtoupper($string); return $result; } /** * 将参数拼接为url: key=value&key=value * @param $params * @return string */ public function ToUrlParams($params) { $string = ''; if (!empty($params)) { $array = array(); foreach ($params as $key => $value) { $array[] = $key . '=' . $value; } $string = implode("&", $array); } return $string; } /** * 将xml转为array * @param string $xml * return array */ public function xml_to_data($xml) { if (!$xml) { return false; } //将XML转为array //禁止引用外部xml实体 libxml_disable_entity_loader(true); $data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true); return $data; } /** * 输出xml字符 * @param $params 参数名称 * return string 返回组装的xml **/ public function data_to_xml($params) { if (!is_array($params) || count($params) <= 0) { return false; } $xml = "<xml>"; foreach ($params as $key => $val) { if (is_numeric($val)) { $xml .= "<" . $key . ">" . $val . "</" . $key . ">"; } else { $xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">"; } } $xml .= "</xml>"; return $xml; } //curl发送请求 private function postXmlCurl($xml, $url, $useCert = false, $second = 30) { $ch = curl_init(); //设置超时 curl_setopt($ch, CURLOPT_TIMEOUT, $second); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); //设置header curl_setopt($ch, CURLOPT_HEADER, FALSE); //要求结果为字符串且输出到屏幕上 curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); if ($useCert == true) { //设置证书 //使用证书:cert 与 key 分别属于两个.pem文件 curl_setopt($ch, CURLOPT_SSLCERTTYPE, 'PEM'); //curl_setopt($ch,CURLOPT_SSLCERT, WxPayConfig::SSLCERT_PATH); curl_setopt($ch, CURLOPT_SSLKEYTYPE, 'PEM'); //curl_setopt($ch,CURLOPT_SSLKEY, WxPayConfig::SSLKEY_PATH); } //post提交方式 curl_setopt($ch, CURLOPT_POST, TRUE); curl_setopt($ch, CURLOPT_POSTFIELDS, $xml); //运行curl $data = curl_exec($ch); //返回结果 if ($data) { curl_close($ch); return $data; } else { $error = curl_errno($ch); curl_close($ch); return false; } } //把对象转成数组 function object2array($array) { if (is_object($array)) { $array = (array)$array; } if (is_array($array)) { foreach ($array as $key => $value) { $array[$key] = $this->object2array($value); } } return $array; } //用户退出登录 function logError($object) { error_log(date("[Y-m-d H:i:s]") . " -[" . $_SERVER['REQUEST_URI'] . "] :" . $object . "/n", 3, "../php_err.log"); } }
app支付宝微信支付
猜你喜欢
转载自blog.csdn.net/qq_26959879/article/details/80064044
今日推荐
周排行