I am looking to add a customer to my QB installation using the Consolibyte PHP library. I know that I need to initialize and queue up my requests by using the following:
$Queue = new QuickBooks_WebConnector_Queue('mysql://root:password#localhost/my_database');
$Queue->enqueue(QUICKBOOKS_ADD_CUSTOMER, $id_value);
In the above, I am merely passing in a unique ID when I queue the request ($id_value). Looking at the _quickbooks_customer_add_request() method, I see that there are 9 parameters for the function. How are these parameters set when I call $Queue->enqueue()?
Here's the function definition:
->enqueue($action, $ident = null, $priority = 0, $extra = null, $user = null, $qbxml = null, $replace = true)
From here:
https://github.com/consolibyte/quickbooks-php/blob/master/QuickBooks/WebConnector/Queue.php#L208
Documentation:
* #param string $action An action to be performed within QuickBooks (see the qbXML and QuickBooks SDK documentation, i.e.: "CustomerAdd", "InvoiceAdd", "CustomerMod", etc.)
* #param mixed $ident A unique identifier (if required) for a record being operated on (i.e. if you're doing a "CustomerAdd", you'd probaly put a unique customer ID number here, so you're SOAP handler function knows which customer it is supposed to add)
* #param integer $priority The priority of the update (higher priority actions will be pushed to QuickBooks before lower priority actions)
* #param array $extra If you need to make additional bits of data available to your request/response functions, you can pass an array of extra data here
* #param string $user The username of the QuickBooks Web Connector user this item should be queued for
* #param boolean $replace Whether or not to replace any other currently queued entries with the same action/ident
Related
I am attempting to programmatically retrieve a list of users (principalType = "User") and their associated appRoleId values for an enterprise app using itsresourceId value from Azure AD. There is a total of ten Users with a combined total of twenty appRoleId values associated with the app. However, when I run my query I receive data for just two users and a combined total of four appRoleId values.
Here's my C# code:
GraphServiceClient myGraphClient = GetGraphServiceClient([scopes]);
// Retrieve the [Id] value for the app. Note [Id] is a pseudonym for the [resourceId] required to retrieve users and app roles assigned.
var servPrinPage = await myGraphClient.ServicePrincipals.Request()
.Select("id,appRoles")
.Filter($"startswith(displayName, 'Display Name')")
.GetAsync()
.ConfigureAwait(false);
// Using the first [Id] value from the [ServicePrincipals] page, retrieve the list of users and their assigned roles for the app.
var appRoleAssignedTo = await myGraphClient.ServicePrincipals[servPrinPage[0].Id].AppRoleAssignedTo.Request().GetAsync().ConfigureAwait(false);
The query returns a ServicePrincipalAppRoleAssignedToCollectionPage (as expected) but the collection only contains four pages (one per User/appRoleId combination).
As an aside, the following query in Microsoft Graph Explorer produces an equivalent result:
https://graph.microsoft.com/v1.0/servicePrincipals/[resourceId]/appRoleAssignedTo
What am I missing here? I need to be able to retrieve the complete list of users and assigned app roles. Any assistance is greatly appreciated.
The issue I was confronting has to do with the pagination feature employed by Azure AD and MS Graph. In a nutshell, I was forced to submit two queries in order to retrieve all twenty records I was expecting.
If you have a larger set of records to be retrieved you may be faced with submitting a much larger number of successive queries. The successive queries are managed using a "skiptoken" passed as a request header each time your query is resubmitted.
Here is my revised code with notation....
// Step #1: Create a class in order to strongly type the <List> which will hold your results.
// Not absolutely necessary but always a good idea when working with <Lists> in C#.
private class AppRoleByUser
{
public string AzureDisplayName;
public string PrincipalDisplayName;
}
// Step #2: Submit a query to acquire the [id] for the Service Principal (i.e. your app).
// Note the [ServicePrincipals].[id] property is synonymous with the [resourceId] needed to
// retrieve [AppRoleAssignedTo] values from Microsoft Graph in the next step.
// Initialize the Microsoft Graph Client.
GraphServiceClient myGraphClient = GetGraphServiceClient("Directory.Read.All");
// Retrieve the Service Principals page containing the app [Id].
var servPrinPage = await myGraphClient.ServicePrincipals.Request().Select("id,appRoles").Filter($"startswith(displayName, 'Your App Name')").GetAsync().ConfigureAwait(false);
// Store the app [Id] in a local variable (for readability).
string resourceId = servPrinPage[0].Id;
// Step #3: Using the [Id]/[ResourceId] value from the previous step, retrieve a list of AppRoleId/DisplayName pairs for your app.
// Results of the successive queries are typed against the class created earlier and are appended to the <List>.
List<AppRoleByUser> appRoleByUser = new List<AppRoleByUser>();
// Note, unlike "Filter" or "Search" parameters, it is not possible to
// add a "Skiptoken" parameter directly to your query in C#.
// Instead, it is necessary to insert the "skiptoken" as request header using the Graph QueryOption class.
// Note the QueryOption List is passed as an empty object on the first pass of the while loop.
var queryOptions = new List<QueryOption>();
// Initialize the variable to hold the anticipated query result.
ServicePrincipalAppRoleAssignedToCollectionPage appRoleAssignedTo = new ServicePrincipalAppRoleAssignedToCollectionPage();
// Note the number of user/role combinations associated with an app is not always known.
// Consequently, you may be faced with the need to acquire multiple pages
// (and submit multiple consecutive queries) in order to obtain a complete
// listing of user/role combinations.
// The "while" loop construct will be utilized to manage query iteration.
// Execution of the "while" loop will be stopped when the "bRepeat" variable is set to false.
bool bRepeat = true;
while (bRepeat == true)
{
appRoleAssignedTo = (ServicePrincipalAppRoleAssignedToCollectionPage) await myGraphClient.ServicePrincipals[resourceId].AppRoleAssignedTo.Request(queryOptions).GetAsync().ConfigureAwait(false);
foreach (AppRoleAssignment myPage in appRoleAssignedTo)
{
// I was not able to find a definitive answer in any of the documents I
// found but it appears the final record in the recordset carries a
// [PrincipalType] = "Group" (all others carry a [PrincipalType] = "User").
if (myPage.PrincipalType != "Group")
{
// Insert "User" data into the List<AppRoleByUser> collection.
appRoleByUser.Add(new AppRoleByUser{ AzureDisplayName = myPage.PrincipalDisplayName, AzureUserRole = myPage.AppRoleId.ToString() });
}
else
{
// The "bRepeat" variable is initially set to true and is set to
// false when the "Group" record is detected thus signaling
// task completion and closing execution of the "while" loop.
bRepeat = false;
}
}
// Acquire the "nextLink" string from the response header.
// The "nextLink" string contains the "skiptoken" string required for the next
// iteration of the query.
string nextLinkValue = appRoleAssignedTo.AdditionalData["#odata.nextLink"].ToString();
// Parse the "skiptoken" value from the response header.
string skipToken = nextLinkValue.Substring(nextLinkValue.IndexOf("=") + 1);
// Include the "skiptoken" as a request header in the next iteration of the query.
queryOptions = new List<QueryOption>()
{
new QueryOption("$skiptoken", skipToken)
};
}
That's a long answer to what should have been a simple question. I am relatively new to Microsoft Graph but it appears to me Microsoft has a long way to go in making this API developer-friendly. All I needed was to know the combination of AppRoles and Users associated with a single, given Azure AD app. One query and one response should have been more than sufficient.
At any rate, I hope my toil might help save time for someone else going forward.
Could you please remove "Filter" from the code and retry the operation. Let us know if that worked.
I am a beginner with hyperledger composer. I want to use webservice API for request/response json inside JavaScript Transaction. it is possible or not? if you have any examples with this please tell me. Thank in advance!
[
{
"firstname": "string",
"lastname": "string",
"gender": "string"
}
]
You can do that using request-promise module which is availabe to all transaction processor functions via the request global variable. You do not need to add the request or request-promise modules to your package.json file, nor do you need to use the require function to load the modules.
The global request method and all of the convenience methods for the various HTTP methods (request.get, request.post, etc.) are available to transaction processor functions. These methods provide a full set of options for handling request bodies, response bodies, HTTP headers, authentication, cookies, proxies, and TLS/SSL.
Eg:
/**
* Buy a given amount of CONGA stocks.
* #param {org.example.BuyStocks} transaction The transaction.
* #transaction
*/
async function buyStocks(transaction) {
// Look up the current price of the CONGA stock, and parse it into a float.
const priceAsStr = await request.get('http://stocks.org/CONGA');
const price = parseFloat(priceAsStr);
// Get the current participant, and update their stock and balance.
const participant = getCurrentParticipant();
const units = transaction.units;
participant.stockUnits += units;
participant.balance -= price * units;
// Update the current participant in the participant registry.
const participantRegistry = await getParticipantRegistry('org.example.Trader');
await participantRegistry.update(participant);
}
Visit this for reference
Occasionally sending mails fail with the Mail::send function of PrestaShop. I use a external mailserver, and the responsible person there told me that no request was received for sending any mails (I find this strange though). So, I made a little logger doing the following:
if ( !Mail::send() )
// logging details here here..
The Mail::send returns false correctly. Now I would like to know the reason. Therefore I would like to log information about the connection in SwiftMailer. Could someone give me any clues how to solve this in a simple manor (not with SwiftMailer plugins, if possible).
Swift Mailer version: 3.3.2
If you set $die param to true you will cause that script stop and a bad experience for customer while buying or admin while changing order status, etc. You should check the following:
Check if email sending fails on specific email template. If true, you could have a problem with template structure, parameters passed, html rendering, etc.
Every error inside Mail::Send funtion is logged in Prestashop Logs. So you should check it there. You could know every possible error identifyng this kind of code inside function Mail::Send: Tools::dieOrLog(Tools::displayError('Error: invalid SMTP server or SMTP port'), $die);
Specific Swift exceptions are logged with this code: PrestaShopLogger::addLog('Swift Error: ' . $e->getMessage(), 3, null, 'Swift_Message'); so it should appear in Prestashop Logs too.
Anyway, Swift has his own log in class Swift_Log_DefaultLog. You can find it at \tools\swift\Swift\Log\DefaultLog.php. You could modify add or dump function to save logs to an specific file or similar.
Good luck.
Set $die parameter true to display the error. You will need _PS_MODE_DEV_ set to true to see it.
/**
* Send Email
*
* #param int $id_lang Language ID of the email (to translate the template)
* #param string $template Template: the name of template not be a var but a string !
* #param string $subject Subject of the email
* #param string $template_vars Template variables for the email
* #param string $to To email
* #param string $to_name To name
* #param string $from From email
* #param string $from_name To email
* #param array $file_attachment Array with three parameters (content, mime and name). You can use an array of array to attach multiple files
* #param bool $mode_smtp SMTP mode (deprecated)
* #param string $template_path Template path
* #param bool $die Die after error
* #param string $bcc Bcc recipient
* #return bool|int Whether sending was successful. If not at all, false, otherwise amount of recipients succeeded.
*/
public static function Send($id_lang, $template, $subject, $template_vars, $to,
$to_name = null, $from = null, $from_name = null, $file_attachment = null, $mode_smtp = null,
$template_path = _PS_MAIL_DIR_, $die = false, $id_shop = null, $bcc = null, $reply_to = null)
Alternatively you could go to backoffice and menu Advanced Parameters -> Logs, type in a Message filter: error and search for results. It's not guaranteed it will show you only email errors but it narrows it down a lot.
It is not possible to tell you the reason for failure of Mail::send() function. There can be multiple reasons for the failure.
There are 12 lines of code in that returns false in the Mail::send() function, each having a different condition. You need to debug the function to find the exact reason.
You can find the Mail::send() function in Mail.php file at /classes/Mail.php
Tip: You can add log with every 'return false;' statement in the function to check which of them is getting executed.
twilio javascript client set from number , Also how I can get the call sid after connect?
I tried to set the from Number in the call options like the next lines before connect and still the same issue in the javascript
$(document).ready(function () {
Twilio.Device.setup(token);
var connection = null;
$("#call").click(function () {
var params = { "Phone": $('#Phone').val(), "from":$('#Phone').val() };
connection = Twilio.Device.connect(params);
return false;
});
});
-- and inside the server side code vbnet when I am generating the token I added the next code but this doesn't solve the from number issue
Dim options As New CallOptions()
options.Record = True
options.From = model.FromNumber
Dim cap = New TwilioCapability(_settings.AccountSID, _settings.AuthToken)
cap.AllowClientOutgoing(_settings.ClientCallApplicationSID, options)
dim token = cap.GenerateToken()
Twilio evangelist here.
The params collection that you pass into the connect function is just a dictionary of key/value pairs. Those key/values simply get passed as parameters to the Voice URL that Twilio requests when Client makes its connection to Twilio, and you can use those parameters to dynamically generate some TwiML markup. Twilio does not do anything with them.
For example, if this is a PHP application, in the Voice URL you could do something like:
<Response>
<Dial>$_REQUEST['From']</Dial>
</Response>
One note of caution, Twilio already adds a parameter called from (which in the case of Client will be the client identifier set when you made your capability token) to the parameters sent to the Voice URL, so you might want to choose a different key name for your dictionary entry. I normally use a name like target for the key that holds the number that I want to dial.
Hope that helps.
To get the call sid, you can get it in connect event.
Please note that I am using Twilio JS v1.9.7
device.on('connect', function (conn) {
log('Successfully established call!');
//Get the CallSid for this call
callUUID = conn.outboundConnectionId;
console.log('CallSid: ' + callUUID);
});
There exists a DocsClient.get_resource_by_id function to get the document entry for a single ID. Is there a similar way to obtain (in a single call) multiple document entries given multiple document IDs?
My application needs to efficiently download the content from multiple files for which I have the IDs. I need to get the document entries to access the appropriate download URL (I could manually construct the URLs, but this is discouraged in the API docs). It is also advantageous to have the document type and, in the case of spreadsheets, the document entry is required in order to access individual worksheets.
Overall I'm trying to reduce I/O waits, so if there's a way I can bundle the doc ID lookup, it will save me some I/O expense.
[Edit] Backporting AddQuery to gdata v2.0 (from Alain's solution):
client = DocsClient()
# ...
request_feed = gdata.data.BatchFeed()
request_entry = gdata.data.BatchEntry()
request_entry.batch_id = gdata.data.BatchId(text=resource_id)
request_entry.batch_operation = gdata.data.BATCH_QUERY
request_feed.add_batch_entry(entry=request_entry, batch_id_string=resource_id, operation_string=gdata.data.BATCH_QUERY)
batch_url = gdata.docs.client.RESOURCE_FEED_URI + '/batch'
rsp = client.batch(request_feed, batch_url)
rsp.entry is a collection of BatchEntry objects, which appear to refer to the correct resources, but which differ from the entries I'd normally get via client.get_resource_by_id().
My workaround is to convert gdata.data.BatchEntry objects into gdata.docs.data.Resource objects ilke thus:
entry = atom.core.parse(entry.to_string(), gdata.docs.data.Resource)
You can use a batch request to send multiple "GET" requests to the API using a single HTTP request.
Using the Python client library, you can use this code snippet to accomplish that:
def retrieve_resources(gd_client, ids):
"""Retrieve Documents List API Resources using a batch request.
Args:
gd_client: authorized gdata.docs.client.DocsClient instance.
ids: Collection of resource id to retrieve.
Returns:
ResourceFeed containing the retrieved resources.
"""
# Feed that holds the batch request entries.
request_feed = gdata.docs.data.ResourceFeed()
for resource_id in ids:
# Entry that holds the batch request.
request_entry = gdata.docs.data.Resource()
self_link = gdata.docs.client.RESOURCE_SELF_LINK_TEMPLATE % resource_id
request_entry.id = atom.data.Id(text=self_link)
# Add the request entry to the batch feed.
request_feed.AddQuery(entry=request_entry, batch_id_string=resource_id)
# Submit the batch request to the server.
batch_url = gdata.docs.client.RESOURCE_FEED_URI + '/batch'
response_feed = gd_client.Post(request_feed, batch_url)
# Check the batch request's status.
for entry in response_feed.entry:
print '%s: %s (%s)' % (entry.batch_id.text,
entry.batch_status.code,
entry.batch_status.reason)
return response_feed
Make sure to sync to the latest version of the project repository.