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 和 MySQL 时区的一点总结
Mar 26 PHP
php jquery 多文件上传简单实例
Dec 23 PHP
一个好用的PHP验证码类实例分享
Dec 27 PHP
php之Smarty模板使用方法示例详解
Jul 08 PHP
php实现的ping端口函数实例
Nov 12 PHP
php检查字符串中是否包含7位GSM字符的方法
Mar 17 PHP
php多线程实现方法及用法实例详解
Oct 26 PHP
php验证码生成器
May 24 PHP
PHP堆栈调试操作简单示例
Jun 15 PHP
PHP获取ttf格式文件字体名的方法示例
Mar 06 PHP
php设计模式之抽象工厂模式分析【星际争霸游戏案例】
Jan 23 PHP
MacOS下PHP7.1升级到PHP7.4.15的方法
Feb 22 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
德生BCL3000的电路分析和打磨
2021/03/02 无线电
php a simple smtp class
2007/11/26 PHP
php empty函数判断mysql表单是否为空
2010/04/12 PHP
codeigniter教程之上传视频并使用ffmpeg转flv示例
2014/02/13 PHP
php实现阿拉伯数字和罗马数字相互转换的方法
2015/04/17 PHP
php阿拉伯数字转中文人民币大写
2015/12/21 PHP
TP5框架简单登录功能实现方法示例
2019/10/31 PHP
javascript Array.prototype.slice的使用示例
2013/11/14 Javascript
使用Chrome调试JavaScript的断点设置和调试技巧
2014/12/16 Javascript
基于JavaScript实现通用tab选项卡(通用性强)
2016/01/07 Javascript
HTML5游戏引擎LTweenLite实现的超帅动画效果(附demo源码下载)
2016/01/26 Javascript
用NODE.JS中的流编写工具是要注意的事项
2016/03/01 Javascript
Markdown+Bootstrap图片自适应属性详解
2016/05/21 Javascript
JavaScript数组方法大全(推荐)
2016/07/05 Javascript
教你JS中的运算符乘方、开方及变量格式转换
2016/08/09 Javascript
AngularJS 限定$scope的范围实例详解
2017/06/23 Javascript
vue实现引入本地json的方法分析
2018/07/12 Javascript
Vue-cli3项目引入Typescript的实现方法
2019/10/18 Javascript
微信小程序实现简单的select下拉框
2020/11/23 Javascript
python字符串与url编码的转换实例
2018/05/10 Python
redis之django-redis的简单缓存使用
2018/06/07 Python
Python 3.x基于Xml数据的Http请求方法
2018/12/28 Python
对Python3 解析html的几种操作方式小结
2019/02/16 Python
python如何实现读取并显示图片(不需要图形界面)
2020/07/08 Python
python实现数学模型(插值、拟合和微分方程)
2020/11/13 Python
Django 权限管理(permissions)与用户组(group)详解
2020/11/30 Python
在PyCharm中安装PaddlePaddle的方法
2021/02/05 Python
Beach Bunny Swimwear官网:设计师泳装和性感比基尼
2019/03/13 全球购物
娇韵诗俄罗斯官方网站:Clarins俄罗斯
2020/10/03 全球购物
奖学金自我鉴定范文
2013/10/03 职场文书
销售类求职信
2014/06/13 职场文书
付款证明格式范文
2015/06/19 职场文书
2015年政治教研组工作总结
2015/07/22 职场文书
《司马光》教学反思
2016/02/22 职场文书
祝福语集锦:给百岁老人祝寿贺词
2019/11/19 职场文书
python内置模块之上下文管理contextlib
2022/06/14 Python