There are no available services for the countries you’ve selected" with CarrierService - shopify

I am integrating carrier service API for shopify store. I have partner account and also i have created development store. After installed my app in my store and subscribed carrier service. But in store shipping settings page i got an error
There are no available services for the countries you’ve selected
How to overcome this issue?
I have in the settings page:
My Carrier Service 5588680759
Rate adjustment: 0% + $0.00
There are no available services for the countries you’ve selected.
Automatically offering future shipping services when they become available
Screenshot:
how can i implement on Checkout Page?

I had the same problem and i solved it changing the callback url of the carrier service to public on my shopify application, you have to check if the url is accessible for everyone. (sorry for my english)
Shopify Documentation

You have to define Call url in shipment carries
"callback_url"=> base_url().'shipment/rates'
add these in controller or file which you add in call url
$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 per item
$overnight_cost = number_format(5, 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'));
// build the array of line items using the prior values
$output = array('rates' => array(
array(
'service_name' => 'Shipment Local',
'service_code' => 'SL',
'total_price' => $overnight_cost,
'currency' => 'PKR',
'min_delivery_date' => $on_min_date,
'max_delivery_date' => $on_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
print $json_output;
Change According to you needs

Related

How do i add whatsapp api link to email orders using the customer phone number?

I would like to add whatsapp link to admin complete orders email, that takes the customer phone number, and adds it to the whatsapp api link.
The idea is that, when i receive notification about order, i can contact my customer using whatsapp and let him know i got his order.
so it should look like this:
api.whatsapp.com/send?phone= {{customer phone number}} &text=...
Add the follows code snippet in your active theme's functions.php and changes the text messages as per you.
function add_wp_link_woocommerce_completed_order_email( $order, $sent_to_admin, $plain_text, $email ) {
if ( $email->id == 'customer_completed_order' || $email->id == 'new_order' ) {
$link = 'https://wa.me/'.$order->get_billing_phone( 'edit' ).'/?text='.urlencode( 'your text messages' );
echo '<div style="margin-bottom: 40px;">
<h2>'.__( 'Customer WhatsApp link', 'text-domain' ) .'</h2>
<p>'.__( 'Contact', 'text-domain' ).'</p>
</div>';
}
}
add_action( 'woocommerce_email_customer_details', 'add_wp_link_woocommerce_completed_order_email', 99, 4 );

PayPal Api Patch on Itemlist doesn't work

I want to add an item to my transaction.
$json = '
[
{
"name": "Voucher",
"description":"Voucher",
"price":"50.00",
"currency":"EUR",
"quantity":"1"
}
]';
$patchAddItem = new \PayPal\Api\Patch();
$patchAddItem->setOp('add')
->setPath('/transactions/0/item_list/items')
->setValue(json_decode($json));
$patchReplace = new \PayPal\Api\Patch();
$patchReplace->setOp('replace')
->setPath('/transactions/0/amount')
->setValue(json_decode('{
"total": "159.00",
"currency": "EUR",
}'));
$patchRequest = new \PayPal\Api\PatchRequest();
$patchRequest->setPatches(array($patchAddItem, $patchReplace));
try {
$this->payment->update($patchRequest, $this->apiContext);
} catch (PayPal\Exception\PayPalConnectionExceptio $ex) {
echo '<pre>';print_r(json_decode($ex->getData()));exit;
}
But I get following Error
Eception: Got Http response code 400 when accessing https://api.sandbox.paypal.com/v1/payments/payment/PAY... in PayPal-PHP-SDK/paypal/rest-api-sdk-php/lib/PayPal/Core/PayPalHttpConnection.php on line 154
PayPal-PHP-SDK/paypal/rest-api-sdk-php/lib/PayPal/Transport/PayPalRestCall.php on line 73: PayPal\Core\PayPalHttpConnection->execute("[{"op":"add","path":"/transactions/0/item_list/ite"... )
PayPal-PHP-SDK/paypal/rest-api-sdk-php/lib/PayPal/Common/PayPalResourceModel.php on line 102: PayPal\Transport\PayPalRestCall->execute(array[1],"/v1/payments/payment/PAY-1S151200BX2478240LEAG3CI","PATCH","[{"op":"add","path":"/transactions/0/item_list/ite"... ,null)
PayPal-PHP-SDK/paypal/rest-api-sdk-php/lib/PayPal/Api/Payment.php on line 615: PayPal\Common\PayPalResourceModel::executeCall("/v1/payments/payment/PAY-1S151200BX2478240LEAG3CI","PATCH","[{"op":"add","path":"/transactions/0/item_list/ite"... ,null,object,null)
At this moment I didn't execute the payment object. Do I have to edit the total attribut from amount too? Well, I tried this too, with same issue...
Even if you are sending only one item to PayPal you still have to set them as an item list with setItemList().
That array should be visible if you json_decode in your payment array:
[item_list] => Array
(
[items] => Array
(
[0] => Array
(
[name] => Ground Coffee 40 oz
[sku] => 123123
[price] => 52.80
[currency] => USD
[quantity] => 1
)
)
I had not run a patch for an item yet. I attempted to send an 'add' similar to your code and tried changing the path to '/transactions/0/item_list/items/1' using the next number in the items array. But could not get an add to work.
The only way I could modify the item_list was to do a complete 'replace' of the item_list, so in a running shopping cart would have to include all the items being purchased, not just the new item.
To do this I prefer to use the functions from the PayPal sdk vs building the json arrays. Their examples of how to create and execute a payment are fairly good and use the SDK functions. http://paypal.github.io/PayPal-PHP-SDK/sample/
However the example on updating a payments builds the json arrays outright.
Below is a testing function to modify the item_list using the Paypay PHP SDK Class Functions. I hard coded the Subtotal and Total to match the values coming form the shopping cart plus the increase from the new item. The item_list is also hard coded using PP's example data. Otherwise item's arrays would be built off of a user's shopping cart items. The type is set to 'replace'.
So, yes. Subtotals and Totals need to be updated to match as well, else the PP call will fail.
function updatePayPalPayment ($type, $createdPayment, $total, $subtotal, $shipping, $currency) {
$subtotal = '54.80';
$total = '71.73';
$details = new Details();
$details->setShipping($shipping)
->setSubtotal($subtotal);
$amount = new Amount();
$amount->setCurrency($currency)
->setTotal($total)
->setDetails($details);
$item1 = new Item();
$item1->setName('Ground Coffee 40 oz')
->setCurrency('USD')
->setQuantity(1)
->setSku("123123") // Similar to `item_number` in Classic API
->setPrice(52.80);
$item2 = new Item();
$item2->setName('Granola bars')
->setCurrency('USD')
->setQuantity(1)
->setSku("321321") // Similar to `item_number` in Classic API
->setPrice(2.0);
$itemList = new ItemList();
$itemList->setItems(array($item1, $item2));
$patchItem = new Patch();
$patchItem->setOp($type)
->setPath('/transactions/0/item_list')
->setValue($itemList);
$patchAmount = new Patch();
$patchAmount->setOp($type)
->setPath('/transactions/0/amount')
->setValue($amount);
$patchRequest = new PatchRequest();
$patchRequest->setPatches(array($patchAmount, $patchItem));
$update = $createdPayment->update($patchRequest, getApiContext());
return $update;
}
I also have found it very helpful to set the apiContext for logging to DEBUG and output to a file in development for much better error messages.
'log.LogEnabled' => true,
'log.FileName' => '_PayPal.log',
'log.LogLevel' => 'DEBUG',
Hope that helps.

How to get all products of a Shopify shop?

In my theme development, I don't find the way to get all the products of my shop.
Although, I can retrieve all the collections with the variable collections (exemple: {% for c in collections %}).
Check this url: https://help.shopify.com/en/themes/customization/collections/change-catalog-page
Like magic... all your products...
Get all products at once or to run a query(API Request) for all products in shopify store :
using this app is more managed -> https://github.com/phpish/shopify_private_app-skeleton so, my solution below is based on this app or you can relate the solution with your solution as well
<?php
session_start();
require __DIR__.'/vendor/autoload.php';
use phpish\shopify;
require __DIR__.'/conf.php';
$shopify = shopify\client(SHOPIFY_SHOP, SHOPIFY_APP_API_KEY, SHOPIFY_APP_PASSWORD, true);
try
{
$products = $shopify('GET /admin/products/count.json', array('published_status'=>'published'));
$totalproducts = $shopify('GET /admin/products/count.json', array('published_status'=>'published'));
$limit = 50;
$totalpage = ceil($totalproducts/$limit);
for($i=1; $i<=$totalpage; $i++){
$products = $shopify('GET /admin/products.json?'.$limit.'=50&page='.$i, array('published_status'=>'published'));
foreach($products as $product){
//do anything at once for all the products in store
}
}
}
catch (shopify\ApiException $e)
{
//
}
Summary : The idea is to retrieve with page=x as parameter. after calculating the number of pages we will have with specified limit i.e 50 at one time fetch.

Issue with retrieving Magento Frontend Session

I am trying to retrieve the customer's login status from Flex application using AMF call to the Magento Customer API :
Mage::app('default');
$session = Mage::getSingleton('customer/session', array('name'=>'frontend') );
$sessId= $session->getSessionId();
if($session->isLoggedIn()) {
$name = "Hi ". Mage::getModel('customer/session')->getCustomer()->getName();
return 'true' . $name;
}
else{
return 'false ' . $sessId;
}
Only the PHP session ID is returned:
PHPSESSID=i5s1gcemc6r8uquadc4rsk9ou5
But the user is logged into the below ID
frontend=3qdcimcdp7nq4bi8jlovqmnq61
Let me know if I am missing something here.
Use the following code to get the customer ID
Mage::getSingleton('core/session', array('name' => 'frontend'));
$customer = Mage::getSingleton('customer/session',array('name' => 'frontend'));
echo $customerId = $customer->getCustomer()->getId();

PayPal Adaptive Payments - Error 520009 - Account is restricted

Apologies in advance if this is a silly question. I did try digging around, but couldn't find an answer.
I'm trying to set up a chained payment (at the sandbox environment), but am getting error 520009 (Account is restricted). Tried several email addresses, and they all give me this error. The email addresses are not registered with Paypal, but as far as I know this shouldn't be an issue as the adaptive payments module doesn't require the receivers to have Paypal accounts in advance (though they will need accounts to actually get the money, of course).
What am I doing wrong?
I did set the fee payer to EACHRECEIVER (as suggested on some threads), but the error remains.
This is what I get back:
ERROR Code: 520009
ERROR Message: Account someone1#gmail.com is restricted
Here's my code:
// Config
$endpoint = trim("https://svcs.sandbox.paypal.com/AdaptivePayments/Pay");
$API_UserName = "MY_USERNAME_FROM_SANDBOX";
$API_Password = "MY_PASSWORD_FROM_SANDBOX";
$API_Signature = "MY_SIGNATURE_FROM_SANDBOX";
$API_AppID = "APP-80W284485P519543T";
$API_RequestFormat = "NV";
$API_ResponseFormat = "NV";
// Create request payload with minimum required parameters
$bodyparams = array (
"requestEnvelope.errorLanguage" => "en_US",
"actionType" => "PAY_PRIMARY",
"cancelUrl" => 'http://www.beta.com/cancel',
"returnUrl" => 'http://www.beta.com/return',
"currencyCode" => 'USD',
"feesPayer" => "EACHRECEIVER",
"actionType" => "PAY_PRIMARY",
"receiverList.receiver[0].email" => 'someone1#gmail.com',
"receiverList.receiver[0].amount" => '10',
"receiverList.receiver[0].primary" => 'true',
"receiverList.receiver[1].email" => 'someone2#gmail.com',
"receiverList.receiver[1].amount" => '5',
"receiverList.receiver[1].primary" => 'false',
);
// Convert payload array into url encoded query string
$body_data = http_build_query($bodyparams, "", chr(38));
try
{
//create request and add headers
$params = array("http" => array(
"method" => "POST",
"content" => $body_data,
"header" =>
"X-PAYPAL-SECURITY-USERID: " . $API_UserName . "\r\n" .
"X-PAYPAL-SECURITY-SIGNATURE: " . $API_Signature . "\r\n" .
"X-PAYPAL-SECURITY-PASSWORD: " . $API_Password . "\r\n" .
"X-PAYPAL-APPLICATION-ID: " . $API_AppID . "\r\n" .
"X-PAYPAL-REQUEST-DATA-FORMAT: " . $API_RequestFormat . "\r\n" .
"X-PAYPAL-RESPONSE-DATA-FORMAT: " . $API_ResponseFormat . "\r\n"
));
//create stream context
$ctx = stream_context_create($params);
//open the stream and send request
$fp = #fopen($endpoint, "r", false, $ctx);
//get response
$response = stream_get_contents($fp);
//check to see if stream is open
if ($response === false) {
throw new Exception("php error message = " . "$php_errormsg");
}
//close the stream
fclose($fp);
//parse the ap key from the response
$keyArray = explode("&", $response);
foreach ($keyArray as $rVal){
list($qKey, $qVal) = explode ("=", $rVal);
$kArray[$qKey] = $qVal;
}
//print the response to screen for testing purposes
If ( $kArray["responseEnvelope.ack"] == "Success") {
foreach ($kArray as $key =>$value){
echo $key . ": " .$value . "<br/>";
}
}
else {
echo 'ERROR Code: ' . $kArray["error(0).errorId"] . " <br/>";
echo 'ERROR Message: ' . urldecode($kArray["error(0).message"]) . " <br/>";
}
}
catch(Exception $e) {
echo "Message: ||" .$e->getMessage()."||";
}
Thanks!
EDIT: I could solve the problem by removing the "feesPayer" param, which needs to be the default value (i.e., EACHRECEIVER) in case of a unilateral payment.
I'm stuck with this issue, too.
I wonder how I could achieve a "unilateral payment", which is described by PayPal as follows:
You can use the Pay API operation to make unilateral payments under
limited circumstances. A unilateral payment is a payment that is made
to a receiver who does not have a PayPal account. Unilateral payments
can be used with simple or parallel payments that are implicit or
preapproved. Unilateral payments are not designed to be used with
chained payments or payments that require manual approval through the
web flow. When you send a unilateral payment, you send a payment
request that includes an email address for a receiver, and this email
address is not linked to a registered PayPal account. The receiver
receives an email notifying the receiver to create an account and
claim the payment. PayPal holds a payment to a receiver whose email
address is not yet registered or confirmed until the receiver creates
a PayPal account and confirms the email address. If a refund specifies
a receiver whose email address is not yet registered or confirmed, the
payment to the receiver is canceled.
Anyone having an idea what parameter-setting using NVP is required to achieve this without getting ERROR Code: 520009 ERROR Message: Account someone1#gmail.com is restricted
Any hint is highly appreciated!
"but as far as I know this shouldn't be an issue as the adaptive
payments module doesn't require the receivers to have Paypal accounts
in advance "
That's incorrect. For Adaptive Chained Payments, all receivers must have an active and verified Personal, Premier or Business PayPal account.