一、創建微服務
1、匯入依賴
<!--微信支付-->
<dependency>
<groupId>com.github.wxpay</groupId>
<artifactId>wxpay-sdk</artifactId>
<version>0.0.3</version>
</dependency>
<!--httpclient支持-->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
2、需要的工具類
HttpClient:http/https相關操作
public class HttpClient {
private String url;
private Map<String, String> param;
private int statusCode;
private String content;
private String xmlParam;
private boolean isHttps;
public boolean isHttps() {
return isHttps;
}
public void setHttps(boolean isHttps) {
this.isHttps = isHttps;
}
public String getXmlParam() {
return xmlParam;
}
public void setXmlParam(String xmlParam) {
this.xmlParam = xmlParam;
}
public HttpClient(String url, Map<String, String> param) {
this.url = url;
this.param = param;
}
public HttpClient(String url) {
this.url = url;
}
public void setParameter(Map<String, String> map) {
param = map;
}
public void addParameter(String key, String value) {
if (param == null)
param = new HashMap<String, String>();
param.put(key, value);
}
public void post() throws ClientProtocolException, IOException {
HttpPost http = new HttpPost(url);
setEntity(http);
execute(http);
}
public void put() throws ClientProtocolException, IOException {
HttpPut http = new HttpPut(url);
setEntity(http);
execute(http);
}
public void get() throws ClientProtocolException, IOException {
if (param != null) {
StringBuilder url = new StringBuilder(this.url);
boolean isFirst = true;
for (String key : param.keySet()) {
if (isFirst) {
url.append("?");
}else {
url.append("&");
}
url.append(key).append("=").append(param.get(key));
}
this.url = url.toString();
}
HttpGet http = new HttpGet(url);
execute(http);
}
/**
* set http post,put param
*/
private void setEntity(HttpEntityEnclosingRequestBase http) {
if (param != null) {
List<NameValuePair> nvps = new LinkedList<NameValuePair>();
for (String key : param.keySet()) {
nvps.add(new BasicNameValuePair(key, param.get(key))); // 引數
}
http.setEntity(new UrlEncodedFormEntity(nvps, Consts.UTF_8)); // 設定引數
}
if (xmlParam != null) {
http.setEntity(new StringEntity(xmlParam, Consts.UTF_8));
}
}
private void execute(HttpUriRequest http) throws ClientProtocolException,
IOException {
CloseableHttpClient httpClient = null;
try {
if (isHttps) {
SSLContext sslContext = new SSLContextBuilder()
.loadTrustMaterial(null, new TrustStrategy() {
// 信任所有
@Override
public boolean isTrusted(X509Certificate[] chain,
String authType)
throws CertificateException {
return true;
}
}).build();
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
sslContext);
httpClient = HttpClients.custom().setSSLSocketFactory(sslsf)
.build();
} else {
httpClient = HttpClients.createDefault();
}
CloseableHttpResponse response = httpClient.execute(http);
try {
if (response != null) {
if (response.getStatusLine() != null) {
statusCode = response.getStatusLine().getStatusCode();
}
HttpEntity entity = response.getEntity();
// 回應內容
content = EntityUtils.toString(entity, Consts.UTF_8);
}
} finally {
response.close();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
httpClient.close();
}
}
public int getStatusCode() {
return statusCode;
}
public String getContent() throws ParseException, IOException {
return content;
}
}
3、組態檔:application.yml
server:
port: 18090
spring:
application:
name: pay
main:
allow-bean-definition-overriding: true
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:7001/eureka
instance:
prefer-ip-address: true
feign:
hystrix:
enabled: true
#hystrix 配置
hystrix:
command:
default:
execution:
timeout:
#如果enabled設定為false,則請求超時交給ribbon控制
enabled: true
isolation:
strategy: SEMAPHORE
#微信支付資訊配置
weixin:
#應用ID
appid: wx8397f8696b538317
#商戶號
partner: 1473426802
#密鑰
partnerkey: T6m9iK73b0kn9g5v426MKfHQH7X8rKwb
#支付回呼地址 通知地址
notifyurl: https://www.cnblogs.com/chawaner/
4、SpringBoot啟動類
/**
* @Author TeaBowl
* @Date 2021/2/1 10:47
* @Version 1.0
*/
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
@EnableEurekaClient
public class WeiXinPayApplication {
public static void main(String[] args) {
SpringApplication.run(WeiXinPayApplication.class,args);
}
}
5、控制層
/**
* @Author TeaBowl
* @Date 2021/2/1 12:01
* @Version 1.0
*/
@RestController
@RequestMapping(value = "/weixin/pay")
public class WeiXinPayController {
@Autowired
private WeixinPayService weixinPayService;
/**
* 創建二維碼
* @param parameterMap:用戶訂單資訊
* @return
*/
@RequestMapping(value = "/create/native")
public Result createNative(@RequestParam Map<String,String> parameterMap){
Map<String,String> resultMap = weixinPayService.createnative(parameterMap);
return new Result(true, StatusCode.OK,"創建二維碼預付訂單成功!",resultMap);
}
}
6、應用層
/**
* @Author TeaBowl
* @Date 2021/2/1 11:01
* @Version 1.0
*/
public interface WeixinPayService {
/**
* 創建二維碼
* @param parameterMap:用戶訂單資訊
* @return
*/
Map createnative(Map<String,String> parameterMap);
}
/**
* @Author TeaBowl
* @Date 2021/2/1 11:00
* @Version 1.0
*/
@Service
public class WeixinPayServiceImpl implements WeixinPayService {
//應用ID
@Value("${weixin.appid}")
private String appid;
//商戶號
@Value("${weixin.partner}")
private String partner;
//密鑰
@Value("${weixin.partnerkey}")
private String partnerkey;
//通知地址
@Value("${weixin.notifyurl}")
private String notifyurl;
/**
* 創建二維碼
*
* @param parameterMap:用戶訂單資訊
* @return
*/
@Override
public Map createnative(Map<String, String> parameterMap) {
try {
//遠程呼叫
//創建一個Map集合存放請求引數
Map<String, String> paramMap = new HashMap<>();
//添加資料
//應用ID
paramMap.put("appid", appid);
//商戶號
paramMap.put("mch_id", partner);
//隨機字串
paramMap.put("nonce_str", WXPayUtil.generateNonceStr());
//商品描述
paramMap.put("body", "茶碗兒購物是真的好");
//訂單號
paramMap.put("out_trade_no", parameterMap.get("outtradeno"));
//交易總金額,單位為:分
paramMap.put("total_fee", parameterMap.get("totalfee"));
//終端IP
paramMap.put("spbill_create_ip", "127.0.0.1");
//通知地址,添URL地址
paramMap.put("notify_url", notifyurl);
//交易型別,NATIVE
paramMap.put("trade_type", "NATIVE");
//簽名
//paramMap.put("sign","");
//Map轉為XML資料,可以自帶簽名
//將請求引數集合,轉為帶有簽名的XML資料格式
String xmlStr = WXPayUtil.generateSignedXml(paramMap, partnerkey);
//URL地址,微信支付介面鏈接
String url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
//提交方式:HTTPS
//創建HttpClient物件,對url請求地址進行操作
HttpClient httpClient = new HttpClient(url);
//設定提交方式為HTTPS
httpClient.setHttps(true);
//提交引數,引數以XML資料格式提交
httpClient.setXmlParam(xmlStr);
//執行請求
//發送XML資料,使用post請求
httpClient.post();
//獲取回傳的資料,此時回傳的資料為XML資料格式
String content = httpClient.getContent();
System.out.println("content:" + content);
//回傳資料轉成Map
Map<String, String> resultMap = WXPayUtil.xmlToMap(content);
return resultMap;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
二、測驗
1、瀏覽器輸入請求地址:http://localhost:18090/weixin/pay/create/native?outtradeno=198999&totalfee=101
2、引數解釋:
? outtradeno:訂單號
? totalfee:總金額
3、瀏覽器請求結果
{
"flag": true,
"code": 20000,
"message": "創建二維碼預付訂單成功!",
"data": {
"nonce_str": "pUPI4MeBq1ikJbOJ",
"code_url": "weixin://wxpay/bizpayurl?pr=qJVBnYYzz",
"appid": "wx8397f8696b538317",
"sign": "7BCED5501AD892D5490A109DADE3383F",
"trade_type": "NATIVE",
"return_msg": "OK",
"result_code": "SUCCESS",
"mch_id": "1473426802",
"return_code": "SUCCESS",
"prepay_id": "wx011403161517455f3f2880f7e02e920000"
}
}
三、生成二維碼
1、使用qrious.js寫一個頁面pay.html,用于生成二維碼
<html>
<head>
<title>二維碼入門小demo</title>
<!--1.引入js 2. 創建一個img標簽 用來存盤顯示二維碼的圖片 3.創建js物件 4.設定js物件的配置項-->
<script src="qrious.js"> </script>
</head>
<body>
<img id="myqrious" >
</body>
<script>
var qrious = new QRious({
element:document.getElementById("myqrious"),// 指定的是圖片所在的DOM物件
size:250,//指定圖片的像素大小
level:'H',//指定二維碼的容錯級別(H:可以恢復30%的資料)
value:'weixin://wxpay/bizpayurl?pr=qJVBnYYzz'//指定二維碼圖片代表的真正的值
})
</script>
</html>
2、打開pay.html,顯示一個二維碼,微信掃碼支付

四、查詢支付狀態
1、控制層添加方法(controller)
/**
* 微信支付狀態查詢
* @param outtradeno:商戶訂單號,由微信服務器生成
* @return
*/
@GetMapping(value = "/status/query")
public Result queryStatus(String outtradeno){
//查詢微信支付狀態
Map map = weixinPayService.queryStatus(outtradeno);
return new Result(true, StatusCode.OK,"微信支付狀態查詢成功!",map);
}
2、應用層添加方法(service、serviceImpl)
/**
* 查詢微信支付狀態
* @param outtradeno:商戶訂單號,由微信服務器生成
* @return
*/
Map queryStatus(String outtradeno);
/**
* 查詢微信支付狀態
* @param outtradeno:商戶訂單號,由微信服務器生成
* @return
*/
@Override
public Map queryStatus(String outtradeno) {
try {
//遠程呼叫
//創建一個Map集合存放請求引數
Map<String, String> paramMap = new HashMap<>();
//添加資料
//應用ID
paramMap.put("appid", appid);
//商戶號
paramMap.put("mch_id", partner);
//隨機字串
paramMap.put("nonce_str", WXPayUtil.generateNonceStr());
//訂單號
paramMap.put("out_trade_no", outtradeno);
//簽名
//paramMap.put("sign","");
//Map轉為XML資料,可以自帶簽名
//將請求引數集合,轉為帶有簽名的XML資料格式
String xmlStr = WXPayUtil.generateSignedXml(paramMap, partnerkey);
//URL地址,微信查詢訂單介面鏈接
String url = "https://api.mch.weixin.qq.com/pay/orderquery";
//提交方式:HTTPS
//創建HttpClient物件,對url請求地址進行操作
HttpClient httpClient = new HttpClient(url);
//設定提交方式為HTTPS
httpClient.setHttps(true);
//提交引數,引數以XML資料格式提交
httpClient.setXmlParam(xmlStr);
//執行請求
//發送XML資料,使用post請求
httpClient.post();
//獲取回傳的資料,此時回傳的資料為XML資料格式
String content = httpClient.getContent();
//System.out.println("content:" + content);
//回傳資料轉成Map
Map<String, String> resultMap = WXPayUtil.xmlToMap(content);
return resultMap;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
3、瀏覽器輸入請求地址:http://localhost:18090/weixin/pay/status/query?outtradeno=198999
引數解釋:outtradeno:訂單號
{
"flag": true,
"code": 20000,
"message": "微信支付狀態查詢成功!",
"data": {
"nonce_str": "9FMEOJb0nhdJzGOQ",
"device_info": "",
"out_trade_no": "198999",
"trade_state": "NOTPAY",
"appid": "wx8397f8696b538317",
"total_fee": "101",
"sign": "1C86209F252D64254542EFC5481FD0D0",
"trade_state_desc": "訂單未支付",
"return_msg": "OK",
"result_code": "SUCCESS",
"mch_id": "1473426802",
"return_code": "SUCCESS"
}
}
因為上面測驗支付二維碼時候,我沒支付,所以查詢訂單支付狀態顯示“訂單未支付”,
五、支付結果回呼
1、控制層添加方法
/**
* 支付結果通知回呼方法
* @param request
* @return
*/
@RequestMapping(value = "/notify/url")
public String notifyurl(HttpServletRequest request) throws Exception {
//獲取網路輸入流,也就是網路輸入流格式的通知結果
ServletInputStream inputStream = request.getInputStream();
//創建一個OutputStream輸出流->輸入檔案
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
//定義緩沖區
byte[] buffer = new byte[1024];
//初始化一個資料長度
int len = 0;
//往緩沖區里讀檔案,資料長度 不等于-1說明有資料
while ((len = inputStream.read(buffer))!=-1){
//緩沖區中的資料 寫入到 輸出流物件中
//從0開始讀到長度最后一位
byteArrayOutputStream.write(buffer,0,len);
}
//將byteArrayOutputStream位元組流轉為位元組陣列
//這就是微信支付結果的位元組陣列
byte[] byteArray = byteArrayOutputStream.toByteArray();
//位元組陣列 轉為 xml字串
String xmlResult = new String(byteArray, "Utf-8");
System.out.println("xmlResult:\n"+xmlResult);
//xml字串 轉為 Map
Map<String, String> resultMap = WXPayUtil.xmlToMap(xmlResult);
System.out.println("resultMap:\n"+resultMap);
//回傳結果
String result = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
return result;
}
2、組態檔中修改回呼地址為動態呼叫
#微信支付資訊配置
weixin:
#應用ID
appid: wx8397f8696b538317
#商戶號
partner: 1473426802
#密鑰
partnerkey: T6m9iK73b0kn9g5v426MKfHQH7X8rKwb
#支付回呼地址 通知地址
#外網域名:http://19453k43d4.51vip.biz:32375
notifyurl: http://19453k43d4.51vip.biz:32375/weixin/pay/notify/url
3、創建二維碼
瀏覽器輸入請求:http://19453k43d4.51vip.biz:32375/weixin/pay//create/native?outtradeno=1999&totalfee=1
{
"flag": true,
"code": 20000,
"message": "創建二維碼預付訂單成功!",
"data": {
"nonce_str": "pUPI4MeBq1ikJbOJ",
"code_url": "weixin://wxpay/bizpayurl?pr=qJVBnYYzd",
"appid": "wx8397f8696b538317",
"sign": "7BCED5501AD892D5490A109DADE3383F",
"trade_type": "NATIVE",
"return_msg": "OK",
"result_code": "SUCCESS",
"mch_id": "1473426802",
"return_code": "SUCCESS",
"prepay_id": "wx011403161517455f3f2880f7e02e920000"
}
}
4、修改pay.html中的value為上步的code_url
<html>
<head>
<title>二維碼入門小demo</title>
<!--1.引入js 2. 創建一個img標簽 用來存盤顯示二維碼的圖片 3.創建js物件 4.設定js物件的配置項-->
<script src="qrious.js"> </script>
</head>
<body>
<img id="myqrious" >
</body>
<script>
var qrious = new QRious({
element:document.getElementById("myqrious"),// 指定的是圖片所在的DOM物件
size:250,//指定圖片的像素大小
level:'H',//指定二維碼的容錯級別(H:可以恢復30%的資料)
value:'weixin://wxpay/bizpayurl?pr=qJVBnYYzd'//指定二維碼圖片代表的真正的值
})
</script>
</html>
5、雙擊打開pay.html,生成一個二維碼,掃碼支付后;
瀏覽器輸入請求地址:http://19453k43d4.51vip.biz:32375/weixin/pay/status/query?outtradeno=1999
{
"flag": true,
"code": 20000,
"message": "微信支付狀態查詢成功!",
"data": {
"transaction_id": "4200000517202002187004756359",
"nonce_str": "ZxVmHMCc1mVr8rxR",
"trade_state": "SUCCESS",
"bank_type": "OTHERS",
"openid": "oNpSGwaqHv74waDX0BLPNrFiYIUo",
"sign": "3DC6A5346C914DE745DBBB7796039BC1",
"return_msg": "OK",
"fee_type": "CNY",
"mch_id": "1473426802",
"cash_fee": "1",
"out_trade_no": "1999",
"cash_fee_type": "CNY",
"appid": "wx8397f8696b538317",
"total_fee": "1",
"trade_state_desc": "支付成功",
"trade_type": "NATIVE",
"result_code": "SUCCESS",
"attach": "",
"time_end": "20200218153715",
"is_subscribe": "N",
"return_code": "SUCCESS"
}
}
6、查看控制臺輸出,有一個支付結果通知

六、MQ訊息中間件監聽
微信服務回傳的支付狀態,發送給MQ訊息中間件
1、在支付系統中匯入依賴
<!--加入ampq-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
2、組態檔application.yml中添加資訊
rabbitmq:
host: 服務器地址
port: 埠
username: 用戶名
password: 密碼
#位置支付交換機和佇列
mq:
pay:
exchange:
order: exchange.order
queue:
order: queue.order
routing:
key: queue.order
實際開發中登錄“服務器地址:15672”手動創建交換機和佇列
3、創建佇列系結交換機配置
/**
* @Author TeaBowl
* @Date 2021/2/3 11:26
* @Version 1.0
*/
@Configuration
public class MQConfig {
/**
* 讀取組態檔中的資訊
*/
@Autowired
private Environment env;
/**
* 創建佇列
* @return
*/
@Bean
public Queue OrderQueue (){
//引數:佇列名
return new Queue(env.getProperty("mq.pay.queue.order"));
}
/**
* 創建交換機
* @return
*/
@Bean
public Exchange OrderExchange (){
//引數:交換機名、是否持久化、是否自動洗掉
return new DirectExchange(env.getProperty("mq.pay.exchange.order"),true,false);
}
/**
* 佇列系結交換機
* @param orderQueue:佇列
* @param orderExchange:交換機
* @return
*/
@Bean
public Binding orderQueueExchange(Queue orderQueue,Exchange orderExchange){
//佇列系結交換機
return BindingBuilder.bind(orderQueue).to(orderExchange).with(env.getProperty("mq.pay.routing.key")).noargs();
}
}
4、controller中注入MQ操作物件
//注入MQ操作物件
@Autowired
private RabbitTemplate rabbitTemplate;
5、修改controller中支付結果通知回呼方法
/**
* 支付結果通知回呼方法
* @param request
* @return
*/
@RequestMapping(value = "/notify/url")
public String notifyurl(HttpServletRequest request) throws Exception {
//獲取網路輸入流,也就是網路輸入流格式的通知結果
ServletInputStream inputStream = request.getInputStream();
//創建一個OutputStream輸出流->輸入檔案
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
//定義緩沖區
byte[] buffer = new byte[1024];
//初始化一個資料長度
int len = 0;
//往緩沖區里讀檔案,資料長度 不等于-1說明有資料
while ((len = inputStream.read(buffer))!=-1){
//緩沖區中的資料 寫入到 輸出流物件中
//從0開始讀到長度最后一位
byteArrayOutputStream.write(buffer,0,len);
}
//將byteArrayOutputStream位元組流轉為位元組陣列
//這就是微信支付結果的位元組陣列
byte[] byteArray = byteArrayOutputStream.toByteArray();
//位元組陣列 轉為 xml字串
String xmlResult = new String(byteArray, "Utf-8");
System.out.println("xmlResult:\n"+xmlResult);
//xml字串 轉為 Map
Map<String, String> resultMap = WXPayUtil.xmlToMap(xmlResult);
System.out.println("resultMap:\n"+resultMap);
//發送支付結果給MQ
rabbitTemplate.convertAndSend("exchange.order","queue.order", JSON.toJSONString(resultMap));
//回傳結果
String result = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
return result;
}
訂單系統監聽MQ訊息
1、在訂單系統中匯入依賴
<!--加入ampq-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
2、組態檔application.yml中添加資訊
rabbitmq:
host: 服務器地址
port: 埠
username: 用戶名
password: 密碼
#位置支付交換機和佇列
mq:
pay:
#交換機
exchange:
order: exchange.order
#佇列
queue:
order: queue.order
routing:
key: queue.order
3、創建監聽MQ資訊配置
/**
* @Author TeaBowl
* @Date 2021/2/3 12:02
* @Version 1.0
* 監聽MQ資訊
*/
@Component
@RabbitListener(queues = "${mq.pay.queue.order}") //監聽佇列
public class OrderMessageListener {
/**
* 支付結果監聽
* @param message:支付結果
*/
@RabbitHandler
public void getMeaaage(String message){
//支付結果回呼通知,Json格式轉為Map
Map<String, String> resultMap = JSON.parseObject(message, Map.class);
System.out.println("監聽到的支付結果資訊:\n"+resultMap);
//從MQ訊息中間件中獲取 支付操作的通信狀態
//通信標識:return_code 狀態:SUCCESS/FAIL
String return_code = resultMap.get("return_code");
//如果支付操作的通信成功
if (return_code.equals("SUCCESS")){
//從MQ訊息中間件中獲取 支付操作的業務結果
//業務結果:result_code 狀態:SUCCESS/FAIL
String result_code = resultMap.get("result_code");
//商戶訂單號:out_trade_no
String out_trade_no = resultMap.get("out_trade_no");
//如果支付操作的業務結果為成功 修改訂單狀態
if (result_code.equals("SUCCESS")){
//從MQ訊息中間件中獲取資訊
//微信支付訂單號:transaction_id
String transaction_id = resultMap.get("transaction_id");
}else {
//如果支付失敗,關閉支付,取消訂單,回滾庫存
}
}
}
}
4、創建二維碼實
a. 瀏覽器請求地址:http://19453k43d4.51vip.biz:32375/weixin/pay/create/native?outtradeno=1769&totalfee=1
{
"flag": true,
"code": 20000,
"message": "創建二維碼預付訂單成功!",
"data": {
"nonce_str": "QlLrzt4vdsKNck1d",
"code_url": "weixin://wxpay/bizpayurl?pr=MjNPE2Dzz",
"appid": "wx8397f8696b538317",
"sign": "CD80E7E68014CF70C36535E231E0FF14",
"trade_type": "NATIVE",
"return_msg": "OK",
"result_code": "SUCCESS",
"mch_id": "1473426802",
"return_code": "SUCCESS",
"prepay_id": "wx03125509016851a5fca270399354320000"
}
}
b. 修改pay.html中的支付地址為code_url地址
<html>
<head>
<title>二維碼入門小demo</title>
<!--1.引入js
2. 創建一個img標簽 用來存盤顯示二維碼的圖片
3.創建js物件 4.設定js物件的配置項-->
<script src="qrious.js"> </script>
</head>
<body>
<img id="myqrious" >
</body>
<script>
var qrious = new QRious({
element:document.getElementById("myqrious"),// 指定的是圖片所在的DOM物件
size:250,//指定圖片的像素大小
level:'H',//指定二維碼的容錯級別(H:可以恢復30%的資料)
value:'weixin://wxpay/bizpayurl?pr=MjNPE2Dzz'//指定二維碼圖片代表的真正的值
})
</script>
</html>
c. 二維碼圖片

5、掃碼支付后,查看瀏覽器RabbitMQ后臺:“服務器地址:15672/#/queues”
查看訊息:


七、修改訂單狀態
1、在訂單工程中進行修改
應用層介面(OrderService)中,添加介面
/**
* 修改訂單狀態
* @param outtradeno:用戶訂單號
* @param paytime:支付時間
* @param transactionid:交易流水號
*/
void updataStatus(String outtradeno,String paytime,String transactionid) throws Exception;
應用層介面實作類(OrderServiceImpl)中,添加方法實作
/**
* 修改訂單狀態
* @param outtradeno:用戶訂單號
* @param paytime:支付時間
* @param transactionid:交易流水號
*/
@Override
public void updataStatus(String outtradeno, String paytime, String transactionid) throws Exception {
//使用時間轉換工具,轉換時間格式
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
Date payTimeInfo = simpleDateFormat.parse(paytime);
//根據用戶訂單號,查詢訂單 order訂單資訊封裝類
Order order = orderMapper.selectByPrimaryKey(outtradeno);
//修改訂單資訊
//設定交易時間
order.setPayTime(payTimeInfo);
//設定支付狀態:0未支付,1已支付,2支付失敗
order.setPayStatus("1");
//設定交易流水號
order.setTransactionId(transactionid);
//資訊更新到資料庫訂單表中
orderMapper.updateByPrimaryKeySelective(order);
}
2、洗掉訂單,回滾庫存
在訂單支付后,如果支付失敗,訂單資料表中的訂單資訊就沒必要保留了,商品庫存也需要回滾到原來的數量;
為了方便二次查詢,訂單并不是真的洗掉了,而是修改了狀態,這叫邏輯洗掉,
應用層介面(OrderService)中,添加介面
/**
* 支付失敗,洗掉[修改狀態]訂單,回滾庫存
* @param outtradeno:用戶訂單號
*/
void deleteOrder(String outtradeno);
應用層介面實作類(OrderServiceImpl)中,添加方法實作
/**
* 支付失敗,洗掉[修改狀態]訂單,回滾庫存
* @param outtradeno:用戶訂單號
*/
@Override
public void deleteOrder(String outtradeno) {
//根據用戶訂單號,查詢訂單 order訂單資訊封裝類
Order order = orderMapper.selectByPrimaryKey(outtradeno);
//修改狀態
//設定更新時間
order.setUpdateTime(new Date());
//設定支付狀態:0未支付,1已支付,2支付失敗
order.setPayStatus("2");
//資訊更新到資料庫訂單表中
orderMapper.updateByPrimaryKeySelective(order);
//回滾庫存->呼叫商品微服務 暫略
}
3、對接監聽
修改MQ資訊監聽配置OrderMessageListener
注入訂單應用的操作物件
@Autowired
private OrderService orderService;
修改支付結果監聽方法
/**
* 支付結果監聽
* @param message:支付結果
*/
@RabbitHandler
public void getMeaaage(String message) throws Exception {
//支付結果回呼通知,Json格式轉為Map
Map<String, String> resultMap = JSON.parseObject(message, Map.class);
System.out.println("監聽到的支付結果資訊:\n"+resultMap);
//從MQ訊息中間件中獲取 支付操作的通信狀態
//通信標識:return_code 狀態:SUCCESS/FAIL
String return_code = resultMap.get("return_code");
//如果支付操作的通信成功
if (return_code.equals("SUCCESS")){
//從MQ訊息中間件中獲取 支付操作的業務結果
//業務結果:result_code 狀態:SUCCESS/FAIL
String result_code = resultMap.get("result_code");
//商戶訂單號:out_trade_no
String out_trade_no = resultMap.get("out_trade_no");
//如果支付操作的業務結果為成功 修改訂單狀態
if (result_code.equals("SUCCESS")){
//修改訂單狀態
//引數:用戶訂單號、支付完成時間、交易流水號
orderService.updataStatus(out_trade_no,resultMap.get("time_end"),resultMap.get("transaction_id"));
}else {
//如果支付失敗,關閉支付,取消訂單,回滾庫存
//關閉支付 暫略
//支付失敗,洗掉[修改狀態]訂單,回滾庫存
orderService.deleteOrder(out_trade_no);
}
}
}
4、測驗
創建二維碼資訊,瀏覽器輸入請求:http://localhost:18090/weixin/pay/create/native?outtradeno=1355321180126445568&totalfee=1
{
"flag": true,
"code": 20000,
"message": "創建二維碼預付訂單成功!",
"data": {
"nonce_str": "Dc7zjYlcdvPxienu",
"code_url": "weixin://wxpay/bizpayurl?pr=s2V4HM3zz",
"appid": "wx8397f8696b538317",
"sign": "7D75E71E44AD669496C14684A66D8501",
"trade_type": "NATIVE",
"return_msg": "OK",
"result_code": "SUCCESS",
"mch_id": "1473426802",
"return_code": "SUCCESS",
"prepay_id": "wx04014823728571d0a1350cf856a41e0000"
}
}
修改pay.html的支付地址
<html>
<head>
<title>二維碼入門小demo</title>
<!--1.引入js
2. 創建一個img標簽 用來存盤顯示二維碼的圖片
3.創建js物件 4.設定js物件的配置項-->
<script src="qrious.js"> </script>
</head>
<body>
<img id="myqrious" >
</body>
<script>
var qrious = new QRious({
element:document.getElementById("myqrious"),// 指定的是圖片所在的DOM物件
size:250,//指定圖片的像素大小
level:'H',//指定二維碼的容錯級別(H:可以恢復30%的資料)
value:'weixin://wxpay/bizpayurl?pr=s2V4HM3zz'//指定二維碼圖片代表的真正的值
})
</script>
</html>
雙擊pay.html生成二維碼

掃碼支付成功后,已經監聽到了資訊

資料庫中的訂單表,也根據監聽到的訊息進行了改變


轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/256364.html
標籤:java
上一篇:資料結構-快速排序
下一篇:Java多執行緒游戲仿真實體分享
