支付宝沙箱支付AlipayEasy

1. 备注

Alipay Easy SDK 简化了服务端调用方式,减少支付的开发流程,对于不以交易为重点的项目是非常合适的。
以下只是简单的调用示例,说明多在代码注释中,更多方法如验签、AES加密、退款、对账等可以查看官方文档了解。
GitHub地址 :https://github.com/alipay/alipay-easysdk/tree/master/java

2. 添加maven依赖

<!-- 支付宝支付(必须)-->
<dependency>
    <groupId>com.alipay.sdk</groupId>
    <artifactId>alipay-easysdk</artifactId>
    <version>2.2.3</version>
</dependency>

<!-- JSON解析器(非必须)-->
<dependency>
    <groupId>com.alibaba.fastjson2</groupId>
    <artifactId>fastjson2</artifactId>
</dependency>

<!-- ZXing二维码(非必须)-->
<dependency>
    <groupId>com.google.zxing</groupId>
    <artifactId>core</artifactId>
    <version>3.4.1</version>
</dependency>
<dependency>
    <groupId>com.google.zxing</groupId>
    <artifactId>javase</artifactId>
    <version>3.4.1</version>
</dependency>

3. 调用支付方法获得付款二维码

/**
 * 支付宝付款
 */
@PostMapping("/alipay")
public R alipay(@RequestBody HashMap<String, Object> map) {
    //设置参数
    Factory.setOptions(getOptions());
    try {
        //商家订单号
        String outTradeNo = IdUtils.fastSimpleUUID();
        //支付金额
        double totalMoney = 99.99;
        //商品名称
        String subject = "千里香混沌";
        //发起API调用(以创建当面付收款二维码为例)
        AlipayTradePrecreateResponse response = Factory.Payment.FaceToFace()
        		//.asyncNotify("https://www.test.com/callback")//如在此处设置异步通知地址,其优先级高于全局Config中配置的地址
                .preCreate(subject, outTradeNo, String.valueOf(totalMoney));

        /*
        //当SDK的API声明中的参数不满足个性化需求时,可按如下方式追加可选业务参数:
        //第一种
        List<Object> goodsDetailList = new ArrayList<>();
        Map<String, Object> goodsDetail = new HashMap<>();
        goodsDetail.put("goods_id", "apple-01");
        goodsDetail.put("goods_name", "Apple iPhone11 128G");
        goodsDetail.put("quantity", 1);
        goodsDetail.put("price", "5799.00");
        goodsDetailList.add(goodsDetail);
        AlipayTradePrecreateResponse response = Factory.Payment.FaceToFace()
                // 调用optional扩展方法,完成可选业务参数(biz_content下的可选字段)的设置
                .optional("seller_id", "2088******225135")
                .optional("discountable_amount", "8.88")
                .optional("goods_detail", goodsDetailList)
                .preCreate("Apple iPhone11 128G", "2234567890", "5799.00");
        //第二种
        Map<String, Object> optionalArgs = new HashMap<>();
        optionalArgs.put("seller_id", "2088******225135");
        optionalArgs.put("discountable_amount", "8.88");
        optionalArgs.put("goods_detail", goodsDetailList);
        AlipayTradePrecreateResponse response = Factory.Payment.FaceToFace()
                // 也可以调用batchOptional扩展方法,批量设置可选业务参数(biz_content下的可选字段)
                .batchOptional(optionalArgs)
                .preCreate("Apple iPhone11 128G", "2234567890", "5799.00");
        */

        //处理响应或异常
        if (ResponseChecker.success(response)) {
            log.info("支付宝付款调用成功");
            //支付二维码链接
            String qrCode = response.getQrCode();
            //二维码链接转图片base64
            String qrBase64 = QRCodeGenerator.qrToBase64(qrCode);
            //一些自定义的订单保存操作
            //map.put("outTradeNo", outTradeNo);
            //map.put("totalMoney", totalMoney);
            //map.put("subject", subject);
            //service.insertPayRecord(map);
            //返回数据
            return R.ok(qrBase64);
        } else {
            log.info("支付宝付款调用失败,原因:" + response.msg + "," + response.subMsg);
            throw new ServiceException("网络异常!");
        }
    } catch (Exception e) {
        log.info("支付宝付款调用失败,原因:" + e.getMessage());
        throw new ServiceException("网络异常!");
    }
}

//这些参数可配置在yaml中,这里以公钥模式为例,也可改为证书模式
private Config getOptions() {
    Config config = new Config();
    config.protocol = "https";//协议
    config.gatewayHost = gatewayHost;//支付宝网关,沙箱环境为:openapi-sandbox.dl.alipaydev.com
    config.signType = "RSA2";//签名方式
    config.appId = appId;//应用id
    config.merchantPrivateKey = merchantPrivateKey;//应用私钥
    config.alipayPublicKey = alipayPublicKey;//支付宝公钥(公钥模式必填)
    //config.merchantCertPath = "/foo/appCertPublicKey_2019051064521003.crt";//应用公钥证书文件路径(证书模式必填)
    //config.alipayCertPath = "/foo/alipayCertPublicKey_RSA2.crt";//支付宝公钥证书文件路径(证书模式必填)
    //config.alipayRootCertPath = "/foo/alipayRootCert.crt";//支付宝根证书文件路径(证书模式必填)
    config.notifyUrl = notifyUrl;//回调地址
    //config.encryptKey = "aa4BtZ4tspm2wnXLb1ThQA==";//AES密钥,调用AES加解密相关接口时需要(可选)
    return config;
}

4. 接收支付结果异步回调

/**
 * 支付结果异步回调
 */
@CrossOrigin
@RequestMapping("/callback")
public void callback(HttpServletRequest request) throws Exception {
    try {
        Map<String, String> params = getRequestParam(request);
        if (!Factory.Payment.Common().verifyNotify(params)) {
            log.info("支付结果校验失败");
        }
        String outTradeNo = params.get("out_trade_no");
        String tradeStatus = params.get("trade_status");
        if (tradeStatus .equals("TRADE_SUCCESS")) {
            log.info("支付成功,订单号:" + outTradeNo );
            //更新保存的订单信息
            //updatePayRecord1(params, outTradeNo );
        } else {
            log.info("支付失败,订单号:" + outTradeNo );
            //更新保存的订单信息
            //updatePayRecord2(params, outTradeNo );
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

//处理得到的参数
private Map<String, String> getRequestParam(final HttpServletRequest request) {
    Map<String, String> res = new HashMap<>();
    Enumeration<?> temp = request.getParameterNames();
    while (temp.hasMoreElements()) {
        String en = (String) temp.nextElement();
        String value = request.getParameter(en);
        res.put(en, value);
    }
    return res;
}

5. 查询支付状态

/**
 * 付款状态同步查询
 * 当需要即时了解支付状态时可调用此接口,如扫码未付款、支付成功、支付失败
 * 可使用定时器轮询或改造为webscoket
 */
@GetMapping("/payStatus/{outTradeNo}")
public R payStatus(@PathVariable String outTradeNo ) {
    AlipayTradeQueryResponse query = null;
    try {
        Factory.setOptions(getOptions());
        query = Factory.Payment.Common().query(outTradeNo );
    } catch (Exception e) {
        e.printStackTrace();
    }
    String httpBody = query.getHttpBody();
    JSONObject jsonObject = JSONObject.parseObject(httpBody);
    JSONObject query_response = jsonObject.getJSONObject("alipay_trade_query_response");
    String trade_status = query_response.getString("trade_status");
    if (StringUtils.isBlank(trade_status)) {
        trade_status = "NO_SCAN_CODE";
    }
    return R.ok(trade_status);
}

6. 二维码工具类

import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import javax.imageio.ImageIO;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

public class QRCodeGenerator {
	//二维码链接转图片base64
    public static String qrToBase64(String qrStr) {
        int width = 300; // 二维码图像宽度
        int height = 300; // 二维码图像高度
        String format = "png"; // 二维码图像格式
        // 设置二维码参数
        Map<EncodeHintType, Object> hints = new HashMap<>();
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
        BitMatrix bitMatrix;
        try {
            bitMatrix = new MultiFormatWriter().encode(qrStr, BarcodeFormat.QR_CODE, width, height, hints);
        } catch (WriterException e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
        // 将BitMatrix转换为BufferedImage
        BufferedImage image = MatrixToImageWriter.toBufferedImage(bitMatrix);
        // 将BufferedImage转换为Base64编码的字符串
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try {
            ImageIO.write(image, format, baos);
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
        byte[] imageBytes = baos.toByteArray();
        return Base64.getEncoder().encodeToString(imageBytes);
    }
}

7. 获得应用id和密钥

支付宝开放平台:https://open.alipay.com/develop/sandbox/app
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值