微信登陆接入(Android/IOS(swift)/Java后台)

本文章仅作为个人笔记

微信Android接入指南,需要登陆后查看(开放平台->资源中心->开发资源->移动应用->接入指南)
微信IOS接入指南,需要登陆后查看(开放平台->资源中心->开发资源->移动应用->接入指南)
微信开放平台
  • 首先要注册成为微信开放平台用户
  • 通过开发者资质认证
    • 提供个人信息
    • 提供公司营业执照等信息
    • 300rmb
  • 创建移动应用并通过审核
    • 提供应用描述
    • 提供应用logo
    • 提供应用安装包
    • 提供应用签名信息(建议下载官方签名获取apk获取签名提交,另外万一签名错误导致登录时返回-6错误码,网页更改签名后需要清理客户端微信缓存再重新尝试。)
  • 万事具备后可以查看到应用的AppID和AppSecret
  • 开始代码模块
  • IOS端(swift):
    • 导入第三方库(cocopods集成)(记得 pod install):

      pod 'WechatOpenSDK'
      
    • 引用:在桥接文件中添加以下代码(桥接文件为项目根目录下的.h文件,如果没有可创建并添加)

      #import "WXApi.h"
      
    • 部分设置:
      image.png
      image.png
      打开项目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>
      

改完info.plist结果如图

  • 等所有配置完毕即可进行编程了。

    • 先贴上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()方法返回用户对象。

  • 至此微信登录对接就完成了,如果还有其他问题或者觉得不对的地方可以评论提出。

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页