APP对接支付宝付款
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对接支付宝付款的更多相关文章
- App对接支付宝移动支付功能
前段时间看了下app对接支付宝移动支付的功能,并自己总结了下支付宝移动支付的实现流程 一.申请流程 前提是已有现成的应用. 1. 申请地址 https://b ...
- 【原创分享·支付宝支付】HBuilder打包APP调用支付宝客户端支付
前言 最近有点空余时间,所以,就研究了一下APP支付.前面很早就搞完APP的微信支付了,但是由于时间上和应用上的情况,支付宝一直没空去研究.然后等我空了的时候,发现支付宝居然升级了支付逻辑,虽然目前还 ...
- wap站、手机APP 接入支付宝、微信、银联支付。
一.wap站 ①.支付宝接入 1.开发前准备:申请一个通过实名认证的企业支付宝账号,并申请开通手机WAP支付功能. 2.流程 参数准备: 企业支付宝账号的PID(也叫ParnerID)和KEY,如果使 ...
- 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 ...
- Django 支付宝付款接口的使用
我们在开发的过程中经常会碰到调用微信或者支付宝接口进行付款,付款完成之后,如果用户绑定了我的账号,我只要有活动了,就要给这个关注我的用户推动消息,让用户知道,比如说,我们经常会关注一些公众号,然后这些 ...
- iOS app集成支付宝支付流程及后台php订单签名处理
iOS app集成支付宝支付流程 1: 开通支付宝商户 由公司去支付宝 https://b.alipay.com/order/serviceIndex.htm 签约支付宝开通支付宝商家: 2:商户支付 ...
- GoDaddy用支付宝付款时出现我们无法处理这笔交易,请查看您的付款信息并重试。
一.GoDaddy操作流程 在GoDaddy上购买及注册域名的操作步骤,请参考https://www.jianshu.com/p/05289a4bc8b2进行操作. 二.我遇到的问题 今天用GoDad ...
- iOS跳转支付宝付款码和扫一扫页面
iOS跳转支付宝付款码和扫一扫页面 // 是否支持支付宝 NSURL * myURL_APP_A = [NSURL URLWithString:@"alipay://"]; if ...
- Python对接支付宝支付自实现
Python对接支付宝支付自实现 # -*- coding: utf-8 -*- import base64 import json import urllib.parse from datetime ...
- Thinkcmf对接支付宝支付和获取用户信息
一. 登录支付宝开放平台 平台地址:https://open.alipay.com/ 二. 创建应用并申请上线 登录后,[进入我的开放平台],依次点击[开发者中心]-& ...
随机推荐
- Python读取保存图像文件
Python处理图像数据时通常需要对图像文件进行读取.保存等操作,因此将现有的方法归纳了一下. 1. PIL 依赖包:Pillow 安装:pip install Pillow 源码: 1 import ...
- 2.2 在resources目录下,新建applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?> <beans> <!-- 这个bean标签的作用是, ...
- 华为MA5626和S2700重置密码
MA5626和S2700交换机,初始化密码遇到的问题. 主要目的把两台设备改成普通二层交换机. 一.MA5626交换机 1.进入设备,发现有密码. 帐号:root 密码:mduadmin 2.使用空配 ...
- 在linux 下如何快速创建环境
首先先在你的主目录下创建一个文件 touch venv python创建环境 python3 -m venv venv 创建虚拟环境 (提示:当你有错找不到的时候可以重新创建一个环境) source ...
- 阿里播放器Aliplayer遇到的所有坑
1,关于阿里播放器使用过的几种播放方式 url (source) ① 要在创建播放器前要拿到资源否则会报错 ② 在有不同清晰度的资源时 直接调用 player.loadByUrl() 方法会报错 官 ...
- mysql:数据库加解密查询
解密:SELECT CONVERT (AES_DECRYPT(UNHEX( column_name), '密钥') USING utf8) AS column_name,from table_name ...
- 073_SFDC Limit
我们在开发的过程中,应多注意一些系统自身的限制,以及遇到此类问题的应对措施: Description Synchronous Limit Asynchronous Limit Total number ...
- textfsm
from concurrent.futures import ThreadPoolExecutor import netmiko import os from threading import Loc ...
- Qt项目移植
从Qt低版本到高版本 一开始使用的是Qt Creator 4.6.2(Enterprise) 后面下载了Qt Creator 4.13.3(Enterprise) 一开始在Qt Creator 4.1 ...
- 关于.bashrc文件
文件作用 存储临时变量 注意 每个user都有自己的.bashrc文件,root用户也有. 普通用户在"/home/username/"目录下 root在"/root&q ...