微信登录+sdk+服务器,微信sdk后端集成

相关参考网址:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115

终极效果:

20170712171242.png

背景介绍:

在我们使用微信浏览器进行浏览网页的时候,有时会有一些需求是要求你所查看的页面可以通过微信分享出去,然而普通的网页,在微信的浏览器中点击分享出去的效果,由于微信自己的一些限制,会导致分享出去的页面并不能达到上图的效果,实际的效果可能是下图这样的,很扯

20170712172149.png

想要达成想要的那种效果,就必须集成微信官方的 JSSDK:

20170717141527.png

20170712171053.png

具体步骤

一、服务器端操作

登录微信公共平台使用开发者账户登录到后台管理系统页面

20170712170738.png

按照下面叙述的步骤绑定想要绑定的服务器域名

20170712170856.png

服务器端

一般的获取验证签名步骤如下:

step1: 使用微信公众号的 APPID 和 APPKEY 在微信的官方接口中获取到应用的 Access_token 网址为

https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=YOURAPPID&secret=YOURAPPSECRET

其中将 YOURAPPID 和 YOURAPPSECRRET 换成公众号的 APPID 和 APPSECRET 即可,成功后的效果会返回你的 access_token

20170717143253.png

step2:使用 step1 中生成的 access_token 在下面链接中获取到最终签名用的 ticket

https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=access_tokenInStep1&type=jsapi

如下图

最终的流程中,我们即可使用这个 ticket 进行对网页的签名

由于整个流程中生成的各个关键码 ,微信都给其设定了时间限制,对于每个时间的使用有效期,都只有 7200 秒,也就是两个小时,所以这些码子必须通过数据库存储的方式存储进数据库,然后定时对其更新,保证每个码子都可以进行有效的签名,具体实际的流程如下:

step1:将 AppId 和 AppKey 存储到数据库 appconfig 里面,更新的代码如下

public void UpdateAccess_tokenAndTicket(){

//获取到AppId 和AppSecret

String appId = configRepository.findByName("WXJSSDKID").getValue();

String appsecret = configRepository.findByName("WXJSSDKSECRET").getValue();

//根据Appid 和Appsecret生成Access token 和ticket

//先更新ACCESS_TOKEN的code

Config config_access_token = configRepository.findByName("ACCESS_TOKEN");

String token_code = WxJSSDKUtil.getAccess_token(appId, appsecret);

if(StringUtils.isNotBlank(token_code)){

config_access_token.setValue(token_code);

configRepository.save(config_access_token);

//根据access获取到ticket并更新他

Config config_ticket = configRepository.findByName("TICKET");

System.out.println("================="+token_code);

String ticket = WxJSSDKUtil.GetTicket(token_code);

if(StringUtils.isNotBlank(ticket)){

System.out.println("new ticket======"+ticket);

config_ticket.setValue(ticket);

configRepository.save(config_ticket);

}

}

}

这里需要调用获取 access_token 和 Ticket 的方法

public class WxJSSDKUtil {

private final static String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token";

private final static String TICKET_URL = "https://api.weixin.qq.com/cgi-bin/ticket/getticket";

/**

* 根据appid和appsecret获取access_token

* @param appid

* @param appsecret

* @return

*/

/**

*获取ACCESSTOKEN

*/

@SuppressWarnings("unchecked")

public static String getAccess_token(String appid, String appsecret){

String param = "grant_type=client_credential&appid="+appid+"&secret="+appsecret;

String res = HttpUtils.sendGet(ACCESS_TOKEN_URL, param);

Map resObj = JSONObject.fromObject(res);

String access_token = (String) resObj.get("access_token");

return access_token;

}

/**

*获取ticket

*/

@SuppressWarnings("unchecked")

public static String GetTicket(String accessToken){

String res = HttpUtils.sendGet(TICKET_URL, "access_token="+accessToken+"&type=jsapi");

Map resObj = JSONObject.fromObject(res);

String ticket = (String) resObj.get("ticket");

return ticket;

}

}

step2: 签名算法 JSSDKUtil.java:

public class WeixinSDKSignUtil {

public static void main(String[] args) {

String jsapi_ticket = "jsapi_ticket";

// 注意 URL 一定要动态获取,不能 hardcode

String url = "http://example.com";

Map ret = sign(jsapi_ticket, url);

};

public static Map sign(String jsapi_ticket, String url) {

Map ret = new HashMap();

String nonce_str = create_nonce_str();

String timestamp = create_timestamp();

String string1;

String signature = "";

//注意这里参数名必须全部小写,且必须有序

string1 = "jsapi_ticket=" + jsapi_ticket +

"&noncestr=" + nonce_str +

"&timestamp=" + timestamp +

"&url=" + url;

try

{

MessageDigest crypt = MessageDigest.getInstance("SHA-1");

crypt.reset();

crypt.update(string1.getBytes("UTF-8"));

signature = byteToHex(crypt.digest());

}

catch (NoSuchAlgorithmException e)

{

e.printStackTrace();

}

catch (UnsupportedEncodingException e)

{

e.printStackTrace();

}

ret.put("url", url);

ret.put("jsapi_ticket", jsapi_ticket);

ret.put("nonceStr", nonce_str);

ret.put("timestamp", timestamp);

ret.put("signature", signature);

return ret;

}

private static String byteToHex(final byte[] hash) {

Formatter formatter = new Formatter();

for (byte b : hash)

{

formatter.format("%02x", b);

}

String result = formatter.toString();

formatter.close();

return result;

}

private static String create_nonce_str() {

return UUID.randomUUID().toString();

}

private static String create_timestamp() {

return Long.toString(System.currentTimeMillis() / 1000);

}

}

至此服务器端的签名流程和准备已经全部完成,下期会说整个流程中的前端页面签名步骤