Skip to content

相关地址(服务器端回调地址、客户端支付成功/失败回调都在)的参数我们都使用枚举类进行管理,请求参数单独封装成一个对象进行参数传递,最后对支付功能再进行进一步的封装。

创建服务器回调地址枚举类

回调地址我们使用枚举类进行统一管理

java
/**
 * @author cv大魔王
 * @description 支付宝支付回调地址枚举类
 * @date 2022/8/13
 */
public enum AlipayNotifyUrlEnum {

    TEST_URL("/api/v1/ali/callback"),

    COURSE_URL("/api/v1/ali/course/callback");

    private String url;
    
    AlipayNotifyUrlEnum(String url) {
        this.url = url;
    }
    public String getUrl() {
        return url;
    }
}

创建客户端支付成功回调地址枚举类

如果是网页支付,那么支付成功时,客户端会返回我们回调的地址页面,我们对这个地址也创建枚举类

java
/**
 * @author cv大魔王
 * @description 支付宝支付回调地址枚举类
 * @date 2022/8/13
 */
public enum AlipayReturnUrlEnum {

    COURSE_URL("/course/pay/success?orderId=");

    private String url;

    AlipayReturnUrlEnum(String url) {
        this.url = url;
    }

    public String getUrl() {
        return url;
    }
}

创建客户端支付失败回调地址枚举类

用户付款中途退出返回商户网站的地址,也就是用户没有真的付款所跳转的地址。

java
/**
 * @author cv大魔王
 * @description 支付宝支付回调地址枚举类
 * @date 2022/8/13
 */
public enum AlipayReturnFailUrlEnum {

    COURSE_URL("/course/pay/order?orderId=")
    ;

    private String url;

    AlipayReturnFailUrlEnum(String url) {
        this.url = url;
    }

    public String getUrl() {
        return url;
    }
}

支付宝请求参数传递类

java
@Data
public class AlipayParam {

    /**
     * 服务器端回调地址,支付成功后支付宝将支付结果按这个地址进行通知
     */
    private AlipayNotifyUrlEnum callbackEnum;

    /**
     * 客户端支付成功回调地址,用户支付成功后跳转回网页或APP
     */
    private String returnUrl;

    /**
     * 订单id
     */
    private String orderId;

    /**
     * 支付金额
     */
    private BigDecimal price;

    /**
     * 商品标题或其他标注售卖物品的信息
     */
    private String title;

    /**
     * 客户端用户支付中途取消支付后跳转回网页或APP
     */
    private String returnFailUrl;
}

发送H5支付请求工具类

H5支付请求返回的是HTML页面,我们把页面直接返回出去即可

java
@Slf4j
@Component
public class AliPayUtils {
    @Autowired
    private AliPayConfig aliPayConfig;

    @Autowired
    private AlipayClient alipayClient;

    public void aliPayH5(AlipayParam alipayParam, HttpServletResponse httpResponse) {
        // 1.创建阿里云支付请求对象
        AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest();
        request.setNotifyUrl(aliPayConfig.getNotifyDomain() + alipayParam.getCallbackEnum().getUrl());
        request.setReturnUrl(aliPayConfig.getReturnDomain() + alipayParam.getReturnUrl());

        // 2.获取支付统一JSON格式请求参数
        JSONObject bizContent = getBizContent(alipayParam, aliPayConfig);
        // 3.JSON中设置支付方式是H5支付
        bizContent.put("product_code", "QUICK_WAP_WAY");
        // 4.将json数据插入到请求体中
        request.setBizContent(bizContent.toString());
        AlipayTradeWapPayResponse response = null;
        try {
            // 5.注意请求方式
            response = alipayClient.pageExecute(request);
            if (response.isSuccess()) {
                //直接将完整的表单html输出到页面
                httpResponse.setContentType("text/html;charset=UTF-8");
                httpResponse.getWriter().write(response.getBody());
                httpResponse.getWriter().flush();
                httpResponse.getWriter().close();
            } else {
                throw new DefaultException(ResultEnum.ERROR);
            }
        } catch (AlipayApiException | IOException e) {
            e.printStackTrace();
            throw new DefaultException(ResultEnum.ERROR);
        }
    }

    /**
     * 封装支付统一请求参数,订单号、支付金额、商品标题等数据都是各个都需要的
     *
     * @return 请求信息JSON对象
     */
    private JSONObject getBizContent(AlipayParam alipayParam, AliPayConfig aliPayConfig) {
        JSONObject bizContent = new JSONObject();
        bizContent.put("out_trade_no", alipayParam.getOrderId());
        bizContent.put("total_amount", alipayParam.getPrice());
        // 商品标题如果长度超过100则进行截取
        bizContent.put("subject", alipayParam.getTitle().length() > 100 ? alipayParam.getTitle().substring(0, 100) : alipayParam.getTitle());
        bizContent.put("quit_url", aliPayConfig.getReturnDomain() + alipayParam.getReturnFailUrl());
        return bizContent;
    }
}

H5支付接口开发

直接在浏览器输入请求地址即可,如果有内网穿透更好,直接手机浏览器访问接口地址,即可自动跳转到支付宝。

java
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.xk857.alipay.domain.AlipayParam;
import com.xk857.alipay.enums.AlipayNotifyUrlEnum;
import com.xk857.alipay.enums.AlipayReturnFailUrlEnum;
import com.xk857.alipay.enums.AlipayReturnUrlEnum;
import com.xk857.alipay.util.AliPayUtils;

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


@Slf4j
@RestController
@RequestMapping("/api/v1/ali")
public class AlipayController {

    @Autowired
    private AliPayUtils aliPayUtils;

    /**
     * H5测试
     */
    @GetMapping("/h5")
    public void submitOrderAliPay(HttpServletRequest request, HttpServletResponse response) {
        AlipayParam alipayParam = new AlipayParam();
        alipayParam.setCallbackEnum(AlipayNotifyUrlEnum.TEST_URL);
        String orderId = IdWorker.getIdStr();
        log.info("H5生成的订单id是:{}",orderId);
        alipayParam.setReturnUrl(AlipayReturnUrlEnum.COURSE_URL.getUrl()+orderId);
        alipayParam.setOrderId(orderId);
        alipayParam.setPrice(new BigDecimal("0.05"));
        alipayParam.setTitle("5分钱测试订单");
        alipayParam.setReturnFailUrl(AlipayReturnFailUrlEnum.COURSE_URL.getUrl()+orderId);
        aliPayUtils.aliPayH5(alipayParam,response);
    }
}

说明:其他的支付方法都大体相似,官网的例子也非常清晰明了,我这里主要是撰写在项目中应该如何对接支付宝支付,对其进行了一定的封装和优化,如果你有更好的封装方法欢迎评论区留言指出,网页/移动应用文档指引 - 支付宝文档中心