概述:springboot 集成支付宝支付
springboot 集成支付宝支付
- 引入pom依赖
<dependency> <groupId>com.alipay.sdk</groupId> <artifactId>alipay-sdk-java</artifactId> <version>4.10.0.ALL</version> </dependency> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.2</version> </dependency> 12345678910
- 在配置文件配置私钥,支付宝公钥(注意不是支付宝应用公钥)
alipay: appid: XXXXXXXXXXXXX gatewayUrl: https://openapi.alipay.com/gateway.do (正式环境网关,若用沙箱环境,需要更改) format: json charset: utf-8 signType: RSA2 returnUrl: http://XXXXXXXXXXXXXXXX/alipay/return(同步回调,不需要配置,只要路径正确,本地可以访问即可) notifyUrl: http://XXXXXXXXXXXXX/alipay/notify(异步回调,需要在支付宝上配置路径,外网可访问) app-private-key: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX alipay-public-key: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 1234567891011
- 支付宝配置类
@Component public class AlipayConfig { // 应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号 @Value("${alipay.appid}") public String app_id; // 商户私钥,您的PKCS8格式RSA2私钥 @Value("${alipay.app-private-key}") public String merchant_private_key; // 支付宝公钥,查看地址:https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥。 @Value("${alipay.alipay-public-key}") public String alipay_public_key; // 服务器异步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问 //public static String notify_url = "http://工程公网访问地址/alipay.trade.page.pay-JAVA-UTF-8/notify_url.jsp"; @Value("${alipay.notifyUrl}") public String notify_url ; // 页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问 // public static String return_url = "http://工程公网访问地址/alipay.trade.page.pay-JAVA-UTF-8/return_url.jsp"; @Value("${alipay.returnUrl}") public String return_url ; // 签名方式 @Value("${alipay.signType}") public String sign_type; // 字符编码格式 @Value("${alipay.charset}") public String charset; // 支付宝网关 @Value("${alipay.gatewayUrl}") public String gatewayUrl; @Value("${alipay.format}") public String format; // 支付宝网关 @Value("${alipay.logs}") public static String log_path; //↑↑↑↑↑↑↑↑↑↑请在这里配置您的基本信息↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ public static void logResult(String sWord) { FileWriter writer = null; try { writer = new FileWriter(log_path + "alipay_log_" + System.currentTimeMillis()+".txt"); writer.write(sWord); } catch (Exception e) { e.printStackTrace(); } finally { if (writer != null) { try { writer.close(); } catch (IOException e) { e.printStackTrace(); } } } } } 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
- 控制器
生成支付宝支付二维码: @PostMapping("/gotoPayPage") @ResponseBody public void gotoPayPage(){ AlipayTradePagePayRequest pagePayRequest=new AlipayTradePagePayRequest(); //SDK 公共请求类,包含公共请求参数,以及封装了签名与验签,开发者无需签名与验签 AlipayClient alipayClient = new DefaultAlipayClient(alipayConfig.gatewayUrl,alipayConfig.app_id,alipayConfig.merchant_private_key, alipayConfig.format, alipayConfig.charset, alipayConfig.alipay_public_key, alipayConfig.sign_type); pagePayRequest.setReturnUrl(alipayConfig.return_url); pagePayRequest.setNotifyUrl(alipayConfig.notify_url); // 订单模型 String productCode = "FAST_INSTANT_TRADE_PAY"; //商户订单号 String orderNo = “订单号”; //付款金额 String totalFee = “付款金额,以元为单位”; //订单名称 String subject = "456"; //商品描述 String body = "123"; AlipayTradePayModel model = new AlipayTradePayModel(); model.setOutTradeNo(orderNo); model.setProductCode(productCode); model.setTotalAmount(totalFee); model.setSubject("subject"); // model.setBody("body"); pagePayRequest.setBizModel(model); //请求 String form = ""; try { //String result = alipayClient.pageExecute(pagePayRequest).getBody(); AlipayTradePagePayResponse payResponse = alipayClient.pageExecute(pagePayRequest); form = payResponse.getBody(); response.setContentType("text/html;charset="+alipayConfig.charset); response.getWriter().write(form); response.getWriter().flush(); response.getWriter().close(); }catch (Exception e){ e.printStackTrace(); throw new RuntimeException("支付宝二维码数据生成失败"); } } 2、支付宝同步回调方法 @GetMapping("/return") public String returnCallback(HttpServletRequest request, HttpServletResponse response){ System.out.println("**************************同步回调方法执行*******************************************"); //获取支付宝GET过来反馈信息 Map<String,String> params = new HashMap<String,String>(); Map requestParams = request.getParameterMap(); try { 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); } System.out.println("params---------->"+params); //调用SDK验证签名 boolean signVerified = AlipaySignature.rsaCheckV1(params,alipayConfig.alipay_public_key, alipayConfig.charset, alipayConfig.sign_type); if (signVerified){ //商户订单号 String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"),"UTF-8"); //支付宝交易号 String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"),"UTF-8"); //付款金额 String total_amount = new String(request.getParameter("total_amount").getBytes("ISO-8859-1"),"UTF-8"); //TODO 将支付宝返回的数据记录到数据库中 //1、根据订单号查询订单是否存在, //2、根据支付宝返回的trade_status状态进行下一步要操作,成功:更新订单状态, //response.getWriter().write("success"); return "success"; }else { return "fail"; // response.getWriter().write("fail"); } }catch (Exception e){ e.printStackTrace(); throw new RuntimeException("回调异常"); } } 3、异步回调 @PostMapping("/notify") @ResponseBody public String notifyUrl(HttpServletRequest request,HttpServletResponse response){ //获取支付宝POST过来反馈信息 Map<String,String> params = new HashMap<String,String>(); Map<String,String[]> requestParams = request.getParameterMap(); try { 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] + ","; } //乱码解决,这段代码在出现乱码时使用 valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8"); params.put(name, valueStr); } System.out.println("支付宝支付返回参数params-------->"+params); boolean signVerified = AlipaySignature.rsaCheckV1(params, alipayConfig.alipay_public_key, alipayConfig.charset, alipayConfig.sign_type); //调用SDK验证签名 System.out.println("signVerified----->"+signVerified); PrintWriter out = null; if (signVerified){ //商户订单号 orderNo String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"),"UTF-8"); //支付宝交易号 String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"),"UTF-8"); //买家支付宝交易账号 String buyer_id = new String(request.getParameter("buyer_id").getBytes("ISO-8859-1"),"UTF-8"); //交易总金额 String total_amount = new String(request.getParameter("total_amount").getBytes("ISO-8859-1"),"UTF-8"); //实收金额 String receipt_amount = new String(request.getParameter("receipt_amount").getBytes("ISO-8859-1"),"UTF-8"); //付款金额 String buyer_pay_amount = new String(request.getParameter("buyer_pay_amount").getBytes("ISO-8859-1"),"UTF-8"); //交易时间 String gmt_create = new String(request.getParameter("gmt_create").getBytes("ISO-8859-1"),"UTF-8"); //交易付款时间 String gmt_payment = new String(request.getParameter("gmt_payment").getBytes("ISO-8859-1"),"UTF-8"); //获取appid String app_id = new String(request.getParameter("app_id").getBytes("ISO-8859-1"),"UTF-8"); //交易状态 String trade_status = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"),"UTF-8"); //根据订单查询该订单是否存在 if (memberOrder == null){ throw new AlipayApiException("out_trade_no错误"); } //判断支付金额是否正确 if (!total_amount.equals(memberOrder.getTotalFee().toString())){ throw new AlipayApiException("error total_amount"); } //判断appid是否一致 if (!app_id.equals(alipayConfig.app_id)){ throw new AlipayApiException("app_id不一致"); } System.out.println("trade_status------------>"+trade_status); if(trade_status.equals("TRADE_FINISHED")){ //判断该笔订单是否在商户网站中已经做过处理 //如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序 //如果有做过处理,不执行商户的业务程序 //注意: //退款日期超过可退款期限后(如三个月可退款),支付宝系统发送该交易状态通知 }else if (trade_status.equals("TRADE_SUCCESS")){//向支付宝订单记录表中添加数据 //判断该笔订单是否在商户网站中已经做过处理 //如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序 //如果有做过处理,不执行商户的业务程序 //注意: //付款完成后,支付宝系统发送该交易状态通知 } //response.getOutputStream().print("success"); return "success"; // }else {//验签失败 // response.getOutputStream().print("failure"); return "failure"; } }catch (AlipayApiException e) { System.out.println(e.getErrMsg()); throw new RuntimeException("调用支付宝接口发生异常"); } catch (UnsupportedEncodingException e) { System.out.println(e.getMessage()); throw new RuntimeException("URLDecoderf发生异常"); } } 4、订单查询 @GetMapping("/query") @ResponseBody public String query(String orderNo, String tradeNo){ if (StringUtils.isBlank(orderNo)){ throw new RuntimeException("订单号不能为空"); } //SDK 公共请求类,包含公共请求参数,以及封装了签名与验签,开发者无需签名与验签 AlipayClient alipayClient = new DefaultAlipayClient(alipayConfig.gatewayUrl,alipayConfig.app_id,alipayConfig.merchant_private_key, alipayConfig.format, alipayConfig.charset, alipayConfig.alipay_public_key, alipayConfig.sign_type); AlipayTradeQueryRequest alipay_request = new AlipayTradeQueryRequest(); AlipayTradeQueryModel model=new AlipayTradeQueryModel(); model.setOutTradeNo(orderNo); model.setTradeNo(tradeNo); alipay_request.setBizModel(model); String form = ""; try { AlipayTradeQueryResponse alipay_response =alipayClient.execute(alipay_request); form = alipay_response.getBody(); System.out.println("form----->"+form); return form; }catch (AlipayApiException e){ e.printStackTrace(); throw new RuntimeException("支付宝查询交易数据失败"); } } 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
注意:要对异步回调、同步回调、查询放行,不要拦截