I am using the GoCardless Documentation here to try list all subscriptions for a customer.
I have followed the instructions as you can see below, however nothing at all is displaying when I run this script - does anyone know what I may have done wrong?
require 'vendor/autoload.php';
$client = new \GoCardlessPro\Client(array(
'access_token' => 'XXXXXx',
'environment' => \GoCardlessPro\Environment::LIVE
));
$client->subscriptions()->list([
"params" => ["customer" => "CU000R3B8512345"]
]);
Calling a method on its own doesn’t do anything. It’ll execute the given method, but it’s not going to print anything to your browser screen on its own.
As RiggsFolly says (and is documented in GoCardless’s API documentation), calling $client->subscriptions()->list() will return a cursor-paginated response object. So you need to do something with this result. What that is, I don’t know as it’s your application’s business logic and only you know that.
<?php
use GoCardlessPro\Client;
use GoCardlessPro\Environment;
require '../vendor/autoload.php';
$client = new Client(array(
'access_token' => 'your-access-token-here',
'environment' => Environment::SANDBOX,
));
// Assign results to a $results variable
$results = $client->subscriptions()->list([
'params' => ['customer' => 'CU000R3B8512345'],
]);
foreach ($results->records as $record) {
// $record is a variable holding an individual subscription record
}
Pagination with Gocardless:
function AllCustomers($client)
{
$list = $client->customers()->list(['params'=>['limit'=>100]]);
$after = $list->after;
// DO THINGS
print_r($customers);
while ($after!="")
{
$customers = $list->records;
// DO THINGS
print_r($customers);
// NEXT
$list = $client->customers()->list(['params'=>['after'=>$after,'limit'=>100]]);
$after = $list->after;
}
}
Related
Updated to show new code / new error # 10/12/2020 11:30
I need to copy invoices from my website to xero using their API. I managed to get this working using the OAuth 1 but now need to update to OAuth2.0.
I've installed xero-php-oauth2-starter which connects and works fine with the examples. e.g. if I click the example "Create one Contact" link, the demo contact is created in xero.
As such, I know the link is working.
I've been looking around trying to find an example of how to create an invoice using the API but am finding it incredibly hard to work out.
Below is what I currently have in my xero api folder:
<?php
ini_set('display_errors', 'On');
require __DIR__ . '/vendor/autoload.php';
require_once('storage.php');
// Use this class to deserialize error caught
use XeroAPI\XeroPHP\AccountingObjectSerializer;
// Storage Classe uses sessions for storing token > extend to your DB of choice
$storage = new StorageClass();
$xeroTenantId = (string)$storage->getSession()['tenant_id'];
if ($storage->getHasExpired()) {
$provider = new \League\OAuth2\Client\Provider\GenericProvider([
'clientId' => 'REMOVED',
'clientSecret' => 'REMOVED',
'redirectUri' => 'https://REMOVED/callback.php',
'urlAuthorize' => 'https://login.xero.com/identity/connect/authorize',
'urlAccessToken' => 'https://identity.xero.com/connect/token',
'urlResourceOwnerDetails' => 'https://api.xero.com/api.xro/2.0/Organisation'
]);
$newAccessToken = $provider->getAccessToken('refresh_token', [
'refresh_token' => $storage->getRefreshToken()
]);
// Save my token, expiration and refresh token
$storage->setToken(
$newAccessToken->getToken(),
$newAccessToken->getExpires(),
$xeroTenantId,
$newAccessToken->getRefreshToken(),
$newAccessToken->getValues()["id_token"] );
}
$config = XeroAPI\XeroPHP\Configuration::getDefaultConfiguration()->setAccessToken( (string)$storage->getSession()['token'] );
$apiInstance = new XeroAPI\XeroPHP\Api\AccountingApi(
new GuzzleHttp\Client(),
$config
);
$invoices = '{"invoices":[{
"type":"Invoice.TypeEnum.ACCREC",
"contact":{"contactID":"97af3783-0f32-42be-a06d-8c586c8aa8ec"},
"lineItems":[{
"description":"Acme Tires",
"quantity":2,
"unitAmount":20,
"accountCode":"000",
"taxType":"NONE",
"lineAmount":40
}],
"date":"2019-03-11",
"dueDate":"2018-12-10",
"reference":"Website Design",
"status":"Invoice.StatusEnum.DRAFT"
}]}';
foreach ($import as $invoice) {
//create contact
$xcontact = new XeroAPI\XeroPHP\Models\Accounting\Contact();
$xcontact->setName($contactname);
//create line item
$lineItems = array();
foreach ($invoice['invoiceLineItems'] as $line) {
$newLine = new XeroAPI\XeroPHP\Models\Accounting\LineItem();
$newLine->setDescription($invoice['message']."\n".$line['description']);
$newLine->setQuantity($line['quantity']);
$newLine->setUnitAmount($line['amount']);
$newLine->setAccountCode('200');
$lineItems[] = $newLine;
}
$xinvoice = new XeroAPI\XeroPHP\Models\Accounting\Invoice();
$xinvoice->setType("ACCREC");
$xinvoice->setStatus("AUTHORISED");
$xinvoice->setDate($invoice['invoiceDate']);
$xinvoice->setDueDate($invoice['dueDate']);
$xinvoice->setLineAmountTypes("NoTax");
$xinvoice->setContact($xcontact);
$xinvoice->setLineItems($lineItems);
$xinvoice->setInvoiceNumber("INV-0".$invoice['invoiceNumber']);
$xinvoices['Invoices'][] = $xinvoice;
}
$apiResponse = $apiInstance->createInvoices($xeroTenantId,$xinvoices);
$summarize_errors = false; // bool | If false return 200 OK and mix of successfully created objects and any with validation errors
$unitdp = 4; // int | e.g. unitdp=4 – (Unit Decimal Places) You can opt in to use four decimal places for unit amounts
?>
gives
Fatal error: Uncaught InvalidArgumentException: Missing the required parameter $invoices when calling createInvoices
which I can't seem to find any details on.
I've created the product "Acme Tires" in xero just incase that was causing the issue (I remember in auth 1 that it wouldn't work if the product wasn't listed first).
Any help would be greatly appreciated.
With the new PHP SDK you need to pass an array of Invoice objects.
The following creates Invoices based on the contents of a pre-existing array ($import).
You'll see that you need to place the line items into an array, and then insert that into the invoice object. The invoice itself is then inserted into an array which is passed to the API.
<?php
foreach ($import as $invoice) {
//create contact
$xcontact = new XeroAPI\XeroPHP\Models\Accounting\Contact();
$xcontact->setName($contactname);
//create line item
$lineItems = array();
foreach ($invoice['invoiceLineItems'] as $line) {
$newLine = new XeroAPI\XeroPHP\Models\Accounting\LineItem();
$newLine->setDescription($invoice['message']."\n".$line['description']);
$newLine->setQuantity($line['quantity']);
$newLine->setUnitAmount($line['amount']);
$newLine->setAccountCode('200');
$lineItems[] = $newLine;
}
$xinvoice = new XeroAPI\XeroPHP\Models\Accounting\Invoice();
$xinvoice->setType("ACCREC");
$xinvoice->setStatus("AUTHORISED");
$xinvoice->setDate($invoice['invoiceDate']);
$xinvoice->setDueDate($invoice['dueDate']);
$xinvoice->setLineAmountTypes("NoTax");
$xinvoice->setContact($xcontact);
$xinvoice->setLineItems($lineItems);
$xinvoice->setInvoiceNumber("INV-0".$invoice['invoiceNumber']);
$xinvoices['Invoices'][] = $xinvoice;
}
$apiResponse = $apiInstance->createInvoices($xeroTenantId,$xinvoices);
?>
Update:
$apiInstance will have been created earlier eg.
$apiInstance = new XeroAPI\XeroPHP\Api\AccountingApi(
new GuzzleHttp\Client(),
$config
);
$import was an array in the original script that contained the raw data I wanted to import. You would need to replace this with your own data.
Update 2:
To use your original data, you'll need to remove the
foreach ($import as $invoice) {
loop.
and replace the references to $invoice with your own data.
For example:
//create contact
$xcontact = new XeroAPI\XeroPHP\Models\Accounting\Contact();
$xcontact->setName($contactname);
Would become:
//create contact
$xcontact = new XeroAPI\XeroPHP\Models\Accounting\Contact();
$xcontact->setContactId("97af3783-0f32-42be-a06d-8c586c8aa8ec");
Wow talk about a mind bender. Ok, so whenever I run this
<?php
require_once "../vendor/autoload.php";
use Minishlink\WebPush\WebPush;
use Minishlink\WebPush\Subscription;
$public_key = "PUBLIC_KEY_REDACTED";
$private_key = "PRIVATE_KEY_REDACTED";
$auth = array(
'VAPID' => array(
'subject' => 'https://github.com/Minishlink/web-push-php-example/',
'publicKey' => $public_key, // don't forget that your public key also lives in app.js
'privateKey' => $private_key, // in the real world, this would be in a secret file
)
);
$json = json_decode(file_get_contents("php://input"));
file_put_contents("notification_subscription_info.txt", file_get_contents("php://input"));
try {
$subscription = Subscription::create(json_decode(file_get_contents('php://input'), true));
$notification = [
'subscription' => Subscription::create([ // this is the structure for the working draft from october 2018 (https://www.w3.org/TR/2018/WD-push-api-20181026/)
"endpoint" => "{$json->endpoint}",
"keys" => [
'p256dh' => "{$json->keys->p256dh}",
'auth' => "{$json->keys->auth}"
],
]),
'payload' => 'Hello!',
];
$webPush = new Minishlink\WebPush\WebPush($auth);
$webPush->sendNotification(
$subscription,
$notification['payload'] // optional (defaults null)
);
//version 1 (outside the foreach)
$webPush->flush();
//version 2 (inside the foreach)
foreach($webPush->flush() as $report) { } //This can be empty
} catch (Exception $e) {
echo $e->getMessage();
}
I get very weird behavior in my debugger phpstorm. If I run it with version 1 then I get no push notification and it calls a __destruct method.
If I run version 2 however I get normal behavior and the push notification sends successfully. It appears as if by merely being inside the foreach it changes the flow of the program. I have no idea why this would be and I'm left scratching my head. Does anyone know what is happening?
Edit: I was mistaken about the __destruct method. That's being called because it's the end of the function. In the debugger it's skipping over the flush() call as though it's a literal value. So if I do $report = $webPush->flush(); it will set $report without ever even calling the flush() function (at least that's what it seems like). I even have a breakpoint at the beginning of the flush() function and it isn't hitting it.
We are using this GitHub PHP library for adding javascript in to the head of shopify pages using script tag but we have got stuck somewhere,
it redirects well. We go to app screen to get permission also when we click on install it redirects to redirect page and gives error. in my error log.
Uncaught PHPShopify\Exception\ApiException: script_tag -
expected Array to be a Hash in
This is our app code
<?php
require '/home/xxx/public_html/shopify/1/vendor/autoload.php';
$config = array(
'ShopUrl' => 'xyyy.myshopify.com',
'ApiKey' => 'a07235d5cxx4af2239ea02fe197',
'SharedSecret' => '7ae8a450xxxx2576cf5e7a606c3',
);
PHPShopify\ShopifySDK::config($config);
$shopify = new PHPShopify\ShopifySDK;
$scopes = array('read_orders','read_script_tags','read_products', 'write_script_tags');
$redirectUrl = 'https://xxxx.com/shopify/1/99.php/auth/callback';
$auth = \PHPShopify\AuthHelper::createAuthRequest($scopes, $redirectUrl);
$src = "https://xxxx.com/modules/script72paid.js";
$finalurl='https://xxxxx.myshopify.com/admin/script_tags.json'.
$shopify->ScriptTag->post(array("post"), ''.$finalurl.'', array( "script_tag" => array( "event"=>"onload", "src"=>$src)));
?>
and this is our redirect link code
<?php
require '/home/xxxxxx/public_html/shopify/1/vendor/autoload.php';
$config = array(
'ShopUrl' => 'xxxx.myshopify.com',
'ApiKey' => 'a07235d5cxxxxxx9ea02fe197',
'SharedSecret' => '7ae8a45xxxxxxx76cf5e7a606c3',
);
PHPShopify\ShopifySDK::config($config);
$shopify = new PHPShopify\ShopifySDK;
$accessToken = \PHPShopify\AuthHelper::getAccessToken();
$config2 = array(
'ShopUrl' => 'xxxx.myshopify.com',
'AccessToken' => $accessToken,
);
$shopify2 = new PHPShopify\ShopifySDK($config2);
$src = "https://xxxxx.com/modules/script72paid.js";
$finalurl='https://xxxxx.myshopify.com/admin/script_tags.json'.
$shopify2->ScriptTag->post(array("post"), ''.$finalurl.'', array( "script_tag" => array( "event"=>"onload", "src"=>$src)));
?>
How do we avoid this error with expected Array to be a Hash?
Any help will be great.
Check that you are passing the correct parameters to $shopify->ScriptTag->post() by looking at the function in your copy of the library. Different versions of the library and documentation may have changed something.
Check that those parameters are in the correct order.
Check that all of the arrays you are passing are not actually meant to be objects.
Check if any of the arrays need to wrapped in another array.
I am using the upper mentioned library (Google Cloud Vision Client Library v1) in PHP to assign labels to images... so far so good. It all works, except it returns fewer results than on the google test page... as far as I understand it has to do with a "max_results" parameter which defaults to 10, but I am not able to find where/how to set it manually...
There was a similar question here on Python and there it was as simple as passing it as a parameter - I have tried many options to do this in PHP, but apparently I am doing something wrong...
Here is a link to the documentation : https://googleapis.github.io/google-cloud-php/#/docs/cloud-vision/v0.19.3/vision/v1/imageannotatorclient?method=labelDetection
I am guessing I have to pass it to the "optionalArgs" parameter... but not exactly sure how to do this...
Here is more or less what my code is:
require __DIR__ . '/vendor/autoload.php';
use Google\Cloud\Vision\V1\ImageAnnotatorClient;
$this->client = new ImageAnnotatorClient();
$response = $this->client->labelDetection(...THE IMAGE...);
$labels = $response->getLabelAnnotations();
if ($labels) {
foreach ($labels as $label) {
// do something with $label->getDescription()
}
}
Anyone got an idea how to get more results in the $labels array?
New Method
Since the other answer I provided seems to be deprecated, I am going to provide a sample that uses the setMaxResults method on the Feature object.
$imageAnnotatorClient = new ImageAnnotatorClient();
$gcsImageUri = 'some/image.jpg';
$source = new ImageSource();
$source->setGcsImageUri($gcsImageUri);
$image = new Image();
$image->setSource($source);
$type = Feature_Type::FACE_DETECTION;
$featuresElement = new Feature();
$featuresElement->setType($type);
$featuresElement->setMaxResults(100); // SET MAX RESULTS HERE
$features = [$featuresElement];
$requestsElement = new AnnotateImageRequest();
$requestsElement->setImage($image);
$requestsElement->setFeatures($features);
$requests = [$requestsElement];
$imageAnnotatorClient->batchAnnotateImages($requests);
Deprecated Method
The maxResults value gets specified in the Image constructor
An example of this code can be found in the source code for the Image object.
$imageResource = fopen(__DIR__ . '/assets/family-photo.jpg', 'r');
$image = new Image($imageResource, [
'FACE_DETECTION',
'LOGO_DETECTION'
], [
'maxResults' => [
'FACE_DETECTION' => 1
],
'imageContext' => [
....
]
]
]);
OK, so for anybody who still may need this here is a working example
use Google\Cloud\Vision\Image;
use Google\Cloud\Vision\VisionClient;
$imageResource = fopen(__DIR__ .'/'. $fileIMG, 'r');
$thePic = new Image($imageResource, [
'LABEL_DETECTION',
'LOGO_DETECTION',
'TEXT_DETECTION'
], [
'maxResults' => [
'LABEL_DETECTION' => 20,
'LOGO_DETECTION' => 20,
'TEXT_DETECTION' => 20
],
'imageContext' => []
]);
$vision = new VisionClient();
$result = $vision->annotate($thePic);
$finalLabels = array();
// do the same for $results->text(), $results->logos()
if($result->labels()){
foreach ($result->labels() as $key => $annonObj) {
$tmp = $annonObj->info();
$finalLabels[] = $tmp['description'];
}
}
But... as it says in the official documentation
Please note this client will be deprecated in our next release. In order
to receive the latest features and updates, please take
the time to familiarize yourself with {#see Google\Cloud\Vision\V1\ImageAnnotatorClient}.
So I still need a way to do this using the ImageAnnotatorClient class... any ideas anyone?
All,
I'm trying to get https://github.com/artisaninweb/laravel-soap to work, but no love. This is likely not a problem with the package, but a gap in my understanding of PHP (which I haven't used in a number of years).
The doco says:
SoapWrapper::add(function ($service) {
$service->name('currency')->wsdl('http://currencyconverter.kowabunga.net/converter.asmx?WSDL');
});
$data = [
'CurrencyFrom' => 'USD',
'CurrencyTo' => 'EUR',
'RateDate' => '2014-06-05',
'Amount' => '1000'
];
SoapWrapper::service('currency',function($service) use ($data) {
var_dump($service->getFunctions());
var_dump($service->call('GetConversionAmount',$data)->GetConversionAmountResult);
});
Now that all works great... But how on earth do I get the response from $service->call... back out into my application?
I've tried
$response = SoapWrapper::service('currency',function($service) use ($data) {
$service->call('GetConversionAmount',$data)->GetConversionAmountResult;
});
but that just returns the soap client response.
I've tried:
$response = '';
SoapWrapper::service('currency',function($service) use ($data) {
$response = $service->call('GetConversionAmount',$data)->GetConversionAmountResult;
});
but that does nothing as it seems anything inside that wrapper call only exists inside that block.
They are really the only two things I could think of doing as I'm not very familiar with all these singleton calls that seem to occur in Laravel (I was also of the opinion that they should be avoided like the plague).
Any help would be greatly appreciated.
I'm the creator of the laravel-soap package.
You can give the data back like so:
$response = '';
$data = [
'CurrencyFrom' => 'USD',
'CurrencyTo' => 'EUR',
'RateDate' => '2014-06-05',
'Amount' => '1000'
];
SoapWrapper::service('currency',function($service) use ($data,&$response) {
$response = $service->call('GetConversionAmount',$data)->GetConversionAmountResult;
});
var_dump($response);
This is called passing by reference: http://php.net/manual/en/language.references.pass.php
I've you got some issues with the laravel-soap package please create a issue on Github.