支付宝支付

1.沙箱环境

https://docs.open.alipay.com/200/105310/   开发者中心

2.接入步骤

1.创建应用并获取APPID

2.配置秘钥

3.搭建和配置开发环境

4.引入sdk

5.线上验收

1.创建应用并获取APPID

 

2.配置秘钥

1.生成RSA秘钥   (应用私钥,应用公钥)

2.上传公钥

3.搭建和配置开发环境

开发文档   下载demo jar 包

https://alipay.open.taobao.com/docs/doc.htm?spm=a219a.7629140.0.0.17024b700tO3ya&treeId=193&articleId=106291&docType=1

调用接口属性配置

    其实就是demo中的 src 中的AlipayConfig文件 

public class AlipayConfig {
    /**
     * 商户appid
     */
    private String appID;
    /**
     * 私钥 rsa2 私钥
     */
    private String rsaPrivateKey;
    /**
     * 支付宝公钥
     */
    private String alipayPublicKey;
    /**
     * 服务器异步通知页面路径 需http://或者https://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
     */
    private String notifyUrl = "";
    /**
     * 页面跳转同步通知页面路径 需http://或者https://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问 商户可以自定义同步跳转地址
     */
    private String returnUrl;
    /**
     * 请求网关地址
     */
    private String url;
    /**
     * 编码
     */
    private String charset;
    /**
     * 返回格式
     */
    private String format;

    /**
     * 日志记录目录
     */
    private String logPath;
    /**
     * RSA2
     */
    private String signType;

    /**
     * 支付成功跳转页面
     */
    private String paymentSuccessUrl;
    /**
     * 支付失败跳转页面
     */
    private String paymentFailureUrl;
    //省略getter、setter

 

支付宝配置文件

<!-- 支付宝手机网站支付 -->
<bean id="alipayConfig" class="cn.itrip.trade.config.AlipayConfig">
    <property name="appID" value="2016092500596021"/>    
    <!-- 应用私钥 -->
    <property name="rsaPrivateKey" value=""/>
    <!-- 回调方法要 设置一个可以公开访问的域名-->
    <property name="notifyUrl" value="http://bc6782a9.ngrok.io/trade/notify"/>
    <property name="returnUrl" value="http://bc6782a9.ngrok.io/trade/return"/>
    <!--网关 固定的-->
    <property name="url" value="https://openapi.alipaydev.com/gateway.do"/>
    <property name="charset" value="UTF-8"/>
    <property name="format" value="json"/>    
    <!--支付宝公钥-->
    <property name="alipayPublicKey" value=""/>
    <property name="logPath" value="/logs"/>
    <property name="signType" value="RSA2"/>
    <property name="paymentSuccessUrl" value="/trade/paysuccess.jsp"/>
    <property name="paymentFailureUrl" value="/trade/payfailure.jsp"/>
</bean>

 

     sdk包说明

                    alipay-sdk-java*.jar: 支付宝SDK编译文件jar

                    alipay-sdk-java*-source.jar" 支付宝SDK源码文件jar

                    commons-logging-1.1.1.jar: sdk依赖的日志文件

     核心api:

                    AlipayClient: 封装签名与验证

                    AlipayTradeWapPayRequest: 支付请求类

                    AlipayTradeWapPayModel:封装请求支付信息

编写代码

编写好dao层与beans层对应的代码

 

编写service层的业务代码

@Service("TradeService")
public class TradeServiceImpl implements TradeService {
    private Logger logger = Logger.getLogger(TradeServiceImpl.class);

    @Resource
    private ItripHotelOrderMapper itripHotelOrderMapper;


    @Override
    public ItripHotelOrder loadItripHotelOrder(String orderNo) throws Exception {
        Map<String, Object> params = new HashMap<>();
        params.put("orderNo", orderNo);
        ItripHotelOrder itripHotelOrder = this.getItripHotelOrderListByMap(params);
        return itripHotelOrder;

    }

    @Override
    public ItripHotelOrder getItripHotelOrderListByMap(Map<String, Object> param) throws Exception {
        List<ItripHotelOrder> list = itripHotelOrderMapper.getItripHotelOrderListByMap(param);
        if (list.size() > 0)
            return list.get(0);
        return null;// 没有此订单
    }

    @Override
    public void payFailed(String orderNo, int payType, String tradeNo) throws Exception {
        logger.debug("订单支付失败:" + orderNo);
        Map<String, Object> params = new HashMap<>();
        params.put("orderNo", orderNo);
        ItripHotelOrder itripHotelOrder = this.getItripHotelOrderListByMap(params);
        itripHotelOrder.setOrderStatus(1);//支付状态:已取消
        itripHotelOrder.setPayType(payType);
        itripHotelOrder.setTradeNo(tradeNo);//交易号(如支付宝交易号)
        itripHotelOrderMapper.updateItripHotelOrder(itripHotelOrder);

    }

    @Override
    public void paySuccess(String orderNo, int payType, String tradeNo) throws Exception {
        logger.debug("订单支付成功:" + orderNo);
        Map<String, Object> params = new HashMap<>();
        params.put("orderNo", orderNo);
        ItripHotelOrder itripHotelOrder = this.getItripHotelOrderListByMap(params);
        itripHotelOrder.setOrderStatus(2);//支付成功
        itripHotelOrder.setPayType(payType);
        itripHotelOrder.setTradeNo(tradeNo);//交易号(如支付宝交易号)
        itripHotelOrderMapper.updateItripHotelOrder(itripHotelOrder);

    }

    @Override
    public boolean processed(String orderNo) throws Exception {
        Map<String, Object> params = new HashMap<>();
        params.put("orderNo", orderNo);
        ItripHotelOrder itripHotelOrder = this.getItripHotelOrderListByMap(params);
        // 状态为2  已支付成功
        return itripHotelOrder.getTradeNo() != null && itripHotelOrder.getOrderStatus() == 2 &&
                !itripHotelOrder.getTradeNo().equals("");

    }
}

controller

@Controller
public class TradeController {
    private Logger logger = Logger.getLogger(TradeController.class);
    @Resource
    private TradeService tradeService;

    @Resource
    private AlipayConfig alipayConfig;

    @RequestMapping(value = "/topay/{orderno}",method = RequestMethod.GET)
    public String toPay(@PathVariable String orderno, ModelMap modelMap) throws Exception {
        System.out.println("11111");
        Map<String, Object> params = new HashMap<>();
        params.put("orderNo", orderno);
        ItripHotelOrder order = tradeService.getItripHotelOrderListByMap(params);
        modelMap.put("orderNo", order.getOrderNo());
        modelMap.put("payAmount", order.getPayAmount());
        modelMap.put("roomId", order.getRoomId());
        modelMap.put("count", order.getCount());
        modelMap.put("hotelName", order.getHotelName());
        return "../pay";
    }

    @RequestMapping(value = "/dopay", method = RequestMethod.POST)
    /*订单提交到支付宝*/
    public void pay(
            @RequestParam String WIDout_trade_no,
            @RequestParam String WIDsubject,
            @RequestParam String WIDtotal_amount, HttpServletResponse response) {
        // 超时时间 可空
        String timeout_express = "2m";
        // 销售产品码 必填
        String product_code = "QUICK_WAP_PAY";
        // SDK 公共请求类,包含公共请求参数,以及封装了签名与验签,开发者无需关注签名与验签
        // 调用RSA签名方式
        AlipayClient client = new DefaultAlipayClient(alipayConfig.getUrl(),
                alipayConfig.getAppID(), alipayConfig.getRsaPrivateKey(),
                alipayConfig.getFormat(), alipayConfig.getCharset(),
                alipayConfig.getAlipayPublicKey(), alipayConfig.getSignType());
        AlipayTradeWapPayRequest alipay_request = new AlipayTradeWapPayRequest();


        // 封装请求支付信息
        AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
        model.setOutTradeNo(WIDout_trade_no);
        try {
            model.setSubject(new String(WIDsubject.getBytes("iso-8859-1"),"utf-8"));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        model.setTotalAmount(WIDtotal_amount);
        model.setTimeoutExpress(timeout_express);
        model.setProductCode(product_code);
        alipay_request.setBizModel(model);
        // 设置异步通知地址
        alipay_request.setNotifyUrl(alipayConfig.getNotifyUrl());
        // 设置同步地址
        alipay_request.setReturnUrl(alipayConfig.getReturnUrl());
        // form表单生产
        String form = "";
        try {
            // 调用SDK生成表单
            form = client.pageExecute(alipay_request).getBody();
            System.out.println(form);
            response.setContentType("text/html;charset="+ alipayConfig.getCharset());
            response.getWriter().write(form);// 直接将完整的表单html输出到页面
            response.getWriter().flush();
            response.getWriter().close();
        } catch (AlipayApiException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    @RequestMapping(value = "/notify", method = RequestMethod.POST)
    public void doNotify(HttpServletRequest request, HttpServletResponse response) {
        System.out.println("notify:交易完成");
        try {
            // 获取支付宝POST过来反馈信息
            Map<String, String> params = new HashMap<String, String>();
            Map requestParams = request.getParameterMap();
            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"), "gbk");
                params.put(name, valueStr);
            }

            // 获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表(以下仅供参考)//
            // 商户订单号
            String out_trade_no = request.getParameter("out_trade_no");
            // 支付宝交易号
            String trade_no = request.getParameter("trade_no");
            // 交易状态
            String trade_status = request.getParameter("trade_status");
            System.out.println(out_trade_no+"---"+trade_no+"---"+trade_status);
            // 获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)//
            // 计算得出通知验证结果
            // boolean AlipaySignature.rsaCheckV1(Map<String, String> params, String
            // publicKey, String charset, String sign_type)
            boolean verify_result = AlipaySignature.rsaCheckV1(params,
                    alipayConfig.getAlipayPublicKey(), alipayConfig.getCharset(), "RSA2");
            System.out.println(verify_result);
            if (verify_result) {// 验证成功
                // 
                // 请在这里加上商户的业务逻辑程序代码

                //即时到账普通版,那么这时的交易状态值为:  TRADE_FINISHED;如果是即时到账高级版,此时的交易状态值就为:TRADE_SUCCESS
                //收到TRADE_FINISHED请求后,这笔订单就结束了,支付宝不会再主动请求商户网站了;收到TRADE_SUCCESS请求后,后续一定还有至少一条通知记录,即TRADE_FINISHED。
                if (trade_status.equals("TRADE_FINISHED")) {
                    // 判断该笔订单是否在商户网站中已经做过处理
                    // 如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序
                    // 请务必判断请求时的total_fee、seller_id与通知时获取的total_fee、seller_id为一致的
                    // 如果有做过处理,不执行商户的业务程序
                    if (!tradeService.processed(out_trade_no)) {
                        // 修改数据
                        tradeService.paySuccess(out_trade_no, 2, trade_no);
                    }
                    logger.info("订单:" + out_trade_no + " 交易完成");
                    // 注意:
                    // 如果签约的是可退款协议,退款日期超过可退款期限后(如三个月可退款),支付宝系统发送该交易状态通知
                    // 如果没有签约可退款协议,那么付款完成后,支付宝系统发送该交易状态通知。
                } else if (trade_status.equals("TRADE_SUCCESS")) {
                    // 判断该笔订单是否在商户网站中已经做过处理
                    // 如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序
                    // 请务必判断请求时的total_fee、seller_id与通知时获取的total_fee、seller_id为一致的
                    // 如果有做过处理,不执行商户的业务程序
                    if (!tradeService.processed(out_trade_no)) {
                        // 修改数据
                        tradeService.paySuccess(out_trade_no, 2, trade_no);
                    }
                    logger.info("订单:" + out_trade_no + " 交易成功");

                    // 注意:
                    // 如果签约的是可退款协议,那么付款完成后,支付宝系统发送该交易状态通知。
                }

                response.getWriter().println("success"); // 请不要修改或删除

                // 
            } else {// 验证失败
                tradeService.payFailed(out_trade_no, 1, trade_no);
                response.getWriter().println("fail");
            }
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            logger.error(e.getMessage());
        } catch (AlipayApiException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            logger.error(e.getMessage());
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            logger.error(e.getMessage());
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            logger.error(e.getMessage());
        }
    }

    @RequestMapping(value = "/return", method = RequestMethod.GET)
    public void doReturn(HttpServletRequest request,
                         HttpServletResponse response) {
        System.out.println("doReturn............");
        try {
            //获取支付宝GET过来反馈信息
            Map<String, String> params = new HashMap<String, String>();
            Map requestParams = request.getParameterMap();
            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);
            }

            //获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表(以下仅供参考)//
            //商户订单号

            String out_trade_no = request.getParameter("out_trade_no");

            //支付宝交易号

            String trade_no = request.getParameter("trade_no");

            //获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)//
            //计算得出通知验证结果
            //boolean AlipaySignature.rsaCheckV1(Map<String, String> params, String publicKey, String charset, String sign_type)
            boolean verify_result = AlipaySignature.rsaCheckV1(params, alipayConfig.getAlipayPublicKey(), alipayConfig.getCharset(), "RSA2");

            if (verify_result) {//验证成功
                String id = tradeService.loadItripHotelOrder(out_trade_no).getId() + "";
                System.out.println("成功。。。。。。。。。");
                //提示支付成功
                response.sendRedirect(
                        String.format(alipayConfig.getPaymentSuccessUrl(), out_trade_no, id));
            } else {
                System.out.println("失败。。。。。。。。。");
                //提示支付失败
                response.sendRedirect(alipayConfig.getPaymentFailureUrl());
            }
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            logger.error(e.getMessage());
        } catch (AlipayApiException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            logger.error(e.getMessage());
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            logger.error(e.getMessage());
        }

    }

}

jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>支付页面</title>
</head>
<body>
<form action="/trade/dopay" method="post">
    <table>
        <tr>
            <td>订单编号:</td>
            <td>${orderNo}
                <input type="hidden" name="WIDout_trade_no" value="${orderNo}">
                <input type="hidden" name="WIDsubject" value="${hotelName}">
                <input type="hidden" name="WIDtotal_amount" value="${payAmount}">
            </td>
        </tr>
        <tr>
            <td>订单名称:</td>
            <td>${hotelName}
            </td>
        </tr>
        <tr>
            <td>付款金额:</td>
            <td>${payAmount}。。。。
            </td>
        </tr>
        <tr>
            <td>商品描述:</td>
            <td>房间号:${roomId} 数量:${count}
            </td>
        </tr>
        <tr>
            <td colspan="2">
                <input type="submit" value="确认付款">
            </td>
        </tr>
    </table>
</form>
</body>
</html>

   支付回调通知:

                1.服务器异步通知

                            notify_url: 支付宝使用post方式,保证99.9999%的通知到达率

                2.页面跳转同步通知

                            return_url: 是支付宝使用get方式,是由客户浏览器触发的一个通知,不保证其到达率

运行测试

 

登陆支付宝时用的是沙箱账户中的买家账号

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值