微信支付签名函数-简单方便

在php使用微信支付的时候,你会发现微信支付自带的API 十分复杂,其实是一个很简单的东西,程序员却装装13,弄得这么复杂,经过本人看代码,把微信支付相关过程简化出来,希望给有需要用的人用上。www.yiyou.org

<?php
/*
 * 生成微信支付签名
 * $input 输入参数格式 array('appid'=>'2323232','mch_id'=>'2222')
 * $secret  支付密钥,这个是自己设的,具体看微信api
 */
function weixin_sign($input,$secret){
    $para_filter=  wx_paraFilter($input);
    $para_sort = wx_argSort($para_filter); //参数排序
    $prestr = wx_createLinkstring($para_sort); ////把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串
    $mysign = strtoupper(md5($prestr.'&key='.$secret));  //签名
    return $mysign;
}
/**
 * 除去数组中的空值和签名参数
 * @param $para 签名参数组
 * return 去掉空值与签名参数后的新签名参数组
 */
function wx_paraFilter($para) {
	$para_filter = array();
	while (list ($key, $val) = each ($para)) {
		if($key == "sign" || $key == "sign_type" || $val == "")continue;
		else	$para_filter[$key] = $para[$key];
	}
	return $para_filter;
}
/**
 * 对数组排序
 * @param $para 排序前的数组
 * return 排序后的数组
 */
function wx_argSort($para) {
	ksort($para);
	reset($para);
	return $para;
}
function wx_createLinkstring($para) {
	$arg  = "";
	while (list ($key, $val) = each ($para)) {
		$arg.=$key."=".$val."&";
	}
	//去掉最后一个&字符
	$arg = substr($arg,0,count($arg)-2);
	
	//如果存在转义字符,那么去掉转义
	if(get_magic_quotes_gpc()){$arg = stripslashes($arg);}
	
	return $arg;
}
function to_xml($arr_data){
    $xml = "<xml>";
    foreach ($arr_data as $key=>$val)
    {
            if (is_numeric($val)){
                    $xml.="<".$key.">".$val."</".$key.">";
            }else{
                    $xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
            }
    }
    $xml.="</xml>";
    return $xml;
}
function xml2array($xml){
    libxml_disable_entity_loader(true);
    $data=json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
    return $data;
}
function nonce_str(){
    return md5(md5(time()).mt_rand(0, 100));
}
function http_request_xml($url, $postdata = null,$useCert=false){
    #$data = http_build_query($postdata);
    //echo ROOT_PATH.'/Libs/weixinapi/cert/apiclient_cert.pem';
    if(function_exists('curl_exec')){
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            if($postdata){
                curl_setopt($ch, CURLOPT_POST, 1);
                curl_setopt($ch, CURLOPT_POSTFIELDS, $postdata);

            }else{
                curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
                curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
            }
            if($useCert == true){
			//设置证书
			//使用证书:cert 与 key 分别属于两个.pem文件
			curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
			curl_setopt($ch,CURLOPT_SSLCERT, ROOT_PATH.'/Libs/weixinapi/cert/apiclient_cert.pem');
			curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
			curl_setopt($ch,CURLOPT_SSLKEY,ROOT_PATH.'/Libs/weixinapi/cert/apiclient_key.pem');  
            }
            $data = curl_exec($ch);
            if( curl_errno ( $ch )){
                echo  'Curl error: '  .  curl_error ( $ch );
            }
            curl_close($ch);
    }else{
            if($postdata){
                    $url = $url.'?'.$postdata;
                    $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);
                    $data = file_get_contents($url, false, $context);
            }else{
                $ctx = stream_context_create(array( 
                        'http' => array( 
                        'timeout' => 5 //设置一个超时时间,单位为秒 
                        ))); 
                $data=file_get_contents($url, 0, $ctx); 
            }
    }
    return $data;
}

因为我的微信是在框架内使用的,其中有一些变量要注意一下,ROOT_PATH是一个绝对路径,这个地方可以改改。调用办法

function wxpay($order){
        /*
         * 微信支付统一下单接口
         * https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_1
         */
        $body='付款';
        if($order['type']==2){
            $body='打赏楼主';
        }
        $parames=array(
            'appid'=> $this->APPID,
            'mch_id'=>  $this->MCHID,
            'nonce_str'=>  nonce_str(),
            'body'=>$body,
            'out_trade_no'=>$order['orderid'],
            'total_fee'=>$order['total_money']*100,  //单位分
            'spbill_create_ip'=>$_SERVER['REMOTE_ADDR'],
            'notify_url'=>  get_siteurl().'/jrmmpay/notify',
        );
        if(is_weixin()){  //在微信内部
            $parames['trade_type']='JSAPI';
            $parames['openid']=  $this->get_openid();
        }else{
            $parames['trade_type']='NATIVE';
             $parames['product_id']=$order['id'];
        }
        
        $parames['sign'] = weixin_sign($parames, $this->PAYKEY);   //加入排序
        
        $xml = to_xml($parames);
        //print_r($xml);exit;
        $respon=http_request_xml('https://api.mch.weixin.qq.com/pay/unifiedorder',$xml);

        $data=  xml2array($respon);
        //print_r($data);
        if($data['result_code']=='FAIL'){
            //查成功
            header('Content-Type: text/html; charset=UTF-8');
            echo $data['err_code_des'];exit;
        }
        
        if(is_weixin()){
            $param=array(
              'appId'=> $this->APPID,
               'timeStamp'=>  '"'.time().'"',
               'nonceStr'=>  nonce_str(),
               'package'=>'prepay_id='.$data['prepay_id'],
               'signType'=>"MD5",

           );

            $param['paySign'] = weixin_sign($param, $this->PAYKEY);   
           $this->tpl->assign('param',  json_encode($param));
           $this->tpl->assign('order',$order);
            $this->tpl->draw('payment/weixinjsapi');
        }else{
            echo "<img width=\"400\" height=\"400\" src=\"?app=payment&act=qrcode&data=".  urlencode($data['code_url'])."\">";
        }

        
    }
 /*
 * 生成二维码图片
 */
 function qrcode(){
 require_once ROOT_PATH.'Libs/weixinapi/phpqrcode/phpqrcode.php';
 $url = urldecode($_GET["data"]);
 QRcode::png($url,FALSE,QR_ECLEVEL_L,11);
 }

上面的函数已经装扫码支付和普通支付集成在一起了。

下面是js API调用

<!DOCTYPE html>
<html>
    <head>
        <title>正在进行支付</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <script type="text/javascript">
        function onBridgeReady(){
           WeixinJSBridge.invoke(
               'getBrandWCPayRequest', {$param},
               function(res){     
                   //alert('{$param}');
                   if(res.err_msg == "get_brand_wcpay_request:ok" ) {
                       //window.location.href='/jinrimaoming.php?app=index&act=view2&id={$order.articleid}';
                       alert('ok');
                   }else{
                      // window.location.href='/jinrimaoming.php?app=index&act=view2&id={$order.articleid}';
                      alert('fail');
                   }
               }
           );
        }
        window.onload = function(){
            if (typeof WeixinJSBridge == "undefined"){
               if( document.addEventListener ){
                   document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
               }else if (document.attachEvent){
                   document.attachEvent('WeixinJSBridgeReady', onBridgeReady); 
                   document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
               }
            }else{
               onBridgeReady();
            }            
    }    
    </script>
    </head>
    <body>
        <div>支付正在进行中...</div>
    </body>
</html>