博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
微信公众平台——分享接口踩坑记
阅读量:5319 次
发布时间:2019-06-14

本文共 5625 字,大约阅读时间需要 18 分钟。

前言

本以为有微信公众平台开发文档,自定义分享样式还不简单?带着这样的想法,经历了两天半的踩坑经历,我写下了这篇文章。

开发分享接口在目录中: 微信网页开发 --> 微信SDK说明文档中

流程摘要

一、按照文档,第一步要绑定安全域名,即“JS接口安全域名”(此处标记1号坑)

二、第二步引入JS文件,需要下载并将其上传到服务器。这里要注意,在第一步中绑定的域名(路径)要能够访问到这个文件

三、第三步通过config接口注入权限验证配置。这里面的参数全部都要从后端获取,我的方案是服务端渲染。如果验证不通过最有可能的原因是签名算法错误。此步骤后端有很多的工作要做:先获取access_token,再根据它获取jsapi_ticket,然后再写签名算法进行计算得出签名,才将这些数据渲染到前端页面上。(此处标记踩坑点)

四、第四步ready和error接口,并且将分享接口写在ready内。

正文

一、关于JS接口安全域名

  最理想的是绑定网站地址,例如www.baidu.com。如果暂时不知道如何办成,可以先绑一个路径,如www.baidu.com/mp。

  为什么这里是1号坑?因为你如果绑定的是路径,你要分享的链接一定要在绑定的这个路径下,即使是同一个域名,不在这个路径下,对不起,签名非法。

  所以如果你想让该域名下所有的链接都可以用上自定义分享样式,就要将其绑定网站地址。

二、关于config接口。主要的工作在后端:

  1.获取access_token。(二号大坑,内含若干小坑)

    微信公众平台有两种access_token,一种可以用来第三方登录,另一种就是JS-SDK使用。获取它需要你的开发者ID和密码。

    此处要注意,(一)服务号和企业号是不一样的!

    (1)ID和密码不一样。服务号是appID和appSecret,而企业号叫做corpid和corpsecret

    (2)获取token的链接不一样,前者是api开头,后者是qyapi开头。我做的是服务号(虽然认证主体也是企业),地址是https://api.weixin.qq.com/cgi-bin/token

    (二)两种access_token要区别清楚

    (1)请求地址和参数不一样,前者地址是https://api.weixin.qq.com/sns/oauth2/access_token  后者是https://api.weixin.qq.com/cgi-bin/token。此处我们用的是后者

    (2)请求次数不一样。前者可以无限次获取,后者获取次数非常有限(具体次数不详),官方建议自己设缓存,且有效期7200秒。

    (三)如果access_token获取不对,下一步会报错,官方有提供测试获取token

  2.获取jsapi_ticket(三号大坑)

    确保token获取正确后,我们来获取ticket。同样地,

    (1)要区别服务号和企业号,因为请求地址都不一样,此处是https://api.weixin.qq.com/cgi-bin/ticket/getticket(不含参数)

    (2)获取次数有限,有效期同7200S,需设缓存。

  3.签名算法

    这里不多说,官方有提供签名算法的验证检测。

三、一切都完成以后

调试没有报错,测试分享成功,本以为大功告成,可又出了一些问题?

  1. IOS端分享正常,Android端却还是自定义之前的老样子
  2. 无论是IOS端还是Android端,点击第一次分享出来的链接,再次分享,又回到了老样子

解决:

  1. 问题出在微信平台。分享接口有很多个,我只用了updateAppMessageShareData和updateTimelineShareData,后面即将废弃的几个接口既没有声明也没有使用。这看上去没问题,可这就是问题所在(测试人员的微信都是7.0版本,JS-SDK版本是1.4.0)。解决办法是将所有分享接口都在config中声明。
  2. 二次分享问题。原因在第一次分享以后腾讯在原url上加了一些参数,导致新的url与原来的不符,与计算签名时的url不同,签名无效。解决办法是前端第一行js代码判断当前url是否是原url,如果不是则跳转到原url。

四、代码贡上

Python Django后端:

def get_accesstoken():    "获取access_token"    appid = '************'    appsecret = '***********'    def http_get_token(conn, now_time):        "向服务器获取token"        try:            url = u'https://api.weixin.qq.com/cgi-bin/token'            params = {                'appid': appid,                'secret': appsecret,                'grant_type': 'client_credential'            }            res = requests.get(url, params=params).json()            access_token = res['access_token']            # 存redis缓存            conn.hmset("access_token", {"token": access_token, "timestamp": now_time})            return access_token        except Exception as e:            traceback.print_exc()            return HttpResponse(json.dumps('access_token获取失败:%s' % e))    # 首先取缓存    conn = redis.StrictRedis(host='127.0.0.1', port='6379')    redis_token = conn.hgetall("access_token")    now_time = time.time()    if redis_token:  # 如果有token缓存        redis_time = float(str(redis_token[b"timestamp"], encoding="utf-8"))        if now_time - redis_time < 6000:  # 如果token没过期            access_token = str(redis_token[b"token"], encoding="utf-8")        else:  # 如果已过期,重新获取            access_token = http_get_token(conn, now_time)    else:  # 如果没有缓存,创建一个        access_token = http_get_token(conn, now_time)    return access_tokendef get_jsapiticket(access_token):    "获取 jsapi_ticket"    def http_get_jsapi(conn, now_time):        try:            url2 = u'https://api.weixin.qq.com/cgi-bin/ticket/getticket'            params = {                'access_token': access_token,                'type': 'jsapi'            }            res2 = requests.get(url2, params=params).json()            if res2["errmsg"] == "ok":                jsapi_ticket = res2["ticket"]                conn.hmset("jsapi", {"ticket": jsapi_ticket, "timestamp": now_time})                return jsapi_ticket        except Exception as e:            traceback.print_exc()            return HttpResponse(json.dumps('jsapi获取失败:%s' % e))    # 首先取缓存    conn = redis.StrictRedis(host='127.0.0.1', port='6379')    redis_jsapi = conn.hgetall("jsapi")    now_time = time.time()    if redis_jsapi:  # 如果有token缓存        redis_time = float(str(redis_jsapi[b"timestamp"], encoding="utf-8"))        if now_time - redis_time < 6000:  # 如果token没过期            jsapi_ticket = str(redis_jsapi[b"ticket"], encoding="utf-8")        else:  # 如果已过期,重新获取            jsapi_ticket = http_get_jsapi(conn, now_time)    else:  # 如果没有缓存,创建一个        jsapi_ticket = http_get_jsapi(conn, now_time)    return jsapi_ticketdef share(url):    "自定义分享"    appid = '***********'    # 获取access_token    access_token = get_accesstoken()    # 获取jsapi_ticket    jsapi_ticket = get_jsapiticket(access_token)    if jsapi_ticket is not None:        # 签名算法        class Sign:            def __init__(self, jsapi_ticket, url):                self.ret = {                    'nonceStr': self.__create_nonce_str(),                    'jsapi_ticket': jsapi_ticket,                    '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)]).encode(                    encoding="utf-8")                self.ret['signature'] = hashlib.sha1(string).hexdigest()                return self.ret        sign = Sign(jsapi_ticket, url)        we_share = sign.sign()        we_share.setdefault("appid", appid)        return we_share    else:        print("jsapi为空,share没有返回值")

前端:

 

转载于:https://www.cnblogs.com/V587Chinese/p/10539788.html

你可能感兴趣的文章
利用pca分析fmri的生理噪声
查看>>
div水平居中且垂直居中
查看>>
epoll使用具体解释(精髓)
查看>>
AndroidArchitecture
查看>>
原生JavaScript第六篇
查看>>
安装Endnote X6,但Word插件显示的总是Endnote Web"解决办法
查看>>
python全栈 计算机硬件管理 —— 硬件
查看>>
大数据学习
查看>>
简单工厂模式
查看>>
Delphi7编译的程序自动中Win32.Induc.a病毒的解决办法
查看>>
Objective-C 【关于导入类(@class 和 #import的区别)】
查看>>
倍福TwinCAT(贝福Beckhoff)常见问题(FAQ)-点击运行按钮进入到运行状态报错Error starting TwinCAT System怎么办 AdsWarning1823怎么办...
查看>>
【转】javascript 中的很多有用的东西
查看>>
Centos7.2正常启动关闭CDH5.16.1
查看>>
Android 监听返回键、HOME键
查看>>
Android ContentProvider的实现
查看>>
sqlserver 各种判断是否存在(表名、函数、存储过程等)
查看>>
给C#学习者的建议 - CLR Via C# 读后感
查看>>
Recover Binary Search Tree
查看>>
Java 实践:生产者与消费者
查看>>