Java支付宝支付(Alipay),支付接口,同步异步通知

做这个测试必须先注册成为支付宝开发者,最好要有一定的Java基础.注意同步异步通知这个必须要让支付宝可以访问你的项目,也就是说必须让支付宝可以访问你的项目中的方法,所以要把项目放在公网上,如果只是简单测试推荐使用花生壳

 

1.添加Alipay-sdk支付jar包: 

alipay-sdk-java20170324180803.jar

alipay-sdk-java20170324180803-source.jar

commons-logging-1.1.1.jar    //spring框架有日志包可忽略

2.编写支付宝网关密钥等配置文件

import java.io.FileWriter;
import java.io.IOException;

/* *
 *类名:AlipayConfig
 *功能:基础配置类
 *详细:设置帐户有关信息及返回路径
 *修改日期:2017-04-05
 *说明:
 *以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。
 *该代码仅供学习和研究支付宝接口使用,只是提供一个参考。
 */

public class AlipayConfig {

//↓↓↓↓↓↓↓↓↓↓请在这里配置您的基本信息↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

    // 应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号
    public static String app_id = "20160926******";

    // 商户私钥,您的PKCS8格式RSA2私钥
    public static String merchant_private_key = "私钥";

    // 支付宝公钥,查看地址:https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥。
    public static String alipay_public_key = "公钥";

    // 服务器异步通知页面路径  需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
public static String notify_url = "http://yan.eicp.net:26003/MyCSDN/pay/pay_notify";

// 页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
public static String return_url = "http://yan.eicp.net:26003/MyCSDN/pay/pay_return";



    // 签名方式
    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 = "C:\\";


//↑↑↑↑↑↑↑↑↑↑请在这里配置您的基本信息↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑

    /**
     * 写日志,方便测试(看网站需求,也可以改成把记录存入数据库)
     * @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();
                }
            }
        }
    }
}

 

 

3.编写支付宝支付工具类 :做的是将订单信息公钥私钥等交给支付宝进行加密后返回到界面层

import com.alipay.api.*;
import com.alipay.api.domain.AlipayTradeWapPayModel;
import com.alipay.api.request.*;
import com.it.exception.AlipayRuntimeException;

public class AlipayUtil {

    public static String pay(String out_trade_no, String total_amount, String subject, String body) {
        //获得初始化的AlipayClient
        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);

        //设置订单信息
        AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
        model.setOutTradeNo(out_trade_no);//必填,商户订单号
        model.setSubject(subject);//必填,订单名称
        model.setTotalAmount(total_amount);//必填,付款金额
        model.setBody(body);//选填,商品描述
        model.setProductCode("FAST_INSTANT_TRADE_PAY");//必填,电脑支付FAST_INSTANT_TRADE_PAY,手机支付QUICK_WAP_WAY
        //model.setTimeoutExpress(timeout_express);//选填,增加自定义超时时间参数timeout_express
        alipayRequest.setBizModel(model);

        //请求
        try {
            //把支付信息加密好(私钥),向支付宝后端申请支付,后端用公钥解开信息,生成带有二维码的连接返回给用户,要求用户按链接跳转
            String result = alipayClient.pageExecute(alipayRequest).getBody();
            return result;
        } catch (AlipayApiException e) {
            throw new AlipayRuntimeException("支付宝支付失败", e);
        }

    }
}

 

 

4.编写控制器调用支付工具类

 

//发起支付,等待支付宝返回支付页面
    @RequestMapping(value = "/paydo", method = RequestMethod.POST)
    public void payDo(HttpServletRequest request, HttpServletResponse response,float money) throws Exception {
//        System.out.println("测试支付");
        Member m = (Member) request.getSession().getAttribute("m");
        response.setContentType("text/html; charset=utf-8");//千万不要忘了设编码,否则密钥报错!!!!!!
        PrintWriter out = response.getWriter();    //输出流

        String out_trade_no = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + "_" + m.getId();//订单号
        String total_amount = money + "";                 //支付金额
        String subject = m.getNickName() + "充值";        //订单名称
        String body = "手机充值";                       //商品描述


        out.print(AlipayUtil.pay(out_trade_no, total_amount, subject, body));
    }

 

//异步通知
    @RequestMapping(value = "/pay_notify",method = RequestMethod.POST)
    public void notifyUrl(HttpServletResponse response,HttpServletRequest request) throws IOException, AlipayApiException {
        System.out.println("异步通知");
        PrintWriter out  = response.getWriter();
        request.setCharacterEncoding("utf-8");//乱码解决,这段代码在出现乱码时使用
        //获取支付宝POST过来反馈信息
        Map params = new HashMap();
        Map requestParams = request.getParameterMap();
        for(String str :requestParams.keySet()){
            String name = str;
            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] + ",";
            }
            params.put(name, valueStr);
        }

        boolean signVerified = AlipaySignature.rsaCheckV1(params, AlipayConfig.alipay_public_key, AlipayConfig.charset, AlipayConfig.sign_type); //调用SDK验证签名

        if(!signVerified) {
            System.out.println("验签失败");
            out.print("fail");
            return;
        }

        //商户订单号,之前生成的带用户ID的订单号
        String out_trade_no = params.get("out_trade_no");
        //支付宝交易号
        String trade_no = params.get("trade_no");
        //付款金额
        String total_amount = params.get("total_amount");
        //交易状态
        String trade_status = new String(request.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在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序
            //如果有做过处理,不执行商户的业务程序


            //增加用户在数据库余额
            String[] ss = out_trade_no.split("_");
            int mid = Integer.parseInt(ss[1]);
            Member m = memberService.findOne(mid);
            m.setScore(m.getScore() + (int)Double.parseDouble(total_amount));
            memberService.edit(m);
            //添加充值记录
            service.add(new PayInfo(trade_no,new Date(),"积分充值",m));
            System.out.println("trade_no:"+trade_no+"
out_trade_no:"
+out_trade_no+"
total_amount:"
+total_amount);

        }

        out.print("success");
    }

    //同步通知
    @RequestMapping(value = "/pay_return",method = RequestMethod.GET)
    public String returnUrl(HttpServletRequest request) throws UnsupportedEncodingException, AlipayApiException {
        System.out.println("同步通知");
        request.setCharacterEncoding("utf-8");//乱码解决,这段代码在出现乱码时使用
        //获取支付宝GET过来反馈信息
        Map params = new HashMap();
        Map requestParams = request.getParameterMap();
        for(String str :requestParams.keySet()){
            String name = str;
            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] + ",";
            }
            params.put(name, valueStr);
        }

        boolean signVerified = AlipaySignature.rsaCheckV1(params, AlipayConfig.alipay_public_key, AlipayConfig.charset, AlipayConfig.sign_type); //调用SDK验证签名

        if(signVerified) {
            System.out.println("验签成功-跳转到成功后页面");
            //跳转至支付成功后的页面,
            return "redirect:payment";
        }else {
            System.out.println("验签失败-跳转到充值页面让用户重新充值");
            return "redirect:addmoney";
        }

        //打印请求中的字段
//        for (String str:params.keySet()) {
//            System.out.println(str +":"+ params.get(str));
//        }
    }

5.前端页面,调用controller方法即可

<form action="${pageContext.request.contextPath}/paydo" method="POST">
   充值金额:<input type="text" name="money" />
<br/>
<input type="submit"  value="充值"/>
form>

 

 

 

 

 

 

 

你可能感兴趣的:(Java支付宝支付(Alipay),支付接口,同步异步通知)