ThinkPHP实现微信支付(jsapi支付)流程教程详解

之前写过一篇文章讲了PHP实现微信支付(jsapi支付)流程 ,详见文章:PHP实现微信支付(jsapi支付)流程。

当时的环境是没有使用框架的,直接在一个域名指向的目录下边新建目录之后访问该目录实现的,但应用到框架中,还是有一些问题,在ThinkPHP中,由于路由规则与支付授权目录有出入,所以会报错。本篇讲讲在TP中集成微信支付的流程。

鹅厂出的SDK和文档,就是让你看不懂,使劲绕,这酸爽用了就知道。文档和SDK不是应该越简单通俗易懂越好么?难道只有使劲重构才能显示出鹅厂程序猿技术的高超咩?额...是不是暴露了我菜鸟的属性...其实SDK蛮好用,只是上一篇文章中也看到了,在支付完成回调函数中,着实让人绕的晕头转向。

对于不想被官方绕的,想在TP中使用微信支付的可以看看一个大神自己根据官方文档重构精简打造而成的适用于TP的支付SDK,源码我下载下来看过了,代码写的很优雅简介,流程也很简单,通俗易懂。详见博文:http://baijunyao.com/article/78

我自己还是皱着眉头,使用了官方的SDK,也成功实现了支付,下面跟大家分享一下流程:

1.SDK下载和修改

这个就不过多讲了,不知道的可以看看我的上一篇文章:PHP实现微信支付(jsapi支付)流程,里边详细详述了下载下来的文件哪些是需要修改的。

2.公众号设置

A. 还是需要设置网页授权域名,这个没啥特殊的;

B. 这里要注意一下支付授权目录,使用TP很多人都使用的是重写模式(REWRITE模式)或者在使用REWRITE模式的同时,使用伪静态模式,这时候生成的链接为: http://serverName/Home/Blog/read/id/1

如果使用的是PATHINFO模式的话,生成的链接就是:http://serverName/index.php/Home/Blog/read/id/1,比如在Home模块下的Blog控制器中的某个方法进行支付,我们支付的授权目录应该是 http://serverName/Home/Blog/ 或者 http://serverName/index.php/Home/Blog/,这个根据自己的TP的设置的URL模式而定。

3.支付流程

(1)统一下单

下单的支付参数配置,这个跟上一篇讲的基本不变,重点注意的是支付回调验证链接,因为要多次调用,我就直接在Application/Common/Common/function.php中将参数配置封装起来了,我的SDK放在项目根目录下的Api目录下,所以引入SDK的时候不是使用Vendor函数。

/**
 * 微信支付
 * @param string $openId  openid
 * @param string $goods  商品名称
 * @param string $attach  附加参数,我们可以选择传递一个参数,比如订单ID
 * @param string $order_sn 订单号
 * @param string $total_fee 金额
 */
function wxpay($openId,$goods,$order_sn,$total_fee,$attach){
 require_once APP_ROOT."/Api/wxpay/lib/WxPay.Api.php";
 require_once APP_ROOT."/Api/wxpay/payment/WxPay.JsApiPay.php";
 require_once APP_ROOT.'/Api/wxpay/payment/log.php';
 //初始化日志
 $logHandler= new CLogFileHandler(APP_ROOT."/Api/wxpay/logs/".date('Y-m-d').'.log');
 $log = Log::Init($logHandler, 15);
 $tools = new JsApiPay();
 if(empty($openId)) $openId = $tools->GetOpenid();
 $input = new WxPayUnifiedOrder();
 $input->SetBody($goods);     //商品名称
 $input->SetAttach($attach);     //附加参数,可填可不填,填写的话,里边字符串不能出现空格
 $input->SetOut_trade_no($order_sn);   //订单号
 $input->SetTotal_fee($total_fee);   //支付金额,单位:分
 $input->SetTime_start(date("YmdHis"));  //支付发起时间
 $input->SetTime_expire(date("YmdHis", time() + 600));//支付超时
 $input->SetGoods_tag("test3");
 //$input->SetNotify_url("http://".$_SERVER['HTTP_HOST']."/payment.php"); //支付回调验证地址
 $input->SetNotify_url("http://".$_SERVER['HTTP_HOST']."/payment.php/WexinApi/WeixinPay/notify");
 $input->SetTrade_type("JSAPI");    //支付类型
 $input->SetOpenid($openId);     //用户openID
 $order = WxPayApi::unifiedOrder($input); //统一下单
 $jsApiParameters = $tools->GetJsApiParameters($order);
 return $jsApiParameters;
} 

注意,注意,敲黑板划重点了:

支付回调验证链接,必须是没有权限验证的,如果你自己访问那个链接,还需要登录注册验证的,就不要尝试了,必须要可以无障碍访问的链接,而且也不要有一连串的参数传递。

最好就是简单粗暴的 http://serverName/xxx.php ,我在跟目录下,类似于index.php,重新写了一个专门的供支付回调的入口文件payment.php,和它对应的Application/目录下的模块(WexinApi)、控制器(WeixinPay)及方法(notify):

// 检测PHP环境
if(version_compare(PHP_VERSION,'5.3.0','<')) die('require PHP > 5.3.0 !');
// $_GET['m']='Admin';
// 开启调试模式 建议开发阶段开启 部署阶段注释或者设为false
define('APP_DEBUG',True);
//指定模块控制器和方法
$_GET['m']='WexinApi';
$_GET['c']='WeixinPay';
$_GET['a']='notify';
// 定义应用目录
define('APP_PATH','./Application/');
define("APP_ROOT",dirname(__FILE__));
// 引入ThinkPHP入口文件
require './ThinkCore/ThinkCore.php';
// 亲^_^ 后面不需要任何代码了 就是如此简单 

现在访问 http://serverName/payment.php ,就会直接进入到  http://serverName/payment.php/WexinApi/WeixinPay/notify ,这样回调验证链接可以写  http://serverName/payment.php ,也可以写 http://serverName/payment.php/WexinApi/WeixinPay/notify

(2)发起支付

照样很简单:

/**
* 支付测试
* 微信访问:http://daoshi.sdxiaochengxu.com/payment.php/WexinApi/WeixinPay/pay
*/
public function pay(){
 $order_sn = getrand_num(true);
 $openId = '';
 $jsApiParameters = wxpay($openId,'江南极客',$order_sn,1);
 $this->assign(array(
  'data' => $jsApiParameters
 ));
 $this->display();
} 

<html>
<head>
 <meta http-equiv="content-type" content="text/html;charset=utf-8"/>
 <meta name="viewport" content="width=device-width, initial-scale=1"/>
 <title>小尤支付测试</title>
 <script type="text/javascript">
 //调用微信JS api 支付
 function jsApiCall()
 {
  var data={$data};
  WeixinJSBridge.invoke(
   'getBrandWCPayRequest', data,
   function(res){
    WeixinJSBridge.log(res.err_msg);
    //alert('err_code:'+res.err_code+'err_desc:'+res.err_desc+'err_msg:'+res.err_msg);
    //alert(res.err_code+res.err_desc+res.err_msg);
    //alert(res);
    if(res.err_msg == "get_brand_wcpay_request:ok"){
     alert("支付成功!");
     window.location.href="http://m.blog.csdn.net/article/details?id=72765676" rel="external nofollow" ;
    }else if(res.err_msg == "get_brand_wcpay_request:cancel"){
     alert("用户取消支付!");
    }else{
     alert("支付失败!");
    }
   }
  );
 }
 function callpay()
 {
  if (typeof WeixinJSBridge == "undefined"){
   if( document.addEventListener ){
    document.addEventListener('WeixinJSBridgeReady', jsApiCall, false);
   }else if (document.attachEvent){
    document.attachEvent('WeixinJSBridgeReady', jsApiCall);
    document.attachEvent('onWeixinJSBridgeReady', jsApiCall);
   }
  }else{
   jsApiCall();
  }
 }
 </script>
</head>
<body>
 <br/>
 <font color="#9ACD32"><b>该笔订单支付金额为<span style="color:#f00;font-size:50px">1分</span>钱</b></font><br/><br/>
 <font color="#9ACD32"><b><span style="color:#f00;font-size:50px;margin-left:40%;">1分</span>钱也是爱</b></font><br/><br/>
 <div align="center">
  <button style="width:210px; height:50px; border-radius: 15px;background-color:#FE6714; border:0px #FE6714 solid; cursor: pointer; color:white; font-size:16px;" type="button" onclick="callpay()" >果断买买买^_^</button>
 </div>
</body>
</html> 

不过支付页面的URL要注意了,因为支付页面的URL肯定带有不少参数,刚才说了TP中使用的REWRITE模式,你的链接为类似[  http://serverName/Home/Blog/read/id/1 ]这样的,可能带有更多参数,这时候微信支付会认为你的支付授权目录是[  http://serverName/Home/Blog/read/id/ ],但是你真实的授权目录是[  http://serverName/Home/Blog/],所以就会报错。处理方法就是,在进入支付页面的时候,重构URL,写成普通模式,即为[  http://serverName/Home/Blog/read?id=1],这样就可以了。

(3)支持成功回调

现在支付完成,就会进入到之前写好的链接对应的方法,即[  http://serverName/payment.php/WexinApi/WeixinPay/notify]:

//微信支付回调验证
public function notify(){
 $xml = $GLOBALS['HTTP_RAW_POST_DATA'];
 // 这句file_put_contents是用来查看服务器返回的XML数据 测试完可以删除了
 file_put_contents('./Api/wxpay/logs/log.txt',$xml,FILE_APPEND);
 //将服务器返回的XML数据转化为数组
 //$data = json_decode(json_encode(simplexml_load_string($xml,'SimpleXMLElement',LIBXML_NOCDATA)),true);
 $data = xmlToArray($xml);
 // 保存微信服务器返回的签名sign
 $data_sign = $data['sign'];
 // sign不参与签名算法
 unset($data['sign']);
 $sign = $this->makeSign($data);
 // 判断签名是否正确 判断支付状态
 if ( ($sign===$data_sign) && ($data['return_code']=='SUCCESS') && ($data['result_code']=='SUCCESS') ) {
  $result = $data;
  // 这句file_put_contents是用来查看服务器返回的XML数据 测试完可以删除了
  file_put_contents('./Api/wxpay/logs/log1.txt',$xml,FILE_APPEND);
  //获取服务器返回的数据
  $order_sn = $data['out_trade_no']; //订单单号
  $order_id = $data['attach'];  //附加参数,选择传递订单ID
  $openid = $data['openid'];   //付款人openID
  $total_fee = $data['total_fee']; //付款金额
  //更新数据库
  $this->updateDB($order_id,$order_sn,$openid,$total_fee);
 }else{
  $result = false;
 }
 // 返回状态给微信服务器
 if ($result) {
  $str='<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
 }else{
  $str='<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[签名失败]]></return_msg></xml>';
 }
 echo $str;
 return $result;
} 

为了安全起见,对返回过来的签名,要重新验证:

/**
* 生成签名
* @return 签名,本函数不覆盖sign成员变量
*/
protected function makeSign($data){
 //获取微信支付秘钥
 require_once APP_ROOT."/Api/wxpay/lib/WxPay.Api.php";
 $key = \WxPayConfig::KEY;
 // 去空
 $data=array_filter($data);
 //签名步骤一:按字典序排序参数
 ksort($data);
 $string_a=http_build_query($data);
 $string_a=urldecode($string_a);
 //签名步骤二:在string后加入KEY
 //$config=$this->config;
 $string_sign_temp=$string_a."&key=".$key;
 //签名步骤三:MD5加密
 $sign = md5($string_sign_temp);
 // 签名步骤四:所有字符转为大写
 $result=strtoupper($sign);
 return $result;
} 

至此,TP中微信支付也就搞定了。这是集成了官方的SDK实现的,如果不使用SDK,可以使用更简单的方法,见:PHP实现微信支付(jsapi支付)和退款(无需集成支付SDK)

总结

以上所述是小编给大家介绍的ThinkPHP实现微信支付(jsapi支付)流程教程详解,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!

您可能感兴趣的文章:

  • PHP实现微信支付(jsapi支付)和退款(无需集成支付SDK)流程教程详解
  • PHP实现微信支付(jsapi支付)流程步骤详解
  • 微信JSAPI支付操作需要注意的细节
  • 微信公众号支付之坑:调用支付jsapi缺少参数 timeStamp等错误解决方法
  • Java通过JsApi方式实现微信支付
(0)

相关推荐

  • Java通过JsApi方式实现微信支付

    要使用JsApi进行微信支付,首先要从微信获得一个prepay_id,然后通过调用微信的jsapi完成支付,JS API的返回结果get_brand_wcpay_request:ok仅在用户成功完成支付时返回.由于前端交互复杂,get_brand_wcpay_request:cancel或者get_brand_wcpay_request:fail可以统一处理为用户遇到错误或者主动放弃,不必细化区分. 示例代码如下: function onBridgeReady(){ WeixinJSBridge

  • 微信公众号支付之坑:调用支付jsapi缺少参数 timeStamp等错误解决方法

    这段时间一直比较忙,一忙起来真感觉自己就只是一台挣钱的机器了(说的好像能挣到多少钱似的,呵呵):这会儿难得有点儿空闲时间,想把前段时间开发微信公众号支付遇到问题及解决方法跟大家分享下,这些"暗坑"能不掉就不掉吧,要不然关键时刻出问题,真是让人急的焦头烂额. 双12客户的商城活动正在蓄势进行中,却有用户频频反馈说:支付不了,有问题,并截图如下: 当时问题感觉很奇怪,自己测试多次都ok啊,问题来了都赶紧解决吧,最终找到解决办法: 原因是程序中一个字符串变量被错误的设置为数字类型,解决方法很

  • PHP实现微信支付(jsapi支付)和退款(无需集成支付SDK)流程教程详解

    之前有写过几篇文章将微信支付和退款: 1.PHP实现微信支付(jsapi支付)流程 2.ThinkPHP中实现微信支付(jsapi支付)流程 3.PHP实现微信申请退款 这几篇都是使用了微信官方给的PHP版本的SDK,进行支付的时候写代码可以省不少事,步骤也挺简化,但是集成SDK有很多坑,很多人说引入的SDK老报错,或者说官方SDK本身有不少错误,改起来很麻烦,也确实挺麻烦的,对于新手搞支付很容易被绕进去,那么今天就来讲讲不集成支付SDK直接调用支付接口实现支付和退款. 前期准备: 1.当然了,

  • 微信JSAPI支付操作需要注意的细节

    首先介绍一下我在调用微信支付接口使用的是 weixin.senparc SDK,非常方便好用开源的一个微信开发SDK. weixin.senparc SDK 官网:http://weixin.senparc.com/ 先去下载下来Senparc.Weixin SDK. 在调起支付接口之前,需要先要调用统一下单接口,商户系统先调用该接口在微信支付服务后台生成预支付交易单,返回正确的预支付交易回话标识后再在APP里面调起支付. 微信 JsApi支付 在这个目录下 Senparc.Weixin.MP.

  • PHP实现微信支付(jsapi支付)流程步骤详解

    最近接触到一个项目,涉及到微信支付,搞微信开发这么久以来,还没搞过支付,之前也就搞过公众号发红包,感谢前辈们的探索,我看了他们的博文,让我少走了很多弯路. 前期准备: 1.微信认证服务号,并且开通了微信支付 2.微信支付SDK,下载地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1 3.登录微信支付平台https://pay.weixin.qq.com/index.php/account/api_cert下载支付证书

  • ThinkPHP实现微信支付(jsapi支付)流程教程详解

    之前写过一篇文章讲了PHP实现微信支付(jsapi支付)流程 ,详见文章:PHP实现微信支付(jsapi支付)流程. 当时的环境是没有使用框架的,直接在一个域名指向的目录下边新建目录之后访问该目录实现的,但应用到框架中,还是有一些问题,在ThinkPHP中,由于路由规则与支付授权目录有出入,所以会报错.本篇讲讲在TP中集成微信支付的流程. 鹅厂出的SDK和文档,就是让你看不懂,使劲绕,这酸爽用了就知道.文档和SDK不是应该越简单通俗易懂越好么?难道只有使劲重构才能显示出鹅厂程序猿技术的高超咩?额

  • Centos7 Yum安装PHP7.2流程教程详解

    Centos7Yum安装PHP7.2 1.安装源 安装php72w,是需要配置额外的yum源地址的,否则会报错不能找到相关软件包. php高版本的yum源地址,有两部分,其中一部分是epel-release,另外一部分来自webtatic.如果跳过epel-release的话,安装webtatic的时候,会有错误爆出. 所以,这里需要的命令是: rpm -Uvh https://dl.fedoraproject.org/pub/epel/7/x86_64/Packages/e/epel-rele

  • 微信小程序 支付功能实现PHP实例详解

    微信小程序 支付功能实现PHP实例详解 前端代码: wx.request({ url: 'https://www.yourhost.com/weixin/WeiActivity/payJoinfee',//改成你自己的链接 header: { 'Content-Type': 'application/x-www-form-urlencoded' }, method:'POST', success: function(res) { console.log(res.data); console.lo

  • 基于mpvue搭建微信小程序项目框架的教程详解

    简介: mpvue框架对于从没有接触过小程序又要尝试小程序开发的人员来说,无疑是目前最好的选择.mpvue从底层支持 Vue.js 语法和构建工具体系,同时再结合相关UI组件库,便可以高效的实现小程序开发 前言: 本文讲述如何搭建完整的小程序项目框架,因为是第一次使用,有不完善的地方请大佬指正. 搭建内容包括: 1.使用scss语法:依赖插件sass-loader .node-sass 2.像vue一样使用路由:依赖插件 mpvue-entry 和 mpvue-router-patch 3.使用

  • Python制作微信机器人教程详解

    目录 一.环境配置 二.登录 三. 第一个简单的消息发送监控 四.指定某个微信好友发送消息 五.所有微信群监控 六.公众号监听 七.定时发送消息 八.微信智能聊天机器人 一.环境配置 大多数人无法登录网页版,所以饶过它模拟电脑登录,这个模块一定记得安装: pip install itchat-uos pip install itchat 二.登录 #码登录个人微信账号 import itchat itchat.auto_login(hotReload=True)#hotReload= True可

  • 10k+点赞的 SpringBoot 后台管理系统教程详解

    其实项目网上有很多了,但是教程比较详细的没多少,今天分享的项目从安装部署到代码具体功能都有很详细都说明 eladmin 是一款基于 Spring Boot 2.1.0 . Jpa. Spring Security.redis.Vue 的前后端分离的后台管理系统,项目采用分模块开发方式, 权限控制采用 RBAC,支持数据字典与数据权限管理,支持一键生成前后端代码,支持动态路由. 这个开源项目基本稳定,并且后续作者还会继续优化.完全开源!这个真的要为原作者点个赞,如果大家觉得这个项目有用的话,建议可

  • SpringCloud服务网关Gateway的使用教程详解

    目录 Gateway 什么是Gateway 什么是api网关 网关的三个核心概念 路由(Route) 断言(Predicate) 过滤(Filter) gateway的工作流程 如何使用Gateway gateway路由转发 使用配置文件 使用代码配置 路由实现负载均衡 gateway九种断言 gateway过滤修改 Gateway 什么是Gateway   由于Netflix的zuul发生问题,spring公司自己研发了一套网关框架Gateway用于取代zuul的使用.什么是gateway呢?

  • windows server2016安装MySQL5.7.19解压缩版教程详解

    记录了MySQL 5.7.19 winx64解压缩版安装教程,具体内容如下 系统环境:Win7 x64 软件准备:mysql 5.7.19 winx64 下载网址:https://dev.mysql.com/downloads/mysql/ 配置安装流程 具体安装如下: 1.把 mysql-5.7.19-winx64.zip 压缩文件解压到 C:\MySQL\ 目录下: 2.在 C:\MySQL\ 目录下新建 my.ini 配置文件: 3.用文本编辑器或其他编辑器打开 my.ini 文件,把以下

随机推荐