1、支付宝开发平台:https://openhome.alipay.com/

2、进去沙箱,配置支付密钥

记录下appid,然后设置秘钥;

 3、后端代码,配置类

pom文件sdk添加依赖

<!--pom.xml  支付宝sdk -->
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.58</version>
</dependency>
@Configuration
public class AppPayConfig {
/**
* 1.商户appid
*/
public static String APPID = ""; /**
* 私钥 pkcs8格式的
* 这个就是我上面说的应用私钥生成 注意这里是私钥
*/
public static String RSA_PRIVATE_KEY =""
* 3.支付宝公钥
*/
public static String ALIPAY_PUBLIC_KEY = ""; /**
* 4.服务器异步通知页面路径 需http://或者https://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
*/
//这个着重讲一下..支付完成后,支付宝会通过这个url请求到你的服务端..
//这个url一定是要公网可以访问才行...如果需要测试的话..我后面有讲到..
//这里你可以先写你本地项目的url 例如:localhost:8080/项目名/访问路径
public static String notify_url = "http://4e69yn.natappfree.cc/api/v1/aliPayApp/notify_url"; /**
* 5.页面跳转同步通知页面路径 需http://或者https://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问 商户可以自定义同步跳转地址
*/
//这里同上..不做详细说明了..
public static String return_url = "http://4e69yn.natappfree.cc/api/v1/aliPayApp/notify_url"; /**
* 正式环境支付宝网关,如果是沙箱环境需更改成https://openapi.alipaydev.com/gateway.do
*/
public static String URL = "https://openapi.alipaydev.com/gateway.do"; /**
* 7.编码
*/
public static String CHARSET = "UTF-8"; /**
* 私钥 pkcs8格式的
*/
// 8.返回格式
public static String FORMAT = "json"; /**
* //签名方式 加密类型
*/
public static String SIGNTYPE = "RSA2";
}

4、控制层

@RestController
@RequestMapping("api/v1/aliPayApp")
@Slf4j
public class AliPayAppController {
@Autowired
private AliPayAppService aliPayAppService; /**
* 获取支付宝加签后台的订单信息字符串,唤起支付宝APP
* @Title: getAliPayOrderStr
* @description
*/
@RequestMapping("/getAliPayOrderStr")
@ResponseBody
public JsonData getAliPayOrderStr(@RequestParam("userId") Integer userId, @RequestParam("videoId") Integer videoId) {
String aliPayOrderStr = aliPayAppService.getAliPayOrderStr(userId, videoId);
return JsonData.buildSuccess(aliPayOrderStr);
} /**
* 支付宝支付成功后.异步请求该接口
* @Title: notify
*/
@RequestMapping(value="/notify_url",method= RequestMethod.POST)
@ResponseBody
public JsonData notify(HttpServletRequest request, HttpServletResponse response) throws IOException {
log.info("支付宝异步返回支付结果开始");
// 1.从支付宝回调的request域中取值
// 获取支付宝返回的参数集合
Map<String, String[]> aliParams = request.getParameterMap();
// 用以存放转化后的参数集合
Map<String, String> conversionParams = new HashMap<String, String>();
for (Iterator<String> iter = aliParams.keySet().iterator(); iter.hasNext();) {
String key = iter.next();
String[] values = aliParams.get(key);
String valueStr = "";
for (int i = 0; i < values.length; i++) {
valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
}
// 乱码解决,这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
// valueStr = new String(valueStr.getBytes("ISO-8859-1"), "uft-8");
conversionParams.put(key, valueStr);
}
log.info("返回参数集合:" + conversionParams);
String status = aliPayAppService.notify(conversionParams);
if (status.equals("fail")){
return JsonData.buildError("订单修改失败");
}else {
return JsonData.buildSuccess("订单修改失败");
} } /**
* 向支付宝发起订单查询请求
* @Title: checkAlipay
* @description
* @param orderNo 商户订单号
*/
@RequestMapping("/checkAlipay")
@ResponseBody
public JsonData checkAlipay(String orderNo) {
int result = aliPayAppService.checkAlipay(orderNo);
return JsonData.buildSuccess(result);
} /**
* 向支付宝发起退款请求
* @Title: alipayTradeRefund
* @description
* @param orderNo 商户订单号
* @param refundFee 退款金额
*/
@RequestMapping("/alipayTradeRefund")
@ResponseBody
public JsonData alipayTradeRefund(String orderNo, Double refundFee) {
String tradeRefund = aliPayAppService.alipayTradeRefund(orderNo, refundFee);
return JsonData.buildSuccess(tradeRefund);
}
}

5、service层

/**
* 支付宝APP支付业务层接口
*/
public interface AliPayAppService { /**
* 获取支付宝加签后台的订单信息字符串
*/
public String getAliPayOrderStr(Integer userId, Integer videoId); /**
* 支付宝异步请求逻辑处理
*/
public String notify(Map<String, String> conversionParams); /**
* 向支付宝发起订单查询请求
*/
public int checkAlipay(String order_no); /**
* 向支付宝发起退款请求
*/
public String alipayTradeRefund(String order_no, Double refund_fee);
}

6、serviceImpl层

/**
* 阿里支付实现类
*/
@Service
@Slf4j
public class AliPayAppServiceImpl implements AliPayAppService { @Autowired
private AliPayAppService aliPayAppService; @Autowired
private VideoOrderMapper videoOrderMapper; @Autowired
private VideoMapper videoMapper; /**
* 获取支付宝加签后台的订单信息字符串
*/
@Override
@Transactional(propagation = Propagation.REQUIRED)
public String getAliPayOrderStr(Integer userId, Integer videoId) {
String orderString = "";
try {
Video video = videoMapper.selectById(videoId);
//AppUser appUser = appUserMapper.selectById(userId); //生成订单
VideoOrder videoOrder = new VideoOrder();
videoOrder.setVideoId(video.getId());
videoOrder.setOutTradeNo(CommonUtils.generateUUID());
videoOrder.setState(0);
videoOrder.setCreateTime(new Date());
videoOrder.setTotalFee(video.getPrice());
videoOrder.setVideoId(video.getId());
videoOrder.setVideoTitle(video.getTitle());
videoOrder.setVideoImg(video.getCoverImg());
videoOrder.setUserId(userId);
//生成未支付订单
videoOrderMapper.insert(videoOrder);
//实例化客户端(参数:网关地址、商户appid、商户私钥、格式、编码、支付宝公钥、加密类型),为了取得预付订单信息
AlipayClient alipayClient = new DefaultAlipayClient(AppPayConfig.URL, AppPayConfig.APPID,
AppPayConfig.RSA_PRIVATE_KEY, "json", "utf-8",
AppPayConfig.ALIPAY_PUBLIC_KEY, "RSA2");
//实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay
AlipayTradeAppPayRequest ali_request = new AlipayTradeAppPayRequest();
//SDK已经封装掉了公共参数,这里只需要传入业务参数。以下方法为sdk的model入参方式
AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
//业务参数传入,可以传很多,参考API
//model.setPassbackParams(URLEncoder.encode(request.getBody().toString())); //公用参数(附加数据)
//对一笔交易的具体描述信息。如果是多种商品,请将商品描述字符串累加传给body。
model.setBody("云讯网购买视频课程");
//商品名称
model.setSubject(videoOrder.getVideoTitle());
//商户订单号
model.setOutTradeNo(videoOrder.getOutTradeNo());
//交易超时时间 这里的30m就是30分钟
model.setTimeoutExpress("30m");
//支付金额 后面保留2位小数点..不能超过2位
// model.setTotalAmount(String.valueOf(BigDecimal.valueOf(videoOrder.getTotalFee()).divide(BigDecimal.valueOf(100),2,BigDecimal.ROUND_DOWN)));
model.setTotalAmount("0.01"); //销售产品码(固定值) //这个不做多解释..看文档api接口参数解释
model.setProductCode("FACE_TO_FACE_PAYMENT"); //model.setPassbackParams(JSON.toJSONString(alipayBean)); ali_request.setBizModel(model);
//异步回调地址
ali_request.setNotifyUrl(AppPayConfig.notify_url);
//log.info("====================异步通知的地址为:" + ali_request.getNotifyUrl());
//同步回调地址(APP)同上
ali_request.setReturnUrl(AppPayConfig.return_url);
//log.info("====================同步通知的地址为:" + ali_request.getReturnUrl()); // 这里和普通的接口调用不同,使用的是sdkExecute
//返回支付宝订单信息(预处理)
AlipayTradeAppPayResponse alipayTradeAppPayResponse = alipayClient.sdkExecute(ali_request);
//就是orderString 可以直接给APP请求,无需再做处理。
orderString = alipayTradeAppPayResponse.getBody();
System.out.println(orderString); } catch (Exception e) {
e.printStackTrace();
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
log.info("与支付宝交互出错,未能生成订单,请检查代码!");
}
return orderString;
} /**
* 向支付宝发起订单查询请求
*/
@Override
public int checkAlipay(String orderNo) {
log.info("向支付宝发起查询,查询商户订单号为:" + orderNo); try {
// 实例化客户端(参数:网关地址、商户appid、商户私钥、格式、编码、支付宝公钥、加密类型)
AlipayClient alipayClient = new DefaultAlipayClient(AppPayConfig.URL, AppPayConfig.APPID,
AppPayConfig.RSA_PRIVATE_KEY, "json", "utf-8",
AppPayConfig.ALIPAY_PUBLIC_KEY, "RSA2"); AlipayTradeQueryRequest alipayTradeQueryRequest = new AlipayTradeQueryRequest();
alipayTradeQueryRequest.setBizContent("{" + "\"out_trade_no\" : \"" + orderNo + "\"}"); AlipayTradeQueryResponse alipayTradeQueryResponse = alipayClient.execute(alipayTradeQueryRequest);
if (alipayTradeQueryResponse.isSuccess()) { VideoOrder videoOrder = videoOrderMapper.selectById(orderNo); switch (alipayTradeQueryResponse.getTradeStatus()) // 判断交易结果
{
case "TRADE_FINISHED": // 交易结束并不可退款
videoOrder.setState(3);
break;
case "TRADE_SUCCESS": // 交易支付成功
videoOrder.setState(1);
break;
case "TRADE_CLOSED": // 未付款交易超时关闭或支付完成后全额退款
videoOrder.setState(2);
break;
case "WAIT_BUYER_PAY": // 交易创建并等待买家付款
videoOrder.setState(0);
break;
default:
break;
} videoOrderMapper.updateById(videoOrder);// 更新表记录
return videoOrder.getState();
} else {
log.info("调用支付宝查询接口失败!");
}
} catch (AlipayApiException e) {
e.printStackTrace();
}
return 0;
} /**
* 支付宝异步请求逻辑处理
*/
@Override
public String notify(Map<String, String> conversionParams) {
log.info("支付宝异步请求逻辑处理"); // 签名验证(对支付宝返回的数据验证,确定是支付宝返回的)
boolean signVerified = false; try {
// 调用SDK验证签名
signVerified = AlipaySignature.rsaCheckV1(conversionParams, AppPayConfig.ALIPAY_PUBLIC_KEY,
"utf-8", "RSA2"); } catch (AlipayApiException e) {
log.info("验签失败 !");
e.printStackTrace();
} // 对验签进行处理
if (signVerified) {
System.out.println("验签通过");
// 验签通过
// 获取需要保存的数据
String appId = conversionParams.get("app_id");// 支付宝分配给开发者的应用Id
String notifyTime = conversionParams.get("notify_time");// 通知时间:yyyy-MM-dd HH:mm:ss
String gmtCreate = conversionParams.get("gmt_create");// 交易创建时间:yyyy-MM-dd HH:mm:ss
String gmtPayment = conversionParams.get("gmt_payment");// 交易付款时间
//String gmtRefund = conversionParams.get("gmt_refund");// 交易退款时间
//String gmtClose = conversionParams.get("gmt_close");// 交易结束时间
String tradeNo = conversionParams.get("trade_no");// 支付宝的交易号
String outTradeNo = conversionParams.get("out_trade_no");// 获取商户之前传给支付宝的订单号(商户系统的唯一订单号)
//String outBizNo = conversionParams.get("out_biz_no");// 商户业务号(商户业务ID,主要是退款通知中返回退款申请的流水号)
String buyerLogonId = conversionParams.get("buyer_logon_id");// 买家支付宝账号
String buyerId = conversionParams.get("buyer_id"); //买家支付宝用户号(唯一)
String sellerId = conversionParams.get("seller_id");// 卖家支付宝用户号
String sellerEmail = conversionParams.get("seller_email");// 卖家支付宝账号
String totalAmount = conversionParams.get("total_amount");// 订单金额:本次交易支付的订单金额,单位为人民币(元)
String receiptAmount = conversionParams.get("receipt_amount");// 实收金额:商家在交易中实际收到的款项,单位为元
//String invoiceAmount = conversionParams.get("invoice_amount");// 开票金额:用户在交易中支付的可开发票的金额
String buyerPayAmount = conversionParams.get("buyer_pay_amount");// 付款金额:用户在交易中支付的金额
String tradeStatus = conversionParams.get("trade_status");// 获取交易状态 // 支付宝官方建议校验的值(out_trade_no、total_amount、sellerId、app_id)
VideoOrder videoOrder = videoOrderMapper.selectOne(new QueryWrapper<VideoOrder>().eq("out_trade_no", outTradeNo)); if (videoOrder != null && totalAmount.equals(videoOrder.getTotalFee().toString())) {
// 修改数据库支付宝订单表(因为要保存每次支付宝返回的信息到数据库里,以便以后查证) // alipaymentOrder.setNotify_time(DateUtils.parse(notifyTime)); // 通知时间
// alipaymentOrder.setGmt_create(DateUtils.parse(gmtCreate)); // 交易创建时间
// alipaymentOrder.setGmt_payment(DateUtils.parse(gmtPayment)); // 交易付款时间
// //alipaymentOrder.setGmt_refund(DateUtils.parse(gmtRefund)); // 交易退款时间
// //alipaymentOrder.setGmt_close(DateUtils.parse(gmtClose)); // 交易结束时间
// alipaymentOrder.setTrade_no(tradeNo); // 支付宝交易号
// //alipaymentOrder.setOut_biz_no(outBizNo); // 商户业务号(商户业务ID,主要是退款通知中返回退款申请的流水号)
// alipaymentOrder.setBuyer_logon_id(buyerLogonId); // 买家支付宝账号
// alipaymentOrder.setBuyer_id(buyerId); // 买家支付宝用户号(唯一)
// alipaymentOrder.setSeller_id(sellerId); // 卖家支付宝用户号
// alipaymentOrder.setSeller_email(sellerEmail); // 卖家支付宝账号
// alipaymentOrder.setTotal_amount(Double.parseDouble(totalAmount)); //订单金额:本次交易支付的订单金额,单位为人民币(元)
// alipaymentOrder.setReceipt_amount(Double.parseDouble(receiptAmount)); // 实收金额:商家在交易中实际收到的款项,单位为元
// //alipaymentOrder.setInvoiceAmount(Double.parseDouble(invoiceAmount)); // 开票金额:用户在交易中支付的可开发票的金额
// alipaymentOrder.setBuyer_pay_amount(Double.parseDouble(buyerPayAmount)); // 付款金额:用户在交易中支付的金额 switch (tradeStatus) // 判断交易结果
{
case "TRADE_FINISHED": // 交易结束并不可退款
videoOrder.setState(3);
break;
case "TRADE_CLOSED": // 未付款交易超时关闭或支付完成后全额退款
videoOrder.setState(2);
break;
case "TRADE_SUCCESS": // 交易支付成功
videoOrder.setState(1);
break; case "WAIT_BUYER_PAY": // 交易创建并等待买家付款
videoOrder.setState(0);
break;
default:
break;
}
int returnResult = videoOrderMapper.updateById(videoOrder); // 更新交易表中状态 if (tradeStatus.equals("TRADE_SUCCESS")) { // 只处理支付成功的订单:
// 修改交易表状态,支付成功
if (returnResult > 0) {
log.info("======更新商户订单表成功======");
return "success";
} else {
return "fail";
}
} else {
return "fail";
} } else {
log.info("支付宝官方建议校验的值(out_trade_no、total_amount、sellerId、app_id),不一致!返回fail");
return "fail";
} } else { // 验签不通过
log.info("验签不通过 !");
return "fail";
}
} /**
* 向支付宝发起退款请求
*/
@Transactional(propagation = Propagation.REQUIRED)
@Override
public String alipayTradeRefund(String order_no, Double refund_fee) {
String returnStr = null;
int code;
try { AlipayClient alipayClient = new DefaultAlipayClient(AppPayConfig.URL, AppPayConfig.APPID,
AppPayConfig.RSA_PRIVATE_KEY, "json", "utf-8",
AppPayConfig.ALIPAY_PUBLIC_KEY, "RSA2"); AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();//创建API对应的request类
request.setBizContent("{" +
" \"out_trade_no\":\"" + order_no + "\"," +
" \"refund_amount\":\"" + refund_fee + "\"" +
" }");//设置业务参数
AlipayTradeRefundResponse response = alipayClient.execute(request);//通过alipayClient调用API,获得对应的response类 log.info("退款返回参数====" + response); if (response.isSuccess()) {
log.info("====支付宝退款成功");
// 通过订单号查询到商家支付宝订单信息
VideoOrder videoOrder = videoOrderMapper.selectOne(new QueryWrapper<VideoOrder>().eq("out_trade_no", order_no)); if (videoOrder == null) {
log.info("该订单不存在");
}
// // 退款总金额
// videoOrder.setRefund_fee(Double.valueOf(response.getRefundFee()));
// // 退款时间
// alipaymentOrder.setGmt_refund(response.getGmtRefundPay());
// // 退款状态
// alipaymentOrder.setTrade_status(AlipayReturnEnum.TRADE_CLOSED.getIndex());
// // 本次退款是否发生了资金变化
// alipaymentOrder.setFund_change(response.getFundChange());
// // 交易在支付时候的门店名称
// alipaymentOrder.setStore_name(response.getStoreName());
videoOrder.setState(2);
// 修改商家支付宝订单状态以及退款金额
videoOrderMapper.updateById(videoOrder); returnStr = response.getMsg();
} else {
// 返回退款失败消息
log.info("===退款失败===原因:" + response.getSubMsg());
returnStr = response.getSubMsg();
}
code = Integer.parseInt(response.getCode()); } catch (Exception e) {
e.printStackTrace();
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
return returnStr;
}
}

APP对接支付宝付款的更多相关文章

  1. App对接支付宝移动支付功能

    前段时间看了下app对接支付宝移动支付的功能,并自己总结了下支付宝移动支付的实现流程 一.申请流程          前提是已有现成的应用. 1.  申请地址            https://b ...

  2. 【原创分享·支付宝支付】HBuilder打包APP调用支付宝客户端支付

    前言 最近有点空余时间,所以,就研究了一下APP支付.前面很早就搞完APP的微信支付了,但是由于时间上和应用上的情况,支付宝一直没空去研究.然后等我空了的时候,发现支付宝居然升级了支付逻辑,虽然目前还 ...

  3. wap站、手机APP 接入支付宝、微信、银联支付。

    一.wap站 ①.支付宝接入 1.开发前准备:申请一个通过实名认证的企业支付宝账号,并申请开通手机WAP支付功能. 2.流程 参数准备: 企业支付宝账号的PID(也叫ParnerID)和KEY,如果使 ...

  4. PHP实现app唤起支付宝支付代码

    本文主要和大家分享PHP实现app唤起支付宝支付代码,希望能帮助到大家. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 ...

  5. Django 支付宝付款接口的使用

    我们在开发的过程中经常会碰到调用微信或者支付宝接口进行付款,付款完成之后,如果用户绑定了我的账号,我只要有活动了,就要给这个关注我的用户推动消息,让用户知道,比如说,我们经常会关注一些公众号,然后这些 ...

  6. iOS app集成支付宝支付流程及后台php订单签名处理

    iOS app集成支付宝支付流程 1: 开通支付宝商户 由公司去支付宝 https://b.alipay.com/order/serviceIndex.htm 签约支付宝开通支付宝商家: 2:商户支付 ...

  7. GoDaddy用支付宝付款时出现我们无法处理这笔交易,请查看您的付款信息并重试。

    一.GoDaddy操作流程 在GoDaddy上购买及注册域名的操作步骤,请参考https://www.jianshu.com/p/05289a4bc8b2进行操作. 二.我遇到的问题 今天用GoDad ...

  8. iOS跳转支付宝付款码和扫一扫页面

    iOS跳转支付宝付款码和扫一扫页面 // 是否支持支付宝 NSURL * myURL_APP_A = [NSURL URLWithString:@"alipay://"]; if ...

  9. Python对接支付宝支付自实现

    Python对接支付宝支付自实现 # -*- coding: utf-8 -*- import base64 import json import urllib.parse from datetime ...

  10. Thinkcmf对接支付宝支付和获取用户信息

    一.         登录支付宝开放平台 平台地址:https://open.alipay.com/ 二.         创建应用并申请上线 登录后,[进入我的开放平台],依次点击[开发者中心]-& ...

随机推荐

  1. Python读取保存图像文件

    Python处理图像数据时通常需要对图像文件进行读取.保存等操作,因此将现有的方法归纳了一下. 1. PIL 依赖包:Pillow 安装:pip install Pillow 源码: 1 import ...

  2. 2.2 在resources目录下,新建applicationContext.xml

    <?xml version="1.0" encoding="UTF-8"?> <beans> <!-- 这个bean标签的作用是, ...

  3. 华为MA5626和S2700重置密码

    MA5626和S2700交换机,初始化密码遇到的问题. 主要目的把两台设备改成普通二层交换机. 一.MA5626交换机 1.进入设备,发现有密码. 帐号:root 密码:mduadmin 2.使用空配 ...

  4. 在linux 下如何快速创建环境

    首先先在你的主目录下创建一个文件 touch venv python创建环境 python3 -m venv venv 创建虚拟环境 (提示:当你有错找不到的时候可以重新创建一个环境) source ...

  5. 阿里播放器Aliplayer遇到的所有坑

    1,关于阿里播放器使用过的几种播放方式 url (source) ① 要在创建播放器前要拿到资源否则会报错 ② 在有不同清晰度的资源时  直接调用 player.loadByUrl() 方法会报错 官 ...

  6. mysql:数据库加解密查询

    解密:SELECT CONVERT (AES_DECRYPT(UNHEX( column_name), '密钥') USING utf8) AS column_name,from table_name ...

  7. 073_SFDC Limit

    我们在开发的过程中,应多注意一些系统自身的限制,以及遇到此类问题的应对措施: Description Synchronous Limit Asynchronous Limit Total number ...

  8. textfsm

    from concurrent.futures import ThreadPoolExecutor import netmiko import os from threading import Loc ...

  9. Qt项目移植

    从Qt低版本到高版本 一开始使用的是Qt Creator 4.6.2(Enterprise) 后面下载了Qt Creator 4.13.3(Enterprise) 一开始在Qt Creator 4.1 ...

  10. 关于.bashrc文件

    文件作用 存储临时变量 注意 每个user都有自己的.bashrc文件,root用户也有. 普通用户在"/home/username/"目录下 root在"/root&q ...