微信小程序無法在前端直接獲取用戶的手機號,只能獲取到aes加密后的手機號信息和一個code。將加密后的手機信息和code傳到我們自己寫的服務就可以解密了。
解密需要兩個步驟:
1.使用code從微信API獲取session key。
直接使用以下參數,對api發起get請求
https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=APPSECRET&js_code=CODE&grant_type=authorization_code
| 屬性 | 描述 |
appid |
微信小程序的appid,從微信小程序平台獲取,每個小程序都不一樣 |
secret |
微信小程序的app secret,從微信小程序平台獲取,每個小程序都不一樣 |
js_code |
小程序前端獲取用戶手機號信息時的code |
grant_type |
固定值 authorization_code |
2.使用session key解密加密的手機信息。
go語言代碼示例
package main
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"encoding/base64"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"github.com/gin-gonic/gin"
)
type Reply struct {
Code int `json:"code"`
Data interface{} `json:"data"`
}
func main() {
gin.SetMode(gin.ReleaseMode)
router := gin.Default() //實例化一個gin
router.POST("/getnum", getNum)
fmt.Println("服務啟動...端口為9300")
router.Run("127.0.0.1:9300") //監聽9300端口
}
func getNum(c *gin.Context) {
var req struct {
EncryptedData string
Iv string
Code string
}
err := c.Bind(&req)
if err != nil {
c.Error(err)
}
url := "https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=" + req.Code + "&grant_type=authorization_code"
resp, err := http.Get(url)
if err != nil {
c.Error(err)
}
defer resp.Body.Close()
s, _ := ioutil.ReadAll(resp.Body)
res := make(map[string]string)
json.Unmarshal(s, &res)
key, _ := base64.StdEncoding.DecodeString(res["session_key"])
iv, _ := base64.StdEncoding.DecodeString(req.Iv)
ciphertext, _ := base64.StdEncoding.DecodeString(req.EncryptedData)
plaintext := make([]byte, len(ciphertext))
block, err := aes.NewCipher(key)
if err != nil {
panic(err)
}
mode := cipher.NewCBCDecrypter(block, iv)
mode.CryptBlocks(plaintext, ciphertext)
plaintext = PKCS7UnPadding(plaintext)
fmt.Println("return:", string(plaintext))
c.JSON(http.StatusOK, Reply{http.StatusOK, string(plaintext)})
}
// 發送post請求
func post(url, data string) (string, error) {
reader := bytes.NewReader([]byte(data))
request, err := http.NewRequest("POST", url, reader)
if err != nil {
return "", err
}
defer request.Body.Close() //程序在使用完回復后必須關閉回復的主體
request.Header.Set("Content-Type", "application/json;charset=UTF-8")
//必須設定該參數,POST參數才能正常提交,意思是以json串提交數據
client := http.Client{}
resp, err := client.Do(request) //Do 方法發送請求,返回 HTTP 回復
if err != nil {
return "", err
}
respBytes, err := ioutil.ReadAll(resp.Body)
if err != nil {
return "", err
}
return string(respBytes), nil
}
func PKCS7Padding(ciphertext []byte) []byte {
padding := aes.BlockSize - len(ciphertext)%aes.BlockSize
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
return append(ciphertext, padtext...)
}
func PKCS7UnPadding(plantText []byte) []byte {
length := len(plantText)
unpadding := int(plantText[length-1])
return plantText[:(length - unpadding)]
}
