企业付款到零钱

这次我们老老实实,一行一行的看文档,官方链接: https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_1

  1. 场景介绍

    image.png

    整个限制条件主要包含: 对方必须在微信实名认证,每个人每天只能最多只能收款10次,请求30次/s.具体可以前往产品设置了解

  2. 付款流程,就不继续贴官方图了,直接上代码

    a. 为了方便,还是新建个基类,payToUser.php

    <?php

    namespace app\api\controller;

    use think\Controller;

    class payToUser extends Controller{

        protected $appid = '你的商户appid'; // 商户账号appid

        protected $mch_id = '你的商户号'; // 商户号

        protected $key = '你的秘钥'; //支付密钥签名

        protected $sendUrl = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers'; //付款地址

        protected $searchUrl = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/gettransferinfo'; //查询地址


        /**

         * xml转数组

         * @param $xml

         * @return mixed

         */

        public function xmltoarray($xml) {

            //禁止引用外部xml实体

            libxml_disable_entity_loader(true);

            $xmlstring = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);

            $val = json_decode(json_encode($xmlstring),true);

            return $val;

        }


        /**

         * 数组转xml

         * @param $data

         * @return string

         */

        public function arraytoxml($data){

            $str='<xml>';

            foreach($data as $k=>$v) {

                $str.='<'.$k.'>'.$v.'</'.$k.'>';

            }

            $str.='</xml>';

            return $str;

        }


        /**

         * 生成随机数

         * @param int $length

         * @return string

         */

        public function createNoncestr($length =32){

            $chars = "ABCDEFGHIJKLMNOPQRSTUVWXYabcdefghijklmnopqrstuvwxyz0123456789";

            $str ="";


            for($i=0;$i<$length;$i++){

                $str.= substr($chars, mt_rand(0, strlen($chars)-1), 1);

            }

            return $str;

        }


        /**

         * 发送post请求

         * @param $url

         * @param $vars

         * @param int $second

         * @param array $aHeader

         * @return bool|string

         */

        function curl_post_ssl($url, $vars, $second = 30, $aHeader = array()){

            $ch = curl_init();//初始化curl

            curl_setopt($ch, CURLOPT_TIMEOUT, $second);//设置执行最长秒数

            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);//要求结果为字符串且输出到屏幕上

            curl_setopt($ch, CURLOPT_URL, $url);//抓取指定网页

            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);// 终止从服务端进行验证

            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);//

            //证书的位置

            curl_setopt($ch, CURLOPT_SSLCERT, '你的证书地址/apiclient_cert.pem');

            //证书key的位置

            curl_setopt($ch, CURLOPT_SSLKEY,  '你的证书地址/apiclient_key.pem');

            if (count($aHeader) >= 1) {

                curl_setopt($ch, CURLOPT_HTTPHEADER, $aHeader);//设置头部

            }

            curl_setopt($ch, CURLOPT_POST, 1);//post提交方式

            curl_setopt($ch, CURLOPT_POSTFIELDS, $vars);//全部数据使用HTTP协议中的"POST"操作来发送


            $data = curl_exec($ch);//执行回话

            if ($data) {

                curl_close($ch);

                return $data;

            } else {

                $error = curl_errno($ch);

                echo "call faild, errorCode:$error\n";

                curl_close($ch);

                return false;

            }

        }



        /**

         * 付款到零钱

         * @param $amount

         * @param $re_openid

         * @param string $desc

         * @param $partner_trade_no

         * @param string $check_name

         * @return mixed

         */

        public function sendMoney($amount,$re_openid,$desc='奖励',$partner_trade_no,$check_name=''){

            $total_amount = $amount;

            $data=array(

                'mch_appid'=>$this->appid,//商户账号appid

                'mchid'=> $this->mch_id,//商户号

                'nonce_str'=>$this->createNoncestr(),//随机字符串

                'partner_trade_no'=> $partner_trade_no,//商户订单号

                'openid'=> $re_openid,//用户openid

                'check_name'=>'NO_CHECK',//校验用户姓名选项,

                're_user_name'=> $check_name,//收款用户姓名

                'amount'=>$total_amount,//金额,单位为分

                'desc'=> $desc,//企业付款描述信息

                'spbill_create_ip'=> '',//Ip地址

            );

            //生成签名算法

            $secrect_key=$this->key;///这个就是个API密码。MD5 32位。

            $data=array_filter($data);

            ksort($data);

            $str='';

            foreach($data as $k=>$v) {

                $str.=$k.'='.$v.'&';

            }

            $str.='key='.$secrect_key;

            $data['sign']=md5($str);

            //生成签名算法

            $xml=$this->arraytoxml($data);

            $url=$this->sendUrl; //调用接口

            $res=$this->curl_post_ssl($url,$xml);

            $return=$this->xmltoarray($res);


            return $return;

        }


        /**

         * 查询付款状态

         * @param string $partner_trade_no

         * @return mixed

         */

        public function searchMoney($partner_trade_no=''){

            $data=array(

                'appid'=>$this->appid,//商户账号appid

                'mch_id'=> $this->mch_id,//商户号

                'nonce_str'=>$this->createNoncestr(),//随机字符串

                'partner_trade_no'=> $partner_trade_no,//商户订单号

            );

            //生成签名算法

            $secrect_key=$this->key;///这个就是个API密码。MD5 32位。

            $data=array_filter($data);

            ksort($data);

            $str='';

            foreach($data as $k=>$v) {

                $str.=$k.'='.$v.'&';

            }

            $str.='key='.$secrect_key;

            $data['sign']=md5($str);

            //生成签名算法

            $xml=$this->arraytoxml($data);

            $url=$this->searchUrl; //调用接口

            $res=$this->curl_post_ssl($url,$xml);

            $return=$this->xmltoarray($res);

            return $return;

        }

    }

    b. 在控制器调用,测试

    /**

         * @param int $amount       转账金额

         * @param string $partner_trade_no  订单号

         */

        public function test($amount=0,$partner_trade_no=''){

            $pay = new PayToUser();

            if($partner_trade_no){   //有订单号则为查询

                print_r($pay->searchMoney($partner_trade_no));

            }else{  //无订单号为付款

                print_r($pay->sendMoney($amount,$this->auth->openid,$desc='测试',$check_name=''));

            }

        }

    437ae9775f8b88806285b23657adc66.png

    image.png

  3. 查询付款结果

    52d29aa1908a24d2030f47547961f1f.png


基本都是复制粘贴的事情了,重点提示,产品设置一定记得修改,不改也点进去看看,不然有时会错得莫名其妙.比如余额不足,用户领取金额上限,用户领取次数上限.还有疑问,欢迎留言

发表评论