微信JS开发与使用手记

本文档仅为微信开发文档记录,非参考文档,非官方文档。如果其中出现错误,欢迎指正。然后其中有代码是参考的网上资料,具体参考哪里的,已经记不清了。

这里记录下来,希望对以后开发有帮助,也可以帮助到需要的同学。

然后我也不知道为什么从word复制进来,代码都在一起了,太多了我也不一个个去分开了。

注:这是我之前写开发的时候用到的,可能已经过时了或者有更好的方法。因为有一段时间没有写javaweb开发了,我最近浏览时了解到Spring中的@Schedule注解,可以每隔多少时间调用一次方法,我觉得可以用来去获取token,但是自己还没有尝试过,仅仅提出来作为参考。

一、关于微信开发中JS-SDK的使用,其中包括AccessToken的获取与JsApiTicket的获取以及全局缓存的问题

开发前的准备与说明:

1).绑定域名,在微信公众号的【公众号设置】-【js接口安全域名中设置】

2).引入JS文件,http://res.wx.qq.com/open/js/jweixin-1.2.0.js(具体版本可看官方文档)

3).在开发中的页面,是需要先用config接口注入权限验证配置的,其中包括的内容有:

appId,timestamp,nonceStr,signature,jsApiList:[],其中签名是需要jsApiTicket生成的,而jsApiTicket是需要AccessToken来生成的。

并且根据微信官方,获取这些凭证每天是有次数限制的。建议的是全局缓存这两个数据在服务器端。接下来详细解说一下这几个步骤。

1.微信AccessToken的获取

第一步:

建立一个通用类,CommonUtil类

第二步:定义两个final static变量,分别为去获取AccessToken的地址与获取jsApiTicket的地址(微信官方文档指出,这两个是发送请求到微信指定服务器获取的。这两个量定义很快就会用到。)

代码如下:

```

//凭证获取(GET)

public final staticStringtoken_url="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";

private final staticStringjsApiTicket_url="https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";

```

第三步:从上面的地址或者是微信官方文档都可看出,微信获取这两个凭证都是用的https协议,而返回的数据是一个JSON格式的数据。所以定义个静态方法来发送https请求,并获取到数据。(这个请求的方法我也是从网上获取来的,属于CommonUtil类)

```

/**

*发送https请求

*

*@paramrequestUrl请求地址

*@paramrequestMethod请求方式(GET、POST)

*@paramoutputStr提交的数据

*@returnJSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)

*/

public  static  JSONObject  httpsRequest(Stringr equestUrl,String requestMethod,String outputStr){

JSONObjectjsonObject=null;

try{

//创建SSLContext对象,并使用我们指定的信任管理器初始化

TrustManager [] tm={new  MyX509TrustManager()};

SSLContextssl  Context=SSLContext.getInstance("SSL","SunJSSE");

sslContext.init(null,tm,newjava.security.SecureRandom());

//从上述SSLContext对象中得到SSLSocketFactory对象

SSLSocketFactoryssf=sslContext.getSocketFactory();

URLurl=newURL(requestUrl);

HttpsURLConnectionconn=(HttpsURLConnection)url.openConnection();

conn.setSSLSocketFactory(ssf);

conn.setDoOutput(true);

conn.setDoInput(true);

conn.setUseCaches(false);

//设置请求方式(GET/POST)

conn.setRequestMethod(requestMethod);

//当outputStr不为null时向输出流写数据

if(null!=outputStr){

OutputStreamoutputStream=conn.getOutputStream();

//注意编码格式

outputStream.write(outputStr.getBytes("UTF-8"));

outputStream.close();

}

//从输入流读取返回内容

InputStreaminputStream=conn.getInputStream();

InputStreamReaderinputStreamReader=newInputStreamReader(inputStream,"utf-8");

BufferedReaderbufferedReader=newBufferedReader(inputStreamReader);

Stringstr=null;

StringBufferbuffer=newStringBuffer();

while((str=bufferedReader.readLine())!=null){

buffer.append(str);

}

//释放资源

bufferedReader.close();

inputStreamReader.close();

inputStream.close();

inputStream=null;

conn.disconnect();

jsonObject=JSONObject.fromObject(buffer.toString());

}catch(ConnectExceptionce){

}catch(Exceptione){

}

returnjsonObject;

}

```

第四步:封装AccessToken类

封装AccessToken类,方便之后处理数据。

```

* AccessToken类,表示微信的token参数

* token:凭证

* expiresIn:凭证有效时间,单位为秒

* **/

publicclassAccessToken{

privateStringtoken;

privateintexpiresIn;

publicStringgetToken(){

returntoken;

}

publicvoidsetToken(Stringtoken){

this.token=token;

}

publicintgetExpiresIn(){

returnexpiresIn;

}

publicvoidsetExpiresIn(intexpiresIn){

this.expiresIn=expiresIn;

}

}

```

第五步:定义获取access_token方法

```

publicstaticAccessTokengetAccessToken(Stringappid,Stringappsecret){

AccessTokenaccessToken=null;

StringrequestUrl=token_url.replace("APPID",appid).replace("APPSECRET",appsecret);

JSONObjectjsonObject=httpsRequest(requestUrl,"GET",null);

//请求成功

if(null!=jsonObject){

try{

accessToken=newAccessToken();

accessToken.setToken(jsonObject.getString("access_token"));

accessToken.setExpiresIn(jsonObject.getInt("expires_in"));

}catch(Exceptione){

accessToken=null;

System.out.println("获取token失败~~~~~~~~~~~~~~~~~~~~~~");

}

}

returnaccessToken;

}

```

这个方法是用来向微信服务器获取access_token,需要传入的数据为appid与appsecret,这两个数据都是微信公众平台获取的,不叙述了。

以上方法为获取accessToken的过程,除了发送请求的方法有些复杂外,其他都是简单易懂的。

2.获取JSAPITICKET步骤

第一步:封装JsApiTicket类

```

* JsApiTicket类,用于微信内部调动js的凭证内容

* ticket:凭证

* expiresIn:有效时间

*

* **/

publicclassJsApiTicket{

privateStringticket;

privateintexpiresIn;

publicStringgetTicket(){

returnticket;

}

publicvoidsetTicket(Stringticket){

this.ticket=ticket;

}

publicintgetExpiresIn(){

returnexpiresIn;

}

publicvoidsetExpiresIn(intexpiresIn){

this.expiresIn=expiresIn;

}

}

```

第二步:书写获取jsapiticket的方法,这个方法和获取accessToken方法是类似的,发送一个请求到微信服务器,但是传入的参数是accessToken

```

/**

*获取JsApiTicket

* 2017.5.8

*/

publicstaticJsApiTicketgetJsApiTicket(StringaccessToken){

JsApiTicketjsApiTicket=null;

StringrequestUrl=jsApiTicket_url.replace("ACCESS_TOKEN",accessToken);

JSONObjectjsonObject=httpsRequest(requestUrl,"GET",null);

if(null!=jsonObject){

jsApiTicket=newJsApiTicket();

jsApiTicket.setTicket(jsonObject.getString("ticket"));

jsApiTicket.setExpiresIn(jsonObject.getInt("expires_in"));

}

returnjsApiTicket;

}

```

以上是获取jsApiTicket的方法,但是在js前端发送验证的是签名而非这个凭证,但是签名是由jsApiTicket作为参数来生成,下面来说创建签名的方法

3.创建验证签名:

第一步、定义Sha1Util类,我不知道微信开发包中是否存在这个类,有的话不必自己定义,没有的话就自己写一个

第二步:在该类中书写获取随机字符串的方法,很快会用到

```

publicstaticStringgetNonceStr(){

Randomrandom=newRandom();

returnMD5Util.MD5Encode(String.valueOf(random.nextInt(10000)),"UTF-8");

}

```

第三步:书写获取时间戳的方法:很快会用到

```

publicstaticStringgetTimeStamp(){

returnString.valueOf(System.currentTimeMillis()/1000);

}

```

第四步:书写创建签名的方法,这也是最后要生成签名的方法:

```

//创建签名SHA1

publicstaticStringcreateSHA1Sign(SortedMapsignParams)throwsException{

StringBuffersb=newStringBuffer();

Setes=signParams.entrySet();

Iteratorit=es.iterator();

while(it.hasNext()){

Map.Entryentry=(Map.Entry)it.next();

Stringk=(String)entry.getKey();

Stringv=(String)entry.getValue();

sb.append(k+"="+v+"&");

//要采用URLENCODER的原始值!

}

Stringparams=sb.substring(0,sb.lastIndexOf("&"));

returngetSha1(params);

}

//Sha1签名

publicstaticStringgetSha1(Stringstr){

if(str==null||str.length()==0){

returnnull;

}

charhexDigits[]={'0','1','2','3','4','5','6','7','8','9',

'a','b','c','d','e','f'};

try{

MessageDigestmdTemp=MessageDigest.getInstance("SHA1");

mdTemp.update(str.getBytes("UTF-8"));

byte[]md=mdTemp.digest();

intj=md.length;

charbuf[]=newchar[j*2];

intk=0;

for(inti=0;i

bytebyte0=md[i];

buf[k++]=hexDigits[byte0>>>4&0xf];

buf[k++]=hexDigits[byte0&0xf];

}

returnnewString(buf);

}catch(Exceptione){

returnnull;

}

}

```

第五步:回到CommonUtil类中,书写一个创建签名的方法。为方便传数据到页面上进行验证,故所有的数据都是作为参数传入,分别为随机字符串,jsApiTicket,时间戳,url,其中url为你要调用的页面地址,#之后的不要

然后对传入的数据进行排序,生成签名

```

/**

*创建jsApi签名

*

*/

publicstaticStringcreateJsApiTicketSign(Stringnoncestr,StringjsApiTicket,Stringtimestamp,Stringurl){

Stringstring1="jsapi_ticket="+jsApiTicket

+"&noncestr="+noncestr

+"×tamp="+timestamp

+"&url="+url;

Stringsignature=Sha1Util.getSha1(string1);

returnsignature;

}

```

到此为止,签名已经生成了。准确的来说,其实现在已经可以去开发jssdk了。但是,全局缓存的问题没有解决,接下来我们去解决这个问题。

4.全局缓存问题

全局缓存问题我所知道的有两种方法,一种是将他存入到数据库当中。第二种则是因为我用的spring框架开发,利用他缓存在全局中。

第一步:建立一个final类,也就是全局缓存的ServletContextUtil,在这个类中生成全局唯一的的ServletContext,并且在这里面定义从全局缓存的数据中获取AccessToken与JsApiTicket

代码如下:

```

/**

*全局缓存ServletContext

*@authorAdministrator

*

*/

publicfinalclassServletContextUtil{

privatestaticServletContextservletContext;

privateServletContextUtil(){}

publicsynchronizedstaticServletContextget(){

if(null==servletContext){

WebApplicationContext  webApplicationContext=ContextLoader.getCurrentWebApplicationContext();

servletContext=webApplicationContext.getServletContext();

}

returnservletContext;

}

//获取缓存的AccesToken

publicstaticAccessTokengetAccessToken(){

return(AccessToken)ServletContextUtil.get().getAttribute("Contants.ACCESS_TOKEN");

}

//获取缓存的JSAPITICKET

publicstaticJsApiTicketgetJsApiTicket(){

return(JsApiTicket)ServletContextUtil.get().getAttribute("Contants.JSAPI_TICKET");

}

```

第二步:返回到CommonUtil类中,书写一个方法,该方法用于获取两个凭证并且存储到全局中。其中appid与appsecret我是用的全局常量,你可以使用其他的方法

```

/**

*

*获取与缓存

*/

public static void initAndSetAccessToken(){

AccessTokenaccessToken=getAccessToken(InWeiChatPayConfigUtil.appid,InWeiChatPayConfigUtil.appsecret);

System.out.println("1111111111111111111111111111111111111111"+accessToken.getToken());

if(null!=accessToken){

ServletContextsc=ServletContextUtil.get();

sc.removeAttribute("Contants.ACCESS_TOKEN");

sc.setAttribute("Contants.ACCESS_TOKEN",accessToken);

JsApiTicketjsApiTicket=getJsApiTicket(accessToken.getToken());

System.out.println("111111111111111111111111"+jsApiTicket.getTicket());

if(null!=jsApiTicket){

sc.removeAttribute("Contants.JSAPI_TICKET");

sc.setAttribute("Contants.JSAPI_TICKET",jsApiTicket);

}else{

System.out.println("获取jsapi失败·······················");

}

}else{

System.out.println("获取AccessToken失败·····················");

}

}

```

第三步、我们需要新建一个监听器,用于每隔7000秒就去获取一次凭证,代码如下:

```

/**

*微信缓存监听器

*@authorAdministrator

*

*/

public class WXAccessTokenListener implements ApplicationListener{

@Override

publicvoidonApplicationEvent(ContextRefreshedEventevent){

//TODOAuto-generated method stub

if(event.getApplicationContext().getParent()==null){

Runnablerunnable=newRunnable(){

@Override

publicvoidrun(){

CommonUtil.initAndSetAccessToken();

}

};

ScheduledExecutorServiceservice=Executors.newSingleThreadScheduledExecutor();

service.scheduleAtFixedRate(runnable,1,7000,TimeUnit.SECONDS);

}

}

}

```

第四步:这是最后一步了,就是需要再spring容器中注册这个监听器,否则是无效的。

那么获取与缓存的问题也就解决了,惊不惊喜?意不意外?

下面演示一下我的使用方式:


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容