|
|
<?php
defined('IN_PHPCMS') or exit('No permission resources.');
if (isset($set_modules) && $set_modules == TRUE)
{
$i = isset($modules) ? count($modules) : 0;
$modules[$i]['code'] = basename(__FILE__, '.class.php');
$modules[$i]['name'] = L('weixinpay', '', 'pay');
$modules[$i]['desc'] = L('weixinpay_desc', '', 'pay');
$modules[$i]['is_cod'] = '0';
$modules[$i]['is_online'] = '1';
$modules[$i]['author'] = '易百讯开发团队';
$modules[$i]['website'] = 'http://www.yibaixun.com/';
$modules[$i]['version'] = '1.0.0';
$modules[$i]['config'] = array(
array('name' => 'weixinpay_appid','type' => 'text','value' => ''),
array('name' => 'weixinpay_appsecret','type' => 'text','value' => ''),
array('name' => 'weixinpay_mchid','type' => 'text','value' => ''),
array('name' => 'weixinpay_key','type' => 'text','value' => ''),
);
return;
}
pc_base::load_app_class('pay_abstract','','0');
// 开启session
$session_storage = 'session_'.pc_base::load_config('system','session_storage');
pc_base::load_sys_class($session_storage);
class Weixinpay extends paymentabstract{
public function __construct($config = array()) {
if (!empty($config)) $this->set_config($config);
$this->config['return_url'] = return_url('Weixinpay'); //大写
$this->config['weixinpay_signtype'] = 'MD5';
}
public function getpreparedata() {
$prepare_data = array();
return $prepare_data;
}
public function get_code()
{
if (!defined('CHARSET'))
{
$charset = 'utf-8';
}
else
{
$charset = CHARSET;
}
$charset = strtoupper($charset);
//配置参数
$this->payments = $this->config ;//"Weixinpay";
//根目录url
$root_url = '/';
//查找openid
$account_db = pc_base::load_model('pay_account_model');
$member_db = pc_base::load_model('member_model');
$payorderinfo = $account_db->get_one(array('id'=> $this->order_info['id']), '`userid`');
$memberinfo = $member_db->get_one(array('userid'=> $payorderinfo['userid']), '`connectid`'); //这里需要获取会员的openid
//$openid = $memberinfo['connectid'];
$openid = $_SESSION['openid'];
if(empty($openid)){
echo "获取openid失败!";
//这个openid 需要预先获取 一般在网站入口那里 设置 :不存在openid 测请求 返回code 通过code 获取openid
}
$this->setParameter("openid",$openid);
//商品描述
$this->setParameter("body", $this->order_info['id']);
//商户订单号
$this->setParameter("out_trade_no", $this->order_info['id']);
//订单总金额
$this->setParameter("total_fee", $this->product_info['price'] * 100);
//支付币种
//$this->setParameter("fee_type", "1");
//通知URL
$this->setParameter("notify_url", $this->config['return_url']);
//订单生成的机器IP
$this->setParameter("spbill_create_ip", ip());
//传入参数字符编码
$this->setParameter("input_charset", $charset);
//交易类型
$this->setParameter("trade_type","JSAPI");
$prepay_id = $this->getPrepayId();
$this->setPrepayId($prepay_id);
// 为微信支付返回不能带参数 只能伪静态
// echo $this->config['return_url'];
$jsapi = $this->getParameters();
$price = $this->product_info['price'];
// print_r(json_decode($jsapi,true));
//wxjsbridge
$html = <<<EOF
<html> <head><title>微信支付</title> </head>
<body style="display: flex;
justify-content:center;
align-items: center; width: 100%;">
<br/>
<div align="center" style="width:100%; display: block;" >
<font color="#9ACD32"><b>该笔订单支付金额为<span style="color:#f00;font-size:50px"> $price </span>元</b></font><br/><br/>
<button style="width:90%; height:100px; line-height: 100px; border-radius:5px;background-color:#00b43c; border:0px #00b43c solid; cursor: pointer; color:white; font-size:36px;" type="button"color:#34b434;font-style:italic;">callpay()" >立即支付</button>
</div>
</body>
</html>
<script type="text/javascript">
//调用微信JS api 支付
function jsApiCall()
{
WeixinJSBridge.invoke(
'getBrandWCPayRequest',$jsapi,
function(res){
WeixinJSBridge.log(res.err_msg);
if(res.err_msg == "get_brand_wcpay_request k") {
location.href='/index.php?m=member';
}else{
alert(res.err_code+res.err_desc+res.err_msg);
}
}
);
}
function callpay()
{
if (typeof WeixinJSBridge == "undefined"){
if( document.addEventListener ){
document.addEventListener('WeixinJSBridgeReady', jsApiCall, false);
}else if (document.attachEvent){
document.attachEvent('WeixinJSBridgeReady', jsApiCall);
document.attachEvent('onWeixinJSBridgeReady', jsApiCall);
}
}else{
jsApiCall();
}
}
callpay();
</script>
EOF;
$button = $html;
return $button;
}
/**
* 客户端接收数据
* 状态码说明 (0 交易完成 1 交易失败 2 交易超时 3 交易处理中 4 交易未支付)
*
*
*
* 执行日期:2016-11-18-00:37:17
【接收到的notify通知】:
<xml><appid><![CDATA[wxe3d0167cf9c9fbb2]]></appid>
<attach><![CDATA[10]]></attach>
<bank_type><![CDATA[CFT]]></bank_type>
<cash_fee><![CDATA[2]]></cash_fee>
<fee_type><![CDATA[CNY]]></fee_type>
<is_subscribe><![CDATA[Y]]></is_subscribe>
<mch_id><![CDATA[1383733802]]></mch_id>
<nonce_str><![CDATA[s4l9wggn9dxx356pie7jguv0mahu8fbq]]></nonce_str>
<openid><![CDATA[oudtvwBsblPqpKiGPSi-2qaPsm30]]></openid>
<out_trade_no><![CDATA[14794006211967]]></out_trade_no>
<result_code><![CDATA[SUCCESS]]></result_code>
<return_code><![CDATA[SUCCESS]]></return_code>
<sign><![CDATA[51520F6851E5CC3B46F37D7CA8A22898]]></sign>
<time_end><![CDATA[20161118003718]]></time_end>
<total_fee>2</total_fee>
<trade_type><![CDATA[JSAPI]]></trade_type>
<transaction_id><![CDATA[4002572001201611180049986614]]></transaction_id>
</xml>
*
*
*/
public function receive() {
//获取通知的数据
$xml = $GLOBALS['HTTP_RAW_POST_DATA'];
//$xml = file_get_contents('php://input');
$postdata=$this->xmlToArray($xml);
//$this->logResult("log::respond::postdata:",$postdata);
$wxsign = $postdata['sign'];
$this->payments = $this->config ;// 同步系统配置参数
//排除无关的sign
unset($postdata['sign']);
$sign = $this->getSign($postdata);
$return_data['order_status'] = 5; //必要参数
$sinarr = array('wxsign'=>$wxsign,'sign'=>$sign,'key'=>$this->payments['weixinpay_key']);
$this->logResult("log::respond::sign_pk_data:",$sinarr);
//先不比对签名
if ($wxsign == $sign) {
// 交易成功
if ($postdata['result_code'] == 'SUCCESS') {
// 获取out_trade_no 传过去的订单号
$return_data['order_id'] = $postdata['out_trade_no']; //必要参数
$return_data['order_status'] = 0;
// $this->logResult("log::respond::success_data:",$return_data);
$returndata['return_code'] = 'SUCCESS';
//order_paid($order_sn, 2);
}
} else {
$return_data['order_status'] = 5;
$returndata['return_code'] = 'FAIL';
$returndata['return_msg'] = '签名失败';
}
return $return_data;
}
/**
* 相应服务器应答状态
* @param $result
*/
public function response($result) {
if (FALSE == $result) echo 'ok';
else echo 'success';
}
/**
* 返回字符过滤
* @param $parameter
*/
private function filterParameter($parameter)
{
$para = array();
foreach ($parameter as $key => $value)
{
if ('sign' == $key || 'sign_type' == $key || '' == $value || 'm' == $key || 'a' == $key || 'c' == $key || 'code' == $key ) continue;
else $para[$key] = $value;
}
return $para;
}
// 设置请求参数
function setParameter($parameter, $parameterValue) {
$this->parameters[$this->trimString($parameter)] = $this->trimString($parameterValue);
}
// 设置参数时需要用到的字符处理函数
function trimString($value){
$ret = null;
if (null != $value) {
$ret = $value;
if (strlen($ret) == 0) {
$ret = null;
}
}
return $ret;
}
//生成随机数
function create_noncestr( $length = 32 ) {
$chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
$str ="";
for ( $i = 0; $i < $length; $i++ ) {
$str.= substr($chars, mt_rand(0, strlen($chars)-1), 1);
}
return $str;
}
// 获取prepay_id
function getPrepayId()
{
$this->postXml();
$this->result = $this->xmlToArray($this->response);
$prepay_id = $this->result["prepay_id"];
return $prepay_id;
}
// post请求xml
function postXml()
{
$xml = $this->createXml();
$this->response = $this->postXmlCurl($xml,'https://api.mch.weixin.qq.com/pay/unifiedorder','30');
//var_dump($this->response);
return $this->response;
}
// 设置标配的请求参数,生成签名,生成接口参数xml
function createXml()
{
$this->parameters["appid"] = $this->payments['weixinpay_appid'];//公众账号ID
$this->parameters["mch_id"] = $this->payments['weixinpay_mchid'];//商户号
$this->parameters["nonce_str"] = $this->create_noncestr();//随机字符串
$this->parameters["sign"] = $this->getSign($this->parameters);//签名
//print_r($this->parameters);
return $this->arrayToXml($this->parameters);
}
function xmlToArray($xml)
{
//将XML转为array
$array_data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
return $array_data;
}
function arrayToXml($arr)
{
$xml = "<xml>";
foreach ($arr as $key=>$val)
{
if (is_numeric($val))
{
$xml.="<".$key.">".$val."</".$key.">";
}
else
$xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
}
$xml.="</xml>";
return $xml;
}
/**
* @brief 从xml到array转换数据格式
* @param xml $xmlData
* @return array
*/
private function converArray($xmlData)
{
$result = array();
$xmlHandle = xml_parser_create();
xml_parse_into_struct($xmlHandle, $xmlData, $resultArray);
foreach($resultArray as $key => $val)
{
if($val['tag'] != 'XML')
{
$result[$val['tag']] = $val['value'];
}
}
return array_change_key_case($result);
}
function postXmlCurl($xml,$url,$second=30)
{
//初始化curl
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL, $url);
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE);
curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,FALSE);
//设置header
curl_setopt($ch, CURLOPT_HEADER, FALSE);
//要求结果为字符串且输出到屏幕上
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
//post提交方式
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
//运行curl
$data = curl_exec($ch);
curl_close($ch);
//var_dump($data);
if($data)
{
//curl_close($ch);
return $data;
}
else
{
$error = curl_errno($ch);
echo "curl出错,错误码:$error"."<br>";
echo "<a href='http://curl.haxx.se/libcurl/c/libcurl-errors.html'>错误原因查询</a></br>";
curl_close($ch);
return false;
}
}
// 作用:生成签名
public function getSign($Obj)
{
foreach ($Obj as $k => $v)
{
$Parameters[$k] = $v;
}
//签名步骤一:按字典序排序参数
ksort($Parameters);
$String = $this->formatBizQueryParaMap($Parameters, false);
//echo '【string1】'.$String.'</br>';
//签名步骤二:在string后加入KEY
$String = $String."&key=".$this->payments['weixinpay_key'];
//echo "【string2】".$String."</br>";
//签名步骤三:MD5加密
$String = md5($String);
//echo "【string3】 ".$String."</br>";
//签名步骤四:所有字符转为大写
$result_ = strtoupper($String);
//echo "【result】 ".$result_."</br>";
return $result_;
}
/**
* 格式化参数,签名过程需要使用
*/
function formatBizQueryParaMap($paraMap, $urlencode)
{
$buff = "";
ksort($paraMap);
foreach ($paraMap as $k => $v)
{
if($urlencode)
{
$v = urlencode($v);
}
//$buff .= strtolower($k) . "=" . $v . "&";
$buff .= $k . "=" . $v . "&";
}
$reqPar;
if (strlen($buff) > 0)
{
$reqPar = substr($buff, 0, strlen($buff)-1);
}
return $reqPar;
}
function setPrepayId($prepayId)
{
$this->prepay_id = $prepayId;
}
/**
* 设置jsapi的参数
*/
function getParameters()
{
$jsApiObj["appId"] = $this->payments['weixinpay_appid'];
$timeStamp = time();
$jsApiObj["timeStamp"] = "$timeStamp";
$jsApiObj["nonceStr"] = $this->create_noncestr();
$jsApiObj["package"] = "prepay_id=$this->prepay_id";
$jsApiObj["signType"] = $this->payments['weixinpay_signtype'];
$jsApiObj["paySign"] = $this->getSign($jsApiObj);
$this->parameters = json_encode($jsApiObj);
return $this->parameters;
}
//增加
function logResult($word = '',$var=array()) {
$output= strftime("%Y%m%d %H:%M:%S", time()) . "\n" ;
$output .= $word."\n" ;
if(!empty($var)){
$output .= print_r($var, true)."\n";
}
$output.="\n";
$log_path=PHPCMS_PATH . "/log/";
if(!is_dir($log_path)){
@mkdir($log_path, 0777, true);
}
file_put_contents($log_path."weixin.txt", $output, FILE_APPEND | LOCK_EX);
}
}
?>
|
|