【支付宝支付】Java实现支付宝手机网站支付流程

前言

微信登录网页授权与APP授权
微信JSAPI支付
微信APP支付
微信APP和JSAPI退款
支付宝手机网站支付
支付宝APP支付
支付宝退款
以上我都放到个人公众号,搜一搜:JAVA大贼船,文末有公众号二维码!觉得个人以后开发会用到的可以关注一下哦!少走点弯路…

官方文档

支付宝手机网站支付没有微信支付那么琐碎(这里真的是想吐槽一下wxpay,配置太多了,文档阅读性也不友好!!),支付宝官方文档已经写得挺详细了,所以本文不对参数做详细的解释

开放能力文档:

https://opendocs.alipay.com/open/203/107084

手机网站支付api

https://opendocs.alipay.com/apis/api_1/alipay.trade.wap.pay

开发准备工作

  • 创建应用

开发者使用支付宝账号登录开放平台(需实名认证的支付宝账号),根据实际需求创建应用(如“支付应用”)。

备注:创建应用时的应用状态为“开发中”,无法在线上正式调用接口。

  • 填写应用基础信息
  • 添加应用功能
  • 配置应用环境
  • 应用申请上线,等待审核

代码实现

引入依赖
	<!-- 支付宝支,基础jdk -->
		<dependency>
			<groupId>com.alipay.sdk</groupId>
			<artifactId>alipay-sdk-java</artifactId>
			<version>4.9.5.ALL</version>
		</dependency>
参数配置

application.yml

# 支付宝相关
ALIPAY:
# 应用ID
 APP_ID: 
 # 应用私钥
 APP_PRIVATE_KEY: 
 #应用公钥
 APP_PUBLIC_KEY: 
 # 支付宝公钥
 ALIPAY_PUBLIC_KEY: 
 # 统一签名算法
 SIGN_TYPE: RSA2
 # 统一字符
 CHARSET: utf-8
 # 返回数据格式
 FORMAT: json
 # 支付基础API
 SERVER_URL: https://openapi.alipay.com/gateway.do
 #支付宝支付回调地址
 ALIPAY_NOTIFY_URL: 
 # 支付宝H5收银台会自动跳转回商户return_url指定的页面。
 RETURN_URL:
 # 支付宝Api版本
 API_VERSION: 1.0
  # 产品码 
 PROD_CODE: 
 # 终端信息
 TERMINAL_INFO: 
 # 终端信息类型
 TERMINAL_TYPE: 

YmlParament

   //支付宝相关
   @Value("${ALIPAY.APP_ID}")
   private String appId;

   @Value("${ALIPAY.APP_PRIVATE_KEY}")
   private String appPrivatekey;

   @Value("${ALIPAY.APP_PUBLIC_KEY}")
   private String appPublickey;

   @Value("${ALIPAY.ALIPAY_PUBLIC_KEY}")
   private String alipayPublickey;

   @Value("${ALIPAY.SIGN_TYPE}")
   private String signType;

   @Value("${ALIPAY.CHARSET}")
   private String charset;

   @Value("${ALIPAY.FORMAT}")
   private String format;

   @Value("${ALIPAY.SERVER_URL}")
   private String serverUrl;

   @Value("${ALIPAY.ALIPAY_NOTIFY_URL}")
   private String alipayNotifyUrl;

   @Value("${ALIPAY.RETURN_URL}")
   private String returnUrl;

   @Value("${ALIPAY.API_VERSION}")
   private String apiVersion;

   @Value("${ALIPAY.PROD_CODE}")
   private String prodCode;

   @Value("${ALIPAY.TERMINAL_INFO}")
   private String terminalInfo;

   @Value("${ALIPAY.TERMINAL_TYPE}")
   private String terminalType;

初始化支付宝支付配置

AlipayConfig

	@Autowired
   private YmlParament ymlParament;
   
   /**
    * 设置支付宝客户端
    * @return
    */
   @Bean
   public AlipayClient setAlipayClient() {
      return new DefaultAlipayClient(
            ymlParament.getServerUrl(), 
            ymlParament.getAppId(),
            ymlParament.getAppPrivatekey(), 
            ymlParament.getFormat(), 
            ymlParament.getCharset(), 
          //这里不要搞错,这里是应用公钥而不是支付宝公钥
            ymlParament.getAppPublickey(), 
            ymlParament.getSignType()
            ); 
   }
   
/**
	 * 设置网页支付请求基础参数
	 * @return
	 */
	@Bean
	public AlipayTradeWapPayRequest setAlipayTradeWapPayRequest() {
		AlipayTradeWapPayRequest atwpr = new AlipayTradeWapPayRequest();
		atwpr.setApiVersion(ymlParament.getApiVersion());
		atwpr.setProdCode(ymlParament.getProdCode());// 产品码
		atwpr.setTerminalInfo(ymlParament.getTerminalInfo());// 终端信息
		atwpr.setTerminalType(ymlParament.getTerminalType());// 终端信息类型
		return atwpr;
	}

手机网站支付

ZfbPay

	/**
	 * 手机网站支付
	 * 
	 * @param ac        支付宝客户端,传入 @Autowired AlipayClient
	 * @param rquest    基础参数,传入 @Autowired AlipayTradeWapPayRequest
	 * @param returnUrl 付款成功后跳转的页面
	 * @param notifyUrl 付款成功后通知的页面或方法
	 * @param mode      实际参数,参考:https://opendocs.alipay.com/open/203/107090
	 */
	public static AlipayTradeWapPayResponse wapPay(AlipayClient ac, AlipayTradeWapPayRequest rquest, String returnUrl,
			String notifyUrl, AlipayTradeWapPayModel mode) throws AlipayApiException {
		rquest.setBizModel(mode);
		rquest.setReturnUrl(returnUrl);
		rquest.setNotifyUrl(notifyUrl);
		return ac.pageExecute(rquest);
	}

	/**
	 * 手机网站支付,处理业务参数
	 */
	public static AlipayTradeWapPayResponse wapPay(AlipayClient ac, AlipayTradeWapPayRequest rquest, String returnUrl,
			String notifyUrl, String orderNo,String subject,String orderAmount) throws AlipayApiException {
		AlipayTradeWapPayModel mode = new AlipayTradeWapPayModel();
		mode.setOutTradeNo(orderNo);
		mode.setSubject(subject);
		mode.setTotalAmount(orderAmount);
		return wapPay(ac, rquest, returnUrl, notifyUrl, mode);
	}

/**
	 * 支付宝支付回调验证签名
	 * 验证签名;参考:https://opendocs.alipay.com/open/203/105286
	 * @param params       参数
	 * @param alipayPublickey 传入支付宝公钥
	 * @return true 正确 false 失败
	 * @throws AlipayApiException
	 */
	public static boolean rsaCheckV1(Map<String, String> params, String alipayPublickey) throws AlipayApiException {
		return AlipaySignature.rsaCheckV1(params, alipayPublickey, "utf-8", "RSA2");
	}

服务层(业务逻辑略)

 	@Autowired
    private AlipayClient alipayClient;
    @Autowired
    private AlipayTradeWapPayRequest alipayTradeWapPayRequest;	


	@Transactional
    @Override
    public String insertAlipayH5PayInfo(String sendOrderNo,String subject, String orderAmount){
        try {
            AlipayTradeWapPayResponse alipayTradeWapPayResponse = ZfbPay.wapPay(alipayClient, alipayTradeWapPayRequest, ymlParament.getReturnUrl(),
                    ymlParament.getAlipayNotifyUrl(), sendOrderNo, subject, orderAmount);
            /* 获取页面成功 */
            if (!alipayTradeWapPayResponse.isSuccess()) {
                throw new RuntimeException(alipayTradeWapPayResponse.getMsg());
            }
            return alipayTradeWapPayResponse.getBody();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

controller(略)

到这里支付宝支付就成功了,是不是相当微信支付简单多了_,接下来支付宝支付成功就会回调页面和服务端啦

支付宝回调通知

官方文档:https://opendocs.alipay.com/open/203/105286

    @ApiOperation("支付宝回调")
    @PostMapping("callback")
    public String callback(HttpServletRequest request) throws Exception {
        Object object = new Object();
        Map<String, String> params = convertRequestParamsToMap(request);
        log.info("支付宝回调:已回调,参数为====" + params);
           try {
              checkCallbackAlipay(params);
               /*处理一些业务*/
            } catch (Exception e) {
                e.printStackTrace();
            }
            return ZfbUtils.RETURN_SUCCESS;
        }
    }

/**
	 * 校验签名
	 *验签文档:https://opendocs.alipay.com/open/203/105286
	 */
    private void checkCallbackAlipay(Map<String, String> params) throws Exception {
        if (!"TRADE_SUCCESS".equals(params.get("trade_status"))) {
            throw new Exception("支付宝支付失败!");
        }
        //校验签名
        if (!ZfbPay.rsaCheckV1(params, ymlParament.getAlipayPublickey())) {
            throw new Exception("支付宝回调签名认证失败");
        }
        //校验一些业务逻辑
        //订单是否支付重复
        //判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额)
    	//.....
        // 校验通知中的seller_id(或者seller_email)是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email),
        // 验证app_id是否为该商户本身。
        if (!params.get("app_id").equals(ymlParament.getAppId())) {
            throw new Exception("APPID不对!");
        }
    }

/**
	 * 获取支付宝回调参数
	 */
private static Map<String, String> convertRequestParamsToMap(HttpServletRequest request) {
		Map<String, String> retMap = new HashMap<String, String>();
		Set<Map.Entry<String, String[]>> entrySet = request.getParameterMap().entrySet();
		for (Map.Entry<String, String[]> entry : entrySet) {
			String name = entry.getKey();
			String[] values = entry.getValue();
			int valLen = values.length;
			if (valLen == 1) {
				retMap.put(name, values[0]);
			} else if (valLen > 1) {
				StringBuilder sb = new StringBuilder();
				for (String val : values) {
					sb.append(",").append(val);
				}
				retMap.put(name, sb.toString().substring(1));
			} else {
				retMap.put(name, "");
			}
		}
		return retMap;
	}
交易查询

若不想在支付回调时候去做签名校验,那我们可以主动去查询这笔订单是否支付成功

 /*查询订单是否支付成功*/
AlipayTradeQueryResponse response = orderQuery(ac, params.get("out_trade_no"));
                if (!"TRADE_SUCCESS".equals(response.getTradeStatus())){
                    throw new Exception("<==支付宝支付失败==>订单号为【"+ params.get("out_trade_no")+ "】的订单");
                }

/**
	 * 交易查询接口,处理业务参数	 						https://opendocs.alipay.com/apis/api_1/alipay.trade.query#%E5%93%8D%E5%BA%94%E5%8F%82%E6%95%B0	
     * @param outTradeNo 订单号
	 * @return
	 * @throws AlipayApiException
	 */
	public static AlipayTradeQueryResponse orderQuery(AlipayClient ac , String outTradeNo) throws Exception {
		AlipayTradeQueryModel model = new AlipayTradeQueryModel();
		model.setOutTradeNo(outTradeNo);
		AlipayTradeQueryResponse response = tradeQuery(ac,model);
		if(!response.isSuccess()){
			throw new Exception("调用支付宝查询接口失败");
		}
		return response;
	}

/*交易查询接口*/
	public static AlipayTradeQueryResponse tradeQuery(AlipayClient ac,AlipayTradeQueryModel model) throws AlipayApiException{
		AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
		request.setBizModel(model);
		return ac.execute(request);
	}

【支付宝支付】Java实现支付宝手机网站支付流程_第1张图片

你可能感兴趣的:(支付宝支付)