1. 程式人生 > >微信發紅包 PHP 實現

微信發紅包 PHP 實現

follow 鏈接 scheme 好的 lan tools exit req reac

最近做生日營銷,需要微信發紅包,特此從網上找了一篇教程

首先你的有個服務號,並且開通了微信支付,我在這就不說怎麽去申請和開通了,我是看了微信官方文檔後,想看官方文檔的朋友可以到下面這個鏈接

https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_1

class WxRedPack
{
    //配置參數信息
    const SHANGHUHAO = "***********";//商戶號
    const PARTNERKEY = "***********";

    //核心支付函數,參數:請求地址和參數
    function
pay($url, $obj) { $obj[‘nonce_str‘] = $this->create_noncestr(); //創建隨機字符串 $stringA = $this->create_qianming($obj, false); //創建簽名 $stringSignTemp = $stringA . "&key=2470f691aee2bfae92087c10e81cb4d0"; //簽名後加api $sign = strtoupper(md5($stringSignTemp)); //
簽名加密並大寫 $obj[‘sign‘] = $sign; //將簽名傳入數組 $postXml = $this->arrayToXml($obj); //將參數轉為xml格式 $responseXml = $this->curl_post_ssl($url, $postXml); //提交請求 return $responseXml; } //生成簽名,參數:生成簽名的參數和是否編碼 function create_qianming($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); //去掉末尾符號“&” } return $reqPar; } //生成隨機字符串,默認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; } //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(__FILE__) . DIRECTORY_SEPARATOR . ‘cert‘ . DIRECTORY_SEPARATOR . ‘apiclient_cert.pem‘); curl_setopt($ch, CURLOPT_SSLKEY, dirname(__FILE__) . DIRECTORY_SEPARATOR . ‘cert‘ . DIRECTORY_SEPARATOR . ‘apiclient_key.pem‘); curl_setopt($ch, CURLOPT_CAINFO, dirname(__FILE__) . DIRECTORY_SEPARATOR . ‘cert‘ . DIRECTORY_SEPARATOR . ‘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; } } }
然後調用:
public function setredpack($moneys,$openid)
    {
        $money = $moneys; //最低1元,單位分
        $sender = "******";
        $obj2 = array();
        $obj2[‘wxappid‘] = "**********"; //appid
        $obj2[‘mch_id‘] = "***********";        //商戶id
        $obj2[‘mch_billno‘] = "********" . date(‘YmdHis‘) . rand(1000, 9999);//商戶訂單號
        $obj2[‘client_ip‘] = $_SERVER[‘REMOTE_ADDR‘];
        $obj2[‘re_openid‘] = $openid; //接收紅包openid
        $obj2[‘total_amount‘] = $money;
        $obj2[‘min_value‘] = $money;
        $obj2[‘max_value‘] = $money;
        $obj2[‘total_num‘] = 1;
        $obj2[‘scene_id‘] = ‘PRODUCT_2‘;
        $obj2[‘nick_name‘] = $sender;
        $obj2[‘send_name‘] = $sender;
        $obj2[‘wishing‘] = "恭喜發財";
        $obj2[‘act_name‘] = $sender ;
        $obj2[‘remark‘] = $sender ;

        $url = "https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack";
     $Wxpay = new WxRedPack();
    $res = $wxpay->pay($url, $obj2);return $res; 
}
另一個版本方法:

一個PHP文件搞定微信支付系列之現金紅包

網上的很多PHP微信支付接入教程都頗為復雜,且需要配置和引入較多的文件,本人通過整理後給出一個單文件版的,希望可以給各位想接入微信支付的帶來些許幫助和借鑒意義。

直接運行該文件即可給指定的微信用戶發送現金紅包。

需要註意的事項:

  • 1.微信現金紅包要求必傳證書,需要到https://pay.weixin.qq.com 賬戶中心->賬戶設置->API安全->下載證書,然後修改代碼中的證書路徑

  • 2.默認的使用場景是抽獎(即scene_id參數為PRODUCT_2),額度是1-200元,所以測試時的最低金額是1元。如需修改在產品中心->產品大全->現金紅包->產品設置中修改

  • 3.該文件需放到支付授權目錄下,可以在微信支付商戶平臺->產品中心->開發配置中設置。

  • 4.如提示簽名錯誤可以通過微信支付簽名驗證工具進行驗證:https://pay.weixin.qq.com/wik...

  • 5.錯誤碼參照 :https://pay.weixin.qq.com/wik...

  • <?php
    /**
     * 關於微信現金紅包的說明
     * 1.微信現金紅包要求必傳證書,需要到https://pay.weixin.qq.com 賬戶中心->賬戶設置->API安全->下載證書,證書路徑在第214行和217行修改
     * 2.默認的使用場景是抽獎(即scene_id參數為PRODUCT_2),額度是1-200元,所以測試時的最低金額是1元。如需修改在產品中心->產品大全->現金紅包->產品設置中修改
     * 3.錯誤碼參照 :https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_4&index=3
     */
    header(‘Content-type:text/html; Charset=utf-8‘);
    $mchid = ‘xxxxx‘;          //微信支付商戶號 PartnerID 通過微信支付商戶資料審核後郵件發送
    $appid = ‘xxxxx‘;  //微信支付申請對應的公眾號的APPID
    $appKey = ‘xxxxx‘;   //微信支付申請對應的公眾號的APP Key
    $apiKey = ‘xxxxx‘;   //https://pay.weixin.qq.com 帳戶設置-安全設置-API安全-API密鑰-設置API密鑰
    
    //①、獲取當前訪問頁面的用戶openid(如果給指定用戶發送紅包,則填寫指定用戶的openid)
    $wxPay = new WxpayService($mchid,$appid,$appKey,$apiKey);
    $openId = $wxPay->GetOpenid();      //獲取openid
    if(!$openId) exit(‘獲取openid失敗‘);
    //②、發送紅包
    $outTradeNo = uniqid();     //你自己的商品訂單號
    $payAmount = 1;          //紅包金額,單位:元
    $sendName = ‘織夢貓‘;    //紅包發送者名稱
    $wishing = ‘感謝您參加猜燈謎活動,祝您元宵節快樂!‘;      //紅包祝福語
    $act_name=‘猜燈謎搶紅包活動‘;           //活動名稱
    $result = $wxPay->createJsBizPackage($openId,$payAmount,$outTradeNo,$sendName,$wishing,$act_name);
    echo ‘success‘;
    
    class WxpayService
    {
        protected $mchid;
        protected $appid;
        protected $appKey;
        protected $apiKey;
        public $data = null;
    
        public function __construct($mchid, $appid, $appKey,$key)
        {
            $this->mchid = $mchid;
            $this->appid = $appid;
            $this->appKey = $appKey;
            $this->apiKey = $key;
        }
    
        /**
         * 通過跳轉獲取用戶的openid,跳轉流程如下:
         * 1、設置自己需要調回的url及其其他參數,跳轉到微信服務器https://open.weixin.qq.com/connect/oauth2/authorize
         * 2、微信服務處理完成之後會跳轉回用戶redirect_uri地址,此時會帶上一些參數,如:code
         * @return 用戶的openid
         */
        public function GetOpenid()
        {
            //通過code獲得openid
            if (!isset($_GET[‘code‘])){
                //觸發微信返回code碼
                $scheme = $_SERVER[‘HTTPS‘]==‘on‘ ? ‘https://‘ : ‘http://‘;
                $baseUrl = urlencode($scheme.$_SERVER[‘HTTP_HOST‘].$_SERVER[‘PHP_SELF‘].$_SERVER[‘QUERY_STRING‘]);
                $url = $this->__CreateOauthUrlForCode($baseUrl);
                Header("Location: $url");
                exit();
            } else {
                //獲取code碼,以獲取openid
                $code = $_GET[‘code‘];
                $openid = $this->getOpenidFromMp($code);
                return $openid;
            }
        }
    
        /**
         * 通過code從工作平臺獲取openid機器access_token
         * @param string $code 微信跳轉回來帶上的code
         * @return openid
         */
        public function GetOpenidFromMp($code)
        {
            $url = $this->__CreateOauthUrlForOpenid($code);
            $res = self::curlGet($url);
            //取出openid
            $data = json_decode($res,true);
            $this->data = $data;
            $openid = $data[‘openid‘];
            return $openid;
        }
    
        /**
         * 構造獲取open和access_toke的url地址
         * @param string $code,微信跳轉帶回的code
         * @return 請求的url
         */
        private function __CreateOauthUrlForOpenid($code)
        {
            $urlObj["appid"] = $this->appid;
            $urlObj["secret"] = $this->appKey;
            $urlObj["code"] = $code;
            $urlObj["grant_type"] = "authorization_code";
            $bizString = $this->ToUrlParams($urlObj);
            return "https://api.weixin.qq.com/sns/oauth2/access_token?".$bizString;
        }
    
        /**
         * 構造獲取code的url連接
         * @param string $redirectUrl 微信服務器回跳的url,需要url編碼
         * @return 返回構造好的url
         */
        private function __CreateOauthUrlForCode($redirectUrl)
        {
            $urlObj["appid"] = $this->appid;
            $urlObj["redirect_uri"] = "$redirectUrl";
            $urlObj["response_type"] = "code";
            $urlObj["scope"] = "snsapi_base";
            $urlObj["state"] = "STATE"."#wechat_redirect";
            $bizString = $this->ToUrlParams($urlObj);
            return "https://open.weixin.qq.com/connect/oauth2/authorize?".$bizString;
        }
    
        /**
         * 拼接簽名字符串
         * @param array $urlObj
         * @return 返回已經拼接好的字符串
         */
        private function ToUrlParams($urlObj)
        {
            $buff = "";
            foreach ($urlObj as $k => $v)
            {
                if($k != "sign") $buff .= $k . "=" . $v . "&";
            }
            $buff = trim($buff, "&");
            return $buff;
        }
    
        /**
         * 發送紅包
         * @param string $openid 用戶在該公眾號下的Openid
         * @param float $totalFee 紅包金額 單位元
         * @param string $outTradeNo 訂單號
         * @param string $orderName 紅包發送者名稱
         * @param string $wishing 祝福語
         * @param string $actName 互動名稱
         * @return string
         */
        public function createJsBizPackage($openid, $totalFee, $outTradeNo, $sendName,$wishing,$actName)
        {
            $config = array(
                ‘mch_id‘ => $this->mchid,
                ‘appid‘ => $this->appid,
                ‘key‘ => $this->apiKey,
            );
            $unified = array(
                ‘wxappid‘ => $config[‘appid‘],
                ‘send_name‘ => $sendName,
                ‘mch_id‘ => $config[‘mch_id‘],
                ‘nonce_str‘ => self::createNonceStr(),
                ‘re_openid‘ => $openid,
                ‘mch_billno‘ => $outTradeNo,
                ‘client_ip‘ => ‘127.0.0.1‘,
                ‘total_amount‘ => intval($totalFee * 100),       //單位 轉為分
                ‘total_num‘=>1,                 //紅包發放總人數
                ‘wishing‘=>$wishing,            //紅包祝福語
                ‘act_name‘=>$actName,           //活動名稱
                ‘remark‘=>‘remark‘,            //備註信息,如為中文註意轉為UTF8編碼
                ‘scene_id‘=>‘PRODUCT_2‘,      //發放紅包使用場景,紅包金額大於200時必傳。https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_4&index=3
            );
            $unified[‘sign‘] = self::getSign($unified, $config[‘key‘]);
            $responseXml = $this->curlPost(‘https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack‘, self::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);
            }
            return true;
        }
    
        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 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); //設置cURL允許執行的最長秒數
            if (!empty($options)) {
                curl_setopt_array($ch, $options);
            }
            //https請求 不驗證證書和host
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
    
            //第一種方法,cert 與 key 分別屬於兩個.pem文件
            //默認格式為PEM,可以註釋
            curl_setopt($ch,CURLOPT_SSLCERTTYPE,‘PEM‘);
            curl_setopt($ch,CURLOPT_SSLCERT,getcwd().‘/cert/apiclient_cert.pem‘);
            //默認格式為PEM,可以註釋
            curl_setopt($ch,CURLOPT_SSLKEYTYPE,‘PEM‘);
            curl_setopt($ch,CURLOPT_SSLKEY,getcwd().‘/cert/apiclient_key.pem‘);
            //第二種方式,兩個文件合成一個.pem文件
    //        curl_setopt($ch,CURLOPT_SSLCERT,getcwd().‘/all.pem‘);
            $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;
        }
    
        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;
        }
    }
    ?>

    github下載地址:https://github.com/dedemao/we...

微信發紅包 PHP 實現