/*
* Copyright 2007-2107 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.ymate.platform.module.wechat.support;
import com.alibaba.fastjson.JSONObject;
import net.ymate.platform.module.wechat.AccountDataMeta;
import net.ymate.platform.module.wechat.IAccountDataProvider;
import net.ymate.platform.module.wechat.WeChat;
import net.ymate.platform.module.wechat.WeChat.WX_API;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;
/**
* <p>
* DefaultAccountDataProvider
* </p>
* <p>
* <p/>
* </p>
*
* @author 刘镇(suninformation@163.com)
* @version 0.0.0
* <table style="border:1px solid gray;">
* <tr>
* <th width="100px">版本号</th><th width="100px">动作</th><th
* width="100px">修改人</th><th width="100px">修改时间</th>
* </tr>
* <!-- 以 Table 方式书写修改历史 -->
* <tr>
* <td>0.0.0</td>
* <td>创建类</td>
* <td>刘镇</td>
* <td>2014年3月28日上午11:02:10</td>
* </tr>
* </table>
*/
public class DefaultAccountDataProvider implements IAccountDataProvider {
private static final Log _LOG = LogFactory.getLog(DefaultAccountDataProvider.class);
protected static Map<String, AccountDataMeta> __accountCaches = new ConcurrentHashMap<String, AccountDataMeta>();
private static ConcurrentHashMap<String, ReentrantLock> __LOCK_MAP = new ConcurrentHashMap<String, ReentrantLock>();
/**
* 构造器
*/
public DefaultAccountDataProvider() {
}
/* (non-Javadoc)
* @see net.ymate.platform.module.wechat.IAccountDataProvider#initialize()
*/
public void initialize() throws Exception {
}
/* (non-Javadoc)
* @see net.ymate.platform.module.wechat.IAccountDataProvider#destroy()
*/
public void destroy() throws Exception {
}
/* (non-Javadoc)
* @see net.ymate.platform.module.wechat.IAccountDataProvider#registerAccount(net.ymate.platform.module.wechat.AccountDataMeta)
*/
public void registerAccount(AccountDataMeta account) throws Exception {
__accountCaches.put(account.getAccountId(), account);
}
/* (non-Javadoc)
* @see net.ymate.platform.module.wechat.IAccountDataProvider#unregisterAccount(java.lang.String)
*/
public AccountDataMeta unregisterAccount(String accountId) {
return __accountCaches.remove(accountId);
}
/* (non-Javadoc)
* @see net.ymate.platform.module.wechat.IAccountDataProvider#getAccountIds()
*/
public Set<String> getAccountIds() {
return Collections.unmodifiableSet(__accountCaches.keySet());
}
/* (non-Javadoc)
* @see net.ymate.platform.module.wechat.IAccountDataProvider#checkAccountValid(java.lang.String)
*/
public boolean checkAccountValid(String accountId) {
return __accountCaches.containsKey(accountId);
}
/* (non-Javadoc)
* @see net.ymate.platform.module.wechat.IAccountDataProvider#getAccessToken(java.lang.String)
*/
public String getAccessToken(String accountId) throws Exception {
AccountDataMeta _accessToken = __accountCaches.get(accountId);
if (_accessToken == null || (System.currentTimeMillis() >= _accessToken.getAccessTokenExpires())) {
ReentrantLock _locker = __LOCK_MAP.get(accountId + "_accesstoken");
if (_locker == null) {
_locker = new ReentrantLock();
ReentrantLock _previous = __LOCK_MAP.putIfAbsent(accountId + "_accesstoken", _locker);
if (_previous != null) {
_locker = _previous;
}
}
_locker.lock();
//
try {
long _currentTime = System.currentTimeMillis();
if (_accessToken == null || (_currentTime >= _accessToken.getAccessTokenExpires())) {
// {"access_token":"ACCESS_TOKEN","expires_in":7200}
JSONObject _tokenJSON = null;
try {
_tokenJSON = WeChat.__doCheckJsonResult(HttpClientHelper.create().doGet(WX_API.WX_ACCESS_TOKEN.concat("&appid=") + getAppId(accountId) + "&secret=" + getAppSecret(accountId)));
} catch (Exception e) {
_LOG.debug("AccessToken Exception: ", e);
_tokenJSON = WeChat.__doCheckJsonResult(HttpClientHelper.create().doGet(WX_API.WX_ACCESS_TOKEN.concat("&appid=") + getAppId(accountId) + "&secret=" + getAppSecret(accountId)));
}
_LOG.debug("AccessToken Result: " + _tokenJSON.toJSONString());
_accessToken.setAccessToken(_tokenJSON.getString("access_token"));
_accessToken.setAccessTokenExpires(_currentTime + _tokenJSON.getIntValue("expires_in") * 1000);
//
_LOG.debug("AccessToken Has Expired, Get " + _accessToken.getAccountId() + " From Remote: " + _accessToken.getAccessToken());
}
} finally {
_locker.unlock();
}
} else {
_LOG.debug("Get " + _accessToken.getAccountId() + " AccessToken From Cache: " + _accessToken.getAccessToken());
}
return _accessToken.getAccessToken();
}
public String getJsApiTicket(String accountId) throws Exception {
AccountDataMeta _accessToken = __accountCaches.get(accountId);
if (_accessToken == null || (System.currentTimeMillis() >= _accessToken.getAccessTokenExpires())) {
ReentrantLock _locker = __LOCK_MAP.get(accountId + "_jsapitoken");
if (_locker == null) {
_locker = new ReentrantLock();
ReentrantLock _previous = __LOCK_MAP.putIfAbsent(accountId + "_jsapitoken", _locker);
if (_previous != null) {
_locker = _previous;
}
}
_locker.lock();
//
try {
long _currentTime = System.currentTimeMillis();
if (_accessToken == null || (_currentTime >= _accessToken.getJsAPiTicketExpires())) {
// { "errcode":0, "errmsg":"ok", "ticket":"bxLdikRXVbTPdHSM05e5u5sUoXNKd8-41ZO3MhKoyN5OfkWITDGgnr2fwJ0m9E8NYzWKVZvdVtaUgWvsdshFKA", "expires_in":7200 }
JSONObject _ticketJSON = null;
try {
_ticketJSON = WeChat.__doCheckJsonResult(HttpClientHelper.create().doGet(WX_API.OAUTH_JSAPI_TICKET.concat(getAccessToken(accountId))));
} catch (Exception e) {
_LOG.debug("JsApiToken Exception: ", e);
_ticketJSON = WeChat.__doCheckJsonResult(HttpClientHelper.create().doGet(WX_API.OAUTH_JSAPI_TICKET.concat(getAccessToken(accountId))));
}
_LOG.debug("JsApiToken Result: " + _ticketJSON.toJSONString());
_accessToken.setJsApiTicket(_ticketJSON.getString("ticket"));
_accessToken.setJsAPiTicketExpires(_currentTime + _ticketJSON.getIntValue("expires_in") * 1000);
//
_LOG.debug("JsApiToken Has Expired, Get " + _accessToken.getAccountId() + " From Remote: " + _accessToken.getJsApiTicket());
}
} finally {
_locker.unlock();
}
} else {
_LOG.debug("Get " + _accessToken.getAccountId() + " JsApiToken From Cache: " + _accessToken.getJsApiTicket());
}
return _accessToken.getJsApiTicket();
}
/* (non-Javadoc)
* @see net.ymate.platform.module.wechat.IAccountDataProvider#getAppId(java.lang.String)
*/
public String getAppId(String accountId) {
return __accountCaches.get(accountId).getAppId();
}
/* (non-Javadoc)
* @see net.ymate.platform.module.wechat.IAccountDataProvider#getAppSecret(java.lang.String)
*/
public String getAppSecret(String accountId) {
return __accountCaches.get(accountId).getAppSecret();
}
public String getAppAesKey(String accountId) {
return __accountCaches.get(accountId).getAppAesKey();
}
public String getLastAppAesKey(String accountId) {
return __accountCaches.get(accountId).getLastAppAesKey();
}
public int isMsgEncrypted(String accountId) {
return __accountCaches.get(accountId).getIsMsgEncrypted();
}
/* (non-Javadoc)
* @see net.ymate.platform.module.wechat.IAccountDataProvider#getRedirectURI(java.lang.String)
*/
public String getRedirectURI(String accountId) {
return __accountCaches.get(accountId).getRedirectUri();
}
public int getType(String accountId) {
return __accountCaches.get(accountId).getType();
}
public boolean isVerified(String accountId) {
return __accountCaches.get(accountId).getIsVerified() == 1;
}
public String getAttribute(String accountId, String attrKey) {
return __accountCaches.get(accountId).getAttribute(attrKey);
}
}