2014-12-06 76 views
0

这是一个非常混乱的问题,所以我会尽我所能详细说明。我有一个Facebook的画布应用程序,需要支付,当用户点击付款按钮,将出现以下情况:以错误的顺序完成回调函数

  1. 我的JavaScript回调函数被调用,并通过支付ID,所以我保存这个支付的ID等信息到我的订单数据库。

  2. Facebook调用一个回叫网址,我已经设置了让我知道付款何时通过。它只给我付款ID,所以我使用它来搜索数据库中的行,并附上他们发送的付款ID。然后,我使用该行中的信息填充发送给客户的电子邮件,以确认其订单。

我的大问题是,由于某种原因步骤2中得到第1步之前完成,所以当我尝试查找付款ID在数据库中,它还不存在,所以我不能发给客户发电子邮件。我能做些什么来解决这个问题?我在下面的两个步骤都有伪代码。

第1步:

using (OrderDBContext order = new OrderDBContext()) 
      { 
       string message = Encryption.SimpleDecryptWithPassword(orderDetails.request_id, GlobalFacebookConfiguration.Configuration.AppId, 0); 
       string[] finalMessage = message.Split('@'); 
       int orderID = Convert.ToInt16(finalMessage.ElementAtOrDefault(2)); 
       Models.Order row = order.Orders.Where(i => i.ID == orderID).FirstOrDefault(); 

       switch (orderDetails.status) 
       { 
        case "completed": 
         row.PaymentID = orderDetails.payment_id; 
         row.Currency = orderDetails.currency; 
         row.HashKey = orderDetails.request_id; 
         row.Paid = true; 

         order.SaveChanges(); 
         return Json(new { message = "Your payment was processed! You will receive a confirmation email soon." }, JsonRequestBehavior.AllowGet); 
        case "initiated": 
         row.PaymentID = orderDetails.payment_id; 
         row.Currency = orderDetails.currency; 
         row.HashKey = orderDetails.request_id; 
         row.Paid = false; 

         order.SaveChanges(); 
         return Json(new { message = "Your payment is being processed! You will receive a confirmation email as soon as the payment is confirmed." }, JsonRequestBehavior.AllowGet); 
       } 
      } 

第2步:

dynamic result = new StreamReader(request.InputStream).ReadToEnd(); 
       var items = JsonConvert.DeserializeObject<RootObject>(result); 
       string paymentID; 

       if (items.entry != null && items.entry.Count > 0) 
       { 
        paymentID = items.entry[0].id; 
       } 
       else 
       { 
        // logic when items.entry is null or doesn't have any elements 
        paymentID = null; 
       } 

       if (PaymentHelper.confirmPayment(paymentID, GlobalFacebookConfiguration.Configuration.AppId, GlobalFacebookConfiguration.Configuration.AppSecret)) 
       { 
        // if payment is confirmed then send email to us with the order details 
        // then send confirmation email to user letting them know that we are working on it 
        using (OrderDBContext order = new OrderDBContext()) 
        { 
         Order row = order.Orders.Where(i => i.PaymentID == paymentID).FirstOrDefault(); 
         SendEmail.sendOrderDetailsToWriter(row); 
         SendEmail.sendOrderDetailsToCustomer(row); 
        } 
       } 
+0

你需要第三步同步2个第一。 – tschmit007 2014-12-06 10:25:04

+0

@ tschmit007不确定你的意思。你能举一些例子代码吗? – user3610374 2014-12-06 11:03:51

回答

1

什么启动Facebook操作?步骤#1中的某些事情是否会导致步骤#2启动?或者两个步骤是异步开始的?

假设后者(因为这是更困难的情况下),你应该做这样的事情:

readonly object o = new object(); 
bool databaseUpdated; 

// user clicked the payment button 
void onClick() 
{ 
    databaseUpdated = false; 

    StartStep1(); 
    StartStep2(); 
} 

// completion routines for steps #1 and #2 
void stepOneDone() 
{ 
    lock (o) 
    { 
     // do the database update here...i.e. the code you posted for step #1 

     databaseUpdated = true; 
     Monitor.Pulse(o); 
    } 
} 

void stepTwoDone() 
{ 
    lock (o) 
    { 
     while (!databaseUpdated) 
     { 
      Monitor.Wait(o); 
     } 

     // Process Facebook response here...i.e. the code you posted for step #2 
    } 
} 

以上使用共享锁的两个操作相互同步。 databaseUpdated标志当然表示数据库更新是否已完成。如果在数据库更新甚至开始之前启动了步骤#2完成(即,步骤#2在步骤#1之前获得了锁定),则它将检查该标记,注意它尚未设置,并且将等待。致电Monitor.Wait()释放锁定,以便步骤#1可以接受。然后第1步完成它需要做的事情,设置标志,然后向第2步的线程发出信号,表示它可以继续。

当然,如果步骤#1先获得锁定,则步骤#2甚至不能得到它。当锁再次可用并且步骤#2可以处理超过lock声明时,该标志将被设置并且可以继续其快乐的方式。 :)

这是可能的有一种有趣的方式来解决使用新的成语的问题,但没有更多的上下文我不能说。以上应该可以肯定。

最后,一个小小的尼特:为什么你宣布第2步result变量为dynamic?除了string之外,ReadToEnd()方法将不会返回任何内容。这里使用dynamic毫无意义,由于需要动态绑定(这取决于C#编译器是否注意到它是毫无意义的),所以最多可能会产生额外的开销;我不记得编译规则是什么那里)。

+0

用户通过点击付款按钮来启动步骤,并且在付款窗口关闭后立即启动步骤1,但步骤2本质上取决于Facebook,因为当付款在其结束时完成时,步骤2开始向回叫发布帖子。在我的本地调试步骤1中总是先通过,但是当我直接通过Facebook查看应用程序的工作方式时,第2步总是首先经过。我希望这给你你需要的背景。 – user3610374 2014-12-07 02:59:20

+0

你尝试过应用我上面描述的技术吗?如果没有,你应该。如果你做到了,它有用吗?如果没有,你应该详细描述为什么不。 – 2014-12-07 03:02:07

+0

我还没有。我即将尝试。我只是想先回答你的问题 – user3610374 2014-12-07 03:11:59

1

在伪代码:

Semaphore = 0; 

function Step1() { 
    //do your stuff 
    Semaphore++; 
} 

function Step2() { 
    //do your stuff 
    Semaphore++; 
} 

function Step3() { 
    while (1) { // for example a setTimer in javascript 
     if (Semaphore >= 2) { 
      // send email 
      break; 
     } 
     if (timeout()) { 
      // send error message 
      break; 
     } 
     sleep(200); 
    } 
} 

Step1.Start(); 
Step2.Start(); 
Step3.Start(); 

你当然可以找到一个javascript框架允许同步两个任务。这里是一个非常简单和天真的同步。