Java架构学习(五十五)支付宝回调核心代码之同步回调实现&支付宝回调接口&同步回调和异步回调&使用form表单隐藏同步回调参数

版权声明:本文为博主原创文章,未经博主允许不得转载。如需要授权请联系[email protected] https://blog.csdn.net/leeue/article/details/86646544

一、支付宝回调接口

回调:分布式事物解决方案。

1、通知结果:分为
   同步通知:  以浏览器方式重定向到网站上去。
   异步通知:支付宝会以httpclient技术更改订单状态。

为什么项目要做服务化?
服务化的好处是把共同的代码抽象出来封装成接口给别人调用。
扩展性高,降低耦合性。

分布式事物:
	A B两个支付服务,调用订单服务进行订单状态更改
	payInfo.update();
	orderInfoClient.update();---http协议
   

当orderInfoClient.update()没有问题的时候,会发出一个通知给payInfo.update(),
这个时候两个服务就会一起提交事物。
当orderInfoClient.update()有问题的时候,也会发出通知给payInfo.update(),这个时候就会一起    		   
回滚事物。

MQ解决分布式事物。 它自身有重试机制。我们只需要处理接口幂等性就好了。

二、同步回调与异步回调

订单信息表中有个state状态。为0就是没有支付 1表示已支付。

aliPayInfo.update();支付宝数据库支付信息状态已经变成已支付
会以httpclient.回调接口,异步通知通过回调接口,把订单状态告诉给网站。

三、同步回调代码

同步回调代码书写过程:

首先肯定是要在api工程中创建一个专门做回调的api接口。

在这里插入图片描述

在实现类中实现:
@Override
	@ResponseBody
	public ResponseBase synCallBack(@RequestParam Map<String, String> params) {
		try {
			// 1.日志记录
			log.info("####支付宝同步通知synCallBack####开始,params:{}", params);
			// 2.验签操作
			boolean signVerified = AlipaySignature.rsaCheckV1(params, AlipayConfig.alipay_public_key,
					AlipayConfig.charset, AlipayConfig.sign_type); // 调用SDK验证签名
			
			log.info("####支付参数验签signVerified:{}####",signVerified);
			// ——请在这里编写您的程序(以下代码仅作参考)——
			if (!signVerified) {
				return setResultError("验签失败!");
			}
			// 商户订单号
			String outTradeNo = params.get("outTradeNo");
			// 支付宝交易号
			String tradeNo = params.get("tradeNo");
			// 付款金额
			String totalAmount = params.get("totalAmount");

			JSONObject data = new JSONObject();
			data.put("outTradeNo", outTradeNo);
			data.put("tradeNo", tradeNo);
			data.put("totalAmount", totalAmount);

			return setResultSuccess(data);
		} catch (Exception e) {
			log.info("####支付宝支付异常####,异常原因:{}", e);
			return setResultError("系统错误");
		} finally {
			// 不管是否有错,都会打印
			log.info("####支付宝同步通知synCallBack####结束,params:{}", params);
		}

	}

在这里插入图片描述


整合到PCweb上去

支付流程:首先网站生成支付token,然后调用支付宝支付接口,支付完成后有同步回调和异步回调。

四、使用form表单隐藏同步回调参数

支付回调的时候使用的同步回调是使用了GET,所以回传过来的信息会在地址栏上,可见。
这样不安全。
所以要使用from表单隐藏回调参数,在内部使用post提交。

优化代码变成在内部进行post进行转发提交。

/**
	 * 支付宝 同步回调通知 封装成form表单来进行提交
	 * 
	 * @return
	 * @throws IOException 
	 */
	@RequestMapping("/returnUrl")
	public void synCallBack(HttpServletRequest request, HttpServletResponse response)
			throws IOException {
		// 获取支付宝GET过来反馈信息
		log.info("#####支付宝同步回调接口CallBackController#####synCallBack开始");

		// 设置成这种格式才能解析成网页
		response.setContentType("text/html;charset=utf-8");

		Map<String, String> params = new HashMap<String, String>();
		Map<String, String[]> requestParams = request.getParameterMap();
		for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext();) {
			String name = (String) iter.next();
			String[] values = (String[]) requestParams.get(name);
			String valueStr = "";
			for (int i = 0; i < values.length; i++) {
				valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
			}
			// 乱码解决,这段代码在出现乱码时使用
			valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
			params.put(name, valueStr);
		}
		log.info("#####支付宝同步回调接口CallBackController#####synCallBack接受参数params:{}", params);
		ResponseBase synCallBackResponseBase = callBackServiceFegin.synCallBack(params);
		log.info("#####支付宝同步回调接口CallBackController#####synCallBack结束");
		if (!synCallBackResponseBase.getRtnCode().equals(Constants.HTTP_RES_CODE_200)) {

			// 如果是200直接返回的是报错页面
			request.setAttribute("error", synCallBackResponseBase.getMsg());
			return;
		}

		LinkedHashMap data = (LinkedHashMap) synCallBackResponseBase.getData();
		// 商户订单号
		String outTradeNo = (String) data.get("outTradeNo");
		// 支付宝交易号
		String tradeNo = (String) data.get("tradeNo");
		// 交易金额
		String totalAmount = (String) data.get("totalAmount");

		// 将这些内容转发到页面上去
		request.setAttribute("outTradeNo", outTradeNo);
		request.setAttribute("tradeNo", tradeNo);
		request.setAttribute("totalAmount", totalAmount);

		// 封装成html 浏览器模拟去提交
		String formHtml = "<form name='punchout_form' method='post' action='http://127.0.0.1:81/alibaba/callBack/synSuccessPage' >"
				+ "	<input type='hidden' name='outTradeNo' value="+outTradeNo+"> "
				+ "<input type='hidden' name='tradeNo' value="+tradeNo+"> "
				+ " <input type='hidden' name='totalAmount' value="+totalAmount+"> "
				+ "<input type='submit' value='立即支付' style='display:none'> "
				+ "</form> <script>document.forms[0].submit();</script>";

		//封装成POST 表单后,在页面上进行渲染出来
		PrintWriter writer = response.getWriter();
		writer.write(formHtml);
		writer.close();
	}

	/**
	 * 以post回调,隐藏参数
	 * 
	 * @return
	 */
	@RequestMapping(value = "synSuccessPage", method = RequestMethod.POST)
	public String synSuccessPage(HttpServletRequest request, String outTradeNo, String tradeNo, String totalAmount) {

		log.info("####以POST提交了回调支付信息表单了  synSuccessPage#####");
		// 将这些内容转发到页面上去
		request.setAttribute("outTradeNo", outTradeNo);
		request.setAttribute("tradeNo", tradeNo);
		request.setAttribute("totalAmount", totalAmount);
		return PAY_SUCCESS;

	}
封装回写成html记住

在这里插入图片描述


已经成功换行了

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/leeue/article/details/86646544