一下内容僅為服務端功能,前端業務沒必要
采用證書方式開發
支付寶開發并不難,文檔寫的很清楚,不想隔壁寫的那麼惡心
https://opendocs.alipay.com/open/194/105203
調用流程
首先在項目中引入alipay
<!-- https://mvnrepository.com/artifact/com.alipay.sdk/alipay-sdk-java -->
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>4.10.209.ALL</version>
</dependency>
接入準備可取官方文檔檢視 https://opendocs.alipay.com/open/01csp3
配置支付寶 AliPayConfig
package com.bootdo.payment.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.util.ClassUtils;
import java.io.*;
import java.util.ArrayList;
/**
* 支付寶支付配置檔案
*/
@Component
@ConfigurationProperties(prefix = "pay.alipay")
public class AliPayConfig {
//私有構造方法
private AliPayConfig(){};
//聲明一個對象的引用
private static AliPayConfig aliPayConfig = null;
//判斷一下如果對象為null在建立一個對象
public static AliPayConfig getInstance(){
if(aliPayConfig == null){
aliPayConfig = new AliPayConfig();
}
return aliPayConfig;
}
// 商戶appid
private String appID;
// 支付寶公鑰
private String getAliPayPublicKey;
// 私鑰 pkcs8格式的
private String private_key;
// 伺服器異步通知頁面路徑 需http://或者https://格式的完整路徑,不能加?id=123這類自定義參數,必須外網可以正常通路
private String precreate_notify;
// 請求網關位址
private String alipay_URL;
// 編碼
private String getCharset="UTF-8";
// 傳回格式
private String getFormat="json";
// RSA2
private String getSignType="RSA2";
private String getProductCode="QUICK_WAP_WAY";
// subject
private String getSubject="WASHER";
/**
* 應用公鑰證書路徑
*/
public String app_cert_path = ClassUtils.getDefaultClassLoader().getResource("").getPath()+"/static/cert/alipay/appCertPublicKey_2019112769464240.crt";
/**
* 支付寶公鑰證書檔案路徑
*/
public String alipay_cert_path = ClassUtils.getDefaultClassLoader().getResource("").getPath()+"/static/cert/alipay/alipayCertPublicKey_RSA2.crt";
/**
* 支付寶CA根證書檔案路徑
*/
public String alipay_root_cert_path = ClassUtils.getDefaultClassLoader().getResource("").getPath()+"/static/cert/alipay/alipayRootCert.crt";
public String getApp_cert_path() {
return app_cert_path;
}
public void setApp_cert_path(String app_cert_path) {
this.app_cert_path = app_cert_path;
}
public String getAlipay_cert_path() {
return alipay_cert_path;
}
public void setAlipay_cert_path(String alipay_cert_path) {
this.alipay_cert_path = alipay_cert_path;
}
public String getAlipay_root_cert_path() {
return alipay_root_cert_path;
}
public void setAlipay_root_cert_path(String alipay_root_cert_path) {
this.alipay_root_cert_path = alipay_root_cert_path;
}
public String getAppID() {
return appID;
}
public void setAppID(String appID) {
this.appID = appID;
}
public String getGetAliPayPublicKey() {
return getAliPayPublicKey;
}
public void setGetAliPayPublicKey(String getAliPayPublicKey) {
this.getAliPayPublicKey = getAliPayPublicKey;
}
public String getPrivate_key() {
return private_key;
}
public void setPrivate_key(String private_key) {
this.private_key = private_key;
}
public String getPrecreate_notify() {
return precreate_notify;
}
public void setPrecreate_notify(String precreate_notify) {
this.precreate_notify = precreate_notify;
}
public String getAlipay_URL() {
return alipay_URL;
}
public void setAlipay_URL(String alipay_URL) {
this.alipay_URL = alipay_URL;
}
public String getGetCharset() {
return getCharset;
}
public void setGetCharset(String getCharset) {
this.getCharset = getCharset;
}
public String getGetFormat() {
return getFormat;
}
public void setGetFormat(String getFormat) {
this.getFormat = getFormat;
}
public String getGetSignType() {
return getSignType;
}
public void setGetSignType(String getSignType) {
this.getSignType = getSignType;
}
public String getGetProductCode() {
return getProductCode;
}
public void setGetProductCode(String getProductCode) {
this.getProductCode = getProductCode;
}
public String getGetSubject() {
return getSubject;
}
public void setGetSubject(String getSubject) {
this.getSubject = getSubject;
}
/**
* 取出公匙檔案裡面的公匙
* @return
*/
public String aliPayPublicKey(){
String publicKey="";
ArrayList<String> list = new ArrayList<>();
try {
InputStreamReader inputStreamReader = new InputStreamReader(getClass().getClassLoader().getResourceAsStream(getAliPayPublicKey));
BufferedReader br =new BufferedReader(inputStreamReader);
String str =null;
while ((str = br.readLine())!=null){
list.add(str);
}
//掐頭去尾
for (int i = 0; i < list.size(); i++) {
if(i!=0&&i!=list.size()-1){
publicKey += list.get(i).trim();
}
}
br.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return publicKey;
}
}
接口 AliPayService
package com.bootdo.payment.service;
import com.bootdo.common.utils.R;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
/**
* 支付寶支付接口
*/
public interface AliPayService {
/**
* 支付寶 統一收單線下交易預建立
* 商家可調用 alipay.trade.precreate(統一收單線下交易預建立)接口,傳入訂單商品及金額的資訊建立訂單。支付寶将傳回支付二維碼資訊用于使用者掃碼支付
* @param orderNo: 訂單編号
* @param amount: 實際支付金額
* @param body: 訂單描述
* @param paymentType 支付類型
* @return
*/
R precreate(String orderNo, double amount, String body,Integer paymentType);
/**
* 支付寶 統一收單線下交易查詢
* 商家可調用 alipay.trade.query(統一收單線下交易查詢)接口,通過商戶網站唯一訂單号 out_trade_no 或支付寶交易号 trade_no 查詢對應訂單支付情況。
* @param orderNo 訂單編号
* @return
*/
R orderQuery(String orderNo);
/**
* 支付寶 統一收單交易撤銷接口
* 支付交易傳回失敗或支付系統逾時,商家可調用 alipay.trade.cancel(統一收單交易撤銷接口)通過商戶網站唯一訂單号 out_trade_no 或支付寶交易号 trade_no 撤銷交易。
* @param orderNo
* @return
*/
R cancel(String orderNo);
/**
* 支付寶 統一收單交易退款接口
* 當交易發生之後一段時間内,由于業務原因(如金額錯誤,使用者退款或者對賬不平等等)需要退款時,
* 商家可以調用 alipay.trade.refund(統一收單交易退款接口)通過商戶網站唯一訂單号 out_trade_no
* 或支付寶交易号 trade_no,将對應訂單支付款退還給買家,支付寶将在收到退款請求并且驗證成功之後,
* 按照退款規則将支付款按原路退到買家帳号上。支援全額或部分退款。
* @param orderNo 訂單編号
* @param amount: 實際支付金額
* @param refundReason: 退款原因
* @return
*/
R refund(String orderNo, double amount, String refundReason);
/**
* 驗證回調簽名
* @param request 請求資訊
* @return
*/
String notify(HttpServletRequest request);
}
實作類 AliPayServiceImpl
package com.bootdo.payment.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.CertAlipayRequest;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeCancelModel;
import com.alipay.api.domain.AlipayTradePrecreateModel;
import com.alipay.api.domain.AlipayTradeQueryModel;
import com.alipay.api.domain.AlipayTradeRefundModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeCancelRequest;
import com.alipay.api.request.AlipayTradePrecreateRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradeCancelResponse;
import com.alipay.api.response.AlipayTradePrecreateResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.bootdo.common.utils.R;
import com.bootdo.payment.config.AliPayConfig;
import com.bootdo.payment.domain.SelfmachineDO;
import com.bootdo.payment.service.AliPayService;
import com.bootdo.payment.service.SelfmachineService;
import com.bootdo.payment.util.QrCodeUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.math.BigDecimal;
import java.util.*;
/**
* @author snow
*/
@Service
public class AliPayServiceImpl implements AliPayService {
private static final Logger logger = LoggerFactory.getLogger(AliPayServiceImpl.class);
@Autowired
private AliPayConfig aliPayConfig=AliPayConfig.getInstance();
@Autowired
private SelfmachineService selfmachineService;
@Override
public R precreate(String orderNo, double amount, String body, Integer paymentType) {
//建立API對應的 request
AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();
//拼裝訂單參數
AlipayTradePrecreateModel model = new AlipayTradePrecreateModel();
//商戶訂單号。64 個字元以内的大小,可包含字母、數字、下劃線。需保證該參數在商戶端不重複
model.setOutTradeNo(orderNo);
//訂單總金額,機關為元,精确到小數點後兩位
model.setTotalAmount(String.valueOf(amount));
//訂單标題
model.setSubject(body);
//該筆訂單允許的最晚付款時間,逾期将關閉交易,從生成二維碼開始計時。
model.setTimeoutExpress("2m");
//該筆訂單允許的最晚付款時間,逾期将關閉交易,從生成二維碼開始計時。
model.setQrCodeTimeoutExpress("2m");
request.setBizModel(model);
//回調位址
request.setNotifyUrl(aliPayConfig.getPrecreate_notify());
try {
AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest());
logger.info("發起AliPay下單請求");
AlipayTradePrecreateResponse execute = alipayClient.certificateExecute(request);
//将傳回資料轉換格式
JSONObject jsonObject = JSON.parseObject(execute.getBody());
Map response = (Map) jsonObject.get("alipay_trade_precreate_response");
//列印傳回資訊
response.forEach((k,v) -> logger.info("訂單key={},訂單val={}",k,v));
Map<String,Object> map = new HashMap<>();
if (execute.isSuccess()) {
//訂單建立成功
//儲存訂單資訊,前台輪詢訂單狀态
SelfmachineDO selfmachineDO = new SelfmachineDO(orderNo,paymentType,new BigDecimal(Double.valueOf(amount)),1,new Date());
if(selfmachineService.save(selfmachineDO)<0){
logger.error("支付寶預建立訂單資訊儲存失敗");
return R.error("訂單資訊儲存失敗,請重新整理重試");
}
//将傳回的 qr_code 生成二維碼圖檔
map.put("qrCode_img",QrCodeUtil.generateQrCode(response.get("qr_code").toString()));
return R.ok().put("data",map);
}else{
return R.error(response.get("sub_msg").toString());
}
} catch (AlipayApiException e) {
e.printStackTrace();
logger.error("支付寶統一下單失敗");
return R.error().put("data","支付寶統一下單失敗");
}
}
@Override
public R orderQuery(String orderNo) {
Map<String,Object> map = new HashMap<>();
//構造API請求
AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
//發送請求
//拼裝訂單參數
AlipayTradeQueryModel model = new AlipayTradeQueryModel();
//設定業務參數
//商戶網站唯一訂單号
model.setOutTradeNo(orderNo);
request.setBizModel(model);
//回調位址
request.setNotifyUrl(aliPayConfig.getPrecreate_notify());
try {
AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest());
//通過alipayClient調用API,獲得對應的response類
AlipayTradeQueryResponse execute = alipayClient.certificateExecute(request);
//将傳回資料轉換格式
JSONObject jsonObject = JSON.parseObject(execute.getBody());
Map response = (Map) jsonObject.get("alipay_trade_query_response");
//列印傳回資訊
response.forEach((k,v) -> logger.info("訂單key={},訂單val={}",k,v));
if (execute.isSuccess()) {
logger.error("支付寶訂單查詢成功");
return R.ok("支付寶訂單查詢成功").put("data",response);
}else{
switch (response.get("sub_code").toString()){
case "ACQ.SYSTEM_ERROR":
//系統錯誤
logger.error("系統錯誤");
return R.error("支付寶系統錯誤,請重新整理重試!");
case "ACQ.INVALID_PARAMETER":
//參數無效
logger.error("參數無效");
return R.error("支付寶系統錯誤,請重新整理重試!");
case "ACQ.TRADE_NOT_EXIST":
//查詢的交易不存在
logger.error("查詢的交易不存在");
return R.ok();
default:
return R.ok();
}
}
} catch (AlipayApiException e) {
e.printStackTrace();
logger.error("支付寶訂單查詢失敗2");
return R.ok("支付寶訂單查詢失敗");
}
}
@Override
public R cancel(String orderNo) {
//建立 API 對應的request 類
AlipayTradeCancelRequest request = new AlipayTradeCancelRequest();
//設定業務參數
AlipayTradeCancelModel model = new AlipayTradeCancelModel();
//商戶網站唯一訂單号
model.setOutTradeNo(orderNo);
request.setBizModel(model);
//回調位址
request.setNotifyUrl(aliPayConfig.getPrecreate_notify());
try {
AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest());
AlipayTradeCancelResponse execute = alipayClient.certificateExecute(request);
//将傳回資料轉換格式
JSONObject jsonObject = JSON.parseObject(execute.getBody());
Map response = (Map) jsonObject.get("alipay_trade_cancel_response");
logger.info("支付寶撤銷");
//列印傳回資訊
response.forEach((k,v) -> logger.info("訂單key={},訂單val={}",k,v));
if(execute.isSuccess()){
//action
// 本次撤銷觸發的交易動作,接口調用成功且交易存在時傳回。可能的傳回值:
//close:交易未支付,觸發關閉交易動作,無退款;
//refund:交易已支付,觸發交易退款動作;
//未傳回:未查詢到交易,或接口調用失敗;
logger.info("支付寶訂單撤銷成功={}",orderNo);
return R.ok("支付寶訂單撤銷成功");
}else{
logger.error("支付寶撤銷交易失敗"+response.get("sub_msg").toString());
return R.error(response.get("sub_msg").toString());
}
} catch (AlipayApiException e) {
e.printStackTrace();
logger.error("支付寶撤銷錯誤");
return R.error("支付寶撤銷錯誤");
}
}
@Override
public R refund(String orderNo, double amount, String refundReason) {
//建立 API 對應的request 類
AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
//設定業務參數
AlipayTradeRefundModel model = new AlipayTradeRefundModel();
//商戶網站唯一訂單号
model.setOutTradeNo(orderNo);
//需要退款的金額,該金額不能大于訂單金額,機關為元,支援兩位小數
model.setRefundAmount(String.valueOf(amount));
request.setBizModel(model);
//回調位址
request.setNotifyUrl(aliPayConfig.getPrecreate_notify());
try {
AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest());
AlipayTradeRefundResponse execute = alipayClient.certificateExecute(request);
//将傳回資料轉換格式
JSONObject jsonObject = JSON.parseObject(execute.getBody());
Map response = (Map) jsonObject.get("alipay_trade_cancel_response");
//列印傳回資訊
logger.info("支付寶退款");
response.forEach((k,v) -> logger.info("訂單key={},訂單val={}",k,v));
if(execute.isSuccess()){
logger.info("支付寶退款成功={}",orderNo);
return R.ok();
}else{
logger.error("支付寶撤銷交易"+response.get("sub_msg").toString());
return R.error(response.get("sub_msg").toString());
}
} catch (AlipayApiException e) {
e.printStackTrace();
logger.info("支付寶退款失敗={}",orderNo);
return R.error("支付寶退款失敗");
}
}
@Override
public String notify(HttpServletRequest request) {
// 将異步通知中收到的待驗證所有參數都存放到map中
Map<String, String> params = convertRequestParamsToMap(request);
String paramsJson = JSON.toJSONString(params);
logger.info("支付寶回調,{}", paramsJson);
try {
// 調用SDK驗證簽名
boolean signVerified = AlipaySignature.rsaCertCheckV1(params, aliPayConfig.getAlipay_cert_path(),
aliPayConfig.getGetCharset(), aliPayConfig.getGetSignType());
if (signVerified) {
logger.info("支付寶回調成功");
// 按照支付結果異步通知中的描述,對支付結果中的業務内容進行1\2\3\4二次校驗,校驗成功後在response中傳回success,校驗失敗傳回failure
this.check(params);
//校驗通過修改訂單狀态可根據自己業務需求編寫業務代碼
if(selfmachineService.update(selfmachineDO)>0){
logger.info("支付寶回調簽名認證成功");
// 如果簽名驗證正确,立即傳回success
return "success";
}else{
logger.info("支付寶回調儲存業務失敗,傳回失敗讓支付寶重試");
return "failure";
}
} else {
logger.info("支付寶回調簽名認證失敗,signVerified=false, paramsJson:{}", paramsJson);
return "failure";
}
} catch (AlipayApiException e) {
logger.error("支付寶回調簽名認證失敗,paramsJson:{},errorMsg:{}", paramsJson, e.getMessage());
return "failure";
}
}
/**
* 将request中的參數轉換成Map
* @param request
* @return
*/
private static Map<String, String> convertRequestParamsToMap(HttpServletRequest request) {
Map<String, String> retMap = new HashMap<String, String>();
Set<Map.Entry<String, String[]>> entrySet = request.getParameterMap().entrySet();
for (Map.Entry<String, String[]> entry : entrySet) {
String name = entry.getKey();
String[] values = entry.getValue();
int valLen = values.length;
if (valLen == 1) {
retMap.put(name, values[0]);
} else if (valLen > 1) {
StringBuilder sb = new StringBuilder();
for (String val : values) {
sb.append(",").append(val);
}
retMap.put(name, sb.toString().substring(1));
} else {
retMap.put(name, "");
}
}
return retMap;
}
/**
* 1、商戶需要驗證該通知資料中的out_trade_no是否為商戶系統中建立的訂單号,
* 2、判斷total_amount是否确實為該訂單的實際金額(即商戶訂單建立時的金額),
* 3、校驗通知中的seller_id(或者seller_email)是否為out_trade_no這筆單據的對應的操作方(有的時候,一個商戶可能有多個seller_id/seller_email),
* 4、驗證app_id是否為該商戶本身。上述1、2、3、4有任何一個驗證不通過,則表明本次通知是異常通知,務必忽略。
* 在上述驗證通過後商戶必須根據支付寶不同類型的業務通知,正确的進行不同的業務處理,并且過濾重複的通知結果資料。
* 在支付寶的業務通知中,隻有交易通知狀态為TRADE_SUCCESS或TRADE_FINISHED時,支付寶才會認定為買家付款成功。
*
* @param params
* @throws AlipayApiException
*/
private void check(Map<String, String> params) throws AlipayApiException {
String outTradeNo = params.get("out_trade_no");
// 1、商戶需要驗證該通知資料中的out_trade_no是否為商戶系統中建立的訂單号,
SelfmachineDO selfmachineDO = selfmachineService.get(outTradeNo);
if (selfmachineDO == null) {
throw new AlipayApiException("out_trade_no錯誤");
}
// 2、判斷total_amount是否确實為該訂單的實際金額(即商戶訂單建立時的金額),
if (!String.valueOf(selfmachineDO.getAmount()).equals(params.get("total_amount"))) {
throw new AlipayApiException("error total_amount");
}
// 3、校驗通知中的seller_id(或者seller_email)是否為out_trade_no這筆單據的對應的操作方(有的時候,一個商戶可能有多個seller_id/seller_email),
// 第三步可根據實際情況省略
// 4、驗證app_id是否為該商戶本身。
if (!params.get("app_id").equals(aliPayConfig.getAppID())) {
throw new AlipayApiException("app_id不一緻");
}
}
/**
* 初始化構造 CertAlipayRequest
* @return
*/
private CertAlipayRequest certAlipayRequest(){
//構造client
CertAlipayRequest certAlipayRequest = new CertAlipayRequest();
//設定網關位址
certAlipayRequest.setServerUrl(aliPayConfig.getAlipay_URL());
//設定應用Id
certAlipayRequest.setAppId(aliPayConfig.getAppID());
//設定應用私鑰
certAlipayRequest.setPrivateKey(aliPayConfig.getPrivate_key());
//設定請求格式,固定值json
certAlipayRequest.setFormat("json");
//設定字元集
certAlipayRequest.setCharset(aliPayConfig.getGetCharset());
//設定簽名類型
certAlipayRequest.setSignType(aliPayConfig.getGetSignType());
//設定應用公鑰證書路徑
certAlipayRequest.setCertPath(aliPayConfig.getApp_cert_path());
//設定支付寶公鑰證書路徑
certAlipayRequest.setAlipayPublicCertPath(aliPayConfig.getAlipay_cert_path());
//設定支付寶根證書路徑
certAlipayRequest.setRootCertPath(aliPayConfig.getAlipay_root_cert_path());
return certAlipayRequest;
}
}
控制器層 AliPayController
package com.bootdo.payment.controller;
import com.bootdo.common.utils.R;
import com.bootdo.payment.domain.SelfmachineDO;
import com.bootdo.payment.service.AliPayService;
import com.bootdo.payment.service.SelfmachineService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
/**
* 支付寶支付
* @author snow
*/
@RestController
@RequestMapping("/api/aliPay")
@CrossOrigin
public class AliPayController {
@Autowired
private SelfmachineService selfmachineService;
@Autowired
private AliPayService aliPayService;
//支付寶當面付 開始
/**
* 支付寶 統一收單線下交易預建立
* 商家可調用 alipay.trade.precreate(統一收單線下交易預建立)接口,傳入訂單商品及金額的資訊建立訂單。支付寶将傳回支付二維碼資訊用于使用者掃碼支付
* @param orderNo 訂單編号
* @param amount 金額
* @param body 商品資訊
* @param paymentType 支付類型 1微信支付,2支付寶支付
* @return
*/
@RequestMapping("/precreate")
public R precreate(@RequestParam String orderNo,@RequestParam double amount,@RequestParam String body,@RequestParam Integer paymentType){
//1.驗證訂單是否存在、
R rs = aliPayService.orderQuery(orderNo);
if(Integer.parseInt(rs.get("code").toString())!=0){
return rs;
}
//2.統一收單線下交易預建立
R r = aliPayService.precreate(orderNo,amount,body,paymentType);
if(Integer.parseInt(r.get("code").toString())==0){
return r;
}
return r.error(r.get("sub_msg").toString().equals("")?r.get("sub_msg").toString():"訂單建立失敗");
}
/**
* 支付寶 統一收單線下交易查詢
* 商家可調用 alipay.trade.query(統一收單線下交易查詢)接口,通過商戶網站唯一訂單号 out_trade_no 或支付寶交易号 trade_no 查詢對應訂單支付情況。
* @param orderNo 訂單編号
* @return
*/
@RequestMapping("/orderQuery")
public R orderQuery(String orderNo){
Map<String,Object> map = aliPayService.orderQuery(orderNo);
if(new Boolean(map.get("success").toString())){
return R.ok();
}
return R.error(map.get("sub_msg").toString());
}
/**
* 支付寶 統一收單交易撤銷接口
* 支付交易傳回失敗或支付系統逾時,商家可調用 alipay.trade.cancel(統一收單交易撤銷接口)通過商戶網站唯一訂單号 out_trade_no 或支付寶交易号 trade_no 撤銷交易。
* @param orderNo
* @return
*/
@RequestMapping("/cancel")
public R cancel(String orderNo){
R r = aliPayService.cancel(orderNo);
if(Integer.parseInt(r.get("code").toString())==0){
//自己的業務
return r.ok("支付寶訂單撤銷成功");
}
return r.error(r.get("sub_msg").toString());
}
/**
* 支付寶 統一收單交易退款接口
* 當交易發生之後一段時間内,由于業務原因(如金額錯誤,使用者退款或者對賬不平等等)需要退款時,
* 商家可以調用 alipay.trade.refund(統一收單交易退款接口)通過商戶網站唯一訂單号 out_trade_no
* 或支付寶交易号 trade_no,将對應訂單支付款退還給買家,支付寶将在收到退款請求并且驗證成功之後,
* 按照退款規則将支付款按原路退到買家帳号上。支援全額或部分退款。
* @param orderNo 訂單編号
* @param amount: 實際支付金額
* @param refundReason: 退款原因
* @return
*/
@RequestMapping("/refund")
public R refund(String orderNo, double amount, String refundReason){
R r = aliPayService.refund(orderNo,amount,refundReason);
if(Integer.parseInt(r.get("code").toString())==0){
return r.ok();
}
return r.error(r.get("sub_msg").toString());
}
/**
* 驗證回調簽名
* @param request 請求資訊
* @return
*/
@PostMapping("/notify")
public String notify(HttpServletRequest request){
return aliPayService.notify(request);
}
/**
* 放棄支付
* @param orderNo
* @return
*/
@PostMapping("/giveUpPayMent")
public R giveUpPayMent(@RequestParam String orderNo){
//1·查詢支付訂單狀态
Map<String,Object> map = aliPayService.orderQuery(orderNo);
if(Integer.parseInt(map.get("code").toString())==0){
//2·撤銷訂單
if(aliPayService.cancel(orderNo).get("code").equals("0")){
//閉單成功修改自己的業務
return R.ok("支付寶訂單撤銷成功!");
}
return R.ok("支付寶訂單撤銷成功!");
}
return R.error(map.get("trade_state").toString());
}
//支付寶當面付 結束
}
QrCodeUtil工具類
<!-- 二維碼生成-->
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.3.3</version>
<scope>compile</scope>
</dependency>
QrCodeUtil
package com.bootdo.payment.util;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Base64;
/**
* 二維碼生成
*/
public class QrCodeUtil {
public static String generateQrCode(String code_url){
String code="data:image/png;base64,";
Base64.Encoder encoder = Base64.getEncoder();
try {
QRCodeWriter qrCodeWriter = new QRCodeWriter();
//傳回給應用層的 tempToken 是經過base64加密傳回後端需要解密
BitMatrix bitMatrix = qrCodeWriter.encode(code_url, BarcodeFormat.QR_CODE, 430, 430);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
MatrixToImageWriter.writeToStream(bitMatrix, "PNG", outputStream);
code += encoder.encodeToString(outputStream.toByteArray());
} catch (IOException | WriterException e) {
e.printStackTrace();
}
return code;
}
}
到此支付寶當面付完成,此文章僅作為自己的開發經驗記錄,如有不合理之處還請給位指點一二,謝謝