webfox / laravel-xero-oauth2

A Laravel integration for Xero using the Oauth 2.0 spec
MIT License
50 stars 32 forks source link

Provide Create Invoice Example I try lot of requests but not create any invoice using your package #2

Closed chirag2324 closed 4 years ago

chirag2324 commented 4 years ago

Hello there,

I am using this package for my laravel framework and try to create a new invoice but I can't create the invoice of using JSON or XML request.

Please see my below code:

`<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request; use Webfox\Xero\OauthCredentialManager; use XeroAPI\XeroPHP\Models\Accounting\Account;

class XeroController extends Controller {

public function index(Request $request, OauthCredentialManager $xeroCredentials)
{
    try {
        // Check if we've got any stored credentials
        if ($xeroCredentials->exists()) {
            /*
             * We have stored credentials so we can resolve the AccountingApi,
             * If we were sure we already had some stored credentials then we could just resolve this through the controller
             * But since we use this route for the initial authentication we cannot be sure!
             */
            //$invoices = json_decode('{"invoices":[{"type":"ACCREC","contact":{"contactID":"00000000-0000-0000-000-000000000000"},"lineItems":[{"description":"Acme Tires","quantity":2,"unitAmount":"20.0","accountCode":"000","taxType":"NONE","lineAmount":"40.0"}],"date":"2019-03-11","dueDate":"2019-03-20","reference":"Website Design","status":"AUTHORISED"}]}');

$invoices = 'ACCRECMartin Hudson2020-03-28T00:00:002020-04-04T00:00:00ExclusiveMonthly rental for property at 56a Wilkins Avenue4.3400395.00200';

//$invoices = '{ invoices:[ { type: Invoice.TypeEnum.ACCREC, contact:{ contactID:"00000000-0000-0000-000-000000000000" }, lineItems:[ { description:"Acme Tires", quantity:2.0, unitAmount:20.0, accountCode:"000", taxType:"NONE", lineAmount:40.0 } ], date:"2019-03-11", dueDate:"2018-12-10", reference:"Website Design", status: Invoice.StatusEnum.DRAFT } ] }';

            $xero             = resolve(\XeroAPI\XeroPHP\Api\AccountingApi::class);
            $invoice = $xero->createInvoices($xeroCredentials->getTenantId(),$invoices);
            //$invoice = $xero->updateOrCreateInvoices($xeroCredentials->getTenantId(),$invoices);
            $organisationName = $xero->getOrganisations($xeroCredentials->getTenantId())->getOrganisations()[0]->getName();
            $user             = $xeroCredentials->getUser();
            $username         = "{$user['given_name']} {$user['family_name']} ({$user['username']})";
        }
    } catch (\throwable $e) {
        // This can happen if the credentials have been revoked or there is an error with the organisation (e.g. it's expired)
        $error = $e->getMessage();
    }

    return view('xero', [
        'connected'        => $xeroCredentials->exists(),
        'error'            => $error ?? null,
        'organisationName' => $organisationName ?? null,
        'username'         => $username ?? null,
        'invoice'         => $invoice ?? null
    ]);
}

} `

I got the below error (PFA localhost 8000 manage xero ).

Thanks In advance.

hailwood commented 4 years ago

Hi @chirag2324 once you've have an instance of \XeroAPI\XeroPHP\Api\AccountingApi::class you're dealing directly with Xero's api library, so you'd be to to ask for support there on actually using the endpoints.

This package is simply a bridge so you don't have to deal with the Oauth2 gymnastics in Laravel.

However I can see you've run into a trap with their docs! Yep their docs aren't actually valid PHP which is fun their "$invoices" example is a kind of weird json/php hybrid.

In general I suggest using the model classes provided by the xero library, Something like this should work

use XeroAPI\XeroPHP\Models\Accounting\Invoice;
use XeroAPI\XeroPHP\Models\Accounting\Invoices;
use XeroAPI\XeroPHP\Models\Accounting\TaxType;
use XeroAPI\XeroPHP\Models\Accounting\LineItem;
use XeroAPI\XeroPHP\Models\Accounting\AccountType;
use XeroAPI\XeroPHP\Models\Accounting\CurrencyCode;

$invoices = [];

for($i = 0; $i < 10; $i++) {

    $lineItems = [];
    for($j = 1; $j < 6; $j++) {
        $lineItem = new LineItem();
        $lineItem->setQuantity(1);
        $lineItem->setUnitAmount(100 * $j);
        $lineItem->setDescription("Line {$j}");
        $lineItem->setTaxType(TaxType::OUTPUT2);
        $lineItem->setAccountCode(AccountType::SALES);
        $lineItems[] = $lineItem;
    }

    $xeroInvoice = new Invoice();
    $xeroInvoice->setType(Invoice::TYPE_ACCREC);
    $xeroInvoice->setContact(/* XERO_CONTACT_UUID */);
    $xeroInvoice->setReference(/* AN INTERNAL REFERENCE */);
    $xeroInvoice->setLineItems($lineItems);
    $xeroInvoice->setCurrencyCode(CurrencyCode::NZD);
    $xeroInvoice->setDueDate(now()->addDays(14));
    $invoices[] = $xeroInvoice;
}

$xero = resolve(\XeroAPI\XeroPHP\Api\AccountingApi::class);
$xero->updateOrCreateInvoices(new Invoices(['invoices' => $invoices]));
chirag2324 commented 4 years ago

Hii @hailwood ,

Thank you so much for your response it really helps me.

In this package, We can only connect one Xero account at a single time can it be multiple accounts?

Means Can I make this package dynamically. I have stored CLIENT ID and CLIENT SECRET in my database so I will connect as per my use.

Thank you,

hailwood commented 4 years ago

The CLIENT_ID and CLIENT_SECRET are in relation to the Xero App you'd register, and even if you have multiple accounts you should only need one application.

But to answer your question, as it stands the package only supports a single account. To support multiple would require extracting an interface out from the CredentialManager class and then creating concrete methods for storing the credentials retrieved on authorization.

chirag2324 commented 4 years ago

@hailwood I really appriciate your prompt reply can you please provide me the logic behind to develop support multiple accounts in this package.

Thank you so much.

hailwood commented 4 years ago

That's not a small change unfortunately and would require a bit of time to implement.

It's effectively a case of creating

interface OauthCredentialManager {}

with any methods we use publicly, and then create something like

class CacheOauthCredentialManager implements OauthCredentialManager {}

Then in the XeroServiceProvider binding the implementation to the interface.

After the PR was merged this would then allow you to create something like a MultiUserOauthCredentialManager class with your custom logic.

chirag2324 commented 4 years ago

Hii @hailwood

It's possible to implement I think it's helpful for me as well as others.

If yes, then how much time later you have to give me the good news.

Thanks once again. I really appreciate your instant support.

hailwood commented 4 years ago

Probably not within the next month unfortunately, with Covid-19 our time to add additional features to our open source packages is limited.

You're welcome to attempt a PR though!

chirag2324 commented 4 years ago

@hailwood Okay, Thank you so much for your support. If any updates related this package ping me If possible.

Thanks

chirag2324 commented 4 years ago

Hello @hailwood ,

When I start the Xero integration on my website first I try the below package.

https://github.com/XeroAPI/xero-php-oauth2

But In this, I found the below error:

https://github.com/XeroAPI/xero-php-oauth2/issues/87

So my just concern on how to solve the above issue? It's helpful for me.

Maybe you have to used to create your package using https://github.com/XeroAPI/xero-php-oauth2 this package as a reference.

Thank you so much in advance.

hailwood commented 4 years ago

So that's your own attempt at getting the Xero api working rather than using this package yeah?

Either way, the primary issue you've run into there is that you haven't prefixed the class with a slash I.e.

new XeroApi\XeroPHP\Api\AccountingApi

Should be

new \XeroApi\XeroPHP\Api\AccountingApi

Or import the AccountingApi with a use statement and just use the classname


use XeroApi\XeroPHP\Api\AccountingApi;

//...

new AccountingApi(...);

But that's general PHP not specific to this package or even Laravel, I do suggest you join the Larachat slack for general support :)

chirag2324 commented 4 years ago

Hey @hailwood

Thank you much bro. My issue is solved.

chirag2324 commented 4 years ago

hello @hailwood

Can you please help me out for the below issue:

https://github.com/XeroAPI/xero-php-oauth2/issues/90

Thanks in advance.

kunallibra commented 4 years ago

@chirag2324 , @StuBez @EunusHosen @accessTechnology @hailwood I followed your example: $invoices = [];

     $lineItem = new LineItem();
     $lineItem->setQuantity(1);
     $lineItem->setUnitAmount(100 * 1);
     $lineItem->setDescription("Line 1");
     $lineItem->setTaxType(TaxType::OUTPUT2);
     $lineItem->setAccountCode(AccountType::SALES);
     $lineItems[] = $lineItem;

 $xeroInvoice = new Invoice();
 $xeroInvoice->setType(Invoice::TYPE_ACCREC);
 $xeroInvoice->setContact("963f7413-145a-48ca-a9e2-6c9013e17d90");
 $xeroInvoice->setReference("AB-123");
 $xeroInvoice->setLineItems($lineItems);

 $xeroInvoice->setDueDate(now()->addDays(14));
 $invoices[] = $xeroInvoice;

$xero = resolve(\XeroAPI\XeroPHP\Api\AccountingApi::class); $xero->createInvoices(new Invoices(['xero_tenant_id' => $xeroCredentials->getTenantId(),'invoices' => $invoices]));

but I am getting an error. The error is: Too few arguments to function XeroAPI\XeroPHP\Api\AccountingApi::createInvoices(), 1 passed in /Applications/XAMPP/xamppfiles/htdocs/gull/app/Http/Controllers/Admin/XeroController.php on line 345 and at least 2 expected

Can you please give some light on this. Thanks

hailwood commented 4 years ago

@kunallibra please don't tag everyone in this issue.

The issue is likely this line

$xero->createInvoices(new Invoices(['xero_tenant_id' => $xeroCredentials->getTenantId(),'invoices' => $invoices]));

Which I believe should be(I may have them backwards)

$xero->createInvoices($xeroCredentials->getTenantId(), new Invoices(['invoices' => $invoices]));

However at this point you're dealing with he Xero API directly, the only code there that's part of this package is $xeroCredentials->getTenantId() so I'd suggest asking for future help on the Xero PHP github repo :+1:

lukem15 commented 3 years ago

Hi @hailwood , I've followed your example but I get the following error message:

[400] Client error:PUT https://api.xero.com/api.xro/2.0/Invoices?summarizeErrors=falseresulted in a400 Bad Requestresponse: { "ErrorNumber": 14, "Type": "PostDataInvalidException", "Message": "JSON request body could not be read, Error (truncated...)

I've been stuck on this for days and cannot get this to work!

My code:

`$invoices = []; for($i = 0; $i < 10; $i++) {

$lineItems = [];
for($j = 1; $j < 6; $j++) {
    $lineItem = new LineItem();
    $lineItem->setQuantity(1);
    $lineItem->setUnitAmount(100 * $j);
    $lineItem->setDescription("Line {$j}");
    $lineItem->setTaxType(TaxType::OUTPUT2);
    $lineItem->setAccountCode(AccountType::SALES);
    $lineItems[] = $lineItem;
}

$xeroInvoice = new Invoice();
$xeroInvoice->setType(Invoice::TYPE_ACCREC);
$xeroInvoice->setContact($contact_id);
$xeroInvoice->setReference('Ref-54541354');
$xeroInvoice->setLineItems($lineItems);
$xeroInvoice->setDueDate(now()->addDays(14));
$invoices[] = $xeroInvoice;

}

$xero = resolve(\XeroAPI\XeroPHP\Api\AccountingApi::class); $xero->createInvoices($xeroCredentials->getTenantId(), new Invoices(['invoices' => $invoices]));`

Any help would be greatly appreciated!

accesstechnology-mike commented 3 years ago

What errors are you getting?

On Fri, 5 Mar 2021, 10:22 lukem15, notifications@github.com wrote:

Hi @hailwood https://github.com/hailwood , I've followed your example but I get the following error message:

[400] Client error: PUT https://api.xero.com/api.xro/2.0/Invoices?summarizeErrors=falseresulted in a 400 Bad Request response: { "ErrorNumber": 14, "Type": "PostDataInvalidException", "Message": "JSON request body could not be read, Error (truncated...)

I've been stuck on this for days and cannot get this to work!

My code:

`$invoices = [];

for($i = 0; $i < 10; $i++) {

$lineItems = []; for($j = 1; $j < 6; $j++) { $lineItem = new LineItem(); $lineItem->setQuantity(1); $lineItem->setUnitAmount(100 * $j); $lineItem->setDescription("Line {$j}"); $lineItem->setTaxType(TaxType::OUTPUT2); $lineItem->setAccountCode(AccountType::SALES); $lineItems[] = $lineItem; }

$xeroInvoice = new Invoice(); $xeroInvoice->setType(Invoice::TYPE_ACCREC); $xeroInvoice->setContact($contact_id); $xeroInvoice->setReference('Ref-54541354'); $xeroInvoice->setLineItems($lineItems); $xeroInvoice->setDueDate(now()->addDays(14)); $invoices[] = $xeroInvoice;

}

$xero = resolve(\XeroAPI\XeroPHP\Api\AccountingApi::class); $xero->createInvoices($xeroCredentials->getTenantId(), new Invoices(['invoices' => $invoices]));`

Any help would be great appreciated!

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/webfox/laravel-xero-oauth2/issues/2#issuecomment-791325182, or unsubscribe https://github.com/notifications/unsubscribe-auth/ANFXY4PVJLPG2F47AZGB5V3TCCWE3ANCNFSM4LVO7Z3A .

lukem15 commented 3 years ago

@accesstechnology-mike Hi Mike, I fixed the problem in the end.

The problem was with the

$xeroInvoice->setContact($contact_id);

I didn't include $contact->setContactID($contact_id);

One more problem I'm having now with this is that I am also trying to add a payment to this invoice that has been created. However when I try and make the payment I get an error "Payments can only be made against Authorised documents"

I'm presuming it is because the above code creates a new DRAFT invoice?

Therefore I've updated it to the following:

$xeroInvoice = new Invoice(); $xeroInvoice->setStatus(Invoice::STATUS_AUTHORISED); $xeroInvoice->setType(\XeroAPI\XeroPHP\Models\Accounting\Invoice::TYPE_ACCREC); $xeroInvoice->setLineAmountTypes(LineAmountTypes::EXCLUSIVE); $xeroInvoice->setContact($contact); $xeroInvoice->setReference('REF-521866414'); $xeroInvoice->setLineItems($lineItems); $xeroInvoice->setDueDate(now()->addDays(14)); $invoices[] = $xeroInvoice;

It appears to be working however when I try and find the invoice in Xero it doesn't exist?

Any help please?

accesstechnology-mike commented 3 years ago

I use draft, but don't apply payments. Make sure you new submissions are duplicates of ones that are already paid too:

In Xero, Payments are only able to be applied against Invoices that are in

the Authorized state (e.g. new Payments cannot be made against Bills in Xero that are already Paid, or against Draft Bills).

On Fri, 5 Mar 2021 at 14:50, lukem15 notifications@github.com wrote:

@accesstechnology-mike https://github.com/accesstechnology-mike Hi Mike, I fixed the problem in the end.

The problem was with the

$xeroInvoice->setContact($contact_id);

I didn't include $contact->setContactID($contact_id);

One more problem I'm having now with this is that I am also trying to add a payment to this invoice that has been created. However when I try and make the payment I get an error "Payments can only be made against Authorised documents"

I'm presuming it is because the above code creates a new DRAFT invoice?

Therefore I've updated it to the following:

$xeroInvoice = new Invoice(); $xeroInvoice->setStatus(Invoice::STATUS_SUBMITTED); $xeroInvoice->setType(\XeroAPI\XeroPHP\Models\Accounting\Invoice::TYPE_ACCREC); $xeroInvoice->setLineAmountTypes(LineAmountTypes::EXCLUSIVE); $xeroInvoice->setContact($contact); $xeroInvoice->setReference('REF-521866414'); $xeroInvoice->setLineItems($lineItems); $xeroInvoice->setDueDate(now()->addDays(14)); $invoices[] = $xeroInvoice;

It appears to be working however when I try and find the invoice in Xero it doesn't exist?

Any help please?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/webfox/laravel-xero-oauth2/issues/2#issuecomment-791466305, or unsubscribe https://github.com/notifications/unsubscribe-auth/ANFXY4NM6ILLV5O7EM7LS6LTCDVRXANCNFSM4LVO7Z3A .