欢迎来到258分享网,纯净的网络源码分享基地!

258资源分享网

全部作品
全部作品
网站源码
微信源码
素材特效
源码插件
视频教程
建站学院
热门搜索: 织梦  农业种植  农业  安全设置  官方
258资源分享 > 建站学院 > 微信开发 > 微信支付服务商接入指引

推荐下载

HTML5响应式自适应网咯设计

2020-05-12   浏览:740

高端HTML5响应式企业通用网

2020-05-06   浏览:521

html5响应式外贸网站英文版

2020-05-08   浏览:510

HTML5自适应律师工作室类网

2020-04-04   浏览:504

HTML5影视传媒文化公司类网

2020-05-12   浏览:500

微信支付服务商接入指引

发布时间:2020-10-13  
微信支付服务商接入指引

本文主要针对服务商下特约商户的小程序支付进行讲解。(扫码支付, h5支付大致流程都差不多,了解了小程序支付能够很快接入其他支付类型)

说明:本文中的支付都是指在服务商模式下

支付主体

服务商:拥有支付开发能力的第三方提供商

普通商户: 拥有开发能力的商户

特约商户:服务商下的商户

一个商家主体可以在不同服务商下申请特约商户,每个服务商都会给商家主体在此服务商下一个特约商户号。

普通商户申请需要花费大约300RMB,服务商申请特约商户不需要费用。

一个商家主体可以申请 普通商户,特约商户。同一个商户主体申请的普通商户与在服务商下申请的特约商户号是独立的。

服务商

服务商下的特约商户的资金流转不会直接经过服务商的支付账户,最终消费者的资金直接和服务商下的特约商户进行来往,但是服务商可以查看自己下的特约商户资金流水。

服务商小程序开发文档

开发支付 开发之前

申请注册服务商,通过之后登录微信商户平台,进入菜单: 服务商功能 --> 特约商户管理 -->新增商户(也就是申请服务商下的特约商户)
申请如果没有问题会在三到五天通过,之后可以在特约商户管理
下看到服务商自己的特约商户,我们在开发中需要 服务商商户号及这里的商户号(特约商户号)

支付需要接口:微信统一下单,及提供给微信的回调接口

微信官方给的业务流程图:

微信支付服务商接入指引

可以很清晰的理解业务流程走向。

统一下单接口 微信统一下单请求参数

统一下单请求参数封装为我们可以处理的对象:

此处我的命名是: WechatUnifiedorderRequest

以下是我开发中遇到一些坑,主要是由于微信官方的文档给的参数很模糊,特别是小程序支付。

 

微信支付服务商接入指引

在填充好了WechatUnifiedorderRequest对象后对我们填充的值按照字典排序,连接key进行签名,以xml格式字符向微信发起请求

我们需要对对象按照字典序排序

第一步,设所有发送或者接收到的数据为集合M,将集合M内非空参数值的参数按照参数名ASCII码从小到大排序(字典序),使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串stringA。

字典排序后的字符连接key(需要在微信商户平台进行配置建议使用UUID生成32位)

MD5加密签名,得到sign填充WechatUnifiedorderRequest对象

WechatUnifiedorderRequest转换为微信需要的xml类型

发起请求

得到微信统一下单的响应(是xml字符格式),解析为对象(对返回的响应封装对象进行处理WechatUnifiedorderResponse),

对返回的对象进行验证,通过验证返回给小程序 需要的参数及签名 小程序调起支付API

小程序支付成功,微信开始回调在统一下单传给微信的回调地址

获取下单用户的真实IP /** * 获取用户真实IP * 如果有代理,获取真实客户端IP * @param request * @return */ public static String getRealId(HttpServletRequest request){ String xForwardedForHeader= request.getHeader("X-Forwarded-For"); if(xForwardedForHeader == null){ return request.getRemoteAddr(); }else { return new StringTokenizer(xForwardedForHeader, ",").nextToken().trim(); } }
 
按照字典序排序 /** * 使用java反射机制,动态获取对象的属性和参数值,排除值为null的情况,并按字典序排序 * @param object * @return */ public static String getSortMap(Object object) throws Exception{ //1.得到属性的名称及值 如果为null不存入map Field [] fields = object.getClass().getDeclaredFields(); Map<String,String> map = new HashMap<>(); for(Field field : fields){ String name = field.getName(); /*String methodName = "get"+name.replaceFirst(name.substring(0, 1), name.substring(0, 1) .toUpperCase());*/ //通过get方法直接获取属性值 field.setAccessible(true); Object value = field.get(object); if (value != null){ map.put(name, value.toString()); } } //排序 Map<String, String> sortMap = new TreeMap<String,String>( new Comparator<String>() { @Override public int compare(String arg0, String arg1) { return arg0.compareTo(arg1); } }); sortMap.putAll(map); StringBuilder sortFeil = new StringBuilder(); //得到键值对的格式(即key1=value1&key2=value2… sortMap.forEach((k,v)-> { sortFeil.append(k+"="+v+"&"); }); //移除最后一个 & sortFeil.deleteCharAt(sortFeil.length()-1); return sortFeil.toString(); }  

使用字典序返回的字符连接key,使用MD5进行加密,得到sign

WechatUnifiedorderRequest转换为微信需要的xml类型

在WechatUnifiedorderRequest对象上使用注解

@xmlAccessorType @xmlAccessorType(XmlAccessType.FIELD)