欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

微信、支付宝支付

程序员文章站 2022-07-13 17:07:09
...

前言

在实际开发过程中,订单的付款、打赏等功能,必然离不开用户的支付。如今最流行的支付方式:微信和支付宝现在已经非常成熟,而且都有自己独立的api去供开发者调用。话不多说,我们来看看如何将支付集成到我们的系统中去。

背景

公司有这样一个需求:在PC端,用户下单之后需要去进行扫码支付,像实际生活中买东西,选完商品之后需要扫商户的二维码进行支付,我们的系统也需要这样的业务。基于此背景,我们选取了蚂蚁金服的电脑网站支付和微信的统一下单两个应用

一、支付宝支付

1.官方文档

电脑网站支付

2.细节

引用支付主要是对其API进行调用,封装好参数,然后去进行参数的拼接,最后得到一个重要的参数:qr_code。拿到的这个qrcode需要对其进行生成二维码。
我用的是google的zxing去进行二维码的生成。(个人见解:也可以使用qrcode,日本开发的一个工具,但是那个对于移动端比较好,PC端还是建议用zxing)
Maven依赖:

        <dependency>
            <groupId>com.google.zxing</groupId>
            <artifactId>core</artifactId>
            <version>3.0.0</version>
        </dependency>
        <dependency>
            <groupId>com.google.zxing</groupId>
            <artifactId>javase</artifactId>
            <version>3.0.0</version>
       </dependency>

因为系统中所有的图片资源我都是放在阿里的oss下的。首先用BitMatrix对象生成一个输出流,然后再将这个输出流转化为OSS上传API需要的输入流,最后上传上去,生成一个链接,返回给前台。下面给出我生成二维码的方法:

public String generateQRcode(String qrCodeInfo) {
        //二维码颜色
        final int BLACK = 0xFF000000;
        //二维码颜色
        final int WHITE = 0xFFFFFFFF;
        final int width = 148;
        final int height = 148;
        String format = ".jpg";
        Hashtable hints = new Hashtable();
        hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
        hints.put(EncodeHintType.MARGIN, 2);
        try {
            BitMatrix bitMatrix = new MultiFormatWriter().encode(qrCodeInfo, BarcodeFormat.QR_CODE, width, height, hints);
            //2、获取二维码宽高
            int codeWidth = bitMatrix.getWidth();
            int codeHeight = bitMatrix.getHeight();
            //3、将二维码放入缓冲流
            BufferedImage image = new BufferedImage(codeWidth, codeHeight, BufferedImage.TYPE_INT_RGB);
            for (int i = 0; i < codeWidth; i++) {
                for (int j = 0; j < codeHeight; j++) {
                    //4、循环将二维码内容定入图片
                    image.setRGB(i, j, bitMatrix.get(i, j) ? BLACK : WHITE);
                }
            }
            // 创建一个输出流
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            //将图片写出到指定位置(复制图片)
            ImageIO.write(image, "jpg", os);
            // 创建输入流获取存放输出流信息
            // toByteArray(): 创建一个新分配的字节数组,数组的大小和当前输出流的大小,内容是当前输出流的拷贝。
            InputStream is = new ByteArrayInputStream(os.toByteArray());
            return this.upload(is, format);
        } catch (WriterException | IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }

public String upload(InputStream inputStream, String format) {
        ObjectMetadata meta = new ObjectMetadata();
        meta.setContentType("image/png");
        String firmwareId = String.valueOf(inputStream.hashCode()) + System.nanoTime() + format;
        ossClient.putObject(qrcodeBucketName, firmwareId, inputStream,meta);
        return firmwareId;
    }
3.回调

生成二维码链接了,用户付完款,肯定需要通知我们的系统去进行业务的修改(订单的状态、用户账单的操作等)。如何去进行通知呢?首先在支付宝的AlipayTradePrecreateRequest对象中需要设置一个属性notifyUrl,这个属性就是支付宝用来通知我们的系统用户完成支付的。

request.setNotifyUrl(alipayProperties.getNotifyUrl());

设置完这个属性之后,只要用户支付成功,支付宝就会调用我们的这个接口,然后我们拿到支付宝回调过来的参数,去进行业务的修改。
给出支付宝回调的接口

  @ApiOperation(notes = "支付宝支付完的成功回调",value = "支付宝支付完的成功回调")
    @PostMapping("/alipay")
    public void alipayNotify(){
        Map<String, String> params = convertRequestParamsToMap(httpServletRequest); // 将异步通知中收到的待验证所有参数都存放到map中
        String paramsJson = JSON.toJSONString(params);
        LOGGER.info("【支付宝支付】回调,{}", paramsJson);
        try {
            // 调用SDK验证签名
            boolean signVerified = AlipaySignature.rsaCheckV1(params, alipayProperties.getPublicKey(),
                    alipayProperties.getCharset(), alipayProperties.getSignType());
            if (signVerified) {
                LOGGER.info("支付宝回调签名认证成功");
                // 按照支付结果异步通知中的描述,对支付结果中的业务内容进行1\2\3\4二次校验,校验成功后在response中返回success,校验失败返回failure
                this.check(params,order);
                Integer payType = 2;
                if (HzyConstant.ALIPAY_SUCCESS.equals(params.get("trade_status"))){
                    payOrderfinish(params, order,payType);
                }
            } else {
                LOGGER.info("支付宝回调签名认证失败,signVerified=false, paramsJson:{}", paramsJson);
            }
        } catch (AlipayApiException e) {
            LOGGER.error("支付宝回调签名认证失败,paramsJson:{},errorMsg:{}", paramsJson, e.getMessage());
        }

    }

我对支付宝返回的参数进行了一个二次封装,下面列出工具类以及对应的实体类。
支付宝回调后对应的实体类

import java.math.BigDecimal;
import java.util.Date;

/**
 * @Author Tinner
 * @create 2019/6/12 18:44
 */
public class AlipayNotifyParam {
    private String appId;
    private String tradeNo; // 支付宝交易凭证号
    private String outTradeNo; // 原支付请求的商户订单号
    private String outBizNo; // 商户业务ID,主要是退款通知中返回退款申请的流水号
    private String buyerId; // 买家支付宝账号对应的支付宝唯一用户号。以2088开头的纯16位数字
    private String buyerLogonId; // 买家支付宝账号
    private String sellerId; // 卖家支付宝用户号
    private String sellerEmail; // 卖家支付宝账号
    private String tradeStatus; // 交易目前所处的状态,见交易状态说明
    private BigDecimal totalAmount; // 本次交易支付的订单金额
    private BigDecimal receiptAmount; // 商家在交易中实际收到的款项
    private BigDecimal buyerPayAmount; // 用户在交易中支付的金额
    private BigDecimal refundFee; // 退款通知中,返回总退款金额,单位为元,支持两位小数
    private String subject; // 商品的标题/交易标题/订单标题/订单关键字等
    private String body; // 该订单的备注、描述、明细等。对应请求时的body参数,原样通知回来
    private Date gmtCreate; // 该笔交易创建的时间。格式为yyyy-MM-dd HH:mm:ss
    private Date gmtPayment; // 该笔交易的买家付款时间。格式为yyyy-MM-dd HH:mm:ss
    private Date gmtRefund; // 该笔交易的退款时间。格式为yyyy-MM-dd HH:mm:ss.S
    private Date gmtClose; // 该笔交易结束时间。格式为yyyy-MM-dd HH:mm:ss
    private String fundBillList; // 支付成功的各个渠道金额信息,array
    private String passbackParams; // 公共回传参数,如果请求时传递了该参数,则返回给商户时会在异步通知时将该参数原样返回。

    //get  set方法   你们去自己生成吧~
}

将map转化为实体类的工具类(用到了阿里的JSON)

 private AlipayNotifyParam buildAlipayNotifyParam(Map<String, String> params) {
        String json = JSON.toJSONString(params);
        return JSON.parseObject(json, AlipayNotifyParam.class);
    }

二、微信支付

引用一篇文章吧~里面介绍的肯定比我详细
微信统一下单API
微信回调的API:
微信支付成功回调