openssl-0.9.8k_WIN32(RSA密钥生成工具)生成商户私钥.根据商户私钥生成商户公钥(RSA密钥生成工具),把商户公钥在支付宝的私钥管理页面进行提交,支付宝会为商户提供一个支付宝公钥既
package com.alipay.client.callback;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.alipay.client.base.PartnerConfig;
import com.alipay.client.security.RSASignature;
/**
* 安全支付支付完成商户同步处理程序
* 对支付宝返回订单信息验签名
*/public class RSACallBack
extends HttpServlet {
private static final long serialVersionUID = -2234271646410251381L;
//签名成功
public static final String RESULT_CHECK_SIGN_SUCCEED = "T";
//签名失败
public static final String RESULT_CHECK_SIGN_FAILED = "F";
@SuppressWarnings("unchecked")
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws UnsupportedEncodingException {
//获得待签名数据和签名值
String sign = URLDecoder.decode(request.getParameter("sign"),"utf-8");
String content = URLDecoder.decode(request.getParameter("content"),"utf-8");
String retVal = RESULT_CHECK_SIGN_FAILED;
//使用支付宝公钥验签名
try {
PrintWriter out = response.getWriter();
if(RSASignature.doCheck(content, sign, PartnerConfig.RSA_ALIPAY_PUBLIC)){
retVal=RESULT_CHECK_SIGN_SUCCEED;
}
response.setContentType("text/html");
System.out.println("retVal : " + retVal);
out.print(retVal);
out.flush();
out.close();
}
catch (Exception e) {
e.printStackTrace();
System.out.println("验签名失败");
}
}
}
这个类基本不需要做修改,主要是RESULT_CHECK_SIGN_SUCCEED和RESULT_CHECK_SIGN_FAILED的值必须要与客户端相应代码的相应字段保持一致.这个类主要是支付完成之后客户端与服务器进行的一次验签名,可以用来更新数据给客户端.
/**
* Alipay.com Inc.
* Copyright (c) 2005-2008 All Rights Reserved.
*/package com.alipay.client.notify;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import java.util.Map;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.airplane.base.AbstractExecution;
import com.airplane.dao.IntegralDao;
import com.airplane.dao.OrderDao;
import com.airplane.dao.UserDao;
import com.airplane.domain.Integral;
import com.airplane.domain.Order;
import com.airplane.domain.User;
import com.alipay.client.base.PartnerConfig;
import com.alipay.client.security.RSASignature;
/**
* 接收通知并处理
*
* @author 3y
* @version $Id: NotifyReceiver.java, v 0.1 2011-8-15 下午03:11:58 3y Exp $
*/public class RSANotifyReceiver
extends HttpServlet {
private static final long serialVersionUID = 7216412938937049671L;
private static Log logger = LogFactory.getLog(RSANotifyReceiver.
class);
@SuppressWarnings("unchecked")
public void doPost(HttpServletRequest request, HttpServletResponse response){
System.out.println("接收到通知!");
//获得通知参数
try{
Map map = request.getParameterMap();
//获得通知签名
String sign = (String) ((Object[]) map.get("sign"))[0];
logger.info("sign="+sign);
//获得待验签名的数据
String verifyData = getVerifyData(map);
logger.info("verifyData="+verifyData);
boolean verified =
false;
//使用支付宝公钥验签名
try {
verified = RSASignature.doCheck(verifyData, sign, PartnerConfig.RSA_ALIPAY_PUBLIC);
logger.info("verified="+verified);
}
catch (Exception e) {
e.printStackTrace();
}
PrintWriter out = response.getWriter();
//验证签名通过
if (verified) {
//根据交易状态处理业务逻辑
//当交易状态成功,处理业务逻辑成功。回写success logger.info("支付宝支付:保存数据库信息success");
out.print("success");
}
else{
out.print("fail");
}
}
}
else{
out.print("fail");
}
}
else {
System.out.println("接收支付宝系统通知验证签名失败,请检查!");
out.print("fail");
}
}
catch (Exception e) {
e.printStackTrace();
logger.info(e);
}
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException {
doPost(request, response);
}
/**
* 获得验签名的数据
* @param map
* @return
* @throws Exception
*/ @SuppressWarnings("unchecked")
private String getVerifyData(Map map) {
String notify_data = (String) ((Object[]) map.get("notify_data"))[0];
logger.info(notify_data);
return "notify_data="+notify_data;
}
}
RSANotifyReceiver.java是支付宝回调服务器的servlet,需要安卓客户端传递该servlet地址及相关参数给支付宝,支付宝会在支付完成之后进行回调.回调之后会返回消息给支付宝.
/**
* Alipay.com Inc.
* Copyright (c) 2005-2008 All Rights Reserved.
*/
package com.alipay.client.trade;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.Security;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import com.airplane.action.BackStageAction;
import com.alipay.client.base.PartnerConfig;
import com.alipay.client.security.RSASignature;
import com.alipay.client.util.StringUtil;
/**
*
* 安全支付服务器端处理程序
*
* 1.将业务参数:合作商户ID、 外部交易号、商品名称、商品的具体描述、商品总价、卖家帐户、notify_url这些参数按照固定顺序签名
* 2.将签名结果返回客户端
* @author 3Y
*/
public class RSATrade extends HttpServlet {
private static final long serialVersionUID = -3035307235076650766L;
private static Log logger = LogFactory.getLog(RSATrade.class);
static {
Security.addProvider(new BouncyCastleProvider());
}
String basePath="";
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws IOException {
System.out.println("request in");
response.setCharacterEncoding("utf-8");
PrintWriter out = response.getWriter();
logger.info("here");
//得到应用服务器地址
String path = request.getContextPath();
basePath = request.getScheme() + "://" + request.getLocalAddr() + ":"
+ request.getServerPort() + path + "/";
logger.info("here1");
String strReString="";
//检查商户PartnerConfig.java文件的配置参数
logger.info(checkInfo());
if(!checkInfo()){
strReString="<result><is_success>F</is_success><error>缺少partner或者seller," +
"请在com/alipay/client/base/PartnerConfig.java中增加</error></result>";
out.print(strReString);
return;
}
String signData=getSignDate(request);
String sign = sign(signData,PartnerConfig.RSA_PRIVATE);
signData = URLEncoder.encode(signData,"utf-8");
sign = URLEncoder.encode(sign,"utf-8");
logger.info(signData);
logger.info(sign);
//返回待签名数据和签名数据
strReString="<result><is_success>T</is_success><content>"+signData+"</content><sign>"+sign+"</sign></result>";
logger.info(strReString);
//对返回客户端的数据encode
out.print(strReString);
return;
}
//检查商户PartnerConfig.java文件的配置参数
private boolean checkInfo() {
String partner = PartnerConfig.PARTNER;
String seller = PartnerConfig.SELLER;
//如果合作商户ID为空或者账号ID为空返回false
if (StringUtil.isBlank(partner) || StringUtil.isBlank(seller))
return false;
return true;
}
/**
* 准备待签名的数据
*
* @param request
* @return
* @throws UnsupportedEncodingException
*/
private String getSignDate(
HttpServletRequest request) throws UnsupportedEncodingException {
request.setCharacterEncoding("utf-8");
//合作商户ID
String partner = PartnerConfig.PARTNER;
//卖家帐号
String seller = PartnerConfig.SELLER;
// 外部交易号 这里取当前时间,商户可根据自己的情况修改此参数,但保证唯一性
String outTradeNo = System.currentTimeMillis() + "";
String opt = request.getParameter("opt").trim();
String user_id = request.getParameter("user_id").trim();
//opt:0为支付,1为充值
if("0".equals(opt)){
outTradeNo = request.getParameter("order_id").trim();
}else if("1".equals(opt)){
outTradeNo = System.currentTimeMillis() + "";
}
// 商品名称
String subject = request.getParameter("subject").trim();
// 商品具体描述
String body = request.getParameter("body").trim();
// 商品总价
String totalFee = request.getParameter("total_fee").trim();
// 接收支付宝发送的通知的url 商户可根据自己的情况修改此参数
String notify_url = basePath+"servlet/RSANotifyReceiver?opt=" + opt +"&order_id="+outTradeNo+"&user_id="+user_id+"&payMoney="+totalFee;
//组装待签名数据
String signData = "partner=" + "\"" + partner + "\"";
signData += "&";
signData += "seller=" + "\"" + seller + "\"";
signData += "&";
signData += "out_trade_no=" + "\"" + outTradeNo + "\"";
signData += "&";
signData += "subject=" + "\"" + subject+ "\"";
signData += "&";
signData += "body=" + "\"" + body + "\"";
signData += "&";
signData += "total_fee=" + "\""+ totalFee + "\"";
signData += "&";
signData += "notify_url=" + "\""+notify_url+ "\"";
return signData;
}
/**
* 对参数进行签名
*
* @param signData 待签名数据,key rsa商户私钥
* @return
*/
private String sign(String signData,String key) {
System.out.println("signData:"+signData);
String sign = "";
try {
sign = RSASignature.sign(signData, key);
} catch (Exception e1) {
e1.printStackTrace();
}
return sign;
}
}
RSATrade.java为客户端与服务器端为商品信息进行的签名操作,签名完成之后服务器会将签名信息以及回调地址返给客户端.客户端拿到回调地址交给支付宝进行回调.
支付宝流程为:客户端在支付宝支付之前请求RSATrade.java,此时服务器为商品信息注册签名,签名完成之后服务器把签名过的商品信息和支付宝的回调地址(RSANotifyReceiver
)和参数传给客户端,客户端会把回调地址和签过名的商品信息交给支付宝,支付宝在完成支付之后请求回调地址,进行签名和公钥验证,验证成功即可执行持久化操作.若操作成功,客户端会请求RSACallBack.java类,进行客户端与服务器端的同步操作.