开发这个功能的时候走了很多弯路磨了很多时间,我发一下我自己用的来帮助大家
我的首页内容
index.js
Page({
data: {
//判断小程序的API,回调,参数,组件等是否在当前版本可用。
canIUse: wx.canIUse('button.open-type.getUserInfo'),
isHide: false
},
onLoad: function() {
},
//获取用户code
getcode: function(res){
var that = this;
// 查看是否授权
wx.getSetting({
success: function(res) {
if (res.authSetting['scope.userInfo']) {
wx.getUserInfo({
success: function(res) {
// 用户已经授权过,不需要显示授权页面,所以不需要改变 isHide 的值 根据自己的需求有其他操作再补充 我这里实现的是在用户授权成功后,调用微信的 wx.login 接口,从而获取code
wx.login({
// success: res => {
// 获取到用户的 code 之后:res.code 可以传给后台,再经过解析获取用户的 openid 代码如下
// wx.login({
success: function (res) {
console.log("用户的code:" + res.code);
// if (res.code) { //使用小程序登录接口完成后端用户登录
wx.request({
url: "填写服务器接口一定要HTTPS的可以去natapp买一个" +"/getOpenid",
data: {
code: res.code,
appid: "自己的APPID",
secret: "自己的APPSECRET",
},
method:'POST',
header: {
'content-type': 'application/json' // POST请求
},
success: function (res) {
//把openid保存到缓存里
wx.setStorageSync("openid", res.openid);
wx.setStorageSync("session_key", res.session_key);
}
})
// } else {
// console.log('获取用户登录态失败!' + res.errMsg)
// }
}
});
// }
// });
}
});
} else {
// 用户没有授权
// 改变 isHide 的值,显示授权页面
that.setData({
isHide: true
});
}
}
});
},
//获取用户开发信息
bindGetUserInfo: function(e) {
if (e.detail.userInfo) {
//用户按了允许授权按钮
var that = this;
// 获取到用户的信息了,打印到控制台上看下
console.log("用户的信息如下:");
console.log(e.detail.openid);
console.log(e.detail.userInfo);
//授权成功后,通过改变 isHide 的值,让实现页面显示出来,把授权页面隐藏起来
that.setData({
isHide: false
});
} else {
//用户按了拒绝按钮
wx.showModal({
title: '警告',
content: '您点击了拒绝授权,将无法进入小程序,请授权之后再进入!!!',
showCancel: false,
confirmText: '返回授权',
success: function(res) {
// 用户没有授权成功,不需要改变 isHide 的值
if (res.confirm) {
console.log('用户点击了“返回授权”');
}
}
});
}
},
//获取用户手机号授权按钮
getPhoneNumber: function (e) {
var app = getApp();
wx.request({
url: "填写服务器接口一定要是HTTPS的可以去natapp买一个" +"/postPhoneNumber", //解密手机号码接口
data: {
encryptedData: e.detail.encryptedData,
iv: e.detail.iv
},
method:'POST',
header: {
'content-type': 'application/json' // POST请求
},
success: function (res) {
console.log(res.data.phoneNumber);
wx.setStorageSync("phonenumber", res.data.phoneNumber);
}
})
},
})
后端Java代码
Controller层代码
package com.pyx.wechatapplet2.conntroller.wechat;
import com.alibaba.fastjson.JSON;
import com.pyx.wechatapplet2.entity.user.Openid;
import com.pyx.wechatapplet2.util.AesCbcUtil;
import com.pyx.wechatapplet2.util.JDBCUtil;
import com.pyx.wechatapplet2.util.redis.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.json.JSONObject;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
@RestController
@Slf4j
public class WechatgetPhone {
public String Openid;
public String session_key;
public String getOpenid() {
return Openid;
}
public void setOpenid(String openid) {
Openid = openid;
}
@PostMapping("/getOpenid")
@Transactional(rollbackFor = Exception.class)
public synchronized com.alibaba.fastjson.JSONObject getSessionKeyOropenid(@RequestBody Openid openid ) throws Exception {
System.out.println("Openid code:" + openid.getCode());
CloseableHttpClient httpclient = HttpClients.createDefault();
//发送get请求读取调用微信 https://api.weixin.qq.com/sns/jscode2session 接口获取openid用户唯一标识
HttpGet httpget = new HttpGet("https://api.weixin.qq.com/sns/jscode2session?appid=" + "自己的APPID" + "&secret=" + "自己的appsecret" + "&js_code=" + openid.getCode() + "&grant_type=authorization_code");
CloseableHttpResponse response = httpclient.execute(httpget);
HttpEntity entity = response.getEntity();
com.alibaba.fastjson.JSONObject jsonObject = JSON.parseObject(EntityUtils.toString(entity));
RedisUtil.setStringValue("session_key" , jsonObject.getString("session_key"));
session_key=jsonObject.getString("session_key");
Openid=jsonObject.getString("openid");
System.out.println("Openid:" + Openid);
RedisUtil.setStringValue("openid",jsonObject.getString("openid"));
log.info(jsonObject.toJSONString());
//----------------------------------解密用户信息-----------------------------------------
// String userInfo = null;
// JSONObject userInfoJSON = null;
// Thread.sleep(500);
// try {
// byte[] resultByte = AES.decrypt(Base64.decodeBase64(openid.getEncryptedData()),
// Base64.decodeBase64(jsonObject.getString("session_key")),
// Base64.decodeBase64(openid.getIv()));
//
// userInfo = new String(resultByte, "UTF-8");
// System.out.println("userInfo:" + userInfo);
// userInfoJSON = JSON.parseObject(userInfo);
// } catch (Exception e) {
// e.printStackTrace();
// }
// System.out.println("userInfo:" + userInfoJSON);
//----------------------------------解密用户信息-----------------------------------------
return null;
}
//获取用户手机号信息
@PostMapping(value ="/postPhoneNumber")
// @GetMapping(value = "/getPhoneNumber")
public Object getPhoneNumber(@RequestBody Openid openid , @RequestParam(value = "param") String param) throws Exception {
// 加密秘钥
String sessionKey = RedisUtil.getStringValue("session_key");
//手机号数据String类型
String result = AesCbcUtil.decrypt(openid.getEncryptedData() , sessionKey , openid.getIv() , "UTF-8");
System.out.println(result);
//把String类型转变成JSONObject
JSONObject resultObj = new JSONObject(result);//resultArray.optJSONObject(0);
//用spring从JSONObject拿需要的数据
String phoneNumber= resultObj.getString("phoneNumber");
String watermark= resultObj.getString("watermark");
JSONObject resultObj2 = new JSONObject(watermark);
String appid=resultObj2.getString("appid");
//数据库操作
HttpServletRequest request = null;
Connection connection=null;
PreparedStatement ps=null;
ResultSet rs;
try{
connection= JDBCUtil.getConnection();
String selectSQL = "select * from user_information where phoneNumber = ?";
ps=connection.prepareStatement(selectSQL);
ps.setString(1,phoneNumber);
ps.execute();
String phone=null;
rs=ps.executeQuery();
while(rs.next()){
phone = rs.getString("phoneNumber");//rs.getInt("UserName");
}
System.out.println(phone+"查询到的数据");
if(phone==null){
String sql="insert into user_information values(null,?,?,? ) ";
ps=connection.prepareCall(sql);
ps.setString(1,appid);
ps.setString(2,phoneNumber);
ps.setString(3,Openid);
ps.execute();
}else {
System.out.println("已经有该数据");
}
//增加代码
}catch (SQLException e){
e.printStackTrace();
}finally {
JDBCUtil.close(connection);
}
System.out.println("_____下面是拿到的数据_____");
System.out.println(phoneNumber);
System.out.println(watermark);
System.out.println(appid);
return result;
}
}
手机号解密代码
AesCbcUtil
package com.yiqidaojia.wechatapplet2.util;
import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.*;
import java.security.spec.InvalidParameterSpecException;
/**
* Created by yfs on 2018/3/25.
*
* AES-128-CBC 加密方式
* 注:
* AES-128-CBC可以自己定义“密钥”和“偏移量“。
* AES-128是jdk自动生成的“密钥”。
*/
public class AesCbcUtil {
static {
//BouncyCastle是一个开源的加解密解决方案,主页在http://www.bouncycastle.org/
Security.addProvider(new BouncyCastleProvider());
}
/**
* AES解密
*
* @param data //密文,被加密的数据
* @param key //秘钥
* @param iv //偏移量
* @param encodingFormat //解密后的结果需要进行的编码
* @return
* @throws Exception
*/
public static String decrypt(String data, String key, String iv, String encodingFormat) throws Exception {
// initialize();
//被加密的数据
byte[] dataByte = Base64.decodeBase64(data);
//加密秘钥
byte[] keyByte = Base64.decodeBase64(key);
//偏移量
byte[] ivByte = Base64.decodeBase64(iv);
try {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
SecretKeySpec spec = new SecretKeySpec(keyByte, "AES");
AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");
parameters.init(new IvParameterSpec(ivByte));
cipher.init(Cipher.DECRYPT_MODE, spec, parameters);// 初始化
byte[] resultByte = cipher.doFinal(dataByte);
if (null != resultByte && resultByte.length > 0) {
String result = new String(resultByte, encodingFormat);
return result;
}
return null;
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidParameterSpecException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
}
}
redis代码用于储存微信服务器发过来的session_key
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisShardInfo;
import redis.clients.jedis.ShardedJedis;
import redis.clients.jedis.ShardedJedisPool;
import java.io.*;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
/**
* Redis工具类
*/
public class RedisUtil {
private static Logger logger = LoggerFactory.getLogger(RedisUtil.class);
/**
* 默认过期时间,单位/秒, 60*60*2=2H, 两小时
*/
private static final int DEFAULT_EXPIRE_TIME = 7200;
private static List redisList;
public static void init(List redisList) {
RedisUtil.redisList = redisList;
}
// ------------------------ ShardedJedisPool ------------------------
private static ShardedJedisPool shardedJedisPool;
private static ReentrantLock INSTANCE_INIT_LOCL = new ReentrantLock(false);
/**
* 获取ShardedJedis实例
*
* @return
*/
private static int timeout = 2;
private static ShardedJedis getInstance() {
if (shardedJedisPool == null) {
try {
if (INSTANCE_INIT_LOCL.tryLock(timeout, TimeUnit.SECONDS)) {
try {
if (shardedJedisPool == null) {
// JedisPoolConfig
JedisPoolConfig config = new JedisPoolConfig();
// 最大连接数, 默认8个
config.setMaxTotal(200);
// 最大空闲连接数, 默认8个
config.setMaxIdle(50);
// 设置最小空闲数
config.setMinIdle(8);
// 获取连接时的最大等待毫秒数(如果设置为阻塞时BlockWhenExhausted),如果超时就抛异常, 小于零:阻塞不确定的时间, 默认-1
config.setMaxWaitMillis(10000);
// 在获取连接的时候检查有效性, 默认false
config.setTestOnBorrow(true);
// 调用returnObject方法时,是否进行有效检查
config.setTestOnReturn(true);
// Idle时进行连接扫描
config.setTestWhileIdle(true);
//表示idle object evitor两次扫描之间要sleep的毫秒数
config.setTimeBetweenEvictionRunsMillis(30000);
//表示idle object evitor每次扫描的最多的对象数
config.setNumTestsPerEvictionRun(10);
//表示一个对象至少停留在idle状态的最短时间,然后才能被idle object evitor扫描并驱逐;这一项只有在timeBetweenEvictionRunsMillis大于0时才有意义
config.setMinEvictableIdleTimeMillis(60000);
// JedisShardInfo List
List jedisShardInfos = new LinkedList();
for (Redis redis : redisList) {
String[] addressInfo = redis.getAddress().split(":");
String host = addressInfo[0];
int port = Integer.valueOf(addressInfo[1]);
JedisShardInfo jedisShardInfo = new JedisShardInfo(host, port, 10000);
if (redis.getPassword() != null && !"".equals(redis.getPassword())) {
jedisShardInfo.setPassword(redis.getPassword());
}
jedisShardInfos.add(jedisShardInfo);
}
shardedJedisPool = new ShardedJedisPool(config, jedisShardInfos);
logger.info(">>>>>>>>>>> JedisUtil.ShardedJedisPool init success.");
}
} finally {
INSTANCE_INIT_LOCL.unlock();
}
}
} catch (InterruptedException e) {
logger.error(e.getMessage(), e);
}
}
if (shardedJedisPool == null) {
throw new NullPointerException(">>>>>>>>>>> JedisUtil.ShardedJedisPool is null.");
}
ShardedJedis shardedJedis = shardedJedisPool.getResource();
return shardedJedis;
}
// ------------------------ serialize and unserialize ------------------------
/**
* 将对象-->byte[] (由于jedis中不支持直接存储object所以转换成byte[]存入)
*
* @param object
* @return
*/
private static byte[] serialize(Object object) {
ObjectOutputStream oos = null;
ByteArrayOutputStream baos = null;
try {
// 序列化
baos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(baos);
oos.writeObject(object);
byte[] bytes = baos.toByteArray();
return bytes;
} catch (Exception e) {
logger.error("{}", e);
} finally {
try {
oos.close();
baos.close();
} catch (IOException e) {
logger.error("{}", e);
}
}
return null;
}
/**
* 将byte[] -->Object
*
* @param bytes
* @return
*/
private static Object unserialize(byte[] bytes) {
ByteArrayInputStream bais = null;
try {
// 反序列化
bais = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new ObjectInputStream(bais);
return ois.readObject();
} catch (Exception e) {
logger.error("{}", e);
} finally {
try {
bais.close();
} catch (IOException e) {
logger.error("{}", e);
}
}
return null;
}
// ------------------------ jedis util ------------------------
/**
* Set String
*
* @param key
* @param value
* @param seconds 存活时间,单位/秒
* @return
*/
public static String setStringValue(String key, String value, int seconds) {
String result = null;
ShardedJedis client = getInstance();
try {
result = client.setex(key, seconds, value);
} catch (Exception e) {
logger.info("{}", e);
} finally {
client.close();
}
return result;
}
/**
* Set String (默认存活时间, 2H)
*
* @param key
* @param value
* @return
*/
public static String setStringValue(String key, String value) {
return setStringValue(key, value, DEFAULT_EXPIRE_TIME);
}
/**
* Set Object
*
* @param key
* @param obj
* @param seconds 存活时间,单位/秒
*/
public static String setObjectValue(String key, Object obj, int seconds) {
String result = null;
ShardedJedis client = getInstance();
try {
result = client.setex(key.getBytes(), seconds, serialize(obj));
} catch (Exception e) {
logger.info("{}", e);
} finally {
client.close();
}
return result;
}
/**
* Set Object (默认存活时间, 2H)
*
* @param key
* @param obj
* @return
*/
public static String setObjectValue(String key, Object obj) {
return setObjectValue(key, obj, DEFAULT_EXPIRE_TIME);
}
/**
* Get String
*
* @param key
* @return
*/
public static String getStringValue(String key) {
String value = null;
ShardedJedis client = getInstance();
try {
value = client.get(key);
} catch (Exception e) {
logger.info("", e);
} finally {
client.close();
}
return value;
}
/**
* Get Object
*
* @param key
* @return
*/
public static Object getObjectValue(String key) {
Object obj = null;
ShardedJedis client = getInstance();
int index = key.indexOf("forever-");
try {
byte[] bytes = client.get(key.getBytes());
if (bytes != null && bytes.length > 0) {
obj = unserialize(bytes);
}
} catch (Exception e) {
logger.info("", e);
} finally {
client.close();
}
//重置过期时间
if (index < 0) {
expire(key, DEFAULT_EXPIRE_TIME);
}
return obj;
}
/**
* Delete
*
* @param key
* @return Integer reply, specifically:
* an integer greater than 0 if one or more keys were removed
* 0 if none of the specified key existed
*/
public static Long del(String key) {
Long result = null;
ShardedJedis client = getInstance();
try {
result = client.del(key);
} catch (Exception e) {
logger.info("{}", e);
} finally {
client.close();
}
return result;
}
/**
* incrBy value值加i
*
* @param key
* @param i
* @return new value after incr
*/
public static Long incrBy(String key, int i) {
Long result = null;
ShardedJedis client = getInstance();
try {
result = client.incrBy(key, i);
} catch (Exception e) {
logger.info("{}", e);
} finally {
client.close();
}
return result;
}
/**
* exists
*
* @param key
* @return Boolean reply, true if the key exists, otherwise false
*/
public static Boolean exists(String key) {
Boolean result = null;
ShardedJedis client = getInstance();
try {
result = client.exists(key);
} catch (Exception e) {
logger.info("{}", e);
} finally {
client.close();
}
return result;
}
/**
* expire 重置存活时间
*
* @param key
* @param seconds 存活时间,单位/秒
* @return Integer reply, specifically:
* 1: the timeout was set.
* 0: the timeout was not set since the key already has an associated timeout (versions lt 2.1.3), or the key does not exist.
*/
public static Long expire(String key, int seconds) {
Long result = null;
ShardedJedis client = getInstance();
try {
result = client.expire(key, seconds);
} catch (Exception e) {
logger.info("{}", e);
} finally {
client.close();
}
return result;
}
/**
* expireAt 设置存活截止时间
*
* @param key
* @param unixTime 存活截止时间戳
* @return
*/
public static Long expireAt(String key, long unixTime) {
Long result = null;
ShardedJedis client = getInstance();
try {
result = client.expireAt(key, unixTime);
} catch (Exception e) {
logger.info("{}", e);
} finally {
client.close();
}
return result;
}
/**
* Set Object(永久有效)
*
* @param key
* @param obj
*/
public static String setForeverObjectValue(String key, Object obj) {
String result = null;
ShardedJedis client = getInstance();
try {
result = client.set(key.getBytes(), serialize(obj));
} catch (Exception e) {
logger.info("{}", e);
} finally {
client.close();
}
return result;
}
}
pom依赖
org.projectlombok
lombok
true
cn.hutool
hutool-all
4.1.21
io.springfox
springfox-swagger2
2.9.2
io.springfox
springfox-swagger-ui
2.9.2
com.google.code.gson
gson
2.8.2
com.alibaba
druid
1.1.10
com.alibaba
fastjson
1.2.7
com.squareup.okhttp3
okhttp
3.10.0
redis.clients
jedis
2.9.0
org.springframework.boot
spring-boot-starter-web
org.mybatis.spring.boot
mybatis-spring-boot-starter
2.1.1
org.springframework.boot
spring-boot-configuration-processor
true
org.apache.ibatis
ibatis-core
3.0
mysql
mysql-connector-java
8.0.15
org.projectlombok
lombok
true
org.springframework.boot
spring-boot-starter-test
test
org.junit.vintage
junit-vintage-engine
dom4j
dom4j
1.6.1
org.apache.commons
commons-lang3
3.6
commons-configuration
commons-configuration
1.10
commons-io
commons-io
2.5
org.apache.httpcomponents
httpclient
com.fasterxml
classmate
1.4.0
cn.hutool
hutool-all
4.5.0
org.bouncycastle
bcprov-jdk15on
1.55
org.apache.httpcomponents
httpclient
4.3.5
com.vaadin.external.google
android-json
0.0.20131108.vaadin1
com.vaadin.external.google
android-json
0.0.20131108.vaadin1
org.springframework.boot
spring-boot-maven-plugin
至此所有代码都完成了
在这里特别感谢一下帮助我的大佬 王子洋
这里是他的博客大家可以去看看
王子洋老师在B站有一个微信公众号的讲解视频大家感兴趣的可以去看一看名字是《Java开发之旅》