Android—基於開放平台v3SDK,開發支付填坑。,androidv3sdk
接觸支付之前聽說過這是一個坑,,,心裡已經有了準備。。。我以為我沒準跳坑出不來了,沒有想到我填上了,調用成功之後我感覺公司所有的同事都是漂亮的,隔著北京的大霧霾我彷彿看見了太陽~~~好了,裝逼結束。。。進入正題
開發準備:
1.在開放平台申請帳號
2.成功後建立應用,就是填一些看似很官方很正經的資料了。。。(說審核7天左右,沒有意外的情況下你的app第二天就審核成功了是不是很開心,有了appid,是不是就可以調用微 信支付了????-------想多了,真的)
3.支付是需要額外申請的:需要資料審核,賬戶驗證,協議簽署等步驟,(我記得,,資料審核要填寫的東西好多,,,好多,,,賬戶驗證就是你審核成功後會發送郵件到你 註冊時登記的郵箱帳號,其中含有隨機金額用於賬戶驗證,協議簽署,略,太簡單)一定要好好閱讀你郵件的任何資訊,因為有的細節錯了,,,你可能填坑很久。。。。。。
正式開發階段:
問題1:
調用官方的SDK發現只能成功的調起一次,再次支付的時候怎麼也調用不起來了
解決:
似乎不是什麼正經方法:在手機設定中管理應用程式,清除資料,緩衝,,再來一遍,絕對可以調起來(當然還是只是一次。。。。)
繼續:
我認為要用支付嘛,,就只看了調用支付介面的文檔:
後來發現需要的參數prepayid是怎麼也找不到啊,,後來才發現這個prepayid是先調用”統一下單“這個介面時候溫馨反過來的東西,但是官方的SDK中並沒有統一下單的代碼。坑嗎???
所以要先看統一下單文檔了
1.使用自己的APP調用的時候把官網down下來的SDK中WXPayEntryActivity拷貝到自己的項目,所在包的名字最後一定是.wxapi(我連包一起拷了。。。。)
2.在項目資訊清單檔中填寫:
3.SDK中的AppRegister拷貝下來,,,裡面換成你自己的appid,然後在項目清單中也註冊一下。
4.重點來了,,就是你APP要調支付的activity,我這還叫PayActivity
要調起支付頁面,要在這個activity中,將你的app註冊到
接下來先調用統一下單擷取prepayid,參數,人家要xml格式的!我們就得發送xml格式的!
好了調用的時候把這個方法的傳回值當參數傳,,等待返回success吧!。。
我遇見的錯誤:簽名錯誤
我的原因是大意了 ConfigUtil.NOTIFY_URL這個參數寫的Null 字元串
還有是因為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;@Overrideprotected 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() {@Overridepublic void onClick(View v) {GetPrepayIdTask getPrepayId = new GetPrepayIdTask();getPrepayId.execute();}});/** * 將該app註冊到 */check_pay_btn.setOnClickListener(new View.OnClickListener() {@Overridepublic 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;@Overrideprotected void onPreExecute() {dialog = ProgressDialog.show(PayActivity.this, getString(R.string.app_tip),getString(R.string.getting_prepayid));}@Overrideprotected void onPostExecute(Map<String, String> result) {if (dialog != null) {dialog.dismiss();}sb.append("prepay_id\n" + result.get("prepay_id") + "\n\n");resultunifiedorder = result;}@Overrideprotected void onCancelled() {super.onCancelled();}@Overrideprotected 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 自己下載一下拷貝一下。。。
參考部落格 https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_1
備忘,希望能給大家帶來協助。。。