javaWeb学习

springboot实现支付宝支付案例

2020-05-24  本文已影响0人  haiyong6

做了一个测试案例,用的沙箱测试账号
可以去支付宝官网注册一个开发者账号,获取沙箱账号,地址: https://openhome.alipay.com/platform/appDaily.htm?tab=info
注册完之后会看到以下画面:

支付宝支付沙箱应用 支付宝支付沙箱账号

上面两个图中,我们可以看到有这个几个有用的信息:
1.APPID
2.支付宝网关
3.商家账号 登录密码
4.买家账号 登录密码 支付密码

接下来,我们在沙箱应用里要设置一下RSA2公钥
首先下载生成公钥和私钥的工具,地址:https://opendocs.alipay.com/open/291/105971#LDsXr

支付宝支付公钥生成工具
如上图,只有windows版和macOs版,用linux的心疼一秒钟,还好我有windows虚拟机。
支付宝支付公钥生成
如上图,安装之后,点击生成秘钥即可生成公钥和私钥,复制保存好这个公钥和私钥
接下来更改沙箱应用中RSA2的公钥,把刚刚生成的公钥复制到在线网站上保存。
支付宝支付保存公钥到在线网站

到现在为止,准备工作已经做完了。

在springboot上创建一个AlipayConfig类

package com.zhaohy.app.config;

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

public class AlipayConfig {
    // 应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号
    public static String APP_ID = "";

    // 商户私钥,您的PKCS8格式RSA2私钥,这些就是我们刚才设置的
    public static String RSA_PRIVATE_KEY = "";

    // 支付宝公钥,查看地址:https://openhome.alipay.com/platform/keyManage.htm
    // 对应APPID下的支付宝公钥。,这些就是我们刚才设置的
    public static String ALIPAY_PUBLIC_KEY = "";

    // 异步通知,再这里我们设计自己的后台代码
    public static String notify_url = "http://www.zhaohy.org.cn";

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

    // 签名方式
    public static String SIGN_TYPE = "RSA2";

    // 字符编码格式
    public static String CHARSET = "utf-8";

    // 支付宝网关 https://openapi.alipaydev.com/gateway.do https://openapi.alipay.com/gateway.do
    public static String GATEWAYURL = "https://openapi.alipaydev.com/gateway.do";

    // 支付宝网关
    public static String LOG_PATH = "/home/zhaohy/alipayLog/";
    
    public static String FORMAT = "json";

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

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

把之前的appid,公钥,私钥和网关地址都填在上面代码里

新建AlipayService类

package com.zhaohy.app.service;

import com.alipay.api.AlipayApiException;

public interface AlipayService {
    /**
     * web端订单支付
     * 
     * @param outTradeNo  订单编号(唯一)
     * @param totalAmount 订单价格
     * @param subject     商品名称
     */
    String webPagePay(String outTradeNo, Integer totalAmount, String subject) throws Exception;

    /**
     * app端订单支付
     * 
     * @param outTradeNo  订单编号
     * @param totalAmount 订单价格
     * @param subject     商品名称
     */
    String appPagePay(String outTradeNo, Integer totalAmount, String subject) throws Exception;

    /**
     * 退款
     * 
     * @param outTradeNo   订单编号
     * @param refundReason 退款原因
     * @param refundAmount 退款金额
     * @param outRequestNo 标识一次退款请求,同一笔交易多次退款需要保证唯一,如需部分退款,则此参数必传
     */
    String refund(String outTradeNo, String refundReason, Integer refundAmount, String outRequestNo)
            throws AlipayApiException;

    /**
     * 交易查询
     * 
     * @param outTradeNo 订单编号(唯一)
     */
    String query(String outTradeNo) throws AlipayApiException;

    /**
     * 交易关闭
     * 
     * @param outTradeNo订单编号(唯一)
     */
    String close(String outTradeNo) throws AlipayApiException;

    /**
     * 退款查询
     * 
     * @param outTradeNo   订单编号(唯一)
     * @param outRequestNo 标识一次退款请求,同一笔交易多次退款需要保证唯一,如需部分退款,则此参数必传
     */
    String refundQuery(String outTradeNo, String outRequestNo) throws AlipayApiException;
}

新建AlipayServiceImpl实现类

package com.zhaohy.app.service.impl;

import java.util.HashMap;
import java.util.Map;

import org.springframework.stereotype.Service;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeWapPayModel;
import com.alipay.api.request.AlipayTradeCloseRequest;
import com.alipay.api.request.AlipayTradeFastpayRefundQueryRequest;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.request.AlipayTradeWapPayRequest;
import com.zhaohy.app.config.AlipayConfig;
import com.zhaohy.app.service.AlipayService;
import com.zhaohy.app.utils.AppFrameworkUtil;
@Service("AlipayService")
public class AlipayServiceImpl implements AlipayService {

    /** 调取支付宝接口 web端支付 */
    DefaultAlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.GATEWAYURL, AlipayConfig.APP_ID,
            AlipayConfig.RSA_PRIVATE_KEY, "json", AlipayConfig.CHARSET, AlipayConfig.ALIPAY_PUBLIC_KEY,
            AlipayConfig.SIGN_TYPE);

    /** 调取支付宝接口app端支付 */
    AlipayClient alipayClients = new DefaultAlipayClient(AlipayConfig.GATEWAYURL, AlipayConfig.APP_ID,
            AlipayConfig.RSA_PRIVATE_KEY, "json", AlipayConfig.CHARSET, AlipayConfig.ALIPAY_PUBLIC_KEY,
            AlipayConfig.SIGN_TYPE);

    /**
     * web端订单支付
     * 
     * @param outTradeNo  订单编号(唯一)
     * @param totalAmount 订单价格
     * @param subject     商品名称
     */
    @Override
    public String webPagePay(String outTradeNo, Integer totalAmount, String subject) throws Exception {

        AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
        /** 同步通知,支付完成后,支付成功页面 */
        alipayRequest.setReturnUrl(AlipayConfig.return_url);
        /** 异步通知,支付完成后,需要进行的异步处理 */
        alipayRequest.setNotifyUrl(AlipayConfig.notify_url);

        Map<String, String> bizContentMap = new HashMap<String, String>();
        bizContentMap.put("out_trade_no", outTradeNo);
        bizContentMap.put("total_amount", totalAmount + "");
        bizContentMap.put("subject", subject);
        bizContentMap.put("body", "商品名称");
        bizContentMap.put("timeout_express", "90m");
        bizContentMap.put("product_code", "FAST_INSTANT_TRADE_PAY");
        String bizContentJson = AppFrameworkUtil.structureConfigParamsGroupJSONDataWithOutSimpleResultBean(bizContentMap);
        alipayRequest.setBizContent(bizContentJson);

        /** 转换格式 */
        String result = alipayClient.pageExecute(alipayRequest).getBody().replace('\"', '\'').replace('\n', ' ');
        return result;
    }

    /**
     * 退款
     * 
     * @param outTradeNo   订单编号
     * @param refundReason 退款原因
     * @param refundAmount 退款金额
     * @param outRequestNo 标识一次退款请求,同一笔交易多次退款需要保证唯一,如需部分退款,则此参数必传
     */
    @Override
    public String refund(String outTradeNo, String refundReason, Integer refundAmount, String outRequestNo)
            throws AlipayApiException {
        AlipayTradeRefundRequest alipayRequest = new AlipayTradeRefundRequest();

        /** 调取接口 */
        alipayRequest.setBizContent("{\"out_trade_no\":\"" + outTradeNo + "\"," + "\"refund_amount\":\"" + refundAmount
                + "\"," + "\"refund_reason\":\"" + refundReason + "\"," + "\"out_request_no\":\"" + outRequestNo
                + "\"}");
        String result = alipayClient.execute(alipayRequest).getBody();
        return result;
    }

    /**
     * 交易查询
     * 
     * @param outTradeNo 订单编号(唯一)
     */
    @Override
    public String query(String outTradeNo) throws AlipayApiException {
        AlipayTradeQueryRequest alipayRequest = new AlipayTradeQueryRequest();
        /** 请求接口 */
        alipayRequest.setBizContent("{\"out_trade_no\":\"" + outTradeNo + "\"," + "\"trade_no\":\"" + "" + "\"}");
        /** 转换格式 */
        String result = alipayClient.execute(alipayRequest).getBody();
        return result;
    }

    /**
     * 交易关闭
     * 
     * @param outTradeNo订单编号(唯一)
     */
    @Override
    public String close(String outTradeNo) throws AlipayApiException {
        AlipayTradeCloseRequest alipayRequest = new AlipayTradeCloseRequest();

        alipayRequest.setBizContent("{\"out_trade_no\":\"" + outTradeNo + "\"," + "\"trade_no\":\"" + "" + "\"}");

        String result = alipayClient.execute(alipayRequest).getBody();

        return result;
    }

    /**
     * 退款查询
     * 
     * @param outTradeNo   订单编号(唯一)
     * @param outRequestNo 标识一次退款请求,同一笔交易多次退款需要保证唯一,如需部分退款,则此参数必传
     */
    @Override
    public String refundQuery(String outTradeNo, String outRequestNo) throws AlipayApiException {
        AlipayTradeFastpayRefundQueryRequest alipayRequest = new AlipayTradeFastpayRefundQueryRequest();

        /** 请求接口 */
        alipayRequest.setBizContent(
                "{\"out_trade_no\":\"" + outTradeNo + "\"," + "\"out_request_no\":\"" + outRequestNo + "\"}");

        /** 格式转换 */
        String result = alipayClient.execute(alipayRequest).getBody();

        return result;
    }

    /**
     * app端订单支付
     * 
     * @param outTradeNo  订单编号
     * @param totalAmount 订单价格
     * @param subject     商品名称
     */
    @Override
    public String appPagePay(String outTradeNo, Integer totalAmount, String subject) throws Exception {
        AlipayTradeWapPayRequest alipayRequest = new AlipayTradeWapPayRequest();

        /** 同步通知,支付完成后,支付成功页面 */
        alipayRequest.setReturnUrl(AlipayConfig.return_url);
        /** 异步通知,支付完成后,需要进行的异步处理 */
        alipayRequest.setNotifyUrl(AlipayConfig.notify_url);

        /** 销售产品码(固定) */
        String productCode = "QUICK_WAP_WAY";

        /** 进行赋值 */
        AlipayTradeWapPayModel wapPayModel = new AlipayTradeWapPayModel();
        wapPayModel.setOutTradeNo(outTradeNo);
        wapPayModel.setSubject(subject);
        wapPayModel.setTotalAmount(totalAmount.toString());
        wapPayModel.setBody("商品名称");
        wapPayModel.setTimeoutExpress("2m");
        wapPayModel.setProductCode(productCode);
        alipayRequest.setBizModel(wapPayModel);

        /** 格式转换 */
        String result = alipayClients.pageExecute(alipayRequest).getBody().replace('\"', '\'').replace('\n', ' ');
        return result;
    }

}

新建AlipayController

package com.zhaohy.app.controller;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.zhaohy.app.service.AlipayService;
import com.zhaohy.app.utils.AppFrameworkUtil;
@Controller
public class AlipayController {
    @Autowired
    private AlipayService alipayService;
    
    @RequestMapping("/alipayTest.do")
    public String test(HttpServletRequest request) {
        request.setAttribute("ctx", AppFrameworkUtil.getWebRootUrl(request, ""));
        return "html/alipay";
    }

    /**
     * web 订单支付
     */
    @RequestMapping("/alipay/getPagePay")
    public void getPagePay(HttpServletRequest request, HttpServletResponse response) throws Exception {
        /** 模仿数据库,从后台调数据 */
        String outTradeNo = "19960310621211";
        Integer totalAmount = 1;
        String subject = "苹果28";

        String pay = alipayService.webPagePay(outTradeNo, totalAmount, subject);
        System.out.println(pay);

        Map<Object, Object> resultMap = new HashMap<>();
        resultMap.put("data", pay);

        AppFrameworkUtil.renderJSON(response, AppFrameworkUtil.structureConfigParamsGroupJSONData(resultMap));
    }

    /**
     * app 订单支付
     */
    @RequestMapping("/alipay/getAppPagePay")
    public void getAppPagePay(HttpServletRequest request, HttpServletResponse response) throws Exception {
        /** 模仿数据库,从后台调数据 */
        String outTradeNo = "1312332";
        Integer totalAmount = 1000;
        String subject = "天猫超市014";

        String pay = alipayService.appPagePay(outTradeNo, totalAmount, subject);

        System.out.println(pay);
        Map<Object, Object> resultMap = new HashMap<>();
        resultMap.put("data", pay);
        AppFrameworkUtil.renderJSON(response, AppFrameworkUtil.structureConfigParamsGroupJSONData(resultMap));

    }

    /**
     * 交易查询
     */
    @RequestMapping("/alipay/aipayQuery")
    public void alipayQuery(HttpServletRequest request, HttpServletResponse response) throws Exception {
        /** 调取支付订单号 */
        String outTradeNo = "13123";

        String query = alipayService.query(outTradeNo);

        //Object json = JSONObject.toJSON(query);

        /*
         * JSONObject jObject = new JSONObject(); jObject.get(query);
         */
        AppFrameworkUtil.renderJSON(response, query);
    }

    /**
     * 退款
     * 
     * @throws AlipayApiException
     */
    @RequestMapping("/alipay/alipayRefund")
    public void alipayRefund(HttpServletRequest request, HttpServletResponse response) throws AlipayApiException {
        String outTradeNo = request.getParameter("outTradeNo");
        String outRequestNo = request.getParameter("outRequestNo");
        String refundAmount = request.getParameter("refundAmount");
        /** 调取数据 */
        // String outTradeNo = "15382028806591197";
        String refundReason = "用户不想购买";
        // refundAmount = 1;
        // outRequestNo = "22";

        String refund = alipayService.refund(outTradeNo, refundReason, Integer.parseInt(refundAmount), outRequestNo);

        System.out.println(refund);

        AppFrameworkUtil.renderJSON(response, refund);
    }

    /**
     * 退款查询
     * 
     * @throws AlipayApiException
     */
    @RequestMapping("/alipay/refundQuery")
    public void refundQuery(HttpServletRequest request, HttpServletResponse response) throws AlipayApiException {

        /** 调取数据 */
        String outTradeNo = "13123";
        String outRequestNo = "2";

        String refund = alipayService.refundQuery(outTradeNo, outRequestNo);

        AppFrameworkUtil.renderJSON(response, refund);

    }

    /**
     * 交易关闭
     * 
     * @throws AlipayApiException
     */
    @RequestMapping("/alipay/alipayclose")
    public void alipaycolse(HttpServletRequest request, HttpServletResponse response) throws AlipayApiException {

        /** 调取数据 */
        String outTradeNo = "13123";

        String close = alipayService.close(outTradeNo);

        AppFrameworkUtil.renderJSON(response, close);
    }
}

controller里getAppPagePay是app订单支付,里面写死的是测试数据,如果正式用,可以当参数传进来。
演示app 订单支付,因为app订单支付会跳转到支付宝进行登录支付,如果没有监测到支付宝应用,则用网页版的支付宝进行支付,会比较方便。
调用上面的/alipayTest.do接口会跳转到html/alipay.html页面
alipay.html代码如下:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script th:src="@{${ctx} + '/js/jquery/jquery-3.2.1.min.js'}"></script>
<script th:src="@{${ctx} + '/js/common/common.js'}"></script>

<script>
$(function(){
    let url = "http://127.0.0.1:8082/alipay/getAppPagePay";
    let params = {}
    let result = getData(params, url);
    console.log(result)
    $("#alipay").html(result.data);
})
function getData(dataArr, url){
    let results = null;
    $.ajax({
        url:url,
        data:JSON.stringify(dataArr),
        contentType:'application/json',
        dataType:'json',
        async:false,
        type:'post',
        beforeSend: function(request) {
            if(!booleanEmpty(localStorage.getItem("token"))){
                request.setRequestHeader("token", localStorage.getItem("token"));
            }
        },
        success:function(result){
            if("403" == result.result_code){
                alert(result.result_msg);
                window.location.href = $("#rootPath").val() + "/user/loginPage.do"
            } else{
                results = result.data;
            }
        },
        complete:function (){  //在数据加载完成之后,要删除掉 正在加载的dom
        }
    });
    
    return results;
};
</script>
</head>
<body>
    <div id="alipay"></div>
</body>


</html>

可以看到,一进来这个页面会请求app订单支付接口,那个接口会返回一个form表单,并提交给支付宝进行支付,那个form表单的html放到#alipay div中便会自动执行跳转.

启动项目,访问http://127.0.0.1:8082/alipayTest.do

支付宝支付跳转页面
如图,电脑访问跳转到了上图页面,点击继续浏览器付款,登录沙箱买家账号,输入支付密码即可
支付宝支付付款页面
点击确认付款,输入密码
image
几秒钟后会跳转回AlipayConfig里面设置的http:www.zhaohy.org.cn
支付宝支付跳转回页面
至此,整个支付过程已经完成~
上一篇 下一篇

猜你喜欢

热点阅读