前言 

        假如想通过手机扫码把钱转入银行账号,除了直接跟银行做接口。可以选择第三方支付平台,常见的有微信、支付宝、银联等,他们都跟各个银行做好了接口,通过平台接口对接就不用考虑各家银行接口。当然,带来了技术简便,额外要付出手续费。

        还有一种支付平台,他们整合了第三方支付平台,调用一个接口,可以实现微信、支付宝、银联等,实现手机扫码支付把钱转账到指定银行账号。商联通付就是其中一个,我们现在详细讨论下,这些接口如何实现。

 接口实现思路

假如我们去买东西,一般做以下操作步骤:
1、弹出支付二维码
2、手机扫二维码支付
3、手机接收支付结果信息

作为程序员,可能就需要多考虑几步,先通过泳道图,看下系统与平台之间的联系:

java通联支付对接分账 通联支付接口_开发语言

备注:

1、服务/pc端指的是业务系统,实际就是业务系统与平台做个接口,需要手机端扫码支付

2、回调地址是由服务(业务系统)提供,由平台接收到手机支付后,异步回调(异步同步主要由平台决定)

3、支付地址,其实就是手机端支付页面。为了提供手机扫码支付,就需要把支付地址转为二维码,供手机扫码。

技术实现,主要解决两个问题

1、回调地址,需要跳过权限限制(账号、密码)检测

2、返回支付地址,需要转为二维码图片,就需要转为图片地址

具体代码如下:


1、异步回调地址,需要跳过用户检测,spring mvc 配置代码如下:


/**
 * spring mvc 的框架配置
 */
@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {

    @Autowired private WebsiteTokenInterceptor websiteTokenInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {

        // 回调地址:Constants.URL_PREFIX + "/exam_pay/callback"
        registry.addInterceptor(websiteTokenInterceptor)
                .addPathPatterns("/**")
                .excludePathPatterns(
                        Constants.URL_PREFIX + "/exam_pay/callback",
                );
    }

}

2、支付地址转为二维码的代码实现:

/**
     * 根据回调地址生成二维码(返回base64图片地址)
     */
    public String getPayQrcode(String receiveUrl) {
        if (Strings.isNullOrEmpty(receiveUrl))
            BusinessException.throwConstraintException("无法完成操作,没有返回回调地址,无法生成二维码");

        try {
            log.debug("公开招聘缴费,返回二维码地址 = {}", receiveUrl);

            byte[] qrCode = getBase64QRCode(receiveUrl, RenderQrCodeOptions.DEFAULT);
            String qrCodeString = Encodes.encodeBase64(qrCode);

            return "data:image/png;base64,".concat(qrCodeString);
        } catch (WriterException e) {
            log.warn("二维码生成失败:{}/{}", e.getClass(), e.getLocalizedMessage());
            BusinessException.throwConstraintException("无法完成操作,二维码生成失败");
        }

        return null;
    }


    /**
     * 生成Base64的二维码
     */
    public static byte[] getBase64QRCode(String content, RenderQrCodeOptions options) throws WriterException {
        MultiFormatWriter multiFormatWriter = new MultiFormatWriter();

        Map<EncodeHintType, Object> hints = new HashMap<>();
        //设置二维码四周白色区域的大小
        hints.put(EncodeHintType.MARGIN, options.getMargin());
        //设置二维码的容错性
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.values()[options.getCorrectionLevel()]);
        //画二维码
        BitMatrix bitMatrix = multiFormatWriter.encode(content, BarcodeFormat.QR_CODE, options.getWidth(), options.getHeight(), hints);
        BufferedImage image = toBufferedImage(bitMatrix);
        //注意此处拿到字节数据
        return imageToBytes(image, FORMAT_NAME);
    }

    /**
     * BufferedImage转Bytes
     */
    private static byte[] imageToBytes(BufferedImage image, String format) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        try {
            ImageIO.write(image, format, out);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return out.toByteArray();
    }