微信支付-那些神奇的坑
程序员文章站
2022-07-13 16:51:21
...
前段时间,由于工作需要,处理过*的微信支付。刚开始的时候,以为跟国内的微信支付没什么区别,很简单,但在实际操作中,才发现,这就是坑爹的货。
前人栽树,后人乘凉。我愿在此栽树一棵,愿后来人在此能乘凉。
接下来,请让我细数*微信支付的坑。(为保证坑的深度,请让我以境内和*来对比)
第一坑(业务接口名称叫法不一致)
- 境内的叫统一下单接口
- *的统一下单接口全部叫支付接口,也有叫公众账号&小程序支付接口
第二坑(统一下单请求地址不一致)
- 境内的请求地址是:https://api.mch.weixin.qq.com/pay/unifiedorder
- *的请求地址是:https://pay.swiftpass.cn/pay/gateway
第三坑(统一下单参数名称不一致)
- 境内的参数有: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;
}
后续
- 对于微信支付的坑,本篇肯定没有完全覆盖,如有其他朋友发现,欢迎留言。
- 对于微信支付相关,欢迎探讨。