PC端 微信支付

1. 下载微信官网demo

	工欲善其事必先利其器(下载微信官网支付demo)       https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=11_1
	
	知其然知其所以然(熟悉接口API参数方便结合业务场景获取):    https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_1

   如不知该用哪个版本可以参考: https://download.csdn.net/download/qq_16771097/16669146  
	
	*简单的配置我这里就不复述了,看过官网下过demo,修改MyConfig配置文件就好。* 

特别注意:
WXPay.java 默认是SignType.HMACSHA256需要修改为SignType.MD5;
异步回调通知(支付/退款)必须配置外网可以访问https,并且无参数!!!

 public WXPay(final WXPayConfig config, final String notifyUrl, final boolean autoReport, final boolean useSandbox) 
 throws Exception {
    
    
      this.config = config;
       this.notifyUrl = notifyUrl;
       this.autoReport = autoReport;
       this.useSandbox = useSandbox;
       if (useSandbox) {
    
    
           this.signType = SignType.HMACSHA256; // 沙箱环境
       }else {
    
    
           this.signType = SignType.MD5;
       }
       this.wxPayRequest = new WXPayRequest(config);
  }

2.微信支付-订单回调接口

特别注意: // 交易成功判断条件: return_code、result_code和trade_state都为SUCCESS

/**
 * 微信支付-订单回调接口
 * @param request
 * @param response
 * @throws Exception
 */
@ApiOperation(value = "微信支付-订单回调接口")
@RequestMapping(value="/wxPay/async", produces="text/html;charset=utf-8")
public void wxPayAsyncNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
    
    
    String resultXml = stuPlatNotifyService.wxPayAsyncNotify(request);
    BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(response.getOutputStream());
    bufferedOutputStream.write(resultXml.getBytes());
    bufferedOutputStream.flush();
    bufferedOutputStream.close();
}

//微信支付回调 先判断返回结果是否正常 再验证签名 再根据 商品订单号 查询支付订单是否支付完成 最后更新订单状态与数据
@Override
public String wxPayAsyncNotify(HttpServletRequest request) {
    
    
	String returnXmlMessage = null;
	String notifyXmlData = null;
	try {
    
    
		notifyXmlData = readXmlFromStream(request);
		Map<String, String> notifyMapData = WXPayUtil.xmlToMap(notifyXmlData);
		if (WXPayConstants.SUCCESS.equals(notifyMapData.get("return_code"))) {
    
    
			//log.info(">>>----------------wxPayAsyncNotify---------------:{}", notifyMapData);
			String outTradeNo = notifyMapData.get("out_trade_no");    //获取 商品订单号
			WXPay wxpay = new WXPay(new MyConfig(certUrl));
			boolean signatureValid = wxpay.isPayResultNotifySignatureValid(notifyMapData);  // 验证签名
			if (signatureValid) {
    
    
				//先查询核实订单再确认更新订单
				Map<String, String> map = WxPayUtils.orderQueryDetail(outTradeNo, certUrl);
				String wxPayStatus = map.get(WXPayConstants.WX_PAY_STATUS);
				if(StringUtils.isNotEmpty(wxPayStatus) && wxPayStatus.equals(WXPayConstants.SUCCESS)){
    
    
					//log.info(">>>----------------wxPayAsyncNotify---------------:{}", map);
					//String transactionId = map.get("transaction_id");
					//String timeEnd = DateFormatUtils.getDateStr(map.get("time_end"));
					 
					// update status success
				 
					// 一切正常返回的xml数据
					returnXmlMessage = setReturnXml(WXPayConstants.SUCCESS, "OK");
				}else{
    
    
					// update status fail
					returnXmlMessage = setReturnXml(WXPayConstants.FAIL, "-wxPayAsyncNotify-orderQuery-failed!");
					log.error("-wxPayAsyncNotify-orderQuery-failed!--"+map.get("return_msg"));
				}
			} else {
    
    
				returnXmlMessage = setReturnXml(WXPayConstants.FAIL, "-wxPayAsyncNotify-Verification sign failed!");
				log.error("-wxPayAsyncNotify-Verification sign failed!");
			}
		}else{
    
    
			returnXmlMessage = setReturnXml(WXPayConstants.FAIL, "--wxPayAsyncNotify--");
			log.error("-wxPayAsyncNotify--"+notifyMapData.get("return_msg"));
		}
	} catch (IOException e) {
    
    
		returnXmlMessage = setReturnXml(WXPayConstants.FAIL, "An exception occurred while reading the WeChat server returning xml data in the stream.");
		log.error("-[wxPayAsyncNotify] [读取微信服务器返回流中xml数据时发生异常:{}] ", ExceptionUtils.getStackTrace(e));
	} catch (Exception e) {
    
    
		log.error("-[wxPayAsyncNotify] [xml数据:{}] [异常:{}] ", notifyXmlData, ExceptionUtils.getStackTrace(e));
		returnXmlMessage = setReturnXml(WXPayConstants.FAIL, "Payment successful, exception occurred during asynchronous notification processing.");
		log.error("-[wxPayAsyncNotify] [支付成功异步消息处理失败:{}]", returnXmlMessage);
	}
	return returnXmlMessage;
}

3.微信退款-订单回调接口

/**
   * 微信退款-订单回调接口
    * @param request
    * @param response
    * @throws Exception
    */
   @ApiOperation(value = "微信退款-订单回调接口")
   @RequestMapping(value="/wxRefund/async", produces="text/html;charset=utf-8")
   public void wxRefundAsyncNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
    
    
       String resultXml = stuPlatNotifyService.wxRefundAsyncNotify(request);
       BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(response.getOutputStream());
       bufferedOutputStream.write(resultXml.getBytes());
       bufferedOutputStream.flush();
       bufferedOutputStream.close();
   }

//微信退款回调 先判断返回结果是否正常 再解析加密信息 再根据 商品订单号 查询支付订单是否退款完成 最后更新订单状态与数据
@Override
public String wxRefundAsyncNotify(HttpServletRequest request) {
    
    
	String returnXmlMessage = null;
	String notifyXmlData = null;
	try {
    
    
		notifyXmlData = readXmlFromStream(request);
		Map<String, String> notifyMapData = WXPayUtil.xmlToMap(notifyXmlData);
		if (WXPayConstants.SUCCESS.equals(notifyMapData.get("return_code"))) {
    
    
			String reqInfo = notifyMapData.get("req_info");   // 获得加密信息
			// 进行AES解密 获取req_info中包含的相关信息(解密失败会抛出异常)
			String refundData = wxDecodeUtil.decryptData(reqInfo);
			Map<String, String> reqInfoMap = WXPayUtil.xmlToMap(refundData);
			//log.info(">>>----------------wxRefundAsyncNotify---------------reqInfoMap:{}", reqInfoMap);

			String outTradeNo = reqInfoMap.get("out_trade_no");         //获取 商品订单号
			String outRefundNo = reqInfoMap.get("out_refund_no");       //获取 退款订单号

			//先查询核实订单再确认更新订单
			Map<String, String> refundMap = WxPayUtils.refundQuery(outTradeNo, certUrl);
			if(WXPayConstants.SUCCESS.equals(refundMap.get("return_code"))){
    
    
				//log.info(">>>----------------wxRefundAsyncNotify---------------refundMap:{}", refundMap);
				String transactionId = refundMap.get("transaction_id");
				String refundCount = refundMap.get("refund_count");
				if(StringUtils.isNotEmpty(refundCount) && Integer.parseInt(refundCount)>0){
    
    
					String refundTime = null;
					Integer refundInt = Integer.parseInt(refundCount);
					boolean refundBool = false;
					for(int i=0;i<refundInt;i++){
    
    
						if(WXPayConstants.SUCCESS.equals(refundMap.get("refund_status_"+i)) && outRefundNo.equals(refundMap.get("out_refund_no_"+i))){
    
    
							refundBool = true;
							refundTime = refundMap.get("refund_success_time_"+i);
							break;
						}
					}
					if(refundBool){
    
    
						//update status success
						// 一切正常返回的xml数据
						returnXmlMessage = setReturnXml(WXPayConstants.SUCCESS, "OK");
					}else{
    
    
						//update status fail 
						returnXmlMessage = setReturnXml(WXPayConstants.FAIL, "-wxRefundAsyncNotify-refundQuery-out_refund_no--");
						log.error("-wxRefundAsyncNotify-refundQuery-out_refund_no--"+refundMap.get("return_msg"));
					}
				}
			}else{
    
    
				returnXmlMessage = setReturnXml(WXPayConstants.FAIL, "-wxRefundAsyncNotify-refundQuery-fail!");
				log.error("-wxRefundAsyncNotify-refundQuery-fail!"+refundMap.get("return_msg"));
			}
		}else{
    
    
			returnXmlMessage = setReturnXml(WXPayConstants.FAIL, "-wxRefundAsyncNotify-refund-fail!");
			log.error("-wxRefundAsyncNotify-refund-fail!"+notifyMapData.get("return_msg"));
		}
	} catch (IOException e) {
    
    
		returnXmlMessage = setReturnXml(WXPayConstants.FAIL, "An exception occurred while reading the WeChat server returning xml data in the stream.");
		log.error("[wxRefundAsyncNotify] [读取微信服务器返回流中xml数据时发生异常:{}] ", ExceptionUtils.getStackTrace(e));
	} catch (Exception e) {
    
    
		log.error("[wxRefundAsyncNotify] [xml数据:{}] [异常:{}] ", notifyXmlData, ExceptionUtils.getStackTrace(e));
		returnXmlMessage = setReturnXml(WXPayConstants.FAIL, "Payment successful, exception occurred during asynchronous notification processing.");
		log.warn("[wxRefundAsyncNotify] [退款异步消息处理失败:{}]", returnXmlMessage);
	}
	return returnXmlMessage;
}

4.支付回调,退款回调(公共方法)

//从流中读取微信返回的xml数据
private String readXmlFromStream(HttpServletRequest httpServletRequest) throws IOException {
    
    
    InputStream inputStream = httpServletRequest.getInputStream();
    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
    final StringBuffer sb = new StringBuffer();
    String line = null;
    try {
    
    
        while ((line = bufferedReader.readLine()) != null) {
    
    
            sb.append(line);
        }
    } finally {
    
    
        bufferedReader.close();
        inputStream.close();
    }
    return sb.toString();
}

//设置返回给微信服务器的xml信息
private String setReturnXml(String returnCode, String returnMsg) {
    
    
    return "<xml><return_code><![CDATA[" + returnCode + "]]></return_code><return_msg><![CDATA[" + returnMsg + "]]></return_msg></xml>";
}

// 下面这段代码至验签的地方,代码是通用的,可以直接用(支付宝获取 支付、退款)
private Map<String, String> getMapParams(HttpServletRequest request){
    
    
    Map<String, String> params = new HashMap<>();
    Map requestParams = request.getParameterMap();
    for (Iterator 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);
    }
    return params;
}

5.回调通知注意事项

https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=23_8&index=6

在这里插入图片描述

Guess you like

Origin blog.csdn.net/qq_16771097/article/details/113047839