Google Content API for Shopping: Error Creating Shipment - php

I'm looking to mark an order in Google Shopping as shipped but getting hung up with how to format the lineItems. I'm following the official docs for shipping line items:
https://developers.google.com/shopping-content/v2/reference/v2.1/orders/shiplineitems
And here is my code:
$client = new Google_Client();
$service = new Google_Service_ShoppingContent($client);
// Get Order and Line Items
$order = $service->orders->get('MERCHANT-ID', 'ORDER-ID', array());
$lineItems = $order->getLineItems();
// Prepare Item Info
foreach($lineItems as $item) {
$items = array('lineItemId' => $item->getId(),'productId' => $item->getProduct()->getId(), 'quantity' => $item->quantityPending);
}
// Prepare Shipment Info
$shipment = array('shipmentId' => 'xxx', 'carrier' => 'ups', 'trackingId' => '1234567890');
// Prepare PostBody
$postBody = new Google_Service_ShoppingContent_OrdersShipLineItemsRequest();
$postBody->operationId = rand();
$postBody->lineItems = $items;
$postBody->shipmentInfos = $shipment;
// Mark Google Order as Shipped
$service->orders->shiplineitems('MERCHANT-ID', 'ORDER-ID', $postBody, array());
This produces the following error, but I haven't been able to figured out exactly what is wrong:
Google_Service_Exception: { "error": { "errors": [ { "domain": "global", "reason": "invalid", "message": "Invalid value for lineItems: {lineItemId=HI2PTRMVLNCZEXP, productId=online:en:US:d3k3245, quantity=2}", "locationType": "other", "location": "" } ], "code": 400, "message": "Invalid value for lineItems: {lineItemId=HI2PTRMVLNCZEXP, productId=online:en:US:d3k3245, quantity=2}" } }
Any ideas what I'm doing wrong?

The API is expecting an Array of Google_Service_ShoppingContent_OrderShipmentLineItemShipment class.
$lineItemShipments = array();
$lineItemShipment = new Google_Service_ShoppingContent_OrderShipmentLineItemShipment();
$lineItemShipment->setLineItemId($item->getId());
$lineItemShipment->setQuantity($item->quantityPending);
$lineItemShipments[] = $lineItemShipment;
$postBody->setLineItems($lineItemShipments);

Related

Google PHP API returning invalid argument error

I am trying to get location insights through the Google PHP Library.
I am doing the example for -> Retrieving basic insights for a given list of locations.
from this page: https://support.google.com/business/thread/1774669/php-code-example-insights-with-mybusiness-php-v3-2?hl=en
require_once $_SERVER['DOCUMENT_ROOT']."/google/auth_google.php";
require_once $_SERVER['DOCUMENT_ROOT']."/MyBusiness.php";
$mybusinessService = new Google_Service_Mybusiness($client);
$accounts = $mybusinessService->accounts;
$accountsList = $accounts->listAccounts()->getAccounts();
$locationStatistics = [];
//
foreach ($accountsList as $accKey => $account) {
$locations = $mybusinessService->accounts_locations;
$locationsList = $locations->listAccountsLocations($account->name)->getLocations();
//
$firstDay = date("Y-m-d\TH:i:s.000\Z", strtotime(date('Y-m-1')));
$lastDay = date("Y-m-d\TH:i:s.000\Z", strtotime("today"));
// // Final Goal of my Code
if (empty($locationsList)===false) {
foreach ($locationsList as $locKey => $location) {
$reviewLink = $location['metadata']['newReviewUrl'];
$locationNames = $location->locationName;
$reportLocationInsightsRequest = new Google_Service_MyBusiness_ReportLocationInsightsRequest($client);
$basicRequest = new Google_Service_MyBusiness_BasicMetricsRequest($client);
$metricRequests = new Google_Service_MyBusiness_MetricRequest($client);
$metricRequests->setMetric("ALL");
$basicRequest->setMetricRequests($metricRequests);
$timeRange = new Google_Service_MyBusiness_TimeRange($client);
$timeRange->setStartTime($firstDay);
$timeRange->setEndTime($lastDay);
$basicRequest->setTimeRange($timeRange);
$reportLocationInsightsRequest->setBasicRequest($basicRequest);
$reportLocationInsightsRequest->setLocationNames(array($location->name));
$reportLocationInsightsResponse = $locations->reportInsights($account->name, $reportLocationInsightsRequest);
$locationMetrics = $reportLocationInsightsResponse->getLocationMetrics();
$locationMetricsArray = array();
$locationMetricsArray['locationMetrics']['locationName'] = array($locationMetrics[0]->getLocationName());
$locationMetricsArray['locationMetrics']['timeZone'] = array($locationMetrics[0]->getTimeZone());
$metricValuesArray = array();
foreach ($locationMetrics[0]->getMetricValues() as $value) {
$metricValuesItem = array();
$metricValuesItem['metric'] = $value['metric'];
$metricValuesItem['totalValue']['timeDimension']['timeRange']['endTime'] = $value['totalValue']['timeDimension']['timeRange']['endTime'];
$metricValuesItem['totalValue']['timeDimension']['timeRange']['startTime'] = $value['totalValue']['timeDimension']['timeRange']['startTime'];
$metricValuesItem['totalValue']['metricOption'] = $value['totalValue']['metricOption'];
$metricValuesItem['totalValue']['value'] = $value['totalValue']['value'];
$metricValuesArray[] = $metricValuesItem;
}
$locationMetricsArray['locationMetrics']['metricValues'] = $metricValuesArray ;
$locData =array();
$locID = str_replace('https://search.google.com/local/writereview?placeid=', '', $reviewLink);
$locData['name'] = $locationNames;
$locData['reviewLink'] = $reviewLink;
$locData['locationID'] = $locID;
}
}
}
But I am getting the following error:
PHP Fatal error: Uncaught Google\Service\Exception: {
"error": {
"code": 400,
"message": "Request contains an invalid argument.",
"errors": [
{
"message": "Request contains an invalid argument.",
"domain": "global",
"reason": "badRequest"
}
],
"status": "INVALID_ARGUMENT"
}
}
There was nothing wrong with the code. The problem was happening from the
$firstDay = date("Y-m-d\TH:i:s.000\Z", strtotime(date('Y-m-1')));
$lastDay = date("Y-m-d\TH:i:s.000\Z", strtotime("today"));
If $firstDay and $lastDay are equal the API returns an error.

Square API - invalid character 'C' looking for beginning of value

I am using Square Charge API, and following is my request object for a test card -
I am using Square provided PHP client to connect to the API. And I am receiving following response for "Charge" endpoint -
[HTTP/1.1 400 Bad Request] {"errors":[{"category":"INVALID_REQUEST_ERROR","code":"BAD_REQUEST","detail":"invalid character 'C' looking for beginning of value (line 1, character 1)"}]}
Following is my code in PHP -
public function chargeCustomerCard($userId, $custId, $cardId, $note, $billingAddres, $amount, $idempotencyKey){
$billingAddrRequest = array("address_line_1" => $billingAddres->addr1, "address_line_2" => $billingAddres->addr2, "locality" => $billingAddres->city, "administrative_district_level_1" => $billingAddres->state, "postal_code" => $billingAddres->zip, "country" => $billingAddres->country);
$billingAddressReq = new \SquareConnect\Model\Address($billingAddrRequest);
$moneyRequest = array("amount" => $amount, "currency" => "USD");
$money = new \SquareConnect\Model\Money($moneyRequest);
$request = array("idempotency_key" => $idempotencyKey, "customer_id" => $custId, "customer_card_id" => $cardId, "delay_capture" => false, "amount_money" => $money, "billing_address" => $billingAddressReq, "note" => $note, "reference_id" => $userId);
$charge = new \SquareConnect\Model\ChargeRequest($request);
$response = null;
try{
$charge_api = new \SquareConnect\Api\TransactionsApi();
$response = $charge_api->charge($this->authtoken, $this->locationId, $charge);
if($response != null && count($response->getErrors()) == 0){
$transaction = $response->getTransaction();
$data = array();
$data['transactionId'] = $transaction->getId();
$data['created'] = $transaction->getCreatedAt();
$data['referenceId'] = $transaction->getReferenceId(); //this should be equal to userid
$tender = $transaction->getTenders()[0];
$data['tenderId'] = $tender->getId();
$data['note'] = $tender->getNote();
$data['amount'] = ($tender->getAmountMoney()->getAmount())/100;
$data['currency'] = $tender->getAmountMoney()->getCurrency();
$processingFee = $tender->getProcessingFeeMoney();
if(isset($processingFee) && !empty($processingFee)){
$data['processingFee'] = $tender->getProcessingFeeMoney()->getAmount();
}else{
$data['processingFee'] = 0;
}
$data['tendertype'] = $tender->getType();
$data['cardStatus'] = $tender->getCardDetails()->getStatus();
$data['cardBrand'] = $tender->getCardDetails()->getCard()->getCardBrand();
$data['cardLast4'] = $tender->getCardDetails()->getCard()->getLast4();
$data['idempotencyKey'] = $idempotencyKey;
$data['customerPayId'] = $custId;
$data['customerCardId'] = $cardId;
return $this->generateReturnData(PAY_API_SUCCESS, '', $data);
}else{
return $this->generateReturnData(PAY_API_FAIL, '', $response->getErrors());
}
}catch(Exception $e) {
return $e->getMessage();
}
}
Can someone please point out to me what am I doing wrong here. I am really stuck here. Other API endpoints are working fine, such as, Create Customer, Create Customer Card API endpoints, using the same approach and same PHP client provided by square.
PS - this is on sandbox

Twinfield gives error when I tried to create new invoice

I want to create an invoice to third party invoice software i.e. twinfield from API. I give all the param according to its library and doc and call from API but it will give error.
{
"success": false,
"error": "Item code not found., The description of an item line cannot be adjusted." }
The API is php-twinfield.
The code is given below.
public function saveInvoice($values)
{
try
{
$user = $values['user'];
$password = $values['password'];
$organization = $values['organisation'];
$officecode = $values['officecode'];
$connection = new \PhpTwinfield\Secure\WebservicesAuthentication($user, $password, $organization);
$customerApiConnector = new \PhpTwinfield\ApiConnectors\CustomerApiConnector($connection);
$office = Office::fromCode($officecode);
$customer = $customerApiConnector->get('1008',$office);
$InvoiceApiConnector = new \PhpTwinfield\ApiConnectors\InvoiceApiConnector($connection);
//class invoiceline object
$line = new \PhpTwinfield\InvoiceLine();
$line
->setArticle(2)
->setQuantity(2)
->setValueExcl(100)
->setUnits(1)
->setVatCode('VH')
->setUnitsPriceExcl(100)
->setDim1(8020)
->setDescription("Testinvoice anand")
->setAllowDiscountOrPremium(false);
//class invoice object
$invoice = new \PhpTwinfield\Invoice();
$invoice
->setCustomer($customer)
->setBank('BNK')
->setDueDate(\Carbon\Carbon::now()->addMonth())
->setPeriod('2018/12')
->setCurrency('EUR')
->setStatus('concept')
->setInvoiceDate('20180606')
->addLine($line)
->setPaymentMethod('cash')
->setInvoiceType('FACTUUR');
$result = $InvoiceApiConnector->send($invoice);
print_r($result);
//$jsonResponse = JsonResponse::success($result);
}
catch (SoapFault $e)
{
$jsonResponse = empty($e->getMessage()) ? JsonResponse::error(class_basename($e)) : JsonResponse::error($e->getMessage());
}
//return $jsonResponse;
}
if change in this line $line->setArticle(0) the error is like that.
{
"success": false,
"error": "ResponseException" }

How to set validation method in Google spreadsheets API

I am confused about the new Google Sheets API v4. My question is: how can I set validation rules for specified column(s) in spreadsheet?
There is no useful tutorial with description how to use appropriate methods.
Result should look like following sample:
That validation should be set before data upload (which works fine).
My current code:
$client = getClient();
$service = new Google_Service_Sheets($client);
$fileId = 'my-document-id';
$body = new Google_Service_Sheets_SetDataValidationRequest(array(
'setRange' => new Google_Service_Sheets_GridRange(
array(
'sheetId'=>'List1',
'startColumnIndex'=>'0',
'endColumnIndex'=>'1'
)
),
'setRule' => new Google_Service_Sheets_DataValidationRule(
array(
'setValues'=>array('YES','NO')
)
)
));
$sheetReq = new Google_Service_Sheets_Request($client);
$sheetReq->setSetDataValidation($body);
$batchUpdateRequest = new Google_Service_Sheets_BatchUpdateSpreadsheetRequest(array(
'requests' => $sheetReq
));
$result = $service->spreadsheets->batchUpdate($fileId, $batchUpdateRequest);
Thank you #random-parts for help, it has brought me to the right track. If someone else will try to solve similar problem in PHP in feature, please find bellow fully working example:
$client = $this->getClient();
$service = new Google_Service_Sheets($client);
$ary_values = ['yes','nope','maybe','never ever'];
foreach( $ary_values AS $d ) {
$cellData = new Google_Service_Sheets_ConditionValue();
$cellData->setUserEnteredValue($d);
$values[] = $cellData;
}
$conditions = new Google_Service_Sheets_BooleanCondition();
$conditions->setType('ONE_OF_LIST');
$conditions->setValues($values);
$setRule= new Google_Service_Sheets_DataValidationRule();
$setRule->setCondition($conditions);
$setRule->setInputMessage('Please set correct value');
$setRule->setShowCustomUi(true);
$range = new Google_Service_Sheets_GridRange();
$range->setStartRowIndex(1);
$range->setEndRowIndex(5);
$range->setStartColumnIndex(1);
$range->setEndColumnIndex(2);
$range->setSheetId(YOUR_SHEET_ID); //replace this by your sheet ID
$valReq = new Google_Service_Sheets_SetDataValidationRequest();
$valReq->setRule($setRule);
$valReq->setRange($range);
$sheetReq = new Google_Service_Sheets_Request();
$sheetReq->setSetDataValidation($valReq);
$bodyReq = new Google_Service_Sheets_BatchUpdateSpreadsheetRequest();
$bodyReq->setRequests($sheetReq);
$result = $service->spreadsheets->batchUpdate($fileId, $bodyReq);
The DataValidationRule object would look like the following:
"rule": {
"condition": {
"type": "ONE_OF_LIST",
"values": [
{ userEnteredValue: "Yes"},
{ userEnteredValue: "No"}
],
},
"inputMessage": "",
"strict": true,
"showCustomUi": true,
}
You want to use rule.condition.type ONE_OF_LIST and then enter the rule.condition.values you want in the list. showCustomUi will show the dropdown
A full example using google apps script from the Sheets script editor:
function setDataVal () {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var validation = {
"setDataValidation": {
"range": {
"sheetId": sheet.getSheetId(),
"startRowIndex": 1,
"endRowIndex": 5,
"startColumnIndex": 1,
"endColumnIndex": 5,
},
"rule": {
"condition": {
"type": "ONE_OF_LIST",
"values": [
{ userEnteredValue: "Yes"},
{ userEnteredValue: "No"}
],
},
"inputMessage": "",
"strict": true,
"showCustomUi": true,
}
},
}
var req = {
"requests": [validation],
"includeSpreadsheetInResponse": false,
}
Sheets.Spreadsheets.batchUpdate(req, ss.getId())
}
Sheets API advanced service will have to be enabled

cakephp and Webhooks

Im new to cakephp and have implemented the Webshop Solution Snipcart. When an order is processed by snipcart they send a webhook to our site. The webhook looks like this according to their documentation:
{
eventName: "order:completed",
mode: "Live",
createdOn: "2013-07-04T04:18:44.5538768Z",
content: {
token: "22808196-0eff-4a6e-b136-3e4d628b3cf5",
creationDate: "2013-07-03T19:08:28.993Z",
modificationDate: "2013-07-04T04:18:42.73Z",
status: "Processed",
paymentMethod: "CreditCard",
email: "customer#snipcart.com",
cardHolderName: "Nicolas Cage",
billingAddressName: "Nicolas Cage",
billingAddressCompanyName: "Company name",
billingAddressAddress1: "888 The street",
billingAddressAddress2: "",
billingAddressCity: "Québec",
billingAddressCountry: "CA",
billingAddressProvince: "QC",
billingAddressPostalCode: "G1G 1G1",
billingAddressPhone: "(888) 888-8888",
shippingAddressName: "Nicolas Cage",
shippingAddressCompanyName: "Company name",
shippingAddressAddress1: "888 The street",
shippingAddressAddress2: "",
shippingAddressCity: "Québec",
shippingAddressCountry: "CA",
shippingAddressProvince: "QC",
shippingAddressPostalCode: "G1G 1G1",
shippingAddressPhone: "(888) 888-8888",
shippingAddressSameAsBilling: true,
finalGrandTotal: 310.00,
shippingAddressComplete: true,
creditCardLast4Digits: "4242",
shippingFees: 10.00,
shippingMethod: "Livraison",
items: [{
uniqueId: "eb4c9dae-e725-4dad-b7ae-a5e48097c831",
token: "22808196-0eff-4a6e-b136-3e4d628b3cf5",
id: "1",
name: "Movie",
price: 300.00,
originalPrice: 300.00,
quantity: 1,
url: "https://snipcart.com",
weight: 10.00,
description: "Something",
image: "http://placecage.com/50/50",
customFieldsJson: "[]",
stackable: true,
maxQuantity: null,
totalPrice: 300.0000,
totalWeight: 10.00
}],
subtotal: 610.0000,
totalWeight: 20.00,
hasPromocode: false,
promocodes: [],
willBePaidLater: false
}
}
And the consume the webhooks looks like this:
<?php
$json = file_get_contents('php://input');
$body = json_decode($json, true);
if (is_null($body) or !isset($body['eventName'])) {
// When something goes wrong, return an invalid status code
// such as 400 BadRequest.
header('HTTP/1.1 400 Bad Request');
return;
}
switch ($body['eventName']) {
case 'order:completed':
// This is an order:completed event
// do what needs to be done here.
break;
}
// Return a valid status code such as 200 OK.
header('HTTP/1.1 200 OK');
My question is, how do I do this in CakePHP version 2.4. I've been looking for days now on the internet for a solution, but tho i'm inexperienced I can't find a proper solution.
Solved it:
public function webhooks(){
//check if POST
if ($this->request->is('post')) {
//Allow raw POST's
$url = 'php://input';
//decode
$json = json_decode(file_get_contents($url), true);
if (is_null($json) or !isset($json['eventName'])) {
// When something goes wrong, return an invalid status code
// such as 400 BadRequest.
header('HTTP/1.1 400 Bad Request');
return;
}
//do whatever needs to be done, in this case remove the quantity ordered from the stock in db.
switch ($json['eventName']) {
case 'order:completed':
$id = $json['content']['items'][0]['id'];
$quantity = $json['content']['items'][0]['quantity'];
$query = $this->Shop->findById($id, 'Shop.stock');
$stock = $query['Shop']['stock'];
$stock = $stock - $quantity;
$this->Shop->updateAll(array('Shop.stock' => $stock), array('Shop.id' => $id));
break;
}
header('HTTP/1.1 200 OK');
}
}
the only thing I would add to your answer is a few more "cake" ways of doing some things.
public function webhooks(){
//check if POST
if ($this->request->is('post') || $this->request->is('put')) {
//Allow raw POST's
$url = 'php://input';
//decode
$json = json_decode(file_get_contents($url), true);
if (empty($json) or empty($json['eventName'])) {
throw new BadRequestException('Invalid JSON Information');
}
//do whatever needs to be done, in this case remove the quantity ordered from the stock in db.
switch ($json['eventName']) {
case 'order:completed':
$id = $json['content']['items'][0]['id'];
$quantity = $json['content']['items'][0]['quantity'];
$shop = $this->Shop->find('first', array(
'conditions' => array(
'Shop.id' => $id,
),
'fields' => array(
'Shop.stock',
),
));
if (empty($shop)) {
throw new NotFoundException(__('Invalid Shop Content'));
}
$stock = $shop['Shop']['stock'];
$stock = $stock - $quantity;
$this->Shop->id = $id;
$this->Shop->saveField('stock', $stock);
break;
}

Categories