updated the cocart implementation

This commit is contained in:
Gilbert Kimutai 2019-12-17 05:15:48 +03:00
parent e07d3236a3
commit d528e38709
26 changed files with 173 additions and 320 deletions

View File

@ -199,6 +199,7 @@ dependencies {
implementation project(path: ':woodroid')
implementation project(path: ':firebasecart')
implementation project(path: ':core')
implementation project(path: ':cocart')
implementation 'org.fabiomsr:moneytextview:1.1.0'

View File

@ -7,12 +7,12 @@ import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.firestore.CollectionReference
import com.google.firebase.firestore.DocumentReference
import com.google.firebase.firestore.FirebaseFirestore
import me.gilo.cocart.model.CartItem
import me.gilo.woodroid.app.common.CompletionGenericLiveData
import me.gilo.woodroid.app.common.QueryLiveData
import me.gilo.woodroid.app.common.WooLiveData
import me.gilo.woodroid.app.models.CartLineItem
import me.gilo.woodroid.Woocommerce
import me.gilo.woodroid.models.LineItem
import me.gilo.woodroid.models.Product
import javax.inject.Inject
@ -87,9 +87,16 @@ constructor() {
}
fun cart(context: Context): WooLiveData<Map<String, LineItem>> {
val callBack = WooLiveData<Map<String, LineItem>>()
woocommerce.CartRepository(context).cart().enqueue(callBack)
fun addToCart(context: Context, productId: Int, quantity: Int): WooLiveData<CartItem> {
val callBack = WooLiveData<CartItem>()
woocommerce.CartRepository(context).addToCart(productId, quantity).enqueue(callBack)
return callBack
}
fun cart(context: Context, customerId: String): WooLiveData<Map<String, CartItem>> {
val callBack = WooLiveData<Map<String, CartItem>>()
woocommerce.CartRepository(context).cart(customerId).enqueue(callBack)
return callBack
}

View File

@ -11,6 +11,7 @@ import android.widget.FrameLayout
import android.widget.TextView
import android.widget.Toast
import androidx.core.content.ContextCompat
import androidx.lifecycle.Observer
import kotlinx.android.synthetic.main.activity_product.*
import kotlinx.android.synthetic.main.content_product.*
import me.gilo.woodroid.app.R
@ -20,6 +21,7 @@ import me.gilo.woodroid.app.common.Status
import me.gilo.woodroid.app.events.ProductEvent
import me.gilo.woodroid.app.models.CartLineItem
import me.gilo.woodroid.app.ui.state.ProgressDialogFragment
import me.gilo.woodroid.app.utils.AppUtils
import me.gilo.woodroid.app.viewmodels.ProductViewModel
import me.gilo.woodroid.models.Product
import org.greenrobot.eventbus.EventBus
@ -55,32 +57,56 @@ class ProductActivity : BaseActivity() {
}
cart()
viewCart(AppUtils(baseContext).cartSession)
}
private fun addToCart(product: Product) {
viewModel.addToCart(product.id).observe(this, androidx.lifecycle.Observer { response ->
viewModel.addToCart(baseContext, product.id, 1).observe(this, Observer { response ->
when (response!!.status()) {
Status.LOADING -> {
}
Status.SUCCESS -> {
toast("success!")
val cartItem = response.data()
AppUtils(baseContext).saveCartSession(cartItem.key, "")
}
Status.ERROR -> {
toast("error : " + response.error().message)
}
Status.EMPTY -> {
}
}
})
}
private fun viewCart(customerId: String) {
viewModel.cart(baseContext, customerId).observe(this, Observer { response ->
when (response!!.status()) {
Status.LOADING -> {
}
Status.SUCCESS -> {
toast("success!")
}
Status.ERROR -> {
toast("error : " + response.error().message)
}
Status.EMPTY -> {
}
}
})
}

View File

@ -16,6 +16,7 @@ import me.gilo.woodroid.app.adapter.ProductAdapter
import me.gilo.woodroid.app.common.BaseActivity
import me.gilo.woodroid.app.common.Status
import me.gilo.woodroid.app.ui.state.ProgressDialogFragment
import me.gilo.woodroid.app.utils.AppUtils
import me.gilo.woodroid.app.viewmodels.ProductViewModel
import me.gilo.woodroid.models.Product
import me.gilo.woodroid.models.filters.ProductFilter
@ -135,7 +136,8 @@ class ShopActivity : BaseActivity() {
}
private fun cart() {
viewModel.cart(baseContext).observe(this, androidx.lifecycle.Observer { response ->
val cartKey = AppUtils(baseContext).cartSession
viewModel.cart(baseContext, cartKey).observe(this, androidx.lifecycle.Observer { response ->
when (response!!.status()) {
Status.LOADING -> {
}

View File

@ -63,7 +63,7 @@ public class AppUtils {
public String getCartSession() {
SharedPreferences prefs = context.getSharedPreferences(MY_PREFS_NAME, context.MODE_PRIVATE);
return prefs.getString("cartSession", null);
return prefs.getString("cartSession", "");
}
public String getExpiry() {

View File

@ -51,9 +51,9 @@ public final class CartViewModel extends ViewModel {
return cartRepository.setQuantity(cartLineItem, quantity);
}
public WooLiveData<Map<String, LineItem>> cart(Context context) {
return cartRepository.cart(context);
}
// public WooLiveData<Map<String, CartLineItem>> cart(Context context) {
// return cartRepository.cart(context);
// }
public WooLiveData<Order> createOrder(Order order) {
return orderRepository.create(order);

View File

@ -4,6 +4,8 @@ import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
import android.content.Context;
import com.google.firebase.firestore.DocumentReference;
import me.gilo.cocart.model.CartItem;
import me.gilo.woodroid.app.common.CompletionGenericLiveData;
import me.gilo.woodroid.app.common.QueryLiveData;
import me.gilo.woodroid.app.common.WooLiveData;
@ -74,8 +76,12 @@ public final class ProductViewModel extends ViewModel {
return cartRepository.setQuantity(cartLineItem, quantity);
}
public WooLiveData<Map<String, LineItem>> cart(Context context) {
return cartRepository.cart(context);
public WooLiveData<Map<String, CartItem>> cart(Context context, String customerId) {
return cartRepository.cart(context, customerId);
}
public WooLiveData<CartItem> addToCart(Context context, int productId, int quantity) {
return cartRepository.addToCart(context, productId, quantity);
}
public WooLiveData<List<Product>> products(ProductFilter filter) {

View File

@ -1,18 +0,0 @@
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
}
}

View File

@ -2,7 +2,9 @@ package me.gilo.cocart.data.api
import me.gilo.cocart.data.requests.CartItemRequest
import me.gilo.cocart.data.requests.CartRequest
import me.gilo.cocart.model.CartItem
import me.gilo.cocart.model.CartTotal
import retrofit2.Call
import retrofit2.http.*
@ -10,6 +12,29 @@ interface ItemsAPI {
@Headers("Content-Type: application/json")
@POST("add-item")
fun addToCart(@Body body: CartItemRequest): Call<Map<String, CartItem>>
fun addToCart(@Body body: CartItemRequest): Call<CartItem>
@Headers("Content-Type: application/json")
@GET("get-cart")
fun list( @Query("thumb") thumb: Boolean = true): Call<Map<String, CartItem>>
@POST("get-cart/saved")
fun getCustomerCart(@Body body: CartRequest): Call<Map<String, CartItem>>
@Headers("Content-Type: application/json")
@POST("clear")
fun clear(): Call<String>
@Headers("Content-Type: application/json")
@GET("count-items")
fun count(): Call<Int>
@Headers("Content-Type: application/json")
@POST("calculate")
fun calculate(@Query("return") returnTotal: Boolean = true): Call<String>
@Headers("Content-Type: application/json")
@GET("totals")
fun totals(@Query("html") returnTotal: Boolean = true): Call<CartTotal>
}

View File

@ -1,12 +0,0 @@
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)
}
}

View File

@ -1,174 +0,0 @@
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)
}
}
}
}

View File

@ -1,14 +0,0 @@
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>
}

View File

@ -1,8 +0,0 @@
package me.gilo.woodroid.data.callbacks
import me.gilo.woodroid.models.Customer
class CustomerData {
lateinit var customer: Customer
}

View File

@ -1,7 +0,0 @@
package me.gilo.woodroid.data.callbacks
import me.gilo.woodroid.models.Order
class Data {
lateinit var order: Order
}

View File

@ -1,11 +0,0 @@
package me.gilo.woodroid.data.callbacks
import me.gilo.woodroid.models.Order
import java.util.ArrayList
class OrderCallback {
var orders = ArrayList<Order>()
}

View File

@ -1,12 +0,0 @@
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
}

View File

@ -1,8 +0,0 @@
package me.gilo.woodroid.data.callbacks
import me.gilo.woodroid.models.Product
class ProductData {
var product: Product? = null
}

View File

@ -1,13 +0,0 @@
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>
}

View File

@ -1,11 +0,0 @@
package me.gilo.woodroid.data.callbacks
import me.gilo.woodroid.models.ProductReview
import java.util.ArrayList
class ReviewsData {
lateinit var productReviews: ArrayList<ProductReview>
}

View File

@ -1,10 +0,0 @@
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
}

View File

@ -0,0 +1,11 @@
package me.gilo.cocart.data.requests
import com.google.gson.annotations.SerializedName
data class CartRequest(
@SerializedName("id")
var customerId: String? = null,
@SerializedName("thumb")
var thumb: Boolean?
)

View File

@ -9,7 +9,9 @@ class CartItem {
var productId: Int = 0
@SerializedName("variation_id")
var variationId: Int = 0
var variationId: Int? = null
var variation: Array<Any>? = null
lateinit var subtotal: String
@SerializedName("subtotal_tax")
@ -22,7 +24,8 @@ class CartItem {
lateinit var name: String
lateinit var key: String
lateinit var sku: String
lateinit var variations: String
lateinit var data_hash: String
}

View File

@ -0,0 +1,54 @@
package me.gilo.cocart.model
import com.google.gson.annotations.SerializedName
data class CartTotal (
@SerializedName("subtotal")
var subtotal: String? = "",
@SerializedName("subtotal_tax")
var subtotalTax: Float? = 0f,
@SerializedName("shipping_total")
var shippingTotal: String? = "",
@SerializedName("shipping_tax")
var shippingTax: Float? = 0f,
@SerializedName("shipping_taxes")
var shippingTaxes: Map<String, Float>? = HashMap(),
@SerializedName("discount_total")
var discountTotal: Float? = 0f,
@SerializedName("discount_tax")
var discountTax: Float? = 0f,
@SerializedName("cart_contents_total")
var cartContentsTotal: String? = "",
@SerializedName("cart_contents_tax")
var cartContentsTax: Float? = 0f,
@SerializedName("cart_contents_taxes")
var cartContentsTaxes: Map<String, Float>? = HashMap(),
@SerializedName("fee_total")
var feeTotal: String? = "",
@SerializedName("fee_tax")
var feeTax: String? = "",
@SerializedName("fee_taxes")
var feeTaxes: Any,
@SerializedName("total")
var total: String? = "",
@SerializedName("total_tax")
var totalTax: Float? = 0f
)

View File

@ -2,6 +2,7 @@ package me.gilo.cocart.repo
import me.gilo.cocart.data.api.ItemsAPI
import me.gilo.cocart.data.requests.CartItemRequest
import me.gilo.cocart.data.requests.CartRequest
import me.gilo.cocart.model.CartItem
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
@ -35,7 +36,7 @@ class CoCartRepository(private var baseUrl: String, consumerKey: String, consume
apiService = retrofit.create(ItemsAPI::class.java)
}
fun addToCart(productId: Int, quantity: Int): Call<Map<String, CartItem>> {
fun addToCart(productId: Int, quantity: Int): Call<CartItem> {
val cartItemRequest = CartItemRequest(
productId = productId, quantity = quantity
)
@ -43,5 +44,17 @@ class CoCartRepository(private var baseUrl: String, consumerKey: String, consume
return apiService.addToCart(cartItemRequest)
}
fun cart(): Call<Map<String, CartItem>> {
return apiService.list()
}
fun cart(customerId: Int, thumb:Boolean = false): Call<Map<String, CartItem>> {
return apiService.list(thumb)
}
fun getCustomerCart(customerId: String, thumb:Boolean = false): Call<Map<String, CartItem>> {
return apiService.getCustomerCart(CartRequest(customerId=customerId, thumb = true))
}
}

View File

@ -37,7 +37,7 @@ class Woocommerce(siteUrl: String, apiVerion: ApiVersion, consumerKey: String, c
init {
val baseUrl = "$siteUrl/wp-json/wc/v$apiVerion/"
val cartBaseUrl = "$siteUrl/wp-json/wc/v2/"
val cartBaseUrl = "$siteUrl/wp-json/cocart/v1/"
orderNoteRepository = OrderNoteRepository(baseUrl, consumerKey, consumerSecret)
refundRepository = RefundRepository(baseUrl, consumerKey, consumerSecret)
@ -129,7 +129,6 @@ class Woocommerce(siteUrl: String, apiVerion: ApiVersion, consumerKey: String, c
}
fun CartRepository(context: Context): CartRepository {
cartRepository.turnOnCookies(context)
return cartRepository
}

View File

@ -8,8 +8,12 @@ class CartRepository(internal var baseUrl: String, consumerKey: String, consumer
private var cartRepository: CoCartRepository = CoCartRepository(baseUrl, consumerKey, consumerSecret)
fun addToCart(productId: Int, quantity: Int): Call<Map<String, CartItem>> {
fun addToCart(productId: Int, quantity: Int): Call<CartItem> {
return cartRepository.addToCart(productId, quantity)
}
fun cart(customerId: String): Call<Map<String, CartItem>> {
return cartRepository.getCustomerCart(customerId = customerId)
}
}