微信支付的官方文檔雖然詳細,但缺乏現成的 Demo 代碼,導致初次接觸的開發者需要花費大量時間進行測試。從文檔可知,微信回調通知的數據結構相當複雜,屬於多段式數據,除了常規的 POST 數據外,還包含額外的 XML 格式信息,這就要求開發者必須同時掌握多種數據讀取方式。
理解 PHP 中 php://input 與 $_POST 的行為差異是關鍵。以下整理幾個核心規則:
application/x-www-form-urlencoded 時,PHP 會自動解析 Body 並填入 $_POST(已經過 urldecode)。multipart/form-data(涉及檔案上傳時會為空)。application/x-www-form-urlencoded 且為 POST 請求 時,$_POST 與 php://input 內容「一致」(格式不同但數據相同)。php://input 無法讀取 $_GET 數據,因為查詢字串在請求頭的 PATH 中。php://input 而非 $_POST,正是因為其 Content-Type 為 text/xml,PHP 不會自動解析填入 $_POST。微信支付通知同時包含表單字段與 XML 附加信息,必須採用雙通道讀取:
array ( 'bank_type' => '3006', 'discount' => '0', 'fee_type' => '1', 'input_charset' => 'UTF-8', 'notify_id' => 'YaNO6cznoNZK0aGb8nJWGgVUWssjt7Ze7gWRaRS0R_5w9oXgGNkRGxReEk0r45yk3I9a2_gzo9IqgqMYbap6bxC2T3p0o-2C', 'out_trade_no' => '1214284731', 'partner' => '12xxxxxxxx', 'product_fee' => '3400', 'sign' => '545FA0E8B594BBXXXX48XX142F084TY', 'sign_type' => 'MD5', 'time_end' => '20130223110224', 'total_fee' => '3400', 'trade_mode' => '1', 'trade_state' => '0', 'transaction_id' => '12XXX449012014XXX33174005XXX', 'transport_fee' => '0', )
<xml><OpenId><![CDATA[o0pd3jqHaN7b0tVPDFJPzJEkSCLw]]></OpenId> <AppId><![CDATA[wxXXX06XX2cXXX88XX]]></AppId> <IsSubscribe>1</IsSubscribe> <TimeStamp>1400814743</TimeStamp> <NonceStr><![CDATA[lqxwMsiY9EXRDpms]]></NonceStr> <AppSignature><![CDATA[c2dxxxe186116b32b06axxxc1a688b671eexxx5e]]></AppSignature> <SignMethod><![CDATA[sha1]]></SignMethod> </xml>
獲取兩部分數據後,需進行簽名驗證、訂單狀態更新、庫存扣減等業務邏輯。建議封裝為統一的通知處理類,異步處理耗時操作,並記錄完整日誌供排查。