微信紅包是營銷活動的利器,本文深度解析 PHP 實現微信公眾號發送紅包的完整流程,提供從底層 API 封裝到高層類庫的多種代碼方案,助你快速落地。
封裝簽名生成、證書雙向認證、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...
}
class ArrayToXML {
public function toXml($data) {
$xml = '';
foreach ($data as $key => $value) {
if (is_numeric($value)) {
$xml .= "<$key>$value$key>";
} else {
$xml .= "<$key>$key>";
}
}
$xml .= ' ';
return $xml;
}
}
支援 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) { /* ... */ }
}
更貼近官方文檔參數命名,含完整支付流程:
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 位隨機串 */ }
}
getcwd() 確保正確。微信紅包開發核心在於參數規範、簽名正確、證書配置。本文提供的三種封裝層級(基礎類、綜合類庫、實戰版)可根據項目複雜度選擇。建議封裝為 Composer 包,統一管理配置與依賴,提升複用性。