QuickBooks API "Failed to open required file" - laravel

I'm integrating QuickBooks API in my newly created laravel app. But I'm always stuck with an error of Failed to open required file. I've been searching for the same problem but none of them works. Is there anyone who have tried to integrate QuickBooks API to their laravel app ? Can you guide me on how do it ?
QuickBooks_Loader::load(): Failed opening required 'C:\wamp64\www\...\vendor\consolibyte\quickbooks/QuickBooks\Driver\.php' (include_path='.;C:\php\pear;C:\wamp64\www\...\vendor\consolibyte\quickbooks')
this is how I set up my qbo env variables.
QB_DSN= mysqli://root:#localhost:3306/omni_qbo
QB_TOKEN=AB11573209674XW53cTKF8xf5lY8vva2A4C8aMliPMWgWGUOl7
QB_OAUTH_CONSUMER_KEY= ABsW9nlMQEpjnzYNvl5ySx1FSqpaibMuJEe1DS0xMMt8bKpQoZ
QB_CONSUMER_SECRET=SxbO5CUvclrWWTFTnVCB1ZWvwk8TjqM67shCv3VP
QB_OAUTH_URL=http://localhost:8000/qbo/oauth
QB_SUCCESS_URL=http://localhost:8000/qbo/success
QB_SANDBOX=true
QB_USERNAME=DO_NOT_CHANGE_ME
QB_TENANT=12345
This is the controller sample code I copied from the link . I just followed the steps on how to integrate quickbooks api to laravel but still not working.
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers\Controller;
class QuickBookController extends Controller
{
private $IntuitAnywhere;
private $context;
private $realm;
public function __construct(){
if (!\QuickBooks_Utilities::initialized(env('QBO_DSN'))) {
// Initialize creates the neccessary database schema for queueing up requests and logging
\QuickBooks_Utilities::initialize(env('QBO_DSN'));
}
$this->IntuitAnywhere = new \QuickBooks_IPP_IntuitAnywhere(env('QBO_DSN'), env('QBO_ENCRYPTION_KEY'), env('QBO_OAUTH_CONSUMER_KEY'), env('QBO_CONSUMER_SECRET'), env('QBO_OAUTH_URL'), env('QBO_SUCCESS_URL'));
}
public function qboConnect(){
if ($this->IntuitAnywhere->check(env('QBO_USERNAME'), env('QBO_TENANT')) && $this->IntuitAnywhere->test(env('QBO_USERNAME'), env('QBO_TENANT'))) {
// Set up the IPP instance
$IPP = new \QuickBooks_IPP(env('QBO_DSN'));
// Get our OAuth credentials from the database
$creds = $this->IntuitAnywhere->load(env('QBO_USERNAME'), env('QBO_TENANT'));
// Tell the framework to load some data from the OAuth store
$IPP->authMode(
\QuickBooks_IPP::AUTHMODE_OAUTH,
env('QBO_USERNAME'),
$creds);
if (env('QBO_SANDBOX')) {
// Turn on sandbox mode/URLs
$IPP->sandbox(true);
}
// This is our current realm
$this->realm = $creds['qb_realm'];
// Load the OAuth information from the database
$this->context = $IPP->context();
return true;
} else {
return false;
}
}
public function qboOauth(){
if ($this->IntuitAnywhere->handle(env('QBO_USERNAME'), env('QBO_TENANT')))
{
; // The user has been connected, and will be redirected to QBO_SUCCESS_URL automatically.
}
else
{
// If this happens, something went wrong with the OAuth handshake
die('Oh no, something bad happened: ' . $this->IntuitAnywhere->errorNumber() . ': ' . $this->IntuitAnywhere->errorMessage());
}
}
public function qboSuccess(){
return view('qbo_success');
}
public function qboDisconnect(){
$this->IntuitAnywhere->disconnect(env('QBO_USERNAME'), env('QBO_TENANT'),true);
return redirect()->intended("/yourpath");// afer disconnect redirect where you want
}

Related

Getting error using Laravel PayPal billing agreement

I'm getting an error using Laravel PayPal billing agreement. I received HTTP response code 400 when accessing https://api.sandbox.paypal.com/v1/payments/billing-agreements/. I'm
getting this error once I try to complete the agreement process.
$id = my_created_plan_id
protected function agreement($id)
{
$agreement = new Agreement();
$agreement->setName('Base Agreement')->setDescription('Basic Agreement')
// ->setStartDate(date("Y-m-d").'T9:45:04Z'); ->setStartDate('2021-07-05T9:45:04Z');
$agreement->setPlan($this->Plan($id));
$agreement->setPayer($this->payer());
$agreement->setShippingAddress($this->shippingAddress());
$agreement = $agreement->create($this->apiContext);
return $agreement->getApprovalLink();
}
protected function Plan($id)
{
$plan = new Plan();
$plan->setId($id);
return $plan;
}
protected function payer()
{
$payer = new Payer();
$payer->setPaymentMethod('paypal');
return $payer;
}
protected function shippingAddress()
{
$shippingAddress = new ShippingAddress();
$shippingAddress->setLine1('111 First Street')
->setCity('Saratoga')
->setState('CA')
->setPostalCode('95070')
->setCountryCode('US');
return $shippingAddress;
}
You are using a deprecated SDK that does not support the current version of PayPal Subscriptions, for which there is no SDK.
Change your integration to not use that old SDK. The new Subscribe button itself is JavaScript. Use direct HTTPS calls with curl or similar when you need to call an API to create Products and Plans or administer Subscriptions.
(You can also do so in your account's web interface, rather than via API)
Sandbox: https://www.sandbox.paypal.com/billing/
Live: https://www.paypal.com/billing/
protected function agreement($id)
{
$agreement = new Agreement();
$agreement->setName('Base Agreement')->setDescription('Basic Agreement')
// ->setStartDate(date("Y-m-d").'T9:45:04Z'); ->setStartDate('2021-07-05T9:45:04Z');
//Replace above line with below line
//->setStartDate(gmdate("Y-m-d\TH:i:s\Z", time()+60));
$agreement->setPlan($this->Plan($id));
$agreement->setPayer($this->payer());
$agreement->setShippingAddress($this->shippingAddress());
$agreement = $agreement->create($this->apiContext);
return $agreement->getApprovalLink();
}
You cannot comment on the start date of the agreement.
you must provide the start date of agreement and the error occurred due to this issue.

HttpContext.Session.Abandon() doesn't work in MVC core. Session.clear doesn't log my user out

I get an error that says "ISession does not contain a definition for 'Abandon' and no accessible extension method 'Abandon' accepting a first argument of type 'ISession' could be found".
I have tried using session.clear but even after logging out if I open the website the user is logged in.
This is the error I get
This is how I have implemented Session in my ASP .NET CORE project:
Create a SessionTimeout filter:
public class SessionTimeout : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext context)
{
if (context.HttpContext.Session == null ||!context.HttpContext.Session.TryGetValue("UserID", out byte[] val))
{
context.Result =
new RedirectToRouteResult(new RouteValueDictionary(new
{
controller = "Pages",
action = "SessionTimeout"
}));
}
base.OnActionExecuting(context);
}
}
Register this filter in your Startup.cs:
In your ConfigureServices method:
services.AddSession(options =>
{
options.IdleTimeout = TimeSpan.FromMinutes(10);
});
In your Configure add:
app.UseSession();
And finally decorate your class/method with your filter like:
[SessionTimeout]
public class DashboardController : Controller
To destroy your session based on Logout event from your View:
public IActionResult Logout()
{
HttpContext.Session.Clear();
return RedirectToAction("Login", new { controller = "Pages" });
}
It seems my session is being stored in cookies and not getting cleared/deleted when used session.clear()
so I've used this and it seems to work like a charm.
foreach (var cookie in Request.Cookies.Keys)
{
if (cookie == ".AspNetCore.Session")
Response.Cookies.Delete(cookie);
}
HttpContext.Session.Clear() wasn't working for me on my live site in the Controller for my Account/Logout page.
I found out that setting a href of /Account/Logout/ was the problem. I changed my links to /Account/Logout.
If you're having Session problems in .NET Core 3.1 then try this. It may also account for why I couldn't get Cookie Authentication to work - I gave up in the end and switched to using Sessions.

Access TempData within custom middleware

I have custom middleware that provides global error handling. If an exception is caught it should log the details with a reference number. I then want to redirect the user to an error page and only show the reference number. My research shows that TempData should be ideal for this but it only seems to be accessible from within a controller context. I tried adding the reference number to HttpContext.Items["ReferenceNumber"] = Guid.NewGuid();
But this value is lost through the redirect.
How can middleware pass information through a redirect? Do I just have to put the number in a querystring?
Inside the middleware class you need to add a reference to get access to the required interfaces. I have this middleware in a separate project and needed to add this NuGet package.
using Microsoft.AspNetCore.Mvc.ViewFeatures;
This then allows you to request the correct services within the middleware.
//get TempData handle
ITempDataDictionaryFactory factory = httpContext.RequestServices.GetService(typeof(ITempDataDictionaryFactory)) as ITempDataDictionaryFactory;
ITempDataDictionary tempData = factory.GetTempData(httpContext);
After you have ITempDataDictionary you can use it like you would use TempData within a controller.
//pass reference number to error controller
Guid ReferenceNum = Guid.NewGuid();
tempData["ReferenceNumber"] = ReferenceNum.ToString();
//log error details
logger.LogError(eventID, exception, ReferenceNum.ToString() + " - " + exception.Message);
Now when I get the the controller after a redirect I have no issues pulling out the reference number and using it in my view.
//read value in controller
string refNum = TempData["ReferenceNumber"] as string;
if (!string.IsNullOrEmpty(refNum))
ViewBag.ReferenceNumber = refNum;
#*display reference number if one was provided*#
#if (ViewBag.ReferenceNumber != null){<p>Reference Number: #ViewBag.ReferenceNumber</p>}
Once you put this all together, you give users a reference number that they can give you to help troubleshoot the problem. But, you are not passing back potentially sensitive error information which could be misused.
You can register an ITempDataProvider yourself and use it in your middleware. Here is a small sample I got working between two simple paths. If you are already using MVC the ITempDataProvider is probably already registered. The issue I faced was the path of the cookie that was written. It was /page1 so /page2 did not have access to the cookie. So I had to override the options as you can see in code below.
I hope this will help you :)
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IDataProtectionProvider>(s => DataProtectionProvider.Create("WebApplication2"));
services.Configure<CookieTempDataProviderOptions>(options =>
{
options.Path = "/";
});
services.AddSingleton<ITempDataProvider, CookieTempDataProvider>();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ITempDataProvider tempDataProvider)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.Map("/page1", (app1) =>
{
app1.Run(async context =>
{
tempDataProvider.SaveTempData(context, new Dictionary<string, object> { ["Message"] = "Hello from page1 middleware" });
await context.Response.WriteAsync("Hello World! I'm page1");
});
});
app.Map("/page2", (app1) =>
{
app1.Run(async context =>
{
var loadTempData = tempDataProvider.LoadTempData(context);
await context.Response.WriteAsync("Hello World! I'm page2: Message from page1: " + loadTempData["Message"]);
});
});
}
This led me in the right direction: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/app-state#cookie-based-tempdata-provider
Happy coding! :)

How do I check whether a mobile device has already been registered

I'm using the Amazon AWS Ruby SDK for Amazon SNS but I'm having some trouble with devices already being registered. Sometimes when a device gets registered again I get an error like AWS::SNS::Errors::InvalidParameter Invalid parameter: Token Reason: Endpoint arn:aws:sns:us-east-1:**** already exists with the same Token, but different attributes.. How do I check whether an endpoint already exists and more importantly, how do I get the endpoint for a given token?
Credit to BvdBijl's idea, I made an extension method to delete the existing one if found and then add it.
using System;
using System.Text.RegularExpressions;
using Amazon.SimpleNotificationService;
using Amazon.SimpleNotificationService.Model;
namespace Amazon.SimpleNotificationService
{
public static class AmazonSimpleNotificationServiceClientExtensions
{
private const string existingEndpointRegexString = "Reason: Endpoint (.+) already exists with the same Token";
private static Regex existingEndpointRegex = new Regex(existingEndpointRegexString);
public static CreatePlatformEndpointResponse CreatePlatformEndpointIdempotent(
this AmazonSimpleNotificationServiceClient client,
CreatePlatformEndpointRequest request)
{
try
{
var result = client.CreatePlatformEndpoint(request);
return result;
}
catch (AmazonSimpleNotificationServiceException e)
{
if (e.ErrorCode == "InvalidParameter")
{
var match = existingEndpointRegex.Match(e.Message);
if (match.Success) {
string arn = match.Groups[1].Value;
client.DeleteEndpoint(new DeleteEndpointRequest
{
EndpointArn = arn,
});
return client.CreatePlatformEndpoint(request);
}
}
throw;
}
}
}
}
It looks like amazone resolved this issue.
I'm using RoR and used to have same problem when trying to register and existing GCM code I got an error message saying
"AWS::SNS::Errors::InvalidParameter Invalid parameter: Token Reason: Endpoint arn:aws:sns:us-east-1:**** already exists with the same Token, but different attributes."
although I used same (empty) attributes. Now when I send an existing GCM code (with same attributes as the original one) I get the endpoint arn and not the error message.
ListEndpointsByPlatformApplication only return 100 endpoints, you have to use nextToken to get more. Here is my implementation.
public void deleteEndpoint(string token, string PlatformApplicationArn)
{
ListEndpointsByPlatformApplicationRequest listRequest = new ListEndpointsByPlatformApplicationRequest();
listRequest.PlatformApplicationArn = PlatformApplicationArn;
Logger.Info("Deleting endpoint with token -> " + token);
var list = snsClient.ListEndpointsByPlatformApplication(listRequest);
do
{
foreach (var x in list.Endpoints.Where(x => x.Attributes["Token"] == token))
{
snsClient.DeleteEndpoint(new DeleteEndpointRequest() { EndpointArn = x.EndpointArn });
Logger.Info("Endpoint removed-> " + x.EndpointArn);
return;
}
listRequest.NextToken = list.NextToken;
list = snsClient.ListEndpointsByPlatformApplication(listRequest);
}
while (list.NextToken != null);
}

Cannot get any facebook permissions with C# facebook SDK

I have a fairly simple site which allow users to connect via facebook.
I am using C# facebook sdk MVC.
At first i didn't need any specific permission so there were no problems for users to connect. my code looked like this
public class FacebookController : BaseController
{
public FacebookSession FacebookSession
{
get { return (new CanvasAuthorizer().Session); }
}
public ActionResult Profile()
{
var client = new FacebookClient(this.FacebookSession.AccessToken);
dynamic me = client.Get("me");
ViewBag.Name = me.name;
ViewBag.Id = me.id;
return View();
}
}
and on my webconfig
<facebookSettings appId="XXXXXXXXXXXXXX" appSecret="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"/>
After a while I needed more specific permissions so I added CanvasAuthorize to my action - as so
[CanvasAuthorize(Permissions = "user_about_me,user_relationships,email,publish_stream")]
public ActionResult Profile()
That got me this exception:
Exception Details: System.Exception: CanvasUrl is null or empty
So I added to my Webconfig the canvasUrl which got me the same error with out the canvasPage So now my web config has all 4
<facebookSettings appId="XXXXXXXXXX" appSecret="XXXXXXXXXXXXXXXXXXXXx" canvasUrl = "http://localhost:60606/" canvasPage = "https://apps.facebook.com/XXXXXXXXXXXX/"/>
So now my user can log in via facebook, my problem is that when he does log in he is getting redirect to my Facebook app (http://apps.facebook.com/XXXXXXXXX/facebook/profile)
instead back to my site(http://localhost:60606/facebook/profile)
How can I get the Permissions that i need and redirect my user back to my site after he logs in?
Thanks
Well, My bad
CanvasAuthorize is just as it sounds, authorization for canvas.
So you cannot use it without an app canvas on facebook.
What I should have done is use the FacebookOAuthClient
var oAuthClient = new FacebookOAuthClient(FacebookApplication.Current);
oAuthClient.RedirectUri = new Uri("XXXXXXXXXXXXXX");
var loginUri = oAuthClient.GetLoginUrl(new Dictionary<string, object> { { "state", null }, { "scope", "user_about_me,user_relationships,email" } });
return Redirect(loginUri.AbsoluteUri);

Resources