java实现微信h5支付

话不多说直接上代码,首先是controller层代码

 @Autowired
 private IWxPayServiceH5 wxPayServiceH5;
 
 @ResponseBody
 @RequestMapping(value = "/wxpayH5.do" )
 public Message weixinPayWap(HttpServletRequest request, HttpServletResponse response){
  response.setHeader("Access-Control-Allow-Origin", "*");
  try{
   String orderNo = request.getParameter("orderNo");//订单号
   String notify_url  ="这里写回调页面";
   String tradeType = "MWEB";//H5支付交易类型
   return wxPayServiceH5.unifiedorderH5(request, orderNo, notify_url, tradeType );
  }catch(BusinessException e){
   logger.error("获取微信支付所需参数接口:业务异常【{}】", e.getMessage());
   return new Message(false, e.getMessage());
  }catch(Exception e){
   logger.error("获取微信支付所需参数接口:系统异常【{}】", e.getMessage());
   e.printStackTrace();
   return new Message(false, "系统异常");
  }
 }

下面是service层的代码

@Override
	public Message unifiedorderH5(HttpServletRequest request, String openid,
			String orderNo, String notify_url, String tradeType)
			throws Exception {
		logger.info("=====>Method:【unifiedorderH5】>>H5调用微信统一下单接口");
		// appid
		String appid = CodeTable.APPID;
		// 商户号
		String mch_id = CodeTable.SALE_MCH_ID;
		// 商户签名KEY
		String SIGNKEY = CodeTable.SALE_MCH_KEY;
		
		//上面的三个参数都是申请H5支付微信给的参数
		// 用户端ip
		String spbill_create_ip = WxPayInaddrUtil.getRealIp(request);
		
		// 随机数
		String nonce_str = WxPayMD5Util.getMessageDigest(String.valueOf(
				new Random().nextInt(10000)).getBytes());
		// 微信订单号为订单号
		String out_trade_no = orderNo;

		// 产品名称
		String body = "H5支付接口";
		// 金额
		String total_fee = "1";
		

		// 签名数据

		StringBuilder sb = new StringBuilder();

		sb.append("appid=" + appid);
		sb.append("&body=" + body);
		sb.append("&mch_id=" + mch_id);
		sb.append("&nonce_str=" + nonce_str);
		sb.append("&notify_url=" + notify_url);
		sb.append("&out_trade_no=" + out_trade_no);
		sb.append("&sign_type=" + "MD5");//这个开发文档上说不是必要参数,但是不加有时候会报错
		sb.append("&spbill_create_ip=" + spbill_create_ip);
		sb.append("&total_fee=" + total_fee);
		sb.append("&trade_type=" + tradeType);
		sb.append("&key=" + SIGNKEY);
		System.out.println("sb=>" + sb);

		// 签名MD5加密

		String sign = WxPayMD5Util.MD5Encode(sb.toString(), "UTF-8");
		System.out.println("sign=" + sign);

		if (StringUtils.isBlank(sign)) {
			logger.info("生成签名失败!");
			throw new BusinessException("生成支付签名失败!");
		}
		// 拼接请求xml(由于用实体拼接,拼接后的xml下划线会很长,所以用字符串拼接)
		Map<String, Object> map = new HashMap<String, Object>();
		String xml = "<xml>" +
		"<appid>" + appid + "</appid>" +
		"<mch_id>" + mch_id + "</mch_id>" +
		"<nonce_str>" + nonce_str + "</nonce_str>" +
		"<sign>" + sign + "</sign>" +
		"<body>" + body + "</body>"+ 
		"<out_trade_no>" + out_trade_no + "</out_trade_no>" +
		"<total_fee>" + total_fee + "</total_fee>"+
		"<trade_type>" + tradeType + "</trade_type>" +
		"<notify_url>" + notify_url + "</notify_url>"+
		"<sign_type>MD5</sign_type>" +
		"<spbill_create_ip>" + spbill_create_ip + "</spbill_create_ip>"+
		"</xml>";
		map.put("sign", sign);
		logger.info("请求下单接口,请求报文==【{}】", map);
		Message msg = postWeChatByStr(CodeTable.WXPAY_ORDER, xml);
		//WXPAY_ORDER = "https://api.mch.weixin.qq.com/pay/unifiedorder";//这是微信统一下单接口
		if (!msg.getResult()) {
			logger.info("请求核心异常");
			throw new BusinessException("请求核心异常");
		}
		// xml转实体
		ResultBean resultBean = (ResultBean) XstreamUtils.getBean(
				msg.getInfo(), ResultBean.class);
		if (resultBean == null) {
			logger.info("转换实体失败!");
			throw new BusinessException("转换实体失败!");
		}
		
		//转换实体可以不用,我是为了方便
		// 判断是否成功返回
		if ("SUCCESS".equals(resultBean.getReturn_code())
				&& "SUCCESS".equals(resultBean.getResult_code())) {
			logger.info("下单接口调用成功!");
			Map<String, Object> maps = new HashMap<String, Object>();
			String return_code = resultBean.getReturn_code();
			String return_msg = resultBean.getReturn_msg();
			String mweb_url = resultBean.getMweb_url();
			
			maps.put("return_code", return_code);
			maps.put("return_msg", return_msg);
			maps.put("mweb_url", mweb_url);
			//个人认为对于H5微信支付最重要的就是这个mweb_url
			return new Message(true, "生成微信支付参数成功!", maps);
		} else {
			logger.info("下单接口调用失败!");
			throw new BusinessException("下单接口调用失败!");
		}

	}

	/**
	 * 调用微信下单接口
	 * 
	 * @param interfaceCode
	 * @param paramStr
	 * @return
	 * @throws Exception
	 */
	private Message postWeChatByStr(String interfaceCode, String paramStr) {
		
		String URL = BaseConstantService.queryCanstant(interfaceCode);
		if (StringUtils.isNotBlank(URL)) {
			// 请求核心
			logger.info("请求微信:链接【{}】参数串【{}】", URL, paramStr);
			String json = HttpUtil.post(URL, paramStr, 30000);
			logger.info("请求微信:返回【{}】", json);
			// 返回结果非空校验
			if (StringUtils.isBlank(json)) {
				throw new BusinessException("微信返回结果为空");
			}
			return new Message(true, json);
		} else {
			throw new BusinessException("微信接口地址为空!或不符合格式!");
		}
	}

下面是用到的util

public class HttpUtil {
/**
	 * 
	 * @description 通过HTTP协议向服务器段发送请求,并得到返回结果,根据项目要求所有请求代码为UTF-8,请求地址必须用 URLEncoder.encode进行UTF-8转化。
	 * @param serviceUrl  服务器地址
	 * @param pMap       请求的键值对入参
	 * @return String 返回数据
	 */
	public static String post(String requestUrl, String para, int timeout) {
		String result = "";
		CloseableHttpClient httpclient = null;
		CloseableHttpResponse response = null;
		long start_time = System.currentTimeMillis();
		try {
			HttpPost httpPost = new HttpPost(requestUrl);
			httpPost.setConfig(getConfig(timeout));
			if (para != null && !para.trim().equals("")) {
				StringEntity reqEntity = new StringEntity(para, DEFAULT_CHARSET);
				reqEntity.setContentType("charset=" + DEFAULT_CHARSET);
				reqEntity.setContentEncoding(DEFAULT_CHARSET);
				httpPost.setEntity(reqEntity);
			}
			if(requestUrl.indexOf("https://") == 0){
				logger.info("根据请求地址【{}】转换访问方式成https",requestUrl);
				httpclient = createSSLClientDefault();
			}else{
				httpclient = createSSLClientDefaultBycrert(null, null);
			}
			response = httpclient.execute(httpPost);
			int statusCode = response.getStatusLine().getStatusCode();
			logger.info("执行http请求返回状态码【{}】,耗时【{}】", statusCode, (System.currentTimeMillis() - start_time));
			HttpEntity entity = response.getEntity();
			StringBuffer sb = new StringBuffer();
			if (entity != null) {
				BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(entity.getContent(), DEFAULT_CHARSET));
				String text = null;
				while ((text = bufferedReader.readLine()) != null) {
					sb.append(text);
				}
			}
			result = sb.toString();
			EntityUtils.consume(entity);
			
			if(statusCode != 200){
				logger.info("Http请求异常,返回码【{}】,返回内容【{}】", statusCode, result);
				return null;
			}
			return result;
		} catch (ConnectTimeoutException ex) {
			logger.error("执行http请求,发生异常。异常信息如下:", ex);
			throw new BusinessException("连接超时");
		}catch(SocketTimeoutException ex){
			logger.error("执行http请求,发生异常。异常信息如下:", ex);
			throw new MyTimeoutException("读取信息超时");
		}catch(Exception ex){
			logger.error("执行http请求,发生异常。异常信息如下:", ex);
			throw new BusinessException("系统正在维护中,请稍后再试");
		} finally {
			try {
				if (response != null) {
					response.close();
				}
				if (httpclient != null) {
					httpclient.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
			logger.info("根据请求地址【{}】返回信息【{}】,请求耗时【{}】", requestUrl, result, (System.currentTimeMillis() - start_time));
		}
	}
	
}


public class WxPayMD5Util {
/**
     * 返回大写MD5
     *
     * @param origin
     * @param charsetname
     * @return
     */
    public static String MD5Encode(String origin, String charsetname) {
        String resultString = null;
        try {
            resultString = new String(origin);
            MessageDigest md = MessageDigest.getInstance("MD5");
            if (charsetname == null || "".equals(charsetname))
                resultString = byteArrayToHexString(md.digest(resultString.getBytes()));
            else
                resultString = byteArrayToHexString(md.digest(resultString.getBytes(charsetname)));
        } catch (Exception exception) {
        }
        return resultString.toUpperCase();
    }
	
	
	public final static String getMessageDigest(byte[] buffer) {

		char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
				'a', 'b', 'c', 'd', 'e', 'f' };

		try {

			MessageDigest mdTemp = MessageDigest.getInstance("MD5");

			mdTemp.update(buffer);

			byte[] md = mdTemp.digest();

			int j = md.length;

			char str[] = new char[j * 2];

			int k = 0;

			for (int i = 0; i < j; i++) {

				byte byte0 = md[i];

				str[k++] = hexDigits[byte0 >>> 4 & 0xf];

				str[k++] = hexDigits[byte0 & 0xf];

			}

			return new String(str);

		} catch (Exception e) {

			return null;

		}

	}

}




public class WxPayInaddrUtil {
	/**
	 * 
	 * 获取真实ip地址 通过阿帕奇代理的也能获取到真实ip
	 * 
	 * @param request
	 * 
	 * @return
	 */

	public static String getRealIp(HttpServletRequest request) {

		String ip = request.getHeader("x-forwarded-for");

		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {

			ip = request.getHeader("Proxy-Client-IP");

		}

		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {

			ip = request.getHeader("WL-Proxy-Client-IP");

		}

		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {

			ip = request.getRemoteAddr();

		}

		return ip;

	}
}



页面的话在返回mweb_url 后不要直接访问这个链接,在当前页面用js

window.location.href = mweb_url

跳转就可以了

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值