I am attempting to create a custom REST resource. My module is as follows:
/example.info.yml
name: Example
description: ''
type: module
core: 8.x
version: DEV
dependencies:
- serialization
- basic_auth
- rest
/src/Plugin/rest/resource/BasicGetResource.php
namespace Drupal\Example\Plugin\rest\resource;
use Drupal\rest\Plugin\ResourceBase;
use Drupal\rest\ResourceResponse;
/**
* Provides an Example Resource
*
* #RestResource(
* id = "example_resource",
* label = #Translation("Example Resource"),
* uri_paths = {
* "canonical" = "/api/basic",
* "https://www.drupal.org/link-relations/create" = "/api/basic"
* }
* )
*/
class ExampleResource extends ResourceBase {
/**
* Responds to GET requests.
* #return \Drupal\rest\ResourceResponse
*/
public function get() {
$response = ['data' => 'Basic Authentication'];
return new ResourceResponse($response);
}
/**
* Responds to POST requests.
* #return \Drupal\rest\ResourceResponse
*/
public function post($data) {
$response = ['data' => $data];
return new ResourceResponse($response);
}
}
/config/install/rest.resource.example_resource.yml
langcode: en
status: true
dependencies:
module:
- basic_auth
- example
- serialization
_core:
default_config_hash: NSa-WWwv2X-ogB4ojX2-m6rCsWMY6tzOZFZySnI5yfM
id: example_resource
plugin_id: example_resource
granularity: resource
configuration:
methods:
- GET
- POST
formats:
- json
authentication:
- basic_auth
Attaching the following Javascript to a Block for POST:
var token;
var credentials = btoa("[USERNAME]:[PASSWORD]");
var settings = {
"async": true,
"crossDomain": true,
"url": "/rest/session/token",
"method": "GET",
"headers": {"Content-Type": "application/x-www-form-urlencoded"},
};
$.ajax(settings).done(function (response) {
token = response;
});
$('#btn-basic-post').click(function() {
var form = new FormData();
form.append("message", "Hello World!");
var settings = {
"async": true,
"crossDomain": true,
"url": "/api/basic?_format=json",
"method": "POST",
"headers": {
"x-csrf-token": token,
"authorization": "Basic " + credentials,
"cache-control": "no-cache",
"Content-Type": "application/json",
"Accept": 'application/json',
},
"processData": false,
"contentType": false,
"mimeType": "multipart/form-data",
"data": form
}
$.ajax(settings).done(function (response) {
alert(response.data);
});
});
I receive status 400, with response {"message":"Syntax error"}. The following log is records:
Symfony\Component\HttpKernel\Exception\BadRequestHttpException: Syntax error in Drupal\rest\RequestHandler->handle() (line 101 of C:\Users\bamberj\Sites\devdesktop\drupal-rest\core\modules\rest\src\RequestHandler.php).
Any advice would be much appreciated. Thanks.
https://www.drupal.org/project/drupal/issues/2928340
Data was not encoded correctly ...
var data = JSON.stringify({
message: 'Hello World',
});
var settings = {
"async": true,
"crossDomain": true,
"url": "/api/basic?_format=json",
"method": "POST",
"headers": {
"x-csrf-token": token,
"authorization": "Basic YWRtaW46YWRtaW4=",
"cache-control": "no-cache",
"Content-Type": "application/json",
"Accept": 'application/json',
},
"data": data,
"dataType": "JSON",
}
$.ajax(settings).done(function (response) {
console.log(response);
});
Thanks cilefen. See https://www.drupal.org/project/drupal/issues/2928340#comment-12371675.
Related
I'm trying to integrate PayPal as a payment method in my react-native app. I get an access token by hitting https://api.sandbox.paypal.com/v1/oauth2/token API, but when I'm trying to pass access token to payment API https://api.sandbox.paypal.com/v1/payments/payment got response with status code 400 or 500 both are varying.
My code is
let currency = '100 INR'
currency.replace("INR", "")
const dataDetail = {
"intent": "sale",
"payer": {
"payment_method": "paypal"
},
"transactions": [{
"amount": {
"total": currency,
"currency": "INR",
"details": {
"subtotal": currency,
"tax": "0",
"shipping": "0",
"handling_fee": "0",
"shipping_discount": "0",
"insurance": "0"
}
}
}],
"redirect_urls": {
"return_url": "https://example.com",
"cancel_url": "https://example.com"
}
}
fetch('https://api.sandbox.paypal.com/v1/oauth2/token', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Accept-Language': 'en_US',
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': 'Basic ' + btoa('AUrtJxcHfMUlDjHgV2FHMOUnzMkUeu86_km7h67uEHzH5b5RN7Vo-q8AYPtcdz7Iaioc46xW0H9JQZmT:EMbbJ-YqQLT6liuPtJURq2pAgh9WuUTDKmV355_VIeADst0BMlnUNKiHVLK7itCyZFXrEQOex9p93WO8')
},
body: 'grant_type=client_credentials'
}).then(response => response.json())
.then(async (data) => {
console.log(data.access_token)
this.setState({accessToken:data.access_token})
// console.log(JSON.stringify(dataDetail))
fetch ('https://api.sandbox.paypal.com/v1/payments/payment',
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer '+(this.state.accessToken)
},
body:dataDetail
}
)
.then(response => {
console.log('response=====',response)
// const { id, links } = response.data
// const approvalUrl = links.find(data => data.rel == "approval_url")
// this.setState({
// paymentId: id,
// approvalUrl: approvalUrl.href
// })
}).catch(err => {
console.log({ ...err })
})
}).catch(function (error) {
let edata = error.message;
console.log('Error:', edata)
}
)
Any one can help please ?
response
{"_bodyBlob": {"_data": {"__collector": [Object], "blobId": "f2d967a5-2700-4f03-b2ac-2e4ec22f10e4", "offset": 0, "size": 232}}, "_bodyInit": {"_data": {"__collector": [Object], "blobId": "f2d967a5-2700-4f03-b2ac-2e4ec22f10e4", "offset": 0, "size": 232}}, "bodyUsed": false, "headers": {"map": {"cache-control": "max-age=0, no-cache, no-store, must-revalidate", "content-language": "*", "content-length": "232", "content-type": "application/json", "date": "Tue, 23 Feb 2021 07:20:25 GMT", "paypal-debug-id": "27bb91ae40c3a"}}, "ok": false, "status": 400, "statusText": undefined, "type": "default", "url": "https://api.sandbox.paypal.com/v1/payments/payment"}
reference Link PAYPAL INTEGRATION IN REACT-NATIVE
https://api.sandbox.paypal.com/v1/payments/payment
v1/payments is a deprecated API. You should integrate the current v2/checkout/orders instead.
Here is some documentation -- you want "Create Order" and "Capture Order" API calls.
But, if you want to understand the problems with your v1 code, here they are fixed and with proper request+response data logging
Issues:
currency variable wasn't being set to a valid number w/o spaces
You need to JSON.stringify() your request body.
<script>
let currency = '100 INR';
currency = currency.replace("INR", "").trim() ; //this was a problem line, replace() is not in-place. And also extra space to trim
let accessToken = '';
const dataDetail = {
"intent": "sale",
"payer": {
"payment_method": "paypal"
},
"transactions": [{
"amount": {
"total": currency,
"currency": "INR",
"details": {
"subtotal": currency,
"tax": "0",
"shipping": "0",
"handling_fee": "0",
"shipping_discount": "0",
"insurance": "0"
}
}
}],
"redirect_urls": {
"return_url": "https://example.com",
"cancel_url": "https://example.com"
}
}
fetch('https://api.sandbox.paypal.com/v1/oauth2/token', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Accept-Language': 'en_US',
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': 'Basic ' + btoa('AUrtJxcHfMUlDjHgV2FHMOUnzMkUeu86_km7h67uEHzH5b5RN7Vo-q8AYPtcdz7Iaioc46xW0H9JQZmT:EMbbJ-YqQLT6liuPtJURq2pAgh9WuUTDKmV355_VIeADst0BMlnUNKiHVLK7itCyZFXrEQOex9p93WO8')
},
body: 'grant_type=client_credentials'
}).then(response => response.json())
.then(async (data) => {
console.log(data.access_token)
accessToken=data.access_token
// console.log(JSON.stringify(dataDetail))
let createRequest = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer '+(accessToken)
},
body:JSON.stringify(dataDetail)
}
console.log('Request body string',createRequest.body);
console.log('Request body (formatted)', JSON.stringify( JSON.parse(createRequest.body) ,null,4) );
fetch ('https://api.sandbox.paypal.com/v1/payments/payment',createRequest
)
.then(function(response) {
console.log('Response object', response);
return response.json()
})
.then(async(data) => {
console.log('Response data',data);
console.log('Response data (formatted)', JSON.stringify(data,null,4) );
}).catch(err => {
console.log({ ...err })
})
}).catch(function (error) {
let edata = error.message;
console.log('Error:', edata)
})
</script>
Im creating a script that will process a credit transaction and I always getting this response:
{
"errors": [
{
"code": "PMT-4002",
"type": "invalid_request",
"message": "requestId is required.",
"detail": "requestId",
"infoLink": "https://developer.intuit.com/v2/docs?redirectID=PayErrors"
}
]
}
Im trying to figure out where to put the "request-id" parameter on the request body. Here is my code:
function QBOcreatecharge(){
var token = "TOKEN"
var service = getQuickbooksService();
if (service.hasAccess()) {
var url = 'https://sandbox.api.intuit.com/quickbooks/v4/payments/charges'
var Details =
{
"amount": "80.00",
"currency": "USD",
"capture": "false",
"token": token
}
var params = {
headers: {
Authorization: 'Bearer ' + service.getAccessToken()
},
contentType: 'application/json',
method: 'POST',
payload: JSON.stringify(Details),
muteHttpExceptions:true
}
var response = UrlFetchApp.fetch(url, params);
var value = JSON.parse(response.getContentText())
Logger.log(value)
}
else{
var authorizationUrl = service.getAuthorizationUrl();
Logger.log('Open the following URL and re-run the script: %s', authorizationUrl);
}
}
How do I add the requestId parameter? I tried to insert it on the link, on the header and nothing work. Im using UrlFetch on Google Apps Script. Any help will be appreciated. Thanks!
The Request-Id is a header you need to send. e.g.:
headers: {
Authorization: 'Bearer ' + service.getAccessToken(),
'Request-Id': your unique value here
},
Intuit documents it here:
https://developer.intuit.com/app/developer/qbpayments/docs/develop/explore-the-quickbooks-payments-api/rest-api-features#identifiers
I am trying to use fetch to POST an API call to Cloud Convert and getting the following error:
message: "The given data was invalid."
code: "INVALID_DATA"
errors: {...}
tasks: Array(1)
0: "The tasks field is required."
Here is my code (on Wix):
export async function convertMp4toMp3(fileUrl, filename) {
filename = filename.replace(/mp4/gi, "mp3")
let job = {
tasks: {
"import-2": {
"operation": "import/url",
"url": fileUrl
},
"task-1": {
"operation": "convert",
"input_format": "mp4",
"output_format": "mp3",
"engine": "ffmpeg",
"input": [
"import-2"
],
"audio_codec": "mp3",
"audio_qscale": 0
},
"export-1": {
"operation": "export/google-cloud-storage",
"input": [
"task-1"
],
"project_id": "project-id",
"bucket": "bucket",
"client_email": "client_emailXXXXXXX",
"file": filename,
"private_key": "My Private Key
}
}
}
let options = {
"method": "POST",
"body": job,
"headers": {
"Authorization": "Bearer MyApiKey",
"Content-type": "application/json"
}
}
let response = await fetch("https://api.cloudconvert.com/v2/jobs", options)
console.log(response.json())
}
As you can see, the "tasks" field is populated with the jobs...
The fetch API does not automatically encode JSON.
Try:
let options = {
"method": "POST",
"body": JSON.stringify(job),
"headers": {
"Authorization": "Bearer MyApiKey",
"Content-type": "application/json"
}
}
I'm trying to send an email using a google tag manager custom html tag when certain events are triggered.
This is the code (XXXXX for omission where needed)
<script>
var settings = {
"async": true,
"crossDomain": true,
"url": "https://api.sendgrid.com/v3/mail/send",
"method": "POST",
"headers": {
"authorization": "Bearer XXXXXXXXXXXXX",
"content-type": "application/json"
},
"processData": false,
"data": "{\"personalizations\":[{\"to\":[{\"email\":\"XXXXXXXXXX\",\"name\":\"John Doe\"}],\"dynamic_template_data\":{\"verb\":\"yes\",\"adjective\":\"test\",\"noun\":\"\",\"currentDayofWeek\":\"\"},\"subject\":\"Hello, World!\"}],\"from\":{\"email\":\"XXXXXXXXXXXXXXX\",\"name\":\"John Doe\"},\"reply_to\":{\"email\":\"XXXXXXXXXXXXXXX\",\"name\":\"John Doe\"},\"template_id\":\"XXXXXXXXXXXXXXX"}"
}
jQuery.ajax(settings).done(function (response) {
console.log(response);
});
</script>
Now This block (minus the script tags) runs when using the built in send grid "try it out" feature. Why will this not work from GTM?
Sounds like this code might be getting added and run prior to jQuery being ready. Try the following update to the code:
<script>
jQuery(function() {
var settings = {
"async": true,
"crossDomain": true,
"url": "https://api.sendgrid.com/v3/mail/send",
"method": "POST",
"headers": {
"authorization": "Bearer XXXXXXXXXXXXX",
"content-type": "application/json"
},
"processData": false,
"data": "{\"personalizations\":[{\"to\":[{\"email\":\"XXXXXXXXXX\",\"name\":\"John Doe\"}],\"dynamic_template_data\":{\"verb\":\"yes\",\"adjective\":\"test\",\"noun\":\"\",\"currentDayofWeek\":\"\"},\"subject\":\"Hello, World!\"}],\"from\":{\"email\":\"XXXXXXXXXXXXXXX\",\"name\":\"John Doe\"},\"reply_to\":{\"email\":\"XXXXXXXXXXXXXXX\",\"name\":\"John Doe\"},\"template_id\":\"XXXXXXXXXXXXXXX"}"
}
jQuery.ajax(settings).done(function (response) {
console.log("SendGrid Response:", response);
});
});
</script>
Try that and see if you see anything in the console labeled "SendGrid Response:". That'll definitively let us know if this script is running at all.
This is how I'm calling a web service.
fetch('http://**someurl**', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
username : "admin",
password: "admin123",
})
})
When I call it from postman I get a response like this :
{
"code": 1,
"message": {
"Object1": [
{
"Id": 1,
"Name": "COWDUNG",
"manufacturer": "OWN",
"description": "ORGANIC MANUER",
"type": "Fertilizer"
}
]
}
}
Can anyone tell me how to handle the response?
Hope this helps.
fetch(url, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
username : "admin",
password: "admin123",
})
}).then((response) => response.json()).then((responseJson) => {
// you'll get the response in responseJson
})
.catch((error) => {
//you will get error here.
});