暢購商城(十二):接入微信掃碼支付
阿新 • • 發佈:2020-09-11
> **好好學習,天天向上**
>
> 本文已收錄至我的Github倉庫[**DayDayUP**](https://github.com/RobodLee/DayDayUP):github.com/RobodLee/DayDayUP,歡迎Star
+ [暢購商城(一):環境搭建](https://blog.csdn.net/weixin_43461520/article/details/107095045)
+ [暢購商城(二):分散式檔案系統FastDFS](https://blog.csdn.net/weixin_43461520/article/details/107137843)
+ [暢購商城(三):商品管理](https://blog.csdn.net/weixin_43461520/article/details/107243543)
+ [暢購商城(四):Lua、OpenResty、Canal實現廣告快取與同步](https://blog.csdn.net/weixin_43461520/article/details/107348436)
+ [暢購商城(五):Elasticsearch實現商品搜尋](https://blog.csdn.net/weixin_43461520/article/details/107466286)
+ [暢購商城(六):商品搜尋](https://blog.csdn.net/weixin_43461520/article/details/107579868)
+ [暢購商城(七):Thymeleaf實現靜態頁](https://blog.csdn.net/weixin_43461520/article/details/107728072)
+ [暢購商城(八):微服務閘道器和JWT令牌](https://blog.csdn.net/weixin_43461520/article/details/107817503)
+ [暢購商城(九):Spring Security Oauth2](https://blog.csdn.net/weixin_43461520/article/details/108144023)
+ [暢購商城(十):購物車](https://blog.csdn.net/weixin_43461520/article/details/108268837)
+ [暢購商城(十一):訂單](https://blog.csdn.net/weixin_43461520/article/details/108319715)
+ [暢購商城(十二):接入微信支付](https://blog.csdn.net/weixin_43461520/article/details/108524375)
## 支付流程
![](https://gitee.com/RobodLee/image_store/raw/master/Java/暢購商城12:接入微信支付/支付流程.png)
為了實現支付的功能,這裡選擇接入微信支付。流程就是我們通過訂單系統下單,然後訂單系統呼叫支付系統去向微信支付的伺服器傳送請求,然後獲取二維碼返回給使用者,然後訂單系統就開始監聽MQ。使用者掃碼支付後,支付系統將支付狀態存進MQ中。訂單系統檢測到使用者已經付錢了,就將訂單設為已支付,然後存進MySQL中。可能會因為網路問題導致訂單系統獲取不到支付狀態,所以訂單系統會定時向微信支付伺服器傳送請求去查詢訂單狀態。
## 微信支付簡介
要想接入微信支付,就得有認證過的服務號,這個我沒有,所以申請不了。就用黑馬提供的賬號吧,我試了一下,可以用。
```properties
appid(公眾賬號ID):wx8397f8696b538317
mch_id(商戶號):1473426802
key(商戶金鑰):T6m9iK73b0kn9g5v426MKfHQH7X8rKwb
```
> 微信支付的開發文件:[https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_1](https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_1)
在這個官方的開發文件裡面介紹了微信支付相關的API並且提供了SDK。
![](https://gitee.com/RobodLee/image_store/raw/master/Java/暢購商城12:接入微信支付/微信支付sdk目錄結構.png)
這個SDK的內容不多,只有幾個類,我稍微介紹一下:
+ WXPayConfig:這是個抽象類,裡面有幾個方法,是用來獲取核心引數的,比如公眾號id,商戶號,金鑰等,所以在使用的時候要先去例項化這個類將幾個重要引數配置進去。
+ WXPay:和訂單相關的方法都封裝在這個類裡面,比如下單,查詢訂單,取消訂單等。裡面有個方法**fillRequestData()**,每次執行下單等操作的時候都會去呼叫這個方法將WXPayConfig中的幾個核心引數封裝到請求引數的Map集合裡。
+ WXPayRequest:這個是負責請求伺服器的,WXPay也都是通過呼叫這個類中的方法去請求伺服器的,執行相應方法的時候,會將WXPay傳過來的Map集合轉換成XML格式的字串,然後使用HttpClient向伺服器傳送請求。沒錯,微信支付是通過XML進行資料傳輸的。
+ WXPayUtil:這是個工具類,封裝了一些常用方法,比如Map轉XML,XML轉Map等。
在這個專案中用到的微信的Native支付,也就是掃碼支付,有兩種模式,我們用到的是模式二。
![](https://gitee.com/RobodLee/image_store/raw/master/Java/暢購商城12:接入微信支付/微信掃碼支付模式二時序圖.png)
首先在暢購的訂單系統中生成訂單,然後將一些必要的引數傳入到微信支付的後臺,然後就會產生一個預支付的訂單,將支付連結返回給我們,我們再根據支付連結生成二維碼傳給使用者。使用者掃碼支付後再將支付結果傳到我們的後臺,這樣整個支付的流程就結束了。
## 準備工作
介紹完了微信支付後,就來說一下專案中該怎麼去整合微信支付。視訊中用的是第三方的依賴,我用的是官方的。微信支付的SDK在Maven的遠端倉庫裡是沒有的,所以需要自己下載然後手動匯入。這裡面有兩個坑有必要說一下,前面不是提到**WXPayConfig**是個抽象類麼,那麼用的時候肯定得去繼承才能例項化吧。但是裡面的抽象方法都沒有許可權修飾符,所以預設是包訪問許可權,我們既然是Maven依賴這個SDK,那麼我們寫的程式碼自然不會和它在同一個包下,所以要先在這幾個抽象方法前面新增**public**修飾符。而且,微信提供的sdk文件裡還寫成了implements抽象類,真搞不懂微信怎麼會犯這種錯~~~
現在就可以將這個SDK新增到我們本地的Maven倉庫裡了,在解壓後的sdk的根目錄下執行`mvn install`命令。
![](https://gitee.com/RobodLee/image_store/raw/master/Java/暢購商城12:接入微信支付/mvninstallsdk.png)
當出現**BUILD SUCCESS**的字樣的時候,就說明已經成功新增到本地的Maven倉庫了。這時候第二個坑就來了,如果就這麼新增到我們的專案中就有可能會出現Maven依賴衝突:
![](https://gitee.com/RobodLee/image_store/raw/master/Java/暢購商城12:接入微信支付/maven依賴衝突.png)
可以看到,出現衝突的包是**slf4j-simple**,而微信支付sdk恰好依賴了這個包,所以在匯入微信支付的時候把這個依賴排除掉即可。
```xml
```
然後就可以建立支付的工程了。在changgou-service下建立一個Moudle名為**changgou-service-wechatpay**,然後**將微信支付的依賴新增到這個工程下**,啟動類沒啥好說的,配置檔案如下:
```yml
server:
port: 18090
spring:
application:
name: wechatpay
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
#微信支付資訊配置
wechat:
# 應用id
app_id: wx8397f8696b538317
# 商戶號id
mch_id: 1473426802
# 金鑰
key: T6m9iK73b0kn9g5v426MKfHQH7X8rKwb
# 支付回撥地址
notify_url: http://www.itcast.cn
```
這裡配置了appid,mch_id,key,notify_url這幾個引數,用的時候直接讀取就可以了。這樣支付微服務就搭建好了。
## 微信支付二維碼生成
新增一個Controller層的類WeChatPayController,然後再建立一個入口方法,因為二維碼支付叫做Native支付,所以這裡就起名為createNative了,接收一個Order引數,視訊中用的是Map接收引數。但是既然是建立訂單,直接用Order作為引數可讀性不是好很多嗎。
```java
//建立二維碼
@RequestMapping(value = "/create/native")
public Result createNative(@RequestBody Order order){