Sign-in with Google API: How to get gender, birthday and city in 2022? - google-api

I have a Sign-in with Google API integration that has been approved by Google and is currently working. Other than the basic information, I would also like to obtain gender, birthday and city.
Here's an example of an oauth response I get from Google when logging-in a user:
Google\Service\Oauth2\Userinfo Object ( [internal_gapi_mappings:protected] => Array ( [familyName] => family_name [givenName] => given_name [verifiedEmail] => verified_email ) [email] => contact#xxxxxxxxxxx.com [familyName] => xxxxxxxx [gender] => [givenName] => xxxxxx [hd] => xxxxxxxxxxx.com [id] => xxxxxxxxxxxxxxxxxxxxxxxx [link] => https://plus.google.com/xxxxxxxxxxxxxxxxxxxxxx [locale] => en [name] => xxxxxxx xxxxxxxxx [picture] => https://lh3.googleusercontent.com/a/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx [verifiedEmail] => 1 [modelData:protected] => Array ( [verified_email] => 1 [given_name] => xxxxxx [family_name] => xxxxxxxxxx ) [processed:protected] => Array ( ) )
*note that the gender this user is already set to public in his Google account (still, the gender field appears to be blank).
My questions are:
Is it still possible in 2022?
Can I do it with the sign-in with Google API or with some other API? (involving multiple requests)
What scopes do I need to set in the Google Cloud Console oauth section?
Is there any PHP working example / documentation?
Unfortunately, I did not find any good official/unofficial (and recent) documentation/tutorials related to my use-case. Anyone knows the best approach to follow here?

To get a users gender and birthday information you go though the People api
The people.get method will return this information
{
"resourceName": "people/d200475532672775346",
"etag": "%EgUBBwguNxoEAQIFByIMR3BzQkR2cnI1ZGc9",
"genders": [
{
"metadata": {
"primary": true,
"source": {
"type": "PROFILE",
"id": "d200475532672775346"
}
},
"value": "female",
"formattedValue": "Female"
}
],
"birthdays": [
{
"metadata": {
"primary": true,
"source": {
"type": "PROFILE",
"id": "d200475532672775346"
}
},
"date": {
"month": 1,
"day": 6
}
},
{
"metadata": {
"source": {
"type": "ACCOUNT",
"id": "d200475532672775346"
}
},
"date": {
"year": 1971,
"month": 1,
"day": 6
}
}
]
}

Related

i want to change my API response to become array of array object in laravel

i have a problem for the response, i want to change the response API because i need for my mobile APP, the feature have filter object based on date. So i hope you all can help me to solve the problem
i wanna change the response for my API
before:
{
"tasks": [
{
"id": 7,
"user_id": 1,
"title": "gh",
"date": "2022-02-10 13:05:00",
"deskripsi": "gfh",
"created_at": "2022-02-09T06:05:56.000000Z",
"updated_at": "2022-02-09T06:05:56.000000Z"
},
{
"id": 5,
"user_id": 1,
"title": "ghf",
"date": "2022-02-17 16:05:00",
"deskripsi": "fghf",
"created_at": "2022-02-09T06:05:12.000000Z",
"updated_at": "2022-02-09T06:05:12.000000Z"
},
{
"id": 6,
"user_id": 1,
"title": "fgh",
"date": "2022-02-17 18:05:00",
"deskripsi": "gh",
"created_at": "2022-02-09T06:05:40.000000Z",
"updated_at": "2022-02-09T06:05:40.000000Z"
}
]
}
here is the code for the response API above
return response([
'tasks' => Task::where('user_id', auth()->user()->id)->where('date','>',NOW())->orderBy('date','asc')->get(),
],200);
and i want to change it my response API into this response
{
"tasks": [
{
"date": "2022-02-10",
"task": [
{
"id": 7,
"user_id": 1,
"title": "gh",
"date": "2022-02-10 13:05:00",
"deskripsi": "gfh",
"created_at": "2022-02-09T06:05:56.000000Z",
"updated_at": "2022-02-09T06:05:56.000000Z"
},
{
"id": 7,
"user_id": 1,
"title": "gh",
"date": "2022-02-10 15:05:00",
"deskripsi": "gfh",
"created_at": "2022-02-09T06:05:56.000000Z",
"updated_at": "2022-02-09T06:05:56.000000Z"
}
]
},
{
"date": "2022-02-12",
"task": [
{
"id": 7,
"user_id": 1,
"title": "gh",
"date": "2022-02-12 13:05:00",
"deskripsi": "gfh",
"created_at": "2022-02-09T06:05:56.000000Z",
"updated_at": "2022-02-09T06:05:56.000000Z"
}
]
},
]
}
Do groupBy on the resulting Collection from the query (see docs: https://laravel.com/docs/9.x/collections#method-groupby)
For example, you could do:
$tasksGroupedByDate = Task::where(.......)
->get()
->groupBy(fn (Task $task) => $task->date->format('Y-m-d'));
(Note: above uses PHP 7.4 arrow functions. Also, add a date cast on the date column in your Task model to be able to use ->format( directly on the date field)
The above code results to:
{
'2022-01-01' => [
{ Task object },
{ Task object },
{ Task object },
],
'2022-01-02' => [
{ Task object },
{ Task object },
{ Task object },
],
}
(used Task object for brevity, but that will be ['id' => 1, 'title' => 'Task name', .....])
To morph that to the structure you want, you can use map and then values to remove the keys and turn it back to an ordered array:
$tasksGroupedByDate->map(fn ($tasksInGroup, $date) => [
'date' => $date,
'task' => $tasksInGroup
])->values();
If you want to combine everything into one method chain:
return [
'tasks' => Task::where(......)
->get()
->groupBy(fn (Task $task) => $task->date->format('Y-m-d'))
->map(fn ($tasksInGroup, $date) => [
'date' => $date,
'task' => $tasksInGroup
])
->values(),
];
It sounds like you want to create a human friendly date field based on the date column, then group by it.
While solutions do exists to accomplish this at the database level, I believe you'd still need to loop around it again afterwards to get the hierarchy structure you're looking for. I don't think it's too complicated for PHP to loop through it.
My suggestion is as follows:
Before:
return response([
'tasks' => Task::where('user_id', auth()->user()->id)
->where('date','>',NOW())->orderBy('date','asc')->get(),
],200);
After:
$out = [];
$tasks = Task::where('user_id', auth()->user()->id)
->where('date','>',NOW())->orderBy('date','asc')->get();
foreach($tasks as $task) {
$date = strtok((string)$task->date, ' ');
if (empty($out[$date])) {
$out[$date] = (object)['date' => $date, 'task' => []];
}
$out[$date]->task[] = $task;
}
$out = array_values($out);
return response(['tasks' => $out], 200);
Note in the above I'm using the function strtok. This function might look new even to the most senior of php developers.... It's a lot like explode, except it can be used to grab only the first part before the token you're splitting on. While I could have used explode, since the latter part after the token isn't needed, strtok is better suited for the job here.
$task = Task::where('user_id', auth()->user()->id)->where('date','>',NOW())->orderBy('date','asc')->get();
foreach($task as $item){
$date[] = item->date;
$result = Task::where('user_id', auth()->user()->id)->where('date','=', $date)->get();
}
return response([
'tasks' =>
['date' => $date,
'task' => $task]
],200);
maybe something like this

Cannot retreive virtual card number in test mode via stripe API using Go examples

Trying to follow the example here: https://stripe.com/docs/issuing/cards/virtual
When I add params.AddExpand("number"), no number is returned, yet via the dashboard I was able to see the card numbers. Here's sample code and redacted info for the Req and Resp.
func (ac *appContext) CardRetrieve(id string) *stripe.IssuingCard {
stripe.Key = ac.Config.Stripe.SecretKey
params := stripe.IssuingCardParams{}
params.AddExpand("number")
params.AddExpand("cvc")
ic_num, _ := card.Get(id, &params)
return ic_num
}
Returns:
{
"id": "ic_redacted",
"object": "issuing.card",
"brand": "Visa",
"cancellation_reason": null,
"cardholder": {
"id": "ich_redacted",
"object": "issuing.cardholder",
"billing": {
"address": {
"city": "A Beach",
"country": "US",
"line1": "404 Main St.",
"line2": "Suite #302",
"postal_code": "19001",
"state": "DE"
}
},
"company": null,
"created": 1613338532,
"email": "redacted#notreal.com",
"individual": {
"dob": {
"day": 20,
"month": 10,
"year": 1990
},
"first_name": "User",
"last_name": "Testing",
"verification": {
"document": {
"back": null,
"front": null
}
}
},
"livemode": false,
"metadata": {
},
"name": "User Testing",
"phone_number": "+15165551212",
"requirements": {
"disabled_reason": "under_review",
"past_due": [
]
},
"spending_controls": {
"allowed_categories": [
],
"blocked_categories": [
],
"spending_limits": [
{
"amount": 1,
"categories": [
],
"interval": "daily"
}
],
"spending_limits_currency": "usd"
},
"status": "active",
"type": "individual"
},
"created": 1613338532,
"currency": "usd",
"exp_month": 1,
"exp_year": 2024,
"last4": "0088",
"livemode": false,
"metadata": {
},
"replaced_by": null,
"replacement_for": null,
"replacement_reason": null,
"shipping": null,
"spending_controls": {
"allowed_categories": null,
"blocked_categories": null,
"spending_limits": [
{
"amount": 1,
"categories": [
],
"interval": "daily"
}
],
"spending_limits_currency": "usd"
},
"status": "inactive",
"type": "virtual"
}
What confuses me is the documentation found here:
https://stripe.com/docs/issuing/cards/virtual
It says: You can retrieve both the full unredacted card number and CVC from the API. For security reasons, these fields are only available for virtual cards and will be omitted unless you explicitly request them with the expand property. Additionally, they are only available through the Retrieve a card endpoint. That links to the issue card retrieval end point, but the params defined in the virtual cards example references the CardParams{} struct.
No of the examples show what imported module their aliasing for card to exec card.Get, but it stands to reason given the flow of the documentation that this should be IssuingCardParams{} and that the card alias is referencing: "github.com/stripe/stripe-go/issuing/card"
I also find it strange that we're defining params in the example but not passing it into the card.Get()
Edit:
I went digging through the module and it seems like to get the card details you have to call: details, _ := card.Details(id, params) but I get a 404 when trying to call that. The object returned is actually the right object and I see number and cvc, albeit nil.
I get the following error:
2021/02/15 00:33:06 Request error from Stripe (status 404): {"status":404,"message":"Unrecognized request URL (GET: /v1/issuing/cards/ic_redacted/details). Please see https://stripe.com/docs
So it seems you need to include a /v72 in the import:
"github.com/stripe/stripe-go/v72"
The documentation should be updated to show this and the virtual card example for go should also be updated.

JIRA API Error: 'It is not on the appropriate screen, or unknown' when calling Create Issue endpoint

I met an issue when I call the create issue API in my code, the error is It is not on the appropriate screen, or unknown.' But when trying the test API with the same parameters in postman, it succeeds, is there anyone who knows the reason for this error?
This is my code:
create_url = "https://myjira/rest/api/2/issue/"
jira_hash =
{
"fields": {
"project": {
"id": "51606"
},
"issuetype": {
"name": "SOAK EVENT"
},
"priority": {
"name": "Critical"
},
"labels": ["Chandler"],
"customfield_10012": {
"id": "10006"
},
"fixVersions": [{
"name": "2019-05-r1"
}],
"summary": "10297",
"description": "description"
}
}
HTTParty.post(create_url,
:body => jira_hash.to_json,
:headers => {'Content-Type' => 'application/json', 'Authorization'
=> auth})

Error creating events with Microsoft graph

$p=array(
'subject'=>'Registrado desde iSchool',
'body'=>array(
'contentType'=>'HTML',
'content'=>'Evento de prueba',
),
'start'=>array(
'dateTime'=>'2017-05-28T12:00:00',
'timeZone'=>'Pacific Standard Time'
),
'end'=>array(
'dateTime'=>'2017-05-28T17:00:00',
'timeZone'=>'Pacific Standard Time'
),
'location'=>array('displayName'=>'Mi casa'),
'attendees'=>array(
'emailAddress'=>array('address'=>'email', 'name'=>'name'),
'type'=>'required'
),
);
$this->crear('calendars/'.$this->mg_model->idCalendarioUsuario().'/events', $p);
This function "$this->mg_model->idCalendarioUsuario()" Return the calendar ID
public function crear($objeto, $datos){
//$this->graph->setApiVersion("beta");
$r = $this->graph->createRequest("POST", "/me/$objeto")
//->addHeaders(array("Content-Type" => "application/json"))
->attachBody($datos)
->setReturnType(Event::class)
->execute();
}
Error: 400 Bad Request` response: { "error": { "code": "BadRequest", "message": "Property attendees in payload has a value that does not matc (truncated...)
What am I doing wrong?
The JSON payload for your example should look like this:
{
"subject": "Registrado desde iSchool",
"body": {
"contentType": "HTML",
"content": "Evento de prueba"
},
"start": {
"dateTime": "2017-05-28T12:00:00",
"timeZone": "Pacific Standard Time"
},
"end": {
"dateTime": "2017-05-28T17:00:00",
"timeZone": "Pacific Standard Time"
},
"location": {
"displayName": "Mi casa"
},
"attendees": [{
"emailAddress": {
"address": "email",
"name": "name"
},
"type": "required"
}]
}
Your attendees collection however is rendering as an object instead of an array. It is rendering your attendees as an object instead of an array. This is likely the cause of that payload error.
"attendees": {
"emailAddress": {
"address": "email",
"name": "name"
},
"type": "required"
}
Please note, I'm not a PHP expert so my code here may be rather inelegant. That said, I believe you can ensure it renders as an array by wrapping it in an additional array():
'attendees'=>array(array(
'emailAddress'=>array('address'=>'email', 'name'=>'name'),
'type'=>'required'
)),
Here is the PHP example:
"attendees" => [ array (
"emailAddress" => array(
"address" => "user#domain.com",
"name" => "User's first and last name",
),
"type" => "required",
)],

Filter on aggregated bucket keys?

Given data model structure like this,
{
Id: 123,
"string_facet": [
{
"name": "make",
"value": "Audi"
},
{
"name": "carListType",
"value": "PERSON EU"
},
{
"name": "modelType",
"value": ""
},
{
"name": "engineBrand",
"value": "APT"
},
{
"name": "typeDescription",
"value": "8D2"
}
],
"number_facet": [
{
"name": "typeNumber",
"value": 4614
},
{
"name": "serialNumber",
"value": 2
},
{
"name": "engineSize",
"value": 18
},
{
"name": "horsePower",
"value": 125
},
{
"name": "kw",
"value": 92
},
{
"name": "engineVolume",
"value": 1781
},
{
"name": "listType",
"value": 0
}
],
"dateTime_facet": [
{
"name": "fromDate",
"value": "1999-04-01T00:00:00"
},
{
"name": "toDate",
"value": "2000-10-01T00:00:00"
}
]
}
I want to get aggregates facet names, and values per name. However, I'm only interested in facets that have specific names, such as: make and engineBrand. Note that facets are of type nested.
I have tried the following .NEST expression, but it still returns all of the facet names.
.Global("global", g => g
.Aggregations(ag => ag
.Filter("global_makes", f => f
.Filter(ff => ff
.Nested(n => n
.Path("string_facet")
.Filter(pf => pf.Term("string_facet.name", "make")))
)
.Aggregations(agg => agg
.Nested("nested_string_facet", nested => nested
.Path("string_facet")
.Aggregations(stringFacet => stringFacet
.Terms("name", nameAgg => nameAgg.Field("string_facet.name").Size(0)
.Aggregations(nameAggNext => nameAggNext
.Terms("value", valueAgg => valueAgg.Field("string_facet.value").Size(0))
)
)
)
)
)
)
)
)
);
I have a filter within global (to lose scope of a passed in query), and then filter only on string_facet.name which match "make", but results still include all other names as well. How do I filter out aggregation to include only buckets where name is "make"?
This helped. https://github.com/elastic/elasticsearch/issues/4449
Essentially had to move filter part deeper into aggregation.

Resources