微信小程序获取用户手机号
微信小程序获取用户手机号码教程(包含前后端)前言 在开发微信小程序时,获取用户手机号码是常见的需求之一。本教程将为你详细 - 掘金
一、前端实现获取用户手机号码
在微信小程序中,可以通过调用 wx.login() 获取用户的登录凭证 code,然后将 code 发送给后端服务器,由后端通过微信提供的接口获取用户的手机号码。具体步骤如下:
1.前端获取用户登录凭证 code
在前端页面的逻辑层中,调用 wx.login() 方法获取用户的登录凭证 code,并将其发送给后端服务器
// 前端页面的逻辑层
wx.login({
success: (res) => {
if (res.code) {
// 获取到用户登录凭证 code
const code = res.code;
// 将 code 发送给后端服务器
wx.request({
url: 'https://your-backend-server.com/getPhoneNumber',
data: { code: code },
method: 'POST',
success: (res) => {
console.log(res.data);
},
fail: (err) => {
console.error('请求后端接口失败', err);
},
});
} else {
console.error('获取用户登录凭证失败', res.errMsg);
}
},
fail: (err) => {
console.error('调用 wx.login 失败', err);
},
});
2.后端解析用户登录凭证获取手机号码
在后端服务器中,通过微信提供的接口解析用户的登录凭证 code,获取用户的手机号码。 需要注意的是,后端需要与微信进行交互,因此需要使用相应的微信开放接口。
这里以 Node.js 和 Express 为例,演示后端如何实现解析用户登录凭证并获取手机号码的功能。
// 后端服务器使用 Node.js 和 Express 实现
const express = require('express');
const axios = require('axios');
const app = express();
const appId = 'your-app-id'; // 微信小程序的 AppID
const appSecret = 'your-app-secret'; // 微信小程序的 AppSecret
app.use(express.json());
app.post('/getPhoneNumber', async (req, res) => {
const { code } = req.body;
if (!code) {
return res.status(400).json({ error: '缺少用户登录凭证 code' });
}
try {
// 向微信服务器发送请求,获取 session_key 和 openid
const response = await axios.get('https://api.weixin.qq.com/sns/jscode2session', {
params: {
appid: appId,
secret: appSecret,
js_code: code,
grant_type: 'authorization_code',
},
});
const { session_key, openid } = response.data;
// 这里可以根据需要存储 session_key 和 openid 到数据库
// 此处省略解密手机号码的步骤,具体解密方法请参考微信文档
// 返回手机号码等相关信息给前端
res.json({ phoneNumber: '用户手机号码' });
} catch (error) {
console.error('请求微信接口失败', error);
res.status(500).json({ error: '服务器内部错误' });
}
});
const port = 3000;
app.listen(port, () => {
console.log(`服务器运行在 http://localhost:${port}`);
});
二、注意事项
在使用微信提供的接口前,需要在微信公众平台申请开发者账号并创建小程序,获取 AppID 和 AppSecret。
在后端处理用户手机号码时,要遵循相关法律法规,保护用户的隐私和安全,不得将用户手机号码泄露或用于非法用途。
在前端获取用户登录凭证时,要注意处理可能的异常情况,确保代码的稳定性。
(99+ 封私信 / 85 条消息) 微信小程序 获取手机号 JS - 知乎
刚开始开发微信小程序的时候,想着实现手机验证码登入,后来查阅资料得知,发给用户的短信是要自己付费的。后来想想,微信获取用户的手机号一样可以保证手机号码的真实性,因为手机号既然可以绑定微信,那么肯定是被严格核验过的,然后就开始了获取手机号之旅,网上教程有很多,但不知什么原因,都是会少一些内容,有的只有前端代码,没有后端;有的后端代码是PHP,不是我们想要的 Java 或者JavaScript。我抱着开源的思想,给大家分享我获取手机号的办法,希望能帮到大家。
首先我们可以去看一看官方文档,获取手机号大致分为以下四步:
第1步:使用wx.login接口获取code(临时数据)
第2步:使用第一步的code,获取session_key和openid(确认用户唯一的数据)
第3步:使用getPhoneNumber接口,获取iv和encryptedData(获取加密的数据)
第4步:解密返回数据,获取手机号码(解密后的数据)
下面详细讲解:
第一步:使用wx.login接口获取code(临时数据)
官方文档是这么写的:
获取微信用户绑定的手机号,需先调用wx.login接口。
因为需要用户主动触发才能发起获取手机号接口,所以该功能不由 API 来调用,需用 button 组件的点击来触发。
注意:目前该接口针对非个人开发者,且完成了认证的小程序开放(不包含海外主体)。需谨慎使用,若用户举报较多或被发现在不必要场景下使用,微信有权永久回收该小程序的该接口权限。
我们可以提炼出下面几条关键信息:
只能由非个人的小程序才能获取用户手机号。
获取手机号必须由button按钮组件触发,而不能写在onLoad()内自动获取。
需在必要的情况下使用。
第一步获取code的代码和运行截图和第二步一起给,因为这两步必须写在一个方法内,不能单独两个方法,然后在onLoad()调用,因为小程序执行onLoad()内的方法,并不是按照代码先后顺序的(经验之谈)
第二步:使用第一步的code,获取session_key和openid(确认用户唯一的数据)
sessionkey和openid是用户的身份证明,一位用户在使用某一个小程序的时候,sessionkey是唯一的。当然一位用户在使用不同的小程序的时候,sessionkey是不一样的。
官网文档是这样写的:
需要将 button 组件 open-type 的值设置为 getPhoneNumber,当用户点击并同意之后,可以通过 bindgetphonenumber 事件回调获取到微信服务器返回的加密数据, 然后在第三方服务端结合 session_key 以及 app_id 进行解密获取手机号。
我们需要拿来第一步获取到的code,来向服务器换取sessionkey和openid。

具体代码如下:
getLogin: function () {
var that = this;
wx.login({
success: function (res) {
console.log(res);
that.setData({
code: res.code,
})
wx.request({
url: 'https://api.weixin.qq.com/sns/jscode2session?appid=wx846bd21xxxxxxxxx&secret=45135d68ebe49de6fe313xxxxxxxxxxx&js_code=' + that.data.code + '&grant_type=authorization_code',
method: 'POST',
header: {
'content-type': 'application/json'
},
success: function (res) {
console.log(res);
that.setData({
sessionkey: res.data.session_key,
openid: res.data.openid,
})
}
})
}
})
},
我们只需要在onLoad()这个生命周期函数内调用这个方法就可以了。
该方法首先调用wx.login()接口,获取到code,保存在页面变量code中,也就是第一步的操作代码。
接着调用wx.request()接口向服务器请求换取sessionkey和openid,再copy本代码的时候,你要替换掉appid和secret,这些可以在微信公众平台获取。
正常情况下,你就可以获取到sessionkey和openid了,当然如果你是个人认证的小程序,那恐怕就报错了。如果还有其他错误,欢迎在文章下方留言。
但是这只是在测试的时候可以获取,在实际运维的时候不能这样写,我们看微信官方文档的说明:
在微信开发者工具中,可以临时开启 开发环境不校验请求域名、TLS版本及HTTPS证书 选项,跳过服务器域名的校验。此时,在微信开发者工具中及手机开启调试模式时,不会进行服务器域名的校验。
在服务器域名配置成功后,建议开发者关闭此选项进行开发,并在各平台下进行测试,以确认服务器域名配置正确。
也就是说
appid和secret需要自己替换。
<%@ page contentType="text/html; charset=utf-8" language="java" import="java.sql.*" errorPage="" %>
<%@ page language="java" import="java.net.*,java.io.*"%>
<%!
public static String GetURLstr(String strUrl)
{
InputStream in = null;
OutputStream out = null;
String strdata = "";
try
{
URL url = new URL(strUrl);
in = url.openStream();
out = System.out;
byte[] buffer = new byte[4096];
int bytes_read;
while ((bytes_read = in.read(buffer)) != -1)
{
String reads = new String(buffer, 0, bytes_read, "UTF-8");
strdata = strdata + reads;
}
in.close();
out.close();
return strdata;
}
catch (Exception e)
{
System.err.println(e);
System.err.println("Usage: java GetURL <URL> [<filename>]");
return strdata;
}
}
%>
<%
request.setCharacterEncoding("UTF-8");
String str_code = "";
str_code = request.getParameter("code");
String str_token = "";
str_token = str_token + "https://api.weixin.qq.com/sns/jscode2session";
str_token = str_token + "?appid=wx846bd21xxxxxxxxx&secret=45135d68ebe49de6fe313xxxxxxxxxxx";
str_token = str_token + "&js_code=" + str_code ;
str_token = str_token + "&grant_type=authorization_code";
String neirong_token = "";
neirong_token = GetURLstr(str_token);
out.print(neirong_token);
%>
这个jsp文件需要放在Tomcat安装目录的webapp,用来被微信小程序前台来请求数据。
同时,我们微信小程序前台代码也要稍加修改。改为向jsp文件获取,传上去一个参数code。
getLogin: function () {
var that = this;
wx.login({
success: function (res) {
console.log(res);
that.setData({
code: res.code,
})
wx.request({
url: 'https://127.0.0.1:8080/test/getOpenId.jsp?code=' + that.data.code,
method: 'POST',
header: {
'content-type': 'application/json'
},
success: function (res) {
console.log(res);
that.setData({
sessionkey: res.data.session_key,
openid: res.data.openid,
})
}
})
}
})
}
效果同下图所示:

第三步:使用getPhoneNumber接口,获取iv和encryptedData(获取加密的数据)
我们还是先来看官网文档怎么写的:
需要将 button 组件 open-type 的值设置为 getPhoneNumber,当用户点击并同意之后,可以通过 bindgetphonenumber 事件回调获取到微信服务器返回的加密数据, 然后在第三方服务端结合 session_key 以及 app_id 进行解密获取手机号。
然后就是官网文档的demo:
//WXML
<button open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber"></button>
//JS
Page({
getPhoneNumber (e) {
console.log(e.detail.errMsg)
console.log(e.detail.iv)
console.log(e.detail.encryptedData)
}
})
我们可以从中看出:获取手机号必须由button按钮组件触发,而不能写在onLoad()内自动获取。
也就是说,这一步不需要我们进行什么操作,只要在WXML定义一个按钮,加上open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber"属性,然后在JS文件中写一个getPhoneNumber方法,该方法有一个参数e,我们可以从这个e中获取iv和encryptedData,这个encryptedData就是加密的数据,其中包括我们需要的电话号码。
那么,接下来就需要我们解密了。
第四步:解密返回数据,获取手机号码(解密后的数据)
我们还是先来看下官方文档:
微信会对这些开放数据做签名和加密处理。开发者后台拿到开放数据后可以对数据进行校验签名和解密,来保证数据不被篡改。
接口如果涉及敏感数据(如wx.getUserInfo当中的 openId 和 unionId),接口的明文内容将不包含这些敏感数据。开发者如需要获取敏感数据,需要对接口返回的加密数据(encryptedData) 进行对称解密。 解密算法如下:
对称解密使用的算法为 AES-128-CBC,数据采用PKCS#7填充。
对称解密的目标密文为 Base64_Decode(encryptedData)。
对称解密秘钥 aeskey = Base64_Decode(session_key), aeskey 是16字节。
对称解密算法初始向量 为Base64_Decode(iv),其中iv由数据接口返回。
微信官方提供了多种编程语言的示例代码。每种语言类型的接口名字均一致。调用方式可以参照示例。
我们可以看出什么内容?关键的信息如下:
我们获取到了sessionkey和openid,要把sessionkey和openid用来解密第三步的加密数据。
我们需要用到某个高深的算法。
官方提供的解密算法没有Java和JavaScript版。
我使用了JavaScript版,改解密数据的模板结构如下,我会在下面把所有的代码提供给大家。

这个解密算法,会把第二步获取的sessionkey和openid,第三步获取的 iv和encryptedData,解密成真正的手机号码。
我们先来看获取手机号的页面的代码:
var WXBizDataCrypt = require('../../utils/RdWXBizDataCrypt.js');
var AppId = 'wx846bd21xxxxxxxxx'
var AppSecret = '45135d68ebe49de6fe313xxxxxxxxxxx'
getPhoneNumber(e) {
var that = this;
console.log(e.detail.errMsg)
console.log(e.detail.iv)
console.log(e.detail.encryptedData)
var pc = new WXBizDataCrypt(AppId, this.data.sessionkey)
wx.getUserInfo({
success: function (res) {
var data = pc.decryptData(e.detail.encryptedData, e.detail.iv)
console.log('解密后 data: ', data)
console.log('手机号码: ', data.phoneNumber)
that.setData({
tel: data.phoneNumber,
})
}
})
},
appid和secret需要自己替换。
我们先来看运行效果:

点击允许之后,开发工具的调试区域会打印如下信息:

这样就成功获取到了手机号码。
接下来是该JavaScript解密算法的部分代码,因为代码太长了,放文章里面不太合适,我会单独上传到CSDN下载模块,拿来即用即可,大家也可以在下面评论区找我要文件,笔者每天都登CSDN,谢谢大家的理解和配合。
SHA1.js
(function(){
var C = (typeof window === 'undefined') ? require('./Crypto').Crypto : window.Crypto;
// Shortcuts
var util = C.util,
charenc = C.charenc,
UTF8 = charenc.UTF8,
Binary = charenc.Binary;
// Public API
var SHA1 = C.SHA1 = function (message, options) {
var digestbytes = util.wordsToBytes(SHA1._sha1(message));
return options && options.asBytes ? digestbytes :
options && options.asString ? Binary.bytesToString(digestbytes) :
util.bytesToHex(digestbytes);
};
// The core
SHA1._sha1 = function (message) {
// Convert to byte array
if (message.constructor == String) message = UTF8.stringToBytes(message);
/* else, assume byte array already */
var m = util.bytesToWords(message),
l = message.length * 8,
w = [],
H0 = 1732584193,
H1 = -271733879,
H2 = -1732584194,
H3 = 271733878,
H4 = -1009589776;
// Padding
m[l >> 5] |= 0x80 << (24 - l % 32);
m[((l + 64 >>> 9) << 4) + 15] = l;
for (var i = 0; i < m.length; i += 16) {
var a = H0,
b = H1,
c = H2,
d = H3,
e = H4;
for (var j = 0; j < 80; j++) {
if (j < 16) w[j] = m[i + j];
else {
var n = w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16];
w[j] = (n << 1) | (n >>> 31);
}
var t = ((H0 << 5) | (H0 >>> 27)) + H4 + (w[j] >>> 0) + (
j < 20 ? (H1 & H2 | ~H1 & H3) + 1518500249 :
j < 40 ? (H1 ^ H2 ^ H3) + 1859775393 :
j < 60 ? (H1 & H2 | H1 & H3 | H2 & H3) - 1894007588 :
(H1 ^ H2 ^ H3) - 899497514);
H4 = H3;
H3 = H2;
H2 = (H1 << 30) | (H1 >>> 2);
H1 = H0;
H0 = t;
}
H0 += a;
H1 += b;
H2 += c;
H3 += d;
H4 += e;
}
return [H0, H1, H2, H3, H4];
};
// Package private blocksize
SHA1._blocksize = 16;
SHA1._digestsize = 20;
})();
Crypto.js
if (typeof Crypto == "undefined" || ! Crypto.util)
{
(function(){
var base64map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
// Global Crypto object
// with browser window or with node module
var Crypto = (typeof window === 'undefined') ? exports.Crypto = {} : window.Crypto = {};
// Crypto utilities
var util = Crypto.util = {
// Bit-wise rotate left
rotl: function (n, b) {
return (n << b) | (n >>> (32 - b));
},
// Bit-wise rotate right
rotr: function (n, b) {
return (n << (32 - b)) | (n >>> b);
},
// Swap big-endian to little-endian and vice versa
endian: function (n) {
// If number given, swap endian
if (n.constructor == Number) {
return util.rotl(n, 8) & 0x00FF00FF |
util.rotl(n, 24) & 0xFF00FF00;
}
// Else, assume array and swap all items
for (var i = 0; i < n.length; i++)
n[i] = util.endian(n[i]);
return n;
},
// Generate an array of any length of random bytes
randomBytes: function (n) {
for (var bytes = []; n > 0; n--)
bytes.push(Math.floor(Math.random() * 256));
return bytes;
},
// Convert a byte array to big-endian 32-bit words
bytesToWords: function (bytes) {
for (var words = [], i = 0, b = 0; i < bytes.length; i++, b += 8)
words[b >>> 5] |= (bytes[i] & 0xFF) << (24 - b % 32);
return words;
},
// Convert big-endian 32-bit words to a byte array
wordsToBytes: function (words) {
for (var bytes = [], b = 0; b < words.length * 32; b += 8)
bytes.push((words[b >>> 5] >>> (24 - b % 32)) & 0xFF);
return bytes;
},
// Convert a byte array to a hex string
bytesToHex: function (bytes) {
for (var hex = [], i = 0; i < bytes.length; i++) {
hex.push((bytes[i] >>> 4).toString(16));
hex.push((bytes[i] & 0xF).toString(16));
}
return hex.join("");
},
// Convert a hex string to a byte array
hexToBytes: function (hex) {
for (var bytes = [], c = 0; c < hex.length; c += 2)
bytes.push(parseInt(hex.substr(c, 2), 16));
return bytes;
},
// Convert a byte array to a base-64 string
bytesToBase64: function (bytes) {
// Use browser-native function if it exists
if (typeof btoa == "function") return btoa(Binary.bytesToString(bytes));
for(var base64 = [], i = 0; i < bytes.length; i += 3) {
var triplet = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2];
for (var j = 0; j < 4; j++) {
if (i * 8 + j * 6 <= bytes.length * 8)
base64.push(base64map.charAt((triplet >>> 6 * (3 - j)) & 0x3F));
else base64.push("=");
}
}
return base64.join("");
},
// Convert a base-64 string to a byte array
base64ToBytes: function (base64) {
// Use browser-native function if it exists
if (typeof atob == "function") return Binary.stringToBytes(atob(base64));
// Remove non-base-64 characters
base64 = base64.replace(/[^A-Z0-9+\/]/ig, "");
for (var bytes = [], i = 0, imod4 = 0; i < base64.length; imod4 = ++i % 4) {
if (imod4 == 0) continue;
bytes.push(((base64map.indexOf(base64.charAt(i - 1)) & (Math.pow(2, -2 * imod4 + 8) - 1)) << (imod4 * 2)) |
(base64map.indexOf(base64.charAt(i)) >>> (6 - imod4 * 2)));
}
return bytes;
}
};
// Crypto character encodings
var charenc = Crypto.charenc = {};
// UTF-8 encoding
var UTF8 = charenc.UTF8 = {
// Convert a string to a byte array
stringToBytes: function (str) {
return Binary.stringToBytes(unescape(encodeURIComponent(str)));
},
// Convert a byte array to a string
bytesToString: function (bytes) {
return decodeURIComponent(escape(Binary.bytesToString(bytes)));
}
};
// Binary encoding
var Binary = charenc.Binary = {
// Convert a string to a byte array
stringToBytes: function (str) {
for (var bytes = [], i = 0; i < str.length; i++)
bytes.push(str.charCodeAt(i) & 0xFF);
return bytes;
},
// Convert a byte array to a string
bytesToString: function (bytes) {
for (var str = [], i = 0; i < bytes.length; i++)
str.push(String.fromCharCode(bytes[i]));
return str.join("");
}
};
})();
}
CryptoMath.js
(function(){
var C = (typeof window === 'undefined') ? require('./Crypto').Crypto : window.Crypto;
// Shortcut
var util = C.util;
// Convert n to unsigned 32-bit integer
util.u32 = function (n) {
return n >>> 0;
};
// Unsigned 32-bit addition
util.add = function () {
var result = this.u32(arguments[0]);
for (var i = 1; i < arguments.length; i++)
result = this.u32(result + this.u32(arguments[i]));
return result;
};
// Unsigned 32-bit multiplication
util.mult = function (m, n) {
return this.add((n & 0xFFFF0000) * m,
(n & 0x0000FFFF) * m);
};
// Unsigned 32-bit greater than (>) comparison
util.gt = function (m, n) {
return this.u32(m) > this.u32(n);
};
// Unsigned 32-bit less than (<) comparison
util.lt = function (m, n) {
return this.u32(m) < this.u32(n);
};
})();
官方提供的python解密代码:
https://res.wx.qq.com/wxdoc/dist/assets/media/aes-sample.eae1f364.zip
import base64
import json
from Crypto.Cipher import AES
class WXBizDataCrypt:
def __init__(self, appId, sessionKey):
self.appId = appId
self.sessionKey = sessionKey
def decrypt(self, encryptedData, iv):
# base64 decode
sessionKey = base64.b64decode(self.sessionKey)
encryptedData = base64.b64decode(encryptedData)
iv = base64.b64decode(iv)
cipher = AES.new(sessionKey, AES.MODE_CBC, iv)
decrypted = json.loads(self._unpad(cipher.decrypt(encryptedData)))
if decrypted['watermark']['appid'] != self.appId:
raise Exception('Invalid Buffer')
return decrypted
def _unpad(self, s):
return s[:-ord(s[len(s)-1:])]
使用:
from WXBizDataCrypt import WXBizDataCrypt
import base64
def main():
appId = 'wx4f4bc4dec97d474b'
sessionKey = base64.b64decode('d2b62a017badd2155473adb9a2d2b262aec798e3b0108ec74c9a1db23a65beeb')
encryptedData = 'I+B0/24OtVh0UnYkgJr3eC7S7LfdCTrGshlsTwcp1EH4PyFRNYogkyZ1ftjfrvjwrWCJ9y65B2LEPt34Med9LhbjU6YoqCsC3NCKMIoOu/TmbrSiIdM7tOK31OJ4xONfoghUqhCmOpcaKR2kKFWXQJfBlQOAlw/py5vEvR38qFbBHkLRju6XrNFriXuPxflmkCorfVmIElMWDFjUD1eD4A=='
iv = 'r25X1WFu/7jFZtPr3id49Q=='
pc = WXBizDataCrypt(appId, sessionKey)
print(pc.decrypt(encryptedData, iv))
if __name__ == '__main__':
main()
用AI生成的JAVA:
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
import org.json.JSONObject;
import java.nio.charset.StandardCharsets;
public class WXBizDataCrypt {
private String appId;
private String sessionKey;
public WXBizDataCrypt(String appId, String sessionKey) {
this.appId = appId;
this.sessionKey = sessionKey;
}
public JSONObject decrypt(String encryptedData, String iv) throws Exception {
// base64 decode
byte[] sessionKeyBytes = Base64.getDecoder().decode(sessionKey);
byte[] encryptedDataBytes = Base64.getDecoder().decode(encryptedData);
byte[] ivBytes = Base64.getDecoder().decode(iv);
SecretKeySpec keySpec = new SecretKeySpec(sessionKeyBytes, "AES");
IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
byte[] decryptedBytes = cipher.doFinal(encryptedDataBytes);
String decryptedText = new String(decryptedBytes, StandardCharsets.UTF_8);
JSONObject decrypted = new JSONObject(decryptedText);
JSONObject watermark = decrypted.getJSONObject("watermark");
if (!watermark.getString("appid").equals(appId)) {
throw new Exception("Invalid Buffer");
}
return decrypted;
}
}
使用
public class Main {
public static void main(String[] args) {
try {
String appId = "your_app_id";
String sessionKey = "your_session_key";
String encryptedData = "encrypted_data_from_wechat";
String iv = "iv_from_wechat";
WXBizDataCrypt crypt = new WXBizDataCrypt(appId, sessionKey);
JSONObject result = crypt.decrypt(encryptedData, iv);
System.out.println(result.toString(4)); // 美化输出
} catch (Exception e) {
e.printStackTrace();
}
}
}
<dependencies>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20231013</version>
</dependency>
</dependencies>
主要转换说明:
-
Base64解码:使用Java 8+的
Base64.getDecoder().decode()替代Python的base64.b64decode() -
AES解密:使用
javax.crypto.Cipher进行AES/CBC/PKCS5Padding解密 -
JSON处理:使用
org.json.JSONObject替代Python的json.loads() -
字符编码:明确使用UTF-8编码处理字符串
-
异常处理:Java需要显式声明异常抛出
这个Java版本的功能与原始Python代码完全一致,能够正确解密微信小程序的加密数据。
========================================
上面是AI说的,我没测试过.
浙公网安备 33010602011771号