您的位置:首页 > 移动开发 > 微信开发

微信第三方登录和支付

2015-07-24 11:49 633 查看

微信登录

获取access_token时序图:

1. 第三方发起微信授权登录请求,微信用户允许授权第三方应用后,微信会拉起应用或重定向到第三方网站,并且带上授权临时票据code参数;

2. 通过code参数加上AppID和AppSecret等,通过API换取access_token;

3. 通过access_token进行接口调用,获取用户基本数据资源或帮助用户实现基本操作。



下载微信最新sdk,集成jar包到app中。



2.定义微信登录所需参数常量 ,基本配置

public static class WeiXin {
// 请同时修改 androidmanifest.xml里面,添加调用微信支付的activity里的属性<data
// android:scheme="wxe9546a8b8614b7c6"/>
// appid
public static final String APP_ID = "wxe95468u8u8614b7c6";
public static final String AppSecret = "12aac456789k899895";
// 商户号
public static final String MCH_ID = "1278888801";
// API密钥,在商户平台设置
public static final String API_KEY = "ghjkllljhh787787yh78yh78## 标题 ##";
// 接收微信支付异步通知回调地址
public static final String notify_url = "";
// 微信授权域
public static final String scope = "snsapi_userinfo";
public static BaseResp resp;// 登录信息
public static BaseResp PayResp;// 支付信息
}


在androidmainifest.xml中注册微信回调activity,注意定义的activity必须在wxapi包下面。否则无法回调

<!-- 用户微信回调的 activity -->
<activity
android:name=".wxapi.WXEntryActivity"
android:exported="true"
android:label="@string/app_name"
android:launchMode="singleTop"
android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen" >
</activity>


3.微信登录工具类

package com.zhimei.beck.utils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONException;
import org.json.JSONObject;

/**
*
* @ClassName: WXLoginUtil
* @Description: 微信登录工具类
* @author 胡业辉
* @date 2015年7月22日
*
*/
public class WXLoginUtil {
private static String get_access_token = "";
// 获取第一步的code后,请求以下链接获取access_token
public static String GetCodeRequest = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
// 获取用户个人信息
public static String GetUserInfo = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID";

/**
* 获取access_token的URL(微信)
*
* @param code
*            授权时,微信回调给的
* @return URL
*/
public static String getCodeRequest(String code) {
String result = null;
GetCodeRequest = GetCodeRequest.replace("APPID",
urlEnodeUTF8(Constants.WeiXin.APP_ID));
GetCodeRequest = GetCodeRequest.replace("SECRET",
urlEnodeUTF8(Constants.WeiXin.AppSecret));
GetCodeRequest = GetCodeRequest.replace("CODE", urlEnodeUTF8(code));
result = GetCodeRequest;
return result;
}

/**
* 获取access_token等等的信息(微信)
*/
public String WXGetAccessToken(String weixinCode) {
HttpClient get_access_token_httpClient = new DefaultHttpClient();
get_access_token = getCodeRequest(weixinCode);
String access_token = "";
String openid = "";
try {
HttpPost postMethod = new HttpPost(get_access_token);
HttpResponse response = get_access_token_httpClient
.execute(postMethod); // 执行POST方法
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
InputStream is = response.getEntity().getContent();
BufferedReader br = new BufferedReader(
new InputStreamReader(is));
String str = "";
StringBuffer sb = new StringBuffer();
while ((str = br.readLine()) != null) {
sb.append(str);
}
is.close();
String josn = sb.toString();
JSONObject json1 = new JSONObject(josn);
access_token = (String) json1.get("access_token");
openid = (String) json1.get("openid");
} else {
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return getUserInfo(access_token, openid);

}

/**
* 获取用户个人信息的URL(微信)
*
* @param access_token
*            获取access_token时给的
* @param openid
*            获取access_token时给的
* @return URL
*/
public String getUserInfo(String access_token, String openid) {
String result = null;
GetUserInfo = GetUserInfo.replace("ACCESS_TOKEN",
urlEnodeUTF8(access_token));
GetUserInfo = GetUserInfo.replace("OPENID", urlEnodeUTF8(openid));
result = GetUserInfo;
return result;
}

/**
* 获取微信用户个人信息
*
* @param get_user_info_url
*            调用URL
*/
public Map<String, String> WXGetUserInfo(String get_user_info_url) {
HttpClient get_access_token_httpClient = new DefaultHttpClient();
Map<String, String> info = new HashMap<String, String>();
try {
HttpGet getMethod = new HttpGet(get_user_info_url);
HttpResponse response = get_access_token_httpClient
.execute(getMethod); // 执行GET方法
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
InputStream is = response.getEntity().getContent();
BufferedReader br = new BufferedReader(
new InputStreamReader(is));
String str = "";
StringBuffer sb = new StringBuffer();
while ((str = br.readLine()) != null) {
sb.append(str);
}
is.close();
String josn = sb.toString();
JSONObject json1 = new JSONObject(josn);
info.put("openid", (String) json1.get("openid"));
info.put("nickname", (String) json1.get("nickname"));
info.put("headimgurl", (String) json1.get("headimgurl"));
} else {
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return info;
}

public static String urlEnodeUTF8(String str) {
String result = str;
try {
result = URLEncoder.encode(str, "UTF-8");
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
}


定义微信回调activity。用于接收登陆成功后返回信息,在这里我将返回信息存放到一个全局变量中,在回调完成后在onresume()中进行获取操作。

public class WXEntryActivity extends FrontiaWeixinShareActivity implements
IWXAPIEventHandler {
private IWXAPI api;
private BaseResp resp = null;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
api = WXAPIFactory.createWXAPI(this, Constants.WeiXin.APP_ID, false);
api.handleIntent(getIntent(), this);
}

@Override
protected boolean handleIntent() {
if (super.handleIntent()) {
return true;
} else {
return false;
}
}

// 微信发送请求到第三方应用时,会回调到该方法
@Override
public void onReq(BaseReq req) {
finish();
}

@Override
public void onResp(BaseResp resp) {
String result = "";
if (resp != null) {
this.resp = resp;
Constants.WeiXin.resp = resp;
}
switch (resp.errCode) {
case BaseResp.ErrCode.ERR_OK:
result = "发送成功";
finish();
break;
case BaseResp.ErrCode.ERR_USER_CANCEL:
result = "发送取消";
finish();
break;
case BaseResp.ErrCode.ERR_AUTH_DENIED:
result = "发送被拒绝";
finish();
break;
default:
result = "发送返回";
finish();
break;
}
}

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


基本所需要的东西都已有,下面将进行调用微信登录,这里微信登入必须要用户手机安装微信客户端才可。

private IWXAPI mWeixinAPI;
private String weixinCode;
private BaseResp resp;

/*
* 微信授权
*/
private void startWinxi() {
if (mWeixinAPI == null) {
mWeixinAPI = WXAPIFactory.createWXAPI(this,
Constants.WeiXin.APP_ID, false);
}
if (!mWeixinAPI.isWXAppInstalled()) {
// 提醒用户没有按照微信
return;
}
mWeixinAPI.registerApp(Constants.WeiXin.APP_ID);
SendAuth.Req req = new SendAuth.Req();
req.scope = Constants.WeiXin.scope;
req.state = "wechat_sdk_demo_test";
mWeixinAPI.sendReq(req);
}


回调后在onresume()方法中获取微信登录信息

@Override
protected void onResume() {
super.onResume();

if (Constants.WeiXin.resp != null) {
resp = Constants.WeiXin.resp;
Constants.WeiXin.resp = null;
if (resp.getType() == ConstantsAPI.COMMAND_SENDAUTH) {
// code返回
weixinCode = ((SendAuth.Resp) resp).code;
/*
* 将你前面得到的AppID、AppSecret、code,拼接成URL
*/
Thread thread = new Thread(downloadRun);
thread.start();
try {
thread.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}

public Runnable downloadRun = new Runnable() {

@Override
public void run() {
WXLoginUtil wxLoginUtil = new WXLoginUtil();
String get_user_info_url = wxLoginUtil.WXGetAccessToken(weixinCode);
//此处获取微信登录成功后的信息
Map<String, String> info = wxLoginUtil
.WXGetUserInfo(get_user_info_url);
}
};


微信支付

微信支付理论和微信登录一样,都是进行授权后调用微信相关功能,然后进行数据处理。首页下载官方sdK,将其中的MD5.javaMD5Util.java,**Util.java**Java文件及libammsdk.jar导入到项目中。然后再进行参数配置,同时修改androidmanifest.xml文件,这里我在上方微信登录已配置好。

微信支付首先需要将app注册到微信:

final IWXAPI msgApi = WXAPIFactory.createWXAPI(aty, null);
// 将该app注册到微信
msgApi.registerApp(Constants.WeiXin.APP_ID);


然后调用服务段接口,通过服务去生成一个订单号。然后再去进行支付操作。这里我整合了一个支付工具类,如下,具体参数可根据需求进行修改:

package com.zhimei.beck.wxapi;

import java.io.StringReader;
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 android.annotation.SuppressLint;
import android.app.Dialog;
import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;
import android.util.Xml;

import com.tencent.mm.sdk.modelpay.PayReq;
import com.tencent.mm.sdk.openapi.IWXAPI;
import com.tencent.mm.sdk.openapi.WXAPIFactory;
import com.zhimei.beck.utils.Constants;
import com.zhimei.beck.utils.DialogUtil;

/**
*
* @ClassName: WXPayUtil
* @Description:微信支付工具类
* @author 胡业辉
* @date 2015年7月24日
*
*/
public class WXPayUtil {
PayReq req;
IWXAPI msgApi;
Dialog dialog;
Map<String, String> resultunifiedorder;
Context context;

public WXPayUtil(Context context) {
this.context = context;
this.msgApi = WXAPIFactory.createWXAPI(context, null);
this.msgApi.registerApp(Constants.WeiXin.APP_ID);
this.req = new PayReq();

}

public void startPay(String body, String outTradeNo, String price) {
this.dialog = DialogUtil.createLoadingDialog(context, "加载中......");
new GetPrepayIdTask(body, outTradeNo, price).execute();
}

public class GetPrepayIdTask extends
AsyncTask<Void, Void, Map<String, String>> {
private String body;
private String outTradeNo;
private String price;

public GetPrepayIdTask(String body, String outTradeNo, String price) {
super();
this.body = body;
this.outTradeNo = outTradeNo;
this.price = price;
}

@Override
protected void onPreExecute() {
dialog.show();
}

@Override
protected Map<String, String> doInBackground(Void... params) {
String url = String
.format("https://api.mch.weixin.qq.com/pay/unifiedorder");
String entity = genProductArgs(body, outTradeNo, price);
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;
}

@Override
protected void onPostExecute(Map<String, String> result) {
if (dialog != null) {
dialog.dismiss();
}
resultunifiedorder = result;
genPayReq();
}

@Override
protected void onCancelled() {
super.onCancelled();
}

}

/*
* 生成订单参数
*/
private String genProductArgs(String body, String outTradeNo, String price) {
StringBuffer xml = new StringBuffer();
try {
price = Integer.parseInt(price) * 100 + "";
String nonceStr = genNonceStr();
xml.append("</xml>");
List<NameValuePair> packageParams = new LinkedList<NameValuePair>();
packageParams.add(new BasicNameValuePair("appid",
Constants.WeiXin.APP_ID));
// 商品或支付单简要描述
packageParams.add(new BasicNameValuePair("body", body));
packageParams.add(new BasicNameValuePair("mch_id",
Constants.WeiXin.MCH_ID));
// 随机字符串
packageParams.add(new BasicNameValuePair("nonce_str", nonceStr));
// 接收微信支付异步通知回调地址
packageParams.add(new BasicNameValuePair("notify_url",
Constants.WeiXin.notify_url));
// 商户系统内部的订单号,32个字符内、可包含字母, 其他说明见商户订单号
packageParams
.add(new BasicNameValuePair("out_trade_no", outTradeNo));
// 终端IP APP和网页支付提交用户端ip,Native支付填调用微信支付API的机器IP。
packageParams.add(new BasicNameValuePair("spbill_create_ip",
"127.0.0.1"));
// 总金额 订单总金额,只能为整数,详见支付金额
packageParams.add(new BasicNameValuePair("total_fee", price));
// 交易类型
packageParams.add(new BasicNameValuePair("trade_type", "APP"));
String sign = genPackageSign(packageParams);
packageParams.add(new BasicNameValuePair("sign", sign));
String xmlstring = toXml(packageParams);
return new String(xmlstring.toString().getBytes(), "ISO8859-1");
} catch (Exception e) {
return null;
}

}

/*
* 支付接口请求参数
*/
private void genPayReq() {
req.appId = Constants.WeiXin.APP_ID;
req.partnerId = Constants.WeiXin.MCH_ID;
req.prepayId = resultunifiedorder.get("prepay_id");
req.packageValue = "Sign=WXPay";
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));
// 扩展字段 暂填写固定值Sign=WXPay
signParams.add(new BasicNameValuePair("package", req.packageValue));
// 商户号
signParams.add(new BasicNameValuePair("partnerid", req.partnerId));
// 预支付交易会话ID 微信返回的支付交易会话ID
signParams.add(new BasicNameValuePair("prepayid", req.prepayId));
// 时间戳
signParams.add(new BasicNameValuePair("timestamp", req.timeStamp));
req.sign = genAppSign(signParams);
sendPayReq();
}

/*
* 调起微信支付
*/
private void sendPayReq() {
msgApi.registerApp(Constants.WeiXin.APP_ID);
msgApi.sendReq(req);
}

/**
* 生成签名
*/

@SuppressLint("DefaultLocale")
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.WeiXin.API_KEY);
String packageSign = MD5.getMessageDigest(sb.toString().getBytes())
.toUpperCase();
Log.e("orion", packageSign);
return packageSign;
}

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.WeiXin.API_KEY);

String appSign = MD5.getMessageDigest(sb.toString().getBytes())
.toUpperCase();
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();
}

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;

}

private String genNonceStr() {
Random random = new Random();
return MD5.getMessageDigest(String.valueOf(random.nextInt(10000))
.getBytes());
}

private long genTimeStamp() {
return System.currentTimeMillis() / 1000;
}

}


4.支付后,会回调WXPayEntryActivity.java,将返回信息保存在全局变量中。然后再onresume()方法中进行处理。

package com.zhimei.beck.wxapi;

import com.tencent.mm.sdk.constants.ConstantsAPI;
import com.tencent.mm.sdk.modelbase.BaseReq;
import com.tencent.mm.sdk.modelbase.BaseResp;
import com.tencent.mm.sdk.openapi.IWXAPI;
import com.tencent.mm.sdk.openapi.IWXAPIEventHandler;
import com.tencent.mm.sdk.openapi.WXAPIFactory;
import com.zhimei.beck.R;
import com.zhimei.beck.utils.Constants;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;

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.pay_result);
api = WXAPIFactory.createWXAPI(this, Constants.WeiXin.APP_ID);
api.handleIntent(getIntent(), this);
}

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

@Override
public void onReq(BaseReq req) {
finish();
}

@Override
public void onResp(BaseResp resp) {
Log.d(TAG, "onPayFinish, errCode = " + resp.errCode);
if (resp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX) {
Constants.WeiXin.PayResp = resp;
}
finish();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: