Java 支付宝支付 Alipay

本文详细介绍了如何集成支付宝API进行在线支付,并通过回调机制确保支付的安全与可靠性。包括设置请求参数、处理回调响应、验证签名等关键步骤,旨在帮助开发者实现安全高效的支付功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

相关官方文档位置:https://docs.open.alipay.com/api_1

阿里的文档还是比较清晰明了的,Java部分的代码更是做了非常棒的封装,引用jar包中的方法,支付宝的流程都类似,可以迅速的写出相应的支付代码;

alipay.trade.app.pay(统一收单交易支付接口)  为例子:

我们可以看到这些公共请求的参数,其中必填参数是必填的,不能为空,也有相应的格式要求,描述中有很好的解释,非必填参数的话有其实也比较重要

notify_url:支付宝服务器主动通知商户服务器里指定的页面http/https路径。

就是回调的地址:意思是 如果填了回调地址,在支付成功后,阿里方面会主动请求这个地址,将相应的支付信息传给你,这个能使支付更加保险,一般在支付后阿里方面会给app端或web端一个反馈,然后app端可以主动请求查询接口来验证支付是否成功,但之间有个时间差,可能影响用户体验什么的,而填了回调后,能使这个功能更加保险,双重验证总是更加保险,在回调中能做很多事情;

app_auth_token: 其实这个是第三方应用调用支付所必须的字段,类似于微信支付中的access_token,但也有点不同,这个相当于去获取相应的支付授权,但是我遇到第三方应用都把他入驻到阿里的平台中,就不用这个字段了,一定要用第三方应用的话,可以看文档,有请求过程,Java 的代码也封装的很好,获取十分简单。

下面讲主要请求参数我放在代码里面了,我再代码里面通过注释来解释

pom.xml里面要加入相应的jar包

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

controller:


import javax.servlet.http.HttpServletRequest;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.edgecdj.constant.AliPayProperties;
import com.edgecdj.constant.GlobleConstant;
import com.edgecdj.domain.AliPayModel;
import com.edgecdj.domain.JsonResult;
import com.edgecdj.paydemo.alipay.service.AliPayService;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;

/**
 * 支付宝支付
 * 
 * @author cdj
 */
@RestController
@RequestMapping("/AliPay")
@Api("阿里支付")
public class AliPayController {
	private Log log = LogFactory.getLog(AliPayController.class);
	@Autowired
	AliPayService aliPayService;

	// @Autowired
	// AliPayService aliPayService;

	@ApiOperation(value = "测试阿里支付", notes = "测试阿里支付")
	@ApiImplicitParams({})
	@GetMapping("/TestAlipay")
	public JsonResult testAlipay() {
		try {
			// 这个东西必备
			AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do",
					AliPayProperties.appid, AliPayProperties.private_key, "json", "UTF-8",
					AliPayProperties.alipay_public_key, "RSA2");
			// 发起App支付请求
			AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
			AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
			// 订单描述
			model.setBody("我是测试数据");
			// 订单标题
			model.setSubject("App支付测试Java");
			// 商户订单号 就是商户后台生成的订单号
			model.setOutTradeNo("201503200101010011");
			// 该笔订单允许的最晚付款时间,逾期将关闭交易。取值范围:1m~15d。m-分钟,h-小时,d-天,1c-当天 (屁股后面的字母一定要带,不然报错)
			model.setTimeoutExpress("30m");
			// 订单总金额 ,默认单位为元,精确到小数点后两位,取值范围[0.01,100000000]
			model.setTotalAmount("0.01");
			// 销售产品码 不必填
			model.setProductCode("QUICK_MSECURITY_PAY");
			request.setBizModel(model);
			// request.setNotifyUrl("商户外网可以访问的异步地址,不写就是不回调");
			// 通过api的方法请求阿里接口获得反馈
			AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
			System.out.println(response.getBody());
			if (response.isSuccess()) {
				System.out.println("调用成功");
			} else {
				System.out.println("调用失败");
			}
			return JsonResult.success(response.getBody());
		} catch (Exception e) {
			return JsonResult.failMsg(e.getMessage());
		}
	}


	@ApiOperation(value = "Alipay 查询订单状态接口", notes = "Alipay 查询订单状态接口")
	@ApiImplicitParams({})
	@PostMapping("/AliPayQuery")
	public JsonResult aliPayQuery(@RequestBody AliPayModel aliPayModel) {
		JSONObject resultObject = aliPayService.alipayQuery(aliPayModel);
		Boolean flag = (Boolean) resultObject.get(GlobleConstant.RESULTFLAG);
		if (flag) {
			return JsonResult.success(resultObject);
		} else {
			return JsonResult.failMsg(resultObject.get(GlobleConstant.ERRMSG).toString());
		}
	}

	@ApiOperation(value = "Alipay Notify回调", notes = "Alipay Notify回调")
	@ApiImplicitParams({})
	@PostMapping("/AppAliPayNotify")
	public JsonResult appAliPayNotify(HttpServletRequest request) {
		try {
			aliPayService.appAliPayNotify(request);
			return JsonResult.success(null);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			return JsonResult.failMsg(e.getMessage());
		}
	}

}

执行成功后会得到这样这样一串数据

{
  "result": "success",
  "msg": null,
  "data": "alipay_sdk=alipay-sdk-java-3.3.4.ALL&app_id=2018071360622098&biz_content=%7B%22body%22%3A%22%E6%88%91%E6%98%AF%E6%B5%8B%E8%AF%95%E6%95%B0%E6%8D%AE%22%2C%22out_trade_no%22%3A%22201503200101010011%22%2C%22product_code%22%3A%22QUICK_MSECURITY_PAY%22%2C%22subject%22%3A%22App%E6%94%AF%E4%BB%98%E6%B5%8B%E8%AF%95Java%22%2C%22timeout_express%22%3A%2230m%22%2C%22total_amount%22%3A%220.01%22%7D&charset=UTF-8&format=json&method=alipay.trade.app.pay&sign=BU%2Bd1TDYXCtWf8r2DJjvULSlgd1Kg%2Fp5jkB09g4NxlERN88xDUdRgtXF1vO8KZXj5dT%2BgTH2Pp%2FZ1lgvilcBAEQaa3W5hr6LzLKMo03VmGGA1UsUVbCNGzwV1ALaT72jcsQhWBC7JfK9b2p%2BNwU34BduQlNw%2Fq6J6wYJgdwoHE%2FokAmNfOnnNADg0sWTYyRZb8IyZP2yHlu4rGz7KTLYiXOyYKQFFnRXgks7hCSmES5omW1lBtxQ%2F63EAR%2Fj1UE%2BYbnyoTKMXiNcsG9%2Fo%2FOgoa2zD9lcxiXYZOrKqGlR8FZXke3FI6I%2FO3lVrTPqq1VgdyDm7kffoM3lwOFB4WUliw%3D%3D&sign_type=RSA2&timestamp=2018-07-23+13%3A11%3A12&version=1.0"
}

然后将data里的这串数据传给app端,由App端请求支付接口,就能发起支付了。

其他的支付接口都比较类似,官方文档上也有相应的代码,传入相应的请求参数,举一反三 ,阿里支付的代码还是挺好理解的。

 

阿里回调回来的参数

controller:

	@ApiOperation(value = "Alipay Notify回调", notes = "Alipay Notify回调")
	@ApiImplicitParams({})
	@PostMapping("/AppAliPayNotify")
	public JsonResult appAliPayNotify(HttpServletRequest request) {
		try {
			aliPayService.appAliPayNotify(request);
			return JsonResult.success(null);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			return JsonResult.failMsg(e.getMessage());
		}
	}

service: 

package com.edgecdj.paydemo.alipay.service.impl;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alipay.api.internal.util.AlipaySignature;
import com.edgecdj.constant.AliPayProperties;
import com.edgecdj.paydemo.alipay.service.AliPayService;

@Service
@Transactional
public class AlipayServiceImpl implements AliPayService {
	private Log log = LogFactory.getLog(AlipayServiceImpl.class);

	@Override
	public void appAliPayNotify(HttpServletRequest request) {
		System.out.println("----------------阿里服务器消费手机回调-------" + request);
		Map<String, String> params = new HashMap<String, String>();
		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] + ",";
			}
			// 乱码解决,这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
			// valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk");
			params.put(name, valueStr);
		}
		try {
			// 调用SDK验证签名
			boolean flag = AlipaySignature.rsaCheckV1(params, AliPayProperties.alipay_public_key,
					AliPayProperties.charset, "RSA2");
			// 商户订单号
			String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"), "UTF-8");
			// 支付宝交易号
			String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"), "UTF-8");
			// 交易状态
			String trade_status = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"), "UTF-8");
			String total_amount = new String(request.getParameter("total_amount").getBytes("ISO-8859-1"), "UTF-8");
			String info = "flag==" + flag + ";out_trade_no = " + out_trade_no + ";trade_no" + trade_no
					+ ";trade_status = " + trade_status + ";total_amount=" + total_amount;
			log.info(info);
			if (flag && trade_status.equals("TRADE_SUCCESS")) {
				// 修改订单状态
				// 已缴费----开始处理业务
				
			}

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}

再强调一下,支付的话验证最好是  查询+notifyurl 接口 ;因为这样跟保险,但需要注意的是自己数据库里面订单状态的修改,毕竟有两次验证,时间上是有差距的,所以在订单状态及费用的处理上需要多加留意。

/** *SDK调用说明 */ public function index() { //调用测试 import('AlipaySDK.Alipay'); $pay = new \Alipay(); /** * $trade_type 交易类型 app wap web */ $data = $pay->alipay('215360251411626', '0.01', '测试', '测试', 'web', 'http://www.test.com/callback'); //wap 结果string(880) "https://openapi.alipay.com/gateway.do?alipay_sdk=alipay-sdk-php-20180705&app_id=2018072660781410&biz;_content={"body":"测试","subject":"测试","out_trade_no":"215360251411626","timeout_express":"90m","total_amount":"0.01","product_code":"QUICK_WAP_PAY"}&charset=UTF-8&format=json&method=alipay.trade.wap.pay&notify_url=http://www.test.com/callback&sign=RKPyAKAPv28GKfhWIdsCCOualcg2DMCbhpny6yw/tTvJ3Och+yIfS1au7zbGBnm5sFoX2enfgfZekTqBCyzK0/Irw01zDSAOJM4mPYxs96OUkOglWS5Zuq64JwQBAzesFvzKBGgsH2ecL8EUCclDbBIIrAT/DWr6KenyvQvXOxVQNwn540NoS754oBU0w9vLdrGj0Jljvn8D6cbDgnHiE8qLOgpaXv1ROLwtol0yj2H7cM/G7A9RM5Y8jV1aVNYWND8M4XAK5Wr8zwoa9RocbqDpYfw66NXSvrsuFpHf7MpWtSybH5TnxOP5kwzr7pJRDi0XRAyD9u1geei9thUsqA==&sign_type=RSA2&timestamp=2018-09-04+11:50:49&version=1.0" //app 结果直接返回客户端无需处理 alipay_sdk=alipay-sdk-php-20180705&app_id=2018072660781410&biz;_content={"body":"测试","subject":"测试","out_trade_no":"215360251411626","timeout_express":"90m","total_amount":"0.01","product_code":"QUICK_MSECURITY_PAY"}&charset=UTF-8&format=json&method=alipay.trade.app.pay¬ify_url=http://www.test.com/callback&sign_type=RSA2×tamp=2018-09-04+11:54:53&version=1.0&sign=Ab6a0lDxaNcWLL7XcETM85DbBrJI8Sj6czPGKBNK17MZ85FBeStKL+nA/Z4tMORC7H39ooVCDz9ILpbRUfU0eaE7Oe2MOz+Jsj7oUEqwvbvt7eebyPgy2PmPlfAwcZypKla0nUJwHOF5F0cL+mvMGk/K7f2PYMtWL/dIfPOQGC1hBoKFiS+ZF7jIJ98R0AaITAjvQ1drAmJqXpMzUCa1XsTCuQXMXYKu8DNGb/hooJu0xUH/qUU+4fKD0TmBYANQHIrKIBNFl6J2Gw504Mlcfh929ce+YdzF8DXQjacsBSp7f08UJ/FfRvhVXqAfX8lAFETGjc7FXGgU6simNgv1UQ== //web 结果 https://openapi.alipay.com/gateway.do?alipay_sdk=alipay-sdk-php-20180705&app_id=2018072660781410&biz;_content={"body":"测试","subject":"测试","out_trade_no":"215360251411626","timeout_express":"90m","total_amount":"0.01","product_code":"FAST_INSTANT_TRADE_PAY"}&charset=UTF-8&format=json&method=alipay.trade.page.pay¬ify_url=http://www.test.com/callback&sign=l9+A5ZByhwLjQwzRes9+ymKkFVu7uMND4j6cIWmXIXHjrBnGaHkcr+hVkwocaU3d/hB2hdPnxDruhyYFgchnsIA/XWumosG9uEnKyD/T52+VZ8FxLh5wpwH0ucvKzbMjgIWk9dPVjUAU5Zz7QjqKsJ+AsItFpttd0tEVZD4je2PFp5mizeCWT0id0H+y44IGexN705rNe6TGpfJDG0RSDsbD/ZoCzd8FRzC9cv5uwf00J1E9Yc0bUH/l37WFDBTv/LZnqdfeWpaiu8ro7CJ3R+z/xGQTHToo2zLtEc4Cwop096X8WqwSdGbyI9FCemcFzigRB+6yzD9nS4PsWEG3Ug==&sign_type=RSA2×tamp=2018-09-04+11:56:06&version=1.0 echo $data; exit; } /** * 回调地址 */ public function callback() { import('AlipaySDK.Alipay'); $pay = new \Alipay(); $data = $_POST; $verify_result = $pay->check($data); if ($verify_result) { // 验证成功 $out_trade_no = $data['out_trade_no']; // 支付宝交易号 $trade_no = $data['trade_no']; // 交易状态 $trade_status = $data['trade_status']; if ($trade_status == 'TRADE_FINISHED') { //成功之后的操作 } else if ($trade_status == 'TRADE_SUCCESS') { //成功之后的操作 } echo "success"; // 请不要修改或删除 } else { // 验证失败 echo "fail"; } } 声明:是文档根据Alipay文档二次整合,完全开源。如果觉得还可以请点击收藏
### 支付宝SDK Java验签失败的原因分析 支付宝SDK Java中的验签失败通常由以下几个原因引起: #### 1. **密钥配置错误** 商户需要正确配置应用私钥(`APP_PRIVATE_KEY`)、应用公钥(`APP_PUBLIC_KEY`),以及支付宝公钥(`ALIPAY_PUBLIC_KEY`)。如果这些密钥配置有误,则可能导致签名或验签失败。确保商户上传到支付宝开放平台的应用公钥与本地使用的应用私钥是一对匹配的RSA/RSA2密钥[^1]。 #### 2. **签名字符串生成逻辑不一致** 签名字符串是由请求参数按照特定规则拼接而成的。如果商户端生成的签名字符串与支付宝期望的签名字符串不同,也会导致验签失败。以下是常见的几个需要注意的地方: - 参数排序:签名字符串应按ASCII码顺序排列所有参与签名的参数。 - 值处理:对于空值或者特殊字符未做URL编码可能会导致差异。 - 字符集:确保使用UTF-8作为字符集来生成签名字符串[^2]。 #### 3. **时间戳超时** 如果请求的时间戳距离当前时间过久远,也可能被判定为非法请求而拒绝服务。因此要确认发送请求时所带上的timeStamp字段是否有效且接近实时时刻。 #### 4. **版本兼容性问题** 使用较新版本sdk如 `alipay-sdk-java-4.10.170.ALL` 可能存在一些旧版api不再支持的情况或者是默认行为有所改变,这同样会影响最终的结果准确性。所以建议查看官方文档了解最新变动并调整相应代码实现方式[^3]。 下面给出一段简单的java示例用于展示如何完成一次完整的支付操作含签名及后续验证过程: ```java import com.alipay.api.AlipayApiException; import com.alipay.api.internal.util.AlipaySignature; public class AlipayUtil { private static final String APP_PRIVATE_KEY = "your_app_private_key"; private static final String ALIPAY_PUBLIC_KEY = "alipay_public_key"; public boolean verify(String paramsStr, String sign) throws AlipayApiException{ Map<String, String> paramMap = new HashMap<>(); try { JSONObject jsonObject = JSON.parseObject(paramsStr); for (String key : jsonObject.keySet()) { paramMap.put(key, jsonObject.getString(key)); } } catch(Exception e){ throw new RuntimeException(e.getMessage()); } return AlipaySignature.rsaCheckV1(paramMap,"utf-8",ALIPAY_PUBLIC_KEY,"RSA2"); } } ``` 此段程序展示了通过引入阿里巴巴提供的工具库来进行rsa加密校验的过程,其中包含了必要的输入项即待检验的数据流还有之前提到过的各种类型的钥匙材料等内容。 --- ###
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值