import hashlib
import random
import string
import urllib
import xml.etree.ElementTree as et
import time
import requests
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36',
}
class WeChatConfig(object):
appid = '微信appid'
AppSecret = '微信AppSecret'
mch_id = '微信商戶id'
api_key = '微信支付密鑰'
def get_access_token():
"""
jssdk 刷新accesstoken的方法
微信基礎接口所需的 accesstoken
:param appid:
:param secret:
:
:return:
"""
appid = WeChatConfig.appid
secret = WeChatConfig.AppSecret
url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=' + \
appid + '&secret=' + secret
html = requests.get(url, headers=headers).text
m = eval(html)
return m
def get_open_id_token(APPID, SECRET, CODE):
"""
通過前端傳的code 和 WeChatConfig中的基本信息 來獲取用戶的openid還有一個網頁授權的accesstoken
"""
url = 'https://api.weixin.qq.com/sns/oauth2/access_token?appid=' + APPID + \
'&secret=' + SECRET + '&code=' + CODE + '&grant_type=authorization_code'
html = requests.get(url, headers=headers)
html_response = html.json()
return html_response
def get_user_info2(access_token, openid):
"""
這個access_token是基礎accessToken
通過 openid 和 基礎接口的accesstoken 來獲取用戶信息 和下面的get_user_info不同的是 這個更加詳細
:param access_token:
:param openid:
:return:
微信公衆平臺開發文檔介紹:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140839
"""
url = 'https://api.weixin.qq.com/cgi-bin/user/info?access_token={0}&openid={1}&lang=zh_CN'.format(access_token,
openid)
html = requests.get(url, headers=headers)
html.encoding = 'utf-8'
html_response = html.json()
return html_response
def get_user_info(access_token, openid):
"""
這個access_token是網頁授權 獲取用戶信息
:param access_token:
:param openid:
:return:
微信公衆平臺開發文檔介紹:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842
"""
url = 'https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s&lang=zh_CN' % (access_token, openid)
html = requests.get(url, headers=headers)
html.encoding = 'utf-8'
html_response = html.json()
return html_response
def get_ticket(access_token):
"""
:param access_token: 基礎accesstoken
:return:
"""
url = 'https://api.weixin.qq.com/cgi-bin/ticket/getticket?' \
'access_token=' + access_token + '&type=jsapi'
html = requests.get(url, headers=headers).text
m = eval(html)
return m
def get_sign(ticket, url):
"""
前端調用jssdk所需要的簽名
"""
return_dict = {}
timestamp = int(time.time() * 1000)
noncestr = ''.join(random.sample(string.ascii_letters + string.digits, 8))
sign = 'jsapi_ticket=' + ticket + '&noncestr=' + noncestr + '×tamp=' + str(
timestamp) + '&url=' + url
sha = hashlib.sha1(sign.encode('utf-8'))
encrypts = sha.hexdigest()
return_dict = {"timestamp": timestamp, "nonceStr": noncestr,
"signature": encrypts, "appId": WeChatConfig.appid}
return return_dict
def get_Package(body,
notify_url,
openid,
spbill_create_ip,
total_fee,
out_trade_no,
):
"""
前端調起微信H5支付所需要的參數
這裏獲取的是 prepay_id
"""
appid = WeChatConfig.appid
mch_id = WeChatConfig.mch_id
api_key = WeChatConfig.api_key
nonce_str = ''.join(random.sample(
string.ascii_letters + string.digits, 32))
# timeStamp = time.time()
# out_trade_no = "{0}{1}".format(WeChatConfig.appid, int(timeStamp * 100))
stringA = "appid=" + appid + \
"&body=" + body + \
"&mch_id=" + mch_id + \
"&nonce_str=" + nonce_str + \
"¬ify_url=" + notify_url + \
"&openid=" + openid + \
"&out_trade_no=" + out_trade_no + \
"&spbill_create_ip=" + spbill_create_ip + \
"&total_fee=" + total_fee + \
"&trade_type=JSAPI"
stringSignTemp = stringA + "&key=" + api_key # api-key未知
paySign = hashlib.md5(stringSignTemp.encode('utf-8')).hexdigest().upper()
# print('paySign=', paySign)
PayXml = "<xml>\
<appid>" + appid + "</appid>\
<body>" + body + "</body>\
<mch_id>" + mch_id + "</mch_id>\
<nonce_str>" + nonce_str + "</nonce_str>\
<notify_url>" + notify_url + "</notify_url>\
<openid>" + openid + "</openid>\
<out_trade_no>" + out_trade_no + "</out_trade_no>\
<spbill_create_ip>" + spbill_create_ip + "</spbill_create_ip>\
<total_fee>" + total_fee + "</total_fee>\
<trade_type>JSAPI</trade_type>\
<sign>" + paySign + "</sign>\
</xml>"
req = urllib.request.Request(
"https://api.mch.weixin.qq.com/pay/unifiedorder")
req.add_header('User-Agent',
'Mozilla/6.0 (iPhone; CPU iPhone OS 8_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/8.0 Mobile/10A5376e Safari/8536.25')
unifiedorderXML = urllib.request.urlopen(req, data=PayXml.encode('utf-8'))
tree = et.parse(unifiedorderXML)
root = tree.getroot()
# psign = root.find('sign').text
prepay_id = root.find("prepay_id").text
package = "prepay_id=" + prepay_id
return package
def get_PaySign(package):
"""
將 要傳給前端的數據全部打包發給前端
"""
timestamp = int(time.time() * 1000)
noncestr = ''.join(random.sample(string.ascii_letters + string.digits, 8))
stringB = "appId=" + WeChatConfig.appid + "&nonceStr=" + noncestr + "&package=" + package + "&signType=MD5&timeStamp=" + str(
timestamp)
stringBSignTemp = stringB + "&key={0}".format(WeChatConfig.api_key)
paysign = hashlib.md5(stringBSignTemp.encode('utf-8')).hexdigest().upper()
# 生成微信支付簽名
Payment = {}
Payment['timestamp'] = timestamp
Payment['noncestr'] = noncestr
Payment['paySign'] = paysign
Payment['package'] = package
return Payment
以上是調用微信接口相關
關於倆個accesstoken和倆個調用微信用戶信息的接口大家可以看下這篇文章
微信獲取用戶信息的兩個接口和兩個ACCESS_TOKEN
關於微信支付 我也是通過前人的總結了解的 如下
python+h5微信支付總結
關於如何儲存 基礎accesstoken的方法
本人是通過數據庫拉取有效期內的accesstoken
新建一張model
class AccessToken(models.Model):
# access_token # 存放access_token
# expires # 存放毫秒數
# update_time # 更新時間戳
access_token = models.CharField(max_length=255, null=True, blank=True, verbose_name='基礎accessToken')
expires = models.IntegerField(default=7200, verbose_name='可存放的時間')
update_time = models.IntegerField(null=True, blank=True, verbose_name='更新時間')
class Meta:
verbose_name = '微信accesstoken記錄表'
verbose_name_plural = '微信accesstoken記錄表'
db_table = 'WCaccesstoken'
def __str__(self):
return self.access_token
如何驗證 accesstoken是否有效
import time
def send_accesstoken():
try:
accesstoken = AccessToken.objects.get(id=1)
update_time = accesstoken.update_time
now_time = int(time.time())
if update_time < now_time:
# 驗證是否過期
M_accesstoken = get_access_token()
access_token = M_accesstoken['access_token']
accesstoken.access_token = access_token
_updatetime = int(time.time()) + 7200
# 更新過期時間
accesstoken.update_time = _updatetime
accesstoken.save()
return access_token
else:
return accesstoken.access_token
except:
M_accesstoken = get_access_token()
access_token = M_accesstoken['access_token']
_accesstoken = AccessToken()
_accesstoken.access_token = access_token
_updatetime = int(time.time()) + 7200
_accesstoken.update_time = _updatetime
_accesstoken.save()
return access_token