支付宝对接 java后端

1,753 阅读3分钟
前段时间,公司需要接入支付宝,现在腾出了一点时间,所以做一下总结,分享一些自己项目中遇到的坑,本文
app支付为例。对于支付宝的对接,无疑官方文档是最全,最完善的,所以给大家一个传送 

支付宝官方文档 1.创建应用并获取APPID 2.配置应用


###集成开发 本文使用支付宝sdk进行支付宝对接,请到[支付宝java demo](https://docs.open.alipay.com/54/103419/)进行下载 ####1.参数说明

FireShot Capture 2 - 开放平台文档中心 - https___docs.open.alipay.com_204_105465_.png

2.APP客户端请求orderString的生成

 // 请求网关地址
    public static final String ALIPAY_URL = "https://openapi.alipay.com/gateway.do";
 // 异回调地址
    public static final String ALIPAY_NOTIFY_URL = "https://www.nickbi.com/alipay/notify";
 // 商户appid
    public static final String ALIPAY_APPID = "xxxxxx";
// 私钥 pkcs8格式的(可用支付宝秘钥工具生成)
    public static final String ALIPAY_RSA_PRIVATE_KEY = “xxxxx”
 // 返回格式
    public static final String ALIPAY_ALI_FORMAT = "json";
 // 返回格式
    public static final String ALIPAY_ALI_FORMAT = "json";
// 支付宝公钥(可在设置了公钥私钥后,在支付宝商户后台查看)
    public static final String ALI_PUBLIC_KEY = “xxxxx”
// RSA2
    public static final String ALIPAY_SIGNTYPE = "RSA2";

 /**
  * 获得app端支付宝参数
  */
    public String getAlipayReqeustString(String orderNo, String totalAmount)
            throws AlipayApiException {
        //app Request
        AlipayClient alipayClient = new DefaultAlipayClient(ALIPAY_URL,
                ALIPAY_APPID, ALIPAY_RSA_PRIVATE_KEY, ALIPAY_ALI_FORMAT,
               ALIPAY_CHARSET,  ALI_PUBLIC_KEY,ALIPAY_SIGNTYPE);
        //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay
        AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
        //SDK已经封装掉了公共参数,这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
        AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
        //model.setBody(body);
        model.setSubject(“简书打赏”);
        model.setOutTradeNo(orderNo);
        //订单超时时间:取值范围:1m~15d。m-分钟,h-小时,d-天,1c-当天
        model.setTimeoutExpress(“30m”);
       //订单总支付金额
        model.setTotalAmount(totalAmount);
       //销售产品码:商家和支付宝签约的产品码,为固定值QUICK_MSECURITY_PAY
        model.setProductCode("QUICK_MSECURITY_PAY");
        request.setBizModel(model);
        request.setNotifyUrl(ALIPAY_NOTIFY_URL);
        //这里和普通的接口调用不同,使用的是sdkExecute
        AlipayTradeAppPayResponse response =  alipayClient.sdkExecute(request);
        return response.getBody();//就是orderString 可以直接给客户端请求,无需再做处理。
    }

###3.回调处理

    @ResponseBody
    @RequestMapping(value = "/alipay/notify", method = RequestMethod.POST)
    public String getPayNotify(HttpServletRequest request) throws Exception {
        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 = 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_fee = "0.00";
        if (request.getParameter("total_amount") != null) {
            total_fee = new String(request.getParameter("total_amount").getBytes("ISO-8859-1"),
                    "UTF-8");
        }

        //交易状态
        String trade_status = new String(
                request.getParameter("trade_status").getBytes("ISO-8859-1"), "UTF-8");

        //异步通知ID
        String notify_id = request.getParameter("notify_id");

        if (notify_id != null && !"".equals(notify_id)) {
            boolean verify_result = AlipaySignature
                    .rsaCheckV1(params, ALI_PUBLIC_KEY, AppContents.ALI_CHARSET,
                            ALIPAY_SIGNTYPE);
            if (verify_result) {
                //使用支付宝公钥验签
                //订单支付成功
                //if (trade_status.equals("TRADE_FINISHED") || trade_status.equals("TRADE_SUCCESS")) {
                if (trade_status.equals("TRADE_SUCCESS")) {
                //业务处理,使用自己的接口,进行订单处理
                    boolean result = orderService.getNotify(......)
                    if (result) {
                        return "success";
                    }
                }
                //订单超时关闭,修改订单
                if (trade_status.equals("TRADE_CLOSED")) {
                    boolean result = orderService.getCloseNotify(......)
                    if (result) {
                        return "success";
                    }
                }
                return "fail";
            } else {
                //验证签名失败
                return "fail";
            }

        } else {
            return "fail";
        }
    }

###总结 ####遇到的一些坑:

在项目的前期,使用app端的同步回调去处理订单信息,但是由于用户操作的确定性,所以在回调过程中会出现很多
意向不到的结果,所以订单处理异步回调更稳妥(老哥如果觉得想飙车,去试一把那我也是不拒绝的)。另外对于异步
回调也会出现未知原因,所以关于订单的轮询查询,订单矫正请自行尝试,到时可以一起交流下。