RayOkaah / woocommerce

Woocommerce SDK for Flutter. The Complete Woo Commerce SDK for Flutter.
BSD 3-Clause "New" or "Revised" License
119 stars 110 forks source link

Placing Order // addToCart is not working Missing X-WC-Store-API-NONCE #26

Open nsubash38 opened 4 years ago

nsubash38 commented 4 years ago

Can you please tell the whole process of placing an order. addtomycart is not working and I need guide to place order.

rawquesh commented 4 years ago

the same problem with me so now I think we should use a local cart

nsubash38 commented 4 years ago

@rakeshbishnoi457 have you solved it already ?

nsubash38 commented 4 years ago

@rakeshbishnoi457 @RayOkaah @akfaisel you guys have any solution please? I am badly stuck at it !

rawquesh commented 4 years ago

@nsubash38 you can use cocart (documentation) with requests package to store cookies like a browser but in my situation, I have some issue with this so I'm using Hive local database and its working great for now, you can play with both and use which one is good for you 😊

nsubash38 commented 4 years ago

@rakeshbishnoi457 and how are you posting orders to woocommerce backend after that. I am having really bad time with it ! Please help me !

ngominhtrungit commented 4 years ago

@rakeshbishnoi457 I am also looking for a demo to make a shopping cart, don't know if you have a solution yet?

rawquesh commented 4 years ago

@ngominhtrungit @nsubash38 I'm using hive local database with a custom adapter, my custom adapter so I can proceed to checkout

import 'package:hive/hive.dart';
part 'cart_model.g.dart';

@HiveType(typeId: 0)
class CartModel {
  @HiveField(0)
  final String name;
  @HiveField(1)
  final String image;
  @HiveField(2)
  final String price;
  @HiveField(3)
  final String regularPrice;
  @HiveField(4)
  final int quantity;
  @HiveField(5)
  final int id;
  @HiveField(6)
  final int stockQuantity;

  CartModel({
    this.name,
    this.image,
    this.price,
    this.regularPrice,
    this.id,
    this.stockQuantity,
    this.quantity
  });
}

Vidoe link try this out if you still have a problem then let me know

rawquesh commented 4 years ago

@nsubash38 for everything like login/signup, orders, list of all products, and much more available in this package woocommerce 0.9.7

yashz05 commented 3 years ago

hey guys i was able to solve this issue 1st i created plugin for nonce which will give you nonce jus by jwt 2nd send http post req to url and save nonce in mobile i used sharedprefrence 3rd i copied addtomycart from plugin modified a little and it worked for now code and plugin below Download plugin url https://drive.google.com/file/d/1dxU47rk0AYREwDQdHNHL9EpKTZOG6wZZ/view?usp=sharing **Valid urls

//code start

Future Getnonse(String token) async { Map<String, String> requestHeaders = {'Authorization': 'Bearer $token'}; final response = await http.get(config.BASE_URL + '/wp-json/nonce/v1/get', headers: requestHeaders);

var j = json.decode(response.body);
print(j['nonce']);
return j['nonce']; //later u can save this nonce vai sharedpreference or etc i am using shared preference

} //code end

Next add to cart with nonce //this was taken from woocommerce

//code start

Future addToMyCartfix( {@required String itemId, @required String quantity, List variations}) async { SharedPreferences prefs = await SharedPreferences.getInstance(); var jwt = await prefs.getString('jwt'); var nonc = await prefs.getString('nonce'); Map<String, dynamic> data = { 'id': itemId, 'quantity': quantity, }; Map<String, String> requestHeaders = { 'Authorization': 'Bearer $jwt', 'X-WC-Store-API-Nonce': nonc }; if (variations != null) data['variations'] = variations;

final response = await http.post(
    config.BASE_URL + '/wp-json/wc/store/cart/add-item',
    body: data,
    headers: requestHeaders);

if (response.statusCode >= 200 && response.statusCode < 300) {
  final jsonStr = json.decode(response.body);
  print('added to my cart : ' + jsonStr.toString());
  // return WooCartItem.fromJson(jsonStr);
} else {
  WooCommerceError err =
      WooCommerceError.fromJson(json.decode(response.body));
  throw err;
}

}

//code end

**Get Nonce Api response { "nonce": "9d753b6d45", "user": 1 }

Verify Nonce Api Response { "status": 1, "user": 1 }**

i was unable to add code block so made it bold (i am new to this )

ngominhtrungit commented 3 years ago

@nsubash38 Do you have a solution to the cart problem? i am not sure how?

naumanmir commented 3 years ago

If you want to test REST endpoints without providing a nonce, you can use the following filter:

add_filter( 'woocommerce_store_api_disable_nonce_check', '__return_true' ); Nonce checks will be bypassed if woocommerce_store_api_disable_nonce_check evaluates to true.

NOTE: This should only be done on development sites where security is not important. Do not enable this in production.

jaysathvara1998 commented 3 years ago

@yashz05 can you able to get my cart

yashz05 commented 3 years ago

@jaysathvara1998

Smooth like butter

jaysathvara1998 commented 3 years ago

@yashz05 can you please tell me which endpoint you are using for get my cart items?

rawquesh commented 3 years ago

@jaysathvara1998 I have a better approach for the cart system you can dm me

jaysathvara1998 commented 3 years ago

@rakeshbishnoi457 where can I DM you?

rawquesh commented 3 years ago

@jaysathvara1998 discord id - Addicted#8123

jaysathvara1998 commented 3 years ago

@yashz05 can you please share your code snippet or anything else for get the cart item, I used the code that you give in the comment in this issue to add an item to the cart, but unable to get that item.

yashz05 commented 3 years ago

@jaysathvara1998 Hey text me here https://wa.link/9kmisd

ap26091995 commented 3 years ago

how to create an order? what to pass in body? I have pass this in body: { "first_name":firstName.text, "last_name":lastName.text, "city":city.text, "country":country.text, "email":emailId.text, "state":state.text, "address_1":address.text, "phone":phoneNo.text, "postcode":pinCode.text, }

but not showing this details in woocommerce orders

rawquesh commented 3 years ago

@ap26091995 on which API you are sending this data ? provide the code

ap26091995 commented 3 years ago

https://www.example.com/wp-json/wc/v3/orders/?consumer_key=ck_xxxxxxxxxxxxxx98&consumer_secret=cs_xxxxxxxxxxxxxx1

rawquesh commented 3 years ago

@ap26091995 try with the postman and try to get data first check if the API or everything is working or not then try to hit post request. pass the same data as mentioned here

ap26091995 commented 3 years ago

yes i had check this in postman. in postman i submit data without passing any value in body then its showing me in woocoomerce orders but all details shows blank because not passing any data, later i submit data using parameter but not showing in order. tried by this also but showing Unhandled Exception: type '_InternalLinkedHashMap<String, String>' is not a subtype of type 'String' in type cast

body: {

  "billing":{
        "first_name": firstName.text,
        "last_name": lastName.text,
        "city": city.text,
        "country": country.text,
        "email": emailId.text,
        "state": state.text,
        "address_1": address.text,
        "phone": phoneNo.text,
        "postcode": pinCode.text,
      }
    }
ap26091995 commented 3 years ago

okay i have solved that issue

Divinoart commented 3 years ago

I have the solution Tested and working fine. pls follow strictly.

  1. woocommerce doesn't handle add to cart so you will have to use cocart to do this

to do this write this code

String username = 'usersEmail'; String password = 'usersPassword'; String basicAuth = 'Basic ' + base64Encode(utf8.encode('$username:$password')); print(basicAuth); http.Response r = await http.post(Keys.baseUrl+"/wp-json/cocart/v1/add-item", body: data, headers: <String, String>{'authorization': basicAuth}); print(r.statusCode); print(r.body);

docx here

    PS: for this to word you will need to edit the JWT autentication file so it can accept auth via bearer token.
    follow the method from [this link ](https://wordpress.org/support/topic/fix-basic-authentication-jwt_auth_bad_auth_header-error/)
CarloDotLog commented 3 years ago

I forked this project to add CoCart implementation. You need to install the CoCart plugin and the enhancement one, both free, on your WordPress site. Then, see to my fork.

thomaspouly commented 3 years ago

hello, can you give me a more detailed tutorial for use ur fork? I don't know how to use it to addToCart

CarloDotLog commented 3 years ago

Hi @thomaspouly you were right, there is no fork about CoCart. I didn't publish it anymore.

So, some simple steps to get started:

  1. Install the CoCart plugin on your WordPress site.
  2. Install the CoCart enhanced plugin.
  3. Then copy code from this Gist.
  4. and Import into your project.

One note: in the Gist, you will find two classes, Variation and VariationData that you need to implement by yourself on your needs. In my case, I have some weight-option definitions, but you could have different needs.

;)

thomaspouly commented 3 years ago

Thank you, i will try this

iNahvi commented 3 years ago

i did come up with a solution that worked . It makes use of woocommerce cart module. the original module's api is currently intended to be used internally. but it is accessible externally too.

i have explained the concept here https://github.com/RayOkaah/woocommerce/issues/7#issuecomment-874584684

and finally able to come up with a code that works, so basically every time a cart function is called it would 1st check for the X-WC-store-API-NONCE . since it always gets the NONCE before the Api call. even if the nonce for a user's cart changes on expiration . it will get the current nonce generated from the woocommerce cart.

i have been coding for only few weeks. so please correct it if it does not follow coding best practices.

ADDED

  String? _wcstoreapi;
  String? get wcStoreApi => _wcstoreapi;

ADDED fetchXWCStoreAPINonce FUNCTION

  /// HTTP Get Call to Woocommerce block STOREAPI CART module to get X-WC-Store-API-Nonce [wc_store_api]
  /// Sends Get Request with your Authorization JWT bearer [_token] string. to receive a renspose header
  /// header consists the logged in users X-WC-Store-API-Nonce
  ///
  /// Associated endpoint : yourwebsite.com/wp-json/wp-json/wc/store/cart
  ///
  Future<String?> fetchXWCStoreAPINonce() async {
    _authToken = await _localDbService.getSecurityToken();
    _urlHeader['Authorization'] = 'Bearer ' + _authToken!;
    final response = await http.get(
        Uri.parse(this.baseUrl + URL_STORE_API_PATH + 'cart'),
        headers: _urlHeader);

    if (response.statusCode >= 200 && response.statusCode < 300) {
      final reponseHeader = response.headers;
      _wcstoreapi = reponseHeader['x-wc-store-api-nonce'];
      if (reponseHeader.length == 0)
        throw new WooCommerceError(
            code: 'Error', message: "Could not Retreive X-WC-Store-API-Nonce");
      _printToLog('["x-wc-store-api-nonce"] : ' + _wcstoreapi!.toString());
      return _wcstoreapi;
    } else {
      WooCommerceError err =
          WooCommerceError.fromJson(json.decode(response.body));
      throw err;
    }
  }

CANGED addToMyCart FUCNTION https://github.com/RayOkaah/woocommerce/blob/5d22e4a3fea00a1c83fc3eb7ebad894aebeb12c5/lib/woocommerce.dart#L1001-L1031

TO

  /// Accepts an int [id] of a product or product variation, int quantity, and an array of chosen variation attribute objects
  /// Related endpoint : wc/store/cart/add-item
  ///

  Future<WooCartItem> addToMyCart(
      {required String itemId,
      required String quantity,
      List<WooProductVariation>? variations}) async {
    Map<String, dynamic> data = {
      'id': itemId,
      'quantity': quantity,
    };
    if (variations != null) data['variations'] = variations;
    await getAuthTokenFromDb();
    final wcstoreapi = await fetchXWCStoreAPINonce();
    final _surlHeader = 'Bearer ' + _authToken!;
    Map<String, String> _storeheader = {
      'Authorization': _surlHeader,
      'X-WC-Store-API-Nonce': wcstoreapi!
    };
    final response = await http.post(
        Uri.parse(this.baseUrl + URL_STORE_API_PATH + 'cart/add-item'),
        headers: _storeheader,
        body: data);

    if (response.statusCode >= 200 && response.statusCode < 300) {
      final jsonStr = json.decode(response.body);

      _printToLog('added to my cart : ' + jsonStr.toString());
      return WooCartItem.fromJson(jsonStr);
    } else {
      WooCommerceError err =
          WooCommerceError.fromJson(json.decode(response.body));
      throw err;
    }
  }

CHANGED updateMyCartItemByKey FUNCTION https://github.com/RayOkaah/woocommerce/blob/5d22e4a3fea00a1c83fc3eb7ebad894aebeb12c5/lib/woocommerce.dart#L1156-L1184

TO

  /// Accepts string [key] of a item in cart , string quantity, and an array of chosen variation attribute objects
  /// Related endpoint : wc/store/cart/update-item
  ///

  Future<WooCartItem> updateMyCartItemByKey(
      {required String key,
      required String quantity,
      List<WooProductVariation>? variations}) async {
    Map<String, dynamic> data = {
      'key': key,
      'quantity': quantity,
    };
    if (variations != null) data['variations'] = variations;
    await getAuthTokenFromDb();
    final wcstoreapi = await fetchXWCStoreAPINonce();
    final _surlHeader = 'Bearer ' + _authToken!;
    Map<String, String> _storeheader = {
      'Authorization': _surlHeader,
      'X-WC-Store-API-Nonce': wcstoreapi!
    };

    final response = await http.post(
        Uri.parse(this.baseUrl + URL_STORE_API_PATH + 'cart/update-item'),
        headers: _storeheader,
        body: data);

    if (response.statusCode >= 200 && response.statusCode < 300) {
      final jsonStr = json.decode(response.body);
      _printToLog('added to my cart : ' + jsonStr.toString());
      return WooCartItem.fromJson(jsonStr);
    } else {
      WooCommerceError err =
          WooCommerceError.fromJson(json.decode(response.body));
      throw err;
    }
  }

I HAVE NOT YET CHANGED ALL OF THE CART FUNCTIONS TO WORK WITH X-WC-store-API-NONCE. THIS IS TO SHOW HOW IT WORKED FOR ME. I ASSUME SAME THING CAN BE APPLIED TO REST OF THE CART FUNCTIONS.

you can refer to the woocommerce-gutenbarg-products-block's storeAPI cart documentation for all the API CALLs. https://github.com/woocommerce/woocommerce-gutenberg-products-block/blob/trunk/src/StoreApi/docs/cart.md

Resource Available endpoints
Cart /wc/store/cart
  /wc/store/cart/add-item
  /wc/store/cart/remove-item
  /wc/store/cart/update-item
  /wc/store/cart/apply-coupon
  /wc/store/cart/remove-coupon
  /wc/store/cart/update-customer
  /wc/store/cart/select-shipping-rate

i am still pretty new to programming and github..so still have to figure out how i can share the solutions i find to problems i faced. so for now this sharing it as a comment here :D