提供微商城·微分销·小程序开店需求
5分钟开通你的微信商城店铺!2018-09-20 作者:秩名
本文主要针对服务商下特约商户的小程序支付进行讲解。(扫码支付, h5支付大致流程都差不多,了解了小程序支付能够很快接入其他支付类型)
说明:本文中的支付都是指在服务商模式下
一个商家主体可以在不同服务商下申请特约商户,每个服务商都会给商家主体在此服务商下一个特约商户号。
普通商户申请需要花费大约300RMB,服务商申请特约商户不需要费用。
一个商家主体可以申请 普通商户,特约商户。同一个商户主体申请的普通商户与在服务商下申请的特约商户号是独立的。
服务商下的特约商户的资金流转不会直接经过服务商的支付账户,最终消费者的资金直接和服务商下的特约商户进行来往,但是服务商可以查看自己下的特约商户资金流水。
服务商小程序开发文档
申请注册服务商,通过之后登录微信商户平台,进入菜单: 服务商功能 --> 特约商户管理 -->新增商户(也就是申请服务商下的特约商户)
申请如果没有问题会在三到五天通过,之后可以在特约商户管理
下看到服务商自己的特约商户,我们在开发中需要服务商商户号及这里的商户号(特约商户号)
统一下单请求参数封装为我们可以处理的对象:
此处我的命名是: WechatUnifiedorderRequest
以下是我开发中遇到一些坑,主要是由于微信官方的文档给的参数很模糊,特别是小程序支付。
我们需要对对象按照字典序排序
第一步,设所有发送或者接收到的数据为集合M,将集合M内非空参数值的参数按照参数名ASCII码从小到大排序(字典序),使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串stringA。
/**
* 获取用户真实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 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 sortMap = new TreeMap(
new Comparator() {
@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对象上使用注解
/**
* 微信统一下单请求对象
*
* @Author xuelongjiang
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "xml")//xml的根元素
public class WechatUnifiedorderRequest implements Serializable{
}
对象转换为xml字符
引入包:import javax.xml.bind.JAXBContext
/**
* 对象转换为xml
* @param object
* @return
*/
public static String objectToXml(Object object){
StringWriter sw = new StringWriter();
try {
JAXBContext context = JAXBContext.newInstance(object.getClass());
Marshaller marshaller = context.createMarshaller();
marshaller.marshal(object,sw);
}catch (Exception e){
e.printStackTrace();
logger.error("对象解析xml出现异常,对象为"+object.toString());
}
return sw.toString();
}
封装对象:WechatUnifiedorderResponse 表示微信统一下单响应的对象。
请求微信统一下单返回示例:
![CDATA[10000101]]>
参数值用XML转义即可,CDATA标签用于说明数据不被XML解析器解析,在转为对象的时候我们需要解析
WechatUnifiedorderResponse对象使用注解
以上的和WechatUnifiedorderRequest是一样,但是由于需要解析,我们创建CDataAdapter继承XmlAdapter ,使用注解@XmlJavaTypeAdapter来处理,在WechatUnifiedorderResponse需要处理的域上使用注解
如下:
@XmlJavaTypeAdapter(CDataAdapter.class)// 解析
private String return_code; //返回状态码
/**
*
* 注解使用, 对象与xml转换的字段需要有
*
* @Author xuelongjiang
*/
public class CDataAdapter extends XmlAdapter {
private static Logger logger = LoggerFactory.getLogger(CDataAdapter.class);
/**
* Do-nothing constructor for the derived classes.
*/
protected CDataAdapter() {
super();
}
/**
* Convert a value type to a bound type.
*
* @param v The value to be converted. Can be null.
* @throws Exception if there's an error during the conversion. The caller is responsible for
* reporting the error to the user through {@link ValidationEventHandler}.
*/
@Override
public String unmarshal(String v) throws Exception {
if("".equals(v)){
return "";
}
String v1 = null;
String v2 = null;
String subStart = "= 0){
v1 = v.substring(subStart.length(),v.length());
}else {
return v;
}
String subEnd = "]]>";
int b = v1.indexOf(subEnd);
if(b>= 0){
v2 = v1.substring(0,b);
}
return v2;
}
/**
* Convert a bound type to a value type.
*
* @param v The value to be convereted. Can be null.
* @throws Exception if there's an error during the conversion. The caller is responsible for
* reporting the error to the user through {@link ValidationEventHandler}.
*/
@Override
public String marshal(String v) throws Exception {
logger.info("对象转换xml:"+"");
return "";
}
}
到此为止,我们已经得到微信统一下单的响应值了,后续的处理不是很复杂。按照文档不会有很大的坑。
在做微信支付的时候,难点是以上的:请求参数说明模糊,在经历几次的传参试验及百度谷歌之后,才明白了参数的具体的使用,其实后续在做扫码支付的时候,发现扫码支付解释的比较清楚,小程序的文档确实比较坑。
推荐文章
是不是很多微信用户在使用微信小程序时会出现这样的问题,比如,突然中断的情况,其实这就是微信小程序闪退。微信小程...
日前,百度陆续开放了多个智能小程序流量入口,具体包括以下三类: 第一类是中心化入口。 用户除了在“我的“菜单可以...
微信应用的一个很大的优势就在于使用过程中是不需要进行注册和显式登录的,大部分问题基本上可以一键解决。但是在授权...
见到 wx.request 的第一眼,就让我想起了 $.ajax 这东西,使用起来确实有很多不方便,不能忍,幸好小程序是支持ES6语法的,所...
天店收银系统有星耀、星云、标准三个版本,每套系统版本的价格都有所不同,价格从800元起,下面小编就为大家从适用业态...
收银系统小程序的开通流程 1. 选择合适的收银软件 目前市场上有多种收银软件提供小程序店铺功能。例如,店益就是一款能...
在互联网高速发展的今天,线上线下一体化的商业模式已成为主流。特别是对于零售行业而言,将收银系统与微信公众号对接...
收银系统对接微信小程序的流程 准备工作:首先,商家需要准备好收银系统和小程序的开发环境。对于收银系统,可以使用...
直接说答案:目前是不能直接推送自己的小程序的。 不过也不是说没有办法,可以通过视频号小店,然后跳转到自己的微信...
第一:线上线下收银系统 线上线下收银系统是一种结合了实体店铺与在线销售渠道的技术解决方案。这种系统不仅提高了收...