史上最简单Java服务端对接支付宝支付教程,前端为APP。
官方开发文档:https://docs.open.alipay.com/204/105297/
以上就是整个支付流程了,吭哧吭哧,开搞!
在支付宝开放平台申请应用权限,开通支付功能,生成应用的私钥,公钥等等就不赘述了。上面贴的官方文档里面都有介绍。下面是需要用到的参数:
环境:
com.alipay.sdk
alipay-sdk-java
3.3.4.ALL
@Slf4j
public class AliPayProperties {
public static final String APP_ID = "20...8";//APPID
public static final String PRIVATE_KEY = "MIIEvgI.......q9s";//你的应用私钥
public static final String PUBLIC_KEY = "MIIBIjA.......QAB";//支付宝公钥
public static final String NOTIFY_URL = "http://..../v1/pay/ali/notify/";//你的支付回调地址
public static final String RETURN_URL = "http://..../v1/pay/ali/notify/";//你的支付回调地址
public static final String SIGN_TYPE = "RSA2";//签名加密类型(固定)
public static final String CHARSET = "utf-8";
public static final String GATEWAY_URL = "https://openapi.alipay.com/gateway.do";//支付宝网关(固定)
public static final String FORMAT = "json";
}
@RestController
@RequestMapping("/v1/pay/ali")
@Slf4j
public class AliPayController {
@Autowired
private AliPayUtil aliPayUtil;
/** * 获取支付宝支付加密字符串 * * @param * @param * @return * @throws Exception */
@PostMapping(value = "/getAppPayOrderStr")
@ApiOperation(value = "支付宝支付")
@NoMaybeResponse//自定义注解,封装返回值的
public String getAppPayOrderStr(@RequestBody @Validated AliPayDTO aliPayDTO) {
return aliPayUtil.getAliPayOrderStr(aliPayDTO, CurrentUserSession.getUserId());
}
/** * 支付宝回调 * 注意,这个接口必须是开放式的,项目启动,能随便访问,避开自己项目的网关,验证之类的。 * @param request * @throws Exception */
@RequestMapping(value = "/notify")
@ApiOperation(value = "支付宝回调接口")
public String notify(HttpServletRequest request) {
return aliPayUtil.notify(request);
}
}
AliPayDTO 是自定义的业务类,根据自己项目需要定义,我这里就传了订单的id,支付业务类型-订单支付。把各种支付的业务场景整合到一起了的。
AliPayDTO.java
@Data
public class AliPayDTO {
@ApiModelProperty("订单编号集-订单支付才需要传")
private List<Long> orderNos;
@ApiModelProperty("支付类型(必传) 1-订单第一次支付 2-订单补款 3-服务费充值")
@NotNull
private Integer payType;
@ApiModelProperty("金额-服务费充值才需要传")
private BigDecimal money;
@ApiModelProperty("备用字段")
private String temp;
}
AliPayUtil.java
包含了支付,支付回调,退款,查看支付信息等方法。
@Slf4j
@Component
public class AliPayUtil {
@Autowired
TOrderMapper orderMapper;
@Autowired
TOrderLineMapper orderLineMapper;
@Autowired
IOrderService orderService;
@Autowired
private IUserService userService;
/** * 业务逻辑处理 * * @return */
public String getAliPayOrderStr(AliPayDTO aliPayDTO, String userId) {
if (aliPayDTO.getPayType().equals(PayServiceTypeEnum.SERVICE_FEE.getCode())) {
//服务费充值业务处理
WXServiceRechargeDTO rechargeDTO = new WXServiceRechargeDTO();
rechargeDTO.setServiceMoney(aliPayDTO.getMoney());
long no = userService.addServiceRecharge(rechargeDTO, userId);
aliPayDTO.setTemp(String.valueOf(no));
//获取支付字符串
return this.createAliPayString(aliPayDTO);
} else if (aliPayDTO.getPayType().equals(PayServiceTypeEnum.ORDER.getCode())) {
// TODO 订单支付
return null;
} else {
return null;
}
}
/** * 获取支付宝加签后台的订单信息字符串 * * @return */
public String createAliPayString(AliPayDTO aliPayDTO) {
try {
//实例化客户端
AlipayClient alipayClient = this.getAliPayClient();
AlipayTradeAppPayRequest aliPayRequest = new AlipayTradeAppPayRequest();
AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
model.setBody(JSONObject.toJSONString(aliPayDTO.getOrderNos()));
model.setSubject("不可能科技支付宝销售订单");
// 支付订单号 本系统定义的支付单号
model.setOutTradeNo(RandomUtils.createNo32());
// 业务参数(支付业务类型,订单的id),json格式,必须URLEncoder编码(可以把在回调时需要的参数放在这里,支付宝会原样返回)
model.setPassbackParams(URLEncoder.encode(JSONObject.toJSONString(aliPayDTO), "GBK"));
// 支付超时时间
model.setTimeoutExpress("30m");
// 支付金额 aliPayDTO.getMoney()
model.setTotalAmount("0.01");
model.setProductCode("QUICK_MSECURITY_PAY");
aliPayRequest.setBizModel(model);
// 支付成功后 接收支付宝异步通知的服务端url
aliPayRequest.setNotifyUrl(AliPayProperties.NOTIFY_URL);
AlipayTradeAppPayResponse aliPayResponse = alipayClient.sdkExecute(aliPayRequest);
return aliPayResponse.getBody();
} catch (UnsupportedEncodingException e) {
throw new BusinessException(BusinessErrorCode.FAIL);
} catch (AlipayApiException e) {
log.info("getAliPayOrderStr error :{}", e);
throw new BusinessException(BusinessErrorCode.GET_ALIPAY_PAY_STR_ERROR);
}
}
public String notify(HttpServletRequest request) {
log.info("支付宝支付回调开始----------------------------------------------------------!");
//从支付宝回调的request域中取值
Map<String, String[]> aliParams = request.getParameterMap();
//用以存放转化后的参数集合
Map<String, String> conversionParams = new HashMap<String, String>();
for (Iterator<String> iter = aliParams.keySet().iterator(); iter.hasNext(); ) {
String key = iter.next();
String[] values = aliParams.get(key);
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"), "uft-8");
conversionParams.put(key, valueStr);
}
return this.notify(conversionParams);
}
/** * 验证回调参数,根据支付的业务类型处理数据 * * @param conversionParams * @return */
private String notify(Map<String, String> conversionParams) {
//签名验证(对支付宝返回的数据验证,确定是支付宝返回的)
boolean signVerified = false;
try {
//调用SDK验证签名
signVerified = AlipaySignature.rsaCheckV1(conversionParams, AliPayProperties.PUBLIC_KEY, AliPayProperties.CHARSET, AliPayProperties.SIGN_TYPE);
} catch (AlipayApiException e) {
log.debug("支付宝回调,SDK验证签名失败!");
e.printStackTrace();
}
if (signVerified) {
//验签通过 修改订单状态
String appId = conversionParams.get("app_id");
//订单金额:本次交易支付的订单金额,单位为人民币(元)
String totalAmount = conversionParams.get("total_amount");
//业务参数 AliPayDTO
String passbackParams = conversionParams.get("passback_params");
//支付宝的交易号
String tradeNo = conversionParams.get("trade_no");
//商户系统的唯一订单号
String outTradeNo = conversionParams.get("out_trade_no");
// 获取交易状态
String tradeStatus = conversionParams.get("trade_status");
try {
passbackParams = URLDecoder.decode(passbackParams, "GBK");
} catch (UnsupportedEncodingException e) {
log.info("URLDecoder.decode error");
}
// 支付的类型和关联的订单号
AliPayDTO aliPayDTO = JSONArray.parseObject(passbackParams, AliPayDTO.class);
log.info("本次支付类型:{},关联的订单号:{},本次支付总金额:{},appId:{},aliPayDTO:{}", aliPayDTO.getPayType(), aliPayDTO.getOrderNos(), totalAmount, appId, aliPayDTO);
//验证支付状态
boolean payStatus = false;
switch (tradeStatus) {
case "TRADE_FINISHED": //完成
case "TRADE_SUCCESS":
payStatus = true;
break;
case "WAIT_BUYER_PAY": //待支付
break;
case "TRADE_CLOSED": //交易关闭
break;
default:
break;
}
if (payStatus) {
if (aliPayDTO.getPayType().equals(PayServiceTypeEnum.ORDER.getCode())) {
//TODO 订单支付
} else if (aliPayDTO.getPayType().equals(PayServiceTypeEnum.SERVICE_FEE.getCode())) {
//服务费充值
Map<String, Object> params = new HashMap<>(2);
params.put("no", aliPayDTO.getTemp());
userService.rechargeNotify(params, tradeNo, null);
}
return "success";
} else {
return null;
}
} else {
log.info("验签不通过");
return "fail";
}
}
/** * 查看支付订单信息 * * @param outTradeNo 商户网站唯一订单号 * @param tradeNo 支付宝交易号 * @return 公共响应参数 code,msg 响应参数: https://docs.open.alipay.com/api_1/alipay.trade.query */
public String queryPayment(String outTradeNo, String tradeNo) {
AlipayClient alipayClient = this.getAliPayClient();
AlipayTradeQueryRequest alipayTradeQueryRequest = new AlipayTradeQueryRequest();
AlipayTradeQueryModel model = new AlipayTradeQueryModel();
model.setOutTradeNo(outTradeNo);
model.setTradeNo(tradeNo);
alipayTradeQueryRequest.setBizModel(model);
try {
AlipayTradeQueryResponse alipayTradeQueryResponse = alipayClient.execute(alipayTradeQueryRequest);
String queryPaymentStr = alipayTradeQueryResponse.getBody();
log.info("订单号:{},支付宝支付单号:{}", outTradeNo, tradeNo);
return queryPaymentStr;
} catch (AlipayApiException e) {
e.printStackTrace();
}
return null;
}
/** * 支付宝订单退款 * * @param outTradeNo 本系统生成的商户订单编号 * @param tradeNo 支付宝订单交易号 * @param refundAmount 退款金额 不得大于订单金额 * @param refundReason 退款说明 * @param outRequestNo 标识一次退款请求,同一笔交易多次退款需要保证唯一,如需部分退款,则此参数必传。 * @return 公共返回参数 code,msg, 响应参数实例: https://docs.open.alipay.com/api_1/alipay.trade.refund */
public void alipayRefund(String outTradeNo, String tradeNo, String refundAmount, String refundReason, String outRequestNo) {
log.info("支付宝退款开始------------------------------------------------------!");
AlipayClient alipayClient = this.getAliPayClient();
//订单编号,支付宝交易号不为空
if (outTradeNo != null && tradeNo != null) {
AlipayTradeRefundRequest aliPayRequest = new AlipayTradeRefundRequest();
AlipayTradeRefundModel model = new AlipayTradeRefundModel();
model.setOutTradeNo(outTradeNo);
model.setTradeNo(tradeNo);
model.setRefundAmount(refundAmount);
model.setRefundReason(refundReason);
model.setOutRequestNo(outRequestNo);
aliPayRequest.setBizModel(model);
try {
AlipayTradeRefundResponse aliPayResponse = alipayClient.execute(aliPayRequest);
log.debug("aliPayResponse:{}", aliPayResponse);
if (!"10000".equals(aliPayResponse.getCode())) {
log.info("支付宝退款失败,支付宝交易号:{},状态码:{}", tradeNo, aliPayResponse.getCode());
throw new BusinessException(BusinessErrorCode.ALIPAY_PAY_REFUND_ERROR);
}
} catch (AlipayApiException e) {
e.printStackTrace();
}
}
}
/** * 获取支付宝Client * * @return */
private AlipayClient getAliPayClient() {
return new DefaultAlipayClient(
AliPayProperties.GATEWAY_URL, AliPayProperties.APP_ID, AliPayProperties.PRIVATE_KEY, AliPayProperties.FORMAT,
AliPayProperties.CHARSET, AliPayProperties.PUBLIC_KEY, AliPayProperties.SIGN_TYPE);
}
}
就这么简单,支付宝支付,退款就可以对接完成。