微信支付申通過後,可調用「獲取用戶共享收貨地址」接口。用戶點擊按鈕授權後,直接將微信儲存的收貨地址填入訂單頁,省去手動輸入,大幅提升轉化率。注意:必須由用戶主動點擊觸發,不可自動獲取(隱私保護)。
用戶點擊結算 → 跳轉微信 OAuth2 頁面:
https://open.weixin.qq.com/connect/oauth2/authorize?
appid=APPID
&redirect_uri=URL_ENCODED_訂單頁地址
&response_type=code
&scope=snsapi_base
&state=任意字符串
#wechat_redirect
redirect_uri 必須 URL 編碼scope=snsapi_base 靜默授權(不彈窗),僅獲取 openidstate 可攜帶業務參數(如訂單 ID)微信重定向至 redirect_uri?code=CODE,服務端用 code 換取 access_token:
<?php
$code = $_GET['code'];
$url = "https://api.weixin.qq.com/sns/oauth2/access_token?"
. "appid=APPID&secret=APP_SECRET&code={$code}&grant_type=authorization_code";
$response = file_get_contents($url); // 或 curl
$data = json_decode($response, true);
if (isset($data['errcode'])) {
// 錯誤處理:code 過期、已使用、頻率限制等
exit('授權失敗: ' . $data['errmsg']);
}
$accessToken = $data['access_token'];
$openid = $data['openid'];
// 注意:此 access_token 僅用於獲取用戶信息,非基礎接口 access_token
?>
<?php
// 簽名算法:SHA1(accesstoken=...&appid=...&noncestr=...×tamp=...&url=...)
// 參與簽名的 url 必須是當前頁面完整 URL(不含 # 及後內容)
$timestamp = time();
$nonceStr = md5(uniqid(mt_rand(), true)); // 32位隨機串
$url = 'https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
$string = "accesstoken={$accessToken}"
. "&appid=APPID"
. "&noncestr={$nonceStr}"
. "×tamp={$timestamp}"
. "&url={$url}";
$addrSign = sha1($string);
// 傳遞給前端的配置
$wxConfig = [
'appId' => 'APPID',
'scope' => 'jsapi_address',
'signType' => 'sha1',
'addrSign' => $addrSign,
'timeStamp' => "$timestamp", // JS 需字符串
'nonceStr' => $nonceStr
];
?>
<!-- 頁面引入微信 JS-SDK -->
<script src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
<button id="getAddressBtn">獲取微信收貨地址</button>
<div id="address_info"></div>
<script>
document.getElementById('getAddressBtn').onclick = function() {
// 配置參數來自 PHP 渲染
wx.config({
appId: '',
timestamp: ,
nonceStr: '',
signature: '',
jsApiList: ['editAddress']
});
wx.ready(function() {
wx.editAddress({
scope: 'jsapi_address',
signType: 'sha1',
addrSign: '',
timeStamp: '',
nonceStr: '',
success: function(res) {
// res: {userName, telNumber, proviceFirstStageName, addressCitySecondStageName, addressCountiesThirdStageName, addressDetailInfo, ...}
const addr = `${res.proviceFirstStageName}${res.addressCitySecondStageName}${res.addressCountiesThirdStageName}${res.addressDetailInfo}`;
document.getElementById('address_info').innerHTML =
`<b>收件人:${res.userName}</b> <b>${res.telNumber}</b><br>收貨地址:${addr}`;
// 可選:AJAX 保存至後端數據庫
saveAddressToBackend(res);
},
fail: function(res) {
alert('獲取失敗:' + res.errMsg);
}
});
});
};
function saveAddressToBackend(addrData) {
fetch('/api/save-wx-address', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify(addrData)
});
}
</script>
| 風險點 | 解決方案 |
|---|---|
| 微信重複回調導致 code 失效 | 用 Redis/setnx 鎖住 code,或記錄已用 code 10 分鐘內去重 |
| 簽名驗證失敗 | 確保 url 為當前頁完整 URL(含查詢參數,不含 #hash),參數名大小寫、排序完全一致 |
| JS-SDK 配置無效 | 確認微信公眾平台「JS 接口安全域名」已配置,且引入 jweixin.js |
| 用戶拒絕授權 | 捕獲 fail 回調,友好提示引導手動填寫 |
editAddress 讓用戶選擇其他地址微信共享地址功能通過 OAuth2 靜默授權獲取 openid,結合 JS-SDK 簽名調用 wx.editAddress 實現。核心難點在於簽名參數構造(特別是 url 計算)與微信頻控處理。正確實現可顯著減少用戶輸入成本,是電商類小程序/公眾號支付場景的標配功能。