支付宝手机网站支付接入及支付后回调方法的实现java版

手机网站支付整个流程如下,从图1到图4。一般手机上的浏览器都可以吊起支付宝收银台(图3),为保险起见,可自行引导用户使用支付宝浏览器(将图1网址生成二维码,让用户用支付宝扫一扫)。判断是否为支付宝浏览器的方法:https://blog.csdn.net/qq_15023917/article/details/108636685

图1图2都为jsp页面,自己简单写写即可,也可借鉴官网给出的demo中的pay.jsp中的代码(demo地址:https://opendocs.alipay.com/open/203/105910);此处不再列出,以下代码只列出点击图2的支付按钮时,调用支付宝下单接口和支付成功后的回调方法:

点击图2的支付按钮时,调用的后端方法为:

//唤起支付宝收银台
public void payAli()throws ServletException, IOException{
		HttpServletRequest request = ServletActionContext.getRequest();
		HttpServletResponse resp = ServletActionContext.getResponse();
		//1.设置将发送到客户端的响应的内容类型
		resp.setContentType("text/html;charset="+"UTF-8");
		 String subject = "支付宝缴费";//自定义描述
	        String total_amount ="0.01";//前端传过来的付款金额 

	       String  out_trade_no = "123456789";//自定义订单编号,可以是时间戳,回调方法中会自动返回过来
	       //2.填充业务参数
	        String content="{" +
	                " \"out_trade_no\":\""+out_trade_no+"\"," +
	                " \"total_amount\":\""+total_amount+"\"," +
	                " \"subject\":\""+subject+"\"," +
	                " \"product_code\":\"QUICK_WAP_PAY\"" +
	                " }";
	      //3.去支付
	        AlipayTradeWapPayResponse alipayResponse= null;
	        try {
	            alipayResponse = payAliExecute(content);

	        } catch (Exception e) {
	            e.printStackTrace();
	        } 
	        String form= alipayResponse.getBody();
	        //System.out.println(form);

	        //4.输出支付宝返回的表单页面
	        resp.setContentType("text/html;charset="+"UTF-8");
	        resp.getWriter().write(form);//直接将完整的表单html输出到页面
	        resp.getWriter().flush();
	        resp.getWriter().close();
	}

//支付时所需参数配置
public AlipayTradeWapPayResponse payAliExecute(String content) throws AlipayApiException {
		String OPEN_API_DOMAIN="https://openapi.alipay.com/gateway.do";//支付宝网关,沙箱环境和正是环境有区别
		String APP_ID="2021000116680665";//appID(换成自己的appid)
		String APP_PRIVATE_KEY="";//私钥 pkcs8格式的(此处自己添加,太长了)
		String FORMAT = "json";//返回格式
		String CHAR_SET = "UTF-8";//编码
		String SIGNTYPE = "RSA2";// RSA2
		String ALIPAY_PUBLIC_KEY ="";//支付宝公钥(此处自己添加,太长了)
		AlipayClient alipayClient = new DefaultAlipayClient(
	            OPEN_API_DOMAIN, APP_ID, APP_PRIVATE_KEY, FORMAT,
	            CHAR_SET, ALIPAY_PUBLIC_KEY,SIGNTYPE);
        //1. 创建API对应的request
        AlipayTradeWapPayRequest alipayRequest = new AlipayTradeWapPayRequest();
        //2. 在公共参数中设置回调和通知地址(应用提供给支付宝的请求路径)
        //alipayRequest.setReturnUrl("http://218.58.60.111:18086/pls/successPayPlsWeChatAction.action");//同步回调方法(可以不设置,设置的话就是点击图4的完成按钮后,返回的页面,不设置直接返回到支付宝首页)
        String notigy="http://218.58.60.111:18086/pls/alipayNotifyPlsWeChatAction.action";//异步回调方法地址(支付成功后的回调地址,用来处理自己的业务,此地址必须保证外网可访问,因为支付宝服务器要访问它,可以是ip+端口号的形式,也可以是域名)
        alipayRequest.setNotifyUrl(notigy);
        // 填充业务参数
        alipayRequest.setBizContent(content);

        //3.执行请求
        AlipayTradeWapPayResponse alipayResponse = alipayClient
                .pageExecute(alipayRequest);
        return alipayResponse;
	}

以上代码中需要引入jar包和sdk,可以在支付宝的demo中找到,也可以在我这里下载 https://download.csdn.net/download/qq_15023917/13084828 ,执行完以上两方法后,手机端会自动打开图3,输入支付密码,点击立即付款,成功后会跳转到图4,同时后端会回调之前设置的回调方法alipayNotify();回调方法相关代码:

//import java.util.concurrent.ExecutorService;
private ExecutorService executorService = Executors.newFixedThreadPool(20);
	public void alipayNotify(){
		HttpServletRequest request = ServletActionContext.getRequest();
		HttpServletResponse response = ServletActionContext.getResponse();
		PrintWriter writer = null;
        try {
        	Map<String, String> params = new LinkedHashMap<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] + ",";
    	                }
    	                // 乱码解决,这段代码在出现乱码时使用
    	                // valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
    	                params.put(name, valueStr);
    	            }
    	            String tradeStatus = params.get("trade_status");
    	            String outTradeNo= params.get("out_trade_no");
                    String buyerLogonId= params.get("buyer_logon_id");
                    String appId= params.get("app_id");
               //此处只列出来几个参数,如果有其他需要,可都获取出来
            // 调用SDK验证签名 (params,ALIPAY_PUBLIC_KEY,CHAR_SET,SIGNTYPE)
            String ALIPAY_PUBLIC_KEY="";//支付宝公钥,去开放平台获取(自己配置上)
            boolean signVerified = AlipaySignature.rsaCheckV1(params, ALIPAY_PUBLIC_KEY,
                    "UTF-8", "RSA2");
            if (signVerified) {
                log.info("支付宝回调签名认证成功");
                // 按照支付结果异步通知中的描述,对支付结果中的业务内容进行1\2\3\4二次校验,校验成功后在response中返回success,校验失败返回failure
                // 另起线程处理业务
                executorService.execute(new Runnable() {
                    //@Override
                    public void run() {
                        // 支付成功
                        if (tradeStatus.equals("TRADE_FINISHED")
                                || tradeStatus.equals("TRADE_SUCCESS")) {
                            try {

                            	//在这里处理支付成功后的业务逻辑
                                //......
                                //......
                                //实现自己的业务逻辑即可
                            	 
                            } catch (Exception e) {
                                log.error("支付宝回调业务处理报错");
                                e.printStackTrace();
                            }
                        } else {
                            log.error("没有处理支付宝回调业务");
                        }
                    }
                });
                // 如果签名验证正确,立即返回success,后续业务另起线程单独处理
                // 业务处理失败,可查看日志进行补偿,跟支付宝已经没多大关系。
        	    try {
        			writer = response.getWriter();
        		} catch (IOException e) {
        			e.printStackTrace();
        		}
        	    writer.write("success"); // 一定要返回success
        	    writer.flush();
        	    return;
            } else {
                log.info("支付宝回调签名认证失败");
                writer.write("failure");
        	    writer.flush();
        	    return;
            }
        } catch (AlipayApiException e) {
            log.error("支付宝回调签名认证失败");
            e.printStackTrace();
            writer.write("failure");
    	    writer.flush();
    	    return;
        }
	}

附加:支付宝回调时返回的数据格式,可作为参考,取值时用得到

//支付宝返回的数据格式

{
	        subject = 支付宝缴费, 
	        buyer_logon_id = lzr *** @163.com, 
		auth_app_id = 2021002101686667, 
		notify_type = trade_status_sync, 
		out_trade_no = 1604308759922, 
		point_amount = 0.00, 
		version = 1.0, 
		fund_bill_list = [{
		"amount": "0.01",
		"fundChannel": "PCREDIT"
	         }],
		buyer_id = 2088902602846671, 
		total_amount = 0.01, 
		trade_no = 2020110222001442571425774676, 
		notify_time = 2020 - 11 - 02 17: 19: 22, 
		charset = UTF - 8, 
		invoice_amount = 0.01, 
		trade_status = TRADE_SUCCESS, 
		gmt_payment = 2020 - 11 - 02 17: 19: 21, 
		gmt_create = 2020 - 11 - 02 17: 19: 20, 
		buyer_pay_amount = 0.01, 
		receipt_amount = 0.01, 
		app_id = 2021002101666167, 
		seller_id = 2088621861666309, 
		notify_id = 2020110200222171966042571439456101, 
		seller_email = zndbbfb @edijse.com.cn
}

完整代码大致如上,不明白的可留言

支付宝手机网站支付完整流程可参考https://blog.csdn.net/qq_15023917/article/details/109452228

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值