重新建库,开源大部分代码,脱敏处理
@@ -0,0 +1,19 @@
|
||||
*.iml
|
||||
.gradle
|
||||
/local.properties
|
||||
/.idea/caches
|
||||
/.idea/libraries
|
||||
/.idea/modules.xml
|
||||
/.idea/workspace.xml
|
||||
/.idea/navEditor.xml
|
||||
/.idea/assetWizardSettings.xml
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
||||
.externalNativeBuild
|
||||
.cxx
|
||||
local.properties
|
||||
/app/release/
|
||||
.idea
|
||||
/.idea/
|
||||
/app/src/main/jniLibs/arm64-v8a/libJniQrCodeSign.so
|
||||
@@ -0,0 +1 @@
|
||||
/build
|
||||
@@ -0,0 +1,63 @@
|
||||
plugins {
|
||||
alias(libs.plugins.android.application)
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "cn.nahco3awa.naouc"
|
||||
compileSdk = 36
|
||||
|
||||
defaultConfig {
|
||||
applicationId = "cn.nahco3awa.naouc"
|
||||
minSdk = 26
|
||||
targetSdk = 36
|
||||
versionCode = 1
|
||||
versionName = "0.1.5"
|
||||
|
||||
ndk {
|
||||
abiFilters.add("arm64-v8a")
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
isMinifyEnabled = false
|
||||
proguardFiles(
|
||||
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||
"proguard-rules.pro"
|
||||
)
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_11
|
||||
targetCompatibility = JavaVersion.VERSION_11
|
||||
}
|
||||
buildFeatures {
|
||||
viewBinding = true
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
getByName("main") {
|
||||
jniLibs.srcDirs("src/main/jniLibs")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
dependencies {
|
||||
implementation(libs.gson)
|
||||
implementation(libs.okhttp)
|
||||
implementation(libs.appcompat)
|
||||
implementation(libs.material)
|
||||
implementation(libs.constraintlayout)
|
||||
implementation(libs.lifecycle.livedata.ktx)
|
||||
implementation(libs.lifecycle.viewmodel.ktx)
|
||||
implementation(libs.navigation.fragment)
|
||||
implementation(libs.navigation.ui)
|
||||
implementation(libs.activity)
|
||||
implementation(libs.zxing.android.embedded)
|
||||
implementation(libs.recyclerview)
|
||||
testImplementation(libs.junit)
|
||||
androidTestImplementation(libs.ext.junit)
|
||||
androidTestImplementation(libs.espresso.core)
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
@@ -0,0 +1,45 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||
android:fullBackupContent="@xml/backup_rules"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:networkSecurityConfig="@xml/network_security_config"
|
||||
android:theme="@style/Theme.NaOUC">
|
||||
<activity
|
||||
android:name=".ui.ouc.activity.OucWaterActivity"
|
||||
android:exported="false"
|
||||
android:label="无卡取水" />
|
||||
<activity
|
||||
android:name=".ui.ouc.activity.OucNetActivity"
|
||||
android:exported="false"
|
||||
android:label="校园网账号管理" />
|
||||
<activity
|
||||
android:name=".ui.ouc.activity.OucBalanceActivity"
|
||||
android:exported="false"
|
||||
android:label="我的余额" />
|
||||
<activity
|
||||
android:name=".ui.ouc.activity.OucLoginMainActivity"
|
||||
android:label="登录到 OUC" />
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:exported="true"
|
||||
android:label="NaOUC">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -0,0 +1,43 @@
|
||||
package cn.nahco3awa.naouc;
|
||||
|
||||
import static android.widget.Toast.LENGTH_SHORT;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.navigation.NavController;
|
||||
import androidx.navigation.Navigation;
|
||||
import androidx.navigation.ui.AppBarConfiguration;
|
||||
import androidx.navigation.ui.NavigationUI;
|
||||
|
||||
import com.google.android.material.bottomnavigation.BottomNavigationView;
|
||||
|
||||
import cn.nahco3awa.naouc.databinding.ActivityMainBinding;
|
||||
|
||||
public class MainActivity extends AppCompatActivity {
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
MyCrashHandler crashHandler = MyCrashHandler.newInstance();
|
||||
crashHandler.init(this);
|
||||
Thread.setDefaultUncaughtExceptionHandler(crashHandler);
|
||||
|
||||
ActivityMainBinding binding = ActivityMainBinding.inflate(getLayoutInflater());
|
||||
setContentView(binding.getRoot());
|
||||
|
||||
BottomNavigationView navView = findViewById(R.id.nav_view);
|
||||
AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(
|
||||
R.id.navigation_ouc, R.id.navigation_weouc)
|
||||
.build();
|
||||
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_activity_main);
|
||||
NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
|
||||
NavigationUI.setupWithNavController(binding.navView, navController);
|
||||
}
|
||||
|
||||
private void sorryNo() {
|
||||
Toast.makeText(this, "× 抱歉,不行。", LENGTH_SHORT).show();
|
||||
finish();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
package cn.nahco3awa.naouc;
|
||||
|
||||
import static android.widget.Toast.LENGTH_LONG;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Environment;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
|
||||
public class MyCrashHandler implements Thread.UncaughtExceptionHandler {
|
||||
private Thread.UncaughtExceptionHandler mDefaultHandler;
|
||||
private Context mcontext;
|
||||
private static MyCrashHandler myCrashHandler;
|
||||
|
||||
private MyCrashHandler() {}
|
||||
|
||||
public static synchronized MyCrashHandler newInstance() {
|
||||
if (myCrashHandler == null)
|
||||
myCrashHandler = new MyCrashHandler();
|
||||
return myCrashHandler;
|
||||
}
|
||||
|
||||
public void init(Context context) {
|
||||
mcontext = context;
|
||||
mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
|
||||
Thread.setDefaultUncaughtExceptionHandler(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uncaughtException(@NonNull Thread t, Throwable e) {
|
||||
new AlertDialog.Builder(mcontext)
|
||||
.setTitle("未捕获的异常!")
|
||||
.setMessage(e.getMessage())
|
||||
.show();
|
||||
Toast.makeText(mcontext, e.getMessage(), LENGTH_LONG).show();
|
||||
if (!handleExample(e) && mDefaultHandler != null) {
|
||||
mDefaultHandler.uncaughtException(t, e);
|
||||
} else {
|
||||
try {
|
||||
Thread.sleep(3000);
|
||||
} catch (InterruptedException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
android.os.Process.killProcess(android.os.Process.myPid());
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean handleExample(Throwable ex) {
|
||||
if(ex == null)
|
||||
return false;
|
||||
saveCrashInfoToFile(ex);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void saveCrashInfoToFile(Throwable ex) {
|
||||
Writer writer = new StringWriter();
|
||||
PrintWriter printWriter = new PrintWriter(writer);
|
||||
ex.printStackTrace(printWriter);
|
||||
Throwable exCause = ex.getCause();
|
||||
while (exCause != null) {
|
||||
exCause.printStackTrace(printWriter);
|
||||
exCause = exCause.getCause();
|
||||
}
|
||||
printWriter.close();
|
||||
|
||||
long timeMillis = System.currentTimeMillis();
|
||||
String fileName = "crash-" + timeMillis + ".log";
|
||||
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
|
||||
String path = "/storage/emulated/0/crash_logInfo/";
|
||||
File fl = new File(path);
|
||||
if (!fl.exists()) {
|
||||
boolean ignored = fl.mkdirs();
|
||||
}
|
||||
try {
|
||||
FileOutputStream fileOutputStream = new FileOutputStream(path + fileName);
|
||||
fileOutputStream.write(writer.toString().getBytes());
|
||||
fileOutputStream.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,368 @@
|
||||
package cn.nahco3awa.naouc.network.ouc;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import cn.nahco3awa.naouc.network.ouc.request.AccountPayAliPayOUCRequest;
|
||||
import cn.nahco3awa.naouc.network.ouc.request.GetBarCodePayOUCRequest;
|
||||
import cn.nahco3awa.naouc.network.ouc.request.GetCardAccInfoOUCRequest;
|
||||
import cn.nahco3awa.naouc.network.ouc.request.GetInfoByTokenOUCRequest;
|
||||
import cn.nahco3awa.naouc.network.ouc.request.GetMyBillOUCRequest;
|
||||
import cn.nahco3awa.naouc.network.ouc.request.GetPhotoBySnoOUCRequest;
|
||||
import cn.nahco3awa.naouc.network.ouc.request.GetRsaOUCRequest;
|
||||
import cn.nahco3awa.naouc.network.ouc.request.GetValidateCodeOUCRequest;
|
||||
import cn.nahco3awa.naouc.network.ouc.request.LoginOUCRequest;
|
||||
import cn.nahco3awa.naouc.network.ouc.request.NetGdcOUCRequest;
|
||||
import cn.nahco3awa.naouc.network.ouc.request.OUCRequest;
|
||||
import cn.nahco3awa.naouc.network.ouc.request.TsmOUCRequest;
|
||||
import cn.nahco3awa.naouc.network.ouc.request.WaterApiAccUseHzWatchRequest;
|
||||
import cn.nahco3awa.naouc.network.ouc.request.WaterApiBookCodeCancelRequest;
|
||||
import cn.nahco3awa.naouc.network.ouc.request.WaterApiBookCodeRequest;
|
||||
import cn.nahco3awa.naouc.network.ouc.response.AccountPayOUCResponse;
|
||||
import cn.nahco3awa.naouc.network.ouc.response.GetBarCodePayOUCResponse;
|
||||
import cn.nahco3awa.naouc.network.ouc.response.GetCardAccInfoOUCResponse;
|
||||
import cn.nahco3awa.naouc.network.ouc.response.GetInfoByTokenOUCResponse;
|
||||
import cn.nahco3awa.naouc.network.ouc.response.GetMyBillOUCResponse;
|
||||
import cn.nahco3awa.naouc.network.ouc.response.GetPhotoBySnoOUCResponse;
|
||||
import cn.nahco3awa.naouc.network.ouc.response.GetRsaKeyOUCResponse;
|
||||
import cn.nahco3awa.naouc.network.ouc.response.GetValidateCodeOUCResponse;
|
||||
import cn.nahco3awa.naouc.network.ouc.response.LoginOUCResponse;
|
||||
import cn.nahco3awa.naouc.network.ouc.response.NetGdcOUCResponse;
|
||||
import cn.nahco3awa.naouc.network.ouc.response.OUCCallback;
|
||||
import cn.nahco3awa.naouc.network.ouc.response.TsmOUCResponse;
|
||||
import cn.nahco3awa.naouc.network.ouc.response.WaterApiAccUseHzWatchResponse;
|
||||
import cn.nahco3awa.naouc.network.ouc.response.WaterApiBookCodeCancelResponse;
|
||||
import cn.nahco3awa.naouc.network.ouc.response.WaterApiBookCodeResponse;
|
||||
import okhttp3.Call;
|
||||
import okhttp3.Callback;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
|
||||
public class OUCRequestSender {
|
||||
public static OUCRequestSender INSTANCE = null;
|
||||
private String sessionId;
|
||||
private final String imeiTicket;
|
||||
private String sourceTypeTicket;
|
||||
private String jSessionId;
|
||||
private final OkHttpClient httpClient;
|
||||
private OUCRequestSender(String imeiTicket) {
|
||||
this.imeiTicket = imeiTicket;
|
||||
this.sourceTypeTicket = "0";
|
||||
this.sessionId = "";
|
||||
this.jSessionId = "";
|
||||
httpClient = new OkHttpClient();
|
||||
}
|
||||
|
||||
public static void init(String imeiTicket) {
|
||||
INSTANCE = new OUCRequestSender(imeiTicket);
|
||||
}
|
||||
|
||||
public static OUCRequestSender getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
public String getImeiTicket() {
|
||||
return imeiTicket;
|
||||
}
|
||||
|
||||
public String getSessionId() {
|
||||
return sessionId;
|
||||
}
|
||||
|
||||
public String getSourceTypeTicket() {
|
||||
return sourceTypeTicket;
|
||||
}
|
||||
|
||||
public Request.Builder setAspHeaders(Request.Builder request) {
|
||||
return request.header("Cookie", "JSESSIONID=" + jSessionId + "; ASP.NET_SessionId=" + getSessionId() + "; imeiticket=" + getImeiTicket() + "; sourcetypeticket=" + getSourceTypeTicket())
|
||||
.header("X-Requested-With", "XMLHttpRequest")
|
||||
.header("Origin", "https://vcard.ouc.edu.cn")
|
||||
.header("Sec-Fetch-Site", "same-origin")
|
||||
.header("Sec-Fetch-Mode", "cors")
|
||||
.header("Sec-Fetch-Dest", "empty")
|
||||
.header("Referer", "https://vcard.ouc.edu.cn//Phone/Login")
|
||||
.header("User-Agent", "Mozilla/5.0 (Linux; Android 12; ALA-AN70 Build/HONORALA-AN70; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/99.0.4844.88 Mobile Safari/537.36");
|
||||
}
|
||||
|
||||
public void waterApiBookCodeCancel(WaterApiBookCodeCancelRequest request, OUCCallback<WaterApiBookCodeCancelResponse> callback) {
|
||||
sendRequest(request, new Callback() {
|
||||
@Override
|
||||
public void onFailure(@NonNull Call call, @NonNull IOException e) {
|
||||
callback.onFailure(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(@NonNull Call call, @NonNull Response response) {
|
||||
try {
|
||||
callback.onSuccess(new WaterApiBookCodeCancelResponse(response));
|
||||
} catch (Exception e) {
|
||||
callback.onFailure(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void waterApiBookCode(WaterApiBookCodeRequest request, OUCCallback<WaterApiBookCodeResponse> callback) {
|
||||
sendRequest(request, new Callback() {
|
||||
@Override
|
||||
public void onFailure(@NonNull Call call, @NonNull IOException e) {
|
||||
callback.onFailure(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(@NonNull Call call, @NonNull Response response) {
|
||||
try {
|
||||
callback.onSuccess(new WaterApiBookCodeResponse(response));
|
||||
} catch (Exception e) {
|
||||
callback.onFailure(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void waterApiAccUseHzWatch(WaterApiAccUseHzWatchRequest request, OUCCallback<WaterApiAccUseHzWatchResponse> callback) {
|
||||
sendRequest(request, new Callback() {
|
||||
@Override
|
||||
public void onFailure(@NonNull Call call, @NonNull IOException e) {
|
||||
callback.onFailure(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(@NonNull Call call, @NonNull Response response) {
|
||||
try {
|
||||
callback.onSuccess(new WaterApiAccUseHzWatchResponse(response));
|
||||
} catch (Exception e) {
|
||||
callback.onFailure(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void netGdc(NetGdcOUCRequest request, OUCCallback<NetGdcOUCResponse> callback) {
|
||||
sendRequest(request, new Callback() {
|
||||
@Override
|
||||
public void onFailure(@NonNull Call call, @NonNull IOException e) {
|
||||
callback.onFailure(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(@NonNull Call call, @NonNull Response response) {
|
||||
try {
|
||||
callback.onSuccess(new NetGdcOUCResponse(response));
|
||||
} catch (Exception e) {
|
||||
callback.onFailure(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void tsm(TsmOUCRequest request, OUCCallback<TsmOUCResponse> callback) {
|
||||
sendRequest(request, new Callback() {
|
||||
@Override
|
||||
public void onFailure(@NonNull Call call, @NonNull IOException e) {
|
||||
callback.onFailure(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(@NonNull Call call, @NonNull Response response) {
|
||||
try {
|
||||
callback.onSuccess(new TsmOUCResponse(response));
|
||||
} catch (Exception e) {
|
||||
callback.onFailure(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void getMyBill(GetMyBillOUCRequest request, OUCCallback<GetMyBillOUCResponse> callback) {
|
||||
sendRequest(request, new Callback() {
|
||||
@Override
|
||||
public void onFailure(@NonNull Call call, @NonNull IOException e) {
|
||||
callback.onFailure(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(@NonNull Call call, @NonNull Response response) {
|
||||
try {
|
||||
callback.onSuccess(new GetMyBillOUCResponse(response));
|
||||
} catch (Exception e) {
|
||||
callback.onFailure(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void accountPayAlipay(AccountPayAliPayOUCRequest request, OUCCallback<AccountPayOUCResponse> callback) {
|
||||
sendRequest(request, new Callback() {
|
||||
@Override
|
||||
public void onFailure(@NonNull Call call, @NonNull IOException e) {
|
||||
callback.onFailure(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(@NonNull Call call, @NonNull Response response) {
|
||||
try {
|
||||
callback.onSuccess(new AccountPayOUCResponse(response));
|
||||
} catch (Exception e) {
|
||||
callback.onFailure(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void getCardAccInfo(GetCardAccInfoOUCRequest request, OUCCallback<GetCardAccInfoOUCResponse> callback) {
|
||||
sendRequest(request, new Callback() {
|
||||
@Override
|
||||
public void onFailure(@NonNull Call call, @NonNull IOException e) {
|
||||
callback.onFailure(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
|
||||
callback.onSuccess(new GetCardAccInfoOUCResponse(response));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void getBarCodePay(GetBarCodePayOUCRequest request, OUCCallback<GetBarCodePayOUCResponse> callback) {
|
||||
sendRequest(request, new Callback() {
|
||||
@Override
|
||||
public void onFailure(@NonNull Call call, @NonNull IOException e) {
|
||||
callback.onFailure(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(@NonNull Call call, @NonNull Response response) {
|
||||
GetBarCodePayOUCResponse response1;
|
||||
try {
|
||||
response1 = new GetBarCodePayOUCResponse(response);
|
||||
callback.onSuccess(response1);
|
||||
} catch (Exception e) {
|
||||
callback.onFailure(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void getPhotoBySno(GetPhotoBySnoOUCRequest request, OUCCallback<GetPhotoBySnoOUCResponse> callback) {
|
||||
sendRequest(request, new Callback() {
|
||||
@Override
|
||||
public void onFailure(@NonNull Call call, @NonNull IOException e) {
|
||||
callback.onFailure(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(@NonNull Call call, @NonNull Response response) {
|
||||
callback.onSuccess(new GetPhotoBySnoOUCResponse(response));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void getInfoByToken(GetInfoByTokenOUCRequest request, OUCCallback<GetInfoByTokenOUCResponse> callback) {
|
||||
sendRequest(request, new Callback() {
|
||||
@Override
|
||||
public void onFailure(@NonNull Call call, @NonNull IOException e) {
|
||||
callback.onFailure(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(@NonNull Call call, @NonNull Response response) {
|
||||
try {
|
||||
callback.onSuccess(new GetInfoByTokenOUCResponse(response));
|
||||
} catch (Exception e) {
|
||||
callback.onFailure(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void getRsaKey(GetRsaOUCRequest request, OUCCallback<GetRsaKeyOUCResponse> callback) {
|
||||
sendRequest(request, new Callback() {
|
||||
@Override
|
||||
public void onFailure(@NonNull Call call, @NonNull IOException e) {
|
||||
callback.onFailure(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(@NonNull Call call, @NonNull Response response) {
|
||||
callback.onSuccess(new GetRsaKeyOUCResponse(response));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void login(LoginOUCRequest request, OUCCallback<LoginOUCResponse> callback) {
|
||||
sendRequest(request, new Callback() {
|
||||
@Override
|
||||
public void onFailure(@NonNull Call call, @NonNull IOException e) {
|
||||
callback.onFailure(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(@NonNull Call call, @NonNull Response response) {
|
||||
try {
|
||||
callback.onSuccess(new LoginOUCResponse(response));
|
||||
} catch (Exception e) {
|
||||
callback.onFailure(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void getValidateCode(GetValidateCodeOUCRequest request, OUCCallback<GetValidateCodeOUCResponse> callback) {
|
||||
sendRequest(request, new Callback() {
|
||||
@Override
|
||||
public void onFailure(@NonNull Call call, @NonNull IOException e) {
|
||||
callback.onFailure(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(@NonNull Call call, @NonNull Response response) {
|
||||
callback.onSuccess(new GetValidateCodeOUCResponse(response));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void sendRequest(OUCRequest request, Callback callback) {
|
||||
Request req = request.makeRequest(this);
|
||||
Call call = httpClient.newCall(req);
|
||||
call.enqueue(new Callback() {
|
||||
@Override
|
||||
public void onFailure(@NonNull Call call, @NonNull IOException e) {
|
||||
callback.onFailure(call, e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
|
||||
if (response.isSuccessful()) {
|
||||
String setCookie = response.header("Set-Cookie");
|
||||
if (setCookie != null) {
|
||||
for (String cookie : setCookie.split(";")) {
|
||||
String[] kv = cookie.split("=");
|
||||
if (kv[0].equals("ASP.NET_SessionId")) {
|
||||
OUCRequestSender.this.sessionId = kv[1];
|
||||
}
|
||||
if (kv[0].equals("JSESSIONID")) {
|
||||
OUCRequestSender.this.jSessionId = kv[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
callback.onResponse(call, response);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public String getjSessionId() {
|
||||
return jSessionId;
|
||||
}
|
||||
|
||||
public void setSessionId(String sessionId) {
|
||||
this.sessionId = sessionId;
|
||||
}
|
||||
|
||||
public void setSourceTypeTicket(String sourceTypeTicket) {
|
||||
this.sourceTypeTicket = sourceTypeTicket;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package cn.nahco3awa.naouc.network.ouc.request;
|
||||
|
||||
import cn.nahco3awa.naouc.network.ouc.OUCRequestSender;
|
||||
import okhttp3.FormBody;
|
||||
import okhttp3.Request;
|
||||
|
||||
public class AccountPayAliPayOUCRequest implements OUCRequest {
|
||||
public static final String URL = "https://vcard.ouc.edu.cn/User/Account_Pay";
|
||||
private final String account;
|
||||
private final String tranamt;
|
||||
|
||||
public AccountPayAliPayOUCRequest(String account, String tranamt) {
|
||||
this.account = account;
|
||||
this.tranamt = tranamt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Request makeRequest(OUCRequestSender sender) {
|
||||
return sender.setAspHeaders(new Request.Builder()
|
||||
.url(URL)
|
||||
.post(new FormBody.Builder()
|
||||
.addEncoded("account", account)
|
||||
.addEncoded("acctype", "001")
|
||||
.addEncoded("tranamt", tranamt)
|
||||
.addEncoded("objtype", "own")
|
||||
.addEncoded("paytype", "alipay")
|
||||
.addEncoded("client_type", "wap")
|
||||
.addEncoded("paymethod", "4")
|
||||
.addEncoded("iacctype", "acc")
|
||||
.addEncoded("iswap", "0")
|
||||
.addEncoded("json", "true")
|
||||
.build())).build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
package cn.nahco3awa.naouc.network.ouc.request;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
|
||||
import cn.nahco3awa.naouc.network.ouc.OUCRequestSender;
|
||||
import cn.nahco3awa.naouc.util.QrCodeSign;
|
||||
import cn.nahco3awa.naouc.util.RSASign;
|
||||
import cn.nahco3awa.naouc.util.SignUtils;
|
||||
import okhttp3.FormBody;
|
||||
import okhttp3.Request;
|
||||
|
||||
public class GetBarCodePayOUCRequest implements OUCRequest {
|
||||
public static final String URL = "https://vcard.ouc.edu.cn:20085/PhonePay/MobilePayCommon";
|
||||
private final String account;
|
||||
private final String cardId;
|
||||
private final String imei;
|
||||
private final String sourceType;
|
||||
|
||||
public GetBarCodePayOUCRequest(String account, String cardId, String imei, String sourceType) {
|
||||
this.account = account;
|
||||
this.cardId = cardId;
|
||||
this.imei = imei;
|
||||
this.sourceType = sourceType;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
method
|
||||
timestamp
|
||||
v
|
||||
registerid
|
||||
request
|
||||
sign
|
||||
// md5string
|
||||
clientType
|
||||
versionName
|
||||
versionCode
|
||||
sourcetype
|
||||
imei
|
||||
MD5string
|
||||
*/
|
||||
public static final String UTF_8 = "UTF-8";
|
||||
@Override
|
||||
public Request makeRequest(OUCRequestSender sender) {
|
||||
HashMap<String, String> map = new HashMap<>();
|
||||
|
||||
JsonObject jsonObject = new JsonObject();
|
||||
JsonObject jsonObject2 = new JsonObject();
|
||||
|
||||
jsonObject.addProperty("account", account);
|
||||
jsonObject.addProperty("acctype", "001");
|
||||
jsonObject.addProperty("sourcetype", sourceType);
|
||||
jsonObject.addProperty("flag", "00");
|
||||
jsonObject.addProperty("cardid", cardId);
|
||||
jsonObject2.add("synjones.pay.getbarcode", jsonObject);
|
||||
|
||||
JsonArray jsonArray = new JsonArray();
|
||||
jsonArray.add(jsonObject2);
|
||||
|
||||
String request;
|
||||
map.put("method", "synjones.pay.getbarcode");
|
||||
String timestamp;
|
||||
timestamp = URLEncoder.encode(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(System.currentTimeMillis())), StandardCharsets.UTF_8);
|
||||
map.put("timestamp", timestamp);
|
||||
map.put("v", "1.0");
|
||||
map.put("registerid", "mobileby");
|
||||
request = new SignUtils().sign(jsonArray.get(0).toString(), "qJzGEh6hESZDVJeCnFPGuxzaiB7NLQM5", "DESede");
|
||||
String nr = URLEncoder.encode(request, StandardCharsets.UTF_8);
|
||||
map.put("request", nr);
|
||||
String sign = URLEncoder.encode(RSASign.sign(map), StandardCharsets.UTF_8);
|
||||
map.put("sign", sign);
|
||||
|
||||
String signStatus = QrCodeSign.getSign(map);
|
||||
|
||||
if (signStatus != null) {
|
||||
if (signStatus.equals("sign_error")) {
|
||||
throw new RuntimeException("验证签名失败!");
|
||||
}
|
||||
|
||||
map.put("clientType", "1");
|
||||
map.put("versionName", "1.5.5");
|
||||
map.put("versionCode", "10505");
|
||||
map.put("sourcetype", sourceType);
|
||||
map.put("imei", imei);
|
||||
|
||||
signStatus = QrCodeSign.getSign(map);
|
||||
String md5 = QrCodeSign.getBase64(signStatus).toLowerCase();
|
||||
|
||||
FormBody formBody = new FormBody.Builder()
|
||||
.add("method", "synjones.pay.getbarcode")
|
||||
.add("timestamp", timestamp)
|
||||
.add("v", "1.0")
|
||||
.add("registerid", "mobileby")
|
||||
.add("request", nr)
|
||||
.add("sign", sign)
|
||||
.add("md5string", md5)
|
||||
.add("clientType", "1")
|
||||
.add("versionName", "1.5.5")
|
||||
.add("versionCode", "10505")
|
||||
.add("sourcetype", sourceType)
|
||||
.add("imei", imei)
|
||||
.build();
|
||||
|
||||
return sender.setAspHeaders(new Request.Builder()
|
||||
.url(URL)
|
||||
.post(formBody)).build();
|
||||
}
|
||||
throw new RuntimeException("签名为空!");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package cn.nahco3awa.naouc.network.ouc.request;
|
||||
|
||||
import cn.nahco3awa.naouc.network.ouc.OUCRequestSender;
|
||||
import okhttp3.FormBody;
|
||||
import okhttp3.Request;
|
||||
|
||||
public class GetCardAccInfoOUCRequest implements OUCRequest {
|
||||
public static final String URL = "https://vcard.ouc.edu.cn/User/GetCardAccInfo";
|
||||
private final String account;
|
||||
|
||||
public GetCardAccInfoOUCRequest(String account) {
|
||||
this.account = account;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Request makeRequest(OUCRequestSender sender) {
|
||||
return sender.setAspHeaders(new Request.Builder()
|
||||
.post(new FormBody.Builder()
|
||||
.addEncoded("acc", account)
|
||||
.addEncoded("json", "true")
|
||||
.build())
|
||||
.url(URL)).build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package cn.nahco3awa.naouc.network.ouc.request;
|
||||
|
||||
import cn.nahco3awa.naouc.network.ouc.OUCRequestSender;
|
||||
import okhttp3.FormBody;
|
||||
import okhttp3.Request;
|
||||
|
||||
public class GetInfoByTokenOUCRequest implements OUCRequest {
|
||||
public static final String URL = "https://vcard.ouc.edu.cn/NoBase/GetInfoByToken";
|
||||
private final String imei;
|
||||
private final String sourceType;
|
||||
private final String token;
|
||||
|
||||
public GetInfoByTokenOUCRequest(String imei, String sourceType, String token) {
|
||||
this.imei = imei;
|
||||
this.sourceType = sourceType;
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Request makeRequest(OUCRequestSender sender) {
|
||||
return sender.setAspHeaders(new Request.Builder())
|
||||
.url(URL)
|
||||
.post(new FormBody.Builder()
|
||||
.addEncoded("clientType", "1")
|
||||
.addEncoded("imei", imei)
|
||||
.addEncoded("sourcetype", sourceType)
|
||||
.addEncoded("versionName", "1.5.5")
|
||||
.addEncoded("versionCode", "10505")
|
||||
.addEncoded("token", token)
|
||||
.build())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
// 5760548
|
||||
@@ -0,0 +1,28 @@
|
||||
package cn.nahco3awa.naouc.network.ouc.request;
|
||||
|
||||
import cn.nahco3awa.naouc.network.ouc.OUCRequestSender;
|
||||
import okhttp3.FormBody;
|
||||
import okhttp3.Request;
|
||||
|
||||
public class GetMyBillOUCRequest implements OUCRequest {
|
||||
public static final String URL = "https://vcard.ouc.edu.cn/Report/GetMyBill";
|
||||
private final String account;
|
||||
private final int page;
|
||||
|
||||
public GetMyBillOUCRequest(String account, int page) {
|
||||
this.account = account;
|
||||
this.page = page;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Request makeRequest(OUCRequestSender sender) {
|
||||
return sender.setAspHeaders(new Request.Builder())
|
||||
.url(URL)
|
||||
.post(new FormBody.Builder()
|
||||
.addEncoded("account", account)
|
||||
.addEncoded("page", String.valueOf(page))
|
||||
.addEncoded("json", "true")
|
||||
.build())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package cn.nahco3awa.naouc.network.ouc.request;
|
||||
|
||||
import cn.nahco3awa.naouc.network.ouc.OUCRequestSender;
|
||||
import okhttp3.FormBody;
|
||||
import okhttp3.Request;
|
||||
|
||||
public class GetPhotoBySnoOUCRequest implements OUCRequest {
|
||||
public static final String URL = "https://vcard.ouc.edu.cn/NoBase/GetPhotoBySno";
|
||||
private final String imei;
|
||||
private final String sourceType;
|
||||
private final String sno;
|
||||
|
||||
public GetPhotoBySnoOUCRequest(String imei, String sourceType, String sno) {
|
||||
this.imei = imei;
|
||||
this.sourceType = sourceType;
|
||||
this.sno = sno;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Request makeRequest(OUCRequestSender sender) {
|
||||
return sender.setAspHeaders(new Request.Builder())
|
||||
.url(URL)
|
||||
.post(new FormBody.Builder()
|
||||
.addEncoded("accesstype", sourceType)
|
||||
.addEncoded("clientType", "1")
|
||||
.addEncoded("sno", sno)
|
||||
.addEncoded("imei", imei)
|
||||
.addEncoded("sourcetype", sourceType)
|
||||
.addEncoded("versionName", "1.5.5")
|
||||
.addEncoded("versionCode", "10505")
|
||||
.build())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package cn.nahco3awa.naouc.network.ouc.request;
|
||||
|
||||
import cn.nahco3awa.naouc.network.ouc.OUCRequestSender;
|
||||
import okhttp3.FormBody;
|
||||
import okhttp3.Request;
|
||||
|
||||
public class GetRsaOUCRequest implements OUCRequest {
|
||||
public static final String URL = "https://vcard.ouc.edu.cn/Common/GetRsaKey";
|
||||
@Override
|
||||
public Request makeRequest(OUCRequestSender sender) {
|
||||
return sender.setAspHeaders(new Request.Builder())
|
||||
.url(URL)
|
||||
.post(new FormBody.Builder()
|
||||
.addEncoded("json", "true")
|
||||
.build())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package cn.nahco3awa.naouc.network.ouc.request;
|
||||
|
||||
import cn.nahco3awa.naouc.network.ouc.OUCRequestSender;
|
||||
import okhttp3.Request;
|
||||
|
||||
public class GetValidateCodeOUCRequest implements OUCRequest {
|
||||
public static final String URL = "https://vcard.ouc.edu.cn/Phone/GetValidateCode";
|
||||
private long time;
|
||||
public GetValidateCodeOUCRequest(long time) {
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
public long getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public void setTime(long time) {
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Request makeRequest(OUCRequestSender sender) {
|
||||
return sender.setAspHeaders(new Request.Builder()
|
||||
.url(URL + "?time=" + getTime())
|
||||
.get())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package cn.nahco3awa.naouc.network.ouc.request;
|
||||
|
||||
import cn.nahco3awa.naouc.network.ouc.OUCRequestSender;
|
||||
import okhttp3.FormBody;
|
||||
import okhttp3.Request;
|
||||
|
||||
public class LoginOUCRequest implements OUCRequest {
|
||||
public static final String URL = "https://vcard.ouc.edu.cn/Phone/Login";
|
||||
private final String sno;
|
||||
private final String pwd;
|
||||
private final boolean remember;
|
||||
private final String uclass;
|
||||
private final String yzm;
|
||||
private final String key;
|
||||
|
||||
public LoginOUCRequest(String sno, String pwd, boolean remember, String uClass, String yzm, String key) {
|
||||
this.sno = sno;
|
||||
this.pwd = pwd;
|
||||
this.remember = remember;
|
||||
this.uclass = uClass;
|
||||
this.yzm = yzm;
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Request makeRequest(OUCRequestSender sender) {
|
||||
return sender.setAspHeaders(new Request.Builder()
|
||||
.url(URL)
|
||||
.post(new FormBody.Builder()
|
||||
.addEncoded("sno", sno)
|
||||
.addEncoded("pwd", pwd)
|
||||
.addEncoded("remember", remember ? "1" : "0")
|
||||
.addEncoded("uclass", uclass)
|
||||
.addEncoded("yzm", yzm)
|
||||
.addEncoded("key", key)
|
||||
.addEncoded("json", "true")
|
||||
.build()))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package cn.nahco3awa.naouc.network.ouc.request;
|
||||
|
||||
import cn.nahco3awa.naouc.network.ouc.OUCRequestSender;
|
||||
import okhttp3.Request;
|
||||
|
||||
public class NetCheckOUCRequest implements OUCRequest {
|
||||
public static final String URL = "https://vcard.ouc.edu.cn:8988/web/common/check.html?";
|
||||
@Override
|
||||
public Request makeRequest(OUCRequestSender sender) {
|
||||
return sender.setAspHeaders(new Request.Builder())
|
||||
.url(URL + "ticket=" + sender.getSourceTypeTicket())
|
||||
.get()
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package cn.nahco3awa.naouc.network.ouc.request;
|
||||
|
||||
import cn.nahco3awa.naouc.network.ouc.OUCRequestSender;
|
||||
import okhttp3.FormBody;
|
||||
import okhttp3.Request;
|
||||
|
||||
public class NetGdcOUCRequest implements OUCRequest {
|
||||
public static final String URL = "https://vcard.ouc.edu.cn:8988/web/NetWork/NetGdc.html";
|
||||
private final String account;
|
||||
private final String netAccount;
|
||||
private final int tran;
|
||||
|
||||
public NetGdcOUCRequest(String account, String netAccount, int tran) {
|
||||
this.account = account;
|
||||
this.netAccount = netAccount;
|
||||
this.tran = tran;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Request makeRequest(OUCRequestSender sender) {
|
||||
return sender.setAspHeaders(new Request.Builder())
|
||||
.url(URL)
|
||||
.post(new FormBody.Builder()
|
||||
.addEncoded("aid", "0030000000000301")
|
||||
.addEncoded("account", account)
|
||||
.addEncoded("tran", String.valueOf(tran))
|
||||
.addEncoded("netacc", netAccount)
|
||||
.addEncoded("acctype", "###")
|
||||
.build())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package cn.nahco3awa.naouc.network.ouc.request;
|
||||
|
||||
import cn.nahco3awa.naouc.network.ouc.OUCRequestSender;
|
||||
import okhttp3.Request;
|
||||
|
||||
public interface OUCRequest {
|
||||
Request makeRequest(OUCRequestSender sender);
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package cn.nahco3awa.naouc.network.ouc.request;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import cn.nahco3awa.naouc.network.ouc.OUCRequestSender;
|
||||
import okhttp3.FormBody;
|
||||
import okhttp3.Request;
|
||||
|
||||
public class TsmOUCRequest implements OUCRequest {
|
||||
public static final String URL = "https://vcard.ouc.edu.cn:8988/web/Common/Tsm.html";
|
||||
private final String account;
|
||||
private final String payAccount;
|
||||
|
||||
public TsmOUCRequest(String account, String payAccount) {
|
||||
this.account = account;
|
||||
this.payAccount = payAccount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Request makeRequest(OUCRequestSender sender) {
|
||||
JsonObject jsonObject = new JsonObject();
|
||||
JsonObject queryInfo = new JsonObject();
|
||||
queryInfo.addProperty("aid", "0030000000000301");
|
||||
queryInfo.addProperty("account", account);
|
||||
queryInfo.addProperty("payacc", payAccount);
|
||||
jsonObject.add("query_net_info", queryInfo);
|
||||
return sender.setAspHeaders(new Request.Builder())
|
||||
.url(URL)
|
||||
.post(new FormBody.Builder()
|
||||
.addEncoded("jsondata", jsonObject.toString())
|
||||
.addEncoded("funname", "synjones.onecard.query.net.info")
|
||||
.addEncoded("json", "true")
|
||||
.build())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package cn.nahco3awa.naouc.network.ouc.request;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Base64;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
import cn.nahco3awa.naouc.network.ouc.OUCRequestSender;
|
||||
import okhttp3.Request;
|
||||
|
||||
public class WaterApiAccUseHzWatchRequest implements OUCRequest {
|
||||
public static final String URL = "http://222.195.158.17:5003/waterapi/api/AccUseHzWatch";
|
||||
public static final byte[] PUBLIC_KEY = Base64.getDecoder().decode("3n4DdO47LWH2Co/WfpbdyA==");
|
||||
public static final String AES_MODE = "AES/ECB/PKCS5Padding";
|
||||
public static final String AES = "AES";
|
||||
private final String account;
|
||||
public WaterApiAccUseHzWatchRequest(String account) {
|
||||
this.account = account;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Request makeRequest(OUCRequestSender sender) {
|
||||
JsonObject jsonObject = new JsonObject();
|
||||
jsonObject.addProperty("ano", account);
|
||||
try {
|
||||
byte[] raw = jsonObject.toString().getBytes(StandardCharsets.UTF_8);
|
||||
SecretKeySpec keySpec = new SecretKeySpec(PUBLIC_KEY, AES);
|
||||
Cipher cipher = Cipher.getInstance(AES_MODE);
|
||||
cipher.init(Cipher.ENCRYPT_MODE, keySpec);
|
||||
byte[] encryptedInfo = cipher.doFinal(raw);
|
||||
String info = Base64.getEncoder().encodeToString(encryptedInfo).replaceAll("=", "%3D");
|
||||
return new Request.Builder()
|
||||
.url(URL + "?info=" + info + "&token=" + sender.getSourceTypeTicket())
|
||||
.get()
|
||||
.build();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package cn.nahco3awa.naouc.network.ouc.request;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Base64;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
import cn.nahco3awa.naouc.network.ouc.OUCRequestSender;
|
||||
import okhttp3.Request;
|
||||
|
||||
public class WaterApiBookCodeCancelRequest implements OUCRequest {
|
||||
public static final String URL = "http://222.195.158.17:5003/waterapi/api/BookCodeReqCancel";
|
||||
public static final byte[] PUBLIC_KEY = Base64.getDecoder().decode("3n4DdO47LWH2Co/WfpbdyA==");
|
||||
public static final String AES_MODE = "AES/ECB/PKCS5Padding";
|
||||
public static final String AES = "AES";
|
||||
private final String account;
|
||||
private final int classNo;
|
||||
|
||||
public WaterApiBookCodeCancelRequest(String account, int classNo) {
|
||||
this.account = account;
|
||||
this.classNo = classNo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Request makeRequest(OUCRequestSender sender) {
|
||||
JsonObject jsonObject = new JsonObject();
|
||||
jsonObject.addProperty("ano", account);
|
||||
jsonObject.addProperty("classno", classNo);
|
||||
try {
|
||||
byte[] raw = jsonObject.toString().getBytes(StandardCharsets.UTF_8);
|
||||
SecretKeySpec keySpec = new SecretKeySpec(PUBLIC_KEY, AES);
|
||||
Cipher cipher = Cipher.getInstance(AES_MODE);
|
||||
cipher.init(Cipher.ENCRYPT_MODE, keySpec);
|
||||
byte[] encryptedInfo = cipher.doFinal(raw);
|
||||
String info = Base64.getEncoder().encodeToString(encryptedInfo).replaceAll("=", "%3D");
|
||||
return new Request.Builder()
|
||||
.url(URL + "?info=" + info + "&token=" + sender.getSourceTypeTicket())
|
||||
.get()
|
||||
.build();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package cn.nahco3awa.naouc.network.ouc.request;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Base64;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
import cn.nahco3awa.naouc.network.ouc.OUCRequestSender;
|
||||
import okhttp3.Request;
|
||||
|
||||
public class WaterApiBookCodeRequest implements OUCRequest {
|
||||
public static final String URL = "http://222.195.158.17:5003/waterapi/api/BookCodeReq";
|
||||
public static final byte[] PUBLIC_KEY = Base64.getDecoder().decode("3n4DdO47LWH2Co/WfpbdyA==");
|
||||
public static final String AES_MODE = "AES/ECB/PKCS5Padding";
|
||||
public static final String AES = "AES";
|
||||
private final String account;
|
||||
private final int classNo;
|
||||
|
||||
public WaterApiBookCodeRequest(String account, int classNo) {
|
||||
this.account = account;
|
||||
this.classNo = classNo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Request makeRequest(OUCRequestSender sender) {
|
||||
JsonObject jsonObject = new JsonObject();
|
||||
jsonObject.addProperty("ano", account);
|
||||
jsonObject.addProperty("classno", classNo);
|
||||
try {
|
||||
byte[] raw = jsonObject.toString().getBytes(StandardCharsets.UTF_8);
|
||||
SecretKeySpec keySpec = new SecretKeySpec(PUBLIC_KEY, AES);
|
||||
Cipher cipher = Cipher.getInstance(AES_MODE);
|
||||
cipher.init(Cipher.ENCRYPT_MODE, keySpec);
|
||||
byte[] encryptedInfo = cipher.doFinal(raw);
|
||||
String info = Base64.getEncoder().encodeToString(encryptedInfo).replaceAll("=", "%3D");
|
||||
return new Request.Builder()
|
||||
.url(URL + "?info=" + info + "&token=" + sender.getSourceTypeTicket())
|
||||
.get()
|
||||
.build();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package cn.nahco3awa.naouc.network.ouc.response;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
import okhttp3.Response;
|
||||
|
||||
public class AccountPayOUCResponse extends OUCResponse {
|
||||
private final String url;
|
||||
private final String method;
|
||||
private final String orderId;
|
||||
public AccountPayOUCResponse(Response response) {
|
||||
super(response);
|
||||
JsonObject jsonObject = JsonParser.parseReader(response.body().charStream()).getAsJsonObject();
|
||||
if (!jsonObject.get("IsSucceed").getAsBoolean()) {
|
||||
throw new RuntimeException(jsonObject.get("Msg").getAsString());
|
||||
}
|
||||
url = jsonObject.get("Msg").getAsString();
|
||||
method = jsonObject.get("Obj").getAsString();
|
||||
orderId = jsonObject.get("OrderID").getAsString();
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public String getMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
public String getOrderId() {
|
||||
return orderId;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package cn.nahco3awa.naouc.network.ouc.response;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
import okhttp3.Response;
|
||||
|
||||
public class GetBarCodePayOUCResponse extends OUCResponse {
|
||||
private final int account;
|
||||
private final long expires;
|
||||
private final String[] barcode;
|
||||
public GetBarCodePayOUCResponse(Response response) {
|
||||
super(response);
|
||||
JsonObject object = JsonParser.parseReader(response.body().charStream()).getAsJsonObject();
|
||||
if (!object.get("retcode").getAsString().equals("0")) {
|
||||
Log.e("GBCP", object.toString());
|
||||
throw new RuntimeException(object.get("errmsg").getAsString());
|
||||
}
|
||||
JsonObject obj = object.getAsJsonObject("obj");
|
||||
account = Integer.parseInt(obj.get("ACCOUNT").getAsString());
|
||||
expires = Long.parseLong(obj.get("EXPIRES").getAsString());
|
||||
barcode = new String[4];
|
||||
var awa = obj.get("BARCODE").getAsJsonArray();
|
||||
for (int i = 0; i < 4; i++) {
|
||||
barcode[i] = awa.get(i).getAsString();
|
||||
}
|
||||
}
|
||||
|
||||
public int getAccount() {
|
||||
return account;
|
||||
}
|
||||
|
||||
public long getExpires() {
|
||||
return expires;
|
||||
}
|
||||
|
||||
public String[] getBarcode() {
|
||||
return barcode;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package cn.nahco3awa.naouc.network.ouc.response;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import okhttp3.Response;
|
||||
|
||||
public class GetCardAccInfoOUCResponse extends OUCResponse {
|
||||
private final int balance; // 我们假定海大没有富哥
|
||||
public GetCardAccInfoOUCResponse(Response response) throws IOException {
|
||||
super(response);
|
||||
JsonObject jsonObject = JsonParser.parseString(response.body().string()).getAsJsonObject();
|
||||
String msg = jsonObject.get("Msg").getAsString();
|
||||
JsonObject queryObject = JsonParser.parseString(msg).getAsJsonObject().get("query_accinfo").getAsJsonObject();
|
||||
if (!queryObject.get("retcode").getAsString().equals("0")) {
|
||||
throw new RuntimeException(queryObject.get("errmsg").getAsString());
|
||||
}
|
||||
balance = Integer.parseInt(queryObject.get("accinfo").getAsJsonArray().get(0).getAsJsonObject().get("balance").getAsString());
|
||||
}
|
||||
|
||||
public int getBalance() {
|
||||
return balance;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
package cn.nahco3awa.naouc.network.ouc.response;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
import okhttp3.Response;
|
||||
|
||||
public class GetInfoByTokenOUCResponse extends OUCResponse {
|
||||
private final String no;
|
||||
private final String name;
|
||||
private final String sex;
|
||||
private final String sno;
|
||||
private final String lastUpdate;
|
||||
private final String account;
|
||||
private final String cardId;
|
||||
private final String password;
|
||||
private final String bmmc;
|
||||
private final String subjectCode;
|
||||
private final String subjectName;
|
||||
private final String gradeName;
|
||||
private final String schoolName;
|
||||
private final String pidName;
|
||||
private final String pidCode;
|
||||
private final String classCode;
|
||||
private final String expDate;
|
||||
private final String areaCode;
|
||||
private final String deptCode;
|
||||
private final String className;
|
||||
|
||||
public GetInfoByTokenOUCResponse(Response response) {
|
||||
super(response);
|
||||
JsonObject object = JsonParser.parseReader(response.body().charStream()).getAsJsonObject();
|
||||
if (!object.get("IsSucceed").getAsBoolean()) {
|
||||
throw new RuntimeException(object.get("Msg").getAsString());
|
||||
}
|
||||
JsonObject obj2 = object.getAsJsonObject("Obj");
|
||||
no = obj2.get("NO").getAsString();
|
||||
name = obj2.get("NAME").getAsString();
|
||||
sex = obj2.get("SEX").getAsString();
|
||||
sno = obj2.get("SNO").getAsString();
|
||||
lastUpdate = obj2.get("LASTUPDATE").getAsString();
|
||||
account = obj2.get("ACCOUNT").getAsString();
|
||||
cardId = obj2.get("CARDID").getAsString();
|
||||
subjectName = obj2.get("ZYMC").getAsString();
|
||||
subjectCode = obj2.get("ZYDM").getAsString();
|
||||
gradeName = obj2.get("NJMC").getAsString();
|
||||
schoolName = obj2.get("XQMC").getAsString();
|
||||
pidName = obj2.get("PIDNAME").getAsString();
|
||||
pidCode = obj2.get("PIDCODE").getAsString();
|
||||
classCode = obj2.get("BJDM").getAsString();
|
||||
expDate = obj2.get("EXPDATE").getAsString();
|
||||
areaCode = obj2.get("AREACODE").getAsString();
|
||||
deptCode = obj2.get("DEPTCODE").getAsString();
|
||||
className = obj2.get("BJMC").getAsString();
|
||||
password = obj2.get("PASSWORD").getAsString();
|
||||
bmmc = obj2.get("BMMC").getAsString();
|
||||
}
|
||||
|
||||
public String getClassName() {
|
||||
return className;
|
||||
}
|
||||
|
||||
public String getDeptCode() {
|
||||
return deptCode;
|
||||
}
|
||||
|
||||
public String getAreaCode() {
|
||||
return areaCode;
|
||||
}
|
||||
|
||||
public String getExpDate() {
|
||||
return expDate;
|
||||
}
|
||||
|
||||
public String getClassCode() {
|
||||
return classCode;
|
||||
}
|
||||
|
||||
public String getPidCode() {
|
||||
return pidCode;
|
||||
}
|
||||
|
||||
public String getPidName() {
|
||||
return pidName;
|
||||
}
|
||||
|
||||
public String getSchoolName() {
|
||||
return schoolName;
|
||||
}
|
||||
|
||||
public String getGradeName() {
|
||||
return gradeName;
|
||||
}
|
||||
|
||||
public String getSubjectName() {
|
||||
return subjectName;
|
||||
}
|
||||
|
||||
public String getSubjectCode() {
|
||||
return subjectCode;
|
||||
}
|
||||
|
||||
public String getBmmc() {
|
||||
return bmmc;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public String getCardId() {
|
||||
return cardId;
|
||||
}
|
||||
|
||||
public String getAccount() {
|
||||
return account;
|
||||
}
|
||||
|
||||
public String getLastUpdate() {
|
||||
return lastUpdate;
|
||||
}
|
||||
|
||||
public String getSno() {
|
||||
return sno;
|
||||
}
|
||||
|
||||
public String getSex() {
|
||||
return sex;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getNo() {
|
||||
return no;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package cn.nahco3awa.naouc.network.ouc.response;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import cn.nahco3awa.naouc.network.ouc.response.data.SingleBillData;
|
||||
import okhttp3.Response;
|
||||
|
||||
public class GetMyBillOUCResponse extends OUCResponse {
|
||||
private final List<SingleBillData> billData;
|
||||
public GetMyBillOUCResponse(Response response) {
|
||||
super(response);
|
||||
JsonObject jsonObject = JsonParser.parseReader(response.body().charStream()).getAsJsonObject();
|
||||
var arr = jsonObject.get("rows").getAsJsonArray();
|
||||
billData = new ArrayList<>(arr.size());
|
||||
Gson gson = new Gson();
|
||||
for (JsonElement jsonElement : arr) {
|
||||
billData.add(gson.fromJson(jsonElement, SingleBillData.class));
|
||||
}
|
||||
}
|
||||
|
||||
public List<SingleBillData> getBillData() {
|
||||
return billData;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package cn.nahco3awa.naouc.network.ouc.response;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
import java.util.Base64;
|
||||
|
||||
import okhttp3.Response;
|
||||
|
||||
public class GetPhotoBySnoOUCResponse extends OUCResponse {
|
||||
private final Bitmap image;
|
||||
public GetPhotoBySnoOUCResponse(Response response) {
|
||||
super(response);
|
||||
JsonObject object = JsonParser.parseReader(response.body().charStream()).getAsJsonObject();
|
||||
if (!object.get("IsSucceed").getAsBoolean()) {
|
||||
throw new RuntimeException(object.get("Msg").getAsString());
|
||||
}
|
||||
String imageBase64 = object.get("Obj").getAsString();
|
||||
byte[] bs = Base64.getDecoder().decode(imageBase64);
|
||||
image = BitmapFactory.decodeByteArray(bs, 0, bs.length);
|
||||
}
|
||||
|
||||
public Bitmap getImage() {
|
||||
return image;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package cn.nahco3awa.naouc.network.ouc.response;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
import okhttp3.Response;
|
||||
|
||||
public class GetRsaKeyOUCResponse extends OUCResponse {
|
||||
private final String msg;
|
||||
private final String e;
|
||||
private final String mod;
|
||||
public GetRsaKeyOUCResponse(Response response) {
|
||||
super(response);
|
||||
JsonObject object = JsonParser.parseReader(response.body().charStream()).getAsJsonObject();
|
||||
msg = object.get("Msg").getAsString();
|
||||
String[] keys = object.get("Obj").getAsString().split(",");
|
||||
e = keys[0];
|
||||
mod = keys[1];
|
||||
}
|
||||
|
||||
public String getMod() {
|
||||
return mod;
|
||||
}
|
||||
|
||||
public String getMsg() {
|
||||
return msg;
|
||||
}
|
||||
|
||||
public String getE() {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package cn.nahco3awa.naouc.network.ouc.response;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
|
||||
import okhttp3.Response;
|
||||
|
||||
public class GetValidateCodeOUCResponse extends OUCResponse {
|
||||
private final Bitmap image;
|
||||
|
||||
public GetValidateCodeOUCResponse(Response response) {
|
||||
super(response);
|
||||
image = BitmapFactory.decodeStream(response.body().byteStream());
|
||||
}
|
||||
|
||||
public Bitmap getImage() {
|
||||
return image;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
package cn.nahco3awa.naouc.network.ouc.response;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
import okhttp3.Response;
|
||||
|
||||
public class LoginOUCResponse extends OUCResponse {
|
||||
private final String rescouseType;
|
||||
private final String no;
|
||||
private final String name;
|
||||
private final String sex;
|
||||
private final String sno;
|
||||
private final String lastUpdate;
|
||||
private final String account;
|
||||
private final String cardId;
|
||||
private final String tel;
|
||||
private final String subjectName;
|
||||
private final String subjectCode;
|
||||
private final String gradeName;
|
||||
private final String schoolName;
|
||||
private final String pidName;
|
||||
private final String pidCode;
|
||||
private final String classCode;
|
||||
private final String expDate;
|
||||
private final String areaCode;
|
||||
private final String deptCode;
|
||||
private final String className;
|
||||
private final String createdDate;
|
||||
public LoginOUCResponse(Response response) {
|
||||
super(response);
|
||||
JsonObject object = JsonParser.parseReader(response.body().charStream()).getAsJsonObject();
|
||||
if (!object.get("IsSucceed").getAsBoolean()) {
|
||||
throw new RuntimeException(object.get("Msg").getAsString());
|
||||
}
|
||||
JsonObject obj2 = object.getAsJsonObject("Obj2");
|
||||
rescouseType = obj2.get("RescouseType").getAsString();
|
||||
no = obj2.get("NO").getAsString();
|
||||
name = obj2.get("NAME").getAsString();
|
||||
sex = obj2.get("SEX").getAsString();
|
||||
sno = obj2.get("SNO").getAsString();
|
||||
lastUpdate = obj2.get("LASTUPDATE").getAsString();
|
||||
account = obj2.get("ACCOUNT").getAsString();
|
||||
cardId = obj2.get("CARDID").getAsString();
|
||||
tel = obj2.get("TEL").getAsString();
|
||||
subjectName = obj2.get("ZYMC").getAsString();
|
||||
subjectCode = obj2.get("ZYDM").getAsString();
|
||||
gradeName = obj2.get("NJMC").getAsString();
|
||||
schoolName = obj2.get("XQMC").getAsString();
|
||||
pidName = obj2.get("PIDNAME").getAsString();
|
||||
pidCode = obj2.get("PIDCODE").getAsString();
|
||||
classCode = obj2.get("BJDM").getAsString();
|
||||
expDate = obj2.get("EXPDATE").getAsString();
|
||||
areaCode = obj2.get("AREACODE").getAsString();
|
||||
deptCode = obj2.get("DEPTCODE").getAsString();
|
||||
className = obj2.get("BJMC").getAsString();
|
||||
createdDate = obj2.get("CREATEDATE").getAsString();
|
||||
}
|
||||
|
||||
|
||||
public String getCreatedDate() {
|
||||
return createdDate;
|
||||
}
|
||||
|
||||
public String getClassName() {
|
||||
return className;
|
||||
}
|
||||
|
||||
public String getDeptCode() {
|
||||
return deptCode;
|
||||
}
|
||||
|
||||
public String getAreaCode() {
|
||||
return areaCode;
|
||||
}
|
||||
|
||||
public String getExpDate() {
|
||||
return expDate;
|
||||
}
|
||||
|
||||
public String getClassCode() {
|
||||
return classCode;
|
||||
}
|
||||
|
||||
public String getPidCode() {
|
||||
return pidCode;
|
||||
}
|
||||
|
||||
public String getPidName() {
|
||||
return pidName;
|
||||
}
|
||||
|
||||
public String getSchoolName() {
|
||||
return schoolName;
|
||||
}
|
||||
|
||||
public String getGradeName() {
|
||||
return gradeName;
|
||||
}
|
||||
|
||||
public String getSubjectCode() {
|
||||
return subjectCode;
|
||||
}
|
||||
|
||||
public String getSubjectName() {
|
||||
return subjectName;
|
||||
}
|
||||
|
||||
public String getTel() {
|
||||
return tel;
|
||||
}
|
||||
|
||||
public String getCardId() {
|
||||
return cardId;
|
||||
}
|
||||
|
||||
public String getAccount() {
|
||||
return account;
|
||||
}
|
||||
|
||||
public String getLastUpdate() {
|
||||
return lastUpdate;
|
||||
}
|
||||
|
||||
public String getSno() {
|
||||
return sno;
|
||||
}
|
||||
|
||||
public String getSex() {
|
||||
return sex;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getNo() {
|
||||
return no;
|
||||
}
|
||||
|
||||
public String getRescouseType() {
|
||||
return rescouseType;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package cn.nahco3awa.naouc.network.ouc.response;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
import okhttp3.Response;
|
||||
|
||||
public class NetGdcOUCResponse extends OUCResponse {
|
||||
private final int retCode;
|
||||
private final String errMessage;
|
||||
private final String aid;
|
||||
private final String account;
|
||||
private final String accountType;
|
||||
private final int tranAmount;
|
||||
public NetGdcOUCResponse(Response response) {
|
||||
super(response);
|
||||
JsonObject jsonObject = JsonParser.parseReader(response.body().charStream()).getAsJsonObject().getAsJsonObject("pay_net_gdc");
|
||||
retCode = Integer.parseInt(jsonObject.get("retcode").getAsString());
|
||||
errMessage = jsonObject.get("errmsg").getAsString();
|
||||
aid = jsonObject.get("aid").getAsString();
|
||||
account = jsonObject.get("account").getAsString();
|
||||
accountType = jsonObject.get("acctype").getAsString();
|
||||
tranAmount = Integer.parseInt(jsonObject.get("tranamt").getAsString());
|
||||
}
|
||||
|
||||
public int getRetCode() {
|
||||
return retCode;
|
||||
}
|
||||
|
||||
public int getTranAmount() {
|
||||
return tranAmount;
|
||||
}
|
||||
|
||||
public String getAccount() {
|
||||
return account;
|
||||
}
|
||||
|
||||
public String getAccountType() {
|
||||
return accountType;
|
||||
}
|
||||
|
||||
public String getAid() {
|
||||
return aid;
|
||||
}
|
||||
|
||||
public String getErrMessage() {
|
||||
return errMessage;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package cn.nahco3awa.naouc.network.ouc.response;
|
||||
|
||||
public interface OUCCallback<R extends OUCResponse> {
|
||||
void onSuccess(R response);
|
||||
void onFailure(Throwable e);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package cn.nahco3awa.naouc.network.ouc.response;
|
||||
|
||||
import okhttp3.Response;
|
||||
|
||||
public abstract class OUCResponse {
|
||||
private final Response response;
|
||||
public OUCResponse(Response response) {
|
||||
this.response = response;
|
||||
}
|
||||
|
||||
public Response getResponse() {
|
||||
return response;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package cn.nahco3awa.naouc.network.ouc.response;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
import okhttp3.Response;
|
||||
|
||||
public class TsmOUCResponse extends OUCResponse {
|
||||
private final String msg;
|
||||
private final String aid;
|
||||
private final String account;
|
||||
private final String netAccount;
|
||||
private final float balance;
|
||||
private final boolean isFrozen;
|
||||
private final boolean hasLost;
|
||||
private final String retcode;
|
||||
|
||||
public TsmOUCResponse(Response response) {
|
||||
super(response);
|
||||
JsonObject jsonObject = JsonParser.parseReader(response.body().charStream()).getAsJsonObject().getAsJsonObject("query_net_info");
|
||||
if (!jsonObject.get("retcode").getAsString().equals("0")) {
|
||||
throw new RuntimeException(jsonObject.get("errmsg").getAsString());
|
||||
}
|
||||
retcode = jsonObject.get("retcode").getAsString();
|
||||
msg = jsonObject.get("errmsg").getAsString();
|
||||
aid = jsonObject.get("aid").getAsString();
|
||||
account = jsonObject.get("account").getAsString();
|
||||
JsonObject netAccountObject = jsonObject.getAsJsonObject("netacc");
|
||||
netAccount = netAccountObject.get("netacc").getAsString();
|
||||
balance = Integer.parseInt(netAccountObject.get("bal").getAsString()) / 100.0f;
|
||||
isFrozen = netAccountObject.get("freezeflag").getAsString().equals("1");
|
||||
hasLost = netAccountObject.get("lostflag").getAsString().equals("1");
|
||||
}
|
||||
|
||||
public String getMsg() {
|
||||
return msg;
|
||||
}
|
||||
|
||||
public String getAid() {
|
||||
return aid;
|
||||
}
|
||||
|
||||
public String getAccount() {
|
||||
return account;
|
||||
}
|
||||
|
||||
public String getNetAccount() {
|
||||
return netAccount;
|
||||
}
|
||||
|
||||
public float getBalance() {
|
||||
return balance;
|
||||
}
|
||||
|
||||
public boolean isFrozen() {
|
||||
return isFrozen;
|
||||
}
|
||||
|
||||
public boolean hasLost() {
|
||||
return hasLost;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package cn.nahco3awa.naouc.network.ouc.response;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import cn.nahco3awa.naouc.network.ouc.response.data.SingleWaterHzWatchData;
|
||||
import okhttp3.Response;
|
||||
|
||||
public class WaterApiAccUseHzWatchResponse extends OUCResponse {
|
||||
private final int retNo;
|
||||
private final String description;
|
||||
private final List<SingleWaterHzWatchData> data;
|
||||
public WaterApiAccUseHzWatchResponse(Response response) {
|
||||
super(response);
|
||||
JsonObject jsonObject = JsonParser.parseReader(response.body().charStream()).getAsJsonObject();
|
||||
retNo = jsonObject.get("RetNo").getAsInt();
|
||||
description = jsonObject.get("RetDsp").getAsString();
|
||||
if (retNo != 0) {
|
||||
throw new RuntimeException(description);
|
||||
}
|
||||
data = new ArrayList<>();
|
||||
for (JsonElement single : jsonObject.getAsJsonArray("List")) {
|
||||
JsonObject singleData = single.getAsJsonObject();
|
||||
data.add(new SingleWaterHzWatchData(
|
||||
singleData.get("ClassNo").getAsInt(),
|
||||
singleData.get("ClassName").getAsString(),
|
||||
singleData.get("PosNum").getAsInt(),
|
||||
singleData.get("WarnPosNum").getAsInt(),
|
||||
singleData.get("UseFreeRate").getAsInt(),
|
||||
singleData.get("BookRate").getAsInt(),
|
||||
singleData.get("Actkind").getAsInt(),
|
||||
singleData.get("BookCode").getAsString()
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
public List<SingleWaterHzWatchData> getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public int getRetNo() {
|
||||
return retNo;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package cn.nahco3awa.naouc.network.ouc.response;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
import okhttp3.Response;
|
||||
|
||||
public class WaterApiBookCodeCancelResponse extends OUCResponse {
|
||||
private final int retNo;
|
||||
private final String description;
|
||||
private final String bookCode;
|
||||
public WaterApiBookCodeCancelResponse(Response response) {
|
||||
super(response);
|
||||
JsonObject jsonObject = JsonParser.parseReader(response.body().charStream()).getAsJsonObject();
|
||||
retNo = jsonObject.get("RetNo").getAsInt();
|
||||
description = jsonObject.get("RetDsp").getAsString();
|
||||
bookCode = jsonObject.get("BookCode").getAsString();
|
||||
}
|
||||
|
||||
public String getBookCode() {
|
||||
return bookCode;
|
||||
}
|
||||
|
||||
public int getRetNo() {
|
||||
return retNo;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package cn.nahco3awa.naouc.network.ouc.response;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
import okhttp3.Response;
|
||||
|
||||
public class WaterApiBookCodeResponse extends OUCResponse {
|
||||
private final int retNo;
|
||||
private final String description;
|
||||
private final String bookCode;
|
||||
public WaterApiBookCodeResponse(Response response) {
|
||||
super(response);
|
||||
JsonObject jsonObject = JsonParser.parseReader(response.body().charStream()).getAsJsonObject();
|
||||
retNo = jsonObject.get("RetNo").getAsInt();
|
||||
description = jsonObject.get("RetDsp").getAsString();
|
||||
bookCode = jsonObject.get("BookCode").getAsString();
|
||||
}
|
||||
|
||||
public String getBookCode() {
|
||||
return bookCode;
|
||||
}
|
||||
|
||||
public int getRetNo() {
|
||||
return retNo;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package cn.nahco3awa.naouc.network.ouc.response.data;
|
||||
|
||||
public class SingleBillData {
|
||||
public int RO; // 行数
|
||||
public String OCCTIME; // 支出事件
|
||||
public String EFFECTDATE; // 生效时间
|
||||
public String XQ; // 星期
|
||||
public String MERCNAME; // 消费地点
|
||||
public float TRANAMT; // 金额
|
||||
public String TRANNAME; // 支付方式
|
||||
public float CARDBAL; // 余额
|
||||
public String JDESC; // 流水简介
|
||||
public int JNUM;
|
||||
public String MACCOUNT;
|
||||
public String TRANCODE;
|
||||
public String F1;
|
||||
public String F2;
|
||||
public String F3;
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
package cn.nahco3awa.naouc.network.ouc.response.data;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public final class SingleWaterHzWatchData {
|
||||
private final int ClassNo;
|
||||
private final String ClassName;
|
||||
private final int PosNum;
|
||||
private final int WarnPosNum;
|
||||
private final int UseFreeRate;
|
||||
private final int BookRate;
|
||||
private int Actkind;
|
||||
private String BookCode;
|
||||
|
||||
public SingleWaterHzWatchData(
|
||||
int ClassNo, // 单位编号
|
||||
String ClassName, // 单位名称
|
||||
int PosNum, // 设备量
|
||||
int WarnPosNum, // ???
|
||||
int UseFreeRate, // 空闲率
|
||||
int BookRate, // 预约比例(66为0.66%)
|
||||
int Actkind, // 0未预约 1已预约
|
||||
String BookCode // 预约编号
|
||||
) {
|
||||
this.ClassNo = ClassNo;
|
||||
this.ClassName = ClassName;
|
||||
this.PosNum = PosNum;
|
||||
this.WarnPosNum = WarnPosNum;
|
||||
this.UseFreeRate = UseFreeRate;
|
||||
this.BookRate = BookRate;
|
||||
this.Actkind = Actkind;
|
||||
this.BookCode = BookCode;
|
||||
}
|
||||
|
||||
public int ClassNo() {
|
||||
return ClassNo;
|
||||
}
|
||||
|
||||
public String ClassName() {
|
||||
return ClassName;
|
||||
}
|
||||
|
||||
public int PosNum() {
|
||||
return PosNum;
|
||||
}
|
||||
|
||||
public int WarnPosNum() {
|
||||
return WarnPosNum;
|
||||
}
|
||||
|
||||
public int UseFreeRate() {
|
||||
return UseFreeRate;
|
||||
}
|
||||
|
||||
public int BookRate() {
|
||||
return BookRate;
|
||||
}
|
||||
|
||||
public int Actkind() {
|
||||
return Actkind;
|
||||
}
|
||||
|
||||
public String BookCode() {
|
||||
return BookCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) return true;
|
||||
if (obj == null || obj.getClass() != this.getClass()) return false;
|
||||
var that = (SingleWaterHzWatchData) obj;
|
||||
return this.ClassNo == that.ClassNo &&
|
||||
Objects.equals(this.ClassName, that.ClassName) &&
|
||||
this.PosNum == that.PosNum &&
|
||||
this.WarnPosNum == that.WarnPosNum &&
|
||||
this.UseFreeRate == that.UseFreeRate &&
|
||||
this.BookRate == that.BookRate &&
|
||||
this.Actkind == that.Actkind &&
|
||||
Objects.equals(this.BookCode, that.BookCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(ClassNo, ClassName, PosNum, WarnPosNum, UseFreeRate, BookRate, Actkind, BookCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SingleWaterHzWatchData[" +
|
||||
"ClassNo=" + ClassNo + ", " +
|
||||
"ClassName=" + ClassName + ", " +
|
||||
"PosNum=" + PosNum + ", " +
|
||||
"WarnPosNum=" + WarnPosNum + ", " +
|
||||
"UseFreeRate=" + UseFreeRate + ", " +
|
||||
"BookRate=" + BookRate + ", " +
|
||||
"Actkind=" + Actkind + ", " +
|
||||
"BookCode=" + BookCode + ']';
|
||||
}
|
||||
|
||||
public void setActkind(int actkind) {
|
||||
Actkind = actkind;
|
||||
}
|
||||
|
||||
public void setBookCode(String bookCode) {
|
||||
BookCode = bookCode;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package cn.nahco3awa.naouc.network.weouc;
|
||||
|
||||
public enum LoginType {
|
||||
UNDERGRADUATE("undergraduate");
|
||||
String name;
|
||||
LoginType(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package cn.nahco3awa.naouc.network.weouc;
|
||||
|
||||
import okhttp3.OkHttpClient;
|
||||
|
||||
public class WeOUCRequestSender {
|
||||
private final OkHttpClient client;
|
||||
private WeOUCRequestSender() {
|
||||
client = new OkHttpClient();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package cn.nahco3awa.naouc.network.weouc.request;
|
||||
|
||||
import cn.nahco3awa.naouc.network.weouc.LoginType;
|
||||
import cn.nahco3awa.naouc.network.weouc.WeOUCRequestSender;
|
||||
import okhttp3.FormBody;
|
||||
import okhttp3.Request;
|
||||
|
||||
public class KbWeOUCRequest implements WeOUCRequest {
|
||||
public static final String URL = "https://api.weouc.com/api/jw/kb";
|
||||
private final int xn;
|
||||
private final int xq;
|
||||
private final String sno;
|
||||
private final LoginType loginType;
|
||||
private final String password;
|
||||
|
||||
public KbWeOUCRequest(int xn, int xq, String sno, LoginType loginType, String password) {
|
||||
this.xn = xn;
|
||||
this.xq = xq;
|
||||
this.sno = sno;
|
||||
this.loginType = loginType;
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Request makeRequest(WeOUCRequestSender sender) {
|
||||
return new Request.Builder()
|
||||
.url(URL)
|
||||
.post(new FormBody.Builder()
|
||||
.addEncoded("xn", String.valueOf(xn))
|
||||
.addEncoded("xq", String.valueOf(xq))
|
||||
.addEncoded("sno", sno)
|
||||
.addEncoded("loginType", loginType.getName())
|
||||
.addEncoded("password", password)
|
||||
.build())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package cn.nahco3awa.naouc.network.weouc.request;
|
||||
|
||||
import cn.nahco3awa.naouc.network.weouc.WeOUCRequestSender;
|
||||
import okhttp3.Request;
|
||||
|
||||
public interface WeOUCRequest {
|
||||
Request makeRequest(WeOUCRequestSender sender);
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package cn.nahco3awa.naouc.network.weouc.response;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import cn.nahco3awa.naouc.network.weouc.response.data.kb.ClassData;
|
||||
import okhttp3.Response;
|
||||
|
||||
public class KbWeOUCResponse extends WeOUCResponse {
|
||||
private final List<ClassData> classes;
|
||||
private final boolean fromCache;
|
||||
private final String message;
|
||||
private final int status;
|
||||
public KbWeOUCResponse(Response response) {
|
||||
super(response);
|
||||
JsonObject jsonObject = JsonParser.parseReader(response.body().charStream()).getAsJsonObject();
|
||||
fromCache = jsonObject.get("from_cache").getAsBoolean();
|
||||
message = jsonObject.get("message").getAsString();
|
||||
status = jsonObject.get("status").getAsInt();
|
||||
classes = ClassData.parseClassesData(jsonObject.get("data").getAsJsonArray());
|
||||
}
|
||||
|
||||
public int getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public List<ClassData> getClasses() {
|
||||
return classes;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public boolean isFromCache() {
|
||||
return fromCache;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package cn.nahco3awa.naouc.network.weouc.response;
|
||||
|
||||
public interface WeOUCCallback<R extends WeOUCResponse> {
|
||||
void onSuccess(R response);
|
||||
void onFailure(Throwable e);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package cn.nahco3awa.naouc.network.weouc.response;
|
||||
|
||||
import okhttp3.Response;
|
||||
|
||||
public abstract class WeOUCResponse {
|
||||
private final Response response;
|
||||
public WeOUCResponse(Response response) {
|
||||
this.response = response;
|
||||
}
|
||||
|
||||
public Response getResponse() {
|
||||
return response;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
package cn.nahco3awa.naouc.network.weouc.response.data.kb;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class ClassData {
|
||||
private final String name;
|
||||
private final String classRoom;
|
||||
private final String credit;
|
||||
private final String origin;
|
||||
private final String status;
|
||||
private final String teacher;
|
||||
private final int begin;
|
||||
private final int num;
|
||||
private final int day;
|
||||
private final List<String> weeks;
|
||||
|
||||
public static final Map<Integer, Integer> DAY_OF_WEEK_MAP = new HashMap<>();
|
||||
public static final int[] CLASS_MINUTES = {
|
||||
0,
|
||||
8 * 60,
|
||||
9 * 60,
|
||||
10 * 60 + 10,
|
||||
11 * 60 + 10,
|
||||
// rest
|
||||
13 * 60 + 30,
|
||||
14 * 60 + 30,
|
||||
15 * 60 + 30,
|
||||
16 * 60 + 30,
|
||||
17 * 60 + 30,
|
||||
18 * 60 + 30,
|
||||
19 * 60 + 30,
|
||||
20 * 60 + 30
|
||||
};
|
||||
|
||||
public ClassData(String name, String classRoom, String credit, String origin, String status, String teacher, int begin, int num, int day, List<String> weeks) {
|
||||
this.name = name;
|
||||
this.classRoom = classRoom;
|
||||
this.credit = credit;
|
||||
this.origin = origin;
|
||||
this.status = status;
|
||||
this.teacher = teacher;
|
||||
this.begin = begin;
|
||||
this.num = num;
|
||||
this.day = day;
|
||||
this.weeks = weeks;
|
||||
}
|
||||
|
||||
public List<String> getWeeks() {
|
||||
return weeks;
|
||||
}
|
||||
|
||||
public int getDay() {
|
||||
return day;
|
||||
}
|
||||
|
||||
public int getNum() {
|
||||
return num;
|
||||
}
|
||||
|
||||
public int getBegin() {
|
||||
return begin;
|
||||
}
|
||||
|
||||
public String getTeacher() {
|
||||
return teacher;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public String getOrigin() {
|
||||
return origin;
|
||||
}
|
||||
|
||||
public String getCredit() {
|
||||
return credit;
|
||||
}
|
||||
|
||||
public String getClassRoom() {
|
||||
return classRoom;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public int getMinutesOfDay() {
|
||||
return CLASS_MINUTES[getBegin()];
|
||||
}
|
||||
|
||||
public static ClassData fromJson(JsonObject jsonObject) {
|
||||
return new Gson().fromJson(jsonObject, ClassData.class);
|
||||
}
|
||||
|
||||
public static List<ClassData> parseClassesData(JsonArray data) {
|
||||
List<ClassData> ret = new ArrayList<>();
|
||||
for (JsonElement datum : data) {
|
||||
for (JsonElement classes : datum.getAsJsonObject().getAsJsonArray("classes")) {
|
||||
if (classes.isJsonArray()) {
|
||||
for (JsonElement classData : classes.getAsJsonArray()) {
|
||||
if (classData.isJsonObject()) {
|
||||
ret.add(fromJson(classData.getAsJsonObject()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static int getClassDayByDayOfWeek(int dayOfWeek) {
|
||||
return DAY_OF_WEEK_MAP.get(dayOfWeek);
|
||||
}
|
||||
|
||||
static {
|
||||
DAY_OF_WEEK_MAP.put(Calendar.SUNDAY, 6);
|
||||
DAY_OF_WEEK_MAP.put(Calendar.MONDAY, 0);
|
||||
DAY_OF_WEEK_MAP.put(Calendar.TUESDAY, 1);
|
||||
DAY_OF_WEEK_MAP.put(Calendar.WEDNESDAY, 2);
|
||||
DAY_OF_WEEK_MAP.put(Calendar.THURSDAY, 3);
|
||||
DAY_OF_WEEK_MAP.put(Calendar.FRIDAY, 4);
|
||||
DAY_OF_WEEK_MAP.put(Calendar.SATURDAY, 5);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,385 @@
|
||||
package cn.nahco3awa.naouc.ui.ouc;
|
||||
|
||||
import static android.content.Context.MODE_PRIVATE;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
import com.google.zxing.WriterException;
|
||||
import com.google.zxing.common.BitMatrix;
|
||||
import com.journeyapps.barcodescanner.BarcodeEncoder;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Locale;
|
||||
import java.util.Random;
|
||||
|
||||
import cn.nahco3awa.naouc.R;
|
||||
import cn.nahco3awa.naouc.databinding.FragmentOucBinding;
|
||||
import cn.nahco3awa.naouc.network.ouc.OUCRequestSender;
|
||||
import cn.nahco3awa.naouc.network.ouc.request.GetBarCodePayOUCRequest;
|
||||
import cn.nahco3awa.naouc.network.ouc.request.GetCardAccInfoOUCRequest;
|
||||
import cn.nahco3awa.naouc.network.ouc.request.GetInfoByTokenOUCRequest;
|
||||
import cn.nahco3awa.naouc.network.ouc.request.NetCheckOUCRequest;
|
||||
import cn.nahco3awa.naouc.network.ouc.request.TsmOUCRequest;
|
||||
import cn.nahco3awa.naouc.network.ouc.request.WaterApiAccUseHzWatchRequest;
|
||||
import cn.nahco3awa.naouc.network.ouc.response.GetBarCodePayOUCResponse;
|
||||
import cn.nahco3awa.naouc.network.ouc.response.GetCardAccInfoOUCResponse;
|
||||
import cn.nahco3awa.naouc.network.ouc.response.GetInfoByTokenOUCResponse;
|
||||
import cn.nahco3awa.naouc.network.ouc.response.OUCCallback;
|
||||
import cn.nahco3awa.naouc.network.ouc.response.TsmOUCResponse;
|
||||
import cn.nahco3awa.naouc.network.ouc.response.WaterApiAccUseHzWatchResponse;
|
||||
import cn.nahco3awa.naouc.ui.ouc.activity.OucBalanceActivity;
|
||||
import cn.nahco3awa.naouc.ui.ouc.activity.OucLoginMainActivity;
|
||||
import cn.nahco3awa.naouc.ui.ouc.activity.OucNetActivity;
|
||||
import cn.nahco3awa.naouc.ui.ouc.activity.OucWaterActivity;
|
||||
import okhttp3.Call;
|
||||
import okhttp3.Callback;
|
||||
import okhttp3.Response;
|
||||
|
||||
public class OUCFragment extends Fragment {
|
||||
private SharedPreferences preferences;
|
||||
private FragmentOucBinding binding;
|
||||
private String sourceType = null;
|
||||
private Button loginButton;
|
||||
private TextView welcomeTextView;
|
||||
private ActivityResultLauncher<Intent> loginLauncher;
|
||||
private ImageView barcodeImageView;
|
||||
private ImageView qrCodeImageView;
|
||||
private TextView balanceTextView;
|
||||
private TextView netBalanceTextView;
|
||||
private TextView waterAvailableTextView;
|
||||
private ImageView netBalanceImageView;
|
||||
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
binding = FragmentOucBinding.inflate(inflater, container, false);
|
||||
View root = binding.getRoot();
|
||||
Context context = root.getContext();
|
||||
|
||||
preferences = context.getSharedPreferences("ouc", MODE_PRIVATE);
|
||||
if (!preferences.contains("imei")) {
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
Random random = new Random();
|
||||
for (int i = 0; i < 32; i++) {
|
||||
stringBuilder.append(random.nextInt(10));
|
||||
}
|
||||
preferences.edit()
|
||||
.putString("imei", stringBuilder.toString())
|
||||
.apply();
|
||||
}
|
||||
OUCRequestSender.init(preferences.getString("imei", "1145141919810deadbeef52013149922"));
|
||||
|
||||
loginLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
|
||||
if (result.getResultCode() == Activity.RESULT_OK) {
|
||||
refreshLogonState();
|
||||
}
|
||||
});
|
||||
|
||||
loginButton = root.findViewById(R.id.oucMainLoginButton);
|
||||
welcomeTextView = root.findViewById(R.id.oucMainWelcomeTextView);
|
||||
barcodeImageView = root.findViewById(R.id.oucBarcodeImageView);
|
||||
qrCodeImageView = root.findViewById(R.id.qrCodeImageView);
|
||||
balanceTextView = root.findViewById(R.id.balanceTextView);
|
||||
netBalanceTextView = root.findViewById(R.id.netBalanceTextView);
|
||||
netBalanceImageView = root.findViewById(R.id.netImage);
|
||||
waterAvailableTextView = root.findViewById(R.id.waterBalanceTextView);
|
||||
|
||||
loginButton.setOnClickListener(this::onClickLogin);
|
||||
welcomeTextView.setOnClickListener(this::onClickWelcomeText);
|
||||
barcodeImageView.setOnClickListener(this::onClickRefreshPayCode);
|
||||
qrCodeImageView.setOnClickListener(this::onClickRefreshPayCode);
|
||||
root.findViewById(R.id.cashButton).setOnClickListener(this::onClickBalance);
|
||||
root.findViewById(R.id.netButton).setOnClickListener(this::onClickNet);
|
||||
root.findViewById(R.id.waterButton).setOnClickListener(this::onClickWater);
|
||||
|
||||
refreshLogonState();
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
private GetInfoByTokenOUCResponse infoResponse = null;
|
||||
|
||||
public void refreshLogonState() {
|
||||
if (isLogon()) {
|
||||
loginButton.setText("登出");
|
||||
sourceType = preferences.getString("source_ticket", "");
|
||||
OUCRequestSender.getInstance().setSourceTypeTicket(sourceType);
|
||||
OUCRequestSender.getInstance().getInfoByToken(new GetInfoByTokenOUCRequest(OUCRequestSender.getInstance().getImeiTicket(), sourceType, sourceType), new OUCCallback<>() {
|
||||
@Override
|
||||
public void onSuccess(GetInfoByTokenOUCResponse response) {
|
||||
infoResponse = response;
|
||||
requireActivity().runOnUiThread(() -> {
|
||||
refreshWelcomeText();
|
||||
refreshPayCode();
|
||||
refreshBalance();
|
||||
refreshNetBalance();
|
||||
refreshAvailableWater();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable e) {
|
||||
requireActivity().runOnUiThread(() -> {
|
||||
Toast.makeText(getActivity(), "获取个人信息失败!", Toast.LENGTH_SHORT).show();
|
||||
welcomeTextView.setText("可能需要重新登录?");
|
||||
if (e.getMessage() != null && e.getMessage().equals("令牌失效")) {
|
||||
preferences.edit()
|
||||
.putBoolean("logon", false)
|
||||
.apply();
|
||||
refreshLogonState();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
loginButton.setText("登录");
|
||||
welcomeTextView.setText("尚未登录");
|
||||
}
|
||||
}
|
||||
|
||||
private void onClickRefreshPayCode(View view) {
|
||||
if (isLogon() && infoResponse != null) {
|
||||
refreshPayCode();
|
||||
refreshBalance();
|
||||
refreshNetBalance();
|
||||
refreshAvailableWater();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
refreshLogonState();
|
||||
}
|
||||
|
||||
private void refreshAvailableWater() {
|
||||
waterAvailableTextView.setText("...");
|
||||
OUCRequestSender.getInstance().waterApiAccUseHzWatch(new WaterApiAccUseHzWatchRequest(infoResponse.getAccount()), new OUCCallback<>() {
|
||||
@Override
|
||||
public void onSuccess(WaterApiAccUseHzWatchResponse response) {
|
||||
requireActivity().runOnUiThread(() -> waterAvailableTextView.setText(response.getData().size() + " 可用"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable e) {
|
||||
requireActivity().runOnUiThread(() -> waterAvailableTextView.setText("获取失败"));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void refreshNetBalance() {
|
||||
netBalanceTextView.setText("...");
|
||||
if (OUCRequestSender.getInstance().getjSessionId().isEmpty()) {
|
||||
OUCRequestSender.getInstance().sendRequest(new NetCheckOUCRequest(), new Callback() {
|
||||
@Override
|
||||
public void onFailure(@NonNull Call call, @NonNull IOException e) {
|
||||
requireActivity().runOnUiThread(() -> netBalanceTextView.setText("获取失败"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(@NonNull Call call, @NonNull Response response) {
|
||||
refreshNetByTsm();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
refreshNetByTsm();
|
||||
}
|
||||
}
|
||||
|
||||
private void refreshNetByTsm() {
|
||||
String account = infoResponse.getAccount();
|
||||
OUCRequestSender.getInstance().tsm(new TsmOUCRequest(account, infoResponse.getSno()), new OUCCallback<>() {
|
||||
@Override
|
||||
public void onSuccess(TsmOUCResponse response) {
|
||||
requireActivity().runOnUiThread(() -> {
|
||||
int redColor = 0xFFF44336;
|
||||
if (response.isFrozen()) {
|
||||
netBalanceTextView.setText("停机");
|
||||
netBalanceImageView.setColorFilter(redColor, PorterDuff.Mode.MULTIPLY);
|
||||
} else {
|
||||
netBalanceTextView.setText(String.format(Locale.SIMPLIFIED_CHINESE, "%.2f", response.getBalance()));
|
||||
netBalanceImageView.setColorFilter(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable e) {
|
||||
requireActivity().runOnUiThread(() -> {
|
||||
netBalanceTextView.setText("获取失败");
|
||||
new androidx.appcompat.app.AlertDialog.Builder(requireActivity())
|
||||
.setTitle("网费详情获取失败")
|
||||
.setMessage(e.getMessage())
|
||||
.show();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void refreshBalance() {
|
||||
String account = infoResponse.getAccount();
|
||||
balanceTextView.setText("...");
|
||||
OUCRequestSender.getInstance().getCardAccInfo(new GetCardAccInfoOUCRequest(account), new OUCCallback<>() {
|
||||
@Override
|
||||
public void onSuccess(GetCardAccInfoOUCResponse response) {
|
||||
requireActivity().runOnUiThread(() -> balanceTextView.setText(String.format(Locale.SIMPLIFIED_CHINESE, "%.2f", response.getBalance() / 100.0)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable e) {
|
||||
requireActivity().runOnUiThread(() -> balanceTextView.setText("获取失败"));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void refreshPayCode() {
|
||||
String account = infoResponse.getAccount();
|
||||
|
||||
try {
|
||||
GetBarCodePayOUCRequest getBarCodePayOUCRequest = new GetBarCodePayOUCRequest(account, "1", OUCRequestSender.getInstance().getImeiTicket(), OUCRequestSender.getInstance().getSourceTypeTicket());
|
||||
OUCRequestSender.getInstance().getBarCodePay(getBarCodePayOUCRequest, new OUCCallback<>() {
|
||||
@Override
|
||||
public void onSuccess(GetBarCodePayOUCResponse response) {
|
||||
try {
|
||||
requireActivity().runOnUiThread(() -> {
|
||||
try {
|
||||
BarcodeFormat barcodeFormat = BarcodeFormat.CODE_128;
|
||||
BarcodeEncoder barcodeEncoder = new BarcodeEncoder();
|
||||
BitMatrix bitMatrix = barcodeEncoder.encode(response.getBarcode()[0], barcodeFormat, barcodeImageView.getWidth(), barcodeImageView.getHeight());
|
||||
Bitmap barcodeBitmap = barcodeEncoder.createBitmap(bitMatrix);
|
||||
barcodeImageView.setImageBitmap(barcodeBitmap);
|
||||
|
||||
bitMatrix = barcodeEncoder.encode(response.getBarcode()[0], BarcodeFormat.QR_CODE, qrCodeImageView.getWidth(), qrCodeImageView.getHeight());
|
||||
Bitmap qrBitmap = barcodeEncoder.createBitmap(bitMatrix);
|
||||
qrCodeImageView.setImageBitmap(qrBitmap);
|
||||
} catch (WriterException e) {
|
||||
requireActivity().runOnUiThread(() -> new AlertDialog.Builder(requireActivity())
|
||||
.setTitle("显示支付码错误!")
|
||||
.setMessage(e.getMessage())
|
||||
.setNegativeButton("蒿", null)
|
||||
.show());
|
||||
}
|
||||
|
||||
});
|
||||
} catch (Exception e) {
|
||||
requireActivity().runOnUiThread(() -> new AlertDialog.Builder(requireActivity())
|
||||
.setTitle("显示支付码错误!")
|
||||
.setMessage(e.getMessage())
|
||||
.setNegativeButton("蒿", null)
|
||||
.show());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable e) {
|
||||
requireActivity().runOnUiThread(() -> new AlertDialog.Builder(requireActivity())
|
||||
.setTitle("获取支付码错误!")
|
||||
.setMessage(e.getMessage())
|
||||
.setNegativeButton("蒿", null)
|
||||
.show());
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
requireActivity().runOnUiThread(() -> new AlertDialog.Builder(requireActivity())
|
||||
.setTitle("获取支付码错误!")
|
||||
.setMessage(e.getMessage())
|
||||
.setNegativeButton("蒿", null)
|
||||
.show());
|
||||
}
|
||||
}
|
||||
|
||||
private void onClickWater(View view) {
|
||||
if (isLogon() && infoResponse != null) {
|
||||
Intent intent = new Intent(getActivity(), OucWaterActivity.class);
|
||||
intent.putExtra("account", infoResponse.getAccount());
|
||||
startActivity(intent);
|
||||
}
|
||||
}
|
||||
|
||||
private void onClickBalance(View view) {
|
||||
if (isLogon() && infoResponse != null) {
|
||||
Intent intent = new Intent(getActivity(), OucBalanceActivity.class);
|
||||
intent.putExtra("account", infoResponse.getAccount());
|
||||
startActivity(intent);
|
||||
}
|
||||
}
|
||||
|
||||
private void onClickNet(View view) {
|
||||
if (isLogon() && infoResponse != null) {
|
||||
Intent intent = new Intent(getActivity(), OucNetActivity.class);
|
||||
intent.putExtra("account", infoResponse.getAccount());
|
||||
intent.putExtra("sno", infoResponse.getSno());
|
||||
startActivity(intent);
|
||||
}
|
||||
}
|
||||
|
||||
private void refreshWelcomeText() {
|
||||
if (isLogon()) {
|
||||
welcomeTextView.setText("欢迎回来," + getName() + "~");
|
||||
} else {
|
||||
welcomeTextView.setText("尚未登录");
|
||||
}
|
||||
}
|
||||
|
||||
private String getName() {
|
||||
return preferences.getString("nickname", infoResponse == null ? "" : infoResponse.getName());
|
||||
}
|
||||
|
||||
public boolean isLogon() {
|
||||
return preferences.getBoolean("logon",false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
binding = null;
|
||||
}
|
||||
|
||||
public void onClickLogin(View view) {
|
||||
if (isLogon()) {
|
||||
preferences.edit()
|
||||
.putBoolean("logon", false)
|
||||
.apply();
|
||||
refreshLogonState();
|
||||
} else {
|
||||
loginLauncher.launch(new Intent(getActivity(), OucLoginMainActivity.class));
|
||||
}
|
||||
}
|
||||
|
||||
private void onClickWelcomeText(View view) {
|
||||
EditText editText = new EditText(requireContext());
|
||||
editText.setHint("输出昵称...");
|
||||
String nick = preferences.getString("nickname", infoResponse == null ? "" : infoResponse.getName());
|
||||
editText.setText(nick);
|
||||
new androidx.appcompat.app.AlertDialog.Builder(requireActivity())
|
||||
.setTitle("设置昵称:")
|
||||
.setView(editText)
|
||||
.setNegativeButton("取消", null)
|
||||
.setPositiveButton("应用", (dialogInterface, i) -> {
|
||||
preferences.edit()
|
||||
.putString("nickname", editText.getText().toString())
|
||||
.apply();
|
||||
refreshWelcomeText();
|
||||
})
|
||||
.show();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
package cn.nahco3awa.naouc.ui.ouc.activity;
|
||||
|
||||
import static android.view.View.INVISIBLE;
|
||||
import static android.view.View.VISIBLE;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.text.InputType;
|
||||
import android.view.View;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Locale;
|
||||
|
||||
import cn.nahco3awa.naouc.R;
|
||||
import cn.nahco3awa.naouc.network.ouc.OUCRequestSender;
|
||||
import cn.nahco3awa.naouc.network.ouc.request.AccountPayAliPayOUCRequest;
|
||||
import cn.nahco3awa.naouc.network.ouc.request.GetCardAccInfoOUCRequest;
|
||||
import cn.nahco3awa.naouc.network.ouc.request.GetMyBillOUCRequest;
|
||||
import cn.nahco3awa.naouc.network.ouc.response.AccountPayOUCResponse;
|
||||
import cn.nahco3awa.naouc.network.ouc.response.GetCardAccInfoOUCResponse;
|
||||
import cn.nahco3awa.naouc.network.ouc.response.GetMyBillOUCResponse;
|
||||
import cn.nahco3awa.naouc.network.ouc.response.OUCCallback;
|
||||
import cn.nahco3awa.naouc.ui.ouc.view.ItemMyBillAdapter;
|
||||
|
||||
public class OucBalanceActivity extends AppCompatActivity {
|
||||
private String account;
|
||||
private TextView balanceTextView;
|
||||
private RecyclerView myBillView;
|
||||
private ItemMyBillAdapter adapt = new ItemMyBillAdapter(new ArrayList<>());
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_ouc_balance);
|
||||
|
||||
Intent intent = getIntent();
|
||||
account = intent.getStringExtra("account");
|
||||
|
||||
balanceTextView = findViewById(R.id.balanceBigTextView);
|
||||
|
||||
myBillView = findViewById(R.id.myBillListView);
|
||||
myBillView.setVisibility(INVISIBLE);
|
||||
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
|
||||
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
|
||||
myBillView.setLayoutManager(layoutManager);
|
||||
myBillView.setAdapter(adapt);
|
||||
|
||||
refreshBalance();
|
||||
refreshMyBill();
|
||||
}
|
||||
|
||||
private void refreshMyBill() {
|
||||
myBillView.setVisibility(INVISIBLE);
|
||||
OUCRequestSender.getInstance().getMyBill(new GetMyBillOUCRequest(account, 1), new OUCCallback<>() {
|
||||
@Override
|
||||
public void onSuccess(GetMyBillOUCResponse response) {
|
||||
runOnUiThread(() -> {
|
||||
adapt = new ItemMyBillAdapter(response.getBillData());
|
||||
myBillView.setAdapter(adapt);
|
||||
myBillView.setVisibility(VISIBLE);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable e) {
|
||||
myBillView.setVisibility(INVISIBLE);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void refreshBalance() {
|
||||
OUCRequestSender.getInstance().getCardAccInfo(new GetCardAccInfoOUCRequest(account), new OUCCallback<>() {
|
||||
@Override
|
||||
public void onSuccess(GetCardAccInfoOUCResponse response) {
|
||||
runOnUiThread(() -> balanceTextView.setText(String.format(Locale.SIMPLIFIED_CHINESE, "%.2f", response.getBalance() / 100.0)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable e) {
|
||||
runOnUiThread(() -> Toast.makeText(OucBalanceActivity.this, "获取余额失败!", Toast.LENGTH_SHORT).show());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void onClickPay(View view) {
|
||||
EditText editText = new EditText(this);
|
||||
editText.setHint("请输入金额...");
|
||||
editText.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL);
|
||||
new AlertDialog.Builder(this)
|
||||
.setTitle("充值")
|
||||
.setView(editText)
|
||||
.setNegativeButton("取消", null)
|
||||
.setPositiveButton("充值", (dialogInterface, i) -> {
|
||||
String amountString = editText.getText().toString();
|
||||
double amount = Double.parseDouble(amountString) * 100;
|
||||
String parsedAmount = String.valueOf((int)amount);
|
||||
OUCRequestSender.getInstance().accountPayAlipay(new AccountPayAliPayOUCRequest(account, parsedAmount), new OUCCallback<>() {
|
||||
@Override
|
||||
public void onSuccess(AccountPayOUCResponse response) {
|
||||
runOnUiThread(() -> {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(response.getUrl()));
|
||||
startActivity(intent);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable e) {
|
||||
runOnUiThread(() -> Toast.makeText(OucBalanceActivity.this, "下单失败!", Toast.LENGTH_SHORT).show());
|
||||
}
|
||||
});
|
||||
})
|
||||
.show();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
package cn.nahco3awa.naouc.ui.ouc.activity;
|
||||
|
||||
import static android.widget.Toast.LENGTH_SHORT;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.PublicKey;
|
||||
import java.security.spec.RSAPublicKeySpec;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
|
||||
import cn.nahco3awa.naouc.R;
|
||||
import cn.nahco3awa.naouc.network.ouc.OUCRequestSender;
|
||||
import cn.nahco3awa.naouc.network.ouc.request.GetRsaOUCRequest;
|
||||
import cn.nahco3awa.naouc.network.ouc.request.GetValidateCodeOUCRequest;
|
||||
import cn.nahco3awa.naouc.network.ouc.request.LoginOUCRequest;
|
||||
import cn.nahco3awa.naouc.network.ouc.response.GetRsaKeyOUCResponse;
|
||||
import cn.nahco3awa.naouc.network.ouc.response.GetValidateCodeOUCResponse;
|
||||
import cn.nahco3awa.naouc.network.ouc.response.LoginOUCResponse;
|
||||
import cn.nahco3awa.naouc.network.ouc.response.OUCCallback;
|
||||
|
||||
public class OucLoginMainActivity extends AppCompatActivity {
|
||||
|
||||
private SharedPreferences preferences;
|
||||
private EditText snoEdit;
|
||||
private EditText passwordEdit;
|
||||
private EditText ysmEdit;
|
||||
private CheckBox rememberCheck;
|
||||
private ImageView ysmImageView;
|
||||
private Button loginButton;
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_ouc_login_main);
|
||||
|
||||
snoEdit = findViewById(R.id.editTextOucSno);
|
||||
passwordEdit = findViewById(R.id.editTextOucPassword);
|
||||
ysmEdit = findViewById(R.id.editTextOucYsm);
|
||||
rememberCheck = findViewById(R.id.checkBoxOucRemember);
|
||||
ysmImageView = findViewById(R.id.oucYsmImageView);
|
||||
loginButton = findViewById(R.id.buttonOucLogin);
|
||||
|
||||
preferences = getSharedPreferences("ouc", MODE_PRIVATE);
|
||||
if (preferences.getBoolean("mem", false)) {
|
||||
snoEdit.setText(preferences.getString("mem_sno", ""));
|
||||
passwordEdit.setText(preferences.getString("mem_pwd", ""));
|
||||
rememberCheck.setChecked(true);
|
||||
}
|
||||
|
||||
getLoginNeeds();
|
||||
}
|
||||
|
||||
private void getLoginNeeds() {
|
||||
loginButton.setEnabled(false);
|
||||
refreshYsmCode();
|
||||
}
|
||||
|
||||
private void refreshYsmCode() {
|
||||
OUCRequestSender.getInstance().getValidateCode(new GetValidateCodeOUCRequest(System.currentTimeMillis() + 1000 * 60 * 5), new OUCCallback<>() {
|
||||
@Override
|
||||
public void onSuccess(GetValidateCodeOUCResponse response) {
|
||||
runOnUiThread(() -> {
|
||||
ysmImageView.setImageBitmap(response.getImage());
|
||||
loginButton.setEnabled(true);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable e) {
|
||||
runOnUiThread(() -> {
|
||||
Toast.makeText(OucLoginMainActivity.this, "网络连接有点问题,请重试", LENGTH_SHORT).show();
|
||||
new AlertDialog.Builder(OucLoginMainActivity.this)
|
||||
.setTitle("错误")
|
||||
.setMessage("网络错误:\n" + e.getMessage())
|
||||
.setNegativeButton("好", null)
|
||||
.show();
|
||||
});
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void onLoginFailed(Throwable e) {
|
||||
new AlertDialog.Builder(this)
|
||||
.setTitle("登录失败……")
|
||||
.setMessage("中国海洋大学门户登录失败,请稍后再试。\n" + e.getMessage())
|
||||
.setNegativeButton("好", null)
|
||||
.show();
|
||||
refreshYsmCode();
|
||||
}
|
||||
|
||||
public void onClickLogin(View view) {
|
||||
loginButton.setEnabled(false);
|
||||
OUCRequestSender.getInstance().getRsaKey(new GetRsaOUCRequest(), new OUCCallback<>() {
|
||||
@Override
|
||||
public void onSuccess(GetRsaKeyOUCResponse response) {
|
||||
try {
|
||||
String pwd = passwordEdit.getText().toString();
|
||||
BigInteger bigExpo = new BigInteger(response.getE(), 16);
|
||||
BigInteger bigModulus = new BigInteger(response.getMod(), 16);
|
||||
RSAPublicKeySpec keySpec = new RSAPublicKeySpec(bigModulus, bigExpo);
|
||||
KeyFactory factory = KeyFactory.getInstance("RSA");
|
||||
PublicKey publicKey = factory.generatePublic(keySpec);
|
||||
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
|
||||
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
|
||||
byte[] light = pwd.getBytes(StandardCharsets.UTF_8);
|
||||
byte[] encrypted = cipher.doFinal(light);
|
||||
StringBuilder builder = new StringBuilder(encrypted.length * 2);
|
||||
for (byte b : encrypted) {
|
||||
String hexB = Integer.toHexString(b & 0xFF);
|
||||
if (hexB.length() == 1) {
|
||||
hexB = "0" + hexB;
|
||||
}
|
||||
builder.append(hexB);
|
||||
}
|
||||
String encryptedHex = builder.toString();
|
||||
OUCRequestSender.getInstance().login(new LoginOUCRequest(snoEdit.getText().toString(), encryptedHex, rememberCheck.isChecked(), "8898", ysmEdit.getText().toString(), response.getMsg()), new OUCCallback<>() {
|
||||
@Override
|
||||
public void onSuccess(LoginOUCResponse loginResponse) {
|
||||
runOnUiThread(() -> {
|
||||
if (rememberCheck.isChecked()) {
|
||||
preferences.edit()
|
||||
.putString("mem_sno", loginResponse.getSno())
|
||||
.putString("mem_pwd", pwd)
|
||||
.apply();
|
||||
}
|
||||
preferences.edit()
|
||||
.putString("source_ticket", loginResponse.getRescouseType())
|
||||
.putBoolean("mem", rememberCheck.isChecked())
|
||||
.putBoolean("logon", true)
|
||||
.putString("sno", loginResponse.getSno())
|
||||
.apply();
|
||||
String name = preferences.getString("nickname", loginResponse.getName());
|
||||
Toast.makeText(OucLoginMainActivity.this, name + ",欢迎回来~", LENGTH_SHORT).show();
|
||||
setResult(Activity.RESULT_OK);
|
||||
finish();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable e) {
|
||||
runOnUiThread(() -> OucLoginMainActivity.this.onLoginFailed(e));
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
runOnUiThread(() -> OucLoginMainActivity.this.onLoginFailed(e));
|
||||
Log.e("OUCLogin", "Login failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable e) {
|
||||
runOnUiThread(() -> OucLoginMainActivity.this.onLoginFailed(e));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,195 @@
|
||||
package cn.nahco3awa.naouc.ui.ouc.activity;
|
||||
|
||||
import static android.widget.Toast.LENGTH_SHORT;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.net.Uri;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.os.Bundle;
|
||||
import android.text.InputType;
|
||||
import android.view.View;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Locale;
|
||||
|
||||
import cn.nahco3awa.naouc.R;
|
||||
import cn.nahco3awa.naouc.network.ouc.OUCRequestSender;
|
||||
import cn.nahco3awa.naouc.network.ouc.request.NetGdcOUCRequest;
|
||||
import cn.nahco3awa.naouc.network.ouc.request.TsmOUCRequest;
|
||||
import cn.nahco3awa.naouc.network.ouc.response.NetGdcOUCResponse;
|
||||
import cn.nahco3awa.naouc.network.ouc.response.OUCCallback;
|
||||
import cn.nahco3awa.naouc.network.ouc.response.TsmOUCResponse;
|
||||
import okhttp3.Call;
|
||||
import okhttp3.Callback;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
|
||||
public class OucNetActivity extends AppCompatActivity {
|
||||
private TextView netStatusTextView;
|
||||
private TextView netBalanceTextView;
|
||||
private String account;
|
||||
private String sno;
|
||||
private SharedPreferences preferences;
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_ouc_net);
|
||||
Intent intent = getIntent();
|
||||
account = intent.getStringExtra("account");
|
||||
sno = intent.getStringExtra("sno");
|
||||
netStatusTextView = findViewById(R.id.netStatusTextView);
|
||||
netBalanceTextView = findViewById(R.id.netBalanceBigTextView);
|
||||
refreshBalance();
|
||||
preferences = getSharedPreferences("net", MODE_PRIVATE);
|
||||
}
|
||||
|
||||
private void refreshBalance() {
|
||||
OUCRequestSender.getInstance().tsm(new TsmOUCRequest(account, sno), new OUCCallback<>() {
|
||||
@Override
|
||||
public void onSuccess(TsmOUCResponse response) {
|
||||
runOnUiThread(() -> {
|
||||
netBalanceTextView.setText(String.format(Locale.SIMPLIFIED_CHINESE, "%.2f", response.getBalance()));
|
||||
netStatusTextView.setText(response.isFrozen() ? "校园网停机" : "校园网余额");
|
||||
if (response.isFrozen()) netStatusTextView.setTextColor(0xFFF44336);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable e) {
|
||||
runOnUiThread(() -> {
|
||||
netStatusTextView.setText("查询失败");
|
||||
netBalanceTextView.setText("");
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void onClickPay(View view) {
|
||||
EditText editText = new EditText(this);
|
||||
editText.setHint("请输入金额(元):");
|
||||
editText.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL);
|
||||
new AlertDialog.Builder(this)
|
||||
.setTitle("网费缴纳")
|
||||
.setView(editText)
|
||||
.setNegativeButton("取消", null)
|
||||
.setPositiveButton("缴纳", (dialog, which) -> {
|
||||
String amountString = editText.getText().toString();
|
||||
double amount = Double.parseDouble(amountString) * 100;
|
||||
OUCRequestSender.getInstance().netGdc(new NetGdcOUCRequest(account, sno, (int) amount), new OUCCallback<>() {
|
||||
@Override
|
||||
public void onSuccess(NetGdcOUCResponse response) {
|
||||
runOnUiThread(() -> {
|
||||
if (response.getRetCode() == 0) {
|
||||
Toast.makeText(OucNetActivity.this, "缴费成功~", LENGTH_SHORT).show();
|
||||
refreshBalance();
|
||||
} else {
|
||||
Toast.makeText(OucNetActivity.this, "缴费失败:" + response.getErrMessage(), LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable e) {
|
||||
runOnUiThread(() -> Toast.makeText(OucNetActivity.this, "缴费失败!", LENGTH_SHORT).show());
|
||||
}
|
||||
});
|
||||
})
|
||||
.show();
|
||||
}
|
||||
|
||||
public void onClickLogin(View view) {
|
||||
String password = preferences.getString("password", "");
|
||||
if (password.isEmpty()) {
|
||||
EditText editText = new EditText(this);
|
||||
editText.setHint("请输入校园网密码...");
|
||||
editText.setAutofillHints(View.AUTOFILL_HINT_PASSWORD);
|
||||
editText.setInputType(InputType.TYPE_TEXT_VARIATION_PASSWORD);
|
||||
new AlertDialog.Builder(this)
|
||||
.setTitle("校园网认证")
|
||||
.setView(editText)
|
||||
.setNegativeButton("登录", (dialogInterface, i) -> {
|
||||
preferences.edit()
|
||||
.putString("password", editText.getText().toString())
|
||||
.apply();
|
||||
onClickLogin(null);
|
||||
})
|
||||
.show();
|
||||
return;
|
||||
}
|
||||
WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(WIFI_SERVICE);
|
||||
int iip = wifiManager.getConnectionInfo().getIpAddress();
|
||||
String ip = String.format(
|
||||
Locale.SIMPLIFIED_CHINESE,
|
||||
"%d.%d.%d.%d",
|
||||
(iip & 0xff),
|
||||
(iip >> 8 & 0xff),
|
||||
(iip >> 16 & 0xff),
|
||||
(iip >> 24 & 0xff)
|
||||
);
|
||||
OkHttpClient client = new OkHttpClient();
|
||||
var request = new Request.Builder()
|
||||
.url(String.format(
|
||||
Locale.SIMPLIFIED_CHINESE,
|
||||
"https://wxrz.ouc.edu.cn:802/eportal/portal/login?&callback=dr1003&login_method=1&user_account=%s&user_password=%s&wlan_user_ip=%s&wlan_user_ipv6=&wlan_user_mac=000000000000&wlan_ac_ip=&wlan_ac_name=&jsVersion=4.1&terminal_type=1&lang=zh-cn&v=3288&lang=zh",
|
||||
sno, password, ip
|
||||
))
|
||||
.get()
|
||||
.build();
|
||||
client.newCall(request).enqueue(new Callback() {
|
||||
@Override
|
||||
public void onFailure(@NonNull Call call, @NonNull IOException e) {
|
||||
Toast.makeText(OucNetActivity.this, "登录失败,请检查校园网连接!", LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
|
||||
var resp = response.body().string();
|
||||
|
||||
if (!resp.startsWith("dr1003(") || !resp.endsWith(");")) {
|
||||
Toast.makeText(OucNetActivity.this, "登录失败,响应异常!", LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
|
||||
resp = resp.substring(7, resp.length() - 2);
|
||||
JsonObject jsonObject = JsonParser.parseString(resp).getAsJsonObject();
|
||||
|
||||
int result = jsonObject.get("result").getAsInt();
|
||||
String msg = jsonObject.get("msg").getAsString();
|
||||
if (result == 1) {
|
||||
Toast.makeText(OucNetActivity.this, "校园网登录成功~", LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
|
||||
int code = jsonObject.get("ret_code").getAsInt();
|
||||
if (code == 2) {
|
||||
Toast.makeText(OucNetActivity.this, "您已经在线啦~", LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
|
||||
new AlertDialog.Builder(OucNetActivity.this)
|
||||
.setTitle("校园网登录失败...")
|
||||
.setMessage(msg)
|
||||
.setNegativeButton("好吧", null)
|
||||
.setPositiveButton("再试一次", (dialogInterface, i) -> onClickLogin(null))
|
||||
.show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void onClickOfficial(View view) {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://222.195.158.36/Self/"));
|
||||
startActivity(intent);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package cn.nahco3awa.naouc.ui.ouc.activity;
|
||||
|
||||
import static android.view.View.INVISIBLE;
|
||||
import static android.view.View.VISIBLE;
|
||||
import static android.widget.Toast.LENGTH_SHORT;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import cn.nahco3awa.naouc.R;
|
||||
import cn.nahco3awa.naouc.network.ouc.OUCRequestSender;
|
||||
import cn.nahco3awa.naouc.network.ouc.request.WaterApiAccUseHzWatchRequest;
|
||||
import cn.nahco3awa.naouc.network.ouc.response.OUCCallback;
|
||||
import cn.nahco3awa.naouc.network.ouc.response.WaterApiAccUseHzWatchResponse;
|
||||
import cn.nahco3awa.naouc.ui.ouc.view.ItemWaterAdapter;
|
||||
|
||||
public class OucWaterActivity extends AppCompatActivity {
|
||||
private String account = null;
|
||||
private RecyclerView waterListView;
|
||||
private ItemWaterAdapter adapter;
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_ouc_water);
|
||||
|
||||
Intent intent = getIntent();
|
||||
account = intent.getStringExtra("account");
|
||||
adapter = new ItemWaterAdapter(new ArrayList<>(), account, this);
|
||||
|
||||
waterListView = findViewById(R.id.waterListView);
|
||||
waterListView.setVisibility(INVISIBLE);
|
||||
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
|
||||
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
|
||||
waterListView.setLayoutManager(layoutManager);
|
||||
waterListView.setAdapter(adapter);
|
||||
|
||||
refreshWaterList();
|
||||
}
|
||||
|
||||
private void refreshWaterList() {
|
||||
waterListView.setVisibility(INVISIBLE);
|
||||
OUCRequestSender.getInstance().waterApiAccUseHzWatch(new WaterApiAccUseHzWatchRequest(account), new OUCCallback<>() {
|
||||
@Override
|
||||
public void onSuccess(WaterApiAccUseHzWatchResponse response) {
|
||||
runOnUiThread(() -> {
|
||||
adapter = new ItemWaterAdapter(response.getData(), account, OucWaterActivity.this);
|
||||
waterListView.setAdapter(adapter);
|
||||
waterListView.setVisibility(VISIBLE);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable e) {
|
||||
runOnUiThread(() -> {
|
||||
waterListView.setVisibility(INVISIBLE);
|
||||
Toast.makeText(OucWaterActivity.this, "刷新列表失败:" + e.getMessage(), LENGTH_SHORT).show();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
refreshWaterList();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
package cn.nahco3awa.naouc.ui.ouc.view;
|
||||
|
||||
import android.graphics.PorterDuff;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import cn.nahco3awa.naouc.R;
|
||||
import cn.nahco3awa.naouc.network.ouc.response.data.SingleBillData;
|
||||
|
||||
public class ItemMyBillAdapter extends RecyclerView.Adapter<ItemMyBillAdapter.ViewHolder> {
|
||||
private final List<SingleBillData> billData;
|
||||
|
||||
public ItemMyBillAdapter(List<SingleBillData> billData) {
|
||||
this.billData = billData;
|
||||
}
|
||||
|
||||
@NonNull @Override
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.cell_my_bill, parent, false);
|
||||
return new ViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
||||
SingleBillData data = billData.get(position);
|
||||
holder.setData(data);
|
||||
}
|
||||
|
||||
public void addBillData(SingleBillData data) {
|
||||
billData.add(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return billData.size();
|
||||
}
|
||||
|
||||
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
private final ImageView iconImageView;
|
||||
private final TextView tranNameTextView;
|
||||
private final TextView mercnNameTextView;
|
||||
private final TextView amountTextView;
|
||||
private final TextView balanceTextView;
|
||||
private SingleBillData data = null;
|
||||
public ViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
iconImageView = itemView.findViewById(R.id.cellMyBillImageView);
|
||||
tranNameTextView = itemView.findViewById(R.id.cellMyBillTranNameTextView);
|
||||
mercnNameTextView = itemView.findViewById(R.id.cellMyBillMercnNameTextView);
|
||||
amountTextView = itemView.findViewById(R.id.cellMyBillAmountTextView);
|
||||
balanceTextView = itemView.findViewById(R.id.cellMyBillBalanceTextView);
|
||||
|
||||
itemView.setOnClickListener(view -> {
|
||||
if (data != null) {
|
||||
new AlertDialog.Builder(view.getContext())
|
||||
.setTitle("消费详情")
|
||||
.setMessage("订单时间:" + data.OCCTIME +
|
||||
"\n生效时间:" + data.EFFECTDATE +
|
||||
"\n流水金额:" + getFormat(data.TRANAMT) +
|
||||
"\n账户余额:" + getFormat(data.CARDBAL) +
|
||||
"\n支付地点:" + data.MERCNAME +
|
||||
"\n\n" + data.JDESC)
|
||||
.setNegativeButton("好",null)
|
||||
.show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setData(SingleBillData data) {
|
||||
this.data = data;
|
||||
float amt = data.TRANAMT;
|
||||
int color = amt < 0 ? 0xFFF44336 : 0xFF8BC34A;
|
||||
iconImageView.setColorFilter(color, PorterDuff.Mode.MULTIPLY);
|
||||
amountTextView.setTextColor(color);
|
||||
amountTextView.setText(getFormat(amt));
|
||||
tranNameTextView.setText(data.TRANNAME);
|
||||
mercnNameTextView.setText(data.MERCNAME);
|
||||
balanceTextView.setText("余额:" + getFormat(data.CARDBAL));
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private static String getFormat(float amt) {
|
||||
return String.format(Locale.SIMPLIFIED_CHINESE, "%.2f", amt);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
package cn.nahco3awa.naouc.ui.ouc.view;
|
||||
|
||||
import static android.widget.Toast.LENGTH_SHORT;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import cn.nahco3awa.naouc.R;
|
||||
import cn.nahco3awa.naouc.network.ouc.OUCRequestSender;
|
||||
import cn.nahco3awa.naouc.network.ouc.request.WaterApiBookCodeCancelRequest;
|
||||
import cn.nahco3awa.naouc.network.ouc.request.WaterApiBookCodeRequest;
|
||||
import cn.nahco3awa.naouc.network.ouc.response.OUCCallback;
|
||||
import cn.nahco3awa.naouc.network.ouc.response.WaterApiBookCodeCancelResponse;
|
||||
import cn.nahco3awa.naouc.network.ouc.response.WaterApiBookCodeResponse;
|
||||
import cn.nahco3awa.naouc.network.ouc.response.data.SingleWaterHzWatchData;
|
||||
|
||||
public class ItemWaterAdapter extends RecyclerView.Adapter<ItemWaterAdapter.ViewHolder> {
|
||||
private final List<SingleWaterHzWatchData> data;
|
||||
private final String account;
|
||||
private final Activity activity;
|
||||
public ItemWaterAdapter(List<SingleWaterHzWatchData> data, String account, Activity activity) {
|
||||
this.data = data;
|
||||
this.account = account;
|
||||
this.activity = activity;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.cell_ouc_water, parent, false);
|
||||
return new ViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
||||
SingleWaterHzWatchData datum = data.get(position);
|
||||
holder.setData(datum, account, activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return data.size();
|
||||
}
|
||||
|
||||
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
private final TextView nameTextView;
|
||||
private final TextView statusTextView;
|
||||
private final TextView bookTextView;
|
||||
private SingleWaterHzWatchData data = null;
|
||||
private String account = null;
|
||||
private boolean active;
|
||||
private Activity activity;
|
||||
public ViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
active = true;
|
||||
nameTextView = itemView.findViewById(R.id.cellOucWaterNameTextView);
|
||||
statusTextView = itemView.findViewById(R.id.cellOucWaterStatusTextView);
|
||||
bookTextView = itemView.findViewById(R.id.cellOucWaterBookTextView);
|
||||
|
||||
itemView.setOnClickListener(view -> {
|
||||
if (data != null && active) {
|
||||
active = false;
|
||||
if (data.Actkind() == 0) {
|
||||
// 预约请求
|
||||
OUCRequestSender.getInstance().waterApiBookCode(new WaterApiBookCodeRequest(account, data.ClassNo()), new OUCCallback<>() {
|
||||
@Override
|
||||
public void onSuccess(WaterApiBookCodeResponse response) {
|
||||
activity.runOnUiThread(() -> {
|
||||
data.setActkind(1);
|
||||
data.setBookCode(response.getBookCode());
|
||||
setData(data, account, activity);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable e) {
|
||||
activity.runOnUiThread(() -> Toast.makeText(view.getContext(), "预约失败", LENGTH_SHORT).show());
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// 取消预约
|
||||
OUCRequestSender.getInstance().waterApiBookCodeCancel(new WaterApiBookCodeCancelRequest(account, data.ClassNo()), new OUCCallback<>() {
|
||||
@Override
|
||||
public void onSuccess(WaterApiBookCodeCancelResponse response) {
|
||||
activity.runOnUiThread(() -> {
|
||||
data.setActkind(0);
|
||||
data.setBookCode("");
|
||||
setData(data, account, activity);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable e) {
|
||||
activity.runOnUiThread(() -> Toast.makeText(view.getContext(), "取消预约失败", LENGTH_SHORT).show());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setData(SingleWaterHzWatchData data, String account, Activity activity) {
|
||||
this.account = account;
|
||||
this.data = data;
|
||||
this.activity = activity;
|
||||
active = true;
|
||||
int color = (data.Actkind() == 1 || data.UseFreeRate() <= 0) ? 0xFFF44336 : 0xFF8BC34A;
|
||||
nameTextView.setText(data.ClassName());
|
||||
statusTextView.setText(String.format(Locale.SIMPLIFIED_CHINESE, "%.2f", data.UseFreeRate() / 100.0f) + "% 可用");
|
||||
bookTextView.setTextColor(color);
|
||||
bookTextView.setText(data.Actkind() == 1 ? data.BookCode() : (data.UseFreeRate() > 0 ? "可预约" : "不可用"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package cn.nahco3awa.naouc.ui.weouc;
|
||||
|
||||
import static android.content.Context.MODE_PRIVATE;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import cn.nahco3awa.naouc.databinding.FragmentWeoucBinding;
|
||||
|
||||
public class WeOUCFragment extends Fragment {
|
||||
private FragmentWeoucBinding binding;
|
||||
private Activity activity;
|
||||
private Context context;
|
||||
private View root;
|
||||
private SharedPreferences preferences;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
binding = FragmentWeoucBinding.inflate(inflater, container, true);
|
||||
activity = requireActivity();
|
||||
context = requireContext();
|
||||
root = binding.getRoot();
|
||||
|
||||
preferences = context.getSharedPreferences("weouc", MODE_PRIVATE);
|
||||
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package cn.nahco3awa.naouc.util;
|
||||
|
||||
import android.util.Base64;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Map;
|
||||
|
||||
import synjones.commerce.utils.JniQrCodeSign;
|
||||
|
||||
public class QrCodeSign {
|
||||
private static final JniQrCodeSign jniQrCodeSign = new JniQrCodeSign();
|
||||
|
||||
public static String getSign(Map<?, ?> map) {
|
||||
return jniQrCodeSign.GetSign(map);
|
||||
}
|
||||
|
||||
public static String getSign(String str) {
|
||||
return jniQrCodeSign.GetOfflineQrCode(str);
|
||||
}
|
||||
|
||||
public static String getBase64(String str) {
|
||||
return new String(Base64.decode(str, 0), StandardCharsets.UTF_8);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package cn.nahco3awa.naouc.util;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class RSASign {
|
||||
private static final String f16254a = "SHA1withRSA";
|
||||
private static final String f16256c = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDil3PZhXSwuPZZ9M4oRARVCyvNjV6Ogw2ndE+1uIzt4SAsI5SlWwp3EL37es++FWd73lLX74h5NYxrzUo+yLPc1E0eqIw6MANPtd+mAFY+SsA2FdjJN91iNorqL+HKzYGzMn3yQ8BbiNWtX3L692smTRcVsimeeNm2/EdOAddrpQIDAQAB";
|
||||
private static final String f16257d = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAOKXc9mFdLC49ln0zihEBFULK82NXo6DDad0T7W4jO3hICwjlKVbCncQvft6z74VZ3veUtfviHk1jGvNSj7Is9zUTR6ojDowA0+136YAVj5KwDYV2Mk33WI2iuov4crNgbMyffJDwFuI1a1fcvr3ayZNFxWyKZ542bb8R04B12ulAgMBAAECgYAwiEnq/DerJmK1j8acPz1CTds68p2fHpjNFg+Al5+vz7lJWvGanS5XpEFc3MgkKYd5s3vA/nAXrg1+hYDyg6BqM+lI6OHRZxPynaeQQeOiMDdTvR+pZ3b8uSx386riD1DM5d1oGRg9tMvJxQVCQU0bLrxViv2+KJf44dT3yqLJ3QJBAOwmsjpZi1BT+13IREjmdwEuTZRf7Ksffa1SvNyI+EoIpHZrM6V1w6vhRmJsENWe75qvJYy3hhem3i77O6z84oMCQQD1ow/fPTNxtM5qQKxMux3BEixp/j23ib+MIkoswmd+ARGtUEKqwnjXJWoXneXfWhMQTTJhBb5REwOEjOmv8IC3AkB09dlyMuVgHKgz07uWS6cHS7Ka2UOzoX4yePcXVzN6H3utNv02ZvRJzeJ5XsKbuwM7HqI/ZqogTsJejIoK7JkXAkAODxoudctG+8lArZju/1qxnT+rhWC0645qD+Bc9XeE77y6Rbi7G0xdTAfpeCEbCoXCzhhPE0wUSdlOsd4CMuq7AkBUD8WlEup0Ypa7oXTPGIdCOPZ+gxIWfEKBMAvi1paik+HIRfBdeaIPG1PyXrYDg8QWcZ3IrzMqLd9+jZ7XdYUF";
|
||||
public static String sign(HashMap<String, String> map) {
|
||||
String str = "";
|
||||
Object[] array = map.keySet().toArray();
|
||||
Arrays.sort(array);
|
||||
for (Object obj : array) {
|
||||
str = (obj.equals("request") || obj.equals("timestamp")) ? str + obj + URLDecoder.decode(map.get(obj), StandardCharsets.UTF_8) : str + obj + map.get(obj);
|
||||
}
|
||||
System.out.println("sourcestr=" + str);
|
||||
String strB = new SignUtils().getPrivateKey(str, f16257d, f16254a);
|
||||
System.out.println("sign=" + strB);
|
||||
return strB;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package cn.nahco3awa.naouc.util;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Base64;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
|
||||
public class SignUtils {
|
||||
public String getPrivateKey(String data, String key, String alg) {
|
||||
try {
|
||||
return new String(Base64.getEncoder().encode(SignatureUtil.getPrivateSign(data.getBytes(), Base64.getDecoder().decode(key), alg)));
|
||||
} catch (GeneralSecurityException e) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
public String sign(String s, String key, String mode) {
|
||||
Base64.Encoder encoder = Base64.getEncoder();
|
||||
try {
|
||||
return new String(encoder.encode(SymmetricCryptoUtil.encrypt(s.getBytes(StandardCharsets.UTF_8), Base64.getDecoder().decode(key), mode, Cipher.ENCRYPT_MODE)));
|
||||
} catch (NoSuchPaddingException | NoSuchAlgorithmException |
|
||||
InvalidAlgorithmParameterException | InvalidKeyException |
|
||||
IllegalBlockSizeException | BadPaddingException e) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package cn.nahco3awa.naouc.util;
|
||||
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.Signature;
|
||||
import java.security.spec.PKCS8EncodedKeySpec;
|
||||
|
||||
public class SignatureUtil {
|
||||
public static byte[] getPrivateSign(byte[] bs, byte[] bs2, String alg) throws GeneralSecurityException {
|
||||
PrivateKey privateKeyA = a(bs2, alg);
|
||||
Signature signature = Signature.getInstance(alg);
|
||||
signature.initSign(privateKeyA);
|
||||
signature.update(bs);
|
||||
return signature.sign();
|
||||
}
|
||||
|
||||
public static PrivateKey a(byte[] bArr, String str) throws GeneralSecurityException {
|
||||
return KeyFactory.getInstance(a(str, "with")).generatePrivate(new PKCS8EncodedKeySpec(bArr));
|
||||
}
|
||||
|
||||
public static String a(String str, String str2) {
|
||||
int iIndexOf;
|
||||
return (str2 == null || (iIndexOf = str.indexOf(str2)) == -1) ? "" : str.substring(iIndexOf + str2.length());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package cn.nahco3awa.naouc.util;
|
||||
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
public class SymmetricCryptoUtil {
|
||||
public static byte[] encrypt(byte[] data, byte[] key, String algorithm, int mode) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
|
||||
String finalAlgorithm = algorithm + "/CBC/PKCS5Padding";
|
||||
byte[] iv = createZeroBlock(finalAlgorithm);
|
||||
return encrypt(key, iv, finalAlgorithm, "CBC", mode).doFinal(data);
|
||||
}
|
||||
|
||||
public static Cipher encrypt(byte[] key, byte[] iv, String transformation, String algorithm, int mode) throws InvalidKeyException, InvalidAlgorithmParameterException, NoSuchPaddingException, NoSuchAlgorithmException {
|
||||
Cipher cipher = Cipher.getInstance(transformation);
|
||||
SecretKeySpec secretKeySpec = new SecretKeySpec(key, a(transformation, "/"));
|
||||
if (isEquals(algorithm, "CBC")) {
|
||||
cipher.init(mode, secretKeySpec, new IvParameterSpec(iv));
|
||||
} else {
|
||||
cipher.init(mode, secretKeySpec);
|
||||
}
|
||||
return cipher;
|
||||
}
|
||||
|
||||
public static byte[] createZeroBlock(String transformation) throws NoSuchPaddingException, NoSuchAlgorithmException {
|
||||
int blockSize = Cipher.getInstance(transformation).getBlockSize();
|
||||
return new byte[blockSize];
|
||||
}
|
||||
|
||||
public static boolean isEquals(CharSequence charSequence, CharSequence charSequence2) {
|
||||
if (charSequence == charSequence2) {
|
||||
return true;
|
||||
}
|
||||
if (charSequence == null || charSequence2 == null) {
|
||||
return false;
|
||||
}
|
||||
if ((charSequence instanceof String) && (charSequence2 instanceof String)) {
|
||||
return charSequence.equals(charSequence2);
|
||||
}
|
||||
return charSequence.equals(charSequence2);
|
||||
}
|
||||
|
||||
public static String a(String str, String str2) {
|
||||
if (str == null || str2 == null) {
|
||||
return str;
|
||||
}
|
||||
if (str2.isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
int iIndexOf = str.indexOf(str2);
|
||||
return iIndexOf == -1 ? str : str.substring(0, iIndexOf);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package cn.nahco3awa.naouc.util.passwd;
|
||||
|
||||
public class BarrettMu {
|
||||
public BigInt modulus;
|
||||
public int k;
|
||||
public BigInt mu;
|
||||
public BigInt bkplus1;
|
||||
|
||||
public BarrettMu(BigInt m) {
|
||||
modulus = m.biCopy();
|
||||
k = modulus.biHighIndex() + 1;
|
||||
BigInt b2k = new BigInt();
|
||||
b2k.digits[2 * k] = 1;
|
||||
mu = BigInt.biDivide(b2k, modulus);
|
||||
bkplus1 = new BigInt();
|
||||
bkplus1.digits[k + 1] = 1;
|
||||
}
|
||||
|
||||
public BigInt modulo(BigInt x) {
|
||||
var q1 = BigInt.biDivideByRadixPower(x, this.k - 1);
|
||||
var q2 = BigInt.biMultiply(q1, this.mu);
|
||||
var q3 = BigInt.biDivideByRadixPower(q2, this.k + 1);
|
||||
var r1 = BigInt.biModuloByRadixPower(x, this.k + 1);
|
||||
var r2term = BigInt.biMultiply(q3, this.modulus);
|
||||
var r2 = BigInt.biModuloByRadixPower(r2term, this.k + 1);
|
||||
var r = BigInt.biSubtract(r1, r2);
|
||||
if (r.isNeg) {
|
||||
r = BigInt.biAdd(r, this.bkplus1);
|
||||
}
|
||||
var rgtem = BigInt.biCompare(r, this.modulus) >= 0;
|
||||
while (rgtem) {
|
||||
r = BigInt.biSubtract(r, this.modulus);
|
||||
rgtem = BigInt.biCompare(r, this.modulus) >= 0;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
public BigInt multiplyMod(BigInt x, BigInt y) {
|
||||
var xy = BigInt.biMultiply(x, y);
|
||||
return this.modulo(xy);
|
||||
}
|
||||
|
||||
public BigInt powMod(BigInt x, BigInt y) {
|
||||
var result = new BigInt();
|
||||
result.digits[0] = 1;
|
||||
var a = x;
|
||||
var k = y;
|
||||
while (true) {
|
||||
if ((k.digits[0] & 1) != 0) result = this.multiplyMod(result, a);
|
||||
k = k.biShiftRight(1);
|
||||
if (k.digits[0] == 0 && k.biHighIndex() == 0) break;
|
||||
a = this.multiplyMod(a, a);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,444 @@
|
||||
package cn.nahco3awa.naouc.util.passwd;
|
||||
|
||||
public class BigInt {
|
||||
public boolean isNeg;
|
||||
public int[] digits;
|
||||
public static int maxDigits;
|
||||
public static int[] zeroArray;
|
||||
public static BigInt bigZero;
|
||||
public static BigInt bigOne;
|
||||
public static final int BI_RADIX = 1 << 16;
|
||||
public static final int BI_RADIX_BASE = 2;
|
||||
public static final int BI_RADIX_BITS = 16;
|
||||
public static final int BI_HALF_RADIX = BI_RADIX >>> 1;
|
||||
public static final long BI_RADIX_SQUARED = (long) BI_RADIX * BI_RADIX;
|
||||
public static final int MAX_DIGIT_VAL = BI_RADIX - 1;
|
||||
public static final long MAX_INTEGER = 9_999_999_999_999_998L;
|
||||
public static final int[] LOW_BIT_MASKS = new int[] {
|
||||
0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F,
|
||||
0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF,
|
||||
0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF
|
||||
};
|
||||
public static final int[] HIGH_BIT_MASKS = new int[] {
|
||||
0x0000, 0x8000, 0xC000, 0xE000, 0xF000, 0xF800,
|
||||
0xFC00, 0xFE00, 0xFF00, 0xFF80, 0xFFC0, 0xFFE0,
|
||||
0xFFF0, 0xFFF8, 0xFFFC, 0xFFFE, 0xFFFF
|
||||
};
|
||||
public static final char[] HEX_TO_CHAR = new char[] {
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
||||
'a', 'b', 'c', 'd', 'e', 'f'
|
||||
};
|
||||
public static final char[] hexatrigesimalToChar = new char[] {
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
||||
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
|
||||
'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
|
||||
'u', 'v', 'w', 'x', 'y', 'z'
|
||||
};
|
||||
|
||||
public static void setMaxDigits(int value) {
|
||||
maxDigits = value;
|
||||
zeroArray = new int[maxDigits];
|
||||
for (int i = 0; i < maxDigits; i++) {
|
||||
zeroArray[i] = 0;
|
||||
}
|
||||
bigZero = new BigInt();
|
||||
bigOne = new BigInt();
|
||||
bigOne.digits[0] = 1;
|
||||
}
|
||||
|
||||
public BigInt() {
|
||||
digits = zeroArray.clone();
|
||||
isNeg = false;
|
||||
}
|
||||
|
||||
public BigInt(boolean flag) {
|
||||
if (flag) {
|
||||
digits = null;
|
||||
} else {
|
||||
digits = zeroArray.clone();
|
||||
}
|
||||
isNeg = false;
|
||||
}
|
||||
|
||||
public static int charToHex(char c) {
|
||||
int zero = 48;
|
||||
int nine = zero + 9;
|
||||
int lA = 97;
|
||||
int lZ = lA + 25;
|
||||
int bA = 65;
|
||||
int bZ = bA + 25;
|
||||
|
||||
if (c >= zero && c <= nine) {
|
||||
return c - zero;
|
||||
} else if (c >= bA && c <= bZ) {
|
||||
return 10 + c - bA;
|
||||
} else if (c >= lA && c <= lZ) {
|
||||
return 10 + c - lA;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static int hexToDigit(String s) {
|
||||
int result = 0;
|
||||
int sl = Math.min(s.length(), 4);
|
||||
for (int i = 0; i < sl; i++) {
|
||||
result <<= 4;
|
||||
result |= charToHex(s.charAt(i));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static BigInt biFromHex(String s) {
|
||||
BigInt result = new BigInt();
|
||||
int sl = s.length();
|
||||
for (int i = sl, j = 0; i > 0; i -= 4, ++j) {
|
||||
int ia = Math.max(i - 4, 0);
|
||||
int ib = Math.min(i, 4);
|
||||
result.digits[j] = hexToDigit(s.substring(Math.min(ia, ib), Math.max(ia, ib)));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static BigInt biDivideByRadixPower(BigInt x, int n) {
|
||||
var ret = new BigInt();
|
||||
arrayCopy(x.digits, n, ret.digits, 0, ret.digits.length - n);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static BigInt biMultiply(BigInt x, BigInt y) {
|
||||
var result = new BigInt();
|
||||
int c;
|
||||
var n = x.biHighIndex();
|
||||
var t = y.biHighIndex();
|
||||
int uv, k;
|
||||
|
||||
for (int i = 0; i <= t; ++i) {
|
||||
c = 0;
|
||||
k = i;
|
||||
for (int j = 0; j <= n; ++j, ++k) {
|
||||
uv = result.digits[k] + x.digits[j] * y.digits[i] + c;
|
||||
result.digits[k] = uv & MAX_DIGIT_VAL;
|
||||
c = uv >>> BI_RADIX_BITS;
|
||||
//c = Math.floor(uv / biRadix);
|
||||
}
|
||||
result.digits[i + n + 1] = c;
|
||||
}
|
||||
// Someone give me a logical xor, please.
|
||||
result.isNeg = x.isNeg != y.isNeg;
|
||||
return result;
|
||||
}
|
||||
|
||||
public static BigInt biModuloByRadixPower(BigInt x, int n) {
|
||||
var result = new BigInt();
|
||||
arrayCopy(x.digits, 0, result.digits, 0, n);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static String biToHex(BigInt x) {
|
||||
StringBuilder result = new StringBuilder();
|
||||
for (var i = x.biHighIndex(); i > -1; --i) {
|
||||
result.append(digitToHex(x.digits[i]));
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
|
||||
public static String reverseStr(String s)
|
||||
{
|
||||
StringBuilder result = new StringBuilder();
|
||||
for (var i = s.length() - 1; i > -1; --i) {
|
||||
result.append(s.charAt(i));
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
private static String digitToHex(int n) {
|
||||
var mask = 0xf;
|
||||
StringBuilder result = new StringBuilder();
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
result.append(HEX_TO_CHAR[n & mask]);
|
||||
n >>>= 4;
|
||||
}
|
||||
return reverseStr(result.toString());
|
||||
}
|
||||
|
||||
public static String biToString(BigInt x, int radix) {
|
||||
var b = new BigInt();
|
||||
b.digits[0] = radix;
|
||||
var qr = biDivideModulo(x, b);
|
||||
StringBuilder result = new StringBuilder(hexatrigesimalToChar[qr[1].digits[0]]);
|
||||
while (biCompare(qr[0], bigZero) == 1) {
|
||||
qr = biDivideModulo(qr[0], b);
|
||||
// [???] digit = qr[1].digits[0];
|
||||
result.append(hexatrigesimalToChar[qr[1].digits[0]]);
|
||||
}
|
||||
return (x.isNeg ? "-" : "") + reverseStr(result.toString());
|
||||
}
|
||||
|
||||
public int biHighIndex() {
|
||||
int result = digits.length - 1;
|
||||
while (result > 0 && digits[result] == 0) -- result;
|
||||
return result;
|
||||
}
|
||||
|
||||
public BigInt biCopy() {
|
||||
BigInt result = new BigInt(true);
|
||||
result.digits = digits.clone();
|
||||
result.isNeg = isNeg;
|
||||
return result;
|
||||
}
|
||||
|
||||
public static final int BITS_PER_DIGIT = 16;
|
||||
public int biNumBits() {
|
||||
int n = biHighIndex();
|
||||
int d = digits[n];
|
||||
int m = (n + 1) * BITS_PER_DIGIT;
|
||||
int result;
|
||||
for (result = m; result > m - BITS_PER_DIGIT; --result) {
|
||||
if ((d & 0x8000) != 0) break;
|
||||
d <<= 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static BigInt biAdd(BigInt x, BigInt y) {
|
||||
BigInt result;
|
||||
|
||||
if (x.isNeg != y.isNeg) {
|
||||
y.isNeg = !y.isNeg;
|
||||
result = biSubtract(x, y);
|
||||
y.isNeg = !y.isNeg;
|
||||
}
|
||||
else {
|
||||
result = new BigInt();
|
||||
var c = 0;
|
||||
int n;
|
||||
for (var i = 0; i < x.digits.length; ++i) {
|
||||
n = x.digits[i] + y.digits[i] + c;
|
||||
result.digits[i] = n % BI_RADIX;
|
||||
c = (n >= BI_RADIX) ? 1 : 0;
|
||||
}
|
||||
result.isNeg = x.isNeg;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public static BigInt biSubtract(BigInt x, BigInt y) {
|
||||
BigInt result;
|
||||
if (x.isNeg != y.isNeg) {
|
||||
y.isNeg = !y.isNeg;
|
||||
result = biAdd(x, y);
|
||||
y.isNeg = !y.isNeg;
|
||||
} else {
|
||||
result = new BigInt();
|
||||
int n, c;
|
||||
c = 0;
|
||||
for (var i = 0; i < x.digits.length; ++i) {
|
||||
n = x.digits[i] - y.digits[i] + c;
|
||||
result.digits[i] = n % BI_RADIX;
|
||||
// Stupid non-conforming modulus operation.
|
||||
if (result.digits[i] < 0) result.digits[i] += BI_RADIX;
|
||||
c = -((n < 0) ? 1 : 0);
|
||||
}
|
||||
// Fix up the negative sign, if any.
|
||||
if (c == -1) {
|
||||
c = 0;
|
||||
for (var i = 0; i < x.digits.length; ++i) {
|
||||
n = -result.digits[i] + c;
|
||||
result.digits[i] = n % BI_RADIX;
|
||||
// Stupid non-conforming modulus operation.
|
||||
if (result.digits[i] < 0) result.digits[i] += BI_RADIX;
|
||||
c = -((n < 0) ? 1 : 0);
|
||||
}
|
||||
// Result is opposite sign of arguments.
|
||||
result.isNeg = !x.isNeg;
|
||||
} else {
|
||||
// Result is same sign.
|
||||
result.isNeg = x.isNeg;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void arrayCopy(int[] src, int srcStart, int[] dest, int destStart, int n)
|
||||
{
|
||||
var m = Math.min(srcStart + n, src.length);
|
||||
for (int i = srcStart, j = destStart; i < m; ++i, ++j) {
|
||||
dest[j] = src[i];
|
||||
}
|
||||
}
|
||||
|
||||
public BigInt biShiftLeft(int n) {
|
||||
int digitCount = (int) Math.floor((double) n / BITS_PER_DIGIT);
|
||||
var result = new BigInt();
|
||||
|
||||
arrayCopy(digits, 0, result.digits, digitCount,
|
||||
result.digits.length - digitCount);
|
||||
|
||||
var bits = n % BITS_PER_DIGIT;
|
||||
var rightBits = BITS_PER_DIGIT - bits;
|
||||
int i, i1;
|
||||
for (i = result.digits.length - 1, i1 = i - 1; i > 0; --i, --i1) {
|
||||
result.digits[i] = ((result.digits[i] << bits) & MAX_DIGIT_VAL) |
|
||||
((result.digits[i1] & HIGH_BIT_MASKS[bits]) >>>
|
||||
(rightBits));
|
||||
}
|
||||
result.digits[0] = ((result.digits[i] << bits) & MAX_DIGIT_VAL);
|
||||
result.isNeg = isNeg;
|
||||
return result;
|
||||
}
|
||||
|
||||
public static int biCompare(BigInt x, BigInt y)
|
||||
{
|
||||
if (x.isNeg != y.isNeg) {
|
||||
return 1 - 2 * (x.isNeg ? 1 : 0);
|
||||
}
|
||||
for (var i = x.digits.length - 1; i >= 0; --i) {
|
||||
if (x.digits[i] != y.digits[i]) {
|
||||
if (x.isNeg) {
|
||||
return 1 - 2 * (x.digits[i] > y.digits[i] ? 1 : 0);
|
||||
} else {
|
||||
return 1 - 2 * (x.digits[i] < y.digits[i] ? 1 : 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public BigInt biShiftRight(int n)
|
||||
{
|
||||
int digitCount = (int) Math.floor((double) n / BITS_PER_DIGIT);
|
||||
var result = new BigInt();
|
||||
arrayCopy(digits, digitCount, result.digits, 0,
|
||||
digits.length - digitCount);
|
||||
var bits = n % BITS_PER_DIGIT;
|
||||
var leftBits = BITS_PER_DIGIT - bits;
|
||||
for (int i = 0, i1 = i + 1; i < result.digits.length - 1; ++i, ++i1) {
|
||||
result.digits[i] = (result.digits[i] >>> bits) |
|
||||
((result.digits[i1] & LOW_BIT_MASKS[bits]) << leftBits);
|
||||
}
|
||||
result.digits[result.digits.length - 1] >>>= bits;
|
||||
result.isNeg = isNeg;
|
||||
return result;
|
||||
}
|
||||
|
||||
public static BigInt biMultiplyDigit(BigInt x, int y)
|
||||
{
|
||||
int n, c, uv;
|
||||
|
||||
BigInt result = new BigInt();
|
||||
n = x.biHighIndex();
|
||||
c = 0;
|
||||
for (var j = 0; j <= n; ++j) {
|
||||
uv = result.digits[j] + x.digits[j] * y + c;
|
||||
result.digits[j] = uv & MAX_DIGIT_VAL;
|
||||
c = uv >>> BI_RADIX_BITS;
|
||||
//c = Math.floor(uv / biRadix);
|
||||
}
|
||||
result.digits[1 + n] = c;
|
||||
return result;
|
||||
}
|
||||
|
||||
public static BigInt biMultiplyByRadixPower(BigInt x, int n)
|
||||
{
|
||||
var result = new BigInt();
|
||||
arrayCopy(x.digits, 0, result.digits, n, result.digits.length - n);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static BigInt[] biDivideModulo(BigInt x, BigInt y) {
|
||||
int nb = x.biNumBits();
|
||||
int tb = y.biNumBits();
|
||||
boolean origYIsNeg = y.isNeg;
|
||||
BigInt q, r;
|
||||
if (nb < tb) {
|
||||
if (x.isNeg) {
|
||||
q = bigOne.biCopy();
|
||||
q.isNeg = !y.isNeg;
|
||||
x.isNeg = false;
|
||||
y.isNeg = false;
|
||||
r = biSubtract(y, x);
|
||||
// Restore signs, 'cause they're references.
|
||||
x.isNeg = true;
|
||||
y.isNeg = origYIsNeg;
|
||||
} else {
|
||||
q = new BigInt();
|
||||
r = x.biCopy();
|
||||
}
|
||||
return new BigInt[]{q, r};
|
||||
}
|
||||
|
||||
q = new BigInt();
|
||||
r = x;
|
||||
|
||||
// Normalize Y.
|
||||
int t = (int) (Math.ceil((double) tb / BITS_PER_DIGIT) - 1);
|
||||
var lambda = 0;
|
||||
while (y.digits[t] < BI_HALF_RADIX) {
|
||||
y = y.biShiftLeft(1);
|
||||
++lambda;
|
||||
++tb;
|
||||
t = (int) (Math.ceil((double) tb / BITS_PER_DIGIT) - 1);
|
||||
}
|
||||
// Shift r over to keep the quotient constant. We'll shift the
|
||||
// remainder back at the end.
|
||||
r = r.biShiftLeft(lambda);
|
||||
nb += lambda; // Update the bit count for x.
|
||||
int n = (int) (Math.ceil((double) nb / BITS_PER_DIGIT) - 1);
|
||||
|
||||
var b = biMultiplyByRadixPower(y, n - t);
|
||||
while (biCompare(r, b) != -1) {
|
||||
++q.digits[n - t];
|
||||
r = biSubtract(r, b);
|
||||
}
|
||||
for (var i = n; i > t; --i) {
|
||||
var ri = (i >= r.digits.length) ? 0 : r.digits[i];
|
||||
var ri1 = (i - 1 >= r.digits.length) ? 0 : r.digits[i - 1];
|
||||
var ri2 = (i - 2 >= r.digits.length) ? 0 : r.digits[i - 2];
|
||||
var yt = (t >= y.digits.length) ? 0 : y.digits[t];
|
||||
var yt1 = (t - 1 >= y.digits.length) ? 0 : y.digits[t - 1];
|
||||
if (ri == yt) {
|
||||
q.digits[i - t - 1] = MAX_DIGIT_VAL;
|
||||
} else {
|
||||
q.digits[i - t - 1] = (int) Math.floor((double) (ri * BI_RADIX + ri1) / yt);
|
||||
}
|
||||
|
||||
var c1 = q.digits[i - t - 1] * ((yt * BI_RADIX) + yt1);
|
||||
var c2 = (ri * BI_RADIX_SQUARED) + (((long) ri1 * BI_RADIX) + ri2);
|
||||
while (c1 > c2) {
|
||||
--q.digits[i - t - 1];
|
||||
c1 = q.digits[i - t - 1] * ((yt * BI_RADIX) | yt1);
|
||||
c2 = ((long) ri * BI_RADIX * BI_RADIX) + (((long) ri1 * BI_RADIX) + ri2);
|
||||
}
|
||||
|
||||
b = biMultiplyByRadixPower(y, i - t - 1);
|
||||
r = biSubtract(r, biMultiplyDigit(b, q.digits[i - t - 1]));
|
||||
if (r.isNeg) {
|
||||
r = biAdd(r, b);
|
||||
--q.digits[i - t - 1];
|
||||
}
|
||||
}
|
||||
r = r.biShiftRight(lambda);
|
||||
// Fiddle with the signs and stuff to make sure that 0 <= r < y.
|
||||
q.isNeg = x.isNeg != origYIsNeg;
|
||||
if (x.isNeg) {
|
||||
if (origYIsNeg) {
|
||||
q = biAdd(q, bigOne);
|
||||
} else {
|
||||
q = biSubtract(q, bigOne);
|
||||
}
|
||||
y = y.biShiftRight(lambda);
|
||||
r = biSubtract(y, r);
|
||||
}
|
||||
// Check for the unbelievably stupid degenerate case of r == -0.
|
||||
if (r.digits[0] == 0 && r.biHighIndex() == 0) r.isNeg = false;
|
||||
|
||||
return new BigInt[]{q, r};
|
||||
}
|
||||
|
||||
public static BigInt biDivide(BigInt x, BigInt y) {
|
||||
return biDivideModulo(x, y)[0];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package cn.nahco3awa.naouc.util.passwd;
|
||||
|
||||
public class RSA {
|
||||
public static class RSAKeyPair {
|
||||
public BigInt e;
|
||||
public BigInt d;
|
||||
public BigInt m;
|
||||
public int digitSize;
|
||||
public int chunkSize;
|
||||
public int radix;
|
||||
public BarrettMu barrett;
|
||||
|
||||
public RSAKeyPair(String encryptionExponent, String decryptionExponent, String modulus) {
|
||||
this.e = BigInt.biFromHex(encryptionExponent);
|
||||
this.d = BigInt.biFromHex(decryptionExponent);
|
||||
this.m = BigInt.biFromHex(modulus);
|
||||
|
||||
////////////////////////////////// TYF
|
||||
this.digitSize = 2 * m.biHighIndex() + 2;
|
||||
this.chunkSize = this.digitSize - 11;
|
||||
////////////////////////////////// TYF
|
||||
|
||||
this.radix = 16;
|
||||
this.barrett = new BarrettMu(this.m);
|
||||
}
|
||||
}
|
||||
public static String encryptedString(RSAKeyPair key, String s) {
|
||||
////////////////////////////////// TYF
|
||||
if (key.chunkSize > key.digitSize - 11)
|
||||
{
|
||||
return "Error";
|
||||
}
|
||||
////////////////////////////////// TYF
|
||||
|
||||
|
||||
var a = new int[s.length()];
|
||||
var sl = s.length();
|
||||
|
||||
var i = 0;
|
||||
while (i < sl) {
|
||||
a[i] = s.charAt(i);
|
||||
i++;
|
||||
}
|
||||
|
||||
var al = a.length;
|
||||
StringBuilder result = new StringBuilder();
|
||||
int j, k;
|
||||
BigInt block;
|
||||
for (i = 0; i < al; i += key.chunkSize) {
|
||||
block = new BigInt();
|
||||
j = 0;
|
||||
|
||||
//for (k = i; k < i + key.chunkSize; ++j) {
|
||||
// block.digits[j] = a[k++];
|
||||
// block.digits[j] += a[k++] << 8;
|
||||
//}
|
||||
|
||||
////////////////////////////////// TYF
|
||||
// Add PKCS#1 v1.5 padding
|
||||
// 0x00 || 0x02 || PseudoRandomNonZeroBytes || 0x00 || Message
|
||||
// Variable a before padding must be of at most digitSize-11
|
||||
// That is for 3 marker bytes plus at least 8 random non-zero bytes
|
||||
int x;
|
||||
var msgLength = (i+key.chunkSize)>al ? al%key.chunkSize : key.chunkSize;
|
||||
var paddedSize = Math.max(8, key.digitSize - 3 - msgLength);
|
||||
// Variable b with 0x00 || 0x02 at the highest index.
|
||||
int[] b = new int[Math.max(msgLength+1+paddedSize, key.digitSize)];
|
||||
for (x=0; x<msgLength; x++)
|
||||
{
|
||||
b[x] = a[i+msgLength-1-x];
|
||||
}
|
||||
b[msgLength] = 0; // marker
|
||||
|
||||
for (x=0; x<paddedSize; x++) {
|
||||
b[msgLength+1+x] = (int) (Math.floor(Math.random()*254) + 1); // [1,255]
|
||||
}
|
||||
// It can be asserted that msgLength+paddedSize == key.digitSize-3
|
||||
b[key.digitSize-2] = 2; // marker
|
||||
b[key.digitSize-1] = 0; // marker
|
||||
|
||||
for (k = 0; k < key.digitSize; ++j)
|
||||
{
|
||||
block.digits[j] = b[k++];
|
||||
block.digits[j] += b[k++] << 8;
|
||||
}
|
||||
////////////////////////////////// TYF
|
||||
|
||||
var crypt = key.barrett.powMod(block, key.e);
|
||||
var text = key.radix == 16 ? BigInt.biToHex(crypt) : BigInt.biToString(crypt, key.radix);
|
||||
result.append(text).append(" ");
|
||||
}
|
||||
return result.substring(0, Math.max(result.toString().length() - 1, 0)); // Remove last space.
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package synjones.commerce.utils;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class JniQrCodeSign {
|
||||
public native String GetOfflineQrCode(String str);
|
||||
|
||||
public native String GetOfflineQrCodeData(String str);
|
||||
|
||||
public native String GetRandomNum();
|
||||
|
||||
/** @noinspection rawtypes*/
|
||||
public native String GetSign(Map map);
|
||||
|
||||
public native String SetKeyAndSha1(String str, String str2);
|
||||
|
||||
public native String SetKeyAndSha1(String str, String str2, int i);
|
||||
|
||||
static {
|
||||
System.loadLibrary("JniQrCodeSign");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="#333333"
|
||||
android:alpha="0.6">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M20,4L4,4c-1.11,0 -1.99,0.89 -1.99,2L2,18c0,1.11 0.89,2 2,2h16c1.11,0 2,-0.89 2,-2L22,6c0,-1.11 -0.89,-2 -2,-2zM20,18L4,18v-6h16v6zM20,8L4,8L4,6h16v2z"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,11 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="#333333"
|
||||
android:alpha="0.6">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM13.41,18.09L13.41,20h-2.67v-1.93c-1.71,-0.36 -3.16,-1.46 -3.27,-3.4h1.96c0.1,1.05 0.82,1.87 2.65,1.87 1.96,0 2.4,-0.98 2.4,-1.59 0,-0.83 -0.44,-1.61 -2.67,-2.14 -2.48,-0.6 -4.18,-1.62 -4.18,-3.67 0,-1.72 1.39,-2.84 3.11,-3.21L10.74,4h2.67v1.95c1.86,0.45 2.79,1.86 2.85,3.39L14.3,9.34c-0.05,-1.11 -0.64,-1.87 -2.22,-1.87 -1.5,0 -2.4,0.68 -2.4,1.64 0,0.84 0.65,1.39 2.67,1.91s4.18,1.39 4.18,3.91c-0.01,1.83 -1.38,2.83 -3.12,3.16z"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,11 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="#333333"
|
||||
android:alpha="0.6">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M11.8,10.9c-2.27,-0.59 -3,-1.2 -3,-2.15 0,-1.09 1.01,-1.85 2.7,-1.85 1.78,0 2.44,0.85 2.5,2.1h2.21c-0.07,-1.72 -1.12,-3.3 -3.21,-3.81V3h-3v2.16c-1.94,0.42 -3.5,1.68 -3.5,3.61 0,2.31 1.91,3.46 4.7,4.13 2.5,0.6 3,1.48 3,2.41 0,0.69 -0.49,1.79 -2.7,1.79 -2.06,0 -2.87,-0.92 -2.98,-2.1h-2.2c0.12,2.19 1.76,3.42 3.68,3.83V21h3v-2.15c1.95,-0.37 3.5,-1.5 3.5,-3.55 0,-2.84 -2.43,-3.81 -4.7,-4.4z"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,11 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="#333333"
|
||||
android:alpha="0.6">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM11,19.93c-3.95,-0.49 -7,-3.85 -7,-7.93 0,-0.62 0.08,-1.21 0.21,-1.79L9,15v1c0,1.1 0.9,2 2,2v1.93zM17.9,17.39c-0.26,-0.81 -1,-1.39 -1.9,-1.39h-1v-3c0,-0.55 -0.45,-1 -1,-1L8,12v-2h2c0.55,0 1,-0.45 1,-1L11,7h2c1.1,0 2,-0.9 2,-2v-0.41c2.93,1.19 5,4.06 5,7.41 0,2.08 -0.8,3.97 -2.1,5.39z"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,11 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="#333333"
|
||||
android:alpha="0.6">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M5,13.18v4L12,21l7,-3.82v-4L12,17l-7,-3.82zM12,3L1,9l11,6 9,-4.91V17h2V9L12,3z"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,11 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="#333333"
|
||||
android:alpha="0.6">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M12,2c-5.33,4.55 -8,8.48 -8,11.8c0,4.98 3.8,8.2 8,8.2s8,-3.22 8,-8.2C20,10.48 17.33,6.55 12,2zM7.83,14c0.37,0 0.67,0.26 0.74,0.62c0.41,2.22 2.28,2.98 3.64,2.87c0.43,-0.02 0.79,0.32 0.79,0.75c0,0.4 -0.32,0.73 -0.72,0.75c-2.13,0.13 -4.62,-1.09 -5.19,-4.12C7.01,14.42 7.37,14 7.83,14z"/>
|
||||
</vector>
|
||||
|
After Width: | Height: | Size: 212 B |
|
After Width: | Height: | Size: 757 B |
|
After Width: | Height: | Size: 505 B |
|
After Width: | Height: | Size: 747 B |
|
After Width: | Height: | Size: 596 B |
|
After Width: | Height: | Size: 542 B |
|
After Width: | Height: | Size: 173 B |
|
After Width: | Height: | Size: 480 B |
|
After Width: | Height: | Size: 314 B |
|
After Width: | Height: | Size: 442 B |
|
After Width: | Height: | Size: 370 B |
|
After Width: | Height: | Size: 358 B |
|
After Width: | Height: | Size: 314 B |
|
After Width: | Height: | Size: 947 B |
|
After Width: | Height: | Size: 584 B |
|
After Width: | Height: | Size: 920 B |
|
After Width: | Height: | Size: 724 B |
|
After Width: | Height: | Size: 717 B |
|
After Width: | Height: | Size: 490 B |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 931 B |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.0 KiB |
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M3,13h8L11,3L3,3v10zM3,21h8v-6L3,15v6zM13,21h8L21,11h-8v10zM13,3v6h8L21,3h-8z" />
|
||||
</vector>
|
||||