18910140161

微信公众号H5开发调用微信 js-sdk的那些事

顺晟科技

2021-06-16 10:56:20

269

要求

如果你正在开发微信H5页面,需要调用微信js接口,专门总结一下调用过程

步骤

首先,绑定安全域名

登录微信公众平台,进入“微信官方账号设置”的“功能设置”,填写“JS接口安全域名”

注意:

1.需要从微信官方账号管理平台下载验证证书的txt文本内容,然后上传到填写域名或路径指向的web服务器(或虚拟主机)的目录下(如果填写了域名,则将文件放在域名的根目录下,如wx.qq.com/MP_verify_1FKXuKnjqdNephyv.txt;)如果填写了路径,则将文件放在路径目录下,如wx.qq.com/mp/MP_verify_1FKXuKnjqdNephyv.txt,确保可以访问。

2.绑定域名时,只填写域名部分,必须由ICP备案。不需要http://协议前缀,也不需要访问页面路径

正确的例子:www.baidu.com

错误示例:www.baidu.com/index http://www.baidu.com

二、介绍微信js-sdk文件

在需要调用JS接口的页面上引入以下JS文件(支持HTTPS):http://res.wx.qq.com/open/js/jweixin-1.4.0.js

为了进一步提高服务稳定性,当上述资源不可访问时,可以改为访问:http://res2.wx.qq.com/open/js/jweixin-1.4.0.js(支持https)

第三,获取wx.config()参数

在调用微信js-sdk接口之前,需要wx.config进行权限验证。验证需要以下参数

wx.config({

调试:真。//打开调试模式,所有被调用的API的返回值都会在客户端告警上发出。如果您想查看传入的参数,您可以在电脑端打开它们,参数信息将通过日志打印出来,只打印在电脑端。

AppId: ' ',//必选,微信官方账号标识

Timestamp://必需,生成签名的时间戳

NonceStr: ' ',//必需,生成随机签名字符串

签名: ' ',//必需,已签名

JsApiList: [] //是必填项,是要使用的JS接口列表

});

签名生成和jsApiList的步骤在微信文档中。详见链接:https://mp.weixin.qq.com/wiki? T=resource/RES _ mainid=MP 142114115通过官方文档,我们知道要生成一个签名,我们需要一个随机字符串nonceStr、一个时间戳、一个证书jsapi_ticket、一个url(包括http或https协议头和页面路径)来调用接口页面,然后我们需要一个sha1加密算法

在这里,我将只与您分享一些用于生成签名的代码(java)。

1.首先我们需要通过微信微信官方账号的接口获取accessToken,调用微信接口获取jsapi _ ticket此时,我们需要的是一个可以发送请求的工具,它封装了一个HttpReq类:

公共类HttpReq {

公共静态字符串doGet(字符串url) {

CloseableHttpClient httpClient=null;

CloseableHttpResponse响应=null

字符串结果=' ';

尝试{

//通过地址默认配置创建一个httpClient实例

httpClient=httpclients . create default();

//创建httpGet远程连接实例

http get Http get=new Http get(URL);

//设置请求头信息并进行身份验证

//httpgetsetheader(' Authorization ','持票人da 3 efcbf-0845-4 Fe 3-8 ABA-ee 040 be 542 c 0 ');

//设置配置请求参数

request config=request config . custom()。setconnecttimeout(35000)//连接主机服务超时。setconnectionrequesttime out(35000)//请求超时。setSocketTimeout(60000)//数据读取超时。build();

//为httpGet实例设置配置

http get . SetConfig(RequestConfig);

//执行get请求以获取返回的对象

response=httpclient . execute(HttpGet);

//通过return对象获取返回数据

HttpEntity entity=response . GetEntity();

//通过EntityUtils中的toString方法将结果转换成字符串

result=EntityUtils.toString(实体);

} catch(ClientProtocoleException e){

e . printstacktrace();

} catch (IOException e) {

e . printstacktrace();

}最后{

//关闭资源

if (null!=响应){

尝试{

response . close();

} catch (IOException e) {

e .printstacktrace();

}

}

if (null!=httpClient) {

尝试{

httpclient。close();

} catch (IOException e) {

e .printstacktrace();

}

}

}

返回结果;

}

公共静态字符串映射(字符串url、映射字符串、对象参数映射){

CloseableHttpClient httpClient=null;

CloseableHttpResponse httpResponse=null;

字符串结果=' ';

//创建客户端实例

httpClient=httpclients。创建默认值();

//创建获得远程连接实例

Http set Http set=新建Http set(URL);

//配置请求参数实例

请求配置请求配置=请求配置。自定义().setConnectTimeout(35000)//设置连接主机服务超时时间。setconnectionrequest time out(35000)//设置连接请求超时时间。setSocketTimeout(60000)//设置读取数据连接超时时间。build();

//为获得实例设置配置

http设置。SetConfig(RequestConfig);

//设置请求头

http设置。addheader(' Content-Type ',' application/x-www-form-URL encoded ');

//封装邮政请求参数

if (null!=ParAmpMap ParAmpMap。size()0){

ListNameValuePair nvps=new ArrayListNameValuePair();

//通过地图集成entrySet方法获取实体

SetMap .EntryString,Object entrySet=param map。entrySet();

//循环遍历,获取迭代器

迭代器对象迭代器=entryset。iterator();

while (iterator.hasNext()) {

地图对象映射入口=迭代器。next();

nvps。添加新的基本名称值对(MapEntry。GetKey(),mapEntry.getValue().toString()));

}

//为获得设置封装好的请求参数

尝试{

httpset。setentity(新的UrlEncodedFormEntity(nvps,' UTF-8 '));

} catch(unsupportedencodinegexception e){

e .printstacktrace();

}

}

尝试{

//httpClient对象执行邮政请求,并返回响应参数对象

httpResponse=httpclient。execute(http set);

//从响应对象中获取响应内容

HttpEntity实体=httpresponse。getentity();

result=EntityUtils.toString(实体);

} catch(ClientProtocoleException e){

e .printstacktrace();

} catch (IOException e) {

e .printstacktrace();

}最后{

//关闭资源

if (null!=httpResponse) {

尝试{

http响应。close();

} catch (IOException e) {

e .printstacktrace();

}

}

if (null!=httpClient) {

尝试{

httpclient。close();

} catch (IOException e) {

e .printstacktrace();

}

}

}

返回结果;

}

}

使用得到或者邮政请求都可以调用,返回的结果是线类型,如果需要解析成JSONObject,需要使用jsonobject。parse object();

获取到jsapi_ticket后,需要做一个变量的缓存(因为微信给我们提供的这个接口有调用次数限制),这里我采用设置一个全局过期时间,如果过期了,就重新发送请求获取,(因为只有一个变量需要缓存,就没有使用其他框架来做缓存)大家也可以参考一下:

/**jsapi_ticket*/

私有静态字符串jsapiTicket

/**jsapi_ticket过期时间*/

私有静态长jsapiTicketExpires

/**设置jsapiTicket*/

private int setJsapiTicket(){

long Curtime=系统。CurrentiMemillis();

如果(Curtime jsapticket过期jsapticket!=null){

系统。出去。println(' JSapiticket没有过期,不再重新获取!');

返回1;

}

JSON对象访问令牌RES=GetAccessToken();//获取访问令牌的方法需要大家自己发送请求(涉及到业务方隐私)

if(accessTokenRes==null){

System.out.println('获取访问令牌失败!');

返回0;

}

字符串访问令牌=访问令牌。getStrIng(' access _ token ');

尝试{

string RES=Httpreq。DoGet(' https://API。微信。QQ。com/CGI-bin/ticket/getticket?access _ token=' AccessToken ' type=jsapi ');

JSON对象结果=JSON。ParseObject(RES);

if(result.getString('errmsg ').等于(' ok '){

jsapiTicket=结果。getString(' ticket ');

jsapticket expires=Curtime 7200 * 1000;

}

}捕获(例外e){

系统。出去。println(' get JSapiticket上的错误,e);

返回0;

}

返回1;

}

在获取全局变量jsapiTicket之前,需要进行一次setJsapiTicket,并根据其返回状态码进行判断是否发送请求

/**设置jsapiTicket*/

int setticketrees=Setjsapiticket();

if(setticketrees==0 | | JSapiTick==null){

System.out.println('获取jsapiTicket失败!');

返回空

}

string jsapi _ ticket=JSapiticket;//获取jsapi_ticket

2.获取到jsapi_ticket之后,我们需要自己生成一个长度为16的随机字符串(官方文档里的随机字符串长度为16,所以这里生成长度为16的),具体生成代码如下:

公共类RandomStr {

私有静态char ch[]={ '0 ',' 1 ',' 2 ',' 3 ',' 4 ',' 5 ',' 6 ',' 7 ',' 8 ',' 9 ',' A ',' B ',' C ',' D ',' E ',' F ',' G ',

' h ',' I ',' J ',' K ',' L ',' M ',' N ',' O ',' P ',' Q ',' R ',' S ',' T ',' U ',' V ',' W ',' X ',' Y ',' Z ',' a ',' b ',

' c ',' d ',' e ',' f ',' g ',' h ',' I ',' j ',' k ',' l ',' m ',' n ',' o ',' p ',' q ',' r ',' s ',' t ',' u ',' v ',' w ',

x ',' y ',' z ',' 0 ',' 1 ' };//最后又重复两个0和1,因为需要凑足数组长度为64

私有静态Random Random=new Random();

//生成指定长度的随机字符串

公共静态字符串createRandomString(int length) {

if(长度0) {

int index=0;

char[] temp=新的char[length];

int num=random。nextint();

for(int I=0;我长度% 5;i ) {

temp[index ]=ch[num 63].//取后面六位,记得对应的二进制是以补码形式存在的。

num=6;//63的二进制为:111111

//为什么要右移6位?因为数组里面一共有64个有效字符。为什么要除5取余?因为一个(同国际组织)国际组织型要用四个字节表示,也就是32位。

}

for(int I=0;我长度/5;i ) {

num=随机。nextint();

for(int j=0;j5;j ) {

temp[index ]=ch[num 63].

num=6;

}

}

返回新字符串(临时,0,长度);

}

else if(长度==0) {

返回"";

}

else {

抛出新的IllegalArgumentException();

}

}

公共静态void main(String[] args) {

系统。出去。println(createRandomString(16));

}

}

调用RandomStr类的静态方法createRandomString,传入你需要创建随机字符串的长度,即可生成

3.生成当前时间的秒数(时间戳):

//生成的时间戳单位为毫秒,除以1000变为秒数

长时间戳=系统。CurrentiMemillis()/1000;

4.按照指定顺序拼接字符串,然后使用sha1算法生成签名(注意:拼接的字符串必须是如下顺序jsapi _ ticket=' jsapi _ ticket ' non estr=' non estr ' timestamp=' timestamp ' URL=' URL)

长时间戳=系统。CurrentiMemillis()/1000;//当前的时间戳(秒)

字符串非波峰=随机字符串。createdrandom字符串(16);//长度为16的随机字符串

字符串URL='-';//需要调用软件开发工具包的页面路径

string jsapi _ ticket=JSapiticket;//通过调用微信接口生成的jsapi_ticket

/**加密字符串*/

string str=' jsapi _ ticket=' jsapi _ ticket ' non estr=' non estr ' timestamp=' timestamp ' URL=' URL;

/**通过加密拼接的字符串获取签名*/

字符串签名=Sha1。encode(str);//签名即为生成的签名,Sha1算法代码见下方

sha1算法的代码如下:

公共类Sha1 {

私有静态最终字符[]HEX _ DIGETS={ ' 0 ',' 1 ',' 2 ',' 3 ',' 4 ',' 5 ',

6 ',' 7 ',' 8 ',' 9 ',' a ',' b ',' c ',' d ',' e ',' f ' };

私有静态字符串getFormattedText(字节[]字节){

int len=bytes.length

StringBuilder buf=new StringBuilder(len * 2);

//把密文转换成十六进制的字符串形式

for(int j=0;j lenj ) {

buf。append(HEX _ DIGETS[(bytes[j]4)0x0f]);

buf . append(HEX _ DIGETS[bytes[j]0x0f]);

}

return buf . ToString();

}

公共静态字符串编码(字符串){

if (str==null) {

返回null

}

尝试{

消息摘要消息摘要=消息摘要. GetInstance(' SHA1 ');

messagedigest . update(str . GetBytes());

返回getformatedtext(messagedigest . digest());

}捕获(例外e) {

引发新的RuntimeException(e);

}

}

}

这样我们需要的签名、生成签名的时间戳、随机字符串都是可用的,前台可以通过调用Controller直接获取,然后进行wx.config()进行授权验证;

第四,调用wx.config()验证微信接口调用

在conroller中添加一个请求,用来调用上面的代码模型获取签名,生成签名的时间戳和字符串。

然后在前台需要调用微信界面的页面上调用,获取相应的参数,然后执行wx.config()。验证成功后,可以在wx.ready()的回调中调用微信界面;(以微信扫为例)

$.ajax({

type:'post ',

Url:'/getWxConfig.do ',//获取有关wx.config的信息

成功:函数(结果){

console.log(结果)

wx.config({

//开启调试模式,所有被调用的API的返回值都会在客户端被告警。要查看输入参数,您可以在电脑端打开它们,参数信息将通过日志打印出来,只打印在电脑端。

debug: false,

//必选,微信官方账号标识

appId: result.data.appId,

//必选,生成签名时间戳

timestamp : result . data . timestamp,

//必需,生成随机签名字符串

non crest : result . data . non crest,

//必填,已签名,见附录1

signature re : result . data . signature

//必选,要使用的JS接口列表。所有JS接口列表见附录2

jsApiList : ['scanQRCode' ]

});

},

错误:函数(err){

console.error(错误)

}

})

/* *在/**wx.config()错误后返回消息*/

wx.error(function(res) {

console.log中出错(':' RES . errmsg);

});

/* *微信准备好之后,所有调用微信界面的内容都需要放在这里*/

wx.ready(function() {

//点击按钮扫描二维码

$('#scanQRCode ')。on('click ',function(){

wx.scanQRCode({

NeedResult : 1,//默认为0,扫描结果由微信处理,1直接返回扫描结果。

扫描类型: ['二维码'],//可以指定是扫描二维码还是一维码,默认都可以

成功:功能(res) {

console . log(RES);//代码扫描结果

}

});

})

});

终于,你完了!

我们已经准备好了,你呢?
2024我们与您携手共赢,为您的企业形象保驾护航