本文章仅作为个人笔记
微信Android接入指南,需要登陆后查看(开放平台->资源中心->开发资源->移动应用->接入指南)
微信IOS接入指南,需要登陆后查看(开放平台->资源中心->开发资源->移动应用->接入指南)
微信开放平台
- 首先要注册成为微信开放平台用户
- 通过开发者资质认证
- 提供个人信息
- 提供公司营业执照等信息
- 300rmb
- 创建移动应用并通过审核
- 提供应用描述
- 提供应用logo
- 提供应用安装包
- 提供应用签名信息(建议下载官方签名获取apk获取签名提交,另外万一签名错误导致登录时返回-6错误码,网页更改签名后需要清理客户端微信缓存再重新尝试。)
- 万事具备后可以查看到应用的AppID和AppSecret
- 开始代码模块
- IOS端(swift):
-
导入第三方库(cocopods集成)(记得 pod install):
pod 'WechatOpenSDK'
-
引用:在桥接文件中添加以下代码(桥接文件为项目根目录下的.h文件,如果没有可创建并添加)
#import "WXApi.h"
-
部分设置:
打开项目info.plist,加入如下代码(主要是NSAllowsArbitraryLoads及其值还有就是weixin/wechat):<key>NSAppTransportSecurity</key> <dict> <key>NSAllowsArbitraryLoads</key> <true/> </dict> <key>LSApplicationQueriesSchemes</key> <array> <string>weixin</string> <string>wechat</string> </array>
-
-
等所有配置完毕即可进行编程了。
-
先贴上AppDelegate部分主要代码
@UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var wechatAuthBack: HttpUtilsBack? var wechatPayBack: HttpUtilsBack? func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { _ = WXApi.registerApp(StaticParam.WECHART_APPID)//appid字符串 return true } func application(_ application: UIApplication, handleOpen url: URL) -> Bool { switch url.scheme { case StaticParam.WECHART_APPID: _ = WXApi.handleOpen(url, delegate: self) default: print("handleOpenUrl1") } return true } func application(_ application: UIApplication, open url: URL , sourceApplication: String?, annotation: Any) -> Bool { switch url.scheme { case StaticParam.WECHART_APPID: _ = WXApi.handleOpen(url, delegate: self) default: print("handleOpenUrl2") } return true } } extension AppDelegate: WXApiDelegate { func onReq(_ req: BaseReq!) { } func onResp(_ resp: BaseResp!) { var code: String? var error: BaseError? if resp.isKind(of: SendAuthResp.self) { let authResp = resp as! SendAuthResp if authResp.errCode == 0 { code = authResp.code } else { error = BaseError(authResp.errStr) } } else if resp.isKind(of: PayResp.self) { let payResp = resp as! PayResp if payResp.errCode == 0 { code = payResp.returnKey } else { error = BaseError(payResp.errStr) } } if wechatAuthBack != nil { if error == nil && code == nil { error = "登录失败" } wechatAuthBack?.finish(result: code, error: error) } else if wechatPayBack != nil { if error == nil && code == nil { error = "支付失败" } wechatPayBack?.finish(result: code, error: error) } } } protocol HttpUtilsBack { func finish(result: String?, error: BaseError?) }
-
再贴上登录部分主要代码
let req = SendAuthReq() req.scope = "snsapi_userinfo" //获取用户信息 req.state = String(Date().timeIntervalSince1970) //随机值即可,这里用时间戳 WXApi.send(req)
-
贴上登录回调代码:
appDelegate?.wechatAuthBack = WechatAuthBack() //创建回调类 struct WechatAuthBack: HttpUtilsBack { func finish(result: String?, error: BaseError?) { if error == nil { //登录成功回调 } else { //登录失败回调 } } }
-
-
如果调用成功会回调onResp方法,后续在onResp内处理即可,处于安全考虑,建议用户信息解析给服务器端处理,这里直接将获取的信息上传至服务器即可
-
Android端:
-
引入jar包(在build.gradle文件内)
dependencies { api 'com.tencent.mm.opensdk:wechat-sdk-android-with-mta:+' }
-
添加必要权限
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
-
登录相关代码
//初始化IWXAPI实例 IWXAPI api = WXAPIFactory.createWXAPI(activity, appId, true); api.registerApp(appId); //初始化登录请求对象 SendAuth.Req req = new SendAuth.Req(); req.scope = "snsapi_userinfo"; req.state = String.valueOf(System.currentTimeMillis()); //发送登录请求 api.sendReq(req); //最后记得在activity的onDestroy方法内取消注册IWXAPI对象 api.unregisterApp();
-
登录结果接收类
-
在{包名}.wxapi下创建WXEntryActivity类
-
本人写的代码(WXEntryActivity)如下:
import android.app.Activity; import android.os.Bundle; import android.util.Log; import com.tencent.mm.opensdk.constants.ConstantsAPI; import com.tencent.mm.opensdk.modelbase.BaseReq; import com.tencent.mm.opensdk.modelbase.BaseResp; import com.tencent.mm.opensdk.modelmsg.SendAuth; import com.tencent.mm.opensdk.openapi.IWXAPIEventHandler; public class WXEntryActivity extends Activity implements IWXAPIEventHandler { public static final String APP_ID = "";//这里写自己的appid public static Back authBack; private IWXAPI api; public interface Back { public void onFiled(int errorCode); public void onSuccess(String code, String state); } public static void registAuthBack(Back back) { authBack = back; } public static void unregistAuthBack() { authBack = null; } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); api = WXAPIFactory.createWXAPI(this, appId, true); api.handleIntent(this, this) } @Override public void onReq(BaseReq baseReq) { Log.e("-----1", "baseReq=" + baseReq); } @Override public void onResp(BaseResp baseResp) { switch (baseResp.getType()) { case ConstantsAPI.COMMAND_PAY_BY_WX: Log.e("-----1", "onPayFinish,errCode=" + baseResp.errCode); // 0:成功; -1:错误; -2:用户取消; break; case ConstantsAPI.COMMAND_SENDAUTH: Log.e("-----1", "onAuthFinish,errCode=" + baseResp.errCode); if (authBack != null) { // 0:成功; -1:错误; -2:用户取消; SendAuth.Resp authResp = (SendAuth.Resp) baseResp; if (authResp.errCode == 0) { authBack.onSuccess(authResp.code, authResp.state); } else { authBack.onFiled(baseResp.errCode); } } break; } finish(); } @Override protected void onDestroy() { super.onDestroy(); api.unregisterApp(); } }
-
记得在AndroidManifest.xml文件下注册此Activity时需使用如下格式(主要是确保有android:exported="true"属性):
<activity android:name=".wxapi.WXEntryActivity" android:exported="true" android:label="@string/app_name" />
-
相信大家也看到WXEntryActivity类下有个registAuthBack方法,传入了一个回调,这个就是当你调起微信登录后可以调用的,获取登录结果,返回的code字符串上传至服务器获取用户信息(也可以在客户端做,但是不安全,建议在服务器做)。
-
-
-
服务器端:
-
因为只是发送get请求然后解析结果,所以直接上2个工具类:
-
网络请求封装类:
import javax.net.ssl.HttpsURLConnection; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.Proxy; import java.net.URL; import java.util.HashMap; import java.util.List; import java.util.Map; public class HttpUtils { private String HTTPS = "https"; private String GET = "GET"; private String POST = "POST"; private static HttpUtils httpUtils; private HttpUtils() { } public static HttpUtils getInstance() { if (httpUtils == null) { httpUtils = new HttpUtils(); } return httpUtils; } public interface IWebCallback { void onCallback(int status, String message, Map<String, List<String>> heard, byte[] data); void onFail(int status, String message); } public byte[] getURLResponse(String urlString, HashMap<String, String> heads) { byte[] result = null; if (urlString != null) { HttpURLConnection conn = null; //连接对象 InputStream is = null; ByteArrayOutputStream baos = null; try { URL url = new URL(urlString); //URL对象 if (urlString.startsWith(HTTPS)) { conn = (HttpsURLConnection) url.openConnection(); } else { conn = (HttpURLConnection) url.openConnection(); } conn.setConnectTimeout(5 * 1000); conn.setDoOutput(true); conn.setRequestMethod(GET); if (heads != null) { for (String key : heads.keySet()) { conn.addRequestProperty(key, heads.get(key)); } } is = conn.getInputStream(); //获取输入流,此时才真正建立链接 baos = new ByteArrayOutputStream(); byte[] temp = new byte[1024]; int len; while ((len = is.read(temp)) != -1) { baos.write(temp, 0, len); } result = baos.toByteArray(); } catch (Exception e) { } finally { CloseUtils.closeSilently(is); CloseUtils.closeSilently(baos); if (conn != null) { conn.disconnect(); } } } return result; } public void getURLResponse(String urlString, HashMap<String, String> heads, IWebCallback iWebCallback) { getURLResponse(urlString, heads, null, iWebCallback); } public void getURLResponse(String urlString, HashMap<String, String> heads, Proxy proxy, IWebCallback iWebCallback) { if (urlString != null) { HttpURLConnection conn = null; //连接对象 InputStream is = null; ByteArrayOutputStream baos = null; try { URL url = new URL(urlString); //URL对象 if (proxy == null) { if (urlString.startsWith(HTTPS)) { conn = (HttpsURLConnection) url.openConnection(); } else { conn = (HttpURLConnection) url.openConnection(); } } else { if (urlString.startsWith(HTTPS)) { conn = (HttpsURLConnection) url.openConnection(proxy); } else { conn = (HttpURLConnection) url.openConnection(proxy); } } conn.setConnectTimeout(5 * 1000); conn.setDoOutput(true); conn.setRequestMethod(GET); if (heads != null) { for (String key : heads.keySet()) { conn.addRequestProperty(key, heads.get(key)); } } is = conn.getInputStream(); //获取输入流,此时才真正建立链接 baos = new ByteArrayOutputStream(); byte[] temp = new byte[1024]; int len; while ((len = is.read(temp)) != -1) { baos.write(temp, 0, len); } if (iWebCallback != null) { iWebCallback.onCallback(conn.getResponseCode(), conn.getResponseMessage(), conn.getHeaderFields(), baos.toByteArray()); } } catch (Exception e) { int code = 600; try { code = conn == null ? 600 : conn.getResponseCode(); } catch (Exception e1) { } if (iWebCallback != null) { iWebCallback.onFail(code, e.toString()); } } finally { CloseUtils.closeSilently(is); CloseUtils.closeSilently(baos); if (conn != null) { conn.disconnect(); } } } } public byte[] postURLResponse(String urlString, HashMap<String, String> headers, byte[] postData) { byte[] result = null; if (urlString != null) { HttpURLConnection conn = null; //连接对象 InputStream is = null; ByteArrayOutputStream baos = null; try { URL url = new URL(urlString); //URL对象 if (urlString.startsWith(HTTPS)) { conn = (HttpsURLConnection) url.openConnection(); } else { conn = (HttpURLConnection) url.openConnection(); } conn.setConnectTimeout(5 * 1000); conn.setDoOutput(true); conn.setRequestMethod(POST); //使用post请求 conn.setRequestProperty("Charsert", "UTF-8"); if (headers != null) { for (Map.Entry<String, String> temp : headers.entrySet()) { conn.setRequestProperty(temp.getKey(), temp.getValue()); } } conn.getOutputStream().write(postData); is = conn.getInputStream(); //获取输入流,此时才真正建立链接 baos = new ByteArrayOutputStream(); byte[] temp = new byte[1024]; int len; while ((len = is.read(temp)) != -1) { baos.write(temp, 0, len); } result = baos.toByteArray(); } catch (Exception e) { } finally { CloseUtils.closeSilently(is); CloseUtils.closeSilently(baos); if (conn != null) { conn.disconnect(); } } } return result; } public void postURLResponse(String urlString, HashMap<String, String> headers, byte[] postData, IWebCallback iWebCallback) { if (urlString != null) { HttpURLConnection conn = null; //连接对象 InputStream is = null; ByteArrayOutputStream baos = null; try { URL url = new URL(urlString); //URL对象 if (urlString.startsWith(HTTPS)) { conn = (HttpsURLConnection) url.openConnection(); } else { conn = (HttpURLConnection) url.openConnection(); } conn.setConnectTimeout(5 * 1000); conn.setDoOutput(true); conn.setRequestMethod(POST); //使用post请求 conn.setRequestProperty("Charsert", "UTF-8"); if (headers != null) { for (Map.Entry<String, String> temp : headers.entrySet()) { conn.setRequestProperty(temp.getKey(), temp.getValue()); } } conn.getOutputStream().write(postData); is = conn.getInputStream(); //获取输入流,此时才真正建立链接 baos = new ByteArrayOutputStream(); byte[] temp = new byte[1024]; int len; while ((len = is.read(temp)) != -1) { baos.write(temp, 0, len); } if (iWebCallback != null) { iWebCallback.onCallback(conn.getResponseCode(), conn.getResponseMessage(), conn.getHeaderFields(), baos.toByteArray()); } } catch (Exception e) { int code = 600; try { code = conn == null ? 600 : conn.getResponseCode(); } catch (Exception e1) { } if (iWebCallback != null) { iWebCallback.onFail(code, e.toString()); } } finally { CloseUtils.closeSilently(is); CloseUtils.closeSilently(baos); if (conn != null) { conn.disconnect(); } } } } }
-
用于解析支付订单查询返回信息解析
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @JacksonXmlRootElement(localName = "xml") public class WXPayResponse { @JacksonXmlProperty(localName = "return_code") private String returnCode;//返回码 @JacksonXmlProperty(localName = "return_msg") private String returnMsg;//返回信息 @JacksonXmlProperty(localName = "appid") private String appid;//appid @JacksonXmlProperty(localName = "mch_id") private String mchId;//商户号 @JacksonXmlProperty(localName = "nonce_str") private String nonceStr;//随机字符串 @JacksonXmlProperty(localName = "sign") private String sign;//签名 @JacksonXmlProperty(localName = "result_code") private String resultCode;//业务结果 @JacksonXmlProperty(localName = "err_code") private String errCode;//错误代码 @JacksonXmlProperty(localName = "err_code_des") private String errCodeDes;//错误代码描述 @JacksonXmlProperty(localName = "device_info") private String deviceInfo;//设备号 @JacksonXmlProperty(localName = "openid") private String openid;//用户标识 @JacksonXmlProperty(localName = "is_subscribe") private String isSubscribe;//是否关注公众账号 @JacksonXmlProperty(localName = "trade_type") private String tradeType;//交易类型 @JacksonXmlProperty(localName = "trade_state") private String tradeState;//交易状态 @JacksonXmlProperty(localName = "bank_type") private String bankType;//付款银行 @JacksonXmlProperty(localName = "total_fee") private String totalFee;//总金额 @JacksonXmlProperty(localName = "fee_type") private String feeType;//货币种类 @JacksonXmlProperty(localName = "cash_fee") private String cashFee;//现金支付金额 @JacksonXmlProperty(localName = "cash_fee_type") private String cashFeeType;//现金支付货币类型 @JacksonXmlProperty(localName = "settlement_total_fee") private String settlementTotalFee;//应结订单金额 @JacksonXmlProperty(localName = "coupon_fee") private String couponFee;//代金券金额 @JacksonXmlProperty(localName = "coupon_count") private String couponCount;//代金券使用数量 @JacksonXmlProperty(localName = "transaction_id") private String transactionId;//微信支付订单号 @JacksonXmlProperty(localName = "out_trade_no") private String outTradeNo;//商户订单号 @JacksonXmlProperty(localName = "attach") private String attach;//附加数据 @JacksonXmlProperty(localName = "time_end") private String timeEnd;//支付完成时间 @JacksonXmlProperty(localName = "trade_state_desc") private String tradeStateDesc;//交易状态描述 public String getReturnCode() { return returnCode; } public void setReturnCode(String returnCode) { this.returnCode = returnCode; } public String getReturnMsg() { return returnMsg; } public void setReturnMsg(String returnMsg) { this.returnMsg = returnMsg; } public String getAppid() { return appid; } public void setAppid(String appid) { this.appid = appid; } public String getMchId() { return mchId; } public void setMchId(String mchId) { this.mchId = mchId; } public String getNonceStr() { return nonceStr; } public void setNonceStr(String nonceStr) { this.nonceStr = nonceStr; } public String getSign() { return sign; } public void setSign(String sign) { this.sign = sign; } public String getResultCode() { return resultCode; } public void setResultCode(String resultCode) { this.resultCode = resultCode; } public String getErrCode() { return errCode; } public void setErrCode(String errCode) { this.errCode = errCode; } public String getErrCodeDes() { return errCodeDes; } public void setErrCodeDes(String errCodeDes) { this.errCodeDes = errCodeDes; } public String getDeviceInfo() { return deviceInfo; } public void setDeviceInfo(String deviceInfo) { this.deviceInfo = deviceInfo; } public String getOpenid() { return openid; } public void setOpenid(String openid) { this.openid = openid; } public String getIsSubscribe() { return isSubscribe; } public void setIsSubscribe(String isSubscribe) { this.isSubscribe = isSubscribe; } public String getTradeType() { return tradeType; } public void setTradeType(String tradeType) { this.tradeType = tradeType; } public String getTradeState() { return tradeState; } public void setTradeState(String tradeState) { this.tradeState = tradeState; } public String getBankType() { return bankType; } public void setBankType(String bankType) { this.bankType = bankType; } public String getTotalFee() { return totalFee; } public void setTotalFee(String totalFee) { this.totalFee = totalFee; } public String getFeeType() { return feeType; } public void setFeeType(String feeType) { this.feeType = feeType; } public String getCashFee() { return cashFee; } public void setCashFee(String cashFee) { this.cashFee = cashFee; } public String getCashFeeType() { return cashFeeType; } public void setCashFeeType(String cashFeeType) { this.cashFeeType = cashFeeType; } public String getSettlementTotalFee() { return settlementTotalFee; } public void setSettlementTotalFee(String settlementTotalFee) { this.settlementTotalFee = settlementTotalFee; } public String getCouponFee() { return couponFee; } public void setCouponFee(String couponFee) { this.couponFee = couponFee; } public String getCouponCount() { return couponCount; } public void setCouponCount(String couponCount) { this.couponCount = couponCount; } public String getTransactionId() { return transactionId; } public void setTransactionId(String transactionId) { this.transactionId = transactionId; } public String getOutTradeNo() { return outTradeNo; } public void setOutTradeNo(String outTradeNo) { this.outTradeNo = outTradeNo; } public String getAttach() { return attach; } public void setAttach(String attach) { this.attach = attach; } public String getTimeEnd() { return timeEnd; } public void setTimeEnd(String timeEnd) { this.timeEnd = timeEnd; } public String getTradeStateDesc() { return tradeStateDesc; } public void setTradeStateDesc(String tradeStateDesc) { this.tradeStateDesc = tradeStateDesc; } @Override public String toString() { return "WXPayResponse{" + "returnCode='" + returnCode + '\'' + ", returnMsg='" + returnMsg + '\'' + ", appid='" + appid + '\'' + ", mchId='" + mchId + '\'' + ", nonceStr='" + nonceStr + '\'' + ", sign='" + sign + '\'' + ", resultCode='" + resultCode + '\'' + ", errCode='" + errCode + '\'' + ", errCodeDes='" + errCodeDes + '\'' + ", deviceInfo='" + deviceInfo + '\'' + ", openid='" + openid + '\'' + ", isSubscribe='" + isSubscribe + '\'' + ", tradeType='" + tradeType + '\'' + ", tradeState='" + tradeState + '\'' + ", bankType='" + bankType + '\'' + ", totalFee='" + totalFee + '\'' + ", feeType='" + feeType + '\'' + ", cashFee='" + cashFee + '\'' + ", cashFeeType='" + cashFeeType + '\'' + ", settlementTotalFee='" + settlementTotalFee + '\'' + ", couponFee='" + couponFee + '\'' + ", couponCount='" + couponCount + '\'' + ", transactionId='" + transactionId + '\'' + ", outTradeNo='" + outTradeNo + '\'' + ", attach='" + attach + '\'' + ", timeEnd='" + timeEnd + '\'' + ", tradeStateDesc='" + tradeStateDesc + '\'' + '}'; } }
-
解析微信登录支付签名返回对象
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; @JacksonXmlRootElement(localName = "xml") public class WXResponse { @JacksonXmlProperty(localName = "return_code") private String returnCode;//返回码 @JacksonXmlProperty(localName = "return_msg") private String returnMsg;//返回信息 @JacksonXmlProperty(localName = "appid") private String appid;//appid @JacksonXmlProperty(localName = "mch_id") private String mchId;//商户号 @JacksonXmlProperty(localName = "nonce_str") private String nonceStr;//随机字符串 @JacksonXmlProperty(localName = "sign") private String sign;//签名 @JacksonXmlProperty(localName = "result_code") private String resultCode;//结果码 @JacksonXmlProperty(localName = "err_code") private String errCode;//错误码 @JacksonXmlProperty(localName = "err_code_des") private String errCodeDes;//错误描述 @JacksonXmlProperty(localName = "prepay_id") private String prepayId;//支付id @JacksonXmlProperty(localName = "trade_type") private String tradeType;//支付类型 @JacksonXmlProperty(localName = "device_info") private String deviceInfo;//设备信息 public String getReturnCode() { return returnCode; } public void setReturnCode(String returnCode) { this.returnCode = returnCode; } public String getReturnMsg() { return returnMsg; } public void setReturnMsg(String returnMsg) { this.returnMsg = returnMsg; } public String getAppid() { return appid; } public void setAppid(String appid) { this.appid = appid; } public String getMchId() { return mchId; } public void setMchId(String mchId) { this.mchId = mchId; } public String getNonceStr() { return nonceStr; } public void setNonceStr(String nonceStr) { this.nonceStr = nonceStr; } public String getSign() { return sign; } public void setSign(String sign) { this.sign = sign; } public String getResultCode() { return resultCode; } public void setResultCode(String resultCode) { this.resultCode = resultCode; } public String getErrCode() { return errCode; } public void setErrCode(String errCode) { this.errCode = errCode; } public String getErrCodeDes() { return errCodeDes; } public void setErrCodeDes(String errCodeDes) { this.errCodeDes = errCodeDes; } public String getPrepayId() { return prepayId; } public void setPrepayId(String prepayId) { this.prepayId = prepayId; } public String getTradeType() { return tradeType; } public void setTradeType(String tradeType) { this.tradeType = tradeType; } public String getDeviceInfo() { return deviceInfo; } public void setDeviceInfo(String deviceInfo) { this.deviceInfo = deviceInfo; } @Override public String toString() { return "WXResponse{" + "returnCode='" + returnCode + '\'' + ", returnMsg='" + returnMsg + '\'' + ", appid='" + appid + '\'' + ", mchId='" + mchId + '\'' + ", nonceStr='" + nonceStr + '\'' + ", sign='" + sign + '\'' + ", resultCode='" + resultCode + '\'' + ", errCode='" + errCode + '\'' + ", errCodeDes='" + errCodeDes + '\'' + ", prepayId='" + prepayId + '\'' + ", tradeType='" + tradeType + '\'' + ", deviceInfo='" + deviceInfo + '\'' + '}'; } }
-
用于返回给客户端
public class ResponseWX { private String appid; private String partnerid; private String noncestr; private String packageName; private String prepayid; private String timestamp; private String sign; private String orderNumber; public String getAppid() { return appid; } public void setAppid(String appid) { this.appid = appid; } public String getPartnerid() { return partnerid; } public void setPartnerid(String partnerid) { this.partnerid = partnerid; } public String getNoncestr() { return noncestr; } public void setNoncestr(String noncestr) { this.noncestr = noncestr; } public String getPackageName() { return packageName; } public void setPackageName(String packageName) { this.packageName = packageName; } public String getPrepayid() { return prepayid; } public void setPrepayid(String prepayid) { this.prepayid = prepayid; } public String getTimestamp() { return timestamp; } public void setTimestamp(String timestamp) { this.timestamp = timestamp; } public String getSign() { return sign; } public void setSign(String sign) { this.sign = sign; } public String getOrderNumber() { return orderNumber; } public void setOrderNumber(String orderNumber) { this.orderNumber = orderNumber; } @Override public String toString() { return "ResponseWX{" + "appid='" + appid + '\'' + ", partnerid='" + partnerid + '\'' + ", noncestr='" + noncestr + '\'' + ", packageName='" + packageName + '\'' + ", prepayid='" + prepayid + '\'' + ", timestamp='" + timestamp + '\'' + ", sign='" + sign + '\'' + ", orderNumber='" + orderNumber + '\'' + '}'; } }
-
关键工具类
import com.alibaba.fastjson.JSON; import java.util.*; public class WechartUtils { private static final String APP_ID = "";//应用ID private static final String CT_NUMBER = "";//商户号 private static final String SECRET = "";//这些都能从官方文档获取 private static final String KEY = "";// private static final String GET_ACCESS_TOKEN = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + APP_ID + "&secret=" + SECRET + "&code=%s&grant_type=authorization_code"; private static final String GET_USER_INFO = "https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s"; private static final String GET_FIRST_ORDER = "https://api.mch.weixin.qq.com/pay/unifiedorder"; private static final String GET_ORDER = "https://api.mch.weixin.qq.com/pay/orderquery"; public static boolean checkWXOrder(String orderNumber) { SortedMap<String, String> temp = new TreeMap<String, String>() { { put("appid", APP_ID);//应用ID put("mch_id", CT_NUMBER);//商户号 put("nonce_str", MD5Utils.MD5(String.valueOf(System.currentTimeMillis()), false));//随机字符串 put("out_trade_no", orderNumber);//商户订单号 } }; temp.put("sign", getSign(temp)); String xml = getXml(temp); byte[] result = HttpUtils.getInstance().postURLResponse(GET_ORDER, null, xml.getBytes()); WXPayResponse wxPayResponse = XMLUtils.getObject(new String(result), WXPayResponse.class); return wxPayResponse != null && "SUCCESS".equals(wxPayResponse.getReturnCode()) && "SUCCESS".equals(wxPayResponse.getResultCode()) && "SUCCESS".equals(wxPayResponse.getTradeState()); } public static ResponseWX getWXResponse(String goodsName, String goodsDesc , String orderNumber, String price, String ip) throws Exception { SortedMap<String, String> temp = new TreeMap<String, String>() { { put("appid", APP_ID);//应用ID put("mch_id", CT_NUMBER);//商户号 put("nonce_str", MD5Utils.MD5(String.valueOf(System.currentTimeMillis()), false));//随机字符串 put("body", goodsName);//商品描述 put("attach", goodsDesc);//附加数据 put("out_trade_no", orderNumber);//商户订单号 put("total_fee", price);//总金额 put("spbill_create_ip", ip);//终端IP put("notify_url", "");//这里填写自己的回调通知地址 put("trade_type", "APP");//交易类型 } }; temp.put("sign", getSign(temp)); String xml = getXml(temp); byte[] result = HttpUtils.getInstance().postURLResponse(GET_FIRST_ORDER, null, xml.getBytes()); WXResponse response = XMLUtils.getObject(new String(result), WXResponse.class); if (response != null && "SUCCESS".equals(response.getReturnCode()) && "SUCCESS".equals(response.getResultCode()) && response.getPrepayId() != null) { ResponseWX responseWX = new ResponseWX(); responseWX.setAppid(response.getAppid()); responseWX.setNoncestr(response.getNonceStr()); responseWX.setPackageName("Sign=WXPay"); responseWX.setPartnerid(response.getMchId()); responseWX.setTimestamp(String.valueOf(System.currentTimeMillis() / 1000)); responseWX.setPrepayid(response.getPrepayId()); responseWX.setSign(getSign(new TreeMap<String, String>() { { put("appid", responseWX.getAppid());//应用ID put("partnerid", responseWX.getPartnerid());//商户号 put("noncestr", responseWX.getNoncestr());//商品描述 put("package", responseWX.getPackageName());//随机字符串 put("prepayid", responseWX.getPrepayid());//商户订单号 put("timestamp", responseWX.getTimestamp());//附加数据 } })); responseWX.setOrderNumber(orderNumber); return responseWX; } throw new Exception("签名失败"); } private static String getXml(SortedMap<String, String> data) { StringBuilder result = new StringBuilder("<xml>"); for (Map.Entry<String, String> kv : data.entrySet()) { result.append("<").append(kv.getKey()).append(">").append(kv.getValue()) .append("</").append(kv.getKey()).append(">"); } return result.append("</xml>").toString(); } private static String getSign(SortedMap<String, String> data) { String result = null; if (data != null) { StringBuilder key = new StringBuilder(); boolean isFirst = true; for (Map.Entry<String, String> kv : data.entrySet()) { if (isFirst) { isFirst = false; } else { key.append("&"); } key.append(kv.getKey()); key.append("="); key.append(kv.getValue()); } key.append("&key=").append(KEY); return MD5Utils.MD5(key.toString(), false).toUpperCase(); } return result; } public static WechartUserResponse getUser(String authCode) { WechartUserResponse result = null; String host = String.format(GET_ACCESS_TOKEN, authCode); byte[] response = HttpUtils.getInstance().getURLResponse(host, null); if (response != null) { AccessTokenResponse accessTokenResponse; try { accessTokenResponse = JSON.parseObject(new String(response), AccessTokenResponse.class); } catch (Exception e) { System.out.println("Format response error.e=" + e + ";response=" + new String(response)); return result; } if (accessTokenResponse != null && accessTokenResponse.accessToken != null) { response = HttpUtils.getInstance().getURLResponse(host, null); if (response != null) { host = String.format(GET_USER_INFO, accessTokenResponse.accessToken, accessTokenResponse.openid); response = HttpUtils.getInstance().getURLResponse(host, null); try { result = JSON.parseObject(new String(response), WechartUserResponse.class); if (result.unionid == null) { System.out.println("Get user info error." + ";response=" + new String(response)); result = null; } } catch (Exception e) { System.out.println("Format response error.e=" + e + ";response=" + new String(response)); } } } } return result; } public static class WechartUserResponse { private String openid; private String nickname; private int sex; private String language; private String city; private String province; private String country; private String headimgurl; private String unionid; public String getOpenid() { return openid; } public void setOpenid(String openid) { this.openid = openid; } public String getNickname() { return nickname; } public void setNickname(String nickname) { this.nickname = nickname; } public int getSex() { return sex; } public void setSex(int sex) { this.sex = sex; } public String getLanguage() { return language; } public void setLanguage(String language) { this.language = language; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } public String getProvince() { return province; } public void setProvince(String province) { this.province = province; } public String getCountry() { return country; } public void setCountry(String country) { this.country = country; } public String getHeadimgurl() { return headimgurl; } public void setHeadimgurl(String headimgurl) { this.headimgurl = headimgurl; } public String getUnionid() { return unionid; } public void setUnionid(String unionid) { this.unionid = unionid; } @Override public String toString() { return "WechartUserResponse{" + "openid='" + openid + '\'' + ", nickname='" + nickname + '\'' + ", sex=" + sex + ", language='" + language + '\'' + ", city='" + city + '\'' + ", province='" + province + '\'' + ", country='" + country + '\'' + ", headimgurl='" + headimgurl + '\'' + ", unionid='" + unionid + '\'' + '}'; } } private static class AccessTokenResponse { private String accessToken; private int expiresIn; private String refreshToken; private String openid; private String scope; private String unionid; public String getAccessToken() { return accessToken; } public void setAccessToken(String accessToken) { this.accessToken = accessToken; } public int getExpiresIn() { return expiresIn; } public void setExpiresIn(int expiresIn) { this.expiresIn = expiresIn; } public String getRefreshToken() { return refreshToken; } public void setRefreshToken(String refreshToken) { this.refreshToken = refreshToken; } public String getOpenid() { return openid; } public void setOpenid(String openid) { this.openid = openid; } public String getScope() { return scope; } public void setScope(String scope) { this.scope = scope; } public String getUnionid() { return unionid; } public void setUnionid(String unionid) { this.unionid = unionid; } } }
-
-
因为中间用了xml解析,所以需要导入"com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.9.5" 的jar包,这里为gradle导入
-
最后服务器端只需要开接口接收客户端传递的code,然后调用getUser()方法返回用户对象。
-
-
至此微信登录对接就完成了,如果还有其他问题或者觉得不对的地方可以评论提出。