Coupon Magento API Soap - web-services

I’ve a problem with the Coupon API when i make :
$couponCode = "test";
$resultCartCoupon = $proxy->call($sessionId, "cart_coupon.add", array($shoppingCartId, $couponCode));
I always got : Uncaught SoapFault exception: [1083] Coupon is not valid if i try the coupon code in the front end there is no problem. Is there anyone who have ever used this API part with success ?
Thanks.

This error comes from Mage_Checkout_Model_Cart_Coupon_Api::_applyCoupon()
if ($couponCode) {
if (!$couponCode == $quote->getCouponCode()) {
$this->_fault('coupon_code_is_not_valid');
}
}
This looks like it could be a bug, instead it should be if ($couponCode != $quote->getCouponCode()) { but I'm not certain.
It could be that the cart (quote) you're trying to apply the coupon to isn't valid, i.e. doesn't have the qualifying items it needs to receive the coupon. Are you sure $shoppingCartId correctly matches the expected quote in Magento's sales_flat_quote table?

I noticed that the error is in this excerpt:
try {
$quote->getShippingAddress()->setCollectShippingRates(true);
$quote->setCouponCode(strlen($couponCode) ? $couponCode : '')
->collectTotals()
->save();
} catch (Exception $e) {
$this->_fault("cannot_apply_coupon_code", $e->getMessage());
}
In this specific line: ->collectTotals() By removing this stretch , not of error , but not applied the coupon.

After debugging 2-3 hour on API, I have solved this error at my-end. Check below code which i have used in Coupon API.
<?php
$mage_url = 'http://yoursiteurl/api/soap?wsdl';
$mage_user= "API_User"; //webservice user login
$mage_api_key = "API_PASSWORD"; //webservice user pass
$client = new SoapClient($mage_url);
$couponCode = 'couponCode'; // a coupon to be apply
$shoppingCartId = '35'; // a cart Id which i have put test id
$sessionId = $client->login($mage_user, $mage_api_key);
$result = $client->call($sessionId,'cart_coupon.add',array($shoppingCartId,$couponCode));
print_r($result);
?>
The above code gives error that "Uncaught SoapFault exception: [1083] Coupon is not valid". When i debugg the core code i came to know that magento cart.create API insert wrong store id in sales_flat_quote table. I have changed the store id value in sales_flat_quote table manually and again run the Coupon API and after that it works perfectly. So here is the my solution. When you create cart id just run the below update query to change the store id.
<?php
$shoppingCartId = $soap->call( $sessionId, 'cart.create');
$mageFilename = '../app/Mage.php';
require_once $mageFilename;
umask(0);
Mage::app();
$db_write1 = Mage::getSingleton('core/resource')->getConnection('core_write');
$updateQue = "update sales_flat_quote set store_id='1' where entity_id ='".$shoppingCartId."'";
$db_write1->query($updateQue);
// Now run the Coupon API here
?>
Code taken from here : http://chandreshrana.blogspot.in/2015/11/uncaught-soapfault-exception-1083.html

You do not need to write direct SQL to resolve this issue. Just specify store ID parameter in the API call. Example is below is the demo script to apply discount code using Magento SOAP APIs V2 :
/* Set Discount Code */
try
{
$result = $client->shoppingCartCouponAdd($session, $quoteId, 'test123',$storeId);
echo "<br>Apply discount code: ";
var_dump($result);
}
catch(Exception $ex)
{
echo "<br>Discount code Failed: " . $ex->getMessage();
}
To apply discount code, perform following steps :
$quoteId = $client->shoppingCartCreate($session,$storeId);
/* Set cart customer */
$guest = true;
if ($guest)
{
$customerData = array(
"firstname" => "testFirstname",
"lastname" => "testLastName",
"email" => "testEmail#mail.com",
"mode" => "guest",
"website_id" => "1"
);
}
else
{
$customer = array(
"customer_id" => '69301',
"website_id" => "1",
"group_id" => "1",
"store_id" => "1",
"mode" => "customer",
);
}
//Set cart customer (assign customer to quote)
$resultCustomerSet = $client->shoppingCartCustomerSet($session, $quoteId, $customerData,$storeId);
/* Set customer addresses Shipping and Billing */
$addresses = array(
array(
"mode" => "shipping",
"firstname" => "Ahsan",
"lastname" => "testLastname",
"company" => "testCompany",
"street" => "testStreet",
"city" => "Karachi",
"region" => "Sindh",
"postcode" => "7502",
"country_id" => "PK",
"telephone" => "0123456789",
"fax" => "0123456789",
"is_default_shipping" => 0,
"is_default_billing" => 0
),
array(
"mode" => "billing",
"firstname" => "Ahsan",
"lastname" => "testLastname",
"company" => "testCompany",
"street" => "testStreet",
"city" => "Karachi",
"region" => "Sindh",
"postcode" => "7502",
"country_id" => "PK",
"telephone" => "0123456789",
"fax" => "0123456789",
"is_default_shipping" => 0,
"is_default_billing" => 0
)
);
//Set cart customer address
$resultCustomerAddress = $client->shoppingCartCustomerAddresses($session, $quoteId, $addresses,$storeId);
/* Set payment method */
$responsePayment = $client->shoppingCartPaymentMethod($session, $quoteId, array(
'method' => 'cashondelivery',
),$storeId);
/* Set shipping method */
$setShipping = $client->shoppingCartShippingMethod($session, $quoteId, 'flatrate_flatrate',$storeId);
After all above apply discount code,
try
{
$result = $client->shoppingCartCouponAdd($session, $quoteId, 'test123',$storeId);
echo "<br>Apply discount code: ";
var_dump($result);
}
catch(Exception $ex)
{
echo "<br>Discount code Failed: " . $ex->getMessage();
}

Related

Regular expression for laravel username and #tags

how can I set up a Regular expression for #username and #example on post field form, just like Twitter , when a user uses #hashtag in there post I will like to automatically save it to tag table and when a user uses #john symbol I would like to automatically notify the user he /she has been mentioned , please what is the logic behind this I don't have idea on how to start
im getting this error
BadMethodCallException
Method App\Http\Livewire\createPost::tag does not exist.
public function createPost()
{
if (auth()->check()) {
$this->validate();
$posts = Post::create([
'user_id' => auth()->user()->id,
'school_id' => $this->school,
'body' => $this->body,
'is_anon' => $this->is_anon,
$url = \url(route('posts.show', $this->id)),
]);
preg_match_all('/(?<=#)(\w+)/mi', $this->body, $matchedTags, PREG_SET_ORDER, 0);
foreach($matchedTags as $matchedTag) {
if(!$tag = tag::where('name', $matchedTag[0])->first()) {
$tag = tag::create(['name' => $matchedTag[0]]);
}
$this->tags()->attach($tag->id);
}
assuming your input string is $str, you can use these:
preg_match_all('/(?<=#)(\w+)/mi', $str, $atSignMatches, PREG_SET_ORDER, 0);
preg_match_all('/(?<=#)(\w+)/mi', $str, $poundMatches, PREG_SET_ORDER, 0);
and then you can print the $atSignMatches and $poundMatches which are the resulting values.
More info on https://www.php.net/manual/en/function.preg-match-all.php
Update: Steps
These are the steps to extract users and make notifications.
Get Request payload.
Extract Tags (using #)
Create Tag records in table
Extract mentions (using #)
Create notification for mentioners
public function save(Request $request) {
{
$post = Post::create($request->all());
$content = $post->content;
preg_match_all('/(?<=#)(\w+)/mi', $content, $matchedTags, PREG_SET_ORDER, 0);
foreach($matchedTags as $matchedTag) {
if(!$tag = Tag::where('name', $matchedTag[0])->first()) {
$tag = Tag::create(['name' => $matchedTag[0]]);
}
$post->tags()->attach($tag->id);
}
preg_match_all('/(?<=#)(\w+)/mi', $content, $matchedMentions, PREG_SET_ORDER, 0);
foreach($matchedMentions as $matchedMention) {
if($user = User::where('username', $matchedMention[0])->first()) {
$user->notifications()->create([
'post_id' => $post->id,
'type' => "MENTION",
'seen' => false,
'time' => \Carbon\Carbon::now()
]);
}
}
}
Notes:
Make sure to change the tag and notification creation implementation matching your table structure.

Remember me cookie cakephp 4 not working correctly after logout

I’m working with CakePHP 4.
Following the documentation, I set up ‘remember me’ cookie, when I pass login, I see in the browser the CookieAuth controller with correct values for username e password.
Point is that when I logout, I still see the cookie in my browser (it will expires in few days) but I expected username e password input text with precompiled value in the login form.
Is this the correct behaviour?
I tried to get these fields populated but incurred in many different errors related to cookie reading/writing as
Argument 1 passed to Cake\Http\Response::withCookie() must implement interface Cake\Http\Cookie\CookieInterface, string given
This is my code:
in app_local.php:
‘Security’ => [
‘salt’ => env(‘SECURITY_SALT’, ‘string’, //here my random string
],
-in Application.php
$cookies = new EncryptedCookieMiddleware(
[‘CookieAuth’],
Configure::read(‘Security.cookieKey’)
);
and inside getAuthenticationService(ServerRequestInterface $request), after Session and before Form:
$authenticationService->loadAuthenticator(‘Authentication.Cookie’, [
‘rememberMeField’ => ‘remember_me’,
‘fields’ => [
‘username’ => ‘email’,
‘password’ => ‘password’,
],
‘loginUrl’ => ‘/’,
‘cookie’=>[
‘name’=>‘CookieAuth’,
‘expire’=> new DateTime(‘Thu, 31 Dec 20 15:00:00 +0000’)
]
]);
in UsersController, login function
public function login()
{
$this->Authorization->skipAuthorization();
$cookie = [‘email’=>’’, ‘password’=>’’, ‘remember_me’=>0];
if ($this->request->getCookie('CookieAuth')) {
$cookie = $this->request->getCookie('CookieAuth');
debug('cookie');
}
// if remember_me
if($this->request->getData('remember_me') == 1) {
$this->response = $this->response->withCookie(new Cookie('CookieAuth'), $this->request->getData());
}
else {
//$this->Cookie->delete('CookieAuth');
}
$this->set($cookie);
// other code
}
-Templates\Users\login.php:
<?= $this->Form->control('email', ['required' => true]) ?>
<?= $this->Form->control('password', ['required' => true]) ?>
<?= $this->Form->control('remember_me', ['type' => 'checkbox']);?>
<?= $this->Form->submit(__('Login')); ?>
Any help would be really appreciated, thanks.
Ii tried it on version 4.x. It works fine
config/app.php
'Security' => [
'salt' => env('SECURITY_SALT', 'string'), //here my random string
'cookieKey' => env('SECURITY_COOKIE_KEY', 'string'), //here my random string],
Application.php | function middleware
->add(new EncryptedCookieMiddleware(['CookieAuth'],Configure::read('Security.cookieKey')))
Application.php | function getAuthenticationService
$service->loadAuthenticator('Authentication.Cookie', [ 'fields' => $fields, 'cookie' => [ 'name' => 'CookieAuth', 'expires' => (new Time())->addDays(30), ], 'loginUrl' => '/users/login', ]);
<?= $this->Form->control('remember_me', ['type' => 'checkbox']);?>

Get result from vTiger webservice

I am writing a wordpress-plugin which queries data from the vTiger Webservice-API. I read the tutorial (https://wiki.vtiger.com/index.php/Webservices_tutorials#QueryResult) and know the reference (https://wiki.vtiger.com/index.php/Webservice_reference_manual). In the tutorial the use Zend-JSON and HTTP_Client. I use cURL (because it was installed and I thought it was worth a try to use before I install other utilities). It works quite well and I am able to Login to vTiger with our API-User and send the queries. What I receive is something like this:
array(2) {
["success"]=>
bool(true)
["result"]=>
array(4) {
["sessionName"]=>
string(21) "4d103e2058f9d365c22ff"
["userId"]=>
string(4) "19x9"
["version"]=>
string(4) "0.22"
["vtigerVersion"]=>
string(5) "6.5.0"
}
}
Looks very good to me but the Thing I am missing is the actual data from my query.
This is my PHP-Code:
$vtiger->initCurl();
$challengeToken = $vtiger->getChallengeToken();
$sessionId = $vtiger->getSessionId($challengeToken);
$result = $vtiger->query($sessionId, "SELECT firstname FROM 'Contacts' WHERE lastname = 'XXX';");
$wpdb->replace( $wpdb->prefix.$_CONFIG['dbtable'], array( 'id' => 1, 'syncfields' => $result), array('%d', '%s') );
$vtiger->logout($sessionId);
$vtiger->closeCurl();
$result = json_decode($result, true);
return var_dump(($result['success']) ? $result : "Error");
What am I missing to get the firstname (or any other value from the vTiger-DB)?
In the Code I am just writing the Response to the wp-db (extra-Table).
Thanks,
Nico
Vtiger Result Return in array format. you should change your code
$vtiger->initCurl();
$challengeToken = $vtiger->getChallengeToken();
$sessionId = $vtiger->getSessionId($challengeToken);
$result = $vtiger->query($sessionId, "SELECT firstname FROM 'Contacts' WHERE lastname = 'XXX';");
$syncfield = result['0'];
$wpdb->replace( $wpdb->prefix.$_CONFIG['dbtable'], array( 'id' => 1, 'syncfields' => $syncfield), array('%d', '%s') );
$vtiger->logout($sessionId);
$vtiger->closeCurl();
$result = json_decode($result, true);
return var_dump(($result['success']) ? $result : "Error");
َAlso You Can Use vtiger CRM Webservice Client Library
http://forge.vtiger.com/projects/vtwsclib/

using Cakephp Restful WS with primary key different from default 'id'

I want to create a Webservice in cakephp but the primary key is not id_supp but taken the default value id
this is the modal:
<?php
App::uses('AppModel', 'Model');
class Supplier extends AppModel {
var $primaryKey = 'id_supp';
this is the route
Router::mapResources(array('suppliers'));
and this is the view action
public function view($id) {
$supplier = $this->Supplier->findById($id);
$this->set(array(
'supplier' => $supplier,
'_serialize' => array('supplier')
));
}
The result when accessing the following url via GET
/suppliers/54f4dc83-0bd0-4fdd-ab8b-0a08ba3b5702.json
is:
{
"code": 500,
"url": "\/TN\/Back_rest\/suppliers\/54f4dc83-0bd0-4fdd-ab8b-0a08ba3b5702.json",
"name": "SQLSTATE[42S22]: Column not found: 1054 Unknown column 'Supplier.id' in 'where clause'",
"error": {
"errorInfo": [
"42S22",
1054,
"Unknown column 'Supplier.id' in 'where clause'"
],
"queryString": "SELECT `Supplier`.`id_supp`, `Supplier`.`company_name`, `Supplier`.`contact_name`, `Supplier`.`contact_title`, `Supplier`.`address`, `Supplier`.`postcode`, `Supplier`.`phone`, `Supplier`.`fax`, `Supplier`.`www`, `Supplier`.`active`, `Supplier`.`created`, `Supplier`.`modified` FROM `tn`.`suppliers` AS `Supplier` WHERE `Supplier`.`id` = '54f4dc83-0bd0-4fdd-ab8b-0a08ba3b5702' LIMIT 1"
}}
Because cakephp uses convention over configuration you should use id for your table primary id field. In your example you could find what you are looking for like this:
public function view($id = null) {
$supplier = $this->Supplier->find('first', array(
'conditions' => array(
'Supplier.id_supp' => $id
)
));
$this->set(array(
'supplier' => $supplier,
'_serialize' => array('supplier')
));
}
or like this:
public function view($id = null) {
$this->Supplier->primaryKey = $id;
$supplier = $this->Supplier->find('first');
$this->set(array(
'supplier' => $supplier,
'_serialize' => array('supplier')
));
}
or like this:
public function view($id = null) {
$supplier = $this->Supplier->findByIdSupp($id);
$this->set(array(
'supplier' => $supplier,
'_serialize' => array('supplier')
));
}
Choose what ever pleases you the most.

Drupal services endpoint returns 404 : Could not find resource retrieve

I followed this tutorial :
http://pingv.com/blog/an-introduction-drupal-7-restful-services
and seems everyone have the same problem as mine in the comments.
I made a rest service with drupal services module :
Server = REST
path = api/mohtadoon
mohtadoon_api.module file
<?php
/**
* Implements of hook_services_resources().
*/
function mohtadoon_api_services_resources() {
$api = array(
'mohtadoon' => array(
'operations' => array(
'retrieve' => array(
'help' => 'Retrieves mohtadoon data',
'callback' => 'mohtadoon_api_stories_retrieve',
'file' => array('file' => 'inc', 'module' => 'mohtadoon_api','name' => 'resources/mohtadoon_api'),
'access arguments' => array('access content'),
),
),
),
);
return $api;
}
mohtadoon_api.inc file in resources/mohtadoon_api path
<?php
function mohtadoon_api_stories_retrieve() {
return mohtadoon_api_find_stories();
}
function mohtadoon_api_find_stories() {
// Compose query
$query = db_select('node', 'n');
$query->join('node_revision', 'v', '(n.nid = v.nid) AND (n.vid = v.vid)');
$query->join('users', 'u', 'n.uid = u.uid');
$query->join('field_data_body', 'b', '((b.entity_type = \'node\') AND (b.entity_id = n.nid) AND (b.revision_id = n.vid))');
$query->fields('v', array('timestamp', 'title'));
$query->addField('u', 'name', 'author');
$query->addField('b', 'body_value', 'content');
$query->condition('n.type', 'stories', '=');
$items = $query->execute()->fetchAll();
return $items;
}
?>
when I access the path
http://localhost/mohtadoon01/?q=api/mohtadoon/retrieve
where mohtadoon01 is project path AND ?q= because
the request result is 404 Not found: Could not find resource retrieve.
why is this happens && how to debug something like this ... I didn't deal with drupal before and want to make only one get web service.
You likely need to url encode your string:
http://localhost/mohtadoon01/?q=api%2Fmohtadoon%2Fretrieve
Can't promise this will work though, depending on your drupal configuration.
Slashes are allowed in query string, as per RFC: http://ietf.org/rfc/rfc3986.txt, however many services out of the box do not: you may need to enable AllowEncodedSlashes.
I encountered exactly the same thing using Services 7.x-3.7. To understand the issue, I looked through the following file:
services/servers/rest_server/includes/RESTServer.inc
Given the definition of your service, the code exercised by GET requests for your resource should be:
protected function resolveController($resource, &$operation) {
...
if ( $request_method == 'GET'
&& $canon_path_count >= 1
&& isset($resource['operations']['retrieve'])
&& $this->checkNumberOfArguments($canon_path_count, $resource['operations']['retrieve'])
&& !empty($canonical_path_array[0])
) {
$operation_type = 'operations';
$operation = 'retrieve';
}
...
}
If we now take a look at the code for $this->checkNumberOfArguments():
// We can see from the snippet above that $args_number = $canon_path_count and hence that
// $args_number is always greater than 0
protected function checkNumberOfArguments($args_number, $resource_operation, $required_args = 0) {
$not_required_args = 0;
if (isset($resource_operation['args'])) {
foreach ($resource_operation['args'] as $argument) {
if (isset($argument['source']) && is_array($argument['source']) && isset($argument['source']['path'])) {
if (!empty($argument['optional'])) {
$not_required_args++;
}
else {
$required_args++;
}
}
}
}
// This is where we fall down; Since the service definition does not include any args,
// both $required_args and $not_required_args will equal zero when we get here. Not a problem
// for the first condition (1 >= 0), but clearly the second condition (1 <= 0 + 0) will evaluate
// to false and hence the argument count will not be accepted. As a result, the services module
// does not accept this controller and reports this as '404 not found'
return $args_number >= $required_args && $args_number <= $required_args + $not_required_args;
}
Try adding an argument to your service definition like this:
<?php
/**
* Implements of hook_services_resources().
*/
function mohtadoon_api_services_resources() {
$api = array(
'mohtadoon' => array(
'operations' => array(
'retrieve' => array(
'help' => 'Retrieves mohtadoon data',
'callback' => 'mohtadoon_api_stories_retrieve',
'file' => array('file' => 'inc', 'module' => 'mohtadoon_api','name' => 'resources/mohtadoon_api'),
'access arguments' => array('access content'),
'arg' => array(
array(
'name' => 'entity',
'type' => 'string',
'description' => 'Entity to operate on',
'source' => array('path' => '0'),
'optional' => TRUE,
'default' => '0',
),
),
),
),
),
);
return $api;
}
EDIT:
I think what is confusing people reading the blog post that you linked to (and I was one of those!) is that the URL given as the accessor for the service includes as its final parameter the name of the method that it was intended to invoke ('retrieve'). You could replace 'retrieve' with pretty much anything and the service should still respond (e.g. '/api/blog/pink-rabbit' or, in your case, 'api/mohtadoon/pink-rabbit'). The web service definitions themselves do not indicate what value of parameters can be passed to the endpoint. What counts is what HTTP method is used to access the service and how many parameters are passed to the endpoint (zero or more). Some types of operation require at least a certain number of parameters (e.g. 'retrieve' operations require at least one parameter to identify the specific thing that you want to retrieve).