轻源码

  • QingYuanMa.com
  • 全球最大的互联网技术和资源下载平台
搜索
一起源码网 门户 终极进阶 查看主题

微信小程序开发我遇到的一些坑和建议:智能客服的实现,提醒的实现,支付实现(JAVA) ...

发布者: y.l.m | 发布时间: 2018-1-12 03:54| 查看数: 5225| 评论数: 1|帖子模式

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

主要功能:

  • 支付接口调测:点击支持我们,可以直接捐赠;
  • 提醒功能:主要使用客服通知以及微信小卡片通知;
  • 自定义账本字段:主要就各种Event的Tag可以扩展字段;
  • 文件上传下载:支持事件上传图片,录音文件;

首先要做到上面这些,后台必须要从小程序平台得到的信息如下图:

准备工作就绪,讲讲我开发这个小程序遇到的一些问题以及相应实现吧

前端问题

  • 高度不能用rpx,不然无法计算以及自适应,所以我后来改成了px,不知道有没有更好的方案;
  • 首页应该要验证token合法性,要去服务器请求验证,这个过程是异步的,所以在载入首页之前应该有个splash过渡窗口引导,不然进入首页token非法的就将无法请求到数据,不知道有没有更好的方案;
  • 排版布局使用的是weui,不知道还有没有更好的wxss可以使用;
  • 由于异步调用多会乱,所以后来引入的Promise,好很多;

后台问题

支付实现; 
支付微信为了安全性,增加了数字签名,首先你要发起一个订单,得到订单号,有了这个订单号,就可以启动微信支付功能了,以下是代码:

  1. public JSONObject prePay() throws Exception{
  2. UserBean ub = getWxUser();
  3. if(ub!=null){
  4. String appid = (StrUtil.formatNullStr(TagConst.globalMap.get("wx.appid")));
  5. String appkey = (StrUtil.formatNullStr(TagConst.globalMap.get("wx.seckey")));
  6. String mch_id = (StrUtil.formatNullStr(TagConst.globalMap.get("wx.mchid")));
  7. String mchkey = (StrUtil.formatNullStr(TagConst.globalMap.get("wx.mchkey")));
  8. String openId = ub.getUid();
  9. String clientIP = HttpUtils.getIP(request);
  10. if(clientIP.indexOf(":")>0) clientIP = "127.0.0.1";
  11. String fee = StrUtil.formatNullStr(request.getParameter("fee"),"1");
  12. String body = StrUtil.formatNullStr(request.getParameter("body"));
  13. String atta = StrUtil.formatNullStr(request.getParameter("atta"));
  14. String nonce_str = UUIDHexGenerator.generate();
  15. String today = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
  16. String code = PayUtil.createCode(8);
  17. String out_trade_no = mch_id+today+code;//商户订单号
  18. String spbill_create_ip = clientIP;//终端IP
  19. String trade_type = "JSAPI";//交易类型
  20. String openid=openId;//用户标识
  21. /**/
  22. PayInfo paymentPo = new PayInfo();
  23. paymentPo.setAppid(appid);
  24. paymentPo.setMch_id(mch_id);
  25. paymentPo.setNonce_str(nonce_str);
  26. paymentPo.setBody(body);
  27. paymentPo.setOut_trade_no(out_trade_no);
  28. paymentPo.setTotal_fee(fee);
  29. paymentPo.setSpbill_create_ip(spbill_create_ip);
  30. paymentPo.setNotify_url(URL_NOTIFY);
  31. paymentPo.setTrade_type(trade_type);
  32. paymentPo.setOpenid(openid);
  33. // 把请求参数打包成数组
  34. Map<String, String> sParaTemp = new HashMap<String, String>();
  35. sParaTemp.put("appid", paymentPo.getAppid());
  36. sParaTemp.put("mch_id", paymentPo.getMch_id());
  37. sParaTemp.put("nonce_str", paymentPo.getNonce_str());
  38. sParaTemp.put("body", paymentPo.getBody());
  39. sParaTemp.put("out_trade_no", paymentPo.getOut_trade_no());
  40. sParaTemp.put("total_fee",paymentPo.getTotal_fee());
  41. sParaTemp.put("spbill_create_ip", paymentPo.getSpbill_create_ip());
  42. sParaTemp.put("notify_url",paymentPo.getNotify_url());
  43. sParaTemp.put("trade_type", paymentPo.getTrade_type());
  44. sParaTemp.put("openid", paymentPo.getOpenid());
  45. // 除去数组中的空值和签名参数
  46. Map<String, String> sPara = PayUtil.paraFilter(sParaTemp);
  47. String prestr = PayUtil.createLinkString(sPara); // 把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串
  48. String key = "&key="+mchkey; // 商户支付密钥
  49. //MD5运算生成签名
  50. String mysign = PayUtil.sign(prestr, key, "utf-8").toUpperCase();
  51. paymentPo.setSign(mysign);
  52. String respXml = MessageUtil.messageToXML(paymentPo);
  53. respXml = respXml.replace("__", "_");
  54. String url = "";
  55. String param = respXml;
  56. String result =PayUtil.httpRequest(url, "POST", param);
  57. Map<String, String> map = new HashMap<String, String>();
  58. InputStream in=new ByteArrayInputStream(result.getBytes());
  59. // 读取输入流
  60. SAXReader reader = new SAXReader();
  61. Document document = reader.read(in);
  62. Element root = document.getRootElement();
  63. List<Element> elementList = root.elements();
  64. for (Element element : elementList) {
  65. map.put(element.getName(), element.getText());
  66. }
  67. // 返回信息
  68. String return_code = map.get("return_code");
  69. String return_msg = map.get("return_msg");
  70. JSONObject jsonObject=new JSONObject() ;
  71. if(return_code=="SUCCESS"||return_code.equals(return_code)){
  72. String prepay_id = map.get("prepay_id");
  73. jsonObject.put("nonceStr", nonce_str);
  74. jsonObject.put("package", "prepay_id="+prepay_id);
  75. Long timeStamp= System.currentTimeMillis()/1000;
  76. jsonObject.put("timeStamp", timeStamp+"");
  77. String stringSignTemp = "appId="+appid+"&nonceStr=" + nonce_str + "&package=prepay_id=" + prepay_id+ "&signType=MD5&timeStamp=" + timeStamp;
  78. String paySign=PayUtil.sign(stringSignTemp, "&key="+mchkey, "utf-8").toUpperCase();
  79. jsonObject.put("paySign", paySign);
  80. return jsonObject;
  81. }
  82. }
  83. return null;
  84. }

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

  1. public static void sendMsgCard(String openId,String formId,String time,String title,String description ){
  2. String temp_id = StrUtil.formatNullStr(TagConst.globalMap.get("wx.template.notify"));
  3. String dataKeyWorks = "{";
  4. dataKeyWorks += "\"keyword1\":{\"color\":\"#173177\",\"value\":\""+time+"\"},";
  5. dataKeyWorks += "\"keyword2\":{\"color\":\"#173177\",\"value\":\""+title+"\"},";
  6. dataKeyWorks += "\"keyword3\":{\"color\":\"#173177\",\"value\":\""+description+"\"}";
  7. dataKeyWorks += "}";
  8. String json = "{"+
  9. "\"touser\":\""+openId+"\","+
  10. "\"template_id\":\""+temp_id+"\","+
  11. "\"page\":\"pages/index/index\","+
  12. "\"form_id\":\""+formId+"\","+
  13. "\"data\":"+dataKeyWorks+""+
  14. "}";
  15. String url = "" + getMsgToken();
  16. String result =PayUtil.httpRequest(url, "POST", json);
  17. }
  18. public static void sendMsgCard(String date,String openId,String formId,String time,String title,String description ){
  19. String temp_id = StrUtil.formatNullStr(TagConst.globalMap.get("wx.template.notify"));
  20. String dataKeyWorks = "{";
  21. dataKeyWorks += "\"keyword1\":{\"color\":\"#173177\",\"value\":\""+time+"\"},";
  22. dataKeyWorks += "\"keyword2\":{\"color\":\"#173177\",\"value\":\""+title+"\"},";
  23. dataKeyWorks += "\"keyword3\":{\"color\":\"#173177\",\"value\":\""+description+"\"}";
  24. dataKeyWorks += "}";
  25. String json = "{"+
  26. "\"touser\":\""+openId+"\","+
  27. "\"template_id\":\""+temp_id+"\","+
  28. "\"page\":\"pages/index/index?dt="+date.split(" ")[0]+"\","+
  29. "\"form_id\":\""+formId+"\","+
  30. "\"data\":"+dataKeyWorks+""+
  31. "}";
  32. String url = "" + getMsgToken();
  33. String result =PayUtil.httpRequest(url, "POST", json);
  34. }
  35. public static void sendMsg2User(String openId,String data){
  36. String json = "{"+
  37. "\"touser\":\""+openId+"\","+
  38. "\"msgtype\":\"text\","+
  39. "\"text\":"+
  40. "{"+
  41. "\"content\":\""+data+"\""+
  42. "}"+
  43. "}";
  44. String url = "" + getMsgToken();
  45. String result =PayUtil.httpRequest(url, "POST", json);
  46. }
  47. private static long lastTime = 0;
  48. private static String accessToken = "";
  49. private static String getMsgToken(){
  50. if(lastTime>0 && ((new Date().getTime()-lastTime)<6000*1000)){
  51. return accessToken;
  52. }
  53. String url = ""+
  54. StrUtil.formatNullStr(TagConst.globalMap.get("wx.appid"))+"&secret=" + StrUtil.formatNullStr(TagConst.globalMap.get("wx.seckey"));
  55. String retStr = PayUtil.httpRequest(url, "GET", null);
  56. JSONObject json = JSON.parseObject(retStr);
  57. if(json!=null){
  58. lastTime = new Date().getTime();
  59. accessToken = StrUtil.formatNullStr(json.get("access_token"));
  60. }
  61. return accessToken;
  62. }

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

  1. //接入在线客服的token固定值
  2. public String wx_getmsg() throws Exception{
  3. String token = StrUtil.formatNullStr(TagConst.globalMap.get("wx.contact.token"));
  4. String contactKey = StrUtil.formatNullStr(TagConst.globalMap.get("wx.contact.seckey"));
  5. String signature = StrUtil.formatNullStr(request.getParameter("signature"));
  6. String timestamp = StrUtil.formatNullStr(request.getParameter("timestamp"));
  7. String nonce = StrUtil.formatNullStr(request.getParameter("nonce"));
  8. String echostr = StrUtil.formatNullStr(request.getParameter("echostr"));
  9. String _signature = SHA1.getSHA1(token, timestamp, nonce);
  10. if (!signature.equals(_signature)) {
  11. throw new AesException(AesException.ValidateSignatureError);
  12. }
  13. //发来消息的用户ID
  14. String openid = StrUtil.formatNullStr(request.getParameter("openid"));
  15. String encrypt_type=StrUtil.formatNullStr(request.getParameter("encrypt_type"));
  16. String msg_signature=StrUtil.formatNullStr(request.getParameter("msg_signature"));
  17. WXBizMsgCrypt pc = new WXBizMsgCrypt(token, contactKey, StrUtil.formatNullStr(TagConst.globalMap.get("wx.appid")));
  18. InputStream is = request.getInputStream();
  19. ByteArrayOutputStream out = new ByteArrayOutputStream(10240);
  20. org.apache.commons.io.IOUtils.copy(is, out);
  21. String jsonStr = new String(out.toByteArray(), request.getCharacterEncoding());
  22. String result2 = pc.decryptMsg(msg_signature, timestamp, nonce, jsonStr);
  23. DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
  24. DocumentBuilder db = dbf.newDocumentBuilder();
  25. Document document = db.parse(new InputSource(new ByteArrayInputStream(result2.getBytes("utf-8"))));
  26. Element root = document.getDocumentElement();
  27. NodeList nodelist1 = root.getElementsByTagName("MsgType");
  28. NodeList nodelist2 = root.getElementsByTagName("Content");
  29. NodeList eventNodelist = root.getElementsByTagName("Event");
  30. NodeList nodelist3 = root.getElementsByTagName("FromUserName");
  31. String msgType = nodelist1.item(0).getTextContent();
  32. String content = (nodelist2!=null && nodelist2.item(0)!=null) ? nodelist2.item(0).getTextContent() : "";
  33. String fromOpnId = nodelist3.item(0).getTextContent();
  34. String event = (eventNodelist!=null && eventNodelist.item(0)!=null) ? eventNodelist.item(0).getTextContent() : "";
  35. if(msgType.equals("text")){
  36. String data = "Sorry,我不能理解您的指令!";
  37. //责任链模式处理消息
  38. MsgHandler searchTaskHander = new SearchTasksMsgHandler();
  39. MsgHandler robotMsgHandler = new RobotMsgHandler();
  40. searchTaskHander.setSuccessor(robotMsgHandler);
  41. data = searchTaskHander.handleRequest(fromOpnId, data);
  42. WXTemplateMsgManager.sendMsg2User(fromOpnId,data);
  43. }else if(msgType.equals("event") && event.equals("user_enter_tempsession")){
  44. String data = "为你提供搜索、天气等一系列个性化服务,现在开始可以向我提问.";
  45. WXTemplateMsgManager.sendMsg2User(fromOpnId,data);
  46. }else{
  47. String data = "不支持的消息";
  48. WXTemplateMsgManager.sendMsg2User(fromOpnId,data);
  49. }
  50. return echostr;
  51. }

最新评论

bichao520 发表于 2022-5-9 19:12
源码下载教程

轻源码让程序更轻更快

QingYuanMa.com

工作时间 周一至周六 8:00-17:30

侵权处理

客服QQ点击咨询

关注抖音号

定期抽VIP

Copyright © 2016-2021 https://www.171739.xyz/ 滇ICP备13200218号

快速回复 返回顶部 返回列表