说点感悟,聊点技术

18年年底公司上线了一个AI识别柑橘病虫害的小程序。19年初Boss又说,要开发一个柑橘日报网站,通过给种植柑橘的目标用户推送柑橘类的技术文章来达到给小程序引流的目的。当时听了,脑子立刻就冒出了这样的想法:这他妈不就是爬取数据,后台做数据展示、以及文章个性化推送了吗?像我这暴脾气,说干就干。在产品原型搞完成之后,对照产品原型规划了一下这个网站开发的思路,就开始开干。


说点什么


万事都没有想象的那么简单,但也没有说的那么难,毕竟这个网站主要还是展示数据和用户的个性化推送。技术点不是很多,业务也不复杂。在刚开始爬取数据的时候就遇到了一些棘手问题,不过在各位大佬的帮助下,机智的小李还是很快就解决了。后台开发的话,也遇到了一些问题,踩了好几个坑。不过今天主要想聊一下在微信实现文章的分享功能,所以那些年踩过的别的一些坑就不细说了,以后会逐个分享工作中遇到的问题。


感悟:困难不可避免,遇到不要畏惧,但也不能掉以轻心。做每件事之前需要考虑到最坏打算,以防到时措手不及。



我是18年10.8号来这家公司上班的,刚来第一天领导就说我们这个项目必须在11.16号上线,因为11.22号要带着这个产品参加成都的一个展会。当时一听瞬间懵逼,短短一个月多一点时间,而且整个项目什么都没有,心想这么可能完成了。当时我们这个项目组就4个人,1个是我们boss、1个UI、1个算法,而我就自然而然的被叫去开发后台了smiley_5.pngsmiley_5.pngsmiley_5.png。虽然当时面试的岗位也是算法岗位,但是老板看我简历之前有做过后台开发,由于人手不够,所以就被后台开发了。。。


感悟:面试不要担心什么,心有疑虑的必须向面试官问清楚。否则,进来之后,失望的还是你自己。



来这边的第一个项目是开发一个AI识别柑橘病虫害的小程序。虽然后台不是很难,业务一般般,但是整个项目组做后台的就我一个人,讨论的人也没有,完全是单枪匹马的干,压力还是有的。而且之前没有开发过小程序后台,看微信开发文档也需要一定时间。但是当看到那些微信开发文档的时候,越看越懵逼,越看越不会。特别是这次做文章分享功能的时候,文档没有看清楚,开发完之后,和前端连联调才发现文档搞错了, 真的有砍人的冲动。最后索性放弃微信开发文档,直接度娘找到一篇技术博客完美的解决了问题。


感悟:团队真的很重要。一个好的团队,可以让你少走弯路,少踩许多坑,让你以最快的速度成长。



回到主题


上边说这么多,也许是因为刚过完年感慨太多,所以一逼逼就停不下来2_05.png2_05.png2_05.png今天主要是说一下如何分享文章给微信好友。这个功能其实很简单,前提是你需要读懂微信的官方开发文档,明白后台需要做什么事情。不过微信官方开发文档不知道别人看了啥感受,反正我看的是一脸懵逼,看完第一感受有种要回小学重学语文的赶脚。当然,这也是为什么要将这么简单的一个功能也要在这里说的原因。好了,废话不说了,直接进入主题。


这里推荐之前在网上参考的一篇技术文章,讲解简单,清楚。链接地址:https://www.cnblogs.com/txw1958/p/weixin-js-sharetimeline.html。当然,读文章能力超强的可以看微信官方开发文档。

1.获得Access Token:


接口调用请求说明

Method: GET
Params:
 grant_type: client_credential(写死不变)
 appid: 第三方用户唯一凭证
 secret: 第三方用户唯一凭证密钥,既appsecret  
Url: https://api.weixin.qq.com/cgi-bin/token?
grant_type=client_credential&appid=APPID&secret=APPSECRET

正常就会返回如下格式:

{"access_token":"ACCESS_TOKEN","expires_in":7200}



2.获取jsapi_ticket:


生成签名之前必须先了解一下jsapi_ticket,jsapi_ticket是公众号用于调用微信JS接口的临时票据。正常情况下,jsapi_ticket的有效期为7200秒,通过access_token来获取。由于获取jsapi_ticket的api调用次数非常有限,频繁刷新jsapi_ticket会导致api调用受限,影响自身业务,必须在自己的服务全局缓存jsapi_ticket 。这里使用redis来实现。


接口调用请求说明

Method: GET
Params:
 access_token: ACCESS_TOKEN # 上一步获取的access_token  
Url: https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi


正常返回Json数据格式如下:

{
  "errcode":0,
  "errmsg":"ok",
  "ticket":"dHSM05e5u5s0m9E8NYzWKVZVbTPXNKd8-41ZN5OfkWITDGgO3MhKoysdshFKAnr2fwJvdVtaUgWv",
  "expires_in":7200
}



3. 签名算法实现


签名生成规则如下:签名参数包括:noncestr(随机字符串), 有效的jsapi_ticket, timestamp(时间戳), url(当前请求传递过来的url) 。对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1。这里需要注意的是所有参数名均为小写字符。对string1作sha1加密,字段名和字段值都采用原始值,不进行URL 转义。


假设当前需要的签名参数如下:

noncestr = wgWedZYTm3WPwzz0ccnW
jsapi_ticket = dHSM05e5u5s0m9E8NYzWKVZVbTPXNKd8-41ZN5OfkWITDGgO3MhKoysdshFKAnr2fwJvdVtaUgWv
timestamp = 1550401085
url = http://mp.weixin.qq.com?params=value


步骤1. 对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1

jsapi_ticket=dHSM05e5u5s0m9E8NYzWKVZVbTPXNKd8-41ZN5OfkWITDGgO3MhKoysdshFKAnr2fwJvdVtaUgWv&
noncestr=wgWedZYTm3WPwzz0ccnW&timestamp=1550401085&
url=http://mp.weixin.qq.com?params=value


步骤2. 对string1进行sha1签名,得到signature

ca0874ef9c0790fde62f999e9590c27e50ceb3dd


到这里,通过文档介绍,相信大家已经知道分享文章给微信好友的开发业务已经熟悉了。


后台业务流程如下所示:


640?wx_fmt=png

接下来就是展示后台的代码,最好是结合流程图和代码一起看:


@api.route("/share", methods=["POST"])
def share_article():
   """主要是处理分享文章"""
   try:
       request_data = request.get_json()
   except Exception as e:
       current_app.logger.error("request error {}".format(e))
       return define_make_response(str(dict(status=0, msg="请求错误", data=[])))
   url = request_data.get("url")
   if not url:
       return define_make_response(str(dict(status=0, msg="参数错误", data=[])))
   # 微信服务器获取access_token
   try:
       ticket_flag = redis_store.get("ticket_flag")
   except Exception as e:
       current_app.logger.error("redis error: {}".format(e))
       return define_make_response(str(dict(status=0, msg="redis查询失败", data=[])))
   if not ticket_flag:
       response = get_access_token()
       if not response[0]:
           current_app.logger.error("获取access_token失败:{}".format(response[1]))
           return define_make_response(str(dict(status=0, msg="获取微信access_token失败", data=[])))
       # 获取jsapi_ticket
       jsapi_ticket = get_jsapi_ticket(response[1])
       if not jsapi_ticket[0]:
           return define_make_response(str(dict(status=0, msg="获取ticket失败", data=[])))
       # 设置签名ticket
       ticket = jsapi_ticket[1]
   else:
       ticket = ticket_flag.decode("utf8")
   noncestr = generate_noncestr()
   timestamp = int(time.time())
   sign_str = "jsapi_ticket={}&noncestr={}&timestamp={}&url={}".format(ticket, noncestr, timestamp, url)
   sha = sha1()
   sha.update(sign_str.encode("utf8"))
   signature = sha.hexdigest()
   try:
       redis_store.setex("ticket_flag", TICKET_EXPIRES, ticket)
   except Exception as e:
       current_app.logger.error("redis error: {}".format(e))
       return define_make_response(str(dict(status=0, msg="redis保存参数失败", data=[])))
   data = [{"signature": signature, "noncestr": noncestr, "timestamp": timestamp, "appId": APP_ID}]
   return define_make_response(str(dict(status=1, msg="", data=data)))


到此为止,文档解析和后台代码分享已经完成。要是还有什么疑虑或者问题,欢迎大家私下交流。



Python全家桶

640?


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值