我是mvc的新手,试图从Quickbooks调用Api以获取公司信息(沙盒),因此我按照intuit.com上的说明进行操作:创建应用程序,生成客户端ID,客户端密码并在web.config中使用。我也生成了OAuth2,使用用户名和密码登录后,在项目中可以看到“连接到Quickbooks”对话框,现在我正试图调用Api,因此首先我创建了OAuth2RequestValidator类的dobject,但错误提示为“未将对象引用设置为对象实例,因为我正在使用声明进行身份验证,我认为ClaimsPrincipal无法读取ClaimsIdentity的声明,并且被卡在此处,我试图使用intuit.com中的示例代码>
这是获得身份验证并调用api的控制器
public class AppController : Controller
{
public static string clientid = ConfigurationManager.AppSettings["clientid"];
public static string clientsecret = ConfigurationManager.AppSettings["clientsecret"];
public static string redirectUrl = ConfigurationManager.AppSettings["redirectUrl"];
public static string environment = ConfigurationManager.AppSettings["appEnvironment"];
public static OAuth2Client auth2Client = new OAuth2Client(clientid, clientsecret, redirectUrl, environment);
/// <summary>
/// Use the Index page of App controller to get all endpoints from discovery url
/// </summary>
public ActionResult Index()
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
Session.Clear();
Session.Abandon();
Request.GetOwinContext().Authentication.SignOut("Cookies");
return View();
}
/// <summary>
/// Start Auth flow
/// </summary>
public ActionResult InitiateAuth(string submitButton)
{
switch (submitButton)
{
case "Connect to QuickBooks":
List<OidcScopes> scopes = new List<OidcScopes>();
scopes.Add(OidcScopes.Accounting);
string authorizeUrl = auth2Client.GetAuthorizationURL(scopes);
return Redirect(authorizeUrl);
default:
return (View());
}
}
/// <summary>
/// QBO API Request
/// </summary>
public ActionResult ApiCallService()
{
if (Session["realmId"] != null)
{
string realmId = Session["realmId"].ToString();
try
{
var principal = User as ClaimsPrincipal;
OAuth2RequestValidator oauthValidator = new OAuth2RequestValidator(principal.FindFirst("access_token").Value);
// Create a ServiceContext with Auth tokens and realmId
ServiceContext serviceContext = new ServiceContext(realmId, IntuitServicesType.QBO, oauthValidator);
serviceContext.IppConfiguration.MinorVersion.Qbo = "23";
// Create a QuickBooks QueryService using ServiceContext
QueryService<CompanyInfo> querySvc = new QueryService<CompanyInfo>(serviceContext);
CompanyInfo companyInfo = querySvc.ExecuteIdsQuery("SELECT * FROM CompanyInfo").FirstOrDefault();
string output = "Company Name: " + companyInfo.CompanyName + " Company Address: " + companyInfo.CompanyAddr.Line1 + ", " + companyInfo.CompanyAddr.City + ", " + companyInfo.CompanyAddr.Country + " " + companyInfo.CompanyAddr.PostalCode;
return View("ApiCallService", (object)("QBO API call Successful!! Response: " + output));
}
catch (Exception ex)
{
return View("ApiCallService", (object)("QBO API call Failed!" + " Error message: " + ex.Message));
}
}
else
return View("ApiCallService", (object)"QBO API call Failed!");
}
/// <summary>
/// Use the Index page of App controller to get all endpoints from discovery url
/// </summary>
public ActionResult Error()
{
return View("Error");
}
/// <summary>
/// Action that takes redirection from Callback URL
/// </summary>
public ActionResult Tokens()
{
return View("Tokens");
}
该控制器创建了访问令牌和刷新令牌
public class CallbackController : Controller
{
/// <summary>
/// Code and realmid/company id recieved on Index page after redirect is complete from Authorization url
/// </summary>
public async Task<ActionResult> Index()
{
//Sync the state info and update if it is not the same
var state = Request.QueryString["state"];
if (state.Equals(AppController.auth2Client.CSRFToken, StringComparison.Ordinal))
{
ViewBag.State = state + " (valid)";
}
else
{
ViewBag.State = state + " (invalid)";
}
string code = Request.QueryString["code"] ?? "none";
string realmId = Request.QueryString["realmId"] ?? "none";
await GetAuthTokensAsync(code, realmId);
ViewBag.Error = Request.QueryString["error"] ?? "none";
return RedirectToAction("Tokens", "App");
}
/// <summary>
/// Exchange Auth code with Auth Access and Refresh tokens and add them to Claim list
/// </summary>
private async Task GetAuthTokensAsync(string code, string realmId)
{
if (realmId != null)
{
Session["realmId"] = realmId;
}
Request.GetOwinContext().Authentication.SignOut("TempState");
var tokenResponse = await AppController.auth2Client.GetBearerTokenAsync(code);
var claims = new List<Claim>();
if (Session["realmId"] != null)
{
claims.Add(new Claim("realmId", Session["realmId"].ToString()));
}
if (!string.IsNullOrWhiteSpace(tokenResponse.AccessToken))
{
claims.Add(new Claim("access_token", tokenResponse.AccessToken));
claims.Add(new Claim("access_token_expires_at", (DateTime.Now.AddSeconds(tokenResponse.AccessTokenExpiresIn)).ToString()));
}
if (!string.IsNullOrWhiteSpace(tokenResponse.RefreshToken))
{
claims.Add(new Claim("refresh_token", tokenResponse.RefreshToken));
claims.Add(new Claim("refresh_token_expires_at", (DateTime.Now.AddSeconds(tokenResponse.RefreshTokenExpiresIn)).ToString()));
}
var id = new ClaimsIdentity(claims, "Cookies");
Request.GetOwinContext().Authentication.SignIn(id);
}
}
注意:这是用户在完成身份验证后重定向的控制器。
,这是我尝试调用api时发生的错误 bject引用未设置为对象的实例。 说明:执行当前Web请求期间发生未处理的异常。请查看堆栈跟踪,以获取有关错误及其在代码中起源的更多信息。
异常详细信息:System.NullReferenceException:没有对象引用 设置为对象的实例。
源错误:
第66行:// {第67行:var 主体=用户作为ClaimsPrincipal;第68行:
OAuth2RequestValidator oauthValidator =新 OAuth2RequestValidator(principal.FindFirst(“ access_token”)。Value); 第69行:第70行://使用以下命令创建ServiceContext 身份验证令牌和realmId
答案 0 :(得分:1)
刚遇到这个问题,找到了解决办法,也许能帮别人省点时间。
IntuitAPI 文档假设您正在使用 Cookie 身份验证
将此添加到 Startup.cs 然后尝试
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = "Cookies"
});
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = "TempState",
AuthenticationMode = AuthenticationMode.Passive
});