Laravel 5 dingo api, add multiple transformed objects to the response - laravel-5.1

Want to add a transformed object along with other response, I have used following code:
$accessToken = Authorizer::issueAccessToken();
$user = User::where('email', $request->get('username'))->with('profile')->first();
if ($user) {
$accessToken['user'] = $this->response->item($user, new UserTransformer);
}
return $accessToken;
Expected Response:
{
"access_token": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"token_type": "Bearer",
"expires_in": 31536000,
"data": {
"id": 1,
"email": "xxxxx",
"profile": {
"data": {
"id": 1,
"first_name": "Muhammad",
"last_name": "Shakeel",
}
}
}
}
but not getting transformed object, there must be some better way to add multiple transformed objects with response. Am I missing something?
Edit
Current response returns user object without transformation and if I return only user transformed object like following, it returns correct transformed object:
return $this->response->item($user, new UserTransformer);

As discussed on the issue tracker(https://github.com/dingo/api/issues/743#issuecomment-160514245), jason lewis responded to the ticket with following:
The only way you could do this at the moment would be to reverse that. So you'd return the response item, then add in the access token data, probably as meta data.
So, something like this.
return $this->response->item($user, new UserTransformer)->setMeta($accessToken);
The response will then contain a meta data key which will contain your access token data.

I got it to work using Internal Requests. https://github.com/dingo/api/wiki/Internal-Requests
So what you can do is
Suppose you have a route that fetches transformed user object at api/users/{email_id}?access_token=...
While issuing the access_token you can do the following :
$dispatcher = app('Dingo\Api\Dispatcher');
$array = Authorizer::issueAccessToken();
$array['user'] = $dispatcher->get('api/users/'.$request->get("username").'?access_token='.$array['access_token']);
return $array;
This will return transformed data.
NOTE : You will need to have a route that fetches user data.
You will have to handle cases in /api/users/{email-id} where email-id does not exist.

Related

Google Slides API reports Invalid requests[0].updateTableCellProperties: Invalid field: table_cell_properties

Trying to troubleshoot an error message my app gets after sending a batchUpdate request to Google Slides API
Invalid requests[19].updateTableCellProperties: Invalid field: table_cell_properties
The 19th request in the batch is the only updateTableCellProperties request I have. If I removing the 19th request from the batch, everything works fine.
Other requests which I run in this batchUpdate with no issues are are insertTableRows, deleteTableRow, insertText, updateParagraphStyle, updateTextStyle, updateTableColumnProperties. They all work on the same table, so I use the same objectId, but depending on the request I have to specify it as tableObjectId instead of objectId.
Unsure if I am generating a wrong request for the only updateTableCellProperties request I have, or if there is a problem in the Google Slides ruby gem itself, I tried sending just this updateTableCellProperties request from the Google Slides API explorer which has some validation on the request structure. So I sent this updateTableCellProperties batchUpdate request
{
"requests": [
{
"updateTableCellProperties": {
"objectId": "gf9d8fea71f_22_1",
"tableRange": {
"location": {
"columnIndex": 0,
"rowIndex": 1
}
},
"fields": "tableCellProperties",
"tableCellProperties": {
"tableCellBackgroundFill": {
"solidFill": {
"color": {
"themeColor": "LIGHT1"
}
}
}
}
}
}
]
}
And I got this error:
{
"error": {
"code": 400,
"message": "Invalid requests[0].updateTableCellProperties: Invalid field: table_cell_properties",
"status": "INVALID_ARGUMENT"
}
}
Why is this updateTableCellProperties request reported as invalid? I am also confused by the output of the error message as it mentions table_cell_properties in snake case, while the documentation only mentions tableCellProperties in camel case, and my request also only mentions tableCellProperties in camel case. I am only aware of the ruby gems translating between snake case and camel case, but this is not relevant to the API Explorer.
The error Invalid field: table_cell_properties originates from the erroneously specified fields property
See documentation:
fields
At least one field must be specified. The root tableCellProperties is implied and should not be specified. A single "*" can be used as short-hand for listing every field.
So you need to modify fields
from
"fields": "tableCellProperties"
to
"fields": "tableCellBackgroundFill.solidFill.color"
or to
"fields": "*"
There is a second problem with your request:
When specifying the table range, it is required to set the properties rowSpan and columnSpan.
A complete, correct request would be:
{
"requests": [
{
"updateTableCellProperties": {
"objectId": "gf9d8fea71f_22_1",
"tableRange": {
"location": {
"columnIndex": 0,
"rowIndex": 1
},
"rowSpan": 1,
"columnSpan": 1
},
"fields": "tableCellBackgroundFill.solidFill.color",
"tableCellProperties": {
"tableCellBackgroundFill": {
"solidFill": {
"color": {
"themeColor": "LIGHT1"
}
}
}
}
}
}
]
}

Can't place GraphQL custom type as a Postman variable

Has anyone had luck with placing a GraphQL custom type argument as a Postman or Graphql variable? I'm kinda spinning in circles right now, I hope a fresh pair of eyes could point me in the right direction.
What I'm trying to do is to send a mutation request using Postman. The problem I'm having is that the method I'm calling is taking a custom type as an argument. Placing the content of that variable as GraphQL variable or Postman variable is giving me a headache. I can't embedd pictures yet, so here are the links (they are safe).
Schema
This custom type is a JSON-like structure, consisting of two enums and a set of primitive types (strings, ints...). I can screenshot the entire thing but basically that's it: two enums followed by strings, ints...
Custom type definition
What I've tried so far:
Simply hardcoding the request in Postman works but I wish to send multiple requests with varying data
Placing it in a GraphQL variable results in error message
{
"errors": [
{
"message": "Bad request - invalid request body.",
"locations": []
}
],
"data": null
}
Placing the custom type content as a Postman environment variable works, but I'm getting a syntax error (although the request passes...).
Request body is below. Hardcoding it and using a Postman variable produces the same request body, apart from the syntax error.
query: "mutation {
createApplication(request: {
applicationKind: NEW_ISSUANCE,
documentKind: REGULAR_PASSPORT,
personalData: {
timestamp: null,
firstname: "NAME",
lastname: "LASTNAME",
middlename: "MIDDLENAME",
dateOfBirth: "2011-09-28",
citizenshipCountryCode: "USA",
gender: MALE,
personalNumber: "3344",
placeOfBirth: "CHICAGO",
municipalityOfBirth: "SOUTH",
countryCodeOfBirth: "USA"},
addressData:{
street: "WEST",
municipality: "EAST",
place: "CHICAGO",
country: {
code: "USA",
name: null
},
entrance: "б",
flat: "13",
number: "35"}
})
{
__typename
... on AsyncTaskStatus {
taskID
state
payload {
... on ApplicationUpdated {
applicationID
applicationNumber
__typename
}
__typename
}
__typename
}
... on Error {
...errorData
__typename
}
}
}
fragment errorData on Error {
__typename
code
message
}"
Postman variable with a squiggly line
I'm spinning in circles right now. Has anyone had any luck with Postman requests of this kind?
I can post more info, screenshots...just let me know. I'll be watching this topic closely and provide feedback.
Thank you for your time.
please add a the variable in variable section as :
{
"request": {{request}}
}
and then refer this in your query as
$request

Keep getting Twilio error message 90100 on execution, but results are working

I'm not a programmer so please forgive me. But I've spent hours and hours of research on the topic of collecting information with Twilio AutoPilot and posted that data to Airtable, which I will then have Zapier do some things with that data. I finally had a breakthrough today and am now able to post data from a call or text to Airtable. The only way I got the ending to work was to send the call or text to Studio to finish up the call. Everything seems to work from the end user standpoint, but I'm getting an error 90100 from Twilio. I'm sure I'm just missing one line of code for this to work, and I'm at the end of my rope.
{
"actions": [
{
"say": "Okay lets get you a new appointment. I just need you to answer a few questions."
},
{
"collect": {
"name": "member",
"questions": [
{
"question": "Please tell me your first name.",
"name": "name",
"type": "Twilio.FIRST_NAME"
},
{
"question": "Thanks, and what is your email address?",
"name": "email",
"type": "Twilio.EMAIL"
}
],
"on_complete": {
"redirect": "task://complete_booking"
}
}
}
]
}
Then i have another task setup to redirect to the Twilio Function. This is probably overkill, but it's what I found in research.
{
"actions": [
{
"redirect": {
"method": "POST",
"uri": "https://TWILIO_FUNCTION_URL/atable_post"
}
}
]
}
Then the function is as follows. Mind you, this is posting correctly to airtable.
exports.handler = function(context, event, callback) {
let memory = JSON.parse(event.Memory);
let name = memory.twilio.collected_data.member.answers.name.answer;
let email = memory.twilio.collected_data.member.answers.email.answer;
console.log(memory);
let member = {
name : memory.twilio.collected_data.member.answers.name.answer,
email : memory.twilio.collected_data.member.answers.email.answer,
date : Date.now()
};
var Airtable = require("airtable");
var base = new Airtable({apikey: context.AIRTABLE_API_KEY}).base("AIRTABLE_ID");
base("Members1").create(member, function(err, record) {
if (err) { console.error(err); return; }
console.log(record.getId());
callback(null, member);
});
};
The call hung up at this point, so I redirected it to a Studio Flow, which does work and the call finishes with the response I'm give it before ending the call. Again, everything is working fine, but I get the following error from twilio, and I have no idea how to resolve it.
Invalid Autopilot Actions JSON: Invalid Autopilot Action
Any help would be greatly appreciated. Thanks!
Nice work James! It looks the the issue is the redirect to your Twilio Function is not returning the expected JSON Action response to execute.
Autopilot - Redirect
https://www.twilio.com/docs/autopilot/actions/redirect
Redirecting to URLs When redirecting to a URL, Redirect will make an
HTTP callback to your application and will expect an Autopilot Actions
JSON as a response. The request will contain all the dialogue
information. This is an example of a dynamic Action since the JSON is
rendered dynamically with a URL or your own endpoint.
Can you modify the Twilio Function to return valid Action JSON to Autopilot which sets the returned data, if needed via the Remember action which you can access from Studio?

Zapier - add data to JSON response (App development)

We are creating a Zapier app to expose our APIs to the public, so anyone can use it. The main endpoint that people are using returns a very large and complex JSON object. Zapier, it looks like, has a really difficult time parsing nested complex JSON. But it does wonderful with a very simple response object such as
{ "field": "value" }
Our data that is being returned has this structure and we want to move some of the fields to the root of the response so it's easily parsed by Zapier.
"networkSections": [
{
"identifier": "Deductible",
"label": "Deductible",
"inNetworkParameters": [
{
"key": "Annual",
"value": " 600.00",
"message": null,
"otherInfo": null
},
{
"key": "Remaining",
"value": " 600.00",
"message": null,
"otherInfo": null
}
],
"outNetworkParameters": null
},
So, can we do something to return for example the remaining deductible?
I got this far (adding outputFields) but this returns an array of values. I'm not sure how to parse through this array either in the Zap or in the App.
{key: 'networkSections[]inNetworkParameters[]key', label: 'xNetworkSectionsKey',type: 'string'},
ie this returns an array of "Annual", "Remaining", etc
Great question. In this case, there's a lot going on, and outputFields can't quite handle it all. :(
In your example, inNetworkParameters contains an array of objects. Throughout our documentation, we refer to these as line items. These lines items can be passed to other actions, but the different expected structures presents a bit of a problem. The way we've handled this is by letting users map line-items from one step's output to another step's input per field. So if step 1 returns
{
"some_array": [
{
"some_key": "some_value"
}
]
}
and the next step needs to send
{
"data": [
{
"some_other_key": "some_value"
}
]
}
users can accomplish that by mapping some_array.some_key to data.some_other_key.
All of that being said, if you want to always return a Remaining Deductible object, you'll have to do it by modifying the result object itself. As long as this data is always in that same order, you can do something akin to
var data = z.JSON.parse(bundle.response.content);
data["Remaining Deductible"] = data.networkSections[0].inNetworkParameters[1].value;
return data;
If the order differs, you'll have to implement some sort of search to find the objects you'd like to return.
I hope that all helps!
Caleb got me where I wanted to go. For completeness this is the solution.
In the creates directory I have a js file for the actual call. The perform part is below.
perform: (z, bundle) => {
const promise = z.request({
url: 'https://api.example.com/API/Example/' + bundle.inputData.elgRequestID,
method: 'GET',
headers: {
'content-type': 'application/json',
}
});
return promise.then(function(result) {
var data = JSON.parse(result.content);
for (var i=0; i<data.networkSections.length; i++) {
for (var j=0; j<data.networkSections[i].inNetworkParameters.length; j++) {
// DEDUCT
if (data.networkSections[i].identifier == "Deductible" &&
data.networkSections[i].inNetworkParameters[j].key == "Annual")
data["zAnnual Deductible"] = data.networkSections[i].inNetworkParameters[j].value;
} // inner for
} // outer for
return data;
});

Docusign Not Generating Multiple Embedded Recipient Views

I am using the Docusign Rest API, through a gem for Rails. I have 2 recipients, and need both of them to sign the document.
It should work like this:
Generate envelope with borrower(s) info passing to the envelope.
Display embedded document for signing.
Return to custom url/action
If there is another signer, it should
reload the iframe
ask for second signers signature, with the same template that was just signed
Instead it breaks when I reloads the iframe for the 2nd signer. It generates the envelope, with my second signer with its unique ID, email etc. However when I then create the recipient view, it returns nil.
How do I get signer 1 to sign, then load it for the second signer right after, with all the custom fields filled both times?
def deliver(signing_borrower)
client = DocusignRest::Client.new
hashData = {
status: 'sent',
template_id: my_id
signers: [
{
embedded: true,
name: signing_borrower.name,
email: signing_borrower_email,
role_name: if (signing_borrower==borrower) then 'Borrower' else 'Co-borrower' end
}
]
}
generate_liabilities
hashData[:signers][0][:tabs] = if (signing_borrower==borrower) then custom_fields else co_borrower_custom_fields end
#if there is a coborrower, add that data to the form as the second signer
if co_borrower
if signing_borrower==co_borrower then opposite_of_signing_borrower = borrower else opposite_of_signing_borrower = co_borrower end
borrower2= {
name: opposite_of_signing_borrower.name,
email: signing_borrower_email(opposite_of_signing_borrower),
role_name: if (opposite_of_signing_borrower==co_borrower) then 'Co-borrower' else 'Borrower' end
}
#add second borrower to hash to generate envelope with all form fields filled
hashData[:signers] << borrower2
hashData[:signers][1][:tabs] = {
textTabs: text_tabs,
checkboxTabs: checkbox_tabs
}
end
response = client.create_envelope_from_template hashData
self.envelope_id = response["envelopeId"]
self.signing_url = DocusignRest::Client.new.get_recipient_view({
envelope_id: self.envelope_id,
name: signing_borrower.name,
email: signing_borrower_email(signing_borrower),
return_url: return_url
})
response
end
The hashData
{:status=>"sent",
:email=>
{:subject=>"Application...",
:body=>"please sign...."},
:template_id=>"XXXX-XXXX-XXXX",
:signers=>
[{:embedded=>true,
:name=>"DAVID L. TESTCASE",
:email=>"email#test.com",
:role_name=>"Borrower",
:tabs=>
{:textTabs=>
[{:tablabel=>"phone",
:name=>"phone",
:value=>"717-717-7171"}]
}
},
{:name=>"MARISOL TESTCASE",
:email=>"email2#test.com",
:role_name=>"Co-borrower",
:tabs=>
{:textTabs=>
[{:tablabel=>"phone",
:name=>"phone",
:value=>"717-717-7171"}]
}
}]}
You can accomplish what you're trying to do by making 3 API calls:
Create Envelope request, specifying both recipients as 'embedded/captive' by setting clientUserId property for each recipient.
POST Recipient View request to get the URL to launch the first signer's signing session.
POST Recipient View request to get the URL to launch the second signer's signing session.
Here's example JSON for those three calls.
1 - Create Envelope Request
POST https://{{env}}.docusign.net/restapi/{{version}}/accounts/{{acctId}}/envelopes
{
"emailSubject": "Please sign this",
"emailBlurb": "Please sign...thanks!",
"templateId": "064A7973-B7C1-41F3-A2AD-923CE8889333",
"status": "sent",
"templateRoles": [
{
"roleName": "Borrower",
"name": "John Doe",
"email": "johnsemail#outlook.com",
"recipientId": "1",
"clientUserId": "123",
"tabs":{
"textTabs":[
{
"tabLabel":"BorrowerPhone",
"value":"717-717-7171"
},
],
}
},
{
"roleName": "Co-borrower",
"name": "Jane Doe",
"email": "janesemail#outlook.com",
"recipientId": "2",
"clientUserId": "567",
"tabs":{
"textTabs":[
{
"tabLabel":"Co-borrowerPhone",
"value":"717-717-7171"
},
],
}
}
]
}
A successful response will contain the Id of the newly created Envelope.
2 - POST Recipient View (for the First Recipient)
Make this call when the first signer is ready to sign. In the request URL, {{envelopeId}} is the Envelope Id value that was returned in the response of the Create Envelope request, and information in the request body corresponds to info you submitted for the first recipient in the Create Envelope request.
POST https://{{env}}.docusign.net/restapi/{{version}}/accounts/{{acctId}}/envelopes/{{envelopeId}}/views/recipient
{
"authenticationMethod": "Email",
"clientUserId": "123",
"userName": "John Doe",
"email": "johnsemail#outlook.com",
"returnUrl": "http://www.google.com"
}
The response will contain the URL that can be used to launch the DocuSign Envelope for the first recipient.
3 - POST Recipient View (for the Second Recipient)
Make this call when it's time for the second signer to sign. In the request URL, {{envelopeId}} is the Envelope Id value that was returned in the response of the Create Envelope request, and information in the request corresponds to info you submitted for the second recipient in the Create Envelope request.
POST https://{{env}}.docusign.net/restapi/{{version}}/accounts/{{acctId}}/envelopes/{{envelopeId}}/views/recipient
{
"authenticationMethod": "Email",
"clientUserId": "567",
"userName": "Jane Doe",
"email": "janesemail#outlook.com",
"returnUrl": "http://www.google.com"
}
The response will contain the URL that can be used to launch the DocuSign Envelope for the second recipient.
I think the problem is in the JSON request body that you're building. I'm curious where you added the embedded => true property from, that's not in the API docs or examples. As far as I know that is not a valid property, but I think the DocuSign API is forgiving in that it doesn't error out when non-recognized properties are sent, it ignores them instead.
In general, when you are creating Embedded (aka "Captive") recipients you need to configure at least 3 properties for these recipients:
1. email
2. name
3. clientUserId
All of these are client configurable (i.e. you can set them to whatever you want), however whatever values you use when adding each recipient.. you need to reference the same exact values when requesting a signing URL for them.
For example, to add two embedded recipients you can send the following (partial) request body:
"signers": [
{
"name": "Sally Doe",
"email": "test_1#email.com"
"clientUserId": "1000"
},
{
"name": "John Doe",
"email": "test_2#email.com"
"clientUserId": "1001"
}
]
If you do not specify the routingOrder for your recipients then it will default to routing order = 1. And if you don't specify a recipientId, the system will generate a unique GUID for each and assign to them.
Once your envelope has been created and your recipients have been added to it, you can then request the signing URLs, but as mentioned you'll need to reference the same values for name, email, and clientUserId.
For more info you can check out the page on Embedding functionality at the DocuSign Developer Center:
http://www.docusign.com/developer-center/explore/features

Resources