相信技术的力量

Java服务端集成支付宝支付SDK

文档

蚂蚁金服官方文档

https://docs.open.alipay.com/54/103419/

https://docs.open.alipay.com/291/105974

秘钥生成

https://docs.open.alipay.com/291/105971/

验签

https://docs.open.alipay.com/200/106120

流程说明

参考
http://www.crocutax.com/blog/application-process-records-of-alipay

应用公钥上传支付宝,生成支付宝公钥,上传后,官方弹窗提示:应用公钥(SHA256withRsa)已经上传成功,请查看支付宝公钥

支付宝公钥用于发起支付及验签

添加依赖

Maven依赖地址

https://search.maven.org/search?q=g:com.alipay.sdk%20AND%20a:alipay-sdk-java&core=gav

最新Maven

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

集成步骤

1.准备参数

   //----------------------------支付宝账号--------------------------------
private static final String ALI_APP_ID = "2018102561798725";

//应用私钥
private static final String APPLICATION_PRIVATE_KEY = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCK5cB6lDMhQvZar902GE70iXZhXNXR0+Ep9LC4UQqQhy0pQfNFcj/aBtPfAl7m/7txoKsqewy8jAt60hyh+pD/rQXo1WWbDlXa24wdVNr2zJQTVvD7pFwzdwtDLxXFZDjMngU00lc0na1XwM+02Fmb94OCa7/CWHuFze2S79kCBNLrnfKaOucu2l6OYdxhPPp2u+czwBg0Gq/gwhP6MXh0TlKwSAYk93NLONMvindUzSudi499YVQGQ1D3Ke1FFSeZ4VCcfiZLDVKjBkNaItECtnbBNSGoJbY9OWjvQCOPI/dLIiIYXV+x1gZPTCj44MenxBKyUx4XIjpGb+cZXsDnAgMBAAECggEBAIh3b4N/9DRr3CwBufAaNgjgviSu143PBNz6Al81kJGrnl145JGIzN9j8eqcI64F+J6NY17bgwoE9op3wZYL30a1MqcucyPDE+tx5dozsubk3V+a/i3fsI8IGVKrAlLsQzoWz7q0JuYVPWiIkgp2vqQUrWsIfmFuGf6+8vp5GNd3fNVIDi5EFRgR5bvWGNEJBLpChjKHNxcnb8BO+rv226H1S79OyNCcjT1+bMz5kiFU1EY+RKhIGYrudQDbRpLhaX7MKV/1lMLvNr/2XEiUBI/dSgCG/t+LHl3HP8nTJhmf6X/f5uTpIONdOBU04p0ndSsGw6BGtKD5CUPmSod/v8ECgYEA07XJB58blFdhqsggcUziVDhOpgOluYdadMJ7Ux/CIyA8ezpAhFTTT6hPanAKWC7pazd8O/Hiles4bWLD3aaIk5nVHGM5Wn8P9uTLwpQtW1Rr7Ik0ufr54iM+kLwMfyzO+Uzpu/bJx2u/wNbNDJO8NH99g+LJyfU42kA6zkjJolcCgYEAp/R1Ydjp7G7hgR/IXIH9m/s1F0+V5AE97u11fQXYEJFxqLAKq9rzKIS4l+1Mxi66W31CpFy6omPxOsdwQ95J7UFlE+ZzGFYbrcpXnt/Esj+K6olbmohKvpbH6J2dEGMKJdK8Vfx9jc696HWzoa/KrGK6Sj2Ja6N1o7AsZ3joW/ECgYB8F5uj2gECbE2VGwTZJGWtU+vVp2GmY84DjlNXH9BdYnHREQ3sAwRxNoiGLPIDSkwLSlSJlnhnw54pj7Ca5Rg82/hsUUS25K9o2icNAGmtlMhFtw6uzItXn6z2jSMOECepPQnr4PXY7DFTSRSbgKTaaLgba/03YYNXejp923BEtQKBgQCcVoVdS1iT6LKoSzlqQuYbZ76HsGFKF43a9dbDRclVws0VxKhqSCjHsqNRaGZqo9x8hSCfdmGT/4vwtuzdf/E4lALOf1jrclvZbdwZ2xlxAo0AvFM0iWFp/1ieQviM5GPxyTPepmUIt0U3OTi4bLYvuMbHjHh6ZXF/qOHsfzNrQQKBgG/KS3/uBblZpNQy81Q+lOORZO+TiZjd+WM/u8sk/Rtr0nX6CxkcEU+UVULYff3Xf/Qki6un8IU4GI6yexz1ioXgBRA7AaMnVNihmCGNFjP2g958oBortrMqdwCsX/2p1cZG6onPWyqB27YzU7uYapzvltT+jQLzWfu0V2/JcBCi";

//应用公钥 (上传支付宝后得到 [支付宝公钥] , 项目里用不上这个,代码里只使用支付宝公钥)
public static final String  APPLICATION_PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAiuXAepQzIUL2Wq/dNhhO9Il2YVzV0dPhKfSwuFEKkIctKUHzRXI/2gbT3wJe5v+7caCrKnsMvIwLetIcofqQ/60F6NVlmw5V2tuMHVTa9syUE1bw+6RcM3cLQy8VxWQ4zJ4FNNJXNJ2tV8DPtNhZm/eDgmu/wlh7hc3tku/ZAgTS653ymjrnLtpejmHcYTz6drvnM8AYNBqv4MIT+jF4dE5SsEgGJPdzSzjTL4p3VM0rnYuPfWFUBkNQ9yntRRUnmeFQnH4mSw1SowZDWiLRArZ2wTUhqCW2PTlo70AjjyP3SyIiGF1fsdYGT0wo+ODHp8QSslMeFyI6Rm/nGV7A5wIDAQAB";

//支付宝公钥
public static final String  ALI_PAY_PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2k9K23V7rZeGNdqFmN/DajW8E9jyNafRzdDkA/pBAygyppUv13U7canYMc68OKCNEG1cyoPi7DNIHDM8mOPwPDVN9TgH4QuP0VFJRNwgJYrE59wZCSeoCd8DJXYnNJt5K0+zkqwFUbiIOhN7ZnBwmEO+lgxeECxQ42mp+hLp7R5ztZBTcNVRHRTfpN9PN8FF9d7/VWaU7IX9wygc+LPUi8tA3L4fOJPhRqG+fsXmGUoiz/JTWmi4+TGymesYPZ/NF7whv28abt2Y62EWRrKtLnjcOclN52N47ln7JYgNb4J8L7L9j3RZik0rzM5+Fd8VM0sOT0oggctl0xcS3cBBEQIDAQAB";

private static final String CALLBACK_URL_ALI = "http://47.99.172.109:8080/anbao/order/alipaySuccessCallBack";

2.发起支付

//实例化客户端
AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", APP_ID, APP_PRIVATE_KEY, "json", CHARSET, ALIPAY_PUBLIC_KEY, "RSA2");
//实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay
AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
//SDK已经封装掉了公共参数,这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
model.setBody("我是测试数据");
model.setSubject("App支付测试Java");
model.setOutTradeNo(outtradeno);
model.setTimeoutExpress("30m");
model.setTotalAmount("0.01");
model.setProductCode("QUICK_MSECURITY_PAY");
request.setBizModel(model);
request.setNotifyUrl("商户外网可以访问的异步地址");
try {
        //这里和普通的接口调用不同,使用的是sdkExecute
        AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
        System.out.println(response.getBody());//就是orderString 可以直接给客户端请求,无需再做处理。
    } catch (AlipayApiException e) {
        e.printStackTrace();
}

3.验签

@PostMapping("/alipaySuccessCallBack")
@Transactional
public void alipaySuccessCallBack(HttpServletRequest request, HttpServletResponse response) throws AlipayApiException {
    logger.info("支付宝成功回调了");
    //将异步通知中收到的所有参数都存放到map中  通过request.getParameterMap()获取
    Map<String, String> paramsMap = new HashMap<>();
    Map requestParams = request.getParameterMap();

    for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
        String name = (String) iter.next();
        String[] values = (String[]) requestParams.get(name);
        String valueStr = "";
        for (int i = 0; i < values.length; i++) {
            valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
        }
        //乱码解决,这段代码在出现乱码时使用。
        //valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
        paramsMap.put(name, valueStr);
    }
    //调用SDK验证签名,记alipaypublickey是支付宝的公钥,请去open.alipay.com对应应用下查看。
    //boolean AlipaySignature.rsaCheckV1(Map<String, String> params, String publicKey, String charset, String sign_type)
    boolean signVerified = AlipaySignature.rsaCheckV1(paramsMap, OrderManagerImpl.ALI_PAY_PUBLIC_KEY, "utf-8", "RSA2");
    if (signVerified) {
        String orderno = paramsMap.get("out_trade_no");
        PayOrder payOrder = baseRepository.getObjById(PayOrder.class,orderno);
        payOrder.setEnumStatus(OrderStatus.PAYED.getValue());
        logger.info("支付宝支付成功:"+payOrder.toString());
        baseRepository.updateObj(payOrder);
    }else {
        logger.info("支付宝成功回调验签失败");
    }
}

常见问题

支付宝里两个应用,比如一个 [XXX],一个 [应用2.0签约],用哪个?

用前者

algid parse error, not a sequence

验签工具生成的文件有三个

  • rsa_private_key_pkcs8.pem
  • rsa_private_key.pem
  • rsa_public_key.pem

    私钥使用第一个pkcs8格式的编码即可

验签失败

  1. 支付宝公钥使用错误导致
  2. 验签方法使用错误
  3. 参数错误导致,例如乱码,带自定义参数,编码格式

1.可以使用官方的验签方式进行验签测试,或者更换公私钥试试;最好用windows的签名生成工具

2.RSA2加密,验签需要使用如下方法

boolean signVerified = AlipaySignature.rsaCheckV1(params, AlipayConfig.ALIPAY_PUBLIC_KEY, "UTF-8",AlipayConfig.SIGN_TYPE);

支付成功,但是收不到回调. ☆☆☆

支付宝回调,以any方式定义路由.get方式无法收到回调

⬆️