Parcourir la source

两斤苹果五毛钱

小柒2012 il y a 7 ans
Parent
commit
67a509f791

+ 10 - 0
.settings/org.eclipse.jdt.core.prefs

@@ -1,4 +1,14 @@
 eclipse.preferences.version=1
+org.eclipse.jdt.core.codeComplete.argumentPrefixes=
+org.eclipse.jdt.core.codeComplete.argumentSuffixes=
+org.eclipse.jdt.core.codeComplete.fieldPrefixes=
+org.eclipse.jdt.core.codeComplete.fieldSuffixes=
+org.eclipse.jdt.core.codeComplete.localPrefixes=
+org.eclipse.jdt.core.codeComplete.localSuffixes=
+org.eclipse.jdt.core.codeComplete.staticFieldPrefixes=
+org.eclipse.jdt.core.codeComplete.staticFieldSuffixes=
+org.eclipse.jdt.core.codeComplete.staticFinalFieldPrefixes=
+org.eclipse.jdt.core.codeComplete.staticFinalFieldSuffixes=
 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
 org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
 org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7

+ 81 - 19
pom.xml

@@ -1,21 +1,83 @@
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-  <modelVersion>4.0.0</modelVersion>
-  <groupId>com.itstyle.pay</groupId>
-  <artifactId>spring-boot-pay</artifactId>
-  <packaging>war</packaging>
-  <version>0.0.1-SNAPSHOT</version>
-  <name>spring-boot-pay Maven Webapp</name>
-  <url>http://maven.apache.org</url>
-  <dependencies>
-    <dependency>
-      <groupId>junit</groupId>
-      <artifactId>junit</artifactId>
-      <version>3.8.1</version>
-      <scope>test</scope>
-    </dependency>
-  </dependencies>
-  <build>
-    <finalName>spring-boot-pay</finalName>
-  </build>
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<groupId>com.itstyle.pay</groupId>
+	<artifactId>spring-boot-pay</artifactId>
+	<packaging>jar</packaging>
+	<version>0.0.1-SNAPSHOT</version>
+	<name>spring-boot-pay</name>
+	<url>http://maven.apache.org</url>
+
+	<properties>
+		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+	</properties>
+	<!-- spring-boot-starter-parent包含了大量配置好的依赖管理,在自己项目添加这些依赖的时候不需要写<version>版本号 -->
+	<parent>
+		<groupId>org.springframework.boot</groupId>
+		<artifactId>spring-boot-starter-parent</artifactId>
+		<version>1.5.2.RELEASE</version>
+	</parent>
+	<dependencies>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-web</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-test</artifactId>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-thymeleaf</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework</groupId>
+			<artifactId>springloaded</artifactId>
+		</dependency>
+		<!-- 支付宝 SDK-->
+		<dependency>
+		    <groupId>com.acts</groupId>
+		    <artifactId>alipay-trade-sdk</artifactId>
+		    <version>1.0.0</version>
+		</dependency>
+		<dependency>
+		    <groupId>com.acts</groupId>
+		    <artifactId>alipay-sdk-java</artifactId>
+		    <version>1.0.0</version>
+		</dependency>
+		<dependency>
+		    <groupId>org.apache.commons</groupId>
+		    <artifactId>commons-lang3</artifactId>
+		    <version>3.6</version>
+		</dependency>
+		<!-- json-lib -->
+		<dependency>
+		    <groupId>net.sf.json-lib</groupId>
+		    <artifactId>json-lib</artifactId>
+		    <version>2.4</version>
+		</dependency>
+	</dependencies>
+	<build>
+		<finalName>spring-boot-pay</finalName>
+		<plugins>
+			<!-- 打包项目 mvn clean package -->
+			<plugin>
+				<groupId>org.springframework.boot</groupId>
+				<artifactId>spring-boot-maven-plugin</artifactId>
+				<dependencies>
+					<!-- mvn spring-boot:run 热部署启动 -->
+					<dependency>
+						<groupId>org.springframework</groupId>
+						<artifactId>springloaded</artifactId>
+						<version>1.2.7.RELEASE</version>
+					</dependency>
+				</dependencies>
+			</plugin>
+		</plugins>
+	</build>
 </project>

+ 22 - 0
src/main/java/com/itstyle/Application.java

@@ -0,0 +1,22 @@
+package com.itstyle;
+
+import org.apache.log4j.Logger;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.context.annotation.ComponentScan;
+/**
+ * 支付主控
+ * 创建者 科帮网
+ * 创建时间	2017年7月27日
+ *
+ */
+@EnableAutoConfiguration
+@ComponentScan(basePackages={"com.itstyle.modules"})
+public class Application  {
+	private static final Logger logger = Logger.getLogger(Application.class);
+	
+	public static void main(String[] args) throws InterruptedException {
+		SpringApplication.run(Application.class, args);
+		logger.info("支付项目启动 ");
+	}
+}

+ 33 - 0
src/main/java/com/itstyle/common/constants/Constants.java

@@ -0,0 +1,33 @@
+package com.itstyle.common.constants;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.springframework.web.context.ContextLoader;
+
+public class Constants {
+	
+	/**系统启动初始化**/
+	public static Map<String, String> PAY_URL = new ConcurrentHashMap<String, String>();
+	
+	public static final String SF_FILE_SEPARATOR = System.getProperty("file.separator");//文件分隔符
+	public static final String SF_LINE_SEPARATOR = System.getProperty("line.separator");//行分隔符
+	public static final String SF_PATH_SEPARATOR = System.getProperty("path.separator");//路径分隔符
+	
+	
+	public static final String PATH = ContextLoader.getCurrentWebApplicationContext().getServletContext().getRealPath("/file")
+	         +Constants.SF_FILE_SEPARATOR;
+
+	public static final String QRCODE_PATH = PATH+"pay_qrCode"; 
+	
+	public static final String WEIXIN_BILL = "tradetime, ghid, mchid, submch, deviceid, wxorder, bzorder, openid, tradetype, tradestatus, bank, currency, totalmoney, redpacketmoney, wxrefund, bzrefund, refundmoney, redpacketrefund, refundtype, refundstatus, productname, bzdatapacket, fee, rate";
+	
+	public static final String PATH_BASE_INFO_XML = SF_FILE_SEPARATOR+"WEB-INF"+SF_FILE_SEPARATOR+"xmlConfig"+SF_FILE_SEPARATOR;
+	
+	public static final String CURRENT_USER = "UserInfo";
+	
+	public static final String SUCCESS = "success";
+	
+	public static final String FAIL = "fail";
+	
+}

+ 44 - 0
src/main/java/com/itstyle/common/constants/PayWay.java

@@ -0,0 +1,44 @@
+package com.itstyle.common.constants;
+/**
+ * 支付途径
+ * 创建者 科帮网
+ * 创建时间	2017年7月27日
+ *
+ */
+public enum PayWay {
+	PC("PC,平板",(short)1),MOBILE("手机",(short)2);
+	
+	private Short code;
+	private String name;
+	
+	private PayWay(String name, Short code) {
+		this.name = name;
+		this.code = code;
+	}
+
+	public static String getName(Short code,String name) {
+		for (PayWay c : PayWay.values()) {
+			if (c.getCode() == code) {
+				return c.name;
+			}
+		}
+		return null;
+	}
+	
+	public String getName() {
+		return name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	public short getCode() {
+		return code;
+	}
+
+	public void setCode(short code) {
+		this.code = code;
+	}
+
+}

+ 111 - 0
src/main/java/com/itstyle/common/model/Product.java

@@ -0,0 +1,111 @@
+package com.itstyle.common.model;
+import java.io.Serializable;
+/**
+ * 产品订单信息
+ * 创建者 科帮网
+ * 创建时间	2017年7月27日
+ *
+ */
+public class Product implements Serializable {
+	private static final long serialVersionUID = 1L;
+	private String productId;// 商品ID
+	private String body;// 商品描述
+	private String totalFee;// 总金额(单位是分)
+	private String outTradeNo;// 订单号(唯一)
+	private String spbillCreateIp;// 发起人IP地址
+	private String attach;// 附件数据主要用于商户携带订单的自定义数据
+	private Short payType;// 支付类型(1:支付宝 2:微信 3:银联)
+	private Short payWay;// 支付方式 (1:PC,平板 2:手机)
+	private String frontUrl;// 前台回调地址
+
+	public Product() {
+		super();
+	}
+
+	public Product(String productId, String body, String totalFee,
+			String outTradeNo, String spbillCreateIp, String attach,
+			Short payType, Short payWay, String frontUrl) {
+		super();
+		this.productId = productId;
+		this.body = body;
+		this.totalFee = totalFee;
+		this.outTradeNo = outTradeNo;
+		this.spbillCreateIp = spbillCreateIp;
+		this.attach = attach;
+		this.payType = payType;
+		this.payWay = payWay;
+		this.frontUrl = frontUrl;
+	}
+
+	public String getProductId() {
+		return productId;
+	}
+
+	public void setProductId(String productId) {
+		this.productId = productId;
+	}
+
+	public String getBody() {
+		return body;
+	}
+
+	public void setBody(String body) {
+		this.body = body;
+	}
+
+	public String getTotalFee() {
+		return totalFee;
+	}
+
+	public void setTotalFee(String totalFee) {
+		this.totalFee = totalFee;
+	}
+
+	public String getOutTradeNo() {
+		return outTradeNo;
+	}
+
+	public void setOutTradeNo(String outTradeNo) {
+		this.outTradeNo = outTradeNo;
+	}
+
+	public String getSpbillCreateIp() {
+		return spbillCreateIp;
+	}
+
+	public void setSpbillCreateIp(String spbillCreateIp) {
+		this.spbillCreateIp = spbillCreateIp;
+	}
+
+	public String getAttach() {
+		return attach;
+	}
+
+	public void setAttach(String attach) {
+		this.attach = attach;
+	}
+
+	public Short getPayType() {
+		return payType;
+	}
+
+	public void setPayType(Short payType) {
+		this.payType = payType;
+	}
+
+	public Short getPayWay() {
+		return payWay;
+	}
+
+	public void setPayWay(Short payWay) {
+		this.payWay = payWay;
+	}
+
+	public String getFrontUrl() {
+		return frontUrl;
+	}
+
+	public void setFrontUrl(String frontUrl) {
+		this.frontUrl = frontUrl;
+	}
+}

+ 160 - 0
src/main/java/com/itstyle/common/utils/CommonUtil.java

@@ -0,0 +1,160 @@
+package com.itstyle.common.utils;
+
+import java.math.BigDecimal;
+
+import org.apache.commons.lang3.StringUtils;
+
+public class CommonUtil {
+	/**
+	 * 除法
+	 */
+	public static BigDecimal divide(String arg1, String arg2) {
+		if (StringUtils.isEmpty(arg1)) {
+			arg1 = "0.0";
+		}
+		if (StringUtils.isEmpty(arg2)) {
+			arg2 = "0.0";
+		}
+		BigDecimal big3 = new BigDecimal("0.00");
+		if (Double.parseDouble(arg2) != 0) {
+			BigDecimal big1 = new BigDecimal(arg1);
+			BigDecimal big2 = new BigDecimal(arg2);
+			big3 = big1.divide(big2, 2, BigDecimal.ROUND_HALF_EVEN);
+		}
+		return big3;
+	}
+
+	/**
+	 * 乘法
+	 */
+	public static BigDecimal mul(String arg1, String arg2) {
+		if (StringUtils.isEmpty(arg1)) {
+			arg1 = "0.0";
+		}
+		if (StringUtils.isEmpty(arg2)) {
+			arg2 = "0.0";
+		}
+		BigDecimal big1 = new BigDecimal(arg1);
+		BigDecimal big2 = new BigDecimal(arg2);
+		BigDecimal big3 = big1.multiply(big2);
+		return big3;
+	}
+
+	/**
+	 * 减法
+	 */
+	public static BigDecimal sub(String arg1, String arg2) {
+		if (StringUtils.isEmpty(arg1)) {
+			arg1 = "0.0";
+		}
+		if (StringUtils.isEmpty(arg2)) {
+			arg2 = "0.0";
+		}
+		BigDecimal big1 = new BigDecimal(arg1);
+		BigDecimal big2 = new BigDecimal(arg2);
+		BigDecimal big3 = big1.subtract(big2);
+		return big3;
+	}
+
+	/**
+	 * 加法
+	 */
+	public static BigDecimal add(String arg1, String arg2) {
+		if (StringUtils.isEmpty(arg1)) {
+			arg1 = "0.0";
+		}
+		if (StringUtils.isEmpty(arg2)) {
+			arg2 = "0.0";
+		}
+		BigDecimal big1 = new BigDecimal(arg1);
+		BigDecimal big2 = new BigDecimal(arg2);
+		BigDecimal big3 = big1.add(big2);
+		return big3;
+	}
+
+	/**
+	 * 加法
+	 */
+	public static String add2(String arg1, String arg2) {
+		if (StringUtils.isEmpty(arg1)) {
+			arg1 = "0.0";
+		}
+		if (StringUtils.isEmpty(arg2)) {
+			arg2 = "0.0";
+		}
+		BigDecimal big1 = new BigDecimal(arg1);
+		BigDecimal big2 = new BigDecimal(arg2);
+		BigDecimal big3 = big1.add(big2);
+		return big3.toString();
+	}
+
+	/**
+	 * 四舍五入保留N位小数 先四舍五入在使用double值自动去零
+	 * 
+	 * @param arg
+	 * @param scare
+	 *            保留位数
+	 * @return
+	 */
+	public static String setScare(BigDecimal arg, int scare) {
+		BigDecimal bl = arg.setScale(scare, BigDecimal.ROUND_HALF_UP);
+		return String.valueOf(bl.doubleValue());
+	}
+
+	public static double setDifScare(double arg) {
+		BigDecimal bd = new BigDecimal(arg);
+		BigDecimal bl = bd.setScale(2, BigDecimal.ROUND_HALF_UP);
+		return Double.parseDouble(bl.toString());
+	}
+
+	/**
+	 * 四舍五入保留两位小数 先四舍五入在使用double值自动去零
+	 * 
+	 * @param arg
+	 * @return
+	 */
+	public static String setDifScare(String arg) {
+		BigDecimal bd = new BigDecimal(arg);
+		BigDecimal bl = bd.setScale(2, BigDecimal.ROUND_HALF_UP);
+		return bl.toString();
+	}
+
+	/**
+	 * 四舍五入保留N位小数 先四舍五入在使用double值自动去零(传参String类型)
+	 * 
+	 * @param arg
+	 * @return
+	 */
+	public static String setDifScare(String arg, int i) {
+		BigDecimal bd = new BigDecimal(arg);
+		BigDecimal bl = bd.setScale(i, BigDecimal.ROUND_HALF_UP);
+		return bl.toString();
+	}
+
+	/**
+	 * 转化成百分数 先四舍五入在使用double值自动去零
+	 * 
+	 * @param arg
+	 * @return
+	 */
+	public static String setFenScare(BigDecimal arg) {
+		BigDecimal bl = arg.setScale(3, BigDecimal.ROUND_HALF_UP);
+		String scare = String.valueOf(mul(bl.toString(), "100").doubleValue());
+		String fenScare = scare + "%";
+		return fenScare;
+	}
+
+	/**
+	 * 使用java正则表达式去掉多余的.与0
+	 * 
+	 * @param s
+	 * @return
+	 */
+	public static String subZeroAndDot(String s) {
+		if (s.indexOf(".") > 0) {
+			s = s.replaceAll("0+?$", "");// 去掉多余的0
+			s = s.replaceAll("[.]$", "");// 如最后一位是.则去掉
+		}
+		return s;
+	}
+}

+ 70 - 0
src/main/java/com/itstyle/modules/alipay/service/IAliPayService.java

@@ -0,0 +1,70 @@
+package com.itstyle.modules.alipay.service;
+
+import com.itstyle.common.model.Product;
+/**
+ * 扫码支付以及手机H5支付
+ * 创建者 科帮网
+ * 创建时间	2017年7月27日
+ */
+public interface IAliPayService {
+	/**
+	 * 阿里支付预下单
+	 * 如果你调用的是当面付预下单接口(alipay.trade.precreate),调用成功后订单实际上是没有生成,因为创建一笔订单要买家、卖家、金额三要素。
+     * 预下单并没有创建订单,所以根据商户订单号操作订单,比如查询或者关闭,会报错订单不存在。
+     * 当用户扫码后订单才会创建,用户扫码之前二维码有效期2小时,扫码之后有效期根据timeout_express时间指定。
+	 * @Author  科帮网
+	 * @param product
+	 * @return  String
+	 * @Date	2017年7月27日
+	 * 更新日志
+	 * 2017年7月27日  科帮网 首次创建
+	 *
+	 */
+	String aliPay(Product product);
+    /**
+     * 阿里支付退款
+     * @Author  科帮网
+     * @param product
+     * @return  String
+     * @Date	2017年7月27日
+     * 更新日志
+     * 2017年7月27日  科帮网 首次创建
+     *
+     */
+	String aliRefund(Product product);
+	/**
+	 * 关闭订单
+	 * @Author  科帮网
+	 * @param product
+	 * @return  String
+	 * @Date	2017年7月27日
+	 * 更新日志
+	 * 2017年7月27日  科帮网 首次创建
+	 *
+	 */
+	String aliCloseorder(Product product);
+	/**
+     * 下载对账单 
+	 * @Author	科帮网 
+	 * @param billDate(账单时间:日账单格式为yyyy-MM-dd,月账单格式为yyyy-MM。)
+	 * @param billType(trade、signcustomer;trade指商户基于支付宝交易收单的业务账单;signcustomer是指基于商户支付宝余额收入及支出等资金变动的帐务账单;)
+	 * @return  String
+	 * @Date	2017年7月27日
+	 * 更新日志
+	 * 2017年7月27日  科帮网 首次创建
+	 *
+	 */
+	String downloadBillUrl(String billDate,String billType);
+	/**
+	 * 手机支付返回一个form表单 然后调用方刷新到H5页面
+	 * @Author  科帮网
+	 * @param product
+	 * @return  String
+	 * @Date	2017年7月27日
+	 * 更新日志
+	 * 2017年7月27日  科帮网 首次创建
+	 * 备注:人民币单位为分
+	 * attach 附件参数 使用json格式传递 用于回调区分
+	 */
+	String aliPayMobile(Product product);
+}

+ 244 - 0
src/main/java/com/itstyle/modules/alipay/service/impl/AliPayServiceImpl.java

@@ -0,0 +1,244 @@
+package com.itstyle.modules.alipay.service.impl;
+
+import java.io.File;
+
+import net.sf.json.JSONObject;
+
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+
+import com.alipay.api.AlipayApiException;
+import com.alipay.api.AlipayClient;
+import com.alipay.api.AlipayResponse;
+import com.alipay.api.request.AlipayDataDataserviceBillDownloadurlQueryRequest;
+import com.alipay.api.request.AlipayTradeCloseRequest;
+import com.alipay.api.request.AlipayTradeWapPayRequest;
+import com.alipay.api.response.AlipayDataDataserviceBillDownloadurlQueryResponse;
+import com.alipay.api.response.AlipayTradeCloseResponse;
+import com.alipay.api.response.AlipayTradePrecreateResponse;
+import com.alipay.demo.trade.config.Configs;
+import com.alipay.demo.trade.model.ExtendParams;
+import com.alipay.demo.trade.model.builder.AlipayTradePrecreateRequestBuilder;
+import com.alipay.demo.trade.model.builder.AlipayTradeRefundRequestBuilder;
+import com.alipay.demo.trade.model.result.AlipayF2FPrecreateResult;
+import com.alipay.demo.trade.model.result.AlipayF2FRefundResult;
+import com.alipay.demo.trade.utils.ZxingUtils;
+import com.itstyle.common.constants.Constants;
+import com.itstyle.common.model.Product;
+import com.itstyle.common.utils.CommonUtil;
+import com.itstyle.modules.alipay.service.IAliPayService;
+import com.itstyle.modules.alipay.util.AliPayConfig;
+@Service("aliPayService")
+public class AliPayServiceImpl implements IAliPayService {
+	private static final Logger logger = LoggerFactory.getLogger(AliPayServiceImpl.class);
+	
+	@Override
+	public String aliPay(Product product) {
+		logger.info(product.getAttach()+"(订单号:"+product.getOutTradeNo()+"生成支付宝支付码)");
+		String  message = Constants.SUCCESS;
+		String imgPath= Constants.SF_FILE_SEPARATOR+"alipay_"+product.getOutTradeNo()+".png";
+		String outTradeNo = product.getOutTradeNo();
+		String subject = product.getBody();
+		String totalAmount =  CommonUtil.divide(product.getTotalFee(), "100").toString();
+		// 如果该字段为空,则默认为与支付宝签约的商户的PID,也就是appid对应的PID
+		String sellerId = "";
+		// (必填) 商户门店编号,通过门店号和商家后台可以配置精准到门店的折扣信息,详询支付宝技术支持
+		String storeId = "test_store_id";
+		// 业务扩展参数,目前可添加由支付宝分配的系统商编号(通过setSysServiceProviderId方法),详情请咨询支付宝技术支持
+		ExtendParams extendParams = new ExtendParams();
+		extendParams.setSysServiceProviderId("2088100200300400500");
+		// 订单描述,可以对交易或商品进行一个详细地描述,比如填写"购买商品2件共15.00元"
+		String body = "购买商品2件共15.00元";
+		// 支付超时,定义为120分钟
+		String timeoutExpress = "120m";
+		// 创建扫码支付请求builder,设置请求参数
+		String notifyUrl  = Constants.PAY_URL.get("alipay_notify_url");
+		AlipayTradePrecreateRequestBuilder builder = new AlipayTradePrecreateRequestBuilder()
+		.setSubject(subject)
+		.setTotalAmount(totalAmount)
+		.setOutTradeNo(outTradeNo)
+		.setSellerId(sellerId)
+		.setBody(body)//128长度 --附加信息
+		.setStoreId(storeId)
+		.setExtendParams(extendParams)
+		.setTimeoutExpress(timeoutExpress)
+        .setNotifyUrl(notifyUrl);//支付宝服务器主动通知商户服务器里指定的页面http路径,根据需要设置
+		
+		AlipayF2FPrecreateResult result = AliPayConfig.getAlipayTradeService().tradePrecreate(builder);
+		switch (result.getTradeStatus()) {
+		case SUCCESS:
+			logger.info("支付宝预下单成功: )");
+			
+			AlipayTradePrecreateResponse response = result.getResponse();
+			dumpResponse(response);
+			ZxingUtils.getQRCodeImge(response.getQrCode(), 256, imgPath);
+			break;
+			
+		case FAILED:
+			logger.info("支付宝预下单失败!!!");
+			message = Constants.FAIL;
+			break;
+			
+		case UNKNOWN:
+			logger.info("系统异常,预下单状态未知!!!");
+			message = Constants.FAIL;
+			break;
+			
+		default:
+			logger.info("不支持的交易状态,交易返回异常!!!");
+			message = Constants.FAIL;
+			break;
+		}
+		return message;
+	}
+	 // 简单打印应答
+    private void dumpResponse(AlipayResponse response) {
+        if (response != null) {
+        	logger.info(String.format("code:%s, msg:%s", response.getCode(), response.getMsg()));
+            if (StringUtils.isNotEmpty(response.getSubCode())) {
+            	logger.info(String.format("subCode:%s, subMsg:%s", response.getSubCode(), response.getSubMsg()));
+            }
+            logger.info("body:" + response.getBody());
+        }
+    }
+	@Override
+	public String aliRefund(Product product) {
+		logger.info("订单号:"+product.getOutTradeNo()+"支付宝退款");
+		String  message = Constants.SUCCESS;
+		 // (必填) 外部订单号,需要退款交易的商户外部订单号
+        String outTradeNo = product.getOutTradeNo();
+        // (必填) 退款金额,该金额必须小于等于订单的支付金额,单位为元
+        String refundAmount = CommonUtil.divide(product.getTotalFee(), "100").toString();
+
+        // (必填) 退款原因,可以说明用户退款原因,方便为商家后台提供统计
+        String refundReason = "正常退款,用户买多了";
+
+        // (必填) 商户门店编号,退款情况下可以为商家后台提供退款权限判定和统计等作用,详询支付宝技术支持
+        String storeId = "test_store_id";
+
+        // 创建退款请求builder,设置请求参数
+        AlipayTradeRefundRequestBuilder builder = new AlipayTradeRefundRequestBuilder()
+                .setOutTradeNo(outTradeNo)
+                .setRefundAmount(refundAmount)
+                .setRefundReason(refundReason)
+                //.setOutRequestNo(outRequestNo)
+                .setStoreId(storeId);
+
+        AlipayF2FRefundResult result = AliPayConfig.getAlipayTradeService().tradeRefund(builder);
+        switch (result.getTradeStatus()) {
+            case SUCCESS:
+            	logger.info("支付宝退款成功: )");
+                break;
+
+            case FAILED:
+            	logger.info("支付宝退款失败!!!");
+            	message = Constants.FAIL;
+                break;
+
+            case UNKNOWN:
+            	logger.info("系统异常,订单退款状态未知!!!");
+            	message = Constants.FAIL;
+                break;
+
+            default:
+            	logger.info("不支持的交易状态,交易返回异常!!!");
+            	message = Constants.FAIL;
+                break;
+        }
+		return message;
+	}
+    /**
+     * 如果你调用的是当面付预下单接口(alipay.trade.precreate),调用成功后订单实际上是没有生成,因为创建一笔订单要买家、卖家、金额三要素。
+     * 预下单并没有创建订单,所以根据商户订单号操作订单,比如查询或者关闭,会报错订单不存在。
+     * 当用户扫码后订单才会创建,用户扫码之前二维码有效期2小时,扫码之后有效期根据timeout_express时间指定。
+     * =====只有支付成功后 调用此订单才可以=====
+     */
+	@Override
+	public String aliCloseorder(Product product) {
+		logger.info("订单号:"+product.getOutTradeNo()+"支付宝关闭订单");
+		String  message = Constants.SUCCESS;
+		try {
+			String imgPath= Constants.QRCODE_PATH+Constants.SF_FILE_SEPARATOR+"alipay_"+product.getOutTradeNo()+".png";
+			File file = new File(imgPath);
+            if(file.exists()){
+            	AlipayClient alipayClient = AliPayConfig.getAlipayClient();
+            	AlipayTradeCloseRequest request = new AlipayTradeCloseRequest();
+            	request.setBizContent("{" +
+            			"    \"out_trade_no\":\""+product.getOutTradeNo()+"\"" +
+            			"  }");
+            	AlipayTradeCloseResponse response = alipayClient.execute(request);
+            	if(response.isSuccess()){//扫码未支付的情况
+            		logger.info("订单号:"+product.getOutTradeNo()+"支付宝关闭订单成功并删除支付二维码");
+            		file.delete();
+            	}else{
+            		if("ACQ.TRADE_NOT_EXIST".equals(response.getSubCode())){
+            			logger.info("订单号:"+product.getOutTradeNo()+response.getSubMsg()+"(预下单 未扫码的情况)");
+            		}else if("ACQ.TRADE_STATUS_ERROR".equals(response.getSubCode())){
+            			logger.info("订单号:"+product.getOutTradeNo()+response.getSubMsg());
+            		}else{
+            			logger.info("订单号:"+product.getOutTradeNo()+"支付宝关闭订单失败"+response.getSubCode()+response.getSubMsg());
+            			message = Constants.FAIL;
+            		}
+            	}
+			}
+		} catch (Exception e) {
+			e.printStackTrace();
+			message = Constants.FAIL;
+			logger.info("订单号:"+product.getOutTradeNo()+"支付宝关闭订单异常");
+		}
+		return message;
+	}
+	@Override
+	public String downloadBillUrl(String billDate,String billType) {
+		logger.info("获取支付宝订单地址:"+billDate);
+		String downloadBillUrl = "";
+		try {
+			AlipayDataDataserviceBillDownloadurlQueryRequest request = new AlipayDataDataserviceBillDownloadurlQueryRequest();
+			request.setBizContent("{" + "    \"bill_type\":\"trade\","
+					                   + "    \"bill_date\":\"2016-12-26\"" + "  }");
+			
+			AlipayDataDataserviceBillDownloadurlQueryResponse response
+			                          = AliPayConfig.getAlipayClient().execute(request);
+			if (response.isSuccess()) {
+				logger.info("获取支付宝订单地址成功:"+billDate);
+				downloadBillUrl = response.getBillDownloadUrl();//获取下载地
+			} else {
+				logger.info("获取支付宝订单地址失败"+response.getSubMsg()+":"+billDate);
+			}
+		} catch (Exception e) {
+			e.printStackTrace();
+			logger.info("获取支付宝订单地址异常:"+billDate);
+		}
+		return downloadBillUrl;
+	}
+	@Override
+	public String aliPayMobile(Product product) {
+		logger.info("支付宝手机支付下单");
+		String  totalFee =  CommonUtil.divide(product.getTotalFee(), "100").toString();
+		AlipayTradeWapPayRequest alipayRequest = new AlipayTradeWapPayRequest();
+		String subject = "买个苹果而已";
+		String returnUrl =  "回调地址 http 自定义";
+		alipayRequest.setReturnUrl(returnUrl);//前台通知
+		String notifyUrl  = Constants.PAY_URL.get("alipay_notify_url");
+        alipayRequest.setNotifyUrl(notifyUrl);//后台回调
+        JSONObject bizContent = new JSONObject();
+        bizContent.put("out_trade_no", product.getOutTradeNo());
+        bizContent.put("total_amount", totalFee);//订单金额
+        bizContent.put("subject",subject);//订单标题
+        bizContent.put("seller_id", Configs.getPid());//实际收款账号,一般填写商户PID即可
+        bizContent.put("product_code", "QUICK_WAP_PAY");//手机网页支付
+		bizContent.put("body", "两个苹果五毛钱");
+		String biz = bizContent.toString().replaceAll("\"", "'");
+        alipayRequest.setBizContent(biz);
+        logger.info("业务参数:"+alipayRequest.getBizContent());
+        String form = "支付宝异常";
+        try {
+            form = AliPayConfig.getAlipayClient().pageExecute(alipayRequest).getBody();
+        } catch (AlipayApiException e) {
+        	logger.error("支付宝构造表单失败",e);
+        }
+        return form;
+	}
+}

+ 70 - 0
src/main/java/com/itstyle/modules/alipay/util/AliPayConfig.java

@@ -0,0 +1,70 @@
+package com.itstyle.modules.alipay.util;
+import com.alipay.api.AlipayClient;
+import com.alipay.api.DefaultAlipayClient;
+import com.alipay.demo.trade.config.Configs;
+import com.alipay.demo.trade.service.AlipayTradeService;
+import com.alipay.demo.trade.service.impl.AlipayTradeServiceImpl;
+/**
+ * 配置公共参数
+ * 创建者 科帮网
+ * 创建时间	2017年7月27日
+ */
+public final class AliPayConfig {
+	
+	 /**
+     * 私有的默认构造子,保证外界无法直接实例化
+     */
+    private AliPayConfig(){};
+    
+	/**
+     * 收款方账号
+     */
+    public static final String SELLER_ID = "zhifu@52itstyle.com";
+	 /**
+     * 参数类型
+     */
+    public static String PARAM_TYPE = "json";
+    /**
+     * 编码
+     */
+    public static String CHARSET = "UTF-8";
+    /**
+     * 类级的内部类,也就是静态的成员式内部类,该内部类的实例与外部类的实例
+     * 没有绑定关系,而且只有被调用到才会装载,从而实现了延迟加载
+     */
+    private static class SingletonHolder{
+        /**
+         * 静态初始化器,由JVM来保证线程安全
+         */
+		private  static AlipayClient alipayClient = new DefaultAlipayClient(
+													Configs.getOpenApiDomain(), Configs.getAppid(),
+													Configs.getPrivateKey(), PARAM_TYPE, CHARSET,
+													Configs.getAlipayPublicKey());
+		
+		private  static AlipayTradeService tradeService = new AlipayTradeServiceImpl.ClientBuilder().build();
+    }
+    /**
+     * 支付宝APP请求客户端实例
+     * @Author  科帮网
+     * @return  AlipayClient
+     * @Date	2017年7月27日
+     * 更新日志
+     * 2017年7月27日  科帮网 首次创建
+     *
+     */
+    public static AlipayClient getAlipayClient(){
+        return SingletonHolder.alipayClient;
+    }
+    /**
+     * 电脑端预下单
+     * @Author  科帮网
+     * @return  AlipayTradeService
+     * @Date	2017年7月27日
+     * 更新日志
+     * 2017年7月27日  科帮网 首次创建
+     *
+     */
+    public static AlipayTradeService getAlipayTradeService(){
+        return SingletonHolder.tradeService;
+    }
+}

+ 17 - 0
src/main/resources/application-dev.properties

@@ -0,0 +1,17 @@
+#\u9879\u76eecontextPath
+server.context-path=/springboot_pay
+#\u670d\u52a1\u7aef\u53e3
+server.port=8080
+#session\u6700\u5927\u8d85\u65f6\u65f6\u95f4(\u5206\u949f)\uff0c\u9ed8\u8ba4\u4e3a30
+server.session-timeout=60
+#\u8be5\u670d\u52a1\u7ed1\u5b9aIP\u5730\u5740\uff0c\u542f\u52a8\u670d\u52a1\u5668\u65f6\u5982\u672c\u673a\u4e0d\u662f\u8be5IP\u5730\u5740\u5219\u629b\u51fa\u5f02\u5e38\u542f\u52a8\u5931\u8d25\uff0c\u53ea\u6709\u7279\u6b8a\u9700\u6c42\u7684\u60c5\u51b5\u4e0b\u624d\u914d\u7f6e
+# server.address=192.168.16.11
+
+#tomcat\u6700\u5927\u7ebf\u7a0b\u6570\uff0c\u9ed8\u8ba4\u4e3a200
+server.tomcat.max-threads=100
+#tomcat\u7684URI\u7f16\u7801
+server.tomcat.uri-encoding=UTF-8
+
+#spring boot\u4ece\u63a7\u5236\u53f0\u6253\u5370\u51fa\u6765\u7684\u65e5\u5fd7\u7ea7\u522b\u53ea\u6709ERROR, WARN \u8fd8\u6709INFO\uff0c\u5982\u679c\u4f60\u60f3\u8981\u6253\u5370debug\u7ea7\u522b\u7684\u65e5\u5fd7
+#debug=true
+logging.level.root=INFO

+ 17 - 0
src/main/resources/application-prod.properties

@@ -0,0 +1,17 @@
+#\u9879\u76eecontextPath
+server.context-path=/springboot_pay
+#\u670d\u52a1\u7aef\u53e3
+server.port=8080
+#session\u6700\u5927\u8d85\u65f6\u65f6\u95f4(\u5206\u949f)\uff0c\u9ed8\u8ba4\u4e3a30
+server.session-timeout=60
+#\u8be5\u670d\u52a1\u7ed1\u5b9aIP\u5730\u5740\uff0c\u542f\u52a8\u670d\u52a1\u5668\u65f6\u5982\u672c\u673a\u4e0d\u662f\u8be5IP\u5730\u5740\u5219\u629b\u51fa\u5f02\u5e38\u542f\u52a8\u5931\u8d25\uff0c\u53ea\u6709\u7279\u6b8a\u9700\u6c42\u7684\u60c5\u51b5\u4e0b\u624d\u914d\u7f6e
+# server.address=192.168.16.11
+
+#tomcat\u6700\u5927\u7ebf\u7a0b\u6570\uff0c\u9ed8\u8ba4\u4e3a200
+server.tomcat.max-threads=100
+#tomcat\u7684URI\u7f16\u7801
+server.tomcat.uri-encoding=UTF-8
+
+#spring boot\u4ece\u63a7\u5236\u53f0\u6253\u5370\u51fa\u6765\u7684\u65e5\u5fd7\u7ea7\u522b\u53ea\u6709ERROR, WARN \u8fd8\u6709INFO\uff0c\u5982\u679c\u4f60\u60f3\u8981\u6253\u5370debug\u7ea7\u522b\u7684\u65e5\u5fd7
+#debug=true
+logging.level.root=INFO

+ 17 - 0
src/main/resources/application-test.properties

@@ -0,0 +1,17 @@
+#\u9879\u76eecontextPath
+server.context-path=/springboot_pay
+#\u670d\u52a1\u7aef\u53e3
+server.port=8080
+#session\u6700\u5927\u8d85\u65f6\u65f6\u95f4(\u5206\u949f)\uff0c\u9ed8\u8ba4\u4e3a30
+server.session-timeout=60
+#\u8be5\u670d\u52a1\u7ed1\u5b9aIP\u5730\u5740\uff0c\u542f\u52a8\u670d\u52a1\u5668\u65f6\u5982\u672c\u673a\u4e0d\u662f\u8be5IP\u5730\u5740\u5219\u629b\u51fa\u5f02\u5e38\u542f\u52a8\u5931\u8d25\uff0c\u53ea\u6709\u7279\u6b8a\u9700\u6c42\u7684\u60c5\u51b5\u4e0b\u624d\u914d\u7f6e
+# server.address=192.168.16.11
+
+#tomcat\u6700\u5927\u7ebf\u7a0b\u6570\uff0c\u9ed8\u8ba4\u4e3a200
+server.tomcat.max-threads=100
+#tomcat\u7684URI\u7f16\u7801
+server.tomcat.uri-encoding=UTF-8
+
+#spring boot\u4ece\u63a7\u5236\u53f0\u6253\u5370\u51fa\u6765\u7684\u65e5\u5fd7\u7ea7\u522b\u53ea\u6709ERROR, WARN \u8fd8\u6709INFO\uff0c\u5982\u679c\u4f60\u60f3\u8981\u6253\u5370debug\u7ea7\u522b\u7684\u65e5\u5fd7
+#debug=true
+logging.level.root=INFO

+ 3 - 0
src/main/resources/application.yml

@@ -0,0 +1,3 @@
+spring:
+  profiles:
+    active: dev