Java对接支付宝支付
准备工具
SpringBoot工程构建
导入支付宝支付的maven依赖
获取支付宝的API 密钥,支付宝公钥,支付宝私钥等配置文件
定义当面支付的地址
https://openapi.alipay.com/gateway.do
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>4.3.0.ALL</version>
</dependency>
<dependency>
<groupId>com.ibeetl</groupId>
<artifactId>beetl</artifactId>
<version>${beetl.version}</version>
</dependency>
<dependency>
<groupId>net.sourceforge.jexcelapi</groupId>
<artifactId>jxl</artifactId>
<version>2.6.10</version>
</dependency>
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.4</version>
<classifier>jdk15</classifier>
</dependency>
</dependencies>
package com.jowim.service.impl;
import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradePayRequest;
import com.alipay.api.request.AlipayTradePrecreateRequest;
import com.alipay.api.request.ZolozAuthenticationCustomerSmilepayInitializeRequest;
import com.alipay.api.response.AlipayTradePayResponse;
import com.alipay.api.response.AlipayTradePrecreateResponse;
import com.alipay.api.response.ZolozAuthenticationCustomerSmilepayInitializeResponse;
import com.jowim.constant.ResultConstants;
import com.jowim.entity.Orders;
import com.jowim.entity.Product;
import com.jowim.entity.ProductInOrders;
import com.jowim.entity.Site;
import com.jowim.mapper.ProductInOrdersMapper;
import com.jowim.mapper.ProductMapper;
import com.jowim.service.IAliPayMethod;
import com.jowim.service.IOrdersService;
import com.jowim.service.IRedisCache;
import com.jowim.service.ISiteService;
import com.jowim.tool.FavoritesHelper;
import com.jowim.util.ResponseMessage;
import org.apache.catalina.servlet4preview.http.HttpServletRequest;
import org.apache.commons.codec.digest.DigestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.*;
@Service
public class AlipayMethodImpl implements IAliPayMethod {
/**
* 站点
*/
@Autowired
private ISiteService iSiteService;
/**
* 订单
*/
@Autowired
private IOrdersService iOrdersService;
/**
* 订单内商品
*/
@Autowired
private ProductInOrdersMapper productInOrdersMapper;
/**
* 产品
*/
@Autowired
private ProductMapper productMapper;
/**
* 缓存
*/
@Autowired
private IRedisCache iRedisCache;
private final static Logger log = LoggerFactory.getLogger(AlipayMethodImpl.class);
public static String siteID = "355e307afbe95a9c85cfb9732fef204d";
//当面支付
private static final String URL = "https://openapi.alipay.com/gateway.do";
//通知地址,自己的实际回调接口
private static final String notify_url = "";
// 编码
public static String CHARSET = "UTF-8";
// 返回格式
public static String FORMAT = "json";
public static String SIGNTYPE = "RSA2";
/**
* 支付宝支付码支付
*
* @param json
* @param httpRequest
* @param httpResponse
* @return
*/
@Override
@Transactional
public ResponseMessage<Object> doPost(String json, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws AlipayApiException {
//商户订单号,64个字符以内、可包含字母、数字、下划线;需保证在商户端不重复
String orderNo = JSON.parseObject(json).getString("orderNo");
//支付授权码,25~30开头的长度为16~24位的数字,实际字符串长度以开发者获取的付款码长度为准
String authCode = JSON.parseObject(json).getString("authCode");
//订单标题
String subject = JSON.parseObject(json).getString("subject");
if (FavoritesHelper.isNull(orderNo) || FavoritesHelper.isNull(subject)) {
return ResponseMessage.error(ResultConstants.RESULT_NULL);
}
Site site = iSiteService.selectById(siteID);
String appId = site.getAppId();
String publicKey = site.getAliPublicKey();
String privateKey = site.getAliPrivateKey();
Orders orders = iOrdersService.selectById(orderNo);
if (null == orders) {
return ResponseMessage.error("未查询到该订单,请重试!");
}
BigDecimal moneys = orders.getSalesAmount();
AlipayClient alipayClient = new DefaultAlipayClient(URL, appId, privateKey, FORMAT, CHARSET, publicKey, SIGNTYPE); //获得初始化的AlipayClient
AlipayTradePayRequest alipayRequest = new AlipayTradePayRequest();//创建API对应的request
alipayRequest.setBizContent("{" +
"\"out_trade_no\":\"" + orderNo + "\"," + // 商户订单号,64个字符以内、可包含字母、数字、下划线;需保证在商户端不重复
"\"scene\":\"bar_code\"," +
"\"auth_code\":\"" + authCode + "\"," +
"\"product_code\":\"FACE_TO_FACE_PAYMENT\"," +
"\"subject\":\"" + subject + "\"," +
"\"total_amount\":\"" + moneys + "\"," +
" }");//填充业务参数
AlipayTradePayResponse response = alipayClient.execute(alipayRequest);
String form = response.getBody();
if (response.isSuccess()) {
System.out.println("调用成功");
log.info("调用成功");
BigDecimal totalMoney = new BigDecimal(response.getTotalAmount());
//更新订单
orders.setPayState("0");
orders.setActualPayment(totalMoney);
//查出订单内的商品
List<ProductInOrders> productInOrdersList = productInOrdersMapper.selectProductInorders(
orders.getSupermarketId(), orders.getId());
//查出商品信息
List<Product> productList = productMapper.selectProductByIdList(productInOrdersList);
List<Product> relaProductList = new ArrayList<>();
for (ProductInOrders productInOrders : productInOrdersList) {
for (Product product : productList) {
//如果未关联装箱
if ("1".equals(product.getRelateOrNot())) {
product.setStock(product.getStock() - productInOrders.getNum());
}
//如果关联装箱
if ("0".equals(product.getRelateOrNot())) {
//查出所关联的单品
Product relaProduct = productMapper.selectById(product.getRelationId());
relaProduct.setStock(relaProduct.getStock() - (relaProduct.getRelateNum() * productInOrders.getNum()));
relaProductList.add(relaProduct);
}
}
}
productList.addAll(relaProductList);
try {
iOrdersService.updateById(orders);
productMapper.updateProductByList(productList);
} catch (Exception e) {
e.printStackTrace();
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
return ResponseMessage.error("支付成功,更新数据库失败!");
}
log.info("支付宝免密支付成功!");
return ResponseMessage.ok(2, "支付成功");
} else {
System.out.println("调用失败");
log.info("调用失败");
return ResponseMessage.error("调用失败");
}
}
/**
* 支付宝扫码支付
*
* @param json
* @param httpRequest
* @return
*/
@Override
public ResponseMessage<Object> doPost2(String json, HttpServletRequest httpRequest) throws AlipayApiException {
//商户订单号,64个字符以内、可包含字母、数字、下划线;需保证在商户端不重复
String orderNo = JSON.parseObject(json).getString("orderNo");
// // 支付授权码,25~30开头的长度为16~24位的数字,实际字符串长度以开发者获取的付款码长度为准
// String authCode = JSON.parseObject(json).getString("authCode");
//订单标题
String subject = JSON.parseObject(json).getString("subject");
if (FavoritesHelper.isNull(orderNo) || FavoritesHelper.isNull(subject)) {
return ResponseMessage.error(ResultConstants.RESULT_NULL);
}
Site site = iSiteService.selectById(siteID);
String appId = site.getAppId();
String publicKey = site.getAliPublicKey();
String privateKey = site.getAliPrivateKey();
Orders orders = iOrdersService.selectById(orderNo);
if (null == orders) {
return ResponseMessage.error("未查询到该订单,请重试!");
}
BigDecimal moneys = orders.getSalesAmount();
AlipayClient alipayClient = new DefaultAlipayClient(URL, appId, privateKey, FORMAT, CHARSET, publicKey, SIGNTYPE); //获得初始化的AlipayClient
AlipayTradePrecreateRequest alipayRequest = new AlipayTradePrecreateRequest();//创建API对应的request
alipayRequest.setNotifyUrl(notify_url);
alipayRequest.setBizContent("{" +
"\"out_trade_no\":\"" + orderNo + "\"," + // 商户订单号,64个字符以内、可包含字母、数字、下划线;需保证在商户端不重复
"\"subject\":\"" + subject + "\"," +
"\"total_amount\":\"" + moneys + "\"," +
" }");//填充业务参数
AlipayTradePrecreateResponse response = alipayClient.execute(alipayRequest);
if (response.isSuccess()) {
System.out.println("调用成功");
return ResponseMessage.ok(response.getQrCode());
} else {
System.out.println("调用失败");
return ResponseMessage.error("请求失败!");
}
}
/**
* 回调
* 1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号,
* 2、判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额),
* 3、校验通知中的seller_id(或者seller_email) 是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email),
* 4、验证app_id是否为该商户本身。上述1、2、3、4有任何一个验证不通过,则表明本次通知是异常通知,务必忽略。
* 在上述验证通过后商户必须根据支付宝不同类型的业务通知,正确的进行不同的业务处理,并且过滤重复的通知结果数据。
* 在支付宝的业务通知中,只有交易通知状态为TRADE_SUCCESS或TRADE_FINISHED时,支付宝才会认定为买家付款成功。
*
* @param request
* @return
*/
@Override
public String getNotify(HttpServletRequest request, HttpServletResponse response) throws UnsupportedEncodingException {
Site site = iSiteService.selectById(siteID);
String appId = site.getAppId();
String publicKey = site.getAliPublicKey();
Map<String, String> params = convertRequestParamsToMap(request); // 将异步通知中收到的待验证所有参数都存放到map中
String paramsJson = JSON.toJSONString(params);
log.info("支付宝回调,{}", paramsJson);
try {
boolean signVerified = AlipaySignature.rsaCheckV1(params, publicKey, CHARSET, SIGNTYPE);
if (signVerified) {
// 按照支付结果异步通知中的描述,对支付结果中的业务内容进行二次校验,校验成功后在response中返回success,校验失败返回failure
String outTradeNo = params.get("out_trade_no");
// 1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号,
Orders orders = iOrdersService.selectById(outTradeNo);
//判断订单是否存在
if (orders == null) {
return "failure";
}
//判断是否已更改过数据库
if ("0".equals(orders.getPayState())){
return "success";
}
BigDecimal amout = new BigDecimal(params.get("total_amount"));
//判断金额是否正确
if (0!=amout.compareTo(orders.getSalesAmount())){
return "failure";
}
if (!params.get("app_id").equals(appId)) {
return "failure";
}
//更新订单
orders.setPayState("0");
orders.setActualPayment(amout);
//查出订单内的商品
List<ProductInOrders> productInOrdersList = productInOrdersMapper.selectProductInorders(
orders.getSupermarketId(), orders.getId());
//查出商品信息
List<Product> productList = productMapper.selectProductByIdList(productInOrdersList);
List<Product> relaProductList = new ArrayList<>();
for (ProductInOrders productInOrders : productInOrdersList) {
for (Product product : productList) {
//如果未关联装箱
if ("1".equals(product.getRelateOrNot())) {
product.setStock(product.getStock() - productInOrders.getNum());
}
//如果关联装箱
if ("0".equals(product.getRelateOrNot())) {
//查出所关联的单品
Product relaProduct = productMapper.selectById(product.getRelationId());
relaProduct.setStock(relaProduct.getStock() - (relaProduct.getRelateNum() * productInOrders.getNum()));
relaProductList.add(relaProduct);
}
}
}
productList.addAll(relaProductList);
try {
iOrdersService.updateById(orders);
productMapper.updateProductByList(productList);
}catch (Exception e){
e.printStackTrace();
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
return "failure";
}
return "success";
}
} catch (AlipayApiException e) {
e.printStackTrace();
}
return "failure";
}
/**
* 刷脸支付初始化
* @param json
* @return
*/
@Override
public ResponseMessage<Object> doPost3(String json,HttpServletRequest httpRequest) throws AlipayApiException {
return null;
}
// 将request中的参数转换成Map
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;
}
}