Can Stripe have status as active and trialing at the same time? - wordpress

Is it possible to have status as active and trialing both?
Following code works for active subscription but I also want to retrieve data having status as "trialing".
$all_subs = \Stripe\Subscription::all(
array(
"plan" => $group_plan_id,
"status" => "active",
'limit' => 100
)
);

The documentation specifically says "one of...", so you can only choose one status per call. You will need to either make two calls with each status type, or use the status "all" to get ALL of the types (which will also return cancelled, past_due, and unpaid) and then filter out the ones you don't want.
$all_subs = \Stripe\Subscription::all(
array(
"plan" => $group_plan_id,
"status" => "all",
"limit" => 100
)
);
$statuses = array('active','trialing');
foreach ($all_subs->data as $sub) {
if (!in_array($sub->status,$statuses)) {
continue;
}
// do some code here
}
Source: Stripe API Reference

Related

Woocommerce update_status() Only Works for Admin Orders

Very odd issue. I have built a plugin (for a client, not a public one) that creates a couple of REST endpoints that a shipping service (Shippo) passes data to (all this is fine and working). The plugin takes the data, gets an Order Number, and attempts to set a Completed status.
The code only works perfectly if the Order is from the Admin account. But any other custom account and the status will not save. An order note is generated claiming the status was changed, and I can set meta data on the order. But the status will not change.
In the code, I have attempted to use update_status() and set_status() both with and without .save();
add_action('rest_api_init', function () {
register_rest_route('lab/v1', '/shipment_label_created_shippo', ['methods' => 'POST', 'callback' => 'rest_shipment_label_created_shippo', 'permission_callback' => '__return_true', ]);
register_rest_route('lab/v1', '/shipment_label_updated_shippo', ['methods' => 'POST', 'callback' => 'rest_shipment_label_updated_shippo', 'permission_callback' => '__return_true', ]);
register_rest_route('lab/v1', '/shipment_tracking_updated_shippo', ['methods' => 'POST', 'callback' => 'rest_shipment_tracking_updated_shippo', 'permission_callback' => '__return_true', ]);});
// Label Created in Shippo (transaction_created)
function rest_shipment_label_created_shippo($data){
$log = new WC_Logger();
$response = new WP_REST_Response("Failed");
$response->set_status(200);
$meta_order_number = $data['data']['metadata'];
$woo_order_number = explode(" ", $meta_order_number);
$order_number = intval($woo_order_number[1]);
if ($shippo_status == "SUCCESS" && !is_null($shippo_order_id)) {
if( class_exists('WC_Order') && $order_number > 0 ) {
$order = wc_get_order($order_number);
if ($order) {
$payment_method = $order->get_payment_method();
$payment_method_title = $order->get_payment_method_title();
$date_paid = $order->get_date_paid();
// Update the Order Meta as well for tracking
$update_order_was_shipped = update_post_meta($order_number, '_order_was_shipped', $date_shipped);
// Add the Shippo Transaction ID
$update_transactionid = update_post_meta($order_number, '_shippo_transaction_id', $shippo_transaction_id);
if ($payment_method == "invoice" && !is_null($date_paid))
{
$order->update_status('shipped-invoiced');
$saved_order_id = $order->save();
}
else
{
$order->update_status('completed');
$saved_order_id = $order->save();
}
}
Thanks in advance for any thoughts you might have!
Just in case someone else stumbles onto this I wanted to answer the question.
The reason it appears as though only Admin orders (orders I placed) are working is because I never had the order tab up. Our client, always had the Order open that they were updating via a 3rd party. When the Rest API was hit by the 3rd party, order details were not saved because the order was locked.
This makes sense of course, but was not top of mind for me.

Wordpress REST API "orderby" meta value

I am execting following GET request to obtain data form wordpress
http://domain:port/wp-json/wp/v2/announcement?_fields=announcement_category,effective_start_date,effective_end_date
The result is as below
[
{
"announcement_category": [
216
],
"effective_start_date": "2020-03-27",
"effective_end_date": "2020-04-16"
},
{
"announcement_category": [
215
],
"effective_start_date": "2020-03-25",
"effective_end_date": "2020-03-31"
}]
I need to sort/order my response in the ASC order of the "announcemet_category" value. (there is always one value for this array)
I know "orderby" does not support meta_values.
How to enable meta_value sorting and how can I execute my query for this.
Please help
You should be able to sort on a meta value using:
$q = new WP_Query(
// Other query params e.g. post type...
array(
'meta_key' => 'announcement_category',
'orderby' => 'meta_value_num',
'order' => 'ASC',
)
);
Based on this answer.
However I think your issue is that as you've pointed out, announcement_category is an array rather than a number, which you won't be able to sort on.
If you can't change announcement_category to a number rather than an array, you can use a usort to sort the results of your WordPress query, before sending the API response:
$arr1 = array(
array('announcement_category'=>array(216)),
array('announcement_category'=>array(218)),
array('announcement_category'=>array(202)),
array('announcement_category'=>array(300)),
);
function sortByOrder($a, $b) {
return $a['announcement_category'][0] - $b['announcement_category'][0];
}
usort($arr1, 'sortByOrder');
print_r($arr1); // Ordered ascendingly
Alternatively, you can use javascript on the client side to sort the response as required:
announcements.sort(function (a, b) {
return a[announcement_category][0] - b[announcement_category][0];
});
Array Sort

Get list of Webhooks from Woocommerce

I have built a Wordpress plugin that among other things, creates several Woocommerce Webhooks upon activation. This is done using internal API classes and functions, as per below:
function createWebhook($userID,$topic,$secret,$deliveryURL,$status)
{
$webhook = new WC_Webhook();
$webhook->set_user_id($userID); // User ID used while generating the webhook payload.
$webhook->set_topic( $topic ); // Event used to trigger a webhook.
$webhook->set_secret( $secret ); // Secret to validate webhook when received.
$webhook->set_delivery_url( $deliveryURL ); // URL where webhook should be sent.
$webhook->set_status( $status ); // Webhook status.
$save = $webhook->save();
return $save;
}
This works well.
What I want to be able to do is remove these Webhooks upon deactivation of the plugin. Is there any way to fetch the Woocommerce Webhooks via the internal Wordpress or Woocommerce API, so I can loop through and remove the relevant ones?
I would just remove all Webhooks where the delivery URL has a domain of xyz.com. This part is straight-forward, I just don't know how to fetch the Webhooks.
I don't want to use the external Woocommerce API, which requires an API key and HTTP requests.
Thanks
I ended up querying the database to get the webhooks, which looks to be working well. I'm not sure there's any other way. Please let me know if there is!
global $wpdb;
$results = $wpdb->get_results( "SELECT webhook_id, delivery_url FROM {$wpdb->prefix}wc_webhooks" );
foreach($results as $result)
{
if(strpos($result->delivery_url, 'domain.com') !== false)
{
$wh = new WC_Webhook();
$wh->set_id($result->webhook_id);
$wh->delete();
}
}
#greg's answer points you in the right direction, but the returned data is just an array of ID's for each webhook, to get more data you need to parse those ID's into webhook objects - which has protected props, but public getter methods, like so:
$data_store = \WC_Data_Store::load( 'webhook' );
$webhooks = $data_store->search_webhooks([ 'status' => 'active', 'paginate' => true ] );
$_items = array_map( 'wc_get_webhook', $webhooks->webhooks );
$_array = [];
foreach( $_items as $_item ){
$_array[] = [
'id' => $_item->get_id(),
'name' => $_item->get_name(),
'topic' => $_item->get_topic(),
'delivery_url' => $_item->get_delivery_url(),
'secret' => $_item->get_secret(),
];
}
You can get an array of all webhook IDs with the following:
$data_store = WC_Data_Store::load( 'webhook' );
$webhooks = $data_store->search_webhooks();
That's what WooCommerce does when building the table list:
https://github.com/woocommerce/woocommerce/blob/master/includes/admin/class-wc-admin-webhooks-table-list.php

Google Analytics Custom Metrics not showing up

I want to push the products profit of a transaction to Google Analytics.
With this i want to generate a report where i can see the total Product revenue and it's profit for each product that has been ordered.
i'm using this api to push custom metrics to analytics (Measurement protocol api)
I have made several custom metrics in analytics, for example:
Productsprofit (Scope hit, decimal)
Productsprofit2 (Scope Product, decimal)
I've googled several times and i think i need to use the Scope Hit for this type of tracking, am i right?
I've used the api to push the metric with the right indexes to Analytics
$analytics->setTransactionId('test'.$orderId)
->setAffiliation('Testshop')
->setRevenue(number_format($orderTotalPrice,2,'.',''))
->setTax(number_format($taxTotal,2,'.',''))
->setShipping(number_format($shippingTotal,2,'.',''))
->setCouponCode('');
foreach($orderInfo['orderDetails'] as $orderDetail) {
// Include a product, only required fields are SKU and Name
$productData1 = [
'sku' => $orderDetail['model'],
'name' => $orderDetail['name'],
'brand' => '',
'category' => '',
'variant' => '',
'price' => number_format($orderDetail['price'], 2, '.', ''),
'quantity' => $orderDetail['aantal'],
'coupon_code' => '',
'position' => 0,
'custom_metric_3'=>50.45, //<-- test data (Hit)
'custom_metric_4'=>15.50 //<-- test data (Product)
];
$analytics->addProduct($productData1);
}
// Don't forget to set the product action, in this case to PURCHASE
$analytics->setProductActionToPurchase();
// Finally, you must send a hit, in this case we send an Event
$analytics->setEventCategory('Checkout')
->setEventAction('Purchase')
->sendEvent();
I've created a custom report and added these metric to my report. But both metrics stay empty in my report.
Does anyone know what i'm doing wrong ? or what might solve my problem?
Thanks in advance!
In the PHP library that you are using, custom metrics and dimensions are set in a different manner depending on the scope, for Product scope you use the product array like you did, for Hit scope you use the setCustomMetric method. In your code this would look like:
$analytics->setTransactionId('test'.$orderId)
->setAffiliation('Testshop')
->setRevenue(number_format($orderTotalPrice,2,'.',''))
->setTax(number_format($taxTotal,2,'.',''))
->setShipping(number_format($shippingTotal,2,'.',''));
foreach($orderInfo['orderDetails'] as $orderDetail) {
$productData1 = [
'sku' => $orderDetail['model'],
'name' => $orderDetail['name'],
'brand' => 'the brand',
'category' => 'test category',
'variant' => 'variant x',
'price' => number_format($orderDetail['price'], 2, '.', ''),
'quantity' => $orderDetail['qty'],
'coupon_code' => 'coupon used',
'custom_metric_4' => 15.50,
];
$analytics->addProduct($productData1);
}
$analytics->setProductActionToPurchase();
$analytics->setCustomMetric(50.45, 3);
$analytics->setEventCategory('Checkout')
->setEventAction('Purchase')
->sendEvent();
Notice the call to $analytics->setCustomMetric(50.45, 3); before sending the hit. This should send the right data, the rest is creating or looking at the right report in Google Analytics.

Using token as data selector

I created the following token; however, when I try to use site:coupons as a data selector in a loop action
It does not appear in data selection browser. Note that it does appear as replacement pattern when i use for example "Show a message on the site" action.
I spent lot of time searching in the internet and rules' token' issue queue, i tried to read the source codes of core token , token and rules as well. I also found some information too like data selector are no tokens! or rules only works with entities!
So far i couldn't get this to work no matter hard i tried. My data is not entity. Is there anyway to integrate it with rules?
I couldn't find any official documentation on this so i created an issue with hope that some of the rule's experts can help me out.
Note : if i replace site with coupon-link in the following code, it won't even appear as replacement pattern in rules. but it works fine as token anywhere else but in rules
Thanks in advance
<?php
/**
* Implements hook_token_info().
*/
function coupon_link_token_info() {
$types['coupon-link'] = array(
'name' => t("Coupon link coupon info"),
'description' => t("Info about linked coupon via url."),
);
// Andy Pangus specific tokens.
$tokens['site']['coupon-code'] = array(
'name' => t("Coupon Link Coupon Code"),
'description' => t("The code of the coupon entered via url."),
);
$tokens['site']['coupon'] = array(
'name' => t("Coupon Link Coupon"),
'description' => t("The coupon entered via url."),
'type' => 'commerce_coupon'
);
$tokens['site']['coupons'] = array(
'name' => t("Coupon Link List Coupons"),
'description' => t("The coupons entered via url."),
'type' => 'array'
);
return array(
'types' => $types,
'tokens' => $tokens,
);
}
/**
* Implements hook_tokens().
*
* #ingroup token_example
*/
function coupon_link_tokens($type, $tokens, array $data = array(), array $options = array()) {
$replacements = array();
$sanitize = !empty($options['sanitize']);
// Text format tokens.
if ($type == 'site' && __coupon_link_get_coupon_code()) {
//$format = $data['format'];
foreach ($tokens as $name => $original) {
switch ($name) {
case 'coupon-code':
// Since {filter_format}.format is an integer and not user-entered
// text, it does not need to ever be sanitized.
$replacements[$original] = $sanitize ? filter_xss(__coupon_link_get_coupon_code()) : __coupon_link_get_coupon_code();
break;
case 'coupon':
// Since the format name is user-entered text, santize when requested.
$replacements[$original] = __coupon_link_get_coupon(__coupon_link_get_coupon_code());
break;
case 'coupons':
// Since the format name is user-entered text, santize when requested.
$replacements[$original] = array(__coupon_link_get_coupon(__coupon_link_get_coupon_code()));
break;
}
}
}
return $replacements;
}
?>
A few things.
Tokens are formatted as [type:token] as explained on the hook_token_info api page. For your example, it would be [coupon-link:coupon]. I'm not sure why you're appending your tokens to the site array, as your custom coupon token probably has nothing to do with sitewide tokens like *site_url* or *site_name*.
Because the types are machine names, you should change it to coupon_link as machine names with dashes are not Drupal standard.
If you truly get lost, I suggest also looking at the token example from the examples module.

Resources