1. 程式人生 > >C#開發BIMFACE系列36 服務端API之:回撥機制

C#開發BIMFACE系列36 服務端API之:回撥機制

系列目錄     【已更新最新開發文章,點選檢視詳細】

  在《C# 開發 BIMFACE 系列文章》中介紹了模型轉換、模型對比介面。這2個功能介面比較特殊,發起請求後,邏輯處理是在BIMFACE雲端進行的,通常需要5~10分鐘。當邏輯處理完成後,BIMFACE通過回撥機制通知對比結果。

  BIMFACE支援回撥機制。在呼叫方發起模型轉換、模型整合、模型對比、生成離線資料包等操作時,可以通過傳入引數callback的方式來啟用回撥機制。 在BIMFACE處理完相應操作後,根據呼叫方傳入的回撥地址通知呼叫方相應操作的結果。

URL引數:

signature(簽名):為了確保回撥訊息是由BIMFACE發出的,呼叫方在收到回撥訊息後,須驗證簽名。簽名的計算方式:MD5(``appKey:appSecret:compareId:status:nonce''),如果呼叫方計算的簽名與BIMFACE返回的簽名一致,則證明該訊息是安全可靠的。

應用收到回撥後,須向BIMFace傳送回執,回執訊息:HTTP STATUS 200

Callbak示例:

* 呼叫方對檔案1685236328506848發起了模型轉換,並且傳入的回撥地址是:https://my.app.com/callback。

* BIMFACE在模型轉換任務處理完成後,會發送一個get請求到呼叫方的callback地址:
 https://my.app.com/callback?fileId=1685236328506848&status=success&thumbnail=38044a282f55cb26e3704643dccd2b55/thumbnail/96.png,38044a282f55cb26e3704643dccd2b55/thumbnail/256.png&reason=&signature=99a6fccb1894dfdb4cce48fd5ec58110&nonce=123abc

* 呼叫方接收到這條請求後,可以進行signature的驗證,併發送回執訊息。

特別說明

  BIMFACE的回撥機制與微信公眾號或者小程式開發類似,需要開發者提供開發者伺服器,且有正式合法域名或者外網IP,對外公佈一個地址,BIMFACE伺服器能訪問到該地址才可以。

  如果無法提供有效的回撥地址,則只能通過手動呼叫 模型轉換、模型整合、模型對比、生成離線資料包等操作的其他API來獲取對應的處理結果。

  在.NET平臺下實現該功能可以使用 WebService、一般處理程式、WebAPI等技術方式實現。下面介紹在一般處理程式中實現的思路與步驟。

 1、配置BIMACE開發者賬號資訊。

  在web.config 或者 app.config 檔案中配置開發者賬號資訊,供驗證訊息簽名時使用。

 2、獲取BIMFace伺服器傳送的回撥請求引數。

1 long fileId = context.Request.QueryString["fileId"].ToLong();  // 檔案ID
2 string status = context.Request.QueryString["status"];         // 轉換的結果
3 string reason = context.Request.QueryString["reason"];         // 若轉換失敗,則返回失敗原因
4 string thumbnail = context.Request.QueryString["thumbnail"];   // 縮圖地址
5 string nonce = context.Request.QueryString["nonce"];           // 回撥隨機數
6 string signature = context.Request.QueryString["signature"];   // BIMFACE的加密簽名

 3、根據請求引數計算簽名。

  簽名的計算方式:MD5(``appKey:appSecret:compareId:status:nonce'')

 1 /// <summary>
 2 ///  根據回撥的引數計算簽名
 3 /// </summary>
 4 /// <param name="appKey">開發者祕鑰</param>
 5 /// <param name="appSecret">開發者密碼</param>
 6 /// <param name="fileId">BIMFace發出的回撥資訊:檔案ID</param>
 7 /// <param name="status">BIMFace發出的回撥資訊:轉換的結果</param>
 8 /// <param name="nonce">BIMFace發出的回撥資訊:回撥隨機數</param>
 9 /// <returns></returns>
10 public static string GetCallbackSignature(string appKey, string appSecret, long fileId, string status, string nonce)
11 {
12     return string.Format("{0}:{1}:{2}:{3}:{4}", appKey, appSecret, fileId, status, nonce).EncryptByMD5();
13 }

 其中使用到的擴充套件方法 EncryptByMD5() 實現如下:

 1 /// <summary>
 2 ///  自定義擴充套件方法:使用 MD5(不可逆加密) 演算法加密字串。返回二進位制形式的字串。字串的編碼方式為UTF8。
 3 /// </summary>
 4 /// <param name="this">擴充套件物件。字串。編碼方式為UTF8</param>
 5 /// <param name="caseType">字串大小寫。預設小寫</param>
 6 /// <returns></returns>
 7 public static string EncryptByMD5(this string @this, CaseType caseType = CaseType.Lower)
 8 {
 9     using (MD5 md5 = MD5.Create())
10     {
11         var sb = new StringBuilder();
12         byte[] hashBytes = md5.ComputeHash(Encoding.UTF8.GetBytes(@this));
13         foreach (byte bytes in hashBytes)
14         {
15             sb.Append(bytes.ToString("X2"));//X2 表示二進位制
16         }
17 
18         return caseType == CaseType.Upper ? sb.ToString() : sb.ToString().ToLower();
19     }
20 }
View Code

 4、驗證簽名。

  將步驟3中的計算結果與BIMFace發出的回撥訊息簽名做對比,如果簽名一直則證明該訊息是安全可靠的。 

 1 /// <summary>
 2 ///  驗證BIMFace發出的回撥訊息簽名信息是否安全可靠
 3 /// </summary>
 4 /// <param name="appKey">開發者祕鑰</param>
 5 /// <param name="appSecret">開發者密碼</param>
 6 /// <param name="fileId">BIMFace發出的回撥資訊:檔案ID</param>
 7 /// <param name="status">BIMFace發出的回撥資訊:轉換的結果</param>
 8 /// <param name="nonce">BIMFace發出的回撥資訊:回撥隨機數</param>
 9 /// <param name="signature">BIMFace發出的回撥資訊:簽名</param>
10 /// <param name="custCalcSignature">輸出引數:根據BIMFACE平臺的加密規則計算出來的簽名信息</param>
11 /// <returns></returns>
12 public static bool CheckCallbackSignature(string appKey, string appSecret, long fileId, string status, string nonce, string signature, out string custCalcSignature)
13 {
14     /* signature(簽名):為了確保回撥訊息是由BIMFace發出的,應用在收到回撥訊息後,須驗證簽名。
15     * 簽名的計算方式:MD5("appKey:appSecret:fileId:status:nonce"),如果應用計算的簽名與BIMFace返回的簽名一致,則證明該訊息是安全可靠的。 
16     */
17     custCalcSignature = GetCallbackSignature(appKey, appSecret, fileId, status, nonce);
18 
19     return custCalcSignature == signature;
20 }

 5、根據簽名驗證結果做出回執響應訊息。

      如果驗證簽名成功則可以將模型轉換、模型整合、模型對比、生成離線資料包等操作的處理結果寫入資料庫儲存供後續其他業務邏輯使用。

   簽名成功後,須向BIMFace傳送回執,回執訊息:HTTP STATUS 200。

 1 bool checkSignature = CallbackUtils.CheckCallbackSignature(appKey, appSecret, fileId, status, nonce, signature, out custCalcSignature);
 2 if (checkSignature)
 3 {
 4     tip = "[BIMFace發出的回撥資訊簽名驗證成功!]"
 5           + Environment.NewLine
 6           + callbackResponse;
 7     LogUtility.Info(tip);
 8 
 9     //Todo 此處可以根據fileId把相關的資訊寫入資料庫中
10 
11     // 回執訊息:應用收到回撥後,須向BIMFace傳送回執,回執訊息:HTTP STATUS 200
12     context.Response.Write("HTTP STATUS 200");
13 }
14 else
15 {
16     tip = "[BIMFace發出的回撥資訊簽名驗證不通過!]"
17         + Environment.NewLine
18         + callbackResponse
19         + Environment.NewLine
20         + "自定義計算簽名 custCalcSignature:" + custCalcSignature;
21 
22     LogUtility.Error(tip);
23 
24     context.Response.Write(tip);
25 }

如果簽名驗證失敗,則需要將簽名信息寫入文字日誌供分析原因使用。此時通過編碼方式實現郵件、簡訊、微信訊息等方式通知開發者回撥程式處理結果不正確,使其及時知道業務系統的執行狀況。

 6、釋出程式並使用該回調地址。

  程式完成後釋出到開發者伺服器。在模型轉換、模型整合、模型對比、生成離線資料包等操作的API介面引數中使用該回調地址。

完整的程式碼如下:

 1 /// <summary>
 2 ///  BimFace回撥處理
 3 /// </summary>
 4 public class BimFaceHandler : IHttpHandler
 5 {
 6     public void ProcessRequest(HttpContext context)
 7     {
 8         context.Response.ContentType = "text/plain";
 9         context.Response.ContentEncoding = Encoding.UTF8;
10 
11         string appKey = ConfigUtility.GetAppSettingValue("BIMFACE_AppKey");
12         string appSecret = ConfigUtility.GetAppSettingValue("BIMFACE_AppSecret");
13         string uid = context.Request.QueryString["uid"];  // SparkBimFace
14 
15         #region 校驗
16         if (appKey.IsNullOrWhiteSpace())
17         {
18             LogUtility.Error("BIMFace appKey 配置項沒有配置!");
19 
20             return;
21         }
22 
23         if (appSecret.IsNullOrWhiteSpace())
24         {
25             LogUtility.Error("BIMFace appSecret 配置項沒有配置!");
26 
27             return;
28         }
29 
30         if (uid.IsNullOrWhiteSpace())
31         {
32             LogUtility.Error("[非法請求]回撥地址Url連結中的引數 uid 沒有配置或者配置的值為空!");
33 
34             return;
35         }
36         #endregion
37 
38         long fileId = context.Request.QueryString["fileId"].ToLong();  // 檔案ID
39         string status = context.Request.QueryString["status"];         // 轉換的結果
40         string reason = context.Request.QueryString["reason"];         // 若轉換失敗,則返回失敗原因
41         string thumbnail = context.Request.QueryString["thumbnail"];   // 縮圖地址
42         string nonce = context.Request.QueryString["nonce"];           // 回撥隨機數
43         string signature = context.Request.QueryString["signature"];   // BIMFACE的加密簽名
44 
45         string callbackResponse = string.Format("fileId:{0},\r\nstatus:{1},\r\nreason:{2},\r\nthumbnail:{3},\r\nnonce:{4},\r\nsignature:{5}",
46                                                  fileId, status, reason, thumbnail, nonce, signature);
47         string tip;
48         string custCalcSignature;
49        
50         bool checkSignature = CallbackUtils.CheckCallbackSignature(appKey, appSecret, fileId, status, nonce, signature, out custCalcSignature);
51         if (checkSignature)
52         {
53             tip = "[BIMFace發出的回撥資訊簽名驗證成功!]"
54                   + Environment.NewLine
55                   + callbackResponse;
56             LogUtility.Info(tip);
57 
58             //Todo 此處可以根據fileId把相關的資訊寫入資料庫中
59 
60             // 回執訊息:應用收到回撥後,須向BIMFace傳送回執,回執訊息:HTTP STATUS 200
61             context.Response.Write("HTTP STATUS 200");
62         }
63         else
64         {
65             tip = "[BIMFace發出的回撥資訊簽名驗證不通過!]"
66                 + Environment.NewLine
67                 + callbackResponse
68                 + Environment.NewLine
69                 + "自定義計算簽名 custCalcSignature:" + custCalcSignature;
70 
71             LogUtility.Error(tip);
72 
73             context.Response.Write(tip);
74         }
75 
76         context.Response.End();
77     }
78 
79     /// <summary>
80     ///  該屬性獲得一個布林值,指示另一個請求是否可以使用該HTTP處理程式的例項。
81     /// <para>如果設定為true,能提高效能,但要注意執行緒之間安全性問題。如果設定為false,則執行緒是安全的</para>
82     /// </summary>
83     public bool IsReusable
84     {
85         get
86         {
87             return false;
88         }
89     }
90 }
系列目錄     【已更新最新開發文章,點選檢視詳細