一,简要说明:
支付宝支付大概分为2种方式:1.app支付 2.手机网站支付。所用的参数:appid,private_key,open_public_key也基本相同,感觉没有微信那么乱。但是使用的时候要确保是完整的一套,基本上报以上3个中参数错误,大概就是没有使用一套参数,另外sign_type签名方式也要注意,新旧版本不同,新的是RSA2(阿里推荐),旧的是RSA。
二.准备工作,申请账号>签约>配置,具体的有支付宝得到文档接口说:https://openhome.alipay.com/developmentDocument.htm“>这里写链接内容, 选择自己需要的按照文档来。
三.开发:
1.app支付代码
后台接口中的代码:
Map<String, String> params = OrderInfoUtil2_0.buildOrderParamMap(APP_ID, outTradeNo, subject,body, totalamount, UtilDate.getDateFormatter());
String orderParam = OrderInfoUtil2_0.buildOrderParam(params);
String sign = OrderInfoUtil2_0.getSign(params, AlipayConfig.private_key);
final String orderInfo = orderParam + "&" + sign;
回调解析业务处理:
//异步通知ID
String notify_id=request.getParameter("notify_id");
//sign
String sign=request.getParameter("sign");
if(notify_id!=""&¬ify_id!=null){////判断接受的post通知中有无notify_id,如果有则是异步通知。
if(AlipayNotify.verifyResponse(notify_id).equals("true"))//判断成功之后使用getResponse方法判断是否是支付宝发来的异步通知。
{
if(AlipayNotify.getSignVeryfy(params, sign))//使用支付宝公钥验签
{
//——请根据您的业务逻辑来编写程序(以下代码仅作参考)——
if(trade_status.equals("TRADE_FINISHED")){
//判断该笔订单是否在商户网站中已经做过处理
//如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序
//如果有做过处理,不执行商户的业务程序
//注意:
//退款日期超过可退款期限后(如三个月可退款),支付宝系统发送该交易状态通知
//请务必判断请求时的total_fee、seller_id与通知时获取的total_fee、seller_id为一致的
} else if (trade_status.equals("TRADE_SUCCESS")){
《@@》 //自己的业务逻辑出来
}
工具方法:
/**
* 构造支付订单参数列表
*
* @param pid
* @param app_id
* @param target_id
* @return
*/
public static Map<String, String> buildOrderParamMap(String app_id,String outTradeNo,String subject,String body,String total_amount,String timestamp) {
Map<String, String> keyValues = new HashMap<String, String>();
keyValues.put("app_id", app_id);
keyValues
.put("biz_content",
"{\"timeout_express\":\"30m\",\"product_code\":\"QUICK_MSECURITY_PAY\",\"total_amount\":\""+total_amount+"\",\"subject\":\""+subject+"\",\"body\":\""+body+"\",\"out_trade_no\":\""
+ outTradeNo + "\"}");
keyValues.put("charset", "utf-8");
keyValues.put("method", "alipay.trade.app.pay");
keyValues.put("sign_type", "RSA2");
keyValues.put("timestamp", timestamp);
keyValues.put("notify_url", "回调地址");
keyValues.put("version", "1.0");
return keyValues;
}
/**
* 构造支付订单参数信息
*
* @param map
* 支付订单参数
* @return
*/
public static String buildOrderParam(Map<String, String> map) {
List<String> keys = new ArrayList<String>(map.keySet());
StringBuilder sb = new StringBuilder();
for (int i = 0; i < keys.size() - 1; i++) {
String key = keys.get(i);
String value = map.get(key);
sb.append(buildKeyValue(key, value, true));
sb.append("&");
}
String tailKey = keys.get(keys.size() - 1);
String tailValue = map.get(tailKey);
sb.append(buildKeyValue(tailKey, tailValue, true));
return sb.toString();
}
/**
* 拼接键值对
*
* @param key
* @param value
* @param isEncode
* @return
*/
private static String buildKeyValue(String key, String value,
boolean isEncode) {
StringBuilder sb = new StringBuilder();
sb.append(key);
sb.append("=");
if (isEncode) {
try {
sb.append(URLEncoder.encode(value, "UTF-8"));
} catch (UnsupportedEncodingException e) {
sb.append(value);
}
} else {
sb.append(value);
}
return sb.toString();
}
/**
* 对支付参数信息进行签名
*
* @param map
待签名授权信息
* @return
*/
public static String getSign(Map<String, String> map, String rsaKey) {
List<String> keys = new ArrayList<String>(map.keySet());
// key排序
Collections.sort(keys);
StringBuilder authInfo = new StringBuilder();
for (int i = 0; i < keys.size() - 1; i++) {
String key = keys.get(i);
String value = map.get(key);
authInfo.append(buildKeyValue(key, value, false));
authInfo.append("&");
}
String tailKey = keys.get(keys.size() - 1);
String tailValue = map.get(tailKey);
authInfo.append(buildKeyValue(tailKey, tailValue, false));
String oriSign = SignUtils.sign(authInfo.toString(), rsaKey);
String encodedSign = "";
try {
encodedSign = URLEncoder.encode(oriSign, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return "sign=" + encodedSign;
}
/**
* 根据反馈回来的信息,生成签名结果
* @param Params 通知返回来的参数数组
* @param sign 比对的签名结果
* @return 生成的签名结果
*/
public static boolean getSignVeryfy(Map<String, String> Params, String sign) {
//过滤空值、sign与sign_type参数
Map<String, String> sParaNew = AlipayCore.paraFilter(Params);
//获取待签名字符串
String preSignStr = AlipayCore.createLinkString(sParaNew);
//获得签名验证结果
boolean isSign = false;
if(AlipayConfig.sign_type.equals("RSA")){
isSign = RSA.verify(preSignStr, sign, open_public_key, charset);
}
return isSign;
}
2.网页支付:
首先 集成Alipay-sdk,本人用的是maven,具体可参考:这里写链接内容
public void doPost(HttpServletRequest httpRequest, HttpServletResponse httpResponse,String json, ModelMap modelMap)throws ServletException, IOException {
AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", APP_ID, private_key, "json", CHARSET, public_key, AlipayConfig.sign_type); //获得初始化的AlipayClient
AlipayTradeWapPayRequest alipayRequest = new AlipayTradeWapPayRequest();//创建API对应的request
alipayRequest.setReturnUrl("http://domain.com/CallBack/return_url.jsp");
alipayRequest.setNotifyUrl( "回调地址");//在公共参数中设置回跳和通知地址
Result result = new Result();
result.setStatus(ResultEnum.fail_blank.getCode());
//获取对应的参数值
try {
String type ="";
String subject = "";
String body = "";
String userid = "";
String money = "";//圆
alipayRequest.setBizContent("{" +
" \"out_trade_no\":\""+outTradeNo+"\"," +
" \"total_amount\":\""+money+"\"," +
" \"subject\":\""+subject+"\"," +
" \"body\":\""+subject+"\"," +
" \"product_code\":\"QUICK_WAP_PAY\"" +
" }");//填充业务参数
String form="";
try {
form = alipayClient.pageExecute(alipayRequest).getBody(); //调用SDK生成表单
} catch (AlipayApiException e) {
e.printStackTrace();
}
httpResponse.setContentType("text/html;charset=" + CHARSET);
httpResponse.getWriter().write(form);//直接将完整的表单html输出到页面
httpResponse.getWriter().flush();
httpResponse.getWriter().close();
} catch (Exception e) {
e.printStackTrace();
result.setMsg(e.getMessage());
}
}
待续。