index.wxnk
<!-- pages/own/index/index.wxml -->
<view>
<view data-route="{{infoRoute}}" bindtap="link" class="bg-box contain flex-center">
<image src="/image/head.png" class="img"></image>
<view>
<view data-route="{{infoRoute}}" class="text-s">用户GHJUGNKH</view>
<view>159****5623</view>
</view>
</view>
<view class="contain">
<view class="card">
<view class="flex-v-sb">
<view class="text-m font-bold" data-tab="0" data-route="{{orderRoute}}" bindtap="order">
订单中心
</view>
<view class="text-sm text-deepgray" data-route="{{addressRoute}}" bindtap="link">
管理收货地址
<van-icon name="arrow" />
</view>
</view>
<view class="flex-v-sb order-box">
<view class="item" data-tab="1" data-route="{{orderRoute}}" bindtap="order">
<image src="/image/own-1.png" class="icon"></image>
<view class="text-sm">待发货</view>
</view>
<view class="item" data-tab="2" data-route="{{orderRoute}}" bindtap="order">
<image src="/image/own-2.png" class="icon"></image>
<view class="text-sm">已发货</view>
</view>
<view class="item" data-route="{{logisticsRoute}}" bindtap="link">
<image src="/image/own-3.png" class="icon"></image>
<view class="text-sm">物流查询</view>
</view>
</view>
</view>
<view class="card">
<view data-route="{{rewardRoute}}" bindtap="link" class="text-m font-bold">奖励中心</view>
<van-row data-route="{{rewardRoute}}" bindtap="link">
<van-col span="8">
<view class="text-l text-red text-bold">29</view>
<view class="text-sm m-t">邀请总数</view>
</van-col>
<van-col span="8">
<view class="text-l text-red text-bold">200</view>
<view class="text-sm m-t">实际参数</view>
</van-col>
<van-col span="8">
<view class="text-l text-red text-bold">1000</view>
<view class="text-sm m-t">预计总收益</view>
</van-col>
</van-row>
<view class="flex-v-sb" style="margin-top: 46rpx;">
<image src="{{img}}" class="code-img" bindtap="previewImage" />
<van-button round custom-class="invite">邀请好友</van-button>
<van-button round custom-class="withdrawal" data-route="{{withdrawalRoute}}" bindtap="link">
提现
</van-button>
</view>
</view>
<!-- <button open-type="getUserInfo"
bindgetuserinfo="onGetuserinfo">
获取Openid
</button> -->
<!-- <button open-type="getUserInfo"
bindgetuserinfo="login">
授权进行获取用户信息
</button> -->
<button bindtap="login">授权登录</button><!--授权登录-->
<button class="cu-btn bg-green btn-primary round" open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber">获取电话号码</button>
</view>
<van-overlay show="{{ show }}" bindtap="onClickHide">
<view class="wrapper">
<image src="{{img}}" class="preview-img code-img"></image>
</view>
</van-overlay>
</view>
index.js
// pages/own/index/index.js
import {
Request
} from '../../../utils/request.js'
let request = new Request()
Page({
/**
* 页面的初始数据
*/
data: {
img: '/image/code.png',
show: false,
infoRoute: '/pages/own/personInfo/personInfo',
orderRoute: '/pages/own/order/index/index',
addressRoute: '/pages/own/address/index/index',
logisticsRoute: '/pages/own/logistics/index/index',
rewardRoute: '/pages/own/reward/index/index',
withdrawalRoute: '/pages/own/withdrawal/index/index',
},
previewImage() {
this.setData({
show: true
});
},
onClickHide() {
this.setData({
show: false
});
},
order: function (e) {
var route = e.currentTarget.dataset.route;
let tab = e.currentTarget.dataset.tab;
wx.navigateTo({
url: route + '?tab=' + tab
})
},
link: function (e) {
var route = e.currentTarget.dataset.route
console.log(route)
wx.navigateTo({
url: route
})
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
if (typeof this.getTabBar === 'function' &&
this.getTabBar()) {
this.getTabBar().setData({
selected: 3
})
}
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
},
// onGetuserinfo:function(e){
// // console.log(e)
// // 登录
// wx.login({
// success: res => {
// console.log(res)
// request.login({code:res.code}).then(r => {
// })
// }
// })
// },
//授权登录
login(){
var openId;
wx.login({
success: res => {
request.login({code:res.code}).then(r => {
openId = r;
})
}
})
wx.getUserProfile({
desc: '用于完善会员资料',
success:res =>{
let user = res.userInfo
user.openId=openId;
user.qrcode = ""; //如果传值说明是新用户不是别人分享来的
request.saveUser({user}).then(r => {
})
//把用户信息缓存到本地
wx.setStorageSync('user', user)
console.log("用户信息",user)
this.setData({
userInfo:user
})
},
fail: res=>{
console.log('授权失败',res)
}
})
},
//退出登录
loginOut(){
this.setData({
userInfo:''
})
wx.setStorageSync('user', null)
},
//手机号码授权
getPhoneNumber(e) {
// console.log('获取电话号码')
// console.log(e.detail.errMsg)
// console.log(e.detail.iv)
// console.log(e.detail.encryptedData)
// 用户同意授权
if (e.detail.errMsg === 'getPhoneNumber:ok') {
console.log('确定')
wx.login({
success: res => {
console.log(res)
var code = res.code;
request.getPhone({encryptedData: e.detail.encryptedData, iv: e.detail.iv, code:code}).then(r => {
})
}
})
}else{
console.log('拒绝')
}
},
// login:function(e){
// //console.log(6)
// wx.showModal({//用户授权弹窗
// title: '温馨提示',
// content: '允许进行微信授权',
// success(res) {
// console.log(res)
// //如果用户点击了确定按钮
// if (res.confirm) {
// wx.getUserProfile({
// desc: '获取你的昵称、头像、地区及性别',
// success: res => {
// console.log(res.userInfo)//控制台输出结果
// var user = res.userInfo;
// user.openId="111";
// user.qrcode="222";
// request.saveUser({user}).then(r => {
// })
// console.log("获取成功");
// },
// fail: res => {
// console.log(res)
// //拒绝授权
// wx.showToast({
// title: '登录失败',
// icon: 'error',
// duration: 2000
// });
// return;
// }
// });
// } else if (res.cancel) {
// //如果用户点击了取消按钮
// console.log(3);
// wx.showToast({
// title: '登录失败',
// icon: 'error',
// duration: 2000
// });
// return;
// }
// }
// })
// }
})
request.js
import {
HTTP
} from './http-p.js'
class Request extends HTTP {
send(url) {
return this.request({
url: url
})
}
// login
login(code) {
return this.request({
url: 'wx/login',
data: code,
method: 'POST',
contentType: 'application/x-www-form-urlencoded'
})
}
// 保存信息
saveUser(userInfo) {
return this.request({
url: 'wx',
data: userInfo,
dataType:"json",
method: 'POST',
contentType: 'application/json'
})
}
//获取手机号码
getPhone(datas){
return this.request({
url: 'wx/getPhone',
data: datas,
method: 'POST',
contentType: 'application/x-www-form-urlencoded'
})
}
}
export {
Request
}
后端代码:
wxController:
package cn.umidata.nucleic.api.controller;
import cn.hutool.json.JSONObject;
import cn.umidata.nucleic.api.utils.AesCbcUtil;
import cn.umidata.nucleic.api.utils.Httprequests;
import cn.umidata.nucleic.api.utils.WXBizDataCrypt;
import cn.umidata.nucleic.common.core.controller.BaseController;
import cn.umidata.nucleic.common.core.domain.AjaxResult;
import cn.umidata.nucleic.common.core.domain.R;
import cn.umidata.nucleic.common.exception.ServiceException;
import cn.umidata.nucleic.core.message.Message;
import cn.umidata.nucleic.wechat.domain.WechatUser;
import cn.umidata.nucleic.wechat.service.IWechatUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.util.StringUtils;
import java.util.HashMap;
import java.util.Map;
/**
* @BelongsProject: nucleic
* @BelongsPackage: cn.umidata.nucleic.api.controller
* @Author: zhanghui
* @CreateTime: 2022-09-06 15:37
* @Description: @Api("小程序端-微信管理")
* @Version: 1.0
*/
@Api(tags = "小程序端-微信管理")
@RestController
@RequestMapping("/wx")
public class wxController extends BaseController {
@Autowired
private IWechatUserService wechatUserService;
@Value("${miniporgram.appid}")
private String appid;
@Value("${miniporgram.secret}")
private String secret;
/* @GetMapping
@ApiOperation(value = "查询微信用户列表",notes = "查询微信用户列表")
public TableDataInfo list(WechatUser wechatUser)
{
startPage();
List<WechatUser> list = wechatUserService.selectWechatUserList(wechatUser);
return getDataTable(list);
}*/
@ApiOperation(value = "新增微信用户",notes = "新增微信用户")
@PostMapping
public AjaxResult add(@RequestBody JSONObject jsonObject)
{
int flag = 0;
// return toAjax(wechatUserService.insertWechatUser(wechatUser));
System.out.println("进入:新增微信用户");
//System.out.println(jsonObject);
Map<String,Object> map = (Map<String, Object>) jsonObject.get("user");
/* System.out.println(map.get("nickName"));
System.out.println(map.get("avatarUrl"));
System.out.println(map.get("openId"));
System.out.println(map.get("gender"));*/
//查询用户是否存在,如果用户存在就不插入
WechatUser wxUser = wechatUserService.findByOpenId((map.get("openId").toString()));
if (wxUser==null){
WechatUser wechatUser = new WechatUser();
wechatUser.setName(map.get("nickName").toString());
wechatUser.setAvatar(map.get("avatarUrl").toString());
wechatUser.setOpenid(map.get("openId").toString());
wechatUser.setGender(Long.valueOf(map.get("gender").toString()));
wechatUser.setQrcode(map.get("qrcode").toString());
flag = wechatUserService.insertWechatUser(wechatUser);
}
return toAjax(flag);
}
@ApiOperation(value = "获取微信用户详细信息",notes = "获取微信用户详细信息")
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id)
{
return AjaxResult.success(wechatUserService.selectWechatUserById(id));
}
/*
* @description: 授权登录获取用户的openid和session_key
* @author: zhanghui
* @date: 2022/9/8 0008 下午 4:55
* 发送 https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code
**/
@ApiOperation(value = "授权登录", notes = "不需要登录")
@ApiImplicitParam(paramType = "query", name = "wx.login返回的code", value = "code")
@PostMapping(value = "login")
public Message login(String code) {
// return new Message(getLoginResult(code, null));
// System.out.println("进入后台:"+code);
String params = "appid=" + appid + "&secret=" + secret + "&js_code=" + code + "&grant_type=authorization_code";
String sendGet = Httprequests.sendGet("https://api.weixin.qq.com/sns/jscode2session", params); //发起请求拿到key和openid
// System.out.println(sendGet);
JSONObject json = new JSONObject(sendGet);
// String sessionkey=json.get("session_key").toString(); //会话秘钥
String openid=json.get("openid").toString(); //用户唯一标识
/* System.out.println(sessionkey);
System.out.println(openid);*/
return new Message(openid);
}
/*
* @description: 获取电话号码
* @author: zhanghui
* @date: 2022/9/9 0009 上午 10:17
* https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=ACCESS_TOKEN
**/
@ApiOperation(value = "获取电话号码",notes = "获取电话号码")
@PostMapping("/getPhone")
public Message getPhone(String encryptedData,String iv,String code ) throws Exception {
AesCbcUtil aesCbcUtil = new AesCbcUtil();
String params = "appid=" + appid + "&secret=" + secret + "&js_code=" + code + "&grant_type=authorization_code";
String sendGet = Httprequests.sendGet("https://api.weixin.qq.com/sns/jscode2session", params); //发起请求拿到key和openid
//获取AccessToken https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
/* String paramsToken = "appid=" + appid + "&secret=" + secret;
String AccessTokenSendGet = Httprequests.sendGet("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credentia",paramsToken);
System.out.println("AccessTokenSendGet:>>>>>>"+AccessTokenSendGet);*/
//String sendPost = Httprequests.sendPost("https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=ACCESS_TOKEN");
// System.out.println(sendGet);
JSONObject json = new JSONObject(sendGet);
String sessionkey=json.get("session_key").toString(); //会话秘钥
String openid=json.get("openid").toString(); //用户唯一标识
System.out.println("openid:"+openid);
System.out.println("会话秘钥:"+sessionkey);
// System.out.println("encryptedData:"+encryptedData);
// System.out.println("iv:"+iv);
String phone = "";
WechatUser wxUser = wechatUserService.findByOpenId(openid);
if (wxUser!=null){
if (wxUser.getPhonenumber()!=null){
phone = wxUser.getPhonenumber();
}else{
phone = aesCbcUtil.decode(sessionkey,encryptedData,iv);
}
}
System.out.println("电话号码:"+phone);
wechatUserService.updateWechatUserByOpenId(openid,phone);
return new Message(phone);
}
/* @ApiOperation(value = "登录")
@PostMapping("/wxlogin")
public R callback(String code, String encryptedData, String iv){
System.out.println("----------------------------------------------");
//1.判断code是否合法
if(StringUtils.isEmpty(code)){
throw new ServiceException("22008 登录失败,尝试刷新重新登录!");
}
//2:通过code获取access_token
String params = "appid=" + appid + "&secret=" + secret + "&js_code=" + code + "&grant_type=authorization_code";
String sendGet = Httprequests.sendGet("https://api.weixin.qq.com/sns/jscode2session", params); //发起请求拿到key和openid
String res = WXBizDataCrypt.decrypt1(encryptedData,sessionkey,iv);
JSONObject jsons = new JSONObject(res);
System.out.println("-----------json------------------"+jsons);
JSONObject json = new JSONObject(sendGet);
//解析微信用户得唯一凭证openid
String openid = json.get("openid").toString(); //用户唯一标识
String session_key =json.get("session_key").toString(); //会话秘钥
*//* if (!StringUtils.isEmpty(res)&&res.length()>0){
String sex="0";
if(json.getInteger("gender")==1){
sex="男";
}else if(json.getInteger("gender")==2){
sex="女";
}
resultMap.put("avatarUrl",json.getString("avatarUrl"));
resultMap.put("nickName",json.getString("nickName"));
resultMap.put("sex",sex);
}*//*
//封装返回
// return R.ok().data("resultMap",resultMap);
*//* }catch (Exception e){
return R.error().code(601).message("微信解析失败");
}*//*
return R.ok();
}*/
}
获取电话号码解析工具:
AesCbcUtil:
package cn.umidata.nucleic.api.utils;
import cn.hutool.json.JSONObject;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.apache.commons.codec.binary.Base64;
import org.springframework.util.Base64Utils;
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.AlgorithmParameters;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.InvalidParameterSpecException;
/**
* @BelongsProject: nucleic
* @BelongsPackage: cn.umidata.nucleic.api.utils
* @Author: zhanghui
* @CreateTime: 2022-09-09 10:33
* @Description: 解密
* @Version: 1.0
*/
@Data
public class AesCbcUtil {
@ApiModelProperty(value = "用户信息的加密数据")
private String userInfoEncryptedData;
@ApiModelProperty(value = "用户信息加密算法的初始向量")
private String userInfoIv;
@ApiModelProperty(value = "手机号加密算法的初始向量")
private String iv;
@ApiModelProperty(value = "用户手机号的加密数据")
private String encryptedData;
/*
* @description:解密
* @author: zhanghui
* @date: 2022/9/9 0009 上午 10:35
* @param encryptedData 包括敏感数据在内的完整用户信息的加密数据,
* @param key 秘钥
* @param iv 加密算法的初始向量,
* @param encodingFormat 解密后的结果需要进行的编码
**/
public static String decrypt(String encryptedData,String key, String iv, String encodingFormat) throws Exception {
// initialize();
//被加密的数据
byte[] dataByte = Base64.decodeBase64(encryptedData);
//加密秘钥
byte[] keyByte = Base64.decodeBase64(key);
//偏移量
byte[] ivByte = Base64.decodeBase64(iv);
try {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
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;
}
public JSONObject decodeUserInfo(String sessionKey) throws Exception {
byte[] encrypData = Base64Utils.decodeFromString(userInfoEncryptedData);
byte[] ivData = Base64Utils.decodeFromString(userInfoIv);
byte[] sessionKeyByte = Base64Utils.decodeFromString(sessionKey);
AlgorithmParameterSpec ivSpec = new IvParameterSpec(ivData);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecretKeySpec keySpec = new SecretKeySpec(sessionKeyByte, "AES");
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
String resultString = new String(cipher.doFinal(encrypData), "UTF-8");
JSONObject object = new JSONObject(resultString);
return object;
}
public String decode(String sessionKey,String encryptedData,String iv ) throws Exception {
byte[] encrypData = Base64Utils.decodeFromString(encryptedData);
byte[] ivData = Base64Utils.decodeFromString(iv);
byte[] sessionKeyByte = Base64Utils.decodeFromString(sessionKey);
AlgorithmParameterSpec ivSpec = new IvParameterSpec(ivData);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecretKeySpec keySpec = new SecretKeySpec(sessionKeyByte, "AES");
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
String resultString = new String(cipher.doFinal(encrypData), "UTF-8");
JSONObject object = new JSONObject(resultString);
return object.get("phoneNumber").toString();
}
}
http发起请求工具:
package cn.umidata.nucleic.api.utils;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;
import java.util.Map;
/**
* @BelongsProject: nucleic
* @BelongsPackage: cn.umidata.nucleic.api.utils
* @Author: zhanghui
* @CreateTime: 2022-09-08 17:18
* @Description: http发起请求
* @Version: 1.0
*/
public class Httprequests {
//发送GET请求:
public static String sendGet (String url,String param) {
String result ="";
BufferedReader in =null;
try {
String urlNameString = url +"?" +param;
System.out.println("发送的链接请求:"+urlNameString);
URL reaurl = new URL(urlNameString);
URLConnection connection = reaurl.openConnection();
//设置通用
connection.setRequestProperty("accept", "*/*");
connection.setRequestProperty("connection", "keep-Alive");
connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
//建立实际的连接
connection.connect();
Map<String, List<String>> map = connection.getHeaderFields();
//定义 BufferedReader输入流来读取URL的响应
in = new BufferedReader(new InputStreamReader(
connection.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
System.out.println("发送GET请求出现异常!" + e);
e.printStackTrace();
}
// 使用finally块来关闭输入流
finally {
try {
if (in != null) {
in.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
return result;
}
/**
* 向指定 URL 发送POST方法的请求
* @param url 发送请求的 URL
* @param param 参数
* @return String 所代表远程资源的响应结果
*/
public static String sendPost(String url, String param) {
PrintWriter out = null;
BufferedReader in = null;
String result = "";
try {
URL realUrl = new URL(url);
// 打开和URL之间的连接
URLConnection conn = realUrl.openConnection();
// 设置通用的请求属性
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("user-agent",
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
// 发送POST请求必须设置如下两行
conn.setDoOutput(true);
conn.setDoInput(true);
// 获取URLConnection对象对应的输出流
out = new PrintWriter(conn.getOutputStream());
// 发送请求参数
out.print(param);
// flush输出流的缓冲
out.flush();
// 定义BufferedReader输入流来读取URL的响应
in = new BufferedReader(
new InputStreamReader(conn.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
System.out.println("发送 POST 请求出现异常!"+e);
e.printStackTrace();
}
//使用finally块来关闭输出流、输入流
finally{
try{
if(out!=null){
out.close();
}
if(in!=null){
in.close();
}
}
catch(IOException ex){
ex.printStackTrace();
}
}
return result;
}
}