android實現微信支付
阿新 • • 發佈:2019-01-31
微信支付給大家先過一個邏輯,想要執行微信的分享、支付等功能,必須要進行獲取AccessToken,獲取AccessToken必須要在微信開放平臺註冊一個賬號,並且建立一個應用,稽核通過後得到appkey與APP_SECRET,通過這兩個引數去呼叫new GetAccessTokenTask().execute();去獲得AccessToken(注意呼叫支付時要註冊下api.registerApp(Constants.APP_ID); ),然後再執行new
GetPrepayIdTask(result.accessToken);方法去獲取prepayid。接下來就是呼叫sendPayReq方法,去呼叫支付介面。
支付需要商戶祕鑰,應該是在開放平臺開通支付功能後給的祕鑰,由於沒有開通支付功能,所以直接用官方demo上的包名和祕鑰,appkey等,程式碼也是從官方demo拆分下的,只要把Constants中APP_ID,PARTNER_KEY,APP_KEY,APP_SECRET,PARTNER_ID替換成你自己的,就能用了,如果替換包名要一致。不替換就是呼叫官方的,直接上程式碼吧。 demo下載地址http://download.csdn.net/detail/u012303938/8434105
Constants類
MainActivity類package net.sourceforge.simcpux; public class Constants { public static final String APP_ID = "wxd930ea5d5a258f4f"; public static final String PARTNER_KEY = "8934e7d15453e97507ef794cf7b0519d"; public static final String APP_KEY = "L8LrMqqeGRxST5reouB0K66CaYAWpqhAVsq7ggKkxHCOastWksvuX1uvmvQclxaHoYd3ElNBrNO2DHnnzgfVG9Qs473M3DTOZug5er46FhuGofumV8H2FVR9qkjSlC5K"; // wxd930ea5d5a258f4f 對應的支付金鑰 /** * 微信開放平臺和商戶約定的金鑰 * * 注意:不能hardcode在客戶端,建議genSign這個過程由伺服器端完成 */ public static final String APP_SECRET = "db426a9829e4b49a0dcac7b4162da6b6"; // wxd930ea5d5a258f4f 對應的金鑰 public static final String PARTNER_ID = "1900000109"; public static class ShowMsgActivity { public static final String STitle = "showmsg_title"; public static final String SMessage = "showmsg_message"; public static final String BAThumbData = "showmsg_thumb_data"; } }
package net.sourceforge.simcpux; import java.util.LinkedList; import java.util.List; import java.util.Random; import org.apache.http.NameValuePair; import org.apache.http.client.utils.URLEncodedUtils; import org.apache.http.message.BasicNameValuePair; import org.json.JSONObject; import com.tencent.mm.sdk.constants.Build; import com.tencent.mm.sdk.modelpay.PayReq; import com.tencent.mm.sdk.openapi.IWXAPI; import com.tencent.mm.sdk.openapi.WXAPIFactory; import android.os.AsyncTask; import android.os.Bundle; import android.app.Activity; import android.app.ProgressDialog; import android.util.Log; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.Toast; public class MainActivity extends Activity { private static final String TAG = "Values"; private IWXAPI api; private Button btn_pay; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); api = WXAPIFactory.createWXAPI(this, Constants.APP_ID, false); findView(); addListener(); } private void addListener() { // TODO Auto-generated method stub btn_pay.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { // TODO Auto-generated method stub //根據微信的例子去獲取token //boolean isPaySupported = api.getWXAppSupportAPI() >= Build.PAY_SUPPORTED_SDK_INT; //Toast.makeText(MainActivity.this, String.valueOf(isPaySupported), Toast.LENGTH_SHORT).show(); new GetAccessTokenTask().execute(); } }); } private class GetAccessTokenTask extends AsyncTask<Void, Void, GetAccessTokenResult> { @Override protected void onPreExecute() { } @Override protected void onPostExecute(GetAccessTokenResult result) { if (result.localRetCode == LocalRetCode.ERR_OK) { Toast.makeText(MainActivity.this, "獲取access token成功", Toast.LENGTH_LONG).show(); Log.d(TAG, "onPostExecute, accessToken = " + result.accessToken); Log.i("values", "say:2"); GetPrepayIdTask getPrepayId = new GetPrepayIdTask(result.accessToken); getPrepayId.execute(); } else { Log.i("values", "say:1"); Toast.makeText(MainActivity.this, getString(R.string.get_access_token_fail, result.localRetCode.name()), Toast.LENGTH_LONG).show(); } } @Override protected GetAccessTokenResult doInBackground(Void... params) { GetAccessTokenResult result = new GetAccessTokenResult(); /* * 執行獲取token操作 */ String url = String.format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s", Constants.APP_ID, Constants.APP_SECRET); Log.d(TAG, "get access token, url = " + url); byte[] buf = Util.httpGet(url); if (buf == null || buf.length == 0) { result.localRetCode = LocalRetCode.ERR_HTTP; Log.d(TAG, "get access token, url = " + url); return result; } String content = new String(buf); result.parseFrom(content); Log.i("values", "result:" + content); return result; } } private static class GetPrepayIdResult { private static final String TAG = "MicroMsg.SDKSample.MainActivity.GetPrepayIdResult"; public LocalRetCode localRetCode = LocalRetCode.ERR_OTHER; public String prepayId; public int errCode; public String errMsg; public void parseFrom(String content) { if (content == null || content.length() <= 0) { Log.e(TAG, "parseFrom fail, content is null"); localRetCode = LocalRetCode.ERR_JSON; return; } try { JSONObject json = new JSONObject(content); if (json.has("prepayid")) { // success case prepayId = json.getString("prepayid"); localRetCode = LocalRetCode.ERR_OK; } else { localRetCode = LocalRetCode.ERR_JSON; } errCode = json.getInt("errcode"); errMsg = json.getString("errmsg"); } catch (Exception e) { localRetCode = LocalRetCode.ERR_JSON; } } } private static class GetAccessTokenResult { private static final String TAG = "MicroMsg.SDKSample.MainActivity.GetAccessTokenResult"; public LocalRetCode localRetCode = LocalRetCode.ERR_OTHER; public String accessToken; public int expiresIn; public int errCode; public String errMsg; public void parseFrom(String content) { if (content == null || content.length() <= 0) { Log.e(TAG, "parseFrom fail, content is null"); localRetCode = LocalRetCode.ERR_JSON; return; } try { JSONObject json = new JSONObject(content); if (json.has("access_token")) { // success case accessToken = json.getString("access_token"); expiresIn = json.getInt("expires_in"); localRetCode = LocalRetCode.ERR_OK; } else { errCode = json.getInt("errcode"); errMsg = json.getString("errmsg"); localRetCode = LocalRetCode.ERR_JSON; } } catch (Exception e) { localRetCode = LocalRetCode.ERR_JSON; } } } private void findView() { // TODO Auto-generated method stub btn_pay=(Button) findViewById(R.id.btn_pay); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } private String genNonceStr() { Random random = new Random(); return MD5.getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes()); } private long genTimeStamp() { return System.currentTimeMillis() / 1000; } /** * 建議 traceid 欄位包含使用者資訊及訂單資訊,方便後續對訂單狀態的查詢和跟蹤 */ private String getTraceId() { return "crestxu_" + genTimeStamp(); } /** * 注意:商戶系統內部的訂單號,32個字元內、可包含字母,確保在商戶系統唯一 */ private String genOutTradNo() { Random random = new Random(); return MD5.getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes()); } private long timeStamp; private String nonceStr, packageValue; private String genSign(List<NameValuePair> params) { StringBuilder sb = new StringBuilder(); int i = 0; for (; i < params.size() - 1; i++) { sb.append(params.get(i).getName()); sb.append('='); sb.append(params.get(i).getValue()); sb.append('&'); } sb.append(params.get(i).getName()); sb.append('='); sb.append(params.get(i).getValue()); String sha1 = Util.sha1(sb.toString()); Log.d(TAG, "genSign, sha1 = " + sha1); return sha1; } private String genProductArgs() { JSONObject json = new JSONObject(); try { json.put("appid", Constants.APP_ID); String traceId = getTraceId(); // traceId 由開發者自定義,可用於訂單的查詢與跟蹤,建議根據支付使用者資訊生成此id json.put("traceid", traceId); nonceStr = genNonceStr(); json.put("noncestr", nonceStr); List<NameValuePair> packageParams = new LinkedList<NameValuePair>(); packageParams.add(new BasicNameValuePair("bank_type", "WX")); packageParams.add(new BasicNameValuePair("body", "千足金箍棒")); packageParams.add(new BasicNameValuePair("fee_type", "1")); packageParams.add(new BasicNameValuePair("input_charset", "UTF-8")); packageParams.add(new BasicNameValuePair("notify_url", "http://weixin.qq.com")); packageParams.add(new BasicNameValuePair("out_trade_no", genOutTradNo())); packageParams.add(new BasicNameValuePair("partner", "1900000109")); packageParams.add(new BasicNameValuePair("spbill_create_ip", "196.168.1.1")); packageParams.add(new BasicNameValuePair("total_fee", "1")); packageValue = genPackage(packageParams); json.put("package", packageValue); timeStamp = genTimeStamp(); json.put("timestamp", timeStamp); List<NameValuePair> signParams = new LinkedList<NameValuePair>(); signParams.add(new BasicNameValuePair("appid", Constants.APP_ID)); signParams.add(new BasicNameValuePair("appkey", Constants.APP_KEY)); signParams.add(new BasicNameValuePair("noncestr", nonceStr)); signParams.add(new BasicNameValuePair("package", packageValue)); signParams.add(new BasicNameValuePair("timestamp", String.valueOf(timeStamp))); signParams.add(new BasicNameValuePair("traceid", traceId)); json.put("app_signature", genSign(signParams)); json.put("sign_method", "sha1"); } catch (Exception e) { Log.e(TAG, "genProductArgs fail, ex = " + e.getMessage()); return null; } return json.toString(); } private void sendPayReq(GetPrepayIdResult result) { PayReq req = new PayReq(); req.appId = Constants.APP_ID; req.partnerId = Constants.PARTNER_ID; req.prepayId = result.prepayId; req.nonceStr = nonceStr; req.timeStamp = String.valueOf(timeStamp); req.packageValue = "Sign=" + packageValue; List<NameValuePair> signParams = new LinkedList<NameValuePair>(); signParams.add(new BasicNameValuePair("appid", req.appId)); signParams.add(new BasicNameValuePair("appkey", Constants.APP_KEY)); 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 = genSign(signParams); // 在支付之前,如果應用沒有註冊到微信,應該先呼叫IWXMsg.registerApp將應用註冊到微信 api.sendReq(req); } private static enum LocalRetCode { ERR_OK, ERR_HTTP, ERR_JSON, ERR_OTHER } private String genPackage(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.PARTNER_KEY); // 注意:不能hardcode在客戶端,建議genPackage這個過程都由伺服器端完成 // 進行md5摘要前,params內容為原始內容,未經過url encode處理 String packageSign = MD5.getMessageDigest(sb.toString().getBytes()).toUpperCase(); return URLEncodedUtils.format(params, "utf-8") + "&sign=" + packageSign; } private class GetPrepayIdTask extends AsyncTask<Void, Void, GetPrepayIdResult> { private ProgressDialog dialog; private String accessToken; public GetPrepayIdTask(String accessToken) { this.accessToken = accessToken; } @Override protected void onPreExecute() { } @Override protected void onPostExecute(GetPrepayIdResult result) { if (dialog != null) { dialog.dismiss(); } if (result.localRetCode == LocalRetCode.ERR_OK) { Toast.makeText(MainActivity.this, "獲取prepayid成功", Toast.LENGTH_LONG).show(); sendPayReq(result); } else { Toast.makeText(MainActivity.this, getString(R.string.get_prepayid_fail, result.localRetCode.name()), Toast.LENGTH_LONG).show(); } } @Override protected void onCancelled() { super.onCancelled(); } @Override protected GetPrepayIdResult doInBackground(Void... params) { String url = String.format("https://api.weixin.qq.com/pay/genprepay?access_token=%s", accessToken); String entity = genProductArgs(); Log.d(TAG, "doInBackground, url = " + url); Log.d(TAG, "doInBackground, entity = " + entity); GetPrepayIdResult result = new GetPrepayIdResult(); byte[] buf = Util.httpPost(url, entity); if (buf == null || buf.length == 0) { result.localRetCode = LocalRetCode.ERR_HTTP; return result; } String content = new String(buf); Log.d(TAG, "doInBackground, content = " + content); result.parseFrom(content); return result; } } }
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<Button
android:id="@+id/btn_pay"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="呼叫微信支付" />
</RelativeLayout>