美文网首页tool for work
微信登陆接入(Android/IOS(swift)/Java后台

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

作者: 草丛里的黄盖 | 来源:发表于2018-10-10 14:46 被阅读21次

    本文章仅作为个人笔记

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

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

    相关文章

      网友评论

        本文标题:微信登陆接入(Android/IOS(swift)/Java后台

        本文链接:https://www.haomeiwen.com/subject/ysztaftx.html