欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

springboot+vue+對(duì)接支付寶接口+二維碼掃描支付功能(沙箱環(huán)境)

 更新時(shí)間:2020年10月15日 09:21:52   作者:£漫步 云端彡  
這篇文章主要介紹了springboot+vue+對(duì)接支付寶接口+二維碼掃描支付(沙箱環(huán)境),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

1. 什么是支付寶接口(沙箱環(huán)境)?

記錄時(shí)間:2020年10月15日3:55

現(xiàn)如今,手機(jī)支付已相當(dāng)普遍,而作為開發(fā)人員應(yīng)該對(duì)手機(jī)支付操作有所了解。而支付寶接口是支付寶提供的一個(gè)接口,用來對(duì)接軟件應(yīng)用程序在進(jìn)行金錢交易使用。然后對(duì)于編程愛好者而言,想學(xué)習(xí)這一點(diǎn)就有點(diǎn)難,因?yàn)橐胧褂弥Ц秾毥涌冢仨毲疤崾鞘褂密浖?yīng)用程序,軟件應(yīng)用程序需要向支付寶申請(qǐng),提交一系列資料,這一點(diǎn)是實(shí)現(xiàn)不了的。這就對(duì)開發(fā)者增加了一定的難度,因?yàn)楫a(chǎn)品沒有上線,然后需要對(duì)接支付寶接口就是很大的問題,所以出現(xiàn)了沙箱環(huán)境,具有虛擬的用戶和管理員賬戶,進(jìn)行實(shí)驗(yàn)測試是否對(duì)接成功。接下來就根據(jù)我的經(jīng)驗(yàn),簡單的介紹一下我的使用和學(xué)習(xí)過程。

使用技術(shù)+編程軟件:

springboot(idea)vue + elementui(HBuilderX)+ vue-qr(vue生成二維碼框架)NATAPP(連接外網(wǎng),實(shí)現(xiàn)支付寶回調(diào))websocket(實(shí)現(xiàn)前端響應(yīng))

步驟:

準(zhǔn)備沙箱環(huán)境JAVA + springboot 中使用 SDK 連接支付寶接口配置前端使用vue+elementui頁面設(shè)計(jì)需要注意點(diǎn)結(jié)果測試

首先創(chuàng)建應(yīng)用,這里是沙箱環(huán)境,先準(zhǔn)備沙箱環(huán)境:

百度搜索**支付寶螞蟻金服**,登錄支付包賬號(hào),出現(xiàn)如下顯示:

在這里插入圖片描述

這里是創(chuàng)建應(yīng)用的地方,也就是說有項(xiàng)目要上線時(shí),在這里申請(qǐng)。使用沙箱環(huán)境的話,點(diǎn)擊左上角開放平臺(tái),然后往下拉,會(huì)出現(xiàn)沙箱二字,點(diǎn)擊進(jìn)入即可:

在這里插入圖片描述

然后就可以看到支付寶官網(wǎng)介紹的沙箱環(huán)境的使用,其實(shí)官網(wǎng)已經(jīng)介紹的非常詳細(xì)了,如有小伙伴們看著嫌麻煩,可以根據(jù)我學(xué)習(xí)的步驟作為參考。在如何使用沙箱環(huán)境下點(diǎn)擊沙箱應(yīng)用鏈接,去配置自己的沙箱環(huán)境。

在這里插入圖片描述

點(diǎn)擊 i 符號(hào),上面有提示鏈接,如何生成RSA2密鑰,這里就不詳細(xì)介紹了,官網(wǎng)寫的非常明白,我這么笨的人也可以學(xué)會(huì),相信小伙伴們也可以學(xué)會(huì)的。按照步驟會(huì)生成兩個(gè)文件:應(yīng)用公鑰和應(yīng)用私鑰。記住,是應(yīng)用公鑰,而不是支付寶公鑰。這里學(xué)習(xí)過程中沒有使用證書模式。

在這里插入圖片描述

然后點(diǎn)擊RSA2的設(shè)置/查看。將產(chǎn)生的應(yīng)用公鑰復(fù)制進(jìn)去就可以了,而下面會(huì)生成支付寶公鑰,在后續(xù)連接過程中非常重要,需要區(qū)分使用的是支付寶公鑰還是應(yīng)用公鑰。

在這里插入圖片描述

JAVA + springboot 中使用 SDK 連接支付寶接口配置

在這里插入圖片描述 

這里是官網(wǎng)使用SDK的方法,這里使用舊版的方式,新版的方式我使用過程中出現(xiàn)某些問題不會(huì)解決。
使用之前,先封裝幾個(gè)配置,第一個(gè)是連接支付寶的配置:

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

/**
 * 支付寶接口配置類
 */
@Configuration
public class PayConfig {
 // 請(qǐng)?zhí)顚懩腁ppId,例如:2019091767145019(必填)
 private static final String appID = "2016102500758313";
 //應(yīng)用私鑰,這里修改生成的私鑰即可(必填)
 private static final String privateKey = "";
 //支付寶公鑰,而非應(yīng)用公鑰(必填)
 public static final String publicKey = "";
	//默認(rèn)即可(必填)
 public static final String charset = "utf-8";
	//默認(rèn)即可(必填)
 public static final String signType = "RSA2";
 @Bean
 public AlipayClient alipayClient(){
 	//沙箱環(huán)境使用https://openapi.alipaydev.com/gateway.do,線上環(huán)境使用https://openapi.alipay.com/gateway.do
  return new DefaultAlipayClient("https://openapi.alipaydev.com/gateway.do", appID, privateKey, "json", charset, publicKey, signType);
 }
	/**
	 * 驗(yàn)簽,是否正確
	 */
 public static boolean checkSign(HttpServletRequest request){
  Map<String, String[]> requestMap = request.getParameterMap();
  Map<String, String> paramsMap = new HashMap<>();
  requestMap.forEach((key, values) -> {
   String strs = "";
   for(String value : values) {
    strs = strs + value;
   }
   System.out.println(key +"===>"+strs);
   paramsMap.put(key, strs);
  });
  System.out.println();
  //調(diào)用SDK驗(yàn)證簽名
  try {
   return AlipaySignature.rsaCheckV1(paramsMap, PayConfig.publicKey, PayConfig.charset, PayConfig.signType);
  } catch (AlipayApiException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
   System.out.println("*********************驗(yàn)簽失敗********************");
   return false;
  }

 }
}

然后封裝一個(gè)支付寶回調(diào)的參數(shù)對(duì)象,這里就不需要自己手動(dòng)去獲取參數(shù)了

import java.io.Serializable;

/**
 * 支付寶回調(diào)參數(shù)
 */
public class AliReturnPayBean implements Serializable {
 /**
  *
  */
 private static final long serialVersionUID = 1L;

 /**
  * 開發(fā)者的app_id
  */
 private String app_id;

 /**
  * 商戶訂單號(hào)
  */
 private String out_trade_no;

 /**
  * 簽名
  */
 private String sign;

 /**
  * 交易狀態(tài)
  */
 private String trade_status;

 /**
  * 支付寶交易號(hào)
  */
 private String trade_no;

 /**
  * 交易的金額
  */
 private String total_amount;

 public String getTotal_amount() {
  return total_amount;
 }

 public void setTotal_amount(String total_amount) {
  this.total_amount = total_amount;
 }

 public String getApp_id() {
  return app_id;
 }

 public void setApp_id(String app_id) {
  this.app_id = app_id;
 }

 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 getSign() {
  return sign;
 }

 public void setSign(String sign) {
  this.sign = sign;
 }

 public String getTrade_status() {
  return trade_status;
 }

 public void setTrade_status(String trade_status) {
  this.trade_status = trade_status;
 }

 public String getTrade_no() {
  return trade_no;
 }

 public void setTrade_no(String trade_no) {
  this.trade_no = trade_no;
 }

 @Override
 public String toString() {
  return "AliReturnPayBean [app_id=" + app_id + ", out_trade_no=" + out_trade_no + ", sign=" + sign
    + ", trade_status=" + trade_status + ", trade_no=" + trade_no + "]";
 }
}

然后寫一個(gè)控制層去連接支付寶,控制層必須是@Controller修飾,而不是@RestController修飾,因?yàn)橹Ц秾毜幕卣{(diào)函數(shù)里面返回的是請(qǐng)求。具體事例如下:
前提:在pom.xml 中導(dǎo)入SDK依賴:

<dependency>
 <groupId>com.alipay.sdk</groupId>
 <artifactId>alipay-sdk-java</artifactId>
 <version>4.10.145.ALL</version>
</dependency>
package com.example.zhifubaozhifu.controller;


import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.request.AlipayTradePrecreateRequest;
import com.alipay.api.response.AlipayTradePrecreateResponse;
import com.example.zhifubaozhifu.config.PayConfig;
import com.example.zhifubaozhifu.util.AliReturnPayBean;
import com.example.zhifubaozhifu.util.Shop;
import com.example.zhifubaozhifu.util.WebSocket;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;

@Controller
@Slf4j
public class Test {
 @Autowired
 private AlipayClient alipayClient;
 @Autowired
 private WebSocket webSocket;


 @RequestMapping("/createQR")
 @ResponseBody
 public String send() throws AlipayApiException {
  AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest(); //創(chuàng)建API對(duì)應(yīng)的request類
  // 在下面會(huì)介紹notifyUrl怎么來的
  request.setNotifyUrl("http://cv95x3.natappfree.cc/call");
  //同步回調(diào)地址
//  request.setReturnUrl("");
  request.setBizContent(" {" +
				" \"primary_industry_name\":\"IT科技/IT軟件與服務(wù)\"," +
				" \"primary_industry_code\":\"10001/20102\"," +
				" \"secondary_industry_code\":\"10001/20102\"," +
				" \"secondary_industry_name\":\"IT科技/IT軟件與服務(wù)\"" +
				" }");;
  AlipayTradePrecreateResponse response = alipayClient.execute(request);
  String path = "zhifu.jpg";
  if (response.isSuccess()) {
   System.out.println("調(diào)用成功");
   return response.getQrCode();
  } else {
   System.out.println("調(diào)用失敗");
  }
  return "";
 }


 /**
  * 支付寶回調(diào)函數(shù)
  * @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("支付寶的的回調(diào)函數(shù)被調(diào)用");
  if (!PayConfig.checkSign(request)) {
   log.info("驗(yàn)簽失敗");
   response.getWriter().write("failture");
   return;
  }
  if (returnPay == null) {
   log.info("支付寶的returnPay返回為空");
   response.getWriter().write("success");
   return;
  }
  log.info("支付寶的returnPay" + returnPay.toString());
  //表示支付成功狀態(tài)下的操作
  if (returnPay.getTrade_status().equals("TRADE_SUCCESS")) {
   log.info("支付寶的支付狀態(tài)為TRADE_SUCCESS");
   //業(yè)務(wù)邏輯處理 ,webSocket在下面會(huì)有介紹配置
   webSocket.sendMessage("true");
  }
  response.getWriter().write("success");
 }
}

前端使用vue+elementui頁面設(shè)計(jì):
vue項(xiàng)目的搭建這里就不介紹,首先準(zhǔn)備環(huán)境,添加 vue-qr 插件:

npm install vue-qr --save

前端代碼:

<template>
	<div>
		<!-- 支付按鈕,模擬支付操作 -->
		<van-button type="primary" @click="pay">支付</van-button>

		<el-dialog :title="paySucc?'支付成功':'掃碼支付'" :visible.sync="dialogVisible" width="16%" center>
			<!-- 生成二維碼圖片 -->
			<vueQr :text="text" :size="200" v-if="!paySucc"></vueQr>
			<!-- 使用websocket監(jiān)控是否掃描,掃描成功顯示成功并退出界面 -->
			<span class="iconfont icon-success" style="position: relative;font-size: 100px;color:#42B983;margin-left: 50px;top:-10px;" v-else></span>
		</el-dialog>

	</div>
</template>

<script>
	import vueQr from 'vue-qr'
	export default {
		data() {
			return {
				dialogVisible: false,
				text: "",
				paySucc: false
			}
		},
		components: {
			vueQr
		},
		methods: {
			pay() {
				let _this = this;
				_this.paySucc = false;
				_this.dialogVisible = true;
				this.axios.request("http://localhost:8081/createQR")
					.then((response) => {
						_this.text = response.data;
						_this.dialogVisible = true;
						//使用webSocket發(fā)送請(qǐng)求,下面會(huì)簡單介紹websocket使用
						if ("WebSocket" in window) {
							// 打開一個(gè) web socket
							var ws = new WebSocket("ws://localhost:8081/bindingRecord");

							ws.onopen = function() {
								// Web Socket 已連接上,使用 send() 方法發(fā)送數(shù)據(jù)
								// ws.send("data");
								// alert("數(shù)據(jù)發(fā)送中...");
							};

							ws.onmessage = function(evt) {
								var received_msg = evt.data;
								// alert("數(shù)據(jù)已接收..." + evt.data);
								if (Boolean(evt.data)) {
									_this.paySucc = true;
									setTimeout(() => {
										_this.dialogVisible = false;
									}, 3 * 1000);
								}
								ws.close();

							};
							
							ws.onclose = function() {
								// // 關(guān)閉 websocket
								console.log("連接已關(guān)閉...");
							};
						} else {
							// 瀏覽器不支持 WebSocket
							alert("您的瀏覽器不支持 WebSocket!");
						}
					}).catch((err) => {
						console.log(err)
					})
			},
			back(dataUrl, id) {
				console.log(dataUrl, id)
			}
		}
	}
</script>

<style>
	.btn {
		margin-left: 100px;
	}
</style>

這樣前后端代碼就準(zhǔn)備就緒了,再上面的代碼中有兩個(gè)需要注意的: 第一個(gè)問題是:notifyUrl使用的url是外網(wǎng)地址,并不是IP地址,否則會(huì)無法回調(diào)。但是在學(xué)習(xí)環(huán)境下使用不了外網(wǎng)地址。這就需要使用**NATAPP**。百度搜索NATAPp官網(wǎng),點(diǎn)進(jìn)去下載,它是一個(gè)natapp.exe 應(yīng)用,這有這個(gè)。在官網(wǎng)注冊(cè)賬號(hào),點(diǎn)擊購買免費(fèi)隧道(免費(fèi)隧道只能購買兩個(gè),要珍惜哦。隧道協(xié)議寫web,其他的就按要本地環(huán)境配置就可以了)。購買之后就會(huì)有下面一條自己的隧道

在這里插入圖片描述

雙擊natapp.exe ,進(jìn)入控制臺(tái),輸入以下命令,開啟隧道:

# 這里的值是上面的authtoken的值
natapp --authtoken=值

之后如下顯示:

在這里插入圖片描述

這里的外網(wǎng)連接地址,就是notifyUrl的地址,然后再加上方法mapping路徑即可,如我的是:http://cv95x3.natappfree.cc/call

第二個(gè)問題是:支付成功后,回調(diào)函數(shù)執(zhí)行了,如何告訴前端我已經(jīng)支付成功,同時(shí)關(guān)閉掃描二維碼按鈕,這里就用到了websocket,這里不詳細(xì)介紹websocket是什么,只要知道一點(diǎn),它是可以監(jiān)聽到后端是否發(fā)送信息。首先在pom.xml中導(dǎo)入依賴:

<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-websocket</artifactId>
 <version>2.3.4.RELEASE</version>
</dependency>

然后創(chuàng)建一個(gè)webconfig的配置類:

package com.example.zhifubaozhifu.util;

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;

/**
 * @desc: WebSocket服務(wù)
 *
 **/
//連接webSocket服務(wù)的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("【新建連接】,連接總數(shù):{}", webSockets.size());
 }

 /**
  * 斷開連接
  */
 @OnClose
 public void onClose(){
  webSockets.remove(this);
  log.info("【斷開連接】,連接總數(shù):{}", webSockets.size());
 }

 /**
  * 接收到信息
  * @param message
  */
 @OnMessage
 public void onMessage(String message){
  log.info("【收到】,客戶端的信息:{},連接總數(shù):{}", message, webSockets.size());
 }

 /**
  * 發(fā)送消息
  * @param message
  */
 public void sendMessage(String message){
  log.info("【廣播發(fā)送】,信息:{},總連接數(shù):{}", message, webSockets.size());
  for (WebSocket webSocket : webSockets) {
   try {
    webSocket.session.getBasicRemote().sendText(message);
   } catch (IOException e) {
    log.info("【廣播發(fā)送】,信息異常:{}", e.fillInStackTrace());
   }
  }
 }

}

然后使用的時(shí)候調(diào)用方法onMessage即可接收消息,使用onMessage即可廣發(fā)消息。

前端使用步驟:

<script type="text/javascript">
 function WebSocketTest()
 {
  if ("WebSocket" in window)
  {
   alert("您的瀏覽器支持 WebSocket!");
   
   // 打開一個(gè) web socket
   var ws = new WebSocket("ws://localhost:9998/echo");
   
   ws.onopen = function()
   {
   // Web Socket 已連接上,使用 send() 方法發(fā)送數(shù)據(jù)
   ws.send("發(fā)送數(shù)據(jù)");
   alert("數(shù)據(jù)發(fā)送中...");
   };
   
   ws.onmessage = function (evt) 
   { 
   var received_msg = evt.data;
   alert("數(shù)據(jù)已接收...");
   };
   
   ws.onclose = function()
   { 
   // 關(guān)閉 websocket
   alert("連接已關(guān)閉..."); 
   };
  }
  
  else
  {
   // 瀏覽器不支持 WebSocket
   alert("您的瀏覽器不支持 WebSocket!");
  }
 }
</script>

想詳細(xì)了解的話,可以去菜鳥教程學(xué)習(xí)。

使用思路: 前端先創(chuàng)建websocket , 連接到后端websocket ,這樣才能將websocket通道連接。當(dāng)支付成功之后,后端向前端反饋支付成功信息,前端監(jiān)控接收到消息后做處理,即關(guān)閉二維碼對(duì)話框。

測試結(jié)果:

在這里插入圖片描述

然后下載支付寶沙箱版手機(jī)即可掃描模擬支付,在螞蟻金服的沙箱環(huán)境中就有二維碼下載,如下圖:

加粗樣式

這里指記錄了支付到回調(diào)處理的操作,再這之上還可進(jìn)行進(jìn)一步的封裝。

搞定,記錄結(jié)束。

結(jié)束時(shí)間:2020年10月15日6:12

到此這篇關(guān)于springboot+vue+對(duì)接支付寶接口+二維碼掃描支付(沙箱環(huán)境)的文章就介紹到這了,更多相關(guān)springboot對(duì)接支付寶支付接口內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論