微信扫描支付订单数据生成类[模式二]

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了微信扫描支付订单数据生成类[模式二]相关的知识,希望对你有一定的参考价值。

微信扫描支付订单数据生成类[模式二]

*

*必要条件:

*1.微信公共号

*2.微信公共号APPID

*3.微信公共号 【微信支付】 绑定的 商户号MCH_ID

*4. 微信公共号 商户支付密钥

*

* 支付流程:

* 1、调用统一下单,取得code_url,生成二维码

* 2、用户扫描二维码,进行支付

* 3、支付完成之后,微信服务器会通知支付成功

* 4、在支付成功通知中需要查单确认是否真正支付成功

业务流程说明:

(1)商户后台系统根据用户选购的商品生成订单。

(2)用户确认支付后调用微信支付【统一下单API】生成预支付交易;

(3)微信支付系统收到请求后生成预支付交易单,并返回交易会话的二维码链接code_url。

(4)商户后台系统根据返回的code_url生成二维码。

(5)用户打开微信“扫一扫”扫描二维码,微信客户端将扫码内容发送到微信支付系统。

(6)微信支付系统收到客户端请求,验证链接有效性后发起用户支付,要求用户授权。

(7)用户在微信客户端输入密码,确认支付后,微信客户端提交授权。

(8)微信支付系统根据用户授权完成支付交易。

(9)微信支付系统完成支付交易后给微信客户端返回交易结果,并将交易结果通过短信、微信消息提示用户。微信客户端展示支付交易结果页面。

(10)微信支付系统通过发送异步消息通知商户后台系统支付结果。商户后台系统需回复接收情况,通知微信后台系统不再发送该单的支付通知。

(11)未收到支付通知的情况,商户后台系统调用【查询订单API】。

(12)商户确认订单已支付后给用户发货。

<?php

class UnifiedOrder
	{
		protected $signKey=‘‘;//商户支付密钥,参考开户邮件设置(必须配置,登录商户平台自行设置)
		protected $url = "https://api.mch.weixin.qq.com/pay/unifiedorder";//扫描支付模式二提交接口
		//订单配置数据	
		protected $orderInfo=array(
				‘body‘=>‘‘,//商品支付描述
				‘attach‘=>‘‘,//附加数据
				‘out_trade_no‘=>‘‘,//交易号
				‘total_fee‘=>‘‘,//总金额
				‘time_start‘=>‘‘,//开始时间
				‘time_expire‘=>‘‘,//有效时间
				‘goods_tag‘=>‘‘,//商品
				‘notify_url‘=>‘‘,//异步通知URL
				‘trande_type‘=>‘‘,//支付类型  NATIVE
				‘product_id‘=>‘‘,//商品ID
				‘Appid‘=>‘111111‘,//公共号APPID
				‘mch_id‘=>‘111111‘,//商户号
				‘bill_create_ip‘=>‘0.0.0.0‘,//客户端IP
				‘nonce_str‘=>‘1111111‘,//随机字符串
			);
		
		//必填参数
		protected $needfileds=array(
				‘out_trade_no‘,
				‘body‘,
				‘total_fee‘,
				‘trade_type‘,
				‘product_id‘,
				‘notify_url‘,
				‘Appid‘,
				‘mch_id‘,
				‘bill_create_ip‘,
				‘nonce_str‘,
			);
			
		//获取订单配置数据	
		public function getOrderinfo()
			{
				return $this->orderInfo;
			}
			
		//设置订单数据	
		public function setOrderinfo($info=array())
			{
				if(!empty($info) && is_array($info))
					{
						foreach($info as $key=>$val)
							{
								if(isset($this->orderInfo[$key]))
									{
										$this->orderInfo[$key]=$val;
									}
							}
					}
				return true;
			}
			
		//检查必填参数
		protected function checkOrderinfo()
			{
				foreach($this->orderInfo as $key=>$val)
					{
						if(in_array($key,$this->needfileds))
							{
								if(!$val)
									{
										throw new Exception(‘缺少统一支付接口必填参数‘.$key.‘!‘);
									}
							}
					}
			}
		
		//生成签名
		protected function setSign()
			{
				ksort($this->orderInfo);
				$signstr=$this->ToKeyVal();
				$signstr=$signstr.‘&key=‘.$this->signKey;
				$signstr=strtoupper(md5($signstr));
				$this->orderInfo[‘sign‘]=$signstr;
				return $signstr;
			}
			
		protected function checkSign()
			{
				if(!$this->orderInfo[‘sign‘])
					{
						throw new Exception(‘签名错误!‘);
					}
					
				$sign=$this->setSign();
				
				if($this->orderInfo[‘sign‘]==$sign)
					{
						return true;
					}
				throw new Exception(‘签名错误!‘);
			}
			
		//生成KEY=VAL参数个数
		protected function ToKeyVal()
			{
				$keyval=‘‘;
				foreach($this->orderInfo as $key=>$val)
					{
						if(strtolower($key)!=‘sign‘ && $val !=‘‘ && !is_array($val))
							{
								$keyval .=$key.‘=‘.$val.‘&‘;
							}
					}
				$keyval=trim($keyval,‘&‘);
				return $keyval;
			}
			
		//数组转换成XML格式数据	
		protected function arrayToXml()
			{
				if(!is_array($this->orderInfo) && count($this->orderInfo)<=0)
					{
						throw new Exception(‘数组数据异常!‘);
					}
					else
						{
							$xml=‘<xml>‘;
							foreach($this->orderInfo as $k=>$v)
								{
									if(is_numeric($v))
										{
											$xml.=‘<‘.$k.‘>‘.$v.‘</‘.$k.‘>‘;
										}
										else
											{
												$xml.=‘<‘.$k.‘>![CDATA[‘.$v.‘]]</‘.$k.‘>‘;
											}
								}
							$xml.=‘</xml>‘;
							return $xml;
						}
			}	
			
		//XML格式数据转换成数组数据
		protected function xmlToArray($xml=‘‘)
			{
				if(!$xml)
					{
							throw new Exception(‘xml数据异常!‘);
					}
					else
						{
							libxml_disable_entity_loader(true);
							$this->returnData=json_decode(json_encode(@simplexml_load_string($xml, ‘SimpleXMLElement‘, LIBXML_NOCDATA)), true);
							return $this->returnData;
						}
			}
			
		//以curl方式提交数据到微信服务器
		protected function curlXml($xml, $url, $ca = 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,false);//严格校验
				//设置header
				curl_setopt($ch, CURLOPT_HEADER, FALSE);
				//要求结果为字符串且输出到屏幕上
				curl_setopt($ch, CURLOPT_RETURNTRANSFER, false);
			
				if($ca == true)
					{
						//设置证书
						//使用证书:cert 与 key 分别属于两个.pem文件
						curl_setopt($ch,CURLOPT_SSLCERTTYPE,‘PEM‘);
						curl_setopt($ch,CURLOPT_SSLCERT, ‘./apiclient_cert.pem‘);
						curl_setopt($ch,CURLOPT_SSLKEYTYPE,‘PEM‘);
						curl_setopt($ch,CURLOPT_SSLKEY, ‘./apiclient_key.pem‘);
					}
				//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);
							throw new Exception("curl出错,错误码:$error");
						}
			}
			
		protected function wxReply($reply=‘‘)
			{
				$this->orderInfo=$this->xmlToArray($reply);
				if($this->orderInfo[‘return_code‘] != ‘SUCCESS‘)
					{
						 return $this->orderInfo;
					}
					
				$this->CheckSign();
				return $this->orderInfo;
			}
			
		//发送请求数据到微信服务器
		public function requestXml($info=array())
			{
				$this->setOrderinfo($info);//设置数据
				$this->checkOrderinfo();//检查必填参数
				$this->setSign();//生成签名
				
				$xml=$this->arrayToXml();//数据格式转换
				$result=$this->curlXml($xml,$this->url,false);//curl发送数据
				$result=$this->wxReply($result);//返回结果处理 
				
				return $result;
			}
			
		
	}

	$class = new UnifiedOrder();
	$info=array(
				‘body‘=>‘test‘,
				‘attach‘=>‘test‘,
				‘out_trade_no‘=>date("YmdHis"),
				‘total_fee‘=>‘1‘,
				‘time_start‘=>date("YmdHis"),
				‘time_expire‘=>date("YmdHis", time() + 600),
				‘goods_tag‘=>‘test‘,
				‘notify_url‘=>‘http://localhost/WXqrpay/notify.php‘,
				‘trande_type‘=>‘NATIVE‘,
				‘product_id‘=>‘10000000111‘,
			);
	$class->requestXml($info);
	$result=$class->getOrderinfo();
	var_dump($result);
?>


本文出自 “一片绿叶一片晴天” 博客,请务必保留此出处http://yipianlvye.blog.51cto.com/8733190/1918971

以上是关于微信扫描支付订单数据生成类[模式二]的主要内容,如果未能解决你的问题,请参考以下文章

微信支付公的众号支付和扫码支付

微信公众号 扫码支付 模式二 demo

微信支付

支付业务模块

SpringBoot整合微信支付

设计模式 - 策略模式