5.Abp vNext 地磅无人值守 微信小程序
地磅无人值守项目 系列文章目录
文章目录
- 前言
- 一、开发微信页面
- 二、2.Abp vNext 开放登录接口
- 1.Abp vNext 开放登录接口
- 2.微信端登录示例
- utils/config.js
- utils/auth.js
- utils/http.js
- utils/business/login.js
- 总结
前言
客户提出新需求:车辆驾人员能在手机上查看自己车辆过磅记录。开搞…
人手一个微信,那就用微信小程序。
之前搞过vue,有很多相似的地方。
一、开发微信页面
页面及代码示例:
index.wxml
<!--index.wxml-->
<view class="page"><view class="page-body"><swiper class="swiper" indicator-dots="{{indicatorDots}}"autoplay="{{autoplay}}" interval="{{interval}}" duration="{{duration}}" circular="true"><block wx:for="{{background}}" wx:key="*this"><swiper-item><image src="{{imgPath + item}}" class="slide-image" mode="aspectFill" /></swiper-item></block></swiper></view><view class="weui-grids"><navigator class="weui-grid" aria-role="button" url="/pages/records/list"><view class="weui-grid__icon"><icon class="iconfont icon-dingdan" /></view><view class="weui-grid__label">历史单据</view></navigator><navigator class="weui-grid" aria-role="button" url="/pages/cars/create/create"><view class="weui-grid__icon"><icon class="iconfont icon-wuliu" /></view><view class="weui-grid__label">车辆录入</view></navigator><navigator class="weui-grid" aria-role="button" url="#"><view class="weui-grid__icon"><icon class="iconfont icon-bingtutubiao" /></view><view class="weui-grid__label">单据统计<text style="font-style:italic;font-size: 26rpx;">待开放</text></view></navigator><navigator class="weui-grid" aria-role="button" url="/pages/cars/list"><view class="weui-grid__icon"><icon class="iconfont icon-auto" /></view><view class="weui-grid__label">车辆管理</view></navigator></view>
</view>
index.js
const {urlList} = require('../../utils/config.js');Page({data: {imgPath: urlList.advertPicListUrl,background: ['/banner01.png', '/banner02.png'],indicatorDots: true,vertical: false,autoplay: true,circular: false,interval: 5000,duration: 500,previousMargin: 0,nextMargin: 0},onShareAppMessage: function(){return{title: "转发给好友",path: "/pages/index/index"}},changeProperty: function (e) {var propertyName = e.currentTarget.dataset.propertyNamevar newData = {}newData[propertyName] = e.detail.valuethis.setData(newData)},changeIndicatorDots: function (e) {this.setData({indicatorDots: !this.data.indicatorDots})},changeAutoplay: function (e) {this.setData({autoplay: !this.data.autoplay})},intervalChange: function (e) {this.setData({interval: e.detail.value})},durationChange: function (e) {this.setData({duration: e.detail.value})}
})
二、2.Abp vNext 开放登录接口
1.Abp vNext 开放登录接口
using FloorScale.Base.Cars;
using FloorScale.Base.CarTypes;
using FloorScale.Base.MaterialFormats;
using FloorScale.Base.Materials;
using FloorScale.Base.MaterialTypes;
using FloorScale.Base.ReceivingUnits;
using FloorScale.Base.Shippers;
using FloorScale.Base.WeightRecords;
using FloorScale.Base.WeightTypes;
using FloorScale.Base.WeightUnits;
using FloorScale.Tenants;
using FloorScale.ThirdParty.WechatMinis.Dtos;
using IdentityModel.Client;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using System;
using System.Net.Http;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Data;
using Volo.Abp.Identity;
using Volo.Abp.Uow;namespace FloorScale.ThirdParty.WechatMinis
{/// <summary>/// 微信小程序/// </summary>[ApiExplorerSettings(GroupName = FloorScaleAppService.SwaggerDocWechatMiniApi)][Authorize]public partial class WechatMiniService : FloorScaleAppService{private const string ProviderName = "WeChatMiniProgram";private const string FixedPassword = ".*_0W@";private readonly IConfiguration _configuration;private readonly IdentityUserManager _userManager;private readonly IWechatMiniRepository _wechatRepository;private readonly IUnitOfWorkManager _unitOfWorkManager;private readonly IDataFilter _dataFilter;//private readonly ITenantRepository _tenantsRepository;private readonly IEfCoreTenantRepository _tenantRepository;private readonly ICarRepository _carRepository;private readonly ICarTypeRepository _typeRepository;private readonly IShipperRepository _shipperRepository;private readonly IReceivingUnitRepository _receivingUnitRepository;private readonly IMaterialTypeRepository _materialTypeRepository;private readonly IMaterialRepository _materialRepository;private readonly IMaterialFormatRepository _formatRepository;private readonly IWeightTypeRepository _weightTypeRepository;private readonly IWeightRecordRepository _weightRecordRepository;private readonly IWeightUnitRepository _weightUnitRepository;public WechatMiniService(IConfiguration configuration,IdentityUserManager userManager,IWechatMiniRepository wechatRepository,IUnitOfWorkManager unitOfWorkManager,IDataFilter dataFilter,IEfCoreTenantRepository tenantRepository,ICarRepository carRepository,ICarTypeRepository typeRepository,IShipperRepository shipperRepository,IReceivingUnitRepository receivingUnitRepository,IMaterialTypeRepository materialTypeRepository,IMaterialRepository materialRepository,IMaterialFormatRepository formatRepository,IWeightTypeRepository weightTypeRepository,IWeightRecordRepository weightRecordRepository,IWeightUnitRepository weightUnitRepository){_configuration = configuration;_userManager = userManager;_wechatRepository = wechatRepository;_unitOfWorkManager = unitOfWorkManager;_dataFilter = dataFilter;_tenantRepository = tenantRepository;_carRepository = carRepository;_typeRepository = typeRepository;_shipperRepository = shipperRepository;_receivingUnitRepository = receivingUnitRepository;_materialTypeRepository = materialTypeRepository;_materialRepository = materialRepository;_formatRepository = formatRepository;_weightTypeRepository = weightTypeRepository;_weightRecordRepository = weightRecordRepository;_weightUnitRepository = weightUnitRepository;}/// <summary>/// 登录/// </summary>/// <param name="login"></param>/// <returns></returns>[AllowAnonymous]public async Task<WeChatToken> GetLoginAsync(GetWechatLoginDto login){var result = new WeChatToken();// 调用第三方服务通过小程序内部登录后的Code获取微信Session信息//var wechatSession = await GetWechatSession(login.Code);//if (wechatSession == null)//{// throw new BusinessException("wechatFail", "获取Openid失败");//}login.ClientId = "FloorScale_App";login.ClientSecret = "****";WechatCode2Session wechatSession = new WechatCode2Session(){Openid = "abcef06",};var tenantId = Guid.Parse(_configuration["WeChatMini:tenantId"]);using (CurrentTenant.Change(tenantId)){// 通过Provider和Openid获取用户的登录信息var wechatLogin = await _userManager.FindByLoginAsync(ProviderName, wechatSession.Openid);var userId = Guid.Empty;// 首次微信登陆if (wechatLogin == null){var idUserLoginInfo = new Microsoft.AspNetCore.Identity.UserLoginInfo(ProviderName,wechatSession.Openid,"微信小程序");if (!CurrentUser.Id.HasValue){userId = GuidGenerator.Create();// 注册用户登录var iduser = new IdentityUser(userId,wechatSession.Openid,email: $"{wechatSession.Openid}@qq.com",tenantId: tenantId);iduser.ExtraProperties.Add(nameof(wechatSession.Openid), wechatSession.Openid);iduser.AddLogin(idUserLoginInfo);// 添加用户信息await _userManager.CreateAsync(iduser, $"{wechatSession.Openid}{FixedPassword}");var wechatUser = new WechatMini(){UserId = iduser.Id,OpenId = wechatSession.Openid,Phone = string.Empty,Email = string.Empty,NickName = string.Empty,Address = string.Empty,AvatarUrl = string.Empty,Birthday = null,Gender = 0,Status = true,TenantId = tenantId};result.NeedUpdate = true;await _wechatRepository.InsertAsync(wechatUser);}else{userId = CurrentUser.Id.Value;var user = await _userManager.GetByIdAsync(CurrentUser.Id.Value);await _userManager.AddLoginAsync(user, idUserLoginInfo);}}else{userId = wechatLogin.Id;}var tokenResponse = await GetTokenByOpenIdAsync(wechatSession.Openid,wechatSession.Openid,login);result.UserId = userId;result.AccessToken = tokenResponse.AccessToken;result.ExpiresIn = tokenResponse.ExpiresIn;result.TokenType = tokenResponse.TokenType;result.Scope = tokenResponse.Scope;result.RefreshToken = tokenResponse.RefreshToken;return result;}}private async Task<TokenResponse> GetTokenByOpenIdAsync(string userName, string password, GetWechatLoginDto login){var disco = await new HttpClient().GetDiscoveryDocumentAsync(_configuration["AuthServer:Authority"]);using (var tokenClient = new HttpClient()){tokenClient.DefaultRequestHeaders.Add("__tenant", _configuration["WeChatMini:tenantId"]);var tokenResponse = await tokenClient.RequestPasswordTokenAsync(new PasswordTokenRequest{Address = disco.TokenEndpoint,ClientId = login.ClientId,ClientSecret = login.ClientSecret,UserName = userName,Password = $"{password}{FixedPassword}"});tokenClient.SetBearerToken(tokenResponse.AccessToken);return tokenResponse;}}private async Task<WechatCode2Session> GetWechatSession(string code){WechatCode2Session result = null;var appid = _configuration["WeChatMini:appid"];var secret = _configuration["WeChatMini:secret"];var httpClient = new HttpClient();var urlWeixin = string.Format(_configuration["WeChatMini:WeixinSessionUri"],appid,secret,code);try{var token = await httpClient.GetStringAsync(urlWeixin);result = JsonConvert.DeserializeObject<WechatCode2Session>(token);}catch { }return result;}/// <summary>/// 获取用户信息/// </summary>/// <param name="uid"></param>/// <returns></returns>public async Task<WechatMiniDto> GetUserInfoAsync(Guid uid){using (CurrentTenant.Change(Guid.Parse(_configuration["WeChatMini:tenantId"]))){var model = await _wechatRepository.GetAsync(p => p.UserId == uid);return ObjectMapper.Map<WechatMini, WechatMiniDto>(model);}}/// <summary>/// 更新用户信息/// </summary>/// <param name="uid"></param>/// <param name="input"></param>/// <returns></returns>public async Task UpdateUserInfoAsync(Guid uid, [FromBody] UpdateWechatMiniDto input){using (CurrentTenant.Change(Guid.Parse(_configuration["WeChatMini:tenantId"]))){var modelUser = await _wechatRepository.GetAsync(p => p.UserId == uid);modelUser.Phone = input.Phone;modelUser.NickName = input.NickName;if (!string.IsNullOrWhiteSpace(input.AvatarUrl))modelUser.AvatarUrl = input.AvatarUrl;modelUser.Address = input.Address;modelUser.Birthday = input.Birthday;modelUser.Gender = input.Gender;var result = await _wechatRepository.UpdateAsync(modelUser);}}/// <summary>/// 删除实体/// </summary>/// <param name="id">编号</param>/// <returns></returns>public async Task DeleteAsync(Guid id){await _wechatRepository.DeleteAsync(id);}}
}
2.微信端登录示例
utils/config.js
// const basePath = 'https://localhost:44385';
const basePath = 'https://scaleapi.caishiben.com';
const urlList = {basePath: basePath,// 刷新tokenrefreshTokeUrl: basePath + '/refreshToke',//token// 登录和首页轮播loginUrl: basePath + '/wxappLogin',//登录advertPicListUrl: basePath + '/wechat',//轮播列表
}
const globalConfig = {clientId: 'FloorScale_App',clientSecret: '********'
}module.exports = {urlList,globalConfig
}
utils/auth.js
import http from './business/login'
import userApi from './business/user'
const {globalConfig} = require('config.js')async function checkSession(){return new Promise((resolve, reject) => {wx.checkSession({success() {return resolve(true)},fail() {return resolve(false)}})})
}// 检测登录状态,返回 true / false
async function checkHasLogined() {const token = wx.getStorageSync('token')if (!token) {return false}const loggined = await checkSession()if (!loggined) {wx.removeStorageSync('token')wx.removeStorageSync('userInfo')wx.removeStorageSync('uid')wx.removeStorageSync('rememberTenant')return false}return true
}async function register(page) {let _this = this;return new Promise((resolve, reject) => {wx.getUserProfile({desc: '用于完善会员资料',fail: () => {resolve(false)},success: (resUser) => {wx.login({fail: () => {resolve(false)},success: resLogin => {http.getLoginToken({data: {code: resLogin.code,clientId: globalConfig.clientId,clientSecret: globalConfig.clientSecret},success: function (resToken) {wx.setStorageSync('token', resToken.access_token)wx.setStorageSync('uid', resToken.uid)if (resToken.needUpdate) {updateUser(resUser.userInfo)}if(page) {page.onShow()}resolve(true)},complete : function(resToken){},fail: function (resToken) {resolve(false)}})}})}})})
}function updateUser(data) {let _this = this;let passData = {"userId": wx.getStorageSync('uid'),"phone": "","nickName": data.nickName,"address": "","avatarUrl": data.avatarUrl,"birthday": null,"gender": data.gender,"remark": ""}userApi.updateUserInfo({data: passData,success: function (res) {},complete : function(res){},fail: function (res) {}})
}module.exports = {checkHasLogined: checkHasLogined,register: register
}
utils/http.js
module.exports = {http(url, method, params) {let requestHeader = {'content-type': 'application/json'}// 获取tokenlet token = wx.getStorageSync('token')if (token){requestHeader.authorization = 'Bearer ' + token}// 在这里判断一下data是否存在,params表示前端需要传递的数据,params是一个对象,有三组键值对,// data:表示请求要发送的数据,success:成功的回调,fail:失败的回调,这三个字段可缺可无,其余字段会忽略if(params.data){for (let key in params.data) { // 在这里判断传过来的参数值为null,就删除这个属性if (params.data[key] == null || params.data[key] == 'null') {delete params.data[key]}}}wx.request({url: urlList.basePath + url,method: method === '' ? 'get' : method,data: params.data,header: requestHeader,success(res) {params.success && params.success(res.data)},fail(err) {params.fail && params.fail(err)},complete(err) {params.complete && params.complete(err)}})}
}
utils/business/login.js
function getSession(params){http('/api/app/wechat-mini/session', 'get', params)
}function getLoginToken(params){http('/api/app/wechat-mini/login', 'get', params)
}export default {getLoginToken,getSession
}
总结
Abp vNext 开放登录接口调通后,剩下的工作就是功能叠加。这个工作有点枯燥。
微信上打开小程序:#小程序://尧安称重/NxgTDIoRdkAWE7g
前端:https://dibang.caishiben.com
接口服务:https://scaleapi.caishiben.com
接口文档:https://scaleapi.caishiben.com/swagger/index.html
5.Abp vNext 地磅无人值守 微信小程序相关推荐
- abp Vnext OpenIddect 扩展微信小程序授权登录
abp vnext6.0之后官方替换了原来的ids4,采用了openIddict的oauth认证框架.使用之前的方法已经不行,以下是OpenIddect 使用ITokenExtensionGrant接 ...
- Abp vNext 地磅无人值守项目目录
地磅无人值守项目目录 第一章 项目概况 第二章 项目后台搭建 2.1.0 abp vnext 接口服务搭建 2.1.1 abp vnext初始化项目 2.1.2 SQL Server数据库 2.1.3 ...
- 2.1.1 Abp vNext 地磅无人值守 接口服务创建
地磅无人值守项目 系列文章目录 文章目录 前言 一.Abp vNext手脚架 二.创建Abp vNext项目 1.创建项目 2.初始化数据库 3.试运行 3.1 查看数据库连接 3.2 浏览器查看 3 ...
- 2.1.0 Abp vNext 地磅无人值守 接口服务搭建
地磅无人值守项目 系列文章目录 文章目录 前言 一.Domain项目创建实体类 1.创建实体类(该类对应 数据库字段) 2.创建表接口类 二.EntityFrameworkCore项目 1.创建表实现 ...
- 2.1.3 Abp vNext 地磅无人值守 业务实现
地磅无人值守项目 系列文章目录 文章目录 前言 一.AbpHelper简介 二.AbpHelper使用 1.创建CarType实体类 2.AbpHelper打开解决方案 3.为CarType实体类生成 ...
- 3.Abp vNext 地磅无人值守 vue 前端搭建
地磅无人值守项目 系列文章目录 文章目录 前言 一.Vue概要 二.文件夹简单说明 api示例 views示例 router示例 1.router/modules文件夹下加入cars.js,代码如下: ...
- 2.1.4 Abp vNext 地磅无人值守 车辆物料实现接口
地磅无人值守项目 系列文章目录 文章目录 前言 一.获取实体数据 二.创建实体数据 三.获取翻页数据 四.更新实体数据 五.删除实体数据 六.CarTypeAppService全部代码 总结 前言 提 ...
- 4.Abp vNext 地磅无人值守 Winform 客户端搭建
地磅无人值守项目 系列文章目录 文章目录 前言 一.基础功能 1. 一台电脑启动一次客户端 2. 日志记录 3. 自动升级功能 二.对接硬件设备 1.对接摄像头 总结 前言 客户端主要是管控车辆进出场 ...
- 1.Abp vNext 地磅无人值守项目
地磅无人值守项目 系列文章目录 文章目录 前言 一.过磅方式 二.系统作业流程 三.系统构成模块 总结 前言 传统的衡称重由于设备.人为因素及流程等问题,导致作弊现象层出不穷.称重过磅效率也得不到有效 ...
最新文章
- 了解关于Hadoop的12个事实
- js字符串与数组的处理
- python面向对象有什么用_Python 中的面向对象没有意义
- Java数据结构和算法(二):数组
- 我的考研~~~3-4月份总结
- Codepen 每日精选(2018-4-21)
- 罗永浩:比起悲剧英雄 我更喜欢被当成失败的小丑
- 刘强东深夜写信诉苦;华为不排斥卖给苹果 5G 芯片;Facebook 再宕机 | 极客头条...
- Java基础篇:如何使用instanceof
- 【工作日志】2013-02-01
- SHAP模型:可解释机器学习模型
- 好用的在线PS编辑器
- DIY回音壁多媒体音箱
- 正整数分解使得乘积最大问题
- 电路设计之--钽电容选取
- 二叉树的结构特点及性质
- win10多显示器设置只有主显示屏显示任务栏
- html 表格排列,html表格如何排序?表格排序详解!
- python爬取网易云音乐排行榜数据
- Python 运用GeoIP2离线数据库定位
热门文章
- 主流实时流处理计算框架Flink初体验
- 【仿真设计】仿真技术在智能制造中的作用;智能制造难点在模型,焦点在仿真;汽车行业CAE研究
- 【mac 实现ai绘画自由安装指南】
- 怎样把word转换成excel表格格式
- Leetcode DAY6: 有效的字母异位词 and 两个数组的交集 and 快乐数 and 两数之和
- mac上优秀的键盘改键神器:Karabiner Elements完美支持m1芯片详细教程解析
- 3ds Max 材质贴图
- Error response from daemon: Container 2c6d35b44a9862c63a6caf11a5622a33fe27979e12e51f9bd96f8dad98521c
- 物理工程建模和AI量化建模的时空跳跃
- 基于labview开发平台的声音信号采集及处理系统设计(任务书+lunwen+翻译及原文+vi源文件+查重报告)