Android—基于微信開放平臺v3SDK,開發微信支付填坑。

ling4444 8年前發布 | 10K 次閱讀 XML 安卓開發 Android開發 移動開發

接觸微信支付之前聽說過這是一個坑,,,心里已經有了準備。。。我以為我沒準跳坑出不來了,沒有想到我填上了,調用成功之后我感覺公司所有的同事都是漂亮的,隔著北京的大霧霾我仿佛看見了太陽~~~好了,裝逼結束。。。進入正題

開發準備:

1.在微信開放平臺申請賬號

2.成功后創建應用,就是填一些看似很官方很正經的資料了。。。(說審核7天左右,沒有意外的情況下你的app第二天就審核成功了是不是很開心,有了appid,是不是就可以調用微   信支付了????-------想多了,真的)

3.微信支付是需要額外申請的:需要資料審核,賬戶驗證,協議簽署等步驟,(我記得,,資料審核要填寫的東西好多,,,好多,,,賬戶驗證就是你審核成功后微信會發送郵件到你   注冊時登記的郵箱賬號,其中含有隨機金額用于賬戶驗證,協議簽署,略,太簡單)一定要好好閱讀你郵件的任何信息,因為有的細節錯了,,,你可能填坑很久。。。。。。

正式開發階段:

問題1:

調用官方的SDK發現只能成功的調起一次微信,再次支付的時候怎么也調用不起來了

解決:

似乎不是什么正經方法:在手機設置中管理應用程序,清除微信數據,緩存,,再來一遍,絕對可以調起來(當然還是只是一次。。。。)

繼續:

我認為要用微信支付嘛,,就只看了調用支付接口的文檔:

后來發現需要的參數prepayid是怎么也找不到啊,,后來才發現這個prepayid是先調用”統一下單“這個接口時候溫馨反過來的東西,但是官方的SDK中并沒有統一下單的代碼。坑嗎???

所以要先看統一下單文檔了    https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_1

1.使用自己的APP調用的時候把官網down下來的SDK中WXPayEntryActivity拷貝到自己的項目,所在包的名字最后一定是.wxapi(我連包一起拷了。。。。)

2.在項目清單文件中填寫:

3.SDK中的AppRegister拷貝下來,,,里面換成你自己的appid,然后在項目清單中也注冊一下。

4.重點來了,,就是你APP要調微信支付的activity,我這還叫PayActivity

要調起微信支付頁面,要在這個activity中,將你的app注冊到微信

接下來先調用統一下單獲取prepayid,參數,微信人家要xml格式的!我們就得發送xml格式的!

好了調用的時候把這個方法的返回值當參數傳,,等待微信返回success吧!。。

我遇見的錯誤:簽名錯誤

我的原因是大意了 ConfigUtil.NOTIFY_URL這個參數寫的空字符串

還有是因為debug版運行的,沒有打包運行

返回成功之后,可以調用支付接口了

不要忘了這一步去跳轉界面,,,,,

沒有跳轉到微信支付可能是你由運行的debug版本,,,,沒有打包。。。。。

下面是我的PayActivity完整代碼:

package com.example.taijiapp.ui;

import java.io.StringReader;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Random;

import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.xmlpull.v1.XmlPullParser;

import com.example.taijiapp.R;
import com.example.taijiapp.util.Constants;
import com.example.taijiapp.util.MD5;
import com.example.taijiapp.util.T;
import com.example.taijiapp.util.Util;
import com.example.taijiapp.utils.ConfigUtil;
import com.tencent.mm.sdk.modelpay.PayReq;
import com.tencent.mm.sdk.openapi.IWXAPI;
import com.tencent.mm.sdk.openapi.WXAPIFactory;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.util.Xml;
import android.view.View;
import android.widget.Button;

public class PayActivity extends Activity {
    PayReq req;
    private IWXAPI msgApi;
    Map<String, String> resultunifiedorder;
    StringBuffer sb;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.pay);
        req = new PayReq();
        sb = new StringBuffer();
        msgApi = WXAPIFactory.createWXAPI(this, Constants.APP_ID);
        /**
         * 將app注冊到微信
         */
        boolean registerApp = msgApi.registerApp(Constants.APP_ID);
        T.show(this, "注冊========"+registerApp+"");
        Button appayBtn = (Button) findViewById(R.id.appay_btn);
        Button check_pay_btn = (Button) findViewById(R.id.check_pay_btn);
        appayBtn.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                GetPrepayIdTask getPrepayId = new GetPrepayIdTask();
                getPrepayId.execute();
            }
        });
        /**
         * 將該app注冊到微信
         */
        check_pay_btn.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                genPayReq();
                sendPayReq();

            }
        });
//      // 生成簽名參數
//      Button appay_pre_btn = (Button) findViewById(R.id.appay_pre_btn);
//      appay_pre_btn.setOnClickListener(new View.OnClickListener() {
//
//          @Override
//          public void onClick(View v) {
//              genPayReq();
//          }
//      });
    }
    /**
     * 生成簽名
     */

    private String genPackageSign(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(Constants.KEY);
        Log.e("拼接=====", sb.toString());
        String packageSign = MD5.getMessageDigest(sb.toString().getBytes()).toUpperCase();
        Log.e("orion生成簽名===", packageSign);
        return packageSign;
    }

    /**
     * 簽名工具 不含商戶密鑰 -暫時不用 = * 編碼格式 UTF-8 = * @return
     */
    public static String createSignNoKey(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('&');
        }
        String signStr = sb.toString();
        String subStr = signStr.substring(0, signStr.length() - 1);
        // 注意sign轉為大寫
        return MD5.getMessageDigest(subStr.getBytes()).toUpperCase();
    }

    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(Constants.KEY);

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

    private String toXml(List<NameValuePair> params) {
        StringBuilder sb = new StringBuilder();
        sb.append("<xml>");
        for (int i = 0; i < params.size(); i++) {
            sb.append("<" + params.get(i).getName() + ">");

            sb.append(params.get(i).getValue());
            sb.append("</" + params.get(i).getName() + ">");
        }
        sb.append("</xml>");

        Log.e("orion", sb.toString());
        return sb.toString();
    }

    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) {
            if (dialog != null) {
                dialog.dismiss();
            }
            sb.append("prepay_id\n" + result.get("prepay_id") + "\n\n");

            resultunifiedorder = result;

        }

        @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();
            Log.e("orion===發送過去", entity);
            byte[] buf = Util.httpPost(url, entity);

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

            return xml;
        }
    }

    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;

    }
    /**
     * 生成隨機數
     * @return
     */
    private String genNonceStr() {
        Random random = new Random();
        return MD5.getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes());
    }
    /**
     * 時間戳
     * @return
     */
    private long genTimeStamp() {
        return System.currentTimeMillis() / 1000;
    }
    /**
     * 隨機數
     * @return
     */
    private String genOutTradNo() {
        Random random = new Random();
        return MD5.getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes());
    }
    /**
     * 獲取設備的ip地址
     * @return
     */
    public String getLocalIpAddress() {
        try {
            for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
                NetworkInterface intf = en.nextElement();
                for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {
                    InetAddress inetAddress = enumIpAddr.nextElement();
                    if (!inetAddress.isLoopbackAddress()) {
                        return inetAddress.getHostAddress().toString();
                    }
                }
            }
        } catch (SocketException ex) {
        }
        return null;
    }

    private String getWifiIp() {
        // 獲取wifi服務
        WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
        // 判斷wifi是否開啟
        if (!wifiManager.isWifiEnabled()) {
            wifiManager.setWifiEnabled(true);
        }
        WifiInfo wifiInfo = wifiManager.getConnectionInfo();
        int ipAddress = wifiInfo.getIpAddress();
        String ip = intToIp(ipAddress);
        return ip;
    }
    /**
     * 轉化成Ip地址的格式
     * @param i
     * @return
     */
    private String intToIp(int i) {

        return (i & 0xFF) + "." + ((i >> 8) & 0xFF) + "." + ((i >> 16) & 0xFF) + "." + (i >> 24 & 0xFF);
    }

    private String genProductArgs() {
        StringBuffer xml = new StringBuffer();
        String ip = getWifiIp();
        if (ip == "" && ip == "") {
            ip = getLocalIpAddress();
        }
        try {
            String nonceStr = genNonceStr();
            xml.append("</xml>");
            List<NameValuePair> packageParams = new LinkedList<NameValuePair>();
            packageParams.add(new BasicNameValuePair("appid", Constants.APP_ID));
            packageParams.add(new BasicNameValuePair("body", "APPtest"));
            packageParams.add(new BasicNameValuePair("mch_id", Constants.MCH_ID));
            packageParams.add(new BasicNameValuePair("nonce_str", nonceStr));
            packageParams.add(new BasicNameValuePair("notify_url", ConfigUtil.NOTIFY_URL));
            packageParams.add(new BasicNameValuePair("out_trade_no", genOutTradNo()));
            packageParams.add(new BasicNameValuePair("spbill_create_ip", ip));
            packageParams.add(new BasicNameValuePair("total_fee", "100"));
            packageParams.add(new BasicNameValuePair("trade_type", "APP"));
            String sign = genPackageSign(packageParams);
            packageParams.add(new BasicNameValuePair("sign", sign));
            String xmlstring = toXml(packageParams);
            return xmlstring;
        } catch (Exception e) {
            Log.e("TAG", "fail, ex = " + e.getMessage());
            return null;
        }
    }

    private void genPayReq() {
        req.appId = Constants.APP_ID;
        req.partnerId = Constants.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==genPayReq===============", signParams.toString());

    }

    private void sendPayReq() {
        boolean sendReq = msgApi.sendReq(req);
        T.show(this, "微信跳轉====="+sendReq+"");
    }

}

里面沒有的類,,,,吶:  http://download.csdn.net/detail/meijuanyou/9571223 自己下載一下拷貝一下。。。

參考資料     http://blog.csdn.net/meijuanyou/article/details/51863720

備忘,希望能給大家帶來幫助。。。

 

來自:http://www.cnblogs.com/yunfang/p/6078208.html

 

 本文由用戶 ling4444 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!