added cocart api structure
This commit is contained in:
parent
b7b8d020b7
commit
e07d3236a3
1
.idea/gradle.xml
generated
1
.idea/gradle.xml
generated
@ -12,6 +12,7 @@
|
|||||||
<set>
|
<set>
|
||||||
<option value="$PROJECT_DIR$" />
|
<option value="$PROJECT_DIR$" />
|
||||||
<option value="$PROJECT_DIR$/app" />
|
<option value="$PROJECT_DIR$/app" />
|
||||||
|
<option value="$PROJECT_DIR$/cocart" />
|
||||||
<option value="$PROJECT_DIR$/core" />
|
<option value="$PROJECT_DIR$/core" />
|
||||||
<option value="$PROJECT_DIR$/firebasecart" />
|
<option value="$PROJECT_DIR$/firebasecart" />
|
||||||
<option value="$PROJECT_DIR$/woodroid" />
|
<option value="$PROJECT_DIR$/woodroid" />
|
||||||
|
|||||||
50
cocart/build.gradle
Normal file
50
cocart/build.gradle
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
apply plugin: 'com.android.library'
|
||||||
|
apply plugin: 'kotlin-android'
|
||||||
|
apply plugin: 'kotlin-android-extensions'
|
||||||
|
|
||||||
|
android {
|
||||||
|
compileSdkVersion 29
|
||||||
|
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
minSdkVersion 16
|
||||||
|
targetSdkVersion 29
|
||||||
|
versionCode 1
|
||||||
|
versionName "1.0"
|
||||||
|
|
||||||
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
consumerProguardFiles 'consumer-rules.pro'
|
||||||
|
}
|
||||||
|
|
||||||
|
buildTypes {
|
||||||
|
release {
|
||||||
|
minifyEnabled false
|
||||||
|
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||||
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||||
|
implementation 'androidx.appcompat:appcompat:1.1.0'
|
||||||
|
implementation 'androidx.core:core-ktx:1.1.0'
|
||||||
|
testImplementation 'junit:junit:4.12'
|
||||||
|
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
|
||||||
|
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
|
||||||
|
|
||||||
|
implementation 'com.squareup.retrofit2:retrofit:2.3.0'
|
||||||
|
implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
|
||||||
|
|
||||||
|
implementation 'com.jakewharton.retrofit:retrofit1-okhttp3-client:1.1.0'
|
||||||
|
|
||||||
|
implementation 'io.reactivex:rxandroid:1.2.1'
|
||||||
|
implementation 'io.reactivex:rxjava:1.3.0'
|
||||||
|
|
||||||
|
implementation 'com.squareup.okhttp3:logging-interceptor:3.10.0'
|
||||||
|
|
||||||
|
implementation 'com.fasterxml.jackson.core:jackson-databind:2.9.8'
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
0
cocart/consumer-rules.pro
Normal file
0
cocart/consumer-rules.pro
Normal file
21
cocart/proguard-rules.pro
vendored
Normal file
21
cocart/proguard-rules.pro
vendored
Normal file
@ -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,24 @@
|
|||||||
|
package me.gilo.cocart
|
||||||
|
|
||||||
|
import androidx.test.platform.app.InstrumentationRegistry
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
|
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
|
||||||
|
import org.junit.Assert.*
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instrumented test, which will execute on an Android device.
|
||||||
|
*
|
||||||
|
* See [testing documentation](http://d.android.com/tools/testing).
|
||||||
|
*/
|
||||||
|
@RunWith(AndroidJUnit4::class)
|
||||||
|
class ExampleInstrumentedTest {
|
||||||
|
@Test
|
||||||
|
fun useAppContext() {
|
||||||
|
// Context of the app under test.
|
||||||
|
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
|
||||||
|
assertEquals("me.gilo.cocart.test", appContext.packageName)
|
||||||
|
}
|
||||||
|
}
|
||||||
2
cocart/src/main/AndroidManifest.xml
Normal file
2
cocart/src/main/AndroidManifest.xml
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="me.gilo.cocart" />
|
||||||
@ -0,0 +1,36 @@
|
|||||||
|
package me.gilo.cocart.callback
|
||||||
|
|
||||||
|
import androidx.lifecycle.LiveData
|
||||||
|
import retrofit2.Call
|
||||||
|
import retrofit2.Callback
|
||||||
|
import retrofit2.Response
|
||||||
|
|
||||||
|
import java.io.IOException
|
||||||
|
|
||||||
|
class CallBackLiveData<T> : LiveData<Resource<T>>(), Callback<T> {
|
||||||
|
init {
|
||||||
|
value = Resource(Status.LOADING)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResponse(call: Call<T>, response: Response<T>) {
|
||||||
|
if (response.isSuccessful) {
|
||||||
|
setValue(Resource(response.body()!!))
|
||||||
|
} else {
|
||||||
|
var error: String? = null
|
||||||
|
try {
|
||||||
|
error = response.errorBody()!!.string()
|
||||||
|
} catch (e: IOException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error == null) {
|
||||||
|
error = "Something went wrong"
|
||||||
|
}
|
||||||
|
setValue(Resource(NetworkException(error)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFailure(call: Call<T>, t: Throwable) {
|
||||||
|
value = Resource(NetworkException(t))
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
package me.gilo.cocart.callback
|
||||||
|
|
||||||
|
class NetworkException : Exception {
|
||||||
|
|
||||||
|
constructor() : super() {}
|
||||||
|
|
||||||
|
constructor(message: String) : super(message) {}
|
||||||
|
|
||||||
|
constructor(message: String, cause: Throwable) : super(message, cause) {}
|
||||||
|
|
||||||
|
constructor(cause: Throwable) : super(cause) {}
|
||||||
|
}
|
||||||
58
cocart/src/main/java/me/gilo/cocart/callback/Resource.kt
Executable file
58
cocart/src/main/java/me/gilo/cocart/callback/Resource.kt
Executable file
@ -0,0 +1,58 @@
|
|||||||
|
package me.gilo.cocart.callback
|
||||||
|
|
||||||
|
|
||||||
|
class Resource<T> private constructor(private val data: T?, private val error: Exception?) {
|
||||||
|
internal var status = Status.LOADING
|
||||||
|
|
||||||
|
val isSuccessful: Boolean
|
||||||
|
get() = data != null && error == null
|
||||||
|
|
||||||
|
constructor(data: T) : this(data, null) {}
|
||||||
|
|
||||||
|
constructor(status: Status) : this(null, null) {
|
||||||
|
this.status = status
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(exception: Exception) : this(null, exception) {
|
||||||
|
this.status = Status.ERROR
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
|
||||||
|
if (error != null) {
|
||||||
|
status = Status.ERROR
|
||||||
|
} else if (data != null) {
|
||||||
|
if (data is List<*>) {
|
||||||
|
if ((data as List<*>).size == 0) {
|
||||||
|
status = Status.EMPTY
|
||||||
|
} else {
|
||||||
|
status = Status.SUCCESS
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
status = Status.SUCCESS
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
status = Status.LOADING
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun data(): T? {
|
||||||
|
if (error != null) {
|
||||||
|
throw IllegalStateException("error is not null. Call isSuccessful() first.")
|
||||||
|
}
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
fun error(): Exception? {
|
||||||
|
if (data != null) {
|
||||||
|
throw IllegalStateException("data is not null. Call isSuccessful() first.")
|
||||||
|
}
|
||||||
|
return error
|
||||||
|
}
|
||||||
|
|
||||||
|
fun status(): Status {
|
||||||
|
return status
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
11
cocart/src/main/java/me/gilo/cocart/callback/Status.kt
Normal file
11
cocart/src/main/java/me/gilo/cocart/callback/Status.kt
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package me.gilo.cocart.callback
|
||||||
|
|
||||||
|
enum class Status {
|
||||||
|
EMPTY,
|
||||||
|
SUCCESS,
|
||||||
|
ERROR,
|
||||||
|
LOADING;
|
||||||
|
|
||||||
|
val isLoading: Status
|
||||||
|
get() = LOADING
|
||||||
|
}
|
||||||
5
cocart/src/main/java/me/gilo/cocart/callback/WooCall.kt
Normal file
5
cocart/src/main/java/me/gilo/cocart/callback/WooCall.kt
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package me.gilo.cocart.callback
|
||||||
|
|
||||||
|
import retrofit2.Call
|
||||||
|
|
||||||
|
interface WooCall<T> : Call<T>
|
||||||
19
cocart/src/main/java/me/gilo/cocart/data/ApiVersion.kt
Normal file
19
cocart/src/main/java/me/gilo/cocart/data/ApiVersion.kt
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
package me.gilo.cocart.data
|
||||||
|
|
||||||
|
enum class ApiVersion {
|
||||||
|
API_VERSION1 {
|
||||||
|
override fun toString(): String {
|
||||||
|
return "1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
API_VERSION2 {
|
||||||
|
override fun toString(): String {
|
||||||
|
return "2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
API_VERSION3 {
|
||||||
|
override fun toString(): String {
|
||||||
|
return "3"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
18
cocart/src/main/java/me/gilo/cocart/data/RestAdapter.kt
Normal file
18
cocart/src/main/java/me/gilo/cocart/data/RestAdapter.kt
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
package me.gilo.woodroid.data
|
||||||
|
|
||||||
|
import org.apache.http.NameValuePair
|
||||||
|
|
||||||
|
import java.util.ArrayList
|
||||||
|
|
||||||
|
class RestAdapter(private val baseUrl: String, private val consumerKey: String, private val consumerSecret: String) {
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
internal var oauth_nonce = ""
|
||||||
|
internal var oauth_timestamp = ""
|
||||||
|
internal var oauth_signature_method = "HMAC-SHA1"
|
||||||
|
|
||||||
|
internal var params: ArrayList<NameValuePair>? = null
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
17
cocart/src/main/java/me/gilo/cocart/data/api/CartAPI.kt
Normal file
17
cocart/src/main/java/me/gilo/cocart/data/api/CartAPI.kt
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package me.gilo.cocart.data.api
|
||||||
|
|
||||||
|
|
||||||
|
import retrofit2.Call
|
||||||
|
import retrofit2.http.*
|
||||||
|
|
||||||
|
interface CartAPI {
|
||||||
|
|
||||||
|
@Headers("Content-Type: application/json")
|
||||||
|
@POST("clear")
|
||||||
|
fun clear(): Call<String>
|
||||||
|
|
||||||
|
@GET("count-items")
|
||||||
|
fun count(): Call<Int>
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
17
cocart/src/main/java/me/gilo/cocart/data/api/FiltersAPI.kt
Normal file
17
cocart/src/main/java/me/gilo/cocart/data/api/FiltersAPI.kt
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package me.gilo.cocart.data.api
|
||||||
|
|
||||||
|
|
||||||
|
import retrofit2.Call
|
||||||
|
import retrofit2.http.*
|
||||||
|
|
||||||
|
interface FiltersAPI {
|
||||||
|
|
||||||
|
@Headers("Content-Type: application/json")
|
||||||
|
@POST("clear")
|
||||||
|
fun clear(): Call<String>
|
||||||
|
|
||||||
|
@GET("count-items")
|
||||||
|
fun count(): Call<Int>
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
15
cocart/src/main/java/me/gilo/cocart/data/api/ItemsAPI.kt
Normal file
15
cocart/src/main/java/me/gilo/cocart/data/api/ItemsAPI.kt
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
package me.gilo.cocart.data.api
|
||||||
|
|
||||||
|
|
||||||
|
import me.gilo.cocart.data.requests.CartItemRequest
|
||||||
|
import me.gilo.cocart.model.CartItem
|
||||||
|
import retrofit2.Call
|
||||||
|
import retrofit2.http.*
|
||||||
|
|
||||||
|
interface ItemsAPI {
|
||||||
|
|
||||||
|
@Headers("Content-Type: application/json")
|
||||||
|
@POST("add-item")
|
||||||
|
fun addToCart(@Body body: CartItemRequest): Call<Map<String, CartItem>>
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
package me.gilo.woodroid.data.auth
|
||||||
|
|
||||||
|
import org.apache.http.NameValuePair
|
||||||
|
|
||||||
|
import java.util.Comparator
|
||||||
|
|
||||||
|
class AlphabeticSorter : Comparator<NameValuePair> {
|
||||||
|
|
||||||
|
override fun compare(nameValuePair1: NameValuePair, nameValuePair2: NameValuePair): Int {
|
||||||
|
return nameValuePair1.name.compareTo(nameValuePair2.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
174
cocart/src/main/java/me/gilo/cocart/data/auth/AuthIntercepter.kt
Normal file
174
cocart/src/main/java/me/gilo/cocart/data/auth/AuthIntercepter.kt
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
package me.gilo.woodroid.data.auth
|
||||||
|
|
||||||
|
import android.util.Base64
|
||||||
|
import android.util.Log
|
||||||
|
import okhttp3.HttpUrl
|
||||||
|
import okhttp3.Interceptor
|
||||||
|
import okhttp3.Request
|
||||||
|
import okhttp3.Response
|
||||||
|
import org.apache.http.NameValuePair
|
||||||
|
import org.apache.http.client.utils.URLEncodedUtils
|
||||||
|
import org.apache.http.message.BasicNameValuePair
|
||||||
|
|
||||||
|
import javax.crypto.Mac
|
||||||
|
import javax.crypto.spec.SecretKeySpec
|
||||||
|
import java.io.IOException
|
||||||
|
import java.io.UnsupportedEncodingException
|
||||||
|
import java.net.URLDecoder
|
||||||
|
import java.net.URLEncoder
|
||||||
|
import java.security.InvalidKeyException
|
||||||
|
import java.security.NoSuchAlgorithmException
|
||||||
|
import java.util.*
|
||||||
|
import java.util.Map
|
||||||
|
|
||||||
|
class AuthIntercepter(private val consumerKey: String, private val consumerSecret: String) : Interceptor {
|
||||||
|
private var oauth_signature = ""
|
||||||
|
|
||||||
|
|
||||||
|
@Throws(IOException::class)
|
||||||
|
override fun intercept(chain: Interceptor.Chain): Response {
|
||||||
|
val params = getOauthParams(chain)
|
||||||
|
|
||||||
|
val builder = chain.request().url().newBuilder()
|
||||||
|
for (entry in params) {
|
||||||
|
builder.addQueryParameter(entry.name, entry.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
val newRequest = chain.request()
|
||||||
|
.newBuilder()
|
||||||
|
.url(builder.build())
|
||||||
|
.header("Accept", "application/json")
|
||||||
|
.build()
|
||||||
|
|
||||||
|
return chain.proceed(newRequest)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getOauthParams(chain: Interceptor.Chain): ArrayList<NameValuePair> {
|
||||||
|
val params = ArrayList<NameValuePair>()
|
||||||
|
|
||||||
|
var request_url = chain.request().url().toString()
|
||||||
|
|
||||||
|
val iterator = getQueryParams(request_url).entries.iterator()
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
val pair = iterator.next() as Map.Entry<*, *>
|
||||||
|
|
||||||
|
val key = pair.key as String
|
||||||
|
val values = pair.value as List<String>
|
||||||
|
var value = ""
|
||||||
|
|
||||||
|
//why there would be multiple values for single key is not so clear to me, will keep this here though
|
||||||
|
if (values.size == 1) {
|
||||||
|
value = values[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
params.add(BasicNameValuePair(key, value))
|
||||||
|
|
||||||
|
iterator.remove()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request_url.contains("?")) {
|
||||||
|
val request_url_end = request_url.indexOf("?")
|
||||||
|
request_url = request_url.substring(0, request_url_end)
|
||||||
|
}
|
||||||
|
|
||||||
|
oauth_nonce = getOauth_nonce()
|
||||||
|
oauth_timestamp = getOauth_timestamp()
|
||||||
|
|
||||||
|
params.add(BasicNameValuePair("oauth_consumer_key", consumerKey))
|
||||||
|
params.add(BasicNameValuePair("oauth_nonce", oauth_nonce))
|
||||||
|
params.add(BasicNameValuePair("oauth_timestamp", oauth_timestamp))
|
||||||
|
params.add(BasicNameValuePair("oauth_signature_method", oauth_signature_method))
|
||||||
|
|
||||||
|
Collections.sort(params, AlphabeticSorter())
|
||||||
|
val encodedParams = URLEncodedUtils.format(params, "utf-8")
|
||||||
|
oauth_signature = getOauth_signature(chain.request().method(), request_url, consumerSecret, encodedParams)
|
||||||
|
|
||||||
|
params.add(BasicNameValuePair("oauth_signature", oauth_signature))
|
||||||
|
|
||||||
|
return params
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getOauth_nonce(): String {
|
||||||
|
return StringBuilder((Math.random() * 100000000.0).toString()).toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getStringToSign(method: String, url: String, parameters: String): String {
|
||||||
|
var string_to_sign = ""
|
||||||
|
try {
|
||||||
|
string_to_sign = StringBuilder("$method&")
|
||||||
|
.append(URLEncoder.encode(url, "utf-8")).append("&")
|
||||||
|
.append(URLEncoder.encode(parameters, "utf-8"))
|
||||||
|
.toString()
|
||||||
|
} catch (e: UnsupportedEncodingException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
|
||||||
|
return string_to_sign
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun getOauth_signature(method: String, url: String, consumerSecret: String, parameters: String): String {
|
||||||
|
var signature = ""
|
||||||
|
val string_to_sign = getStringToSign(method, url, parameters)
|
||||||
|
|
||||||
|
try {
|
||||||
|
val mac = Mac.getInstance(oauth_signature_method)
|
||||||
|
val secret = "$consumerSecret&"
|
||||||
|
mac.init(SecretKeySpec(secret.toByteArray(charset("utf-8")), oauth_signature_method))
|
||||||
|
signature =
|
||||||
|
Base64.encodeToString(mac.doFinal(string_to_sign.toByteArray(charset("utf-8"))), 0).trim { it <= ' ' }
|
||||||
|
} catch (e: NoSuchAlgorithmException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
} catch (e: InvalidKeyException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
} catch (e: UnsupportedEncodingException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
|
||||||
|
return signature
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun getOauth_timestamp(): String {
|
||||||
|
val stamp = (System.currentTimeMillis() / 1000.0).toLong()
|
||||||
|
return StringBuilder(stamp.toString()).toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
|
||||||
|
internal var oauth_nonce = ""
|
||||||
|
internal var oauth_timestamp = ""
|
||||||
|
internal var oauth_signature_method = "HMAC-SHA1"
|
||||||
|
|
||||||
|
fun getQueryParams(url: String): MutableMap<String, List<String>> {
|
||||||
|
try {
|
||||||
|
val params = HashMap<String, List<String>>()
|
||||||
|
val urlParts = url.split("\\?".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
|
||||||
|
if (urlParts.size > 1) {
|
||||||
|
val query = urlParts[1]
|
||||||
|
for (param in query.split("&".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()) {
|
||||||
|
val pair = param.split("=".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
|
||||||
|
val key = URLDecoder.decode(pair[0], "UTF-8")
|
||||||
|
var value = ""
|
||||||
|
if (pair.size > 1) {
|
||||||
|
value = URLDecoder.decode(pair[1], "UTF-8")
|
||||||
|
}
|
||||||
|
|
||||||
|
var values: MutableList<String>? = params[key]?.toMutableList()
|
||||||
|
if (values == null) {
|
||||||
|
values = ArrayList()
|
||||||
|
params[key] = values
|
||||||
|
}
|
||||||
|
values.add(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return params
|
||||||
|
} catch (ex: UnsupportedEncodingException) {
|
||||||
|
throw AssertionError(ex)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
package me.gilo.woodroid.data.callbacks
|
||||||
|
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName
|
||||||
|
import me.gilo.woodroid.models.Category
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.ArrayList
|
||||||
|
|
||||||
|
|
||||||
|
class CategoriesCallback {
|
||||||
|
@SerializedName("product_categories")
|
||||||
|
lateinit var categories: ArrayList<Category>
|
||||||
|
}
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
package me.gilo.woodroid.data.callbacks
|
||||||
|
|
||||||
|
|
||||||
|
import me.gilo.woodroid.models.Customer
|
||||||
|
|
||||||
|
class CustomerData {
|
||||||
|
lateinit var customer: Customer
|
||||||
|
}
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
package me.gilo.woodroid.data.callbacks
|
||||||
|
|
||||||
|
import me.gilo.woodroid.models.Order
|
||||||
|
|
||||||
|
class Data {
|
||||||
|
lateinit var order: Order
|
||||||
|
}
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
package me.gilo.woodroid.data.callbacks
|
||||||
|
|
||||||
|
|
||||||
|
import me.gilo.woodroid.models.Order
|
||||||
|
|
||||||
|
import java.util.ArrayList
|
||||||
|
|
||||||
|
|
||||||
|
class OrderCallback {
|
||||||
|
var orders = ArrayList<Order>()
|
||||||
|
}
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
package me.gilo.woodroid.data.callbacks
|
||||||
|
|
||||||
|
|
||||||
|
import me.gilo.woodroid.models.Product
|
||||||
|
|
||||||
|
import java.util.ArrayList
|
||||||
|
|
||||||
|
|
||||||
|
class ProductCallback {
|
||||||
|
var products = ArrayList<Product>()
|
||||||
|
lateinit var product: Product
|
||||||
|
}
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
package me.gilo.woodroid.data.callbacks
|
||||||
|
|
||||||
|
|
||||||
|
import me.gilo.woodroid.models.Product
|
||||||
|
|
||||||
|
class ProductData {
|
||||||
|
var product: Product? = null
|
||||||
|
}
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
package me.gilo.woodroid.data.callbacks
|
||||||
|
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName
|
||||||
|
import me.gilo.woodroid.models.ProductReview
|
||||||
|
|
||||||
|
import java.util.ArrayList
|
||||||
|
|
||||||
|
|
||||||
|
class ReviewsCallback {
|
||||||
|
@SerializedName("product_reviews")
|
||||||
|
lateinit var productReviews: ArrayList<ProductReview>
|
||||||
|
}
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
package me.gilo.woodroid.data.callbacks
|
||||||
|
|
||||||
|
|
||||||
|
import me.gilo.woodroid.models.ProductReview
|
||||||
|
|
||||||
|
import java.util.ArrayList
|
||||||
|
|
||||||
|
|
||||||
|
class ReviewsData {
|
||||||
|
lateinit var productReviews: ArrayList<ProductReview>
|
||||||
|
}
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
package me.gilo.woodroid.data.callbacks
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName
|
||||||
|
import me.gilo.woodroid.models.Store
|
||||||
|
|
||||||
|
class StoreCallback {
|
||||||
|
|
||||||
|
@SerializedName("store")
|
||||||
|
lateinit var store: Store
|
||||||
|
}
|
||||||
@ -0,0 +1,33 @@
|
|||||||
|
package me.gilo.woodroid.data.cookie
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.preference.PreferenceManager
|
||||||
|
import okhttp3.Interceptor
|
||||||
|
import okhttp3.Request
|
||||||
|
import okhttp3.Response
|
||||||
|
|
||||||
|
import java.io.IOException
|
||||||
|
import java.util.HashSet
|
||||||
|
|
||||||
|
class AddCookiesInterceptor(private val context: Context) : Interceptor {
|
||||||
|
|
||||||
|
@Throws(IOException::class)
|
||||||
|
override fun intercept(chain: Interceptor.Chain): Response {
|
||||||
|
val builder = chain.request().newBuilder()
|
||||||
|
|
||||||
|
val preferences = PreferenceManager.getDefaultSharedPreferences(context).getStringSet(
|
||||||
|
PREF_COOKIES,
|
||||||
|
HashSet()
|
||||||
|
) as HashSet<String>
|
||||||
|
for (cookie in preferences) {
|
||||||
|
builder.addHeader("Cookie", cookie)
|
||||||
|
}
|
||||||
|
|
||||||
|
return chain.proceed(builder.build())
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
val PREF_COOKIES = "PREF_COOKIES"
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
package me.gilo.woodroid.data.cookie
|
||||||
|
|
||||||
|
import okhttp3.Interceptor
|
||||||
|
import okhttp3.Request
|
||||||
|
import okhttp3.Response
|
||||||
|
|
||||||
|
import java.io.IOException
|
||||||
|
|
||||||
|
class DemoCookieInterceptor : Interceptor {
|
||||||
|
|
||||||
|
|
||||||
|
@Throws(IOException::class)
|
||||||
|
override fun intercept(chain: Interceptor.Chain): Response {
|
||||||
|
val builder = chain.request().newBuilder()
|
||||||
|
|
||||||
|
builder.addHeader(
|
||||||
|
"Cookie",
|
||||||
|
"wordpress_logged_in_9073cf57240df660c1e240d327cc46cb=gilo%7C1551794958%7CJx1NTnn0f6wuYlN5a0PmTJxYcPlr1sUUqpr659EKCcG%7C802c643a30a82bf7aa6350b5fb5dd005c019b2e1b1d59566ef0c426e33126eae"
|
||||||
|
)
|
||||||
|
builder.addHeader("Cookie", "woocommerce_cart_hash=d9ec6c9bf0d307629c2a981362735284")
|
||||||
|
builder.addHeader(
|
||||||
|
"Cookie",
|
||||||
|
"wp_woocommerce_session_9073cf57240df660c1e240d327cc46cb=1%7C%7C1551796439%7C%7C1551792839%7C%7Ce6deec897575a9a84bb4a672abf2ed72"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return chain.proceed(builder.build())
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,35 @@
|
|||||||
|
package me.gilo.woodroid.data.cookie
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.SharedPreferences
|
||||||
|
import android.preference.PreferenceManager
|
||||||
|
import okhttp3.Interceptor
|
||||||
|
import okhttp3.Response
|
||||||
|
|
||||||
|
import java.io.IOException
|
||||||
|
import java.util.HashSet
|
||||||
|
|
||||||
|
class ReceivedCookiesInterceptor(private val context: Context) : Interceptor {
|
||||||
|
|
||||||
|
@Throws(IOException::class)
|
||||||
|
override fun intercept(chain: Interceptor.Chain): Response {
|
||||||
|
val originalResponse = chain.proceed(chain.request())
|
||||||
|
|
||||||
|
if (!originalResponse.headers("Set-Cookie").isEmpty()) {
|
||||||
|
val cookies = PreferenceManager.getDefaultSharedPreferences(context).getStringSet(
|
||||||
|
"PREF_COOKIES",
|
||||||
|
HashSet()
|
||||||
|
) as HashSet<String>
|
||||||
|
|
||||||
|
for (header in originalResponse.headers("Set-Cookie")) {
|
||||||
|
cookies.add(header)
|
||||||
|
}
|
||||||
|
|
||||||
|
val memes = PreferenceManager.getDefaultSharedPreferences(context).edit()
|
||||||
|
memes.putStringSet("PREF_COOKIES", cookies).apply()
|
||||||
|
memes.commit()
|
||||||
|
}
|
||||||
|
|
||||||
|
return originalResponse
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
package me.gilo.cocart.data.requests
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName
|
||||||
|
|
||||||
|
data class CartItemRequest(
|
||||||
|
@SerializedName("product_id")
|
||||||
|
var productId: Int,
|
||||||
|
|
||||||
|
@SerializedName("quantity")
|
||||||
|
var quantity: Int,
|
||||||
|
|
||||||
|
@SerializedName("variation_id")
|
||||||
|
var variationId: Int? = null,
|
||||||
|
|
||||||
|
@SerializedName("variation")
|
||||||
|
var variation: Any? = null,
|
||||||
|
|
||||||
|
@SerializedName("cart_item_data")
|
||||||
|
var cartItemData: Any? = null,
|
||||||
|
|
||||||
|
@SerializedName("refresh_totals")
|
||||||
|
var refreshTotals: Boolean? = null,
|
||||||
|
|
||||||
|
@SerializedName("return_cart")
|
||||||
|
var returnCart: Boolean? = null
|
||||||
|
)
|
||||||
28
cocart/src/main/java/me/gilo/cocart/model/CartItem.kt
Normal file
28
cocart/src/main/java/me/gilo/cocart/model/CartItem.kt
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package me.gilo.cocart.model
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName
|
||||||
|
|
||||||
|
|
||||||
|
class CartItem {
|
||||||
|
|
||||||
|
@SerializedName("product_id")
|
||||||
|
var productId: Int = 0
|
||||||
|
|
||||||
|
@SerializedName("variation_id")
|
||||||
|
var variationId: Int = 0
|
||||||
|
|
||||||
|
lateinit var subtotal: String
|
||||||
|
@SerializedName("subtotal_tax")
|
||||||
|
lateinit var subtotalTax: String
|
||||||
|
lateinit var total: String
|
||||||
|
lateinit var totalTax: String
|
||||||
|
lateinit var price: String
|
||||||
|
var quantity: Int = 0
|
||||||
|
lateinit var taxClass: Any
|
||||||
|
lateinit var name: String
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
lateinit var sku: String
|
||||||
|
lateinit var variations: String
|
||||||
|
}
|
||||||
47
cocart/src/main/java/me/gilo/cocart/repo/CoCartRepository.kt
Normal file
47
cocart/src/main/java/me/gilo/cocart/repo/CoCartRepository.kt
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
package me.gilo.cocart.repo
|
||||||
|
|
||||||
|
import me.gilo.cocart.data.api.ItemsAPI
|
||||||
|
import me.gilo.cocart.data.requests.CartItemRequest
|
||||||
|
import me.gilo.cocart.model.CartItem
|
||||||
|
import okhttp3.OkHttpClient
|
||||||
|
import okhttp3.logging.HttpLoggingInterceptor
|
||||||
|
import retrofit2.Call
|
||||||
|
import retrofit2.Retrofit
|
||||||
|
import retrofit2.converter.gson.GsonConverterFactory
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
|
class CoCartRepository(private var baseUrl: String, consumerKey: String, consumerSecret: String) {
|
||||||
|
|
||||||
|
private var apiService: ItemsAPI
|
||||||
|
private var retrofit: Retrofit
|
||||||
|
|
||||||
|
init {
|
||||||
|
val loggingInterceptor = HttpLoggingInterceptor()
|
||||||
|
loggingInterceptor.level = HttpLoggingInterceptor.Level.BODY
|
||||||
|
|
||||||
|
val client = OkHttpClient.Builder()
|
||||||
|
.addInterceptor(loggingInterceptor)
|
||||||
|
.readTimeout(30, TimeUnit.SECONDS)
|
||||||
|
.writeTimeout(30, TimeUnit.SECONDS)
|
||||||
|
.connectTimeout(15, TimeUnit.SECONDS)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
retrofit = Retrofit.Builder()
|
||||||
|
.baseUrl(baseUrl)
|
||||||
|
.addConverterFactory(GsonConverterFactory.create())
|
||||||
|
.client(client)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
apiService = retrofit.create(ItemsAPI::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addToCart(productId: Int, quantity: Int): Call<Map<String, CartItem>> {
|
||||||
|
val cartItemRequest = CartItemRequest(
|
||||||
|
productId = productId, quantity = quantity
|
||||||
|
)
|
||||||
|
|
||||||
|
return apiService.addToCart(cartItemRequest)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
17
cocart/src/test/java/me/gilo/cocart/ExampleUnitTest.kt
Normal file
17
cocart/src/test/java/me/gilo/cocart/ExampleUnitTest.kt
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package me.gilo.cocart
|
||||||
|
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
import org.junit.Assert.*
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Example local unit test, which will execute on the development machine (host).
|
||||||
|
*
|
||||||
|
* See [testing documentation](http://d.android.com/tools/testing).
|
||||||
|
*/
|
||||||
|
class ExampleUnitTest {
|
||||||
|
@Test
|
||||||
|
fun addition_isCorrect() {
|
||||||
|
assertEquals(4, 2 + 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1 +1,2 @@
|
|||||||
include ':app', ':woodroid', ':firebasecart', ':core'
|
include ':app', ':woodroid', ':firebasecart', ':core'
|
||||||
|
include ':cocart'
|
||||||
|
|||||||
@ -56,6 +56,9 @@ dependencies {
|
|||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||||
|
|
||||||
|
|
||||||
|
implementation project(path: ':cocart')
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
|||||||
@ -1,99 +1,15 @@
|
|||||||
package me.gilo.woodroid.repo
|
package me.gilo.woodroid.repo
|
||||||
|
|
||||||
import android.content.Context
|
import me.gilo.cocart.model.CartItem
|
||||||
import me.gilo.woodroid.data.api.CartAPI
|
import me.gilo.cocart.repo.CoCartRepository
|
||||||
import me.gilo.woodroid.data.cookie.AddCookiesInterceptor
|
|
||||||
import me.gilo.woodroid.data.cookie.ReceivedCookiesInterceptor
|
|
||||||
import me.gilo.woodroid.models.LineItem
|
|
||||||
import me.gilo.woodroid.models.filters.CartFilter
|
|
||||||
import okhttp3.OkHttpClient
|
|
||||||
import okhttp3.logging.HttpLoggingInterceptor
|
|
||||||
import retrofit2.Retrofit
|
|
||||||
import retrofit2.Call
|
import retrofit2.Call
|
||||||
import retrofit2.converter.gson.GsonConverterFactory
|
|
||||||
import java.util.concurrent.TimeUnit
|
|
||||||
|
|
||||||
class CartRepository(internal var baseUrl: String, consumerKey: String, consumerSecret: String) {
|
class CartRepository(internal var baseUrl: String, consumerKey: String, consumerSecret: String) {
|
||||||
|
|
||||||
internal var apiService: CartAPI
|
private var cartRepository: CoCartRepository = CoCartRepository(baseUrl, consumerKey, consumerSecret)
|
||||||
internal var retrofit: Retrofit
|
|
||||||
|
|
||||||
init {
|
fun addToCart(productId: Int, quantity: Int): Call<Map<String, CartItem>> {
|
||||||
val loggingInterceptor = HttpLoggingInterceptor()
|
return cartRepository.addToCart(productId, quantity)
|
||||||
loggingInterceptor.level = HttpLoggingInterceptor.Level.BODY
|
|
||||||
|
|
||||||
|
|
||||||
val client = OkHttpClient.Builder()
|
|
||||||
.addInterceptor(loggingInterceptor)
|
|
||||||
.readTimeout(30, TimeUnit.SECONDS)
|
|
||||||
.writeTimeout(30, TimeUnit.SECONDS)
|
|
||||||
.connectTimeout(15, TimeUnit.SECONDS)
|
|
||||||
.build()
|
|
||||||
|
|
||||||
retrofit = Retrofit.Builder()
|
|
||||||
.baseUrl(baseUrl)
|
|
||||||
.addConverterFactory(GsonConverterFactory.create())
|
|
||||||
.client(client)
|
|
||||||
.build()
|
|
||||||
|
|
||||||
apiService = retrofit.create(CartAPI::class.java)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun turnOnCookies(context: Context) {
|
|
||||||
val loggingInterceptor = HttpLoggingInterceptor()
|
|
||||||
loggingInterceptor.level = HttpLoggingInterceptor.Level.BODY
|
|
||||||
|
|
||||||
val client = OkHttpClient.Builder()
|
|
||||||
.addInterceptor(AddCookiesInterceptor(context))
|
|
||||||
.addInterceptor(ReceivedCookiesInterceptor(context))
|
|
||||||
.addInterceptor(loggingInterceptor)
|
|
||||||
.readTimeout(30, TimeUnit.SECONDS)
|
|
||||||
.writeTimeout(30, TimeUnit.SECONDS)
|
|
||||||
.connectTimeout(15, TimeUnit.SECONDS)
|
|
||||||
.build()
|
|
||||||
|
|
||||||
retrofit = Retrofit.Builder()
|
|
||||||
.baseUrl(baseUrl)
|
|
||||||
.addConverterFactory(GsonConverterFactory.create())
|
|
||||||
.client(client)
|
|
||||||
.build()
|
|
||||||
|
|
||||||
apiService = retrofit.create(CartAPI::class.java)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun clear(): Call<String> {
|
|
||||||
return apiService.clear()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fun count(id: Int): Call<Int> {
|
|
||||||
return apiService.count()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun cart(): Call<Map<String, LineItem>> {
|
|
||||||
return apiService.list()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun addToCart(lineItem: LineItem): Call<Map<String, LineItem>> {
|
|
||||||
return apiService.addToCart(lineItem)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun delete(cardId: String): Call<String> {
|
|
||||||
val cartFilter = CartFilter(cardId)
|
|
||||||
return apiService.delete(cartFilter)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun restore(cardId: String): Call<String> {
|
|
||||||
val cartFilter = CartFilter(cardId)
|
|
||||||
return apiService.restore(cartFilter)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun update(cardId: String, quantity: Int): Call<String> {
|
|
||||||
val cartFilter = CartFilter(cardId)
|
|
||||||
cartFilter.quantity = quantity
|
|
||||||
|
|
||||||
return apiService.update(cartFilter)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user