protected WxResp call(String URL, METHOD method, String body) {
String token = getAccessToken();
if (log.isInfoEnabled()) {
log.info("wxapi call: " + URL);
if (log.isDebugEnabled()) {
log.debug(body);
}
}
int retry = retryTimes;
WxResp wxResp = null;
while (retry >= 0) {
try {
String sendUrl = null;
if (!URL.startsWith("http"))
sendUrl = base + URL;
if (URL.contains("?")) {
sendUrl += "&access_token=" + token;
} else {
sendUrl += "?access_token=" + token;
}
Request req = Request.create(sendUrl, method);
if (body != null)
req.setData(body);
Response resp = Sender.create(req).send();
if (!resp.isOK())
throw new IllegalArgumentException("resp code=" + resp.getStatus());
wxResp = Json.fromJson(WxResp.class, resp.getReader("UTF-8"));
// 处理微信返回 40001 invalid credential
if (wxResp.errcode() != 40001) {
break;//正常直接返回
} else {
log.warnf("wxapi of access_token request [%s] finished, but the return code is 40001, try to reflush access_token right now, surplus retry times : %s" ,URL ,retry);
// 强制刷新一次acess_token
reflushAccessToken();
}
} catch (Exception e) {
if (retryTimes >= 0) {
log.warn("reflushing access_token... " + retry + " retries left.", e);
} else {
log.errorf("%s times attempts to get a wx access_token , but all failed!", retryTimes);
throw Lang.wrapThrow(e);
}
} finally {
retry--;
}
}
return wxResp;
}
24 回复
@Override
public String getAccessToken() {
WxAccessToken at = accessTokenStore.get();
if (at == null || at.getExpires() < (System.currentTimeMillis() - at.getLastCacheTimeMillis()) / 1000) {
synchronized (lock) {
//FIX多线程更新token的问题
WxAccessToken at_forupdate = accessTokenStore.get();
if (at_forupdate == null || at_forupdate.getExpires() < (System.currentTimeMillis() - at_forupdate.getLastCacheTimeMillis()) / 1000) {
reflushAccessToken();
}
}
}
return accessTokenStore.get().getToken();
}
WxAccessToken at = accessTokenStore.get();
每次获得的都是null,这是为啥?
<dependency>
<groupId>org.nutz</groupId>
<artifactId>nutzwx</artifactId>
<version>1.r.61.r2</version>
</dependency>
protected void reflushAccessToken() {
String url = String.format("%s/token?grant_type=client_credential&appid=%s&secret=%s", base, appid, appsecret);
if (log.isDebugEnabled())
log.debugf("ATS: reflush access_token send: %s", url);
Response resp = Http.get(url);
if (!resp.isOK())
throw new IllegalArgumentException("reflushAccessToken FAIL , openid=" + openid);
String str = resp.getContent();
if (log.isDebugEnabled())
log.debugf("ATS: reflush access_token done: %s", str);
NutMap re = Json.fromJson(NutMap.class, str);
String token = re.getString("access_token");
int expires = re.getInt("expires_in") - 200;//微信默认超时为7200秒,此处设置稍微短一点
accessTokenStore.save(token, expires, System.currentTimeMillis());
}
然后调用save
public class MemoryAccessTokenStore implements WxAccessTokenStore {
private static final Log log = Logs.get();
WxAccessToken at;
@Override
public WxAccessToken get() {
return at;
}
@Override
public void save(String token, int time, long lastCacheTimeMillis) {
at = new WxAccessToken();
at.setToken(token);
at.setExpires(time);
at.setLastCacheTimeMillis(lastCacheTimeMillis);
log.debugf("new wx access token generated : \n %s", Json.toJson(at, JsonFormat.nice()));
}
}
然而没有存成功的样子,下次过来,还是null
@At
@Ok("json")
@SLog(tag = "获取模板列表", msg = "")
//@RequiresPermissions("wx.tpl.list.get")
public Object getDo(@Param("wxid") String wxid, HttpServletRequest req) {
try {
WxApi2 wxApi2 = wxConfigService.getWxApi2(wxid);
WxResp wxResp = wxApi2.get_all_private_template();
List<Wx_tpl_list> lists = wxResp.getList("template_list", Wx_tpl_list.class);
for (Wx_tpl_list o : lists) {
o.setWxid(wxid);
wxTplListService.insert(o);
}
return Result.success("system.success");
} catch (Exception e) {
return Result.error("system.error");
}
}
在这里直接用了WxApi2Impl的方法
WxResp wxResp = wxApi2.get_all_private_template();
没看到哪里new对象了。。。
/**
* Created by wizzer on 2016/7/2.
*/
@IocBean(args = {"refer:dao"})
public class WxConfigService extends Service<Wx_config> {
public WxConfigService(Dao dao) {
super(dao);
}
public WxApi2 getWxApi2(String wxid) {
Wx_config appInfo = this.fetch(Cnd.where("id", "=", wxid));
WxApi2Impl wxApi2 = new WxApi2Impl();
wxApi2.setAppid(appInfo.getAppid());
wxApi2.setAppsecret(appInfo.getAppsecret());
wxApi2.setEncodingAesKey(appInfo.getEncodingAESKey());
wxApi2.setToken(appInfo.getToken());
return wxApi2;
}
}
有new的操作,是这里有问题吗?
@1037424761 看最新版的NutzWk WxConfigService
如果启用了redis最好用redis来存:
@IocBean(args = {"refer:dao"})
public class WxConfigServiceImpl extends BaseServiceImpl<Wx_config> implements WxConfigService {
@Inject
private JedisPool jedisPool;
public WxConfigServiceImpl(Dao dao) {
super(dao);
}
public WxApi2 getWxApi2(String wxid) {
Wx_config appInfo = this.fetch(Cnd.where("id", "=", wxid));
RedisAccessTokenStore redisAccessTokenStore = new RedisAccessTokenStore();
redisAccessTokenStore.setTokenKey("WxToken:" + wxid);
redisAccessTokenStore.setJedisPool(jedisPool);
WxApi2Impl wxApi2 = new WxApi2Impl();
wxApi2.setAppid(appInfo.getAppid());
wxApi2.setAppsecret(appInfo.getAppsecret());
wxApi2.setEncodingAesKey(appInfo.getEncodingAESKey());
wxApi2.setToken(appInfo.getToken());
wxApi2.setAccessTokenStore(redisAccessTokenStore);
return wxApi2;
}
}
没看明白
public WxApi2 getWxApi2(String wxid) {
Wx_config appInfo = this.fetch(Cnd.where("id", "=", wxid));
RedisAccessTokenStore redisAccessTokenStore = new RedisAccessTokenStore();
redisAccessTokenStore.setTokenKey("WxToken:" + wxid);
redisAccessTokenStore.setJedisPool(jedisPool);
WxApi2Impl wxApi2 = new WxApi2Impl();
wxApi2.setAppid(appInfo.getAppid());
wxApi2.setAppsecret(appInfo.getAppsecret());
wxApi2.setEncodingAesKey(appInfo.getEncodingAESKey());
wxApi2.setToken(appInfo.getToken());
wxApi2.setAccessTokenStore(redisAccessTokenStore);
return wxApi2;
}
中这3句话
RedisAccessTokenStore redisAccessTokenStore = new RedisAccessTokenStore();
redisAccessTokenStore.setTokenKey("WxToken:" + wxid);
redisAccessTokenStore.setJedisPool(jedisPool);
添加进来,在哪里用?
@IocBean(args = {"refer:dao"})
public class WxConfigService extends Service<Wx_config> {
WxApi2Impl wxApi2 = new WxApi2Impl();
public WxConfigService(Dao dao) {
super(dao);
}
public WxApi2 getWxApi2(String wxid) {
Wx_config appInfo = this.fetch(Cnd.where("id", "=", wxid));
wxApi2.setAppid(appInfo.getAppid());
wxApi2.setAppsecret(appInfo.getAppsecret());
wxApi2.setEncodingAesKey(appInfo.getEncodingAESKey());
wxApi2.setToken(appInfo.getToken());
return wxApi2;
}
}
我把new的实例放到外面,发现有用,但是总感觉用什么地方不对。
@IocBean(args = {"refer:dao"})
public class WxConfigService extends Service<Wx_config> {
Map<String, WxApi2Impl> apis = new HashMap<String, WxApi2Impl>();
public WxConfigService(Dao dao) {
super(dao);
}
public synchronized WxApi2 getWxApi2(String wxid) {
WxApi2Impl wxApi2 = apis.get(wxid);
if (wxApi2 == null) {
wxApi2 = new WxApi2Impl();
Wx_config appInfo = this.fetch(Cnd.where("id", "=", wxid));
wxApi2.setAppid(appInfo.getAppid());
wxApi2.setAppsecret(appInfo.getAppsecret());
wxApi2.setEncodingAesKey(appInfo.getEncodingAESKey());
wxApi2.setToken(appInfo.getToken());
}
return wxApi2;
}
}
redis
@Aop("redis")
public void clearCache() {
Set<String> set = jedis().keys("data:wx_api_*");
for (String it : set) {
jedis().del(it.getBytes());
}
}
@Aop("redis")
public synchronized WxApi2 getWxApi2(String wxid) {
WxApi2Impl wxApi2;
byte[] bt = jedis().get(("data:wx_api_impl_" + wxid).getBytes());
if (bt != null) {
wxApi2 = Lang.fromBytes(bt, WxApi2Impl.class);
} else {
Wx_config appInfo = this.fetch(Cnd.where("id", "=", wxid));
RedisAccessTokenStore redisAccessTokenStore = new RedisAccessTokenStore();
redisAccessTokenStore.setTokenKey("data:wx_api_token_" + wxid);
redisAccessTokenStore.setJedisPool(jedisPool);
wxApi2 = new WxApi2Impl();
wxApi2.setAppid(appInfo.getAppid());
wxApi2.setAppsecret(appInfo.getAppsecret());
wxApi2.setEncodingAesKey(appInfo.getEncodingAESKey());
wxApi2.setToken(appInfo.getToken());
wxApi2.setAccessTokenStore(redisAccessTokenStore);
jedis().set(("data:wx_api_impl_" + wxid).getBytes(), Lang.toBytes(wxApi2));
}
return wxApi2;
}
DaoAccessTokenStore.java里的实现,只有fetch和update
private String fetch = "select access_token,access_token_expires,access_token_lastat from wx_config where id=@id";
private String update = "update wx_config set access_token=@access_token, access_token_expires=@access_token_expires, access_token_lastat=@access_token_lastat where id=@id";
我是自己写一个wx_config表的model,再手动插入一个数据?
还是在其它地方有自动建表和插入数据的代码?
添加回复
请先登陆