支付宝企业转账到支付宝账户

发布时间 2023-09-08 17:04:51作者: 天葬

准备工作

  1. 注册企业支付宝,企业认证
  2. 产品中心(支付宝商家平台)->签约转账到支付宝账户
  3. 创建应用(支付宝开放平台)默认签约会有一个应用

相关网站

注意事项

  • 创建的支付宝应用需要绑定对应的产品才可以使用
  • 应用需要上线审核通过接口才可以调用
  • 接口加签方式必须使用证书方式
  • 转账需要账号和实名认证姓名一致

代码示例

阿里SDK

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

单例模式工具类

本示例所有证书都放在resource/certs目录下载加载,方便迁移,如果放在其他路径,项目迁移每次都需手动上传服务器。

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.AlipayConfig;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayFundTransUniTransferModel;
import com.alipay.api.domain.Participant;
import com.alipay.api.internal.util.file.FileUtils;
import com.alipay.api.request.AlipayFundTransUniTransferRequest;
import com.alipay.api.response.AlipayFundTransUniTransferResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ClassPathResource;

import java.io.*;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;

/**
 * @description:
 * @author: Mr.Fang
 * @create: 2023-9-8 
 **/
@Slf4j
public class AlipayUtil {

    private String URL = "https://openapi.alipay.com/gateway.do";
    private String APPID = "应用APPID";
    private String app_private_key = "certs/appPrivate.txt";
    private String CHARSET = "UTF8";
    private String FORMAT = "json";
    private String SIGN_TYPE = "RSA2";
    private String app_cert_path = "certs/appCertPublicKey.crt";
    private String alipay_cert_path = "certs/alipayCertPublicKey_RSA2.crt";
    private String alipay_root_cert_path = "certs/alipayRootCert.crt";
    private AlipayConfig alipayConfig;
    private static AlipayUtil instance;

    // 无惨构造,默认加载支付宝配置信息
    private AlipayUtil() throws IOException {
        alipayConfig = new AlipayConfig();
        //设置网关地址
        alipayConfig.setServerUrl(URL);
        //设置应用ID
        alipayConfig.setAppId(APPID);
        //设置应用私钥
        alipayConfig.setPrivateKey(readToString(new ClassPathResource(app_private_key).getInputStream()));

        //设置请求格式,固定值json
        alipayConfig.setFormat(FORMAT);
        //设置字符集
        alipayConfig.setCharset(CHARSET);
        //设置签名类型
        alipayConfig.setSignType(SIGN_TYPE);
        //设置应用公钥证书路径
        alipayConfig.setAppCertContent(readToString(new ClassPathResource(app_cert_path).getInputStream()));
        //设置支付宝公钥证书路径
        alipayConfig.setAlipayPublicCertContent(readToString(new ClassPathResource(alipay_cert_path).getInputStream()));
        //设置支付宝根证书路径
        alipayConfig.setRootCertContent(readToString(new ClassPathResource(alipay_root_cert_path).getInputStream()));
    }

    /**
     * 读取 resource 文件
     *
     * @param inputStream
     * @return
     */
    private String readToString(InputStream inputStream) {
        try {
            DataInputStream dataInputStream = new DataInputStream(inputStream);
            ByteArrayOutputStream output = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int length;
            while ((length = dataInputStream.read(buffer)) > 0) {
                output.write(buffer, 0, length);
            }
            return output.toString();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static AlipayUtil getInstance() throws IOException {
        if (instance == null) {
            synchronized (AlipayUtil.class) {
                if (instance == null) {
                    instance = new AlipayUtil();
                }
            }
        }
        return instance;
    }

    /**
     * description: 支付宝企业转账到个人
     * create by: Mr.Fang
     *
     * @param bizNo    订单编号
     * @param amount   金额
     * @param title    转账说明
     * @param identity 支付宝手机号或邮箱
     * @param name     支付宝真实姓名
     * @return: Result<java.lang.String>
     * @date: 2023/9/8 
     */
    public Result<String> transfer(String bizNo, String amount, String title, String identity, String name) throws AlipayApiException {
        AlipayClient alipayClient = new DefaultAlipayClient(alipayConfig);
        AlipayFundTransUniTransferRequest request = new AlipayFundTransUniTransferRequest();
        AlipayFundTransUniTransferModel model = new AlipayFundTransUniTransferModel();

        model.setOutBizNo(bizNo); // 订单编号
        model.setTransAmount(amount); // 金额
        model.setBizScene("DIRECT_TRANSFER");
        model.setProductCode("TRANS_ACCOUNT_NO_PWD");
        model.setOrderTitle(title); // 订单标题

        Participant payeeInfo = new Participant();
        payeeInfo.setIdentity(identity); // 用户支付宝账户
        payeeInfo.setIdentityType("ALIPAY_LOGON_ID"); // 固定值
        payeeInfo.setName(name); // 用户真实姓名

        model.setPayeeInfo(payeeInfo);
        request.setBizModel(model);
        AlipayFundTransUniTransferResponse response = alipayClient.certificateExecute(request);
        log.info("转账响应结果:{}", response.getBody());
        if (response.isSuccess()) {
            return Result.OK("转账成功", response.getBody());
        }
        return Result.error("转账失败", response.getBody());
    }
}

resource目录扩展

  • springboot 打包jar文件后通过ClassPathResource 对象可以获取到文件,但是文件路径是无法使用的。
  • 阿里提供的AlipayConfig 对象支持配置证书相关参数有两种方式:第一种证书内容,第二种文件路径。
  • 通过ClassPathResource 拿到文件对象,readToString方法读取文件内容配置证书内容信息。

AlipayConfig 部分代码

public void setRootCertPath(String rootCertPath) {
    this.rootCertPath = rootCertPath;
}
……………………省略
public void setRootCertContent(String rootCertContent) {
    this.rootCertContent = rootCertContent;
}