微信支付PHP SDK之微信公众号支付代码详解

这里假设你已经申请完微信支付

1. 微信后台配置  如图

我们先进行测试,所以先把测试授权目录和 测试白名单添加上。测试授权目录是你要发起微信请求的哪个文件所在的目录。

例如jsapi 发起请求一般是jsapi.php所在目录 为测试目录,测试白名单即开发人员的微信号。

正式的支付授权目录不能和测试的一样否则会报错。不填写或者填错授权目录以及测试白名单都会报错。

报错样例:

NaNsystem:access_denied

不在测试白名单

2. 配置 lib/WxPay.Config.php文件

最主要配置一下四项:

const APPID = '';
const MCHID = '';
const KEY = '';
const APPSECRET = '';
APPID 和 APPSECRET都可以在微信后台中找到。
MCHID 在申请微信支付后发来的邮件中可以找到,KEY 则根据邮件提示

去商户平台配置即可。

3. 访问起始 index.php

首先访问 index.php 你可以看到界面

我们首先需要的是 JSAPI支付。但是看代码 index.php 最下面的链接。他默认是个demo的链接,改为我们自定义的即可

<ul>
  <li style="background-color:#FF7F24"><a href="<?php echo 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'].'example/jsapi.php';?>">JSAPI支付</a></li>
  <li style="background-color:#698B22"><a href="<?php echo 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'].'example/micropay.php';?>">刷卡支付</a></li>
  <li style="background-color:#8B6914"><a href="<?php echo 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'].'example/native.php';?>">扫码支付</a></li>
  <li style="background-color:#CDCD00"><a href="<?php echo 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'].'example/orderquery.php';?>">订单查询</a></li>
  <li style="background-color:#CD3278"><a href="<?php echo 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'].'example/refund.php';?>">订单退款</a></li>
  <li style="background-color:#848484"><a href="<?php echo 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'].'example/refundquery.php';?>">退款查询</a></li>
  <li style="background-color:#8EE5EE"><a href="<?php echo 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'].'example/download.php';?>">下载订单</a></li>
</ul>

当然你也可以直接写死为自己的访问链接。

4. JSAPI 支付

必要代码解析:

$logHandler= new CLogFileHandler("../logs/".date('Y-m-d').'.log');
$log = Log::Init($logHandler, 15);

调用日志类 可以通过 $log->DEBUG(‘test‘); 打印调试信息。其实也可以直接使用 $Log::DEBUG(‘test‘); 来调试

$tools = new JsApiPay();
$openId = $tools->GetOpenid();

主要是为了获取 openid 其中GetOpenid() 函数定义在 文件 WxPay.JsApiPay.php 文件中

public function GetOpenid()
 {
 //通过code获得openid
 if (!isset($_GET['code'])){
  //触发微信返回code码
  $baseUrl = urlencode('http://'.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'].$_SERVER['QUERY_STRING']);
  $url = $this->__CreateOauthUrlForCode($baseUrl);
  Header("Location: $url");
  exit();
 } else {
  //获取code码,以获取openid
   $code = $_GET['code'];
  $openid = $this->getOpenidFromMp($code);
  return $openid;
 }
 }

$baseUrl 其实就是为了在跳转回来这个页面。  可以继续跟踪函数__CreateOauthUrlForCode()  其实就是通过微信的Auth2.0 来获取Openid

参考链接:http://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html

这就需要你把微信的 网页授权接口也设置好。

获取到 Openid 就可以调用微信支付的统一下单接口了。回到 文件 jsapi.php 如下代码

$input = new WxPayUnifiedOrder();
$input->SetBody("test");
$input->SetAttach("test");
$input->SetOut_trade_no(WxPayConfig::MCHID.date("YmdHis"));
$input->SetTotal_fee("1");
$input->SetTime_start(date("YmdHis"));
$input->SetTime_expire(date("YmdHis", time() + 600));
$input->SetGoods_tag("test");
$input->SetNotify_url("http://paysdk.weixin.qq.com/example/notify.php");
$input->SetTrade_type("JSAPI");
$input->SetOpenid($openId);
$order = WxPayApi::unifiedOrder($input);
echo '<font color="#f00"><b>统一下单支付单信息</b></font><br/>';
printf_info($order);
$jsApiParameters = $tools->GetJsApiParameters($order);

这里面的代码:

$input->SetAttach("test");

如果 把值改为 $input->SetAttach("test this is attach");就会存在bug 后面再说,其实这个参数不是必须的干脆可以去掉。

代码:

$input->SetNotify_url(http://paysdk.weixin.qq.com/example/notify.php);

是设置接收支付结果通知的Url 这里是默认的demo 链接我们可以设置成我们的:

$input->SetNotify_url(dirname('http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']).'/notify.php');

当然你也可以选择直接写死。
其中的函数 unifiedOrder($input) 可以到WxPay.Api.php 中文件跟踪,其实就是调用统一下单接口。

在 WxPay.Api.php 中需要更改的一处代码是:

//异步通知url未设置,则使用配置文件中的url
    if(!$inputObj->IsNotify_urlSet()){
      $inputObj->SetNotify_url(WxPayConfig::NOTIFY_URL);//异步通知url
    }

就是当没设置 notifyUrl 的时候回去配置文件中找,但是配置文件中根本没有设置。

所以你可以选择在 配置文件WxPay.Config.php 中加上这个配置,也可以直接写一个默认的notify链接。

函数 GetJsApiParameters() 是获取jsApi支付的参数给变量 $jsApiParameters 方便在下面的Js中调用

jsapi.php 中js的代码:

function jsApiCall()
 {
 WeixinJSBridge.invoke(
  'getBrandWCPayRequest',
  <?php echo $jsApiParameters; ?>,
  function(res){
  WeixinJSBridge.log(res.err_msg);
  alert(res.err_code+res.err_desc+res.err_msg);
  }
 );
 }
 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();
 }
 }

其中点击立即支付按钮调用的就是 callpay() 函数,他有会调用jsApiCall() 函数打开支付程序。
此后输入密码完成支付。

在完成支付页面点击完成会回到这个支付页面,并弹出 支付成功的提示框

这个其实就是 js函数 jsApiCall 里面的alter 弹出的对话框

其中 res.err_msg 为get_brand_wcpay_request:ok 表明前端判断的支付成功,我们可以根据这个将支付跳转到成功页面。

但是这个并不可信。确认是否支付成功还是应当 通过notify.php 处理业务逻辑。

5. 支付结果通知 notify.php

其实这个页面最主要的代码就两行

$notify = new PayNotifyCallBack();
$notify->Handle(false);

其中大部分逻辑在 Handle 函数中处理 文件 WxPay.Notify.php

final public function Handle($needSign = true)
 {
 $msg = "OK";
 //当返回false的时候,表示notify中调用NotifyCallBack回调失败获取签名校验失败,此时直接回复失败
 $result = WxpayApi::notify(array($this, 'NotifyCallBack'), $msg);
 if($result == false){
  $this->SetReturn_code("FAIL");
  $this->SetReturn_msg($msg);
  $this->ReplyNotify(false);
  return;
 } else {
  //该分支在成功回调到NotifyCallBack方法,处理完成之后流程
  $this->SetReturn_code("SUCCESS");
  $this->SetReturn_msg("OK");
 }
 $this->ReplyNotify($needSign);
 }

主要代码:

$result = WxpayApi::notify(array($this, 'NotifyCallBack'), $msg);

跟踪函数 notify 文件WxPay.Api.php

public static function notify($callback, &$msg)
 {
 //获取通知的数据
 $xml = $GLOBALS['HTTP_RAW_POST_DATA'];
 //如果返回成功则验证签名
 try {
  $result = WxPayResults::Init($xml);
 } catch (WxPayException $e){
  $msg = $e->errorMessage();
  return false;
 }

 return call_user_func($callback, $result);
 }

通过 $GLOBALS[‘HTTP_RAW_POST_DATA‘]; 获取同志数据 然后 Init 函数验证签名等。验签成功运行代码

return call_user_func($callback, $result);

即调用了一个回调函数,NotifyCallBack() 函数并传递参数 $result 在NotifyCallBack函数中会调用我们重写的NotifyProcess()函数(此函数在notify.php 中被重写)

NotifyProcess() 判断也没有问题就会 设置返回 success的xml信息

$this->SetReturn_code("SUCCESS");
$this->SetReturn_msg("OK");

并最终调用函数 $this->ReplyNotify($needSign);  echo success的结果

函数ReplyNotify 需要修改一处代码:

final private function ReplyNotify($needSign = true)
 {
 //如果需要签名
 if($needSign == true &&
  $this->GetReturn_code($return_code) == "SUCCESS")
 {
  $this->SetSign();
 }
 WxpayApi::replyNotify($this->ToXml());
 }

$this->GetReturn_code($return_code) == "SUCCESS")

改为

$this->GetReturn_code() == "SUCCESS")

即可。

这样整个流程就结束了。上面提到了 传递订单参数

$input->SetAttach("test");

如果我设置 值为 test this is attach (其实只要有空格就会存在bug)
如图 传递的订单信息

可以看到 attach 信息正常,当然支付也是正常的没有任何问题。

但是发现总是会收到notify 通知,即意味着没有返回给微信服务器正确的结果通知。

打印服务器发来的通知数据

可以看到 attach 是 test+this+is+attach 即空格被转化为加号

打印接收到的签名和程序算出来的签名发现 签名不同,即认为接收结果异常。

所以我们要是想使用attach 这个值就不能有空格,要么干脆不使用这个参数

(等待微信修复这个bug, 也可能是我这边有哪个地方不会? - -#)

这样 微信支付的 JsApi支付就大致分析完成了。

时间: 2015-12-08

php微信支付之APP支付方法

本文实例讲述了微信开放平台移动应用集成微信支付功能.分享给大家供大家参考.具体分析如下: WechatAppPay文件代码如下: 复制代码 代码如下: <?php namespace common\services\WechatPay; class WechatAppPay extends WechatPayBase {     //package参数     public $package = [];     //异步通知参数     public $notify = [];     //推送

浅析PHP微信支付通知的处理方式

通知机制的实现,官方只有文档没有demo代码,对没搞过的人来说,需要花大量时间来做测试. 从文档上说的来看,微信每次通知过来的数据,结构比较复杂,是一个多段数据,除了要取出POST数据外,还要取其它的数据. 这里首先涉及到一个关于php://input与$_POST取值的问题,简单列几点如下: 复制代码 代码如下: 1,Content- Type取值为application/x-www-form-urlencoded时,php会将http请求body相应数据会填入到数组$_POST,填入到$_P

PHP微信支付开发实例

PHP微信支付开发过程,分享给大家,供大家参考,具体内容如下 1.开发环境 Thinkphp 3.2.3 微信:服务号,已认证 开发域名:http://test.paywechat.com (自定义的域名,外网不可访问) 2.需要相关文件和权限 微信支付需申请开通 微信公众平台开发者文档:http://mp.weixin.qq.com/wiki/home/index.html 微信支付开发者文档:https://pay.weixin.qq.com/wiki/doc/api/index.html

php实现微信企业号支付个人的方法详解

本文实例讲述了php实现微信企业号支付个人的方法.分享给大家供大家参考,具体如下: 导语:分销商,微商提现怎么提? 直接用微信支付. 实现如下: 微信支付配置 /*微信支付*/ 'PAY_WEIXIN' => array( 'appid' => 'XXXX', 'appsecret' => 'XXXXXXX', 'mchid' => '1283301801', //商户号 'key' => 'zhudianbaodiandodozhudianbao0527', //商户支付秘

PHP 接入微信扫码支付总结(总结篇)

微信扫码支付分为两种模式, 模式一比较复杂,需要公众号配置回调地址. 模式二比较简单,只需要在代码中配置回调地址就可以了. 我这次使用的是模式二. 需要配置参数, const APPID = 'xxx'; const MCHID = 'xxx'; const KEY = 'xxx'; const APPSECRET = 'xxx'; 配置公众号的appid,appsecret.以及微信支付的mchid与key. 生成二维码,这个页面需要自己去美化,不像支付宝那样自带效果. require_onc

Thinkphp整合微信支付功能

先上效果图:我要告诉你我这一篇文章写的是微信支付之中的(普通商户而非服务商商户的统一下单JSPI)微信支付: 其实自己整合SDK失败了,用了一个博客博主整合的代码,在这里写一下笔记: 前面准备: 1.微信公众号: 独特的appid.appscrect.接口权限之中设置可以获取用户ID信息权限的域名(每个用户对于不同公众都会有一个特有ID,通过这个ID获取用户微信账号基本信息.详情看微信开发者文档).在微信支付按钮出设置微信支付授权目录(写到发起请求的控制器那一层).设置开发者微信账号为测试白名单

php微信支付接口开发程序

php微信支付接口开发程序讲解: 必要条件: appid //公众号后台开发者中心获得(和邮件内的一样) mchid//邮件内获得 key//商户后台自己设置 appsecret //公众号开发者中心获得 两个证书文件,邮件内获得 apiclient_cert.pem   apiclient_key.pem 注意事项: 公众号后台微信支付->开发配置->新增测试目录和测试个人微信号. 开发者中心->网页授权获取用户基本信息->修改成你的测试域名.否则会出现redirect_uri

Thinkphp微信公众号支付接口

本文实例为大家分享了Thinkphp微信公众号支付接口,供大家参考,具体内容如下 第一步  先把文件夹的那两个图片 配置成一样的路径 除了域名要改 其他保持一致. 第二步  把 Weixinpay 这个文件夹放在 \ThinkPHP\Library\Vendor  将Weixinpay文件夹放置到这个Vendor文件夹中 第三步  把  WxJsAPIController.class.php 这个php文件  \Home\Controller  这里面 第四步  把 WxJsAPI这个文件夹 

PHP 微信支付类 demo

一切尽在代码中,代码附有注释,欢迎大家参考. <?php class WxpayService { protected $mchid; protected $appid; protected $key; public function __construct($mchid, $appid, $key) { $this->mchid = $mchid; // 微信支付商户号 PartnerID 通过微信支付商户资料审核后邮件发送 $this->appid = $appid; //公众号AP

php官方微信接口大全(微信支付、微信红包、微信摇一摇、微信小店)

微信入口绑定,微信事件处理,微信API全部操作包含在这些文件中. 内容有:微信摇一摇接口/微信多客服接口/微信支付接口/微信红包接口/微信卡券接口/微信小店接口/JSAPI <?php class WxApi { const appId = ""; const appSecret = ""; const mchid = ""; //商户号 const privatekey = ""; //私钥 public $param

浅谈使用PHP开发微信支付的流程

下面以PHP语言为例,对微信支付的开发流程进行一下说明. 1.获取订单信息 2.根据订单信息和支付相关的账号生成sign,并且生成支付参数 3.将支付参数信息POST到微信服务器,获取返回信息 4.根据返回信息生成相应的支付代码(微信内部)或是支付二维码(非微信内),完成支付. 下面分步骤的讲一下: 1.微信支付中相关的必须的订单参数有三个,分别是:body(商品名或订单描述),out_trade_no(一般为订单号)和total_fee(订单金额,单位"分",要注意单位问题),在不同

浅谈Java代码的 微信长链转短链接口使用 post 请求封装Json(实例)

废话不多说,直接上代码 String longUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + MpUtil.APPID + "&redirect_uri=" + MpUtil.HOMEPAGE + "/nweixinLoginPc.fo%3Frandomcode=" + randomcode + "&response_type=co

利用Python开发微信支付的注意事项

前言 微信支付是由微信及财付通联合推出的移动支付创新产品.如今,随着微信支付的全面开放,相关需求也越来越多,很多开发人员进行微信支付开发及商家申请微信支付时,面临着诸多疑惑. 要想开发顺利进行,首先要对业务流程有个清晰的认识.这里以微信公众号支付为例,因此也借用微信支付官方文档中的业务流程图: 接下来来关注几个开发过程中的关键点,包括: 1.生成商户订单与调用统一下单 API 2.微信服务器交互的数据格式 3.公众号支付下网页内通过 JS-API 调起支付 4.异步通知商户支付结果(回调) 一.

java微信支付接入流程详解

背景 由于项目是采用java编写的,微信包括微信支付大都是php相关,于是微信支付官方文档对java的支持就不是很友好,在网上找了很多文章,基本上没有一篇是真正跑的通的,经过一番整理,先将java接入微信支付详细流程总结出来以便后续使用. 步骤一 准备阶段:已认证微信号,且通过微信支付认证,这个可以看微信文档,很详细,这里就不再重复. 步骤二 配置授权目录,官方推荐使用https类型的url,不知道http能不能行,个人也推荐使用https的保证不会错. 配置授权域名 步骤三 微信支付二次开发所

PHP开发微信支付的代码分享

微信支付,即便交了保证金,你还是处理测试阶段,不能正式发布.必须到你通过程序测试提交订单.发货通知等数据到微信的系统中,才能申请发布. 然后,因为在微信中是通过JS方式调用API,必须在微信后台设置支付授权目录,而且要到二级三级目录下去,这对于使用MVC框架来说,是个小问题. 使用MVC,在开发环境,url往往是native url格式,不能保证一定是带有路径/的形式 所以,比较可靠的方式,是创建实体的子文件夹,这样的化,在系统整体url方面,需要进行一些改造. 另外,最后一步,js调用时,对于

php开发微信支付获取用户地址

使用微信获取地址信息是和微信支付一道申请的,微信支付申请通过,就可以使用该功能. 微信商城中,使用微信支付获取用户的收货地址,可以省略用户输入地址信息的繁复流程,提高用户体验. 但是可能是因为牵扯到用户隐私,所以在使用过程中,需要用户自己主动选择使用该功能,并且是通过点击的操作,我们才可以获取到用户的收货地址,这一点是要注意的. 操作流程如下: 1.用户打开购物车页面,点击结算,跳转到一个微信的oauth2的页面,地址为:https://open.weixin.qq.com/connect/oa

ASP.NET MVC 开发微信支付H5的实现示例(外置浏览器支付)

H5支付是指商户在微信客户端外的移动端网页展示商品或服务,用户在前述页面确认使用微信支付时,商户发起本服务呼起微信客户端进行支付. 主要用于触屏版的手机浏览器请求微信支付的场景.可以方便的从外部浏览器唤起微信支付. 微信开放平台上的也只是简单的介绍了一下逻辑和常见问题,网上查看了很多,说的都不够具体 首先需要在微信商户平台里开通 H5支付 申请入口:登录商户平台-->产品中心-->我的产品-->支付产品-->H5支付 代码逻辑: 1.用户在商户侧完成下单,使用微信支付进行支付 2.

浅谈JavaScript前端开发的MVC结构与MVVM结构

MVC Model–View–Controller (MVC)是一种把信息展现逻辑和用户交互分离的计算机用户界面开发模式:Model包含应用的数据和业务逻辑:Controller负责把用户的输入,转换为命令传递给Model和View;这是维基百科的解释: 这种模式最初是由Trygve Reenskaug在使用Smalltalk-80(1979)工作时设计的,刚开始叫做Model-View-Controller-Editor:后来通过<Design Patterns: Elements of Re

浅谈Spring Boot 开发REST接口最佳实践

本文介绍了Spring Boot 开发REST接口最佳实践,分享给大家,具体如下: HTTP动词与SQL命令对应 GET 从服务器获取资源,可一个或者多个,对应SQL命令中的SELECT GET /users 获取服务器上的所有的用户信息 GET /users/ID 获取指定ID的用户信息 POST 在服务器上创建一个新资源,对应SQL命令中的CREATE POST /users 创建一个新的用户 PUT 在服务器上更新一个资源,客户端提供改变后的完整资源,对应SQL命令中的UPDATE PUT

浅谈使用mpvue开发小程序需要注意和了解的知识点

一.实例生命周期 除了Vue本身的生命周期处,mpvue还兼容了小程序的生命周期,这部分生命周期的钩子来源于微信小程序的Page,除特殊情况外,不建议使用小程序的生命周期钩子. app 部分: onLaunch,初始化 onShow,当小程序启动,或从后台进入前台显示 onHide,当小程序从前台进入后台 page 部分: onLoad,监听页面加载 onShow,监听页面显示 onReady,监听页面初次渲染完成 onHide,监听页面隐藏 onUnload,监听页面卸载 onPullDown