Android APP統合微信支払い


最近プロジェクトの中で支払い機能が必要で、bossは一致して微信で支払うことを決定して、だからネット上で多くの資料を調べて、言うのが全部ではありませんて、終わったら前の同僚を探して指導します.統合に成功した.ここで総括記録をします.
1、アプリに微信決済を統合し、まずもちろん公式サイトに登録して支払い機能を取得する.これらは開発には関係なく、公式サイトで詳しく説明されていますが、ここではあまり文章を作っていません.これらの能力を得ることは開発に条件を提供した.開発で使われるのは、プラットフォームから与えられたAPPID、APPsercet、およびビジネスプラットフォームに設置されたAPP_key.
2、支払い能力などの前提条件が整ったら、開発プロセスです.コードの中でどのようにようやくつり上げて支払うことができて、公式サイトのDEMO自身を参照してもいくつか総括と各方面の大神の指導をしました.次のステップに分けて演奏します.
(1)、まずはもちろんsdkを工事環境に配置し、公式サイトでAndroid端末SDKをダウンロードし、解凍後libmmsdkをダウンロードする.JArはプロジェクトを導入し、DEMOのConstant.JAva(ここでは公式demoの様式を参照して書くが、もちろん他の方式も採用できる)、MD 5.java、Util.JAvaはプロジェクト(私がここで使った)に入れて、これらの前提条件があれば次のコード操作を書くことができます.
(2)、注文情報の生成
受注情報を生成するには以下の方法で生成し,受注情報を生成するには署名ファイルが必要であるため,生成署名が含まれている.微信はすべての要求にXMLパラメータ形式を採用することを要求し、すべての生産注文情報の後、xmlに変換する必要がある.注文情報に必要な要求パラメータは公式サイトで照合できますが、ここには必要なパラメータがいくつか入っています.
受注情報の生成方法:
//        
    private String genProductArgs() {
        StringBuffer xml = new StringBuffer();
        try {
            String nonceStr = genNonceStr();

            xml.append("");
            List packageParams = new LinkedList();

            packageParams.add(new BasicNameValuePair("appid", Constants.APP_ID)); //APPID

            packageParams.add(new BasicNameValuePair("body", "  :" + singlePrice + " x " + payment_num.getText().toString() + " "));  //    

            packageParams.add(new BasicNameValuePair("mch_id", Constants.MCH_ID));  //  ID

            packageParams.add(new BasicNameValuePair("nonce_str", nonceStr));   //     

            packageParams.add(new BasicNameValuePair("notify_url","http://www.weixin.qq.com/wxpay/pay.php")); //    

            packageParams.add(new BasicNameValuePair("out_trade_no",getTrade()));  //     

            packageParams.add(new BasicNameValuePair("spbill_create_ip",getLocalHostIp())); //  IP

            //double price = Double.parseDouble(payment_num.getText().toString()) * (Integer.parseInt(singlePrice) * 100);
            double price = Double.parseDouble(singlePrice) * 100 * n;
            int priceInt = (int) price;
            packageParams.add(new BasicNameValuePair("total_fee", priceInt+""));    //    int   

            packageParams.add(new BasicNameValuePair("trade_type", "APP"));  //    

            String sign = genAppSign(packageParams);
            packageParams.add(new BasicNameValuePair("sign", sign));  //  

            String xmlstring = parseNodeToXML(packageParams);   //   xml

            return xmlstring;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

このxmlリクエストパラメータを構築するにはhttpclientが生成したので,いくつかのパケットが導入された.他の方法で支払い注文を生成することもできます.最後の形式が公式サイトの形式と同じであればいいです.
いくつかのパラメータの生成に関連しています.ここには、私たちのプロジェクトのビジネスロジックがリストされています.もちろん、プロジェクトによって異なります.
//     
    private String getTrade(){
        long nowTime = System.currentTimeMillis();
        SimpleDateFormat format = new SimpleDateFormat("yyMMddHHmmss");
        return format.format(new Date(nowTime));
    }



    //      Sign
    StringBuilder sb = new StringBuilder();
    private String genAppSign(List 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.API_KEY);
        this.sb.append("sign str
" + sb.toString() + "

"); String appSign = MD5.getMessageDigest(sb.toString().getBytes()).toUpperCase(); return appSign; } // private String genNonceStr() { Random random = new Random(); return MD5.getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes()); } /** * xml * @param treeNodes * @return */ public String parseNodeToXML(List treeNodes) { StringBuffer xmlnodes = new StringBuffer(); if (treeNodes != null && treeNodes.size() > 0) { xmlnodes.append(""); for (int i = 0; i < treeNodes.size(); i++) { NameValuePair node = treeNodes.get(i); xmlnodes.append("").append(node.getValue()).append(""+node.getName()+">"); } xmlnodes.append(""); } //return xmlnodes.toString(); String xml = xmlnodes.toString(); try { xml = new String(xml.toString().getBytes(), "ISO8859-1"); // , , perpred_id return xml; } catch (UnsupportedEncodingException e) { e.printStackTrace(); return null; } } // IP public String getLocalHostIp() { String ipaddress = ""; try { Enumeration en = NetworkInterface.getNetworkInterfaces(); // while (en.hasMoreElements()) { NetworkInterface nif = en.nextElement();// ip Enumeration inet = nif.getInetAddresses(); // ip while (inet.hasMoreElements()) { InetAddress ip = inet.nextElement(); if (!ip.isLoopbackAddress() && InetAddressUtils.isIPv4Address(ip.getHostAddress())) { return ip.getHostAddress(); } } } } catch (SocketException e) { Log.e("feige", " ip "); e.printStackTrace(); } return ipaddress; }

(3)、微信バックグラウンド指定インタフェースにアクセスし、perpay_を取得するid.
前のはこのperpayを得るためだと言える.idが用意されており、公式サイトで指定されたインタフェースは「https://api.mch.weixin.qq.com/pay/unifiedorder」リクエストは公式サイトdemoでutilが提供するリクエスト方式を採用
ここでは非同期処理方式を採用し,要求指定インタフェースにperapy_を得る.idの後に直接支払いを吊り上げる方法.
//      id
    public void gotoWechat() {
        new AsyncTask() {
            @Override
            protected Object doInBackground(Object[] objects) {   //  Prepay_id
                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);
                try {
                    xmlParseTest(content);  //       
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (XmlPullParserException e) {
                    e.printStackTrace();
                }
                return null;
            }

            @Override
            protected void onPostExecute(Object o) {
                super.onPostExecute(o);
                wechatPay();
            }
        }.execute();
    }

要求が正常に返されたデータももちろんxml形式であり、perpay_に解析して取り出す必要がある.id(返された結果はperpay_idだけでなく、他の情報も含まれており、個人的には支払いを吊るすにはperpay_idだけでいいと感じています).ここでもdemoを参照して取得した情報をxmlで解析する.
WeixinParentId

/**
     *   xml
     *   prepay_id
     *     Books    
     */
    WeixinParentId book = null;                //    Books    
    public void xmlParseTest(String str) throws IOException, XmlPullParserException {
        XmlPullParser pullParser = Xml.newPullParser();            //  XmlPullParser  
        //InputStream is = getContext().getAssets().open("parse.xml");   //    
        ByteArrayInputStream is = new ByteArrayInputStream(str.getBytes("UTF-8"));
        ArrayList books = null ;

        pullParser.setInput(is, "UTF-8");
        int type = pullParser.getEventType();    //      
        while (type != pullParser.END_DOCUMENT) {   //    
            switch(type){
                case XmlPullParser.START_DOCUMENT:    //    
                    books = new ArrayList();
                    break;
                case XmlPullParser.START_TAG:    //       
                    if (pullParser.getName().equals("xml")) {
                        book = new WeixinParentId();
                    }else if (pullParser.getName().equals("return_msg")) {
                        type = pullParser.next();    //       ,        
                        book.setReturn_msg(pullParser.getText());
                    }else if (pullParser.getName().equals("appid")) {
                        type = pullParser.next();
                        book.setAppid(pullParser.getText());
                    }else if (pullParser.getName().equals("prepay_id")) {
                        type = pullParser.next();
                        book.setPrepay_id(pullParser.getText());
                    }

                    break;
                case XmlPullParser.END_TAG:   //          
                    if (pullParser.getName().equals("book")) {
                        books.add(book);
                        book = null;    //       
                    }
                    break;
            }
            type = pullParser.next();    //       

        }
        //Log.e("test", "book------id----" + book.getPrepay_id());
    }

これが正常に実行された後、bookオブジェクトのperpay_idはすでに割り当てられている.非同期で取り出して使用するだけです.

//   perpay_id        
    protected void wechatPay() {
        PayReq req = new PayReq();
        req.appId = Constants.APP_ID;
        req.partnerId = Constants.MCH_ID;
        req.prepayId = book.getPrepay_id();
        req.packageValue = "Sign=WXPay";
        req.nonceStr = genNonceStr();
        req.timeStamp = String.valueOf(genTimeStamp());

        List signParams = new LinkedList();
        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
" + req.sign + "

"); // , , IWXMsg.registerApp //Log.e("test","book.getPrepay_id()----------"+book.getPrepay_id()+"-------genNonceStr()-------"+genNonceStr()+"--------genTimeStamp()-------"+genTimeStamp()+"---genAppSign(signParams)--"+genAppSign(signParams)); api.sendReq(req); // dialog.dismiss(); } // private long genTimeStamp() { return System.currentTimeMillis() / 1000; }

前の非同期操作方法をボタンクリックイベントに割り当て、すべてのステップが正しい場合、支払いインタフェースに入ることができます.以下の図です.

                   ,               :


    ,     APP ,              。         wxapi   
WXPayEntryActivity  Onresp()        ,                   。            



コールバックでダイアログ・ボックスがポップアップされ、ユーザーに支払いに成功し、他のロジックを処理するように要求されます.
public class WXPayEntryActivity extends Activity implements IWXAPIEventHandler {

    private static final String TAG = "MicroMsg.SDKSample.WXPayEntryActivity";

    private IWXAPI api;


    @Override public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

//        setContentView(R.layout.activity_main2);
        api = WXAPIFactory.createWXAPI(this, Constants.APP_ID);
        api.handleIntent(getIntent(), this);
        api.registerApp(Constants.APP_ID);
    }


    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        setIntent(intent);
        api.handleIntent(intent, this);
    }


    @Override
    public void onReq(BaseReq req) {

    }


    @Override
    public void onResp(BaseResp resp) {
        int errCode = resp.errCode;

        if (errCode == 0) {

            // 0         
            // Intent intent = new Intent("name");
            // sendBroadcast(intent);
            // Log.e("test","         --onResp--");
            // Toast.makeText(this,"    ",Toast.LENGTH_SHORT).show();

            new AlertDialog.Builder(this).setMessage("    ").setPositiveButton("  ", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    dialog.dismiss();
                    finish();
                    PaymentActivity.instance.finish();

                    Intent intent = new Intent(WXPayEntryActivity.this, PuzzGameActivity.class);
                    intent.putExtra("ISPLAY",true);
                    startActivity(intent);

                }
            }).setTitle("  ").create().show();

            Toast.makeText(this,"                ",Toast.LENGTH_LONG).show();

        }
        else if (errCode == -1) {
            //-1         :    、   APPID、    APPID   、   APPID       、     。
            new AlertDialog.Builder(this).setMessage("    ").setPositiveButton("  ", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    dialog.dismiss();
                    finish();
                }
            }).setTitle("  ").create().show();
            finish();
        }
        else if (errCode == -2) {
            //-2          。    :      ,    ,  APP。
            finish();
        }
    }


}

これですべてのステップがほぼ完全になり、公式の例とドキュメントを組み合わせると、プロジェクトに支払い機能を迅速に追加できるはずです.
もちろん、ここで触れた手順はすべてappクライアントで行われていますが、公式サイトでは署名取得などの操作をサービスバックグラウンドで行うことをお勧めしています.安全のためでしょう.つまり、カスタマーサービス側が注文情報をサービス側に伝えることです.サービス側は、支払いを吊り上げるために必要な情報を返します.
(perpay_id、商家id、署名などを含む)その後、クライアントが微信を吊り上げて支払う.