asp.net 核心 3.1 在条带 HttpPost("webhook") 中获取当前身份用户 returns NULL
asp.net core 3.1 getting current identity user within stripe HttpPost("webhook") returns NULL
我根据 stripe 的 example
在我的网站中集成了 stripe 结账支付
一切正常。我可以验证 webhooks 是否与 stripe CLI 一起工作,也可以使用 ngrok,隧道化我的 localhost
.
现在我已经开始实现与身份数据库的交互。
我想在 webhook 触发 checkout.session.completed
.
后将条纹 session.CustomerId
存储在那里
为此,我需要访问我的身份数据库。
我的代码是:
[HttpPost("webhook")]
public async Task<IActionResult> Webhook()
{
// GET logged current user
var currentUser = await _userManager.GetUserAsync(User);
var json = await new StreamReader(HttpContext.Request.Body).ReadToEndAsync();
Event stripeEvent;
try
{
stripeEvent = EventUtility.ConstructEvent(
json,
Request.Headers["Stripe-Signature"],
this.options.Value.WebhookSecret
);
Console.WriteLine($"Webhook notification with type: {stripeEvent.Type} found for {stripeEvent.Id}");
}
catch (Exception e)
{
Console.WriteLine($"Something failed {e}");
return BadRequest();
}
// Handle the event
if (stripeEvent.Type == Events.PaymentIntentSucceeded) //Success
{
var paymentIntent = stripeEvent.Data.Object as PaymentIntent;
var subscriptionItem = stripeEvent.Data.Object as Stripe.Subscription;
var subscriptionInvoice = stripeEvent.Data.Object as Invoice;
var paidTimestamp = paymentIntent.Created;
var paidValidityTimestamp = subscriptionItem.CurrentPeriodEnd;
Console.WriteLine("*********************");
Console.WriteLine(".....................");
Console.WriteLine("Payment Intent Succeeded");
// Then define and call a method to handle the successful payment intent.
// handlePaymentIntentSucceeded(paymentIntent);
paymentIntent.ReceiptEmail = currentUser.Email;
paymentIntent.Shipping.Address.City = currentUser.City;
paymentIntent.Shipping.Address.PostalCode = currentUser.PostalCode.ToString();
paymentIntent.Shipping.Address.Line1 = currentUser.Street + " " + currentUser.CivicNumber;
currentUser.hasPaidQuote = true;
currentUser.paidOnDate = paidTimestamp;
currentUser.paidValidity = paidValidityTimestamp;
currentUser.SubscriptionStatus = paymentIntent.Status;
currentUser.Status = LoginUserStatus.Approved;
await _userManager.UpdateAsync(currentUser);
Console.WriteLine("has paid? " + currentUser.hasPaidQuote);
Console.WriteLine("paid on date: " + currentUser.paidOnDate.Date.ToString());
Console.WriteLine("payment validity: " + currentUser.paidValidity.Date.ToString());
Console.WriteLine("subscription status: " + currentUser.SubscriptionStatus);
Console.WriteLine("user status: " + currentUser.Status.ToString());
Console.WriteLine("customer ID: " + paymentIntent.Customer.Id);
Console.WriteLine("payment intent status: " + paymentIntent.Status);
Console.WriteLine("invoice status from paymentIntent: " + paymentIntent.Invoice.Status);
Console.WriteLine("invoice status from subscriptionItem: " + subscriptionItem.LatestInvoice.Status);
Console.WriteLine("subscription status: " + subscriptionItem.Status);
Console.WriteLine("invoice status: " + subscriptionInvoice.Paid.ToString());
Console.WriteLine(".....................");
Console.WriteLine("*********************");
}
else if (stripeEvent.Type == Events.PaymentIntentPaymentFailed) //Fails due to card error
{
var paymentIntent = stripeEvent.Data.Object as PaymentIntent;
Console.WriteLine("*********************");
Console.WriteLine(".....................");
Console.WriteLine("Payment Intent requires payment method. Payment failed due to card error");
// Then define and call a method to handle the successful attachment of a PaymentMethod.
// handlePaymentMethodAttached(paymentMethod);
Console.WriteLine("payment intent status: " + paymentIntent.Status);
Console.WriteLine("invoice status: " + paymentIntent.Invoice.Status);
Console.WriteLine(".....................");
Console.WriteLine("*********************");
}
else if (stripeEvent.Type == Events.PaymentIntentRequiresAction) //Fails due to authentication
{
var paymentIntent = stripeEvent.Data.Object as PaymentIntent;
Console.WriteLine("*********************");
Console.WriteLine(".....................");
Console.WriteLine("Payment Intent requires actions");
// Then define and call a method to handle the successful attachment of a PaymentMethod.
// handlePaymentMethodAttached(paymentMethod);
Console.WriteLine("payment intent status: " + paymentIntent.Status);
Console.WriteLine("invoice status: " + paymentIntent.Invoice.Status);
Console.WriteLine(".....................");
Console.WriteLine("*********************");
}
else if (stripeEvent.Type == Events.PaymentMethodAttached)
{
var paymentMethod = stripeEvent.Data.Object as PaymentMethod;
Console.WriteLine("Payment Method Attached");
// Then define and call a method to handle the successful attachment of a PaymentMethod.
// handlePaymentMethodAttached(paymentMethod);
}
// ... handle other event types
if (stripeEvent.Type == "checkout.session.completed")
{
var session = stripeEvent.Data.Object as Stripe.Checkout.Session;
ViewBag.eventID = stripeEvent.Id;
Console.WriteLine("*********************");
Console.WriteLine(".....................");
Console.WriteLine("checkout session completed");
Console.WriteLine($"Session ID: {session.Id}");
// Take some action based on session.
currentUser.StripeCustomerId = session.CustomerId;
await _userManager.UpdateAsync(currentUser);
Console.WriteLine("Ssession.CustomerId has been retrieved from session and will be stored into database: " + session.CustomerId);
Console.WriteLine("StripeCustomerId has been stored into database: " + currentUser.StripeCustomerId);
Console.WriteLine(".....................");
Console.WriteLine("*********************");
}
return Ok();
}
我的问题是 var currentUser = await _userManager.GetUserAsync(User);
返回 NULL。
如果我 运行 在调试模式下的代码,我的刹车点上会出现一个带有感叹号的蓝色圆圈。将鼠标悬停在那里我收到通知:“进程或线程自上一步以来发生了变化”。
使用 stripe 的 checkout API 将我重定向到某个地方,丢失了我的会话信息,因此也丢失了任何 link 到我的身份数据库。
如何让我的变量 currentUser
包含登录用户?
我的PaymentsController
如下:
public class PaymentsController : Controller
{
public readonly IOptions<StripeOptions> options;
private readonly IStripeClient client;
private UserManager<VivaceApplicationUser> _userManager;
private readonly IConfiguration Configuration;
public IActionResult Index()
{
return View();
}
public IActionResult canceled()
{
return View();
}
public IActionResult success()
{
return View();
}
public PaymentsController(IOptions<StripeOptions> options,
IConfiguration configuration,
UserManager<VivaceApplicationUser> userManager)
{
this.options = options;
this.client = new StripeClient(this.options.Value.SecretKey);
_userManager = userManager;
Configuration = configuration;
} .......
}
我的[HttpGet("checkout-session")]
是
[HttpGet("checkout-session")]
public async Task<IActionResult> CheckoutSession(string sessionId)
{
var currentUser = await _userManager.GetUserAsync(HttpContext.User);
var service = new SessionService(this.client);
var session = await service.GetAsync(sessionId);
// Retrieve prices of product
var product = new PriceService();
var productBasic = product.Get(Configuration.GetSection("Stripe")["BASIC_PRICE_ID"]);
var productMedium = product.Get(Configuration.GetSection("Stripe")["MEDIUM_PRICE_ID"]);
var productPremium = product.Get(Configuration.GetSection("Stripe")["PREMIUM_PRICE_ID"]);
int quoteBasic = (int)productBasic.UnitAmount;
int quoteMedium = (int)productMedium.UnitAmount;
int quotePremium = (int)productPremium.UnitAmount;
int selectedPlan = (int)session.AmountTotal;
if (!string.IsNullOrEmpty(session.Id))
{
// storing stripe customerId into the User database
// this will be done if checkout.session.completed
//currentUser.StripeCustomerId = session.CustomerId;
if (selectedPlan == quoteBasic)
{
currentUser.Subscription = Models.VivaceUsers.Subscription.Basic;
}
else if (selectedPlan == quoteMedium)
{
currentUser.Subscription = Models.VivaceUsers.Subscription.Medium;
}
else if (selectedPlan == quotePremium)
{
currentUser.Subscription = Models.VivaceUsers.Subscription.Premium;
}
await _userManager.UpdateAsync(currentUser);
}
return Ok(session);
}
在“checkout-session”中,我可以简单地检索 currentUser 没有任何问题:
var currentUser = await _userManager.GetUserAsync(HttpContext.User);
如何在 webhook
方法中获取并 运行ning?
问题是当您收到来自 Stripe 的 POST 请求时没有用户会话。身份验证会话可能由 cookie 管理,并由您客户的浏览器保留。当直接从 Stripe 收到 POST 请求时,该请求将不包含任何与您的已验证用户相关的 cookie。
您将需要另一种方法将结帐会话与数据库中的用户相关联,而不是使用以下方法查找当前用户。
var currentUser = await _userManager.GetUserAsync(HttpContext.User);
有两种标准方法可以解决这个问题。
在结帐会话的元数据中存储用户 ID。
将结帐会话的 ID 存储在您的数据库中,并与当前用户建立某种关系。
许多用户在选项 1 上都取得了成功,创建结帐会话可能类似于以下内容:
var currentUser = await _userManager.GetUserAsync(HttpContext.User);
var options = new SessionCreateOptions
{
SuccessUrl = "https://example.com/success",
Metadata = new Dictionary<string, string>
{
{"UserId", currentUser.ID},
}
//...
};
然后稍后从 webhook 处理程序中查找用户时:
var currentUser = await _userManager.FindByIdAsync(checkoutSession.Metadata.UserId);
感谢 CJAV,我能够找到一种方法来启动它 运行。我还在这里 and also here Reconciling "New Checkout" Session ID with Webhook Event data.
找到了非常有价值的信息
在我的 [HttpPost("create-checkout-session")]
中,我添加了对 ClientReferenceId = currentUser.Id
的引用,如下所示:
var options = new SessionCreateOptions
{
.....
PaymentMethodTypes = new List<string>
{
"card",
},
Mode = "subscription",
LineItems = new List<SessionLineItemOptions>
{
new SessionLineItemOptions
{
Price = req.PriceId,
Quantity = 1,
},
},
Metadata = new Dictionary<string, string>
{
{ "UserId", currentUser.Id },
},
ClientReferenceId = currentUser.Id
};
我的 [HttpPost("webhook")]
现在是:
.....
// Handle the event
if (stripeEvent.Type == Events.PaymentIntentSucceeded) //Success
{
var paymentIntent = stripeEvent.Data.Object as PaymentIntent;
var customerId = paymentIntent.CustomerId;
var invoiceId = paymentIntent.InvoiceId;
var fetchedEmail = paymentIntent.ReceiptEmail;
var customerService = new CustomerService();
var fetchedCustomer = customerService.Get(customerId);
var invoiceService = new InvoiceService();
var fetchedInvoice = invoiceService.Get(invoiceId);
var currentUser = await _userManager.FindByEmailAsync(fetchedEmail);
//var customerReferenceFromSession = session.Metadata.GetValueOrDefault("UserId");
//var currentUser = await _userManager.FindByIdAsync(customerReferenceFromSession);
var paidTimestamp = paymentIntent.Created;
Console.WriteLine("*********************");
Console.WriteLine(".....................");
Console.WriteLine("Payment Intent Succeeded");
// Then define and call a method to handle the successful payment intent.
// handlePaymentIntentSucceeded(paymentIntent);
var Line1 = currentUser.Street + " " + currentUser.CivicNumber;
var paymentIntentOptions = new PaymentIntentUpdateOptions
{
Shipping = new ChargeShippingOptions()
{
Address = new AddressOptions
{
City = currentUser.City,
PostalCode = currentUser.PostalCode.ToString(),
Line1 = Line1
},
Name = currentUser.LastName + " " + currentUser.FirstName
},
};
var paymentIntentService = new PaymentIntentService();
paymentIntentService.Update(
paymentIntent.Id,
paymentIntentOptions
);
paymentIntent.ReceiptEmail = currentUser.Email;
currentUser.hasPaidQuote = true;
currentUser.paidOnDate = paidTimestamp;
currentUser.SubscriptionStatus = paymentIntent.Status;
currentUser.Status = LoginUserStatus.Approved;
await _userManager.UpdateAsync(currentUser);
Console.WriteLine("has paid? " + currentUser.hasPaidQuote);
Console.WriteLine("paid on date: " + currentUser.paidOnDate.Date.ToString());
Console.WriteLine("subscription status: " + currentUser.SubscriptionStatus);
Console.WriteLine("user status: " + currentUser.Status.ToString());
Console.WriteLine("customer ID: " + paymentIntent.CustomerId);
Console.WriteLine("payment intent status: " + paymentIntent.Status);
Console.WriteLine("invoice status from subscriptionItem: " + subscriptionItem.LatestInvoice.Status);
Console.WriteLine("subscription status: " + subscriptionItem.Status);
Console.WriteLine("invoice status: " + subscriptionInvoice.Paid.ToString());
Console.WriteLine(".....................");
Console.WriteLine("*********************");
}
而且有效!!
在条纹文档中做一个简短的通知会很棒。
祝您编码愉快!
我根据 stripe 的 example
在我的网站中集成了 stripe 结账支付一切正常。我可以验证 webhooks 是否与 stripe CLI 一起工作,也可以使用 ngrok,隧道化我的 localhost
.
现在我已经开始实现与身份数据库的交互。
我想在 webhook 触发 checkout.session.completed
.
session.CustomerId
存储在那里
为此,我需要访问我的身份数据库。
我的代码是:
[HttpPost("webhook")]
public async Task<IActionResult> Webhook()
{
// GET logged current user
var currentUser = await _userManager.GetUserAsync(User);
var json = await new StreamReader(HttpContext.Request.Body).ReadToEndAsync();
Event stripeEvent;
try
{
stripeEvent = EventUtility.ConstructEvent(
json,
Request.Headers["Stripe-Signature"],
this.options.Value.WebhookSecret
);
Console.WriteLine($"Webhook notification with type: {stripeEvent.Type} found for {stripeEvent.Id}");
}
catch (Exception e)
{
Console.WriteLine($"Something failed {e}");
return BadRequest();
}
// Handle the event
if (stripeEvent.Type == Events.PaymentIntentSucceeded) //Success
{
var paymentIntent = stripeEvent.Data.Object as PaymentIntent;
var subscriptionItem = stripeEvent.Data.Object as Stripe.Subscription;
var subscriptionInvoice = stripeEvent.Data.Object as Invoice;
var paidTimestamp = paymentIntent.Created;
var paidValidityTimestamp = subscriptionItem.CurrentPeriodEnd;
Console.WriteLine("*********************");
Console.WriteLine(".....................");
Console.WriteLine("Payment Intent Succeeded");
// Then define and call a method to handle the successful payment intent.
// handlePaymentIntentSucceeded(paymentIntent);
paymentIntent.ReceiptEmail = currentUser.Email;
paymentIntent.Shipping.Address.City = currentUser.City;
paymentIntent.Shipping.Address.PostalCode = currentUser.PostalCode.ToString();
paymentIntent.Shipping.Address.Line1 = currentUser.Street + " " + currentUser.CivicNumber;
currentUser.hasPaidQuote = true;
currentUser.paidOnDate = paidTimestamp;
currentUser.paidValidity = paidValidityTimestamp;
currentUser.SubscriptionStatus = paymentIntent.Status;
currentUser.Status = LoginUserStatus.Approved;
await _userManager.UpdateAsync(currentUser);
Console.WriteLine("has paid? " + currentUser.hasPaidQuote);
Console.WriteLine("paid on date: " + currentUser.paidOnDate.Date.ToString());
Console.WriteLine("payment validity: " + currentUser.paidValidity.Date.ToString());
Console.WriteLine("subscription status: " + currentUser.SubscriptionStatus);
Console.WriteLine("user status: " + currentUser.Status.ToString());
Console.WriteLine("customer ID: " + paymentIntent.Customer.Id);
Console.WriteLine("payment intent status: " + paymentIntent.Status);
Console.WriteLine("invoice status from paymentIntent: " + paymentIntent.Invoice.Status);
Console.WriteLine("invoice status from subscriptionItem: " + subscriptionItem.LatestInvoice.Status);
Console.WriteLine("subscription status: " + subscriptionItem.Status);
Console.WriteLine("invoice status: " + subscriptionInvoice.Paid.ToString());
Console.WriteLine(".....................");
Console.WriteLine("*********************");
}
else if (stripeEvent.Type == Events.PaymentIntentPaymentFailed) //Fails due to card error
{
var paymentIntent = stripeEvent.Data.Object as PaymentIntent;
Console.WriteLine("*********************");
Console.WriteLine(".....................");
Console.WriteLine("Payment Intent requires payment method. Payment failed due to card error");
// Then define and call a method to handle the successful attachment of a PaymentMethod.
// handlePaymentMethodAttached(paymentMethod);
Console.WriteLine("payment intent status: " + paymentIntent.Status);
Console.WriteLine("invoice status: " + paymentIntent.Invoice.Status);
Console.WriteLine(".....................");
Console.WriteLine("*********************");
}
else if (stripeEvent.Type == Events.PaymentIntentRequiresAction) //Fails due to authentication
{
var paymentIntent = stripeEvent.Data.Object as PaymentIntent;
Console.WriteLine("*********************");
Console.WriteLine(".....................");
Console.WriteLine("Payment Intent requires actions");
// Then define and call a method to handle the successful attachment of a PaymentMethod.
// handlePaymentMethodAttached(paymentMethod);
Console.WriteLine("payment intent status: " + paymentIntent.Status);
Console.WriteLine("invoice status: " + paymentIntent.Invoice.Status);
Console.WriteLine(".....................");
Console.WriteLine("*********************");
}
else if (stripeEvent.Type == Events.PaymentMethodAttached)
{
var paymentMethod = stripeEvent.Data.Object as PaymentMethod;
Console.WriteLine("Payment Method Attached");
// Then define and call a method to handle the successful attachment of a PaymentMethod.
// handlePaymentMethodAttached(paymentMethod);
}
// ... handle other event types
if (stripeEvent.Type == "checkout.session.completed")
{
var session = stripeEvent.Data.Object as Stripe.Checkout.Session;
ViewBag.eventID = stripeEvent.Id;
Console.WriteLine("*********************");
Console.WriteLine(".....................");
Console.WriteLine("checkout session completed");
Console.WriteLine($"Session ID: {session.Id}");
// Take some action based on session.
currentUser.StripeCustomerId = session.CustomerId;
await _userManager.UpdateAsync(currentUser);
Console.WriteLine("Ssession.CustomerId has been retrieved from session and will be stored into database: " + session.CustomerId);
Console.WriteLine("StripeCustomerId has been stored into database: " + currentUser.StripeCustomerId);
Console.WriteLine(".....................");
Console.WriteLine("*********************");
}
return Ok();
}
我的问题是 var currentUser = await _userManager.GetUserAsync(User);
返回 NULL。
如果我 运行 在调试模式下的代码,我的刹车点上会出现一个带有感叹号的蓝色圆圈。将鼠标悬停在那里我收到通知:“进程或线程自上一步以来发生了变化”。 使用 stripe 的 checkout API 将我重定向到某个地方,丢失了我的会话信息,因此也丢失了任何 link 到我的身份数据库。
如何让我的变量 currentUser
包含登录用户?
我的PaymentsController
如下:
public class PaymentsController : Controller
{
public readonly IOptions<StripeOptions> options;
private readonly IStripeClient client;
private UserManager<VivaceApplicationUser> _userManager;
private readonly IConfiguration Configuration;
public IActionResult Index()
{
return View();
}
public IActionResult canceled()
{
return View();
}
public IActionResult success()
{
return View();
}
public PaymentsController(IOptions<StripeOptions> options,
IConfiguration configuration,
UserManager<VivaceApplicationUser> userManager)
{
this.options = options;
this.client = new StripeClient(this.options.Value.SecretKey);
_userManager = userManager;
Configuration = configuration;
} .......
}
我的[HttpGet("checkout-session")]
是
[HttpGet("checkout-session")]
public async Task<IActionResult> CheckoutSession(string sessionId)
{
var currentUser = await _userManager.GetUserAsync(HttpContext.User);
var service = new SessionService(this.client);
var session = await service.GetAsync(sessionId);
// Retrieve prices of product
var product = new PriceService();
var productBasic = product.Get(Configuration.GetSection("Stripe")["BASIC_PRICE_ID"]);
var productMedium = product.Get(Configuration.GetSection("Stripe")["MEDIUM_PRICE_ID"]);
var productPremium = product.Get(Configuration.GetSection("Stripe")["PREMIUM_PRICE_ID"]);
int quoteBasic = (int)productBasic.UnitAmount;
int quoteMedium = (int)productMedium.UnitAmount;
int quotePremium = (int)productPremium.UnitAmount;
int selectedPlan = (int)session.AmountTotal;
if (!string.IsNullOrEmpty(session.Id))
{
// storing stripe customerId into the User database
// this will be done if checkout.session.completed
//currentUser.StripeCustomerId = session.CustomerId;
if (selectedPlan == quoteBasic)
{
currentUser.Subscription = Models.VivaceUsers.Subscription.Basic;
}
else if (selectedPlan == quoteMedium)
{
currentUser.Subscription = Models.VivaceUsers.Subscription.Medium;
}
else if (selectedPlan == quotePremium)
{
currentUser.Subscription = Models.VivaceUsers.Subscription.Premium;
}
await _userManager.UpdateAsync(currentUser);
}
return Ok(session);
}
在“checkout-session”中,我可以简单地检索 currentUser 没有任何问题:
var currentUser = await _userManager.GetUserAsync(HttpContext.User);
如何在 webhook
方法中获取并 运行ning?
问题是当您收到来自 Stripe 的 POST 请求时没有用户会话。身份验证会话可能由 cookie 管理,并由您客户的浏览器保留。当直接从 Stripe 收到 POST 请求时,该请求将不包含任何与您的已验证用户相关的 cookie。
您将需要另一种方法将结帐会话与数据库中的用户相关联,而不是使用以下方法查找当前用户。
var currentUser = await _userManager.GetUserAsync(HttpContext.User);
有两种标准方法可以解决这个问题。
在结帐会话的元数据中存储用户 ID。
将结帐会话的 ID 存储在您的数据库中,并与当前用户建立某种关系。
许多用户在选项 1 上都取得了成功,创建结帐会话可能类似于以下内容:
var currentUser = await _userManager.GetUserAsync(HttpContext.User);
var options = new SessionCreateOptions
{
SuccessUrl = "https://example.com/success",
Metadata = new Dictionary<string, string>
{
{"UserId", currentUser.ID},
}
//...
};
然后稍后从 webhook 处理程序中查找用户时:
var currentUser = await _userManager.FindByIdAsync(checkoutSession.Metadata.UserId);
感谢 CJAV,我能够找到一种方法来启动它 运行。我还在这里
在我的 [HttpPost("create-checkout-session")]
中,我添加了对 ClientReferenceId = currentUser.Id
的引用,如下所示:
var options = new SessionCreateOptions
{
.....
PaymentMethodTypes = new List<string>
{
"card",
},
Mode = "subscription",
LineItems = new List<SessionLineItemOptions>
{
new SessionLineItemOptions
{
Price = req.PriceId,
Quantity = 1,
},
},
Metadata = new Dictionary<string, string>
{
{ "UserId", currentUser.Id },
},
ClientReferenceId = currentUser.Id
};
我的 [HttpPost("webhook")]
现在是:
.....
// Handle the event
if (stripeEvent.Type == Events.PaymentIntentSucceeded) //Success
{
var paymentIntent = stripeEvent.Data.Object as PaymentIntent;
var customerId = paymentIntent.CustomerId;
var invoiceId = paymentIntent.InvoiceId;
var fetchedEmail = paymentIntent.ReceiptEmail;
var customerService = new CustomerService();
var fetchedCustomer = customerService.Get(customerId);
var invoiceService = new InvoiceService();
var fetchedInvoice = invoiceService.Get(invoiceId);
var currentUser = await _userManager.FindByEmailAsync(fetchedEmail);
//var customerReferenceFromSession = session.Metadata.GetValueOrDefault("UserId");
//var currentUser = await _userManager.FindByIdAsync(customerReferenceFromSession);
var paidTimestamp = paymentIntent.Created;
Console.WriteLine("*********************");
Console.WriteLine(".....................");
Console.WriteLine("Payment Intent Succeeded");
// Then define and call a method to handle the successful payment intent.
// handlePaymentIntentSucceeded(paymentIntent);
var Line1 = currentUser.Street + " " + currentUser.CivicNumber;
var paymentIntentOptions = new PaymentIntentUpdateOptions
{
Shipping = new ChargeShippingOptions()
{
Address = new AddressOptions
{
City = currentUser.City,
PostalCode = currentUser.PostalCode.ToString(),
Line1 = Line1
},
Name = currentUser.LastName + " " + currentUser.FirstName
},
};
var paymentIntentService = new PaymentIntentService();
paymentIntentService.Update(
paymentIntent.Id,
paymentIntentOptions
);
paymentIntent.ReceiptEmail = currentUser.Email;
currentUser.hasPaidQuote = true;
currentUser.paidOnDate = paidTimestamp;
currentUser.SubscriptionStatus = paymentIntent.Status;
currentUser.Status = LoginUserStatus.Approved;
await _userManager.UpdateAsync(currentUser);
Console.WriteLine("has paid? " + currentUser.hasPaidQuote);
Console.WriteLine("paid on date: " + currentUser.paidOnDate.Date.ToString());
Console.WriteLine("subscription status: " + currentUser.SubscriptionStatus);
Console.WriteLine("user status: " + currentUser.Status.ToString());
Console.WriteLine("customer ID: " + paymentIntent.CustomerId);
Console.WriteLine("payment intent status: " + paymentIntent.Status);
Console.WriteLine("invoice status from subscriptionItem: " + subscriptionItem.LatestInvoice.Status);
Console.WriteLine("subscription status: " + subscriptionItem.Status);
Console.WriteLine("invoice status: " + subscriptionInvoice.Paid.ToString());
Console.WriteLine(".....................");
Console.WriteLine("*********************");
}
而且有效!! 在条纹文档中做一个简短的通知会很棒。
祝您编码愉快!