首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 微信紅包開發全攻略:從核心接口到完整類庫實戰

     編輯:PHP 綜合知識

前言

微信紅包是營銷活動的利器,本文深度解析 PHP 實現微信公眾號發送紅包的完整流程,提供從底層 API 封裝到高層類庫的多種代碼方案,助你快速落地。

核心接口實現:wechat_packet 類

封裝簽名生成、證書雙向認證、XML 組裝、cURL 請求等核心邏輯:

class wechat_packet {
    private $url = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack';
    private $mch_id, $weixin_appid, $send_name, $total_num = 1;
    private $wishing, $client_ip, $act_name, $remark, $nonce_str, $api_password;
    private $public_key = "/api/wechat/cert/apiclient_cert.pem";
    private $private_key = '/api/wechat/cert/apiclient_key.pem';
    private $rootca = 'api/wechat/cert/rootca.pem';
    private $arraytoxml;

    public function __construct() {
        // 從配置讀取參數
        $this->weixin_appid = C('wap_weixin_appid');
        $this->mch_id = C('wechat_mch_id');
        $this->send_name = C('wechat_send_name');
        $this->wishing = C('wechat_wishing');
        $this->act_name = C('wechat_act_name');
        $this->client_ip = $_SERVER['SERVER_ADDR'];
        $this->remark = C('wechat_remark');
        $this->nonce_str = $this->create_nonce_str(32);
        $this->api_password = C('wechat_api_password');
        require BASE_PATH . DS . 'api' . DS . 'wechat' . DS . 'arraytoxml.php';
        $this->arraytoxml = new ArrayToXML();
    }

    public function send_post($mch_billno, $re_openid, $total_amount) {
        $sign = $this->create_sign($mch_billno, $re_openid, $total_amount);
        $send_array = [
            'nonce_str' => $this->nonce_str,
            'mch_billno' => $mch_billno,
            'mch_id' => $this->mch_id,
            'wxappid' => $this->weixin_appid,
            'send_name' => $this->send_name,
            're_openid' => $re_openid,
            'total_amount' => $total_amount,
            'total_num' => $this->total_num,
            'wishing' => $this->wishing,
            'client_ip' => $this->client_ip,
            'act_name' => $this->act_name,
            'remark' => $this->remark,
            'sign' => $sign,
        ];
        $send_xml = $this->arraytoxml->toXml($send_array, '');
        $data = $this->curl_post_ssl($this->url, $send_xml);
        $data = $this->xmlToArray($data);
        file_put_contents('adki', var_export($data, true), FILE_APPEND);
    }

    // 雙向證書 cURL 請求
    private function curl_post_ssl($url, $vars, $second = 30, $aHeader = []) {
        $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);
        curl_setopt($ch, CURLOPT_SSLCERTTYPE, 'PEM');
        curl_setopt($ch, CURLOPT_SSLCERT, getcwd() . $this->public_key);
        curl_setopt($ch, CURLOPT_SSLKEYTYPE, 'PEM');
        curl_setopt($ch, CURLOPT_SSLKEY, getcwd() . $this->private_key);
        curl_setopt($ch, CURLOPT_CAINFO, $this->rootca);
        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; }
        $error = curl_errno($ch);
        curl_close($ch);
        return false;
    }

    // 簽名生成(參數 ASCII 排序 + key + MD5 大寫)
    private function create_sign($mch_billno, $re_openid, $total_amount) {
        $string_array = [
            'act_name' => $this->act_name, 'client_ip' => $this->client_ip,
            'mch_billno' => $mch_billno, 'mch_id' => $this->mch_id,
            'nonce_str' => $this->nonce_str, 're_openid' => $re_openid,
            'remark' => $this->remark, 'send_name' => $this->send_name,
            'total_amount' => $total_amount, 'total_num' => $this->total_num,
            'wishing' => $this->wishing, 'wxappid' => $this->weixin_appid,
        ];
        $stringA = '';
        foreach ($string_array as $key => $value) {
            if (!empty($value)) {
                $stringA .= "$key=$value";
                if ($key !== 'wxappid') $stringA .= '&';
            }
        }
        $stringA = $this->gbkToUtf8($stringA);
        $stringSignTemp = "$stringA&key=$this->api_password";
        return strtoupper(md5($stringSignTemp));
    }

    // 其他輔助方法:create_nonce_str, gbkToUtf8, xmlToArray...
}

數組轉 XML 工具類

class ArrayToXML {
    public function toXml($data) {
        $xml = '';
        foreach ($data as $key => $value) {
            if (is_numeric($value)) {
                $xml .= "<$key>$value";
            } else {
                $xml .= "<$key>";
            }
        }
        $xml .= '';
        return $xml;
    }
}

進階封裝:WxApi 綜合類庫

支援 AccessToken、用戶信息、模板消息、OAuth、紅包等全套微信接口:

class WxApi {
    const appId = ""; const appSecret = ""; const mchid = ""; const privatekey = "";
    public $parameters = [];

    // HTTPS 請求(普通/帶證書)
    public function wxHttpsRequest($url, $data = null) { /* ... */ }
    public function wxHttpsRequestPem($url, $vars, $second = 30, $aHeader = []) { /* ... */ }

    // AccessToken & 用戶信息
    public function wxAccessToken($appId = null, $appSecret = null) { /* ... */ }
    public function wxGetUser($openId) { /* ... */ }

    // 模板消息
    public function wxSendTemplate($jsonData) { /* ... */ }
    public function wxSetSend($touser, $template_id, $url, $data, $topcolor = '#7B68EE') { /* ... */ }

    // OAuth 授權
    public function wxOauthBase($redirectUrl, $state = "", $appId = null) { /* ... */ }
    public function wxOauthUserinfo($redirectUrl, $state = "", $appId = null) { /* ... */ }
    public function wxOauthAccessToken($code, $appId = null, $appSecret = null) { /* ... */ }
    public function wxOauthUser($OauthAT, $openId) { /* ... */ }

    // 紅包專用:隨機串、商戶訂單號、參數格式化、簽名、XML 轉換
    public function wxNonceStr($length = 16, $type = false) { /* ... */ }
    public function wxMchBillno($mchid = null) { /* ... */ }
    public function wxSetParam($parameters) { /* ... */ }
    public function wxFormatArray($parameters = null, $urlencode = false) { /* ... */ }
    public function wxMd5Sign($content, $privatekey) { /* ... */ }
    public function wxSha1Sign($content, $privatekey) { /* ... */ }
    public function wxArrayToXml($parameters = null) { /* ... */ }
}

另一實戰版本:Wxapi + WxHongBaoHelper

更貼近官方文檔參數命名,含完整支付流程:

class Wxapi {
    private $app_id = 'wxXXXXXXXXXXXX';
    private $app_secret = 'XXXXXXXXXXXXXXXXXXXXXXXX';
    private $app_mchid = 'XXXXXXXX';

    public function pay($re_openid) {
        include_once('WxHongBaoHelper.php');
        $wxHongBaoHelper = new WxHongBaoHelper();
        $wxHongBaoHelper->setParameter("nonce_str", $this->great_rand());
        $wxHongBaoHelper->setParameter("mch_billno", $this->app_mchid . date('YmdHis') . rand(1000, 9999));
        $wxHongBaoHelper->setParameter("mch_id", $this->app_mchid);
        $wxHongBaoHelper->setParameter("wxappid", $this->app_id);
        $wxHongBaoHelper->setParameter("nick_name", '紅包');
        $wxHongBaoHelper->setParameter("send_name", '紅包');
        $wxHongBaoHelper->setParameter("re_openid", $re_openid);
        $wxHongBaoHelper->setParameter("total_amount", 100); // 分
        $wxHongBaoHelper->setParameter("min_value", 100);
        $wxHongBaoHelper->setParameter("max_value", 100);
        $wxHongBaoHelper->setParameter("total_num", 1);
        $wxHongBaoHelper->setParameter("wishing", '感謝您參與紅包派發活動,祝您新年快樂!');
        $wxHongBaoHelper->setParameter("client_ip", '127.0.0.1');
        $wxHongBaoHelper->setParameter("act_name", '紅包活動');
        $wxHongBaoHelper->setParameter("remark", '快來搶!');

        $postXml = $wxHongBaoHelper->create_hongbao_xml();
        $url = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack';
        $responseXml = $wxHongBaoHelper->curl_post_ssl($url, $postXml);
        $responseObj = simplexml_load_string($responseXml, 'SimpleXMLElement', LIBXML_NOCDATA);
        return $responseObj->return_code;
    }

    public function great_rand() { /* 生成 30 位隨機串 */ }
}

關鍵技術點總結

  1. 簽名算法:參數按 ASCII 排序 → key=value 拼接 → 末尾加 &key=API密鑰 → MD5 → 大寫。
  2. 雙向證書:需配置 apiclient_cert.pem、apiclient_key.pem、rootca.pem,cURL 設置 CURLOPT_SSLCERT/CURLOPT_SSLKEY/CURLOPT_CAINFO。
  3. 隨機串:32 位以內字母數字組合,防重放攻擊。
  4. 商戶訂單號:商戶號 + 日期時間 + 隨機數,確保唯一。
  5. 金額單位:紅包接口金額單位為「分」,非元。

常見坑位避雷

  • libcurl 版本需 ≥ 7.20.1 支援雙向認證。
  • 證書路徑必須為絕對路徑,getcwd() 確保正確。
  • 簽名參數不可遺漏,順序必須嚴格按 ASCII 排序。
  • 測試時關閉 CURLOPT_SSL_VERIFYPEER/VERIFYHOST,生產環境建議開啟並配置 CA 證書。

結語

微信紅包開發核心在於參數規範、簽名正確、證書配置。本文提供的三種封裝層級(基礎類、綜合類庫、實戰版)可根據項目複雜度選擇。建議封裝為 Composer 包,統一管理配置與依賴,提升複用性。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved