美文网首页
微信公众号 企业付款 微信用户(商户号,微信公众号:appid,

微信公众号 企业付款 微信用户(商户号,微信公众号:appid,

作者: 阿_莫西林 | 来源:发表于2020-05-12 15:49 被阅读0次

    流程:

    微信用户从微信公众号进入查询页面(网页授权获取openid),进行提交申请单。
    后台管理员进行审核(支付,驳回),主要记录支付操作。

    事先准备:

        1、商户号
        2、公众号(开通支付功能)
        3、商户号绑定到公众号
        4、证书(由商户号进行生成导出,用于api验证)https://kf.qq.com/faq/180824BrQnQB180824m6v2yA.html

    主要操作:主要两个动作(获取openid,付款)**

    一、 获取用户openid,并记录。(时间,申请金额什么的乱七八糟的参数略略略略)

        可由公众号会话生成(未用)
        网页授权生成(因为有页面用此方法)
        1、请求连接(https://open.weixin.qq.com/connect/oauth2/authorize?appid=*************d&redirect_uri=(回传地址)jump.php&response_type=code&scope=snsapi_base&state=1#wechat_redirect)
        由中转页获取code并请求获取用户openid

    jump.php

    <?php
    $url = "http:**************/jump.php";
    baseAuth($url);
    /**
     * 获取用户的openid
     * @param  string $openid [description]
     * @return [type]         [description]
     */
    function baseAuth($redirect_url)
    {
        //1.准备scope为snsapi_base网页授权页面
        $baseurl = urlencode($redirect_url);
        $snsapi_base_url = 'https://open.weixin.qq.com/connect/oauth2/authorize?appid=w***ad&redirect_uri=' . $baseurl . '&response_type=code&scope=snsapi_base&state=YQJ#wechat_redirect';
     
        //2.静默授权,获取code
        //页面跳转至redirect_uri/?code=CODE&state=STATE
        $code = $_GET['code'];
        if (!isset($code)) {
            header('Location:' . $snsapi_base_url);
        }
        //3.通过code换取网页授权access_token和openid
        $curl = 'https://api.weixin.qq.com/sns/oauth2/access_token?appid=w*****&secret=0*****18&code=' . $code . '&grant_type=authorization_code';
        $content = curl($curl);
        $result = json_decode($content, true);
     
        header("Location:http*******alance.php?open_id={$result['openid']}");//最终页面
    }
    //设置网络请求配置
    function curl($curl, $https = true, $method = 'GET', $data = null)
    {
        // 创建一个新cURL资源
        $ch = curl_init();
        // 设置URL和相应的选项
        curl_setopt($ch, CURLOPT_URL, $curl);    //要访问的网站
        curl_setopt($ch, CURLOPT_HEADER, false);    //启用时会将头文件的信息作为数据流输出。
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);  //将curl_exec()获取的信息以字符串返回,而不是直接输出。 
        if ($https) {
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);  //FALSE 禁止 cURL 验证对等证书(peer's certificate)。
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, true);  //验证主机
        }
        if ($method == 'POST') {
            curl_setopt($ch, CURLOPT_POST, true);  //发送 POST 请求
            curl_setopt($ch, CURLOPT_POSTFIELDS, $data);  //全部数据使用HTTP协议中的 "POST" 操作来发送。
        }
        // 抓取URL并把它传递给浏览器
        $content = curl_exec($ch);
        if ($content  === false) {
            return "网络请求出错: " . curl_error($ch);
            exit();
        }
        //关闭cURL资源,并且释放系统资源
        curl_close($ch);
     
        return $content;
    }
    

    二、 付款(用到之前准备项)

    官方:https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_2

    1、请求参数(简化过了,针对不同进行需求修改)

     //支付rpc
    $this->wx_pay_client = new xmlrpc_client('http:/*********_server.php', 'app_com');
    ....
    $pay_id = time() . rand(1000, 9999);
    $money = $log_data['money'];
    $arr = array(
       'appid' => 'w*****d',//公众号appid
       'partner_trade_no' => $pay_id,//商户订单号(标准见官方文档)
       'openid' => $open_id,//接收人openid
       'amount' => $money * 100,//单位分
        'desc' => '微信提现',//描述
    );
    $rs = $this->wx_pay_client->call('transfers', $arr);//封装过的支付rpc
    if ($rs['result_code'] != 'SUCCESS') {
        $arr = array(
             'ret' => 0,
              'msg' => $rs['return_msg']
        );
    }else{
     
    }
    

    xxx_server.php(rpc,封装了一些常用功能)

    <?php
    define('APPID',"****c");//默认appid(选填)
    define('MCHID',"****");//商户号
    define('PARTNERKEY',"***********2");//商户key
    include_once("***class_xmlrpc.php");//xmlrpc操作类
    class mmpaymktTransfers   {
        //核心支付函数,参数:请求地址和参数
        function postSSLCurl($url,$obj) {
            $obj['nonce_str'] = $this->create_noncestr();    //创建随机字符串
            $obj['sign'] = $this->getSign($obj,false);    //将签名传入数组
            $postXml = $this->arrayToXml($obj);    //将参数转为xml格式
            $responseXml = $this->curl_post_ssl($url,$postXml);    //提交请求
            $resarr = $this->xmlToArray($responseXml);
            return $resarr;
        }
        //生成签名,参数:生成签名的参数和是否编码
        function getSign($arr,$urlencode) {
            $buff = "";
            ksort($arr); //对传进来的数组参数里面的内容按照字母顺序排序,a在前面,z在最后(字典序)
            foreach ($arr as $k=>$v) {
                if(null!=$v && "null" != $v && "sign" != $k) {    //签名不要转码
                    if ($urlencode) {
                        $v = urlencode($v);
                    }
                    $buff.=$k."=".$v."&";
                }
            }
            if (strlen($buff)>0) {
                $reqPar = substr($buff,0,strlen($buff)-1); //去掉末尾符号“&”
            }
            $stringSignTemp = $reqPar."&key=".PARTNERKEY;    //签名后加api
            $sign = strtoupper(md5($stringSignTemp));
            return $sign;
        }
        //生成随机字符串,默认32位
        function create_noncestr($length=32) {
            //创建随机字符
            $chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
            $str = "";
            for($i=0;$i<$length;$i++) {
                $str.=substr($chars, mt_rand(0,strlen($chars)-1),1);
            }
            return $str;
        }
        //数组转xml
        function arrayToXml($arr) {
            $xml = "<xml>";
            foreach ($arr as $key=>$val) {
                if (is_numeric($val)) {
                    $xml.="<".$key.">".$val."</".$key.">";
                } else {
                    $xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
                }
            }
            $xml.="</xml>";
            return $xml;
        }
        //xml转数组
        function xmlToArray($string)
        {
            $ob= simplexml_load_string($string,'SimpleXMLElement', LIBXML_NOCDATA);//将字符串转化为变量
            $json = json_encode($ob);//将对象转化为JSON格式的字符串
            $array = json_decode($json, true);
            return $array;
        }
       //post请求网站,需要证书
        function curl_post_ssl($url, $vars, $second=30,$aHeader=array())
        {
            $ch = curl_init();
            //超时时间
            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);
     
            //cert 与 key 分别属于两个.pem文件(关键点!!)
            //请确保您的libcurl版本是否支持双向认证,版本高于7.20.1
            curl_setopt($ch,CURLOPT_SSLCERT,dirname(dirname(__FILE__)).'/weixin/cert/apiclient_cert.pem');
            curl_setopt($ch,CURLOPT_SSLKEY,dirname(dirname(__FILE__)).'/weixin/cert/apiclient_key.pem');
            curl_setopt($ch,CURLOPT_CAINFO,dirname(dirname(__FILE__)).'/weixin/cert/rootca.pem');
            if( count($aHeader) >= 1 ){
                curl_setopt($ch, CURLOPT_HTTPHEADER, $aHeader);
            }
            curl_setopt($ch,CURLOPT_POST, 1);
            curl_setopt($ch,CURLOPT_POSTFIELDS,$vars);
            $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;
            }
        }
     
    }
    //发送红包
    function sendredpack($m,$p)
    {
        $arr = $p[0];
        $obj = array();
        $obj['wxappid'] = APPID;//appid
        $obj['mch_id'] = MCHID;//mch_id
        $obj['mch_billno'] = $arr['mch_billno'];//订单号,自定义
        $obj['client_ip'] = $_SERVER['REMOTE_ADDR'];
        $obj['re_openid'] = $arr['openid'];//接收红包openid
        $obj['total_amount'] = $arr['money'];
        $obj['min_value'] = $arr['money'];
        $obj['max_value'] = $arr['money'];
     
        $obj['total_num'] = 1;
        $obj['nick_name'] = $arr['sender'];
        $obj['send_name'] = $arr['sender'];
        $obj['wishing'] = $arr['wishing'];
        $obj['act_name'] = $arr['act_name'];
        $obj['remark'] = "";
        $url = "https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack";
        $mmpaymktTransfers = new mmpaymktTransfers();
        $resarr = $mmpaymktTransfers->postSSLCurl($url, $obj);
        return $resarr;
    }
    //查询红包领取状态
    function gethbinfo($m,$p)
    {
        $mch_billno = $p[0];
        $obj['mch_id'] = MCHID;//mch_id
        $obj['appid'] = APPID;//appid
        $obj['mch_billno'] = $mch_billno;
        $obj['bill_type'] = 'MCHT';
        $url = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/gethbinfo';
        $mmpaymktTransfers = new mmpaymktTransfers();
        $resarr = $mmpaymktTransfers->postSSLCurl($url, $obj);
        return $resarr;
    }
    //付款至钱包
    function transfers($m,$p)
    {
        $arr = $p[0];
        $obj = array();
        $obj['mch_appid'] = $arr['appid']?$arr['appid']:APPID;//appid指明这个openid来自哪个应用
        $obj['mchid'] = MCHID;//mch_id
        $obj['partner_trade_no'] = $arr['partner_trade_no'];//商户订单号
        $obj['openid'] = $arr['openid'];//接收红包openid
        $obj['amount'] = $arr['amount'];//金额(单位分)
        $obj['desc'] = $arr['desc'];
        $obj['check_name'] = 'NO_CHECK';//校验用户姓名选项,
        $obj['spbill_create_ip'] = '******';
     
        $url = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers";
        $mmpaymktTransfers = new mmpaymktTransfers();
        $resarr = $mmpaymktTransfers->postSSLCurl($url, $obj);
        return $resarr;
    }
    //查询付款情况
    function gettransferinfo($m,$p)
    {
        $arr = $p[0];
        $obj['mch_id'] = MCHID;//mch_id
        $obj['appid'] = $arr['appid']?$arr['appid']:APPID;//appid指明这个openid来自哪个应用
        $obj['partner_trade_no'] = $arr['partner_trade_no'];
        $url = "https://api.mch.weixin.qq.com/mmpaymkttransfers/gettransferinfo";
        $mmpaymktTransfers = new mmpaymktTransfers();
        $resarr = $mmpaymktTransfers->postSSLCurl($url, $obj);
        return $resarr;
    }
    $xmlrpc_server = new xmlrpc_server();
    $xmlrpc_server->register_method("app_com.sendredpack", "sendredpack");
    $xmlrpc_server->register_method("app_com.gethbinfo", "gethbinfo");
    $xmlrpc_server->register_method("app_com.transfers", "transfers");
    $xmlrpc_server->register_method("app_com.gettransferinfo", "gettransferinfo");
    $xmlrpc_server->call_method();
    ?>
    

    顺便带上xmlrpc.php(马秉尧版本的)

    <?php
    /**
    * @author 马秉尧
    * @copyright (C) 2005 CoolCode.CN
    * @package xmlrpc-epi-php
    * @version 0.7
    */
     
    class xmlrpc_error {
        var $faultCode;
        var $faultString;
        function xmlrpc_error($code, $string) {
            $this->faultCode = $code;
            $this->faultString = $string;
        }
    }
     
    class xmlrpc_server {
        var $server;
        function xmlrpc_server() {
            $this->server = xmlrpc_server_create();
            register_shutdown_function(array(&$this, "__xmlrpc_server"));
        }
     
        function register_method($method_name, $function) {
            xmlrpc_server_register_method($this->server, $method_name, $function);
        }
     
        function xmlrpc_server_add_introspection_data($desc) {
            xmlrpc_server_add_introspection_data($this->server, $desc);
        }
     
        function register_introspection_callback($function) {
            xmlrpc_server_register_introspection_callback($this->server, $function);
        }
     
        function call_method($user_data = null) {
            if (isset($GLOBALS['HTTP_RAW_POST_DATA'])) {
                $request = $GLOBALS['HTTP_RAW_POST_DATA'];
     
            }
            else {
                $request = '';
            }
            $output_options = array(
                           "output_type" => "xml",
                           "verbosity" => "pretty",
                           "escaping" => array("markup"),
                           "version" => "xmlrpc",
                           "encoding" => "utf-8"
                          );
            $response = xmlrpc_server_call_method($this->server, $request, $user_data, $output_options);
            header("HTTP/1.1 200 OK");
            header("Connection: close");
            header("Content-Length: " . strlen($response));
            header("Content-Type: text/xml; charset=utf-8");
            header("Date: " . gmdate("D, d M Y H:i:s") . " GMT");
            print $response;
        }
     
        function __xmlrpc_server() {
            xmlrpc_server_destroy($this->server);
        }
    }
     
    class xmlrpc_client {
        var $scheme;
        var $host;
        var $port;
        var $path;
        var $user;
        var $pass;
        var $namespace;
        var $timeout;
     
        function xmlrpc_client($url, $namespace = '', $user = '', $pass = '', $timeout = 10) {
            $this->use_service($url);
     
            $this->namespace = $namespace;
            $this->user = $user;
            $this->pass = $pass;
            $this->timeout = $timeout;
        }
     
        function use_service($url) {
            $urlparts = parse_url($url);
     
            if (!isset($urlparts['host'])) {
                if (isset($_SERVER["HTTP_HOST"])) {
                    $urlparts['host'] = $_SERVER["HTTP_HOST"];
                }
                else if (isset($_SERVER["SERVER_NAME"])) {
                    $urlparts['host'] = $_SERVER["SERVER_NAME"];
                }
                else {
                    $urlparts['host'] = "localhost";
                }
                if (!isset($urlparts['scheme'])) {
                    if (!isset($_SERVER["HTTPS"]) ||
                        $_SERVER["HTTPS"] == "off"  ||
                        $_SERVER["HTTPS"] == "") {
                        $urlparts['scheme'] = "";
                    }
                    else {
                        $urlparts['scheme'] = "https";
                    }
                }
                if (!isset($urlparts['port'])) {
                    $urlparts['port'] = $_SERVER["SERVER_PORT"];
                }
            }
     
            if (isset($urlparts['scheme']) && ($urlparts['scheme'] == "https")) {
                $urlparts['scheme'] = "ssl";
            }
            else {
                $urlparts['scheme'] = "";
            }
     
            if (!isset($urlparts['port'])) {
                if ($urlparts['scheme'] == "ssl") {
                    $urlparts['port'] = 443;
                }
                else {
                    $urlparts['port'] = 80;
                }
            }
     
            if (!isset($urlparts['path'])) {
                $urlparts['path'] = "/";
            }
            else if (($urlparts['path']{0} != '/') && ($_SERVER["PHP_SELF"]{0} == '/')) {
                $urlparts['path'] = substr($_SERVER["PHP_SELF"], 0, strrpos($_SERVER["PHP_SELF"], '/') + 1) . $urlparts['path'];
            }
     
            $this->scheme = $urlparts['scheme'];
            $this->host = $urlparts['host'];
            $this->port = $urlparts['port'];
            $this->path = $urlparts['path'];
        }
     
        function __invoke($function, $arguments) {
            $output = array(
                "output_type" => "xml",
                "verbosity" => "pretty",
                "escaping" => array("markup"),
                "version" => "xmlrpc",
                "encoding" => "utf-8");
            $request = xmlrpc_encode_request($function, $arguments, $output);
            $content_len = strlen($request);
            $errno = 0;
            $errstr = '';
            $host = ($this->scheme) ? $this->scheme . "://" . $this->host : $this->host;
            $handle = @fsockopen($host, $this->port, $errno, $errstr, $this->timeout);
            $buf = '';
            if ($handle) {
                $auth = '';
                if ($this->user) {
                    $auth = "Authorization: Basic " . base64_encode($this->user . ":" . $this->pass) . "\r\n";
                }
                $http_request =
                    "POST $this->path HTTP/1.0\r\n" .
                    "User-Agent: xmlrpc-epi-php/0.6 (PHP)\r\n" .
                    "Host: $this->host:$this->port\r\n" .
                    $auth .
                    "Content-Type: text/xml; charset=utf-8\r\n" .
                    "Content-Length: $content_len\r\n" .
                    "\r\n" .
                    $request;
                fputs($handle, $http_request, strlen($http_request));
                while (!feof($handle)) {
                    $buf .= fgets($handle, 128);
                }
                fclose($handle);
                if (strlen($buf)) {
    //                $xml = substr($buf, strpos($buf, "<?xml"));
            $xml = preg_replace("/[\\x00-\\x08\\x0b-\\x0c\\x0e-\\x1f]/","",substr($buf, strpos($buf, "<?xml")));
                    if (strlen($xml)) {
                        $result = xmlrpc_decode($xml);
                    }
                    else {
                        $result = new xmlrpc_error(6, "No data received from server");
                    }
                }
                else {
                    $result = new xmlrpc_error(6, "No data received from server");
                }
            }
            else {
                $result = new xmlrpc_error(5, "Didn't receive 200 OK from remote server");
            }
            return $result;
        }
     
        function invoke($function, $args) {
            $arguments = func_get_args();
            array_shift($arguments);
            return $this->__invoke($function, $arguments);
        }
     
        function call($function, $args) {
            $function = ($this->namespace == '') ? $function : $this->namespace . '.' . $function;
            $arguments = func_get_args();
            array_shift($arguments);
            return $this->__invoke($function, $arguments);
        }
    }
     
    /*
    if (function_exists("overload") && version_compare(phpversion(), "5", "<")) {
        class xmlrpc_client extends __xmlrpc_client {
            function __call($function, $arguments, &$return) {
                $function = ($this->namespace == '') ? $function : $this->namespace . '.' . $function;
                $return = $this->__invoke($function, $arguments);
                return true;
            }
        }
        overload('xmlrpc_client');
    }
    else {
        class xmlrpc_client extends __xmlrpc_client {
            function __call($function, $arguments) {
                $function = ($this->namespace == '') ? $function : $this->namespace . '.' . $function;
                return $this->__invoke($function, $arguments);
            }
        }
    }
    */
    ?>
    

    相关文章

      网友评论

          本文标题:微信公众号 企业付款 微信用户(商户号,微信公众号:appid,

          本文链接:https://www.haomeiwen.com/subject/sewbnhtx.html