Java利用沙箱支付實(shí)現(xiàn)電腦掃碼支付教程
一、準(zhǔn)備工作
1、注冊(cè)支付寶開(kāi)放平臺(tái)賬號(hào),成為開(kāi)發(fā)者。
地址:https://open.alipay.com/platform/home.htm

2、進(jìn)入沙箱,進(jìn)行配置。

3.我們可以看到這個(gè)界面

4.后面需要使用的參數(shù)
- APPID
- 商戶(hù)私鑰(使用系統(tǒng)默認(rèn)密鑰的公鑰模式,點(diǎn)擊查看獲?。?/li>
- 支付寶公鑰
- 支付寶網(wǎng)關(guān)
5、手機(jī)上下載沙箱支付寶 (到時(shí)候支付用這個(gè)支付寶支付)

6、下載好支付寶沙箱版后,登錄支付寶提供的賬號(hào)

二、效果展示
1、隨手寫(xiě)的一個(gè)前臺(tái)vue界面

2、進(jìn)入確定訂單界面,可以添加商品描述

3、跳轉(zhuǎn)支付界面,利用沙箱支付寶完成支付

4、完成支付

5、跳回自己設(shè)置的界面

三、實(shí)現(xiàn)代碼
3.1 后臺(tái)代碼
(我這里利用的是SpringBoot集成的SSM,當(dāng)然不使用SpringBoot也可以)
3.1.1 pom.xml文件
不用全部的,重點(diǎn)是 :支付寶sdk包、fastjson
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.zking</groupId>
<artifactId>springboot02</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot02</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.1.18.RELEASE</spring-boot.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.44</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.4.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<version>2.6.2</version>
</dependency>
<!-- 支付寶sdk包 -->
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>3.1.0</version>
</dependency>
<!-- fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.48</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<!-- mvn mybatis-generator:generate -->
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.2</version>
<configuration>
<verbose>true</verbose>
<overwrite>true</overwrite>
<!--配置文件的位置-->
<configurationFile>src/main/resources/generatorConfig.xml</configurationFile>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.1.18.RELEASE</version>
<configuration>
<mainClass>com.zking.springboot02.Springboot02Application</mainClass>
</configuration>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
3.1.2 model包
package com.zking.springboot02.model;
import lombok.Data;
/**
* 支付實(shí)體對(duì)象
* 根據(jù)支付寶接口協(xié)議,其中的屬性名,必須使用下劃線,不能修改
*
* @author 借我丹青妙筆
*/
@Data
public class AlipayBean {
private static final long serialVersionUID = 1L;
/**
* 商戶(hù)訂單號(hào),必填
*
*/
private String out_trade_no;
/**
* 訂單名稱(chēng),必填
*/
private String subject;
/**
* 付款金額,必填
* 根據(jù)支付寶接口協(xié)議,必須使用下劃線
*/
private String total_amount;
/**
* 商品描述,可空
*/
private String body;
/**
* 超時(shí)時(shí)間參數(shù)
*/
private String timeout_express= "10m";
/**
* 產(chǎn)品編號(hào)
*/
private String product_code= "FAST_INSTANT_TRADE_PAY";
public String getOut_trade_no() {
return out_trade_no;
}
public void setOut_trade_no(String out_trade_no) {
this.out_trade_no = out_trade_no;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public String getTotal_amount() {
return total_amount;
}
public void setTotal_amount(String total_amount) {
this.total_amount = total_amount;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
}
3.1.3 utils包AlipayConfig類(lèi)
(請(qǐng)配置好該類(lèi),防止報(bào)錯(cuò))
- appId:APPID,沙箱應(yīng)用提供的
- privateKey: 商戶(hù)私鑰,點(diǎn)擊公鑰證書(shū)查看
- returnUrl : 支付完成后跳轉(zhuǎn)的頁(yè)面,例如我填的是:http://localhost:8088/
package com.zking.springboot02.utils;
import lombok.Data;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
/**
* 配置文件讀取
*
*/
@Configuration
@Data
@Component
public class AlipayConfig {
/**
* 應(yīng)用ID,您的APPID,收款賬號(hào)既是您的APPID對(duì)應(yīng)支付寶賬號(hào)
*/
private String appId = "";
/**
* 商戶(hù)私鑰,您的PKCS8格式RSA2私鑰
*/
private String privateKey = "";
/**
* 支付寶公鑰,
*/
private String publicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyqAN9WzWigim0/3fBK97RFZ7Juu31+DfXMVHTHSTP+4WPvr80zTiIQmT9xTFVGBgD8BBX0XELxqLQxsYQm/MgEgccHTnCKPP7Ci979YuwZyjOysdTc6BNO/6RqPZruih6wSYDJNuJUgY/hwuWi+owUDbHL7NvZ8r/TaIJvEzzhJVrTMsIBQBe66LRE7gE2avwEV8Qck9e4yexsDUD7ja1+2T1ltfHAP2u/SBOD+7PkkPgVkINPDHt4bXZ9DIhPhosiw8IidEEniXj/Ku1wtgETll/btJljhhXq98JHBlw94+yx+BQ+9s2S2CjXkxfdZDB9s+jFy80e6UIV76xxfB0QIDAQAB";
/**
* 服務(wù)器異步通知頁(yè)面路徑需http://格式的完整路徑,不能加?id=123這類(lèi)自定義參數(shù)
*/
private String notifyUrl = "https://www.duan33f.top";
/**
* 頁(yè)面跳轉(zhuǎn)同步通知頁(yè)面路徑 需http://格式的完整路徑.
* 支付完成后返回的地址
*/
private String returnUrl = "";
/**
* 簽名方式
*/
private String signType = "RSA2";
/**
* 字符編碼格式
*/
private String charset = "utf-8";
/**
* 支付寶網(wǎng)關(guān)
*/
private String gatewayUrl = "https://openapi.alipaydev.com/gateway.do";
/**
* 支付寶網(wǎng)關(guān)
*/
private String logPath = "C:\\";
}
Alipay類(lèi)
package com.zking.springboot02.utils;
import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.zking.springboot02.model.AlipayBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* 支付寶支付接口
* @author 借我丹青妙筆
*/
@Component
public class Alipay {
@Autowired
private AlipayConfig alipayConfig;
/**
* 支付接口
* @param alipayBean
* @return
* @throws AlipayApiException
*/
public String pay(AlipayBean alipayBean) throws AlipayApiException {
// 1、獲得初始化的AlipayClient
String serverUrl = alipayConfig.getGatewayUrl();
String appId = alipayConfig.getAppId();
String privateKey = alipayConfig.getPrivateKey();
String format = "json";
String charset = alipayConfig.getCharset();
String alipayPublicKey = alipayConfig.getPublicKey();
String signType = alipayConfig.getSignType();
String returnUrl = alipayConfig.getReturnUrl();
String notifyUrl = alipayConfig.getNotifyUrl();
//System.out.println(appId);
AlipayClient alipayClient = new DefaultAlipayClient(serverUrl, appId, privateKey, format, charset, alipayPublicKey, signType);
// 2、設(shè)置請(qǐng)求參數(shù)
AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
// 頁(yè)面跳轉(zhuǎn)同步通知頁(yè)面路徑
alipayRequest.setReturnUrl(returnUrl);
// 服務(wù)器異步通知頁(yè)面路徑
alipayRequest.setNotifyUrl(notifyUrl);
// 封裝參數(shù)
alipayRequest.setBizContent(JSON.toJSONString(alipayBean));
// 3、請(qǐng)求支付寶進(jìn)行付款,并獲取支付結(jié)果
String result = alipayClient.pageExecute(alipayRequest).getBody();
// 返回付款信息
return result;
}
}
3.1.4 Service包
PayService接口
package com.zking.springboot02.service;
import com.alipay.api.AlipayApiException;
import com.zking.springboot02.model.AlipayBean;
/**
* 支付服務(wù)
* @author 借我丹青妙筆
* @date Dec 12, 2018
*/
public interface PayService {
/**
* 支付寶支付接口
* @param alipayBean
* @return
* @throws AlipayApiException
*/
String aliPay(AlipayBean alipayBean) throws AlipayApiException;
}
PayServiceImpl類(lèi)
package com.zking.springboot02.service.impl;
import com.alipay.api.AlipayApiException;
import com.zking.springboot02.model.AlipayBean;
import com.zking.springboot02.service.PayService;
import com.zking.springboot02.utils.Alipay;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service
public class PayServiceImpl implements PayService {
@Resource
private Alipay alipay;
@Override
public String aliPay(AlipayBean alipayBean) throws AlipayApiException {
return alipay.pay(alipayBean);
}
}
3.1.5 contorller包
payController類(lèi)
package com.zking.springboot02.contorller;
import com.alipay.api.AlipayApiException;
import com.zking.springboot02.model.AlipayBean;
import com.zking.springboot02.service.PayService;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/pay")
@CrossOrigin
public class PayController {
@Resource
private PayService payService;
/**
* 阿里支付
* @param alipayBean
* @return
* @throws AlipayApiException
*/
@PostMapping("/alipay")
public Map alipay(AlipayBean alipayBean) throws AlipayApiException {
System.out.println(alipayBean);
Map<String,Object> map = new HashMap<String,Object>();
String str = payService.aliPay(alipayBean);
System.out.println(str);
map.put("msg",str);
map.put("code",0);
//
return map;
}
}
3.1.6 application.yml文件
server:
port: 8080 #端口號(hào)
servlet:
context-path: /s02 #項(xiàng)目名
3.2 前臺(tái)代碼
(前臺(tái)是利用腳手架搭建的Vue項(xiàng)目)
3.2.1 src下api包下action.js文件
/**
* 對(duì)后臺(tái)請(qǐng)求的地址的封裝,URL格式如下:
* 模塊名_實(shí)體名_操作
*/
export default {
//服務(wù)器
'SERVER': 'http://localhost:8080/s02',
'alipay' : 'http://localhost:8080/s02/pay/alipay',
//獲得請(qǐng)求的完整地址,用于mockjs測(cè)試時(shí)使用
'getFullPath': k => {
return this.SERVER + this[k];
}
}
3.2.2 src下api包下http.js文件
/**
* vue項(xiàng)目對(duì)axios的全局配置
*/
import axios from 'axios'
import qs from 'qs'
//引入action模塊,并添加至axios的類(lèi)屬性u(píng)rls上
import action from '@/api/action'
axios.urls = action
// axios默認(rèn)配置
axios.defaults.timeout = 10000; // 超時(shí)時(shí)間
// axios.defaults.baseURL = 'http://localhost:8080/crm'; // 默認(rèn)地址
axios.defaults.baseURL = action.SERVER;
//整理數(shù)據(jù)
// 只適用于 POST,PUT,PATCH,transformRequest` 允許在向服務(wù)器發(fā)送前,修改請(qǐng)求數(shù)據(jù)
axios.defaults.transformRequest = function(data) {
data = qs.stringify(data);
return data;
};
// 請(qǐng)求攔截器
axios.interceptors.request.use(function(config) {
// let jwt = sessionStorage.getItem('jwt');
// if (jwt) {
// config.headers['jwt'] = jwt;
// }
return config;
}, function(error) {
return Promise.reject(error);
});
// 響應(yīng)攔截器
axios.interceptors.response.use(function(response) {
return response;
}, function(error) {
return Promise.reject(error);
});
export default axios;
3.2.3 src下router下index.js文件
import Vue from 'vue'
import Router from 'vue-router'
import Shop from '@/views/Shop'
import buy from '@/views/buy'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'Shop',
component: Shop
},
{
path: '/buy',
name: 'buy',
component: buy
}
]
})
3.2.4 src下views下Shop.vue文件
<template>
<el-table :data="tableData" style="width: 100%">
<el-table-column prop="out_trade_no" label="編號(hào)">
</el-table-column>
<el-table-column prop="subject" label="訂單名稱(chēng)" >
</el-table-column>
<el-table-column prop="total_amount" label="付款金額">
</el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-button @click="toBuy(scope.row)" type="text" size="small">去支付</el-button>
</template>
</el-table-column>
</el-table>
</template>
<script>
export default {
name: "Shop",
data: function() {
return {
tableData: [{
out_trade_no: '101',
subject: 'Java從入門(mén)到入土',
total_amount: 33
}, {
out_trade_no: '202',
subject: 'Mysql刪庫(kù)跑路指南',
total_amount: 44
}, {
out_trade_no: '303',
subject: 'Java編程思想',
total_amount: 89
}, {
out_trade_no: '404',
subject: 'Java設(shè)計(jì)模式',
total_amount: 56
}]
};
},
methods: {
toBuy(row){
console.log(row);
//利用$router.push進(jìn)行跳轉(zhuǎn)
this.$router.push({
//path后面跟跳轉(zhuǎn)的路由地址
path: '/buy',
//name后面跟跳轉(zhuǎn)的路由名字(必須有親測(cè),不使用命名路由會(huì)傳參失?。?
name: 'buy',
params: {
//imgsListsUrl2是自己定義的名字,this.imgsListsUrl是要被傳遞的值
payInfo: row
}
})
}
},
created: function() {
}
}
</script>
<style>
</style>
3.2.5 src下views下buy.vue文件
<template>
<div class="main">
<center>
<div class="box">
<h2>確定訂單</h2>
<el-form :model="payInfo" :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
<el-form-item label="訂單號(hào)" prop="out_trade_no">
<el-input v-model="payInfo.out_trade_no" readonly="true"></el-input>
</el-form-item>
<el-form-item label="商品名稱(chēng)" prop="subject">
<el-input v-model="payInfo.subject" readonly="true"></el-input>
</el-form-item>
<el-form-item label="商品價(jià)格" prop="total_amount">
<el-input v-model="payInfo.total_amount" readonly="true"></el-input>
</el-form-item>
<el-form-item label="商品描述" prop="body">
<el-input v-model="payInfo.body"></el-input>
</el-form-item>
<el-button type="primary" plain @click="submit" style="width: 100%;" round>付款</el-button>
</el-form>
</div>
</center>
</div>
</template>
<script>
//import axios from 'axios'
export default {
name: "buy",
data() {
return {
payInfo: {
out_trade_no: '',
subject: '',
total_amount: null,
body: ''
}
}
},
mounted() {
//this.$route.params.imgsListsUrl2是傳過(guò)來(lái)的參數(shù)
var time = new Date();
this.payInfo = this.$route.params.payInfo
this.payInfo.out_trade_no = time.getTime();
},
methods: {
submit() {
var url = this.axios.urls.alipay;//得到api下action.js中的alipay
this.axios.post(url, this.payInfo).then(resp => {//調(diào)用后臺(tái)方法
console.log(resp);
const divForm = document.getElementsByTagName('div')
if (divForm.length) {
document.body.removeChild(divForm[0])
}
const div = document.createElement('div')
div.innerHTML = resp.data.msg // data就是接口返回的form 表單字符串
document.body.appendChild(div)
document.forms[0].setAttribute('target', '_blank') // 新開(kāi)窗口跳轉(zhuǎn)
document.forms[0].submit()
}).catch(resp => {
console.log(resp);
});
}
}
}
</script>
<style scoped>
.box {
width: 800px;
}
.left {
width: 85px;
padding-top: 5px;
font-size: 15px;
}
.right {
width: 400px;
}
</style>
3.2.6 src下main.js文件
import Vue from 'vue'
import ElementUI from 'element-ui' //新添加1
import 'element-ui/lib/theme-chalk/index.css' //新添加2,避免后期打包樣式不同,要放在import App from './App';之前
import axios from '@/api/http' //vue項(xiàng)目對(duì)axios的全局配置
import App from './App'
import router from './router'
import VueAxios from 'vue-axios'
Vue.use(VueAxios,axios)
Vue.use(ElementUI) //新添加3
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>'
})
OK,重要的代碼已經(jīng)完全提供了。
聲明:實(shí)現(xiàn)沙箱支付可以讓我們了解如何調(diào)用如支付寶的接口,讓我們理解接口的調(diào)用。
以上就是Java利用沙箱支付實(shí)現(xiàn)電腦掃碼支付教程的詳細(xì)內(nèi)容,更多關(guān)于Java電腦掃碼支付的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
詳解快速排序算法中的區(qū)間劃分法及Java實(shí)現(xiàn)示例
這篇文章主要介紹了詳解快速排序算法中的區(qū)間劃分法及Java實(shí)現(xiàn)示例,文中分別介紹了快排時(shí)兩種區(qū)間劃分的思路,需要的朋友可以參考下2016-04-04
SpringBoot?整合Security權(quán)限控制的初步配置
這篇文章主要為大家介紹了SpringBoot?整合Security權(quán)限控制的初步配置實(shí)例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11
springboot如何接收get和post請(qǐng)求參數(shù)
這篇文章主要介紹了springboot如何接收get和post請(qǐng)求參數(shù),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-06-06
如何使用IntelliJ IDEA的HTTP Client進(jìn)行接口驗(yàn)證
這篇文章主要介紹了如何使用IntelliJ IDEA的HTTP Client進(jìn)行接口驗(yàn)證,本文給大家分享最新完美解決方案,感興趣的朋友跟隨小編一起看看吧2024-06-06
SpringSecurity進(jìn)行認(rèn)證與授權(quán)的示例代碼
SpringSecurity是Spring家族中的一個(gè)安全管理框架,而認(rèn)證和授權(quán)也是SpringSecurity作為安全框架的核心功能,本文主要介紹了SpringSecurity進(jìn)行認(rèn)證與授權(quán)的示例代碼,感興趣的可以了解一下2024-06-06
在Spring框架下配置Quartz集群的詳細(xì)步驟(MySQL數(shù)據(jù)源)
Quartz 是一個(gè)功能強(qiáng)大的調(diào)度庫(kù),可以在 Java 應(yīng)用中用于執(zhí)行定時(shí)任務(wù),本文將介紹如何在 Spring 框架下配置 Quartz 集群,并使用 MySQL 作為數(shù)據(jù)源來(lái)存儲(chǔ)調(diào)度信息,文中有詳細(xì)的代碼供大家參考,需要的朋友可以參考下2025-01-01
Java 使用反射調(diào)用jar包中的類(lèi)方式
這篇文章主要介紹了Java 使用反射調(diào)用jar包中的類(lèi)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-04-04
使用mybatis的interceptor修改執(zhí)行sql以及傳入?yún)?shù)方式
這篇文章主要介紹了使用mybatis的interceptor修改執(zhí)行sql以及傳入?yún)?shù)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12

