Add register api

This commit is contained in:
Mikołaj Pich 2018-06-27 16:21:09 +02:00
parent 2d7abcfc6a
commit d2d19796f3
16 changed files with 391 additions and 16 deletions

1
.gitignore vendored
View file

@ -14,3 +14,4 @@ gradle-app.setting
# gradle/wrapper/gradle-wrapper.properties
.idea/
out/

View file

@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Copyright 2018 Wulkanowy
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View file

@ -1 +1,3 @@
# sdk
# sdk
Implementation of https://gitlab.com/erupcja/uonet-api-docs

View file

@ -23,10 +23,11 @@ sourceCompatibility = 1.8
repositories {
mavenCentral()
jcenter()
maven { url "https://jitpack.io" }
}
dependencies {
implementation 'io.github.wulkanowy:api:0.5.0'
implementation 'com.github.VLO-GDA:uonet-sdk:master-SNAPSHOT'
implementation 'com.google.code.gson:gson:2.8.2'
implementation 'com.squareup.retrofit2:retrofit:2.3.0'
@ -35,6 +36,7 @@ dependencies {
implementation 'io.reactivex:rxjava:1.1.6'
implementation 'io.reactivex:rxandroid:1.2.1'
implementation 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
implementation 'com.squareup.okhttp3:logging-interceptor:3.8.0'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"

View file

@ -1,5 +1,6 @@
#Tue Jun 26 18:52:30 CEST 2018
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip

View file

@ -1,12 +0,0 @@
package io.github.wulkanowy.sdk
import okhttp3.Interceptor
import okhttp3.Response
class ApiSignInterceptor() : Interceptor {
override fun intercept(chain: Interceptor.Chain?): Response {
TODO("not implemented")
}
}

View file

@ -0,0 +1,23 @@
package io.github.wulkanowy.sdk
import com.google.gson.annotations.SerializedName
import java.time.Instant
import java.util.*
abstract class BaseRequest(
@SerializedName("RemoteMobileTimeKey")
val remoteMobileTimeKey: Long = Instant.now().epochSecond,
@SerializedName("TimeKey")
val timeKey: Long = Instant.now().epochSecond - 1,
@SerializedName("RequestId")
val requestId: String = UUID.randomUUID().toString(),
@SerializedName("RemoteMobileAppVersion")
val remoteMobileAppVersion: String = REMOTE_MOBILE_APP_VERSION,
@SerializedName("RemoteMobileAppName")
val remoteMobileAppName: String = REMOTE_MOBILE_APP_NAME
)

View file

@ -0,0 +1,24 @@
package io.github.wulkanowy.sdk
import com.google.gson.annotations.SerializedName
abstract class BaseResponse {
@SerializedName("Status")
lateinit var status: String
@SerializedName("TimeKey")
lateinit var timeKey: String
@SerializedName("TimeValue")
lateinit var timeValue: String
@SerializedName("RequestId")
lateinit var requestId: String
@SerializedName("DayOfWeek")
lateinit var dayOfWeek: String
@SerializedName("AppVersion")
lateinit var appVersion: String
}

View file

@ -0,0 +1,9 @@
package io.github.wulkanowy.sdk
const val USER_AGENT = "MobileUserAgent"
const val APP_VERSION = "18.4.1.388"
const val DEVICE_SYSTEM_TYPE = "Android"
const val DEVICE_SYSTEM_VERSION = "8.1.0"
const val REMOTE_MOBILE_APP_VERSION = "18.4.1.388"
const val REMOTE_MOBILE_APP_NAME = "VULCAN-Android-ModulUcznia"

View file

@ -0,0 +1,41 @@
package io.github.wulkanowy.sdk
import io.github.wulkanowy.sdk.interceptor.SignInterceptor
import io.github.wulkanowy.sdk.register.CertificateRequest
import io.github.wulkanowy.sdk.register.CertificateResponse
import io.github.wulkanowy.sdk.register.RegisterApi
import io.github.wulkanowy.sdk.register.StudentsResponse
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory
import rx.Observable
class Uonet(private val host: String, private val symbol: String, var signature: String = "", var certificate: String = "") {
fun getCertificate(token: String, pin: String, deviceName: String): Observable<CertificateResponse> {
return getRegisterApi().getCertificate(CertificateRequest(tokenKey = token, pin = pin, deviceName = deviceName))
}
fun getPupils(): Observable<StudentsResponse> {
return getRegisterApi().getPupils(object: BaseRequest() {})
}
private fun getRegisterApi() : RegisterApi {
return getRetrofit("Uczen.v3.UczenStart/", signature, certificate).create(RegisterApi::class.java)
}
private fun getRetrofit(baseUrl: String, signature: String = "", certificate: String = ""): Retrofit {
return Retrofit.Builder()
.baseUrl("$host/$symbol/mobile-api/$baseUrl")
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.client(OkHttpClient().newBuilder()
.addInterceptor(HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
.addInterceptor(SignInterceptor(signature, certificate))
.build()
)
.build()
}
}

View file

@ -0,0 +1,33 @@
package io.github.wulkanowy.sdk.interceptor
import io.github.wulkanowy.sdk.USER_AGENT
import net.maciekmm.uonet.EncryptionUtils
import okhttp3.Interceptor
import okhttp3.Response
import okio.Buffer
import java.io.ByteArrayInputStream
import java.util.*
class SignInterceptor(private var signature: String, private var certificate: String) : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val original = chain.request()
val request = original.newBuilder()
request.header("User-Agent", USER_AGENT)
if (signature.isNotBlank() && certificate.isNotBlank()) {
val buffer = Buffer()
original.body()?.writeTo(buffer)
request.header("RequestCertificateKey", certificate)
request.header("RequestSignatureValue", EncryptionUtils.signContent(
buffer.readByteArray(),
ByteArrayInputStream(Base64.getDecoder().decode(signature)))
)
}
request.method(original.method(), original.body())
return chain.proceed(request.build())
}
}

View file

@ -0,0 +1,39 @@
package io.github.wulkanowy.sdk.register
import com.google.gson.annotations.SerializedName
import io.github.wulkanowy.sdk.APP_VERSION
import io.github.wulkanowy.sdk.BaseRequest
import io.github.wulkanowy.sdk.DEVICE_SYSTEM_TYPE
import io.github.wulkanowy.sdk.DEVICE_SYSTEM_VERSION
import java.util.*
data class CertificateRequest(
@SerializedName("PIN")
val pin: String,
@SerializedName("TokenKey")
val tokenKey: String,
@SerializedName("AppVersion")
val appVersion: String = APP_VERSION,
@SerializedName("DeviceId")
val deviceId: String = UUID.randomUUID().toString(),
@SerializedName("DeviceName")
val deviceName: String,
@SerializedName("DeviceNameUser")
val deviceNameUser: String = "",
@SerializedName("DeviceDescription")
val deviceDescription: String = "",
@SerializedName("DeviceSystemType")
val deviceSystemType: String = DEVICE_SYSTEM_TYPE,
@SerializedName("DeviceSystemVersion")
val deviceSystemVersion: String = DEVICE_SYSTEM_VERSION
) : BaseRequest()

View file

@ -0,0 +1,58 @@
package io.github.wulkanowy.sdk.register
import com.google.gson.annotations.SerializedName
data class CertificateResponse(
@SerializedName("IsError")
var isError: Boolean,
@SerializedName("IsMessageForUser")
var isMessageForUser: Boolean,
@SerializedName("Message")
var message: String?,
@SerializedName("TokenKey")
var tokenKey: String?,
@SerializedName("TokenStatus")
var tokenStatus: String,
@SerializedName("TokenCert")
var tokenCert: TokenCert
) {
data class TokenCert(
@SerializedName("CertyfikatKlucz")
var certificateKey: String,
@SerializedName("CertyfikatKluczSformatowanyTekst")
var certificateKeyFormatted: String,
@SerializedName("CertyfikatDataUtworzenia")
var certificateCreatedDate: Int,
@SerializedName("CertyfikatDataUtworzeniaSformatowanyTekst")
var certificateCreatedDateText: String,
@SerializedName("CertyfikatPfx")
var certificatePfx: String,
@SerializedName("GrupaKlientow")
var symbol: String,
@SerializedName("AdresBazowyRestApi")
var apiEndpoint: String,
@SerializedName("UzytkownikLogin")
var userLogin: String,
@SerializedName("UzytkownikNazwa")
var userName: String,
@SerializedName("TypKonta")
var accountType: String?
)
}

View file

@ -0,0 +1,17 @@
package io.github.wulkanowy.sdk.register
import io.github.wulkanowy.sdk.BaseRequest
import retrofit2.http.Body
import retrofit2.http.Headers
import retrofit2.http.POST
import rx.Observable
interface RegisterApi {
@POST("Certyfikat")
@Headers("RequestMobileType: RegisterDevice")
fun getCertificate(@Body certificateRequest: CertificateRequest): Observable<CertificateResponse>
@POST("ListaUczniow")
fun getPupils(@Body pupilsListRequest: BaseRequest): Observable<StudentsResponse>
}

View file

@ -0,0 +1,102 @@
package io.github.wulkanowy.sdk.register
import com.google.gson.annotations.SerializedName
import io.github.wulkanowy.sdk.BaseResponse
data class StudentsResponse(
@SerializedName("Data")
var students: List<Student>
) : BaseResponse() {
data class Student(
@SerializedName("IdOkresKlasyfikacyjny")
val classificationPeriodId: Int,
@SerializedName("OkresPoziom")
val periodLevel: Int,
@SerializedName("OkresNumer")
val periodNumber: Int,
@SerializedName("OkresDataOd")
val periodDateFrom: Int,
@SerializedName("OkresDataDo")
val periodDateTo: Int,
@SerializedName("OkresDataOdTekst")
val periodDateFromText: String,
@SerializedName("OkresDataDoTekst")
val periodDateToText: String,
@SerializedName("IdJednostkaSprawozdawcza")
val reportingUnitId: Int,
@SerializedName("JednostkaSprawozdawczaSkrot")
val reportingUnitShortcut: String,
@SerializedName("JednostkaSprawozdawczaNazwa")
val reportingUnitName: String,
@SerializedName("JednostkaSprawozdawczaSymbol")
val reportingUnitSymbol: String,
@SerializedName("IdJednostka")
val unitId: Int,
@SerializedName("JednostkaNazwa")
val unitName: String,
@SerializedName("JednostkaSkrot")
val unitShortcut: String,
@SerializedName("OddzialSymbol")
val classSymbol: String,
@SerializedName("OddzialKod")
val classCode: String,
@SerializedName("UzytkownikRola")
val userRole: String,
@SerializedName("UzytkownikLogin")
val userLogin: String,
@SerializedName("UzytkownikLoginId")
val userLoginId: Int,
@SerializedName("UzytkownikNazwa")
val userName: String,
@SerializedName("Id")
val Id: Int,
@SerializedName("IdOddzial")
val classId: Int,
@SerializedName("Imie")
val name: String,
@SerializedName("Imie2")
val nameSecond: String,
@SerializedName("Nazwisko")
val surname: String,
@SerializedName("Pseudonim")
val nick: String,
@SerializedName("UczenPlec")
val pupilGender: Int,
@SerializedName("Pozycja")
val position: Int,
@SerializedName("LoginId")
val loginId: Int?
)
}

View file

@ -0,0 +1,35 @@
package io.github.wulkanowy.sdk
import io.github.wulkanowy.sdk.register.CertificateResponse
import io.github.wulkanowy.sdk.register.StudentsResponse
import junit.framework.TestCase.assertEquals
import org.junit.Test
import rx.observers.TestSubscriber
class UonetTest {
private val service by lazy { Uonet("https://api.fakelog.cf", "Default") }
@Test fun registerTest() {
val certificate = service.getCertificate("FK100000", "999999", "Wulkanowy#client")
val certSubscriber = TestSubscriber<CertificateResponse>()
certificate.subscribe(certSubscriber)
certSubscriber.assertCompleted()
certSubscriber.assertNoErrors()
assertEquals(false, certSubscriber.onNextEvents[0].isError)
val tokenCrt = certSubscriber.onNextEvents[0].tokenCert
service.signature = tokenCrt.certificatePfx
service.certificate = tokenCrt.certificateKey
val pupils = service.getPupils()
val pupilSubscriber = TestSubscriber<StudentsResponse>()
pupils.subscribe(pupilSubscriber)
pupilSubscriber.assertCompleted()
pupilSubscriber.assertNoErrors()
assertEquals("Ok", pupilSubscriber.onNextEvents[0].status)
assertEquals(1, pupilSubscriber.onNextEvents[0].students.size)
}
}