Vue 支付宝支付
1、支付宝介绍
支付宝(中国)网络技术有限公司成立于2004年,是国内的第三方支付平台,致力于为企业和个人提供“简单、安全、快速、便捷”的支付解决方案。支付宝公司从2004年建立开始,始终以“信任”作为产品和服务的核心。旗下有“支付宝”与“支付宝钱包”两个独立品牌。自2014年第二季度开始成为当前全球最大的移动支付厂商。
支付宝与国内外180多家银行以及VISA、MasterCard国际组织等机构建立战略合作关系,成为金融机构在电子支付领域最为信任的合作伙伴。
2020年2月,尼泊尔央行向支付宝颁发牌照。7月,支付宝入选区块链战“疫”优秀方案名单。10月,支付宝上线 “晚点付”功能。2021年12月,支付宝与中国银联在全国范围实现收款码扫码互认。
支付宝借呗改成信用贷。 12月2日,支付宝发布公告表示,支付宝与中国银联在2020年开始基于条码互联互通业务展开密切沟通和探索,并陆续在北京、天津、广州、深圳、成都、重庆、西安等多个城市实现收款码扫码互认 。
2022年2月,支付宝公布“支持中国女足发展工作小结”:已累计向中国足协拨款2.5亿元。
2022年8月,支付宝(中国)网络技术有限公司法定代表人、董事长将由井贤栋变更为倪行军。
百度百科介绍:
百度百科-支付宝
2、主要功能
1、支持余额宝,理财收益随时查看;
2、支持各种场景关系,群聊群付更方便;
3、提供本地生活服务,买单打折尽享优惠;
4、为子女父母建立亲情账户;
5、随时随地查询淘宝账单、账户余额、物流信息;
6、免费异地跨行转账,信用卡还款、充值、缴水电煤气费;
7、还信用卡、付款、缴费、充话费、卡券信息智能提醒;
8、行走捐,支持接入iPhone健康数据,可与好友一起健康行走及互动,还可以参与公益。 [63]
9、蚂蚁森林,通过特定方式获得能量,能量可以养成一棵树,养成后即可在现实某个地域种下一棵实体的树 [65] 。
3、日记风波
2016年11月支付宝推出圈子功能,发帖与芝麻信用分捆绑,甚至只限女性,由于出现大量美女自拍,甚至大尺度照片,因此被网友调侃为“支付鸨”。
在支付宝首页搜索框查找圈子功能的入口。其中“白领日记”和“校园日记”的圈子都显示有超过300万人看过,而这两个圈子都是在两三天前创建。但这些打着白领和校园标签的圈子,只允许女性发动态,而这些动态内容含有很多露骨的图片和暗示性语言。根据圈子的规则,明确规定只有女性有发帖权限,男性用户只能点赞、打赏和评论,且芝麻信用低于750分的用户也不允许评论。
支付宝已将一周内引起巨大争议的两大“圈子”悄悄下线。原本出现在支付宝首页的“白领日记”和“校园日记”等邀请,点进去已没有内容。
4、官方网站
支付宝-官网网站
第二节 支付宝沙箱环境开发
1、支付宝沙箱介绍
点击进入 支付宝沙箱环境
# 支付宝沙箱环境
https://opendocs.alipay.com/common/02kkv7
12
2、支付宝扫码登录进入沙箱环境
# 支付宝扫码登录进入沙箱环境
https://openhome.alipay.com/platform/developerIndex.htm
12
3、支付宝沙箱环境介绍
1)、沙箱应用
2)、沙箱账号
3)、沙箱工具
安装后,如下图:
参考文章
- 使用支付宝登录
- 沙箱账号应用
- 当面付代码示例
- 电脑网站支付
以上参考于恩师blog [参码踪 (shenmazong.com)]
支付界面如下所示:
当点击立即支付时,触发支付事件:
.png)]
了解一下支付流程:
调用支付接口→拿到form表单→调起支付页面→查询支付结果
支付详解:
1、支付接口的参数并不是固定的,而是由后端决定,在接口发送成功后,我们会的得到响应数据,该数据并非JSON格式,而是一个表单数据!
开始使用支付宝沙箱完成支付功能》》》》
(1) 、首先引入Alipay依赖
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>4.10.97.ALL</version>
</dependency>
(2) 、写自己的配置文件 AlipayConfig
支付宝网关一定要使用dev沙箱版 正式开发时去掉即可
// 支付宝网关
public static String gatewayUrl = "https://openapi.alipaydev.com/gateway.do";
import java.io.FileWriter;
import java.io.IOException;
/**
* @Author Sun
* @Version 1.0
* @description: 不可描述
* @date
*/
/* *
*类名:AlipayConfig
*功能:基础配置类
*详细:设置帐户有关信息及返回路径
*修改日期:2017-04-05
*说明:
*以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。
*该代码仅供学习和研究支付宝接口使用,只是提供一个参考。
*/
public class AlipayConfig {
//↓↓↓↓↓↓↓↓↓↓请在这里配置您的基本信息↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
// 应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号
public static String app_id = "支付宝账号";
// 商户私钥,您的PKCS8格式RSA2私钥
public static String merchant_private_key = "填写自己的商户私钥";
// 支付宝公钥,查看地址:https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥。
public static String alipay_public_key = "支付宝公钥";
// 服务器异步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
public static String notify_url = "http://工程公网访问地址/alipay.trade.page.pay-JAVA-UTF-8/notify_url.jsp";
// 页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
// public static String return_url = "http://工程公网访问地址/alipay.trade.page.pay-JAVA-UTF-8/return_url.jsp";
public static String return_url = "http://localhost:9013/order/getResult";
// 签名方式
public static String sign_type = "RSA2";
// 字符编码格式
public static String charset = "utf-8";
// 支付宝网关
public static String gatewayUrl = "https://openapi.alipaydev.com/gateway.do";
// 支付宝网关
public static String log_path = "D:\\";
//↑↑↑↑↑↑↑↑↑↑请在这里配置您的基本信息↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
/**
* 写日志,方便测试(看网站需求,也可以改成把记录存入数据库)
* @param sWord 要写入日志里的文本内容
*/
public static void logResult(String sWord) {
FileWriter writer = null;
try {
writer = new FileWriter(log_path + "alipay_log_" + System.currentTimeMillis()+".txt");
writer.write(sWord);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (writer != null) {
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
配置信息完成后来看看接口怎么写的吧
Controller层
/**
* 支付宝支付
* @param payWeChatOrderVo
* @return
* @throws AlipayApiException
*/
@PostMapping("alipay-pay")
public ResultResponse pay(@RequestBody PayWeChatOrderVo payWeChatOrderVo) throws AlipayApiException {
return tbOrderService.aliPay(payWeChatOrderVo);
}
/*
PayWeChatOrderVo自己定义的订单信息根据自己项目变更即可(也可以使用官方给出的参数)
@Data
public class PayWeChatOrderVo implements Serializable {
private Long outTradeNo;
private String description;
private Long amount;
private String attach;
}
*/
Service Impl
@Override
public ResultResponse aliPay(PayWeChatOrderVo payWeChatOrderVo) throws AlipayApiException {
//获得初始化的AlipayClient
AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.gatewayUrl, AlipayConfig.app_id, AlipayConfig.merchant_private_key, "json", AlipayConfig.charset, AlipayConfig.alipay_public_key, AlipayConfig.sign_type);
//设置请求参数
AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
alipayRequest.setReturnUrl(AlipayConfig.return_url);
alipayRequest.setNotifyUrl(AlipayConfig.notify_url);
//商户订单号,商户网站订单系统中唯一订单号,必填
Long out_trade_no = payWeChatOrderVo.getOutTradeNo();
//付款金额,必填
Long total_amount = payWeChatOrderVo.getAmount();
//订单名称,必填
String subject = payWeChatOrderVo.getAttach();
//商品描述,可空
String body = payWeChatOrderVo.getDescription();
alipayRequest.setBizContent("{\"out_trade_no\":\""+ out_trade_no +"\","
+ "\"total_amount\":\""+ total_amount +"\","
+ "\"subject\":\""+ subject +"\","
+ "\"body\":\""+ body +"\","
+ "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");
//若想给BizContent增加其他可选请求参数,以增加自定义超时时间参数timeout_express来举例说明
//alipayRequest.setBizContent("{\"out_trade_no\":\""+ out_trade_no +"\","
// + "\"total_amount\":\""+ total_amount +"\","
// + "\"subject\":\""+ subject +"\","
// + "\"body\":\""+ body +"\","
// + "\"timeout_express\":\"10m\","
// + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");
//请求参数可查阅【电脑网站支付的API文档-alipay.trade.page.pay-请求参数】章节
//请求
String result = alipayClient.pageExecute(alipayRequest).getBody();
return ResultResponse.SUCCESS().data("result", result);
}
最后返回结果:
"result": "<form name=\"punchout_form\" method=\"post\" action=\"https://openapi.alipaydev.com/gateway.do?charset=utf-8&method=alipay.trade.page.pay&sign=YVU9IIZLSal7va53ep%2B46Z2ZFtEE%2BDGiA9abXrKKzJfSHMbXRxxyQNEzRQbrkzY3LsFIJvPkwucDWFH7kBzWSMLnAZptD%2BZymd4byKsNBrVPLba39yw9sO7YgxlJLc9G9v5hd3CPTW2zQYaJXE14rUFVZi%2F5tk7Q4NXvPVVXGcnj%2BfwTjHh0XVJZ4GFb8D7McuVDcVeHy4sXDMCKPZ7BYKbfmDnKCQhwUrF%2B2uMZClUc6xNdyB%2FKS%2FOCJ4pE4LB50aJfUFNKU%2FY2pboCmo9mOnl41LoSMizOGtIhydR6%2FrVPA%2Bnd93lwJ%2FjgxC3ySmnDZ49fHi9YBieAjMmMkdnhTw%3D%3D&return_url=http%3A%2F%2Flocalhost%3A9013%2Forder%2FgetResult¬ify_url=http%3A%2F%2F%E5%B7%A5%E7%A8%8B%E5%85%AC%E7%BD%91%E8%AE%BF%E9%97%AE%E5%9C%B0%E5%9D%80%2Falipay.trade.page.pay-JAVA-UTF-8%2Fnotify_url.jsp&version=1.0&app_id=2021000122606111&sign_type=RSA2×tamp=2022-12-25+16%3A00%3A57&alipay_sdk=alipay-sdk-java-dynamicVersionNo&format=json\">\n<input type=\"hidden\" name=\"biz_content\" value=\"{"out_trade_no":"852963741","total_amount":"1","subject":"1","body":"1","product_code":"FAST_INSTANT_TRADE_PAY"}\">\n<input type=\"submit\" value=\"立即支付\" style=\"display:none\" >\n</form>\n<script>document.forms[0].submit();</script>"
2、接下来如何将得到的数据调起支付界面呢?我们需要在页面中有一个可以提供渲染的元素,该元素可以在网页的任何位置
<div ref="alipayWap" v-html="alipay" />
3、在接口响应成功后,将数据渲染到元素内,通过触发表单的提交事件,就可以调起支付接口了,是不是非常简单
// 调用支付接口
//支付宝
alipayhandleBuy(index, row) {
console.log(index, row);
this.aliPaydialogTableVisible = true;
let param = {};
param.outTradeNo = row.orderNo;
param.description = row.productName;
param.amount = row.orderAmount;
param.attach = row.productName;
this.orderNoa = row.orderNo;
apipay(param).then((res) => {
// 渲染支付页面
this.alipay = res.data.data.result;
// 防抖避免重复支付
this.$nextTick(() => {
// 提交支付表单
this.$refs.alipayWap.children[0].submit();
setTimeout(() => {
// this.toPayFlag = false;
}, 500);
});
});
},
4、最后就是回调函数了
在填写之前的配置信息时同步回调路径写上自己的函数(同步)
/**
* 得到支付结果 以下代码均来自于支付宝官网
* @param request
* @param response
* @return
* @throws AlipayApiException
*/
@Override
public void aliPayResult(HttpServletRequest request, HttpServletResponse response) throws AlipayApiException, IOException {
//获取支付宝GET过来反馈信息
Map<String,String> params = new HashMap<String,String>();
Map<String,String[]> requestParams = request.getParameterMap();
for (Iterator<String> 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] + ",";
}
//乱码解决,这段代码在出现乱码时使用
// valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
params.put(name, valueStr);
}
boolean signVerified = AlipaySignature.rsaCheckV1(params, AlipayConfig.alipay_public_key, AlipayConfig.charset, AlipayConfig.sign_type); //调用SDK验证签名
//——请在这里编写您的程序(以下代码仅作参考)——
String out_trade_no="";
if(signVerified) {
//商户订单号
out_trade_no = request.getParameter("out_trade_no");
//支付宝交易号
String trade_no = request.getParameter("trade_no");
//付款金额
String total_amount = request.getParameter("amount");
System.out.println("trade_no:"+trade_no+"<br/>out_trade_no:"+out_trade_no+"<br/>total_amount:"+total_amount);
log.info("成功转发到产品列表");
//支付成功修改状态
OrderNoInfoVo orderNoInfoVo = new OrderNoInfoVo();
orderNoInfoVo.setOrderNo(out_trade_no);
updateState(orderNoInfoVo);
response.sendRedirect("http://localhost:8080/#/order?orderNo="+out_trade_no);
}else {
System.out.println("验签失败");
log.error("失败转发到订单列表");
//0000 失败订单编号
String fail="0000";
response.sendRedirect("http://localhost:8080/#/order?orderNo="+fail);
}
}
验证成功返还正常的订单编号,失败则返回-0000
这时候重定向到订单列表地址栏取得商品订单编号就可以校验订单是否成功
就绪函数
created() {
this.LoadList();
//取得地址信息
let orderOnInfo=this.$route.query.orderNo
console.log("orderOnInfo====",orderOnInfo)
if(orderOnInfo != null && orderOnInfo!='000'){
this.$message.success("支付成功")
//清除地址栏
let path = this.$route.path; //先获取路由路径
this.$router.push(path); //再跳转路由路径,query参数没带过去,所以被清除了
}
}
单列表地址栏取得商品订单编号就可以校验订单是否成功
就绪函数
created() {
this.LoadList();
//取得地址信息
let orderOnInfo=this.$route.query.orderNo
console.log("orderOnInfo====",orderOnInfo)
if(orderOnInfo != null && orderOnInfo!='000'){
this.$message.success("支付成功")
//清除地址栏
let path = this.$route.path; //先获取路由路径
this.$router.push(path); //再跳转路由路径,query参数没带过去,所以被清除了
}
}
参考链接:【https://blog.csdn.net/Goodboygo/article/details/120153900】