PHP实现APP微信支付的实例讲解


Posted in PHP onFebruary 10, 2018

一、PHP后台后台生成预支付交易单,返回正确的预支付交易回话标识后再在APP里面调起支付!

官方文档:https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_1

根据文档拼接微信需要的参数,这里需要几个方法,直接上代码!

传输给微信的参数要组装成xml格式发送,传如参数数组!

public function ToXml($data=array())
 {
 if(!is_array($data) || count($data) <= 0)
 {
  return '数组异常';
 }
 $xml = "<xml>";
 foreach ($data as $key=>$val)
 {
  if (is_numeric($val)){
  $xml.="<".$key.">".$val."</".$key.">";
  }else{
  $xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
  }
 }
 $xml.="</xml>";
 return $xml;
 }

2.生成随机字符串,微信所需参数! 这里方法很多,看自己爱好都行!

function rand_code(){
 $str = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';//62个字符
 $str = str_shuffle($str);
 $str = substr($str,0,32);
 return $str;
}

3.这里是微信比较重要的一步了,这个方法会多次用到!生成签名

private function getSign($params) {
 ksort($params); //将参数数组按照参数名ASCII码从小到大排序
 foreach ($params as $key => $item) {
  if (!empty($item)) {  //剔除参数值为空的参数
  $newArr[] = $key.'='.$item; // 整合新的参数数组
  }
 }
 $stringA = implode("&", $newArr);  //使用 & 符号连接参数
 $stringSignTemp = $stringA."&key="."************************"; //拼接key
 // key是在商户平台API安全里自己设置的
 $stringSignTemp = MD5($stringSignTemp); //将字符串进行MD5加密
 $sign = strtoupper($stringSignTemp); //将所有字符转换为大写
 return $sign;
 }

4.传递参数给微信,生成预支付订单! 接收微信返回的数据,在反给APP端,APP端调用支付接口,完成支付 ! APP端所需参数见微信文档:https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_12&index=2

public function wx_pay() {
 $nonce_str = $this->rand_code(); //调用随机字符串生成方法获取随机字符串
 $data['appid'] ='wxdbc5dc*******'; //appid
 $data['mch_id'] = '1493*****' ; //商户号
 $data['body'] = "APP支付测试";
 $data['spbill_create_ip'] = $_SERVER['HTTP_HOST']; //ip地址
 $data['total_fee'] = 1;    //金额
 $data['out_trade_no'] = time().mt_rand(10000,99999); //商户订单号,不能重复
 $data['nonce_str'] = $nonce_str;   //随机字符串
 $data['notify_url'] = 'http://xxx.xxx.com/wx_notify'; //回调地址,用户接收支付后的通知,必须为能直接访问的网址,不能跟参数
 $data['trade_type'] = 'APP'; //支付方式
 //将参与签名的数据保存到数组 注意:以上几个参数是追加到$data中的,$data中应该同时包含开发文档中要求必填的剔除sign以外的所有数据
 $data['sign'] = $this->getSign($data); //获取签名
 $xml = $this->ToXml($data);  //数组转xml
 //curl 传递给微信方
 $url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
 //header("Content-type:text/xml");
 $ch = curl_init();
 curl_setopt($ch,CURLOPT_URL, $url);
 if(stripos($url,"https://")!==FALSE){
  curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1);
  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
  curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
 } else {
  curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,TRUE);
  curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,2);//严格校验
 }
 //设置header
 curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1);
 curl_setopt($ch, CURLOPT_HEADER, FALSE);
 //要求结果为字符串且输出到屏幕上
 curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
 //设置超时
 curl_setopt($ch, CURLOPT_TIMEOUT, 30);
 curl_setopt($ch, CURLOPT_POST, TRUE);
 //传输文件
 curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
 //运行curl
 $data = curl_exec($ch);
 //返回结果
 if($data){
  curl_close($ch);
  //返回成功,将xml数据转换为数组.
  $re = $this->FromXml($data);
  if($re['return_code'] != 'SUCCESS'){
  json("201",'签名失败');
  }
  else{
  //接收微信返回的数据,传给APP!
  $arr =array(
   'prepayid' =>$re['prepay_id'],
   'appid' => 'wxdbc5dc*****',
   'partnerid' => '14937****',
   'package' => 'Sign=WXPay',
   'noncestr' => $nonce_str,
   'timestamp' =>time(),
  );
  //第二次生成签名
  $sign = $this->getSign($arr);
  $arr['sign'] = $sign;
  json('200','签名成功',$arr);
  }
 } else {
  $error = curl_errno($ch);
  curl_close($ch);
  json('201',"curl出错,错误码:$error");
 }
 }

5.将xml数据转换为数组,接收微信返回数据时用到.

public function FromXml($xml)
 {
 if(!$xml){
  echo "xml数据异常!";
 }
 //将XML转为array
 //禁止引用外部xml实体
 libxml_disable_entity_loader(true);
 $data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
 return $data;
 }

二、APP支付成功后,会调用你填写的回调地址.

返回参数详见微信文档:https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_7&index=3

// 微信支付回调
 function wx_notify(){
  //接收微信返回的数据数据,返回的xml格式
  $xmlData = file_get_contents('php://input');
  //将xml格式转换为数组
  $data = $this->FromXml($xmlData);
  //用日志记录检查数据是否接受成功,验证成功一次之后,可删除。
  $file = fopen('./log.txt', 'a+');
  fwrite($file,var_export($data,true));
  //为了防止假数据,验证签名是否和返回的一样。
  //记录一下,返回回来的签名,生成签名的时候,必须剔除sign字段。
  $sign = $data['sign'];
  unset($data['sign']);
  if($sign == $this->getSign($data)){
  //签名验证成功后,判断返回微信返回的
  if ($data['result_code'] == 'SUCCESS') {
  //根据返回的订单号做业务逻辑
  $arr = array(
   'pay_status' => 1,
   );
  $re = M('order')->where(['order_sn'=>$data['out_trade_no']])->save($arr);
  //处理完成之后,告诉微信成功结果!
  if($re){
   echo '<xml>
  <return_code><![CDATA[SUCCESS]]></return_code>
  <return_msg><![CDATA[OK]]></return_msg>
  </xml>';exit();
  }
  }
  //支付失败,输出错误信息
  else{
  $file = fopen('./log.txt', 'a+');
  fwrite($file,"错误信息:".$data['return_msg'].date("Y-m-d H:i:s"),time()."\r\n"); 
  }
 }
 else{
  $file = fopen('./log.txt', 'a+');
  fwrite($file,"错误信息:签名验证失败".date("Y-m-d H:i:s"),time()."\r\n"); 
  }
}

在这里,微信APP支付流程就成功走完了!谢谢支持!

以上这篇PHP实现APP微信支付的实例讲解就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

PHP 相关文章推荐
php连接数据库代码应用分析
May 29 PHP
php中serialize序列化与json性能测试的示例分析
Apr 27 PHP
PHP数字字符串左侧补0、字符串填充和自动补齐的几种方法
May 10 PHP
php中cookie实现二级域名可访问操作的方法
Nov 11 PHP
PHP中round()函数对浮点数进行四舍五入的方法
Nov 19 PHP
php分割合并两个字符串的函数实例
Jun 19 PHP
解决laravel 5.1报错:No supported encrypter found的办法
Jun 07 PHP
PHP基于ORM方式操作MySQL数据库实例
Jun 21 PHP
php使用scandir()函数扫描指定目录下所有文件示例
Jun 08 PHP
解决laravel资源加载路径设置的问题
Oct 14 PHP
Laravel 手动开关 Eloquent 修改器的操作方法
Dec 30 PHP
PHP设计模式之 策略模式Strategy详解【对象行为型】
May 01 PHP
PHP有序表查找之插值查找算法示例
Feb 10 #PHP
PHP有序表查找之二分查找(折半查找)算法示例
Feb 09 #PHP
php在windows环境下获得cpu内存实时使用率(推荐)
Feb 08 #PHP
PHP基于redis计数器类定义与用法示例
Feb 08 #PHP
php处理抢购类功能的高并发请求
Feb 08 #PHP
php+redis实现商城秒杀功能
Nov 19 #PHP
php+redis消息队列实现抢购功能
Feb 08 #PHP
You might like
PHP中读取照片exif信息的方法
2014/08/20 PHP
php+jQuery+Ajax实现点赞效果的方法(附源码下载)
2020/07/21 PHP
TP5框架实现签到功能的方法分析
2020/04/05 PHP
浅谈Javascript嵌套函数及闭包
2010/11/09 Javascript
javascript的解析执行顺序在各个浏览器中的不同
2014/03/17 Javascript
在Javascript中处理数组之toSource()方法的使用
2015/06/09 Javascript
javascript实现拖放效果
2015/12/16 Javascript
JS表单验证的代码(常用)
2016/04/08 Javascript
jQuery的文档处理程序详解
2016/05/10 Javascript
关于Angular2 + node接口调试的解决方案
2017/05/28 Javascript
原生JS+Canvas实现五子棋游戏
2020/05/28 Javascript
关于JavaScript语句后面的分号问题
2017/12/07 Javascript
vue 项目打包通过命令修改 vue-router 模式 修改 API 接口前缀
2018/06/13 Javascript
微信小程序支付PHP代码
2018/08/23 Javascript
Vue使用Proxy代理后仍无法生效的解决
2020/11/13 Javascript
python实现带验证码网站的自动登陆实现代码
2015/01/12 Python
Python2.X/Python3.X中urllib库区别讲解
2017/12/19 Python
numpy.transpose对三维数组的转置方法
2018/04/17 Python
Python 监测文件是否更新的方法
2019/06/10 Python
如何解决django-celery启动后迅速关闭
2019/10/16 Python
Python 过滤错误log并导出的实例
2019/12/26 Python
python中如何设置代码自动提示
2020/07/15 Python
Python Django路径配置实现过程解析
2020/11/05 Python
巴黎卡诗美国官方网站:始于1964年的头发头皮护理专家
2017/07/10 全球购物
欧洲最大的品牌水上运动服装和设备在线零售商:Wuituit Outlet
2018/05/05 全球购物
NBA欧洲商店(英国):NBA Europe Store UK
2018/07/27 全球购物
群胜软件Java笔试题
2012/09/29 面试题
Linux管理员面试经常问道的相关命令
2014/12/12 面试题
口腔工艺技术专业毕业生自荐信
2013/09/27 职场文书
商场拾金不昧表扬信
2014/01/13 职场文书
今冬明春火灾防控工作方案
2014/05/29 职场文书
2014年资料员工作总结
2014/11/18 职场文书
护理工作个人总结
2015/03/03 职场文书
英文诗歌翻译方法(赏析)
2019/08/16 职场文书
python套接字socket通信
2022/04/01 Python
安装Windows Server 2012 R2企业版操作系统并设置好相关参数
2022/04/29 Servers