SpringBoot基于支付宝沙箱环境实现支付宝支付和退款

1.环境准备

需要实现支付宝支付功能,首先需要到支付宝开放平台(https://open.alipay.com/dev/workspace),去开通自己的沙箱账号。
SpringBoot基于支付宝沙箱环境实现支付宝支付和退款_第1张图片
然后配置秘钥和私钥,具体操作步骤参照支付宝沙箱支付开发文档,文档很详细,按照文档操作就行。

2.代码开发

2.1 引入依赖


            com.alipay.sdk
            alipay-sdk-java
            3.0.0
        

2.2 配置类
需要根据自己的沙箱,更改配置类相关属性。

public class AlipayConfig {

    // 应用ID,APPID,收款账号既是的APPID对应支付宝账号,开发时使用沙箱提供的APPID,生产环境改成自己的APPID
    public static String APP_ID = ""; //测试
    // 商户私钥,PKCS8格式RSA2私钥
   public static String APP_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://localhost:8188/notifyUrl";
    // 页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问(其实就是支付成功后返回的页面)
    public static String return_url = "http://localhost:8188/returnUrl";
    // 签名方式
    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:\\";

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

支付业务代码
public class PayController {

@ResponseBody
@RequestMapping("/payOrder")
public String payController(HttpServletRequest request, HttpServletResponse response, String id) throws IOException {
    //获得初始化的AlipayClient
    AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.gatewayUrl, AlipayConfig.APP_ID,
            AlipayConfig.APP_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 = ;
    //付款金额,必填
    String total_amount = ;
    //订单名称,必填
    String subject =;
    //商品描述,可空
    String body = "测试";
    // 该笔订单允许的最晚付款时间,逾期将关闭交易。取值范围:1m~15d。m-分钟,h-小时,d-天,1c-当天
    // (1c-当天的情况下,无论交易何时创建,都在0点关闭)。 该参数数值不接受小数点, 如 1.5h,可转换为 90m。
    String timeout_express = "1c";
    alipayRequest.setBizContent("{\"out_trade_no\":\"" + out_trade_no + "\","
            + "\"total_amount\":\"" + total_amount + "\","
            + "\"subject\":\"" + subject + "\","
            + "\"body\":\"" + body + "\","
            + "\"timeout_express\":\"" + timeout_express + "\","
            + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");
    //请求
    String url = "";
    try {
        url = alipayClient.pageExecute(alipayRequest).getBody(); //调用SDK生成表单

        response.setContentType("text/html;charset=" + AlipayConfig.CHARSET);
        response.getWriter().write(url); // 直接将完整的表单html输出到页面
        response.getWriter().flush();
        response.getWriter().close();

    } catch (AlipayApiException e) {
        e.printStackTrace();
    }
    System.out.println(url);
    return url;
}


/**
 * 同步跳转
 *
 * @param request
 * @throws Exception
 */
@ResponseBody
@RequestMapping("/returnUrl")
public ModelAndView returnUrl(HttpServletRequest request) throws Exception {
    ModelAndView mav = new ModelAndView();

    // 获取支付宝GET过来反馈信息(官方固定代码)
    Map params = new HashMap();
    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] + ",";
        }
        params.put(name, valueStr);
    }
    boolean signVerified = AlipaySignature.rsaCheckV1(params, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.CHARSET, AlipayConfig.sign_type); // 调用SDK验证签名
    // 返回界面
    if (signVerified) {
        System.out.println("前往支付成功页面");
        mav.setViewName("redirect:/myOrder");
    } else {
        System.out.println("前往支付失败页面");
          mav.setViewName("redirect:/myOrder");
    }
    return mav;
}

3.退款

public ModelAndView toRefund(HttpServletResponse response, String id) throws IOException {
        ModelAndView mv=new ModelAndView();
        // 设置编码格式
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        //获得初始化的AlipayClient
        AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.gatewayUrl, AlipayConfig.APP_ID,
                AlipayConfig.APP_PRIVATE_KEY, "json", AlipayConfig.CHARSET, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.sign_type);
        //设置请求参数
        AlipayTradeRefundRequest alipayRequest = new AlipayTradeRefundRequest();
        //商户订单号,必填
        String out_trade_no = ;
        //需要退款的金额,该金额不能大于订单金额,必填
        String refund_amount = ;
        //标识一次退款请求,同一笔交易多次退款需要保证唯一。如需部分退款,则此参数必传;不传该参数则代表全额退款
        String out_request_no = new String(UUID.randomUUID().toString());
        // 字符转义很重要
        alipayRequest.setBizContent("{\"out_trade_no\":\"" + out_trade_no + "\","
                + "\"refund_amount\":\"" + refund_amount + "\","
                + "\"out_request_no\":\"" + out_request_no + "\"}");
        //请求
        AlipayTradeRefundResponse result = null;
        try {
            result = alipayClient.execute(alipayRequest);
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        //输出
       out.println(result);
        if (result.isSuccess()) {
            System.out.println("退款成功");
            mv.setViewName("redirect:/myOrder");
        }else {
            System.out.println("退款失败");
            mv.setViewName("error");
        }
        return mv;
    }

注意:
配置文件需要改成自己的沙箱相关内容,本人实测,只要公钥和私钥配置没有问题,基本都不会有错,如有问题,请评论区提出供大家一起学习探讨。

你可能感兴趣的:(java,spring,springboot)