微信支付给大家先过一个逻辑,想要执行微信的分享、支付等功能,必须要进行获取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类
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";
}
}
MainActivity类
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>