也是第一次搞证书方式的,算是记录一下 ,免得以后用到再去翻了,支付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(); } }