Subscription Profiles not supported by Recurring Payment APIs while updating plan price - paypal-subscriptions

I am using paypal api for recurring billing. i want to update plan price using paypal api. for this i am using
$curl = curl_init();
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_URL, 'https://api-3t.sandbox.paypal.com/nvp');
curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query(array(
'USER' => 'ddsds_da_api',
'PWD' => '123412432134',
'SIGNATURE' => 'sgdsdshds',
'METHOD' => 'UpdateRecurringPaymentsProfile',
'VERSION' => '108',
'PROFILEID' => 'I-FYYMDB55ADSH',
'NOTE' => 'Uma nota opcional, explicando o motivo da mudança',
'AMT' => 120,
'CURRENCYCODE' => 'BRL'
)));
$response = curl_exec($curl);
curl_close($curl);
$nvp = array();
if (preg_match_all('/(?<name>[^\=]+)\=(?<value>[^&]+)&?/', $response, $matches)) {
foreach ($matches['name'] as $offset => $name) {
$nvp[$name] = urldecode($matches['value'][$offset]);
}
}
print_r($nvp);
But i am getting this error Subscription Profiles not supported by Recurring Payment APIs Here is my error
<pre>Array
(
[PROFILEID] => I-FYYMDB55ADSH
[TIMESTAMP] => 2015-03-16T15:48:07Z
[CORRELATIONID] => 33216e1739dde
[ACK] => Failure
[VERSION] => 76.0
[BUILD] => 15735246
[L_ERRORCODE0] => 11592
[L_SHORTMESSAGE0] => Subscription Profiles not supported.
[L_LONGMESSAGE0] => Subscription Profiles not supported by Recurring Payment APIs.
[L_SEVERITYCODE0] => Error
)
Please let me know what i did wrong.

As answered in the PayPal Community Help Forum
by PayPal_Frank Administrator answerd: 04-02-2012 11:08 AM
...
The basic subscription button profile IDs are not support by the
GetRecurringPaymentsProfileDetails API. This API would only work for
subscriptions or recurring payment profiles created via the
CreateRecurringPaymentsProfile API through Express Checkout which is
our API based checkout solution. Website Payments Pro is not required
to use Express Checkout. I know this can be frustrating and we
recommend that merchants collect basic subscription information via
IPN to store in their own database or view the information on their
PayPal account. This has also been submitted as a feature request by
our Merchant Technical Services team.
https://www.x.com/developers/paypal/forums/general-support/there-any-api-or-methods-which-i-can-get-...
...

You only can check the Status of such an Agreement when you use a url like:
$url = 'https://api.paypal.com/v1/payments/billing-agreements/'.$z_res[0]['id_agreement']."/transactions?start_date=".substr($logdbarray['Deal_Start'],0,10)."&end_date=".substr($now,0,10);
Here you will get a list of trsansactions. When the last transaction in not status:canceled then the agreement still runs. You will get dates of transactions as well so you can define if you agree to use your paid service or not.

Related

Google Drive API Notifications - File Watch not Sending Add Notifications - possible reasons?

I just set up Google Drive API Change Notifications, specifying the folderId of a certain shared folder that I have on My Drives. It sends notifications if I change the folder name, but doesn't send notifications if I add files.
I set up the channel successfully, as upon issuing these PHP commands
$client = new Google_Client();
$client->setApplicationName('Some Name');
$client->setAuthConfig( __DIR__ . '/service_account.json');
$client->setScopes(Google_Service_Drive::DRIVE);
$client->fetchAccessTokenWithAssertion();
$token = $client->getAccessToken();
$service = new Google\Service\Drive($client);
$httpclient = new \GuzzleHttp\Client();
$folderid = $someid;
$body = [
'kind' => "api#channel",
'id' => uniqid(),
'type' => 'web_hook',
'resourceId' => $folderid,
'resourceUri' => 'https://www.googleapis.com/drive/v3/files/'.$folderid,
'address' => 'myendpoint'
];
$apiendpoint = 'https://www.googleapis.com/drive/v3/files/' . $folderid . '/watch';
$result = $httpclient->post($apiendpoint, [
'headers' => ['Content-Type' => 'application/json', 'Authorization' => "Bearer {$token['access_token']}"],
'body' => json_encode($body),
"http_errors" => false]);
I see a successful return, and my channel immediately sends a sync message to my endpoint, where I have this
function myendpoint (WP_REST_Request $request) {
$headers= getallheaders();
write_log('in google drive webhook with headers '.print_r($headers, true));
$body = $request->get_body();
write_log('in google drive webhook with body '.print_r($body, true));
global $wpdb;
return http_response_code(200);
}
Via my logging, I see
[07-Nov-2021 12:52:35 UTC] in google drive webhook with headers Array
(
[Host] => courses-test.com
[User-Agent] => APIs-Google; (+https://developers.google.com/webmasters/APIs-Google.html)
[Content-Length] => 0
[Accept] => */*
[Accept-Encoding] => gzip, deflate, br
[X-Forwarded-For] => 66.102.8.121
[X-Forwarded-Proto] => https
[X-Goog-Channel-Expiration] => Sun, 07 Nov 2021 13:51:26 GMT
[X-Goog-Channel-Id] => 6187cbc82a08e
[X-Goog-Message-Number] => 1
[X-Goog-Resource-Id] => resid
[X-Goog-Resource-State] => sync
[X-Goog-Resource-Uri] => https://www.googleapis.com/drive/v3/files/folderid?acknowledgeAbuse=false&supportsAllDrives=false&supportsTeamDrives=false&alt=json
[X-Original-Host] => mydomain
)
I read here
https://developers.google.com/drive/api/v3/push
where it says
"To indicate success, you can return any of the following status codes: 200, 201, 202, 204, or 102."
and hence I am returning return http_response_code(200);
and also read here
https://developers.google.com/drive/api/v3/reference/files/watch
and I don't see anything obvious going on here.
Here
https://developers.google.com/search/docs/advanced/crawling/apis-user-agent?visit_id=637718909398077288-2640249237&rd=1
there is this remark
"Avoid unnecessary retry requests by ensuring that your application is well-designed and responds promptly to notification messages (within seconds)."
Now, when I first set up the channel, my endpoint returns right away, so that would seem to negate the above point.
Also, after I get channel set up, I also run these lines
$optParams = array(
'pageSize' => 10,
'fields' => 'nextPageToken, files(id, name)'
);
$results = $service->files->listFiles($optParams);
and indeed see a listing of files.
So I truly at a loss. When I go into the folder, whose folderId I specified to set up the watch channel, and add a file, or edit a file, I don't receive any notifications. The folder in question is shared, but as I understand, sharing only becomes an issue when dealing with shared drives, which is not my case.
And I read here,
https://developers.google.com/drive/api/v3/push#understanding-drive-api-notification-events
that watching for files being added should indeed work on a file watch, when the file is a folder, since add is one of the events for a resource, and it applies to Files.
**Update:
Ok, I seem to have things working, but not based on an add event. The only thing I changed, is that instead of using Guzzle to make the POST, as I show above, I use this
$channel->setId(uniqid());
$channel->setAddress($body['address']);
$channel->setType('web_hook');
$test = $service->files->watch($folderid, $channel);
Maybe adding some of those extra params in the $body like kind, resourceId, was messing things up when I was using POST via Guzzle. Or now that I know resourceId is not same as folderid, maybe that threw a flag on google's end so that a limited number of notifications were being sent. In any case, just using id', address and type seems to be the way to go, which I think is in the Google Drive Push docs. Just that in those docs, also mention of adding those other params in the request, like 'resourceId'. I suspect if I redo using Guzzle, but specify correct resourceId, or just leave it out and use id', address and type, that it would work.
So now, I get this sort of header in my endpoint when I add a file:
(
[Host] => courses-test.com
[User-Agent] => APIs-Google; (+https://developers.google.com/webmasters/APIs-Google.html)
[Content-Length] => 0
[Accept] => */*
[Accept-Encoding] => gzip, deflate, br
[X-Forwarded-For] => someip
[X-Forwarded-Proto] => https
[X-Goog-Changed] => children
[X-Goog-Channel-Expiration] => Mon, 08 Nov 2021 09:46:10 GMT
[X-Goog-Channel-Id] => chanid
[X-Goog-Message-Number] => num
[X-Goog-Resource-Id] => someid
[X-Goog-Resource-State] => update
[X-Goog-Resource-Uri] => https://www.googleapis.com/drive/v3/files/folderid?acknowledgeAbuse=false&supportsAllDrives=false&supportsTeamDrives=false&alt=json
[X-Original-Host] => mydomain
)
So I can detect [X-Goog-Changed] as being children and just keep track of my current uploaded files and see what the new file is. Or maybe using the fields query string somehow I can directly get the new file id?
Still seems odd that getting info about a new file is such a pain. Maybe it is easier in Google Cloud API and Google wants more people signing up for Cloud. In fact that add event only seems to apply to Cloud buckets.
In short: When watching a folder with files().watch() it is currently not possible to receive notifications about new files added to this folder
There are several workarounds that you can find along with explanations in answers to similar questions:
Use changes().watch():
https://stackoverflow.com/a/26551651/11599789 and https://stackoverflow.com/a/67787626/11599789
Pass the folderId to the token:
https://stackoverflow.com/a/33896300/11599789
Make copy of all file's metadata and query for changes:
https://stackoverflow.com/a/18151189/11599789
Also: There is a relevant feature request on Google's Issue Tracker.
It has been closed due to inactivity, but it is worth "starring" and commenting on it to increase visibility.

Yii2 behaviors verbs actions HTTP Methods: post and get

Sometimes, not often, error message appears: "method not allowed yii2 this url can only handle...: POST
Such a code I found in the function behaviors:
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'delete' => ['post']
Can it occurs this error message and why this error occurs sometimes(not often)?
ADDitional
Really, I apologize that forget to indicate that all it used by iframe(page open in an iframe window and apply to yii2 through a url and after the delete action was completed - was redirected back), may be a user is logged out, but doest understand it.
And the controller postController receive as post as get method: delete url as GET, _csrf as POST
Only allow delete action via Post. ($_POST). For more security
Example to access via the get and post method: Not recommended for Delete action.
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'delete' => ['post','get'],
],
],
Update:
Not always error #405 and may be #403 and ...
Cookies and session expired
When you open several browser tabs(or windows) on your site and your session expires. You login through a window (or with another user). In this case the exception is thrown by clicking on the logut in other open tabs and windows(browser).
This is because CSRF protection works only for unsafe request methods such PUT, POST or DELETE. That's why in order to stay safe your application should never ever use GET requests to change application state.
If a logout by tag <a> or url in nav is set as follows:
'data-method' => 'post'
Modify and try using form and ...
example:
Html::beginForm(['.../logout'], 'post')
. Html::submitButton(
'Logout (' . Yii::$app->user->identity->username . ')',
['class' => 'btn btn-link']
)
. Html::endForm()

Get Calendly Scheduled Appointments with Webhook Data

There's very few post here regarding Calendly so hopefully somebody can help with this issue. Below is the code I'm using and the issue is that Calendly only returns the webhook subscription data, not the actually appointments that customers schedule.
I want to receive data as described on their page here: https://developer.calendly.com/docs/sample-webhook-data but I only get webhook subscription data back, not the scheduled appointments.
$url = 'https://calendly.com/api/v1/hooks';
$webhook_url = 'MY URL HERE';
$curl_data = 'url='.$webhook_url.'&events[]=invitee.created&events[]=invitee.canceled';
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_POST,1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
curl_setopt($ch, CURLOPT_POSTFIELDS,$curl_data);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
"X-TOKEN: MY TOKEN ID HERE"
));
$result = curl_exec($ch);
echo $result;
curl_close($ch);
//print_r(json_decode($result, true));<br><br>
$content = trim(file_get_contents("php://input"));<br>
$decoded = json_decode($content, true);<br><br>
echo $decoded;<br>
{"data":[{"type":"hooks","id":380871,"attributes":{"url":"MY URL HERE","created_at":"2019-04-17T11:07:36Z","events":["invitee.created","invitee.canceled"],"state":"active"}}]}
Once you set up your webhook, Calendly will send a POST request to your webhook URL. In other words, once an invitee books or cancels an invite, your webhook URL will receive the payload from Calendly for that specific event.
Webhooks are a little different from API endpoints. An API provides data at the time you send a request; e.g., "Give me a list of all of my users". Conversely, a webhook acts as a listener to some topic and is event-based; e.g., "Tell me when an invitee has booked a meeting (and tell me about the meeting).
Are you looking to get a list of all invitees/meetings? If so, we don't have an API endpoint for that now, but we'd love to hear what you're looking for and how we can help. You can reach out to us here (reference my name and I'll be able to sync up on your request).

Php: how to get video urls in my vimeo account

I have a vimeo api keys and i uploaded videos this url https://vimeo.com and get my all videos link from this link https://vimeo.com/home/myvideos. Now i got response for all my video links details.
<?php
$urls = array();
$videos = array();
// vimeo test
$urls[] = 'https://vimeo.com/243625359';
$urls[] = 'https://vimeo.com/243438242';
foreach ($urls as $url) {
$videos[] = getVideoDetails($url);
}
function getVideoDetails($url)
{
$host = explode('.', str_replace('www.', '', strtolower(parse_url($url, PHP_URL_HOST))));
$host = isset($host[0]) ? $host[0] : $host;
switch ($host) {
case 'vimeo':
$video_id = substr(parse_url($url, PHP_URL_PATH), 1);
$hash = json_decode(file_get_contents("http://vimeo.com/api/v2/video/{$video_id}.json"));
// header("Content-Type: text/plain");
// print_r($hash);
// exit;
return array(
'provider' => 'Vimeo',
'title' => $hash[0]->title,
'description' => str_replace(array("<br>", "<br/>", "<br />"), NULL, $hash[0]->description),
'description_nl2br' => str_replace(array("\n", "\r", "\r\n", "\n\r"), NULL, $hash[0]->description),
'thumbnail' => $hash[0]->thumbnail_large,
'video' => "https://vimeo.com/" . $hash[0]->id,
'embed_video' => "https://player.vimeo.com/video/" . $hash[0]->id,
);
break;
}
}
header("Content-Type: text/plain");
print_r($videos);
Response:
Array
(
[0] => Array
(
[provider] => Vimeo
[title] => SampleVideo_1280x720_10mb
[description] => Vimeo was born in 2004, created by a group of
filmmakers who wanted an easy and beautiful way to share videos with
their friends. Word started to spread, and an insanely supportive
community of creators began to blossom. Now Vimeo is home to more
than:
[description_nl2br] => Vimeo was born in 2004, created by a group of
filmmakers who wanted an easy and beautiful way to share videos
with their friends. Word started to spread, and an insanely
supportive community of creators began to blossom. Now Vimeo is home
to more than:
[thumbnail] => http://i.vimeocdn.com/video/667808655_640.jpg
[video] => https://vimeo.com/243625359
[embed_video] => https://player.vimeo.com/video/243625359
)
[1] => Array
(
[provider] => Vimeo
[title] => SampleVideo_1280x720_5mb
[description] => We spend our days building a product we love for a growing community of millions. And eating lots of free snacks.
[description_nl2br] => We spend our days building a product we love for a growing community of millions. And eating lots of free snacks.
[thumbnail] => http://i.vimeocdn.com/video/667575091_640.jpg
[video] => https://vimeo.com/243438242
[embed_video] => https://player.vimeo.com/video/243438242
)
)
It's good. I applied my video links manually, but correct way to apply my video links dynamic. I want to get my vimeo video urls in based api keys.
It appears you're using the old Simple API (with this url format: http://vimeo.com/api/v2/video/{$video_id}.json) which is no longer supported by Vimeo.
That said, if your videos are embeddable, you'll likely be better off using oEmbed to get the specified metadata (provider, title, description, thumbnail, video). Vimeo's oEmbed documentation is found here: https://developer.vimeo.com/apis/oembed
Regarding the video and embed_video values you're generating, it's best practice to get the video link and embed code exactly from the API. Because you're generating these values on your own, any changes we make to the URL structure may break your links. For example, unlisted videos have an additional hash after the numerical video_id that your code does not account for.
I hope this information helps!

Add groups as collaborator

I am trying to add a group as a collaborator of a folder using the BOX.net api but i can't.
I am not having any issues to add users, but i couldn't add groups.
I am doing it as they say to do it: {id: "GROUP_ID"} but i am getting a "NOT FOUND" error.
I checked the group and folder id and they are both correct.
Did anyone face this issue before? Is there somebody who can help me with this? I would really appreciate it.
Thanks in advance,
Regards,
Marcelo
You have to be a group administrator on the Box Enterprise in order to manage groups. You may need to ask your Box admin to add you as a co-admin, and give you the "manage groups" permission.
Make sure you pass in "type":"group" in the accessible_by field in addition to "id":"GROUP_ID".
This should be documented soon.
Here's a small example of adding a group as collaborator (PHP). This is done via the V2 API, in case you're using the V1 api (saw you mentioned box.net's api, which is the V1 api).
function addGroupColaborator($folderId, $groupId, $accessType, $accessToken){
$options = array(
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_VERBOSE => true,
CURLOPT_HEADER => false,
CURLINFO_HEADER_OUT => false,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false
);
$url = 'https://api.box.com/2.0/collaborations?notify=false';
$options[CURLOPT_HTTPHEADER] = array ("Authorization: Bearer ".$accessToken);
$postf = array(
"item" => array(
"id" => $folderId,
"type" => "folder"
),
"accessible_by" => array(
"id" => $groupId,
"type" => 'group'
),
"role" => $accessType
);
$options[CURLOPT_POST] = true;
$options[CURLOPT_POSTFIELDS] = json_encode($postf);
$ch = curl_init($url);
curl_setopt_array($ch, $options);
$result = curl_exec($ch);
curl_close($ch);
return json_decode($result, true);
}