微信小程序开发我遇到的一些坑和建议

时间:2022-04-30 13:53:06
小程序最近火了,所以我也花点时间研究了下,同时自己也练练手做了一个小程序“商务工作记事册”,在微信小程序里可以被搜索到,接下去我讲讲我开发过程中遇到的一些坑吧,主要针对后台。

主要功能:
 
支付接口调测:点击支持我们,可以直接捐赠;
提醒功能:主要使用客服通知以及微信小卡片通知;
自定义账本字段:主要就各种Event的Tag可以扩展字段;
文件上传下载:支持事件上传图片,录音文件;
首先要做到上面这些,后台必须要从小程序平台得到的信息如下图:

微信小程序开发我遇到的一些坑和建议
 
 准备工作就绪,讲讲我开发这个小程序遇到的一些问题以及相应实现吧,如果需要查看效果,用微信扫描以下二维码体验:

微信小程序开发我遇到的一些坑和建议

UI效果图:
微信小程序开发我遇到的一些坑和建议 微信小程序开发我遇到的一些坑和建议微信小程序开发我遇到的一些坑和建议
 
前端问题
高度不能用rpx,不然无法计算以及自适应,所以我后来改成了px,不知道有没有更好的方案;
首页应该要验证token合法性,要去服务器请求验证,这个过程是异步的,所以在载入首页之前应该有个splash过渡窗口引导,不然进入首页token非法的就将无法请求到数据,不知道有没有更好的方案;
排版布局使用的是weui,不知道还有没有更好的wxss可以使用;
由于异步调用多会乱,所以后来引入的Promise,好很多;
后台问题
支付实现;
支付微信为了安全性,增加了数字签名,首先你要发起一个订单,得到订单号,有了这个订单号,就可以启动微信支付功能了,以下是代码:

 

public JSONObject prePay() throws Exception{
UserBean ub = getWxUser();
if(ub!=null){
String appid = (StrUtil.formatNullStr(TagConst.globalMap.get("wx.appid")));
String appkey = (StrUtil.formatNullStr(TagConst.globalMap.get("wx.seckey")));
        String mch_id = (StrUtil.formatNullStr(TagConst.globalMap.get("wx.mchid")));
        String mchkey = (StrUtil.formatNullStr(TagConst.globalMap.get("wx.mchkey")));
        
String openId = ub.getUid();
String clientIP = HttpUtils.getIP(request);
if(clientIP.indexOf(":")>0) clientIP = "127.0.0.1";

String fee = StrUtil.formatNullStr(request.getParameter("fee"),"1");
String body = StrUtil.formatNullStr(request.getParameter("body"));
String atta = StrUtil.formatNullStr(request.getParameter("atta"));

String nonce_str = UUIDHexGenerator.generate();
        String today = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
        String code = PayUtil.createCode(8);
        String out_trade_no = mch_id+today+code;//商户订单号
        String spbill_create_ip = clientIP;//终端IP
        String trade_type = "JSAPI";//交易类型  
        String openid=openId;//用户标识
        /**/
        PayInfo paymentPo = new PayInfo();
        paymentPo.setAppid(appid);
        paymentPo.setMch_id(mch_id);
        paymentPo.setNonce_str(nonce_str);
        paymentPo.setBody(body);
        paymentPo.setOut_trade_no(out_trade_no);
        paymentPo.setTotal_fee(fee);
        paymentPo.setSpbill_create_ip(spbill_create_ip);
        paymentPo.setNotify_url(URL_NOTIFY);
        paymentPo.setTrade_type(trade_type);
        paymentPo.setOpenid(openid);
        // 把请求参数打包成数组
        Map<String, String> sParaTemp = new HashMap<String, String>();
        sParaTemp.put("appid", paymentPo.getAppid());
        ……
        // 返回信息
        String return_code = map.get("return_code");
        String return_msg = map.get("return_msg");
        JSONObject jsonObject=new JSONObject() ;
        if(return_code=="SUCCESS"||return_code.equals(return_code)){
            String prepay_id = map.get("prepay_id");
            jsonObject.put("nonceStr", nonce_str);
            jsonObject.put("package", "prepay_id="+prepay_id);
            Long timeStamp= System.currentTimeMillis()/1000;
            jsonObject.put("timeStamp", timeStamp+"");
            String stringSignTemp = "appId="+appid+"&nonceStr=" + nonce_str + "&package=prepay_id=" + prepay_id+ "&signType=MD5&timeStamp=" + timeStamp;
            String paySign=PayUtil.sign(stringSignTemp, "&key="+mchkey, "utf-8").toUpperCase();
            jsonObject.put("paySign", paySign);
            return jsonObject;
        }

}
return null;
}

 
提醒的实现;
这个主要首先获取accesstoken,然后根据这个token去发送消息,以下是代码;
 

public static void sendMsgCard(String openId,String formId,String time,String title,String description ){
String temp_id = StrUtil.formatNullStr(TagConst.globalMap.get("wx.template.notify"));
String dataKeyWorks = "{";
……
String url = "https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token=" + getMsgToken();
        String result =PayUtil.httpRequest(url, "POST", json);
}

public static void sendMsgCard(String date,String openId,String formId,String time,String title,String description ){
String temp_id = StrUtil.formatNullStr(TagConst.globalMap.get("wx.template.notify"));
String dataKeyWorks = "{";
……
String url = "https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token=" + getMsgToken();
        String result =PayUtil.httpRequest(url, "POST", json);
}

public static void sendMsg2User(String openId,String data){
……
String url = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=" + getMsgToken();
        String result =PayUtil.httpRequest(url, "POST", json);
}

private static long lastTime = 0;
private static String accessToken = "";

private static String getMsgToken(){
if(lastTime>0 && ((new Date().getTime()-lastTime)<6000*1000)){
return accessToken;
}
String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+
StrUtil.formatNullStr(TagConst.globalMap.get("wx.appid"))+"&secret=" + StrUtil.formatNullStr(TagConst.globalMap.get("wx.seckey"));
String retStr = PayUtil.httpRequest(url, "GET", null);
JSONObject json = JSON.parseObject(retStr);
if(json!=null){
lastTime = new Date().getTime();
accessToken = StrUtil.formatNullStr(json.get("access_token"));
}
return accessToken;
}
 

智能客服的实现;
拦截用户发来的客服消息,这个需要在微信后台开启,开启后微信会给你客服号以及安全码,有了这两个后,等待微信验证你的URL通过,通过后你就可以拦截用户发来的消息了
  

//接入在线客服的token固定值
public String wx_getmsg() throws Exception{

String token = StrUtil.formatNullStr(TagConst.globalMap.get("wx.contact.token"));  
String contactKey = StrUtil.formatNullStr(TagConst.globalMap.get("wx.contact.seckey"));  

String signature = StrUtil.formatNullStr(request.getParameter("signature"));
String timestamp = StrUtil.formatNullStr(request.getParameter("timestamp"));
String nonce = StrUtil.formatNullStr(request.getParameter("nonce"));

String echostr = StrUtil.formatNullStr(request.getParameter("echostr"));

String _signature = SHA1.getSHA1(token, timestamp, nonce);

if (!signature.equals(_signature)) {
throw new AesException(AesException.ValidateSignatureError);
}

//发来消息的用户ID
String openid = StrUtil.formatNullStr(request.getParameter("openid"));
String encrypt_type=StrUtil.formatNullStr(request.getParameter("encrypt_type"));
String msg_signature=StrUtil.formatNullStr(request.getParameter("msg_signature"));

WXBizMsgCrypt pc = new WXBizMsgCrypt(token, contactKey, StrUtil.formatNullStr(TagConst.globalMap.get("wx.appid")));

InputStream is = request.getInputStream(); 
ByteArrayOutputStream out = new ByteArrayOutputStream(10240);
org.apache.commons.io.IOUtils.copy(is, out);
        String jsonStr = new String(out.toByteArray(), request.getCharacterEncoding());
        
……


if(msgType.equals("text")){
String data = "Sorry,我不能理解您的指令!";

//责任链模式处理消息
MsgHandler searchTaskHander = new SearchTasksMsgHandler();
MsgHandler robotMsgHandler = new RobotMsgHandler();
searchTaskHander.setSuccessor(robotMsgHandler);

data = searchTaskHander.handleRequest(fromOpnId, data);

WXTemplateMsgManager.sendMsg2User(fromOpnId,data);
}else if(msgType.equals("event") && event.equals("user_enter_tempsession")){
String data = "为你提供搜索、天气等一系列个性化服务,现在开始可以向我提问.";
WXTemplateMsgManager.sendMsg2User(fromOpnId,data);
}else{
String data = "不支持的消息";
WXTemplateMsgManager.sendMsg2User(fromOpnId,data);
}

return echostr;
}
 

 

4 个解决方案

#1


看起来挺不错的。 

#2


引用 1 楼 ydtpan 的回复:
看起来挺不错的。 


谢谢支持,最近又更新了两次,功能上更完善些

#3


谢谢楼主分享。。。。

#4


提醒的功能可以实现跨7天提醒吗
看微信的文档说明formId只有7天有效期

#1


看起来挺不错的。 

#2


引用 1 楼 ydtpan 的回复:
看起来挺不错的。 


谢谢支持,最近又更新了两次,功能上更完善些

#3


谢谢楼主分享。。。。

#4


提醒的功能可以实现跨7天提醒吗
看微信的文档说明formId只有7天有效期