博客列表 >APP 调微信支付-统一下单

APP 调微信支付-统一下单

sky的博客
sky的博客原创
2018年04月04日 21:39:411120浏览
<?php
namespace Api\Controller;
use Think\Controller;
//别的框架改改也可以用
//WeChatPayController.class.php 文件名

/**
 * 
 * 微信APP 支付 + 回调  适用于TP3.2
 *
 */

class WeChatPayController extends Controller {
	private $appid = '**';//appID
	private $mch_id = '**';//商户ID
	private $key = '***S';//key
	private $notify ='****';//回调地址
	private $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';//统一下请求地址

	/**
	 * 微信统一下单接口
	 * 请求类型 :POST
	 * 所需参数 order 订单号 body 商品描述 total 金额
	 * @return json
	 *
	 * 
	 */

	public function index() {
		//订单号
		$order = I('post.order', time() . mt_rand('1000', '9999'));
		//内容
		$body = I('post.body', '测试');
		//金额默认为0.01
		$total = ltrim(I('post.total', '0.01'),'-') * 100;
		$array = ['appid' => $this -> appid,
		 'mch_id' => $this -> mch_id,
		  'nonce_str' => $this -> randomCreateStr(), 
		  'body' => $body, 'out_trade_no' => $order, 
		  'total_fee' => $total, 
		  'spbill_create_ip' => $this->getIp(),
		 'notify_url' => $this->notify, 
		 'trade_type' => 'APP'];
		
		//生成签名
		$sign = $this -> createSign($array);
		$array['sign'] = $sign;
		
		//生成xml
		$xml = $this -> createXml($array);
		//发送给微信服务器
		$WeChatXml = $this -> postUrl($this -> url, $xml);
		//转为数组
		$WeChatArray = $this -> XMLDataParse($WeChatXml);
		//进行判定
		if ($WeChatArray['return_code'] != 'SUCCESS' || $WeChatArray['result_code'] != 'SUCCESS') {
			exit(json_encode(['error' => 1, 'message' => $WeChatArray], JSON_UNESCAPED_UNICODE));
		}
		//对微信返回的签名进行验证是否正确
		if (!$this -> verifySign($WeChatArray)) {
			exit(json_encode(['error' => 1, 'message' => '微信返回签名失败'], JSON_UNESCAPED_UNICODE));
		}
		//组合要给APP 发送的数据
		
		$AppArray = [
		'appid' => $this -> appid,
		'partnerid' => $this -> mch_id,
		'prepayid' =>$WeChatArray['prepay_id'],
		'package' =>'Sign=WXPay',
		'noncestr'=>$this->randomCreateStr(),
		'timestamp'=>time()
		
		];
		
		//进行签名
		$sign = $this -> createSign($AppArray);
		$AppArray['sign'] = $sign;
		//转换成JSON 返回给APP
		exit(json_encode($AppArray));

	}

	/**
	 *微信回调地址接口 
	 * 
	 * 
	 * 
	 */
	public function notify() {
		//接收微信xml格式信息
		 $xmlData = file_get_contents('php://input');
		 //转换为数组
		$array = json_decode($xmlData,TRUE);
		 $array = $this-> XMLDataParse($xmlData);
		 //对微信返回的签名进行验证是否正确
		if (!$this -> verifySign($array)) {
			exit('<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[签名不正确]]></return_msg></xml>');
		}
		
		/**
		 * !!!注意: 下面的就是连接数据库了,做进一步处理
		 * 
		 * 
		 * 
		 */
		
		//下面是处理完逻辑,返回给微信服务器的
		//exit('<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>');
		
	}




	 private function postUrl($url, $paramsArray) {
		$curl = curl_init();
		// 启动一个CURL会话
		curl_setopt($curl, CURLOPT_URL, $url);
		// 要访问的地址
		curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
		// 跳过证书检查
		//curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); // 对认证证书来源的检查
		//curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 1); // 从证书中检查SSL加密算法是否存在
		//curl_setopt($curl, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']); // 模拟用户使用的浏览器
		//curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); // 使用自动跳转
		curl_setopt($curl, CURLOPT_AUTOREFERER, 1);
		// 自动设置Referer
		curl_setopt($curl, CURLOPT_POST, 1);
		// 发送一个常规的Post请求
		curl_setopt($curl, CURLOPT_POSTFIELDS, $paramsArray);
		// Post提交的数据包
		curl_setopt($curl, CURLOPT_TIMEOUT, 30);
		// 设置超时限制防止死循环
		curl_setopt($curl, CURLOPT_HEADER, 0);
		// 显示返回的Header区域内容
		curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
		// 获取的信息以文件流的形式返回
		$tmpInfo = curl_exec($curl);
		// 执行操作
		if (curl_errno($curl)) {
			echo 'Errno' . curl_error($curl);
			//捕抓异常
		}
		curl_close($curl);
		// 关闭CURL会话
		return $tmpInfo;
		// 返回数据,json格式

	}

	/**
	 * 获取IP 地址
	 *
	 *
	 */

	private function getIp() {
		if (getenv("HTTP_CLIENT_IP") && strcasecmp(getenv("HTTP_CLIENT_IP"), "unknown"))
			$ip = getenv("HTTP_CLIENT_IP");
		else if (getenv("HTTP_X_FORWARDED_FOR") && strcasecmp(getenv("HTTP_X_FORWARDED_FOR"), "unknown"))
			$ip = getenv("HTTP_X_FORWARDED_FOR");
		else if (getenv("REMOTE_ADDR") && strcasecmp(getenv("REMOTE_ADDR"), "unknown"))
			$ip = getenv("REMOTE_ADDR");
		else if (isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], "unknown"))
			$ip = $_SERVER['REMOTE_ADDR'];
		else
			$ip = "unknown";
		return ($ip);
	}

	/**
	 * 验证签名
	 *
	 *
	 */
	private  function verifySign($array) {
		$sign = $array['sign'];
		unset($array['sign']);
		$s = $this -> createSign($array);
		return $s == $sign ? TRUE : FALSE;
	}

	/**
	 * 生成签名
	 * @param $array array 参数 以关联数组 的形势
	 *
	 * @return str 签名
	 */
	private function createSign($array) {
		ksort($array);
		$stringA = '';
		foreach ($array as $ke => $value) {
			$stringA .= $ke . '=' . $value . '&';
		}

		//$stringA = http_build_query($array);
		$stringSignTemp = $stringA . "key=" . $this -> key;
		$sign = strtoupper(md5($stringSignTemp));
		return $sign;
	}

	/**
	 * 生成XML 格式文件
	 * @param $array array 参数 以关联数组 的形势
	 *
	 * @return str xml字符串
	 */
	private function createXml($array) {
		$xml = '<xml>';
		foreach ($array as $key => $value) {
			$xml .= '<' . $key . '>' . $value . '</' . $key . '>';
		}
		$xml .= '</xml>';
		return $xml;
	}

	/**
	 * 随机生成32位字符串
	 * @return str 32位字符串
	 */
	private function randomCreateStr() {
		return strtoupper(md5(microtime(TRUE) . mt_rand(0, 9999)));
	}

	/**
	 * xml格式数据解析函数
	 * @param $xml str  微信返回的xml格式字符串
	 *
	 * @return array 数组
	 */

	private function XMLDataParse($xml) {

		$array_data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
		return $array_data;
	}
上一条:2-迷你计算器下一条:PHP无限分类
声明:本文内容转载自脚本之家,由网友自发贡献,版权归原作者所有,如您发现涉嫌抄袭侵权,请联系admin@php.cn 核实处理。
全部评论
文明上网理性发言,请遵守新闻评论服务协议