1,首先本人使用的是新版即时到帐的接口文档开发。本人没有使用支付宝的sdk包,所有代码都有自己参考Sdk包自己编写。并且wap手机支付异步通知和同步通知(新版称前台回调),都集成在之前开发的电脑扫码支付的同步和异步通知。
2,加密算法使用了RSA2,并使用RSA2进行签名和验证签名,本人使用自定义签名和自定义验签。
3,开发过程中要走了不少弯路,特把自己遇到的坑梳理一下,供自己以后复习和大家参考:
(1)首先使用支付宝提供的生产公钥和私钥的工具,并商家用户创建应用,上传了应用公钥到支付宝,如下图所示:
这里注意的是:(1)选择RSA(SHA256)密钥。(2)这里有个概念没弄明白,应用公钥和支付宝公钥的区别,但是一定要明白签名我们带着自己的应用私钥去签名,当验证签名时,我们使用的是支付宝公钥而非应用公钥,我就在这里吃大亏了。
(2)在签名时参数问题
查看文档,当时没明白,分为公共参数,业务参数之分,起初以为只传递业务参数即可,后来仔细看文档,公共参数也需要传递,并且要把业务参数封装到公共参数 biz_content字段中,并且要转成json字符串格式。
(3)还是签名时,我们要对传递的参数值进行encode编码,哥们啊,看清楚啊,是值不是参数,都是血和泪啊
,之前就是把这个参数都进行了encode编码。验证签名时要对参数值进行decode解码,才能验证成功。对于sign签名要对参数名按照ASCII码排序,之后进行base64.encodeBase64加密和验证签名时Base64.decodeBase64,支付宝SDK的签名方法中已经做了处理,不做解释。这里只贴出了签名时对参数名排序和对参数值的encode加码和验证签名时对参数名排序和对参数值的decode解码代码。
/**
*
* 对签名后的请求参数值
* (1)对key排序
* (2)对value进行encode编码
* (3)验证签名时对value进行decode解码
* @param params
* @param charset
* @return
* @throws IOException
*/
public static String buildQuery(Putter p, String charset) throws IOException {
Map params = p.getMap();
if (params == null || params.isEmpty()) {
return null;
}
StringBuilder query = new StringBuilder();
List keys = new ArrayList(params.keySet());
Collections.sort(keys);
boolean hasParam = false;
if(p.get("sign")!=null && !p.get("sign").equals("")){ //签名时使用
for (int i = 0; i < keys.size(); i++) {
String name = (String) keys.get(i);
String value = (String) params.get(name);
// 忽略参数名或参数值为空的参数
if (areNotEmpty(name, value)) {
if (hasParam) {
query.append("&");
} else {
hasParam = true;
}
query.append(name).append("=").append(URLEncoder.encode(value, charset));
}
}
}else{ //验证签名时使用
for (int i = 0; i < keys.size(); i++) {
String name = (String) keys.get(i);
String value = (String) params.get(name);
// 忽略参数名或参数值为空的参数
if (areNotEmpty(name, value)) {
if (hasParam) {
query.append("&");
} else {
hasParam = true;
}
query.append(name).append("=").append(URLDecoder.decode(value, charset));
}
}
}
return query.toString();
}
(4)支付成功后,只要签名和验签没问题,没有什么好说的,可说的就是前台回调(即同步通知),之前总是不能跳转,看文档说是返回的json格式,说是和异步通知验签不同,其实是相同的,表面上的几点不同如下:
(1) 参数名变更了,旧版的交易金额使用total_fee,新版现在使用total_amount
(2) 名称改名,前台回调
(3) 看文档返回的是json格式数据,但是在处理时,还是可以使用如下代码:
Map<String,String> params = new HashMap<String,String>();
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] + ",";
}
//乱码解决,这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
params.put(name, valueStr);
}
获取数据。然后做回调页面处理即可。