摘要:之前我們已經開發過一款小程序適用的音樂庫,這次開發網易云音樂庫的原因是音樂庫在小程序中環境下無法使用小程序提供的背景音頻播放器播放的問題網易云的加密算法真的比其他幾家復雜太多了。。。
之前我們已經開發過一款小程序適用的qq音樂api庫https://github.com/FisherWY/Q...,這次開發網易云音樂api庫的原因是qq音樂api庫在小程序中iOS環境下無法使用小程序提供的背景音頻播放器播放的問題依賴網易云的加密算法真的比其他幾家api復雜太多了。。。完爆QQ和酷狗
想要直接用的話可以到Github直接取我封裝好的api庫。
Github地址https://github.com/JabinGP/Ne...
本api庫參考了Github上面開源的node庫,因為我們只想要查找音樂和播放音樂這兩個功能,雖然Github那個庫很方便,但是我們不想為了兩個接口特意去跑一個node.js服務。Github上的庫
big-integer.js
這里注意,不要使用最新版的,最新版的庫再模擬器上運行沒有問題,但是在真機調試的上傳包階段會報錯說無法識別big-integer.js,最后在我的嘗試下,選用了一個老版本的庫解決了這個問題。
crypto-js
這個庫是用來aes加密的,在node上面有一個原生的crypto,但是在小程序里我們沒有,所以我照著Github上的源碼一點一點用這個庫翻譯過來的,還有Buffer在小程序里也沒有,我使用這個庫的方法代替了。
獲取api的原理網上很多帖子講的很清楚了,這里推薦幾篇文章,我只做一個簡單的總結,方便大家理解這個庫。
網易云的加密算法大概使用了兩個:
AES加密+BASE64編碼
RSA加密
加密大致流程:
api請求信息先被轉成json字符串格式,然后再使用一個固定的密鑰aes+base64編碼加密,得到了第一個加密結果a。
客戶端從abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/隨機生成一個新的16位密鑰,然后用這個密鑰去加密加密結果a,得到加密結果b。
3.這樣我們的數據就被雙重加密了,但是我們要發給服務器去查詢對應的數據,服務器知道第一個固定的密鑰是多少,可以解開第一個加密結果,但是服務器可不知道我們第二次加密用的是什么,所以服務器還需要得到我們的第二個生成的隨機加密密鑰。
第二個隨機加密密鑰要是直接發給服務器好像就不太安全了,所以客戶端對第二個隨機加密密鑰也進行了加密,使用的就是RSA加密,加密后得到的數據我們稱為c
將b和c發送給服務器,服務器就會返回給我們對應的結果了。
加密核心代碼這段代碼傳入對象后可以直接加密成符合網易云api加密的結果。
// 生成隨機數,size默認16 function createSecretKey(size) { const keys = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" let key = "" for (let i = 0; i < size; i++) { let pos = Math.random() * keys.length pos = Math.floor(pos) key = key + keys.charAt(pos) } return key } // aes加密方法 function aesEncrypt(word, secKey) { let key = CryptoJS.enc.Utf8.parse(secKey); //十六位十六進制數作為密鑰 let iv = CryptoJS.enc.Utf8.parse(aes_mv); //十六位十六進制數作為密鑰偏移量 let srcs = CryptoJS.enc.Utf8.parse(word); let encrypted = CryptoJS.AES.encrypt(srcs, key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }); let res = encrypted.toString(); console.log(res); return res; } // 填充方法 function zfill(str, size) { while (str.length < size) str = "0" + str return str } // rsa加密方法 function rsaEncrypt(text, pubKey, modulus) { const _text = text.split("").reverse().join("") const biText = bigInt(CryptoJS.enc.Utf8.parse(_text).toString(), 16), biEx = bigInt(pubKey, 16), biMod = bigInt(modulus, 16), biRet = biText.modPow(biEx, biMod) return zfill(biRet.toString(16), 256) } // 加密總入口 function Encrypt(obj) { const text = JSON.stringify(obj) const secKey = createSecretKey(16) const encText = aesEncrypt(aesEncrypt(text, nonce), secKey) const encSecKey = rsaEncrypt(secKey, pubKey, modulus) return { params: encText, encSecKey: encSecKey } }封裝好的Api庫
首先到Github下載我的Api庫https://github.com/JabinGP/Ne...
下載完成后,這個庫應該是可以直接導入微信小程序開發工具運行的,但是有幾個注意事項
這個庫是用TypeScript寫的,但是最后編譯成了JS運行,但是編譯后JS代碼可讀性很差,所以我保留了TypeScript源文件,就在NetEaseCloudMusicApi/ts_src里面,應用庫的時候不需要使用到
關閉小程序開發工具的詳情頁的ES6轉ES5,可以使用await處理異步請求(因為庫是用Promise寫的,起碼要能用Promise,實例代碼使用的是await/async)
await關鍵字只能在async修飾過的函數體內部使用,不懂的可以查一下await和async的用法。
NetEaseCloudMusicApi/Libary文件夾里面包含了項目依賴的js文件,應用的時候最好整個NetEaseCloudMusicApi文件夾復制到項目里面使用。
測試的時候可以勾選不校驗合法域名。
開始使用之前的準備找到NetEaseCloudMusicApi這個文件夾,里面應該包括Libary、src、ts_src三個文件夾,Libary是我引用的開源庫,ts_src中是TypeScript源文件,src是ts_src編譯后產生的JavaScript文件夾,也就是說不考慮讀ts源文件的話,可以把ts_src刪了,但是17.4 KB 的大小對應用包體積應該沒有什么影響吧,留著也行。
在要使用到的庫中如下引用
const {MusicManager} = require("../../NetEaseCloudMusicApi/src/MusicManager");
注意要用花括號吧MusicManager括起來,這一句可以需要變化的地方只有
../../NetEaseCloudMusicApi/src/MusicManager中的../../,后面的路徑都代表了NetEaseCloudMusicApi文件夾和NetEaseCloudMusicApi里面文件的路徑,因為我的庫就是這樣的結構,所以不需要改變,../../就要根據你項目中實際結構來改變了。
該類有以下方法:該類提供了所有獲取其他對象的方法,可以通過該類獲取其他需要的對象而不是new
getMusicSearchHelper()
需要參數:{keyword:"搜索歌曲關鍵詞",limit:數字}
返回:MusicSearchHelper搜索器
getMusicUrlHelper()
需要參數:musicId(數字類型的歌曲id)
返回:MusicUrlHelperUrl獲取器
getUserSearchHelper()
需要參數:{userName:"搜索用戶的用戶名關鍵詞",limit:數字}
返回:UserSearchHelper用戶查詢器
getUserListHelper()
需要參數:userId(數字類型的用戶id值)
返回:UserListHelper用戶列表查詢器
getUserListDetailHelper()
需要參數:listId(數字類型的列表id)
返回:UserListDetailHelper用戶列表詳情信息獲取器
用于搜索音樂
可用方法:
getSearchResult()---獲取數據(默認第一頁)
nextPage()--- 下一頁
previousPage()---上一頁
getCurrentPage()---查看當前頁數的
執行完切換頁數后需要再次調用getSearchResult方法查看新的查詢結果。
MusicUrlHelper用于將搜索音樂結果中的id轉換為url播放鏈接
可用方法:
getUrlResult() ---獲取url播放鏈接
UserSearchHelper用于根據用戶名關鍵字搜索用戶
可用方法:
getSearchResult()---獲取搜索結果
UserListHelper用于獲取用戶id后根據id獲取用戶歌單信息
可用方法:
getAllLists()---獲取用戶所有歌單
getILikeList()---獲取用戶的我喜歡歌單
UserListDetailHelper用于獲取歌單id后獲取歌單內歌曲列表
可用方法:
getDeatil()---獲取歌單內列表
搜索歌曲通過MusicManager獲取一個MusicSearchHelper搜索器
MusicSearchHelper的方法:
getSearchResult()---獲取數據(默認第一頁)
nextPage()--- 下一頁
previousPage()---上一頁
getCurrentPage()---查看當前頁數的
執行完切換頁數后需要再次調用getSearchResult方法查看新的查詢結果。
代碼實例
const {MusicManager} = require("../../NetEaseCloudMusicApi/src/MusicManager"); async function test(){ // 搜索歌曲 let musicSearchHelper = MusicManager.getMusicSearchHelper({ keyword: "one more time one more chance", limit: 10 }); console.log(`現在是第${musicSearchHelper.getCurrentPage()}頁`); console.log(await musicSearchHelper.getSearchResult()); musicSearchHelper.nextPage(); console.log(`現在是第${musicSearchHelper.getCurrentPage()}頁`); console.log(await musicSearchHelper.getSearchResult()); musicSearchHelper.previousPage(); console.log(`現在是第${musicSearchHelper.getCurrentPage()}頁`); console.log(await musicSearchHelper.getSearchResult()); console.log(musicSearchHelper); } test();通過搜索歌曲的結果獲取音樂Url
有了搜索結果,我們還需要url才能播放資源
通過MusicManager獲取一個MusicUrlHelperUrl獲取器
通過MusicUrlHelper的getUrlResult方法獲取url
需要注意的是,由于網易云接口時常返回空回復,所以這里我通過20以內的重復次請求直到有結果就停止,如果20次以后還是沒有結果(據我測試20次以內都請求到結果了),也就是返回一個空的字符串"",需要使用者自己重新調用一次urlHelper的getUrlResult方法(2019.04.27)現在不會返回空值了,返回空值發現問題出在使用微信請求時自作聰明將json轉成了a=xxxx&b=xxx的格式,導致微信不能正常轉換請求數據,現在每次請求都能獲取結果。
代碼實例
const {MusicManager} = require("../../NetEaseCloudMusicApi/src/MusicManager"); async function test(){ // 搜索歌曲 let musicSearchHelper = MusicManager.getMusicSearchHelper({ keyword: "one more time one more chance", limit: 10 }); console.log(`現在是第${musicSearchHelper.getCurrentPage()}頁`); console.log(await musicSearchHelper.getSearchResult()); musicSearchHelper.nextPage(); console.log(`現在是第${musicSearchHelper.getCurrentPage()}頁`); console.log(await musicSearchHelper.getSearchResult()); musicSearchHelper.previousPage(); console.log(`現在是第${musicSearchHelper.getCurrentPage()}頁`); console.log(await musicSearchHelper.getSearchResult()); console.log(musicSearchHelper); // 獲取歌曲url let songs = await musicSearchHelper.getSearchResult(); let musicId = songs[0].id; let musicUrlHelper = MusicManager.getMusicUrlHelper(musicId); console.log(`歌曲的ID是:${musicId}`); let url = await musicUrlHelper.getUrlResult(); console.log(`歌曲的url鏈接是:${url}`); } test();4.26更新
新增搜索用戶以及用戶歌單獲取接口
搜索用戶通過MusicManager獲取一個UserSearchHelper用戶查詢器
通過UserSearchHelper的getSearchResult()方法獲取搜索結果
async function test(){ // 搜索用戶 let userSearchHelper = MusicManager.getUserSearchHelper({ userName: "JabinGP", limit: 20 }); let users = await userSearchHelper.getSearchResult(); console.log(users); }獲取用戶歌單
通過MusicManager獲取一個UserListHelper用戶查詢器
通過UserListHelper的
getILikeList() ---獲取我喜歡歌單,返回一個列表對象
getAllLists() ---獲取所有歌單,返回一個列表對象的數組
async function test(){ // 搜索用戶 let userSearchHelper = MusicManager.getUserSearchHelper({ userName: "JabinGP", limit: 20 }); let users = await userSearchHelper.getSearchResult(); console.log(users); // 獲取我喜歡歌單 let userListHelper = MusicManager.getUserListHelper(users[0].userId); let iLikeList = await userListHelper.getILikeList() console.log(iLikeList); }通過歌單里的Id獲取歌曲url
與前面一致,不再贅述
完整實例完整實例代碼在項目page下的index.js中,運行項目就會自動執行輸出結果。
async function test(){ // 搜索歌曲 let musicSearchHelper = MusicManager.getMusicSearchHelper({ keyword: "one more time one more chance", limit: 10 }); console.log(`現在是第${musicSearchHelper.getCurrentPage()}頁`); console.log(await musicSearchHelper.getSearchResult()); musicSearchHelper.nextPage(); console.log(`現在是第${musicSearchHelper.getCurrentPage()}頁`); console.log(await musicSearchHelper.getSearchResult()); musicSearchHelper.previousPage(); console.log(`現在是第${musicSearchHelper.getCurrentPage()}頁`); console.log(await musicSearchHelper.getSearchResult()); console.log(musicSearchHelper); // 獲取歌曲url let songs = await musicSearchHelper.getSearchResult(); let musicId = songs[0].id; let musicUrlHelper = MusicManager.getMusicUrlHelper(musicId); console.log(`歌曲的ID是:${musicId}`); let url = await musicUrlHelper.getUrlResult(); console.log(`歌曲的url鏈接是:${url}`); // 搜索用戶 let userSearchHelper = MusicManager.getUserSearchHelper({ userName: "JabinGP", limit: 20 }); let users = await userSearchHelper.getSearchResult(); console.log(users); // 獲取用戶歌單 let userListHelper = MusicManager.getUserListHelper(users[0].userId); let iLikeList = await userListHelper.getILikeList() console.log(iLikeList); // 獲取我喜歡歌單 let userListDeatilHelper = MusicManager.getUserListDetailHelper(iLikeList.id); let listDetail = await userListDeatilHelper.getDeatil(); console.log(listDetail); let timer=0; for(let song of listDetail.tracks){ musicUrlHelper.musicId=song.id; console.log(`歌曲的ID是:${musicUrlHelper.musicId}`); let url2 = await musicUrlHelper.getUrlResult(); console.log(`歌曲的url鏈接是:${url2}`); if(timer++>20)break; } } test();結尾
2019 4.25目前就只有這兩個接口,因為我們項目就只需要這兩個接口,如果有需要更多接口的,可以在下方評論,以上示例代碼都在Github項目上的index.js中,也就是你把文件導入微信開發者工具后,取消勾選一下詳情的ES6轉ES5以及取消勾選合法域名檢驗,就可以在控制臺看到以上示例代碼的輸出了2019 4.26更新搜索用戶和獲取用戶歌單以及獲取歌單詳細三個接口。
如果對你有幫助,點個Star吧~
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/104093.html
摘要:下一步準備使用網易云代替音樂。已經開發新的網易云代替音樂了,需要的可以看看這篇文章為微信小程序開發的網易云音樂庫 項目要做一個可以為日記添加音樂的小程序,所以要用到音樂api,參考了一些文章后我們封裝了一個qq音樂api庫(完成了動態token獲取,音樂搜索,音樂專輯圖片,音樂名稱,歌手名稱,播放),有需要的可以到Github自提。 小程序qq音樂api庫Gihub地址https://...
摘要:傳統的網頁編程采用的三劍客來實現,在微信小程序中同樣有三劍客。觀察者模式不難實現,重點是如何在微信小程序中搭配其特有的生命周期來使用。交互事件傳統的事件傳遞類型有冒泡型與捕獲型,微信小程序中自然也有。 本文由作者鄒永勝授權網易云社區發布。 簡介為了更好的展示我們即時通訊SDK強悍的能力,網易云信IM SDK微信小程序DEMO的開發就提上了日程。用產品的話說就是: 云信 IM 小程序 S...
摘要:狗蛋狗蛋是基于微信小程序開發的一款。請在微信開發設置中加入合法域名或者在開發設置中勾選不校驗合法域名業務域名版本以及證書。感謝與支持狗蛋豆瓣音樂項目介紹狗蛋是基于微信小程序進行開發,能同時運行在環境下。 狗蛋TV showImg(https://segmentfault.com/img/bVbazwL); 狗蛋TV是基于微信小程序開發的一款App。gordanLee每天都會推薦一首歌、...
閱讀 2222·2021-09-24 10:31
閱讀 3874·2021-09-22 15:16
閱讀 3394·2021-09-22 10:02
閱讀 1010·2021-09-22 10:02
閱讀 1821·2021-09-08 09:36
閱讀 1973·2019-08-30 14:18
閱讀 608·2019-08-30 10:51
閱讀 1862·2019-08-29 11:08