我正在尝试为网站上的付款处理器设置模拟方案。通常,我的网站会重定向到用户付费的处理器网站。然后处理器重定向回我的站点,我等待处理器的立即付款通知(IPN)。然后处理器发布到我的NotifyUrl
,该Notify
路由到我的付款控制器PayFastController
上的[HttpGet]
public RedirectResult Pay(string returnUrl, string notifyUrl, int paymentId)
{
var waitThread = new Thread(Notify);
waitThread.Start(new { paymentId, ipnDelay = 1000 });
return new RedirectResult(returnUrl);
}
public void Notify(dynamic data)
{
// Simulate a delay before PayFast
Thread.Sleep(1000);
// Delegate URL determination to the model, vs. directly to the config.
var notifyUrl = new PayFastPaymentModel().NotifyUrl;
if (_payFastConfig.UseMock)
{
// Need an absoluate URL here just for the WebClient.
notifyUrl = Url.Action("Notify", "PayFast", new {data.paymentId}, "http");
}
// Use a canned IPN message.
Dictionary<string, string> dict = _payFastIntegration.GetMockIpn(data.paymentId);
var values = dict.ToNameValueCollection();
using (var wc = new WebClient())
{
// Just a reminder we are posting to Trocrates here, from PayFast.
wc.UploadValues(notifyUrl, "POST", values);
}
}
操作。为了模拟,我重定向到一个本地操作,在确认点击之后,生成一个线程来发布IPN,就像处理器发布一样,然后重定向回我的注册过程。
我的模拟处理器控制器使用以下两种方法来模拟处理器的响应:
notifyUrl = Url.Action("Notify", "PayFast", new {data.paymentId}, "http");
但是,我得到一个'对象引用没有设置为对象的实例'。以下行中的异常:
data.paymentId
Url.Action
具有有效值,例如112,所以我没有传递对Notify
方法的任何空引用。我怀疑我通过在新线程上调用notifyUrl = Url.Action("Notify", "PayFast");
来丢失某种上下文。但是,如果我只使用protocol
,我会避免异常,但我得到一个相对操作URL,我需要一个带有WebClient.UploadValues
参数的重载,因为只有那个重载才能给我一个绝对的URL {{1}}表示需要。
答案 0 :(得分:2)
当您进入线程时,您将无法再访问Url帮助程序所依赖的HttpContext
和Request属性。所以你永远不应该在线程中使用任何依赖于HttpContext的东西。
在调用线程时,您应该传递线程所需的所有信息,如下所示:
waitThread.Start(new {
paymentId,
ipnDelay = 1000,
notifyUrl = Url.Action("Notify", "PayFast", new { paymentId }, "http")
});
然后在线程回调中:
var notifyUrl = new PayFastPaymentModel().NotifyUrl;
if (_payFastConfig.UseMock)
{
// Need an absoluate URL here just for the WebClient.
notifyUrl = data.notifyUrl;
}