微信开发之微信公众号支付

    上月初的时候写过一篇关于【微信开发之微信登陆】的文章,文章里面大概用()()()()的话语讲述了关于在微信登陆这块的一些理论要点和代码实现。这次算是微信开发系列的延续篇,主要记录一下在工作中遇到的关于微信支付部分功能的实现



    由于工作范围有限,这篇就暂时谈论一下关于微信公众号支付的有关功能。

准备工作

    俗话说的好,(前方高能...)有一件战斗力爆表的装备,升级打怪的速度自然也就更快了,当然这不是一篇介绍如何升级打怪的文章,而是一篇有深度的、有长远意义的文章,好了,自夸的话就不多说了,博主有自知之明。

    虽说不是升级打怪,但是作为一只“”,尤其是是聪明的“猿类”,在遇到新功能的时候,找到好的方法,也就相当于找到了一件衬手的、牛X的兵刃,搞出新()功()能的速度自然也就快很多

1、匍匐前进,观察敌情

关键词:阅读文档。工作中遇到之前未曾做过的功能的时候,相信一个好的猿叔叔/媛姐姐都会有一套自己的解决思路,那么第一步相信能获得大家集体点赞的就是阅读相关的文档了,仔细阅读,细心观察。喏~有关微信支付文档已经放在这里了请点击食用文档读得好,下班下的早~mie~~~

2、扩大范围,隐秘嗅探

关键词:关键字/词搜索。在看完文档之后,仍有不解之处,这时候身边没有可以请教的大佬,映入眼帘的只有电脑、键盘、鼠标,心里一阵慌乱。。。想到下午完不成任务无延期的加班组长的白眼,眼前一黑.............................................................“兄弟...兄弟...你特么醒醒啊,代码需要你,还有个bug没改啊,你不能这样啊”。夏天的时候,网络上段子说的好:空调、wifi、西瓜,‘苏菲’一夏。那么程序员的法宝可就多了,这段就写相关的————搜索引擎、输入关键字、回车。得到的是整个互联网的资源,如果有谷歌的话,那就是整个宇宙的资源了。拥有了整个宇宙的资源之后,还怕啥,就是干,犹豫不划算嘛

3、发现雷区,获取情报

关键词:取经。上面2里面提到的扩大范围,隐秘嗅探,意在我们通过庞大的搜索引擎和互联网获取资源,但是在浏览这些资源的时候,我们要学会辨别哪些是有用的,哪些是已经了解过的,对于无用的水文和了解过的文章可以略过....我们大概会浏览到相当多的博文,良心博主(比如我,歪脸笑.jpg)的博文里,或多或少都会提到些开发过程中遇到的坑/bug,以妨后来者踩坑。

情报展示

    通过上面的准备工作,相信我们已经获取到了诸多的相关资料,本文涉及到的功能实现所需要的相关资料,将会在下面无偿分享出来(PS:为博主的无私奉献精神而感动啊~333333)

什么是公众号支付?

公众号支付是用户在微信中打开商户的H5页面,商户在H5页面通过调用微信支付提供的JSAPI接口调起微信支付模块完成支付。应用场景有:

  • 用户在微信公众账号内进入商家公众号,打开某个主页面,完成支付

  • 用户的好友在朋友圈、聊天窗口等分享商家页面连接,用户点击链接打开商家页面,完成支付

  • 将商户页面转换成二维码,用户扫描二维码后在微信浏览器中打开页面后完成支付

支付流程

关键词

  • 微信支付用户————泛指微信用户

  • 微信客户端————微信APP

  • 商户后台系统————商户平台

  • 微信支付系统————故名思议,微信自己的支付系统

我们先通过一张图了解一下微信支付的流程:

微信内网页支付时序图

这张图相信小伙伴在浏览微信支付文档的时候已经看到过了,虽然从用户点击支付按钮开始微信支付系统确认支付完毕中间经过要13步之多的过程,但是实际上这也是很有必要的,我们可以看到支付在任何时候都是需要重视的,因为这是一个关于的问题,只要涉及到了它,就必须确保它每一步的顺利执行和安全性。在我们快速开发功能的时候,有时候不得不压抑住我们想要窥探其具体实现的好奇心,只了解其中关键几步,以达到快速开发的目的,剩下的好奇心只能等课后了。

总结了其中的关键几步,以便大家参(快速)考(查阅),其中个把关键词均已红色字体标出

  1. 用户在页面点击支付按钮,商户后台系统生成微信支付系统的订单信息,调用下单API,发送给微信支付系统

  2. 微信支付系统接收支付信息生成临时支付单信息,返回给商户后台系统

  3. 商户后台系统拿到临时支付单信息,生成JSAPI(微信支付SDK)调用所需要的支付参数并签名

  4. 通过JSAPI接口发起支付请求给微信支付系统

  5. 微信支付系统检查参数合法性授权域信息,返回验证结果给微信客户端,微信客户端弹出支付窗,输入密码,支付

  6. 用户输入密码完之后,客户端主动提交支付信息到微信支付系统微信支付系统验证授权并处理相应业务,返回处理结果给商户后台,商户后台系统根据结果给用户相应提示

SDK及DEMO

微信已经提供了完整的、安全的、方便使用的SDK供我们饮用,就在微信支付文档里面,或者点我进行查看下载

支付授权目录

支付授权目录,和上篇文章中说到的登陆授权回调域性质差不多,但是区别在于这里用于支付授权
现在的公众号支付授权目录配置已经从公众号迁移到了微信商户平台中,开发者可以在商户平台中进行配置,下图所示:

配置示例

具体公告,请点击:微信支付开发配置页面迁移至商户平台查看

其他几个点

  • 要使用微信公众号支付功能必须是要微信服务号或者企业号

  • 支付的时候也要检查网页授权域名是否设置哦

  • 没有微信开发者工具的一定要下载个微信开发者工具,因为接下来,包括你在做微信开发的时候一定会需要它,它很强势,不用不行

饿货,来个代码饼干?

终于来到开坦克杀敌的环节了,一阵莫名激动,能看到这里的小伙伴一定是真爱啊!~

jsapi.php

为什么把这个文件单独提出来,因为它很重要啊(博主君废话模式开启,23333),这个页面通俗点来说用于调起支付框,输入支付密码的操作。当我们下载好了PHP版的微信支付SDK的时候,打开目录大概会是这个美丽的样子

微信SDK目录

关键代码块:

//②、统一下单
$input = new WxPayUnifiedOrder();
// 商品名称
$input->SetBody('坦克');
// 描述吧应该是 可以省略不写
$input->SetAttach("");
// 订单号
$input->SetOut_trade_no($pay_info['trade_no']);
// 支付金额
$input->SetTotal_fee($pay_info['total_fee']);
// 开始时间
$input->SetTime_start(date("YmdHis"));
// 失效时间
$input->SetTime_expire(date("YmdHis", time() + 600));
// 标签 可以省略不写
$input->SetGoods_tag("");
// 支付回调url
$input->SetNotify_url("");

以上代码均产生于jsapi.php这个文件,代码的注释差不多就是这个意思,没有写注释的博主也不知道啥意思(绝望.jpg,知道的可以告知下...感谢大恩大德)

WxPay.Config.php

这个是关于微信支付配置的文件,放置在SDK根目录下的lib目录里,找到它更改里面的对应配置项。具体有什么作用怎么改,这里就不解释了。文件里的注释写的很清楚,讲真,ZZ都能看的明白,微信SDK开发组的兄弟还是很用心的...点赞

结合CI框架

首先,把SDK目录文件放在application\libraries目录。

1、唤起支付页面
当用户在前端点击支付的时候,跳转到如下方法:

/**
 * 跳转到微信支付页面
 * @param  int $order_id 订单ID
 */
public function index($order_id) {
    /**
     * 首先要校验订单ID、真实性等
     * 这里略过
     */
    $goods_name = $this->order_goods_model->get_value_by_notpk('goods_name', array('order_id' => $order_id));
    $data['pay_info'] = array(
        'trade_no'   => $order_info[0]['order_sn'],//订单名称,必填
        'goods_name' => $goods_name, //商品名称
        'total_fee'  => $order_info[0]['pay_fee']*100,//付款金额,必填
        'remark'     => $goods_name,//商品描述,可空
        );
    // 调用支付页面 jsapi
    $this->load->view("sz_front/wx_alipay/jsapi", $data);
}

2、jsapi页面赋值
大部分代码和原生的差不多,修改一小部分,包括引入各种类库等,这里为了方便展示,采用图片的形式列出

支付详情赋值

支付结果回调

隐藏地址共享

上面三张图一共做了四件事:

  1. 引入所需要的支付类库

  2. 赋值支付信息

  3. 根据支付结果进行提示并跳转页面

  4. 隐藏共享地址

支付异步通知 notify

异步通知,支付完结之后,微信支付系统会发送支付结果到这个地址,要求这个地址可以访问,可以在浏览器输入地址进行测试

public function notify() {
    // 引入异步通知处理类库
    require_once APPPATH.'libraries/Payment/wxpay/example/notify.php';
    $notify = new PayNotifyCallBack();
    $notify->Handle(false);
    
    // 获取支付状态
    $is_success = $notify->IsSuccess(); 
    /**
     * $wx_payinfo 微信支付回调数据
     * 包括支付状态、商户平台的订单、金额、支付成功支付号等
     */
    
    $wx_payinfo = $is_success['data']; 
     //支付成功
    if($is_success['code'] == 1){ 
        /**
         * 业务处理
         */
    }else {

    }
}

注意:在上面的代码中,获取支付状态这里有个IsSuccess方法,这个方法用于获取微信的返回结果,我把他加在了notify.php的类中,具体如下:

/**
 * 自定义方法 检测微信端是否回调成功方法
 * @return multitype:number string
 */
public function IsSuccess(){
     return $this->para;
}

由于异步通知是在“暗地里”进行,所以我们想要监控它,了解它返回了什么数据,可以简单的使用file_put_contents()函数把结果json_encode()一下写入log文件记录。

总结

  • 由于框架的一些特性,微信SDK类库间的相互引入类的时候,可能会出现路径引入的问题,但这些问题并不太会被察觉,所以还需要小心调试。出现路径问题的时候,把引入类库出现问题的相对路径改为绝对路径即可。

  • 微信开发其实很简单,有SDK在手,支付我有。博主君为了凑字数,才编的这么多废话,哈哈哈~

    距离当初做出这个功能已经有一段时间了,当初在百度查阅资料获取到的资源和众多博文地址也已经记不太清了,有兴趣的朋友可以百度搜索PHP微信开发等关键字进行查阅。实际在功能的实现中,遇到最多的问题就是路径引入了。还有就是强烈推荐微信开发者工具,在微信开发的时候相当有用处(就算我不说,各位朋友应该也知道,又一次打脸...啪(pia)啪(pia)啪(pia))。

再见,七月。

你好,八月。

已有 16 条评论
  1. 那些丶我无处安放的哀伤 那些丶我无处安放的哀伤

    大佬 我按照你这个
    require_once APPPATH.'libraries/Payment/wxpay/example/notify.php';

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

    在方法里面引入异步回调通知类 页面报500错误是什么原因??

  2. 那些丶我无处安放的哀伤 那些丶我无处安放的哀伤

    大佬 你QQ在线不

  3. 那些丶我无处安放的哀伤 那些丶我无处安放的哀伤

    加你了

  4. 中国良心博主 中国良心博主

    可以这么理解吧,就是把这个客户的唯一标识,与订单绑定在一起,放在一个表里。
    然后你不是说能获取到微信支付成功后返回的参数吗?参数里就包含有订单编号,根据这个订单编号取出客户ID

  5. 中国良心博主 中国良心博主

    要不加我扣扣聊吧 757080689

  6. 中国良心博主 中国良心博主

    要不加我QQ吧 757080689

  7. 那些丶我无处安放的哀伤 那些丶我无处安放的哀伤

    支付之前?客户ID?是不是拿到他的openid??
    一般不是点击支付后 然后打开回调地址 才会有个订单ID返回吗?

  8. 中国良心博主 中国良心博主

    你可以把客户ID在支付前 就放在你的订单表里面呀
    根据拿到的回调参数里的订单号 查询这个订单对应的客户ID 就好了

  9. 那些丶我无处安放的哀伤 那些丶我无处安放的哀伤

    还是不行 不知啥原因 算了我直接在notify.php里面写成功后的方法 现在又遇到一个难题.
    我在做一个预约挂号的系统 现在支付成功了 因为notify.php后面不能带任何参数.我现在需要更新当前这个预约客户ID里面的字段 比如付款状态 付款时间 付款订单号.这些参数都可以拿到 问题是如何获取这个客户ID来更新这些数据呢?之前的页面因为我都携带了ID在URL地址上 所以只需要get获取到了就能更新了 但问题是现在不能get获取到 因为URL没有参数. 该怎么解决
    就是客户在支付之前 我已经生成了随机的主键ID.现在需要在支付后获取客户对应的ID来更新数据库

  10. 中国良心博主 中国良心博主

    当你确定了,你在地址栏里输入notify的回调地址可以访问后,如果还是接收不到数据,可以参考以下几点排查:
    1、在方法里的第一行随便写个file_put_contents到你的log文件中,测试下log文件是否可写
    2、确定你的引入类都是正常的。测试的话就在地址栏访问notify方法,看下打印出的类对象是否正常
    3、异步返回的地址notify必须要在公网(外网)可以访问到的
    4、最后的方法,通过支付成功后的回调,把每一步下面都加一个写入log的方法,测试到底是哪一行出现的问题

  11. 那些丶我无处安放的哀伤 那些丶我无处安放的哀伤

    对 解决了 但是我现在把notify.php引入到一个方法里面去执行 是不行的 接收不到数据 但是路径直接指向notify.php里面是正常的 怎么回事呢

  12. 倾铃 倾铃

    你好,根据你这个情况,首先第一点可以确定的是,你的notify.php页面公网上(地址栏)里都访问不到,更何况微信异步给你发送的支付通知了,肯定是接受不到的。先把notify的404解决了,再说接收值得问题。

    你的页面访问404,估计是路径的问题。。。你排查一下

  13. 那些丶我无处安放的哀伤 那些丶我无处安放的哀伤

    根据楼主的步骤
    Log::DEBUG(begin notify);
    $notify = new PayNotifyCallBack();

    $notify->Handle(false);

    $is_success = $notify->IsSuccess();
    $wx_payinfo = $is_success['data'];

    //支付成功 if($is_success['code'] == 1){ echo 1; }else { echo 0; }

    $postXml = file_get_contents('php://input');
    file_put_contents('/tmp/erron.log',json_encode($postXml));
    这里就是没有数据写进来 怎么回事呢?而且我直接访问notify.php这个页面是404错误的 找不到页面

  14. 命中水 命中水

    哈哈、多谢支持~ [/玫瑰]

  15. :) :)

    深入浅出,关键LZ比较幽默,2333333333。给你一个大大大大大的赞![/给力]

  16. peter peter

    你好,你好,请求一下,很急,我看了你的文章,但是还差点没完成,能帮忙吗,红包感谢。加一下我微信,yunzhiv。非常感谢,要加啊,很急啊。

添加新评论