2014-12-06 78 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框架允許同步兩個任務。這裏是一個非常簡單和天真的同步。