Java 支付宝支付 Alipay

相关官方文档位置: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 接口 ;因为这样跟保险,但需要注意的是自己数据库里面订单状态的修改,毕竟有两次验证,时间上是有差距的,所以在订单状态及费用的处理上需要多加留意。

猜你喜欢

转载自blog.csdn.net/atmknight/article/details/81164558
今日推荐