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

讲述开发之前,先吐槽一下支付宝的官方文档,做的真乱,看的一头雾水,没有微信那么简单、明了。支付宝接口的调用和普通接口的调用不一样,使用的是支付宝官方的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_idString32支付宝分配给开发者的应用ID2014072300007148
methodString128接口名称alipay.trade.app.pay
formatString40仅支持JSONJSON
charsetString10请求使用的编码格式,如utf-8,gbk,gb2312等utf-8
sign_typeString10商户生成签名字符串所使用的签名算法类型,目前支持RSA2和RSA,推荐使用RSA2RSA2
signString256商户请求参数的签名串,详见签名详见示例
timestampString19发送请求的时间,格式"yyyy-MM-dd HH:mm:ss"2014-07-24 03:07:50
versionString3调用的接口版本,固定为:1.01.0
notify_urlString256支付宝服务器主动通知商户服务器里指定的页面http/https路径。建议商户使用httpshttps://api.xx.com/receive_notify.htm
biz_contentString-业务请求参数的集合,最大长度不限,除公共参数外所有请求参数都必须放在这个参数中传递,具体参照各产品快速接入文档 

1.2业务参数

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

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要使用Java实现支付宝App支付,需要遵循以下步骤: 1. 获取支付宝开发者账号并创建应用程序,获取应用程序的APPID、私钥和公钥。 2. 引入支付宝SDK,可通过maven等方式引入。 3. 在应用程序中实现调用支付宝SDK的代码,具体代码如下: ```java //构造支付订单信息 String orderInfo = getOrderInfo("测试的商品", "该测试商品的详细描述", "0.01"); //对支付订单信息进行签名 String sign = sign(orderInfo, privateKey); //将签名后的支付订单信息和应用程序的APPID拼接成最终的支付请求参数 String payInfo = orderInfo + "&sign=\"" + sign + "\"&" + getSignType(); //调用支付宝SDK发起支付请求 final PayTask payTask = new PayTask(activity); String result = payTask.pay(payInfo, true); //处理支付结果 final PayResult payResult = new PayResult(result); final String resultStatus = payResult.getResultStatus(); if (TextUtils.equals(resultStatus, "9000")) { //支付成功 } else { //支付失败或取消 } ``` 4. 实现获取支付订单信息、签名和签名类型等方法,具体代码如下: ```java //获取支付订单信息 public static String getOrderInfo(String subject, String body, String price) { //构造支付订单信息 Map<String, String> params = new HashMap<>(); params.put("app_id", APPID); params.put("biz_content", "{\"timeout_express\":\"30m\",\"product_code\":\"QUICK_MSECURITY_PAY\",\"total_amount\":\"" + price + "\",\"subject\":\"" + subject + "\",\"body\":\"" + body + "\",\"out_trade_no\":\"" + getOutTradeNo() + "\"}"); params.put("charset", "utf-8"); params.put("method", "alipay.trade.app.pay"); params.put("sign_type", "RSA2"); params.put("timestamp", getCurrentTime()); params.put("version", "1.0"); return buildOrderParam(params); } //对支付订单信息进行签名 public static String sign(String content, String privateKey) { try { PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(Base64.decode(privateKey, Base64.DEFAULT)); KeyFactory keyf = KeyFactory.getInstance("RSA"); PrivateKey priKey = keyf.generatePrivate(priPKCS8); java.security.Signature signature = java.security.Signature.getInstance("SHA256WithRSA"); signature.initSign(priKey); signature.update(content.getBytes("utf-8")); byte[] signed = signature.sign(); return Base64.encodeToString(signed, Base64.DEFAULT); } catch (Exception e) { e.printStackTrace(); } return null; } //获取签名类型 public static String getSignType() { return "RSA2"; } //获取当前时间戳 public static String getCurrentTime() { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); sdf.setTimeZone(TimeZone.getTimeZone("GMT+8")); return sdf.format(new Date()); } //生成唯一的支付订单号 public static String getOutTradeNo() { SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss"); Date date = new Date(); String key = format.format(date); Random r = new Random(); key += r.nextInt(1000); return key; } //将支付请求参数拼接成字符串 public static String buildOrderParam(Map<String, String> map) { StringBuilder sb = new StringBuilder(); for (Map.Entry<String, String> entry : map.entrySet()) { sb.append(entry.getKey()) .append("=") .append(entry.getValue()) .append("&"); } String result = sb.toString(); return result.substring(0, result.length() - 1); } ``` 以上就是Java实现支付宝App支付的基本步骤和代码示例。需要注意的是,支付宝SDK的使用可能会涉及到支付宝的服务协议和隐私协议,开发者应该仔细阅读并遵守相关规定。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值