zoukankan      html  css  js  c++  java
  • 微信开发 -- 企业付款 PHP代码实现

    写这篇文章的目的主要是由于在微信公众平台提供的SDK中并没有提供此功能的SDK实现,

    其实最后实现还是借助 微信公众平台开发文档 和 SDK

    企业付款的应用场景: 公众号向已关注用户付款,比如处理退款、财务结算等

    先说一下实现思路:

    在SDK中自带类库的基础上扩展WxMchPay组件, 实现企业付款功能的扩展。

    话不多说,上代码, 下面是继承SDK,实现企业付款的组件:

    $parameters参数参考: 企业付款API的文档

    <?php
    // 引入SDK
    import('Common.Util.WxPay');
    
    /**
     * 微信企业付款操作类
     * Author  :  Max.wen
     * DateTime: <15/9/16 11:00>
     */
    class WxMchPay extends Wxpay_client_pub
    {
        /**
         * API 参数
         * @var array
         * 'mch_appid'         # 公众号APPID
         * 'mchid'             # 商户号
         * 'device_info'       # 设备号
         * 'nonce_str'         # 随机字符串
         * 'partner_trade_no'  # 商户订单号
         * 'openid'            # 收款用户openid
         * 'check_name'        # 校验用户姓名选项 针对实名认证的用户
         * 're_user_name'      # 收款用户姓名
         * 'amount'            # 付款金额
         * 'desc'              # 企业付款描述信息
         * 'spbill_create_ip'  # Ip地址
         * 'sign'              # 签名
         */
        public $parameters = [];
    
        public function __construct()
        {
            $this->url = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers';
            $this->curl_timeout = WxPayConf_pub::CURL_TIMEOUT;
        }
    
        /**
         * 生成请求xml数据
         * @return string
         */
        public function createXml()
        {
            $this->parameters['mch_appid'] = WxPayConf_pub::APPID;
            $this->parameters['mchid']     = WxPayConf_pub::MCHID;
            $this->parameters['nonce_str'] = $this->createNoncestr();
            $this->parameters['sign']      = $this->getSign($this->parameters);
            return $this->arrayToXml($this->parameters);
        }
    
    
        /**
         *     作用:使用证书,以post方式提交xml到对应的接口url
         */
        function postXmlSSLCurl($xml,$url,$second=30)
        {
            $ch = curl_init();
            //超时时间
            curl_setopt($ch,CURLOPT_TIMEOUT,$second);
            //这里设置代理,如果有的话
            //curl_setopt($ch,CURLOPT_PROXY, '8.8.8.8');
            //curl_setopt($ch,CURLOPT_PROXYPORT, 8080);
            curl_setopt($ch,CURLOPT_URL, $url);
            curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE);
            curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,FALSE);
            //设置header
            curl_setopt($ch,CURLOPT_HEADER,FALSE);
            //要求结果为字符串且输出到屏幕上
            curl_setopt($ch,CURLOPT_RETURNTRANSFER,TRUE);
            //设置证书
            curl_setopt($ch,CURLOPT_CAINFO, WxPayConf_pub::SSLROOTCA_PATH);
            //使用证书:cert 与 key 分别属于两个.pem文件
            //默认格式为PEM,可以注释
            curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
            curl_setopt($ch,CURLOPT_SSLCERT, WxPayConf_pub::SSLCERT_PATH);
            //默认格式为PEM,可以注释
            curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
            curl_setopt($ch,CURLOPT_SSLKEY, WxPayConf_pub::SSLKEY_PATH);
    
            //post提交方式
            curl_setopt($ch,CURLOPT_POST, true);
            curl_setopt($ch,CURLOPT_POSTFIELDS,$xml);
            $data = curl_exec($ch);
            //返回结果
            if($data){
                curl_close($ch);
                return $data;
            }
            else {
                $error = curl_errno($ch);
                echo "curl出错,错误码:$error"."<br>";
                echo "<a href='http://curl.haxx.se/libcurl/c/libcurl-errors.html'>错误原因查询</a></br>";
                curl_close($ch);
                return false;
            }
        }
    
    
    }

    Controller层功能实现:

    <?php
    /**
     * Author  :  Max.wen
     * DateTime: <15/9/20 16:47>
     */
    
    namespace HomeController;
    
    
    class TestController extends CommonController
    {
    
        /**
         * 企业付款测试
         */
        public function rebate()
        {
            import('Common.Util.WxMchPay');
            $mchPay = new WxMchPay();
            // 用户openid
            $mchPay->setParameter('openid', 'oy2lbszXkgvlEKThrzqEziKEBzqU');
            // 商户订单号
            $mchPay->setParameter('partner_trade_no', 'test-'.time());
            // 校验用户姓名选项
            $mchPay->setParameter('check_name', 'NO_CHECK');
            // 企业付款金额  单位为分
            $mchPay->setParameter('amount', 100);
            // 企业付款描述信息
            $mchPay->setParameter('desc', '开发测试');
            // 调用接口的机器IP地址  自定义
            $mchPay->setParameter('spbill_create_ip', '127.0.0.1'); # getClientIp()
            // 收款用户姓名
            // $mchPay->setParameter('re_user_name', 'Max wen');
            // 设备信息
            // $mchPay->setParameter('device_info', 'dev_server');
    
            $response = $mchPay->postXmlSSL();
            if( !empty($response) ) {
                $data = simplexml_load_string($response, null, LIBXML_NOCDATA);
                echo json_encode($data);
            }else{
                echo json_encode( array('return_code' => 'FAIL', 'return_msg' => 'transfers_接口出错', 'return_ext' => array()) );
            }
        }
    }

    完成上述两部分代码,基本就可以成功调用企业付款API了。

    返回结果的数据结构示例:

    {
    	"return_code": "SUCCESS",
    	"return_msg": { },
    	"mch_appid": "wx519cae424099ed6b",
    	"mchid": "1228636402",
    	"device_info": { },
    	"nonce_str": "qjupk84q4iqxkb578hb5h2qiatgcwxwg",
    	"result_code": "SUCCESS",
    	"partner_trade_no": "test-1442801966",
    	"payment_no": "1000018301201509210739170397",
    	"payment_time": "2015-09-21 10:19:26"
    }
    

      

    可能遇到的问题:

    1、CA证书错误

      在WxMchPay中大家可以看到,我重写了SDK中 Wxpay_client_pub 的 postXmlSSLCurl()方法

      因为默认在SDK中的这个方法在CURL POST请求的时候没有附带CA证书。

      相比之下就多了 

      curl_setopt($ch,CURLOPT_CAINFO, WxPayConf_pub::SSLROOTCA_PATH);  这么一行代码。  

      作用就是请求时附带CA证书。

    2、对同一用户转账操作过于频繁,请稍候重试.

      这个错误属于微信服务端的限制,具体限制频率也没有找到那里有说明,不过经过实际测试大概在1分钟左右。

      所以在开发的时候还需要多注意。


    有任何疑问欢迎共同探讨。



    P.S. 搬家至博客园的第一篇随笔, 送给组织的见面礼。希望再次广交猿友。
  • 相关阅读:
    计算机 ------- 网络基础
    设计模式------单例模式
    svn 客户端查看用户名和密码
    Docker:DockerFile(DockerFile解析)
    Docker:容器数据卷(命令方式、DockerFile方式)
    SpringBoot再总结
    Docker:镜像(镜像原理)
    Docker:Docker命令(帮助命令、镜像命令、容器命令)
    Docker(Docker的概念与安装)
    ZooKeeper:zookeeper的常用命令(节点的新增、更新、删除)
  • 原文地址:https://www.cnblogs.com/maxwen/p/4828599.html
Copyright © 2011-2022 走看看