公众号微信支付

 微信开发平台 微信支付官方文档:https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_1

package com.qike.webapp.controller;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.qike.sys.entity.AppOrders;
import com.qike.sys.service.IAppOrdersService;
import com.qike.user.entity.UserInfo;
import com.qike.user.service.IUserInfoService;
import com.qike.utils.BigDecimalUtil;
import com.qike.utils.ShortUUIDUtil;
import com.qike.utils.pay.AppWxPayConfig;
import com.qike.utils.pay.HttpRequest;
import com.qike.utils.pay.WXPayUtil;
import com.qike.webapp.response.ResponseData;
import com.qike.webapp.service.IUserUpgradeService;
import com.qike.webapp.vo.AppAlipayVO;
import com.sun.istack.internal.logging.Logger;

/**
 * 
 * @author liuqiyu
 * @date 2018年12月6日
 */
@Controller
@RequestMapping("/user/wxpay")
public class AppWxPayController {
	// log
	private static final Logger logger = Logger.getLogger(AppWxPayController.class);// logger日志
	// 用户
	@Autowired
	private IUserInfoService userInfoService;

	// 用户升级
	@Autowired
	private IUserUpgradeService userUpgradeService;

	@Autowired
	private IAppOrdersService appOrdersService;

	/**
	 * 微信app支付统一下单
	 * 
	 * @author liuqiyu
	 * @param userId        用户编号
	 * @param orderTotalFee 总金额
	 * @param memberLevelId 等级id
	 * @return
	 */
	@SuppressWarnings("finally")
	@ResponseBody
	@RequestMapping(value = "/weixinPay")
	public synchronized ResponseData weixinPay(AppAlipayVO appAlipayVO, HttpServletRequest request) {

		// 定义返回信息对象
		ResponseData responseData = new ResponseData();
		try {
			
			BigDecimal orderTotalFee = new BigDecimal(appAlipayVO.getTotalAmount());
			// 防止抓包修改订单金额造成损失
			int flag = orderTotalFee.compareTo(BigDecimal.ZERO);
			// 小于0或者等于0
			if (flag == 0 || flag == -1) {
				responseData.setCode(-999);
				responseData.setMsg("付款金额错误!");
				return responseData;
			}
			
			// 商户订单号生成
			String outTradeNo = ShortUUIDUtil.getOrderIdByTime();
			// 封装预支付订单信息
			Map<String, String> paraMap = new HashMap<String, String>();
			paraMap.put("appid", AppWxPayConfig.WX_APPID); // 应用ID
			paraMap.put("mch_id", AppWxPayConfig.MCH_ID); // 商户号
			paraMap.put("nonce_str", AppWxPayConfig.genNonce(30)); // 随机字符串
			paraMap.put("body",  appAlipayVO.getBody()); // 商品描述 APP名字-实际商品名称
			paraMap.put("out_trade_no", outTradeNo); // 商户订单号
			paraMap.put("total_fee", BigDecimalUtil.bigDecimalNullToNumber(orderTotalFee) + ""); // 总金额,单位为分
			paraMap.put("spbill_create_ip", AppWxPayConfig.getIp()); // 终端IP 用户端实际ip
			// TODO 异步通知地址需要修改
			paraMap.put("notify_url", AppWxPayConfig.APP_NOTIFY_URL); // 异步通知地址
			paraMap.put("trade_type", AppWxPayConfig.WX_JSAPI); // 交易类型
			/* paraMap.put("limit_pay", "no_credit"); // 指定支付方式 no_credit--指定不能使用信用卡支付 */

			// 签名生成
			String sign = WXPayUtil.generateSignature(paraMap, AppWxPayConfig.PARTNER_KEY);
			paraMap.put("sign", sign);
			// 将所有参数(map)转xml格式
			String xml = WXPayUtil.mapToXml(paraMap);

			// 统一下单、发送post请求"统一下单接口"返回预支付id:pr=
			String xmlStr = HttpRequest.sendPost(AppWxPayConfig.WX_PAY_URL, xml);

			// 以下内容是返回前端页面的json数据
			String prepay_id = ""; // 预支付id
			if (xmlStr.indexOf("SUCCESS") != -1) {
				// xml数据转储map对象
				Map<String, String> map = WXPayUtil.xmlToMap(xmlStr);
				prepay_id = map.get("prepay_id");
			}

			// 二次签名数据封装
			Map<String, String> payMap = new HashMap<String, String>();
			payMap.put("appId", AppWxPayConfig.WX_APPID);
			payMap.put("timeStamp", AppWxPayConfig.getCurrentTimestamp() + "");
			payMap.put("nonceStr", AppWxPayConfig.genNonce(30));
			payMap.put("signType", AppWxPayConfig.TYPE_MD5);
			payMap.put("package", "prepay_id=" + prepay_id);
			// 二次签名生成
			String paySign = WXPayUtil.generateSignature(payMap, AppWxPayConfig.PARTNER_KEY);
			payMap.put("paySign", paySign);
			payMap.put("out_trade_no", outTradeNo);

			// payMap 是前台调起支付的凭证,将payMap传给前台即可★★★★★

			// ▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼业务处理▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼
			// 创建交易记录
			int insFlasg = this.appOrderCreate(appAlipayVO); // 创建预支付订单(贴合自己的订单写)
			if (insFlasg <= 0) {
				// 封装code、msg、data
				responseData.setCode(300);
				responseData.setMsg("失败");
				return responseData;
			}
			// 封装code、msg、data
			responseData.setCode(200);
			responseData.setMsg("成功");
			responseData.setData(payMap);
			// ▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲业务处理▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲
		} catch (Exception e) {
			// 异常抛出
			e.printStackTrace();
			responseData.setCode(300);
			responseData.setMsg("服务器内部错误");
		} finally {
			return responseData;
		}
	}

	/**
	 * 微信支付通知地址
	 * 
	 * @author liuqiyu
	 * @param request
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value = "/weixinPayNotify", produces = { "application/json;charset=utf-8" })
	public synchronized String weixinPayNotify(HttpServletRequest request, HttpServletResponse response) {
		try {
			// 读取参数
			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();

			// 获取微信调用我们notify_url的返回信息
			String notityXml = new String(outSteam.toByteArray(), "utf-8");
			logger.info("微信支付回调通知--------" + notityXml);

			// 判断返回信息是否为空
			if (null == notityXml || "" == notityXml) {
				/*
				 * 返回状态码 return_code 是 String(16) SUCCESS 请按示例值填写
				 * 
				 * 返回信息 return_msg 是 String(128) OK 请按示例值填写
				 */
				return AppWxPayConfig.setXml("fail", "xml为空");
			}
			// 将xml转为map形式数据
			Map<Object, Object> map = WXPayUtil.xml2Map(notityXml);

			// 判断返回状态和业务结果是否成功
			if (map.get("result_code").toString().equalsIgnoreCase("SUCCESS")
					&& map.get("return_code").toString().equalsIgnoreCase("SUCCESS")) {
				logger.info("微信支付回调通知----返回成功");

				/*
				 * 特别提醒:商户系统对于支付结果通知的内容一定要做签名验证,并校验返回的订单金额是否与商户侧的订单金额一致,防止数据泄漏导致出现“假通知”,造成资金损失。
				 */
				// 验证签名
				if (WXPayUtil.isSignatureValid(notityXml)) {
					// 订单处理 操作 orderConroller 的回写操作?
					logger.info("微信支付----验证签名成功");
					// ▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼业务处理▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼
					/*
					 * 验证订单金额是否与商户侧的订单金额一致
					 */
					// 根据订单号获取订单
					AppOrders appOrders = appOrdersService.getByOrderNum(request.getParameter("out_trade_no"));
					// 判断订单是否存在
					if (null == appOrders) {
						return AppWxPayConfig.setXml("fail", "该订单号不存在");
					}
					appOrders.setTransactionId((String) map.get("transaction_id")); // 微信交易id 可用于查询账单
					appOrders.setPayMoney(new BigDecimal(request.getParameter("cash_fee").toString())); // 实际支付金额
					// 订单金额(数据库存放的)
					BigDecimal orderMoney = appOrders.getOrderMoney();
					// 订单金额(微信回调返回的)
					BigDecimal totalMoney = new BigDecimal(request.getParameter("total_fee").toString());
					// 判断订单金额是否与商户侧的订单金额一致
					if (orderMoney.compareTo(totalMoney) != 0) {
						// 微信支付订单号 用户查看订单。。。

						// 支付金额
						// 设定失败返回信息
						return AppWxPayConfig.setXml("fail", "订单金额与商户侧的订单金额不一致");
					}
					// 进行升级
					userUpgradeService.upgradeSuccess(appOrders);
					// ▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲业务处理▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲
					// ====================================================================
					// 通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了.
					return AppWxPayConfig.setXml("SUCCESS", "OK");
				} else {
					return AppWxPayConfig.setXml("fail", "签名验证失败");
				}
			} else {
				return AppWxPayConfig.setXml("fail", "报文为空");
			}
		} catch (Exception e) {
			e.printStackTrace();
			logger.info("errorMsg:--- 微信通知失败" + e.getMessage());
			return AppWxPayConfig.setXml("fail", "微信通知异常");
		}
	}

工具类分享  WXPayUtil

package com.qike.utils.pay;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.StringWriter;
import java.security.MessageDigest;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.qike.utils.pay.WXPayConstants.SignType;

public class WXPayUtil {

	/**
	 * XML格式字符串转换为Map
	 *
	 * @param strXML XML字符串
	 * @return XML数据转换后的Map
	 * @throws Exception
	 */
	public static Map<String, String> xmlToMap(String strXML) throws Exception {
		try {
			Map<String, String> data = new HashMap<String, String>();
			DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
			DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
			InputStream stream = new ByteArrayInputStream(strXML.getBytes("UTF-8"));
			org.w3c.dom.Document doc = documentBuilder.parse(stream);
			doc.getDocumentElement().normalize();
			NodeList nodeList = doc.getDocumentElement().getChildNodes();
			for (int idx = 0; idx < nodeList.getLength(); ++idx) {
				Node node = nodeList.item(idx);
				if (node.getNodeType() == Node.ELEMENT_NODE) {
					org.w3c.dom.Element element = (org.w3c.dom.Element) node;
					data.put(element.getNodeName(), element.getTextContent());
				}
			}
			try {
				stream.close();
			} catch (Exception ex) {
				// do nothing
			}
			return data;
		} catch (Exception ex) {
			WXPayUtil.getLogger().warn("Invalid XML, can not convert to map. Error message: {}. XML content: {}",
					ex.getMessage(), strXML);
			throw ex;
		}

	}

	/**
	 * 将Map转换为XML格式的字符串
	 *
	 * @param data Map类型数据
	 * @return XML格式的字符串
	 * @throws Exception
	 */
	public static String mapToXml(Map<String, String> data) throws Exception {
		DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
		DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
		org.w3c.dom.Document document = documentBuilder.newDocument();
		org.w3c.dom.Element root = document.createElement("xml");
		document.appendChild(root);
		for (String key : data.keySet()) {
			String value = data.get(key);
			if (value == null) {
				value = "";
			}
			value = value.trim();
			org.w3c.dom.Element filed = document.createElement(key);
			filed.appendChild(document.createTextNode(value));
			root.appendChild(filed);
		}
		TransformerFactory tf = TransformerFactory.newInstance();
		Transformer transformer = tf.newTransformer();
		DOMSource source = new DOMSource(document);
		transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
		transformer.setOutputProperty(OutputKeys.INDENT, "yes");
		StringWriter writer = new StringWriter();
		StreamResult result = new StreamResult(writer);
		transformer.transform(source, result);
		String output = writer.getBuffer().toString(); // .replaceAll("\n|\r", "");
		try {
			writer.close();
		} catch (Exception ex) {
		}
		return output;
	}

	/**
	 * 生成带有 sign 的 XML 格式字符串
	 *
	 * @param data Map类型数据
	 * @param key  API密钥
	 * @return 含有sign字段的XML
	 */
	public static String generateSignedXml(final Map<String, String> data, String key) throws Exception {
		return generateSignedXml(data, key, WXPayConstants.SignType.MD5);
	}

	/**
	 * 生成带有 sign 的 XML 格式字符串
	 *
	 * @param data     Map类型数据
	 * @param key      API密钥
	 * @param signType 签名类型
	 * @return 含有sign字段的XML
	 */
	public static String generateSignedXml(final Map<String, String> data, String key, WXPayConstants.SignType signType)
			throws Exception {
		String sign = generateSignature(data, key, signType);
		data.put(WXPayConstants.FIELD_SIGN, sign);
		return mapToXml(data);
	}

	/**
	 * 判断签名是否正确
	 *
	 * @param xmlStr XML格式数据
	 * @return 签名是否正确
	 * @throws Exception
	 */
	public static boolean isSignatureValid(String xmlStr) throws Exception {
		Map<String, String> data = xmlToMap(xmlStr);
		if (!data.containsKey(WXPayConstants.FIELD_SIGN)) {
			return false;
		}
		String sign = data.get(WXPayConstants.FIELD_SIGN);
		return generateSignature(data, AppWxPayConfig.PARTNER_KEY).equals(sign);
	}

	/**
	 * 判断签名是否正确,必须包含sign字段,否则返回false。使用MD5签名。
	 *
	 * @param data Map类型数据
	 * @param key  API密钥
	 * @return 签名是否正确
	 * @throws Exception
	 */
	public static boolean isSignatureValid(Map<String, String> data, String key) throws Exception {
		return isSignatureValid(data, key, SignType.MD5);
	}

	/**
	 * 判断签名是否正确,必须包含sign字段,否则返回false。
	 *
	 * @param data     Map类型数据
	 * @param key      API密钥
	 * @param signType 签名方式
	 * @return 签名是否正确
	 * @throws Exception
	 */
	public static boolean isSignatureValid(Map<String, String> data, String key, SignType signType) throws Exception {
		if (!data.containsKey(WXPayConstants.FIELD_SIGN)) {
			return false;
		}
		String sign = data.get(WXPayConstants.FIELD_SIGN);
		return generateSignature(data, key, signType).equals(sign);
	}

	/**
	 * 生成签名
	 *
	 * @param data 待签名数据
	 * @param key  API密钥
	 * @return 签名
	 */
	public static String generateSignature(final Map<String, String> data, String key) throws Exception {
		return generateSignature(data, key, WXPayConstants.SignType.MD5);
	}

	/**
	 * 生成签名. 注意,若含有sign_type字段,必须和signType参数保持一致。
	 *
	 * @param data     待签名数据
	 * @param key      API密钥
	 * @param signType 签名方式
	 * @return 签名
	 */
	public static String generateSignature(final Map<String, String> data, String key, WXPayConstants.SignType signType)
			throws Exception {
		Set<String> keySet = data.keySet();
		String[] keyArray = keySet.toArray(new String[keySet.size()]);
		Arrays.sort(keyArray);
		StringBuilder sb = new StringBuilder();
		for (String k : keyArray) {
			if (k.equals(WXPayConstants.FIELD_SIGN)) {
				continue;
			}
			if (data.get(k).trim().length() > 0) // 参数值为空,则不参与签名
				sb.append(k).append("=").append(data.get(k).trim()).append("&");
		}
		sb.append("key=").append(key);
		if (WXPayConstants.SignType.MD5.equals(signType)) {
			return MD5(sb.toString()).toUpperCase();
		} else if (WXPayConstants.SignType.HMACSHA256.equals(signType)) {
			return HMACSHA256(sb.toString(), key);
		} else {
			throw new Exception(String.format("Invalid sign_type: %s", signType));
		}
	}

	/**
	 * 获取随机字符串 Nonce Str
	 *
	 * @return String 随机字符串
	 */
	public static String generateNonceStr() {
		return UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32);
	}

	/**
	 * 生成 MD5
	 *
	 * @param data 待处理数据
	 * @return MD5结果
	 */
	public static String MD5(String data) throws Exception {
		MessageDigest md = MessageDigest.getInstance("MD5");
		byte[] array = md.digest(data.getBytes("UTF-8"));
		StringBuilder sb = new StringBuilder();
		for (byte item : array) {
			sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
		}
		return sb.toString().toUpperCase();
	}

	/**
	 * 生成 HMACSHA256
	 * 
	 * @param data 待处理数据
	 * @param key  密钥
	 * @return 加密结果
	 * @throws Exception
	 */
	public static String HMACSHA256(String data, String key) throws Exception {
		Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
		SecretKeySpec secret_key = new SecretKeySpec(key.getBytes("UTF-8"), "HmacSHA256");
		sha256_HMAC.init(secret_key);
		byte[] array = sha256_HMAC.doFinal(data.getBytes("UTF-8"));
		StringBuilder sb = new StringBuilder();
		for (byte item : array) {
			sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
		}
		return sb.toString().toUpperCase();
	}

	/**
	 * 日志
	 * 
	 * @return
	 */
	public static Logger getLogger() {
		Logger logger = LoggerFactory.getLogger("wxpay java sdk");
		return logger;
	}

	/**
	 * 获取当前时间戳,单位秒
	 * 
	 * @return
	 */
	public static long getCurrentTimestamp() {
		return System.currentTimeMillis() / 1000;
	}

	/**
	 * 获取当前时间戳,单位毫秒
	 * 
	 * @return
	 */
	public static long getCurrentTimestampMs() {
		return System.currentTimeMillis();
	}

	/**
	 * 生成 uuid, 即用来标识一笔单,也用做 nonce_str
	 * 
	 * @return
	 */
	public static String generateUUID() {
		return UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32);
	}

	/**
	 * 把原始的xml转换成map key为节点的路径,值为节点值 ,遇到重复节点用”[数字]“标识第几个节点
	 * 如:<xml><list><test>test1</test><test>test2</test></list></xml> 会转换成
	 * /xml/list[1]/test=test1 /xml/list[2]/test=test2
	 * 
	 * @param message
	 * @return
	 */
	public static Map<Object, Object> xml2Map(String message) {
		Map<Object, Object> data = new LinkedHashMap<Object, Object>();
		Document doc = null;
		try {
			doc = DocumentHelper.parseText(message);
		} catch (DocumentException e) {
			e.printStackTrace();
		}

		Element root = doc.getRootElement();
		String path = "/" + root.getName();
		element2Map(root, data, path);
		return data;
	}

	private static void element2Map(Element ele, Map<Object, Object> data, String path) {
		if (ele == null) {
			return;
		}
		List<Element> childrens = ele.elements();
		if (childrens != null && childrens.size() > 0) {
			Element pre = null;
			Element cur = null;
			Element next = null;
			int nodeIndex = 1;
			int length = childrens.size();
			for (int i = 0; i < length; i++) {
				cur = childrens.get(i);
				String nodePath = cur.getName();
				if (pre == null) {
					next = childrens.get(i + 1);
					if (next.getName().equals(cur.getName())) {
						nodePath += "[" + nodeIndex + "]";
						nodeIndex++;
					}
				} else {
					if (pre.getName().equals(cur.getName())) {
						nodePath += "[" + nodeIndex + "]";
						nodeIndex++;
					} else {
						nodeIndex = 1;
					}
				}
				element2Map(cur, data, nodePath);
				pre = cur;
			}
		} else {
			data.put(path, ele.getText());
		}
	}
}

HttpRequest  

package com.qike.utils.pay;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;
import java.util.Map;

public class HttpRequest {
	/**
	 * 向指定URL发送GET方法的请求
	 *
	 * @param url   发送请求的URL
	 * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
	 * @return URL 所代表远程资源的响应结果
	 */
	public static String sendGet(String url, String param) {
		String result = "";
		BufferedReader in = null;
		try {
			String urlNameString = url + "?" + param;
			System.out.println(urlNameString);
			URL realUrl = new URL(urlNameString);
			// 打开和URL之间的连接
			URLConnection connection = realUrl.openConnection();
			// 设置通用的请求属性
			connection.setRequestProperty("accept", "*/*");
			connection.setRequestProperty("connection", "Keep-Alive");
			connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
			// 建立实际的连接
			connection.connect();
			// 获取所有响应头字段
			Map<String, List<String>> map = connection.getHeaderFields();
			// 遍历所有的响应头字段
			for (String key : map.keySet()) {
				System.out.println(key + "--->" + map.get(key));
			}
			// 定义 BufferedReader输入流来读取URL的响应
			in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
			String line;
			while ((line = in.readLine()) != null) {
				result += line;
			}
		} catch (Exception e) {
			System.out.println("发送GET请求出现异常!" + e);
			e.printStackTrace();
		}
		// 使用finally块来关闭输入流
		finally {
			try {
				if (in != null) {
					in.close();
				}
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}
		return result;
	}

	/**
	 * 向指定 URL 发送POST方法的请求
	 *
	 * @param url   发送请求的 URL
	 * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
	 * @return 所代表远程资源的响应结果
	 */
	public static String sendPost(String url, String param) {
		PrintWriter out = null;
		BufferedReader in = null;
		String result = "";
		try {
			URL realUrl = new URL(url);
			// 打开和URL之间的连接
			URLConnection conn = realUrl.openConnection();
			// 设置通用的请求属性
			conn.setRequestProperty("accept", "*/*");
			conn.setRequestProperty("connection", "Keep-Alive");
			conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
			// 发送POST请求必须设置如下两行
			conn.setDoOutput(true);
			conn.setDoInput(true);
			// 获取URLConnection对象对应的输出流
			out = new PrintWriter(conn.getOutputStream());
			// 发送请求参数
			out.print(param);
			// flush输出流的缓冲
			out.flush();
			// 定义BufferedReader输入流来读取URL的响应
			in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
			String line;
			while ((line = in.readLine()) != null) {
				result += line;
			}
		} catch (Exception e) {
			System.out.println("发送 POST 请求出现异常!" + e);
			e.printStackTrace();
		}
		// 使用finally块来关闭输出流、输入流
		finally {
			try {
				if (out != null) {
					out.close();
				}
				if (in != null) {
					in.close();
				}
			} catch (IOException ex) {
				ex.printStackTrace();
			}
		}
		return result;
	}
}

常量

package com.qike.utils.pay;

/**
 * 常量
 */
public class WXPayConstants {

    public enum SignType {
        MD5, HMACSHA256
    }

    public static final String DOMAIN_API = "api.mch.weixin.qq.com";
    public static final String DOMAIN_API2 = "api2.mch.weixin.qq.com";
    public static final String DOMAIN_APIHK = "apihk.mch.weixin.qq.com";
    public static final String DOMAIN_APIUS = "apius.mch.weixin.qq.com";


    public static final String FAIL     = "FAIL";
    public static final String SUCCESS  = "SUCCESS";
    public static final String HMACSHA256 = "HMAC-SHA256";
    public static final String MD5 = "MD5";

    public static final String FIELD_SIGN = "sign";
    public static final String FIELD_SIGN_TYPE = "sign_type";

    public static final String MICROPAY_URL_SUFFIX     = "/pay/micropay";
    public static final String UNIFIEDORDER_URL_SUFFIX = "/pay/unifiedorder";
    public static final String ORDERQUERY_URL_SUFFIX   = "/pay/orderquery";
    public static final String REVERSE_URL_SUFFIX      = "/secapi/pay/reverse";
    public static final String CLOSEORDER_URL_SUFFIX   = "/pay/closeorder";
    public static final String REFUND_URL_SUFFIX       = "/secapi/pay/refund";
    public static final String REFUNDQUERY_URL_SUFFIX  = "/pay/refundquery";
    public static final String DOWNLOADBILL_URL_SUFFIX = "/pay/downloadbill";
    public static final String REPORT_URL_SUFFIX       = "/payitil/report";
    public static final String SHORTURL_URL_SUFFIX     = "/tools/shorturl";
    public static final String AUTHCODETOOPENID_URL_SUFFIX = "/tools/authcodetoopenid";

    // sandbox
    public static final String SANDBOX_MICROPAY_URL_SUFFIX     = "/sandboxnew/pay/micropay";
    public static final String SANDBOX_UNIFIEDORDER_URL_SUFFIX = "/sandboxnew/pay/unifiedorder";
    public static final String SANDBOX_ORDERQUERY_URL_SUFFIX   = "/sandboxnew/pay/orderquery";
    public static final String SANDBOX_REVERSE_URL_SUFFIX      = "/sandboxnew/secapi/pay/reverse";
    public static final String SANDBOX_CLOSEORDER_URL_SUFFIX   = "/sandboxnew/pay/closeorder";
    public static final String SANDBOX_REFUND_URL_SUFFIX       = "/sandboxnew/secapi/pay/refund";
    public static final String SANDBOX_REFUNDQUERY_URL_SUFFIX  = "/sandboxnew/pay/refundquery";
    public static final String SANDBOX_DOWNLOADBILL_URL_SUFFIX = "/sandboxnew/pay/downloadbill";
    public static final String SANDBOX_REPORT_URL_SUFFIX       = "/sandboxnew/payitil/report";
    public static final String SANDBOX_SHORTURL_URL_SUFFIX     = "/sandboxnew/tools/shorturl";
    public static final String SANDBOX_AUTHCODETOOPENID_URL_SUFFIX = "/sandboxnew/tools/authcodetoopenid";


}

ShortUUIDUtil

	/***
	 * 生成订单流水号 根据时间戳+随机数+进程编程生成订单号
	 * 
	 * @date 2018年11月17日
	 * @return
	 */
	public static String getOrderIdByTime() throws Exception {
		// 获取进程编号
		RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
		Field jvm = runtime.getClass().getDeclaredField("jvm");
		jvm.setAccessible(true);
		VMManagement mgmt = (VMManagement) jvm.get(runtime);
		Method pidMethod = mgmt.getClass().getDeclaredMethod("getProcessId");
		pidMethod.setAccessible(true);
		int pid = (Integer) pidMethod.invoke(mgmt);
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
		String newDate = sdf.format(new Date());
		String result = "";
		Random random = new Random();
		for (int i = 0; i < 3; i++) {
			result += random.nextInt(10);
		}
		// 时间戳+随机数+进程编号
		return newDate + result + pid;
	}

猜你喜欢

转载自blog.csdn.net/qq_37737274/article/details/84852456