Shopify Custom Carrier Service Error : Your cart has been updated and the items you added can’t be shipped to your address - shopify-api

I've create a shopify app using Codeigniter 4. It's a carrier service app. The carrier service is created successfully and I can see it in my development store in settings under manage rates but I'm getting error while checking out. It says - Your cart has been updated and the items you added can’t be shipped to your address. Remove the items to complete your order. Below is the code to create the carrier service:
$response = $client->post(
"carrier_services",
[
"carrier_service" => [
'active' => true,
"name" => "Faast Delivery",
"callback_url" => "https://app.faastdelivery.com/shopify/rate",
"service_discovery" => true,
]
]
);
And here is my callback function.
public function rate(){
// log the raw request -- this makes debugging much easier
$filename = time();
$input = file_get_contents('php://input');
file_put_contents($filename.'-input', $input);
// parse the request
$rates = json_decode($input, true);
// log the array format for easier interpreting
file_put_contents($filename.'-debug', print_r($rates, true));
// total up the cart quantities for simple rate calculations
$quantity = 0;
foreach($rates['rate']['items'] as $item) {
$quantity =+ $item['quantity'];
}
// use number_format because shopify api expects the price to be "25.00" instead of just "25"
// overnight shipping is 5.50 per item
$overnight_cost = number_format($quantity * 5.50, 2, '', '');
// regular shipping is 2.75 per item
$regular_cost = number_format($quantity * 2.75, 2, '', '');
// overnight shipping is 1 to 2 days after today
$on_min_date = date('Y-m-d H:i:s O', strtotime('+1 day'));
$on_max_date = date('Y-m-d H:i:s O', strtotime('+2 days'));
// regular shipping is 3 to 7 days after today
$reg_min_date = date('Y-m-d H:i:s O', strtotime('+3 days'));
$reg_max_date = date('Y-m-d H:i:s O', strtotime('+7 days'));
// build the array of line items using the prior values
$output = array('rates' => array(
array(
'service_name' => 'Faast Delivery',
'service_code' => 'FSTD',
'total_price' => $overnight_cost,
"description" => "This is the fastest option by far",
'currency' => 'EUR',
'min_delivery_date' => $on_min_date,
'max_delivery_date' => $on_max_date
),
array(
'service_name' => 'Faast Delivery',
'service_code' => 'FSTD',
'total_price' => $regular_cost,
"description" => "This is the fastest option by far",
'currency' => 'EUR',
'min_delivery_date' => $reg_min_date,
'max_delivery_date' => $reg_max_date
)
));
// encode into a json response
$json_output = json_encode($output);
// log it so we can debug the response
file_put_contents($filename.'-output', $json_output);
// send it back to shopify
header('Content-Type: application/json');
echo $json_output;
// return $json_output;
}
Thanks in advance.

I guess and from my experience that your response took more than 10 secs and for that, a message was returned instead.
please refer to the below timeout period for each request per min:
RPM under 1500: read timeout will be 10 seconds
RPM between 1500 and 3000: read timeout will be 5 seconds
RPM over 3000: read timeout will be 3 seconds
Refrence: Dynamic Timeout for CarrierService API Rate Requests

Related

Shopware 5 Cache / Price

Good morning,
I change the customer group in the session on Enlight_Controller_Action_PreDispatch.
if ('private' === $customerGroup) {
$this->session->offsetSet('sUserGroup', 'EK');
$this->session->offsetSet('sOutputNet', 0);
$this->session->offsetSet('sUserGroupData', ['id' => 1, 'groupkey' => 'EK']);
} else {
$this->session->offsetSet('sUserGroup', 'H');
$this->session->offsetSet('sOutputNet', 1);
$this->session->offsetSet('sUserGroupData', ['id' => 2, 'groupkey' => 'H']);
}
In the frontend is a form where you can chooose between gross and net.
Without httpCache it works.
With cache you have to load the page 2 times. Then it works, too.
I have added a cache cookie (https://developers.shopware.com/developers-guide/http-cache/#cache-cookie). The X-Content-Digest value changes. But the result is same. I have to load the page 2 times.
Does anyone have an idea?
Thx,
ottscho

Stripe PHP - How do I retrieve the ID of the newly added card?

I would like to allow our customers to add multiple cards to their accounts. So at the checkout, they can select which card to use or add a new one.
I can select the already added card IDs by calling:
$cardid = $customer->sources->data[0]->id;
$cardid = $customer->sources->data[1]->id;
$cardid = $customer->sources->data[2]->id;
etc...
But I need to retrieve the card ID or the newly added card.
//Create Token
try {
$token = \Stripe\Token::create(
array(
"card" => array(
"name" => $_POST['ccname'],
"number" => $_POST['ccnum'],
"exp_month" => $_POST['ccxpm'],
"exp_year" => $_POST['ccxpy'],
"cvc" => $_POST['cccvc'] )
)); }
catch(\Stripe\Error\Card $e) {
$body = $e->getJsonBody();
$err = $body['error'];
$status = $err['message'];
}
// Add new Card to Custid
$customer = \Stripe\Customer::retrieve($_POST['custid']);
$customer->sources->create(
array(
"source" => $token['id']
));
$cardid = $customer->sources->data[]->id; ???
// Charge CustID
$mysum = $_POST['amount']*100;
$charge = \Stripe\Charge::create(array(
'customer' => $customer,
'amount' => $mysum,
'currency' => 'usd',
'card' => $cardid
));
The card creation request will return the newly created card object, so you can simply grab the ID from there:
$new_card = $customer->sources->create(array(
"source" => $token['id']
));
$new_card_id = $new_card->id;
Note that Stripe will validate the card with the issuing bank when adding the new card to the customer, and may return a card_error if the validation fails. You should wrap the card creation request in a try/catch block to handle possible errors.

Telegram bot - receive photo URL

When a user send an image via Telegram bot it there any way to get the image URL? or I just need to save the image somewhere?
In the message array you receive you can find the key photo.
There you will find multiple arrays with the following format
"file_id" : "XXXX",
"file_size" : 1107,
"width" : 90,
"height" : 51
From one of those array you need to take the file_id. You can then request the file_path with a simple get get on the url https://api.telegram.org/bot<token>/getFile?file_id=<file_id>
You will receive an array that looks as following
"ok" : true,
"result" : {
"file_id" : "XXXX",
"file_size" : 27935,
"file_path" : "photo\/file_1.jpg"
}
From the result you need the file_path and you then got the image location https://api.telegram.org/file/bot<token>/<file_path>
This is a three steps process
First when the user send an image, your bot get a JSON structure like this:
Array
(
[update_id] => 820488009
[message] => Array
(
[message_id] => 11338
[from] => Array
(
[id] => xxxxxx
[is_bot] =>
[first_name] => ANSB
[language_code] => fr
)
[chat] => Array
(
[id] => 333333333
[first_name] => ANSB
[type] => private
)
[date] => 1606316785
[photo] => Array
(
[0] => Array
(
[file_id] => AgACAgEAAxkBAAIsSl--cvE_bez8g1Kzbk6LsR4JZOJWAALxqDEbw8TxRQpbG7Np1dvbARV2ShcAAwEAAwIAA20AA6SRAAIeBA
[file_unique_id] => AQADARV2ShcAA6SRAAI
[file_size] => 34888
[width] => 320
[height] => 240
)
[1] => Array
(
[file_id] => AgACAgEAAxkBAAIsSl--cvE_bez8g1Kzbk6LsR4JZOJWAALxqDEbw8TxRQpbG7Np1dvbARV2ShcAAwEAAwIAA3gAA6WRAAIeBA
[file_unique_id] => AQADARV2ShcAA6WRAAI
[file_size] => 204583
[width] => 800
[height] => 600
)
[2] => Array
(
[file_id] => AgACAgEAAxkBAAIsSl--cvE_bez8g1Kzbk6LsR4JZOJWAALxqDEbw8TxRQpbG7Np1dvbARV2ShcAAwEAAwIAA3kAA6KRAAIeBA
[file_unique_id] => AQADARV2ShcAA6KRAAI
[file_size] => 372915
[width] => 1280
[height] => 960
)
)
)
)
As you can see, Telegram create low resolution of the image. If the original image is small, you can have only the original. If it's medium you'll get two. Here yu can see I have 3 images (the original is the big one 1280*960).
So you have to check the size of the array of image wih (eg i PHP)
$nbr_image = count($jsondata['message']['photo']);
in order to read the file_id of your choice so the oe of the smallest, the biggest etc... Take care, the id is NOT the file_unique_id but the big one so the file_id.
Notice if the user send in one time more than one picture, you will get one message for each picture. So each message is about ONE picture, in multiple resolutions.
Once your bot has the file_id, you must call Telegram sending the file_id. The call is a basic one with:
https://api.telegram.org/bot<token_of_your_bot>/getFile?file_id=<file_id of the picture>
You get back a JSON with:
{"ok":true,
"result":
{"file_id":"AgACAgEAAxkBAAIsUV--hZoxZ5_ctnfbVa0zFWjRtMYUAALyqDEbw8TxRdkTI6iDNvHUmKQSMAAEAQADAgADeAADsx8EAAEeBA",
"file_unique_id":"AQADmKQSMAAEsx8EAAE",
"file_size":41597,
"file_path":"photos/file_0.jpg"
}
So a copy of the file_id, the weight (notice you don't get back pixel size!) and the path.
After that, just make a call using the path like this:
https://api.telegram.org/file/bot<token_of_your_bot>/<file_path from the JSON>
and you'll get the picture
One point: each time I get a JSON with the picture in more than one resolution, the big one is the last. But I've find nothing in the doc about that fact. So I'm note sure you can't have the big one in index [0]...
I know I'm too late, but I was researching for it too long. Here is the answer:
const TelegramBot = require('node-telegram-bot-api');
let bot = new TelegramBot(token, {polling: true});
And the function to download it requires file id, which comes within the message
var file_id = (msg.photo[msg.photo.length-1].file_id);
var downloadDir = './images';
let something = ''
var https = require('https')
bot.getFileLink(fileId).then( async (fileUri) => {
var base64Img = require('base64-img');
let time = process.hrtime();
let extension = fileUri.split('.').pop();
let newName = `${time[0]}${time[1]}.${extension}`;
let file = fs.createWriteStream(`${downloadDir}/${newName}`);
let request = await https.get(fileUri, (response) => {
response.pipe(file);
});
file.on('finish', () =>{
console.log('msg.text ='/images/'+newName')
})
//
});
};
Main function is the bot.getFileLink(fileId). Hope it will help who will read this :)

Is it possible to add more options to the interval of poormanscron in drupal?

Basically I need to run cron more frequently than every hour, but the options in Site Information only go as low as 1 hour. Is there anyway to bypass this or add more options to have cron automatically run say every 30 minutes instead?
I've tried adding more to the array in the below function withing the poormanscron module file but they didn't seem to take anyway.
function poormanscron_form_system_site_information_settings_alter(&$form, &$form_state)
{
$form['cron_safe_threshold'] = array(
'#type' => 'select',
'#title' => t('Automatically run cron'),
'#default_value' => variable_get('cron_safe_threshold', 10800),
'#options' => array(0 => t('Never')) + drupal_map_assoc(array(1800, 3600, 10800, 21600, 43200, 86400, 604800), 'format_interval'),
'#description' => t('When enabled, the site will check whether cron has been run in the configured interval and automatically run it upon the next page request. For more information visit the status report page.', array('#status-report-url' => url('admin/reports/status'))),
);
$form['buttons'] += array('#weight' => 100);
array_unshift($form['#submit'], 'poormanscron_site_information_settings_submit');
}

Infinitescroll to finish after a certain number of posts

I am using Paul Irish's infinitescroll with masonry js on a wordpress site. It is a site with a lot of content. I want infintescroll to stop adding new content when it reaches post number 40 and to give the "No additional items" message at that point. I tried to customize the wordpress loop to only return 40 posts but that did not seem to work.
I thought that maybe one of the options in infinitecroll might do the trick but the infintescroll documentation is very sparse. For example, there is an infinitescroll option in the "loading" init section called "finished: undefined" Is it possible to change that parameter to stop the scrolling after a certain number of content items?
Is there some other obvious way to control when infinitescroll stops loading new content?
Any assistance would be greatly appreciated.
In the Administration -> Settings -> Reading you can set Blog pages show at most to 40.
With code:
Two ways I've done Masonry by numbers like your question I've had success with the following:
limit posts_per_page in your query arguments
$args = array(
'posts_per_page' => 40,
'offset' => 5,
'orderby' => 'post_date',
'order' => 'DESC',
'exclude' => 'none',
'post_type' => 'post',
'post_status' => 'publish',
'suppress_filters' => true
);
$posts = new WP_Query( $args );
if ( $posts -> have_posts()) {
while ( $posts -> have_posts() ) : $posts->the_post(); {
//do stuff with the posts returned here
}
}
or by incrementing:
$counts = 0 ;
$posts = new WP_Query( $args );
if ( $posts -> have_posts()) {
while ( $posts -> have_posts() ) : $posts->the_post(); {
//do stuff with the posts returned here
$counts = ++;
if($counts == 40) { return }
}
}

Resources