支付宝API支付使用文档–java《扫一扫支付》–demo但是封装高可用–改一改配置就拿走用!超详细!!有手就行!!!(上)修改官网配置类_一单成的博客-CSDN博客
阿丹:
上一篇文章具体的描述和讲解了官方提供的配置类,以及如何使用注册开发沙箱,本篇文章重点描述和讲解如何实现代码的编写,以及具体实现的流程,以及数据的流向。重点是将开发的过程记录,并最后封装为工具类方便大家开发。尽量做到拿取代码修改配置即可使用。
阿丹提醒:
请在阅读本文章之前先详细查看阿丹的效果演示说明以及本文章中需要的技术栈以及核心思想。以及该技术点的特性。
展示为网站和手机进行支付交互。演示图片中的二维码为一次性扫描的二维码。
解释说明:
本代码或者说例子是用在当面付的预创建接口
构建以及使用这个类:AlipayTradePrecreateRequest
开发思路:
在上次开发的时候我们发现有这两个地址没有写,并且会有疑惑我扫描二维码的页面哪里来呢?
不要着急我在后面会进行说明的。
实现思路以及流程图梳理
在文章中我就不在详解加签等操作了(之前已经完成了封装),我们主要讲解一下,专注于业务的流程以及数据流向。
我将数据流向分为了三条线方便大家,梳理,理解
黑:
1、用户进入结算付款页面
2、根据用户订单信息构建PayReq实体类,携带实体类访问请求/createQR接口
3、与服务/bindingRecord建立websocket连接(用于监听支付信息/状态)
红:
1、/createQR接口生成支付二维码,通过返回response结果的方式来在vue页面使用弹框展示。
2、用户使用扫一扫扫码支付
3、用户手机请求到支付宝应用
绿:
1、支付宝给我们的系统发送支付状态信息,请求调用了/call接口
2、call接口向前台发送支付完成信息完成支付!!
我们开始上代码!!
后台代码:
梳理其实实现很简单。我们需要一个生成二维码的接口、一个websocket接口、一个回调函数(获取支付状态)
相关配置以及使用沙箱说明在这里拿取!!!!!
用于websocekt连接!!
package com.adn.controller;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet;
/**
* WebSocket服务
*
**/
//连接webSocket服务的URL
@ServerEndpoint("/bindingRecord")
@Component
@Slf4j
public class WebSocket {
private Session session;
private static CopyOnWriteArraySet<WebSocket> webSockets = new CopyOnWriteArraySet<>();
/**
* 新建webSocket配置类
* @return
*/
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
/**
* 建立连接
* @param session
*/
@OnOpen
public void onOpen(Session session) {
this.session = session;
webSockets.add(this);
log.info("【新建连接】,连接总数:{}", webSockets.size());
}
/**
* 断开连接
*/
@OnClose
public void onClose(){
webSockets.remove(this);
log.info("【断开连接】,连接总数:{}", webSockets.size());
}
/**
* 接收到信息
* @param message
*/
@OnMessage
public void onMessage(String message){
log.info("【收到】,客户端的信息:{},连接总数:{}", message, webSockets.size());
}
/**
* 发送消息
* @param message
*/
public void sendMessage(String message){
log.info("【广播发送】,信息:{},总连接数:{}", message, webSockets.size());
for (WebSocket webSocket : webSockets) {
try {
webSocket.session.getBasicRemote().sendText(message);
} catch (IOException e) {
log.info("【广播发送】,信息异常:{}", e.fillInStackTrace());
}
}
}
}
代码解释:
这段代码是一个WebSocket服务实现类。它使用了Spring framework提供的注解和依赖项,可以轻松地创建一个WebSocket服务器端点。
主要的注解包括:
@ServerEndpoint("/bindingRecord")
:指定WebSocket的URL地址,客户端将通过这个地址连接到WebSocket服务器。@Component
:将该类声明为Spring组件,可以被Spring容器管理。@OnOpen
、@OnClose
、@OnMessage
:这些注解用于定义WebSocket的生命周期回调方法。@Bean
:这个注解用于表明serverEndpointExporter()
方法返回的实例将被Spring容器管理,用于将WebSocket的相关配置发布为服务器的端点。
该类还包括一些实例变量和方法,用于处理WebSocket连接和消息的收发:
session
:表示当前连接的WebSocket会话。webSockets
:一个用于存储所有连接到WebSocket服务器的WebSocket实例的并发集合。onOpen()
:建立连接时调用的方法,将新的WebSocket实例添加到webSockets
集合中。onClose()
:断开连接时调用的方法,从webSockets
集合中移除当前WebSocket实例。onMessage()
:收到客户端发送的消息时调用的方法,在控制台打印消息和连接总数。sendMessage()
:用于广播消息给所有连接的客户端,使用getBasicRemote().sendText(message)
方法发送消息。
总的来说,这段代码实现了一个简单的WebSocket服务端,可以与客户端建立连接并进行消息的收发。
请求实体类!
package com.adn.common.domain.request;
import lombok.Data;
/**
* 支付请求实体类
* */
@Data
public class PayReq {
//商品订单号
private String out_trade_no;
//订单名称
private String subject;
//付款金额
private String total_amount;
//商品订单描述
private String body;
}
商品订单号、订单名称、付款金额、商品描述这几个参数只有商品订单描述可以选填,其他的都不能为空!!
后台请求
/createQR、/call接口书写
package com.adn.controller;
import com.adn.common.domain.request.PayReq;
import com.adn.common.domain.response.AliReturnPayBean;
import com.adn.common.result.Result;
import com.adn.common.utils.AppUtil;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.request.AlipayTradePrecreateRequest;
import com.alipay.api.response.AlipayTradePrecreateResponse;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@RestController
@Log4j2
public class PayController {
@Resource
private AlipayClient alipayClient;
@Resource
private AlipayTradePagePayRequest alipayTradePagePayRequest;
@Autowired
private AppUtil appUtil;
@Autowired
private WebSocket webSocket;
@RequestMapping("/createQR")
public Result send(@RequestBody PayReq req) {
AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest(); //创建API对应的request/0/ 类
// request.setNotifyUrl("http://cv95x3.natappfree.cc/call");
System.out.println(req.toString());
request.setNotifyUrl(appUtil.getNotifyurl());
//同步回调地址
// request.setReturnUrl("");
request.setBizContent("{\"out_trade_no\":\""+ req.getOut_trade_no() +"\","
+ "\"total_amount\":\""+ req.getTotal_amount() +"\","
+ "\"subject\":\""+ req.getSubject() +"\","
+ "\"body\":\""+ req.getBody() +"\","
+ "\"product_code\":\"FACE_TO_FACE_PAYMENT\"}");
AlipayTradePrecreateResponse response = null;
try {
response = alipayClient.execute(request);
} catch (AlipayApiException e) {
throw new RuntimeException(e);
}
if (response.isSuccess()) {
System.out.println("调用成功");
//获取二维码
return Result.success(response.getQrCode());
} else {
System.out.println("调用失败");
}
return Result.error();
}
/**
* 支付宝回调函数
* @param request
* @param response
* @param returnPay
* @throws IOException
*/
@RequestMapping("/call")
public void call(HttpServletRequest request, HttpServletResponse response, AliReturnPayBean returnPay) throws IOException {
response.setContentType("type=text/html;charset=UTF-8");
log.info("支付宝的的回调函数被调用");
if (!appUtil.checkSign(request)) {
log.info("验签失败");
response.getWriter().write("failture");
return;
}
if (returnPay == null) {
log.info("支付宝的returnPay返回为空");
response.getWriter().write("success");
return;
}
log.info("支付宝的returnPay" + returnPay.toString());
//表示支付成功状态下的操作
if (returnPay.getTrade_status().equals("TRADE_SUCCESS")) {
log.info("支付宝的支付状态为TRADE_SUCCESS");
//业务逻辑处理 ,webSocket在下面会有介绍配置
webSocket.sendMessage("true");
}
response.getWriter().write("success");
}
}
代码解释:
这就是重要的两个的请求的端口路径,那么在这里还有一个重点
这个参数就是面对面的支付的重要参数,在使用前可以去官网上先确定一下相关的状态码。
特别重点!!!
在这里写的路径call其实就是我们之前提到的!配置文件中没有写的!!同步通知地址!!
在我们写过了这个路径的时候要配置中的回调路径地址写上!!!
同时要注意这个地址一定是外网能够访问的!!如果是在本地的开发环境,那就需要去百度一下内网穿透了,要注意这里的配置,在上线(部署服务器之后!!)要将路径的地址改为对应服务器的ip地址。
前台vue页面!!!!
封装的请求:
import request from '@/utils/request'
export function getpay(data) {
return request({
url: '/createQR',
method: 'post',
data: data
})
}
在main.js导入依赖
下载依赖
npm install vue-qr
导入使用依赖
import vueQr from 'vue-qr'
Vue.component('vueQr', vueQr)
vue完整页面
<template>
<div>
<el-form ref="form" :model="payform" label-width="80px">
<el-form-item label="商户订单号">
<el-input v-model="payform.out_trade_no"></el-input>
</el-form-item>
<el-form-item label="订单名称">
<el-input v-model="payform.subject"></el-input>
</el-form-item>
<el-form-item label="付款金额">
<el-input v-model="payform.total_amount"></el-input>
</el-form-item>
<el-form-item label="商品描述">
<el-input v-model="payform.body"></el-input>
</el-form-item>
<!-- 支付按钮,模拟支付操作 -->
<van-button type="primary" @click="pay">支付</van-button>
<el-dialog :title="paySucc?'支付成功':'扫码支付'" :visible.sync="dialogVisible" width="20%" center>
<!-- 生成二维码图片 -->
<vueQr :text="text" :size="200" v-if="!paySucc"></vueQr>
<!-- 使用websocket监控是否扫描,扫描成功显示成功并退出界面 -->
<span class="iconfont icon-success" style="position: relative;font-size: 100px;color:#42B983;margin-left: 50px;top:-10px;" v-else></span>
</el-dialog>
</el-form>
<!-- <el-dialog-->
<!-- title="提示"-->
<!-- :visible.sync="dialogVisible"-->
<!-- width="80%"-->
<!-- hidden="80%"-->
<!-- :before-close="handleClose">-->
<!-- <span slot="footer" class="dialog-footer">-->
<!-- <el-button @click="dialogVisible = false">取 消</el-button>-->
<!-- <el-button type="primary" @click="dialogVisible = false">确 定</el-button>-->
<!-- </span>-->
<!-- </el-dialog>-->
<!-- <div v-html="this.htmlstr"></div>-->
<!-- </div>-->
</div>
</template>
<script>
//这里可以导入其他文件(比如:组件,工具js,第三方插件js,json文件,图片文件等等),
//例如:import 《组件名称》 from '《组件路径》,
import { getpay } from '@/api/pay'
import axios from 'axios'
import vueQr from 'vue-qr'
export default {
//import引入的组件需要注入到对象中才能使用"
components: {
},
props: {},
data() {
//这里存放数据"
return {
text: "",
paySucc: false,
dialogVisible:false,
payform:{
out_trade_no:'',
subject:'',
total_amount:'',
body:'',
},
htmlstr:''
};
},
//计算属性 类似于data概念",
computed: {},
//监控data中的数据变化",
watch: {},
//方法集合",
methods: {
handleClose(done) {
this.$confirm('确认关闭?')
.then(_ => {
done();
})
.catch(_ => {
});
},
paymany() {
getpay(this.pay).then(
res => {
console.log(res)
this.htmlstr = res.data
this.dialogVisible = true
}
)
},
pay() {
let _this = this;
_this.paySucc = false;
_this.dialogVisible = true;
console.log(this.payform)
getpay(this.payform).then(
response=>{
console.log(response)
_this.text = response.data;
_this.dialogVisible = true;
//使用webSocket发送请求,下面会简单介绍websocket使用
if ("WebSocket" in window) {
// 打开一个 web socket
var ws = new WebSocket("ws://服务器的ip:10001/bindingRecord");
ws.onopen = function() {
// Web Socket 已连接上,使用 send() 方法发送数据
// ws.send("data");
// alert("数据发送中...");
};
ws.onmessage = function(evt) {
var received_msg = evt.data;
// alert("数据已接收..." + evt.data);
if (Boolean(evt.data)) {
_this.paySucc = true;
setTimeout(() => {
_this.dialogVisible = false;
}, 3 * 1000);
}
ws.close();
};
ws.onclose = function() {
// // 关闭 websocket
console.log("连接已关闭...");
};
} else {
// 浏览器不支持 WebSocket
alert("您的浏览器不支持 WebSocket!");
}
}).catch((err) => {
console.log(err)
})
},
back(dataUrl, id) {
console.log(dataUrl, id)
}
},
//生命周期 - 创建完成(可以访问当前this实例)",
created() {
alert("预支付效果演示!请注意本页面所有支付均为支付宝开发沙盒,如果支付了,钱可没到阿丹这里!!!")
this.axios = axios; // 初始化 axios
},
//生命周期 - 挂载完成(可以访问DOM元素)",
mounted() {
},
beforeCreate() {
}, //生命周期 - 创建之前",
beforeMount() {
}, //生命周期 - 挂载之前",
beforeUpdate() {
}, //生命周期 - 更新之前",
updated() {
}, //生命周期 - 更新之后",
beforeDestroy() {
}, //生命周期 - 销毁之前",
destroyed() {
}, //生命周期 - 销毁完成",
activated() {
} //如果页面有keep-alive缓存功能,这个函数会触发",
};
</script>
<style scoped>
</style>
注意:
别忘记配置路由!!!并且我使用的是npm来管理依赖的,一定要注意!!
然后就完成了快自己动手尝试一下吧!!!!!
没看错!return_url就是空着了,大家可以写一个空“”来代替,好了大家快自己尝试一下吧!!!!
今天的文章支付宝api支付接口怎么申请_二维码支付API免费调用分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/83576.html