PHP Stripe customers->search not finding accurate results - stripe-payments

I'm having difficulty with STRIPE customer->search returning incorrect results sometimes.
If I search for a customer, and if it does not exist then add it, then repeat - I can find it adds the customer a second/third/fourth/etc times - for a while. Meanwhile on the stripe dashboard, I can see the customers appearing [multiple times].
If I waited a few minutes between initial refreshes - it seems ok.
Perhaps there's a cache, or a lag or something between adding a customer and the search finding it but this is not very helpful. Am I wrong - or is there something I'm not doing?
The relevant PHP code is here:
$stripe = new \Stripe\StripeClient($stripe_secretkey);
echo "<LI>Searching for $customerNm...</LI>";
$json = $stripe->customers->search(['query' => 'name:\'' . $customerNm . '\'']);
foreach ($json->data as $key) {
echo "<LI>Found id:[" . $key->id . "]";
if (strcmp($key->name, $customerNm) == 0) {
$customerId = $key->id;
$email = $key->email;
break;
}
}
echo "<hr>";
if (strcmp($customerId, "") == 0) {
echo "<LI>Result to search is <PRE style='margin-left:20px'>$json</PRE>";
$email = str_replace(" ", "", str_replace(" ", "", "abc#$customerNm.com"));
$json = $stripe->customers->create(
[
'email' => $email,
'name' => $customerNm,
]);
$customerId = $json->id;
echo "<UL>Created New STRIPE customer id: [$customerId]</UL>\n";
}
}
This code can be found running on a sandbox here** where if you were to run the page multiple times - it will keep creating customers [for a while].
(Note, this page will create a cookie "posterUID" which is used as the customer name; once it's created then it stays until expiry or manual deletion).
** The full source to this can be seen here

This is expected behavior per Stripe's Search documentation:
Don’t use search for read-after-write flows (for example, searching immediately after a charge is made) because the data won’t be immediately available to search. Under normal operating conditions, data is searchable in under 1 minute. Propagation of new or updated data could be more delayed during an outage.

Related

Serial Number from custom table not appear in woocommerce_email_before_order_table action

I have a custom table with serial numbers in WordPress. I have successfully got the serial number to appear on both Order received page after testing with Stripe:
https://prnt.sc/9tz8i3BW7lJR
and it also appears on WooCommerce Admin Orders Page:
https://prnt.sc/jLyb5CQqSAH5
I am using the woocommerce_email_before_order_table action. (on customer_completed_order)
I have the code below and I have echoed the Order ID and the Custom TableName and they BOTH appear in the Thanks for shopping with us email.
It seems the $license query returns nothing and I just can't see why it won't appear.
If I exchange the $woo_order_id for the previous order no, like EMS-0051 the serial number appears.
Is this query too early and it hasn't been populated in the custom table before the query is run?
I cannot get it to work..can anyone see what I have done wrong, please?
The Thanks email and CODE are below.
https://prnt.sc/38wa50jTyr3U
<?php
add_action( 'woocommerce_email_before_order_table', 'add_serial_to_email', 25, 4 );
function add_serial_to_email( $order, $sent_to_admin, $plain_text, $email ) {
global $wpdb;
$ipn_tables = $wpdb->prefix ."ipn_data_tbl";
///////BELOW is using 'seq Order No' plugin..this checks if WOO O/N or plugins O/N.
if (empty($order->get_id)) {
$woo_order_id = $order->get_order_number();
}
elseif (empty($order->get_order_number)) {
$woo_order_id = $order->get_id();
}
///check order ID and Table name are there:
if (!empty($woo_order_id && $ipn_tables )) {
echo '<b>ORDER ID:</b> '.$woo_order_id.'<br>'; // echos the Order ID - appears on "Thanks for shopping with us" email
echo '<b>TABLE NAME:</b> '.$ipn_tables.'<br>'; // echo my Custom table name - appears on "Thanks for shopping with us" email
////But the below $license variable doesn't. I think it's a timing thing.
//$license = $wpdb->get_var(" SELECT serial_no FROM $ipn_tables WHERE woo_order_id = $woo_order_id " );
$license = $wpdb->get_var( $wpdb->prepare( "SELECT * FROM {$ipn_tables} WHERE woo_order_id = %s", $woo_order_id ) );
}
if ( $email->id == 'customer_completed_order' ){
printf( '<p class="custom-text">' .__( 'Your Software Serial Number: '.'<span style="color:red;font-weight:bold;font-size:15px">'.$license ));
}
}//function-END
?>
Forgot to show the MyPHPAdmin table:
https://prnt.sc/A4DH1v2STWrL
edit:
I should have mentioned that I put that license check for orderID and table just to see if it was being checked..it appears my get_var query isn't working (empty?) but that same query is used in the other PHP pages I edited.
Looks like I found the issue. It was the fact that 'woocommerce_payment_complete' hook
was too early BUT the hook 'woocommerce_pre_payment_complete' is called first after payment is made but before order status change and before the email is sent. :)
So all I changed in the add_action was change:
woocommerce_payment_complete' TO woocommerce_pre_payment_complete that's it.
And it worked.
part of the add_action updated code

How to get more customer sources using Stripe NodeJS SDK?

I am able to get customer sources only 1st 10 via get customer API:
# stripe.customers.retrieve
{
"id": "cus_DE8HSMZ75l2Dgo",
...
"sources": {
"object": "list",
"data": [
],
"has_more": false,
"total_count": 0,
"url": "/v1/customers/cus_DE8HSMZ75l2Dgo/sources"
},
...
}
But how do I get more? Is the only way via an AJAX call? I was thinking there should be a function somewhere in the SDK?
When you retrieve a Customer object via the API, Stripe will return the sources property which is a List object. The data property will be an array with up to 10 sources in it.
If you want the ability to get more sources than the 10 most recent ones, you will need to use Pagination. The idea is that you will first get a list of N objects (10 by default). Then you will request the next "page" from Stripe by asking for N objects again but using the parameter starting_after set to the id of the last object in the previous page. You will continue doing that until the has_more property in the page returned is false indicating you retrieved all the objects.
For example if your Customer has 35 sources, you would get the first page (10), then call list to get 10 more (20), then 10 more again (30) and then the last call would return only 5 sources (35) and has_more would be false.
To decrease the number of calls, you can also set limit to a higher value. The maximum value is 100 in that case.
Here's what the code would look like:
// list those cards 3 at a time
var listOptions = {limit: 3};
while(1) {
var sources = await stripe.customers.listSources(
customer.id,
listOptions
);
var nbSourcesRetrieved = sources.data.length;
var lastSourceId = sources.data[nbSourcesRetrieved - 1].id;
console.log("Received " + nbSourcesRetrieved + " - last source: " + lastSourceId + " - has_more: " + sources.has_more);
// Leave if we are done with pagination
if(sources.has_more == false) {
break;
}
// Store the last source id in the options for the next page
listOptions['starting_after'] = lastSourceId;
}
You can see a full running example on Runkit here: https://runkit.com/5a6b26c0e3908200129fbb5d/5b49eabda462940012c33880
Taking a quick look into the sources of the stripe-node package, it seems there is a stripe.customers.listSources method, which takes a customerId as parameter and requests to the correct url. I suppose it works similar to the listCards method. But I couldn't find it in the docs, so you have to treat it as an undocumented feature ... But maybe it's just an error in the docs. You could contact the support about it. We used stripe in an old project and they appreciated any input on their documentation.
As of stripe-node 6.11.0, you may auto-paginate list methods, including customer sources. Stripe provides a few different APIs for this to aid with a variety of node versions and styles.
See the docs here
The important part to notice is .autoPagingEach:
await stripe.customers.listSources({ limit: 100 }).autoPagingEach(async (source) => {
doSomethingWithYourSource(source)
})

How can I add the tracking number to the message the users receive?

I have tried editing uc_order module
function uc_order_token_list($type = 'all') {
...
$tokens['order']['order-tracking-number'] = t('The tracking number of the order.');
...
}
function uc_order_token_values($type, $object = NULL) {
...
$values['order-tracking-number'] = uc_tracking_get_order_tracking_numbers($order);
}
Email Message:
[order-first-name] [order-last-name], Your order number [order-link] at [store-name] has been updated. Order status: [order-status] Order tracking number: [order-tracking-number] Order comment: [order-last-comment] Browse to the following page to login to your account and view your order details: [site-login] Thanks again, [store-name] [site-slogan]
But in the message the user receives, the tracking number is not listed.
Actually this did work, I just did not have an actual tracking number for my order since it was a test order, it never actually got shipped.

Chunk is called with unique data, but renders duplicate content

Guess my problem is closely related to this one : Snippet duplicates content when used multiple times on page
The elements of my problem are the following ...
$modx->loadedResources : an (empty) array registered in the main $modx object via a snippet on page load. The array holds resource id's of the resources fetched from the DB randomly, so the same resource isn't shown twice on the same page.
loadRandomResource : a snippet using XPDO-style querying to load a random resource from the DB. It uses $modx->parseChunk() to fill the placeholders in the chunk with the resource data. With each call, it appends the id of the fetched resource being fetched to the $modx->loadResources array.
I used some debugging to check if the resource id's were properly being stored in my array, each time I fetch a new random resource, which happens to be the case. I then checked if the db returns different results, each time I call the loadRandomResource snippet, and it does. I can also confirm that it doesn't return duplicate results (I exclude the already loaded resource ID's in my XPDO query).
However, when calling the snippet at 3 various locations throughout my page template, all 3 snippet calls render the same resource, which is weird, since my debug shows that unique data is being loaded from the DB, and being sent to the chunk for rendering.
Please find below both the snippet code, as well as the chunk mark-up.
Does anyone have any ideas? Any help is much appreciated!
loadRandomResource snippet
$criteria = $modx->newQuery('modResource');
$criteria->select(array('id','pagetitle'));
$criteria->sortby('RAND()');
$criteria->limit(1);
$whereOptions = array(
'parent' => 2,
'deleted' => false,
'hidemenu' => false,
'published' => true
);
if (!empty($modx->loadedResources)) {
$whereOptions['id:NOT IN'] = $modx->loadedResources;
}
$criteria->where($whereOptions);
$resources = $modx->getCollection('modResource', $criteria);
$output = '';
foreach ($resources as $resource) {
$fields = $resource->toArray();
$fields['tv.tvPersonalPicture'] = $resource->getTVValue('tvPersonalPicture');
$fields['tv.tvJobTitle'] = $resource->getTVValue('tvJobTitle');
$output .= $modx->parseChunk('cnkTeamListItem', $fields);
$modx->loadedResources[] = $fields['id'];
}
return $output;
cnkTeamListItem chunk
<div>
<img src="[[+tv.tvPersonalPicture]]" alt="[[+pagetitle]]" />
<h2>[[+pagetitle]]<br /><span>[[+tv.tvJobTitle]]</span></h2>
</div>
I found the answer myself, solution is a bit odd though ...
I was calling my custom snippet 3 times in my template, uncached. Each call though exactly looked the same ...
[[!loadRandomResource? &type='teammember']]
Even though I had the exclamation mark in place, still ModX was caching the call, within the same page request.
So when I added a random unique value to each of the 3 calls, the issue was solved.
Call 1 : [[!loadRandomResource? &type='teammember' &unique='123465']]
Call 2 : [[!loadRandomResource? &type='teammember' &unique='987654']]
Call 1 : [[!loadRandomResource? &type='teammember' &unique='666666']]
Don't know if this is a bug or a feature, but I thought that the exclamation mark prevented caching, both across different pageviews, as well as within the same page view. Anyhow, thx for helping.
I use this code for rendering chunks in snippents:
<?php
// get chunk or template
$tplRow = $modx->getOption('tplRow', $scriptProperties, '');
// get template
if (substr($tplRow, 0, 6) == "#CODE:") {
$tplRow = substr($tplRow, 6);
} elseif ($chunk = $modx->getObject('modChunk', array('name' => $tplRow), true)) {
$tplRow = $chunk->getContent();
} else {
$tplRow = false;
}
// render template
$field = array(); // your fields
if ($tplRow) {
$chunk = $modx->newObject('modChunk');
$chunk->setCacheable(false);
$chunk->setContent($tplRow);
$output[]= $chunk->process($fields);
} else {
$output[]= '<pre>' . print_r($fields, 1) . '</pre>';
}
You do realize you could have done this with getResources, don't you?
http://rtfm.modx.com/display/ADDON/getResources
&sortby=`RAND()`&limit=`1`

Drupal autocomplete fails to pull out data as a subdomain

I managed to pull out data using autocomplete at my local (http://mysite.dev/swan/autocomplete). The json data is displayed.
But when I applied the same module at live (now a subdomain: http://test.mysite.com/swan/autocomplete with different drupal installs), this autocomplete fails to pull out data. No json data is displayed.
Do you have any idea if this is related to cross domain issue, or any possible cause I might not be aware of?
This is the callback:
/**
* Callback to allow autocomplete of organisation profile text fields.
*/
function swan_autocomplete($string) {
$matches = array();
$result = db_query("SELECT nid, title FROM {node} WHERE status = 1 AND type='organisation' AND title LIKE LOWER ('%s%%')", $string, 0, 40);
while ($obj = db_fetch_object($result)) {
$title = check_plain($obj->title);
//$matches[$obj->nid] = $title;
$matches[$title] = $title;
}
//drupal_json($matches); // fails at safari for first timers
print drupal_to_js($matches);
exit();
}
Any hint would be very much appreciated.
Thanks
It's the conflict with password_policy.module. Other similar modules just do the same blocking. These modules stop any autocomplete query.

Resources