無聊寫一個自己接入微信支付的文章

在微信開發平臺下載微信支付sdk 一般叫  libammsdk.jar‘

然後導入到項目libs包內

然後開始集成

(https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=8_5)

這個是微信支付開發文檔地址,不過文檔寫的真心爛死了,步驟一點也不詳細的。


一開始需要調用統一訂單接口獲取預訂單的訂單id也就是字段prepay_id

根據文檔說明,沒特別需要的話我們只傳必填的那些字段就行了

每個字段有對應描述,可以根據描述選擇你需要的字段。

簡單說幾個比較重要的

appid字段就是在你在微信開放平臺(https://open.weixin.qq.com)創建並審覈通過的應用,點查看就能看到如下圖。


mch_id微信支付商戶號 這個就得申請支付功能並審覈通過之後,系統會給你發放一個商戶登錄賬戶 登錄密碼 商戶號發送到你的郵箱中。

格式是這樣的

mch_id就發給郵箱內的微信支付商戶號,也可以用商戶帳號密碼在(https://pay.weixin.qq.com/)登錄商戶管理平臺查看。

sing簽名 這個字段也是比較噁心的,需要把你傳的字段全部整合在一起然後用MD5加密,再改大寫才行

舉個栗子

String a="appid=wx081c8528de654a89&body=測試&detail=測試充值" +
                "&mch_id=1000000000&nonce_str="+"5K8264ILTKCH16CQ2502SI8ZNMTM67VS"+"&notify_url=http://www.baidu.com&out_trade_no="+20150806125346+
                "&spbill_create_ip="+192.168.1.1+"&total_fee="+1+"&trade_type=APP&key=192006250b4c09247ec02edce69f6a2d";

sing=MD5.mdjiami(a).toUpperCase();

驗證sing是否正確可以在(https://pay.weixin.qq.com/wiki/tools/signverify/)這裏進行測試

String a裏除了上傳的參數外還有一個key,這個key要登錄商戶平臺然後在設置密鑰的地方設置的(會提示你要先安裝證書,按提示來就行了)

字段選擇完成後開始傳參數,這個也是比較噁心的他需要用<xml><appid>wx081c8528de654a89</appid><mch_id>1000000000</mch_id></xml>這種格式上傳數據,沒辦法自己拼吧。

ByteArrayOutputStream baos=new ByteArrayOutputStream();
      XmlSerializer xml= Xml.newSerializer();
      xml.setOutput(baos, "UTF-8");
//    xml.startDocument("UTF-8", null);

//    xml.startTag(null, "zuobiao");
      //appid
      xml.startTag(null, "xml");
      xml.startTag(null, "appid");
      xml.text("wx081c8528de654a89");
      xml.endTag(null, "appid");
      //商品名
      xml.startTag(null, "body");
      xml.text("測試");
      xml.endTag(null, "body");
      //商品詳情
      xml.startTag(null, "detail");
      xml.text("測試充值");
      xml.endTag(null, "detail");
      //商戶號
      xml.startTag(null, "mch_id");
      xml.text("1000000000");
      xml.endTag(null, "mch_id");
      //隨機字符串
      xml.startTag(null, "nonce_str");
      xml.text("5K8264ILTKCH16CQ2502SI8ZNMTM67VS");
      xml.endTag(null, "nonce_str");
      //回調地址
      xml.startTag(null, "notify_url");
      xml.text("http://www.baidu.com");
      xml.endTag(null, "notify_url");
      //商戶訂單號
      xml.startTag(null, "out_trade_no");
      xml.text("20150806125346");
      xml.endTag(null, "out_trade_no");
      //用戶ip
      xml.startTag(null, "spbill_create_ip");
      xml.text("192.168.1.1");
      xml.endTag(null, "spbill_create_ip");
      //金額
      xml.startTag(null, "total_fee");
      xml.text(1+"");
      xml.endTag(null, "total_fee");
      //類型
      xml.startTag(null, "trade_type");
      xml.text("APP");
      xml.endTag(null, "trade_type");
      //簽名
      xml.startTag(null, "sign");
      xml.text(sing);
      xml.endTag(null, "sign");


      //abcdefghijklmnopqrstuvwxyz
//    xml.endTag(null, "zuobiao");
      xml.endDocument();

      byte[] xmlData=baos.toByteArray();
      String xmlString=new String(xmlData,"ISO8859-1");
      baos.flush();
      baos.close();
      baos=null;      
      return xmlString;
注意字段值有中文的時候要改成"IS08859-1"編碼不然會提示簽名錯誤

注:這裏我遇到幾次appid跟mch_id不匹配,要按我前面寫的去找appid跟mch_id才行。

然後傳上去返回的還是xml格式的值 我們要進行解析並取到prepay_id的值後面用。

解析方法

ByteArrayInputStream is=new ByteArrayInputStream(str.getBytes());
      XmlPullParser xpp = Xml.newPullParser();
      try{
         xpp.setInput(is,"ISO8859-1");
         int eventType=xpp.getEventType();
         while (eventType!= XmlPullParser.END_DOCUMENT){
            switch (eventType) {
               case XmlPullParser.START_DOCUMENT:
                  break;
               case XmlPullParser.START_TAG:
                  String name = xpp.getName();
                  if (name.equalsIgnoreCase("prepay_id")) {

                     xpp.require(XmlPullParser.START_TAG, null, "prepay_id");
                     id = xpp.nextText();
                     if (xpp.getEventType() != XmlPullParser.END_TAG) {
                        xpp.nextTag();
                     }
                     xpp.require(XmlPullParser.END_TAG, null, "prepay_id");
                     System.out.println("menu option: " + id);

//                   id=xpp.nextText();

                  }
                  break;
               case XmlPullParser.END_TAG:
                  break;
            }
            eventType = xpp.next();
         }
         is.close();
      }catch (Exception e) {
         e.printStackTrace();
      }
//    Toast.makeText(PayActivity.this, id, Toast.LENGTH_SHORT).show();
      return id;
將返回的值轉成String類型然後傳進來就行 返回的值是prepay_id

然後開始準備調起支付接口參數。


這裏還是需要簽名跟前面一樣(參數跟我栗子裏一樣就行了,不需要變,值改對應的就行了。)

String diaoqi = "appid=wx081c8528de654a89&noncestr="+4K8264ILTKCH16CQ2502SI8ZNMTM67V5+"&package="+"Sign=WXPay"+"&partnerid=1000000000&prepayid=" + prepayid +"&timestamp="+14000000000+"&key=192006250b4c09247ec02edce69f6a2d";
這裏注意參數名都是小寫的,因爲調起的代碼中參數字段是大寫我誤以爲是簽名中參數名也要大寫搞的半天一直調不出支付接口直接返回-1

然後開始調起支付關鍵代碼

      boolean isPaySupported = api.getWXAppSupportAPI() >= Build.PAY_SUPPORTED_SDK_INT;
                  if(isPaySupported){//判斷微信當前版本是否支持微信支付。

                     PayReq req = new PayReq();
                     req.appId = "wx081c8528de654a89";
                     req.partnerId = "1000000000";
                     req.prepayId = prepayid;
                     req.nonceStr = 4K8264ILTKCH16CQ2502SI8ZNMTM67V5;
                     req.timeStamp = 14000000000+"";
                     req.packageValue = "Sign=WXPay";
                     req.sign = MD5.mdjiami(diaoqi).toUpperCase();
//                   req.extData = "app data";
                     api.sendReq(req);
//                   Toast.makeText(PayActivity.this, prepayid, Toast.LENGTH_SHORT).show();
                  }
這裏就完成了,正常情況下是正常調起來的。

但是有可能出意外因爲錯誤返回都是-1,所以都是自己找原因。

有可能你app包名或者MD5簽名跟你在微信開發平臺內填寫的不一致。MD5簽名可在(https://open.weixin.qq.com/zh_CN/htmledition/res/dev/download/sdk/Gen_Signature_Android.apk)下載工具獲取。

還有在集成的時候需要注意的地方 需要在項目裏建跟官方demo一樣包名如圖只需要放AppRegister複製官方demo裏的就行,然後接受回調,需要在你的項目包名下例如com.ceshi.activity再建一個包wxapi放入WXPayEntryActivity這個是處理回調的複製官方demo裏的就行了。

如圖還需要在AndroidManifest文件中註冊AppRegister

還有這裏要注意不然也接收不到回調,schem的值是你的appid

這樣基本沒有問題了。

32位隨機數算法

String val = "";
Random random = new Random();

//參數length,表示生成幾位隨機數
for(int i = 0; i < 32; i++) {

   String charOrNum = random.nextInt(2) % 2 == 0 ? "char" : "num";
   //輸出字母還是數字
   if( "char".equalsIgnoreCase(charOrNum) ) {
      //輸出是大寫字母還是小寫字母
      int temp = random.nextInt(2) % 2 == 0 ? 65 : 97;
      val += (char)(random.nextInt(26) + temp);
   } else if( "num".equalsIgnoreCase(charOrNum) ) {
      val += String.valueOf(random.nextInt(10));
   }
}
return val;
獲取時間搓精確掉秒
timeMillis = System.currentTimeMillis()/1000;

還有調起支付前最好判斷下是否安裝了微信不然沒有任何反映跟提示也沒有回調。

判斷的代碼

private boolean isWXAppInstalledAndSupported() {
   IWXAPI msgApi = WXAPIFactory.createWXAPI(this, null);
   msgApi.registerApp("wx081c8528de654a89");

   boolean sIsWXAppInstalledAndSupported = msgApi.isWXAppInstalled()
         && msgApi.isWXAppSupportAPI();

   return sIsWXAppInstalledAndSupported;
}


後面有發現其它問題我再進行補充,也歡迎大家補充問題。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章