針對開發人員的 PayPal 和 IPN(交易狀態更新)介紹


我的收件匣充滿垃圾郵件,這些郵件試圖勸誘我申請商店帳戶,讓網站接受信用卡付款。有了 PayPal,誰還需要那些東西?

如果你的網站需要接受電子付款,那麼 PayPal 就是你的最佳合作夥伴。你無需聯絡 PayPal 業務人員,也不必購買或安裝任何軟體。你需要的只是一個 PayPal 帳戶和一些基本的 HTML 與網路指令碼編寫技能。你可以使用 PayPal 作為線上支付方案,讓 PayPal 負責處理所有複雜的交易結帳工作。

任何網站都可以使用 PayPal 商店服務收取款項。只需填寫一張簡單的線上表格,PayPal 就會提供你一個按鈕,你可以將它貼到你的網站上,然後便可開始收款。無需處理程式設計。此項 PayPal 商店服務的元件名為「線上接受」。

PayPal 線上接受精靈

「線上接受」可獨立作業,如果與 PayPal 商店服務的「交易狀態更新 (IPN)」元件結合使用,功能將變得更加強大。使用交易狀態更新 (IPN),你的網站就可透過 PayPal 收取款項,一有付款,你的伺服器就會收到通知。採用簡單的 CGI 介面,PayPal 將所有你需要紀錄、處理並完成交易的付款詳細資料傳送到你的伺服器。

PayPal 交易狀態更新

如果結合「線上接受」與交易狀態更新,PayPal 將真正成為有價值、使用方便的網路服務。用戶支付的款項會直接存入你的 PayPal 帳戶,不會假手他人。必要時,PayPal 會為你收集運送資料。你還可以變更公司自動處理付款的等級。你剛開始時可先採用簡單的交易結帳流程,等業務逐漸成長後,再整合更多 PayPal 功能和服務,讓 PayPal 自動為你處理付款。

開始使用時,最簡單的方法是依照 PayPal 線上接受精靈的指示執行,並複製精靈給予的 HTML。然後根據你的網站需求,手動或利用程式撰寫模式修改 HTML。以下範例將一一介紹流程的步驟。附註:此範例的前提是我已經架設好網站並正在執行,同時我也有 PayPal 帳戶。

假設我生產小飾品,並希望在個人網站上透過 PayPal 銷售小飾品。首先,我使用 PayPal 的「線上接受」表填寫產品詳細資料,然後 PayPal 提供以下整段的 HTML 供我的網站使用:

<!-- Begin PayPal Logo -->
<form action="https://www.paypal.com/cgi-bin/webscr" method="post">
<input type="hidden" name="cmd" value="_xclick">
<input type="hidden" name="business" value="alanb@alanb.com">
<input type="hidden" name="undefined_quantity" value="1">
<input type="hidden" name="item_name" value="doodad from alanb.com">
<input type="hidden" name="item_number" value="dd01">
<input type="hidden" name="amount" value="4.99">
<input type="hidden" name="return" value="http://alanb.com/doodads/thanks.html">
<input type="hidden" name="cancel_return" value="http://alanb.com/doodads/canceled.html">
<input type="image" border="0" name="submit" src="http://images.paypal.com/images/x-click-but5.gif" alt="請使用 PayPal 付款 - 快捷、免費和安全的付款方式!">
</form>
<!-- End PayPal Logo -->

請注意:business 變數需對應我的電子郵件,電子郵件即我的 PayPal 帳戶。我可以編輯必要的物品名稱、物品編號和金額(價格)。

表格還包括兩個 URL,分別為 return 和 cancel_return。使用這些 URL,可使用戶在完成或取消 PayPal 交易後,返回我的網站。我已建立兩個簡單的網頁 thanks.html 和 canceled.html 作為示範。

我可以就此停止,把 HTML 放到一個網頁上,然後開始接受小飾品訂單。一旦有人按下 PayPal 按鈕並購買小飾品,PayPal 就會把交易詳細資料和客戶的聯絡資料透過電子郵件傳送給我。但是,如果我希望將客戶和交易資料自動輸入我的資料庫,我可以輕易地擴充 HTML 的上方區塊,以便在交易發生時通知我的網路伺服器。我只需將另一個隱藏的輸入欄位加入 HTML 表格即可:

<input type="hidden" name="notify_url" value="http://alanb.com/doodads/notify.cgi">

現在,每次出現小飾品訂單時,PayPal 的伺服器就會呼叫我的 CGI 指令碼 notify.cgi,其中包含訂單詳細資料。這就是交易狀態更新。PayPal 利用 HTTP POST 方法將交易詳細資料傳送到 notify.cgi。notify.cgi 之後會將該交易資料傳回至 PayPal 以確認付款的有效性。在這個簡單的範例中,notify.cgi 會將付款詳細資料紀錄到紀錄檔。PayPal 不要求 notify.cgi 提供任何特別的回應碼,因此我只輸出 foo 結束 HTTP 通訊。

以下是我的 HTML PayPal 按鈕 (已經過修改以使用「交易狀態更新」)及數個其他優化設置:

<!-- Begin PayPal Button -->
<form action="https://www.paypal.com/cgi-bin/webscr" method="post">
<input type="hidden" name="cmd" value="_xclick">
<input type="hidden" name="business" value="alanb@alanb.com">
<input type="hidden" name="undefined_quantity" value="1">
<input type="hidden" name="item_name" value="doodad from alanb.com">
<input type="hidden" name="item_number" value="dd01">
<input type="hidden" name="amount" value="1.99">
<input type="hidden" name="return">
value="http://alanb.com/doodads/thanks.cgi">
<input type="hidden" name="cancel_return">
value="http://alanb.com/doodads/canceled.html">
<input type="hidden" name="notify_url" value="http://alanb.com/doodads/notify.cgi">
<input type="image" border="0" name="submit" src="http://images.paypal.com/images/x-click-but5.gif" alt="使用 PayPal 購買小飾品">
</form>
<!-- End PayPal Button -->

And here is a simple Python script, notify.cgi:

#!/usr/local/bin/python

# notify.cgi -- CGI script that receives PayPal instant payment notifications
# Alan Braverman
# 2001-11-27

import sys, time, urllib

def confirmPayment():
"Ask PayPal to confirm this payment, return status and detail strings"
paymentDetails = sys.stdin.read() # formatted as a CGI query
confirmPostData = paymentDetails + '&cmd=_notify-validate'
confirmPostRequest = urllib.urlopen(
'http://www.paypal.com/cgi-bin/webscr', confirmPostData)
paymentStatus = confirmPostRequest.read() # either VERIFIED or INVALID
return paymentStatus, paymentDetails

def logPayment(paymentStatus, paymentDetails):
"Write payment status and details to a log file"
logFile = open('payments.log', 'a')
logFile.write('%s %s %s\n' % (
time.ctime(time.time()), paymentStatus, paymentDetails))
logFile.close()

def sendResponse():
"Send a simple HTTP response back to PayPal"
print 'Content-type: text/plain\n\nfoo'

def main(argc, argv):
"Process PayPal Instant Payment Notification CGI call"
paymentStatus, paymentDetails = confirmPayment()
logPayment(paymentStatus, paymentDetails)
sendResponse()

if __name__ == "__main__":
main(len(sys.argv), sys.argv)

當然,你可以用各種方式擴展這個概念,從寫入資料庫到自動處理訂單並交付產品或服務,而不是簡單地轉儲到紀錄檔。建議你保持 PayPal 介面常式簡單化,並保持其他流程執行的暢通以完成下單程序。如果 CGI 指令碼有錯誤,則會導致交易失敗。然而,在你的指令碼確認每筆付款之前,PayPal 會繼續通知你。你可以試試使用簡單的例子,便可看見 PayPal 正在點閱你的存取紀錄檔。同樣的道理,如果你的指令碼能夠區別特定的交易與重複的交易,則將可以更有效地從錯誤中復原。

用戶完成交易後,PayPal 會將交易詳細資料張貼到我的返回 URL。因此,我將 thanks.html 替換為 thanks.cgi 指令碼。在本範例中,thanks.cgi 僅會將用戶重新導向至 thanks.html。你可以加以延伸以利用「thanks」頁面中的訂單詳情,產生線上收據或你的清單。

以下是另一個簡單的 Python 指令碼 thanks.cgi:

#!/usr/local/bin/python

def main():
print 'Content-type: text/plain'
print 'Status: 302'
print 'Location: http://alanb.com/doodads/thanks.html'
print

if __name__ == "__main__":
main()

我將不會深入討論這篇文章的交易資料細節。請參閱 PayPal 網站上的交易狀態更新變數表。

當 PayPal 告知你已完成或取消某筆付款時,你就會知道如何著手進行處理。但有時 PayPal 可能會告訴你某筆款項正處於「待處理」狀態。待處理付款的處理方式比較麻煩,PayPal 能對此提供的協助也有限。根據 PayPal IPN 說明文件對於待處理付款的解釋,一發出付款就會通知你的伺服器,當該付款狀態從「待處理」變成「已完成」時會再次發出通知。

經驗豐富的網路工程師會知道 CGI 指令碼除錯的困難度。而 PayPal 也不會允許你付款給自己。為了測試端對端的產品流程,你可能需要建立測試物品並與朋友一起進行除錯。請僱請另一名開發人員協助進行 PayPal 測試。

「我的小飾品」範例已完成,並在 http://alanb.com/doodads 中執行,如果你想從買家的角度觀察其運作方式,可以前往該網站並向我購買小飾品。當然,我並不會發送任何東西給你,但我的小飾品價格可是非常公道哦!


免責聲明:上述內容不是由 PayPal, Inc. 或其任何合作夥伴、子公司提供,而是由每篇文章各自的作者提供。本文章可能含有錯誤,PayPal 不為其內容背書或提供支援。PayPal 建議你如有疑問,或者想了解有關技術支援、擔保或授權使用的資料,請與文章的作者直接聯絡。如果你選擇相信這些文章的內容,請自行承擔風險。若你因相信此內容而導致任何錯誤、傷害或者其他損壞(包括任何偶然的、特別的、間接的或者衍生的損壞),PayPal 概不負責。PayPal 明示排除所有關於本內容,以及使用本內容之保證。