微信登陆接入(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()方法返回用户对象。

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,874评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,151评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,270评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,137评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,116评论 5 370
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,935评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,261评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,895评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,342评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,854评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,978评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,609评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,181评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,182评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,402评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,376评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,677评论 2 344

推荐阅读更多精彩内容