Related
<?php
// // accept all post data and make array
$data = json_decode(file_get_contents('php://input'), true);
// // get the data from the array
$deal_name = "test";
// $deal_source = isset($data['deal_source']) ? $data['deal_source'] : "";
$contact_first_name = isset($data['yrnamr']) ? $data['yrname'] : "";
// $contact_last_name = isset($data['contact_last_name']) ? $data['contact_last_name'] : "";
$contact_email = isset($data['yremail']) ? $data['yremail'] : "";
$contact_phone = isset($data['telephone']) ? $data['telephone'] : "";
$contact_message = isset($data['yrmessage']) ? $data['yrmessage'] : "";
$data_string = json_encode(array(
"custom_fields" => array(),
"email" => $contact_email,
"first_name" => $contact_first_name,
"last_name" => "WA",
"is_public" => true,
"phone" => $contact_phone
));
$api_key = "d7c85d208c924e489f36ae69e1550570";
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://app.teamwave.com/api/crm/deals?api_key='.$api_key,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS =>'{
"custom_fields": {
"27806": {
"$key": 27806,
"field_type": "select",
"key": "source",
"name": "Source",
"options": null,
"position": 1,
"value": "test"
}
},
"currency": 1876589,
"pipeline": 29270,
"stage": 155081,
"title": "Deal Name Dynamic Test 4"
}',
CURLOPT_HTTPHEADER => array(
'Content-Type: application/json'
),
));
$response = curl_exec($curl);
curl_close($curl);
$response = json_decode($response, true);
$deal_id = $response['id'];
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://app.teamwave.com/api/crm/deals/'.$deal_id.'/link-contact?api_key='.$api_key,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS =>$data_string,
CURLOPT_HTTPHEADER => array(
'Content-Type: application/json'
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;`
I use this code to integrate my contactform7 fields with teamwave crm.The code creates a deal and links it with a contact in the CRM. but the data is not being sent on form submission.
I suspect something is wrong where the contact form 7 fields are dynamically fetched. I am not sure what is wrong...............
I am having big issues doing a POST request from wordpress backend.
This is the request I try to make. The AppsSCript is a doPost() endpoint echo-ing the request. It gives me a 400 error.
$body = array(
'firstName' => 'WhyWontYouWork'
);
$args = array(
'method' => 'POST',
'timeout' => 45,
'redirection' => 5,
//'httpversion' => '1.0',
'blocking' => true,
'headers' => array(
'Content-Type' => 'application/json'
),
'body' => $body
);
$request = wp_remote_post ($url, $args);
$response = wp_remote_retrieve_body( $request );
I found out with insomnia, that having a content-length header in the POST request is making Apps Script go crazy. If I remove it, all works.
Hope this helps,
$url = 'https://example.com/api/endpoint';
$args = array(
'method' => 'POST',
'timeout' => 30,
'headers' => array(
'Content-Type' => 'application/json',
),
'body' => json_encode( array( 'data' => 'value' ) ),
);
// Remove the Content-Length header
unset( $args['headers']['Content-Length'] );
// Or Change it
$args['headers']['Content-Length'] = 20166 // in decimal bytes
// Make the remote post request
$response = wp_remote_post( $url, $args );
// Check for errors
if ( is_wp_error( $response ) ) {
// Handle error
} else {
// Handle success
}
I have a custom post type called Auction House. How can I get the permalink to be sitename.com/selling/auction_houses?ah=House1 ?
I need the single URL of all Auction Houses to go to the same URL (sitename.com/selling/auction_houses) but with a custom query string parameter on the end for a single auction house URL. The query string parameter can be used to allow me to pick up and make scroll to the correct auction house on the page.
Thanks,
Neil
EDIT 1:
function cptui_register_my_cpts_auction_house() {
/**
* Post Type: Auction Houses.
*/
$labels = [
"name" => __( "Auction Houses", "custom-post-type-ui" ),
"singular_name" => __( "Auction House", "custom-post-type-ui" ),
];
$args = [
"label" => __( "Auction Houses", "custom-post-type-ui" ),
"labels" => $labels,
"description" => "",
"public" => true,
"publicly_queryable" => true,
"show_ui" => true,
"show_in_rest" => true,
"rest_base" => "",
"rest_controller_class" => "WP_REST_Posts_Controller",
"rest_namespace" => "wp/v2",
"has_archive" => false,
"show_in_menu" => true,
"show_in_nav_menus" => true,
"delete_with_user" => false,
"exclude_from_search" => false,
"capability_type" => "post",
"map_meta_cap" => true,
"hierarchical" => false,
"can_export" => true,
"rewrite" => [ "slug" => "auction_house", "with_front" => true ],
"query_var" => true,
"menu_icon" => "dashicons-store",
"supports" => [ "title", "editor", "thumbnail" ],
"show_in_graphql" => false,
];
register_post_type( "auction_house", $args );
}
add_action( 'init', 'cptui_register_my_cpts_auction_house' );
So there are a few things you need to modify from the original code, as well as a function to add to redirect from the single page to the archive with the query parameters. One thing to note is that users will not be able to get to the single page because it is getting redirected.
Add the following to the $args of the custom part type:
"has_archive" => 'selling/auction_houses',
Modify this in the $args of the custom post type:
Change this:
"rewrite" => [ "slug" => "auction_house", "with_front" => true ],
to this:
"rewrite" => ["slug" => "selling/auction_houses", "with_front" => true],
Lastly add this function to handle the redirect from the single page to the archive page with query parameters.
add_action('template_redirect', 'AH_auction_house_single_redirect');
function AH_auction_house_single_redirect()
{
if (is_singular('auction_house')) {
global $wp;
// Get the slug of the post for url
$slug = end(explode('/', add_query_arg(array(), $wp->request)));
/**
*
* Select whether you want to use 301 or 307 as your redirect
*
*/
// wp_redirect( home_url() . '/selling/auction_houses?ah=' . $slug, 301 );
wp_redirect(home_url() . '/selling/auction_houses?ah=' . $slug, 307);
exit;
}
}
That will make the new code in it's entirety look like this:
function cptui_register_my_cpts_auction_house()
{
/**
* Post Type: Auction Houses.
*/
$labels = [
"name" => __("Auction Houses", "custom-post-type-ui"),
"singular_name" => __("Auction House", "custom-post-type-ui"),
];
$args = [
"label" => __("Auction Houses", "custom-post-type-ui"),
"labels" => $labels,
"description" => "",
"public" => true,
"publicly_queryable" => true,
"show_ui" => true,
"show_in_rest" => true,
"rest_base" => "",
"rest_controller_class" => "WP_REST_Posts_Controller",
"rest_namespace" => "wp/v2",
"has_archive" => 'selling/auction_houses',
"show_in_menu" => true,
"show_in_nav_menus" => true,
"delete_with_user" => false,
"exclude_from_search" => false,
"capability_type" => "post",
"map_meta_cap" => true,
"hierarchical" => false,
"can_export" => true,
"rewrite" => ["slug" => "selling/auction_houses", "with_front" => true],
"query_var" => true,
"menu_icon" => "dashicons-store",
"supports" => ["title", "editor", "thumbnail"],
"show_in_graphql" => false,
];
register_post_type("auction_house", $args);
}
add_action('init', 'cptui_register_my_cpts_auction_house');
add_action('template_redirect', 'AH_auction_house_single_redirect');
function AH_auction_house_single_redirect()
{
if (is_singular('auction_house')) {
global $wp;
// Get the slug of the post for url
$slug = end(explode('/', add_query_arg(array(), $wp->request)));
/**
*
* Select whether you want to use 301 or 307 as your redirect
*
*/
// wp_redirect( home_url() . '/selling/auction_houses?ah=' . $slug, 301 );
wp_redirect(home_url() . '/selling/auction_houses?ah=' . $slug, 307);
exit;
}
}
I use the api version 2.0 and want to create an image share.
LinkedIn describes your image binary file upload process here:
https://learn.microsoft.com/en-us/linkedin/consumer/integrations/self-serve/share-on-linkedin?context=linkedin/consumer/context#create-a-text-share
If you follow the instructions you will get a 400 HTTP error.
I add the Content-Type in the header and get a 201 HTTP status with the X-RestLi-Id in the header. So far so good!
If I want to show my created post on LinkedIn (https://www.linkedin.com/in/me/detail/recent-activity/) I can't find the post with image.
How to fix it? Anybody got an idea?
PHP code:
$imageRequestData = array(
"registerUploadRequest" => array(
"recipes" => array(
"urn:li:digitalmediaRecipe:feedshare-image"
),
"owner" => $urn, // Person URN === urn:li:person:XXXX
"serviceRelationships" => array(
array(
"relationshipType" => "OWNER",
"identifier" => "urn:li:userGeneratedContent"
)
)
)
);
$image_request = $this->post('v2/assets?action=registerUpload', $imageRequestData);
$headers = array();
$headers[] = 'Authorization: Bearer ' . $this->accessToken;
$headers[] = 'X-Restli-Protocol-Version: 2.0.0';
$headers[] = 'Content-Type: ' . mime_content_type($image_path); //ex. image/png
$ch = curl_init();
$options = array(
CURLOPT_HEADER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_URL => $image_request['message']['value']['uploadMechanism']
['com.linkedin.digitalmedia.uploading.MediaUploadHttpRequest']['uploadUrl'],
CURLOPT_HTTPHEADER => $headers,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_POST => true,
CURLOPT_CONNECTTIMEOUT => $this->connectTimeout,
CURLOPT_TIMEOUT => $this->timeout,
CURLOPT_POSTFIELDS => array("upload-file" => new CURLFile($image_path))
);
curl_setopt_array($ch, $options);
$response = curl_exec($ch);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$content = array(
'author' => $urn, // Person URN === urn:li:person:XXX
'lifecycleState' => 'PUBLISHED',
'specificContent' => array(
"com.linkedin.ugc.ShareContent" => array(
'shareCommentary' => array(
"text" => $comment,
),
'shareMediaCategory' => 'IMAGE',
// NONE - The share does not contain any media, only text.
// ARTICLE - The share contains a URL.
// IMAGE - The Share contains an image.
'media' => array(
"status" => "READY",
"media" => $image_request['message']['value']['asset']
)
)
),
"visibility" => array(
"com.linkedin.ugc.MemberNetworkVisibility" => "PUBLIC"
)
);
$postfields = json_encode($content);
$headers = array();
$headers[] = 'x-li-format: json';
$headers[] = 'Authorization: Bearer ' . $this->accessToken;
$headers[] = 'Content-Type: application/json';
$headers[] = 'Content-Length: ' . strlen($postfields);
$headers[] = 'X-Restli-Protocol-Version: 2.0.0';
$ch = curl_init();
$options = array(
CURLOPT_HEADER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_URL => 'https://api.linkedin.com/v2/ugcPosts',
CURLOPT_HTTPHEADER => $headers,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_POST => true,
CURLOPT_CONNECTTIMEOUT => $this->connectTimeout,
CURLOPT_TIMEOUT => $this->timeout,
CURLOPT_POSTFIELDS => $postfields
);
curl_setopt_array($ch, $options);
$response = curl_exec($ch);
You need to change your request to PUT and keep default for SSL VerifyPeer:
$headers = array();
$headers[] = 'Authorization: Bearer ' . $this->accessToken;
$headers[] = 'X-Restli-Protocol-Version: 2.0.0';
$headers[] = 'Content-Type: multipart/form-data';
$ch = curl_init();
$options = array(
CURLOPT_HEADER => true,
CURLOPT_CUSTOMREQUEST => 'PUT', //need to set custom request to PUT instead of post
CURLOPT_RETURNTRANSFER => true,
CURLOPT_URL => $image_request['message']['value']['uploadMechanism']
['com.linkedin.digitalmedia.uploading.MediaUploadHttpRequest']['uploadUrl'],
CURLOPT_HTTPHEADER => $headers,
// CURLOPT_SSL_VERIFYPEER => false, //keep default options
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_POST => true,
CURLOPT_CONNECTTIMEOUT => $this->connectTimeout,
CURLOPT_TIMEOUT => $this->timeout,
CURLOPT_POSTFIELDS => array("upload-file" => new CURLFile($image_path))
);
curl_setopt_array($ch, $options);
$response = curl_exec($ch);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
Or use GuzzleHttp\Client to simplify the upload:
$client =new \GuzzleHttp\Client();
$client->request('PUT',
$image_request['message']['value']['uploadMechanism'] // ↵
['com.linkedin.digitalmedia.uploading.MediaUploadHttpRequest']['uploadUrl'],
[
'headers' => [
'Authorization' => 'Bearer ' . $this->accessToken
],
'body' => fopen($image_path, 'r'),
]
I have a custom post type, card, that I'm exposing through the WP REST API.
function register_card_post_type() {
$labels = array(
"name" => __( 'Cards', '' ),
"singular_name" => __( 'Card', '' ),
);
$args = array(
"label" => __( 'Cards', '' ),
"labels" => $labels,
"description" => "",
"public" => true,
"publicly_queryable" => true,
"show_ui" => true,
"show_in_rest" => true, // ADD TO REST API
"rest_base" => "cards", // ADD TO REST API
"has_archive" => false,
"show_in_menu" => true,
"exclude_from_search" => false,
"capability_type" => "post",
"map_meta_cap" => true,
"hierarchical" => false,
"rewrite" => array( "slug" => "card", "with_front" => true ),
"query_var" => true,
"menu_position" => 5,
"supports" => array( "title" ),
);
register_post_type( "card", $args );
}
add_action( 'init', 'register_card_post_type' );
It seems like by default, the endpoints are public. How do I set the authentication requirements for the endpoint, so that GET /cards/ requires either an auth cookie or header?
In the API handbook is shows how to write a custom endpoint, but ideally is there a filter or hook I can use to extend the autogenerated endpoints?
add_action( 'rest_api_init', function () {
register_rest_route( 'myplugin/v1', '/author/(?P<id>\d+)', array(
'methods' => 'GET',
'callback' => 'my_awesome_func',
'args' => array(
'id' => array(
'validate_callback' => 'is_numeric'
),
),
'permission_callback' => function () {
return current_user_can( 'edit_others_posts' );
}
) );
} );
You can use the rest_pre_dispatchfilter to check the URL and revoke access to that endpoint for not logged in users:
add_filter( 'rest_pre_dispatch', function() {
$url = strtok($_SERVER["REQUEST_URI"],'?');
if ( !is_user_logged_in() &&
!in_array($url, array ( //using "in_array" because you can add mmultiple endpoints here
"/wp-json/cards",
))){
return new WP_Error( 'not-logged-in', 'API Requests to '.$url.' are only supported for authenticated requests', array( 'status' => 401 ) );
}
} );
This is not the best solution because it will run the query and will filter the result, but I'm using this until discover a way to block the API access before the query is executed.