php调微信app支付教程,APP 调微信支付功能

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;

}

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
微信 支付这 官方文档 很乱 写的 也不是很清楚,测试时 一定要与安卓 或 苹果端 一起测试。 否则 根本找不到问题。 废话 不过说 先 说说 几大坑的地方。我也是 借鉴 别人的 博客 才测试成功调起支付。文章后 直接上代码 代码 绝对能调起 微信 测试过的! 第一步,生成prepayid,这一步,只要你的appid,mch_id,key没写错,那么99%以上都能获取到prepayid,如果失败,那肯定是几个ID和key有问题,仔细检查,包括编码等,仔细仔细仔细检查。 问题来了,第二步,对获取到的prepayid进行二次签名,官方文档的坑来了,官方并没有详细说明这一步骤,一切的一切只能靠自己摸索,爬坑。 首先第一坑:参数顺序,我这里用了SortedMap,自动对参数进行asc编码顺序,一劳永逸,当然,也可以用其他map,但一定要注意参数顺序,必须是asc编码顺序。 第二坑:参数package的Sign=WXPay中=的编码问题,转码即可,小坑。 第三坑:苹果系统的timestamp位数,统一成10位即可,小坑。 第四坑:次级大坑,注意,官方文档说到的参与二次签名的参数,prepayId,appId,timeStamp等,如果你用他们的驼峰进行大写,那么你就完了。一定要小写,小写,小写。 第五坑:最大坑,一样,官方文档并没有对于二次签名有过多赘述,如果你上面几个坑完美出坑,那么,你获取到的签名sign跟官方验证的sign绝对是一样的,然而,将这些玩意丢回给APPAPP调起支付,大大的几个字出现了,验证签名失败!WTF!不要急,我已折腾了好几天,终于发现坑在哪里,那就是noncestr随机字符串,参与二次签名的随机字符串不能再次生成,注意,不能再次生成,一定要用第一步中获取prepayid时的那串字符串,一定要用第一步中获取prepayid时的那串字符串,一定要用第一步中获取prepayid时的那串字符串。 第六坑:经历了上述5坑,相信你已经有想干死人的冲动,那么你以为这就结束了吗,还有最后一坑,那就是APP签名已经包名,一定要与开放平台中的一致,然而,即使一致了你以为又结束了吗,NO,如果你更改过开放平台中的签名,并且,在更改前用过APP微信支付,那么一定一定一定一定记得清除微信缓存。 至此,所有坑都成功出坑,终于出现了支付页面,举国欢腾,微信去年买了个表。最后附上MD5签名类
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值