PHP微信支付

1.微信公眾平臺開通微信支付,審核通過。
2.微信商戶平臺配置支付授權(quán)目錄

Paste_Image.png

3.微信交易單號獲取類

<?php

/*
 * 生活服務(wù)_微信付款
 */

namespace Apis\Controller;

use Common\Controller\AppframeController;

class WxpayController extends AppframeController {

    protected $mchid;
    protected $appid;
    protected $key;

    public function _initialize() {
        parent::_initialize();

        $this->mchid = '1430532102'; // 微信支付商戶號 PartnerID 通過微信支付商戶資料審核后郵件發(fā)送
        $this->appid = 'wx20d62ad060e66486'; //公眾號APPID 通過微信支付商戶資料審核后郵件發(fā)送
        $this->key = '8934e7d15453e97507ef7mao521125ab';   //https://pay.weixin.qq.com 帳戶設(shè)置-安全設(shè)置-API安全-API密鑰-設(shè)置API密鑰
    }

    public function createJsBizPackage($openid, $totalFee, $outTradeNo, $orderName, $notifyUrl, $timestamp) {
        
        $config = array(
            'mch_id' => $this->mchid,
            'appid' => $this->appid,
            'key' => $this->key,
        );
        
        $unified = array(
            'appid' => $config['appid'],
            'attach' => '支付', //商家數(shù)據(jù)包,原樣返回
            'body' => $orderName,
            'mch_id' => $config['mch_id'],
            'nonce_str' => $this->createNonceStr(),
            'notify_url' => $notifyUrl,
            'openid' => $openid, //rade_type=JSAPI,此參數(shù)必傳
            'out_trade_no' => $outTradeNo,
            'spbill_create_ip' => '127.0.0.1',
            'total_fee' => intval($totalFee * 100), //單位 轉(zhuǎn)為分
            'trade_type' => 'JSAPI',
        );
        
        $unified['sign'] = $this->getSign($unified, $config['key']);
        $responseXml = $this->curlPost('https://api.mch.weixin.qq.com/pay/unifiedorder', $this->arrayToXml($unified));
        
        $unifiedOrder = simplexml_load_string($responseXml, 'SimpleXMLElement', LIBXML_NOCDATA);
        if ($unifiedOrder === false) {
            die('parse xml error');
        }
        if ($unifiedOrder->return_code != 'SUCCESS') {
            die($unifiedOrder->return_msg);
        }
        if ($unifiedOrder->result_code != 'SUCCESS') {
            die($unifiedOrder->err_code);
            /*
              NOAUTH 商戶無此接口權(quán)限
              NOTENOUGH 余額不足
              ORDERPAID 商戶訂單已支付
              ORDERCLOSED 訂單已關(guān)閉
              SYSTEMERROR 系統(tǒng)錯誤
              APPID_NOT_EXIST   APPID不存在
              MCHID_NOT_EXIST MCHID不存在
              APPID_MCHID_NOT_MATCH appid和mch_id不匹配
              LACK_PARAMS 缺少參數(shù)
              OUT_TRADE_NO_USED 商戶訂單號重復(fù)
              SIGNERROR 簽名錯誤
              XML_FORMAT_ERROR XML格式錯誤
              REQUIRE_POST_METHOD 請使用post方法
              POST_DATA_EMPTY post數(shù)據(jù)為空
              NOT_UTF8 編碼格式錯誤
             */
        }
        //$unifiedOrder->trade_type 交易類型 調(diào)用接口提交的交易類型,取值如下:JSAPI,NATIVE,APP
        //$unifiedOrder->prepay_id 預(yù)支付交易會話標(biāo)識 微信生成的預(yù)支付回話標(biāo)識,用于后續(xù)接口調(diào)用中使用,該值有效期為2小時
        //$unifiedOrder->code_url 二維碼鏈接 trade_type為NATIVE是有返回,可將該參數(shù)值生成二維碼展示出來進(jìn)行掃碼支付
        $arr = array(
            "appId" => $config['appid'],
            "timeStamp" => $timestamp,
            "nonceStr" => $this->createNonceStr(),
            "package" => "prepay_id=" . $unifiedOrder->prepay_id,
            "signType" => 'MD5',
        );
        $arr['paySign'] = $this->getSign($arr, $config['key']);
        return $arr;
    }

    public function notify() {
        $config = array(
            'mch_id' => $this->mchid,
            'appid' => $this->appid,
            'key' => $this->key,
        );
        $postStr = $GLOBALS["HTTP_RAW_POST_DATA"];
        
        $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
        if ($postObj === false) {
            die('parse xml error');
        }
        if ($postObj->return_code != 'SUCCESS') {
            die($postObj->return_msg);
        }
        if ($postObj->result_code != 'SUCCESS') {
            die($postObj->err_code);
        }
        $arr = (array) $postObj;
        unset($arr['sign']);
        if ($this->getSign($arr, $config['key']) == $postObj->sign) {
            // $mch_id = $postObj->mch_id; //微信支付分配的商戶號
            // $appid = $postObj->appid; //微信分配的公眾賬號ID
            // $openid = $postObj->openid; //用戶在商戶appid下的唯一標(biāo)識
            // $transaction_id = $postObj->transaction_id;//微信支付訂單號
            // $out_trade_no = $postObj->out_trade_no;//商戶訂單號
            // $total_fee = $postObj->total_fee; //訂單總金額,單位為分
            // $is_subscribe = $postObj->is_subscribe; //用戶是否關(guān)注公眾賬號,Y-關(guān)注,N-未關(guān)注,僅在公眾賬號類型支付有效
            // $attach = $postObj->attach;//商家數(shù)據(jù)包,原樣返回
            // $time_end = $postObj->time_end;//支付完成時間
            echo '<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
            return $postObj;
        }
    }

    /**
     * curl get
     *
     * @param string $url
     * @param array $options
     * @return mixed
     */
    public static function curlGet($url = '', $options = array()) {
        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
        if (!empty($options)) {
            curl_setopt_array($ch, $options);
        }
        //https請求 不驗證證書和host
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        $data = curl_exec($ch);
        curl_close($ch);
        return $data;
    }

    public static function curlPost($url = '', $postData = '', $options = array()) {
        if (is_array($postData)) {
            $postData = http_build_query($postData);
        }
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30); //設(shè)置cURL允許執(zhí)行的最長秒數(shù)
        if (!empty($options)) {
            curl_setopt_array($ch, $options);
        }
        //https請求 不驗證證書和host
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        $data = curl_exec($ch);
        curl_close($ch);
        return $data;
    }

    public static function createNonceStr($length = 16) {
        $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
        $str = '';
        for ($i = 0; $i < $length; $i++) {
            $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
        }
        return $str;
    }

    public static 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;
    }

    /**
     * 例如:
     * appid:  wxd930ea5d5a258f4f
     * mch_id:  10000100
     * device_info: 1000
     * Body:  test
     * nonce_str: ibuaiVcKdpRxkhJA
     * 第一步:對參數(shù)按照 key=value 的格式,并按照參數(shù)名 ASCII 字典序排序如下:
     * stringA="appid=wxd930ea5d5a258f4f&body=test&device_info=1000&mch_i
     * d=10000100&nonce_str=ibuaiVcKdpRxkhJA";
     * 第二步:拼接支付密鑰:
     * stringSignTemp="stringA&key=192006250b4c09247ec02edce69f6a2d"
     * sign=MD5(stringSignTemp).toUpperCase()="9A0A8659F005D6984697E2CA0A9CF3B7"
     */
    public static function getSign($params, $key) {
        ksort($params, SORT_STRING);
        $unSignParaString = self::formatQueryParaMap($params, false);
        $signStr = strtoupper(md5($unSignParaString . "&key=" . $key));
        return $signStr;
    }

    protected static function formatQueryParaMap($paraMap, $urlEncode = false) {
        $buff = "";
        ksort($paraMap);
        foreach ($paraMap as $k => $v) {
            if (null != $v && "null" != $v) {
                if ($urlEncode) {
                    $v = urlencode($v);
                }
                $buff .= $k . "=" . $v . "&";
            }
        }
        $reqPar = '';
        if (strlen($buff) > 0) {
            $reqPar = substr($buff, 0, strlen($buff) - 1);
        }
        return $reqPar;
    }

}

//方法調(diào)用
$res = $wx->createJsBizPackage($openid, $totalFee, $outTradeNo, $orderName, $notifyUrl, $timestamp);

3.回調(diào)函數(shù)

<?php
header('Content-Type: text/html; charset=utf-8');
$mysql_server_name='localhost'; //改成自己的mysql數(shù)據(jù)庫服務(wù)器
$mysql_username='root'; //改成自己的mysql數(shù)據(jù)庫用戶名
$mysql_password='Pa1mtrends'; //改成自己的mysql數(shù)據(jù)庫密碼
$mysql_database='cloud'; //
$conn=mysql_connect($mysql_server_name,$mysql_username,$mysql_password) or die("error connecting") ; //連接數(shù)據(jù)庫
mysql_query("set names 'utf8'"); //數(shù)據(jù)庫輸出編碼 應(yīng)該與你的數(shù)據(jù)庫編碼保持一致.南昌網(wǎng)站建設(shè)公司百恒網(wǎng)絡(luò)PHP工程師建議用UTF-8 國際標(biāo)準(zhǔn)編碼.
mysql_select_db($mysql_database); //打開數(shù)據(jù)庫

$mchid = '143053xxxx'; // 微信支付商戶號 PartnerID 通過微信支付商戶資料審核后郵件發(fā)送
$appid = 'wx20d62ad06xxxxx'; //公眾號APPID 通過微信支付商戶資料審核后郵件發(fā)送
$key = '8934e7d15453e97507ef7mao5xxxxxx';   //https://pay.weixin.qq.com 帳戶設(shè)置-安全設(shè)置-API安全-API密鑰-設(shè)置API密鑰

$config = array(
    'mch_id' => $mchid,
    'appid' => $appid,
    'key' => $key,
);

$postStr = file_get_contents("php://input");
if (!$postStr) {
    $postStr = "maozi";
}

$postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);

if ($postObj === false) {
    die('parse xml error');
}
if ($postObj->return_code != 'SUCCESS') {
    die($postObj->return_msg);
}
if ($postObj->result_code != 'SUCCESS') {
    die($postObj->err_code);
}
$arr = (array) $postObj;
unset($arr['sign']);

if (getSign($arr, $config['key']) == $postObj->sign) {
    
    $mch_id = $postObj->mch_id; //微信支付分配的商戶號
    $appid = $postObj->appid; //微信分配的公眾賬號ID
    $openid = $postObj->openid; //用戶在商戶appid下的唯一標(biāo)識
    $transaction_id = $postObj->transaction_id;//微信支付訂單號
    $out_trade_no = $postObj->out_trade_no;//商戶訂單號
    $total_fee = $postObj->total_fee; //訂單總金額,單位為分
    $total_fee = floatval($total_fee/100);
    
    $time_end = $postObj->time_end;//支付完成時間
    $time_end = strtotime(substr($time_end,0,4)."-".substr($time_end, 4,2)."-".substr($time_end,6,2)." ".substr($time_end,8,2).":".  substr($time_end, 10, 2).":".substr($time_end, 12, 2));
    
    //用戶id
    $res = mysql_query("select * from cmf_market_order where sn='{$out_trade_no}'",$conn);
    $oinfo = mysql_fetch_assoc($res);
    $uid = $oinfo['uid'];
    
    //查詢訂單是否存在
    $has_sql = "select * from cmf_market_order_wx where wx_sn='{$transaction_id}'";
    $has = mysql_query($has_sql,$conn);
    $has = mysql_fetch_assoc($has);
    if ($has) {
        echo '<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
        exit;
    }
    
    //插入微信訂單信息
    $sql = "insert into cmf_market_order_wx (mch_id,appid,openid,uid,sn,wx_sn,total,time) values ('{$mch_id}','{$appid}','{$openid}','{$uid}','{$out_trade_no}','{$transaction_id}','{$total_fee}','{$time_end}')";
    $result = mysql_query($sql,$conn);
    if ($result) {//更新訂單狀態(tài)
        $up_sql = "update cmf_market_order set haspay=1,status=1,paytime='{$time_end}' where sn='{$out_trade_no}'";
        $result_update = mysql_query($up_sql,$conn);
    }
    
    echo '<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
    return $postObj;
}

function getSign($params, $key) {
    ksort($params, SORT_STRING);
    $unSignParaString = formatQueryParaMap($params, false);
    $signStr = strtoupper(md5($unSignParaString . "&key=" . $key));
    return $signStr;
}

function formatQueryParaMap($paraMap, $urlEncode = false) {
    $buff = "";
    ksort($paraMap);
    foreach ($paraMap as $k => $v) {
        if (null != $v && "null" != $v) {
            if ($urlEncode) {
                $v = urlencode($v);
            }
            $buff .= $k . "=" . $v . "&";
        }
    }
    $reqPar = '';
    if (strlen($buff) > 0) {
        $reqPar = substr($buff, 0, strlen($buff) - 1);
    }
    return $reqPar;
}

?>

4.支付頁面,直接調(diào)用支付接口

<html>
<head>
    <meta http-equiv="content-type" content="text/html;charset=utf-8"/>
    <title>微信安全支付</title>
    
    
    <script type="text/javascript">
        //調(diào)用微信JS api 支付
        function jsApiCall()
        {
            WeixinJSBridge.invoke(
                'getBrandWCPayRequest',
                {
                    "appId": "{$info['appId']}",
                    "timeStamp": "{$info['timeStamp']}",
                    "nonceStr": "{$info['nonceStr']}",
                    "package": "{$info['package']}",
                    "signType": "MD5",
                    "paySign": "{$info['paySign']}"
                },
                function(res){
                    if (res.err_msg == 'get_brand_wcpay_request:ok') {
                        alert("支付成功");
                        window.location.;
                    } else {
                        alert("錯誤");
                    }
                }
            );
        }
        function callpay()
        {
            if (typeof WeixinJSBridge == "undefined"){
                if( document.addEventListener ){
                    document.addEventListener('WeixinJSBridgeReady', jsApiCall, false);
                }else if (document.attachEvent){
                    document.attachEvent('WeixinJSBridgeReady', jsApiCall); 
                    document.attachEvent('onWeixinJSBridgeReady', jsApiCall);
                }
            }else{
                jsApiCall();
            }
        }
    </script>
</head>
<body>
    </br></br></br></br>
    <div align="center">
        <button style="width:210px; height:30px; background-color:#FE6714; border:0px #FE6714 solid; cursor: pointer;  color:white;  font-size:16px;" type="button" onclick="callpay()" >貢獻(xiàn)一下11111111</button>
    </div>
</body>
</html>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,622評論 6 544
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,716評論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,746評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,991評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 72,706評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 56,036評論 1 329
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,029評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 43,203評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,725評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 41,451評論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,677評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,161評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,857評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,266評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,606評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,407評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 48,643評論 2 380

推薦閱讀更多精彩內(nèi)容