技術(shù)匯總:第十四章:電腦端生成支付寶二維碼支付
支付寶支付
第一步:alipay.properties
- alipay_url=https://openapi.alipay.com/gateway.do
- #app的id
- app_id=2018020102122556
- #私鑰
- app_private_key=MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCdQeknhM2rhiGAH6V0ljxn3rAWIdzduTEQuteTfwjnZtvMhQPuuN1b/88D5yMuaZhZNFeUdWb+SmtP9DAzAWWgnT13T0YhJcxP6txm7JBRrjadCRt+LOFxPiPQk5t9fH7yXjw9i4uMDsNJeTncrVZ/AZYrk0ESC9anJR8XeuBc3HE8T4fqlKKl35jlumIWrPbPNQhKGXaGcOnpiaXO9qYYUSP/tnrjNYXHOso0yBs4YTl+LLX2TJ12p3n/oX6HnL4zQgtN5k4QasHP7CIig1ngcVQGfWsMm4djI9KXNXvGLQPfMQEmyb71mM5OCdl1MtAc6OaIAymhSv2hOLNIuyodAgMBAAECggEAe05/P5mGm4QlKI2n8u8KlneqovASe1kG/BNFjkYB+VBR8OAr4TfbepPvAyRuFap+5xN/yMz14VcBJkRWtufVhEdHNxJV7w/wUIncIGhGEYYFFMVbZWhTrbQH6TiUp6TC9dCmc6vD1CKPRkFj+YGBXT0lPy3LzBa0TYNyCbszyhthrgkpuFYbB0R93IPvvBh5NJFXQytwNb2oVopC9AQWviqnZUZcT0eJ087dQ1WLPa6blBD8DP1PUq0Ldr6pgKfObFxIj8+87DlJznRfdEsbqZlS7jagdw5tLr71WJpctIGPqKpgvajfePP/lj3eY82BKQB+aTw0zmAiB05Yes4LgQKBgQDq3EiQR8J1MEN2rpiLt1WvDYYvKVUgOY7Od//fRPgaMBstbe4TzGBpR8E+z267bHAWLaWtHkfX6muFHn1x68ozEUWk/nZq0smWnuPdcy4E7Itbk36W2FF/rOZB7j5ddlC9byrxDSNgcf9/FA/CU+i5KVQpLYfsk2dvwomvu0aFVQKBgQCraXpxzMmsBx4127LsZDO5bxfxb6nqzyK4NPe0VaGiRg8oaCWczcLz1J5iRqC9QeEwsSt4XU1sYBMTcsFpA0apZpm3prH2HJRx/isNENesaHcihF0mMd0WxU3xyRvWSDeZV5A1Zy1ZEJ+p17DGwb2j+yo2uBrDNXBgBWEzXwiRqQKBgBdXFvsHtqKQzlOQHGbeLGy+KlSrheMy9Sc9s7cLkqB/oWPNZfifugEceW71jGqh5y29EZb3yGoDyPWsxwi4Rxr2H3a7Nyd8lT4bwkdyt+MTYvIR4WW6T7chhqyMsbP2GyYIUzsrdBWUnrCRXNOSJTGpksyY0sZHC+OGcMp/EQ4VAoGBAIISSVL/pm1+/UK7U1ukcced8JpKNLM0uVD1CJ50eHHOHgR4e0owrWYfioxisejLjBlJ6AWvL2g0w2T3qKKKVN2JOM4ulU5/w3l4+KwygqaWowizTogEQJPd5ta52ADTzjTzSD/t6nByd+YHAWLhc4lyt0bMj6pf68VBb8/upm75AoGAGAYz79IVHp9eppykufjNcWu6okkG8tZnzuyaWKW/CuKKBWMaTk0vcyQlfJfxIBccoQrBuYyXBdcpPuZ/ys2C25pNrkACuhIKNgnMc0floJoYEfJzetw/3cIimWu4NJzVQOaojaGA58oo2+fub43Xn25Jq4rvSVe3oLdb5xWkw5Q=
- #公鑰
- alipay_public_key=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhkZi6W0wn/prX+NIIF9ATb5Z8ReKK4hFYtBrweDfGHD1mNW7YIZY4G5hE7S2Sry8eFXlFgSlBWlJ4fVnDaK9MkVThpwE2H65ooVlK/wLuyPqovIVpMt/utva5Ayuzv7eQOWK45FdLDNDlK8QLoBko6SS+YbnWnf7a+mrf4NAS4UFClpfe8Byqe8XIraO2Cg4Ko5Y5schX39rOAH8GlLdgqQRYVQ2dCnkIQ+L+I4Cy9Mvw3rIkTwt3MBU+AqREXY4r5Bn6cmmX/9MAJbFqrofGiUAqG+qbjTcZAzgNPfuiD0zXgt/YYjMQMzck75BOmwnYOam2ajODUSQn8Xybsa7wQIDAQAB
- #回調(diào)地址
- return_payment_url=http://localhost:8085/member/pay/alipay/callback/return
- #異步地址需要外網(wǎng)可以訪問(暫時沒有寫)
- notify_payment_url=http://60.205.215.91/alipay/callback/notify
第二步:PayControllerpackage com.macro.mall.portal.controller;
import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.macro.mall.common.api.CommonResult;
import com.macro.mall.model.OmsOrderItem;
import com.macro.mall.model.PaymentInfo;
import com.macro.mall.portal.config.AlipayConfig;
import com.macro.mall.portal.service.OmsPortalOrderService;
import com.macro.mall.portal.service.PaymentService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import net.sf.json.JSONObject;
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.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
* 支付管理
*/
@Controller
@Api(tags = "PayController", description = "支付管理")
@RequestMapping("/member/pay")
public class PayController {
@Autowired
private PaymentService paymentService;
@Autowired
private OmsPortalOrderService omsPortalOrderService;
@Autowired
AlipayClient alipayClient;
@ApiOperation("去支付")
@RequestMapping(value = "/alipay/submit", method = RequestMethod.GET)
@ResponseBody
public String goToPay( String orderSn, BigDecimal totalAmount) {
//根據(jù)訂單編號獲取訂單詳情信息
OmsOrderItem omsOrderItem =omsPortalOrderService.getOrderByOrderSn(orderSn);
//獲取商品名稱
String productName = omsOrderItem.getProductName();
//創(chuàng)建PC場景下單并支付請求對象
AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();//創(chuàng)建API對應的request
//設置同步返回地址,HTTP/HTTPS開頭字符串
alipayRequest.setReturnUrl(AlipayConfig.return_payment_url);
//支付寶服務器主動通知商戶服務器里指定的頁面http/https路徑。
alipayRequest.setNotifyUrl(AlipayConfig.notify_payment_url);//在公共參數(shù)中設置回跳和通知地址
Map<String,String> requestMap = new HashMap<>();
requestMap.put("out_trade_no",orderSn);//訂單編號
requestMap.put("product_code","FAST_INSTANT_TRADE_PAY");//產(chǎn)品交易碼
requestMap.put("total_amount","0.01");//實際付款金額
requestMap.put("subject",productName);//商品名稱
//填充業(yè)務參數(shù)
alipayRequest.setBizContent(JSON.toJSONString(requestMap));
String form="";
try {
//調(diào)用SDK生成表單
form = alipayClient.pageExecute(alipayRequest).getBody();
} catch (AlipayApiException e) {
e.printStackTrace();
}
// 生成(保存)支付信息
PaymentInfo paymentInfo = new PaymentInfo();
paymentInfo.setOutTradeNo(orderSn);
paymentInfo.setPaymentStatus("未支付");
paymentInfo.setOrderId(String.valueOf(omsOrderItem.getOrderId()));
paymentInfo.setTotalAmount(totalAmount);
paymentInfo.setSubject(productName);
paymentInfo.setCreateTime(new Date());
paymentService.save(paymentInfo);
// 發(fā)送檢查支付結(jié)果的消息隊列,
paymentService.sendDelayPaymentCheck(orderSn,5);
return form;
}
@ApiOperation("支付成功后同步回調(diào)轉(zhuǎn)支付成功頁面")
@ResponseBody
@RequestMapping(value = "/alipay/callback/return",method = RequestMethod.GET)
public CommonResult callBackReturn(HttpServletRequest request){// 頁面同步反轉(zhuǎn)的回調(diào)
Map<String,String> paramsMap = new HashMap<String, String>();
Map parameterMap = request.getParameterMap();
for(Iterator<String> iter = parameterMap.keySet().iterator(); iter.hasNext();){
String name = iter.next();
String[] values = (String [])parameterMap.get(name);
String valueStr = "";
for (int i = 0; i < values.length; i++) {
valueStr = (i == values.length - 1 ) ? valueStr + values [i] : valueStr + values[i] + ",";
}
paramsMap.put(name,valueStr);
}
String outTradeNo = request.getParameter("out_trade_no");
String tradeNo = request.getParameter("trade_no");
String sign = request.getParameter("sign");
try {
boolean b = AlipaySignature.rsaCheckV1(paramsMap, AlipayConfig.alipay_public_key,AlipayConfig.charset,AlipayConfig.sign_type);// 對支付寶回調(diào)簽名的校驗
} catch (AlipayApiException e) {
e.printStackTrace();
}
//修改支付信息,冪等性檢查
/* boolean b = paymentService.checkPaymentStatus(outTradeNo);
if(!b){
PaymentInfo paymentInfo = paymentService.checkPaymentResult(outTradeNo);
paymentService.updatePayment(request.getQueryString(),outTradeNo,tradeNo);
//發(fā)送系統(tǒng)消息,出發(fā)并發(fā)商品支付業(yè)務消息隊列
paymentService.sendPaymentSuccess(outTradeNo,paymentInfo.getPaymentStatus(),tradeNo);
}*/
return CommonResult.success("支付成功");
}
}
第三步:發(fā)送檢查支付結(jié)果的消息隊列
@Autowired
private OmsOrderSettingMapper orderSettingMapper;
@Autowired
private AmqpTemplate amqpTemplate;
/**
* 發(fā)送檢查支付結(jié)果的消息隊列
* @param orderSn
* @param count
*/
@Override
public void sendDelayPaymentCheck(String orderSn, int count) {
//獲取訂單超時時間
OmsOrderSetting orderSetting = orderSettingMapper.selectByPrimaryKey(1L);
long delayTimes = orderSetting.getNormalOrderOvertime() * 60 * 1000;
HashMap<Object, Object> hashMap = new HashMap<>();
hashMap.put("out_trade_no",orderSn);
hashMap.put("count",count);
//給延遲隊列發(fā)送消息
amqpTemplate.convertAndSend(QueueEnum.QUEUE_PAY_CANCEL.getExchange(), QueueEnum.QUEUE_PAY_CANCEL.getRouteKey(), hashMap, new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
//給消息設置延遲毫秒值
message.getMessageProperties().setExpiration(String.valueOf(delayTimes));
return message;
}
});
}
第四步:處理發(fā)送檢查支付結(jié)果的消息隊列
package com.macro.mall.portal.component;
import com.macro.mall.model.PaymentInfo;
import com.macro.mall.portal.service.PaymentService;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.HashMap;
/**
* 支付的處理者
*/
@Component
@RabbitListener(queues = "mall.pay.cancel")
public class PayReceiver {
@Autowired
PaymentService paymentService;
@RabbitHandler
public void handle(HashMap mapMessage){
try {
String outTradeNo = mapMessage.get("out_trade_no").toString();
int count = Integer.parseInt(mapMessage.get("count").toString());
// 如果沒有支付成功,再次發(fā)送延遲檢查隊列
if (count > 0) {
// 進行支付狀態(tài)檢查
System.out.println("正在進行第" + (6 - count) + "支付結(jié)果次檢查");
//調(diào)用alipayClient接口,根據(jù)out_trade_no查詢支付信息
PaymentInfo paymentInfo = paymentService.checkPaymentResult(outTradeNo);
Thread thread = new Thread();
thread.start();
Thread.sleep(10000);
//判斷是否已經(jīng)支付成功
if (paymentInfo.getPaymentStatus()!=null&&(paymentInfo.getPaymentStatus().equals("TRADE_SUCCESS") || paymentInfo.getPaymentStatus().equals("TRADE_FINISHED"))) {
// 交易成功或者失敗,記錄交易狀態(tài)
System.out.println("檢查交易結(jié)果成功,記錄交易狀態(tài)。。。");// 修改支付的狀態(tài)信息
// 修改支付信息
boolean b = paymentService.checkPaymentStatus(outTradeNo);
if(!b){
//修改為已支付
paymentService.updatePayment(paymentInfo.getCallbackContent(),outTradeNo,paymentInfo.getAlipayTradeNo());
// 發(fā)送系統(tǒng)消息,出發(fā)并發(fā)商品支付業(yè)務消息隊列
paymentService.sendPaymentSuccess(paymentInfo.getOutTradeNo(),paymentInfo.getPaymentStatus(),paymentInfo.getAlipayTradeNo());
}
} else {//未支付
// 再次進行延遲檢查
System.out.println("正在進行第" + (6 - count) + "支付結(jié)果次檢查,檢查用戶尚未付款成功,繼續(xù)巡檢");
paymentService.sendDelayPaymentCheck(outTradeNo, count - 1);
}
} else {
System.out.println("支付結(jié)果次檢查次數(shù)耗盡,支付未果。。。");
}
} catch (Exception e) {
}
}
}
第五步:調(diào)用alipayClient接口,根據(jù)out_trade_no查詢支付信息
@Autowired
AlipayClient alipayClient;
/**
* 進行支付狀態(tài)檢查
* @param outTradeNo
* @return
*/
@Override
public PaymentInfo checkPaymentResult(String outTradeNo) {
PaymentInfo paymentInfo = new PaymentInfo();
// 調(diào)用alipayClient接口,根據(jù)out_trade_no查詢支付狀態(tài)
AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
Map<String,Object> mapString = new HashMap<String,Object>();
mapString.put("out_trade_no",outTradeNo);
String s = JSON.toJSONString(mapString);
request.setBizContent(s);
AlipayTradeQueryResponse response = null;
try {
response = alipayClient.execute(request);
} catch (AlipayApiException e) {
e.printStackTrace();
}
// 等待付款、付款成功、付款失敗、已經(jīng)結(jié)束
paymentInfo.setCallbackTime(new Date());
paymentInfo.setOutTradeNo(outTradeNo);
paymentInfo.setCallbackContent(response.getMsg());
if(response.isSuccess()){
System.out.println("交易已經(jīng)創(chuàng)建");
paymentInfo.setPaymentStatus(response.getTradeStatus());
paymentInfo.setAlipayTradeNo(response.getTradeNo());
} else {
System.out.println("交易未創(chuàng)建");
}
return paymentInfo;
}
第六步:發(fā)送系統(tǒng)消息,出發(fā)并發(fā)商品支付業(yè)務消息隊列
@Autowired
private OmsOrderSettingMapper orderSettingMapper;
@Autowired
private AmqpTemplate amqpTemplate;
/**
* 發(fā)送系統(tǒng)消息,出發(fā)并發(fā)商品支付業(yè)務消息隊列
* @param outTradeNo
* @param paymentStatus
* @param tradeNo
*/
@Override
public void sendPaymentSuccess(String outTradeNo, String paymentStatus, String tradeNo) {
HashMap<String, String> hashMap = new HashMap<>();
hashMap.put("outTradeNo",outTradeNo);
hashMap.put("paymentStatus",paymentStatus);
hashMap.put("tradeNo",tradeNo);
OmsOrderSetting orderSetting = orderSettingMapper.selectByPrimaryKey(1L);
long delayTimes = orderSetting.getNormalOrderOvertime() * 60 * 1000;
//給延遲隊列發(fā)送消息
amqpTemplate.convertAndSend(QueueEnum.QUEUE_PAYMENT_SUCCESS_CANCEL.getExchange(), QueueEnum.QUEUE_PAYMENT_SUCCESS_CANCEL.getRouteKey(), hashMap, new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
//給消息設置延遲毫秒值
message.getMessageProperties().setExpiration(String.valueOf(delayTimes));
return message;
}
});
}
第七步:處理發(fā)送系統(tǒng)消息,出發(fā)并發(fā)商品支付業(yè)務消息隊列
package com.macro.mall.portal.component;
import com.macro.mall.portal.service.OmsOrderService;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.HashMap;
/**
* 支付成功的處理者
*/
@Component
@RabbitListener(queues = "mall.paysuccess.cancel")
public class PaySuccessReceiver {
@Autowired
private OmsOrderService orderService;
@RabbitHandler
public void handle(HashMap mapMessage){
String outTradeNo = mapMessage.get("outTradeNo").toString();
String trackingNo = mapMessage.get("tradeNo").toString();
String paymentStatus = mapMessage.get("paymentStatus").toString();
// 消費代碼
orderService.updateOrder(outTradeNo,paymentStatus,trackingNo);
// 發(fā)送一個訂單成功的消息隊列,由庫存系統(tǒng)消費(或者調(diào)用庫存接口)
orderService.sendOrderResult(outTradeNo);
}
}
第八步:發(fā)送一個訂單成功的消息隊列,由庫存系統(tǒng)消費(或者調(diào)用庫存接口)
@Autowired
private OmsOrderItemMapper omsOrderItemMapper;
@Autowired
private AmqpTemplate amqpTemplate;
/**
* 發(fā)送一個訂單成功的消息隊列,由庫存系統(tǒng)消費(或者調(diào)用庫存接口)
* @param outTradeNo
*/
@Override
public void sendOrderResult(String outTradeNo) {
OmsOrderItemExample omsOrderItemExample = new OmsOrderItemExample();
OmsOrderItemExample.Criteria criteria = omsOrderItemExample.createCriteria();
criteria.andOrderSnEqualTo(outTradeNo);
List<OmsOrderItem> omsOrderItems = omsOrderItemMapper.selectByExample(omsOrderItemExample);
OmsOrderItem omsOrder = omsOrderItems.get(0);
Long productId = omsOrder.getProductId();
HashMap<String, Long> objectObjectHashMap = new HashMap<>();
objectObjectHashMap.put("productId",productId);
//給延遲隊列發(fā)送消息
amqpTemplate.convertAndSend(QueueEnum.QUEUE_STOCK_QUEUE.getExchange(), QueueEnum.QUEUE_STOCK_QUEUE.getRouteKey(),objectObjectHashMap, new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
//給消息設置延遲毫秒值
message.getMessageProperties().setExpiration(String.valueOf(0));
return message;
}
});
}
第九步:處理發(fā)送一個訂單成功的消息隊列,由庫存系統(tǒng)消費(或者調(diào)用庫存接口)
package com.macro.mall.portal.component;
import com.macro.mall.portal.service.PmsSkuStockService;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.HashMap;
@Component
@RabbitListener(queues = "mall.stock.cancel")
public class StockReserve {
@Autowired
private PmsSkuStockService pmsSkuStockService;
@RabbitHandler
public void handle(HashMap<String, Long> productId){
//根據(jù)訂單編號查詢該訂單的商品數(shù)量
Integer productQuantity = pmsSkuStockService.getProductQuantity(productId);
//根據(jù)商品id減賣家?guī)齑姹淼膸齑?br> pmsSkuStockService.updateOrderStock(productQuantity,productId.get("productId"));
}
}
如果對rabbitmq不熟悉的話可以查看https://blog.csdn.net/java_wxid/article/category/8663217