alipay 证书 java_Java 支付宝使用公钥证书加签 进行支付-查询-退款-转账

本文主要是介绍alipay 证书 java_Java 支付宝使用公钥证书加签 进行支付-查询-退款-转账,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1、引入相关依赖 pom.xml

com.alipay.sdk

alipay-sdk-java

4.9.79.ALL

commons-configuration

commons-configuration

1.10

com.google.zxing

core

3.2.1

2、配置文件 application.yml

[注意]  证书文件必须放到服务器上,放到项目里的证书,在win环境下可以根据路径找到,但打成jar包后就找不到项目里的证书文件了,解决办法是判断服务器环境,根据不同环境拼接证书路径

证书文件目录结构如下,在Linux服务器上部署时,将pay文件夹和jar包放到同一个文件夹下

0e0037ba3160ae6f29cd1af5dc610de9.png

# 支付

pay:

alipay:

gatewayUrl: https://openapi.alipay.com/gateway.do

appid: *****

appPrivateKey:

alipayPublicKey:

appCertPath: /pay/alipay/cert/appCertPublicKey****.crt

alipayCertPath: /pay/alipay/cert/alipayCertPublicKey_RSA2.crt

alipayRootCertPath: /pay/alipay/cert/alipayRootCert.crt

returnUrl: ****

notifyUrl: ****

3、读取配置文件

import lombok.Data;

import lombok.extern.slf4j.Slf4j;

import org.springframework.boot.context.properties.ConfigurationProperties;

import javax.annotation.PostConstruct;

@Data

@Slf4j

@ConfigurationProperties(prefix = "pay.alipay")

public class AlipayProperties {

/**

* 支付宝gatewayUrl

*/

private String gatewayUrl;

/**

* 商户应用id

*/

private String appid;

/**

* RSA私钥,用于对商户请求报文加签

*/

private String appPrivateKey;

/**

* 支付宝RSA公钥,用于验签支付宝应答

*/

private String alipayPublicKey;

/**

* 签名类型

*/

private String signType = "RSA2";

/**

* 格式

*/

private String formate = "json";

/**

* 编码

*/

private String charset = "UTF-8";

/**

* 同步地址

*/

private String returnUrl;

/**

* 异步地址

*/

private String notifyUrl;

/**

* 应用公钥证书

*/

private String appCertPath;

/**

* 支付宝公钥证书

*/

private String alipayCertPath;

/**

* 支付宝根证书

*/

private String alipayRootCertPath;

/**

* 最大查询次数

*/

private static int maxQueryRetry = 5;

/**

* 查询间隔(毫秒)

*/

private static long queryDuration = 5000;

/**

* 最大撤销次数

*/

private static int maxCancelRetry = 3;

/**

* 撤销间隔(毫秒)

*/

private static long cancelDuration = 3000;

private AlipayProperties() {

}

/**

* PostContruct是spring框架的注解,在方法上加该注解会在项目启动的时候执行该方法,也可以理解为在spring容器初始化的时候执行该方法。

*/

@PostConstruct

public void init() {

log.info(description());

}

public String description() {

StringBuilder sb = new StringBuilder("\n支付宝Configs{");

sb.append("支付宝网关: ").append(gatewayUrl).append("\n");

sb.append(", appid: ").append(appid).append("\n");

sb.append(", 商户RSA私钥: ").append(getKeyDescription(appPrivateKey)).append("\n");

sb.append(", 应用公钥证书: ").append(appCertPath).append("\n");

sb.append(", 支付宝公钥证书: ").append(alipayCertPath).append("\n");

sb.append(", 支付宝根证书: ").append(alipayRootCertPath).append("\n");

sb.append(", 支付宝RSA公钥: ").append(getKeyDescription(alipayPublicKey)).append("\n");

sb.append(", 签名类型: ").append(signType).append("\n");

sb.append(", 查询重试次数: ").append(maxQueryRetry).append("\n");

sb.append(", 查询间隔(毫秒): ").append(queryDuration).append("\n");

sb.append(", 撤销尝试次数: ").append(maxCancelRetry).append("\n");

sb.append(", 撤销重试间隔(毫秒): ").append(cancelDuration).append("\n");

sb.append("}");

return sb.toString();

}

private String getKeyDescription(String key) {

int showLength = 6;

if (StringUtils.isNotEmpty(key) && key.length() > showLength) {

return new StringBuilder(key.substring(0, showLength)).append("******")

.append(key.substring(key.length() - showLength)).toString();

}

return null;

}

}

4、在启动时初始化支付宝客户端

import com.alipay.api.AlipayApiException;

import com.alipay.api.CertAlipayRequest;

import com.alipay.api.DefaultAlipayClient;

import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.boot.context.properties.EnableConfigurationProperties;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.util.ResourceUtils;

import java.io.IOException;

@Configuration

@Slf4j

@EnableConfigurationProperties(AlipayProperties.class)

public class AlipayConfiguration {

@Autowired

private AlipayProperties properties;

// /**

// * 支付宝接口加签模式为公钥时使用

// *

// * @return

// */

// @Bean

// public AlipayClient alipayClient() {

// return new DefaultAlipayClient(properties.getGatewayUrl(),

// properties.getAppid(),

// properties.getAppPrivateKey(),

// properties.getFormate(),

// properties.getCharset(),

// properties.getAlipayPublicKey(),

// properties.getSignType());

// }

/**

* 支付宝接口加签模式为公钥证书时使用

*

* @return

*/

@Bean

public DefaultAlipayClient alipayClient() throws AlipayApiException, IOException {

log.info("---------创建支付宝客户端--------");

//判断系统环境

String osName = System.getProperty("os.name");

log.info("-------系统环境--------" + osName);

String serverpath = null;

if (osName.startsWith("Windows")) {

// windows

serverpath = ResourceUtils.getURL("classpath:").getPath();

serverpath += "static/app";

log.info("-------------win文件路径----------" + serverpath);

// } else if (osName.startsWith("Mac OS")) {

// // 苹果

} else {

// unix or linux

serverpath = System.getProperty("user.dir");

log.info("-------------unix or linux文件路径----------" + serverpath);

}

CertAlipayRequest certAlipayRequest = new CertAlipayRequest();

certAlipayRequest.setServerUrl(properties.getGatewayUrl());

certAlipayRequest.setAppId(properties.getAppid());

certAlipayRequest.setFormat(properties.getFormate());

certAlipayRequest.setPrivateKey(properties.getAppPrivateKey());

certAlipayRequest.setCharset(properties.getCharset());

certAlipayRequest.setSignType(properties.getSignType());

certAlipayRequest.setCertPath(serverpath + properties.getAppCertPath());

certAlipayRequest.setAlipayPublicCertPath(serverpath + properties.getAlipayCertPath());

certAlipayRequest.setRootCertPath(serverpath + properties.getAlipayRootCertPath());

return new DefaultAlipayClient(certAlipayRequest);

}

}

5、APP支付

import cn.hutool.core.date.DateUtil;

import com.alipay.api.AlipayApiException;

import com.alipay.api.AlipayClient;

import com.alipay.api.domain.AlipayFundTransPayModel;

import com.alipay.api.domain.AlipayTradeAppPayModel;

import com.alipay.api.domain.AlipayTradeQueryModel;

import com.alipay.api.domain.Participant;

import com.alipay.api.internal.util.AlipaySignature;

import com.alipay.api.request.AlipayFundTransUniTransferRequest;

import com.alipay.api.request.AlipayTradeAppPayRequest;

import com.alipay.api.request.AlipayTradeQueryRequest;

import com.alipay.api.response.AlipayFundTransUniTransferResponse;

import com.alipay.api.response.AlipayTradeAppPayResponse;

import com.alipay.api.response.AlipayTradeQueryResponse;

import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.RequestBody;

import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import java.util.HashMap;

import java.util.Iterator;

import java.util.Map;

import java.util.UUID;

/**

* app支付

*/

@Slf4j

@Controller

@RequestMapping("/app/alipay/app")

public class AlipayAppPayController {

@Autowired

private AlipayProperties alipayProperties;

@Autowired

private AlipayClient alipayClient;

@Autowired

private AlipayProperties aliPayProperties;

/**

* 去支付

*

*

* @param response

* @throws Exception

*/

@RequestMapping("/createOrder")

public void createOrder(HttpServletRequest request, HttpServletResponse response,

@RequestBody Map mapParams) throws AlipayApiException {

BaseResault resPo = new BaseResault();

// 订单模型

String productCode = "QUICK_MSECURITY_PAY";

AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();

Order bean = orderService.getOrderByNum(mapParams.get("orderNum"));

model.setOutTradeNo(bean.getOrderNum());

log.info("----订单编号----" + model.getOutTradeNo());

model.setSubject(bean.getShopName());

log.info("----subject----" + model.getSubject());

model.setTotalAmount(bean.getTotalMoney().toString());

log.info("----金额----" + model.getTotalAmount());

model.setTimeoutExpress("30m");

model.setProductCode(productCode);

AlipayTradeAppPayRequest appPayRequest = new AlipayTradeAppPayRequest();

appPayRequest.setNotifyUrl(‘服务器域名’ + alipayProperties.getNotifyUrl());

log.info("----notifyUrl----" + appPayRequest.getNotifyUrl());

appPayRequest.setBizModel(model);

//实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay

AlipayTradeAppPayResponse ali_response = alipayClient.sdkExecute(appPayRequest); //这里和使用公钥加签支付使用的方法不同

//就是orderString 可以直接给客户端请求,无需再做处理。

log.info("---------支付宝返回---------{}", ali_response.getBody());

resPo.setObj(ali_response.getBody());

resPo.setCode(ConstantApp.AppTokenValidResult.SUCCESS.getCode());

resPo.setMessage(ConstantApp.AppTokenValidResult.SUCCESS.getMessage());

ResponseJsonUtils.json(response, resPo);

}

}

6、查询订单

/**

* 订单查询(最主要用于查询订单的支付状态)

*

* @param orderNo 商户订单号

* @return

*/

@GetMapping("/query")

public void query(HttpServletRequest request, HttpServletResponse response, String orderNo) throws AlipayApiException {

BaseResault resPo = new BaseResault();

AlipayTradeQueryRequest aliRequest = new AlipayTradeQueryRequest();

AlipayTradeQueryModel bizModel = new AlipayTradeQueryModel();

bizModel.setTradeNo(orderNo);

aliRequest.setBizModel(bizModel);

AlipayTradeQueryResponse aliResponse = alipayClient.certificateExecute(aliRequest);

if (aliResponse.isSuccess()) {

log.info("查询支付宝支付状态-----调用成功{}", aliResponse.getBody());

if (aliResponse.getTradeStatus().equals("TRADE_SUCCESS") || aliResponse.getTradeStatus().equals("TRADE_FINISHED")) {

//订单编号

String orderNum = aliResponse.getOutTradeNo();

// 处理业务

resPo.setObj(aliResponse.getBody());

resPo.setCode(ConstantApp.AppTokenValidResult.SUCCESS.getCode());

resPo.setMessage(ConstantApp.AppTokenValidResult.SUCCESS.getMessage());

ResponseJsonUtils.json(response, resPo);

return;

} else {

log.error("支付宝订单" + orderNo + "交易失败,交易状态:" + aliResponse.getTradeStatus());

resPo.setObj(aliResponse.getBody());

resPo.setCode(ConstantApp.AppTokenValidResult.SYSTEM_ERROR.getCode());

resPo.setMessage(ConstantApp.AppTokenValidResult.SYSTEM_ERROR.getMessage());

ResponseJsonUtils.json(response, resPo);

return;

}

} else {

log.info("查询支付宝支付状态------调用失败{}", aliResponse.getBody());

resPo.setObj(aliResponse.getBody());

resPo.setCode(ConstantApp.AppTokenValidResult.SYSTEM_ERROR.getCode());

resPo.setMessage(ConstantApp.AppTokenValidResult.SYSTEM_ERROR.getMessage());

ResponseJsonUtils.json(response, resPo);

return;

}

}

7、转账给用户

/**

* alipay.fund.trans.uni.transfer(单笔转账接口)

*

文档地址

* https://docs.open.alipay.com/api_28/alipay.fund.trans.uni.transfer/

*

* @param response

* @throws Exception

*/

@RequestMapping("/alipayToUser")

public void alipayToUser(HttpServletRequest request, HttpServletResponse response) throws AlipayApiException {

BaseResault resPo = new BaseResault();

//转账金额 不能少于0.1元

String money = request.getParameter("money");

//支付宝账号,支持邮箱、电话号码

String phone = request.getParameter("phone");

//支付宝账户名称

String name = request.getParameter("name");

// 订单模型

AlipayFundTransPayModel model = new AlipayFundTransPayModel();

//商户端的唯一订单号

String orderNum = UUID.randomUUID().toString().replace("-", "");

log.info("============支付宝转账给用户-订单号:" + orderNum + "==============");

model.setOutBizNo(orderNum);

//订单总金额,单位为元,精确到小数点后两位

model.setTransAmount(money);

//业务产品码,

//收发现金红包固定为:STD_RED_PACKET;

//单笔无密转账到支付宝账户固定为:TRANS_ACCOUNT_NO_PWD;

//单笔无密转账到银行卡固定为:TRANS_BANKCARD_NO_PWD

model.setProductCode("TRANS_ACCOUNT_NO_PWD");

//收款方信息

Participant participant = new Participant();

//参与方的唯一标识

participant.setIdentity(phone);

//参与方的标识类型,目前支持如下类型:

//1、ALIPAY_USER_ID 支付宝的会员ID

//2、ALIPAY_LOGON_ID:支付宝登录号,支持邮箱和手机号格式

participant.setIdentityType("ALIPAY_LOGON_ID");

//参与方真实姓名,如果非空,将校验收款支付宝账号姓名一致性。当identity_type=ALIPAY_LOGON_ID时,本字段必填。

participant.setName(name);

model.setPayeeInfo(participant);

//业务备注

model.setRemark("转账测试");

model.setBizScene("DIRECT_TRANSFER");

AlipayFundTransUniTransferRequest appPayRequest = new AlipayFundTransUniTransferRequest();

appPayRequest.setBizModel(model);

//实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.fund.trans.uni.transfer(单笔转账接口)

AlipayFundTransUniTransferResponse ali_response = alipayClient.certificateExecute(appPayRequest);

if (ali_response.isSuccess()) {

log.info("========支付宝转账给用户-调用成功=======" + ali_response.getBody());

resPo.setObj(ali_response.getBody());

resPo.setCode(ConstantApp.AppTokenValidResult.SUCCESS.getCode());

resPo.setMessage(ConstantApp.AppTokenValidResult.SUCCESS.getMessage());

ResponseJsonUtils.json(response, resPo);

} else {

log.info("========支付宝转账给用户-调用失败=======" + ali_response.getBody());

resPo.setObj(ali_response.getBody());

resPo.setCode(ConstantApp.AppTokenValidResult.SYSTEM_ERROR.getCode());

resPo.setMessage(ConstantApp.AppTokenValidResult.SYSTEM_ERROR.getMessage());

ResponseJsonUtils.json(response, resPo);

}

}

8、异步通知

/**

* 证书支付异步通知

* https://docs.open.alipay.com/194/103296

*/

@RequestMapping("/notify")

public String notify(HttpServletRequest request) {

log.info("-----------支付异步通知----------------");

Map requestParams = request.getParameterMap();

log.info(">>>支付宝回调参数:" + requestParams);

Map params = new HashMap<>();

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");

params.put(name, valueStr);

}

log.info(">>>支付宝回调参数解析:" + params);

try {

String alipayCertPath = System.getProperty("user.dir") + aliPayProperties.getAlipayCertPath();

//切记alipaypublickey是支付宝的公钥,请去open.alipay.com对应应用下查看。

boolean flag = AlipaySignature.rsaCertCheckV1(

params,

alipayCertPath,

aliPayProperties.getCharset(),

aliPayProperties.getSignType());

if (flag) {

log.info(">>>支付宝回调签名认证成功");

//商户订单号

String out_trade_no = params.get("out_trade_no");

//交易状态

String trade_status = params.get("trade_status");

//交易金额

String amount = params.get("total_amount");

//商户app_id

String app_id = params.get("app_id");

if ("TRADE_SUCCESS".equals(trade_status) || "TRADE_FINISHED".equals(trade_status)) {

/**

* 自己的业务处理,一定要判断是否已经处理过订单

*/

log.info("-----------^v^支付成功^v^------------");

}

} else {

log.error("没有处理支付宝回调业务,支付宝交易状态:{},params:{}", trade_status, params);

}

} else {

log.info("支付宝回调签名认证失败,signVerified=false, params:{}", params);

return "failure";

}

} catch (Exception e) {

log.error(e.getMessage(), e);

log.info("支付宝回调签名认证失败,signVerified=false, params:{}", params);

return "failure";

}

return "success";

}

9、退款

/**

* 同一订单多次退款

*

* @param orderNo 商户订单号

* @return

*/

@Override

public String multipleRefunds(String orderNo, String refundAmount, String refundReason) throws AlipayApiException {

log.info("------------支付宝退款开始--------------");

AlipayTradeRefundRequest alipayRequest = new AlipayTradeRefundRequest();

AlipayTradeRefundModel model = new AlipayTradeRefundModel();

// 商户订单号

model.setOutTradeNo(orderNo);

// 退款金额 单位元

model.setRefundAmount(refundAmount);

// 退款原因

model.setRefundReason(refundReason);

// 退款订单号(同一个订单可以分多次部分退款,当分多次时必传)

model.setOutRequestNo(UUID.randomUUID().toString());

log.info("------退款参数-----{}-----{}-----{}------{}", orderNo, refundAmount, refundReason, model.getOutRequestNo());

alipayRequest.setBizModel(model);

AlipayTradeRefundResponse alipayResponse = alipayClient.certificateExecute(alipayRequest);

log.info("--------支付宝退款结果---------" + alipayResponse.getBody() + "---------订单号--" + orderNo);

return alipayResponse.getBody();

}

这篇关于alipay 证书 java_Java 支付宝使用公钥证书加签 进行支付-查询-退款-转账的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/259399

相关文章

java如何解压zip压缩包

《java如何解压zip压缩包》:本文主要介绍java如何解压zip压缩包问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Java解压zip压缩包实例代码结果如下总结java解压zip压缩包坐在旁边的小伙伴问我怎么用 java 将服务器上的压缩文件解压出来,

SpringBoot中SM2公钥加密、私钥解密的实现示例详解

《SpringBoot中SM2公钥加密、私钥解密的实现示例详解》本文介绍了如何在SpringBoot项目中实现SM2公钥加密和私钥解密的功能,通过使用Hutool库和BouncyCastle依赖,简化... 目录一、前言1、加密信息(示例)2、加密结果(示例)二、实现代码1、yml文件配置2、创建SM2工具

Spring WebFlux 与 WebClient 使用指南及最佳实践

《SpringWebFlux与WebClient使用指南及最佳实践》WebClient是SpringWebFlux模块提供的非阻塞、响应式HTTP客户端,基于ProjectReactor实现,... 目录Spring WebFlux 与 WebClient 使用指南1. WebClient 概述2. 核心依

Spring Boot @RestControllerAdvice全局异常处理最佳实践

《SpringBoot@RestControllerAdvice全局异常处理最佳实践》本文详解SpringBoot中通过@RestControllerAdvice实现全局异常处理,强调代码复用、统... 目录前言一、为什么要使用全局异常处理?二、核心注解解析1. @RestControllerAdvice2

Spring IoC 容器的使用详解(最新整理)

《SpringIoC容器的使用详解(最新整理)》文章介绍了Spring框架中的应用分层思想与IoC容器原理,通过分层解耦业务逻辑、数据访问等模块,IoC容器利用@Component注解管理Bean... 目录1. 应用分层2. IoC 的介绍3. IoC 容器的使用3.1. bean 的存储3.2. 方法注

Python内置函数之classmethod函数使用详解

《Python内置函数之classmethod函数使用详解》:本文主要介绍Python内置函数之classmethod函数使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录1. 类方法定义与基本语法2. 类方法 vs 实例方法 vs 静态方法3. 核心特性与用法(1编程客

从入门到精通MySQL联合查询

《从入门到精通MySQL联合查询》:本文主要介绍从入门到精通MySQL联合查询,本文通过实例代码给大家介绍的非常详细,需要的朋友可以参考下... 目录摘要1. 多表联合查询时mysql内部原理2. 内连接3. 外连接4. 自连接5. 子查询6. 合并查询7. 插入查询结果摘要前面我们学习了数据库设计时要满

Spring事务传播机制最佳实践

《Spring事务传播机制最佳实践》Spring的事务传播机制为我们提供了优雅的解决方案,本文将带您深入理解这一机制,掌握不同场景下的最佳实践,感兴趣的朋友一起看看吧... 目录1. 什么是事务传播行为2. Spring支持的七种事务传播行为2.1 REQUIRED(默认)2.2 SUPPORTS2

怎样通过分析GC日志来定位Java进程的内存问题

《怎样通过分析GC日志来定位Java进程的内存问题》:本文主要介绍怎样通过分析GC日志来定位Java进程的内存问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、GC 日志基础配置1. 启用详细 GC 日志2. 不同收集器的日志格式二、关键指标与分析维度1.

Java进程异常故障定位及排查过程

《Java进程异常故障定位及排查过程》:本文主要介绍Java进程异常故障定位及排查过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、故障发现与初步判断1. 监控系统告警2. 日志初步分析二、核心排查工具与步骤1. 进程状态检查2. CPU 飙升问题3. 内存