Java支付宝APP支付-生成APP支付订单

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Jay_1989/article/details/82347563

讲述开发之前,先吐槽一下支付宝的官方文档,做的真乱,看的一头雾水,没有微信那么简单、明了。支付宝接口的调用和普通接口的调用不一样,使用的是支付宝官方的SDK的sdkExecute方法。

SDK的下载地址如下:https://docs.open.alipay.com/54/106370/

接口官方的API地址:https://docs.open.alipay.com/204/105465/

1、App支付请求参数说明 

接口功能:外部商户App唤起快捷SDK创建订单并支付。

请求参数是商户在与支付宝进行数据交互时,提供给支付宝的请求数据,以便支付宝根据这些数据进一步处理。

1.1公共参数

参数 类型 是否必填 最大长度 描述 示例值
app_id String 32 支付宝分配给开发者的应用ID 2014072300007148
method String 128 接口名称 alipay.trade.app.pay
format String 40 仅支持JSON JSON
charset String 10 请求使用的编码格式,如utf-8,gbk,gb2312等 utf-8
sign_type String 10 商户生成签名字符串所使用的签名算法类型,目前支持RSA2和RSA,推荐使用RSA2 RSA2
sign String 256 商户请求参数的签名串,详见签名 详见示例
timestamp String 19 发送请求的时间,格式"yyyy-MM-dd HH:mm:ss" 2014-07-24 03:07:50
version String 3 调用的接口版本,固定为:1.0 1.0
notify_url String 256 支付宝服务器主动通知商户服务器里指定的页面http/https路径。建议商户使用https https://api.xx.com/receive_notify.htm
biz_content String - 业务请求参数的集合,最大长度不限,除公共参数外所有请求参数都必须放在这个参数中传递,具体参照各产品快速接入文档  

1.2业务参数

参数 类型 是否必填 最大长度 描述 示例值
body String 128 对一笔交易的具体描述信息。如果是多种商品,请将商品描述字符串累加传给body。 Iphone6 16G
subject String 256 商品的标题/交易标题/订单标题/订单关键字等。 大乐透
out_trade_no String 64 商户网站唯一订单号 70501111111S001111119
timeout_express String 6 该笔订单允许的最晚付款时间,逾期将关闭交易。取值范围:1m~15d。m-分钟,h-小时,d-天,1c-当天(1c-当天的情况下,无论交易何时创建,都在0点关闭)。 该参数数值不接受小数点, 如 1.5h,可转换为 90m。
注:若为空,则默认为15d。
90m
total_amount String 9 订单总金额,单位为元,精确到小数点后两位,取值范围[0.01,100000000] 9.00
product_code String 64 销售产品码,商家和支付宝签约的产品码,为固定值QUICK_MSECURITY_PAY QUICK_MSECURITY_PAY
goods_type String 2 商品主类型:0—虚拟类商品,1—实物类商品
注:虚拟类商品不支持使用花呗渠道
0
passback_params String 512 公用回传参数,如果请求时传递了该参数,则返回给商户时会回传该参数。支付宝会在异步通知时将该参数原样返回。本参数必须进行UrlEncode之后才可以发送给支付宝 merchantBizType%3d3C%26merchantBizNo%3d2016010101111
promo_params String 512 优惠参数
注:仅与支付宝协商后可用
{"storeIdType":"1"}
extend_params String   业务扩展参数,详见下面的“业务扩展参数说明 {"sys_service_provider_id":"2088511833207846"}
enable_pay_channels String 128 可用渠道,用户只能在指定渠道范围内支付
当有多个渠道时用“,”分隔
注:与disable_pay_channels互斥
pcredit,moneyFund,debitCardExpress
disable_pay_channels String 128 禁用渠道,用户不可用指定渠道支付
当有多个渠道时用“,”分隔
注:与enable_pay_channels互斥
pcredit,moneyFund,debitCardExpress
store_id String 32 商户门店编号。该参数用于请求参数中以区分各门店,非必传项。 NJ_001
ext_user_info ExtUserInfo   外部指定买家,详见外部用户ExtUserInfo参数说明  

其它扩展参数,我这里就不详细描述了。

2、代码实现 

2.1基础类

AlipayConfig配置类,主要包含支付宝的配置信息

package com.hisap.xql.api.common.ali;

/**
 * @Author: QijieLiu
 * @Description: 支付宝配置信息
 * @Date: Created in 10:39 2018/8/20
 */
public class AlipayConfig {
	public static String APP_ID = "xxxxxx";
	public static String APP_PRIVATE_KEY = "xxxxxx";//APP私钥
	public static String APP_PUBLIC_KEY = "xxxxxx";//APP公钥
	public static String ALIPAY_PUBLIC_KEY = "xxxxxx";//支付宝公钥
	public static String UNIFIEDORDER_URL = "https://openapi.alipay.com/gateway.do";
        public static String NOTIFY_URL = "http://xxx.xxx.xxx.xxx/XqlApi/xxx/paynotify";
	public static String CHARSET = "UTF-8";
	public static String FORMAT = "json";
	public static String SIGNTYPE = "RSA2";
	public static String TIMEOUT_EXPRESS = "30m";
}

ResponseJson基础类,主要与APP前端进行交互

package com.hisap.xql.api.common.bean;
 
public class ResponseJson {
	// 结果码
	private String code;
	// 结果说明
	private String message;
	// 内容
	private Object data;
 
	public String getCode() {
		return code;
	}
 
	public void setCode(String code) {
		this.code = code;
	}
 
	public String getMessage() {
		return message;
	}
 
	public void setMessage(String message) {
		this.message = message;
	}
 
	public Object getData() {
		return data;
	}
 
	public void setData(Object data) {
		this.data = data;
	}
 
}

2.2业务类

AliPayController类

package com.hisap.xql.api.controller;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alipay.api.internal.util.AlipaySignature;
import com.hisap.xql.api.common.ali.AlipayConfig;
import com.hisap.xql.api.common.bean.ResponseJson;
import com.hisap.xql.api.common.constant.CodeMsg;
import com.hisap.xql.api.common.utils.CommonUtil;
import com.hisap.xql.api.service.AliPayService;

/**
 * @Author: QijieLiu
 * @Description: 支付宝支付信息
 * @Date: Created in 10:39 2018/8/20
 */
@Controller
@RequestMapping("/xxx")
public class AliPayController {
	private static final Logger logger = LoggerFactory.getLogger(AliPayController.class);

	@Autowired
	private AliPayService aliPayService;
	
	@RequestMapping("/xxx")
	@ResponseBody
	public ResponseJson unifiedorder(HttpServletRequest request,
			HttpServletResponse response){
		ResponseJson responseJson = new ResponseJson();
		try{
			String requestJson = IOUtils.toString(request.getInputStream(), "utf-8");
			logger.info("支付宝统一下单接口请求数据json:" + requestJson);
			
			responseJson = aliPayService.unifiedorder(requestJson);
			
			logger.info("支付宝统一下单接口响应数据json:"
					+ JSON.toJSONString(responseJson, SerializerFeature.WriteNullStringAsEmpty));
		}catch(Exception e){
			e.printStackTrace();
			logger.error("支付宝统一下单接口服务端异常,异常信息---" + e.getMessage(), e);
			return CommonUtil.createResponseJson(
					CodeMsg.SERVER_ERROR_CODE, CodeMsg.SERVER_ERROR_MSG, new JSONObject());
		}
		return responseJson;
	}
}

AliPayService接口类

package com.hisap.xql.api.service;

import java.math.BigDecimal;
import java.util.Map;

import com.hisap.xql.api.common.bean.ResponseJson;

/**
 * @Author: QijieLiu
 * @Description: 支付宝支付
 * @Date: Created in 11:29 2018/8/20
 */
public interface AliPayService {
	ResponseJson unifiedorder(String reqJson) throws Exception;
}

AliPayServiceImpl接口实现类

package com.hisap.xql.api.service.impl;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.hisap.xql.api.common.ali.AlipayConfig;
import com.hisap.xql.api.common.ali.AlipayRefund;
import com.hisap.xql.api.common.bean.ResponseJson;
import com.hisap.xql.api.common.constant.CodeMsg;
import com.hisap.xql.api.common.utils.Collections3;
import com.hisap.xql.api.common.utils.CommonUtil;
import com.hisap.xql.api.common.utils.StringUtil;
import com.hisap.xql.api.common.utils.VersionUtil;
import com.hisap.xql.api.dao.XqlOrderGoodsMapper;
import com.hisap.xql.api.model.XqlOrder;
import com.hisap.xql.api.model.XqlOrderGoods;
import com.hisap.xql.api.model.XqlOrderGoodsExample;
import com.hisap.xql.api.model.XqlVersion;
import com.hisap.xql.api.service.AliPayService;
import com.hisap.xql.api.service.CommonService;
import com.hisap.xql.api.service.ErpInterfaceService;
import com.hisap.xql.api.service.WeChatPayService;
import com.hisap.xql.api.service.XqlOrderService;

@Service
public class AliPayServiceImpl implements AliPayService {
	private static final Logger logger = LoggerFactory
			.getLogger(AliPayServiceImpl.class);
	
	@Autowired
	CommonService commonService;

	@Autowired
	XqlOrderService xqlOrderServiceImpl;

	@Autowired
	XqlOrderGoodsMapper xqlOrderGoodsMapper;

	@Autowired
	WeChatPayService weChatPayServiceImpl;
	
	@Autowired
	ErpInterfaceService erpInterfaceServiceImpl;

	@Override
	public ResponseJson unifiedorder(String reqJson) throws Exception {
		ResponseJson responseJson = new ResponseJson();
		
		if (StringUtil.isEmpty(reqJson)) {
			return CommonUtil.createResponseJson(CodeMsg.PARAM_CHECK_ERROR_CODE, "请求参数不能为空", new JSONObject());
		}
		/**获取请求参数*/
		JSONObject reqObj = JSON.parseObject(reqJson);
		/**版本号比较*/
		String appVersion = reqObj.getString("appVersion");
		if (StringUtil.isEmpty(appVersion)) {
			return CommonUtil.createResponseJson(CodeMsg.PARAM_CHECK_ERROR_CODE, "请求参数appVersion不能为空", new JSONObject());
		}
		XqlVersion xqlVersion = commonService.selectXqlVersion();
		if (xqlVersion != null && VersionUtil.compareVersion(xqlVersion.getVersionId(), appVersion) > 0) {
			return CommonUtil.createResponseJson(CodeMsg.FORCE_APP_VERSION_UPDATE_CODE, xqlVersion.getVersionUrl(), new JSONObject());
		}
		
		String orderNoStr = reqObj.getString("orderNo");
		if (StringUtil.isEmpty(orderNoStr)) {
			return CommonUtil.createResponseJson(CodeMsg.PARAM_CHECK_ERROR_CODE, "请求参数orderNo不能为空", new JSONObject());
		}
		
		BigDecimal orderNo = new BigDecimal(orderNoStr);

		/** 订单主信息 */
		XqlOrder xqlOrder = xqlOrderServiceImpl
				.selectXqlOrderByOrderNo(orderNo);
		if (xqlOrder == null) {
			return CommonUtil.createResponseJson(CodeMsg.ORDER_NOT_EXIST_CODE,
					CodeMsg.ORDER_NOT_EXIST_MSG, new JSONObject());
		}

		/** 订单明细信息 */
		XqlOrderGoodsExample xqlOrderGoodsExample = new XqlOrderGoodsExample();
		XqlOrderGoodsExample.Criteria criteria = xqlOrderGoodsExample
				.createCriteria();
		criteria.andOrderNoEqualTo(orderNo);

		List<XqlOrderGoods> xqlOrderGoodsList = xqlOrderGoodsMapper
				.selectByExample(xqlOrderGoodsExample);
		if (Collections3.isEmpty(xqlOrderGoodsList)) {
			return CommonUtil.createResponseJson(
					CodeMsg.ORDER_ITEM_NOT_EXIST_CODE,
					CodeMsg.ORDER_ITEM_NOT_EXIST_MSG, new JSONObject());
		}
		XqlOrderGoods xqlOrderGoods = xqlOrderGoodsList.get(0);
		
		/** 验证库存与优惠券接口 */
		responseJson = erpInterfaceServiceImpl.checkStockAndCouponBeforePay(orderNo);
		if(!responseJson.getCode().equalsIgnoreCase(CodeMsg.SUCCESS_CODE)){
			return responseJson;
		}
		
		if(xqlOrder.getOrderAmount() == 0){
			XqlOrder xqlOrder1 = new XqlOrder();
			xqlOrder1.setOrderNo(orderNo);
			if(xqlOrder.getDeliveryType() == 0){
				xqlOrder1.setOrderStatus(302);
				xqlOrder1.setSelfDeliveryStatus((short) 0);
			}else{
				xqlOrder1.setOrderStatus(201);
			}
			xqlOrder1.setPayStatus((short) 1);
			xqlOrderServiceImpl.updateXqlOrderByOrderNo(xqlOrder1);
			
			return CommonUtil.createResponseJson(
					CodeMsg.SUCCESS_CODE, CodeMsg.SUCCESS_MSG, new JSONObject());
		}
		
		// 实例化客户端
		AlipayClient alipayClient = new DefaultAlipayClient(
				AlipayConfig.UNIFIEDORDER_URL, AlipayConfig.APP_ID,
				AlipayConfig.APP_PRIVATE_KEY, AlipayConfig.FORMAT,
				AlipayConfig.CHARSET, AlipayConfig.APP_PUBLIC_KEY,
				AlipayConfig.SIGNTYPE);
		// 实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay
		AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
		// SDK已经封装掉了公共参数,这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
		AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
		model.setBody(xqlOrderGoods.getGoodsName());
		model.setSubject(xqlOrderGoods.getGoodsName());
		model.setOutTradeNo(orderNo.toString());
		model.setTimeoutExpress(AlipayConfig.TIMEOUT_EXPRESS);
		double totalAmount = (double)xqlOrder.getOrderAmount()/100;
		model.setTotalAmount(String.valueOf(totalAmount));
		model.setProductCode(xqlOrderGoods.getSku().toString());
		request.setBizModel(model);
		request.setNotifyUrl(AlipayConfig.NOTIFY_URL);
		try {
			// 这里和普通的接口调用不同,使用的是sdkExecute
			AlipayTradeAppPayResponse response = alipayClient
					.sdkExecute(request);
			// 就是orderString 可以直接给客户端请求,无需再做处理。
			String message = response.getBody();
			Map<String, String> resMap = new HashMap<String, String>();
			resMap.put("payCode", message);
			logger.info("支付宝统一下单返回数据:" + message);
			responseJson = CommonUtil.createResponseJson(CodeMsg.SUCCESS_CODE,
					CodeMsg.SUCCESS_MSG, resMap);
		} catch (AlipayApiException e) {
			e.printStackTrace();
			logger.error("支付宝统一下单接口服务端异常,异常信息---" + e.getMessage(), e);
			return CommonUtil.createResponseJson(CodeMsg.SERVER_ERROR_CODE,
					CodeMsg.SERVER_ERROR_MSG, new JSONObject());
		}
		return responseJson;
	}

}

好了,支付宝生成APP支付订单就已经完成了,下一章讲述支付宝异步结果通知接口开发。

猜你喜欢

转载自blog.csdn.net/Jay_1989/article/details/82347563