一,支付宝文档中心 :https://docs.open.alipay.com
二,可以查看官方的示例代码:就是将必要的参数封装到请求对象里,然后调取接口。
pom.xml 依赖的jar包
一 :请求支付宝SDK
1 配置类
public final class AliPayConfig {
/**
* 应用号
*/
public static String APP_ID = "xxxxxxxxxxxxxxx";
/**
* 商户的私钥
*/
public static String APP_PRIVATE_KEY = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
/**
* 编码
*/
public static String CHARSET = "UTF-8";
/**
* 支付宝公钥
*/
public static String ALIPAY_PUBLIC_KEY = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
/**
* 支付宝网关地址
*/
private static String GATEWAY = "https://openapi.alipay.com/gateway.do";
/**
* 成功付款回调
*/
public static String PAY_NOTIFY = "http://xxxxxxxxxxx.com/sysControl/portals/alipayNotify.action";
/**
* 前台通知地址
*/
public static String RETURN_URL ="http://xxxxxxxxxxxxxxxxxxxx";
/**
* 参数类型
*/
public static String PARAM_TYPE = "json";
/**
* 成功标识
*/
public static final String SUCCESS_REQUEST = "TRADE_SUCCESS";
/**
* 收款方账号
*/
public static final String SELLER_ID = "jntnaj0136@sandbox.com";
/**
* 产品销售吗
*/
public static final String PRODUCT_CODE= "FAST_INSTANT_TRADE_PAY";
/**
* 仅支持json
*/
public static final String FORMAT= "JSON";
/**
* 仅支持json
*/
public static final String SIGN_TYPE= "RSA2";
/**
* 支付宝请求客户端入口
*/
private volatile static AlipayClient alipayClient = null;
/**
* 不可实例化
*/
private AliPayConfig(){};
/**
* 双重锁单例
* @return 支付宝请求客户端实例
*/
public static AlipayClient getInstance(){
if (alipayClient == null){
synchronized (AliPayConfig.class){
if (alipayClient == null){
alipayClient = new DefaultAlipayClient(GATEWAY,APP_ID,APP_PRIVATE_KEY,PARAM_TYPE,CHARSET,ALIPAY_PUBLIC_KEY,SIGN_TYPE);
}
}
}
return alipayClient;
}
}
2.业务类
/**
* 支付宝
* @param payment
* @return
*/
@Override
public String alipayFrom(Payment payment) {
AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
alipayRequest.setReturnUrl(AliPayConfig.RETURN_URL);
alipayRequest.setNotifyUrl(AliPayConfig.PAY_NOTIFY);
// 待请求参数数组
Map alipayData= new HashMap<>(6);
alipayData.put("out_trade_no",payment.getOrderNumber());
alipayData.put("product_code",AliPayConfig.PRODUCT_CODE);
alipayData.put("total_amount",payment.getCost());
alipayData.put("subject",payment.getMessage());
alipayData.put("body",payment.getMessage());
alipayRequest.setBizContent(JSON.toJSONString(alipayData));
String form = "";
try {
//GET方法返回的是url,直接返给前端。
form = AliPayConfig.getInstance().pageExecute(alipayRequest,"**GET**").getBody();
} catch (AlipayApiException e) {
logger.error("支付宝构造表单失败",e);
}
logger.debug("支付宝支付表单构造:{}",form);
return form;
}
这里是将所需要的参数放在map里,转成JSON。和官网示例差不多。“GET”给前端返回url
二 回调接口
1.controller层
/**
* 支付宝支付回调
*
* @param request
* @return
*/
@RequestMapping(value = "/alipayNotify", method = RequestMethod.POST)
@ResponseBody
public String alipayChange(HttpServletRequest request) {
LOGGER.info("线程ID<{}>收到支付宝回调请求", Thread.currentThread().getId());
Map<String, String> params = new HashMap<>();
Map<String, String[]> requestParams = request.getParameterMap();
for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext();) {
String name = iter.next();
String[] values = requestParams.get(name);
String valueStr = "";
for (int i = 0; i < values.length; i++) {
valueStr = (i == values.length - 1) ? valueStr + values[i]
: valueStr + values[i] + ",";
}
// 乱码解决,这段代码在出现乱码时使用
/*
* try {
* valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
* } catch (UnsupportedEncodingException e) {
* logger.error("回调接收参数乱码",e);
* }
*/
params.put(name, valueStr);
}
PaymentServiceImpl.alipayVerifyNotify( payment)
}
2.service业务层
public class PaymentServiceImpl extends BaseService implements PaymentService {
/**
*
* @param payment
* @return
*/
@Override
public String alipayVerifyNotify(Map<String,String> payment) throws Exception {
boolean signVerified = checkRSA(payment);
// 验证失败
if (!signVerified) {
logger.error("不是支付宝的合法请求!");
return FAILURE;
}
// 验证通知是否有效
boolean checkedTrustiness = checkedTrustiness(payment);
if (!checkedTrustiness) {
logger.error("支付宝请求异常!");
return FAILURE;
}
String trade_status =payment.get("trade_status");
if (TRADE_SUCCESS.equals(trade_status)) {
//防止重复提交 做判断(支付宝可能会多次回调请求)
Order order = iOrderService.selectOrderByOrderNum(payment.get("out_trade_no"));
if(order==null){
logger.error("订单信息查询异常");
return FAILURE;
}
logger.info("订单编号:{}",order.getOrderNumber()+"-订单状态:"+order.getOrderStatus());
if(order.getOrderStatus()==0){
//调查询接口查账号
String buyerLogonId = alipayQuery(payment);
Payment pay =new Payment();
pay.setPayWay(STATUS0);
pay.setCost(new BigDecimal(payment.get("total_amount")));
pay.setOrderId(order.getOrderId());
pay.setPaySerialNum(payment.get("trade_no"));
pay.setUserBankNum(buyerLogonId);
try {
//支付成功修改数据库信息
insertDatabase(pay);
}catch (Exception e){
logger.error("支付宝回调修改数据失败");
PayAnomaly payAnomaly = new PayAnomaly();
payAnomaly.setOrderNumber(payment.get("out_trade_no"));
payAnomaly.setPaySerialNum(payment.get("trade_no"));
payAnomaly.setOrderCost(new BigDecimal(payment.get("total_amount")));
payAnomaly.setPaymentTime(payment.get("gmt_payment"));
payAnomaly.setNotifyTime(payment.get("notify_time"));
payAnomaly.setUserId(order.getUserId());
logger.error("异常订单信息入库");
insertPayAnomaly(payAnomaly);
}
}
}
return SUCCESS;
}
/**
* 验证是否为支付宝的合法请求 --验证签名
* @param requestParams 获取到的请求
* @return
*/
private boolean checkRSA(Map<String,String> requestParams) {
logger.info("收到支付宝验证:{}",requestParams.toString());
boolean isVerify = false;
try {
//调用SDK验证签名
isVerify = AlipaySignature.rsaCheckV1(requestParams, ALIPAY_PUBLIC_KEY, CHARSET,SIGN_TYPE);
logger.debug("支付宝验签结果:{}",isVerify);
return isVerify;
} catch (AlipayApiException e) {
e.printStackTrace();
logger.error("支付宝回调验证签名异常:{}", e);
return isVerify;
}
}
// 验证支付
private boolean checkedTrustiness(Map<String,String> request) {
String out_trade_no = "";
String trade_status = "";
String seller_id = "";
String app_id ;
BigDecimal total_amount;
try {
out_trade_no = request.get("out_trade_no");
total_amount = new BigDecimal(request.get("buyer_pay_amount"));
seller_id = request.get("seller_id");
app_id = request.get("app_id");
trade_status = request.get("trade_status");
} catch (Exception e) {
logger.error("回调参数格式转换异常(orderNum=" + out_trade_no + ")", e);
return false;
}
if (!"TRADE_FINISHED".equals(trade_status) && !"TRADE_SUCCESS".equals(trade_status)) {
logger.error("支付宝返回的交易状态不正确(orderNum=" + out_trade_no + ")");
return false;
}
Order order;
try {
//根据订单id查询订单信息
order = iOrderService.selectOrderByOrderNum(request.get("out_trade_no"));
if(order==null){
logger.error("回调查询订单信息失败(orderNum=" + out_trade_no + ")");
return false;
}
} catch (Exception e) {
logger.error("paybill 查询订单情况异常 (orderNum=" + out_trade_no + ")", e);
return false;
}
// 1.判断totalamount
if (!total_amount.equals(order.getOrderCost())) {
logger.error("支付宝返回的订单金额不正确(orderNum=" + out_trade_no + ")");
return false;
}
// 2.验证app_id
if (!APP_ID.equals(app_id)) {
logger.error("支付宝返回的app_id不正确(orderNum=" + out_trade_no + ")");
return false;
}
// 3.验证order_id
if (!out_trade_no.equals(order.getOrderNumber())) {
logger.error("支付宝返回的订单id不正确(orderNum=" + out_trade_no + ")");
return false;
}
// 4.验证seller_id
/* if (!seller_id.equals(SELLER_ID)) {
logger.error("支付宝返回的订单id不正确(payid=" + out_trade_no + ")");
return false;
}*/
return true;
}
}
1.支付成功,支付宝还多次请求服务器