欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

微信支付-那些神奇的坑

程序员文章站 2022-07-13 16:51:21
...

前段时间,由于工作需要,处理过*的微信支付。刚开始的时候,以为跟国内的微信支付没什么区别,很简单,但在实际操作中,才发现,这就是坑爹的货。
前人栽树,后人乘凉。我愿在此栽树一棵,愿后来人在此能乘凉。

接下来,请让我细数*微信支付的坑。(为保证坑的深度,请让我以境内和*来对比)

第一坑(业务接口名称叫法不一致)

  • 境内的叫统一下单接口
  • *的统一下单接口全部叫支付接口,也有叫公众账号&小程序支付接口

第二坑(统一下单请求地址不一致)

第三坑(统一下单参数名称不一致)

  • 境内的参数有:appid,scene_info等
  • *的参数有:service,version,charset,is_raw,is_minipg,sub_openid,sub_appid,mch_create_ip,
  • 这里仅列出了,不一样的参数,其他相同的参数没有列出,
  • *的参数中service是需要指定pay.weixin.jspay,如果是小程序支付的请求还需要is_raw参数
  • *没有场景参数
  • 境内的没有callback_url参数
  • 境内的没有mch_create_ip参数,*的有

第四坑(微信支付状态不可知)

  • 境内的微信支付,开通了之后,可以在后台看见已开通
  • *的微信支付,开通了之后,后台不会变化,只能靠自己调接口查询
  • 境内和*的返回参数也是类似哦,返回参数跟请求参数类似,都有区别

第五坑(微信支付的开通方式不一致)

  • 境内的微信支付开通方式,只要在后台提交给微信即可
  • *的是需要通过第三方来申请

第六坑(小程序支付方式不一致)

  • 境内的支付流程,需要有再次签名
  • *的支付流程中,不需要有再次签名,微信会返回可以唤起小程序支付的参数

第七坑(文档不一致)

  • 境内的微信支付,很好,很强大,只要看着官网操作即可
  • *的支付,没有官网,有第三方给的文档,这里的坑特别深,关于第三方给的文档中,竟然几个文档都不一致,并且给的demo也跟文档不一致,完全需要靠自己摸索。

不是坑(是建议)

对于*的微信支付,我这边有几点建议给大家
  • 除了看文档,还需要看下微信的官网给出的文档
  • 第三方给的文档,很陈旧,没有时序图,建议对照微信官网时序图
  • 遇到问题,多跟第三方沟通,虽然第三方的demo陈旧,也可以参考,万一可以发现金矿

微信支付的福利(Java版)

生成xml

/**
	 * 
	 * {@link #fromXml(String, Class)}
	 * 
	 * @param obj
	 *            拼接生成XML
	 */
	public static String generateXml(Object obj) {
		StringBuffer sb = new StringBuffer();

		sb.append("<xml>");
		Class<?> cls = obj.getClass();

		List<Field> fs = CommonUtils.getAllField(cls);
		for (Field f : fs) {
			try {
				f.setAccessible(true);
				Object v = f.get(obj);
				if (v != null && v.toString().length() > 0) {
					sb.append("<").append(f.getName()).append(">");
					// <![CDATA[FAIL]]>
					// sb.append("![CDATA[").append(v.toString()).append("]]");
					sb.append(v.toString());
					sb.append("</").append(f.getName()).append(">");
				}
			} catch (Exception e) {
				e.printStackTrace();
			}

		}
		sb.append("</xml>");

		return sb.toString();
	}

解析xml

/**
	 * 
	 * @param xml
	 * @param cls
	 * @return 解析XML
	 */
	public static <D> D fromXml(String xml, Class<D> cls) {
		SAXParserFactory factory = SAXParserFactory.newInstance();
		D obj = null;
		try {

			SAXParser parser = factory.newSAXParser();
			SAXParserHandler handler = new SAXParserHandler();
			StringReader sr = new StringReader(xml);
			InputSource is = new InputSource(sr);
			parser.parse(is, handler);
			Map<String, Object> map = handler.getValues();

			//
			// Class<?> cls = obj.getClass();
			obj = cls.newInstance();
			List<Field> fs = CommonUtils.getAllField(cls);
			for (Field f : fs) {
				String fn = f.getName();
				if (map.containsKey(fn)) {
					Object v = map.get(fn);
					// LOG.info(fn + ":" + v);
					try {
						f.setAccessible(true);
						if (f != null) {
							String typeName = f.getType().getName();
							if ("int".equals(typeName) || "java.lang.Integer".equals(typeName)) {
								f.set(obj, Integer.parseInt(v.toString()));
							} else if ("java.lang.Boolean".equals(typeName) || "boolean".equals(typeName)) {
								f.set(obj, Boolean.parseBoolean(v.toString()));
							} else if ("float".equals(typeName) || "java.lang.Float".equals(typeName)) {
								f.set(obj, Float.parseFloat(v.toString()));
							} else if ("java.lang.Double".equals(typeName) || "double".equals(typeName)) {
								f.set(obj, Double.parseDouble(v.toString()));
							} else if ("long".equals(typeName) || "java.lang.Long".equals(typeName)) {
								f.set(obj, Long.parseLong(v.toString()));
							} else {
								f.set(obj, v);
							}
						}
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}

		} catch (Exception e) {
			e.printStackTrace();
		}
		return obj;
	}

生成参数键值对

	/**
	 * 
	 * @return 值为空的不处理
	 */
	public Map<String, Object> toMap() {
		Map<String, Object> map = new HashMap<String, Object>();

		List<Field> fs = CommonUtils.getAllField(this.getClass());
		for (Field f : fs) {
			try {
				f.setAccessible(true);
				Object o = f.get(this);
				if (o != null && o.toString().length() > 0) {
					map.put(f.getName(), o);
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

		return map;
	}

相关方法

	/**
	 * 
	 * @param cls
	 * @return 包含父类的字段
	 */
	public static List<Field> getAllField(Class<?> cls) {
		List<Field> r = new ArrayList<Field>();
		List<Class<?>> rcls = getAllClass(cls);
		for (Class<?> c : rcls) {
			try {
				Field[] fs = c.getDeclaredFields();
				r.addAll(Arrays.asList(fs));
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return r;
	}

获取所有类

	/**
	 * 
	 * @param cls
	 * @return
	 */
	public static List<Class<?>> getAllClass(Class<?> cls) {
		List<Class<?>> result = new ArrayList<Class<?>>();
		for (; cls != Object.class; cls = cls.getSuperclass()) {
			result.add(cls);
		}
		return result;
	}

后续

  • 对于微信支付的坑,本篇肯定没有完全覆盖,如有其他朋友发现,欢迎留言。
  • 对于微信支付相关,欢迎探讨。