也是第一次搞证书方式的,算是记录一下 ,免得以后用到再去翻了,支付JDK 使用的是4.5 工具类如下
package Test;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.alipay.api.AlipayApiException;
import com.chanxa.monitor.model.AlipayLog;
public interface AlipayInterface {
/**
* 获取支付宝签名
* @param subject
* @param timeoutExpress
* @param notifyUrl
* @param orderId
* @param actualPay
* @return
*/
public String getSign(String subject,String timeoutExpress,String notifyUrl,String orderId,String actualPay)throws AlipayApiException;
/**
* 验证接受的数据是否为支付宝合法数据
*/
public boolean reaCert(Map<String, String> params)throws AlipayApiException;
/**
* 验证返回信息是否正确 正常 返回true 异常返回false
*/
public boolean verific(AlipayLog log,Integer type);
/**
* 支付宝分账关系绑定接口
* @param account 分账方账号 (登陆账号 或 用户号)
* @param type 分账类型 (分账方类型。userId:表示是支付宝账号对应的支付宝唯一用户号;loginName:表示是支付宝登录号 )
* @param name 分账方全称
* @param outRequestNo 外部请求号。32个字符以内,可包含字母、数字、下划线。需保证在商户端不重复。
* @throws AlipayApiException
*/
public boolean bindPaypal(String account,String type,String name,String outRequestNo) throws AlipayApiException;
/**
* 支付宝分账关系解绑接口
* @param account 分账方账号 (登陆账号 或 用户号)
* @param type 分账类型 (分账方类型。userId:表示是支付宝账号对应的支付宝唯一用户号;loginName:表示是支付宝登录号 )
* @param name 分账方全称
* @param outRequestNo 外部请求号。32个字符以内,可包含字母、数字、下划线。需保证在商户端不重复。
* @throws AlipayApiException
*/
public boolean unBindPaypal(String account,String type,String name,String outRequestNo) throws AlipayApiException;
/**
* 支付宝分账接口
* @param outRequestNo 外部请求号。32个字符以内,可包含字母、数字、下划线。需保证在商户端不重复。
* @param tradeNo 支付宝订单号
* @param transIn 收入方账户。如果收入方账户类型为userId,本参数为收入方的支付宝账号对应的支付宝唯一用户号,以2088开头的纯16位数字;如果收入方类型为cardAliasNo,本参数为收入方在支付宝绑定的卡编号;如果收入方类型为loginName,本参数为收入方的支付宝登录号;
* @throws AlipayApiException
* @param amount 分账金额
*/
public boolean settlePaypal(String outRequestNo,String tradeNo,String transIn,BigDecimal amount) throws AlipayApiException;
/**
* 支付宝转账接口
* @param outBizNo 商户端的唯一订单号,对于同一笔转账请求,商户需保证该订单号唯一。
* @param transAmount 订单总金额,单位为元,精确到小数点后两位,
* @param orderTitle 转账业务的标题,用于在支付宝用户的账单里显示
* @param identity 参与方的唯一标识
* @param name 参与方真实姓名,如果非空,将校验收款支付宝账号姓名一致性。当identity_type=ALIPAY_LOGON_ID时,本字段必填。
* @throws AlipayApiException
*/
public boolean transfer(String outBizNo,BigDecimal transAmount,String orderTitle,String identity,String name ) throws AlipayApiException;
/**
* 支付宝扫码支付接口 --web
*@param outTradeNo 商户订单号
*@param totalAmount 订单金额
*@param subject 订单标题
*@param sellerId 卖家支付宝用户ID
* @throws AlipayApiException
* @throws IOException
*/
public String Precreate(String outTradeNo,BigDecimal totalAmount,String subject,String sellerId) throws AlipayApiException, IOException;
}
package Test;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Service;
import com.alipay.api.AlipayApiException;
import com.alipay.api.CertAlipayRequest;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayFundTransUniTransferRequest;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.request.AlipayTradeOrderSettleRequest;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.request.AlipayTradePrecreateRequest;
import com.alipay.api.request.AlipayTradeRoyaltyRelationBindRequest;
import com.alipay.api.request.AlipayTradeRoyaltyRelationUnbindRequest;
import com.alipay.api.response.AlipayFundTransUniTransferResponse;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.alipay.api.response.AlipayTradeOrderSettleResponse;
import com.alipay.api.response.AlipayTradePrecreateResponse;
import com.alipay.api.response.AlipayTradeRoyaltyRelationBindResponse;
import com.alipay.api.response.AlipayTradeRoyaltyRelationUnbindResponse;
import com.chanxa.monitor.model.AlipayLog;
import com.chanxa.monitor.pay.service.AlipayInterface;
import com.chanxa.monitor.utils.Configuration;
@Service
public class AlipayService implements AlipayInterface {
String appid = Configuration.getConfig().getValue("alipau_appKey");
// 私钥
String private_key = Configuration.getConfig().getValue("key_rsa");
// 公钥
String alipay_public_key = Configuration.getConfig().getValue("alipay_public_key");
// 应用公钥证书路径(app_cert_path 文件绝对路径)
String app_cert_path = Configuration.getConfig().getValue("app_cert_path");
// 支付宝公钥证书文件路径(alipay_cert_path 文件绝对路径),支付宝CA根证书文件路径(alipay_root_cert_path
// 文件绝对路径)
String alipay_cert_path = Configuration.getConfig().getValue("alipay_cert_path");
// 支付宝CA根证书文件路径(alipay_root_cert_path 文件绝对路径)
String alipay_root_cert_path = Configuration.getConfig().getValue("alipay_root_cert_path");
CertAlipayRequest certAlipayRequest = new CertAlipayRequest();
public AlipayService() {
certAlipayRequest.setServerUrl("https://openapi.alipay.com/gateway.do");
certAlipayRequest.setAppId(appid);
certAlipayRequest.setPrivateKey(private_key);
certAlipayRequest.setFormat("json");
certAlipayRequest.setCharset("utf-8");
certAlipayRequest.setSignType("RSA2");
certAlipayRequest.setCertPath(app_cert_path);
certAlipayRequest.setAlipayPublicCertPath(alipay_cert_path);
certAlipayRequest.setRootCertPath(alipay_root_cert_path);
}
/**
* @param subject
* 交易标题
* @param timeoutExpress
* 有效时间
* @param notifyUrl
* 回调路径
* @param orderId
* 订单编号
* @param actualPay
* 支付金额
* @throws AlipayApiException
*/
@Override
public String getSign(String subject, String timeoutExpress, String notifyUrl, String orderId, String actualPay)
throws AlipayApiException {
DefaultAlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);
// 实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay
AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
// SDK已经封装掉了公共参数,这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
model.setSubject(subject);
model.setOutTradeNo(orderId);
model.setTimeoutExpress(timeoutExpress);
model.setTotalAmount(actualPay + "");
model.setProductCode("QUICK_MSECURITY_PAY");
request.setBizModel(model);
request.setNotifyUrl(notifyUrl);
try {
// 这里和普通的接口调用不同,使用的是sdkExecute
AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
return response.getBody();
} catch (AlipayApiException e) {
e.printStackTrace();
}
return "";
}
/**
* APP 充值 支付宝回调验签 公共方法
*/
@Override
public boolean reaCert(Map<String, String> params) throws AlipayApiException {
return AlipaySignature.rsaCertCheckV1(params, alipay_cert_path, "utf-8", "RSA2");
}
/**
* APP 充值 验证公共参数部分是否正确 公共方法
*/
@Override
public boolean verific(AlipayLog log, Integer type) {
String seller_email = Configuration.getConfig().getValue("seller_email");
// 判断 回调里卖家支付宝账号 是否为系统卖家支付宝ID
if (!seller_email.equals(log.getSellerEmail())) {
return false;
}
// 判断APPID 是否为系统的APPID
String alipau_appKey = Configuration.getConfig().getValue("alipau_appKey");
if (!alipau_appKey.equals(log.getAuthAppId())) {
return false;
}
return true;
}
/**
* 支付宝分账关系绑定接口
*
* @param account
* 分账方账号 (登陆账号 或 用户号)
* @param type
* 分账类型 (分账方类型。userId:表示是支付宝账号对应的支付宝唯一用户号;loginName:表示是支付宝登录号 )
* @param name
* 分账方全称
* @param outRequestNo
* 外部请求号。32个字符以内,可包含字母、数字、下划线。需保证在商户端不重复。
* @throws AlipayApiException
*/
@Override
public boolean bindPaypal(String account, String type, String name, String outRequestNo) throws AlipayApiException {
DefaultAlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);
AlipayTradeRoyaltyRelationBindRequest request = new AlipayTradeRoyaltyRelationBindRequest();
request.setBizContent(
"{\"receiver_list\":[{\"type\":\"loginName\",\"account\":\"" + account + "\",\"name\":\"" + name + "\"}],\"out_request_no\":" + outRequestNo + "}");
AlipayTradeRoyaltyRelationBindResponse response = alipayClient.certificateExecute(request);
if (response.isSuccess()) {
return true;
} else {
return false;
}
}
/**
* 支付宝分账关系解绑接口
*
* @param account
* 分账方账号 (登陆账号 或 用户号)
* @param type
* 分账类型 (分账方类型。userId:表示是支付宝账号对应的支付宝唯一用户号;loginName:表示是支付宝登录号 )
* @param name
* 分账方全称
* @param outRequestNo
* 外部请求号。32个字符以内,可包含字母、数字、下划线。需保证在商户端不重复。
* @throws AlipayApiException
*/
@Override
public boolean unBindPaypal(String account, String type, String name, String outRequestNo)
throws AlipayApiException {
DefaultAlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);
AlipayTradeRoyaltyRelationUnbindRequest request = new AlipayTradeRoyaltyRelationUnbindRequest();
request.setBizContent(
"{\"receiver_list\":[{\"type\":\"loginName\",\"account\":\"" + account + "\",\"name\":\"" + name + "\"}]," + "\"out_request_no\":" + outRequestNo + "}");
AlipayTradeRoyaltyRelationUnbindResponse response = alipayClient.certificateExecute(request);
if (response.isSuccess()) {
return true;
} else {
return false;
}
}
/**
* 支付宝分账接口
*
* @param outRequestNo
* 外部请求号。32个字符以内,可包含字母、数字、下划线。需保证在商户端不重复。
* @param tradeNo
* 支付宝订单号
* @param transIn
* 收入方账户。如果收入方账户类型为userId,本参数为收入方的支付宝账号对应的支付宝唯一用户号,
* 以2088开头的纯16位数字;如果收入方类型为cardAliasNo,本参数为收入方在支付宝绑定的卡编号;
* 如果收入方类型为loginName,本参数为收入方的支付宝登录号;
* @throws AlipayApiException
* @param amount
* 分账金额
*/
@Override
public boolean settlePaypal(String outRequestNo, String tradeNo, String transIn, BigDecimal amount)
throws AlipayApiException {
DefaultAlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);
AlipayTradeOrderSettleRequest request = new AlipayTradeOrderSettleRequest();
request.setBizContent("{\"out_request_no\":\"" + outRequestNo + "\",\"trade_no\":\"" + tradeNo + "\",\"royalty_parameters\":[{\"trans_in\":\"" + transIn + "\",\"amount\":"+amount+",\"trans_in_type\":\"loginName\"}]}");
AlipayTradeOrderSettleResponse response = alipayClient.certificateExecute(request);
if (response.isSuccess()) {
return true;
} else {
return false;
}
}
/**
* 支付宝转账接口
* @param outBizNo 商户端的唯一订单号,对于同一笔转账请求,商户需保证该订单号唯一。
* @param transAmount 订单总金额,单位为元,精确到小数点后两位,
* @param orderTitle 转账业务的标题,用于在支付宝用户的账单里显示
* @param identity 参与方的唯一标识
* @param name 参与方真实姓名,如果非空,将校验收款支付宝账号姓名一致性。当identity_type=ALIPAY_LOGON_ID时,本字段必填。
* @throws AlipayApiException
*/
@Override
public boolean transfer(String outBizNo, BigDecimal transAmount, String orderTitle, String identity, String name) throws AlipayApiException {
DefaultAlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);
AlipayFundTransUniTransferRequest request = new AlipayFundTransUniTransferRequest();
request.setBizContent("{\"out_biz_no\":\""+outBizNo+"\",\"trans_amount\":"+transAmount+",\"product_code\":\"TRANS_ACCOUNT_NO_PWD\",\"order_title\":\""+orderTitle+"\",\"biz_scene\":\"DIRECT_TRANSFER\",\"payee_info\":{\"identity\":\""+identity+"\",\"identity_type\":\"ALIPAY_LOGON_ID\",\"name\":\""+name+"\"}}");
AlipayFundTransUniTransferResponse response = alipayClient.certificateExecute(request);
if(response.isSuccess()){
return true;
} else {
return false;
}
}
@Override
public String Precreate(String outTradeNo, BigDecimal totalAmount, String subject, String sellerId) throws AlipayApiException, IOException {
DefaultAlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);
AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();//创建API对应的request
alipayRequest.setBizContent("{\"out_trade_no\":\""+outTradeNo+"\",\"total_amount\":"+totalAmount+",\"subject\":\""+subject+"\",\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");
alipayRequest.setReturnUrl("这里是跳转页面");
alipayRequest.setNotifyUrl("这里是返回通知路径");
String form="";
try {
form = alipayClient.pageExecute(alipayRequest).getBody(); //调用SDK生成表单
} catch (AlipayApiException e) {
e.printStackTrace();
}
return form;
}
}
接下来是回调
package Test;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import com.chanxa.monitor.model.AlipayLog;
import com.chanxa.monitor.pay.service.AlipayInterface;
import com.chanxa.monitor.utils.CheckUtil;
@Controller
@RequestMapping("/text/callBack/")
public class PayCallbackController {
Logger logger = LoggerFactory.getLogger( PayCallbackController.class );
@Resource
private AlipayInterface alipayService;
/**
* 处理支付宝回调返回的数据
* @param request
* @return
* @throws Exception
*/
public AlipayLog getAlipayLog(HttpServletRequest request) throws Exception {
AlipayLog log = new AlipayLog();
// 订单号
String out_trade_no = request.getParameter("out_trade_no");
// 支付宝交易号
String trade_no = request.getParameter("trade_no");
// 交易状态
String trade_status = request.getParameter("trade_status");
//交易标题
String subject = request.getParameter("subject");
//卖家支付宝用户号
String seller_id = request.getParameter("seller_id");
//卖家支付宝账号
String seller_email = request.getParameter("seller_email");
//买家支付宝账号对应的支付宝唯一用户号
String buyer_id = request.getParameter("buyer_id");
//买家支付宝账号
String buyer_email = request.getParameter("buyer_email");
//本次交易支付的订单金额,单位为人民币(元)
String total_fee = request.getParameter("total_amount");
//用户在交易中实际付款金额
String buyer_pay_amount = request.getParameter("buyer_pay_amount");
//商家实际收到的金额
String receipt_amount = request.getParameter("receipt_amount");
//appID
String auth_app_id=request.getParameter("auth_app_id");
String gmt_refund = request.getParameter("gmt_refund");
String body = request.getParameter("body");
log.setOrderId(out_trade_no);
log.setBuyerEmail(buyer_email);
log.setBuyerId(buyer_id);
log.setBuyerPayAmount(buyer_pay_amount);
log.setReceiptAmount(receipt_amount);
log.setAuthAppId(auth_app_id);
String gmt_create = request.getParameter("gmt_create");
String gmt_payment = request.getParameter("gmt_payment");
String refund_status = request.getParameter("refund_status");
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
log.setGmtCreate(CheckUtil.isNullEmpty(gmt_create) ? null : dateFormat.parse(gmt_create));
log.setGmtPayment(CheckUtil.isNullEmpty(gmt_payment) ? null : dateFormat.parse(gmt_payment));
log.setGmtRefund(CheckUtil.isNullEmpty(gmt_refund) ? null : dateFormat.parse(gmt_refund));
log.setRefundStatus(refund_status);
log.setSellerEmail(seller_email);
log.setSellerId(seller_id);
log.setSubject(subject);
log.setTotalFee(total_fee);
log.setTradeNo(trade_no);
log.setTradeStatus(trade_status);
log.setBody(body);
return log;
}
/**
* 获取POST过来反馈信息
* @param request
* @return
*/
public Map<String, String> getParamsFromRequest(HttpServletRequest request) {
Map<String, String> params = new HashMap<String, String>();
Map<String, String[]> requestParams = request.getParameterMap();
for (Iterator<String> 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不相等也可以使用这段代码转化
params.put(name, valueStr);
}
return params;
}
/**
* 支付宝回调
* @param request
* @param response
* @throws Exception
*/
@RequestMapping(value = "alipayCallback")
public void alipayCallback(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 获取POST过来反馈信息
Map<String, String> params=this.getParamsFromRequest(request);
//验证是否为支付宝合法参数
boolean flag=alipayService.reaCert(params);
PrintWriter out = response.getWriter();
if(flag){//验签通过
AlipayLog log =this.getAlipayLog(request);
if(log.getTradeStatus().equals("TRADE_SUCCESS")||log.getTradeStatus().equals("TRADE_FINISHED")){
//验证支付信息和订单信息是否匹配
boolean brook=alipayService.verific(log, 1);
if(brook){//验证通过,执行相应的逻辑
//执行完毕 添加支付日志
//返回成功给支付宝
out.println("success");
}else{
//不匹配 原路退回
out.println("failure");
}
}else{
out.println("failure");
}
}else{
out.println("failure");
}
out.flush();
out.close();
}
}