修复:多个企业微信应用 access_token 并存问题

pull/86/head
pppscn 3 years ago
parent f820b4eb94
commit 641c033b1f

@ -27,10 +27,6 @@ public class MyApplication extends Application {
public static List<PhoneUtils.SimInfo> SimInfoList = new ArrayList<>();
//是否关闭页面提示
public static boolean showHelpTip = true;
//企业微信
public static String QyWxAccessToken;
public static long QyWxAccessTokenExpiresIn = 0;
@Override
protected void attachBaseContext(Context base) {

@ -938,20 +938,23 @@ public class SenderActivity extends AppCompatActivity {
show.dismiss();
});
buttonQYWXAppTest.setOnClickListener(view -> {
String cropID = editTextQYWXAppCorpID.getText().toString().trim();
String agentID = editTextQYWXAppAgentID.getText().toString().trim();
String secret = editTextQYWXAppSecret.getText().toString().trim();
String toUser = editTextQYWXAppToUser.getText().toString().trim();
//Boolean atAll = switchQYWXAppAtAll.isChecked();
if (!toUser.isEmpty()) {
try {
SenderQyWxAppMsg.sendMsg(0, handler, cropID, agentID, secret, toUser, R.string.test_content + (new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())), true);
} catch (Exception e) {
Toast.makeText(SenderActivity.this, getString(R.string.failed_to_fwd) + e.getMessage(), Toast.LENGTH_LONG).show();
e.printStackTrace();
}
} else {
QYWXAppSettingVo QYWXAppSettingVoNew = new QYWXAppSettingVo(
editTextQYWXAppCorpID.getText().toString().trim(),
editTextQYWXAppAgentID.getText().toString().trim(),
editTextQYWXAppSecret.getText().toString().trim(),
editTextQYWXAppToUser.getText().toString().trim(),
switchQYWXAppAtAll.isChecked());
if (QYWXAppSettingVoNew.getToUser().isEmpty()) {
Toast.makeText(SenderActivity.this, R.string.invalid_at_mobiles, Toast.LENGTH_LONG).show();
return;
}
try {
SenderQyWxAppMsg.sendMsg(0, handler, senderModel, QYWXAppSettingVoNew, R.string.test_content + (new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())));
} catch (Exception e) {
Toast.makeText(SenderActivity.this, getString(R.string.failed_to_fwd) + e.getMessage(), Toast.LENGTH_LONG).show();
e.printStackTrace();
}
});
}

@ -11,6 +11,8 @@ public class QYWXAppSettingVo implements Serializable {
private String secret;
private String toUser;
private Boolean atAll;
private String accessToken;
private Long expiresIn;
public QYWXAppSettingVo() {
}
@ -23,4 +25,11 @@ public class QYWXAppSettingVo implements Serializable {
this.atAll = atAll;
}
public String getAccessToken() {
if (accessToken == null || accessToken.isEmpty() || expiresIn == null || System.currentTimeMillis() > expiresIn) {
return null;
}
return accessToken;
}
}

@ -193,7 +193,7 @@ public class SendUtil {
QYWXAppSettingVo qYWXAppSettingVo = JSON.parseObject(senderModel.getJsonSetting(), QYWXAppSettingVo.class);
if (qYWXAppSettingVo != null) {
try {
SenderQyWxAppMsg.sendMsg(logId, handError, qYWXAppSettingVo.getCorpID(), qYWXAppSettingVo.getAgentID(), qYWXAppSettingVo.getSecret(), qYWXAppSettingVo.getToUser(), smsVo.getSmsVoForSend(smsTemplate), false);
SenderQyWxAppMsg.sendMsg(logId, handError, senderModel, qYWXAppSettingVo, smsVo.getSmsVoForSend(smsTemplate));
} catch (Exception e) {
LogUtil.updateLog(logId, 0, e.getMessage());
Log.e(TAG, "senderSendMsg: qywx_app error " + e.getMessage());

@ -11,7 +11,8 @@ import androidx.annotation.NonNull;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.idormy.sms.forwarder.MyApplication;
import com.idormy.sms.forwarder.model.SenderModel;
import com.idormy.sms.forwarder.model.vo.QYWXAppSettingVo;
import com.idormy.sms.forwarder.utils.LogUtil;
import com.idormy.sms.forwarder.utils.SettingUtil;
@ -36,77 +37,125 @@ public class SenderQyWxAppMsg extends SenderBaseMsg {
static final String TAG = "SenderQyWxAppMsg";
public static void sendMsg(final long logId, final Handler handError, String corpID, String agentID, String secret, String toUser, String content, boolean forceRefresh) throws Exception {
Log.i(TAG, "sendMsg corpID:" + corpID + " agentID:" + agentID + " secret:" + secret + " toUser:" + toUser + " content:" + content + " forceRefresh:" + forceRefresh);
public static void sendMsg(final long logId, final Handler handError, final SenderModel senderModel, final QYWXAppSettingVo qYWXAppSettingVo, String content) throws Exception {
if (qYWXAppSettingVo == null) {
Toast(handError, TAG, "参数错误");
return;
}
String corpID = qYWXAppSettingVo.getCorpID();
String agentID = qYWXAppSettingVo.getAgentID();
String secret = qYWXAppSettingVo.getSecret();
String toUser = qYWXAppSettingVo.getToUser();
Boolean atAll = qYWXAppSettingVo.getAtAll();
Log.i(TAG, "sendMsg corpID:" + corpID + " agentID:" + agentID + " secret:" + secret + " toUser:" + toUser + " content:" + content);
if (corpID == null || corpID.isEmpty() || agentID == null || agentID.isEmpty() || secret == null || secret.isEmpty()) {
return;
}
//TODO:判断access_token是否失效
if (forceRefresh
|| MyApplication.QyWxAccessToken == null || MyApplication.QyWxAccessToken.isEmpty()
|| System.currentTimeMillis() > MyApplication.QyWxAccessTokenExpiresIn) {
String getTokenUrl = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?";
getTokenUrl += "corpid=" + corpID;
getTokenUrl += "&corpsecret=" + secret;
Log.d(TAG, "getTokenUrl" + getTokenUrl);
OkHttpClient client = new OkHttpClient();
final Request request = new Request.Builder().url(getTokenUrl).get().build();
Call call = client.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(@NonNull Call call, @NonNull final IOException e) {
LogUtil.updateLog(logId, 0, e.getMessage());
Log.d(TAG, "onFailure" + e.getMessage());
if (handError != null) {
Message msg = new Message();
msg.what = NOTIFY;
Bundle bundle = new Bundle();
bundle.putString("DATA", "获取access_token失败" + e.getMessage());
msg.setData(bundle);
handError.sendMessage(msg);
}
}
Observable
.create((ObservableEmitter<Object> emitter) -> {
Toast(handError, TAG, "开始请求接口...");
//TODO:获取有效access_token
String accessToken = qYWXAppSettingVo.getAccessToken();
if (accessToken == null || accessToken.isEmpty()) {
String getTokenUrl = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?";
getTokenUrl += "corpid=" + corpID;
getTokenUrl += "&corpsecret=" + secret;
Log.d(TAG, "getTokenUrl" + getTokenUrl);
OkHttpClient client = new OkHttpClient();
final Request request = new Request.Builder().url(getTokenUrl).get().build();
Call call = client.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(@NonNull Call call, @NonNull final IOException e) {
LogUtil.updateLog(logId, 0, e.getMessage());
qYWXAppSettingVo.setAccessToken("");
qYWXAppSettingVo.setExpiresIn(0L);
if (senderModel != null) {
senderModel.setJsonSetting(JSON.toJSONString(qYWXAppSettingVo));
SenderUtil.updateSender(senderModel);
}
Log.d(TAG, "onFailure" + e.getMessage());
if (handError != null) {
Message msg = new Message();
msg.what = NOTIFY;
Bundle bundle = new Bundle();
bundle.putString("DATA", "获取access_token失败" + e.getMessage());
msg.setData(bundle);
handError.sendMessage(msg);
emitter.onError(new RuntimeException("请求接口异常..."));
}
}
@Override
public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
final String json = Objects.requireNonNull(response.body()).string();
Log.d(TAG, "Code" + response.code() + " Response: " + json);
JSONObject jsonObject = JSON.parseObject(json);
int errcode = jsonObject.getInteger("errcode");
if (errcode == 0) {
MyApplication.QyWxAccessToken = jsonObject.getString("access_token");
MyApplication.QyWxAccessTokenExpiresIn = System.currentTimeMillis() + (jsonObject.getInteger("expires_in") - 120) * 1000L; //提前2分钟过期
Log.d(TAG, "access_token" + MyApplication.QyWxAccessToken);
Log.d(TAG, "expires_in" + MyApplication.QyWxAccessTokenExpiresIn);
sendTextMsg(logId, handError, agentID, toUser, content);
@Override
public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
final String json = Objects.requireNonNull(response.body()).string();
Log.d(TAG, "Code" + response.code() + " Response: " + json);
JSONObject jsonObject = JSON.parseObject(json);
int errcode = jsonObject.getInteger("errcode");
if (errcode == 0) {
String access_token = jsonObject.getString("access_token");
long expires_in = System.currentTimeMillis() + (jsonObject.getInteger("expires_in") - 120) * 1000L; //提前2分钟过期
Log.d(TAG, "access_token" + access_token);
Log.d(TAG, "expires_in" + expires_in);
qYWXAppSettingVo.setAccessToken(access_token);
qYWXAppSettingVo.setExpiresIn(expires_in);
if (senderModel != null) {
senderModel.setJsonSetting(JSON.toJSONString(qYWXAppSettingVo));
SenderUtil.updateSender(senderModel);
}
sendTextMsg(emitter, logId, handError, agentID, toUser, content, access_token);
} else {
String errmsg = jsonObject.getString("errmsg");
LogUtil.updateLog(logId, 0, errmsg);
Log.d(TAG, "onFailure" + errmsg);
if (handError != null) {
Message msg = new Message();
msg.what = NOTIFY;
Bundle bundle = new Bundle();
bundle.putString("DATA", "获取access_token失败" + errmsg);
msg.setData(bundle);
handError.sendMessage(msg);
}
emitter.onError(new RuntimeException("请求接口异常..."));
}
}
});
} else {
String errmsg = jsonObject.getString("errmsg");
LogUtil.updateLog(logId, 0, errmsg);
Log.d(TAG, "onFailure" + errmsg);
if (handError != null) {
Message msg = new Message();
msg.what = NOTIFY;
Bundle bundle = new Bundle();
bundle.putString("DATA", "获取access_token失败" + errmsg);
msg.setData(bundle);
handError.sendMessage(msg);
}
sendTextMsg(emitter, logId, handError, agentID, toUser, content, accessToken);
}
}
});
} else {
sendTextMsg(logId, handError, agentID, toUser, content);
}
}).retryWhen((Observable<Throwable> errorObservable) -> errorObservable
.zipWith(Observable.just(
SettingUtil.getRetryDelayTime(1),
SettingUtil.getRetryDelayTime(2),
SettingUtil.getRetryDelayTime(3),
SettingUtil.getRetryDelayTime(4),
SettingUtil.getRetryDelayTime(5)
), (Throwable e, Integer time) -> time)
.flatMap((Integer delay) -> {
Toast(handError, TAG, "请求接口异常," + delay + "秒后重试");
return Observable.timer(delay, TimeUnit.SECONDS);
}))
.subscribe(System.out::println);
}
//发送文本消息
public static void sendTextMsg(final long logId, final Handler handError, String agentID, String toUser, String content) {
public static void sendTextMsg(ObservableEmitter<Object> emitter, final long logId, final Handler handError, String agentID, String toUser, String content, String accessToken) {
Map textMsgMap = new HashMap();
textMsgMap.put("touser", toUser);
@ -117,60 +166,44 @@ public class SenderQyWxAppMsg extends SenderBaseMsg {
textText.put("content", content);
textMsgMap.put("text", textText);
final String requestUrl = "https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=" + MyApplication.QyWxAccessToken;
final String requestUrl = "https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=" + accessToken;
Log.i(TAG, "requestUrl:" + requestUrl);
final String requestMsg = JSON.toJSONString(textMsgMap);
Log.i(TAG, "requestMsg:" + requestMsg);
Observable
.create((ObservableEmitter<Object> emitter) -> {
Toast(handError, TAG, "开始请求接口...");
OkHttpClient client = new OkHttpClient();
RequestBody requestBody = RequestBody.create(MediaType.parse("application/json;charset=utf-8"), requestMsg);
final Request request = new Request.Builder()
.url(requestUrl)
.addHeader("Content-Type", "application/json; charset=utf-8")
.post(requestBody)
.build();
Call call = client.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(@NonNull Call call, @NonNull final IOException e) {
LogUtil.updateLog(logId, 0, e.getMessage());
Toast(handError, TAG, "发送失败:" + e.getMessage());
emitter.onError(new RuntimeException("请求接口异常..."));
}
@Override
public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
final String responseStr = Objects.requireNonNull(response.body()).string();
Log.d(TAG, "Response" + response.code() + "" + responseStr);
Toast(handError, TAG, "发送状态:" + responseStr);
//TODO:粗略解析是否发送成功
if (responseStr.contains("\"errcode\":0")) {
LogUtil.updateLog(logId, 1, responseStr);
} else {
LogUtil.updateLog(logId, 0, responseStr);
}
}
});
OkHttpClient client = new OkHttpClient();
RequestBody requestBody = RequestBody.create(MediaType.parse("application/json;charset=utf-8"), requestMsg);
final Request request = new Request.Builder()
.url(requestUrl)
.addHeader("Content-Type", "application/json; charset=utf-8")
.post(requestBody)
.build();
Call call = client.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(@NonNull Call call, @NonNull final IOException e) {
LogUtil.updateLog(logId, 0, e.getMessage());
Toast(handError, TAG, "发送失败:" + e.getMessage());
emitter.onError(new RuntimeException("请求接口异常..."));
}
@Override
public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
final String responseStr = Objects.requireNonNull(response.body()).string();
Log.d(TAG, "Response" + response.code() + "" + responseStr);
Toast(handError, TAG, "发送状态:" + responseStr);
//TODO:粗略解析是否发送成功
if (responseStr.contains("\"errcode\":0")) {
LogUtil.updateLog(logId, 1, responseStr);
} else {
LogUtil.updateLog(logId, 0, responseStr);
}
}
});
}).retryWhen((Observable<Throwable> errorObservable) -> errorObservable
.zipWith(Observable.just(
SettingUtil.getRetryDelayTime(1),
SettingUtil.getRetryDelayTime(2),
SettingUtil.getRetryDelayTime(3),
SettingUtil.getRetryDelayTime(4),
SettingUtil.getRetryDelayTime(5)
), (Throwable e, Integer time) -> time)
.flatMap((Integer delay) -> {
Toast(handError, TAG, "请求接口异常," + delay + "秒后重试");
return Observable.timer(delay, TimeUnit.SECONDS);
}))
.subscribe(System.out::println);
}
}

@ -17,7 +17,7 @@
android:orientation="horizontal">
<TextView
android:layout_width="60dp"
android:layout_width="80dp"
android:layout_height="wrap_content"
android:gravity="end"
android:text="@string/set_name"
@ -42,7 +42,7 @@
android:orientation="horizontal">
<TextView
android:layout_width="60dp"
android:layout_width="80dp"
android:layout_height="wrap_content"
android:gravity="end"
android:text="@string/Corp_ID"
@ -67,7 +67,7 @@
android:orientation="horizontal">
<TextView
android:layout_width="60dp"
android:layout_width="80dp"
android:layout_height="wrap_content"
android:gravity="end"
android:text="@string/Agent_ID"
@ -93,7 +93,7 @@
android:orientation="horizontal">
<TextView
android:layout_width="60dp"
android:layout_width="80dp"
android:layout_height="wrap_content"
android:gravity="end"
android:text="@string/App_Secret"
@ -118,7 +118,7 @@
android:orientation="horizontal">
<TextView
android:layout_width="60dp"
android:layout_width="80dp"
android:layout_height="wrap_content"
android:gravity="end"
android:text="@string/is_at_all"
@ -128,7 +128,7 @@
android:id="@+id/switchQYWXAppAtAll"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:checked="false"
android:checked="true"
tools:ignore="UseSwitchCompatOrMaterialXml" />
</LinearLayout>
@ -136,7 +136,8 @@
android:id="@+id/linearLayoutQYWXAppToUser"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
android:orientation="vertical"
android:visibility="gone">
<LinearLayout
android:layout_width="match_parent"
@ -146,7 +147,7 @@
android:orientation="horizontal">
<TextView
android:layout_width="60dp"
android:layout_width="80dp"
android:layout_height="wrap_content"
android:gravity="end"
android:text="@string/specified_member"
@ -159,7 +160,7 @@
android:layout_marginStart="5dp"
android:autofillHints=""
android:inputType="text"
android:text=""
android:text="@string/at_all"
tools:ignore="LabelFor" />
</LinearLayout>

@ -140,6 +140,7 @@
<string name="App_Secret">App Secret</string>
<string name="is_at_all">Is at all</string>
<string name="specified_member">Specified Member</string>
<string name="at_all"><![CDATA[@all]]></string>
<string name="specified_member_tips">TipSpecify members receive messages, member ID list (multiple recipients with \'|\' space, maximum 1000)</string>
<string name="QYWXGroupRobotWebHook">WebHook, e.g. https://qyapi.weixin.qq.com/cgixx?key=xxx</string>
<string name="ServerChanSendKey">ServerChan\'s SendKey</string>

@ -135,11 +135,12 @@
<string name="email_title">邮件主题</string>
<string name="feishu_webhook">Webhook 地址</string>
<string name="feishu_secret">加签 Secret (没有可不填)</string>
<string name="Corp_ID">Corp ID</string>
<string name="Agent_ID">Agent ID</string>
<string name="App_Secret">App Secret</string>
<string name="is_at_all">是否@所有人</string>
<string name="Corp_ID">企业ID</string>
<string name="Agent_ID">应用AgentId</string>
<string name="App_Secret">应用Secret</string>
<string name="is_at_all">是否@all</string>
<string name="specified_member">指定成员</string>
<string name="at_all"><![CDATA[@all]]></string>
<string name="specified_member_tips">Tip指定接收消息的成员成员ID列表多个接收者用|分隔最多支持1000个</string>
<string name="QYWXGroupRobotWebHook">设置WebHook地址:示例https://qyapi.weixin.qq.com/cgixx?key=xxx</string>
<string name="ServerChanSendKey">设置Server酱·Turbo版的SendKey</string>

Loading…
Cancel
Save