天天看點

Android studio 微信支付

寫這個部落格之前我不懂不吐槽一下微信官方的技術文檔寫得太爛,支付demo直接無語,好吧吐槽完畢回歸主題之前做微信支付時遇到了不少麻煩,今天特地寫一篇部落格,希望能給大家帶來幫助,首先你要去在微信開放平台注冊相關賬戶那些就不說了下載下傳官方的架構 導入到自己項目中

好現在代碼開始 定義微信的兩個類

private PayReq req;
private IWXAPI msgApi;       
private StringBuffer sb;      

執行個體化對象

msgApi = WXAPIFactory.createWXAPI(this, Constant.APP_ID);
req = new PayReq();
//注冊appid
msgApi.registerApp(Constant.APP_ID);       
sb=new StringBuffer();      
/***
 * 微信支付
 */
private void weixinPay(){
    //生成prepay_id
    GetPrepayIdTask getPrepayId = new GetPrepayIdTask();
    getPrepayId.execute();
}      

GetprepayIdTask類代碼

private class GetPrepayIdTask extends AsyncTask<Void, Void, Map<String,String>> {

    private ProgressDialog dialog;


    @Override
    protected void onPreExecute() {
        dialog = ProgressDialog.show(PayActivity.this, getString(R.string.app_tip), getString(R.string.getting_prepayid));
    }

    @Override
    protected void onPostExecute(Map<String,String> result) {

        sb.append("prepay_id\n"+result.get("prepay_id")+"\n\n");
        Log.e("prepay_id",sb.toString());
        if (sb==null){
            Toast.makeText(PayActivity.this,"支付異常",Toast.LENGTH_LONG).show();
        }

        resultunifiedorder=result;
        //生成簽名參數
        genPayReq();


        msgApi.sendReq(req);
        if (dialog != null) {
            dialog.dismiss();
        }


    }

    @Override
    protected void onCancelled() {
        super.onCancelled();
    }

    @Override
    protected Map<String,String>  doInBackground(Void... params) {

        String url = String.format("https://api.mch.weixin.qq.com/pay/unifiedorder");
        String entity = genProductArgs();


        byte[] buf = Util.httpPost(url, entity);

        String content = new String(buf);
        Log.e("orion", "----"+content);
        Map<String,String> xml=decodeXml(content);

        return xml;
    }
}      

GetprepayIdTask中的genProductArgs()方法

private String genProductArgs() {
    StringBuffer xml = new StringBuffer();

    try {
        String nonceStr = genNonceStr();

        xml.append("</xml>");
        List<NameValuePair> packageParams = new LinkedList<NameValuePair>();
        packageParams.add(new BasicNameValuePair("appid", Constant.APP_ID));//AppId
        packageParams.add(new BasicNameValuePair("body", "你的訂單"));//支付時描述内容,不支援中文不過被我改了
        packageParams.add(new BasicNameValuePair("mch_id", Constant.MCH_ID));//商戶号
        packageParams.add(new BasicNameValuePair("nonce_str", nonceStr));//MD5加密
        packageParams.add(new BasicNameValuePair("notify_url", "伺服器異步通知位址"));//伺服器通知位址
        packageParams.add(new BasicNameValuePair("out_trade_no","你的訂單号"));//訂單号genOutTradNo()
        packageParams.add(new BasicNameValuePair("spbill_create_ip","127.0.0.1"));//不動不知道幹嘛用的
        packageParams.add(new BasicNameValuePair("total_fee",(int) (0.01*100)+""));//價格隻支援int類型機關分
        packageParams.add(new BasicNameValuePair("trade_type", "APP"));//這個不動是差別是什麼平台

        String sign = genPackageSign(packageParams);
        packageParams.add(new BasicNameValuePair("sign", sign));
         Log.e("微信支付價格",to.format(totalcount*100));

        String xmlstring =toXml(packageParams);

        return new String(xmlstring.toString().getBytes(), "ISO8859-1");//解決body不能寫中文的bug



    } catch (Exception e) {
        Log.e("支付", "----genProductArgs fail, ex = " + e.getMessage());
        return null;
    }


}      

GetprepayIdTask中的decodeXml方法

public Map<String,String> decodeXml(String content) {

    try {
        Map<String, String> xml = new HashMap<String, String>();
        XmlPullParser parser = Xml.newPullParser();
        parser.setInput(new StringReader(content));
        int event = parser.getEventType();
        while (event != XmlPullParser.END_DOCUMENT) {

            String nodeName=parser.getName();
            switch (event) {
                case XmlPullParser.START_DOCUMENT:

                    break;
                case XmlPullParser.START_TAG:

                    if("xml".equals(nodeName)==false){
                        //執行個體化student對象
                        xml.put(nodeName,parser.nextText());
                    }
                    break;
                case XmlPullParser.END_TAG:
                    break;
            }
            event = parser.next();
        }

        return xml;
    } catch (Exception e) {
        Log.e("orion","----"+e.toString());
    }
    return null;

}      

genPayReq()方法生成簽名

/***
 * 生成參數簽名
 */
private void genPayReq() {

    req.appId = Constant.APP_ID;
    req.partnerId = Constant.MCH_ID;
    req.prepayId = resultunifiedorder.get("prepay_id");
    req.packageValue = "prepay_id="+resultunifiedorder.get("prepay_id");
    req.nonceStr = genNonceStr();
    req.timeStamp = String.valueOf(genTimeStamp());


    List<NameValuePair> signParams = new LinkedList<NameValuePair>();
    signParams.add(new BasicNameValuePair("appid", req.appId));
    signParams.add(new BasicNameValuePair("noncestr", req.nonceStr));
    signParams.add(new BasicNameValuePair("package", req.packageValue));
    signParams.add(new BasicNameValuePair("partnerid", req.partnerId));
    signParams.add(new BasicNameValuePair("prepayid", req.prepayId));
    signParams.add(new BasicNameValuePair("timestamp", req.timeStamp));

    req.sign = genAppSign(signParams);

    sb.append("sign\n"+req.sign+"\n\n");


    Log.e("orion", "----"+signParams.toString());

}      

genPayReq() 中的genNoncestr()方法 

private String genNonceStr() {
    Random random = new Random();
    return MD5.getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes());
}      

genPayReq() 中的genAppsingn()方法Appkey是微信商戶平台自己設定的

private String genAppSign(List<NameValuePair> params) {
    StringBuilder sb = new StringBuilder();

    for (int i = 0; i < params.size(); i++) {
        sb.append(params.get(i).getName());
        sb.append('=');
        sb.append(params.get(i).getValue());
        sb.append('&');
    }
    sb.append("key=");
    sb.append(API_KEY);

    this.sb.append("sign str\n"+sb.toString()+"\n\n");
    String appSign = MD5.getMessageDigest(sb.toString().getBytes());
    Log.e("orion","----"+appSign);
    return appSign;
}      

Util類裡面的http請求因為安卓5.0抛棄掉了httpclient 要想使用HttpClient需要在Bulid.gradle做配置請看下面

public static byte[] httpPost(String url, String entity) {
   if (url == null || url.length() == 0) {
      Log.e(TAG, "httpPost, url is null");
      return null;
   }
   
   HttpClient httpClient = getNewHttpClient();
   
   HttpPost httpPost = new HttpPost(url);
   
   try {
      httpPost.setEntity(new StringEntity(entity));
      httpPost.setHeader("Accept", "application/json");
      httpPost.setHeader("Content-type", "application/json");
      
      HttpResponse resp = httpClient.execute(httpPost);
      if (resp.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
         Log.e(TAG, "httpGet fail, status code = " + resp.getStatusLine().getStatusCode());
         return null;
      }

      return EntityUtils.toByteArray(resp.getEntity());
   } catch (Exception e) {
      Log.e(TAG, "httpPost exception, e = " + e.getMessage());
      e.printStackTrace();
      return null;
   }
}      

想要在Android studio裡面是用HttpClient 需要在build.gradle配置

android {
    useLibrary 'org.apache.http.legacy'
}      

項目源碼:http://download.csdn.net/detail/liufatao/9692044

繼續閱讀