第三方庫_網易雲音樂_NetEaseCloudMusicApi


NetEaseCloudMusicApi

項目源地址:

  https://github.com/JabinGP/NetEaseCloudMusicApi

小程序網易雲音樂api模塊

之前我們已經開發過一款小程序適用的qq音樂api庫   https://github.com/FisherWY/QQMusicPlugin

這次開發網易雲音樂api庫的原因是qq音樂api庫在小程序中iOS環境下無法使用小程序提供的背景音頻播放器播放的問題

網易雲的加密算法真的比其他幾家api復雜太多了!!!!完爆QQ和酷狗

依賴

本api庫參考了Github上面開源的node庫,因為我們只想要查找音樂和播放音樂這兩個功能
雖然Github那個庫很方便,但是我們不想為了兩個接口特意去跑一個node.js服務。Github上的庫

  1. big-integer.js
    這里注意,不要使用最新版的,最新版的庫再模擬器上運行沒有問題,但是在真機調試的上傳包階段會報錯說無法識別big-integer.js
    最后在我的嘗試下,選用了一個老版本的庫解決了這個問題。
  2. crypto.js
    這個庫是用來aes加密的,在node上面有一個原生的crypto,但是在小程序里我們沒有,所以我照着Github上的源碼一點一點用這個庫翻譯過來的
    還有Buffer在小程序里也沒有,我使用這個庫的方法代替了。

獲取api的原理

網上很多帖子講的很清楚了,這里推薦幾篇文章,我只做一個簡單的總結,方便大家理解這個庫。
網易雲的加密算法大概使用了兩個:

  1. AES加密+BASE64編碼
  2. RSA加密

加密大致流程:

  1. api請求信息先被轉成json字符串格式,然后再使用一個固定的密鑰aes+base64編碼加密,得到了第一個加密結果a
  2. 客戶端從abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/隨機生成一個新的16位密鑰,然后用這個密鑰去加密加密結果a,得到加密結果b
    3.這樣我們的數據就被雙重加密了,但是我們要發給服務器去查詢對應的數據,服務器知道第一個固定的密鑰是多少,可以解開第一個加密結果,但是服務器可不知道我們第二次加密用的是什么,所以服務器還需要得到我們的第二個生成的隨機加密密鑰。
  3. 第二個隨機加密密鑰要是直接發給服務器好像就不太安全了,所以客戶端對第二個隨機加密密鑰也進行了加密,使用的就是RSA加密,加密后得到的數據我們稱為c
  4. bc發送給服務器,服務器就會返回給我們對應的結果了。

加密核心代碼

這段代碼傳入對象后可以直接加密成符合網易雲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/NetEaseCloudMusicApi
下載完成后,這個庫應該是可以直接導入微信小程序開發工具運行的,但是有幾個注意事項

  1. 這個庫是用TypeScript寫的,但是最后編譯成了JS運行,但是編譯后JS代碼可讀性很差,所以我保留了TypeScript源文件,就在NetEaseCloudMusicApi/ts_src里面,應用庫的時候不需要使用到
  2. 關閉小程序開發工具的詳情頁的ES6轉ES5,可以使用await處理異步請求(因為庫是用Promise寫的,起碼要能用Promise,實例代碼使用的是await/async
  3. await關鍵字只能在async修飾過的函數體內部使用,不懂的可以查一下await和async的用法。
  4. NetEaseCloudMusicApi/Libary文件夾里面包含了項目依賴的js文件,應用的時候最好整個NetEaseCloudMusicApi文件夾復制到項目里面使用。
  5. 測試的時候可以勾選不校驗合法域名。
    1

開始使用之前的准備(源文件目錄結構/如何導入)

  1. 找到NetEaseCloudMusicApi這個文件夾,里面應該包括Libary、src、ts_src三個文件夾,
    1. Libary是我引用的開源庫
    2. ts_src中是TypeScript源文件(源文件可刪除)
    3. src是ts_src編譯后產生的JavaScript文件夾,不考慮讀ts源文件的話,可以把ts_src刪了,但17.4 KB 的大小對應用包體積沒有什么影響吧,留也行。
  2. 在要使用到的庫中如下引用
const {MusicManager} = require("../../NetEaseCloudMusicApi/src/MusicManager");

    注意要用花括號吧MusicManager括起來,這一句可以需要變化的地方只有

../../NetEaseCloudMusicApi/src/MusicManager中的../../

后面的路徑都代表了NetEaseCloudMusicApi文件夾和NetEaseCloudMusicApi里面文件的路徑,因為我的庫就是這樣的結構,所以不需要改變

../../就要根據你項目中實際結構來改變了。

MusicManager

該類有以下方法:該類提供了所有獲取其他對象的方法,可以通過該類獲取其他需要的對象而不是new

  • 搜索歌曲: getMusicSearchHelper()
    • 需要參數:{keyword:"搜索歌曲關鍵詞",limit:數字}
    • 返回:MusicSearchHelper搜索器
    • 例如: let musicSearchHelper = MusicManager.getMusicSearchHelper({ keyword: "李志", limit: 10 });
  • 獲取歌曲url: getMusicUrlHelper()
    • 需要參數:musicId(數字類型的歌曲id)
      返回:MusicUrlHelperUrl獲取器
  • 搜索用戶: getUserSearchHelper()
    • 需要參數:{userName:"搜索用戶的用戶名關鍵詞",limit:數字}
      返回:UserSearchHelper用戶查詢器
  • 獲取用戶歌單: getUserListHelper()
    • 需要參數:userId(數字類型的用戶id值)
      返回:UserListHelper用戶列表查詢器
  • 獲取我喜歡的歌單: getUserListDetailHelper()
    • 需要參數:listId(數字類型的列表id)
      返回:UserListDetailHelper用戶列表詳情信息獲取器

MusicSearchHelper

用於搜索音樂
可用方法:

  • getSearchResult()---獲取數據(默認第一頁)
  • nextPage()--- 下一頁
  • previousPage()---上一頁
  • getCurrentPage()---查看當前頁數的
    執行完切換頁數后需要再次調用getSearchResult方法查看新的查詢結果。

MusicUrlHelper

用於將搜索音樂結果中的id轉換為url播放鏈接
可用方法:

  • getUrlResult() ---獲取url播放鏈接

UserSearchHelper

用於根據用戶名關鍵字搜索用戶
可用方法:

  • getSearchResult()---獲取搜索結果

UserListHelper

用於獲取用戶id后根據id獲取用戶歌單信息
可用方法:

  • getAllLists()---獲取用戶所有歌單
  • getILikeList()---獲取用戶的我喜歡歌單

UserListDetailHelper

用於獲取歌單id后獲取歌單內歌曲列表
可用方法:

  • getDeatil()---獲取歌單內列表

搜索歌曲

  1. 通過MusicManager獲取一個MusicSearchHelper搜索器
  2. MusicSearchHelper的方法:
    • getSearchResult()---獲取數據(默認第一頁)
    • nextPage()--- 下一頁
    • previousPage()---上一頁
    • getCurrentPage()---查看當前頁數的
  3. 執行完切換頁數后需要再次調用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(); 

2

通過搜索歌曲的結果獲取音樂Url

有了搜索結果,我們還需要url才能播放資源

  1. 通過MusicManager獲取一個MusicUrlHelperUrl獲取器
  2. 通過MusicUrlHelpergetUrlResult方法獲取url
  3. 需要注意的是,由於網易雲接口時常返回空回復,所以這里我通過20以內的重復次請求直到有結果就停止,如果20次以后還是沒有結果(據我測試20次以內都請求到結果了),也就是返回一個空的字符串"",需要使用者自己重新調用一次urlHelpergetUrlResult方法(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(); 

3

4.26更新

新增搜索用戶以及用戶歌單獲取接口

搜索用戶

  1. 通過MusicManager獲取一個UserSearchHelper用戶查詢器
  2. 通過UserSearchHelpergetSearchResult()方法獲取搜索結果
async function test(){ // 搜索用戶 let userSearchHelper = MusicManager.getUserSearchHelper({ userName: "JabinGP", limit: 20 }); let users = await userSearchHelper.getSearchResult(); console.log(users); } 

獲取用戶歌單

  1. 通過MusicManager獲取一個UserListHelper用戶查詢器
  2. 通過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更新搜索用戶和獲取用戶歌單以及獲取歌單詳細三個接口。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM