UniApp?+?SpringBoot?實現(xiàn)支付寶支付和退款功能
上篇介紹了UniApp + SpringBoot 實現(xiàn)微信支付和退款功能,喜歡的朋友可以點擊查看。
開發(fā)準(zhǔn)備
- 一臺用于支付的測試機(jī)
- 用于編寫的后端框架接口的 IDE (IDEA 或者 Eclipse 都可以)
- HBuilder X 用來編輯 UniApp 項目的編輯器和編譯器
- 基本的 SpringBoot 的腳手架,可以去 https://start.spring.io/ 或者 IDEA 自帶的快速生成腳手架插件。
- Jdk 11
支付寶支付開發(fā)
后端部分
在 SpringBoot 中添加以下坐標(biāo)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 支付寶官方 SDK-->
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>4.22.32.ALL</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>在 resources 目錄下添加 application.yml 我們不去用默認(rèn)的 application.properties 文件,畢竟 yml 更好看點。并在 yml 中添加以下內(nèi)容
# 服務(wù)啟動端口 server: port: 8080 # 支付寶支付 alipay: server_url: https://openapi.alipay.com/gateway.do app_id: 企業(yè)支付的 APPID private_key: 申請的私鑰 format: json charset: utf-8 alipay_public_key: 申請的公鑰 sign_type: RSA2 notifyUrl: 回調(diào)地址
創(chuàng)建一個 AlipayConfig.java 繼承 com.alipay.api.AlipayConfig
@Getter
@Setter
@ToString
@Component
@ConfigurationProperties(prefix = "alipay")
public class AlipayConfig extends com.alipay.api.AlipayConfig {
private String serverUrl;
private String appId;
private String privateKey;
private String format;
private String charset;
private String alipayPublicKey;
private String signType;
private String notifyUrl;
}創(chuàng)建一個 BizAlipayService.java
import com.alipay.api.AlipayApiException;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* 阿里云支付類
*/
@Service
public class BizAlipayService {
private static Logger logger = LoggerFactory.getLogger(BizAlipayService.class);
@Autowired
AlipayConfig alipayConfig;
private DefaultAlipayClient client() throws AlipayApiException {
return new DefaultAlipayClient(alipayConfig);
}
/**
* 預(yù)下單
*
* @param subject 訂單標(biāo)題
* @param outTradeNo 商家生成的訂單號
* @param totalAmount 訂單總價值
* @return
*/
public String appPay(String subject, String outTradeNo, String totalAmount) {
String source = "";
try {
DefaultAlipayClient client = client();
AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
model.setSubject(subject);
model.setOutTradeNo(outTradeNo);
model.setTotalAmount(totalAmount);
// alipay 封裝的接口調(diào)用
AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
request.setBizModel(model);
request.setNotifyUrl(alipayConfig.getNotifyUrl());
AlipayTradeAppPayResponse response = client.sdkExecute(request);
source = response.getBody();
} catch (AlipayApiException e) {
logger.error("支付出現(xiàn)問題,詳情:{}", e.getErrMsg());
e.printStackTrace();
}
return source;
}
}創(chuàng)建一個 AlipayController.java 來實現(xiàn)接口給前端調(diào)用時使用
import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
@RestController
public class AlipayController {
private static Logger logger = LoggerFactory.getLogger(AlipayController.class);
@Autowired
AlipayConfig alipayConfig;
@Autowired
BizAlipayService alipayService;
/**
* 支付接口
*
* @return
*/
@GetMapping("/pay")
public String orderPay() {
String s = alipayService.appPay("測試支付", String.valueOf(System.currentTimeMillis()), new BigDecimal("0.01").toString());
logger.info("支付生成信息:{}", s);
return s;
}
/**
* 訂單回調(diào)
*
* @return
*/
@RequestMapping(method = RequestMethod.POST, value = "/notify")
public String orderNotify(HttpServletRequest request) {
Map<String, String> params = new HashMap<>();
Map<String, String[]> requestParams = request.getParameterMap();
for (String name : requestParams.keySet()) {
String[] values = 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.getAlipayPublicKey(), alipayConfig.getCharset(), alipayConfig.getSignType());
if (flag) {
logger.info("支付回調(diào)信息:{}", params);
return "success";
} else {
return "error";
}
} catch (AlipayApiException e) {
logger.error("支付寶錯誤回調(diào):{}", e.getErrMsg());
e.printStackTrace();
return "error";
}
}
}上面的 controller 寫了兩個接口一個用來 app端的調(diào)用,一個給支付用來回調(diào)。回調(diào)接口的地址要放到剛才配置中的 notifyUrl 屬性里。
- 由于支付寶回調(diào)要使用線上的地址作為回調(diào)地址,這里我推薦兩個解決辦法
- 使用一臺服務(wù)器+備案的域名搭建上面的后臺地址
- 使用 花生殼 來實現(xiàn)本地內(nèi)網(wǎng)穿透
我使用的是 花生殼 作為本次的開發(fā)環(huán)境,啟動 springboot 的服務(wù),配置好花生殼。后臺部分到目前為止已經(jīng)結(jié)束了。
前端部分
UniApp 是一個使用Vue.js 開發(fā)所有前端應(yīng)用的框架,開發(fā)者編寫一套代碼,可發(fā)布到iOS、Android、Web(響應(yīng)式)、以及各種小程序(微信/支付寶/百度/頭條/飛書/QQ/快手/釘釘/淘寶)、快應(yīng)用等多個平臺。
牛啊,UniApp 能打這么多的端呢,不過這次我只使用 APP 端的功能。
在 HBuilder X 中新建一個項目,我目前使用的版本 3.3.10.20220124

創(chuàng)建好項目之后,在 manifest.json 中勾選以下內(nèi)容

在 index.vue 添加支付相關(guān)功能
<template>
<view class="content">
<image class="logo" src="/static/logo.png"></image>
<view class="text-area">
<text class="title">{{title}}</text>
</view>
<button type="default" @click="goPay()">點我前去支付</button>
</view>
</template>
<script>
export default {
data() {
return {
title: 'Hello'
}
},
onLoad() {
},
methods: {
goPay() {
uni.request({
url: "https://4789j06630.wocp.fun/pay",
success(res) {
uni.requestPayment({
provider: 'alipay',
orderInfo: res.data.data,
success(r) {
uni.showModal({
content: "支付成功",
showCancel: false
})
},
fail(e) {
uni.showModal({
content: "支付失敗,原因為: " + e.errMsg,
showCancel: false
})
},
complete: () => {
console.log("payment結(jié)束")
}
})
}
})
}
}
}
</script>
<style>
page{
background-color: #ff5500;
}
.content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.logo {
height: 200rpx;
width: 200rpx;
margin-top: 200rpx;
margin-left: auto;
margin-right: auto;
margin-bottom: 50rpx;
}
.text-area {
display: flex;
justify-content: center;
}
.title {
font-size: 36rpx;
color: #8f8f94;
}
</style>
點擊 點我前去支付 按鈕就可以打開支付寶進(jìn)行支付了。查看接口返回的 log 信息
支付成功圖展示

生成預(yù)支付信息

支付成功回調(diào)

要記住里面的 trade_no 一會退款還需要這個。
以上就是支付寶支付的內(nèi)容了。下面開始實現(xiàn)退款功能。
支付寶退款開發(fā)
后端部分
在剛才的 BizAlipayService.java 添加以下代碼
/**
* 退款
*
* @param tradeNo
* @param totalAmount
* @return
*/
public AlipayTradeRefundResponse refund(String tradeNo, String totalAmount) {
try {
DefaultAlipayClient client = client();
AlipayTradeRefundModel alipayTradeRefundModel = new AlipayTradeRefundModel();
alipayTradeRefundModel.setTradeNo(tradeNo);
alipayTradeRefundModel.setRefundAmount(totalAmount);
AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
request.setBizModel(alipayTradeRefundModel);
AlipayTradeRefundResponse response = client.execute(request);
return response;
} catch (AlipayApiException e) {
logger.error("退款出現(xiàn)問題,詳情:{}", e.getErrMsg());
e.printStackTrace();
}
return null;
}
在 AlipayController.java 中添加一個接口用于退款操作
/**
* 訂單退款
*
* @return
* @TODO 僅實現(xiàn)了全部退款
*/
@RequestMapping(value = "/order_refund", method = RequestMethod.GET)
public AlipayTradeRefundResponse orderRefund() {
AlipayTradeRefundResponse refund = alipayService.refund("2022020922001434041429269213", "0.01");
return refund;
}
用的是剛才支付寶回調(diào)返回的 trade_no 和 total_amount 。
重啟服務(wù)調(diào)用接口測試是否可以退款,這里我為了省事使用了 Postman 。

手機(jī)此時已經(jīng)收到退款已到賬的消息通知,退款還是很簡單的。后臺也返回了響應(yīng)的支付寶回調(diào)

整套支付流程都上傳到 github 了可以查看 github的源碼 https://github.com/runbrick/pay_spring
到此這篇關(guān)于UniApp+SpringBoot實現(xiàn)支付寶支付和退款的文章就介紹到這了,更多相關(guān)UniApp SpringBoot 支付寶支付和退款內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring之底層架構(gòu)核心概念Environment及用法詳解
這篇文章主要介紹了Spring之底層架構(gòu)核心概念-Environment,本文結(jié)合示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-12-12
Spring配置文件解析之BeanDefinitionReader詳解
這篇文章主要介紹了Spring配置文件解析之BeanDefinitionReader詳解,ApplicationContext.xml配置文件解析成Document對象,真正對xml中元素解析的類是在BeanDefinitionDocumentReader的實現(xiàn)類中來完成的,需要的朋友可以參考下2024-02-02
Mybatis?Interceptor線程安全引發(fā)的bug問題
這篇文章主要介紹了Mybatis?Interceptor線程安全引發(fā)的bug問題及解決,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-02-02
Java日常練習(xí)題,每天進(jìn)步一點點(38)
下面小編就為大家?guī)硪黄狫ava基礎(chǔ)的幾道練習(xí)題(分享)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧,希望可以幫到你2021-07-07

