顺晟科技
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);//代码扫描结果
}
});
})
});
终于,你完了!
17
2022-03
29
2021-08
16
2021-06
16
2021-06
16
2021-06
16
2021-06