部分手机在图片上传的时候,调取不到sd卡相册或其他图片,为了解决这个兼容性问题,同一个页面使用了两种图片上传方案。
html5 :图片编码成base64 ,发送到后台,解码存储。这种方法用于解决非微信浏览器的上传问题。
jsapi:用于解决微信浏览器的上传问题。
思路:
首先判断是否是微信浏览器(微信js接口提供方法),然后调用上面不同的方法。
这里记下jfinal整合jsapi的关键代码和流程 。
前端页面需要一段javascript ,官方文档有详细说明,以下我的config
wx.config({ debug: true, appId: ‘wx23eeb004xxxx8ecb‘, // 必填,公众号的唯一标识 timestamp:‘${timestamp}‘, // 必填,生成签名的时间戳 nonceStr: ‘t8bI2mW5Mxxxx20Y‘, // 必填,生成签名的随机串 signature: ‘${signature}‘, jsApiList: [ ‘chooseImage‘ ] });
以下是前端页面对应的ctrl ,惯例只是关键部分
//微信 ApiConfig ac = new ApiConfig(); String token = ConfigUtil.get("weixinToken"); String appid = ConfigUtil.get("weixinAppId"); String secret = ConfigUtil.get("weixinSecret"); // 配置微信 API 相关常量 ac.setToken(token); ac.setAppId(appid); ac.setAppSecret(secret); /** * 是否对消息进行加密,对应于微信平台的消息加解密方式: * 1:true进行加密且必须配置 encodingAesKey * 2:false采用明文模式,同时也支持混合模式 */ ac.setEncryptMessage(false); ac.setEncodingAesKey(ConfigUtil.get("weixinEncodingAESKey")); ApiConfigKit.setThreadLocalApiConfig(ac); //必须 JssdkTicket jssdkTicket = JssdkTicketUtil.getJssdkTicket(); if (!jssdkTicket.getErrmsg().equals("ok")){ setAttr("errormsg","如需使用图片上传功能,请刷新页面重试"); }else { String fuckU= DateUtil.getCurMis().toString().substring(0,10); String tempStr = new StringBuilder().append("jsapi_ticket=" + jssdkTicket.getTicket() + "&noncestr=t8bI2mW5Mma0I20Y×tamp=" + fuckU + "&url=" + getRequest().getRequestURL()+"").toString(); System.out.println("string1="+tempStr); tempStr = EncryptionKit.sha1Encrypt(tempStr); System.out.println("加密后="+tempStr); setAttr("timestamp", fuckU); setAttr("signature",tempStr); } createToken("blogToken", 30 * 60); render(AppConst.PATH_WAP_PC+"/abc.ftl");
以下是JssdkTicketUtil ,该util用于缓存jsapi_ticket,也是微信官方文档中一再强调的东西
public class JssdkTicketUtil { private static JssdkTicket jssdkTicket; public static JssdkTicket getJssdkTicket() { if(jssdkTicket != null && jssdkTicket.isAvailable()) { return jssdkTicket; } else { refreshAccessToken(); return jssdkTicket; } } private static void refreshAccessToken() { jssdkTicket = requestJssdkTicket(); } private static synchronized JssdkTicket requestJssdkTicket() { JssdkTicket result = null; AccessToken accessToken = AccessTokenApi.getAccessToken(); String json = HttpKit.get("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + accessToken.getAccessToken() + "&type=jsapi"); result = new JssdkTicket(json); if(!result.isAvailable()) { refreshAccessToken(); } return result; } }
以下是jssdkTicket ,用于存储信息
public class JssdkTicket { private String jsapi ;//服务器返回 private Long expiredTime ; //过期时间 private Integer errcode; //错误码 private String errmsg; //错误信息 private String ticket; //票据 private Integer expires_in; // public JssdkTicket(String jsapiStr){ this.jsapi = jsapiStr; try { Map e = (Map)(new ObjectMapper()).readValue(jsapiStr, Map.class); this.expires_in = (Integer)e.get("expires_in"); this.errcode = (Integer)e.get("errcode"); this.errmsg = (String)e.get("errmsg"); this.ticket = (String)e.get("ticket"); if(this.expires_in != null) { this.expiredTime = Long.valueOf(System.currentTimeMillis() + (long)((this.expires_in.intValue() - 5) * 1000)); } } catch (Exception var3) { throw new RuntimeException(var3); } } public boolean isAvailable() { return this.expiredTime == null ? false : (this.errcode != 0 ? false : (this.expiredTime.longValue() < System.currentTimeMillis() ? false : this.ticket != null)); } public String getJsapi() { return jsapi; } public Long getExpiredTime() { return expiredTime; } public Integer getErrcode() { return errcode; } public String getErrmsg() { return errmsg; } public String getTicket() { return ticket; } public Integer getExpires_in() { return expires_in; } }
以上两个类完成参照jfinal-weixin-1.2中对access_token的处理方式 。感谢jfinal作者 @jfinal