微信第三方登录和支付
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.java,MD5Util.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(); } }
相关文章推荐
- 微信企业号 - OAuth验证接口
- 微信登录的文章-二维码网页登录和微信中登录
- 微信二维码网页登录、支付宝手机二维码支付模式实现
- 【JavaWeb】(10)微信公众号开发进阶
- 微信企业号开发:主动发送消息
- 绘图.java(小程序查看器)
- java小程序查看器
- 小程序查看器的用法.java
- 微信开发笔记-调用自定义分享接口
- 微信JS-SDK
- 微信公众平台开发时需要判断微信浏览器访问
- 微信企业号(服务号)坐标定位发生偏移解决方案记录( 附PHP代码)
- IOS高访微信聊天对话界面(sizeWithFont:constrainedToSize和stretchableImageWithLeftCapWidth的使用)
- 使用Android编写录制视频小程序示例
- 统计数组中元素出现的次数——Java小程序
- java版微信支付
- 微信应用签名生成工具
- iOS下微信语音播放之切换听筒和扬声器的方法解决方案
- 微信整合的时候 出现这个“redirect_uri 参数错误”
- Android ActionBar应用实战,高仿微信主界面的设计