? ?最近要接入微信的收货地址共享接口,总是不成功,折腾了好几天,实在没办法网上搜到的帖子也是骂声一片。我把我碰到并解决问题的过程分享出来,希望能给微信的接口文档起到一个辅助作用,让后面进来的开发者能快速的接入,而不需要像我们一样苦逼的浪费好几天,甚至一周的青春。各种羞辱、谩骂的话就不说了,本人还算文明。
? ?如果你能搜到本贴,说明你已经碰到了各种 edit_address:fail ,那么请你仔细阅读我提供的操作步骤。
======================================
1. 请你仔细研读微信官方的接口文档,虽然写的不是特别好,但还是请一字不拉的读完,并理解。我个人的经验,仔细读过后,还是能理解的。
?
2. 请严格按照接口文档的说明来,不能自以为是的认为微信应该是怎么干的。他说大写,你就大写,他说小写,你就小写,乖乖听话就行。(我犯的错误就是自以为是)
?
3. 还是不行的话,请参考下面被折腾到快不行的两网友的帖子:
http://www.front2end.cn/blog/WeChat-delivery-address-sharing-interface-hidden-mystery.html
http://doc.okbase.net/zihunqingxin/archive/99799.html
说到这里,其实上面网友碰到的问题,我都没碰到。本人还是仔细研读,并乖乖的按照微信的接口文档来的,可一个不留神还是犯了先入为主、自以为是的错误。
?
4. 我碰到的问题和url有关,微信接口要求我们的url必须带上授权回调后的code和state参数,我的url是这样的:http://www.xxx.com/addr.jsp?code=xxxx&state=yyyy,我当时的想法是微信要求组装签名字符串的时候,要求用"&"来串起各个需要签名的参数,而我的url里面本身就带有"&",我二话没说就把我的url参数值利用js 的encodeURIComponent() 方法编码了一下,结果就埋下了隐患,微信死活给我 "edit_address:fail"的返回值,加上我就是没想到是url 编码后出的问题,就这问题让我上火了好几天。后来把encodeURIComponent去掉,立马就好了。在调试过程中url的参数值给我的感觉是请越简短越好,不要带中文、网址等,感觉容易签名不过,结论不肯定。加上微信的错误返回值提示的又笼统,大家还是简单点好。
?
代码共享(jsp):
<%@page import="java.util.Map"%> <%@page import="java.util.HashMap"%> <%@page import="com.rockitv.util.JSONUtils"%> <%@page import="com.rockitv.http.Response"%> <%@page import="com.rockitv.http.RockitvHttpClient"%> <%@page import="com.rockitv.http.HttpManager"%> <%@page import="java.util.UUID"%> <%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <% String code = request.getParameter("code"); String state = request.getParameter("state"); String accessTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=appID&secret=appSecret&code="+code+"&grant_type=authorization_code"; Response resp = HttpManager.getRequest(new RockitvHttpClient(), accessTokenUrl, null); int statusCode = resp.getStatusCode(); String content = resp.getContent(); Map<String, Object> accessTokenObj = JSONUtils.getMapper().readValue(content, HashMap.class); String accessToken = (String) accessTokenObj.get("access_token"); String timeStamp = (System.currentTimeMillis() / 1000) + ""; String nonceStr = UUID.randomUUID().toString(); %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta name="viewport" id="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1" /> <meta name="apple-mobile-web-app-capable" content="yes" /> <meta name="apple-mobile-web-app-status-bar-style" content="black" /> <meta name="format-detection" content="telephone=no" /> <title>addr test</title> <!-- 这个js库可以在网上找到 --> <script type="text/javascript" src="./js/sha1.js"></script> </head> <body> addr test <br> code: <%=code %> <br> state: <%=state %> <br> statusCode: <%=statusCode %> <br> content: <%=content %> <br> <input type="button" name="" value="-----微信地址-----" onclick="addr()"> </body> <script type="text/javascript"> alert(window.location.href); var signStr = ""; signStr += "accesstoken="+‘<%=accessToken%>‘; signStr += "&appid=appID"; signStr += "&noncestr="+‘<%=nonceStr%>‘; signStr += "×tamp="+‘<%=timeStamp%>‘; signStr += "&url="+window.location.href; // signStr += "&url="+encodeURIComponent(window.location.href); alert("signStr : " + signStr); // signStr = "accesstoken=OezXcEiiBSKSxW0eoylIeBFk1b8VbNtfWALJ5g6aMgZHaqZwK4euEskSn78Qd5pLsfQtuMdgmhajVM5QDm24W8X3tJ18kz5mhmkUcI3RoLm7qGgh1cEnCHejWQo8s5L3VvsFAdawhFxUuLmgh5FRA&appid=wx17ef1eaef46752cb&noncestr=123456×tamp=1384841012&url=http://open.weixin.qq.com/"; var addrSign = CryptoJS.SHA1(signStr, {asString:true}); addrSign = addrSign.toString(); alert("addrSign type : " + typeof addrSign); alert("addrSign : " + addrSign); function addr() { alert("addr : start"); WeixinJSBridge.invoke(‘editAddress‘, { "appId": "appID", "scope": "jsapi_address", "signType": "sha1", "addrSign": addrSign, "timeStamp": "<%=timeStamp%>", "nonceStr": "<%=nonceStr%>" }, function (res) { alert(JSON.stringify(res)); //若 res 中所带的返回值不为空,则表示用户选择该返回值作为收货地址。 //否则若返回空,则表示用户取消了这一次编辑收货地址。 /* document.form1.address1.value = res.proviceFirstStageName; document.form1.address2.value = res.addressCitySecondStageName; document.form1.address3.value = res.addressCountiesThirdStageName; document.form1.detail.value = res.addressDetailInfo; document.form1.phone.value = res.telNumber; */ } ); alert("addr : end"); } </script> </html>
?
?