当前位置 : 主页 > 网络编程 > PHP >

wemall开源版微商城代码片段--微信公众号支付接口

来源:互联网 收集:自由互联 发布时间:2021-06-30
简介 ============================================ 接口名称:微信公众号支付接口 版本:V3.3 开发语言:PHP ======== 配置说明 =========================================== 1.【基本信息设置】 商户向微信提交
简介
============================================
接口名称:微信公众号支付接口
版本:V3.3
开发语言:PHP

========
配置说明
===========================================

1.【基本信息设置】
商户向微信提交企业以及银行账户资料,商户功能审核通过后,可以获得帐户基本信息,找到本例程的配置文件「WxPay.pub.config.php」,配置好如下信息:
  appId:微信公众号身份的唯一标识。审核通过后,在微信发送的邮件中查看。
  Mchid:受理商ID,身份标识
  Key:商户支付密钥Key。审核通过后,在微信发送的邮件中查看。
  Appsecret:JSAPI接口中获取openid,审核后在公众平台开启开发模式后可查看。

2.【native支付链接设置】
native支付中,用户扫码后调微信会将productid和用户openid发送到商户设置的链接上,确保该链接与实际服务路径一致。本例程的响应服务为「./demo/native_call.php」

3.【JSAPI路径设置】
通过JSAPI发起支付的代码应该放置在商户设置的「支付授权目录」中。
并找到本例程的配置文件「WxPay.pub.config.php」,配置正确的路径。

4.【证书路径设置】
找到本例程的配置文件「WxPay.pub.config.php」,配置证书路径。

5.【异步通知url设置】
找到本例程的配置文件「WxPay.pub.config.php」,配置异步通知url。

6.【必须开启curl服务】
使用Crul需要修改服务器中php.ini文件的设置,找到php_curl.dll去掉前面的";"即可。

7.【设置curl超时时间】
本例程通过curl使用HTTP POST方法,此处可修改其超时时间,默认为30秒。找到本例程的配置文件「WxPay.pub.config.php」,配置curl超时时间。

============
代码文件结构
===========================================
wxpay_php
|-- README.txt---------------------使用说明文本
|-- WxPayHelper--------------------微信支付类库及常用文件
|   |-- SDKRuntimeException.php----异常处理类
|   |-- WxPay.pub.config.php-----------商户配置文件
|   `-- WxPayPubHelper.php------------微信支付类库
|-- demo---------------------------例程
|   |-- js_api_call.php------------JSAPI支付例程
|   |-- native_call_qrcode.php-----native支付静态链接二维码例程
|   |-- native_call.php------------native支付后台响应例程
|   |-- native_call.log------------native支付后台响应日志
|   |-- native_dynamic_qrcode.php--native支付动态链接二维码例程
|   |-- notify_url.php-------------支付结果异步通知例程
|   |-- notify_url.log-------------支付结果异步通知日志
|   |-- order_query.php------------订单查询例程
|   |-- refund.php-----------------退款例程
|   |-- download_bill.php----------对账单例程
|   |-- refund_query.php-----------退款查询例程
|   |-- log_.php-------------------日志类
|   `-- qrcode.js------------------二维码生成工具
`-- index.php

==============
微信支付帮助sdk
====================================================
1.每一个接口对应一个类。
2.常用工具(产生随机字符串、生成签名、以post方式提交xml、证书的使用等)封装成CommonUtil类。
3.接口分三种类型:请求型接口、响应型接口、其他。请求型接口是将参数封装成xml,以post方式提交到微信,微信响应结果;响应型接口则是响应微信的post请求。Wxpay_client_是请求型接口的基类。Wxpay_server_是响应型接口的基类。Wxpay_client_、Wxpay_server_都继承CommonUtil类
4.结构明细
【常用工具】--CommonUtil
    trimString(),设置参数时需要用到的字符处理函数
    createNoncestr(),产生随机字符串,不长于32位
    formatBizQueryParaMap(),格式化参数,签名过程需要用到
    getSign(),生成签名
    arrayToXml(),array转xml
    xmlToArray(),xml转 array
    postXmlCurl(),以post方式提交xml到对应的接口url
    postXmlSSLCurl(),使用证书,以post方式提交xml到对应的接口url
【请求型接口】--Wxpay_client_
    统一支付接口----UnifiedOrder
    订单查询接口----OrderQuery
    退款申请接口----Refund
    退款查询接口----RefundQuery
    对账单接口------DownloadBill
    短链接转换接口--ShortUrl
【响应型接口】--Wxpay_server_
    通用通知接口----Notify
    Native支付——请求商家获取商品信息接口--NativeCall
【其他】
    静态链接二维码--NativeLink
    JSAPI支付-------JsApi

1. [代码][PHP]代码    

作者官网:www.wemallshop.com

2. [代码]SDKRuntimeException.php    

<?php
class  SDKRuntimeException extends Exception {
	public function errorMessage()
	{
		return $this->getMessage();
	}
}
?>

3. [代码]WxPay.pub.config.php    

<?php
/**
* 	配置账号信息
*/
class WxPayConf_pub
{
	//=======【基本信息设置】=====================================
	//微信公众号身份的唯一标识。审核通过后,在微信发送的邮件中查看
	const APPID = '';
	//受理商ID,身份标识
	const MCHID = '';
	//商户支付密钥Key。审核通过后,在微信发送的邮件中查看
	const KEY = '';
	//JSAPI接口中获取openid,审核后在公众平台开启开发模式后可查看
	const APPSECRET = '';
	
	//=======【JSAPI路径设置】===================================
	//获取access_token过程中的跳转uri,通过跳转将code传入jsapi支付页面
	const JS_API_CALL_URL = '';
	
	//=======【证书路径设置】=====================================
	//证书路径,注意应该填写绝对路径
	const SSLCERT_PATH = '';
	const SSLKEY_PATH = '';
	
	//=======【异步通知url设置】===================================
	//异步通知url,商户根据实际开发过程设定
	const NOTIFY_URL = '';
	//=======【curl超时设置】===================================
	//本例程通过curl使用HTTP POST方法,此处可修改其超时时间,默认为30秒
	const CURL_TIMEOUT = 30;
}
	
?>

4. [代码]WxPayPubHelper.php    

<?php
/**
 * 微信支付帮助库
 * ====================================================
 * 接口分三种类型:
 * 【请求型接口】--Wxpay_client_
 * 		统一支付接口类--UnifiedOrder
 * 		订单查询接口--OrderQuery
 * 		退款申请接口--Refund
 * 		退款查询接口--RefundQuery
 * 		对账单接口--DownloadBill
 * 		短链接转换接口--ShortUrl
 * 【响应型接口】--Wxpay_server_
 * 		通用通知接口--Notify
 * 		Native支付——请求商家获取商品信息接口--NativeCall
 * 【其他】
 * 		静态链接二维码--NativeLink
 * 		JSAPI支付--JsApi
 * =====================================================
 * 【CommonUtil】常用工具:
 * 		trimString(),设置参数时需要用到的字符处理函数
 * 		createNoncestr(),产生随机字符串,不长于32位
 * 		formatBizQueryParaMap(),格式化参数,签名过程需要用到
 * 		getSign(),生成签名
 * 		arrayToXml(),array转xml
 * 		xmlToArray(),xml转 array
 * 		postXmlCurl(),以post方式提交xml到对应的接口url
 * 		postXmlSSLCurl(),使用证书,以post方式提交xml到对应的接口url
*/
	include_once("SDKRuntimeException.php");
	include_once("WxPay.pub.config.php");
/**
 * 所有接口的基类
 */
class Common_util_pub
{
	function __construct() {
	}
	function trimString($value)
	{
		$ret = null;
		if (null != $value) 
		{
			$ret = $value;
			if (strlen($ret) == 0) 
			{
				$ret = null;
			}
		}
		return $ret;
	}
	
	/**
	 * 	作用:产生随机字符串,不长于32位
	 */
	public function createNoncestr( $length = 32 ) 
	{
		$chars = "abcdefghijklmnopqrstuvwxyz0123456789";  
		$str ="";
		for ( $i = 0; $i < $length; $i++ )  {  
			$str.= substr($chars, mt_rand(0, strlen($chars)-1), 1);  
		}  
		return $str;
	}
	
	/**
	 * 	作用:格式化参数,签名过程需要使用
	 */
	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;
	}
	
	/**
	 * 	作用:生成签名
	 */
	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=".WxPayConf_pub::KEY;
		//echo "【string2】".$String."</br>";
		//签名步骤三:MD5加密
		$String = md5($String);
		//echo "【string3】 ".$String."</br>";
		//签名步骤四:所有字符转为大写
		$result_ = strtoupper($String);
		//echo "【result】 ".$result_."</br>";
		return $result_;
	}
	
	/**
	 * 	作用:array转xml
	 */
	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; 
    }
	
	/**
	 * 	作用:将xml转为array
	 */
	public function xmlToArray($xml)
	{		
        //将XML转为array        
        $array_data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);		
		return $array_data;
	}
	/**
	 * 	作用:以post方式提交xml到对应的接口url
	 */
	public function postXmlCurl($xml,$url,$second=30)
	{		
        //初始化curl        
       	$ch = curl_init();
		//设置超时
		curl_setopt($ch, CURLOP_TIMEOUT, $second);
        //这里设置代理,如果有的话
        //curl_setopt($ch,CURLOPT_PROXY, '8.8.8.8');
        //curl_setopt($ch,CURLOPT_PROXYPORT, 8080);
        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);
		//返回结果
		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;
		}
	}
	/**
	 * 	作用:使用证书,以post方式提交xml到对应的接口url
	 */
	function postXmlSSLCurl($xml,$url,$second=30)
	{
		$ch = curl_init();
		//超时时间
		curl_setopt($ch,CURLOPT_TIMEOUT,$second);
		//这里设置代理,如果有的话
        //curl_setopt($ch,CURLOPT_PROXY, '8.8.8.8');
        //curl_setopt($ch,CURLOPT_PROXYPORT, 8080);
        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);
		//设置证书
		//使用证书:cert 与 key 分别属于两个.pem文件
		//默认格式为PEM,可以注释
		curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
		curl_setopt($ch,CURLOPT_SSLCERT, WxPayConf_pub::SSLCERT_PATH);
		//默认格式为PEM,可以注释
		curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
		curl_setopt($ch,CURLOPT_SSLKEY, WxPayConf_pub::SSLKEY_PATH);
		//post提交方式
		curl_setopt($ch,CURLOPT_POST, true);
		curl_setopt($ch,CURLOPT_POSTFIELDS,$xml);
		$data = curl_exec($ch);
		//返回结果
		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;
		}
	}
	
	/**
	 * 	作用:打印数组
	 */
	function printErr($wording='',$err='')
	{
		print_r('<pre>');
		echo $wording."</br>";
		var_dump($err);
		print_r('</pre>');
	}
}
/**
 * 请求型接口的基类
 */
class Wxpay_client_pub extends Common_util_pub 
{
	var $parameters;//请求参数,类型为关联数组
	public $response;//微信返回的响应
	public $result;//返回参数,类型为关联数组
	var $url;//接口链接
	var $curl_timeout;//curl超时时间
	
	/**
	 * 	作用:设置请求参数
	 */
	function setParameter($parameter, $parameterValue)
	{
		$this->parameters[$this->trimString($parameter)] = $this->trimString($parameterValue);
	}
	
	/**
	 * 	作用:设置标配的请求参数,生成签名,生成接口参数xml
	 */
	function createXml()
	{
	   	$this->parameters["appid"] = WxPayConf_pub::APPID;//公众账号ID
	   	$this->parameters["mch_id"] = WxPayConf_pub::MCHID;//商户号
	    $this->parameters["nonce_str"] = $this->createNoncestr();//随机字符串
	    $this->parameters["sign"] = $this->getSign($this->parameters);//签名
	    return  $this->arrayToXml($this->parameters);
	}
	
	/**
	 * 	作用:post请求xml
	 */
	function postXml()
	{
	    $xml = $this->createXml();
		$this->response = $this->postXmlCurl($xml,$this->url,$this->curl_timeout);
		return $this->response;
	}
	
	/**
	 * 	作用:使用证书post请求xml
	 */
	function postXmlSSL()
	{	
	    $xml = $this->createXml();
		$this->response = $this->postXmlSSLCurl($xml,$this->url,$this->curl_timeout);
		return $this->response;
	}
	/**
	 * 	作用:获取结果,默认不使用证书
	 */
	function getResult() 
	{		
		$this->postXml();
		$this->result = $this->xmlToArray($this->response);
		return $this->result;
	}
}
/**
 * 统一支付接口类
 */
class UnifiedOrder_pub extends Wxpay_client_pub
{	
	function __construct() 
	{
		//设置接口链接
		$this->url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
		//设置curl超时时间
		$this->curl_timeout = WxPayConf_pub::CURL_TIMEOUT;
	}
	
	/**
	 * 生成接口参数xml
	 */
	function createXml()
	{
		try
		{
			//检测必填参数
			if($this->parameters["out_trade_no"] == null) 
			{
				throw new SDKRuntimeException("缺少统一支付接口必填参数out_trade_no!"."<br>");
			}elseif($this->parameters["body"] == null){
				throw new SDKRuntimeException("缺少统一支付接口必填参数body!"."<br>");
			}elseif ($this->parameters["total_fee"] == null ) {
				throw new SDKRuntimeException("缺少统一支付接口必填参数total_fee!"."<br>");
			}elseif ($this->parameters["notify_url"] == null) {
				throw new SDKRuntimeException("缺少统一支付接口必填参数notify_url!"."<br>");
			}elseif ($this->parameters["trade_type"] == null) {
				throw new SDKRuntimeException("缺少统一支付接口必填参数trade_type!"."<br>");
			}elseif ($this->parameters["trade_type"] == "JSAPI" &&
				$this->parameters["openid"] == NULL){
				throw new SDKRuntimeException("统一支付接口中,缺少必填参数openid!trade_type为JSAPI时,openid为必填参数!"."<br>");
			}
		   	$this->parameters["appid"] = WxPayConf_pub::APPID;//公众账号ID
		   	$this->parameters["mch_id"] = WxPayConf_pub::MCHID;//商户号
		   	$this->parameters["spbill_create_ip"] = $_SERVER['REMOTE_ADDR'];//终端ip	    
		    $this->parameters["nonce_str"] = $this->createNoncestr();//随机字符串
		    $this->parameters["sign"] = $this->getSign($this->parameters);//签名
		    return  $this->arrayToXml($this->parameters);
		}catch (SDKRuntimeException $e)
		{
			die($e->errorMessage());
		}
	}
	
	/**
	 * 获取prepay_id
	 */
	function getPrepayId()
	{
		$this->postXml();
		$this->result = $this->xmlToArray($this->response);
		$prepay_id = $this->result["prepay_id"];
		return $prepay_id;
	}
	
}
/**
 * 订单查询接口
 */
class OrderQuery_pub extends Wxpay_client_pub
{
	function __construct() 
	{
		//设置接口链接
		$this->url = "https://api.mch.weixin.qq.com/pay/orderquery";
		//设置curl超时时间
		$this->curl_timeout = WxPayConf_pub::CURL_TIMEOUT;		
	}
	/**
	 * 生成接口参数xml
	 */
	function createXml()
	{
		try
		{
			//检测必填参数
			if($this->parameters["out_trade_no"] == null && 
				$this->parameters["transaction_id"] == null) 
			{
				throw new SDKRuntimeException("订单查询接口中,out_trade_no、transaction_id至少填一个!"."<br>");
			}
		   	$this->parameters["appid"] = WxPayConf_pub::APPID;//公众账号ID
		   	$this->parameters["mch_id"] = WxPayConf_pub::MCHID;//商户号
		    $this->parameters["nonce_str"] = $this->createNoncestr();//随机字符串
		    $this->parameters["sign"] = $this->getSign($this->parameters);//签名
		    return  $this->arrayToXml($this->parameters);
		}catch (SDKRuntimeException $e)
		{
			die($e->errorMessage());
		}
	}
}
/**
 * 退款申请接口
 */
class Refund_pub extends Wxpay_client_pub
{
	
	function __construct() {
		//设置接口链接
		$this->url = "https://api.mch.weixin.qq.com/secapi/pay/refund";
		//设置curl超时时间
		$this->curl_timeout = WxPayConf_pub::CURL_TIMEOUT;		
	}
	
	/**
	 * 生成接口参数xml
	 */
	function createXml()
	{
		try
		{
			//检测必填参数
			if($this->parameters["out_trade_no"] == null && $this->parameters["transaction_id"] == null) {
				throw new SDKRuntimeException("退款申请接口中,out_trade_no、transaction_id至少填一个!"."<br>");
			}elseif($this->parameters["out_refund_no"] == null){
				throw new SDKRuntimeException("退款申请接口中,缺少必填参数out_refund_no!"."<br>");
			}elseif($this->parameters["total_fee"] == null){
				throw new SDKRuntimeException("退款申请接口中,缺少必填参数total_fee!"."<br>");
			}elseif($this->parameters["refund_fee"] == null){
				throw new SDKRuntimeException("退款申请接口中,缺少必填参数refund_fee!"."<br>");
			}elseif($this->parameters["op_user_id"] == null){
				throw new SDKRuntimeException("退款申请接口中,缺少必填参数op_user_id!"."<br>");
			}
		   	$this->parameters["appid"] = WxPayConf_pub::APPID;//公众账号ID
		   	$this->parameters["mch_id"] = WxPayConf_pub::MCHID;//商户号
		    $this->parameters["nonce_str"] = $this->createNoncestr();//随机字符串
		    $this->parameters["sign"] = $this->getSign($this->parameters);//签名
		    return  $this->arrayToXml($this->parameters);
		}catch (SDKRuntimeException $e)
		{
			die($e->errorMessage());
		}
	}
	/**
	 * 	作用:获取结果,使用证书通信
	 */
	function getResult() 
	{		
		$this->postXmlSSL();
		$this->result = $this->xmlToArray($this->response);
		return $this->result;
	}
	
}
/**
 * 退款查询接口
 */
class RefundQuery_pub extends Wxpay_client_pub
{
	
	function __construct() {
		//设置接口链接
		$this->url = "https://api.mch.weixin.qq.com/pay/refundquery";
		//设置curl超时时间
		$this->curl_timeout = WxPayConf_pub::CURL_TIMEOUT;		
	}
	
	/**
	 * 生成接口参数xml
	 */
	function createXml()
	{		
		try 
		{
			if($this->parameters["out_refund_no"] == null &&
				$this->parameters["out_trade_no"] == null &&
				$this->parameters["transaction_id"] == null &&
				$this->parameters["refund_id "] == null) 
			{
				throw new SDKRuntimeException("退款查询接口中,out_refund_no、out_trade_no、transaction_id、refund_id四个参数必填一个!"."<br>");
			}
		   	$this->parameters["appid"] = WxPayConf_pub::APPID;//公众账号ID
		   	$this->parameters["mch_id"] = WxPayConf_pub::MCHID;//商户号
		    $this->parameters["nonce_str"] = $this->createNoncestr();//随机字符串
		    $this->parameters["sign"] = $this->getSign($this->parameters);//签名
		    return  $this->arrayToXml($this->parameters);
		}catch (SDKRuntimeException $e)
		{
			die($e->errorMessage());
		}
	}
	/**
	 * 	作用:获取结果,使用证书通信
	 */
	function getResult() 
	{		
		$this->postXmlSSL();
		$this->result = $this->xmlToArray($this->response);
		return $this->result;
	}
}
/**
 * 对账单接口
 */
class DownloadBill_pub extends Wxpay_client_pub
{
	function __construct() 
	{
		//设置接口链接
		$this->url = "https://api.mch.weixin.qq.com/pay/downloadbill";
		//设置curl超时时间
		$this->curl_timeout = WxPayConf_pub::CURL_TIMEOUT;		
	}
	/**
	 * 生成接口参数xml
	 */
	function createXml()
	{		
		try 
		{
			if($this->parameters["bill_date"] == null ) 
			{
				throw new SDKRuntimeException("对账单接口中,缺少必填参数bill_date!"."<br>");
			}
		   	$this->parameters["appid"] = WxPayConf_pub::APPID;//公众账号ID
		   	$this->parameters["mch_id"] = WxPayConf_pub::MCHID;//商户号
		    $this->parameters["nonce_str"] = $this->createNoncestr();//随机字符串
		    $this->parameters["sign"] = $this->getSign($this->parameters);//签名
		    return  $this->arrayToXml($this->parameters);
		}catch (SDKRuntimeException $e)
		{
			die($e->errorMessage());
		}
	}
	
	/**
	 * 	作用:获取结果,默认不使用证书
	 */
	function getResult() 
	{		
		$this->postXml();
		$this->result = $this->xmlToArray($this->result_xml);
		return $this->result;
	}
	
	
}
/**
 * 短链接转换接口
 */
class ShortUrl_pub extends Wxpay_client_pub
{
	function __construct() 
	{
		//设置接口链接
		$this->url = "https://api.mch.weixin.qq.com/tools/shorturl";
		//设置curl超时时间
		$this->curl_timeout = WxPayConf_pub::CURL_TIMEOUT;		
	}
	
	/**
	 * 生成接口参数xml
	 */
	function createXml()
	{		
		try 
		{
			if($this->parameters["long_url"] == null ) 
			{
				throw new SDKRuntimeException("短链接转换接口中,缺少必填参数long_url!"."<br>");
			}
		   	$this->parameters["appid"] = WxPayConf_pub::APPID;//公众账号ID
		   	$this->parameters["mch_id"] = WxPayConf_pub::MCHID;//商户号
		    $this->parameters["nonce_str"] = $this->createNoncestr();//随机字符串
		    $this->parameters["sign"] = $this->getSign($this->parameters);//签名
		    return  $this->arrayToXml($this->parameters);
		}catch (SDKRuntimeException $e)
		{
			die($e->errorMessage());
		}
	}
	
	/**
	 * 获取prepay_id
	 */
	function getShortUrl()
	{
		$this->postXml();
		$prepay_id = $this->result["short_url"];
		return $prepay_id;
	}
	
}
/**
 * 响应型接口基类
 */
class Wxpay_server_pub extends Common_util_pub 
{
	public $data;//接收到的数据,类型为关联数组
	var $returnParameters;//返回参数,类型为关联数组
	
	/**
	 * 将微信的请求xml转换成关联数组,以方便数据处理
	 */
	function saveData($xml)
	{
		$this->data = $this->xmlToArray($xml);
	}
	
	function checkSign()
	{
		$tmpData = $this->data;
		unset($tmpData['sign']);
		$sign = $this->getSign($tmpData);//本地签名
		if ($this->data['sign'] == $sign) {
			return TRUE;
		}
		return FALSE;
	}
	
	/**
	 * 获取微信的请求数据
	 */
	function getData()
	{		
		return $this->data;
	}
	
	/**
	 * 设置返回微信的xml数据
	 */
	function setReturnParameter($parameter, $parameterValue)
	{
		$this->returnParameters[$this->trimString($parameter)] = $this->trimString($parameterValue);
	}
	
	/**
	 * 生成接口参数xml
	 */
	function createXml()
	{
		return $this->arrayToXml($this->returnParameters);
	}
	
	/**
	 * 将xml数据返回微信
	 */
	function returnXml()
	{
		$returnXml = $this->createXml();
		return $returnXml;
	}
}
/**
 * 通用通知接口
 */
class Notify_pub extends Wxpay_server_pub 
{
}
/**
 * 请求商家获取商品信息接口
 */
class NativeCall_pub extends Wxpay_server_pub
{
	/**
	 * 生成接口参数xml
	 */
	function createXml()
	{
		if($this->returnParameters["return_code"] == "SUCCESS"){
		   	$this->returnParameters["appid"] = WxPayConf_pub::APPID;//公众账号ID
		   	$this->returnParameters["mch_id"] = WxPayConf_pub::MCHID;//商户号
		    $this->returnParameters["nonce_str"] = $this->createNoncestr();//随机字符串
		    $this->returnParameters["sign"] = $this->getSign($this->returnParameters);//签名
		}
		return $this->arrayToXml($this->returnParameters);
	}
	
	/**
	 * 获取product_id
	 */
	function getProductId()
	{
		$product_id = $this->data["product_id"];
		return $product_id;
	}
	
}
/**
 * 静态链接二维码
 */
class NativeLink_pub  extends Common_util_pub
{
	var $parameters;//静态链接参数
	var $url;//静态链接
	function __construct() 
	{
	}
	
	/**
	 * 设置参数
	 */
	function setParameter($parameter, $parameterValue) 
	{
		$this->parameters[$this->trimString($parameter)] = $this->trimString($parameterValue);
	}
	
	/**
	 * 生成Native支付链接二维码
	 */
	function createLink()
	{
		try 
		{		
			if($this->parameters["product_id"] == null) 
			{
				throw new SDKRuntimeException("缺少Native支付二维码链接必填参数product_id!"."<br>");
			}			
		   	$this->parameters["appid"] = WxPayConf_pub::APPID;//公众账号ID
		   	$this->parameters["mch_id"] = WxPayConf_pub::MCHID;//商户号
		   	$time_stamp = time();
		   	$this->parameters["time_stamp"] = "$time_stamp";//时间戳
		    $this->parameters["nonce_str"] = $this->createNoncestr();//随机字符串
		    $this->parameters["sign"] = $this->getSign($this->parameters);//签名    		
			$bizString = $this->formatBizQueryParaMap($this->parameters, false);
		    $this->url = "weixin://wxpay/bizpayurl?".$bizString;
		}catch (SDKRuntimeException $e)
		{
			die($e->errorMessage());
		}
	}
	
	/**
	 * 返回链接
	 */
	function getUrl() 
	{		
		$this->createLink();
		return $this->url;
	}
}
/**
* JSAPI支付——H5网页端调起支付接口
*/
class JsApi_pub extends Common_util_pub
{
	var $code;//code码,用以获取openid
	var $openid;//用户的openid
	var $parameters;//jsapi参数,格式为json
	var $prepay_id;//使用统一支付接口得到的预支付id
	var $curl_timeout;//curl超时时间
	function __construct() 
	{
		//设置curl超时时间
		$this->curl_timeout = WxPayConf_pub::CURL_TIMEOUT;
	}
	
	/**
	 * 	作用:生成可以获得code的url
	 */
	function createOauthUrlForCode($redirectUrl)
	{
		$urlObj["appid"] = WxPayConf_pub::APPID;
		$urlObj["redirect_uri"] = "$redirectUrl";
		$urlObj["response_type"] = "code";
		$urlObj["scope"] = "snsapi_base";
		$urlObj["state"] = "STATE"."#wechat_redirect";
		$bizString = $this->formatBizQueryParaMap($urlObj, false);
		return "https://open.weixin.qq.com/connect/oauth2/authorize?".$bizString;
	}
	/**
	 * 	作用:生成可以获得openid的url
	 */
	function createOauthUrlForOpenid()
	{
		$urlObj["appid"] = WxPayConf_pub::APPID;
		$urlObj["secret"] = WxPayConf_pub::APPSECRET;
		$urlObj["code"] = $this->code;
		$urlObj["grant_type"] = "authorization_code";
		$bizString = $this->formatBizQueryParaMap($urlObj, false);
		return "https://api.weixin.qq.com/sns/oauth2/access_token?".$bizString;
	}
	
	
	/**
	 * 	作用:通过curl向微信提交code,以获取openid
	 */
	function getOpenid()
	{
		$url = $this->createOauthUrlForOpenid();
        //初始化curl
       	$ch = curl_init();
		//设置超时
		curl_setopt($ch, CURLOP_TIMEOUT, $this->curl_timeout);
		curl_setopt($ch, CURLOPT_URL, $url);
        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,结果以jason形式返回
        $res = curl_exec($ch);
		curl_close($ch);
		//取出openid
		$data = json_decode($res,true);
		$this->openid = $data['openid'];
		return $this->openid;
	}
	/**
	 * 	作用:设置prepay_id
	 */
	function setPrepayId($prepayId)
	{
		$this->prepay_id = $prepayId;
	}
	/**
	 * 	作用:设置code
	 */
	function setCode($code_)
	{
		$this->code = $code_;
	}
	/**
	 * 	作用:设置jsapi的参数
	 */
	public function getParameters()
	{
		$jsApiObj["appId"] = WxPayConf_pub::APPID;
		$timeStamp = time();
	    $jsApiObj["timeStamp"] = "$timeStamp";
	    $jsApiObj["nonceStr"] = $this->createNoncestr();
		$jsApiObj["package"] = "prepay_id=$this->prepay_id";
	    $jsApiObj["signType"] = "MD5";
	    $jsApiObj["paySign"] = $this->getSign($jsApiObj);
	    $this->parameters = json_encode($jsApiObj);
		
		return $this->parameters;
	}
}
?>

5. [代码]download_bill.php    

<?php
/**
 * 对账单接口demo
 * ====================================================
 * 商户可以通过该接口下载历史交易清单。
*/
	include_once("../WxPayPubHelper/WxPayPubHelper.php");
	//对账单日期
	if (!isset($_POST["bill_date"])){
		$bill_date = "20140814";
	}
	else{
	    $bill_date = $_POST["bill_date"];
		
		//使用对账单接口
		$downloadBill = new DownloadBill_pub();
		//设置对账单接口参数
		//设置必填参数
		//appid已填,商户无需重复填写
		//mch_id已填,商户无需重复填写
		//noncestr已填,商户无需重复填写
		//sign已填,商户无需重复填写
		$downloadBill->setParameter("bill_date","$bill_date");//对账单日期 
		$downloadBill->setParameter("bill_type","ALL");//账单类型 
		//非必填参数,商户可根据实际情况选填
		//$downloadBill->setParameter("device_info","XXXX");//设备号  
		
		//对账单接口结果
		$downloadBillResult = $downloadBill->getResult();
		echo $downloadBillResult['return_code'];
		
		if ($downloadBillResult['return_code'] == "FAIL") {
			echo "通信出错:".$downloadBillResult['return_msg'];
		}else{
			 print_r('<pre>');
			 echo "【对账单详情】"."</br>";
			 print_r($downloadBill->response);
			 print_r('</pre>');
		}
	}
	
?>

<!DOCTYPE HTML>
<html>
<head>
	<meta charset="UTF-8">
	<title>微信安全支付</title>
</head>
<body>
	</br></br>
	<div align="center">
		<form  action="./download_bill.php" method="post">
			<p>对账单查询</p>
			<p>日期(格式:20140101): <input type="text" name="bill_date" value="<?php echo $bill_date; ?>"></p>
		    <button type="submit" >提交</button>
		</form>
		</br>

		<a href="../index.php">返回首页</a>

		</br></br>
		<?php
		?>
	</div>
</body>
</html>

6. [代码]index.php    

<!DOCTYPE HTML>
<html>
<head>
	<meta charset="UTF-8">
	<title>微信安全支付</title>
</head>
<body>
	</br></br>
	<div >
		<ul>
			<h1><a href="./js_api_call.php" >1.JSapi支付demo(在微信客户端中点击)</a></h1>
			<h1><a href="./native_call_qrcode.php" >2.native支付模式一demo(用微信扫的静态链接二维码)</a></h1>
			<h1><a href="./native_dynamic_qrcode.php" >3.native支付模式二demo(用微信扫的动态链接二维码)</a></h1>
			<h1><a href="./order_query.php" >4.支付查询接口demo</a></h1>
			<h1><a href="./download_bill.php" >5.对账单接口demo</a></h1>
			<h1><a href="./refund.php" >6.退款接口demo</a></h1>
			<h1><a href="./refund_query.php" >7.退款查询接口demo</a></h1>
		</ul>
	</div>
</body>
</html>

7. [代码]js_api_call.php    

<?php
/**
 * JS_API支付demo
 * ====================================================
 * 在微信浏览器里面打开H5网页中执行JS调起支付。接口输入输出数据格式为JSON。
 * 成功调起支付需要三个步骤:
 * 步骤1:网页授权获取用户openid
 * 步骤2:使用统一支付接口,获取prepay_id
 * 步骤3:使用jsapi调起支付
*/
	include_once("./WxPayPubHelper/WxPayPubHelper.php");
	
	//使用jsapi接口
	$jsApi = new JsApi_pub();
	//=========步骤1:网页授权获取用户openid============
	//通过code获得openid
	if (!isset($_GET['code']))
	{
		//触发微信返回code码
		$url = $jsApi->createOauthUrlForCode(WxPayConf_pub::JS_API_CALL_URL);
		Header("Location: $url"); 
	}else
	{
		//获取code码,以获取openid
	    $code = $_GET['code'];
		$jsApi->setCode($code);
		$openid = $jsApi->getOpenId();
	}
	
	//=========步骤2:使用统一支付接口,获取prepay_id============
	//使用统一支付接口
	$unifiedOrder = new UnifiedOrder_pub();
	
	//设置统一支付接口参数
	//设置必填参数
	//appid已填,商户无需重复填写
	//mch_id已填,商户无需重复填写
	//noncestr已填,商户无需重复填写
	//spbill_create_ip已填,商户无需重复填写
	//sign已填,商户无需重复填写
	$body = $_GET["body"];
	$out_trade_no = $_GET["orderid"];
	$total_fee = $_GET["totalprice"];
	$url = $_GET["url"];
	$unifiedOrder->setParameter("openid","$openid");//商品描述
	$unifiedOrder->setParameter("body","$body");//商品描述
	//自定义订单号,此处仅作举例
	// $timeStamp = time();
	// $out_trade_no = WxPayConf_pub::APPID."$timeStamp";
	$unifiedOrder->setParameter("out_trade_no","$out_trade_no");//商户订单号 
	$unifiedOrder->setParameter("total_fee","$total_fee");//总金额
	$unifiedOrder->setParameter("notify_url",WxPayConf_pub::NOTIFY_URL);//通知地址 
	$unifiedOrder->setParameter("trade_type","JSAPI");//交易类型
	
	//非必填参数,商户可根据实际情况选填
	//$unifiedOrder->setParameter("sub_mch_id","XXXX");//子商户号  
	//$unifiedOrder->setParameter("device_info","XXXX");//设备号 
	//$unifiedOrder->setParameter("attach","XXXX");//附加数据 
	//$unifiedOrder->setParameter("time_start","XXXX");//交易起始时间
	//$unifiedOrder->setParameter("time_expire","XXXX");//交易结束时间 
	//$unifiedOrder->setParameter("goods_tag","XXXX");//商品标记 
	//$unifiedOrder->setParameter("openid","XXXX");//用户标识
	//$unifiedOrder->setParameter("product_id","XXXX");//商品ID
	$prepay_id = $unifiedOrder->getPrepayId();
	//=========步骤3:使用jsapi调起支付============
	$jsApi->setPrepayId($prepay_id);
	$jsApiParameters = $jsApi->getParameters();
	//echo $jsApiParameters;
?>

<html>
<head>
    <meta http-equiv="content-type" content="text/html;charset=utf-8"/>
    <title>微信安全支付</title>

	<script type="text/javascript">
		//调用微信JS api 支付
		function jsApiCall()
		{
			WeixinJSBridge.invoke(
				'getBrandWCPayRequest',
				<?php echo $jsApiParameters; ?>,
				function(res){
					WeixinJSBridge.log(res.err_msg);
					// alert(res.err_code+res.err_desc+res.err_msg);
					if (res.err_msg == 'get_brand_wcpay_request:ok') {
						alert("支付成功!");
					}else if (res.err_msg == 'get_brand_wcpay_request:cancel') {
						alert("已取消支付!");
					}else if (res.err_msg == 'get_brand_wcpay_request:fail') {
						alert("支付失败!");
					};
					window.location.href = '<?php echo $url; ?>';
				}
			);
		}
		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>
</head>
<body>
</body>
</html>

8. [代码]log_.php    

<?php
class Log_
{
	// 打印log
	function  log_result($file,$word) 
	{
	    $fp = fopen($file,"a");
	    flock($fp, LOCK_EX) ;
	    fwrite($fp,"执行日期:".strftime("%Y-%m-%d-%H:%M:%S",time())."\n".$word."\n\n");
	    flock($fp, LOCK_UN);
	    fclose($fp);
	}
}
?>

9. [代码]native_call.php    

<?php
/**
 * Native(原生)支付模式一demo
 * ====================================================
 * 模式一:商户按固定格式生成链接二维码,用户扫码后调微信
 * 会将productid和用户openid发送到商户设置的链接上,商户收到
 * 请求生成订单,调用统一支付接口下单提交到微信,微信会返回
 * 给商户prepayid。
 * 本例程对应的二维码由native_call_qrcode.php生成;
 * 本例程对应的响应服务为native_call.php;
 * 需要两者配合使用。
 * 
*/
	include_once("./log_.php");
	include_once("../WxPayPubHelper/WxPayPubHelper.php");
	
	//以log文件形式记录回调信息,用于调试
	$log_ = new Log_();
	$log_name="./native_call.log";
    //使用native通知接口
	$nativeCall = new NativeCall_pub();
	//接收微信请求
	$xml = $GLOBALS['HTTP_RAW_POST_DATA'];
	$log_->log_result($log_name,"【接收到的native通知】:\n".$xml."\n");
	$nativeCall->saveData($xml);
	
	if($nativeCall->checkSign() == FALSE){
		$nativeCall->setReturnParameter("return_code","FAIL");//返回状态码
		$nativeCall->setReturnParameter("return_msg","签名失败");//返回信息
	}else{
	    //提取product_id
		$product_id = $nativeCall->getProductId();
		
		//使用统一支付接口
		$unifiedOrder = new UnifiedOrder_pub();
		
		//根据不同的$product_id设定对应的下单参数,此处只举例一种
		switch ($product_id) 
		{
			case WxPayConf_pub::APPID."static"://与native_call_qrcode.php中的静态链接二维码对应
				//设置统一支付接口参数
				//设置必填参数
				//appid已填,商户无需重复填写
				//mch_id已填,商户无需重复填写
				//noncestr已填,商户无需重复填写
				//spbill_create_ip已填,商户无需重复填写
				//sign已填,商户无需重复填写
				$unifiedOrder->setParameter("body","贡献一分钱");//商品描述
				//自定义订单号,此处仅作举例
				$timeStamp = time();
				$out_trade_no = WxPayConf_pub::APPID."$timeStamp";
				$unifiedOrder->setParameter("out_trade_no","$out_trade_no");//商户订单号 			$unifiedOrder->setParameter("product_id","$product_id");//商品ID
				$unifiedOrder->setParameter("total_fee","1");//总金额
				$unifiedOrder->setParameter("notify_url",WxPayConf_pub::NOTIFY_URL);//通知地址 
				$unifiedOrder->setParameter("trade_type","NATIVE");//交易类型
				$unifiedOrder->setParameter("product_id","$product_id");//用户标识
				//非必填参数,商户可根据实际情况选填
				//$unifiedOrder->setParameter("sub_mch_id","XXXX");//子商户号  
				//$unifiedOrder->setParameter("device_info","XXXX");//设备号 
				//$unifiedOrder->setParameter("attach","XXXX");//附加数据 
				//$unifiedOrder->setParameter("time_start","XXXX");//交易起始时间
				//$unifiedOrder->setParameter("time_expire","XXXX");//交易结束时间 
				//$unifiedOrder->setParameter("goods_tag","XXXX");//商品标记 
				//$unifiedOrder->setParameter("openid","XXXX");//用户标识
				
				//获取prepay_id
				$prepay_id = $unifiedOrder->getPrepayId();
				//设置返回码
				//设置必填参数
				//appid已填,商户无需重复填写
				//mch_id已填,商户无需重复填写
				//noncestr已填,商户无需重复填写
				//sign已填,商户无需重复填写
				$nativeCall->setReturnParameter("return_code","SUCCESS");//返回状态码
				$nativeCall->setReturnParameter("result_code","SUCCESS");//业务结果
				$nativeCall->setReturnParameter("prepay_id","$prepay_id");//预支付ID
				
				break;
			default:
				//设置返回码
				//设置必填参数
				//appid已填,商户无需重复填写
				//mch_id已填,商户无需重复填写
				//noncestr已填,商户无需重复填写
				//sign已填,商户无需重复填写
				$nativeCall->setReturnParameter("return_code","SUCCESS");//返回状态码
				$nativeCall->setReturnParameter("result_code","FAIL");//业务结果
				$nativeCall->setReturnParameter("err_code_des","此商品无效");//业务结果
				break;
		}
	}
	
	//将结果返回微信
	$returnXml = $nativeCall->returnXml();
	$log_->log_result($log_name,"【返回微信的native响应】:\n".$returnXml."\n");
	echo $returnXml;
	
	//交易完成
?>

10. [代码]native_call_qrcode.php    

<?php
/**
 * Native(原生)支付模式一demo
 * ====================================================
 * 模式一:商户按固定格式生成链接二维码,用户扫码后调微信
 * 会将productid和用户openid发送到商户设置的链接上,商户收到
 * 请求生成订单,调用统一支付接口下单提交到微信,微信会返回
 * 给商户prepayid。
 * 本例程对应的二维码由native_call_qrcode.php生成;
 * 本例程对应的响应服务为native_call.php;
 * 需要两者配合使用。
*/
	include_once("../WxPayPubHelper/WxPayPubHelper.php");
	//设置静态链接
	$nativeLink = new NativeLink_pub();	
	
	//设置静态链接参数
	//设置必填参数
	//appid已填,商户无需重复填写
	//mch_id已填,商户无需重复填写
	//noncestr已填,商户无需重复填写
	//time_stamp已填,商户无需重复填写
	//sign已填,商户无需重复填写
	$product_id = WxPayConf_pub::APPID."static";//自定义商品id
	$nativeLink->setParameter("product_id","$product_id");//商品id
	//获取链接
	$product_url = $nativeLink->getUrl();
	//使用短链接转换接口
	$shortUrl = new ShortUrl_pub();
	//设置必填参数
	//appid已填,商户无需重复填写
	//mch_id已填,商户无需重复填写
	//noncestr已填,商户无需重复填写
	//sign已填,商户无需重复填写
	$shortUrl->setParameter("long_url","$product_url");//URL链接
	//获取短链接
	$codeUrl = $shortUrl->getShortUrl();
	
?>

<!DOCTYPE HTML>
<html>
<head>
	<meta charset="UTF-8">
	<title>微信安全支付</title>
</head>
<body>
	<div align="center" id="qrcode">
		<p >扫我,扫我</p>
	</div>
	<div align="center">
		<a href="../index.php">返回首页</a>
	</div>
</body>
	<script src="./qrcode.js"></script>
	<script>
		var url = "<?php echo $product_url;?>";
		//参数1表示图像大小,取值范围1-10;参数2表示质量,取值范围'L','M','Q','H'
		var qr = qrcode(10, 'M');
		qr.addData(url);
		qr.make();
		var dom=document.createElement('DIV');
		dom.innerHTML = qr.createImgTag();
		var element=document.getElementById("qrcode");
		element.appendChild(dom);
	</script>
</html>

11. [代码]native_dynamic_qrcode.php    

<?php
/**
 * Native(原生)支付-模式二-demo
 * ====================================================
 * 商户生成订单,先调用统一支付接口获取到code_url,
 * 此URL直接生成二维码,用户扫码后调起支付。
 * 
*/
	include_once("../WxPayPubHelper/WxPayPubHelper.php");
	//使用统一支付接口
	$unifiedOrder = new UnifiedOrder_pub();
	
	//设置统一支付接口参数
	//设置必填参数
	//appid已填,商户无需重复填写
	//mch_id已填,商户无需重复填写
	//noncestr已填,商户无需重复填写
	//spbill_create_ip已填,商户无需重复填写
	//sign已填,商户无需重复填写
	$unifiedOrder->setParameter("body","贡献一分钱");//商品描述
	//自定义订单号,此处仅作举例
	$timeStamp = time();
	$out_trade_no = WxPayConf_pub::APPID."$timeStamp";
	$unifiedOrder->setParameter("out_trade_no","$out_trade_no");//商户订单号 
	$unifiedOrder->setParameter("total_fee","1");//总金额
	$unifiedOrder->setParameter("notify_url",WxPayConf_pub::NOTIFY_URL);//通知地址 
	$unifiedOrder->setParameter("trade_type","NATIVE");//交易类型
	//非必填参数,商户可根据实际情况选填
	//$unifiedOrder->setParameter("sub_mch_id","XXXX");//子商户号  
	//$unifiedOrder->setParameter("device_info","XXXX");//设备号 
	//$unifiedOrder->setParameter("attach","XXXX");//附加数据 
	//$unifiedOrder->setParameter("time_start","XXXX");//交易起始时间
	//$unifiedOrder->setParameter("time_expire","XXXX");//交易结束时间 
	//$unifiedOrder->setParameter("goods_tag","XXXX");//商品标记 
	//$unifiedOrder->setParameter("openid","XXXX");//用户标识
	//$unifiedOrder->setParameter("product_id","XXXX");//商品ID
	
	//获取统一支付接口结果
	$unifiedOrderResult = $unifiedOrder->getResult();
	
	//商户根据实际情况设置相应的处理流程
	if ($unifiedOrderResult["return_code"] == "FAIL") 
	{
		//商户自行增加处理流程
		echo "通信出错:".$unifiedOrderResult['return_msg']."<br>";
	}
	elseif($unifiedOrderResult["result_code"] == "FAIL")
	{
		//商户自行增加处理流程
		echo "错误代码:".$unifiedOrderResult['err_code']."<br>";
		echo "错误代码描述:".$unifiedOrderResult['err_code_des']."<br>";
	}
	elseif($unifiedOrderResult["code_url"] != NULL)
	{
		//从统一支付接口获取到code_url
		$code_url = $unifiedOrderResult["code_url"];
		//商户自行增加处理流程
		//......
	}
?>


<!DOCTYPE HTML>
<html>
<head>
	<meta charset="UTF-8">
	<title>微信安全支付</title>
</head>
<body>
	<div align="center" id="qrcode">
	</div>
	<div align="center">
		<p>订单号:<?php echo $out_trade_no; ?></p>
	</div>
	<div align="center">
		<form  action="./order_query.php" method="post">
			<input name="out_trade_no" type='hidden' value="<?php echo $out_trade_no; ?>">
		    <button type="submit" >查询订单状态</button>
		</form>
	</div>
	<br>
	<div align="center">
		<form  action="./refund.php" method="post">
			<input name="out_trade_no" type='hidden' value="<?php echo $out_trade_no; ?>">
			<input name="refund_fee" type='hidden' value="1">
		    <button type="submit" >申请退款</button>
		</form>
	</div>
	<br>
	<div align="center">
		<a href="../index.php">返回首页</a>
	</div>
</body>
	<script src="./qrcode.js"></script>
	<script>
		if(<?php echo $unifiedOrderResult["code_url"] != NULL; ?>)
		{
			var url = "<?php echo $code_url;?>";
			//参数1表示图像大小,取值范围1-10;参数2表示质量,取值范围'L','M','Q','H'
			var qr = qrcode(10, 'M');
			qr.addData(url);
			qr.make();
			var wording=document.createElement('p');
			wording.innerHTML = "扫我,扫我";
			var code=document.createElement('DIV');
			code.innerHTML = qr.createImgTag();
			var element=document.getElementById("qrcode");
			element.appendChild(wording);
			element.appendChild(code);
		}
	</script>
</html>

12. [代码]notify_url.php    

<?php
/**
 * 通用通知接口demo
 * ====================================================
 * 支付完成后,微信会把相关支付和用户信息发送到商户设定的通知URL,
 * 商户接收回调信息后,根据需要设定相应的处理流程。
 * 
 * 这里举例使用log文件形式记录回调信息。
*/
	include_once("./log_.php");
	include_once("./WxPayPubHelper/WxPayPubHelper.php");
	include_once('../../Public/Conf/config.php');
	
    //使用通用通知接口
	$notify = new Notify_pub();
	//存储微信的回调
	$xml = $GLOBALS['HTTP_RAW_POST_DATA'];	
	$notify->saveData($xml);
	
	//验证签名,并回应微信。
	//对后台通知交互时,如果微信收到商户的应答不是成功或超时,微信认为通知失败,
	//微信会通过一定的策略(如30分钟共8次)定期重新发起通知,
	//尽可能提高通知的成功率,但微信不保证通知最终能成功。
	if($notify->checkSign() == FALSE){
		$notify->setReturnParameter("return_code","FAIL");//返回状态码
		$notify->setReturnParameter("return_msg","签名失败");//返回信息
	}else{
		$notify->setReturnParameter("return_code","SUCCESS");//设置返回码
	}
	$returnXml = $notify->returnXml();
	echo $returnXml;
	//==商户根据实际情况设置相应的处理流程,此处仅作举例=======
	
	//以log文件形式记录回调信息
	$log_ = new Log_();
	$log_name="./notify_url.log";//log文件路径
	$log_->log_result($log_name,"【接收到的notify通知】:\n".$xml."\n");
	if($notify->checkSign() == TRUE)
	{
		if ($notify->data["return_code"] == "FAIL") {
			//此处应该更新一下订单状态,商户自行增删操作
			$log_->log_result($log_name,"【通信出错】:\n".$xml."\n");
		}
		elseif($notify->data["result_code"] == "FAIL"){
			//此处应该更新一下订单状态,商户自行增删操作
			$log_->log_result($log_name,"【业务出错】:\n".$xml."\n");
		}
		else{
			//此处应该更新一下订单状态,商户自行增删操作
			$log_->log_result($log_name,"【支付成功】:\n".$xml."\n");
		}		
		//商户自行增加处理流程,
		//例如:更新订单状态
		//例如:数据库操作
		//例如:推送支付完成信息
		$xml = $notify->xmlToArray($xml);
		// 商户订单号
		$out_trade_no = $xml ['out_trade_no'];
		$total_fee = $xml ['total_fee'];
		$uid = $xml ['openid'];
		$log_->log_result($log_name,"【订单号】:\n".$out_trade_no."\n");
		// 判断该笔订单是否在商户网站中已经做过处理
		// 如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序
		// 如果有做过处理,不执行商户的业务程序
		if (! empty ( $out_trade_no )) {
            $sql = "update " . DB_PREFIX . "order set pay_status=1 where orderid='" . $out_trade_no . "'";
            mysql_query ( $sql, $conn );
		}
	}
?>

13. [代码]order_query.php    

<?php
/**
 * 订单查询-demo
 * ====================================================
 * 该接口提供所有微信支付订单的查询。
 * 当支付通知处理异常或丢失的情况,商户可以通过该接口查询订单支付状态。
 * 
*/
	include_once("../WxPayPubHelper/WxPayPubHelper.php");
	
	//退款的订单号
	if (!isset($_POST["out_trade_no"]))
	{
		$out_trade_no = " ";
	}else{
	    $out_trade_no = $_POST["out_trade_no"];
		//使用订单查询接口
		$orderQuery = new OrderQuery_pub();
		//设置必填参数
		//appid已填,商户无需重复填写
		//mch_id已填,商户无需重复填写
		//noncestr已填,商户无需重复填写
		//sign已填,商户无需重复填写
		$orderQuery->setParameter("out_trade_no","$out_trade_no");//商户订单号 
		//非必填参数,商户可根据实际情况选填
		//$orderQuery->setParameter("sub_mch_id","XXXX");//子商户号  
		//$orderQuery->setParameter("transaction_id","XXXX");//微信订单号
		
		//获取订单查询结果
		$orderQueryResult = $orderQuery->getResult();
		
		//商户根据实际情况设置相应的处理流程,此处仅作举例
		if ($orderQueryResult["return_code"] == "FAIL") {
			echo "通信出错:".$orderQueryResult['return_msg']."<br>";
		}
		elseif($orderQueryResult["result_code"] == "FAIL"){
			echo "错误代码:".$orderQueryResult['err_code']."<br>";
			echo "错误代码描述:".$orderQueryResult['err_code_des']."<br>";
		}
		else{
			echo "交易状态:".$orderQueryResult['trade_state']."<br>";
			echo "设备号:".$orderQueryResult['device_info']."<br>";
			echo "用户标识:".$orderQueryResult['openid']."<br>";
			echo "是否关注公众账号:".$orderQueryResult['is_subscribe']."<br>";
			echo "交易类型:".$orderQueryResult['trade_type']."<br>";
			echo "付款银行:".$orderQueryResult['bank_type']."<br>";
			echo "总金额:".$orderQueryResult['total_fee']."<br>";
			echo "现金券金额:".$orderQueryResult['coupon_fee']."<br>";
			echo "货币种类:".$orderQueryResult['fee_type']."<br>";
			echo "微信支付订单号:".$orderQueryResult['transaction_id']."<br>";
			echo "商户订单号:".$orderQueryResult['out_trade_no']."<br>";
			echo "商家数据包:".$orderQueryResult['attach']."<br>";
			echo "支付完成时间:".$orderQueryResult['time_end']."<br>";
		}	
	}
	//商户自行增加处理流程
	//......
	
?>

<!DOCTYPE HTML>
<html>
<head>
	<meta charset="UTF-8">
	<title>微信安全支付</title>
</head>
<body>
	</br></br>
	<div align="center">
		<form  action="./order_query.php" method="post">
			<p>订单查询</p>
			<p>单号: <input type="text" name="out_trade_no" value="<?php echo $out_trade_no; ?>"></p>
		    <button type="submit" >提交</button>
		</form>
		</br>

		<a href="../index.php">返回首页</a>

	</div>
</body>
</html>

14. [代码]qrcode.js    

var qrcode=function(){var qrcode=function(typeNumber,errorCorrectLevel){var PAD0=0xEC;var PAD1=0x11;var _typeNumber=typeNumber;var _errorCorrectLevel=QRErrorCorrectLevel[errorCorrectLevel];var _modules=null;var _moduleCount=0;var _dataCache=null;var _dataList=new Array();var _this={};var makeImpl=function(test,maskPattern){_moduleCount=_typeNumber*4+17;_modules=function(moduleCount){var modules=new Array(moduleCount);for(var row=0;row<moduleCount;row+=1){modules[row]=new Array(moduleCount);for(var col=0;col<moduleCount;col+=1){modules[row][col]=null;}}
return modules;}(_moduleCount);setupPositionProbePattern(0,0);setupPositionProbePattern(_moduleCount-7,0);setupPositionProbePattern(0,_moduleCount-7);setupPositionAdjustPattern();setupTimingPattern();setupTypeInfo(test,maskPattern);if(_typeNumber>=7){setupTypeNumber(test);}
if(_dataCache==null){_dataCache=createData(_typeNumber,_errorCorrectLevel,_dataList);}
mapData(_dataCache,maskPattern);};var setupPositionProbePattern=function(row,col){for(var r=-1;r<=7;r+=1){if(row+r<=-1||_moduleCount<=row+r)continue;for(var c=-1;c<=7;c+=1){if(col+c<=-1||_moduleCount<=col+c)continue;if((0<=r&&r<=6&&(c==0||c==6))||(0<=c&&c<=6&&(r==0||r==6))||(2<=r&&r<=4&&2<=c&&c<=4)){_modules[row+r][col+c]=true;}else{_modules[row+r][col+c]=false;}}}};var getBestMaskPattern=function(){var minLostPoint=0;var pattern=0;for(var i=0;i<8;i+=1){makeImpl(true,i);var lostPoint=QRUtil.getLostPoint(_this);if(i==0||minLostPoint>lostPoint){minLostPoint=lostPoint;pattern=i;}}
return pattern;};var setupTimingPattern=function(){for(var r=8;r<_moduleCount-8;r+=1){if(_modules[r][6]!=null){continue;}
_modules[r][6]=(r%2==0);}
for(var c=8;c<_moduleCount-8;c+=1){if(_modules[6][c]!=null){continue;}
_modules[6][c]=(c%2==0);}};var setupPositionAdjustPattern=function(){var pos=QRUtil.getPatternPosition(_typeNumber);for(var i=0;i<pos.length;i+=1){for(var j=0;j<pos.length;j+=1){var row=pos[i];var col=pos[j];if(_modules[row][col]!=null){continue;}
for(var r=-2;r<=2;r+=1){for(var c=-2;c<=2;c+=1){if(r==-2||r==2||c==-2||c==2||(r==0&&c==0)){_modules[row+r][col+c]=true;}else{_modules[row+r][col+c]=false;}}}}}};var setupTypeNumber=function(test){var bits=QRUtil.getBCHTypeNumber(_typeNumber);for(var i=0;i<18;i+=1){var mod=(!test&&((bits>>i)&1)==1);_modules[Math.floor(i/3)][i%3+_moduleCount-8-3]=mod;}
for(var i=0;i<18;i+=1){var mod=(!test&&((bits>>i)&1)==1);_modules[i%3+_moduleCount-8-3][Math.floor(i/3)]=mod;}};var setupTypeInfo=function(test,maskPattern){var data=(_errorCorrectLevel<<3)|maskPattern;var bits=QRUtil.getBCHTypeInfo(data);for(var i=0;i<15;i+=1){var mod=(!test&&((bits>>i)&1)==1);if(i<6){_modules[i][8]=mod;}else if(i<8){_modules[i+1][8]=mod;}else{_modules[_moduleCount-15+i][8]=mod;}}
for(var i=0;i<15;i+=1){var mod=(!test&&((bits>>i)&1)==1);if(i<8){_modules[8][_moduleCount-i-1]=mod;}else if(i<9){_modules[8][15-i-1+1]=mod;}else{_modules[8][15-i-1]=mod;}}
_modules[_moduleCount-8][8]=(!test);};var mapData=function(data,maskPattern){var inc=-1;var row=_moduleCount-1;var bitIndex=7;var byteIndex=0;var maskFunc=QRUtil.getMaskFunction(maskPattern);for(var col=_moduleCount-1;col>0;col-=2){if(col==6)col-=1;while(true){for(var c=0;c<2;c+=1){if(_modules[row][col-c]==null){var dark=false;if(byteIndex<data.length){dark=(((data[byteIndex]>>>bitIndex)&1)==1);}
var mask=maskFunc(row,col-c);if(mask){dark=!dark;}
_modules[row][col-c]=dark;bitIndex-=1;if(bitIndex==-1){byteIndex+=1;bitIndex=7;}}}
row+=inc;if(row<0||_moduleCount<=row){row-=inc;inc=-inc;break;}}}};var createBytes=function(buffer,rsBlocks){var offset=0;var maxDcCount=0;var maxEcCount=0;var dcdata=new Array(rsBlocks.length);var ecdata=new Array(rsBlocks.length);for(var r=0;r<rsBlocks.length;r+=1){var dcCount=rsBlocks[r].dataCount;var ecCount=rsBlocks[r].totalCount-dcCount;maxDcCount=Math.max(maxDcCount,dcCount);maxEcCount=Math.max(maxEcCount,ecCount);dcdata[r]=new Array(dcCount);for(var i=0;i<dcdata[r].length;i+=1){dcdata[r][i]=0xff&buffer.getBuffer()[i+offset];}
offset+=dcCount;var rsPoly=QRUtil.getErrorCorrectPolynomial(ecCount);var rawPoly=qrPolynomial(dcdata[r],rsPoly.getLength()-1);var modPoly=rawPoly.mod(rsPoly);ecdata[r]=new Array(rsPoly.getLength()-1);for(var i=0;i<ecdata[r].length;i+=1){var modIndex=i+modPoly.getLength()-ecdata[r].length;ecdata[r][i]=(modIndex>=0)?modPoly.getAt(modIndex):0;}}
var totalCodeCount=0;for(var i=0;i<rsBlocks.length;i+=1){totalCodeCount+=rsBlocks[i].totalCount;}
var data=new Array(totalCodeCount);var index=0;for(var i=0;i<maxDcCount;i+=1){for(var r=0;r<rsBlocks.length;r+=1){if(i<dcdata[r].length){data[index]=dcdata[r][i];index+=1;}}}
for(var i=0;i<maxEcCount;i+=1){for(var r=0;r<rsBlocks.length;r+=1){if(i<ecdata[r].length){data[index]=ecdata[r][i];index+=1;}}}
return data;};var createData=function(typeNumber,errorCorrectLevel,dataList){var rsBlocks=QRRSBlock.getRSBlocks(typeNumber,errorCorrectLevel);var buffer=qrBitBuffer();for(var i=0;i<dataList.length;i+=1){var data=dataList[i];buffer.put(data.getMode(),4);buffer.put(data.getLength(),QRUtil.getLengthInBits(data.getMode(),typeNumber));data.write(buffer);}
var totalDataCount=0;for(var i=0;i<rsBlocks.length;i+=1){totalDataCount+=rsBlocks[i].dataCount;}
if(buffer.getLengthInBits()>totalDataCount*8){throw new Error('code length overflow. ('
+buffer.getLengthInBits()
+'>'
+totalDataCount*8
+')');}
if(buffer.getLengthInBits()+4<=totalDataCount*8){buffer.put(0,4);}
while(buffer.getLengthInBits()%8!=0){buffer.putBit(false);}
while(true){if(buffer.getLengthInBits()>=totalDataCount*8){break;}
buffer.put(PAD0,8);if(buffer.getLengthInBits()>=totalDataCount*8){break;}
buffer.put(PAD1,8);}
return createBytes(buffer,rsBlocks);};_this.addData=function(data){var newData=qr8BitByte(data);_dataList.push(newData);_dataCache=null;};_this.isDark=function(row,col){if(row<0||_moduleCount<=row||col<0||_moduleCount<=col){throw new Error(row+','+col);}
return _modules[row][col];};_this.getModuleCount=function(){return _moduleCount;};_this.make=function(){makeImpl(false,getBestMaskPattern());};_this.createTableTag=function(cellSize,margin){cellSize=cellSize||2;margin=(typeof margin=='undefined')?cellSize*4:margin;var qrHtml='';qrHtml+='<table style="';qrHtml+=' border-width: 0px; border-style: none;';qrHtml+=' border-collapse: collapse;';qrHtml+=' padding: 0px; margin: '+margin+'px;';qrHtml+='">';qrHtml+='<tbody>';for(var r=0;r<_this.getModuleCount();r+=1){qrHtml+='<tr>';for(var c=0;c<_this.getModuleCount();c+=1){qrHtml+='<td style="';qrHtml+=' border-width: 0px; border-style: none;';qrHtml+=' border-collapse: collapse;';qrHtml+=' padding: 0px; margin: 0px;';qrHtml+=' width: '+cellSize+'px;';qrHtml+=' height: '+cellSize+'px;';qrHtml+=' background-color: ';qrHtml+=_this.isDark(r,c)?'#000000':'#ffffff';qrHtml+=';';qrHtml+='"/>';}
qrHtml+='</tr>';}
qrHtml+='</tbody>';qrHtml+='</table>';return qrHtml;};_this.createImgTag=function(cellSize,margin){cellSize=cellSize||2;margin=(typeof margin=='undefined')?cellSize*4:margin;var size=_this.getModuleCount()*cellSize+margin*2;var min=margin;var max=size-margin;return createImgTag(size,size,function(x,y){if(min<=x&&x<max&&min<=y&&y<max){var c=Math.floor((x-min)/cellSize);var r=Math.floor((y-min)/cellSize);return _this.isDark(r,c)?0:1;}else{return 1;}});};return _this;};qrcode.stringToBytes=function(s){var bytes=new Array();for(var i=0;i<s.length;i+=1){var c=s.charCodeAt(i);bytes.push(c&0xff);}
return bytes;};qrcode.createStringToBytes=function(unicodeData,numChars){var unicodeMap=function(){var bin=base64DecodeInputStream(unicodeData);var read=function(){var b=bin.read();if(b==-1)throw new Error();return b;};var count=0;var unicodeMap={};while(true){var b0=bin.read();if(b0==-1)break;var b1=read();var b2=read();var b3=read();var k=String.fromCharCode((b0<<8)|b1);var v=(b2<<8)|b3;unicodeMap[k]=v;count+=1;}
if(count!=numChars){throw new Error(count+' != '+numChars);}
return unicodeMap;}();var unknownChar='?'.charCodeAt(0);return function(s){var bytes=new Array();for(var i=0;i<s.length;i+=1){var c=s.charCodeAt(i);if(c<128){bytes.push(c);}else{var b=unicodeMap[s.charAt(i)];if(typeof b=='number'){if((b&0xff)==b){bytes.push(b);}else{bytes.push(b>>>8);bytes.push(b&0xff);}}else{bytes.push(unknownChar);}}}
return bytes;};};var QRMode={MODE_NUMBER:1<<0,MODE_ALPHA_NUM:1<<1,MODE_8BIT_BYTE:1<<2,MODE_KANJI:1<<3};var QRErrorCorrectLevel={L:1,M:0,Q:3,H:2};var QRMaskPattern={PATTERN000:0,PATTERN001:1,PATTERN010:2,PATTERN011:3,PATTERN100:4,PATTERN101:5,PATTERN110:6,PATTERN111:7};var QRUtil=function(){var PATTERN_POSITION_TABLE=[[],[6,18],[6,22],[6,26],[6,30],[6,34],[6,22,38],[6,24,42],[6,26,46],[6,28,50],[6,30,54],[6,32,58],[6,34,62],[6,26,46,66],[6,26,48,70],[6,26,50,74],[6,30,54,78],[6,30,56,82],[6,30,58,86],[6,34,62,90],[6,28,50,72,94],[6,26,50,74,98],[6,30,54,78,102],[6,28,54,80,106],[6,32,58,84,110],[6,30,58,86,114],[6,34,62,90,118],[6,26,50,74,98,122],[6,30,54,78,102,126],[6,26,52,78,104,130],[6,30,56,82,108,134],[6,34,60,86,112,138],[6,30,58,86,114,142],[6,34,62,90,118,146],[6,30,54,78,102,126,150],[6,24,50,76,102,128,154],[6,28,54,80,106,132,158],[6,32,58,84,110,136,162],[6,26,54,82,110,138,166],[6,30,58,86,114,142,170]];var G15=(1<<10)|(1<<8)|(1<<5)|(1<<4)|(1<<2)|(1<<1)|(1<<0);var G18=(1<<12)|(1<<11)|(1<<10)|(1<<9)|(1<<8)|(1<<5)|(1<<2)|(1<<0);var G15_MASK=(1<<14)|(1<<12)|(1<<10)|(1<<4)|(1<<1);var _this={};var getBCHDigit=function(data){var digit=0;while(data!=0){digit+=1;data>>>=1;}
return digit;};_this.getBCHTypeInfo=function(data){var d=data<<10;while(getBCHDigit(d)-getBCHDigit(G15)>=0){d^=(G15<<(getBCHDigit(d)-getBCHDigit(G15)));}
return((data<<10)|d)^G15_MASK;};_this.getBCHTypeNumber=function(data){var d=data<<12;while(getBCHDigit(d)-getBCHDigit(G18)>=0){d^=(G18<<(getBCHDigit(d)-getBCHDigit(G18)));}
return(data<<12)|d;};_this.getPatternPosition=function(typeNumber){return PATTERN_POSITION_TABLE[typeNumber-1];};_this.getMaskFunction=function(maskPattern){switch(maskPattern){case QRMaskPattern.PATTERN000:return function(i,j){return(i+j)%2==0;};case QRMaskPattern.PATTERN001:return function(i,j){return i%2==0;};case QRMaskPattern.PATTERN010:return function(i,j){return j%3==0;};case QRMaskPattern.PATTERN011:return function(i,j){return(i+j)%3==0;};case QRMaskPattern.PATTERN100:return function(i,j){return(Math.floor(i/2)+Math.floor(j/3))%2==0;};case QRMaskPattern.PATTERN101:return function(i,j){return(i*j)%2+(i*j)%3==0;};case QRMaskPattern.PATTERN110:return function(i,j){return((i*j)%2+(i*j)%3)%2==0;};case QRMaskPattern.PATTERN111:return function(i,j){return((i*j)%3+(i+j)%2)%2==0;};default:throw new Error('bad maskPattern:'+maskPattern);}};_this.getErrorCorrectPolynomial=function(errorCorrectLength){var a=qrPolynomial([1],0);for(var i=0;i<errorCorrectLength;i+=1){a=a.multiply(qrPolynomial([1,QRMath.gexp(i)],0));}
return a;};_this.getLengthInBits=function(mode,type){if(1<=type&&type<10){switch(mode){case QRMode.MODE_NUMBER:return 10;case QRMode.MODE_ALPHA_NUM:return 9;case QRMode.MODE_8BIT_BYTE:return 8;case QRMode.MODE_KANJI:return 8;default:throw new Error('mode:'+mode);}}else if(type<27){switch(mode){case QRMode.MODE_NUMBER:return 12;case QRMode.MODE_ALPHA_NUM:return 11;case QRMode.MODE_8BIT_BYTE:return 16;case QRMode.MODE_KANJI:return 10;default:throw new Error('mode:'+mode);}}else if(type<41){switch(mode){case QRMode.MODE_NUMBER:return 14;case QRMode.MODE_ALPHA_NUM:return 13;case QRMode.MODE_8BIT_BYTE:return 16;case QRMode.MODE_KANJI:return 12;default:throw new Error('mode:'+mode);}}else{throw new Error('type:'+type);}};_this.getLostPoint=function(qrcode){var moduleCount=qrcode.getModuleCount();var lostPoint=0;for(var row=0;row<moduleCount;row+=1){for(var col=0;col<moduleCount;col+=1){var sameCount=0;var dark=qrcode.isDark(row,col);for(var r=-1;r<=1;r+=1){if(row+r<0||moduleCount<=row+r){continue;}
for(var c=-1;c<=1;c+=1){if(col+c<0||moduleCount<=col+c){continue;}
if(r==0&&c==0){continue;}
if(dark==qrcode.isDark(row+r,col+c)){sameCount+=1;}}}
if(sameCount>5){lostPoint+=(3+sameCount-5);}}};for(var row=0;row<moduleCount-1;row+=1){for(var col=0;col<moduleCount-1;col+=1){var count=0;if(qrcode.isDark(row,col))count+=1;if(qrcode.isDark(row+1,col))count+=1;if(qrcode.isDark(row,col+1))count+=1;if(qrcode.isDark(row+1,col+1))count+=1;if(count==0||count==4){lostPoint+=3;}}}
for(var row=0;row<moduleCount;row+=1){for(var col=0;col<moduleCount-6;col+=1){if(qrcode.isDark(row,col)&&!qrcode.isDark(row,col+1)&&qrcode.isDark(row,col+2)&&qrcode.isDark(row,col+3)&&qrcode.isDark(row,col+4)&&!qrcode.isDark(row,col+5)&&qrcode.isDark(row,col+6)){lostPoint+=40;}}}
for(var col=0;col<moduleCount;col+=1){for(var row=0;row<moduleCount-6;row+=1){if(qrcode.isDark(row,col)&&!qrcode.isDark(row+1,col)&&qrcode.isDark(row+2,col)&&qrcode.isDark(row+3,col)&&qrcode.isDark(row+4,col)&&!qrcode.isDark(row+5,col)&&qrcode.isDark(row+6,col)){lostPoint+=40;}}}
var darkCount=0;for(var col=0;col<moduleCount;col+=1){for(var row=0;row<moduleCount;row+=1){if(qrcode.isDark(row,col)){darkCount+=1;}}}
var ratio=Math.abs(100*darkCount/moduleCount/moduleCount-50)/5;lostPoint+=ratio*10;return lostPoint;};return _this;}();var QRMath=function(){var EXP_TABLE=new Array(256);var LOG_TABLE=new Array(256);for(var i=0;i<8;i+=1){EXP_TABLE[i]=1<<i;}
for(var i=8;i<256;i+=1){EXP_TABLE[i]=EXP_TABLE[i-4]^EXP_TABLE[i-5]^EXP_TABLE[i-6]^EXP_TABLE[i-8];}
for(var i=0;i<255;i+=1){LOG_TABLE[EXP_TABLE[i]]=i;}
var _this={};_this.glog=function(n){if(n<1){throw new Error('glog('+n+')');}
return LOG_TABLE[n];};_this.gexp=function(n){while(n<0){n+=255;}
while(n>=256){n-=255;}
return EXP_TABLE[n];};return _this;}();function qrPolynomial(num,shift){if(typeof num.length=='undefined'){throw new Error(num.length+'/'+shift);}
var _num=function(){var offset=0;while(offset<num.length&&num[offset]==0){offset+=1;}
var _num=new Array(num.length-offset+shift);for(var i=0;i<num.length-offset;i+=1){_num[i]=num[i+offset];}
return _num;}();var _this={};_this.getAt=function(index){return _num[index];};_this.getLength=function(){return _num.length;};_this.multiply=function(e){var num=new Array(_this.getLength()+e.getLength()-1);for(var i=0;i<_this.getLength();i+=1){for(var j=0;j<e.getLength();j+=1){num[i+j]^=QRMath.gexp(QRMath.glog(_this.getAt(i))+QRMath.glog(e.getAt(j)));}}
return qrPolynomial(num,0);};_this.mod=function(e){if(_this.getLength()-e.getLength()<0){return _this;}
var ratio=QRMath.glog(_this.getAt(0))-QRMath.glog(e.getAt(0));var num=new Array(_this.getLength());for(var i=0;i<_this.getLength();i+=1){num[i]=_this.getAt(i);}
for(var i=0;i<e.getLength();i+=1){num[i]^=QRMath.gexp(QRMath.glog(e.getAt(i))+ratio);}
return qrPolynomial(num,0).mod(e);};return _this;};var QRRSBlock=function(){var RS_BLOCK_TABLE=[[1,26,19],[1,26,16],[1,26,13],[1,26,9],[1,44,34],[1,44,28],[1,44,22],[1,44,16],[1,70,55],[1,70,44],[2,35,17],[2,35,13],[1,100,80],[2,50,32],[2,50,24],[4,25,9],[1,134,108],[2,67,43],[2,33,15,2,34,16],[2,33,11,2,34,12],[2,86,68],[4,43,27],[4,43,19],[4,43,15],[2,98,78],[4,49,31],[2,32,14,4,33,15],[4,39,13,1,40,14],[2,121,97],[2,60,38,2,61,39],[4,40,18,2,41,19],[4,40,14,2,41,15],[2,146,116],[3,58,36,2,59,37],[4,36,16,4,37,17],[4,36,12,4,37,13],[2,86,68,2,87,69],[4,69,43,1,70,44],[6,43,19,2,44,20],[6,43,15,2,44,16]];var qrRSBlock=function(totalCount,dataCount){var _this={};_this.totalCount=totalCount;_this.dataCount=dataCount;return _this;};var _this={};var getRsBlockTable=function(typeNumber,errorCorrectLevel){switch(errorCorrectLevel){case QRErrorCorrectLevel.L:return RS_BLOCK_TABLE[(typeNumber-1)*4+0];case QRErrorCorrectLevel.M:return RS_BLOCK_TABLE[(typeNumber-1)*4+1];case QRErrorCorrectLevel.Q:return RS_BLOCK_TABLE[(typeNumber-1)*4+2];case QRErrorCorrectLevel.H:return RS_BLOCK_TABLE[(typeNumber-1)*4+3];default:return undefined;}};_this.getRSBlocks=function(typeNumber,errorCorrectLevel){var rsBlock=getRsBlockTable(typeNumber,errorCorrectLevel);if(typeof rsBlock=='undefined'){throw new Error('bad rs block @ typeNumber:'+typeNumber+'/errorCorrectLevel:'+errorCorrectLevel);}
var length=rsBlock.length/3;var list=new Array();for(var i=0;i<length;i+=1){var count=rsBlock[i*3+0];var totalCount=rsBlock[i*3+1];var dataCount=rsBlock[i*3+2];for(var j=0;j<count;j+=1){list.push(qrRSBlock(totalCount,dataCount));}}
return list;};return _this;}();var qrBitBuffer=function(){var _buffer=new Array();var _length=0;var _this={};_this.getBuffer=function(){return _buffer;};_this.getAt=function(index){var bufIndex=Math.floor(index/8);return((_buffer[bufIndex]>>>(7-index%8))&1)==1;};_this.put=function(num,length){for(var i=0;i<length;i+=1){_this.putBit(((num>>>(length-i-1))&1)==1);}};_this.getLengthInBits=function(){return _length;};_this.putBit=function(bit){var bufIndex=Math.floor(_length/8);if(_buffer.length<=bufIndex){_buffer.push(0);}
if(bit){_buffer[bufIndex]|=(0x80>>>(_length%8));}
_length+=1;};return _this;};var qr8BitByte=function(data){var _mode=QRMode.MODE_8BIT_BYTE;var _data=data;var _bytes=qrcode.stringToBytes(data);var _this={};_this.getMode=function(){return _mode;};_this.getLength=function(buffer){return _bytes.length;};_this.write=function(buffer){for(var i=0;i<_bytes.length;i+=1){buffer.put(_bytes[i],8);}};return _this;};var byteArrayOutputStream=function(){var _bytes=new Array();var _this={};_this.writeByte=function(b){_bytes.push(b&0xff);};_this.writeShort=function(i){_this.writeByte(i);_this.writeByte(i>>>8);};_this.writeBytes=function(b,off,len){off=off||0;len=len||b.length;for(var i=0;i<len;i+=1){_this.writeByte(b[i+off]);}};_this.writeString=function(s){for(var i=0;i<s.length;i+=1){_this.writeByte(s.charCodeAt(i));}};_this.toByteArray=function(){return _bytes;};_this.toString=function(){var s='';s+='[';for(var i=0;i<_bytes.length;i+=1){if(i>0){s+=',';}
s+=_bytes[i];}
s+=']';return s;};return _this;};var base64EncodeOutputStream=function(){var _buffer=0;var _buflen=0;var _length=0;var _base64='';var _this={};var writeEncoded=function(b){_base64+=String.fromCharCode(encode(b&0x3f));};var encode=function(n){if(n<0){}else if(n<26){return 0x41+n;}else if(n<52){return 0x61+(n-26);}else if(n<62){return 0x30+(n-52);}else if(n==62){return 0x2b;}else if(n==63){return 0x2f;}
throw new Error('n:'+n);};_this.writeByte=function(n){_buffer=(_buffer<<8)|(n&0xff);_buflen+=8;_length+=1;while(_buflen>=6){writeEncoded(_buffer>>>(_buflen-6));_buflen-=6;}};_this.flush=function(){if(_buflen>0){writeEncoded(_buffer<<(6-_buflen));_buffer=0;_buflen=0;}
if(_length%3!=0){var padlen=3-_length%3;for(var i=0;i<padlen;i+=1){_base64+='=';}}};_this.toString=function(){return _base64;};return _this;};var base64DecodeInputStream=function(str){var _str=str;var _pos=0;var _buffer=0;var _buflen=0;var _this={};_this.read=function(){while(_buflen<8){if(_pos>=_str.length){if(_buflen==0){return-1;}
throw new Error('unexpected end of file./'+_buflen);}
var c=_str.charAt(_pos);_pos+=1;if(c=='='){_buflen=0;return-1;}else if(c.match(/^\s$/)){continue;}
_buffer=(_buffer<<6)|decode(c.charCodeAt(0));_buflen+=6;}
var n=(_buffer>>>(_buflen-8))&0xff;_buflen-=8;return n;};var decode=function(c){if(0x41<=c&&c<=0x5a){return c-0x41;}else if(0x61<=c&&c<=0x7a){return c-0x61+26;}else if(0x30<=c&&c<=0x39){return c-0x30+52;}else if(c==0x2b){return 62;}else if(c==0x2f){return 63;}else{throw new Error('c:'+c);}};return _this;};var gifImage=function(width,height){var _width=width;var _height=height;var _data=new Array(width*height);var _this={};_this.setPixel=function(x,y,pixel){_data[y*_width+x]=pixel;};_this.write=function(out){out.writeString('GIF87a');out.writeShort(_width);out.writeShort(_height);out.writeByte(0x80);out.writeByte(0);out.writeByte(0);out.writeByte(0x00);out.writeByte(0x00);out.writeByte(0x00);out.writeByte(0xff);out.writeByte(0xff);out.writeByte(0xff);out.writeString(',');out.writeShort(0);out.writeShort(0);out.writeShort(_width);out.writeShort(_height);out.writeByte(0);var lzwMinCodeSize=2;var raster=getLZWRaster(lzwMinCodeSize);out.writeByte(lzwMinCodeSize);var offset=0;while(raster.length-offset>255){out.writeByte(255);out.writeBytes(raster,offset,255);offset+=255;}
out.writeByte(raster.length-offset);out.writeBytes(raster,offset,raster.length-offset);out.writeByte(0x00);out.writeString(';');};var bitOutputStream=function(out){var _out=out;var _bitLength=0;var _bitBuffer=0;var _this={};_this.write=function(data,length){if((data>>>length)!=0){throw new Error('length over');}
while(_bitLength+length>=8){_out.writeByte(0xff&((data<<_bitLength)|_bitBuffer));length-=(8-_bitLength);data>>>=(8-_bitLength);_bitBuffer=0;_bitLength=0;}
_bitBuffer=(data<<_bitLength)|_bitBuffer;_bitLength=_bitLength+length;};_this.flush=function(){if(_bitLength>0){_out.writeByte(_bitBuffer);}};return _this;};var getLZWRaster=function(lzwMinCodeSize){var clearCode=1<<lzwMinCodeSize;var endCode=(1<<lzwMinCodeSize)+1;var bitLength=lzwMinCodeSize+1;var table=lzwTable();for(var i=0;i<clearCode;i+=1){table.add(String.fromCharCode(i));}
table.add(String.fromCharCode(clearCode));table.add(String.fromCharCode(endCode));var byteOut=byteArrayOutputStream();var bitOut=bitOutputStream(byteOut);bitOut.write(clearCode,bitLength);var dataIndex=0;var s=String.fromCharCode(_data[dataIndex]);dataIndex+=1;while(dataIndex<_data.length){var c=String.fromCharCode(_data[dataIndex]);dataIndex+=1;if(table.contains(s+c)){s=s+c;}else{bitOut.write(table.indexOf(s),bitLength);if(table.size()<0xfff){if(table.size()==(1<<bitLength)){bitLength+=1;}
table.add(s+c);}
s=c;}}
bitOut.write(table.indexOf(s),bitLength);bitOut.write(endCode,bitLength);bitOut.flush();return byteOut.toByteArray();};var lzwTable=function(){var _map={};var _size=0;var _this={};_this.add=function(key){if(_this.contains(key)){throw new Error('dup key:'+key);}
_map[key]=_size;_size+=1;};_this.size=function(){return _size;};_this.indexOf=function(key){return _map[key];};_this.contains=function(key){return typeof _map[key]!='undefined';};return _this;};return _this;};var createImgTag=function(width,height,getPixel,alt){var gif=gifImage(width,height);for(var y=0;y<height;y+=1){for(var x=0;x<width;x+=1){gif.setPixel(x,y,getPixel(x,y));}}
var b=byteArrayOutputStream();gif.write(b);var base64=base64EncodeOutputStream();var bytes=b.toByteArray();for(var i=0;i<bytes.length;i+=1){base64.writeByte(bytes[i]);}
base64.flush();var img='';img+='<img';img+='\u0020src="';img+='data:image/gif;base64,';img+=base64;img+='"';img+='\u0020width="';img+=width;img+='"';img+='\u0020height="';img+=height;img+='"';if(alt){img+='\u0020alt="';img+=alt;img+='"';}
img+='/>';return img;};return qrcode;}();/*  |xGv00|ca8fc6bde81a353e7cede123b304bdb9 */

15. [代码]refund.php    

<?php
/**
 * 退款申请接口-demo
 * ====================================================
 * 注意:同一笔单的部分退款需要设置相同的订单号和不同的
 * out_refund_no。一笔退款失败后重新提交,要采用原来的
 * out_refund_no。总退款金额不能超过用户实际支付金额(现
 * 金券金额不能退款)。
*/
	include_once("../WxPayPubHelper/WxPayPubHelper.php");
	//输入需退款的订单号
	if (!isset($_POST["out_trade_no"]) || !isset($_POST["refund_fee"]))
	{
		$out_trade_no = " ";
		$refund_fee = "1";
	}else{
	    $out_trade_no = $_POST["out_trade_no"];
	    $refund_fee = $_POST["refund_fee"];
		//商户退款单号,商户自定义,此处仅作举例
		$out_refund_no = "$out_trade_no"."$time_stamp";
		//总金额需与订单号out_trade_no对应,demo中的所有订单的总金额为1分
		$total_fee = "1";
		
		//使用退款接口
		$refund = new Refund_pub();
		//设置必填参数
		//appid已填,商户无需重复填写
		//mch_id已填,商户无需重复填写
		//noncestr已填,商户无需重复填写
		//sign已填,商户无需重复填写
		$refund->setParameter("out_trade_no","$out_trade_no");//商户订单号
		$refund->setParameter("out_refund_no","$out_refund_no");//商户退款单号
		$refund->setParameter("total_fee","$total_fee");//总金额
		$refund->setParameter("refund_fee","$refund_fee");//退款金额
		$refund->setParameter("op_user_id",WxPayConf_pub::MCHID);//操作员
		//非必填参数,商户可根据实际情况选填
		//$refund->setParameter("sub_mch_id","XXXX");//子商户号 
		//$refund->setParameter("device_info","XXXX");//设备号 
		//$refund->setParameter("transaction_id","XXXX");//微信订单号
		
		//调用结果
		$refundResult = $refund->getResult();
		
		//商户根据实际情况设置相应的处理流程,此处仅作举例
		if ($refundResult["return_code"] == "FAIL") {
			echo "通信出错:".$refundResult['return_msg']."<br>";
		}
		else{
			echo "业务结果:".$refundResult['result_code']."<br>";
			echo "错误代码:".$refundResult['err_code']."<br>";
			echo "错误代码描述:".$refundResult['err_code_des']."<br>";
			echo "公众账号ID:".$refundResult['appid']."<br>";
			echo "商户号:".$refundResult['mch_id']."<br>";
			echo "子商户号:".$refundResult['sub_mch_id']."<br>";
			echo "设备号:".$refundResult['device_info']."<br>";
			echo "签名:".$refundResult['sign']."<br>";
			echo "微信订单号:".$refundResult['transaction_id']."<br>";
			echo "商户订单号:".$refundResult['out_trade_no']."<br>";
			echo "商户退款单号:".$refundResult['out_refund_no']."<br>";
			echo "微信退款单号:".$refundResult['refund_idrefund_id']."<br>";
			echo "退款渠道:".$refundResult['refund_channel']."<br>";
			echo "退款金额:".$refundResult['refund_fee']."<br>";
			echo "现金券退款金额:".$refundResult['coupon_refund_fee']."<br>";
		}
	}
	
?>

<!DOCTYPE HTML>
<html>
<head>
	<meta charset="UTF-8">
	<title>微信安全支付</title>
</head>
<body>
	</br></br></br></br>
	<div align="center">
		<form  action="./refund.php" method="post">
			<p>申请退款:</p>
			<p>退款单号: <input type="text" name="out_trade_no" value=<?php echo $out_trade_no; ?> ></p>
			<p>退款金额(分): <input type="text" name="refund_fee" value=<?php echo $refund_fee; ?> ></p>
		    <button type="submit" >提交</button>
		</form>
		
		</br>
		<a href="../index.php">返回首页</a>

	</div>
</body>
</html>

16. [代码]refund_query.php    

<?php
/**
 * 退款申请接口-demo
 * ====================================================
 * 
 * 
*/
	include_once("../WxPayPubHelper/WxPayPubHelper.php");
	//要查询的订单号
	if (!isset($_POST["out_trade_no"]))
	{
		$out_trade_no = " ";
	}else{
	    $out_trade_no = $_POST["out_trade_no"];
		
		//使用退款查询接口
		$refundQuery = new RefundQuery_pub();
		//设置必填参数
		//appid已填,商户无需重复填写
		//mch_id已填,商户无需重复填写
		//noncestr已填,商户无需重复填写
		//sign已填,商户无需重复填写
		$refundQuery->setParameter("out_trade_no","$out_trade_no");//商户订单号
		// $refundQuery->setParameter("out_refund_no","XXXX");//商户退款单号
		// $refundQuery->setParameter("refund_id","XXXX");//微信退款单号
		// $refundQuery->setParameter("transaction_id","XXXX");//微信退款单号
		//非必填参数,商户可根据实际情况选填
		//$refundQuery->setParameter("sub_mch_id","XXXX");//子商户号 
		//$refundQuery->setParameter("device_info","XXXX");//设备号 
		
		//退款查询接口结果
		$refundQueryResult = $refundQuery->getResult();
		
		//商户根据实际情况设置相应的处理流程,此处仅作举例
		if ($refundQueryResult["return_code"] == "FAIL") {
			echo "通信出错:".$refundQueryResult['return_msg']."<br>";
		}
		else{
			echo "业务结果:".$refundQueryResult['result_code']."<br>";
			echo "错误代码:".$refundQueryResult['err_code']."<br>";
			echo "错误代码描述:".$refundQueryResult['err_code_des']."<br>";
			echo "公众账号ID:".$refundQueryResult['appid']."<br>";
			echo "商户号:".$refundQueryResult['mch_id']."<br>";
			echo "子商户号:".$refundQueryResult['sub_mch_id']."<br>";
			echo "设备号:".$refundQueryResult['device_info']."<br>";
			echo "签名:".$refundQueryResult['sign']."<br>";
			echo "微信订单号:".$refundQueryResult['transaction_id']."<br>";
			echo "商户订单号:".$refundQueryResult['out_trade_no']."<br>";
			echo "退款笔数:".$refundQueryResult['refund_count']."<br>";
			echo "商户退款单号:".$refundQueryResult['out_refund_no']."<br>";
			echo "微信退款单号:".$refundQueryResult['refund_idrefund_id']."<br>";
			echo "退款渠道:".$refundQueryResult['refund_channel']."<br>";
			echo "退款金额:".$refundQueryResult['refund_fee']."<br>";
			echo "现金券退款金额:".$refundQueryResult['coupon_refund_fee']."<br>";
			echo "退款状态:".$refundQueryResult['refund_status']."<br>";
		}
	}
	
	
?>

<!DOCTYPE HTML>
<html>
<head>
	<meta charset="UTF-8">
	<title>微信安全支付</title>
</head>
<body>
	</br></br></br></br>
	<div align="center">
		<form  action="./refund_query.php" method="post">
			<p>退款查询</p>
			<p>单号: <input type="text" name="out_trade_no"></p>
		    <button type="submit" >提交</button>
		</form>

		</br>
		<a href="../index.php">返回首页</a>

	</div>
</body>
</html>
网友评论