windows系統安裝Python虛擬環境python
首先保證你的系統已經安裝好了Pythonmysql
安裝virtualenvreact
C:\WINDOWS\system32>pip3 install virtualenv Collecting virtualenv Downloading virtualenv-15.1.0-py2.py3-none-any.whl (1.8MB) 100% |████████████████████████████████| 1.8MB 110kB/s Installing collected packages: virtualenv Successfully installed virtualenv-15.1.0 C:\WINDOWS\system32>
安裝virtualenvwrappersql
virtualenvwrapper是virtualenv的一個方便管理虛擬環境的管理器數據庫
pip3 install virtualenvwrapper
指定虛擬環境,保存路徑django
首先在要保存虛擬環境的地方建立一個Evns目錄,而後將這個目錄添加到系統環境變量,之後建立的虛擬環境就會保存在這個目錄,重啓系統後生效json
建立虛擬環境,建立後會自動進入虛擬環境vim
mkvirtualenv 虛擬環境名稱windows
[root@192 xu_ni_huan_jing]# mkvirtualenv jxiou Using base prefix '/usr/local' New python executable in /usr/xu_ni_huan_jing/jxiou/bin/python3.5 Also creating executable in /usr/xu_ni_huan_jing/jxiou/bin/python Installing setuptools, pip, wheel...done. virtualenvwrapper.user_scripts creating /usr/xu_ni_huan_jing/jxiou/bin/predeactivate virtualenvwrapper.user_scripts creating /usr/xu_ni_huan_jing/jxiou/bin/postdeactivate virtualenvwrapper.user_scripts creating /usr/xu_ni_huan_jing/jxiou/bin/preactivate virtualenvwrapper.user_scripts creating /usr/xu_ni_huan_jing/jxiou/bin/postactivate virtualenvwrapper.user_scripts creating /usr/xu_ni_huan_jing/jxiou/bin/get_env_details (jxiou) [root@192 xu_ni_huan_jing]#
5.退出虛擬環境api
deactivate
(jxiou) [root@192 xu_ni_huan_jing]# deactivate [root@192 xu_ni_huan_jing]#
6.查看有哪些虛擬環境
workon
[root@192 /]# workon jxiou2 jxiou [root@192 /]#
7.進入一個指定的虛擬環境
workon jxiou(虛擬環境名稱)
[root@192 /]# workon jxiou (jxiou) [root@192 /]#
8.虛擬環境建立好後,建立Django項目,建立好數據庫,開始本地調試支付請求
支付寶接口集成 ,本地環境調試支付請求
1。首先登陸 螞蟻金服網站,也就是支付寶開發者平臺
登陸螞蟻金服開發者平臺後,建立沙箱應用
也就是支付寶給開發者提供的調試環境應用
注意這裏咱們必定選擇RSA2(SHA256)密鑰(推薦),這個是比較安全的方式,
2.咱們設置應用公鑰
設置公鑰,訪問https://docs.open.alipay.com/291/105971/ 這個網址
下載生成公鑰的工具
下載解壓後
生成公鑰
生成公鑰後會獲得兩個文件
注意:這兩個文件很重要必定要保存好
生成公鑰後,將公鑰填寫到信息配置裏
當咱們填寫好公鑰保存後,會自動給咱們生成支付寶公鑰
將生成的支付寶公鑰,複製下載寫在一個TXT文件裏
這樣咱們就有了3個祕鑰
將3個祕鑰修改爲英文或者拼音名稱後,放到網站項目中
在祕鑰txt文件裏,祕鑰內容的頭部和結尾加上兩行字符串,注意全部祕鑰都要加
-----BEGIN PRIVATE KEY-----
祕鑰內容....
-----END PRIVATE KEY-----
3.支付寶,支付集成代碼
#!/usr/bin/env python # -*- coding:utf8 -*- # pip install pycryptodome 須要模塊加密方面的模塊 __author__ = 'bobby' from datetime import datetime from Crypto.PublicKey import RSA from Crypto.Signature import PKCS1_v1_5 from Crypto.Hash import SHA256 from base64 import b64encode, b64decode from urllib.parse import quote_plus from urllib.parse import urlparse, parse_qs from urllib.request import urlopen from base64 import decodebytes, encodebytes import json class AliPay(object): """ 支付寶支付接口 """ def __init__(self, appid, app_notify_url, app_private_key_path, alipay_public_key_path, return_url, debug=False): self.appid = appid self.app_notify_url = app_notify_url self.app_private_key_path = app_private_key_path self.app_private_key = None self.return_url = return_url with open(self.app_private_key_path) as fp: self.app_private_key = RSA.importKey(fp.read()) self.alipay_public_key_path = alipay_public_key_path with open(self.alipay_public_key_path) as fp: self.alipay_public_key = RSA.import_key(fp.read()) if debug is True: self.__gateway = "https://openapi.alipaydev.com/gateway.do" else: self.__gateway = "https://openapi.alipay.com/gateway.do" def direct_pay(self, subject, out_trade_no, total_amount, return_url=None, **kwargs): biz_content = { "subject": subject, "out_trade_no": out_trade_no, "total_amount": total_amount, "product_code": "FAST_INSTANT_TRADE_PAY", # "qr_pay_mode":4 } biz_content.update(kwargs) data = self.build_body("alipay.trade.page.pay", biz_content, self.return_url) return self.sign_data(data) def build_body(self, method, biz_content, return_url=None): data = { "app_id": self.appid, "method": method, "charset": "utf-8", "sign_type": "RSA2", "timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"), "version": "1.0", "biz_content": biz_content } if return_url is not None: data["notify_url"] = self.app_notify_url data["return_url"] = self.return_url return data def sign_data(self, data): data.pop("sign", None) # 排序後的字符串 unsigned_items = self.ordered_data(data) unsigned_string = "&".join("{0}={1}".format(k, v) for k, v in unsigned_items) sign = self.sign(unsigned_string.encode("utf-8")) ordered_items = self.ordered_data(data) quoted_string = "&".join("{0}={1}".format(k, quote_plus(v)) for k, v in ordered_items) # 得到最終的訂單信息字符串 signed_string = quoted_string + "&sign=" + quote_plus(sign) return signed_string def ordered_data(self, data): complex_keys = [] for key, value in data.items(): if isinstance(value, dict): complex_keys.append(key) # 將字典類型的數據dump出來 for key in complex_keys: data[key] = json.dumps(data[key], separators=(',', ':')) return sorted([(k, v) for k, v in data.items()]) def sign(self, unsigned_string): # 開始計算簽名 key = self.app_private_key signer = PKCS1_v1_5.new(key) signature = signer.sign(SHA256.new(unsigned_string)) # base64 編碼,轉換爲unicode表示並移除回車 sign = encodebytes(signature).decode("utf8").replace("\n", "") return sign def _verify(self, raw_content, signature): # 開始計算簽名 key = self.alipay_public_key signer = PKCS1_v1_5.new(key) digest = SHA256.new() digest.update(raw_content.encode("utf8")) if signer.verify(digest, decodebytes(signature.encode("utf8"))): return True return False def verify(self, data, signature): if "sign_type" in data: sign_type = data.pop("sign_type") # 排序後的字符串 unsigned_items = self.ordered_data(data) message = "&".join(u"{}={}".format(k, v) for k, v in unsigned_items) return self._verify(message, signature) if __name__ == "__main__": """支付請求過程""" # 傳遞參數初始化支付類 alipay = AliPay( appid="2016080800192023", # 設置簽約的appid app_notify_url="http://projectsedus.com/", # 異步支付通知url app_private_key_path=u"ying_yong_si_yao.txt", # 設置應用私鑰 alipay_public_key_path="zhi_fu_bao_gong_yao.txt", # 支付寶的公鑰,驗證支付寶回傳消息使用,不是你本身的公鑰, debug=True, # 默認False, # 設置是不是沙箱環境,True是沙箱環境 return_url="http://47.92.87.172:8000/" # 同步支付通知url ) # 傳遞參數執行支付類裏的direct_pay方法,返回簽名後的支付參數, url = alipay.direct_pay( subject="測試訂單", # 訂單名稱 # 訂單號生成,通常是當前時間(精確到秒)+用戶ID+隨機數 out_trade_no="201702021225", # 訂單號 total_amount=100, # 支付金額 return_url="http://47.92.87.172:8000/" # 支付成功後,跳轉url ) # 將前面後的支付參數,拼接到支付網關 # 注意:下面支付網關是沙箱環境, re_url = "https://openapi.alipaydev.com/gateway.do?{data}".format(data=url) print(re_url) # 最終進行簽名後組合成支付寶的url請求
4.生成支付URL後,咱們用這個URL模擬支付一下
注意:沙箱環境,支付的時候要用沙箱帳號裏提供的支付帳號才能夠支付
支付成功後已經,跳轉到咱們設置的同步處理頁面
5.支付寶支付成功後通知接口驗證
#!/usr/bin/env python # -*- coding:utf8 -*- # pip install pycryptodome 須要模塊加密方面的模塊 __author__ = 'bobby' from datetime import datetime from Crypto.PublicKey import RSA from Crypto.Signature import PKCS1_v1_5 from Crypto.Hash import SHA256 from base64 import b64encode, b64decode from urllib.parse import quote_plus from urllib.parse import urlparse, parse_qs from urllib.request import urlopen from base64 import decodebytes, encodebytes import json class AliPay(object): """ 支付寶支付接口 """ def __init__(self, appid, app_notify_url, app_private_key_path, alipay_public_key_path, return_url, debug=False): self.appid = appid self.app_notify_url = app_notify_url self.app_private_key_path = app_private_key_path self.app_private_key = None self.return_url = return_url with open(self.app_private_key_path) as fp: self.app_private_key = RSA.importKey(fp.read()) self.alipay_public_key_path = alipay_public_key_path with open(self.alipay_public_key_path) as fp: self.alipay_public_key = RSA.import_key(fp.read()) if debug is True: self.__gateway = "https://openapi.alipaydev.com/gateway.do" else: self.__gateway = "https://openapi.alipay.com/gateway.do" def direct_pay(self, subject, out_trade_no, total_amount, return_url=None, **kwargs): biz_content = { "subject": subject, "out_trade_no": out_trade_no, "total_amount": total_amount, "product_code": "FAST_INSTANT_TRADE_PAY", # "qr_pay_mode":4 } biz_content.update(kwargs) data = self.build_body("alipay.trade.page.pay", biz_content, self.return_url) return self.sign_data(data) def build_body(self, method, biz_content, return_url=None): data = { "app_id": self.appid, "method": method, "charset": "utf-8", "sign_type": "RSA2", "timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"), "version": "1.0", "biz_content": biz_content } if return_url is not None: data["notify_url"] = self.app_notify_url data["return_url"] = self.return_url return data def sign_data(self, data): data.pop("sign", None) # 排序後的字符串 unsigned_items = self.ordered_data(data) unsigned_string = "&".join("{0}={1}".format(k, v) for k, v in unsigned_items) sign = self.sign(unsigned_string.encode("utf-8")) ordered_items = self.ordered_data(data) quoted_string = "&".join("{0}={1}".format(k, quote_plus(v)) for k, v in ordered_items) # 得到最終的訂單信息字符串 signed_string = quoted_string + "&sign=" + quote_plus(sign) return signed_string def ordered_data(self, data): complex_keys = [] for key, value in data.items(): if isinstance(value, dict): complex_keys.append(key) # 將字典類型的數據dump出來 for key in complex_keys: data[key] = json.dumps(data[key], separators=(',', ':')) return sorted([(k, v) for k, v in data.items()]) def sign(self, unsigned_string): # 開始計算簽名 key = self.app_private_key signer = PKCS1_v1_5.new(key) signature = signer.sign(SHA256.new(unsigned_string)) # base64 編碼,轉換爲unicode表示並移除回車 sign = encodebytes(signature).decode("utf8").replace("\n", "") return sign def _verify(self, raw_content, signature): # 開始計算簽名 key = self.alipay_public_key signer = PKCS1_v1_5.new(key) digest = SHA256.new() digest.update(raw_content.encode("utf8")) if signer.verify(digest, decodebytes(signature.encode("utf8"))): return True return False def verify(self, data, signature): if "sign_type" in data: sign_type = data.pop("sign_type") # 排序後的字符串 unsigned_items = self.ordered_data(data) message = "&".join(u"{}={}".format(k, v) for k, v in unsigned_items) return self._verify(message, signature) if __name__ == "__main__": """支付寶支付成功後通知接口驗證""" # 接收支付寶支付成功後,向咱們設置的同步支付通知url,請求的參數 return_url = 'http://47.92.87.172:8000/?total_amount=100.00×tamp=2017-10-11+22%3A44%3A17&sign=dHW%2F25EDd%2BYKqkU5krhseDNIOEyDpdJzSAaoqhTC0nlv8%2FEmrQVd0WqgGK0CS8Pax8sK4jIOdGLFa6lQEbIfzvH3Na2W949yCAYX04JL1Bi02wog7a8L7vfW9Kj%2BjfTQxumGH%2B1Drbezdg9gKOx3tX0cb1yBBdfifK6l1%2BE5UjggGbY60F6SD8A8XI06NMWb4ViU%2FLYtBhwAwU2koy1IK2%2BtBJM1xYFuBRlcWF61xCxexHwO0WEA3AwVRW1miuJjOpGiBTOwPI9Huj0WhkyRebIjBhSxReJdZIdTfAgwj4oqo4jAJCHDa6DKBM0H3wjKKXSyMeMBGKQB0Uv2rNdyng%3D%3D&trade_no=2017101121001004320200174640&sign_type=RSA2&auth_app_id=2016080800192023&charset=utf-8&seller_id=2088102170418468&method=alipay.trade.page.pay.return&app_id=2016080800192023&out_trade_no=201702021227&version=1.0' # 將同步支付通知url,傳到urlparse o = urlparse(return_url) # 獲取到URL的各類參數 query = parse_qs(o.query) # 定義一個字典來存放,循環獲取到的URL參數 processed_query = {} # 將URL參數裏的sign字段拿出來 ali_sign = query.pop("sign")[0] # 傳遞參數初始化支付類 alipay = AliPay( appid="2016080800192023", # 設置簽約的appid app_notify_url="http://projectsedus.com/", # 異步支付通知url app_private_key_path=u"ying_yong_si_yao.txt", # 設置應用私鑰 alipay_public_key_path="zhi_fu_bao_gong_yao.txt", # 支付寶的公鑰,驗證支付寶回傳消息使用,不是你本身的公鑰, debug=True, # 默認False, # 設置是不是沙箱環境,True是沙箱環境 return_url="http://47.92.87.172:8000/" # 同步支付通知url ) # 循環出URL裏的參數 for key, value in query.items(): # 將循環到的參數,以鍵值對形式追加到processed_query字典 processed_query[key] = value[0] # 將循環組合的參數字典,以及拿出來的sign字段,傳進支付類裏的verify方法,返回驗證合法性,返回布爾值,True爲合法,表示支付確實成功了,這就是驗證是不是僞造支付成功請求 print(alipay.verify(processed_query, ali_sign)) # 若是別人僞造支付成功請求,它不知道咱們的支付寶公鑰,僞造的就沒法經過驗證,測試能夠將支付寶公鑰更改一下,在驗證就會失敗,別忘了改回來
遠程測試支付成功後返回服務器驗證
首先準備一臺服務器,將開發環境和項目同步到服務器上,而且在服務器上配置好python虛擬環境和所需python插件包
項目同步到服務器上,也就是將本地項目,上傳到服務器進行同步
配置服務器信息
2
上傳項目
數據上傳後,在服務器配置數據庫訪問權限,和配置python環境
配置遠程調試
1,在阿里雲後臺,開放8000端口
2,在服務器開發8000端口
vim /etc/sysconfig/iptables
# Firewall configuration written by system-config-firewall # Manual customization of this file is not recommended. *filter :INPUT ACCEPT [0:0] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [0:0] -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT -A INPUT -p icmp -j ACCEPT -A INPUT -i lo -j ACCEPT -A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT #添加配置項 -A INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT -A INPUT -m state --state NEW -m tcp -p tcp --dport 8000 -j ACCEPT -A INPUT -m state --state NEW -m tcp -p tcp --dport 3306 -j ACCEPT -A INPUT -j REJECT --reject-with icmp-host-prohibited -A FORWARD -j REJECT --reject-with icmp-host-prohibited COMMIT
重啓防火牆
service iptables restart
設置當前,使用的數據庫用戶,能夠任意ip訪問
讓數據庫用戶能夠從外部登錄和本地登錄
1
grant all privileges(除受權外的全部權限) on *.*(表示全部數據庫的全部表) to 'test_user(受權的用戶名)'@'localhost(受權ip)' identified by 'test_user(用戶密碼)';
grant all privileges on *.* to 'test_user'@'localhost' identified by 'test_user';
2
grant all privileges(除受權外的全部權限) on *.*(表示全部數據庫的全部表) to 'test_user(受權的用戶名)'@'%(全部ip)' identified by 'test_user(用戶密碼)';
grant all privileges on *.* to 'test_user'@'%' identified by 'test_user';
配置項目的settings.py文件
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', #配置數據庫引擎名稱 'NAME': 'jxiou', #數據庫名稱 'USER': 'test_user', #數據庫用戶名 'PASSWORD': 'test_user', #數據庫密碼 'HOST': '47.52.39.160', #數據庫連接地址,爲服務器ip 'PORT': '3306', #數據庫端口 } }
2
# SECURITY WARNING: don't run with debug turned on in production! DEBUG = True ALLOWED_HOSTS = ['*'] # 容許任意ip訪問項目
開始遠程調試
2
3
4
5
此時,就能夠用服務器ip加8000端口,訪問服務器網站了
前面,咱們在本地調試了支付寶支付請求,這下咱們要調試,支付寶支付成功後向咱們服務器返回請求咱們要驗證返回的請求,,因此須要將遠程服務器啓動來,接收支付寶的返回
settings.py
import os # Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # 支付寶目錄路徑設置 ying_yong_si_yao = os.path.join(BASE_DIR, 'app1/alipay/ying_yong_si_yao.txt') zhi_fu_bao_gong_yao = os.path.join(BASE_DIR, 'app1/alipay/zhi_fu_bao_gong_yao.txt')
urls.py
from django.conf.urls import url from django.contrib import admin from app1.views import alipaview urlpatterns = [ url(r'^admin/', admin.site.urls), # 支付寶返回url url(r'^alipa/', alipaview, name='alipa'), ]
views.py
#!/usr/bin/env python # -*- coding:utf8 -*- from django.shortcuts import render # Create your views here. from django.shortcuts import render,HttpResponse from django.views.decorators.csrf import csrf_exempt,csrf_protect from app1.alipay.alipay import AliPay from jxiou.settings import ying_yong_si_yao, zhi_fu_bao_gong_yao @csrf_exempt def alipaview(request): if request.method == "GET": processed_dict = {} # 接收支付寶傳遞參數 for key, value in request.GET.items(): # 循環參數 processed_dict[key] = value # 將參數添加到字典 sign = processed_dict.pop('sign', None) # 單獨拿出sign字段 # 傳遞參數初始化支付類 alipay = AliPay( appid="2016080800192023", # 設置簽約的appid app_notify_url="http://47.52.39.160:8000/alipa/", # 異步支付通知url app_private_key_path=ying_yong_si_yao, # 設置應用私鑰 alipay_public_key_path=zhi_fu_bao_gong_yao, # 支付寶的公鑰,驗證支付寶回傳消息使用,不是你本身的公鑰, debug=True, # 默認False, # 設置是不是沙箱環境,True是沙箱環境 return_url="http://47.52.39.160:8000/alipa/" # 同步支付通知url,跳轉地址 ) # 驗證支付寶返回的合法性 yan_zhen = alipay.verify(processed_dict, sign) if yan_zhen is True: # 判斷若是合法 out_trade_no = processed_dict.get('out_trade_no', None) # 商戶訂單號 trade_no = processed_dict.get('trade_no', None) # 支付寶交易號 buyer_id = processed_dict.get('buyer_id', None) # 買家支付寶用戶號 trade_status = processed_dict.get('trade_status', None) # 交易狀態 total_amount = processed_dict.get('total_amount', None) # 訂單金額 receipt_amount = processed_dict.get('receipt_amount', None) # 實收金額 subject = processed_dict.get('subject', None) # 訂單標題 gmt_payment = processed_dict.get('gmt_payment', None) # 交易付款時間 # 數據庫操做 print(out_trade_no) print(trade_no) print(buyer_id) print(trade_status) print(total_amount) print(receipt_amount) print(subject) print(gmt_payment) # 向支付寶返回success,告訴他咱們已經處理,否則他會不停的通知 return HttpResponse('success') if request.method == "POST": # post請求支付寶異步通知 processed_dict = {} # 接收支付寶傳遞參數 for key, value in request.POST.items(): # 循環參數 processed_dict[key] = value # 將參數添加到字典 sign = processed_dict.pop('sign', None) # 單獨拿出sign字段 # 傳遞參數初始化支付類 alipay = AliPay( appid="2016080800192023", # 設置簽約的appid app_notify_url="http://47.52.39.160:8000/alipa/", # 異步支付通知url app_private_key_path=ying_yong_si_yao, # 設置應用私鑰 alipay_public_key_path=zhi_fu_bao_gong_yao, # 支付寶的公鑰,驗證支付寶回傳消息使用,不是你本身的公鑰, debug=True, # 默認False, # 設置是不是沙箱環境,True是沙箱環境 return_url="http://47.52.39.160:8000/alipa/" # 同步支付通知url ) # 驗證支付寶返回的合法性 yan_zhen = alipay.verify(processed_dict, sign) if yan_zhen is True: # 判斷若是合法 out_trade_no = processed_dict.get('out_trade_no', None) # 商戶訂單號 trade_no = processed_dict.get('trade_no', None) # 支付寶交易號 buyer_id = processed_dict.get('buyer_id', None) # 買家支付寶用戶號 trade_status = processed_dict.get('trade_status', None) # 交易狀態 total_amount = processed_dict.get('total_amount', None) # 訂單金額 receipt_amount = processed_dict.get('receipt_amount', None) # 實收金額 subject = processed_dict.get('subject', None) # 訂單標題 gmt_payment = processed_dict.get('gmt_payment', None) # 交易付款時間 # 數據庫操做 print(out_trade_no) print(trade_no) print(buyer_id) print(trade_status) print(total_amount) print(receipt_amount) print(subject) print(gmt_payment) # 向支付寶返回success,告訴他咱們已經處理,否則他會不停的通知 return HttpResponse('success')
WAIT_BUYER_PAY 交易建立,等待買家付款TRADE_CLOSED 未付款交易超時關閉,或支付完成後全額退款TRADE_SUCCESS 交易支付成功TRADE_FINISHED 交易結束,不可退款