上次写了一篇微信支付的文章,倒也还行就是逻辑上面有点欠妥当,这次针对这个问题我用struts2写了一套用于微信验证并能处理各种消息以及H5支付的一套程序,也针对分享到朋友圈这个功能使用了微信的jssdk,感触特别深,废话不多说下面就开始分享我的心得

一   微信如何和struts2整合

针对这个问题,网上基本没有这方面的资料,因此本人也就特别想针对这方面写篇博客,网上没资料其实道理很简单,首先java开发微信应用本身就比较少,市场都被php占领了;还有就是struts2的原因,目前市面上大家熟知的springmvc大大的挤压了struts的空间。所以.......

1  struts2整合微信的注意事项

struts2本身其实就是一个控制器,微信开发首先就是服务器配置那个部分的验证(使用GET请求)以及各种常用消息的接收和回复(POST)请求,因此只需在struts2里写方法暴露给微信服务器访问就OK,这个方法只要区分出GET和POST两种请求就行,GET请求就调用微信验证的相应方法,POST请求就调用消息处理的方法。这样就搞定了,来看下我的方法

package com.debug.weixin.action;import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.Map;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import org.apache.struts2.ServletActionContext;import com.debug.weixin.service.CoreService;
import com.debug.weixin.util.MessageUtil;
import com.debug.weixin.util.SignUtil;
import com.opensymphony.xwork2.ActionContext;public class WeixinAction {public void execute() {HttpServletRequest request = ServletActionContext.getRequest();HttpServletResponse response = ServletActionContext.getResponse();// 判断请求方法是get还是postString method = request.getMethod().trim();if ("get".equalsIgnoreCase(method)) {wxCheck(request, response);} else if ("post".equalsIgnoreCase(method)) {try {processRequest(request, response);} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}}public void wxCheck(HttpServletRequest request, HttpServletResponse response) {// 微信加密签名String signature = request.getParameter("signature");// 时间戳String timestamp = request.getParameter("timestamp");// 随机数String nonce = request.getParameter("nonce");// 随机字符串String echostr = request.getParameter("echostr");PrintWriter out = null;try {out = response.getWriter();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}// 通过检验signature对请求进行校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败if (SignUtil.checkSignature(signature, timestamp, nonce)) {out.print(echostr);}out.close();out = null;}public void processRequest(HttpServletRequest request, HttpServletResponse response) throws Exception{request.setCharacterEncoding("UTF-8");  response.setCharacterEncoding("UTF-8");  String encryptType = request.getParameter("encrypt_type");  // 微信加密签名  String signature = request.getParameter("signature");  // 时间戳  String timestamp = request.getParameter("timestamp"); // 随机数  String nonce = request.getParameter("nonce");  // 响应消息  try{PrintWriter out = response.getWriter(); if (SignUtil.checkSignature(signature, timestamp, nonce)) {  Map<String, String> requestMap = null;  if("aes".equals(encryptType)){requestMap=MessageUtil.parseXmlCrypt(request);String respXml=CoreService.processRequest(requestMap); respXml=MessageUtil.getWxCrypt().encryptMsg(respXml,timestamp,nonce);//System.out.println(respXml);out.print(respXml);  }else{requestMap=MessageUtil.parseXml(request);String respXml=CoreService.processRequest(requestMap); //respXml=MessageUtil.getWxCrypt().encryptMsg(respXml,timestamp,nonce);out.print(respXml);//System.out.println(respXml);}// 调用核心业务类接收消息、处理消息  //String respMessage = CoreService.processRequest(request);  out.close();  }  }catch(Exception e){e.printStackTrace();}}}

这个action还支持密文消息模式,下面就是struts的配置文件了:

<package name="weixin" namespace="/" extends="struts-default">     <action name="weixin" class="com.debug.weixin.action.WeixinAction">  </action>  </package>  

对,你没有看错就是这么的简单。只要肯研究微信开发者文档,没什么事写不出来的

二   struts2版微信实现H5支付

微信H5支付其实是3种支付方式之中,最简单的一种,难点是取得openId和生成微信支付签名2个部分,下面我拆分开来说一下

为了简化操作我写了一个表单,只需填写订单号,提交之后取得openId之后直接调用统一下单接口跳转到支付确认界面

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><base href="<%=basePath%>"><title>提交订单</title><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0"><meta name="description" content="admin-themes-lab"><meta name="author" content="themes-lab"><!--<link rel="stylesheet" type="text/css" href="styles.css">--></head><body><form action="order/order_payConfirm.action" method="POST">订单号:<input name="orderNo" id="orderNo" value="HK2015012315"/><br/><input type="submit" value="提交订单"/></form></body>
</html>

接下来是Action里的代码

package com.debug.weixin.action;import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import net.sf.json.JSONObject;import org.apache.struts2.ServletActionContext;import com.debug.weixin.pojo.WeixinOauth2Token;
import com.debug.weixin.util.AdvancedUtil;
import com.debug.weixin.util.CommonUtil;
import com.debug.weixin.util.ConfigUtil;
import com.debug.weixin.util.PayCommonUtil;
import com.debug.weixin.util.XMLUtil;public class OrderAction extends BaseAction{public String orderIndex(){//HttpServletRequest request = ServletActionContext.getRequest();//HttpServletResponse response = ServletActionContext.getResponse();return "orderIndex";}public void payConfirm() throws Exception{HttpServletRequest request = ServletActionContext.getRequest();HttpServletResponse response = ServletActionContext.getResponse();String orderNo=request.getParameter("orderNo");response.sendRedirect(initOpenId("http://chenwill3.imwork.net/StrutsWX/order/order_h5Pay.action?orderNo="+orderNo));}public void paySuccess() throws Exception{HttpServletRequest request = ServletActionContext.getRequest();HttpServletResponse response = ServletActionContext.getResponse();//这里处理订单InputStream inStream = request.getInputStream();ByteArrayOutputStream outSteam = new ByteArrayOutputStream();byte[] buffer = new byte[1024];int len = 0;while ((len = inStream.read(buffer)) != -1) {outSteam.write(buffer, 0, len);}outSteam.close();inStream.close();String result  = new String(outSteam.toByteArray(),"utf-8");//获取微信调用我们notify_url的返回信息Map<Object, Object> map = XMLUtil.doXMLParse(result);for(Object keyValue : map.keySet()){System.out.println(keyValue+"="+map.get(keyValue));}if (map.get("result_code").toString().equalsIgnoreCase("SUCCESS")) {String orderNo=map.get("out_trade_no").toString();response.getWriter().write(PayCommonUtil.setXML("SUCCESS", ""));   //告诉微信服务器,我收到信息了,不要在调用回调action了System.out.println("-------------"+PayCommonUtil.setXML("SUCCESS", ""));}}public String h5Pay() throws Exception{HttpServletRequest request = ServletActionContext.getRequest();HttpServletResponse response = ServletActionContext.getResponse();String orderNo=request.getParameter("orderNo");String code=request.getParameter("code");WeixinOauth2Token token=AdvancedUtil.getOauth2AccessToken(ConfigUtil.APPID, ConfigUtil.APP_SECRECT, code);SortedMap<Object, Object> parameters = new TreeMap<Object, Object>();parameters.put("appid", ConfigUtil.APPID);parameters.put("mch_id", ConfigUtil.MCH_ID);parameters.put("device_info", "1000");  parameters.put("body", "测试支付订单");parameters.put("nonce_str", PayCommonUtil.CreateNoncestr());parameters.put("out_trade_no", orderNo);//parameters.put("total_fee", String.valueOf(combo.getPrice()*100));parameters.put("total_fee", "1");parameters.put("spbill_create_ip", request.getRemoteAddr());parameters.put("notify_url", ConfigUtil.NOTIFY_URL);parameters.put("trade_type", "JSAPI");parameters.put("openid", token.getOpenId());String sign = PayCommonUtil.createSign("UTF-8", parameters);//System.out.println("我 的签名是:"+sign);  parameters.put("sign", sign);String requestXML = PayCommonUtil.getRequestXml(parameters);String result = CommonUtil.httpsRequestForString(ConfigUtil.UNIFIED_ORDER_URL,"POST", requestXML);System.out.println("----------------------------------");System.out.println(result);System.out.println("----------------------------------");String m=getH5PayStr(result,request);request.setAttribute("h5Info", m);return "wxPay";}
}

这个Action里最主要的方法是payConfirm和paySuccess,payConfirm调用之后会跳转到h5Pay这个方法,之后调用统一下单接口,调用之后进入支付确认界面,该界面的jsp代码如下

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><base href="<%=basePath%>"><title>H5订单支付</title><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0"><meta name="description" content="admin-themes-lab"><meta name="author" content="themes-lab"><!--<link rel="stylesheet" type="text/css" href="styles.css">--></head><script type="text/javascript">function jsApiCall(){WeixinJSBridge.invoke('getBrandWCPayRequest',${h5Info}, function(res){WeixinJSBridge.log(res.err_msg);//alert(res.err_code+res.err_desc+res.err_msg);if(res.err_msg == "get_brand_wcpay_request:ok" ) {  alert("恭喜你,购买成功!");}else{  alert("支付失败了,请联系商户!");}  });}function callpay(){if (typeof WeixinJSBridge == "undefined"){if( document.addEventListener ){document.addEventListener('WeixinJSBridgeReady', jsApiCall, false);}else if (document.attachEvent){document.attachEvent('WeixinJSBridgeReady', jsApiCall); document.attachEvent('onWeixinJSBridgeReady', jsApiCall);}}else{jsApiCall();}}</script><body><input type="button" value="确认支付" οnclick="callpay()"/></body>
</html>

这样支付流程就走通了,下面贴出BaseAction的2个主要方法:

public String initOpenId(String destUrl) throws Exception {String re = URLEncoder.encode(destUrl, "UTF-8");String url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect";url = url.replace("APPID", ConfigUtil.APPID);url = url.replace("REDIRECT_URI", re);return url;}public String getH5PayStr(String result,HttpServletRequest request) throws Exception{Map<String, String> map = XMLUtil.doXMLParse(result);SortedMap<Object,Object> params = new TreeMap<Object,Object>();params.put("appId", ConfigUtil.APPID);params.put("timeStamp", Long.toString(new Date().getTime()));params.put("nonceStr", PayCommonUtil.CreateNoncestr());params.put("package", "prepay_id="+map.get("prepay_id"));params.put("signType", ConfigUtil.SIGN_TYPE);String paySign =  PayCommonUtil.createSign("UTF-8", params);params.put("packageValue", "prepay_id="+map.get("prepay_id"));    //这里用packageValue是预防package是关键字在js获取值出错params.put("paySign", paySign);                                                          //paySign的生成规则和Sign的生成规则一致params.put("sendUrl", ConfigUtil.SUCCESS_URL);                               //付款成功后跳转的页面String userAgent = request.getHeader("user-agent");char agent = userAgent.charAt(userAgent.indexOf("MicroMessenger")+15);params.put("agent", new String(new char[]{agent}));//微信版本号,用于前面提到的判断用户手机微信的版本是否是5.0以上版本。String json = JSONObject.fromObject(params).toString();return json;}

第一个方法是按照获取openid的API写的方法,这个不解释,理解不了只能去看微信开发文档了;第二个方法是拼接用于H5支付的json串

关于支付来最后看下运行截图:

下面就是支付时的截图

到这里支付相关的代码就完结了

三  分享到朋友圈功能(使用JSSDK)

难点:取得AccessToken、取得JSAPITicket、生成jssdk签名

1  取得jsapiticket

accessToken的获取之前已经写过博客,这里直接进入取得jsapiticket的流程,java代码如下

public static JSAPITicket getJsApiTicket(String accessToken){String requestUrl="https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";requestUrl=requestUrl.replace("ACCESS_TOKEN", accessToken);JSONObject json=CommonUtil.httpsRequest(requestUrl, "GET", null);JSAPITicket js=new JSAPITicket();js.setTicket(json.getString("ticket"));js.setExpires_in(json.getInt("expires_in"));return js;
}

有关JSAPITicket方法的代码如下

package com.debug.weixin.pojo;public class JSAPITicket {private String ticket;private int expires_in;public String getTicket() {return ticket;}public void setTicket(String ticket) {this.ticket = ticket;}public int getExpires_in() {return expires_in;}public void setExpires_in(int expiresIn) {expires_in = expiresIn;}
}

2 生成jssdk的签名

微信提供了一个生成签名的方法,我这边使用的代码和微信提供的形式上有点差异,但效果是一样的,下面是生成签名的方法

package com.debug.weixin.util;import java.util.Arrays;
import java.util.UUID;
import java.util.Map;
import java.util.HashMap;
import java.util.Formatter;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;  public class JSSDKSign {public static Map<String, Object> sign(String jsapi_ticket, String url) {Map<String, Object> ret = new HashMap<String, Object>();String nonce_str = create_nonce_str();String timestamp = create_timestamp();String[] paramArr = new String[] { "jsapi_ticket=" + jsapi_ticket,"timestamp=" + timestamp, "noncestr=" + nonce_str, "url=" + url};Arrays.sort(paramArr);// 将排序后的结果拼接成一个字符串String content = paramArr[0].concat("&"+paramArr[1]).concat("&"+paramArr[2]).concat("&"+paramArr[3]);String gensignature = null;try {MessageDigest md = MessageDigest.getInstance("SHA-1");// 对拼接后的字符串进行 sha1 加密byte[] digest = md.digest(content.toString().getBytes());gensignature = byteToStr(digest);} catch (NoSuchAlgorithmException e) {e.printStackTrace();}ret.put("url", url);ret.put("jsapi_ticket", jsapi_ticket);ret.put("nonceStr", nonce_str);ret.put("timestamp", Long.parseLong(timestamp));ret.put("signature", gensignature);return ret;}private static String byteToStr(byte[] byteArray) {String strDigest = "";for (int i = 0; i < byteArray.length; i++) {strDigest += byteToHexStr(byteArray[i]);}return strDigest;}private static String byteToHexStr(byte mByte) {char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a','b', 'c', 'd', 'e', 'f' };char[] tempArr = new char[2];tempArr[0] = Digit[(mByte >>> 4) & 0X0F];tempArr[1] = Digit[mByte & 0X0F];String s = new String(tempArr);return s;}private static String byteToHex(final byte[] hash) {Formatter formatter = new Formatter();for (byte b : hash){formatter.format("%02x", b);}String result = formatter.toString();formatter.close();return result;}private static String create_nonce_str() {return UUID.randomUUID().toString();}private static String create_timestamp() {return Long.toString(System.currentTimeMillis() / 1000);}
}

其实也就是自己加了几个方法,当然了用微信提供的sign方法也是OK的,如果微信自带的有问题,可以用我的

3 展示界面代码如下

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><title>分享到朋友圈</title><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0"><meta name="description" content="admin-themes-lab"><meta name="author" content="themes-lab"><!--<link rel="stylesheet" type="text/css" href="styles.css">--><script type="text/javascript" src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script><script type="text/javascript" src="jquery.min.js"></script></head><script type="text/javascript">$(document).ready(function(){
initPage();
});
function initPage() {
//alert(window.location.href);/***用于获得当前连接url用**/
/***用户点击分享到微信圈后加载接口接口*******/
$.post("jssdk_getJSPara.action",{"url":'http://chenwill3.imwork.net/StrutsWX/jssdk_toSharePage.action'},function(data,status){wx.config({debug: true,appId: '你的appId',timestamp:Number(data.timestamp),nonceStr:data.nonceStr,signature:data.signature,jsApiList: ['checkJsApi','onMenuShareTimeline','hideOptionMenu']});});wx.ready(function(){wx.checkJsApi({jsApiList: ['onMenuShareTimeline',]});wx.onMenuShareTimeline({title: '互联网之子',link: 'http://wx.vland.cc/mobile.php?act=module&rid=406&fromuser=oktsYuHivHXuzdsMeCbWyF7b14UU&name=hllihe&do=sharelihe&weid=7',imgUrl: 'http://wx.vland.cc/resource/attachment/images/7/2015/01/fl2Lk2p5o3iOJP3jdp9iPXI9i93iPm.jpg',trigger: function (res) {alert('用户点击分享到朋友圈');},success: function (res) {alert('已分享');},cancel: function (res) {alert('已取消');},fail: function (res) {alert('wx.onMenuShareTimeline:fail: '+JSON.stringify(res));}});});};
function share(){}</script><body><input type="button" value="分享" οnclick="share()"/></body>
</html>

值得一提的是开发的时候千万不能想着通过自己界面上的按钮点击,之后调用分享到朋友圈的js,这种做法绝对禁止(只有点微信浏览器右上方的那个选项才能触发)

出现这样的alert说明jssdk配置成功了,为了保险起见一般还要判断下微信浏览器是否支持分享到朋友圈

接下来就是点右上方的分享到朋友圈测功能了

输入内容点发送就OK

最后打开朋友圈就能看到分享的东西了

一般情况下这种场景是用在点分享到朋友圈要分享值得内容的功能,正常情况或没特别定制性要求的应用可能用不到,使用jssdk要注意配置这里:

如果是微信支付要配置网页账号和微信支付开发配置

微信支付开发配置一般如下

微信支付和分享到朋友圈-struts版本相关推荐

  1. 微信JS接口 分享到朋友圈 分享给朋友 分享到QQ 拍照或从手机相册中选图 识别音频并返回识别结果 使用微信内置地图查看位置

    微信JS接口 微信JS接口 分享到朋友圈 分享给朋友 分享到QQ 拍照或从手机相册中选图 识别音频并返回识别结果 使用微信内置地图查看位置 来源:http://www.cnblogs.com/txw1 ...

  2. 微信jsapi上传图片php,PHP+MySQL微信通过jsapi分享到朋友圈等平台,实现设置图片、链接...

    问题背景: 微信开发是目前程序开发领域一个比较火热的板块,基于公众号.微信支付等开发层出不穷,纷繁多彩,今天这里就基于微信开发的另外一个小版块,微信网页内分享到朋友圈等平台灵活设置链接和小图标(见下图 ...

  3. golang-vue实现微信小程序分享到朋友圈

    最近涉及到微信小程序分享到朋友圈,不知道微信为什么不直接接口分享,咱也不敢佛,咱也不敢问,只能百度问度娘,看官方文档,网上的一些分享五花八门,每一个重点的,所以整理了一下到底怎样生成二维码分享图片才是 ...

  4. android微信分享走小程序流程,教你怎么把微信小程序分享到朋友圈

    教你怎么把微信小程序分享到朋友圈 2020年07月13日 | 萬仟网移动技术 | 我要评论 7月8日收到邀请,可将小程序页面分享到朋友圈.适用于内容型页面的分享,不适用于有较多交互的页面分享.该功能为 ...

  5. 解决 ios 微信小程序分享到朋友圈 禁用问题

    微信小程序分享到朋友圈 显示当前页面的转发按钮 显示当前页面的转发按钮 wx.showShareMenu 配置当前页面的转发按钮. onLoad(){wx.showShareMenu({withSha ...

  6. 微信公众平台 分享到朋友圈 js代码

    前言:1目前必须是被微信认证过的公众平台才能使用此接口 1.绑定域名 2.引用文件 http://res.wx.qq.com/open/js/jweixin-1.0.0.js 3配置前台js配置 va ...

  7. Swift - 发送消息(文本,图片,文件等)给微信好友或分享到朋友圈

    通过调用微信提供的API接口,我们可以很方便的在应用中发送消息给微信好友,或者分享到朋友圈.在微信开发平台(https://open.weixin.qq.com)里,提供了详细的说明文档和样例.但由于 ...

  8. uniapp 微信小程序分享给微信好友与分享到朋友圈功能

    微信小程序分享 使用方法: onLoad(){wx.showShareMenu({withShareTicket:true,//设置下方的Menus菜单,才能够让发送给朋友与分享到朋友圈两个按钮可以点 ...

  9. 微信小程序分享到朋友圈,在朋友圈打开报错 error code -501023

    未登录模式 | 微信开放文档 未登录模式即无登录态的模式,在未登录模式中,不存在用户的登录态.未登录模式的场景有如: 单页模式:小程序/小游戏分享到朋友圈被打开时 Web 未登录模式:没有登录的 We ...

  10. 微信小程序分享到朋友圈方法与技巧

    来源 | https://www.cnblogs.com/MohunBlogs/archive/2018/05/23/9079942.html 小程序提供onShareAppMessage 函数,此函 ...

最新文章

  1. (译)如何使用box2d来做碰撞检测(且仅用来做碰撞检测)
  2. Prima Cartoonizer中文版
  3. mysql 删除外键
  4. 华为ac控制器web配置手册_家庭WIFI网络规划设计与配置实战,一文教会你
  5. python白森_氧气恋人
  6. Python(20)-高级数据类型的公共方法
  7. C++笔记-基于邻接矩阵的BFS(宽度优先遍历)
  8. 期货市场技术分析05_交易量和持仓兴趣
  9. sql 在某表中加入一列count所有数据_执行COUNT(1)、COUNT(*) 与 COUNT(列名) 到底有什么区别?...
  10. linkscrpit
  11. xshell安装mysql步骤_xshell怎么搭建mysql
  12. c++14 0 名字空间和条件编译
  13. 华为主题锁屏壁纸换不掉_华为手机总出现一些不明照片咋回事,原来你没关闭这个默认设置...
  14. ios签名php在线监控,IOS无需签名无需越狱H5网页在线封装APP教程
  15. 设备划分冲突域和广播域
  16. 为什么Redis 单线程却能支撑高并发?
  17. 树莓派Pico开发板硬件扩展接口及电源模块解析
  18. MySQL 网站上的 GA 是什么意思?
  19. 网易云音乐评论 可视化分析
  20. [转] Phun,让人惊讶的小程序

热门文章

  1. 揭秘强开微粒贷骗局 看完你就明白了
  2. 定义一个接口ITest,接口中有3个抽象方法如下。
  3. hyd.modify
  4. 数据库技术-数据库概念设计
  5. Microsoft Word 论文编排技巧
  6. Ubuntu16.04系统美化
  7. Java实现多文件生成压缩包下载
  8. TSP_旅行商问题 - 遗传算法(四)
  9. 添加企业微信免验证设置
  10. 经典网络-InceptionV1论文及实践