Using laravel to do a webhook for shopify on order creation
I specify my url in the webhook to my site.
I use postcatcher to receive the data from the webhook call so that I know what data they are passing in.
the data looks something like this
{
"customer": {
"default_address": {
"default": true,
"country_name": "Singapore",
"country_code": "SG",
"province_code": null,
"name": "Own Card",
"zip": "234567",
"province": "Singapore",
"phone": "",
"last_name": "Card",
"id": 275454813,
"first_name": "Own",
"country": "Singapore",
"company": "",
"city": "Singapore",
"address2": "",
"address1": ""
},
"last_order_name": null,
"tags": "",
"verified_email": true,
"updated_at": "2014-03-14T06:10:59-04:00",
"total_spent": "0.00",
"state": "disabled",
"orders_count": 0,
"note": null,
"multipass_identifier": null,
"last_order_id": null,
"last_name": "Koh",
"id": 219085425,
"first_name": "Kwang",
"email": "Kwang#a.com.sg",
"created_at": "2014-03-14T05:55:55-04:00",
"accepts_marketing": true
},
"client_details": {
"user_agent": "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36",
"session_hash": "c30217b1565a1f69ca5c1cb944ee6769c39de0f9acc8d6685975d551a2ff246f",
"browser_ip": "118.200.236.161",
"accept_language": "en-GB,en-US;q=0.8,en;q=0.6"
},
"fulfillments": [],
"shipping_address": {
"province_code": null,
"country_code": "SG",
"name": "Own Card",
"zip": "123456",
"province": "Singapore",
"phone": "12345676",
"longitude": "1.151376",
"latitude": "1.2646",
"last_name": "Card",
"first_name": "Own",
"country": "Singapore",
"company": "",
"city": "Singapore",
"address2": "",
"address1": ""
},
"billing_address": {
"province_code": null,
"country_code": "SG",
"name": "Own Card",
"zip": "312133",
"province": "Singapore",
"phone": "",
"longitude": "103.351376",
"latitude": "1.33146",
"last_name": "Card",
"first_name": "Own",
"country": "Singapore",
"company": "",
"city": "Singapore",
"address2": "",
"address1": ""
},
"payment_details": {
"credit_card_company": "Bogus",
"credit_card_number": "XXXX-XXXX-XXXX-1",
"cvv_result_code": null,
"credit_card_bin": "1",
"avs_result_code": null
},
"shipping_lines": [
{
"tax_lines": [],
"title": "Standard Shipping",
"source": "shopify",
"price": "10.00",
"code": "Standard Shipping"
}
],
"line_items": [
{
"tax_lines": [],
"product_exists": true,
"properties": [],
"variant_inventory_management": null,
"name": "test",
"vendor": "Kwang",
"variant_title": "",
"variant_id": 315650553,
"title": "test",
"taxable": true,
"sku": "1",
"requires_shipping": true,
"quantity": 1,
"product_id": 265080025,
"price": "12.00",
"id": 432417197,
"grams": 0,
"fulfillment_status": null,
"fulfillment_service": "manual"
}
],
"tags": "",
"tax_lines": [],
"checkout_id": 221740105,
"processing_method": "direct",
"note_attributes": [],
"discount_codes": [],
"order_number": 1003,
"landing_site_ref": null,
"browser_ip": "118.200.236.122",
"user_id": null,
"updated_at": "2014-03-14T06:10:59-04:00",
"total_weight": 0,
"total_tax": "0.00",
"total_price_usd": "17.37",
"total_price": "22.00",
"total_line_items_price": "12.00",
"total_discounts": "0.00",
"token": "3c71c6a830eee3b7cb0c8627e4d48e03",
"test": true,
"taxes_included": false,
"subtotal_price": "12.00",
"source_url": null,
"source_name": "web",
"source_identifier": null,
"source": "browser",
"referring_site": "",
"reference": null,
"number": 3,
"note": null,
"name": "#1003",
"location_id": null,
"landing_site": "/products/test",
"id": 244075413,
"gateway": "bogus",
"fulfillment_status": null,
"financial_status": "authorized",
"email": "kwank#a.com.sg",
"currency": "SGD",
"created_at": "2014-03-14T06:10:58-04:00",
"confirmed": true,
"closed_at": null,
"checkout_token": "95dc1ed9b867df5b1ecdf770de4eba3b",
"cart_token": "ab1795435caebccb6d96ee69f716a4c9",
"cancelled_at": null,
"cancel_reason": null,
"buyer_accepts_marketing": true
}
How do I actually access it from my php laravel function? I did something like this but when using POSTMAN to send this over i dont get anything from $c.
$inputs = Input::all();
$c = $inputs ['customer'];
Anyone can help?
It seems like you are passing the data as a json body. The code you've shown could've worked but lets try this.
First off do this:
$inputs = Input::all();
$c = $inputs->customer;
Now lets try:
$inputs = Input::json()->all();
$c = $inputs->customer;
Does it return anything?
Finally lets try:
$c = Input::get('customer');
$cd = Input::get('customer.default_address');
Based on the docs:
Some JavaScript libraries such as Backbone may send input to the application as JSON. You may access this data via Input::get like normal.
on postman you have to post that request as a json body.
Select the raw tab then change text to json... and copy paste the whole request into the textarea.
So the actual query you are looking for is:
$customer = Input::get('customer');
now you have everything that is inside the customer in $inputs.
access it like:
$default_address = $customer->default_address; // returns object
$state = $customer->state; // returns string
You can even wrap it around:
if (Request::isJson())
{
// make sure it is from a json body
}
update
try this:
$inputs = Input::all();
dd($inputs); // what does this return?
Related
Im implementing a new feature into my project for when a user begins to search for a tag input, which is a value stored inside of a nested array. With the code that I have currently written, if the whole tag keyword has been typed out, we get back the corresponding user data. Im trying to get this work on every keystroke. I tried to use 'match()' but no luck. Any tips are greatly appreciated.
.... I figured it out
const filterDataByTag = (value) => {
let tagFilter;
let valueLowercase = value.toLowerCase();
if (initialData.data) {
tagFilter = initialData.data.filter((item) => {
item.tag.map((tag) => tag.toLowerCase());
return item.tag.toString().match(valueLowercase);
});
setFilterData(tagFilter);
}
};
[
{
"city": "Fushë-Muhurr",
"company": "Yadel",
"email": "iorton0#imdb.com",
"firstName": "Ingaberg",
"grades": [
"78",
"100",
"92",
"86",
"89",
"88",
"91",
"87"
],
"id": "1",
"lastName": "Orton",
"pic": "https://storage.googleapis.com/hatchways-app.appspot.com/assessments/data/frontend/images/voluptasdictablanditiis.jpg",
"skill": "Oracle",
"tag": ["hello", "test"]
},
{
"city": "Sanghan",
"company": "Avamm",
"email": "cboards1#weibo.com",
"firstName": "Clarke",
"grades": [
"75",
"89",
"95",
"93",
"99",
"82",
"89",
"76"
],
"id": "2",
"lastName": "Boards",
"pic": "https://storage.googleapis.com/hatchways-app.appspot.com/assessments/data/frontend/images/voluptasautreprehenderit.jpg",
"skill": "Sports",
"tag": ["test"]
},
{
"city": "Kugesi",
"company": "Skalith",
"email": "lromanet2#wired.com",
"firstName": "Laurens",
"grades": [
"88",
"90",
"79",
"82",
"81",
"99",
"94",
"73"
],
"id": "3",
"lastName": "Romanet",
"pic": "https://storage.googleapis.com/hatchways-app.appspot.com/assessments/data/frontend/images/aspernaturnonsapiente.jpg",
"skill": "Employee Handbooks",
"tag": []
},
......
const filterDataByTag = (value) => {
let tagFilter;
let valueLowercase = value.toLowerCase();
if (initialData.data) {
tagFilter = initialData.data.filter((item) => {
item.tag.map((tag) => tag.toLowerCase());
return item.tag.forEach((tag) => tag.match(valueLowercase));
});
console.log(tagFilter);
}
};
When the other person declined the meeting and proposed a new time. In Outlook, you can see the proposed time.
Now I am trying to use Microsoft Graph API to get that proposed time.
For example, the original meeting date is 2018-03-08, and the other person declined and proposed a new date 2018-03-12.
I tried
GET /beta/me/messages/{messageId}=?$expand=microsoft.graph.eventMessage/event
However, I cannot find the proposed time from the result returned. How can I get it? Thanks
{
"#odata.context": "https://graph.microsoft.com/beta/$metadata#users('576552d5-3bc0-42a6-a53d-bfceb405db23')/messages/$entity",
"#odata.type": "#microsoft.graph.eventMessage",
"#odata.etag": "W/\"DAAAABYAAACpTc/InBsuTYwTUBb+VIb4AADoRAyI\"",
"id": "AAMkADBlZTUwNTkxLWVmODgtNDVhNC1iZjhlLTdjNjA1ODZlMDI5MgBGAAAAAACUbnk-iwQZRbXMgkfKtmYhBwCpTc-InBsuTYwTUBb_VIb4AAAAAAEMAACpTc-InBsuTYwTUBb_VIb4AADnwc8mAAA=",
"createdDateTime": "2018-03-06T22:29:10Z",
"lastModifiedDateTime": "2018-03-06T22:29:11Z",
"changeKey": "DAAAABYAAACpTc/InBsuTYwTUBb+VIb4AADoRAyI",
"categories": [],
"receivedDateTime": "2018-03-06T22:29:11Z",
"sentDateTime": "2018-03-06T22:29:05Z",
"hasAttachments": false,
"internetMessageId": "<MWHPR15MB18399806CC97C61817C9A2B18BD90#MWHPR15MB1839.namprd15.prod.outlook.com>",
"subject": "New Time Proposed: Test",
"bodyPreview": "",
"importance": "normal",
"parentFolderId": "AAMkADBlZTUwNTkxLWVmODgtNDVhNC1iZjhlLTdjNjA1ODZlMDI5MgAuAAAAAACUbnk-iwQZRbXMgkfKtmYhAQCpTc-InBsuTYwTUBb_VIb4AAAAAAEMAAA=",
"conversationId": "AAQkADBlZTUwNTkxLWVmODgtNDVhNC1iZjhlLTdjNjA1ODZlMDI5MgAQAOnuCMgoRLdGs-1scw6i7EU=",
"conversationIndex": "AdO1mnWL6e4IyChEt0az/WxzDqLsRQAABO5D",
"isDeliveryReceiptRequested": null,
"isReadReceiptRequested": false,
"isRead": false,
"isDraft": false,
"webLink": "https://outlook.office365.com/owa/?ItemID=AAMkADBlZTUwNTkxLWVmODgtNDVhNC1iZjhlLTdjNjA1ODZlMDI5MgBGAAAAAACUbnk%2FiwQZRbXMgkfKtmYhBwCpTc%2FInBsuTYwTUBb%2BVIb4AAAAAAEMAACpTc%2FInBsuTYwTUBb%2BVIb4AADnwc8mAAA%3D&exvsurl=1&viewmodel=ReadMessageItem",
"inferenceClassification": "focused",
"unsubscribeData": [],
"unsubscribeEnabled": false,
"meetingMessageType": "meetingDeclined",
"type": "singleInstance",
"isOutOfDate": false,
"isAllDay": false,
"isDelegated": false,
"body": {
"contentType": "html",
"content": "Hi"
},
"sender": {
"emailAddress": {
"name": "Rose",
"address": "rose#example.com"
}
},
"from": {
"emailAddress": {
"name": "Rose",
"address": "rose#example.com"
}
},
"toRecipients": [
{
"emailAddress": {
"name": "Jack",
"address": "jack#example.com"
}
}
],
"ccRecipients": [],
"bccRecipients": [],
"replyTo": [],
"mentionsPreview": null,
"flag": {
"flagStatus": "notFlagged"
},
"startDateTime": {
"dateTime": "2018-03-08T04:00:00.0000000",
"timeZone": "UTC"
},
"endDateTime": {
"dateTime": "2018-03-08T05:00:00.0000000",
"timeZone": "UTC"
},
"location": {
"displayName": "Test",
"locationType": "default",
"uniqueIdType": "unknown"
},
"recurrence": null,
"event#odata.context": "https://graph.microsoft.com/beta/$metadata#users('576552d5-3bc0-42a6-a53d-bfceb405db23')/messages('AAMkADBlZTUwNTkxLWVmODgtNDVhNC1iZjhlLTdjNjA1ODZlMDI5MgBGAAAAAACUbnk-iwQZRbXMgkfKtmYhBwCpTc-InBsuTYwTUBb_VIb4AAAAAAEMAACpTc-InBsuTYwTUBb_VIb4AADnwc8mAAA%3D')/microsoft.graph.eventMessage/event/$entity",
"event": {
"#odata.etag": "W/\"qU3PyJwbLk2ME1AW/lSG+AAA6EQMeA==\"",
"id": "AAMkADBlZTUwNTkxLWVmODgtNDVhNC1iZjhlLTdjNjA1ODZlMDI5MgBGAAAAAACUbnk-iwQZRbXMgkfKtmYhBwCpTc-InBsuTYwTUBb_VIb4AAAAAAENAACpTc-InBsuTYwTUBb_VIb4AADnwkmiAAA=",
"createdDateTime": "2018-03-06T22:28:32.3852279Z",
"lastModifiedDateTime": "2018-03-06T22:29:11.4604154Z",
"changeKey": "qU3PyJwbLk2ME1AW/lSG+AAA6EQMeA==",
"categories": [],
"originalStartTimeZone": "Pacific Standard Time",
"originalEndTimeZone": "Pacific Standard Time",
"iCalUId": "040000008200E00074C5B7101A82E0080000000000000000000000000000000000000000310000007643616C2D5569640100000033324633333433392D433744452D344338362D393046452D44424639314131363444323900",
"reminderMinutesBeforeStart": 15,
"isReminderOn": true,
"hasAttachments": false,
"subject": "Test",
"bodyPreview": "Test",
"importance": "normal",
"sensitivity": "normal",
"isAllDay": false,
"isCancelled": false,
"isOrganizer": true,
"responseRequested": true,
"seriesMasterId": null,
"showAs": "busy",
"type": "singleInstance",
"webLink": "https://outlook.office365.com/owa/?itemid=AAMkADBlZTUwNTkxLWVmODgtNDVhNC1iZjhlLTdjNjA1ODZlMDI5MgBGAAAAAACUbnk%2FiwQZRbXMgkfKtmYhBwCpTc%2FInBsuTYwTUBb%2BVIb4AAAAAAENAACpTc%2FInBsuTYwTUBb%2BVIb4AADnwkmiAAA%3D&exvsurl=1&path=/calendar/item",
"onlineMeetingUrl": null,
"responseStatus": {
"response": "organizer",
"time": "0001-01-01T00:00:00Z"
},
"body": {
"contentType": "html",
"content": "Hi"
},
"start": {
"dateTime": "2018-03-08T04:00:00.0000000",
"timeZone": "UTC"
},
"end": {
"dateTime": "2018-03-08T05:00:00.0000000",
"timeZone": "UTC"
},
"location": {
"displayName": "Test",
"locationType": "default",
"uniqueId": "Test",
"uniqueIdType": "private"
},
"locations": [
{
"displayName": "Test",
"locationType": "default",
"uniqueId": "Test",
"uniqueIdType": "private"
}
],
"recurrence": null,
"attendees": [
{
"type": "required",
"status": {
"response": "declined",
"time": "2018-03-06T22:29:05Z"
},
"emailAddress": {
"name": "Rose",
"address": "rose#example.com"
}
}
],
"organizer": {
"emailAddress": {
"name": "Jack",
"address": "jack#example.com"
}
}
}
}
The API doesn't expose this information directly. The related entities just don't have the fields defined to show this information. However, the data is obviously there, you just need to know how to get to it. The answer lies in extended properties.
Basically since Graph doesn't expose these values, we need to dig into the MAPI properties that store this data. After a little digging through the Exchange server protocol docs I found PidLidAppointmentProposedStartWhole and PidLidAppointmentProposedEndWhole. We just need to translate those MAPI property definitions into the Graph extended property syntax.
From the doc, those are both in the PSETID_Appointment namespace, which uses the GUID {00062002-0000-0000-C000-000000000046}. PidLidAppointmentProposedStartWhole uses id 0x8250, and PidLidAppointmentProposedEndWhole uses id 0x8251. So those should translate to:
PidLidAppointmentProposedStartWhole: 'SystemTime {00062002-0000-0000-C000-000000000046} Id 0x8250'
PidLidAppointmentProposedEndWhole: 'SystemTime {00062002-0000-0000-C000-000000000046} Id 0x8251'
If we use those in an $expand clause as per Get singleValueLegacyExtendedProperty, we get something like:
GET /me/mailfolders/inbox/messages?$expand=singleValueExtendedProperties($filter=id eq 'SystemTime {00062002-0000-0000-C000-000000000046} Id 0x8250' or id eq 'SystemTime {00062002-0000-0000-C000-000000000046} Id 0x8251')
And the response looks something like this (other properties omitted):
{
"subject": "New Time Proposed: Let's meet",
"singleValueExtendedProperties": [
{
"id": "SystemTime {00062002-0000-0000-c000-000000000046} Id 0x8250",
"value": "2018-03-20T20:00:00Z"
},
{
"id": "SystemTime {00062002-0000-0000-c000-000000000046} Id 0x8251",
"value": "2018-03-20T21:00:00Z"
}
]
}
When using the sample POSTMAN request:
{
"idempotency_key": "74ae1696-b1e3-4328-af6d-f1e04d947a13",
"order": {
"reference_id": "my-order-001",
"line_items": [
{
"name": "line-item-1",
"quantity": "1",
"base_price_money": {
"amount": 1599,
"currency": "USD"
}
},
{
"name": "line-item-2",
"quantity": "2",
"base_price_money": {
"amount": 799,
"currency": "USD"
}
}]
},
"ask_for_shipping_address": true,
"merchant_support_email": "merchant+support#website.com",
"pre_populate_buyer_email": "buyer#email.com",
"pre_populate_shipping_address": {
"address_line_1": "500 Electric Ave",
"address_line_2": "Suite 600",
"locality": "New York",
"administrative_district_level_1": "NY",
"postal_code": "10003",
"first_name": "Jane",
"last_name": "Doe"
},
"redirect_url": "https://merchant.website.com/order-confirm"
}
I'm getting the following response:
{
"errors": [
{
"category": "INVALID_REQUEST_ERROR",
"code": "INVALID_VALUE",
"detail": "The order must have at least one line item.",
"field": "line_items"
}]
}
This is simply executing the sample POSTMAN requests available via https://docs.connect.squareup.com/api/connect/v2/#runningpostman
I was having the same issue and I reached out to Tristan. Tristan replied there was a bug that square development had to fix. I confirmed that the create checkout API is now working properly so this issue should be resolved now.
Are you using your sandbox or production access tokens? I was able to generate a checkout form with the example postman request:
{
"idempotency_key": "73ae1696-b1e3-4328-af6d-f1e04d947a13",
"order": {
"reference_id": "my-order-001",
"line_items": [
{
"name": "line-item-1",
"quantity": "1",
"base_price_money": {
"amount": 1599,
"currency": "USD"
}
},
{
"name": "line-item-2",
"quantity": "2",
"base_price_money": {
"amount": 799,
"currency": "USD"
}
}
]
},
"ask_for_shipping_address": true,
"merchant_support_email": "merchant+support#website.com",
"pre_populate_buyer_email": "buyer#email.com",
"pre_populate_shipping_address": {
"address_line_1": "500 Electric Ave",
"address_line_2": "Suite 600",
"locality": "New York",
"administrative_district_level_1": "NY",
"postal_code": "10003",
"first_name": "Jane",
"last_name": "Doe"
},
"redirect_url": "https://merchant.website.com/order-confirm"
}
I'm working with the Microsoft Graph api to try and sync calendar events from Outlook. I was looking at this article concerning the Outlook api, which suggested I add the header odata.track-changes to my request and I would receive a deltaToken, which I could use on a later request to fetch only those events which had been updated or created since the last sync.
I have been successful fetching events, but I'm not getting a deltaToken back :/
Is this only supported in the Outlook api? Graph's response has Preference-Applied: odata.track-changes, so it's acknowledging my header. Here's my sample request:
GET /v1.0/me/calendar/calendarView
?startDateTime=2016-09-01T00:00:00.0000000
&endDateTime=2099-01-01T00:00:00.0000000
HTTP/1.1
Host: graph.microsoft.com
Authorization: Bearer XXX
Prefer: odata.track-changes
Prefer: odata.maxpagesize=3 //for testing
Cache-Control: no-cache
And my sample response:
{
"#odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('')/calendar/calendarView",
"value": [
{
"#odata.etag": "",
"id": "",
"createdDateTime": "2016-08-04T14:00:25.8552351Z",
"lastModifiedDateTime": "2016-08-25T14:43:54.9950828Z",
"changeKey": "",
"categories": [
"Orange category"
],
"originalStartTimeZone": "Eastern Standard Time",
"originalEndTimeZone": "Eastern Standard Time",
"responseStatus": {
"response": "organizer",
"time": "0001-01-01T00:00:00Z"
},
"iCalUId": "",
"reminderMinutesBeforeStart": 15,
"isReminderOn": true,
"hasAttachments": false,
"subject": "Closing on House",
"body": {
"contentType": "html",
"content": ""
},
"bodyPreview": "",
"importance": "normal",
"sensitivity": "normal",
"start": {
"dateTime": "2016-09-08T19:30:00.0000000",
"timeZone": "UTC"
},
"end": {
"dateTime": "2016-09-08T21:30:00.0000000",
"timeZone": "UTC"
},
"location": {
"displayName": "245 E Main St",
"address": {
"street": "245 E Main St",
"city": "Somewhere",
"state": "NY",
"countryOrRegion": "United States",
"postalCode": ""
}
},
"isAllDay": false,
"isCancelled": false,
"isOrganizer": true,
"recurrence": null,
"responseRequested": true,
"seriesMasterId": null,
"showAs": "busy",
"type": "singleInstance",
"attendees": [],
"organizer": {
"emailAddress": {
"name": "",
"address": ""
}
},
"webLink": "https://outlook.office365.com/owa/?ItemID="
},
{
"#odata.etag": "",
"id": "",
"createdDateTime": "2016-08-19T18:02:39.0607411Z",
"lastModifiedDateTime": "2016-08-19T18:04:10.548447Z",
"changeKey": "",
"categories": [
"Green category"
],
"originalStartTimeZone": "UTC",
"originalEndTimeZone": "UTC",
"responseStatus": {
"response": "organizer",
"time": "0001-01-01T00:00:00Z"
},
"iCalUId": "",
"reminderMinutesBeforeStart": 15,
"isReminderOn": true,
"hasAttachments": false,
"subject": "Moving (off work)",
"body": {
"contentType": "html",
"content": ""
},
"bodyPreview": "",
"importance": "normal",
"sensitivity": "normal",
"start": {
"dateTime": "2016-09-10T00:00:00.0000000",
"timeZone": "UTC"
},
"end": {
"dateTime": "2016-09-13T00:00:00.0000000",
"timeZone": "UTC"
},
"location": {
"displayName": "",
"address": {}
},
"isAllDay": true,
"isCancelled": false,
"isOrganizer": true,
"recurrence": null,
"responseRequested": true,
"seriesMasterId": null,
"showAs": "oof",
"type": "singleInstance",
"attendees": [],
"organizer": {
"emailAddress": {
"name": "",
"address": ""
}
},
"webLink": "https://outlook.office365.com/owa/?ItemID="
},
{
"#odata.etag": "",
"id": "",
"createdDateTime": "2016-09-13T19:05:20.8438647Z",
"lastModifiedDateTime": "2016-09-13T19:05:22.1899702Z",
"changeKey": "",
"categories": [],
"originalStartTimeZone": "America/New_York",
"originalEndTimeZone": "America/New_York",
"responseStatus": {
"response": "organizer",
"time": "0001-01-01T00:00:00Z"
},
"iCalUId": "",
"reminderMinutesBeforeStart": 15,
"isReminderOn": true,
"hasAttachments": false,
"subject": "Coffee Break",
"body": {
"contentType": "html",
"content": ""
},
"bodyPreview": "",
"importance": "normal",
"sensitivity": "normal",
"start": {
"dateTime": "2016-09-15T20:15:00.0000000",
"timeZone": "UTC"
},
"end": {
"dateTime": "2016-09-15T21:15:00.0000000",
"timeZone": "UTC"
},
"location": {
"displayName": "",
"address": {}
},
"isAllDay": false,
"isCancelled": false,
"isOrganizer": true,
"recurrence": null,
"responseRequested": true,
"seriesMasterId": null,
"showAs": "busy",
"type": "singleInstance",
"attendees": [],
"organizer": {
"emailAddress": {
"name": "",
"address": ""
}
},
"webLink": "https://outlook.office365.com/owa/?ItemID="
}
]
}
I redacted anything I thought could be mildly sensitive. Ultimately, my Laravel app is trying to sync events starting 4 months back, and go forever into the future.
If there's a more efficient/better way to do it, I'm open to suggestions. If it matters, these results were generated with Postman. Any help or clarity on this is appreciated.
I ended up using the odata filter like so:
https://graph.microsoft.com/beta/me/calendar/calendarView?startDateTime=2016-05-01T00:00:00Z&endDateTime=2099-01-01T00:00:00Z&$filter=type eq 'singleInstance' and lastModifiedDateTime eq '2016-09-20T07:30:00+00:00'
This will fetch all calendar events scheduled between 2016-05-01T00:00:00Z (May 1st, 2016, midnight, UTC and 2099-01-01T00:00:00Z (January 1st, 2099, midnight, UTC) where the event type is singleInstance (not a recurring event) and the lastModifiedDateTime is after the last sync (in this example, 2016-09-20T07:30:00+00:00).
A few pitfalls with this:
Obviously, this is not url encoded. You would need to do that.
Make sure the + in the lastModifiedDateTime example is properly encoded to %2B, otherwise the Graph API will treat it as a space and reject it.
If you don't filter out recurring events, you will get each recurring event from now until 2099. This is the nature of fetching a list of calendarViews as opposed to events.
If I could do this again, I would probably go back and just do the full calendar sync, which Graph supports (I believe). I just didn't want to sync the whole calendar, only a date range, but it seems that was a doomed endeavor.
But despite the lack of recurring events, it works.
UPDATE
I ended up scrapping this implementation mostly because of the continuing pitfalls I've encountered with maintaining data sync integrity, lack of recurring events, and etc. Instead, I pull calendar events in real time, and maintain a cache. Just some advice in case anyone else ends up in my situation.
when I upload a photo using the arrowdb dashboard on https://platform.appcelerator.com
Cloud.Users.query only shows the photo_id
but whne I created a new user using the dashboard and attached a phot it is showing in the Cloud.Users.query
eg . photo uploaded after user created
{
"id": "563019f18cb04aede69e2111",
"first_name": "store1",
"last_name": "123",
"created_at": "2015-10-28T00:42:25+0000",
"updated_at": "2016-01-22T08:59:44+0000",
"external_accounts": [],
"confirmed_at": "2015-10-28T00:42:25+0000",
"username": "user",
"admin": "false",
"stats": {
"photos": {
"total_count": 0
},
"storage": {
"used": 0
}
},
"photo_id": "56a1dc083a654d090d126792",
"friend_counts": {
"requests": 0,
"friends": 0
}
}
eg. photo uploaded while creating user
{
"id": "56a1f0333a65234234390d7",
"first_name": "qqqq",
"last_name": "wwwe",
"created_at": "2016-01-22T09:02:43+0000",
"updated_at": "2016-01-22T09:07:18+0000",
"external_accounts": [],
"confirmed_at": "2016-01-22T09:02:43+0000",
"username": "qwe",
"admin": "false",
"stats": {
"photos": {
"total_count": 0
},
"storage": {
"used": 0
}
},
"photo": {
"id": "56a1f0333a654d090d0390d8",
"filename": "userPhoto.jpg",
"size": 25394,
"md5": "e20f4fcadf6cde9fccfb458dd11951d4",
"created_at": "2016-01-22T09:02:43+0000",
"updated_at": "2016-01-22T09:02:43+0000",
"processed": true,
"urls": {
"original": "https://s3-us-west-1.amazonaws.com/storage-platform.cloud.appcelerator.com/xmqh1djNEIChtQFP6d37HNH5DQNCXQoX/photos/51/d4/56a1f0333a654d090d0390d9/userPhoto_original.jpg"
},
"content_type": "image/jpeg",
"user": {
"id": "56a1f0333a65234234390d7",
"first_name": "qqqq",
"last_name": "wwwe",
"created_at": "2016-01-22T09:02:43+0000",
"updated_at": "2016-01-22T09:07:18+0000",
"external_accounts": [],
"confirmed_at": "2016-01-22T09:02:43+0000",
"username": "qwe",
"admin": "false",
"stats": {
"photos": {
"total_count": 0
},
"storage": {
"used": 0
}
},
"photo_id": "56a1f0333a654d090d0390d8",
"friend_counts": {
"requests": 0,
"friends": 0
}
}
},
"friend_counts": {
"requests": 0,
"friends": 0
}
}
basically the user which had photo uploaded during creation shows this extra info
"photo": {
"id": "56a1f0333a654d090d0390d8",
"filename": "userPhoto.jpg",
"size": 25394,
"md5": "e20f4fcadf6cde9fccfb458dd11951d4",
"created_at": "2016-01-22T09:02:43+0000",
"updated_at": "2016-01-22T09:02:43+0000",
"processed": true,
"urls": {
"original": "https://s3-us-west-1.amazonaws.com/storage-platform.cloud.appcelerator.com/xmqh1djNEIChtQFP6d37HNH5DQNCXQoX/photos/51/d4/56a1f0333a654d090d0390d9/userPhoto_original.jpg"
},
"content_type": "image/jpeg",
"user": {
"id": "56a1f0333a65234234390d7",
"first_name": "qqqq",
"last_name": "wwwe",
"created_at": "2016-01-22T09:02:43+0000",
"updated_at": "2016-01-22T09:07:18+0000",
"external_accounts": [],
"confirmed_at": "2016-01-22T09:02:43+0000",
"username": "qwe",
"admin": "false",
"stats": {
"photos": {
"total_count": 0
},
"storage": {
"used": 0
}
},
I've been experiencing also that kind of problem, plus I've noticed that the images won't show up from the ArrowDB user interface (not sure if related).
The API returns only an empty object when you query the model:
photo: {}
I've been creating a ticket for the ArrowDB user interface https://jira.appcelerator.org/browse/API-1277.
sachinmw did you create a ticket for the initial problem yet?
A workaround could be to use the photo_id and run another separate query to retrieve the photo model but this is not good for network optimisation purposes.
EDIT
Ok after dealing with Appcelerator directly about having an empty photo: {} Object return the answer is pretty simple:
Whenever you use the query() function like Cloud.Objects.query() from ti.cloud on any ArrowDB object, there is a parameter called response_json_depth which is set to 1 by default and will only return one level of the JSON Object returned by the API.
Without touching that parameter I was seeing:
{
"Vehicle": [
{
"name": "foo",
"photo: {}
}
]
}
By setting response_json_depth to 3 I managed to have:
{
"Vehicle": [
{
"name": "foo",
"photo: {
"urls": {
"original": "http://bar.com"
}
}
}
]
}
Hope that will help someone. The also applies for the Cloud.Objects.show() method for any ArrowDB object.