美文网首页
支付宝接口的调用

支付宝接口的调用

作者: 代码potty | 来源:发表于2018-08-28 07:23 被阅读0次

    研究了几天支付宝接口的调用,期间遇到了很多的问题,直到现在都还没解决,首先列举下问题
    1、问题:
    支付宝进入扫码付款界面后,手机扫描二维码付款,有时候电脑界面没有反应
    可能性分析:
    在成功付款的单子里,我观察了一下付款成功地址会变化,并且这个地址变化首先调用的不是我的
    return_url地址,而是支付宝自己反馈的某些地址,比如:出现支付成功,倒数五秒进入另一个地址的
    页面,还有显示交易成功的交易,再之后才是调用return_url的地址,也就是说这期间会连续跳转三次
    的地址,而我扫码支付成功后(为什么说支付成功,其一支付宝账单里显示支付成功,其二服务器端
    的tomcat的日志里显示notify_url被调用了),页面连第一次跳转都未实现,所以,根据判断,很可能
    是支付宝沙箱那边出现的问题。

    2、问题:
    notify_url必须要放在外网能够访问到的地方,即服务器上。有个疑问,之前这个地址我都是放在本地的,然后使用手机支付宝沙箱进行了支付,在tomcat日志中虽然没有看到它调用notify_url地址,但是在手机支付宝账单中显示支付成功。
    解决:
    return_url是你发送支付请求成功后,客户端就会进行响应的页面跳转,但是无法判断是否支付成功,是否支付成功需要notify_url中的trade_status参数进行判断。

    本次使用的是支付宝提供的demo进行的测试学习,体验了五个功能,分别是支付,交易查询,退款,
    退款查询,交易结束。其中我还进行了部分的修改。

    demo中给我们提供了一个AlipayConfig类和几个jsp页面:
    AlipayConfig类如下:

        public class AlipayConfig {
            
        //↓↓↓↓↓↓↓↓↓↓请在这里配置您的基本信息↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
        
            // 应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号
            public static String app_id = "";
            
            // 商户私钥,您的PKCS8格式RSA2私钥
            public static String merchant_private_key = "";
            
            // 支付宝公钥,查看地址:https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥。
            public static String alipay_public_key = "";
        
            public static String notify_url = "http://193.112.64.192/alipay/notify_url";
        
            // 页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
            public static String return_url = "http://193.112.64.192/alipay/return_url";
        
            // 签名方式
            public static String sign_type = "RSA2";
            
            // 字符编码格式
            public static String charset = "utf-8";
            
            // 支付宝网关
            public static String gatewayUrl = "https://openapi.alipaydev.com/gateway.do";
            
            // 支付宝网关
            public static String log_path = "D:\\logger";
        
        
        //↑↑↑↑↑↑↑↑↑↑请在这里配置您的基本信息↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
        
            /** 
             * 写日志,方便测试(看网站需求,也可以改成把记录存入数据库)
             * @param sWord 要写入日志里的文本内容
             */
            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();
                        }
                    }
                }
            }
        }
    

    1、其中app_id可以在https://openhome.alipay.com/platform/appDaily.htm?tab=info 中的沙箱环境中去找自己的app_id
    2、使用公钥和私钥生成器,生成对应的公钥和私钥,将公钥填入以上地址中的应用公钥中,验证的时候会提示你使用签名,他提供签名工具的生成工具,通过私钥生成,然后进行验证,注意以上代码中的alipay_public_key不是我们刚刚生成的公钥,而是我们公钥和签名传给对方,对方自己生成的一个支付宝公钥(第一天在这个地方卡了很久),然后将这个值复制粘贴到代码中
    3、商品私钥就是之前通过公私钥生成器生成的私钥,直接复制粘贴
    4、notify_url和return_url需要在外网可以正常访问的网址,也就是需要挂在服务器

    return_url同步通知的介绍:
    买家在支付成功后会看到一个支付宝交易提示成功的页面,该页面会停留几秒,然后会自动跳转回商户指定的同步通知页面(参数return_url)
    该页面中获得参数的方式,需要使用GET方式获取,如request.QueryString("out_trade_no")、$_GET['out_trade_no'];
    该方式仅仅在买家付款完成以后进行自动跳转,因此只会进行一次
    该方式不是支付宝主动去调用商户页面,而是支付宝的程序利用页面自动跳转的函数,使用户的当前页面自动跳转;
    基于(4)的原因,可在本机而不是只能在服务器上进行调试;
    返回URL只有一分钟的有效期,超过一分钟该链接地址会失效,验证则会失败;
    设置页面跳转同步通知页面(return_url)的路径时,不要在页面文件的后面再加上自定义参数。例如:
    错误的写法:http://www.alipay.com/alipay/return_url.php?xx=11
    正确的写法:http://www.alipay.com/alipay/return_url.php

    notify_url异步通知的介绍:
    必须保证服务器异步通知页面(notify_url)上无任何字符,如空格、HTML标签、开发系统自带抛出的异常提示信息等;
    支付宝是用POST方式发送通知信息,因此该页面中获取参数的方式,如:
    request.Form("out_trade_no")、$_POST['out_trade_no']。
    支付宝主动发起通知,该方式才会被启用;
    只有在支付宝的交易管理中存在该笔交易,且发生了交易状态的改变,支付宝才会通过该方式发起服务器通知(即时到账中交易状态为“等待买家付款”的状态默认是不会发送通知的);
    服务器间的交互,不像页面跳转同步通知可以在页面上显示出来,这种交互方式是不可见的;
    第一次交易状态改变(即时到账中此时交易状态是交易完成)时,不仅页面跳转同步通知页面会启用,而且服务器异步通知页面也会收到支付宝发来的处理结果通知;
    程序执行完后必须打印输出“success”(不包含引号)。如果商户反馈给支付宝的字符不是success这7个字符,支付宝服务器会不断重发通知,直到超过24小时22分钟。
    一般情况下,25小时以内完成8次通知(通知的间隔频率一般是:2m,10m,10m,1h,2h,6h,15h);
    程序执行完成后,该页面不能执行页面跳转。如果执行页面跳转,支付宝会收不到success字符,会被支付宝服务器判定为该页面程序运行出现异常,而重发处理结果通知;
    cookies、session等在此页面会失效,即无法获取这些数据;
    该方式的调试与运行必须在服务器上,即互联网上能访问;
    该方式的作用主要防止订单丢失,即页面跳转同步通知没有处理订单更新,它则去处理;
    通知ID(参数notify_id)只有一分钟有效期,超过一分钟该次通知会验证失败。一旦验证成功下次再验证就会失效。

    总结:
    notify_url是支付宝模拟post数据给你,只要状态改变就会post给你
    return_url是跳转,用户付款后跳转到你的页面.只有第一次会通知你,以后不会了.
    参考链接:https://www.cnblogs.com/xishuqingchun/p/4864452.html

    接下里就是介绍代码实现:

    首先是创建他提供的发送http请求的工具包AlipayClient
    AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.gatewayUrl, AlipayConfig.app_id, AlipayConfig.merchant_private_key, "json", AlipayConfig.charset, AlipayConfig.alipay_public_key, AlipayConfig.sign_type);

    alipayClient封装公共请求参数,
    AlipayTradePagePayRequest设置付款请求;
    付款其中的方法biz_content封装业务请求参数
    其中biz_content必填的参数有
    out_trade_no//订单号
    total_amount//金额
    subject//商品名称
    product_code//销售产品码,与支付宝签约的产品码名称。 注:目前仅支持FAST_INSTANT_TRADE_PAY
    请求以json格式传递

    例如:

        AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.gatewayUrl, AlipayConfig.app_id, AlipayConfig.merchant_private_key, "json", AlipayConfig.charset, AlipayConfig.alipay_public_key, AlipayConfig.sign_type);
    
        //设置请求参数
        AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
        alipayRequest.setReturnUrl(AlipayConfig.return_url);
        alipayRequest.setNotifyUrl(AlipayConfig.notify_url);
    
        //商户订单号,商户网站订单系统中唯一订单号,必填
        String out_trade_no = new String(request.getParameter("WIDout_trade_no").getBytes("ISO-8859-1"),"UTF-8");
        //付款金额,必填
        String total_amount = new String(request.getParameter("WIDtotal_amount").getBytes("ISO-8859-1"),"UTF-8");
        //订单名称,必填
        String subject = new String(request.getParameter("WIDsubject").getBytes("ISO-8859-1"),"UTF-8");
        //商品描述,可空
        String body = new String(request.getParameter("WIDbody").getBytes("ISO-8859-1"),"UTF-8");
    
        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 = alipayClient.pageExecute(alipayRequest).getBody();//调用sdk生成表单
    
    
        //输出,注意输出格式,错误容易验签失败
        response.setContentType("text/html; charset=utf-8");
        PrintWriter out = response.getWriter();
        out.println(result);
    

    发送完该请求到支付宝后,对于PC网站支付的交易,在用户支付完成之后,支付宝会根据API中商户传入的return_url参数,通过GET请求的形式将部分支付结果参数通知到商户系统。
    页面返回的业务参数只有订单号,交易号,金额和支付宝唯一用户号(select_id)
    注意:也就是获取不到商品描述信息Body

    交易查询的功能,我修改了一下demo中直接向支付宝发送请求来获取自己的数据,我是在return_url验签成功后,直接插入到数据库表格中,然后交易查询的时候,直接查询插入的数据

    退款申请我额外做了个退款申请列表,当用户发起退款申请,不是直接就申请成功,他会修改商品的status属性,变更为“退款申请中”的状态,然后根据这个状态进行表数据的检索,汇成一张子表来显示退款申请用户的列表,然后商户可以选择确认或者取消退款

    退款申请查询,当用户退款成功,在退款申请查询中能查询到相应的退款订单信息否则显示信息为空

    交易结束,交易结束是发生在订单形成,却没有付款的情况下,这一功能我没有进行修改,直接是发送请求到支付宝,而后返回相应的信息。

    相关文章

      网友评论

          本文标题:支付宝接口的调用

          本文链接:https://www.haomeiwen.com/subject/jclziftx.html