赞
踩
方便要开发微信小程序的朋友们,可以快速将服务搭建起来,不要把时间浪费在服务的搭建上,专心写我们的业务代码。
你需要了解的知识:
1.微信小程序大概的开发流程
2.注册小程序(个人测试账号)
3.服务器的配置
4.内网穿透(我用的是花生壳)
5.小程序开发文档先大概看一遍
废话不多说了,你懂得,直接讲重点…
整体小程序上就实现上面这些功能。
logging: level: org.springframework.web: info com.lxh.miniapp: debug cn.binarywang.wx.miniapp: debug server: port: 80 servlet: context-path: / wx: miniapp: configs: - appid: wx2d88824e64axxxxxx secret: f1e1d8785bfbe9d36d538xxxxxxxxx token: miniapp aesKey: K1ewVmypZKPTl2BIB8ySTY9C5rpteZxxxxxxxxx msgDataFormat: JSON
WxMiniAppDemoApplication.java
本项目依赖WxJava - 微信开发 Java SDK。https://github.com/Wechat-Group/WxJava
由于本项目支持多个小程序,在调用接口时,要先调用下面接口切换一下小程序。
public static WxMaService switchover(String appid){
if (StringUtils.isBlank(appid)){
throw new IllegalArgumentException("appId为空");
}
WxMaService wxMaService = WxMiniAppConfiguration.getMaService(appid);
if (wxMaService == null) {
throw new IllegalArgumentException(String.format("未找到对应appid=[%s]的配置,请核实!", appid));
}
return wxMaService;
}
配置消息处理,将WxJava SDK进行初始化
package com.lxh.miniapp.config; import cn.binarywang.wx.miniapp.api.WxMaService; import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl; import cn.binarywang.wx.miniapp.bean.*; import cn.binarywang.wx.miniapp.config.impl.WxMaDefaultConfigImpl; import cn.binarywang.wx.miniapp.message.WxMaMessageHandler; import cn.binarywang.wx.miniapp.message.WxMaMessageRouter; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import lombok.Data; import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; import me.chanjar.weixin.common.error.WxErrorException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Configuration; import javax.annotation.PostConstruct; import java.io.File; import java.util.List; import java.util.Map; import java.util.stream.Collectors; /** * created by lanxinghua@2dfire.com on 2020/2/23 */ @Configuration @Data @EnableConfigurationProperties(WxMiniAppProperties.class) public class WxMiniAppConfiguration { private static final Logger logger = LoggerFactory.getLogger(WxMiniAppConfiguration.class); private WxMiniAppProperties miniAppProperties; private static Map<String/*appid*/, WxMaMessageRouter> routers = Maps.newHashMap(); private static Map<String/*appid*/, WxMaService> maServices = Maps.newHashMap(); public WxMiniAppConfiguration(WxMiniAppProperties miniAppProperties) { this.miniAppProperties = miniAppProperties; } public static WxMaService getMaService(String appid) { WxMaService wxService = maServices.get(appid); if (wxService == null) { throw new IllegalArgumentException(String.format("未找到对应appid=[%s]的配置,请核实!", appid)); } return wxService; } public static WxMaMessageRouter getRouter(String appid) { return routers.get(appid); } /** * 优先进行初始化 */ @PostConstruct public void init(){ // 1.获取到所有小程序的配置 List<WxMiniAppProperties.Config> configs = miniAppProperties.getConfigs(); if (configs == null) { throw new RuntimeException("请添加下相关配置,注意别配错了!"); } // 2.初始化maService和消息路由 maServices = configs.stream().map(e -> { WxMaDefaultConfigImpl config = new WxMaDefaultConfigImpl(); config.setAppid(e.getAppid()); config.setSecret(e.getSecret()); config.setToken(e.getToken()); config.setAesKey(e.getAesKey()); config.setMsgDataFormat(e.getMsgDataFormat()); WxMaService maService = new WxMaServiceImpl(); maService.setWxMaConfig(config); routers.put(e.getAppid(), this.newRouter(maService)); return maService; }).collect(Collectors.toMap(a-> a.getWxMaConfig().getAppid(), a-> a)); } /** * 新建路由 * @param maService * @return */ private WxMaMessageRouter newRouter(WxMaService maService){ final WxMaMessageRouter router = new WxMaMessageRouter(maService); // 配置路由规则 router.rule().handler(LogHandler).next() .rule().async(false).msgType(WxConsts.KefuMsgType.TEXT).handler(textHandler).end(); return router; } private final WxMaMessageHandler LogHandler = (message, context, service, sessionManager) -> { logger.info("【消息日志】:" + message.toString()); return null; }; private final WxMaMessageHandler textHandler = (message, context, service, sessionManager) -> { logger.info("textHandler:" + message.toString()); String msg = message.getContent(); switch (msg){ case "图片":{ sendPic(service, message); break; } case "模板":{ sendTemplate(service, message); break; } case "订阅":{ sendSubscribeMsg(service, message); break; } case "二维码":{ sendQrCode(service, message); break; } default:{ sendText(service, message); break; } } return null; }; private void sendText(WxMaService service, WxMaMessage message){ try { service.getMsgService().sendKefuMsg(WxMaKefuMessage.newTextBuilder().content("回复文本消息") .toUser(message.getFromUser()).build()); }catch (Exception e){ logger.error(e.getMessage()); } } private void sendPic(WxMaService service, WxMaMessage message){ try { WxMediaUploadResult uploadResult = service.getMediaService() .uploadMedia("image", "jpg", ClassLoader.getSystemResourceAsStream("lxh.jpg")); service.getMsgService().sendKefuMsg( WxMaKefuMessage .newImageBuilder() .mediaId(uploadResult.getMediaId()) .toUser(message.getFromUser()) .build()); } catch (WxErrorException e) { logger.error(e.getMessage()); } } // 由于“模板消息”将下线,已不再支持添加模板,请尽快接入“订阅消息”。 private void sendTemplate(WxMaService service, WxMaMessage message){ try { service.getMsgService().sendTemplateMsg(WxMaTemplateMessage.builder() .templateId("2KwZNrdSs78NToB2CBzNKMfwoDN4fAggC7jJAweA4hM") .formId("自己替换可用的formid") .data(Lists.newArrayList( new WxMaTemplateData("keyword1", "模板替换值。。。", "#173177"))) .toUser(message.getFromUser()) .build()); }catch (Exception e){ logger.error(e.getMessage()); } } private void sendSubscribeMsg(WxMaService service, WxMaMessage message){ try { service.getMsgService().sendSubscribeMsg(WxMaSubscribeMessage.builder() .templateId("2KwZNrdSs78NToB2CBzNKMfwoDN4fAggC7jJAweA4hM") .data(Lists.newArrayList( new WxMaSubscribeData("thing1", "一起学习呀", "#173177"), new WxMaSubscribeData("thing2", "今晚一起去图书馆学习啊", "#173177") )) .toUser(message.getFromUser()) .build()); }catch (Exception e){ logger.error(e.getMessage()); } } private void sendQrCode(WxMaService service, WxMaMessage message){ try { final File file = service.getQrcodeService().createQrcode("qrCode", 430); WxMediaUploadResult uploadResult = service.getMediaService().uploadMedia("image", file); service.getMsgService().sendKefuMsg( WxMaKefuMessage .newImageBuilder() .mediaId(uploadResult.getMediaId()) .toUser(message.getFromUser()) .build()); } catch (WxErrorException e) { logger.error(e.getMessage()); } } }
package com.lxh.miniapp.controller; import cn.binarywang.wx.miniapp.api.WxMaService; import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl; import cn.binarywang.wx.miniapp.bean.WxMaMessage; import cn.binarywang.wx.miniapp.constant.WxMaConstants; import cn.binarywang.wx.miniapp.message.WxMaMessageRouter; import com.lxh.miniapp.utils.MiniAppUtils; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.*; import java.util.Objects; /** * created by lanxinghua@2dfire.com on 2020/2/21 * 门户网站 */ @Slf4j @RestController @RequestMapping("/wx/portal/{appid}") public class WxPortalController { private static final Logger logger = LoggerFactory.getLogger(WxPortalController.class); private WxMaService wxMaService; @GetMapping(produces = "text/plain;charset=utf-8") public String authGet(@PathVariable String appid, @RequestParam(name = "signature", required = false) String signature, @RequestParam(name = "timestamp", required = false) String timestamp, @RequestParam(name = "nonce", required = false) String nonce, @RequestParam(name = "echostr", required = false) String echostr) { log.info("\n接收到来自微信服务器的认证消息:[{}, {}, {}, {}]", signature, timestamp, nonce, echostr); if (StringUtils.isAnyBlank(signature, timestamp, nonce, echostr)) { throw new IllegalArgumentException("请求参数非法,请核实!"); } // 切换小程序 wxMaService = MiniAppUtils.switchover(appid); if (wxMaService.checkSignature(timestamp, nonce, signature)) { return echostr; } return "非法请求"; } @PostMapping(produces = "application/xml; charset=UTF-8") public String post(@PathVariable String appid, @RequestBody String requestBody, @RequestParam(name = "msg_signature", required = false) String msgSignature, @RequestParam(name = "signature", required = false) String signature, @RequestParam(name = "encrypt_type", required = false) String encryptType, @RequestParam("timestamp") String timestamp, @RequestParam("nonce") String nonce) { logger.info("\n接收微信请求:[msg_signature=[{}], encrypt_type=[{}], signature=[{}]," + " timestamp=[{}], nonce=[{}], requestBody=[\n{}\n] ", msgSignature, encryptType, signature, timestamp, nonce, requestBody); wxMaService = MiniAppUtils.switchover(appid); final boolean isJson = Objects.equals(wxMaService.getWxMaConfig().getMsgDataFormat(), WxMaConstants.MsgDataFormat.JSON); // 明文传输的消息 if (StringUtils.isBlank(encryptType)) { WxMaMessage inMessage; if (isJson) { inMessage = WxMaMessage.fromJson(requestBody); } else {//xml inMessage = WxMaMessage.fromXml(requestBody); } this.route(inMessage, appid); return "success"; } // aes加密的消息 if ("aes".equals(encryptType)) { WxMaMessage inMessage; if (isJson) { inMessage = WxMaMessage.fromEncryptedJson(requestBody, wxMaService.getWxMaConfig()); } else {//xml inMessage = WxMaMessage.fromEncryptedXml(requestBody, wxMaService.getWxMaConfig(), timestamp, nonce, msgSignature); } this.route(inMessage, appid); return "success"; } throw new RuntimeException("不可识别的加密类型:" + encryptType); } private void route(WxMaMessage message, String appid) { try { WxMaMessageRouter router = MiniAppUtils.getRouter(appid); router.route(message); } catch (Exception e) { this.logger.error(e.getMessage(), e); } } }
// 登录 wx.login({ success: res => { if(this.globalData.openId != null){ console.log("openId:" + this.globalData.openId) return; } // 发送 res.code 到后台换取 openId, sessionKey, unionId console.log("登录:"+res.code) var oauthUrl = this.globalData.baseUrl + "wx/user/" + this.globalData.appId + "/login"; if (res.code) { wx.request({ url: oauthUrl, data: { code: res.code }, success: function (res) { console.log(res) const self = this //获取到用户凭证 存儲 3rd_session var json = JSON.parse(res.data.Data) wx.setStorage({ key: "third_Session", data: json.third_Session }) }, fail: function (res) { } }) } }, fail: function (res) { } }) },
globalData: {
userInfo: null,
openId: 'o0aPU5JJUSr1DoNtkJXqSFa1CqoU',
unionId: null,
baseUrl: 'http://chenxingxing.51vip.biz/',
appId: 'wx2d88824e64aacf4d'
}
onLoad() { var that = this; wx.login({ success: function (e) { // 获取用户信息 var code = e.code; wx.getSetting({ success: res => { console.log(res.authSetting); if (res.authSetting['scope.userInfo']) { // 已经授权,可以直接调用 getUserInfo 获取头像昵称,不会弹框 wx.getUserInfo({ success: res => { console.log(res) // 可以将 res 发送给后台解码出 unionId that.setData({ userInfo: res.userInfo }) that.setData({ isAuth: true }) var userObj = {}; userObj.encryptedData = res.encryptedData; userObj.iv = res.iv; userObj.expires_in = Date.now() + 24 * 7 * 60 * 60; wx.setStorageSync('userInfo', res.userInfo); wx.setStorageSync('userObj', userObj); app.globalData.userInfo = res.userInfo; that.thirdLogin(code,userObj); // 所以此处加入 callback 以防止这种情况 if (that.userInfoReadyCallback) { that.userInfoReadyCallback(res) } } }) }else{ that.setData({ isAuth: false }) } } }) } }); },
建立一个专门跳网页page,通过动态传递url,进行跳转
jump: function(){ var type = "baidu"; wx.navigateTo({ url: "/pages/webview/book?type="+ type, }) console.log(this.data.userInfo) } /** * 生命周期函数--监听页面加载 */ onLoad: function (options) { if (options.type = "baidu") { this.setData({ url: "www.baidu.com" }) } } <web-view src="https://{{url}}"></web-view>
subscribeMessage: function(e) {
console.log(e)
wx.requestSubscribeMessage({
tmplIds: ['2KwZNrdSs78NToB2CBzNKMfwoDN4fAggC7jJAweA4hM', 'fl9rdF50TxnOujwzCbl6KytQJrj3dKCsDTEz2O8gpGQ'],
success(res) {
console.log(res)
}
})
}
<button open-type="getUserInfo" bindgetuserinfo="bindGetUserInfo">授权登录</button>
bindGetUserInfo: function (e) {
console.log(e.detail.userInfo)
if (e.detail.userInfo) {
//用户按了允许授权按钮
this.onLoad();
} else {
//用户按了拒绝按钮
}
}
call:function(){
wx.makePhoneCall({
phoneNumber: phone//仅为示例,并非真实的电话号码
})
}
onShareAppMessage: function (res) {
if (res.from === 'button') {
console.log(res.target)
}
return {
title: '小程序标题',
path: 'pages/index/index'
}
}
不支持本地图片
previewImage: function (e) {
wx.previewImage({
current: this.data.url, // 当前显示图片的http链接
urls: [this.data.url] // 需要预览的图片http链接列表
})
}
<map id="map" longitude="112.984954" latitude="28.174734" scale="14" controls="{{controls}}" bindcontroltap="controltap" markers="{{markers}}" bindmarkertap="markertap" bindregionchange="regionchange" show-location style="width: 100%; height: 300px;"></map> Page({ data: { title: '', markers: [{ iconPath: "../../images/location.png", id: 0, latitude: 28.18116, longitude: 112.991562, width: 50, height: 50, }], }, regionchange(e) { console.log(e.type) }, markertap(e) { console.log(e.markerId) }, controltap(e) { console.log(e.controlId) }
到这里就差不多了,恭喜你,兄弟…
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。