namespace Api\Controller;
use Think\Controller;
/**
* 用别的框架改改也可以用
* 微信APP 支付 + 回调 适用于TP3.2
* 控制器名::WeChatPayController.class.php
*/
class WeChatPayController extends Controller {
private $appid = '###';//appID
private $mch_id = '##';//商户ID
private $key = '###';//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('');
}
/**
* !!!注意: 下面的就是连接数据库了,做进一步处理
*
*
*
*/
//下面是处理完逻辑,返回给微信服务器的
//exit('');
}
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 = '';
foreach ($array as $key => $value) {
$xml .= '' . $value . '' . $key . '>';
}
$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;
}
}