Validate GET status of a url for mailchimp - php

I have created a function that creates a batch webhook in mailchimp so that a callback will be submitted once the batch operations is finished. like following:
// register mailchimp batch webhook
$responseWH = wp_remote_post( 'https://' . substr($mcApi,strpos($mcApi,'-')+1) . '.api.mailchimp.com/3.0/batch-webhooks' ,array(
'headers' => array(
'method' => 'POST',
'Authorization' => 'Basic ' . base64_encode( 'user:'. $mcApi )
),
'body' => json_encode(array(
'url' => 'http://90660d72b8be.ngrok.io/wp-json/lubuvna/v2/batch/2810471250791421617231098394447326550803'
))
));
above code means, when a batch operation is finished MC should call this url:
http://90660d72b8be.ngrok.io/wp-json/lubuvna/v2/batch/2810471250791421617231098394447326550803
If this url is called, then a script will run and notify me that the operation is done und update the the post in wordpress.
but since the header status code is 404, mailchimp is not adding the url to the batch webhook.. instead i get following error:
{
"type": "http://developer.mailchimp.com/documentation/mailchimp/guides/error-glossary/",
"title": "Invalid Resource",
"status": 400,
"detail": "The resource submitted could not be validated. For field-specific details, see the 'errors' array.",
"instance": "05a4430f-c68f-46a5-82af-3b95332d6fe83",
"errors": [
{
"field": "url",
"message": "We couldn't verify the URL is working. Please double check and try again. HTTP Code: 500"
}
]
}
How can i return a 200 status in the header when Mailchimp is trying to make a GET request to the specified URL, while adding the batch webhook? they need a valid url. mailchimp batch webhook
I am using ngrok for connection within localhost which works when i add a URL like http://90660d72b8be.ngrok.io/wp-content/plugins/my-plugin/inc/batch/import.php, because the file actually exist in the plugin directory
but when adding the URL http://90660d72b8be.ngrok.io/wp-json/lubuvna/v2/batch/2810471250791421617231098394447326550803
I can see that mailchimp makes a get request and the code status is 404 like in the screenshot

I hav ended up using follwoing:
function myplugin_registered_rest_routes() {
// batch operation finished
register_rest_route('myplugin/v2', '/batch/(?P<id>\d+)',
array(
array('methods' => ['POST', 'GET'],
'callback' => 'my_awesome_func'
)
)
);
}
add_action( 'rest_api_init', 'myplugin_registered_rest_routes' );
another option of array like #04FS answer:
register_rest_route('myplugin/v2', '/batch/(?P<id>\d+)',
array(
array('methods' => 'GET',
'callback' => 'my_awesome_func',
),
array('methods' => 'POST',
'callback' => 'my_awesome_func'
)
)
);
Another option parsing the url request. Not common when using wordpress API:
add_action('parse_request', 'register_endpoint', 0);
function register_endpoint() {
global $wp;
if ($wp->request == 'wp-json/myplugin/v2/batch/2810471250791421617231098394447326550803') {
header("HTTP/1.1 200 OK");
exit;
}
}

Related

Failed to open stream: HTTP request failed! HTTP/1.1 400 Bad Request - PHP Error

SOLUTION: I had malformed my JSON data for the payload body. The "ttl" => 30 was in the incorrect array() method. This probably won't help anyone in the future, moving the ttl key/value pair made this work correctly as seen below.
$data = array(
"statement" => array(
"actor" => array(
"mbox" => "mailto:test#example.com"
),
),
"ttl" => 30
);
I have checked numerous other StackOverflow questions and cannot find a solution that works. I should note that I am testing this using a local XAMPP server running on port 8080. Not sure if that matters. I have been able to get this working using Postman, but translating it to PHP has been problematic. Am I missing something? I am not all that familiar with PHP, but need this for work.
EDIT: Some more information about what the API is expecting. It's a fairly simple API that requires a JSON body, a Basic Authorization header, and a Content-Type: application/json.
Here is the JSON body I am using in Postman. This is a direct copy/paste from Postman, which is successfully communicating with the API:
{
"statement": {
"actor": {
"mbox": "mailto:test#example.com"
}
},
"ttl": 30
}
Is there a syntax error in my below PHP code for this? Again, I am learning PHP on the fly so I'm unsure if I am properly constructing a JSON payload using the array() method in PHP.
My code below has the $https_user,$https_password, and $url domain changed for obvious security reasons. In my actual PHP code, I have the same credentials and domain used in Postman.
The $randomSessionID serves no real purpose other than an identification number for future requests. Has no affect on the API response failing or succeeding.
<?php
$https_user = 'username';
$https_password = 'password';
$randomSessionID = floor((mt_rand() / mt_getrandmax()) * 10000000);
$url = 'https://www.example.com/session/' . $randomSessionID . '/launch';
$json = json_encode(array(
"statement" => array(
"actor" => array(
"mbox" => "mailto:test#example.com"
),"ttl" => 30
)
));
$options = array(
'http' => array(
'method' => 'POST',
'header' => 'Content-Type: application/json\r\n'.
"Authorization: Basic ".base64_encode("$https_user:$https_password")."\r\n",
'content' => $json
)
);
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
if ($result === FALSE) { /* Handle error */ }
?>
SOLUTION: I had malformed my JSON data for the payload body. The "ttl" => 30 was in the incorrect array() method. This probably won't help anyone in the future, but moving the ttl key/value pair made this work correctly as seen below.
$data = array(
"statement" => array(
"actor" => array(
"mbox" => "mailto:test#example.com"
),
),
"ttl" => 30
);

Shopify Asset API updating collection.liquid using PUT method giving 404 with cURL

I am trying to update collection.liquid using Shopify API.
I am using below Shopify API wrapper with CodeIgniter,
Shopify API wrapper
This wrapper uses cURL to make API calls. I have used this library to make other apps for Shopify and it works just fine with GET,POST methods. For the first time I have tried using PUT method with it. and its giving me cURL Error given below ERROR #22: The requested URL returned error: 404 Not Found"
protected function modify_asset($theme_id)
{
$data = array(
'API_KEY' => $this->config->item('shopify_api_key'),
'API_SECRET' => $this->config->item('shopify_secret'),
'SHOP_DOMAIN' => $this->session->userdata('shop_domain'),
'ACCESS_TOKEN' => $this->session->userdata('access_token')
);
$this->load->library('shopify', $data);
$fields = array(
"asset" => array(
"key" => "templates\/collection.liquid",
"value" => "<p>We are busy updating the store for you and will be back within 10 hours.<\/p>"
)
);
$args = array(
'URL' => '/admin/themes/163760333/assets.json',
'METHOD' => 'PUT',
'RETURNARRAY' => TRUE,
'DATA' => $fields
);
try{
$modification_response = $this->shopify->call($args);
return $modification_response;
}
catch(Exception $e){
$modification_response = $e->getMessage();
log_message('error','In Get Active Theme Id' . $modification_response);
//redirect('/wrong/index');
var_dump('In modification response ' . $modification_response);
exit;
}
}
}
Above is my function to implement the API call. You can see cURL options and its implementation on below link:
cURL options and happening of Shopify API call
Note : This request is working just fine on POSTMAN.
I've just been running some tests on this code using the information you provided, and was able to get a successful submission after removing the backslash in $fields['asset']['key'] as per the example above.
So
"key" => "templates\/collection.liquid",
Becomes:
"key" => "templates/collection.liquid",
It appears Shopify doesn't require forward slashes in file keys to be escaped.

yii2 rest api exception handling

I am using yii2 rest api module in which controller class extends an ActiveController and i have a problem dealing with the error exception . i need a proper json response when HTTP status code that are used by the Yii REST framework like 500 , 400. If i try a wrong method call on access api it show a exception object
object(yii\web\NotFoundHttpException)#170 (8) { ["statusCode"]=> int(404)
In my config/main.php set the response
'response' => [
'class' => 'yii\web\Response',
'on beforeSend' => function ($event) {
$response = $event->sender;
if ($response->data !== null) {
$response->data = [
'success' => $response->isSuccessful,
'data' => $response->data,
];
$response->statusCode = 200;
}
},
]
It should display a msg like:
{
"status": 0,
"error_code": 400,
"message": "Bad request"
}
I have try to add the behaviour verbs in controller using this link : click here
My whole application is based on api so please help me for handling all kind of errors
Also depends on your server configs but usually you don't need any of that. this should be enough:
'response' => [
'format' => yii\web\Response::FORMAT_JSON,
'charset' => 'UTF-8',
],
Here is an output example using those configs: https://yii2-f4a.rhcloud.com/api/tags

Why Share on LinkedIn API return 400 Bad Request?

I'm trying to post a LinkedIn share update via its Share on LinkedIn API using a PHP library LinkedIn-Client API. I've successfully authorized the user and I got the access token returned from it. I use the token along with this share API call. Here is my code:
$linkedInOAuth = new Happyr\LinkedIn\LinkedIn(LINKEDIN_APP_ID, LINKEDIN_APP_SECRET);
if ($accessToken) { // assume that it is retrieved from session
$linkedInOAuth->setAccessToken($accessToken);
$postParams = array(
"content" => array(
'description' => "I'm so exciting to share a post using API."
),
"visibility" => array(
"code" => "connnections-only"
)
);
$result = $linkedInOAuth->api(
"v1/people/~/shares",
array("format" => "json"),
"POST",
$postParams
);
}
However I got 400 bad request error returned from this API call.
Fatal error: Uncaught GuzzleException: 400: Client error response [url] https://api.linkedin.com/v1/people/~/shares?format=json&oauth2_access_token=xxxxxxx [status code] 400 [reason phrase] Bad Request thrown in ...\vendor\happyr\linkedin-api-client\src\Happyr\LinkedIn\Http\GuzzleRequest.php on line 26
What could be the problem?
[UPDATE on 2015-04-30 3:00 PM UTC]
LinkedIn-Client API uses Guzzle internally for HTTP requests. I tried to use GuzzleHttp directly without using Happyr\LinkedIn\LinkedIn->api(), but same error and no success.
if ($accessToken) {
$url = 'https://api.linkedin.com/v1/people/~/shares?format=json&oauth2_access_token=' . $accessToken;
$client = new GuzzleHttp\Client();
$response = $client->post($url, array(
'headers' => array(
'Content-Type' => 'application/json',
'x-li-format' => 'json'
),
'json' => array(
'comment' => 'Check out developer.linkedin.com!',
'content' => array(
'description' => 'I\'m so exciting to share a post using API.'
),
'visibility' => array(
'code' => 'connections-only'
)
)
));
}
Fatal error: Uncaught exception 'GuzzleHttp\Exception\ClientException'
with message 'Client error response [url]
https://api.linkedin.com/v1/people/~/shares?format=json&oauth2_access_token=xxxxx
[status code] 400 [reason phrase] Bad Request' in
\vendor\guzzlehttp\guzzle\src\Exception\RequestException.php:89 Stack
trace: #0 \vendor\guzzlehttp\guzzle\src\Subscriber\HttpError.php(33):
GuzzleHttp\Exception\RequestException::create(Object(GuzzleHttp\Message\Request),
Object(GuzzleHttp\Message\Response)) #1
\vendor\guzzlehttp\guzzle\src\Event\Emitter.php(109):
GuzzleHttp\Subscriber\HttpError->onComplete(Object(GuzzleHttp\Event\CompleteEvent),
'complete') #2 \vendor\guzzlehttp\guzzle\src\RequestFsm.php(91):
GuzzleHttp\Event\Emitter->emit('complete', Object(Guz in
\vendor\guzzlehttp\guzzle\src\Exception\RequestException.php on line
89
[UPDATE on 2015-05-05 9:40 AM UTC]
I copied and used both xml and json examples of Share on LinkedIn API page. This time, the error changed to Internal Server Error.
if ($accessToken) {
$format = 'xml';
$url = 'https://api.linkedin.com/v1/people/~/shares?format='.$format.'&oauth2_access_token=' . $connect->accessToken;
$postParams = array(
"xml" => "
<share>
<comment>Check out developer.linkedin.com!</comment>
<content>
<title>LinkedIn Developer Resources</title>
<description>Leverage LinkedIn's APIs to maximize engagement</description>
<submitted-url>https://developer.linkedin.com</submitted-url>
<submitted-image-url>https://example.com/logo.png</submitted-image-url>
</content>
<visibility>
<code>anyone</code>
</visibility>
</share>",
"json" => array(
"comment" => "Check out developer.linkedin.com!",
"content" => array(
"title" => "LinkedIn Developers Resources",
"description" => "Leverage LinkedIn's APIs to maximize engagement",
"submitted-url" => "https://developer.linkedin.com",
"submitted-image-url" => "https://example.com/logo.png"
),
"visibility" => array(
"code" => "anyone"
)
)
);
$client = new GuzzleHttp\Client();
if ($format === 'xml') {
$response = $client->post($url, array(
'body' => $postParams['xml']
));
} else {
$response = $client->post($url, array(
'headers' => array(
'Content-Type' => 'application/json',
'x-li-format' => 'json'
),
'json' => $postParams['json']
));
}
}
Fatal error: Uncaught exception 'GuzzleHttp\Exception\ServerException'
with message 'Server error response [url]
https://api.linkedin.com/v1/people/~/shares?format=json&oauth2_access_token=xxxx
[status code] 500 [reason phrase] Internal Server Error'
According to the Github issue of Happyr\LinkedIn-API-client, some updates have been made in 0.5.0 and it solved my problem. However, LinkedIn has unclear documentation about its Share API. The following information have to be noted:
The comment field is the sharing update content. The name comment leads confusing.
Using the field comment, URL is optional in the sharing update content.
The content field means snapshot about the content of the URL you are sharing. To describe more clearly, it reflects open graph meta tags;
content.title overrides <meta property="og:title" content="..." />
content.description overrides <meta property="description" content="..." />
content.title overrides <meta property="og:title" content="..." />
content.submitted-url overrides <meta property="og:url" content="..." />
content.submitted-image-url overrides <meta property="og:image" content="..." />
When the content field is used, the field submitted-url is required. The rest are optional. If it is missing, 400 Bad Request would return.
The URLs included in the example codes of LinkedIn Share API would cause 500 Internal Server Error. They should not be used for testing purpose.
The following is the correct usage of API using Happyr\LinkedIn-API-client.
(1) Happyr\LinkedIn - Using the field comment
$linkedInOAuth = new Happyr\LinkedIn\LinkedIn(LINKEDIN_APP_ID, LINKEDIN_APP_SECRET);
// retrieve $accessToken from db or session
$linkedInOAuth->setAccessToken($accessToken);
$postParams = array(
'json' => array(
"comment" => "PHPLucidFrame - The simple, lightweight and flexible web application development framework http://phplucidframe.sithukyaw.com",
"visibility" => array(
"code" => "anyone"
)
)
);
$result = $linkedInOAuth->post('v1/people/~/shares', $postParams);
(2) Happyr\LinkedIn - Using the field content
$linkedInOAuth = new Happyr\LinkedIn\LinkedIn(LINKEDIN_APP_ID, LINKEDIN_APP_SECRET);
// retrieve $accessToken from db or session
$linkedInOAuth->setAccessToken($accessToken);
$postParams = array(
'json' => array(
"content" => array(
"title" => "PHPLucidFrame",
"description" => "The simple, lightweight and flexible web application development framework",
"submitted-url" => "http://phplucidframe.sithukyaw.com"
),
"visibility" => array(
"code" => "anyone"
)
)
);
$result = $linkedInOAuth->post('v1/people/~/shares', $postParams);
The following is the correct usage of API using GuzzleHttp.
(3) GuzzleHttp - Using the field comment
// retrieve $accessToken from db or session
$url = 'https://api.linkedin.com/v1/people/~/shares?format=json&oauth2_access_token=' . $accessToken;
$client = new GuzzleHttp\Client();
$response = $client->post($url, array(
"json" => array(
"comment" => "PHPLucidFrame - The simple, lightweight and flexible web application development framework http://phplucidframe.sithukyaw.com",
"visibility" => array(
"code" => "anyone"
)
)
));
(4) GuzzleHttp - Using the field content
// retrieve $accessToken from db or session
$url = 'https://api.linkedin.com/v1/people/~/shares?format=json&oauth2_access_token=' . $accessToken;
$client = new GuzzleHttp\Client();
$response = $client->post($url, array(
"json" => array(
"content" => array(
"title" => "PHPLucidFrame",
"description" => "The simple, lightweight and flexible web application development framework",
"submitted-url" => "http://phplucidframe.sithukyaw.com"
),
"visibility" => array(
"code" => "anyone"
)
)
));
The fields comment and content can also be used together.
Just a quick guess here but you might need to add json_encode to your $postParams before you send it to the API.
$result = $linkedInOAuth->api(
"v1/people/~/shares",
array("format" => "json"),
"POST",
json_encode($postParams),
);
ALTERNATIVELY
If that does not work I also notice the Linkedin Docs say the following. You could try adding these two headers (if you havent already).
By default, all API calls expect input in XML format, however if it is more covienent for your application to submit data in JSON format, you can inform the APIs that they will be receiving a JSON-formatted payload by including the following two HTTP header values in the call:
Content-Type: application/json
x-li-format: json
Your JSON post body needs to be corrected. Check:
https://developer.linkedin.com/docs/share-on-linkedin
You need to follow either one of these formats.
Share via a comment containing a URL
{
"comment": "Check out developer.linkedin.com! http://linkd.in/1FC2PyG",
"visibility": {
"code": "anyone"
}
}
Share with specific values
{
"comment": "Check out developer.linkedin.com!",
"content": {
"title": "LinkedIn Developers Resources",
"description": "Leverage LinkedIn's APIs to maximize engagement",
"submitted-url": "https://developer.linkedin.com",
"submitted-image-url": "https://example.com/logo.png"
},
"visibility": {
"code": "anyone"
}
}

Woocommerce custom payment gateway redirect

I have a problem. I should do a custom gateway. I know the basics. I read the documentation. URL data to be transmitted (such as user name, the amount of the transaction). My question is how to redirect the user to the payment page of the bank? What is the command and where to give the exact url? And then the returned data must be processed what method? cURL or something else? I could not find any real solution to the problem.
Different gateway's have different needs, if your gateway uses a POST, you can use this to POST the data, and get a response.. it is better than cURL.
$response = wp_remote_post( $environment_url, array(
'method' => 'POST',
'body' => http_build_query( $payload ),
'timeout' => 90,
'sslverify' => false,
) );
// Retrieve the body's response if no errors found
$response_body = wp_remote_retrieve_body( $response );
$response_headers = wp_remote_retrieve_headers( $response );
// Payload would look something like this.
$payload = array(
"amount" => $order.get_total(),
"reference" => $order->get_order_number(),
"orderid" => $order->id,
"return_url" => $this->get_return_url($order) //return to thank you page.
);
//use this if you need to redirect the user to the payment page of the bank.
$querystring = http_build_query( $payload );
return array(
'result' => 'success',
'redirect' => $environment_url . '?' . $querystring,
);

Categories