微信公众号支付 (二、统一下单接口)

3.1  获取到了openId后便可写统一下单接口,统一下单接口主要为了获取prepay_id 


必须传送的参数:  


公众账号ID:appId

商户号:mch_id
随机字符串:nonce_str(长度在32位以内)
签名:sign
商品描述:body
商户订单号:out_trade_no 
金额:total_fee
终端IP:spbill_create_ip  
通知类型:notify_url
交易类型:trade_type(JSAPI--公众号支付、NATIVE--原生扫码支付、APP--app支付)
用户标识:openid(在公众号支付中,统一下单接口中的openId是必须填写的)


统一下单接口连接:https://api.mch.weixin.qq.com/pay/unifiedorder


代码如下:
// 获取http服务请求
		HttpServletRequest request = Struts2Utils.getRequest();
		// 微信端要求按照ASCII字码排序,所以选用SortedMap 因为MAP不会按照ASCII码排序
		SortedMap<String, String> parameters = new TreeMap<String, String>();
		// 公众账号ID
		parameters.put("appid", );
		// 商户号
		parameters.put("mch_id", );
		// 商品描述
		parameters.put("body", );
		// 随机字符串 
		parameters.put("nonce_str", WeiXinUtil.create_nonce_str());
		// 订单号
		parameters.put("out_trade_no",);
		// 金额,微信金额为“分”
		parameters.put("total_fee", );
		// IP地址
		parameters.put("spbill_create_ip", PayCcbAction.getIp(request));
		// 回调地址
		parameters.put("notify_url", );
		// 交易类型   JSAPI--公众号支付、NATIVE--原生扫码支付、APP--app支付 
		parameters.put("trade_type", "JSAPI");
		// 用户表示openId
		parameters.put("openid", );
		// 以上参数加密成sign 输出查看,报签名错误,输出语句到API签名验证工具验证
		String sign = Sign.sign(parameters);
		parameters.put("sign", sign);


创建统一下单接口的参数,上面两个方法:WeiXinUtil.create_nonce_str()生成随机字符串。PayCcbAction.getIp()   IP地址


此处工具类:


/*
	 * 微信JSSDK参数 随机字符串
	 */
	public static String create_nonce_str() {
		return UUID.randomUUID().toString().replaceAll("-", "");
	}
	/*
	 * 获取IP
	 */
	public static String getIp(HttpServletRequest request) {
		String ip = request.getHeader("X-Forwarded-For");
		if (StringUtils.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)) {
			// 多次反向代理后会有多个ip值,第一个ip才是真实ip
			int index = ip.indexOf(",");
			if (index != -1) {
				return ip.substring(0, index);
			} else {
				return ip;
			}
		}
		ip = request.getHeader("X-Real-IP");
		if (StringUtils.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)) {
			return ip;
		}
		return request.getRemoteAddr();
	}


创建完成参数以后微信要求按照ASCII字码进行排序并生成XML,并发送请求


代码如下:

// 发送请求
		HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/pay/unifiedorder");
		StringEntity entityParams = new StringEntity(XmlUtils.parseXML(parameters), "utf-8");
		httpPost.setEntity(entityParams);
		httpPost.setHeader("Content-Type", "text/xml;charset=ISO-8859-1");
		CloseableHttpClient client = HttpClients.createDefault();
		CloseableHttpResponse response = client.execute(httpPost);

发送http请求,将上面创建好的参数生成xml格式,方法XmlUtils.parseXML()  生成XML格式

代码如下:


	/*
	 * 封装XML
	 */
	public static String parseXML(SortedMap<String, String> parameters) {
		StringBuffer sb = new StringBuffer();
		sb.append("<xml>");
		Set es = parameters.entrySet();
		Iterator it = es.iterator();
		while (it.hasNext()) {
			Map.Entry entry = (Map.Entry) it.next();
			String k = (String) entry.getKey();
			String v = (String) entry.getValue();
			if (null != v && !"".equals(v) && !"appkey".equals(k)) {
				sb.append("<" + k + ">" + parameters.get(k) + "</" + k + ">\n");
			}
		}
		sb.append("</xml>");
		return sb.toString();
	}

请求发过去后微信会给返回参数,当return_code=SUCCESS的时候说明统一下单接口没有错误,可以取perpay_id了


代码如下:


// 判断是否获取到返回信息
		if (response != null && response.getEntity() != null) {
			Map<String, String> resultMap = XmlUtils.toMap(EntityUtils.toByteArray(response.getEntity()), "utf-8");
			// 验证微信返回是否正确
			if (!SignUtils.checkParam(resultMap, WeiXinUtils.API_KEY)) {
				System.out.println("=================验证签名不通过===============");
				System.out.println(resultMap.get("return_code"));
				System.out.println(resultMap.get("return_msg"));
			} else {
				// 判断返回参数是否为SUCCESS
				if ("SUCCESS".equals(resultMap.get("return_code")) && "SUCCESS".equals(resultMap.get("result_code"))) {
					return resultMap.get("prepay_id");
				}
			}

		} else {
			System.out.println("获取返回信息失败");
		}


获取到微信返回参数时,验证是否获取到返回信息。当为SUCCESS获取到perpay_id就可以写自己逻辑。配置JS接口,因为JS要配置参数,所以就分开写了,下一篇写配置JS的配置。


方法SignUtils.checkParam()验证是否参数正确,其实判断return_code是否等于SUCCESS就可以了,没必要多一步。


/**
	 * 验证返回参数
	 */
	public static boolean checkParam(Map<String, String> params, String key) {
		boolean result = false;
		if (params.containsKey("sign")) { 
			String sign = params.get("sign");
			params.remove("sign");
			StringBuilder buf = new StringBuilder((params.size() + 1) * 10);
			SignUtils.buildPayParams(buf, params, false);
			String preStr = buf.toString();
			String signRecieve = MD5.sign(preStr, "&key=" + key, "utf-8");
			result = sign.equalsIgnoreCase(signRecieve);
		}
		return result;
	}




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值