Springboot寫服務端App集成第三方支付寶支付(二次修改)

1.省略以下過程

1.1、在支付寶開發者平臺創建app應用並獲取APPID
1.2、配置密鑰
1.3、下載服務端SDK
下載服務端SDK
參數說明

2.application.yml文件的配置如下(只需要這些就夠了)

#支付寶支付配置
#APPID 商戶appid 
#RSA_PRIVATE_KEY 私鑰 pkcs8格式的
#notify_url 服務器異步通知頁面路徑 需http://或者https://格式的完整路徑,不能加?id=123這類自定義參數,必須外網可以正常訪問
#return_url 頁面跳轉同步通知頁面路徑 需http://或者https://格式的完整路徑,不能加?id=123這類自定義參數,必須外網可以正常訪問 商戶可以自定義同步跳轉地址
#URL 請求網關地址
#CHARSET 編碼
#FORMAT 返回格式
#ALIPAY_PUBLIC_KEY 支付寶公鑰
#SIGNTYPE RSA2


alipayconfig:
   appid: 2011111296241128
   rsa_private_key: MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCYfefhdTCK9uyJGOM3JYlI5PyDgbvTwSB84uGALP6ICJv5bT2+huzdLnImpudoAQVdGS5H3c0NcoWSlQlvFedaRNGEt5O+WfMcP0oLfVhKPmUMNsGOLCNLUnRjQfhRLqdr5kmY+AUBZlATtbNBK59Ye6KJ0uMp9X/AWyXa2GMR9Le+C9SYQ8vqk7ddIBPi0zYKWZPMI2JSvXsh2fB889EAFsO+Y9n7+G1yOC1K8p/JUwPu6gT6tXSlBoIypUrs/fZeyp4OmOU+bq2alZyg3c2T2oQIWYkwMt8WUliI4pRn/wMhga3wbbHWNRdGl4fptbWRcTLjQ0M5LmsJF67DlKd/AgMBAAE11111111111111111114N2xAxGOG6TeyKuyzBWWWCxFftFEt65q0YuDvoUrAotog9iyz5gXuHR/S5CHhJMHIC8FyKZI91iYFg+uWaAZlceCpFn7RDJKureEpE+mj3ryRICxvIcoiIZLEv8BJZ+1oQXbQK4pIPfkejEGQeHXAIBYcWJJL4geNDs/vCRynBbjXGHjOxL0XUw9QjrLcxcnEOyDs6ZLuulkemo0phOoW2YrbVoO7JQSLaqKut3YW8RMk1fhuC8lV4QKBgQDfvnqvD9hqEA+25Mao3MSyNMiwD4gA7zqOltEQaMnMxsGbEby6d0nmZet3m3YwFs6pAs2JDQrOa/j4sayMc1p16YCtGz+WFuGHAME+JHNNrAuSdNcpR+SyR5eq6OZFMfeUegN/8M2LRW8Kzp/gBy46i+o48ln/BsWN52OybpVjHQKBgQCuecjCIbtDCOC8YSFVIDBPFHTt/ZbhCJbd/JwiKvIFHVPDOrCr+A4CWsIFhxfO/qEtRMMnFxC+n5B9afIvYspxfbxnEDz4/w47ZAIUT8jo+b01x83jl/8wDDs+n1fuL8Acf8OAaoHTZlV3NtFxmPN9O8MhEtis8AMOQioTZaK2SwKBgEzGN6LKdSAv0rSXW/OljXj408RWD/0CGb3D0okm69fwe46ST4hMVndQkbPBDJUDvnYQGCbm6sZaFlx/2w12p5u+PAEqUG9X+pswjx6bs1T7rBzdKtdna/ogxtJGiH1F4AZ6t6i3IFChyrCSphlhXWOJjx1rS6ZO1IsU0wjvGSOhAoGAUuOao9fgnh02n2hJrKZpLPicAICsUGaDPh0HlBfw+MsRAzv7uQdUqHuzl2qxve4sZlQ3nnePxfAKdfqCS07UvIwumIwXW3fYrBB8CGhLG5uh703oG4sXeh0lfD+5R3g5/ZAZMgXnfaYtTkClyiEO9F0S+8B3Xdl8qiZ21NZBMfcCgYBktqNuymf5zstIqHfSThhzZTbiFbHRRMMY4vYcjU90eDi0FA/jg7jkXuAkZ0PZRnlHiaVKbmJeSYBSeYLWSfEK82ABILTu4YSvXj/EC5g6FrblNKqukKE7a5bVrGXiZEznTVMocz9G5Rxrjt5sjRVUyfyRN800mM/vnHYYs1NI9A==
   notify_url: http://域名:端口/api/alinotifyUrl
   return_url: http://域名:端口/alipay/returnUrl
   url: https://openapi.alipay.com/gateway.do
   charset: UTF-8
   format: JSON
   alipay_public_key: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv9I0K84RWWoJm26xHNPBGDHBPxxkjwaHgMNPNqjVXfD36n57yuLRAu8207Dar+Nu04bktrKJ6XgKBXMZ9Wgbxvc4YtBqFAkvxY9nTdSAolwZgR0/75hR2IrkAPwdv31aOI6v5sMXD91Ksts9tDYZqYobIHWAJ/gxwG11uoSA3mx0BXWXev222222KCG8buFpFM11M1Im2SiocuKY28E66blZw6tqQ71Il3I9lk8kB2rwnBrfx3gVHDbm15OCfNzSTB6TvjfVo+Q0RyQIgTly7cpZY5QFEgINTDq25EqKghzS+v09ytRDOyWDiLKnrzqFe8g0fwUIFqxz4kw4DNhRYQHQIDAQAB
   signtype: RSA2

3.支付寶支付配置文件

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

/**
 * 支付寶支付配置文件
 * @author Administrator
 *
 */
@Component
@ConfigurationProperties(prefix="alipayconfig")
public class AlipayProperties {

	private String appid; // 商戶appid
	
	private String rsa_private_key; // 私鑰 pkcs8格式的
	
	private String notify_url; // 服務器異步通知頁面路徑 需http://或者https://格式的完整路徑,不能加?id=123這類自定義參數,必須外網可以正常訪問
	
	private String return_url; // 頁面跳轉同步通知頁面路徑 需http://或者https://格式的完整路徑,不能加?id=123這類自定義參數,必須外網可以正常訪問 商戶可以自定義同步跳轉地址
	
	private String url; // 請求網關地址
	
	private String charset; // 編碼
	
	private String format; // 返回格式
	
	private String alipay_public_key; // 支付寶公鑰
	
	private String signtype;  // RSA2  簽名方式

	public String getAppid() {
		return appid;
	}

	public void setAppid(String appid) {
		this.appid = appid;
	}

	public String getRsa_private_key() {
		return rsa_private_key;
	}

	public void setRsa_private_key(String rsa_private_key) {
		this.rsa_private_key = rsa_private_key;
	}

	public String getNotify_url() {
		return notify_url;
	}

	public void setNotify_url(String notify_url) {
		this.notify_url = notify_url;
	}

	public String getReturn_url() {
		return return_url;
	}

	public void setReturn_url(String return_url) {
		this.return_url = return_url;
	}

	public String getUrl() {
		return url;
	}

	public void setUrl(String url) {
		this.url = url;
	}

	public String getCharset() {
		return charset;
	}

	public void setCharset(String charset) {
		this.charset = charset;
	}

	public String getFormat() {
		return format;
	}

	public void setFormat(String format) {
		this.format = format;
	}

	public String getAlipay_public_key() {
		return alipay_public_key;
	}

	public void setAlipay_public_key(String alipay_public_key) {
		this.alipay_public_key = alipay_public_key;
	}

	public String getSigntype() {
		return signtype;
	}

	public void setSigntype(String signtype) {
		this.signtype = signtype;
	}

	@Override
	public String toString() {
		return "AlipayProperties [appid=" + appid + ", rsa_private_key=" + rsa_private_key + ", notify_url="
				+ notify_url + ", return_url=" + return_url + ", url=" + url + ", charset=" + charset + ", format="
				+ format + ", alipay_public_key=" + alipay_public_key + ", signtype=" + signtype + "]";
	}
}

4.maven添加jar依賴

<dependency>
    <groupId>alipay-sdk-java</groupId>
    <artifactId>alipay</artifactId>
    <version>3.0.1</version>
</dependency>
<dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.38</version>
 </dependency>

這裏是將支付寶java sdk jar包轉成maven本地倉庫的jar包
具體操作步驟請看我另外一篇文章
轉成maven到本地倉庫的jar包

5.工具類

可以去下載我上傳的資源
我項目的使用的工具類

package io.renren.common.utils;

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

/**
 * 返回數據
 * 
 * @author chenshun
 * @email [email protected]
 * @date 2016年10月27日 下午9:59:27
 */
public class R extends HashMap<String, Object> {
	private static final long serialVersionUID = 1L;
	
	public R() {
		put("code", 0);
		put("msg", "success");
	}
	
	public static R error() {
		return error(500, "未知異常,請聯繫管理員");
	}
	
	public static R error(String msg) {
		return error(500, msg);
	}
	
	public static R error(int code, String msg) {
		R r = new R();
		r.put("code", code);
		r.put("msg", msg);
		return r;
	}

	public static R ok(String msg) {
		R r = new R();
		r.put("msg", msg);
		return r;
	}
	
	public static R ok(Map<String, Object> map) {
		R r = new R();
		r.putAll(map);
		return r;
	}
	
	public static R ok() {
		return new R();
	}

	@Override
	public R put(String key, Object value) {
		super.put(key, value);
		return this;
	}
}

	
	/**
	 * 字符串轉日期對象
	 * @param str
	 * @param format
	 * @return
	 * @throws Exception
	 */
	public static Date formatString(String str,String format) throws Exception{
		if(StringUtil.isEmpty(str)){
			return null;
		}
		SimpleDateFormat sdf=new SimpleDateFormat(format);
		return sdf.parse(str);
	}
	
	/**
	 * 生成當前日期時間串
	 * @return
	 * @throws Exception
	 */
	public static String getCurrentDateStr(){
		Date date=new Date();
		SimpleDateFormat sdf=new SimpleDateFormat("yyyyMMddhhmmssSSS");
		return sdf.format(date);
	}
	/**
	 * 生成當前日期時間串
	 * @param args
	 * @throws Exception
	 */
	public static String getCurrentDateString() {
		Date d = new Date();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");
		String s = sdf.format(d);
		return s;
	}
	public static void main(String[] args) throws Exception {
		System.out.println(getCurrentDateString());
	}
	
}


package io.renren.common.utils;

import org.apache.commons.lang.StringUtils;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 日期處理
 * 
 * @author chenshun
 * @email [email protected]
 * @date 2016年12月21日 下午12:53:33
 */
public class DateUtils {
	/** 時間格式(yyyy-MM-dd) */
	public final static String DATE_PATTERN = "yyyy-MM-dd";
	/** 時間格式(yyyy-MM-dd HH:mm:ss) */
	public final static String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";

    /**
     * 日期格式化 日期格式爲:yyyy-MM-dd
     * @param date  日期
     * @return  返回yyyy-MM-dd格式日期
     */
	public static String format(Date date) {
        return format(date, DATE_PATTERN);
    }

    /**
     * 日期格式化 日期格式爲:yyyy-MM-dd
     * @param date  日期
     * @param pattern  格式,如:DateUtils.DATE_TIME_PATTERN
     * @return  返回yyyy-MM-dd格式日期
     */
    public static String format(Date date, String pattern) {
        if(date != null){
            SimpleDateFormat df = new SimpleDateFormat(pattern);
            return df.format(date);
        }
        return null;
    }

    /**
     * 字符串轉換成日期
     * @param strDate 日期字符串
     * @param pattern 日期的格式,如:DateUtils.DATE_TIME_PATTERN
     */
    public static Date stringToDate(String strDate, String pattern) {
        if (StringUtils.isBlank(strDate)){
            return null;
        }

        DateTimeFormatter fmt = DateTimeFormat.forPattern(pattern);
        return fmt.parseLocalDateTime(strDate).toDate();
    }

    /**
     * 根據週數,獲取開始日期、結束日期
     * @param week  週期  0本週,-1上週,-2上上週,1下週,2下下週
     * @return  返回date[0]開始日期、date[1]結束日期
     */
    public static Date[] getWeekStartAndEnd(int week) {
        DateTime dateTime = new DateTime();
        LocalDate date = new LocalDate(dateTime.plusWeeks(week));

        date = date.dayOfWeek().withMinimumValue();
        Date beginDate = date.toDate();
        Date endDate = date.plusDays(6).toDate();
        return new Date[]{beginDate, endDate};
    }

    /**
     * 對日期的【秒】進行加/減
     *
     * @param date 日期
     * @param seconds 秒數,負數爲減
     * @return 加/減幾秒後的日期
     */
    public static Date addDateSeconds(Date date, int seconds) {
        DateTime dateTime = new DateTime(date);
        return dateTime.plusSeconds(seconds).toDate();
    }

    /**
     * 對日期的【分鐘】進行加/減
     *
     * @param date 日期
     * @param minutes 分鐘數,負數爲減
     * @return 加/減幾分鐘後的日期
     */
    public static Date addDateMinutes(Date date, int minutes) {
        DateTime dateTime = new DateTime(date);
        return dateTime.plusMinutes(minutes).toDate();
    }

    /**
     * 對日期的【小時】進行加/減
     *
     * @param date 日期
     * @param hours 小時數,負數爲減
     * @return 加/減幾小時後的日期
     */
    public static Date addDateHours(Date date, int hours) {
        DateTime dateTime = new DateTime(date);
        return dateTime.plusHours(hours).toDate();
    }

    /**
     * 對日期的【天】進行加/減
     *
     * @param date 日期
     * @param days 天數,負數爲減
     * @return 加/減幾天後的日期
     */
    public static Date addDateDays(Date date, int days) {
        DateTime dateTime = new DateTime(date);
        return dateTime.plusDays(days).toDate();
    }

    /**
     * 對日期的【周】進行加/減
     *
     * @param date 日期
     * @param weeks 週數,負數爲減
     * @return 加/減幾周後的日期
     */
    public static Date addDateWeeks(Date date, int weeks) {
        DateTime dateTime = new DateTime(date);
        return dateTime.plusWeeks(weeks).toDate();
    }

    /**
     * 對日期的【月】進行加/減
     *
     * @param date 日期
     * @param months 月數,負數爲減
     * @return 加/減幾月後的日期
     */
    public static Date addDateMonths(Date date, int months) {
        DateTime dateTime = new DateTime(date);
        return dateTime.plusMonths(months).toDate();
    }

    /**
     * 對日期的【年】進行加/減
     *
     * @param date 日期
     * @param years 年數,負數爲減
     * @return 加/減幾年後的日期
     */
    public static Date addDateYears(Date date, int years) {
        DateTime dateTime = new DateTime(date);
        return dateTime.plusYears(years).toDate();
    }
    /**
     * 將日期轉換成十進制數字
     * @param expireDate
     * @return
     */
    public static int getSecondsFromDate(String expireDate) {
		if (expireDate == null || expireDate.trim().equals(""))
			return 0;
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");
		Date date = null;
		try {
			date = sdf.parse(expireDate);
			return  (int)(date.getTime()/1000);
		} catch (ParseException e) {
			e.printStackTrace();
			return 0;
		}
	}
   
}

5.請求支付寶支付

/**
	 * 支付請求
	 * 
	 * @param alipayTradeWapPayModel
	 * @param response
	 * @throws IOException
	 * @throws ServletException
	 */
	@RequestMapping("/alipay")
	public R pay(TpOrder order, HttpServletRequest request, HttpServletResponse response)
			throws ServletException, Exception {
		// 獲取訂單號
		String orderNo = order.getOrderSn();
		// 訂單總價
		BigDecimal totalAmount = order.getTotalAmount();
		double price = totalAmount.doubleValue();
		System.out.println("price:" + price);
		String form = ""; // 生成支付表單
		// 封裝請求客戶端 // 實例化客戶端
		AlipayClient client = new DefaultAlipayClient(alipayProperties.getUrl(), alipayProperties.getAppid(),
				alipayProperties.getRsa_private_key(), alipayProperties.getFormat(), alipayProperties.getCharset(),
				alipayProperties.getAlipay_public_key(), alipayProperties.getSigntype());

		// 支付請求
		// 實例化具體API對應的request類,類名稱和接口名稱對應,當前調用接口名稱:alipay.trade.app.pay
		AlipayTradeAppPayRequest alipayRequest = new AlipayTradeAppPayRequest();
		// SDK已經封裝掉了公共參數,這裏只需要傳入業務參數。
		// 以下方法爲sdk的model入參方式(model和biz_content同時存在的情況下取biz_content)。
		AlipayTradePayModel model = new AlipayTradePayModel();
		// 描述信息 添加附加數據
		model.setProductCode("QUICK_MSECURITY_PAY"); // 設置銷售產品碼
		model.setOutTradeNo(orderNo); // 設置訂單號
		model.setSubject("--龍英app訂單支付--"); // 訂單名稱
		model.setTotalAmount("" + price + ""); // 支付總金額
		model.setBody("body"); // 設置商品描述
		model.setTimeoutExpress("30m"); // 超時關閉該訂單時間
		// model.setSellerId("[email protected]"); // 商家id
		alipayRequest.setBizModel(model);
		// 異步回調地址
		alipayRequest.setNotifyUrl(alipayProperties.getNotify_url());
		/* AlipayTradeAppPayResponse responses = */
		AlipayTradeAppPayResponse responses = client.sdkExecute(alipayRequest);
		form = responses.getBody();// 生成支付表單
		System.out.println(form); // 就是orderString 可以直接給客戶端請求,無需再做處理
		return R.ok().put("form", form);
	}

5.支付寶服務器異步通知

這個是提供給支付寶調用的接口 在*.yml文件中需要把這個接口完整路徑配置上去
接口裏面主要寫你的業務邏輯代碼
支付寶會多次請求這個接口 所以你需要在支付寶第一次成功請求完成後返回給支付寶請求成功的標識 )

/**
 * 支付寶服務器異步通知
 * 
 * @param request
 * @return
 */
@RequestMapping("/alinotifyUrl")
//@Transactional(isolation = Isolation.SERIALIZABLE)
public void notifyUrl(HttpServletRequest request,HttpServletResponse response) throws Exception {
	String result ="";
	BigDecimal platfor = null;
	System.out.println("11111111111111111111111111111111");
	logger.info("notifyUrl");
	// 獲取支付寶GET過來反饋信息
	Map<String, String> params = new HashMap<String, String>();
	Map<String, String[]> requestParams = request.getParameterMap();
	for (Iterator<String> 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] + ",";
		}
		/* valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8"); */

		params.put(name, valueStr);
		System.out.println("name:" + name + ",valueStr:" + valueStr);
	}

	boolean signVerified = AlipaySignature.rsaCheckV1(params, alipayProperties.getAlipay_public_key(),
			alipayProperties.getCharset(), alipayProperties.getSigntype()); // 調用SDK驗證簽名

	// 商戶訂單號
	String out_trade_no = request.getParameter("out_trade_no");
	// 交易狀態
	String trade_status = request.getParameter("trade_status");
	String trade_no = request.getParameter("trade_no");// 交易流水號
	if (signVerified) { // 驗證成功 更新訂單信息
		if (trade_status.equals("TRADE_FINISHED")) {
			logger.info("TRADE_FINISHED");
		}
		if (trade_status.equals("TRADE_SUCCESS")) {
			if (StringUtil.isNotEmpty(out_trade_no)) {
		             //業務邏輯處理
				//返回給支付寶的 說明接口處理成功 不然會一天24小時調用你接口
						result="success";
					}
					
				}
			}
			logger.info("TRADE_SUCCESS");
		}
		
	} else {
	//返回給支付寶的 說明接口處理失敗 會就行調接口
		result="fail";
		//下面代碼放在業務處理之後,不然業務代碼不會執行
		BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());  
		out.write(result.getBytes());  
		out.flush();  
	    out.close();
	}
	//下面代碼放在業務處理之後,不然業務代碼不會執行
	BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());  
	out.write(result.getBytes());  
	out.flush();  
    out.close();
}

調支付寶支付還是比較簡單的 微信就比較“構思”了,他的接口文檔寫的稀巴爛看得傷腦筋
下一篇文章 springboot寫服務端App集成第三方微信支付

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章