微信SDK踩過的那些坑。。登入分享支付
由於第一次接微信SDK。沿路踩過一個又一個大大小小的坑,以此做一下記錄。
對於安卓版來說。前期一些基本jar匯入。xml配置什麼的都基本不會有什麼問題,按照微信文件來就可以了。
第一個坑在出在簽名上,第三方應用要拉起微信必須保證2點:
1.應用中的包名(Mainfext.xml中的package)必須與後臺配置的一致。
2.應用生成不能是debug包,必須是正式的簽名包。這個簽名必須與後臺配置的一致。
在第一點上,會出錯的概率還是比較小的。
主要出錯會在第2點上,微信官方有微信簽名檢測工具。用檢測工具檢測到的簽名是一串小寫並且中間沒有冒號的字串。
而在後臺配置的卻是直接從在eclipse打簽名包時直接複製出來的MD5簽名。(大寫,並且中間夾雜:)
所以後臺配置的簽名必須與打包時的簽名一致。必須是小寫無冒號的字串。
第二個坑出現在接登入的時候,在拉起微信授權登入之後無法自動返回第三方應用。
問題出在判斷微信是否安裝上。用了api.openWXApp(),導致開啟微信後無法返回,修改為 api.isWXAppInstalled()就完美解決問題了。
- publicstaticvoid sendMsgtoWX()
- {
- System.out.println("hwt c-----------------sendMsgtoWX");
- if(api.isWXAppInstalled())
- {
- // send oauth request
- SendAuth.Req req = new SendAuth.Req();
- req.scope = "snsapi_userinfo";
- req.state = "login_state";
- api.sendReq(req);
- }
- else
- {
- ShowMsg(1);
- }
第三個坑出現在分享圖片的時候。微信對於圖片分享中,對圖片的大小做了限定。圖片分享中主要是兩部分,一個分享出去就直接能看到的一張比較小的圖。還有一張就是點選之後出現的圖片。兩張圖片的具體大小沒有做測試。但是知道第一個圖片必須比較小。太大就會出現無法拉起分享的情況。第二張圖片比較大。基本1M左右應該都沒什麼問題。
- //分享圖片到微信
- publicvoid shareImgToWeixin(String path,int type)//type = 1 好友。type = 2 朋友圈
- {
- System.out.println("----------shareToWeixin--path:"+path);
- File file = new File(path);
- if (!file.exists()) {
- ShowMsg(2);
- return;
- }
- if(api.isWXAppInstalled())
- {
- if(type == 1)
- {
- Bitmap bmp = BitmapFactory.decodeFile(path);
- WXImageObject imgObj = new WXImageObject(bmp);
- imgObj.setImagePath(path+"screenshot.png");
- int num1 =bmp.getByteCount();
- int w =bmp.getWidth();
- int h =bmp.getHeight();
- float scal = 100/(float)w;
- w = (int)(w*scal);
- h = (int)(h*scal);
- System.out.println("----------thumbBmp w:"+w+"h:"+h);
- Bitmap thumbBmp = Bitmap.createScaledBitmap(bmp, w,h, true);
- int num =thumbBmp.getByteCount();
- System.out.println("----------thumbBmp num1:"+num1+"------num:"+num);
- bmp.recycle();
- WXMediaMessage msg = new WXMediaMessage();
- msg.mediaObject = imgObj;
- msg.thumbData = Util.bmpToByteArray(thumbBmp, true);
- SendMessageToWX.Req req = new SendMessageToWX.Req();
- req.scene = (type == 1)?SendMessageToWX.Req.WXSceneSession:SendMessageToWX.Req.WXSceneTimeline;
- req.transaction = buildTransaction("img");
- req.message = msg;
- api.sendReq(req);
- }
- }
- }
在微信支付中遇到的問題還是挺多的,因為微信的流程中資料的接收和傳送都是xml格式的。由於之前沒有對xml格式做過處理,走了不少彎路。
其實流程很簡單,就是將資料拼成xml格式post發過去,再解析xml格式的資料獲得引數。微信第一部分統一下單,由於各種原因我們放在了客戶端中處理。服務端只是生成了一個商戶訂單號。
由於我們的專案ios和安卓是同一套程式碼。所以我們將第一部分統一下單放在了cocos中實現。
其中需要注意的幾點是:在生成簽名的時候,必須把需要傳送過去的引數,除了sign本身之外都需要打進去,少一個都不行。簽名就按照微信官方文件來就可以了。
需要簽名的引數大寫與小寫所生成的簽名是不一樣的。所以,我把需要簽名的引數都是小寫,再在最後轉化為大寫。還有簽名中的key並非AppID或AppSectet,而是在商戶平臺設定的,官方描述為“key設定路徑:微信商戶平臺(pay.weixin.qq.com)-->賬戶設定-->API安全-->金鑰設置”。
- void WXMessage::SendFirstDate(std::string out_trade_no,std::string price,std::string body)
- {
- //網路非同步連線方法
- HttpRequest* request = new HttpRequest();
- request->setUrl("https://api.mch.weixin.qq.com/pay/unifiedorder");
- request->setRequestType(HttpRequest::Type::POST);
- request->setResponseCallback(this, httpresponse_selector(WXMessage::onHttpRequestCompleted));
- std::string postData = "";
- postData += "<xml>";
- postData += "\n";
- postData += "<appid><![CDATA["+(std::string)wx_appid+"]]></appid>";
- postData += "\n";
- postData += "<mch_id><![CDATA["+(std::string)wx_mchid+"]]></mch_id>";
- postData += "\n";
- postData += "<nonce_str><![CDATA["+rand_str()+"]]></nonce_str>";
- postData += "\n";
- postData += "<sign><![CDATA["+Getsign(out_trade_no,price,body)+"]]></sign>";
- postData += "\n";
- postData += "<body><![CDATA["+body+"]]></body>";
- postData += "\n";
- postData += "<out_trade_no><![CDATA["+out_trade_no+"]]></out_trade_no>";
- postData += "\n";
- postData += "<total_fee>"+price+"</total_fee>";
- postData += "\n";
- postData += "<spbill_create_ip><![CDATA["+GetIP()+"]]></spbill_create_ip>";
- postData += "\n";
- postData += "<notify_url><![CDATA["+(std::string)wx_notify_url+"]]></notify_url>";
- postData += "\n";
- postData += "<trade_type><![CDATA["+(std::string)wx_trade_type+"]]></trade_type>";
- postData += "\n";
- postData += "</xml>; <pre name="code" class="cpp">
HttpClient::getInstance()->send(request);
request->release();
}
- void WXMessage::onHttpRequestCompleted(HttpClient *sender, HttpResponse *response)
- {
- if (!response) {
- return;
- }
- if (0 != strlen(response->getHttpRequest()->getTag())) {
- log("%s completed",response->getHttpRequest()->getTag());
- }
- long statusCode = response->getResponseCode();
- char statusString[64] = {};
- sprintf(statusString, "HTTP Status Code: %ld, tag = %s",statusCode,response->getHttpRequest()->getTag());
- log("response code: %ld",statusCode);
- if (!response->isSucceed()) {
- log("response failed");
- log("error buffer: %s",response->getErrorBuffer()