Skip to content

支付示例(JSAPI)

jinyu edited this page Mar 8, 2017 · 11 revisions

JSAPI是微信用户进入公众号的H5页面使用JS发起的支付。

后台构造支付字符串

		String openId = "用户的唯一标识,如owGBft_vbBbOaQOmpEUE4xDLeRSU";
		String body = "支付描述,如订单费用";
		String outTradeNo = "商户侧唯一订单号,如18789913341";
		double totalFee = 1d; // 订单金额 单位元
		String notifyUrl = "支付完成后的回调地址,如http://wx.xxx.com/pay/notify";
		String createIp = "发起支付时的客户端IP地址,如192.168.1.1";
		String attach = "支付时的附加信息,在回调时会原样带上,可为空";
		// 发起一个JS支付请求,这里有个值得注意的地方:微信返回的预交易ID(payRequest.getPrePayId())是有2小时的时效性的,
//超过2小时将不能重新发起支付,需重新生成一个`outTradeNo`订单号再次调用createJSPayRequest接口。
//所以这里的`prePayId`有两种解决方案:1、每次发起支付都重新生成`outTradeNo`订单号,然后调用createJSPayRequest接口。
//2、把`prePayId`缓存起来,然后通过:MchPayRequest payRequest = new JSAPIPayRequest(prePayId,weixinPayProxy.getPayAccount());
//构建一个`MchPayRequest`支付对象。两种方式都有利有弊,请根据实际需求而定。
		MchPayRequest payRequest = weixinPayProxy.createJSPayRequest(openId, body, outTradeNo, totalFee, notifyUrl, createIp, attach);
		// 将支付JSON串放到request作用域
		request.setAttribute("JSPAY", payRequest.toRequestString());
		// model.addAttribute("JSPAY", payRequest.toRequestString());
		// modelAndView.addObject("JSPAY", payRequest.toRequestString());

前端页面JS发起支付

var jspay = ${jspay}; // 接收后台传递过来的支付串
// 调用微信支付JS接口
WeixinJSBridge.invoke('getBrandWCPayRequest',jspay,function(res){
					if(res.err_msg == 'get_brand_wcpay_request:ok'){
						// 支付已完成!,注意这里支付完成指的是前端JS发起支付的操作顺利完成,
//并不意味着真正的支付成功,强烈建议到支付回调中去校验支付成功与否。
					} else if (res.err_msg == 'get_brand_wcpay_request:fail'){
						// 支付出现问题,请稍后再试!
					} else if (res.err_msg == 'get_brand_wcpay_request:cancel'){
						// 已取消支付,请重新支付!
					} else {
						// 支付被拒绝了
					}
				});

处理支付回调

/**
	 * 微信支付成功(前端)时的回调通知
	 * 
	 * @param inputStream
	 *            订单回调
	 * @return &ltxml&gt<br>
	 *         &ltreturn_code&gtSUCCESS/FAIL&lt/return_code&gt<br>
	 *         &ltreturn_msg&gt如非空,为错误 原因签名失败参数格式校验错误&lt/return_msg&gt<br>
	 *         &lt/xml&gt
	 * @throws IOException 
	 * @see <a
	 *      href="http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7">支付结果通知</a>
	 */
        @RequestMapping("/order/notify")
        @ResponseBody
	public String payNotify(InputStream input) throws IOException {
//获取订单信息
		String content = StringUtil.newStringUtf8(IOUtil.toByteArray(input));
		Order order = ListsuffixResultDeserializer.deserialize(content,
				Order.class);
		log.info("jsapi_notify_order_info:", order);
//验证签名
		String sign = order.getSign();
		String valid_sign = weixinPayProxy.getWeixinSignature().sign(order);
		log.info("微信签名----->sign={},vaild_sign={}", sign, valid_sign);
		if (!sign.equals(valid_sign)) {
			return XmlStream.toXML(new XmlResult(Consts.FAIL, "签名错误"));
		}
		// TODO 处理业务逻辑,如没有特殊要求可以考虑单独启一个线程去处理自己的业务,对于微信签名过后就可以返回success了。
                // 需要ajax的形式返回给微信,保证返回值能写到ResponseInputStream就行,Spring mvc使用 @ResponseBody注解,Servlet使用HttpServletResponse#getWrite#write
		return XmlStream.toXML(new XmlResult(Consts.SUCCESS, ""));
	}