過程html
1. 用戶下單python
2. 商戶後臺產生訂單web
3. 請求支付寶web支付頁面(將訂單信息返回給用戶---放在form裏面---隱藏起來-----並經過腳本自動提交此form到支付寶web支付頁)api
4. 用戶在支付寶官方支付web頁上進行支付,完成後,支付寶跳轉(redirect)到form裏面的參數return_url指定的地址。同時異步方式通知商戶後臺(form裏面的參數notify_url指定接收通知的地址)瀏覽器
5. 在return_url指定的頁面裏顯示支付結果(在notify_url指定的頁面裏面處理髮貨邏輯)服務器
技術要點微信
1. 組裝form返回給客戶端,demo以下:異步
<html><head></head><body> <form id='alipaysubmit' name='alipaysubmit' enctype='multipart/form-data' action='https://mapi.alipay.com/gateway.do?_input_charset=utf-8' method='POST'> <input type="hidden" name="seller_email" value="xxx@163.com"/> <input type="hidden" name="_input_charset" value="utf-8"/> <input type="hidden" name="sign" value="31e0dce2c291cfac59401019e3dfe4da"/> <input type="hidden" name="notify_url" value="http://www.xxx.com/alipay_notify"/> <input type="hidden" name="partner" value="20888xxxxxxxx302"/> <input type="hidden" name="subject" value="test"/> <input type="hidden" name="service" value="create_direct_pay_by_user"/> <input type="hidden" name="out_trade_no" value="1470xxxx28068"/> <input type="hidden" name="payment_type" value="1"/> <input type="hidden" name="total_fee" value="0.01"/> <input type="hidden" name="sign_type" value="MD5"/> <input type="hidden" name="return_url" value="http://www.xxx.com/alipay_return"/> <input type="submit" value="submit" style="display:none"/> </form></body> <script>document.forms['alipaysubmit'].submit();</script></html> </html>
注意,基本每一個有name屬性的input的name對應參數都是必填。函數
官方文檔看這裏:https://doc.open.alipay.com/doc2/detail.htm?spm=a219a.7629140.0.0.YRtzUV&treeId=58&articleId=103584&docType=1post
2. 簽名
md5.加密(排序拼接串+密鑰)
所謂「排序拼接串」即爲:將參數按照名稱排序,而後拼接成a=1&b=2的形式(不要加入sign和sign_type參數),本例demo爲:
_input_charset=utf-8¬ify_url=http://www.xxx.com/alipay_notify&out_trade_no=1470xxxx28068&partner=20888xxxxxxxx302&payment_type=1&return_url=http://www.xxx.com/alipay_return&seller_email=xxx@163.com&service=create_direct_pay_by_user&subject=test&total_fee=0.01
python版本實現
for過程步驟3
import md5
def get_alipay_web_html(order_number, goods_name, total_price): """ DEMO演示:返回自動提交支付寶的form的html代碼
args in:
order_number, 商戶訂單號
goods_name, 貨物名稱(購買內容描述)
total_price, 總價 """ url_root = request.url_root web_alipay_data={ "service": "create_direct_pay_by_user", "partner": "2088xxxxxxxx11302", "_input_charset": "utf-8", "payment_type": "1", "notify_url": '%s%s'%(url_root, 'alipay_notify') , "return_url": '%s%s'%(url_root, 'alipay_return') ,# url_for('alipay_return'), "seller_email": "xxx@163.com", "out_trade_no": order_number, "subject": goods_name, "total_fee": total_price, "sign": "test", "sign_type": "MD5" } t="" for k,v in sorted(web_alipay_data.items(), key = lambda x:x[0]): if k not in ('sign', 'sign_type'): t+="%s=%s&"%(k,v) t=t[:-1] key = 'xxxx4mk9ms6rxxxxghlvyrd2sfdxxxx' #print t+key web_alipay_data.update({'sign':md5.new((t+key).encode('utf-8')).hexdigest()}) response_form_html ="""<html><head></head><body> <form id='alipaysubmit' name='alipaysubmit' enctype='multipart/form-data' action='https://mapi.alipay.com/gateway.do?_input_charset=utf-8' method='POST'> %s <input type="submit" value="submit" style="display:none"/> </form></body> <script>document.forms['alipaysubmit'].submit();</script></html> </html> """ html_inputs="" for k,v in web_alipay_data.items(): html_inputs +='<input type="hidden" name="%s" value="%s"/>\n'%(k,v) return response_form_html%html_inputs
在用戶提交訂單(一般post方式)到服務器後, 生成訂單,並將訂單信息包裹到form裏面(以上函數只包裹了訂單號),返回form給客戶端瀏覽器, 因爲腳本
<script>document.forms['alipaysubmit'].submit();</script>
的存在,此form會自動提交給支付寶。
注意變動 partner參數(商戶id)和 key參數(md5加密用密鑰,不知道看這裏),以及商家的郵箱(seller_email);
回調地址(notify_url)和返回地址(return_url)根據實際狀況修改。
支付通知回調
支付寶會將支付結果異步的方式post/get給商戶服務器。
在post方式中,有一個問題須要注意:
若是notifiy_url對應的url裏面有參數(例如: notify_url?xxx_field=xxx_value), 支付寶會將此參數截取出來,放到post的body中,收到的body段會多一個( &xxx_field=xxx_value), 此字段不能參與簽名驗證! 不然簽名不匹配!
即自定義的url參數,會在異步通知的body中post回來, 簽名時要把他們排除出去!!!這一點官方文檔沒有說明。
後記
支付寶/微信支付麻煩的不是技術,而是各類配置,「平臺」入口太多, 一不當心就掉坑裏了。
轉載請註明來自:http://www.cnblogs.com/Tommy-Yu/p/5739971.html,謝謝!