2020微信支付v3版本對接詳細流程
都0202年,我似乎翻遍了百度,都沒找到最新版微信支付v3的對接相關的詳細部落格,我都納悶了,只有自己摸索。還有就是竟然還有人用一些v3對接的假程式碼,來騙積分,我真的服了,感同身受,以下是我對接的過程,免費分享給大家,歡迎小夥伴一起探討。
~首先吐槽下騰訊的文件,自己根據文件看,對於沒有對接經驗的來說,根本看不懂,什麼亂起八糟的,心裡一萬個草泥馬。
其次,特別是對接的資料加密解密,傳遞格式那些是最讓人想瘋的東西。所以已經有大佬把這些基礎的資料對接做了整合,就在gitee上,ijPay。ijPay我們只需要關注的只有給物件設定引數,發起請求,處理響應資料,就完事,很方便。此篇文章就基於此展開對接的講解。
1.gitee開源支付對接原始碼(ijpay)地址
2.ijpay官方文件地址
ps:ijpay中可以自己讀程式碼,再根據騰訊的文件,摸索(ijpay註釋較少).也可以花錢讓ijpay的作者給你線上幫助
整體對接流程概括如下
- 肯定是先下載ijpay原始碼到本地
ijpay整合了許多支付,這裡我們只講解微信支付v3的對接,那麼我自己是另外新建了一個springboot專案,然後把原始碼裡面的微信v3支付的程式碼拷貝到新專案裡面做測試的,缺什麼依賴,根據報紅的提示,自己引入,這裡不做詳細說明.
2.【 微信支付v3版本證照下載】和【配置配置檔案】
這裡先說下公眾號和商戶平臺的關係,公眾號的支付依附於商戶平臺,所以公眾號和商戶平臺要做關聯處理:
登陸商戶平臺–>產品中心–>AppID賬號管理
關聯過程,自行百度咯,不做過多講解
1).證照的下載
登陸商戶平臺–>賬戶中心–>api安全–>API安全
然後生成證照,最終會生成3個檔案
生成流程:
自行檢視官方文件
2).證照copy到【新專案】的資料夾中
我這邊是放在了src\main\resources\cert目錄下
3).設定api祕鑰和apiv3祕鑰
登陸商戶平臺–>賬戶中心–>api安全–>設定api祕鑰/設定apiv3祕鑰
儲存好,後面要用到
4).設定配置檔案 wxpay_v3.properties
為了方便你們copy
#服務商/直連商戶平臺 關聯的 公眾號appid
v3.appId=?
#祕鑰
v3.keyPath=?
#CA證照 格式.pem
v3.certPath=?
#CA證照 格式.p12
v3.certP12Path=?
#平臺證照路徑
v3.platformCertPath=?
#服務商id/商戶id
v3.mchId=?
#自定義 apiv3 祕鑰
v3.apiKey3=?
#自定義 api 祕鑰
v3.apiKey=?
#專案域名
v3.domain=?
ps:這裡講下配置檔案的引數如果獲取
appId:登陸微信公眾平臺–>開發–>基本配置–>開發者ID(AppID)
keyPath: 對應apiclient_key.pem所在路徑
certPath: 對應apiclient_cert.pem所在路徑
certP12Path: 對應apiclient_cert.p12所在路徑
platformCertPath: 【平臺證照】訪問v3支付提供的介面獲取,下面會講
mchId: 登陸商戶平臺–>賬戶中心–>商戶資訊–>微信支付商戶號
apiKey3: 參考上面的設定api祕鑰和apiv3祕鑰
apiKey: 參考上面的設定api祕鑰和apiv3祕鑰
domain: 專案域名
關於專案域名,我這邊用的natapp做的本地內網對映,可以直接在本地做支付測試,因為natapp代理的域名都是備案了的,非常方便,這裡推薦下,不然去伺服器上測試,太麻煩了.
natapp官方連結地址 自己看natapp的文件或者幫助,這裡不做過多講解
5).獲取平臺證照,也就是上圖的platformCert.pem檔案
啟動服務,本地訪問介面: localhost/v3/get
這裡會請求騰訊介面,拿到平臺證照,並儲存到配置檔案所配置的路徑下(注意檔名在配置檔案一開始就要配好)
配置檔案到這裡就配好了
- 支付對接(直連商戶模式)
ps:v3微信支付官方文件
基礎支付–>【直連模式】和【服務商模式】的區別?
1.介面對接的角度來說,就訪問的地址不同,和傳遞的引數有差別,實現的效果是一樣的,響應的引數的處理方式是一樣的
2.從現實邏輯來講,
直連模式是公眾號直接對接商戶平臺,發起支付,
關係為: 公眾號–>商戶平臺
服務商模式是基於直連,商戶平臺又把支付授權給服務商,
關係為: 公眾號–>商戶平臺–>服務商
用服務商模式,貌似有返點啥的,沒有深入研究,有興趣自行百度,兩者對接方式差不多,只是傳遞的引數有些許差別.但相應引數的處理是一樣的,此篇部落格只講直連方式,服務商模式可以自行舉一反三.
一.電腦生成二維碼,手機掃碼支付(nativePay)
用大佬的寫好的程式碼,根本不用關心什麼加密解密什麼的,配置檔案配好,調介面就完事了QAQ
不同的支付的應用場景:
1.nativePay(電腦生成二維碼,手機掃碼支付)
1.jsApiPay(微信自帶瀏覽器中或者說公眾號裡面,喚起微信支付)
1.h5Pay(手機普通瀏覽器中,喚起微信支付)
注意:
1.傳遞引數根據官方文件來看,ijpay原始碼可能在服務商和直連商戶兩種模式的程式碼只提供了其一,靈活斟酌
2.登陸商戶平臺–>產品中心–>我的產品–>開通nativePay
其它的支付看需要開通,具體操作,百度啊QAQ,後面就不提示開通支付這個事情了,自己可以先提前開通了都
大概流程:
請求介面,拿到二維碼生成連結–>用生成二維碼的js生成支付碼–>掃碼支付
官方文件:
響應引數示例
{
"code_url": "weixin://wxpay/bizpayurl/up?pr=NwY5Mz9&groupid=00"
}
1).發起支付請求,獲取二維碼連結地址
請求介面(com.example.wxpay.controller.wxpay.WxPayV3Controller#nativePay):
http://localhost/v3/nativePay
2).響應引數
{
"code_url": "weixin://wxpay/bizpayurl/up?pr=NwY5Mz9&groupid=00"
}
3).生成二維碼(qrcode.min.js)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ko" lang="ko">
<head>
<title>Javascript 二維碼生成庫:QRCode</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no" />
<script type="text/javascript" src="//cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
<script type="text/javascript" src="//static.runoob.com/assets/qrcode/qrcode.min.js"></script>
</head>
<body>
<input id="text" type="text" value="http://www.runoob.com" style="width:80%" /><br />
<div id="qrcode" style="width:100px; height:100px; margin-top:15px;"></div>
<script type="text/javascript">
var qrcode = new QRCode(document.getElementById("qrcode"), {
width : 100,
height : 100
});
function makeCode () {
var elText = document.getElementById("text");
if (!elText.value) {
alert("Input a text");
elText.focus();
return;
}
qrcode.makeCode(elText.value);
}
makeCode();
$("#text").
on("blur", function () {
makeCode();
}).
on("keydown", function (e) {
if (e.keyCode == 13) {
makeCode();
}
});
</script>
</body>
</html>
支付成功後會有一個回撥通知,在一開始傳遞的引數裡面
ijpay裡面也是寫好了的
通知的對接自行看ijpay列印的引數,做自己的邏輯處理
com.example.wxpay.controller.wxpay.WxPayV3Controller#payNotify
二.微信自帶瀏覽器中或者說公眾號裡面,喚起微信支付(jsApiPay)
注意:
配置jsApiPay的支付目錄,我配置的 本地對映的代理域名+’/’
登陸直連商戶平臺–>產品中心–>開發配置–>支付配置–>JSAPI支付
大概流程:
拿到微信使用者的openId–>呼叫ijpay介面(傳入openId)–>響應 喚起微信支付的json資料–>基於響應json,前端js二次請求騰訊介面–>喚起支付
官方文件(jsApiPay下單)
官方文件(jsApiPay喚起支付)
1).拿到微信使用者的openId
參考自部落格:java-微信公眾號選單跳轉網頁獲取openid
就拿openId這一步就挺麻煩
大概流程:
公眾號選單點選–>自定義請求介面1(請求騰訊拿到code)–>重定向自到定義介面2(根據code請求騰訊拿到openId)–>重定向到自定義html頁面,拿到微信使用者openId,初始化呼叫上述介面…
直接上自定義介面的程式碼
WxGZHController.java
package com.example.wxpay.controller.wxpay;
import com.alibaba.fastjson.JSONObject;
import com.example.wxpay.domain.WxPayV3Bean;
import com.ijpay.core.kit.HttpKit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import javax.annotation.Resource;
/**
* @ClassName WxGZHController
* 微信公眾號對接
* @Author ZhangYong
* @Date 2020/11/10 15:46
* @Version 1.0
**/
@RequestMapping("/wxgzh")
@Controller
public class WxGZHController {
private static final Logger log = LoggerFactory.getLogger(WxGZHController.class);
@Resource
WxPayV3Bean wxPayV3Bean;
private static final String serverSuffixUrl = "/wxgzh/weixinoauth";//查詢到code後重定向的目錄
private static final String stateCashout = "cashOut";
private static final String weixinGzhSecret = "785yuiyddsc76f115cd3fa86746";//開發者密碼(AppSecret)
private static final String jsApiPayUrl = "/jsApiPay.html";//使用openId的html頁面
/*獲取微信瀏覽器使用者openId,並跳轉頁面傳遞openId*/
//1.先查詢code
@RequestMapping("/redirecttocashout")
public String redirectToCashout() {
log.info("準備獲取code");
return "redirect:https://open.weixin.qq.com/connect/oauth2/authorize?appid="
+ wxPayV3Bean.getAppId() + "&redirect_uri=" + wxPayV3Bean.getDomain()
+"/"+serverSuffixUrl+"?response_type=code&scope=snsapi_base&state=" + stateCashout + "#wechat_redirect";
}
//2.根據code獲取openId
@RequestMapping("/weixinoauth")
public String weixinOauth(@RequestParam String code,@RequestParam String state) throws Exception {
log.info("獲取code:{}",code);
String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid="
+ wxPayV3Bean.getAppId() + "&secret=" + weixinGzhSecret + "&code=" + code + "&grant_type=authorization_code";
String res = HttpKit.getDelegate().get(url, null);
System.out.println(res);
String openid = JSONObject.parseObject(res).getString("openid");
log.info("根據code查詢得到openId:{}",openid);
String redirect = "";
switch (state){
case stateCashout:
redirect =jsApiPayUrl + "?openId=" + openid;
break;
}
log.info("準備調起jsApi支付,url:{}",redirect);
return "redirect:" + redirect;//重定向到jsApiPay.html並傳遞openId
}
}
jsApiPay.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>jsApi支付測試</title>
<script src="./js/jquery-3.3.1.min.js"></script>
<script src="./js/vue.min.js"></script>
<script src="./js/http.js"></script>
</head>
<body>
<script>
new Vue({
el:'app',
data(){
return {
callPayParam:{
appId:'',
timeStamp:'',
nonceStr:'',
package:'',
signType:'RSA',
paySign:'',
}
}
},
methods:{
prePay(openId){
http.get('/v3/jsApiPay?openId='+openId,{},res=>{
console.log(res)
//alert(res)
this.callPayParam = JSON.parse(res)
this.onBridgeReady()//喚起支付
})
},
onBridgeReady() {
alert(this.callPayParam)
alert(this.callPayParam.appId)
WeixinJSBridge.invoke('getBrandWCPayRequest', {
"appId": this.callPayParam.appId,//公眾號名稱,由商戶傳入
"timeStamp": this.callPayParam.timeStamp,//時間戳,自1970年以來的秒數
"nonceStr": this.callPayParam.nonceStr,//隨機串
"package": this.callPayParam.package,//預支付返回資料
"signType": this.callPayParam.signType,//微信簽名方式:
"paySign":this.callPayParam.paySign //微信簽名
},
function(res) {
if (res.err_msg == "get_brand_wcpay_request:ok") {
// 使用以上方式判斷前端返回,微信團隊鄭重提示:
//res.err_msg將在使用者支付成功後返回ok,但並不保證它絕對可靠。
}
});
}
},
mounted() {
let openId = getQueryVariable('openId')
console.log('openId:'+openId)
this.prePay(openId)
}
})
function onBridgeReady() {
WeixinJSBridge.invoke('getBrandWCPayRequest', {
"appId": "wx2421b1c4370ec43b",
//公眾號名稱,由商戶傳入
"timeStamp": "1395712654",
//時間戳,自1970年以來的秒數
"nonceStr": "e61463f8efa94090b1f366cccfbbb444",
//隨機串
"package": "prepay_id=up_wx21201855730335ac86f8c43d1889123400",
"signType": "RSA",
//微信簽名方式:
"paySign": "oR9d8PuhnIc+YZ8cBHFCwfgpaK9gd7vaRvkYD7rthRAZ\/X+QBhcCYL21N7cHCTUxbQ+EAt6Uy+lwSN22f5YZvI45MLko8Pfso0jm46v5hqcVwrk6uddkGuT+Cdvu4WBqDzaDjnNa5UK3GfE1Wfl2gHxIIY5lLdUgWFts17D4WuolLLkiFZV+JSHMvH7eaLdT9N5GBovBwu5yYKUR7skR8Fu+LozcSqQixnlEZUfyE55feLOQTUYzLmR9pNtPbPsu6WVhbNHMS3Ss2+AehHvz+n64GDmXxbX++IOBvm2olHu3PsOUGRwhudhVf7UcGcunXt8cqNjKNqZLhLw4jq\/xDg==" //微信簽名
},
function(res) {
if (res.err_msg == "get_brand_wcpay_request:ok") {
// 使用以上方式判斷前端返回,微信團隊鄭重提示:
//res.err_msg將在使用者支付成功後返回ok,但並不保證它絕對可靠。
}
});
}
</script>
</body>
</html>
公眾號選單配置
請求的介面為
http://域名/wxgzh/redirecttocashout
對應控制器:com.example.wxpay.controller.wxpay.WxGZHController#redirectToCashout
開發者密碼(AppSecret)
公眾號後臺–>開發–>基本配置–>開發者密碼(AppSecret)
公眾號網頁授權設定
參考上述的參考部落格↑↑
通知處理同上
三.手機普通瀏覽器,喚起微信支付(h5Pay)
後續補全
ps:以上皆為自己的對接經驗,有理解的不夠深刻的地方,多多包涵.如果部落格還有不詳細或者錯誤的地方,歡迎評論告訴我
相關文章
- 申請微信支付詳細流程(最新2018)
- Go語言對接微信支付與退款全流程指南Go
- Java中的微信支付(1):API V3版本簽名詳解JavaAPI
- JAVA版微信支付V3—JSAPI支付JavaJSAPI
- 在App中對接微信和支付寶APP
- 微信支付V3 Java jsApi 掃碼支付JavaJSAPI
- Core3.1 微信v3 JSAPI支付JSAPI
- 移動支付新時代——低程式碼如何對接支付寶和微信支付
- 微信支付 V3 RSA 加簽踩坑
- PHP微信支付類V3介面PHP
- Core3.1 微信v3 JSAPI支付 退款JSAPI
- 關於建行龍支付的聚合支付微信,支付寶 對接PC和H5H5
- 微信小程式的支付流程微信小程式
- 【C#版本】微信公眾號模板訊息對接(二)(圖文詳解)C#
- 微信app支付 java後臺接AndroidAPPJavaAndroid
- 微信支付小微商戶V3版本介面使用libsodium擴充套件以及程式碼示例套件
- Java中的微信支付(3):API V3對微信伺服器響應進行簽名驗證JavaAPI伺服器
- 前端呼叫微信小程式的支付流程前端微信小程式
- 如何在Spring Boot專案中整合微信支付V3Spring Boot
- java如何對接企業微信Java
- 微信支付,支付寶支付
- 前端對接微信分享功能完全指南前端
- PHP對接微信掃碼登入PHP
- alertmanager對接企業微信,釘釘
- 對接Ping++支付
- PHP 對接 paypal 支付PHP
- PayPal支付對接phpPHP
- Django對接支付寶Alipay支付介面Django
- 微信和支付寶的支付流程,以及開發中遇到的坑?
- 支付寶、微信支付(.NET)
- java對接支付寶支付(手機網站支付)Java網站
- Java中的微信支付(2):API V3 微信平臺證照的獲取與重新整理JavaAPI
- 關於微信支付,支付寶支付
- 開通微信支付(微信商戶平臺賬戶)流程及所需資料
- 支付寶小程式對比微信小程式微信小程式
- 微信JSAPI支付JSAPI
- 微信App支付APP
- 對iOS端支付寶和微信支付程式碼進行整合iOS