我有一个使用PayPal自适应付款的电子商务网站。自适应支付请求从PayPal生成PayKey以创建发票。获得PayKey的延迟时间足够长所以我有想法将代码放在一个单独的线程中,而用户在重定向到PayPal之前回答其他一些问题,请参阅下面的代码:
await Task.Run<Task>(async () =>
{
var payResponse = await _payPalApplicationService.ProceedWithPayPal(currentEvent.Id, order.InvoiceId, order.TrackingId, owners.Single(), vModel.TotalPrice, vModel.DeliveryPriceTotal, orderToAdd.TotalTaxes, orderToAdd.SalesRate + orderToAdd.SalesRateTaxes, vModel.SKUViewModels, _payPalApplicationService.PayPalCore._serviceEndPointUrl);
order.PayKey = payResponse.payKey;
_orderService.Update(order);
await _unitOfWorkAsync.SaveChangesAsync();
});
我遇到的问题是一些用户可以快速访问,因此在重定向到PayPal之前尚未生成PayKey。
在将用户重定向到PayPal之前,您是否知道我可以做些什么来确保我获得PayKey?线程任务在与具有重定向的控制器动作不同的控制器动作中完成。
谢谢
大卫
答案 0 :(得分:2)
它可能违反MVC无国籍原则,但一个非常简单的解决方案是将PayKey检索任务存储在会话中。
所以将上面的代码更改为:
Session["PaypalTask"] = await Task.Run<Task>(async () =>
{
var payResponse = await _payPalApplicationService.ProceedWithPayPal(currentEvent.Id, order.InvoiceId, order.TrackingId, owners.Single(), vModel.TotalPrice, vModel.DeliveryPriceTotal, orderToAdd.TotalTaxes, orderToAdd.SalesRate + orderToAdd.SalesRateTaxes, vModel.SKUViewModels, _payPalApplicationService.PayPalCore._serviceEndPointUrl);
order.PayKey = payResponse.payKey;
_orderService.Update(order);
await _unitOfWorkAsync.SaveChangesAsync();
});
然后,您可以稍后在其他控制器中检索该任务,并在那里await
检索该任务。如果它已经完成exectution将立即继续,否则它将等待它继续完成。
像这样的东西
public async Task<ActionResult> Index()
{
var payPalTask = Session["PaypalTask"] as Task;
await payPalTask;
return RedirectToAction("CompltedPayment");
}
当然,您可能还需要考虑错误处理等。
更新
我应该提一下,上面的方法将会话状态存储在内存中。如果您的应用程序使用多个服务器,您可能希望研究粘性会话或某种分布式缓存(如redis),则会出现一些复杂情况。
UPDATE2:
我发布了一个使用简单Task.Delay
到here模拟异步方法的演示。如果您构建此Web应用程序,然后导航到/ InitiatePp它将启动请求。然后/ PpResult / Result将给出正在运行的任务的状态,并且/ PpResult / Wait将等待任务完成。