php接入微信支付,扫码支付和H5支付(非微信浏览器),基于thinkPHP框架 WeChatDeveloper支付类包 踩坑指南

 此文章入选《PHP领域内容榜》第4名

文章介绍

        本文主要介绍通过thinkPHP5和第三方支付类包(WeChatDeveloper)实现快速接入微信扫码支付和微信H5手机网站支付(非微信浏览器),以及如何进行微信支付订单回调、如何判断手机和PC端、如果进行微信订单退款等,整理了部分在开发中经常遇到的错误和难踩的坑!

WeChatDeveloper介绍

  • WeChatDeveloper 是基于 wechat-php-sdk 重构,优化并完善;
  • 运行最底要求 PHP 版本 5.4 , 建议在 PHP7 上运行以获取最佳性能;
  • WeChatDeveloper 针对 access_token 失效增加了自动刷新机制;
  • 微信的部分接口需要缓存数据在本地,因此对目录需要有写权限;
  • 我们鼓励大家使用 composer 来管理您的第三方库,方便后期更新操作;
  • WeChatDeveloper 已历经数个线上项目考验,欢迎 fork 或 star 此项目。
  • 微信商户支持已经支持 v2 接口,组件开发版支持 v3 接口。

WeChatDeveloper功能描述

  • 微信小程序,服务端接口支持
  • 微信认证服务号,服务端接口支持
  • 微信支付(账单、卡券、红包、退款、转账、App支付、JSAPI支付、Web支付、扫码支付等)
  • 支付宝支付(账单、转账、App支付、刷卡支付、扫码支付、Web支付、Wap支付等)

GIT库地址:https://gitee.com/zoujingli/WeChatDeveloper

官方文档地址:https://www.kancloud.cn/zoujingli/wechat-developer

# 首次安装 线上版本(稳定)
composer require zoujingli/wechat-developer

# 首次安装 开发版本 
composer require zoujingli/wechat-developer dev-master

# 更新 WeChatDeveloper
composer update zoujingli/wechat-developer

开发注意事项:

1、H5支付和扫码支付在开发前先到微信支付平台确认有没有开通对应的产品(NATIVE支付和H5支付),如果没有的话需要开通,否则无法使用;

2、扫码支付是PC端,H5支付是网页端,如果想在微信端支付还需要开通JSAPI支付,后续会补充JSAPI的代码;

3、H5支付需要配置对应的安全网址和IP白名单,填一级域名就可以比如:baidu.com;

4、H5支付返回的mwebUrl网址不可以直接复制到在浏览器上访问,这里必须跳转,否则会报错“商家参数格式有误,请联系商家解决”;

5、复制以下代码前必须安装WeChatDeveloper类,下面都是基于这个类写的,如果不安装不用在往下看了;

6、微信退款必须需要双向证书,必须是绝对路径,比如D:/sial/wechat/cert/apiclient_cert.pem;

7、下面代码部分已经用xxx代码,需要替换成自己业务对应的才可以;

8、在支付成功回调的过程中,微信回进行多次回调,记得加验证!!


项目示例:

    /**
     * 微信支付,发起订单
     */
    public function wxPay(){
        // 准备配置参数
        $config = [
            'appid'      => 'wx1238598xxxxxxxxe',
            'appsecret'  => '5d6fg5r8g4xxxxxxxxxxxxxx56564hg5',
            'mch_id'     => '160xxxxx24',
            'mch_key'    => 'NAMECeShi202120xxxxxxxxxxxx21816',
        ];
        try {
            // 创建接口实例
            $wechat = new \WeChat\Pay($config);
            // 组装参数,可以参考官方商户文档
            $options = [
                'body'             => '商品的名称',
                'out_trade_no'     => time(), //订单号
                'total_fee'        => 1, //金额,单位为分
                'notify_url'       => 'http://baidu.com/tongzhi', //异步通知地址,就是下面那个方法
                'spbill_create_ip' => $_SERVER["REMOTE_ADDR"], //客户端IP
            ];
            // 判断是不是手机版,is_wap类在下面
            if(is_wap()){
                $options['trade_type'] = 'MWEB';
                $options['scene_info'] = '{"h5_info": {"type":"Wap","wap_url": "https://www.baidu.com","wap_name": "网站标题"}}';
            }else{
                $options['trade_type'] = 'NATIVE';
            }
            // 请求统一下单接口
            $result = $wechat->createOrder($options);
            // PC端 把微信二维码流转成二维码网址
            $result['code_url'] = "http://asd.com/api/qrcode?code=".$result['code_url'];
            // H5端 拼接回调跳转的网址
            $result['mweb_url'] = $result['mweb_url']."&redirect_url=http://asd.com";
            // 返回json数组给前端
            return json($result);
        } catch (\WeChat\Exceptions\InvalidResponseException $e) {
            // 出现了错误
            echo $e->getMessage() . PHP_EOL;
        }
    }

    /**
     * 微信订单回调
     */
    public function wxCallback(){
        try {
            // 准备配置参数
            $config = [
                'appid'      => 'wx1238598xxxxxxxxe',
                'appsecret'  => '5d6fg5r8g4xxxxxxxxxxxxxx56564hg5',
                'mch_id'     => '160xxxxx24',
                'mch_key'    => 'NAMECeShi202120xxxxxxxxxxxx21816',
            ];
            // 创建接口实例
            $wechat = \WeChat\Pay::instance($config);
            // 获取通知参数
            $data = $wechat->getNotify();
            if ($data['return_code'] === 'SUCCESS' && $data['result_code'] === 'SUCCESS') {
                // 根据业务逻辑进行修改订单
                $arr=[
                    'status'=>"2",
                    'payment_id'=>'wxpay',
                    'payment_name'=>'微信',
                    'payment_number'=>$data['transaction_id'],
                    'payment_time'=>time()
                ];
                // 修改订单,out_trade_no是我们自己的订单号
                // 这里注意:微信回多次回调,记得验证状态,防止秒退款在被改为付款
                Order::update($arr,['out_trade_no'=>$data['out_trade_no','stauts'=>2]]);
            }
        } catch (\WeChat\Exceptions\InvalidResponseException $e) {
            echo $e->getMessage() . PHP_EOL;
        }
    }

    /**
     * 微信退款
     */
    public function wxRefund($data){
        // 准备配置参数
        $config = [
            'appid'      => 'wx1238598xxxxxxxxe',
            'appsecret'  => '5d6fg5r8g4xxxxxxxxxxxxxx56564hg5',
            'mch_id'     => '160xxxxx24',
            'mch_key'    => 'NAMECeShi202120xxxxxxxxxxxx21816',
            // 注意这里需要双向证书,必须是绝对路径,ROOT_PATH是在入口文件定义的
            'ssl_key'    => ROOT_PATH.'wechat/cert/apiclient_key.pem',
            'ssl_cer'    => ROOT_PATH.'wechat/cert/apiclient_cert.pem',
        ];
        try {
            $wechat = \WeChat\Pay::instance($config);
            $options = [
                'transaction_id' => '1629171157', // 订单号
                'out_refund_no'  => '1629171157', // 退款编号
                'total_fee'      => 1, //订单金额,单位为分,*100就是元
                'refund_fee'     => 1, //退款金额
            ];
            $result = $wechat->createRefund($options);
            // 更改数据库状态
            Order::update(['status'=>"-2",['id'=>'订单的ID']);
            return success_json('','退款成功');
        } catch (\WeChat\Exceptions\InvalidResponseException $e) {
            return error_json('退款失败:'.$e->getMessage());
        }
    }
// 判断是否为手机端
function is_wap(){
    // 先检查是否为wap代理,准确度高
    if(stristr($_SERVER['HTTP_VIA'],"wap")){
        return true;
    }
    // 检查浏览器是否接受 WML.
    elseif(strpos(strtoupper($_SERVER['HTTP_ACCEPT']),"VND.WAP.WML") > 0){
        return true;
    }
    //检查USER_AGENT
    elseif(preg_match('/(blackberry|configuration\/cldc|hp |hp-|htc |htc_|htc-|iemobile|kindle|midp|mmp|motorola|mobile|nokia|opera mini|opera |Googlebot-Mobile|YahooSeeker\/M1A1-R2D2|android|iphone|ipod|mobi|palm|palmos|pocket|portalmmm|ppc;|smartphone|sonyericsson|sqh|spv|symbian|treo|up.browser|up.link|vodafone|windows ce|xda |xda_)/i', $_SERVER['HTTP_USER_AGENT'])){
        return true;
    }
    else{
        return false;
    }
}

文章:php快速接入支付宝即时支付,PC网站支付和手机网站支付,基于thinkPHP框架 WeChatDeveloper支付类包


版权声明:本文为weixin_45809825原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。