阿里大於(alidayu)升級爲阿里雲短信服務(dysms)Golang新版SDK

最近需要接入 阿里雲 短信服務 用來發送驗證碼。由於官方並未提供Golang相應SDK,自己就嘗試實現了發送短信的接口,這裏分享給大家。

項目地址:https://github.com/panshiqu/dysms

使用示例:

    if err := dysms.SendSms(accessKeyID, accessSecret, phoneNumbers, signName, templateParam, templateCode); err != nil {
        log.Println("dysms.SendSms", err)
    }

其實就是翻譯了 HTTP協議及簽名 這篇官方API文檔中的示例代碼,Java -> Go

若你也想實現該接口(重複造輪子),我建議你把所有字段值暫設爲官方示例給出的值,譬如時間戳設爲”2017-07-12T02:42:19Z“,這樣你就可以每步都與官方文檔中的打印結果作對比,進而發現自己代碼中的問題。

列舉我遇見的錯誤碼:

InvalidTimeStamp.Expired
時間戳錯誤,發出請求的時間和服務器接收的時間不在15分鐘內。經常出現該錯誤的原因是時區造成的,目前網關使用的時區是GMT等同於UTC。

SignatureNonceUsed
唯一隨機數重複,SignatureNonce是唯一隨機數,用於防止網絡重放攻擊。不同請求間要使用不同的隨機數值。關於網絡重放攻擊,我們可以構造一次合法的請求,打印並記錄URL,因爲Timestamp容忍15分鐘內的誤差,我們就可以在15分鐘內重複訪問該URL進而發送短信。SignatureNonce的存在終結了這種可能,服務器應該會緩存SignatureNonce值至少15分鐘,每次請求到來都會檢查是否存在相同的SignatureNonce值,若存在則請求失敗,返回該錯誤碼。上面實現的接口中用rand.Int63()來產生SignatureNonce值,你可能擔心15分鐘內會產生重複的隨機值,其實大可不必考慮這點,因爲收到該錯誤碼會遞歸調用生成新的隨機值再次請求。

實現該接口大部分時間都在解決一個簡單的錯誤:malformed HTTP status code "HTML"。不要高看這個錯誤,它其實就是字面意思,畸形的,難看的HTTP。之所以會遇到這個錯誤,主要因爲我會打印拼接好的URL,爲了方便我看,在fmt.Sprintf中習慣性加了\n。其實你單去搜索這個錯誤,真是找不到有價值的解釋,因爲很少會有人犯這種錯誤。至於我是如何發現錯在哪裏的,這裏作簡短說明。先是發現複製打印的URL直接用瀏覽器和CURL都可以請求成功,這時還意識不到錯在哪裏。接着用Wireshark抓包發現跟在URL後面的HTTP/1.1,一個在同一行,一個在下一行,因爲不同點不只有這一處,所以雖然發現,但未能給我啓發。再接着就是在代碼中強行用拼接好的URL與複製打印的URL判斷是否相等,果然不相等,同時打印字符串16進制進行對比,終於發現了那深坑。不到三小時實現接口,但是爲了發現這個錯誤,我那天的剩餘時間全部搭進去啦。

這裏有必要提下兩種不同的API,阿里大於已升級爲阿里雲旗下雲通信品牌,現在應該是買不了阿里大於的短信服務吧,只能買升級後的,我就是這樣。兩者有關係但又不兼容,實在是大坑,起初我就是用老的阿里大於Golang第三方SDK去嘗試發送短信,總是回覆錯誤!

{
    "error_response": {
        "code": 11,
        "msg": "Insufficient isv permissions",
        "sub_code": "isv.permission-api-package-limit",
        "sub_msg": "scope ids is 11022 11600 11863",
        "request_id": "eonzx7q4qjvg"
    }
}

搜索了半天才發現真是風馬牛不相及啊。

老的阿里大於Golang第三方SDK
https://github.com/ltt1987/alidayu
https://github.com/northbright/alidayu

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章