http://wechat-python-sdk.readthedocs.io/basic.html
我是从投放卡券开始做起的,也就是从最后的客户端的H5页面脚本的调用做起的,之所以从此做起是因为在微信活动签到开发中未涉及到H5页面对脚本的调用,这一块技术的了解和掌握在微信开发中是必不可少的。急于掌握了解,从微信开发文档中下载了样例代码,代码在python中写得不够具体,对此参照php的代码做了修改,修改思路如下:
1.对access_token jsapi_ticket的凭据的获得后的保存,用文本文档时行保存
在此用到了python对本地文档内容的读写操作
def get_file_content(self,f):
file_object = open(f,'r')
gg = None
try:
gg = file_object.read()
finally:
file_object.close()
gg_dict = eval(gg)
return gg_dict
def set_file_content(self,f,gg):
file_object = open(f, 'w')
try:
file_object.write(gg)
finally:
file_object.close()
在自己的project中的weixin中写有关获得access_token,signature,jsapi_tickedt的逻辑
首先判断jsapi_ticket是否赁据过期,
如有过期,判断access_token是否过期,如未过期读取文本acccess_token,如已过期,重新获得access_token,将access_token值记入文档,无论怎样在获得access_token后就可以用这个凭据来获得jsapi_ticket,并将jsap_ticket在文档中进行保存,然后生成signature,在H5端进行wx.config()的配置。
此过程会遇到
1.在此其间会遇到对文本文件操作权限的问题,由于用的是IIs服务器,对文档的操作权限需赋予 IIS_IUSR。
2.时间的获得(当前时间time.time()),文本中读出的时候为int,不必再做进一步的转换。get_jsapi_ticket()返回的jsapi_ticket_expire_at是数字在开成字符串时需str()转换。
3.在调用wechatBsic时,最好一次性实例 化wechatBaisc,不要在函数中用一次实例化一次。
4.最后的conf 返回值在python中为dict,所以最后HttpResponse向H5做渲值时需在python将Dict转为jsonstr值,通过
import json
json_str=json.dumps(str)
conf = WechatConf(appid=WEIXIN_APPID, appsecret=WEIXIN_APPSECRET)
wt=WechatBasic(conf=conf)
class JSSDK:
def getJsApiTicket(self):
content_ticket=self.get_file_content(WEIXIN_JsApi_Ticket)
if int(content_ticket["expire_time"])<int(time.time()):
access_token=self.getAccessToken()
reply=wt.get_jsapi_ticket()
ticket=reply["jsapi_ticket"]
expire_time=reply["jsapi_ticket_expires_at"]
setc = '{"jsapi_ticket":"' + ticket + '","expire_time":' + str(expire_time) + '}'
self.set_file_content(WEIXIN_JsApi_Ticket,setc)
else:
ticket=content_ticket["jsapi_ticket"]
return ticket
def getAccessToken(self):
content=self.get_file_content(WEIXIN_Access_Token)
if content["expire_time"] < int(time.time()):
reply=wt.get_access_token()
access_token=reply["access_token"]
expire_time=reply["access_token_expires_at"]
setc='{"access_token":"'+access_token+'","expire_time":'+str(expire_time)+'}'
self.set_file_content(WEIXIN_Access_Token,setc)
else:
access_token=content["access_token"]
return access_token
def get_file_content(self,f):
file_object = open(f,'r')#'/static/jsapi_ticket.txt'
gg = None
try:
gg = file_object.read()
finally:
file_object.close()
gg_dict = eval(gg)
return gg_dict
def set_file_content(self,f,gg):
file_object = open(f, 'w')
try:
file_object.write(gg)
finally:
file_object.close()
def __init__(self,url):
self.ret = {
'nonceStr': self.__create_nonce_str(),
'jsapi_ticket': self.getJsApiTicket(),
'timestamp': self.__create_timestamp(),
'url': url
}
def __create_nonce_str(self):
return ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(15))
def __create_timestamp(self):
return int(time.time())
def sign(self):
string = '&'.join(['%s=%s' % (key.lower(), self.ret[key]) for key in sorted(self.ret)])
#print string
self.ret['signature'] = hashlib.sha1(string).hexdigest()
return self.ret
外部调用:
view中调用——Weconf
def getWxConf(request):
if request.method == 'GET':
url=request.GET["url"]
jssdk=JSSDK(url)
json_str=json.dumps(jssdk.sign())
return HttpResponse(json_str)
附录4-卡券扩展字段及签名生成算法
JSSDK使用者请读这里,JSAPI用户可以跳过
卡券签名和JSSDK的签名完全独立,两者的算法和意义完全不同,请不要混淆。JSSDK的签名是使用所有JS接口都需要走的一层鉴权,用以标识调用者的身份,和卡券本身并无关系。其次,卡券的签名考虑到协议的扩展性和简单的防数据擅改,设计了一套独立的签名协议。另外由于历史原因,卡券的JS接口先于JSSDK出现,当时的JSAPI并没有鉴权体系,所以在卡券的签名里也加上了appsecret/api_ticket这些身份信息,希望开发者理解。
卡券 api_ticket
卡券 api_ticket 是用于调用卡券相关接口的临时票据,有效期为 7200 秒,通过 access_token 来获取。这里要注意与 jsapi_ticket 区分开来。由于获取卡券 api_ticket 的 api 调用次数非常有限,频繁刷新卡券 api_ticket 会导致 api 调用受限,影响自身业务,开发者必须在自己的服务全局缓存卡券 api_ticket 。
1.参考以下文档获取access_token(有效期7200秒,开发者必须在自己的服务全局缓存access_token):../15/54ce45d8d30b6bf6758f68d2e95bc627.html
2.用第一步拿到的access_token 采用http GET方式请求获得卡券 api_ticket(有效期7200秒,开发者必须在自己的服务全局缓存卡券 api_ticket):https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=wx_card
api_ticket返回的格式为:
{“errcode”:0,”errmsg”:”ok”,”ticket”:”E0o2-at6NcC2OsJiQTlwlDQBMfHy4gWC97VxQCZsAZf7Bit5O7ysSp80CCc0GWko9pC8nUxNhj3sQFAVFC5Rgw”,”expires_in”:7200}
3.获得api_ticket,由于请求次数的限制,也存在全局存储,过期刷新的程序处理,处理方式与jsapi_ticket,access_token的处理方法一致,以文档进行信息的存储,过期进行文档内容的刷新,由于请求的是外链接,用到了python requests,很好用的,在服务器端可以获得请求结果。
def get_card_api_ticket(self, access_token):
url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket"
param = {"access_token": access_token, "type": "wx_card"}
wb_data = requests.get(url, params=param)
data = wb_data.json()
return data
def card_api_ticket(self):
content_card_api = self.get_file_content(WEIXIN_Card_Api_Ticket)
if int(content_card_api["expire_time"]) < int(time.time()):
access_token = self.getAccessToken()
reply = self.get_card_api_ticket(access_token)
api_ticket = reply["ticket"]
expire_time = int(time.time())+int(reply["expires_in"])
setc = "{'api_ticket':'" + api_ticket + "','expire_time':" + str(expire_time) + "}"
self.set_file_content(WEIXIN_Card_Api_Ticket, setc)
else:
api_ticket = content_card_api["api_ticket"]
self.apiTicket=api_ticket
//views
def get_card_ApiTicket(request):
if request.method=='GET':
cardapi=CardApiTicket()
apiTicket=cardapi.card_api_ticket()
return HttpResponse('{"api_ticket":"'+apiTicket+'"}')
//h5
function init_ApiTicket(){
$.ajax({
type:"GET",
url:"/card/get_card_ApiTicket",
async:true,
success:function(dt){
console.log(dt);
var datajson=JSON.parse(dt);
alert(datajson["api_ticket"])
}
})
}
在此处需总结这种处理方法,回应数据的格式问题
1.在requests中获得的回应数据wx_data需要进行.json()处理,
2.用dict方式来获理反回的json数据,reply[“ticket”]
3.HttpResponse(‘{“api_ticket”:”’+apiTicket+’”}’)返回的数据类型为字符串,些处字符串必须用“号,否则在客户端会报 json token的错误
4.在H5中用JSON.parse(dt)来转为json.
在此客户端有关凭据的获得基本完成,有如爬山终于穿出了山间小路,到了一个开阔地,可以放眼看一看周围的景色了。说到爬山,心又要飞了,坐不住 。
不能歇下来,留个影儿,发点感想,要冲向下一个山头,下一个山头看着不高,但是收费情况不明。
服务器端卡券的创建
从游览导图来看前方的景点如下:
上传商户Logo
获取卡券色值
创建卡券适用门店
首先要了解一下,这几个景点是否再次消费才可以尽情游览。
经过一番的测试发现有些地方,不是很清楚,因为本人从未使用过微信卡券,对其具体的运作不是很清楚,做为独行的旅人,这又是一次走一步看一步的旅途。
决定怎么走,方案路线规划如下:普通优惠券,微信买单。卡券的功能开通认证需要时间等待,为了加速先弄了个测试号。