沙箱环境申请地址:https://open.alipay.com/platform/appDaily.htm?tab=info
所需参数:

//支付宝网关地址:https://openapi.alipay.com/gateway.do 
//支付宝申请的APPID 
//商户应用私钥(与支付宝数据交互时,保证数据安全,防止数据被篡改) 
//支付宝公钥(与支付宝数据交互时,保证数据安全,防止数据被篡改) 
//签名算法类型(RSA2或者RSA,支付宝推荐使用RSA2) 
//编码格式(utf-8,gb2312,gbk) 

各接口详细参数地址:https://opendocs.alipay.com/apis
沙箱app下载地址(注意沙箱APP只有安卓版本的):https://open.alipay.com/platform/appDaily.htm?tab=tool

maven包地址:

  <dependency>
            <groupId>com.alipay.sdk</groupId>
            <artifactId>alipay-sdk-java</artifactId>
            <version>4.22.57.ALL</version>
        </dependency>

SDK所需初始化参数类

app:
  pay:
    ali:
      app_id: 你的appId
      mch_id: 你的沙箱商户id
      server_url: https://openapi.alipaydev.com/gateway.do #这里是沙箱版本的地址
      alipay_private_key: 你的应用私钥
      alipay_public_key: 你的支付宝公钥
      charset: UTF-8
      sign_type: RSA2
      format: json
      notify_url: http://localhost:8080/api/pay/ali/notify
      return_url: http://localhost:8080/api
      refund_url: http://localhost:8080/api
/**
 * @author zhangyujie
 * @since 2022-04-05
 **/
@Data
public class AliProperties {

    /**
     * 应用id
     */
    public String appId;
    /**
     * 应用私钥
     */
    public String alipayPrivateKey;
    /**
     * 支付宝公钥
     */
    public String alipayPublicKey;
    /**
     * 字符编码
     */
    public String charset;
    /**
     * 签名方式
     */
    public String signType;
    /**
     * 数据格式
     */
    public String format;
    /**
     * 商家id
     */
    private String mchId;
    /**
     * 调用接口的url
     */
    private String serverUrl;
    /**
     * 支付回调url
     */
    private String notifyUrl;

    /**
     * pc支付前台通知
     */
    private String returnUrl;

    /**
     * 退款url
     */
    private String refundUrl;

}

/**
 * @author zhangyujie
 * @since 2022-04-05
 **/
@Configuration
@ConfigurationProperties(prefix = "app.pay")
public class AppProperties {

    private AliProperties ali = new AliProperties();

    public AliProperties getAli() {
        return ali;
    }

    public void setAli(AliProperties ali) {
        this.ali = ali;
    }
}

创建AlipayClient

    @Resource
    private AppProperties appProperties;
 /**
     * 阿里 sdk 封装
     */
    private AlipayClient alipayClient;

    @PostConstruct
    public void initMethod() {
        alipayClient = new DefaultAlipayClient(
                appProperties.getAli().getServerUrl(),
                appProperties.getAli().getAppId(),
                appProperties.getAli().getAlipayPrivateKey(),
                appProperties.getAli().getFormat(),
                appProperties.getAli().getCharset(),
                appProperties.getAli().getAlipayPublicKey(),
                appProperties.getAli().getSignType());
    }

获取支付二维码

 /**
     * 支付宝扫码支付生成二维码响应到浏览器
     *
     * @param amount
     * @param response
     * @return
     */
    public void aliQrCodePay(Integer amount, HttpServletResponse response) throws Exception {
        AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();
        Map<String, String> params = new TreeMap<>();
        params.put("out_trade_no", RandomUtil.randomNumbers(10));
        params.put("total_amount", amount.toString());
        params.put("subject", "备注");
        params.put("body", "详情");
        params.put("store_id", "NJ_2031");
        params.put("timeout_express", "90m");
        request.setBizContent(objectMapper.writeValueAsString(params));
        request.setNotifyUrl(appProperties.getAli().getNotifyUrl());

        AlipayTradePrecreateResponse responseData = alipayClient.execute(request);
        log.info("response:{}", responseData.getBody());
        String qrCode = responseData.getQrCode();
        if (!ObjectUtils.isEmpty(qrCode)) {
        // 这里工具类是根据支付宝返回的qrCode利用谷歌的zxing包生成的二维码放进response
            PaymentUtils.createQRCode(qrCode, response);
        }
    }

测试生成二维码:

/**
 * @author zhangyujie
 * @since 2022-04-05
 **/
@Slf4j
@RestController
@RequestMapping(value = "/api/pay/ali")
public class AliPayController {

    @Resource
    private AliPayService aliPayService;

    /**
     * 支付宝扫码支付预下单
     *
     * @param amount
     * @param response
     * @return
     * @throws Exception
     */
    @GetMapping("/qrcode")
    public void qrCodePay(Integer amount, HttpServletResponse response) throws Exception {
        aliPayService.aliQrCodePay(amount, response);
    }

}

可以看到我们的sdk客户端创建的没问题,参数一切正常:这是调用返回的二维码字符串:
在这里插入图片描述
根据支付宝返回的qrCode利用谷歌的zxing包生成的二维码放进response

 public static void createQRCode(String content, HttpServletResponse response) {
        int width = 300, height = 300;
        String format = "png";
        Map<EncodeHintType, Object> hashMap = new HashMap<>();
        hashMap.put(EncodeHintType.CHARACTER_SET, StandardCharsets.UTF_8);
        hashMap.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
        hashMap.put(EncodeHintType.MARGIN, 1);
        try {
            response.setHeader("Cache-control", "no-cache");
            response.setHeader("Pragma", "no-cache");
            response.setHeader("content-type", "image/png");
            response.setCharacterEncoding(StandardCharsets.UTF_8.displayName());
            response.setDateHeader("Expires", 0);
            BitMatrix bitMatrix = new MultiFormatWriter()
                    .encode(content, BarcodeFormat.QR_CODE, width, height, hashMap);
            BufferedImage img = MatrixToImageWriter.toBufferedImage(bitMatrix);
            ImageIO.write(img, format, response.getOutputStream());
        } catch (Exception e) {
            log.warn("create QRCode error message:{}", e.getMessage());
        }
    }

postmain返回结果:
在这里插入图片描述
可以看到二维码是正常出来的,接下来我们使用沙箱APP扫码支付出现问题,咨询了支付宝开发组客服得知沙箱APP在升级,正常情况下是可以看到沙箱app的余额的,现在查看余额也是提示网络不给力请稍后重试
在这里插入图片描述在这里插入图片描述

支付宝提现

 /**
     * 支付宝提现
     *
     * @param amount
     */
    public Result deposit(Integer amount) {
        AlipayFundTransToaccountTransferModel transferModel = new AlipayFundTransToaccountTransferModel();
        transferModel.setOutBizNo(RandomUtil.randomNumbers(10));
        transferModel.setAmount("0.01");
        transferModel.setPayeeAccount("收款方账户");
        transferModel.setPayeeRealName("收款方真实姓名");
        transferModel.setPayerShowName("付款方姓名");
        transferModel.setRemark("remark");
        // ALIPAY_LOGONID:支付宝登录号,支持邮箱和手机号格式
        transferModel.setPayeeType("ALIPAY_LOGONID");
        try {
            AlipayFundTransToaccountTransferRequest request = new AlipayFundTransToaccountTransferRequest();
            request.setBizModel(transferModel);
            AlipayFundTransToaccountTransferResponse response = alipayClient.execute(request);
        } catch (AlipayApiException e) {
            log.info("ali deposit error message:{}", e.getMessage());
            return Result.success(CommonMessage.ALI_DEPOSIT_SUCCESS);
        }
        return Result.error(CommonMessage.ALI_DEPOSIT_FAILED);
    }

PC支付

 /**
     * 阿里pc支付
     *
     * @param amount
     * @param servletRequest
     * @return
     */
    public String aliPcPay(Integer amount, HttpServletRequest servletRequest) throws Exception {
        AlipayTradePagePayRequest payRequest = new AlipayTradePagePayRequest();
        // 前台通知
        payRequest.setReturnUrl(appProperties.getAli().getReturnUrl());
        // 后台回调
        payRequest.setNotifyUrl(appProperties.getAli().getNotifyUrl());
        Map<String, String> params = new TreeMap<>();
        params.put("out_trade_no", "订单号");
        // 订单金额:元
        params.put("total_amount", amount.toString());
        params.put("subject", "订单标题");
        // 实际收款账号,一般填写商户PID即可
        params.put("seller_id", appProperties.getAli().getMchId());
        // 电脑网站支付
        params.put("product_code", "FAST_INSTANT_TRADE_PAY");
        params.put("body", "两个橘子");
        payRequest.setBizContent(objectMapper.writeValueAsString(params));
        log.info("业务参数:" + payRequest.getBizContent());
        String result = CommonMessage.ERROR.getMessage();
        try {
            result = alipayClient.pageExecute(payRequest).getBody();
        } catch (AlipayApiException e) {
            log.error("ali pay error message:{}", e.getMessage());
        }
        return result;
    }

支付宝退款

/**
     * 支付宝退款
     * @param outTradeNo
     * @param tradeNo
     * @param amount
     * @param servletRequest
     * @return
     * @throws Exception
     */
    public Result aliRefund(String outTradeNo,String tradeNo,Integer amount, HttpServletRequest servletRequest) throws Exception {
        // 创建退款请求builder,设置请求参数
        AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
        Map<String, String> params = new TreeMap<>();
        // 必须 商户订单号
        params.put("out_trade_no", outTradeNo);
        // 必须 支付宝交易号
        params.put("trade_no", tradeNo);
        // 必须 退款金额
        params.put("refund_amount", amount.toString());
        // 可选 代表 退款的原因说明
        params.put("refund_reason", "退款的原因说明");
        // 可选 标识一次退款请求,同一笔交易多次退款需要保证唯一(就是out_request_no在2次退款一笔交易时,要不一样),如需部分退款,则此参数必传
        params.put("out_request_no", RandomUtil.randomNumbers(10));
        // 可选 代表 商户的门店编号
        params.put("store_id", "90m");
        request.setBizContent(objectMapper.writeValueAsString(params));
        AlipayTradeRefundResponse responseData = alipayClient.execute(request);
        if (responseData.isSuccess()) {
            log.info("ali refund success tradeNo:{}", "订单号");
            return Result.success(CommonMessage.SUCCESS);
        }
        log.info("ali refund failed tradeNo:{}", "订单号");
        return Result.error(CommonMessage.ALI_PAY_REFUND_FAILED);
    }

APP支付

/**
     * 支付宝App支付
     *
     * @param amount
     * @param servletRequest
     * @return
     */
    public String appPay(Integer amount, HttpServletRequest servletRequest) {
        AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
        // SDK已经封装掉了公共参数,这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
        AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
        model.setBody("购买手机");
        model.setSubject("iPhone 13 pro max");
        model.setOutTradeNo(RandomUtil.randomNumbers(10));
        model.setTimeoutExpress("30m");
        model.setTotalAmount(amount.toString());
        model.setProductCode("QUICK_MSECURITY_PAY");
        request.setBizModel(model);
        request.setNotifyUrl(appProperties.getAli().getNotifyUrl());
        try {
            // 这里和普通的接口调用不同,使用的是sdkExecute
            AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
            //就是orderString 可以直接给客户端请求,无需再做处理。
            log.info("orderString:{}", response.getBody());
            return response.getBody();
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        return null;
    }

支付宝回调地址

 /**
     * 支付回调通知
     *
     * @param request
     * @param response
     */
    public void aliNotify(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String requestXml = PaymentUtils.getRequestData(request);
        Map requestMap = PaymentUtils.xmlToMap(requestXml);
        Assert.notNull(requestMap, CommonMessage.XML_DATA_INCORRECTNESS.getMessage());
        // 当返回的return_code为SUCCESS则回调成功
        if (requestMap.get("code").equals(10000)) {
            log.info("notify success");
        } else {
            log.error("notify failed");
        }
    }

详细代码地址(由于appid为个人的,示例中已改为xxx,请替换自己的appid和公私钥)

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐