支付宝支付完整案例

一: 开发前的准备

任何第三方对接都要获取去平台注册获取appid、密钥等信息。(QQ登录,微信登录,微信支付,支付宝支付......等等)
  支付宝商户信息申请:https://openhome.alipay.com/platform/appDaily.htm?tab=info

 二:支付宝支付案例

支付宝核心代码开发(参考官方PC支付下单文档  https://docs.open.alipay.com/270/alipay.trade.page.pay)

/**
 * 支付宝支付
 * @param price商品价格
 */
public String pay(String price,String orderId) {
    log.info("调用支付宝支付接口开始,price:{}"+price);
    //1. 获得初始化的AlipayClient
    AlipayClient alipayClient = new DefaultAlipayClient(aliPayConfig.getGatewayUrl(), 
                                                        aliPayConfig.getAppId(), 
                                                        aliPayConfig.getMerchantPrivateKey(), 
                                                        "json", 
                                                        aliPayConfig.getCharSet(), 
                                                        aliPayConfig.getAlipayPublicKey(), 
                                                        aliPayConfig.getSignType());
    //2. 设置请求参数
    AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
    alipayRequest.setReturnUrl(aliPayConfig.getReturnUrl());//同步回调地址
    alipayRequest.setNotifyUrl(aliPayConfig.getNotifyUrl());//异步回调地址
    String out_trade_no = orderId;//商户订单号,商户网站订单系统中唯一订单号
    String total_amount = price;   //付款金额
    String subject = "支付宝下单测试"; //订单名称
    String body = "这是一条商品描述记录";//商品描述,可为空
    //3. 将请求参数拼接成json格式。
    alipayRequest.setBizContent("{\"out_trade_no\":\""+ out_trade_no +"\"," 
            + "\"total_amount\":\""+ total_amount +"\"," 
            + "\"subject\":\""+ subject +"\"," 
            + "\"body\":\""+ body +"\"," 
            + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");
    //若想给BizContent增加其他可选请求参数,以增加自定义超时时间参数timeout_express来举例说明
    //alipayRequest.setBizContent("{\"out_trade_no\":\""+ out_trade_no +"\"," 
    //        + "\"total_amount\":\""+ total_amount +"\"," 
    //        + "\"subject\":\""+ subject +"\"," 
    //        + "\"body\":\""+ body +"\"," 
    //        + "\"timeout_express\":\"10m\"," 
    //        + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");
    //请求参数可查阅【电脑网站支付的API文档-alipay.trade.page.pay-请求参数】章节
    
    //请求
    String result = null;
    try {
        result = alipayClient.pageExecute(alipayRequest).getBody();
    } catch (AlipayApiException e) {
        e.printStackTrace();
    }
    log.info("调用支付宝支付接口完成");
    return result;
}

 

三:用户登录并支付

用户输入支付密码后,会调用配置文件里的异步、同步回调路径。(这一部分是支付宝自动完成的,参考sdk支付案例源码http://p.tb.cn/rmsportal_6680_alipay.trade.page.pay-JAVA-UTF-8.zip)

/**
 * 异步回调notifyUrl
 */
@RequestMapping("/notifyUrl")
public String asynCallBack(HttpServletRequest req) throws UnsupportedEncodingException{
    Map<String,String> params = new HashMap<String,String>();
    Map<String,String[]> requestParams = req.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);
    }
    log.info("支付宝异步回调通知,params:{}"+params);
    // 调用SDK验证签名
    boolean signVerified = this.signVerified(params);
    if(signVerified) {//验证成功
        //商户订单号
        String out_trade_no = new String(req.getParameter("out_trade_no").getBytes("ISO-8859-1"),"UTF-8");
        //支付宝交易号
        String trade_no = new String(req.getParameter("trade_no").getBytes("ISO-8859-1"),"UTF-8");
        //交易状态
        String trade_status = new String(req.getParameter("trade_status").getBytes("ISO-8859-1"),"UTF-8");
        
        if(trade_status.equals("TRADE_FINISHED")){
            //判断该笔订单是否在商户网站中已经做过处理
            //如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序
            //如果有做过处理,不执行商户的业务程序
                
            //注意:
            //退款日期超过可退款期限后(如三个月可退款),支付宝系统发送该交易状态通知
        }else if (trade_status.equals("TRADE_SUCCESS")){
            //判断该笔订单是否在商户网站中已经做过处理
            //如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序
            //如果有做过处理,不执行商户的业务程序
            
            //注意:
            //付款完成后,支付宝系统发送该交易状态通知
        }
        return "success";
    }else {//验证失败
        return "fail";
    }
}
/**
 * 同步回调
 */
@RequestMapping("/returnUrl")
@ResponseBody
public void synCallBack(HttpServletRequest req, HttpServletResponse resp) throws Exception {
    resp.setContentType("text/html;charset=utf-8");
    PrintWriter writer = resp.getWriter();
    // 拼装请求参数
    Map<String,String> params = new HashMap<String,String>();
    Map<String,String[]> requestParams = req.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);
    }

    log.info("支付宝同步回调通知,params:{}"+params);
    // 调用SDK验证签名
    boolean signVerified = this.signVerified(params);
    if(!signVerified) {
        log.info("SDK验签失败");
        return;
    }
    //商户订单号
    String out_trade_no = params.get("out_trade_no");
    //支付宝交易号
    String trade_no = params.get("trade_no");
    //付款金额
    String total_amount = params.get("total_amount");
    // 封装成html 浏览器模拟去提交
    String htmlFrom="<form name='punchout_form' "
            + "method='post' "
            + "action='http://127.0.0.1:8081/pay/synSuccessPage' >"
            + "<input type='hidden' name='outTradeNo' value='"+out_trade_no+"'>"
            + "<input type='hidden' name='tradeNo' value='"+trade_no+"'>"
                    + "<input type='hidden' name='totalAmount' value='"+total_amount+"'>"
                            + "<input type='submit' value='立即支付' style='display:none'>"
                            + "</form>"
                            + "<script>document.forms[0].submit();</script>";
    writer.println(htmlFrom);    
}
// 支付宝支付成功页面回调是get方式,会暴露参数。所以我们这里来以post表单隐藏参数
@RequestMapping(value = "/synSuccessPage", method = RequestMethod.POST)
@ResponseBody
private String synSuccessPage(HttpServletRequest request, String outTradeNo, String tradeNo, String totalAmount) {
    request.setAttribute("outTradeNo", outTradeNo);
    request.setAttribute("tradeNo", tradeNo);
    request.setAttribute("totalAmount", totalAmount);
    return "您的订单号: "+outTradeNo+"已经支付成功, 支付金额: "+totalAmount+" 元";
}
/**
 * 调用SDK验证签名
 * @param params 支付宝回调参数
 */
public boolean signVerified(Map<String,String> params) {
    try {
        log.info("调用SDK验证签名....");
        return AlipaySignature.rsaCheckV1(params, aliPayConfig.getAlipayPublicKey(), aliPayConfig.getCharSet(), aliPayConfig.getSignType());
    } catch (AlipayApiException e) {
        return false;
    }
} 

四:成功页面

猜你喜欢

转载自www.cnblogs.com/wlwl/p/10258227.html
今日推荐