微信公眾號(hào) 企業(yè)付款 微信用戶(商戶號(hào),微信公眾號(hào):appid,openid)demo

流程:

微信用戶從微信公眾號(hào)進(jìn)入查詢頁(yè)面(網(wǎng)頁(yè)授權(quán)獲取openid),進(jìn)行提交申請(qǐng)單。
后臺(tái)管理員進(jìn)行審核(支付,駁回),主要記錄支付操作。

事先準(zhǔn)備:

????1、商戶號(hào)
????2、公眾號(hào)(開(kāi)通支付功能)
????3、商戶號(hào)綁定到公眾號(hào)
????4、證書(shū)(由商戶號(hào)進(jìn)行生成導(dǎo)出,用于api驗(yàn)證)https://kf.qq.com/faq/180824BrQnQB180824m6v2yA.html

主要操作:主要兩個(gè)動(dòng)作(獲取openid,付款)**

一、 獲取用戶openid,并記錄。(時(shí)間,申請(qǐng)金額什么的亂七八糟的參數(shù)略略略略)

????可由公眾號(hào)會(huì)話生成(未用)
????網(wǎng)頁(yè)授權(quán)生成(因?yàn)橛许?yè)面用此方法)
????1、請(qǐng)求連接(https://open.weixin.qq.com/connect/oauth2/authorize?appid=*************d&redirect_uri=(回傳地址)jump.php&response_type=code&scope=snsapi_base&state=1#wechat_redirect)
????由中轉(zhuǎn)頁(yè)獲取code并請(qǐng)求獲取用戶openid。

jump.php

<?php
$url = "http:**************/jump.php";
baseAuth($url);
/**
 * 獲取用戶的openid
 * @param  string $openid [description]
 * @return [type]         [description]
 */
function baseAuth($redirect_url)
{
    //1.準(zhǔn)備scope為snsapi_base網(wǎng)頁(yè)授權(quán)頁(yè)面
    $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.靜默授權(quán),獲取code
    //頁(yè)面跳轉(zhuǎn)至redirect_uri/?code=CODE&state=STATE
    $code = $_GET['code'];
    if (!isset($code)) {
        header('Location:' . $snsapi_base_url);
    }
    //3.通過(guò)code換取網(wǎng)頁(yè)授權(quán)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']}");//最終頁(yè)面
}
//設(shè)置網(wǎng)絡(luò)請(qǐng)求配置
function curl($curl, $https = true, $method = 'GET', $data = null)
{
    // 創(chuàng)建一個(gè)新cURL資源
    $ch = curl_init();
    // 設(shè)置URL和相應(yīng)的選項(xiàng)
    curl_setopt($ch, CURLOPT_URL, $curl);    //要訪問(wèn)的網(wǎng)站
    curl_setopt($ch, CURLOPT_HEADER, false);    //啟用時(shí)會(huì)將頭文件的信息作為數(shù)據(jù)流輸出。
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);  //將curl_exec()獲取的信息以字符串返回,而不是直接輸出。 
    if ($https) {
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);  //FALSE 禁止 cURL 驗(yàn)證對(duì)等證書(shū)(peer's certificate)。
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, true);  //驗(yàn)證主機(jī)
    }
    if ($method == 'POST') {
        curl_setopt($ch, CURLOPT_POST, true);  //發(fā)送 POST 請(qǐng)求
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);  //全部數(shù)據(jù)使用HTTP協(xié)議中的 "POST" 操作來(lái)發(fā)送。
    }
    // 抓取URL并把它傳遞給瀏覽器
    $content = curl_exec($ch);
    if ($content  === false) {
        return "網(wǎng)絡(luò)請(qǐng)求出錯(cuò): " . curl_error($ch);
        exit();
    }
    //關(guān)閉cURL資源,并且釋放系統(tǒng)資源
    curl_close($ch);
 
    return $content;
}

二、 付款(用到之前準(zhǔn)備項(xiàng))

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

1、請(qǐng)求參數(shù)(簡(jiǎn)化過(guò)了,針對(duì)不同進(jìn)行需求修改)

 //支付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',//公眾號(hào)appid
   'partner_trade_no' => $pay_id,//商戶訂單號(hào)(標(biāo)準(zhǔn)見(jiàn)官方文檔)
   'openid' => $open_id,//接收人openid
   'amount' => $money * 100,//單位分
    'desc' => '微信提現(xiàn)',//描述
);
$rs = $this->wx_pay_client->call('transfers', $arr);//封裝過(guò)的支付rpc
if ($rs['result_code'] != 'SUCCESS') {
    $arr = array(
         'ret' => 0,
          'msg' => $rs['return_msg']
    );
}else{
 
}

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

<?php
define('APPID',"****c");//默認(rèn)appid(選填)
define('MCHID',"****");//商戶號(hào)
define('PARTNERKEY',"***********2");//商戶key
include_once("***class_xmlrpc.php");//xmlrpc操作類
class mmpaymktTransfers   {
    //核心支付函數(shù),參數(shù):請(qǐng)求地址和參數(shù)
    function postSSLCurl($url,$obj) {
        $obj['nonce_str'] = $this->create_noncestr();    //創(chuàng)建隨機(jī)字符串
        $obj['sign'] = $this->getSign($obj,false);    //將簽名傳入數(shù)組
        $postXml = $this->arrayToXml($obj);    //將參數(shù)轉(zhuǎn)為xml格式
        $responseXml = $this->curl_post_ssl($url,$postXml);    //提交請(qǐng)求
        $resarr = $this->xmlToArray($responseXml);
        return $resarr;
    }
    //生成簽名,參數(shù):生成簽名的參數(shù)和是否編碼
    function getSign($arr,$urlencode) {
        $buff = "";
        ksort($arr); //對(duì)傳進(jìn)來(lái)的數(shù)組參數(shù)里面的內(nèi)容按照字母順序排序,a在前面,z在最后(字典序)
        foreach ($arr as $k=>$v) {
            if(null!=$v && "null" != $v && "sign" != $k) {    //簽名不要轉(zhuǎn)碼
                if ($urlencode) {
                    $v = urlencode($v);
                }
                $buff.=$k."=".$v."&";
            }
        }
        if (strlen($buff)>0) {
            $reqPar = substr($buff,0,strlen($buff)-1); //去掉末尾符號(hào)“&”
        }
        $stringSignTemp = $reqPar."&key=".PARTNERKEY;    //簽名后加api
        $sign = strtoupper(md5($stringSignTemp));
        return $sign;
    }
    //生成隨機(jī)字符串,默認(rèn)32位
    function create_noncestr($length=32) {
        //創(chuàng)建隨機(jī)字符
        $chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
        $str = "";
        for($i=0;$i<$length;$i++) {
            $str.=substr($chars, mt_rand(0,strlen($chars)-1),1);
        }
        return $str;
    }
    //數(shù)組轉(zhuǎn)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轉(zhuǎn)數(shù)組
    function xmlToArray($string)
    {
        $ob= simplexml_load_string($string,'SimpleXMLElement', LIBXML_NOCDATA);//將字符串轉(zhuǎn)化為變量
        $json = json_encode($ob);//將對(duì)象轉(zhuǎn)化為JSON格式的字符串
        $array = json_decode($json, true);
        return $array;
    }
   //post請(qǐng)求網(wǎng)站,需要證書(shū)
    function curl_post_ssl($url, $vars, $second=30,$aHeader=array())
    {
        $ch = curl_init();
        //超時(shí)時(shí)間
        curl_setopt($ch,CURLOPT_TIMEOUT,$second);
        curl_setopt($ch,CURLOPT_RETURNTRANSFER, 1);
        //這里設(shè)置代理,如果有的話
        curl_setopt($ch,CURLOPT_URL,$url);
        curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false);
        curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,false);
 
        //cert 與 key 分別屬于兩個(gè).pem文件(關(guān)鍵點(diǎn)?。?
        //請(qǐng)確保您的libcurl版本是否支持雙向認(rèn)證,版本高于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;
        }
    }
 
}
//發(fā)送紅包
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'];//訂單號(hào),自定義
    $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;
}
//查詢紅包領(lǐng)取狀態(tài)
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指明這個(gè)openid來(lái)自哪個(gè)應(yīng)用
    $obj['mchid'] = MCHID;//mch_id
    $obj['partner_trade_no'] = $arr['partner_trade_no'];//商戶訂單號(hào)
    $obj['openid'] = $arr['openid'];//接收紅包openid
    $obj['amount'] = $arr['amount'];//金額(單位分)
    $obj['desc'] = $arr['desc'];
    $obj['check_name'] = 'NO_CHECK';//校驗(yàn)用戶姓名選項(xiàng),
    $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指明這個(gè)openid來(lái)自哪個(gè)應(yīng)用
    $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();
?>

順便帶上x(chóng)mlrpc.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);
        }
    }
}
*/
?>
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容