App 支付宝支付
1.调起支付流程:
第一步:创建应用并获取APPID
去蚂蚁金服开放平台(open.alipay.com),在开发者中心中创建应用,会生成应用唯一标识(APPID),申请开通支付功能。。
第二步:配置密钥
- 支付宝公钥:支付宝的RSA公钥,商户使用该公钥验证该结果是否是支付宝返回的。
- 2.下载阿里云的RSA密钥工具生成密钥和公钥(下载地址:https://docs.open.alipay.com/291/106097/)
- 3.上传工具生成的公钥到阿里云,私钥放到服务器,调用接口时使用
第三步:集成和开发
1:导入jar包
<!-- 阿里云支付宝支付的jar --> <dependency> <groupId>com.alipay.sdk</groupId> <artifactId>alipay-sdk-java</artifactId> <version>3.3.87.ALL</version> </dependency>
2:具体demo
a:阿里云基本参数类:
public interface AliPayConfig {
/** 支付宝支付的appid */
String APP_ID = "";
/** 应用私钥 */
String PRIVATE_KEY = "";
//应用公钥
String APP_PUBLIC_KEY = "";
//支付宝公钥
String ALI_PUBLIC_KEY ="";
//字符集
String CHARSET = "utf-8";
//数据格式
String FORMAT = "json";
//加密方式
String SIGN_TYPE = "RSA2";
/** 以下参数为调用地址 */
//接收支付宝回调地址notify_url
//测试时候可以映射到本地地址可测试,不一定非要部署到线上
String NOTIFY_URL = "";
String GATEWAY_URL = "https://openapi.alipay.com/gateway.do";
}
b:统一下单接口
@ResponseBody
@RequestMapping("/aliPayOrder")
public JSONObject aliPayOrder(String outtradeno) {
JSONObject returnValue = null;
//实例化客户端
AlipayClient alipayClient = new DefaultAlipayClient(AliPayConfig.GATEWAY_URL, AliPayConfig.APP_ID, AliPayConfig.PRIVATE_KEY, AliPayConfig.FORMAT, AliPayConfig.CHARSET, AliPayConfig.ALI_PUBLIC_KEY, AliPayConfig.SIGN_TYPE);
//实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay
AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
//SDK已经封装掉了公共参数,这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
outtradeno = WeixinPayUtil.getOrderIdByTime();
AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
model.setBody("测试");
model.setSubject("App支付测试");
model.setOutTradeNo(outtradeno);
model.setTimeoutExpress("30m");
model.setTotalAmount("0.01");
model.setProductCode("QUICK_MSECURITY_PAY");
request.setBizModel(model);
request.setNotifyUrl(AliPayConfig.NOTIFY_URL);
try {
//这里和普通的接口调用不同,使用的是sdkExecute
AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
//就是orderString 可以直接给客户端请求,无需再做处理。
returnValue = new JSONObject();
returnValue.put("errCode", ErrorCode.SUCCESS_RETRUN);
returnValue.put("errMsg", "ok");
returnValue.put("data", response.getBody());
logger.info("【支付宝统一下单 --- 成功 】,订单号为:{}",outtradeno);
return returnValue;
} catch (AlipayApiException e) {
logger.info("【支付宝统一下单 --- 失败 】,订单号为:{},原因为:{}",outtradeno,e.getErrMsg().toString());
returnValue = ErrorCodeUtil.ERROR_FAILED("下单失败");
return returnValue;
}
}
c:支付回调接口
@RequestMapping("aliPay_notify")
public void aliPay_notify(HttpServletRequest request, HttpServletResponse response) {
//获取支付宝POST过来反馈信息
Map<String, String> params = new HashMap<>();
Map requestParams = request.getParameterMap();
for (Iterator 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] + ",";
}
params.put(name, valueStr);
}
try {
//验证签名
boolean flag = AlipaySignature.rsaCheckV1(params, AliPayConfig.ALI_PUBLIC_KEY, AliPayConfig.CHARSET, AliPayConfig.SIGN_TYPE);
if (flag) {
if ("TRADE_SUCCESS".equals(params.get("trade_status"))) { //业务逻辑处理
//付款金额
String amount = params.get("buyer_pay_amount");
//商户订单号
String out_trade_no = params.get("out_trade_no");
//支付宝交易号
String trade_no = params.get("trade_no");
//附加数据
String passback_params = params.get("passback_params");
response.getWriter().write("success");
}
}else {
logger.info("【支付宝支付--异步回调】回调失败,签名验证失败");
}
} catch (AlipayApiException e) {
logger.error("【支付宝支付--异步回调】回调失败,阿里云接口调用错误,原因为:{}",e.getMessage());
} catch (Exception e) {
logger.error("【支付宝支付--异步回调】回调失败,原因为:{}",e.getMessage());
}
}
d:退款接口
@RequestMapping("aliPay_refund")
@ResponseBody
public JSONObject aliPay_refund(final String outTradeNo,final String transactionId){
JSONObject returnValue = null ;
try {
//实例化客户端
AlipayClient alipayClient = new DefaultAlipayClient(AliPayConfig.GATEWAY_URL, AliPayConfig.APP_ID, AliPayConfig.PRIVATE_KEY, AliPayConfig.FORMAT, AliPayConfig.CHARSET, AliPayConfig.ALI_PUBLIC_KEY, AliPayConfig.SIGN_TYPE);
//实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.refund
AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
//SDK已经封装掉了公共参数,这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
AlipayTradeRefundModel model = new AlipayTradeRefundModel();
//优先使用支付宝的订单id
if(transactionId == null || transactionId.length() == 0){
model.setOutTradeNo(outTradeNo);
}else {
model.setTradeNo(transactionId);
}
//测试金额1分钱
String price = "0.01";
//测试退款理由
model.setRefundReason("测试退款");
//退款金额
model.setRefundAmount(price);
request.setBizModel(model);
AlipayTradeRefundResponse response = alipayClient.execute(request);
if(response.isSuccess()){
returnValue = ErrorCodeUtil.ERROR_FAILED("退款成功");
return returnValue ;
} else {
returnValue = ErrorCodeUtil.ERROR_FAILED(response.getSubMsg());
return returnValue ;
}
}catch (AlipayApiException e) {
logger.error("【支付宝支付 -- 退款失败】原因为:{}",e.getMessage());
returnValue = ErrorCodeUtil.ERROR_FAILED("退款失败");
return returnValue ;
}
}
e:关闭订单
@ResponseBody
@RequestMapping("aliPay_close")
public JSONObject aliPay_close(final String outTradeNo,final String transactionId){
JSONObject returnValue = null ;
try {
//实例化客户端
AlipayClient alipayClient = new DefaultAlipayClient(AliPayConfig.GATEWAY_URL, AliPayConfig.APP_ID, AliPayConfig.PRIVATE_KEY, AliPayConfig.FORMAT, AliPayConfig.CHARSET, AliPayConfig.ALI_PUBLIC_KEY, AliPayConfig.SIGN_TYPE);
//实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.close
AlipayTradeCloseRequest request = new AlipayTradeCloseRequest();
//SDK已经封装掉了公共参数,这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
AlipayTradeCloseModel model = new AlipayTradeCloseModel();
//优先使用支付宝的订单id
if(transactionId == null || transactionId.length() == 0){
model.setOutTradeNo(outTradeNo);
}else {
model.setTradeNo(transactionId);
}
request.setBizModel(model);
AlipayTradeCloseResponse response = alipayClient.execute(request);
if(response.isSuccess()){
returnValue = ErrorCodeUtil.ERROR_FAILED("订单关闭成功");
return returnValue ;
} else {
returnValue = ErrorCodeUtil.ERROR_FAILED(response.getSubMsg());
return returnValue ;
}
}catch (AlipayApiException e) {
logger.error("【支付宝支付 -- 关闭订单】关闭订单失败,原因为:{}",e.getMessage());
returnValue = ErrorCodeUtil.ERROR_FAILED("订单关闭失败");
return returnValue ;
}
}
f:查询订单状态
@ResponseBody
@RequestMapping("aliPay_query")
public JSONObject aliPay_query(final String outTradeNo,final String transactionId){
JSONObject returnValue = null ;
try {
//实例化客户端
AlipayClient alipayClient = new DefaultAlipayClient(AliPayConfig.GATEWAY_URL, AliPayConfig.APP_ID, AliPayConfig.PRIVATE_KEY, AliPayConfig.FORMAT, AliPayConfig.CHARSET, AliPayConfig.ALI_PUBLIC_KEY, AliPayConfig.SIGN_TYPE);
//实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.query
AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
//SDK已经封装掉了公共参数,这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
AlipayTradeQueryModel model = new AlipayTradeQueryModel();
//优先使用支付宝的订单id
if(transactionId == null || transactionId.length() == 0){
model.setOutTradeNo(outTradeNo);
}else {
model.setTradeNo(transactionId);
}
request.setBizModel(model);
AlipayTradeQueryResponse response = alipayClient.execute(request);
if(response.isSuccess()){
if("WAIT_BUYER_PAY".equals(response.getTradeStatus())){
returnValue = ErrorCodeUtil.ERROR_FAILED("交易创建,等待买家付款");
return returnValue ;
}else if("TRADE_CLOSED".equals(response.getTradeStatus())){
returnValue = ErrorCodeUtil.ERROR_FAILED("未付款交易超时关闭,或支付完成后全额退款");
return returnValue ;
}else if("TRADE_SUCCESS".equals(response.getTradeStatus())){
returnValue = ErrorCodeUtil.ERROR_FAILED("交易支付成功");
return returnValue ;
}else if("TRADE_FINISHED".equals(response.getTradeStatus())){
returnValue = ErrorCodeUtil.ERROR_FAILED("交易结束,不可退款");
return returnValue ;
}else {
returnValue = ErrorCodeUtil.ERROR_FAILED("未知状态");
return returnValue ;
}
} else {
returnValue = ErrorCodeUtil.ERROR_FAILED(response.getSubMsg());
return returnValue ;
}
}catch (AlipayApiException e) {
logger.error("【支付宝支付 -- 查询订单】查询订单失败,原因为:{}",e.getMessage());
returnValue = ErrorCodeUtil.ERROR_FAILED("订单查询失败");
return returnValue ;
}
}