mirror of
https://github.com/pppscn/SmsForwarder
synced 2025-08-03 01:17:41 +08:00
优化:发送通道企业微信应用
支持http/socks5代理(应对IP白名单限制)
This commit is contained in:
parent
93fb0b657a
commit
6ea06ed5ef
@ -1,6 +1,8 @@
|
||||
package com.idormy.sms.forwarder.entity.setting
|
||||
|
||||
import com.idormy.sms.forwarder.R
|
||||
import java.io.Serializable
|
||||
import java.net.Proxy
|
||||
|
||||
data class WeworkAgentSetting(
|
||||
var corpID: String = "",
|
||||
@ -8,4 +10,19 @@ data class WeworkAgentSetting(
|
||||
val secret: String = "",
|
||||
val atAll: Boolean? = false,
|
||||
val toUser: String? = "@all",
|
||||
) : Serializable
|
||||
val proxyType: Proxy.Type = Proxy.Type.DIRECT,
|
||||
val proxyHost: String? = "",
|
||||
val proxyPort: String? = "",
|
||||
val proxyAuthenticator: Boolean? = false,
|
||||
val proxyUsername: String? = "",
|
||||
val proxyPassword: String? = "",
|
||||
) : Serializable {
|
||||
|
||||
fun getProxyTypeCheckId(): Int {
|
||||
return when (proxyType) {
|
||||
Proxy.Type.HTTP -> R.id.rb_proxyHttp
|
||||
Proxy.Type.SOCKS -> R.id.rb_proxySocks
|
||||
else -> R.id.rb_proxyNone
|
||||
}
|
||||
}
|
||||
}
|
@ -8,6 +8,7 @@ import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.CompoundButton
|
||||
import android.widget.RadioGroup
|
||||
import androidx.fragment.app.viewModels
|
||||
import com.google.gson.Gson
|
||||
import com.idormy.sms.forwarder.R
|
||||
@ -33,6 +34,7 @@ import io.reactivex.SingleObserver
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.disposables.Disposable
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import java.net.Proxy
|
||||
import java.util.*
|
||||
|
||||
@Page(name = "企业微信应用")
|
||||
@ -126,6 +128,12 @@ class WeworkAgentFragment : BaseFragment<FragmentSendersWeworkAgentBinding?>(),
|
||||
binding!!.etSecret.setText(settingVo.secret)
|
||||
binding!!.sbAtAll.isChecked = settingVo.atAll == true
|
||||
binding!!.etToUser.setText(settingVo.toUser)
|
||||
binding!!.rgProxyType.check(settingVo.getProxyTypeCheckId())
|
||||
binding!!.etProxyHost.setText(settingVo.proxyHost)
|
||||
binding!!.etProxyPort.setText(settingVo.proxyPort)
|
||||
binding!!.sbProxyAuthenticator.isChecked = settingVo.proxyAuthenticator == true
|
||||
binding!!.etProxyUsername.setText(settingVo.proxyUsername)
|
||||
binding!!.etProxyPassword.setText(settingVo.proxyPassword)
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -136,17 +144,36 @@ class WeworkAgentFragment : BaseFragment<FragmentSendersWeworkAgentBinding?>(),
|
||||
binding!!.btnDel.setOnClickListener(this)
|
||||
binding!!.btnSave.setOnClickListener(this)
|
||||
binding!!.sbAtAll.setOnCheckedChangeListener(this)
|
||||
binding!!.sbProxyAuthenticator.setOnCheckedChangeListener(this)
|
||||
binding!!.rgProxyType.setOnCheckedChangeListener { _: RadioGroup?, checkedId: Int ->
|
||||
if (checkedId == R.id.rb_proxyHttp || checkedId == R.id.rb_proxySocks) {
|
||||
binding!!.layoutProxyHost.visibility = View.VISIBLE
|
||||
binding!!.layoutProxyPort.visibility = View.VISIBLE
|
||||
binding!!.layoutProxyAuthenticator.visibility = if (binding!!.sbProxyAuthenticator.isChecked) View.VISIBLE else View.GONE
|
||||
} else {
|
||||
binding!!.layoutProxyHost.visibility = View.GONE
|
||||
binding!!.layoutProxyPort.visibility = View.GONE
|
||||
binding!!.layoutProxyAuthenticator.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
override fun onCheckedChanged(buttonView: CompoundButton?, isChecked: Boolean) {
|
||||
//注意:因为只有一个监听,暂不需要判断id
|
||||
if (isChecked) {
|
||||
binding!!.etToUser.setText("@all")
|
||||
binding!!.layoutToUser.visibility = View.GONE
|
||||
} else {
|
||||
binding!!.etToUser.setText("")
|
||||
binding!!.layoutToUser.visibility = View.VISIBLE
|
||||
override fun onCheckedChanged(buttonView: CompoundButton, isChecked: Boolean) {
|
||||
when (buttonView.id) {
|
||||
R.id.sb_at_all -> {
|
||||
if (isChecked) {
|
||||
binding!!.etToUser.setText("@all")
|
||||
binding!!.layoutToUser.visibility = View.GONE
|
||||
} else {
|
||||
binding!!.etToUser.setText("")
|
||||
binding!!.layoutToUser.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
R.id.sb_proxyAuthenticator -> {
|
||||
binding!!.layoutProxyAuthenticator.visibility = if (isChecked) View.VISIBLE else View.GONE
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
@ -225,7 +252,26 @@ class WeworkAgentFragment : BaseFragment<FragmentSendersWeworkAgentBinding?>(),
|
||||
val atAll = binding!!.sbAtAll.isChecked
|
||||
val toUser = binding!!.etToUser.text.toString().trim()
|
||||
|
||||
return WeworkAgentSetting(corpID, agentID, secret, atAll, toUser)
|
||||
val proxyType: Proxy.Type = when (binding!!.rgProxyType.checkedRadioButtonId) {
|
||||
R.id.rb_proxyHttp -> Proxy.Type.HTTP
|
||||
R.id.rb_proxySocks -> Proxy.Type.SOCKS
|
||||
else -> Proxy.Type.DIRECT
|
||||
}
|
||||
val proxyHost = binding!!.etProxyHost.text.toString().trim()
|
||||
val proxyPort = binding!!.etProxyPort.text.toString().trim()
|
||||
|
||||
if (proxyType != Proxy.Type.DIRECT && (TextUtils.isEmpty(proxyHost) || TextUtils.isEmpty(proxyPort))) {
|
||||
throw Exception(getString(R.string.invalid_host_or_port))
|
||||
}
|
||||
|
||||
val proxyAuthenticator = binding!!.sbProxyAuthenticator.isChecked
|
||||
val proxyUsername = binding!!.etProxyUsername.text.toString().trim()
|
||||
val proxyPassword = binding!!.etProxyPassword.text.toString().trim()
|
||||
if (proxyAuthenticator && TextUtils.isEmpty(proxyUsername) && TextUtils.isEmpty(proxyPassword)) {
|
||||
throw Exception(getString(R.string.invalid_username_or_password))
|
||||
}
|
||||
|
||||
return WeworkAgentSetting(corpID, agentID, secret, atAll, toUser, proxyType, proxyHost, proxyPort, proxyAuthenticator, proxyUsername, proxyPassword)
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
|
@ -17,6 +17,14 @@ import com.xuexiang.xhttp2.cache.model.CacheMode
|
||||
import com.xuexiang.xhttp2.callback.SimpleCallBack
|
||||
import com.xuexiang.xhttp2.exception.ApiException
|
||||
import com.xuexiang.xui.utils.ResUtils.getString
|
||||
import com.xuexiang.xutil.net.NetworkUtils
|
||||
import okhttp3.Credentials
|
||||
import okhttp3.Response
|
||||
import okhttp3.Route
|
||||
import java.net.Authenticator
|
||||
import java.net.InetSocketAddress
|
||||
import java.net.PasswordAuthentication
|
||||
import java.net.Proxy
|
||||
|
||||
@Suppress("PrivatePropertyName", "UNUSED_PARAMETER")
|
||||
class WeworkAgentUtils private constructor() {
|
||||
@ -42,8 +50,49 @@ class WeworkAgentUtils private constructor() {
|
||||
getTokenUrl += "&corpsecret=" + setting.secret
|
||||
Log.d(TAG, "getTokenUrl:$getTokenUrl")
|
||||
|
||||
XHttp.get(getTokenUrl)
|
||||
.keepJson(true)
|
||||
val request = XHttp.get(getTokenUrl)
|
||||
|
||||
//设置代理
|
||||
if ((setting.proxyType == Proxy.Type.HTTP || setting.proxyType == Proxy.Type.SOCKS)
|
||||
&& !TextUtils.isEmpty(setting.proxyHost) && !TextUtils.isEmpty(setting.proxyPort)
|
||||
) {
|
||||
//代理服务器的IP和端口号
|
||||
Log.d(TAG, "proxyHost = ${setting.proxyHost}, proxyPort = ${setting.proxyPort}")
|
||||
val proxyHost = if (NetworkUtils.isIP(setting.proxyHost)) setting.proxyHost else NetworkUtils.getDomainAddress(setting.proxyHost)
|
||||
if (!NetworkUtils.isIP(proxyHost)) {
|
||||
throw Exception("代理服务器主机名解析失败:proxyHost=$proxyHost")
|
||||
}
|
||||
val proxyPort: Int = setting.proxyPort?.toInt() ?: 7890
|
||||
|
||||
Log.d(TAG, "proxyHost = $proxyHost, proxyPort = $proxyPort")
|
||||
request.okproxy(Proxy(setting.proxyType, InetSocketAddress(proxyHost, proxyPort)))
|
||||
|
||||
//代理的鉴权账号密码
|
||||
if (setting.proxyAuthenticator == true
|
||||
&& (!TextUtils.isEmpty(setting.proxyUsername) || !TextUtils.isEmpty(setting.proxyPassword))
|
||||
) {
|
||||
Log.i(TAG, "proxyUsername = ${setting.proxyUsername}, proxyPassword = ${setting.proxyPassword}")
|
||||
|
||||
if (setting.proxyType == Proxy.Type.HTTP) {
|
||||
request.okproxyAuthenticator { _: Route?, response: Response ->
|
||||
//设置代理服务器账号密码
|
||||
val credential = Credentials.basic(setting.proxyUsername.toString(), setting.proxyPassword.toString())
|
||||
response.request().newBuilder()
|
||||
.header("Proxy-Authorization", credential)
|
||||
.build()
|
||||
}
|
||||
} else {
|
||||
Authenticator.setDefault(object : Authenticator() {
|
||||
override fun getPasswordAuthentication(): PasswordAuthentication {
|
||||
return PasswordAuthentication(setting.proxyUsername.toString(), setting.proxyPassword?.toCharArray())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
request.keepJson(true)
|
||||
.ignoreHttpsCert()
|
||||
.timeOut((SettingUtils.requestTimeout * 1000).toLong()) //超时时间10s
|
||||
.cacheMode(CacheMode.NO_CACHE)
|
||||
.timeStamp(true)
|
||||
@ -96,9 +145,50 @@ class WeworkAgentUtils private constructor() {
|
||||
val requestMsg: String = Gson().toJson(textMsgMap)
|
||||
Log.i(TAG, "requestMsg:$requestMsg")
|
||||
|
||||
XHttp.post(requestUrl)
|
||||
.upJson(requestMsg)
|
||||
val request = XHttp.post(requestUrl)
|
||||
|
||||
//设置代理
|
||||
if ((setting.proxyType == Proxy.Type.HTTP || setting.proxyType == Proxy.Type.SOCKS)
|
||||
&& !TextUtils.isEmpty(setting.proxyHost) && !TextUtils.isEmpty(setting.proxyPort)
|
||||
) {
|
||||
//代理服务器的IP和端口号
|
||||
Log.d(TAG, "proxyHost = ${setting.proxyHost}, proxyPort = ${setting.proxyPort}")
|
||||
val proxyHost = if (NetworkUtils.isIP(setting.proxyHost)) setting.proxyHost else NetworkUtils.getDomainAddress(setting.proxyHost)
|
||||
if (!NetworkUtils.isIP(proxyHost)) {
|
||||
throw Exception("代理服务器主机名解析失败:proxyHost=$proxyHost")
|
||||
}
|
||||
val proxyPort: Int = setting.proxyPort?.toInt() ?: 7890
|
||||
|
||||
Log.d(TAG, "proxyHost = $proxyHost, proxyPort = $proxyPort")
|
||||
request.okproxy(Proxy(setting.proxyType, InetSocketAddress(proxyHost, proxyPort)))
|
||||
|
||||
//代理的鉴权账号密码
|
||||
if (setting.proxyAuthenticator == true
|
||||
&& (!TextUtils.isEmpty(setting.proxyUsername) || !TextUtils.isEmpty(setting.proxyPassword))
|
||||
) {
|
||||
Log.i(TAG, "proxyUsername = ${setting.proxyUsername}, proxyPassword = ${setting.proxyPassword}")
|
||||
|
||||
if (setting.proxyType == Proxy.Type.HTTP) {
|
||||
request.okproxyAuthenticator { _: Route?, response: Response ->
|
||||
//设置代理服务器账号密码
|
||||
val credential = Credentials.basic(setting.proxyUsername.toString(), setting.proxyPassword.toString())
|
||||
response.request().newBuilder()
|
||||
.header("Proxy-Authorization", credential)
|
||||
.build()
|
||||
}
|
||||
} else {
|
||||
Authenticator.setDefault(object : Authenticator() {
|
||||
override fun getPasswordAuthentication(): PasswordAuthentication {
|
||||
return PasswordAuthentication(setting.proxyUsername.toString(), setting.proxyPassword?.toCharArray())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
request.upJson(requestMsg)
|
||||
.keepJson(true)
|
||||
.ignoreHttpsCert()
|
||||
.timeOut((SettingUtils.requestTimeout * 1000).toLong()) //超时时间10s
|
||||
.cacheMode(CacheMode.NO_CACHE)
|
||||
.retryCount(SettingUtils.requestRetryTimes) //超时重试的次数
|
||||
|
@ -185,6 +185,153 @@
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
style="@style/senderBarStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/proxy_settings"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<RadioGroup
|
||||
android:id="@+id/rg_proxyType"
|
||||
style="@style/rg_style"
|
||||
android:layout_marginStart="5dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/rb_proxyNone"
|
||||
style="@style/rg_rb_style"
|
||||
android:checked="true"
|
||||
android:text="@string/proxy_none" />
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/rb_proxyHttp"
|
||||
style="@style/rg_rb_style"
|
||||
android:text="@string/proxy_http" />
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/rb_proxySocks"
|
||||
style="@style/rg_rb_style"
|
||||
android:text="@string/proxy_socks" />
|
||||
|
||||
</RadioGroup>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/layoutProxyHost"
|
||||
style="@style/senderBarStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:visibility="gone">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/hostname" />
|
||||
|
||||
<com.xuexiang.xui.widget.edittext.materialedittext.MaterialEditText
|
||||
android:id="@+id/et_proxyHost"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="5dp"
|
||||
android:layout_weight="1"
|
||||
android:singleLine="true"
|
||||
app:met_clearButton="true" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/layoutProxyPort"
|
||||
style="@style/senderBarStyleWithSwitch"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:visibility="gone">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/port" />
|
||||
|
||||
<com.xuexiang.xui.widget.edittext.materialedittext.MaterialEditText
|
||||
android:id="@+id/et_proxyPort"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="5dp"
|
||||
android:layout_weight="1"
|
||||
android:digits="0123456789"
|
||||
android:inputType="number"
|
||||
android:maxLength="5"
|
||||
android:singleLine="true"
|
||||
app:met_clearButton="true" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="20dp"
|
||||
android:text="@string/proxy_authenticator" />
|
||||
|
||||
<com.xuexiang.xui.widget.button.switchbutton.SwitchButton
|
||||
android:id="@+id/sb_proxyAuthenticator"
|
||||
style="@style/SwitchButtonStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/layoutProxyAuthenticator"
|
||||
style="@style/senderBarStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:visibility="gone">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/username" />
|
||||
|
||||
<com.xuexiang.xui.widget.edittext.materialedittext.MaterialEditText
|
||||
android:id="@+id/et_proxyUsername"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="5dp"
|
||||
android:layout_weight="1"
|
||||
android:singleLine="true"
|
||||
app:met_clearButton="true" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="5dp"
|
||||
android:text="@string/password" />
|
||||
|
||||
<com.xuexiang.xui.widget.edittext.materialedittext.MaterialEditText
|
||||
android:id="@+id/et_proxyPassword"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="5dp"
|
||||
android:layout_weight="1"
|
||||
android:singleLine="true"
|
||||
app:met_passWordButton="true" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
Loading…
x
Reference in New Issue
Block a user