支付寶登錄接入(Android/IOS(swift)/Java后臺)

本文章僅作為個(gè)人筆記

截止發(fā)文在網(wǎng)上找了一圈支付寶登錄的吹散,大部分都是照搬官方的demo弧械,沒什么實(shí)際用處,官方的demo大家應(yīng)該都看過了空民,對于Android來講問題應(yīng)該不大刃唐,后臺就gg了,這里主寫后臺與Android對接心得。
因?yàn)閷?shí)在被支付寶折騰的厲害唁桩,所以這里就不寫什么注冊處簽約什么的流程了闭树,心累耸棒,上些干貨(代碼)荒澡,作為中國人自己的開放平臺,文檔還整理成這個(gè)樣子需要自己琢磨代碼的估計(jì)也就這一家了与殃。也有可能是樓主自己語文或者檢索能力不過關(guān)哦单山,如果看客發(fā)現(xiàn)有不規(guī)范或者不對的地方還望指出,這里先謝過了幅疼。
螞蟻金服開放平臺官網(wǎng)
支付寶Android官方接入文檔
支付寶IOS官方接入文檔
Android客戶端demo&sdk下載地址(1.5.5)
IOS客戶端demo&sdk下載地址(1.5.7)
服務(wù)器端接入官方文檔
登錄結(jié)果返回參數(shù)說明
支付結(jié)果返回參數(shù)說明
  • IOS端

    • 引入官方庫(于Podfile文件加入如下內(nèi)容并運(yùn)行 pod install)

      pod 'AlipaySDK-iOS'
      
    • 于頭文件添加如下內(nèi)容米奸,不知道什么是頭文件的建議參考支付寶IOS官方接入文檔

      #import <AlipaySDK/AlipaySDK.h>
      
    • 添加 URL Schemes ,設(shè)置為aliauth 并設(shè)置值為某一唯一值爽篷,如 包名.aliauth悴晰。設(shè)置為alipay 并設(shè)置值為某一唯一值,如 包名.alipay逐工。

    • 與Localizable.strings 添加 "aliauthback" = ""http://這里需要保持與上面的URL Schemes aliauth值一致铡溪。添加 "alipayback" = ""http://這里需要保持與上面的URL Schemes alipay值一致。

    • 創(chuàng)建AliPayUtils工具文件

              class AliPayUtils {
              
                  private static var aliAuthBack: AliPayBack?
                  private static var aliPayBack: AliPayBack?
              
                  static func login(signStr: String, aliAuthBack: AliPayBack?) {
                      AliPayUtils.aliAuthBack = aliAuthBack
                      AlipaySDK().auth_V2(withInfo: signStr, fromScheme: NSLocalizedString("aliauthback", comment: ""), callback: { (resp) in
                          loginBack(resultDic: resp as! [NSObject: AnyObject])
                      })
                  }
              
                  static func loginBack(resultDic: [NSObject: AnyObject]) {
                      if let Alipayjson: [String: AnyObject] = resultDic as? [String: AnyObject] {
                          let resultStatus = Alipayjson["resultStatus"] as! String
                          print("loginBack resultStatus=\(resultStatus)")
                          if resultStatus == "9000" {//   請求處理成功
                              aliAuthBack?.finish(Alipayjson["result"] as? String)
                          } else {
                              aliAuthBack?.failed()
                          }
                      }
                  }
              
                  static func pay(signStr: String, aliPayBack: AliPayBack?) {
                      AliPayUtils.aliPayBack = aliPayBack
                      AlipaySDK().payOrder(signStr, fromScheme: NSLocalizedString("alipayback", comment: ""), callback: { (resp) in
                          payBack(resultDic: resp as! [NSObject: AnyObject])
                      })
                  }
              
                  static func payBack(resultDic: [NSObject: AnyObject]) {
                      if let Alipayjson: [String: AnyObject] = resultDic as? [String: AnyObject] {
                          let resultStatus = Alipayjson["resultStatus"] as! String
                          print("payBack resultStatus=\(resultStatus)")
                          if resultStatus == "9000" || resultStatus == "8000" {//   訂單支付成功或正在處理中
                              aliPayBack?.finish(Alipayjson["result"] as? String)
                          } else {
                              aliPayBack?.failed()
                          }
                      }
                  }
              
              }
              
              protocol AliPayBack {
                  func finish(_ result: String?)
              
                  func failed()
              }
      
    • 于AppDelegate添加回調(diào)(這里貼主要代碼)

              @UIApplicationMain
              class AppDelegate: UIResponder, UIApplicationDelegate {
              
                  func application(_ application: UIApplication, handleOpen url: URL) -> Bool {
                      switch url.scheme {
                      case NSLocalizedString("aliauthback", comment: ""):
                          AlipaySDK().processAuth_V2Result(url) { (back) in
                              AliPayUtils.loginBack(resultDic: back as! [NSObject: AnyObject])
                          }
                      case NSLocalizedString("alipayback", comment: ""):
                          AlipaySDK().processOrder(withPaymentResult: url) { (back) in
                              AliPayUtils.payBack(resultDic: back as! [NSObject: AnyObject])
                          }
                      default:
                          print("handleOpenUrl1")
                      }
                      print("handleOpenUrl11=\(url.scheme)")
                      return true
                  }
              
                  func application(_ application: UIApplication, open url: URL
                          , sourceApplication: String?, annotation: Any) -> Bool {
                      switch url.scheme {
                      case NSLocalizedString("aliauthback", comment: ""):
                          AlipaySDK().processAuth_V2Result(url) { (back) in
                              AliPayUtils.loginBack(resultDic: back as! [NSObject: AnyObject])
                          }
                      case NSLocalizedString("alipayback", comment: ""):
                          AlipaySDK().processOrder(withPaymentResult: url) { (back) in
                              AliPayUtils.payBack(resultDic: back as! [NSObject: AnyObject])
                          }
                      default:
                          print("handleOpenUrl2")
                      }
                      print("handleOpenUrl12=\(url.scheme)")
                      return true
                  }
              }
      
    • 登錄調(diào)用(這里寫部分偽代碼):

              //從服務(wù)器獲取簽名字符串泪喊,這里后面服務(wù)器開發(fā)會貼出棕硫,客戶端可以不用管。
              var signStr = getSignStrFromService()
              AliPayUtils.login(signStr: result!, aliAuthBack: AliAuthBack())
              //創(chuàng)建AliPayBack實(shí)例
              struct AliAuthBack: AliPayBack {
              
                  func finish(_ result: String?) {
                      //登錄成功袒啼,直接將獲取的結(jié)果上傳至服務(wù)器處理哈扮,服務(wù)器返回用戶信息即可。
                  }
              
                  func failed() {
                      //登錄失敗
                  }
              }
      
  • Android端

    • 接入前奏蚓再,注冊簽約的可另行百度滑肉,這里主要寫代碼部分

    • 下載jar包并導(dǎo)入(這里使用的是alipaySdk-20180601.jar)

    • 放入項(xiàng)目libs文件夾下

    • 與build.gradle導(dǎo)入jar(這里貼部分關(guān)鍵代碼)

          dependencies {
              implementation fileTree(dir: 'libs', include: ['*.jar'])
              implementation files('libs/alipaySdk-20180601.jar')
          }
      
    • 于AndroidManifest.xml注冊權(quán)限及activity(這里貼出部分關(guān)鍵代碼)

          <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" />
          
          <application>
              <activity
                  android:name="com.alipay.sdk.app.H5PayActivity"
                  android:configChanges="orientation|keyboardHidden|navigation|screenSize"
                  android:exported="false"
                  android:screenOrientation="behind"
                  android:windowSoftInputMode="adjustResize|stateHidden" />
              <activity
                  android:name="com.alipay.sdk.app.H5AuthActivity"
                  android:configChanges="orientation|keyboardHidden|navigation"
                  android:exported="false"
                  android:screenOrientation="behind"
                  android:windowSoftInputMode="adjustResize|stateHidden" />
          </application>
      
      • 創(chuàng)建AliPayUtils工具文件(AuthResult/PayResult文件會后面貼出)

                  import android.app.Activity;
                  import android.text.TextUtils;
                  import android.util.Log;
                  
                  import com.alipay.sdk.app.AuthTask;
                  import com.alipay.sdk.app.EnvUtils;
                  import com.alipay.sdk.app.PayTask;
                  
                  import java.util.Map;
                  
                  public class AliPayUtils {
                  
                      public interface Back {
                          public void success(String result);
                  
                          public void failed();
                      }
                  
                      public static void startPay(final Activity activity, final String orderInfo, final Back back) {
                          if (orderInfo == null || back == null) {
                              return;
                          }
                          new Thread(new Runnable() {
                              @Override
                              public void run() {
                  //                EnvUtils.setEnv(EnvUtils.EnvEnum.SANDBOX);//測試使用此設(shè)置
                                  EnvUtils.setEnv(EnvUtils.EnvEnum.ONLINE);//正式環(huán)境使用此設(shè)置
                                  PayTask alipay = new PayTask(activity);
                                  Map<String, String> result = alipay.payV2(orderInfo, true);
                                  PayResult payResult = new PayResult(result);
                                  String resultStatus = payResult.getResultStatus();
                                  if (TextUtils.equals(resultStatus, "9000")) {
                                      back.success(payResult.getResult());
                                  } else {
                                      back.failed();
                                  }
                              }
                          }).start();
                      }
                  
                      public static void login(final Activity activity, final String authInfo, final Back back) {
                          if (authInfo == null || back == null) {
                              return;
                          }
                          new Thread(new Runnable() {
                              @Override
                              public void run() {
                                  AuthTask authTask = new AuthTask(activity);
                                  Map<String, String> result = authTask.authV2(authInfo, true);
                                  AuthResult authResult = new AuthResult(result, true);
                                  String resultStatus = authResult.getResultStatus();
                                  if (TextUtils.equals(resultStatus, "9000")
                                          && TextUtils.equals(authResult.getResultCode(), "200")) {
                                      back.success(authResult.getResult());
                                  } else {
                                      back.failed();
                                  }
                              }
                          }).start();
                      }
                  
                  }
        
    • 創(chuàng)建AuthResult工具文件

                  import android.text.TextUtils;
                  
                  import java.util.Map;
                  
                  public class AuthResult {
                  
                      private String resultStatus;
                      private String result;
                      private String memo;
                      private String resultCode;
                      private String authCode;
                      private String alipayOpenId;
                  
                      public AuthResult(Map<String, String> rawResult, boolean removeBrackets) {
                          if (rawResult == null) {
                              return;
                          }
                  
                          for (String key : rawResult.keySet()) {
                              if (TextUtils.equals(key, "resultStatus")) {
                                  resultStatus = rawResult.get(key);
                              } else if (TextUtils.equals(key, "result")) {
                                  result = rawResult.get(key);
                              } else if (TextUtils.equals(key, "memo")) {
                                  memo = rawResult.get(key);
                              }
                          }
                  
                          String[] resultValue = result.split("&");
                          for (String value : resultValue) {
                              if (value.startsWith("alipay_open_id")) {
                                  alipayOpenId = removeBrackets(getValue("alipay_open_id=", value), removeBrackets);
                                  continue;
                              }
                              if (value.startsWith("auth_code")) {
                                  authCode = removeBrackets(getValue("auth_code=", value), removeBrackets);
                                  continue;
                              }
                              if (value.startsWith("result_code")) {
                                  resultCode = removeBrackets(getValue("result_code=", value), removeBrackets);
                                  continue;
                              }
                          }
                  
                      }
                  
                      private String removeBrackets(String str, boolean remove) {
                          if (remove) {
                              if (!TextUtils.isEmpty(str)) {
                                  if (str.startsWith("\"")) {
                                      str = str.replaceFirst("\"", "");
                                  }
                                  if (str.endsWith("\"")) {
                                      str = str.substring(0, str.length() - 1);
                                  }
                              }
                          }
                          return str;
                      }
                  
                      @Override
                      public String toString() {
                          return "resultStatus={" + resultStatus + "};memo={" + memo + "};result={" + result + "}";
                      }
                  
                      private String getValue(String header, String data) {
                          return data.substring(header.length(), data.length());
                      }
                  
                      /**
                       * @return the resultStatus
                       */
                      public String getResultStatus() {
                          return resultStatus;
                      }
                  
                      /**
                       * @return the memo
                       */
                      public String getMemo() {
                          return memo;
                      }
                  
                      /**
                       * @return the result
                       */
                      public String getResult() {
                          return result;
                      }
                  
                      /**
                       * @return the resultCode
                       */
                      public String getResultCode() {
                          return resultCode;
                      }
                  
                      /**
                       * @return the authCode
                       */
                      public String getAuthCode() {
                          return authCode;
                      }
                  
                      /**
                       * @return the alipayOpenId
                       */
                      public String getAlipayOpenId() {
                          return alipayOpenId;
                      }
                  }  
      
    • 創(chuàng)建PayResult工具文件

                  import android.text.TextUtils;
                  
                  import java.util.Map;
                  
                  public class PayResult {
                      private String resultStatus;
                      private String result;
                      private String memo;
                  
                      public PayResult(Map<String, String> rawResult) {
                          if (rawResult == null) {
                              return;
                          }
                  
                          for (String key : rawResult.keySet()) {
                              if (TextUtils.equals(key, "resultStatus")) {
                                  resultStatus = rawResult.get(key);
                              } else if (TextUtils.equals(key, "result")) {
                                  result = rawResult.get(key);
                              } else if (TextUtils.equals(key, "memo")) {
                                  memo = rawResult.get(key);
                              }
                          }
                      }
                  
                      @Override
                      public String toString() {
                          return "resultStatus={" + resultStatus + "};memo={" + memo
                                  + "};result={" + result + "}";
                      }
                  
                      /**
                       * @return the resultStatus
                       */
                      public String getResultStatus() {
                          return resultStatus;
                      }
                  
                      /**
                       * @return the memo
                       */
                      public String getMemo() {
                          return memo;
                      }
                  
                      /**
                       * @return the result
                       */
                      public String getResult() {
                          return result;
                      }
                  }
      
    • AliPayUtils登錄使用方式:

        //于服務(wù)器獲取登錄簽名字符串(這里為偽代碼),具體代碼后面服務(wù)器先關(guān)會貼出摘仅。
        String signStr = getSignStr();
        //調(diào)用AliPayUtils登錄方法
        AliPayUtils.login(DemoActivity.this, signStr, new AliPayUtils.Back() {
                @Override
                public void success(String result) {
                    //登錄成功靶庙,可將result上傳至服務(wù)器處理。
                }
        
                @Override
                public void failed() {
                    //登錄失敗
                }
            });
  • 服務(wù)器端
    • Android客戶端demo中寫的“真實(shí)App里实檀,privateKey等數(shù)據(jù)嚴(yán)禁放在客戶端惶洲,加簽過程務(wù)必要放在服務(wù)端完成;”相信大家都看到了膳犹,也正是因?yàn)檫@句話樓主連appId都沒有放客戶端恬吕,但是官方并沒有給出明確的解決方案。Android客戶端jar包引入low到居然要下載jar文件放入须床,連gradle引入都不支持铐料,無力吐槽。
    • 為了解決安全問題樓主不得不將加簽所有過程放服務(wù)器端,那么問題來了:
      • 客戶端的簽名代碼用的是客戶端jar包钠惩,服務(wù)器端用的服務(wù)器jar包柒凉,且服務(wù)器根本沒有簽名示例代碼。

      • 為此樓主只有強(qiáng)行將客戶端部分代碼照搬至服務(wù)器端篓跛,不管是否規(guī)范膝捞,至少簽名在服務(wù)器這邊處理是做到了。代碼如下(代碼真心多愧沟,但是為了一個(gè)類完成所有功能蔬咬,只能勉強(qiáng)放一起了。):

              import com.alipay.api.AlipayApiException;
              import com.alipay.api.AlipayClient;
              import com.alipay.api.DefaultAlipayClient;
              import com.alipay.api.domain.AlipayTradeAppPayModel;
              import com.alipay.api.domain.AlipayTradePrecreateModel;
              import com.alipay.api.internal.util.AlipaySignature;
              import com.alipay.api.request.*;
              import com.alipay.api.response.*;
              
              import java.io.UnsupportedEncodingException;
              import java.net.URLEncoder;
              import java.security.KeyFactory;
              import java.security.PrivateKey;
              import java.security.Security;
              import java.security.spec.PKCS8EncodedKeySpec;
              import java.util.*;
              
              public class AliPayUtils {
                  private static final String APP_ID = "";//這個(gè)就不強(qiáng)調(diào)了沐寺,這個(gè)都找不到相比開發(fā)難度很大林艘,我這文筆很難幫到你了。
                  private static final String PID = "";//在開放平臺內(nèi)點(diǎn)擊右上角那里點(diǎn)擊密鑰管理混坞,然后點(diǎn)擊左邊mapi網(wǎng)關(guān)產(chǎn)品密鑰就能看到pid了狐援。
                  private static final String APP_PRIVATE_KEY = "";//下面的這些信息在應(yīng)用信息里邊基本能看到,有些可能需要上傳設(shè)置究孕。
                  private static final String RSA2_PRIVATE = "";//rsa2私鑰
                  private static final String ALIPAY_PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnzG+wSFicJ1BAP+/51vY8Zn4ZVNMgWuJCTAvfUh48QjixfJwYdr0lX8aOOHVLiC4zOBMdKi0Ale/R/myl1duCnWhCz9XgxMG/x5MpuxESU0SY6HZimW                wQGxoRmKsM3ICa7zmBa58nOig0cKY1ipJ6VXmTGSeiwF7TReKAGU8PeyYTZvnTgmIKofD7L8oAQF2xom3RlFbtzkjf4UaYbr+7m52dktPp6t7PwVKbbAiqDfVIoswrBaAPDmBWrf1Uaj8kt3KVzsiJzpN1xT0oRFikKj9KuMbIMI+ESpDr1674ToJa46AjI+0O8WxfQrebMuE/              xkUCG0WaQCXllLjtRXc7wIDAQAB";
                  private static final String CHARSET = "UTF-8";
              
                  public static boolean alipayCallBack(Map<String, String[]> requestParams) {
                      Boolean isPay = false;
                      // 獲取支付寶POST過來反饋信息
                      Map<String, String> params = new HashMap<>();
                      for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
                          String name = (String) iter.next();
                          String[] values = requestParams.get(name);
                          String valueStr = "";
                          for (int i = 0; i < values.length; i++) {
                              valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
                          }
                          params.put(name, valueStr);
                      }
                      try {
                          boolean flag = AlipaySignature.rsaCheckV1(params, ALIPAY_PUBLIC_KEY, CHARSET, "RSA2");
                          if (flag) {
                              String tradeStatus = params.get("trade_status");
                              if ("TRADE_SUCCESS".equals(tradeStatus)
                                      || "TRADE_FINISHED".equals(tradeStatus)) {
                                  String outTradeNo = params.get("out_trade_no");// 商戶訂單號
                                  String tradeNo = params.get("trade_no");// 商戶訂單號
                                  String gmtPayment = params.get("gmt_payment");// 支付時(shí)間
                                  String gmtCreate = params.get("gmt_create");// 創(chuàng)建時(shí)間
              
                              }
                          }
                      } catch (AlipayApiException e) {
                          e.printStackTrace();
                      }
                      return false;
                  }
        
                  public static AlipayTradeQueryResponse getPayInfo(String outTradeNo, String tradeNo) {
                      AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do"
                              , APP_ID, APP_PRIVATE_KEY, "json", CHARSET, ALIPAY_PUBLIC_KEY, "RSA2");
                      AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
                      request.setBizContent("{" +
                              "\"out_trade_no\":\"" + outTradeNo + "\"," +
                              "\"trade_no\":\"" + tradeNo + "\"," +
                              "\"org_pid\":\"" + PID + "\"" +
                              "  }");
                      try {
                          return alipayClient.execute(request);
                      } catch (AlipayApiException e) {
                          return null;
                      }
                  }
              
                  public static String getPayStr(String totalAmount, String subject, String outTradeNo) {
                      AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do"
                              , APP_ID, APP_PRIVATE_KEY, "json", CHARSET, ALIPAY_PUBLIC_KEY, "RSA2");
                      AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
                      AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
                      model.setSubject(subject);
                      model.setOutTradeNo(outTradeNo);
                      model.setTimeoutExpress("10m");
                      model.setTotalAmount(totalAmount);
                      model.setProductCode("QUICK_MSECURITY_PAY");
                      request.setBizModel(model);
                      request.setNotifyUrl("");//這里記得放支付回調(diào)地址
                      try {
                          AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
                          if (response.isSuccess()) {
                              return response.getBody();
                          } else {
                              throw new BaseException(BaseResultEnum.ALIPAY_SIGN_ERROR);
                          }
                      } catch (AlipayApiException e) {
                          throw new BaseException(BaseResultEnum.ALIPAY_SIGN_ERROR);
                      }
                  }
              
                  public static AlipayUserInfoShareResponse signAuthStr(String authCode) throws AlipayApiException {
                      AlipayClient alipayClient = new DefaultAlipayClient(
                              "https://openapi.alipay.com/gateway.do", APP_ID
                              , APP_PRIVATE_KEY, "json", CHARSET, ALIPAY_PUBLIC_KEY
                              , "RSA2");
                      AlipaySystemOauthTokenRequest request = new AlipaySystemOauthTokenRequest();
                      request.setGrantType("authorization_code");
                      request.setCode(authCode);
                      AlipayUserInfoShareRequest userInfoRequest = new AlipayUserInfoShareRequest();
                      AlipaySystemOauthTokenResponse response =
                              alipayClient.execute(request);
                      if (response.isSuccess()) {
                          AlipayUserInfoShareResponse userInfoResponse
                                  = alipayClient.execute(userInfoRequest, response.getAccessToken());
                          if (userInfoResponse.isSuccess()) {
                              return userInfoResponse;
                          }
                          System.out.println("signAuthStr調(diào)用成功");
                      } else {
                          System.out.println("signAuthStr 調(diào)用失敗");
                      }
                      return null;
                  }
              
                  public static String getAuthStr() {
                      Map<String, String> authInfoMap = buildAuthInfoMap();
                      String info = buildOrderParam(authInfoMap);
                      String sign = getSign(authInfoMap, RSA2_PRIVATE, true);
                      return info + "&" + sign;
                  }
              
                  private static String buildOrderParam(Map<String, String> map) {
                      List<String> keys = new ArrayList<String>(map.keySet());
                      StringBuilder sb = new StringBuilder();
                      for (int i = 0; i < keys.size() - 1; i++) {
                          String key = keys.get(i);
                          String value = map.get(key);
                          sb.append(buildKeyValue(key, value, true));
                          sb.append("&");
                      }
                      String tailKey = keys.get(keys.size() - 1);
                      String tailValue = map.get(tailKey);
                      sb.append(buildKeyValue(tailKey, tailValue, true));
                      return sb.toString();
                  }
              
                  private static Map<String, String> buildAuthInfoMap() {
                      Map<String, String> keyValues = new HashMap<String, String>();
                      keyValues.put("app_id", APP_ID);
                      keyValues.put("pid", PID);
                      keyValues.put("apiname", "com.alipay.account.auth");
                      keyValues.put("app_name", "mc");
                      keyValues.put("biz_type", "openservice");
                      keyValues.put("product_id", "APP_FAST_LOGIN");
                      keyValues.put("scope", "kuaijie");
                      keyValues.put("target_id", String.valueOf(System.currentTimeMillis())
                              + new Random().nextInt(10000));
                      keyValues.put("auth_type", "AUTHACCOUNT");
                      keyValues.put("sign_type", "RSA2");
                      return keyValues;
                  }
              
                  private static String getSign(Map<String, String> map, String rsaKey
                          , boolean rsa2) {
                      List<String> keys = new ArrayList<String>(map.keySet());
                      Collections.sort(keys);
                      StringBuilder authInfo = new StringBuilder();
                      for (int i = 0; i < keys.size() - 1; i++) {
                          String key = keys.get(i);
                          String value = map.get(key);
                          authInfo.append(buildKeyValue(key, value, false));
                          authInfo.append("&");
                      }
                      String tailKey = keys.get(keys.size() - 1);
                      String tailValue = map.get(tailKey);
                      authInfo.append(buildKeyValue(tailKey, tailValue, false));
                      String oriSign = sign(authInfo.toString(), rsaKey, rsa2);
                      String encodedSign = "";
                      try {
                          encodedSign = URLEncoder.encode(oriSign, "UTF-8");
                      } catch (UnsupportedEncodingException e) {
                          e.printStackTrace();
                      }
                      return "sign=" + encodedSign;
                  }
              
                  private static String buildKeyValue(String key, String value, boolean isEncode) {
                      StringBuilder sb = new StringBuilder();
                      sb.append(key);
                      sb.append("=");
                      if (isEncode) {
                          try {
                              sb.append(URLEncoder.encode(value, "UTF-8"));
                          } catch (UnsupportedEncodingException e) {
                              sb.append(value);
                          }
                      } else {
                          sb.append(value);
                      }
                      return sb.toString();
                  }
              
                  private static final String ALGORITHM = "RSA";
              
                  private static final String SIGN_ALGORITHMS = "SHA1WithRSA";
              
                  private static final String SIGN_SHA256RSA_ALGORITHMS = "SHA256WithRSA";
              
                  private static final String DEFAULT_CHARSET = "UTF-8";
              
                  private static String getAlgorithms(boolean rsa2) {
                      return rsa2 ? SIGN_SHA256RSA_ALGORITHMS : SIGN_ALGORITHMS;
                  }
              
                  private static String sign(String content, String privateKey, boolean rsa2) {
                      try {
                          PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(
                                  Base64.getDecoder().decode(privateKey));
                          Security.addProvider(
                                  new org.bouncycastle.jce.provider.BouncyCastleProvider());
                          KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM, "BC");
                          PrivateKey priKey = keyFactory.generatePrivate(priPKCS8);
                          java.security.Signature signature = java.security.Signature
                                  .getInstance(getAlgorithms(rsa2));
                          signature.initSign(priKey);
                          signature.update(content.getBytes(DEFAULT_CHARSET));
                          byte[] signed = signature.sign();
                          return Base64.getEncoder().encodeToString(signed);
                      } catch (Exception e) {
                          e.printStackTrace();
                      }
                      return null;
                  }
              
              }
        
      • 貼完代碼可能會有人代碼報(bào)錯(cuò)啥酱,很正常,因?yàn)槔镞呌玫搅斯俜經(jīng)]有說的代碼(原始代碼用的Android的jdk沒問題蚊俺,但是服務(wù)器端的部分jdk代碼和客戶端有差異懈涛,所以就報(bào)錯(cuò)了),解決方案:

         # gradle用戶在build.gardle加入:
         "org.bouncycastle:bcprov-jdk16:1.45",
         # mvn用戶在pom.xml加入:
         <dependency>
           <groupId>org.bouncycastle</groupId>
           <artifactId>bcprov-jdk16</artifactId>
           <version>1.45</version>
         </dependency>
        
      • 這樣服務(wù)器端簽名代碼就寫好(只是簽名字符串)泳猬,調(diào)用getAuthStr()方法就能返回了批钠。

      • 首先將獲得的realResult上傳至服務(wù)器。然后我這邊貼下服務(wù)器端的處理代碼(首先是getAlipayAuthCode()方法得封,傳入的是realResult埋心,返回的是authCode,讓后將獲得的authCode傳入signAuthStr()方法就獲得了用戶信息了忙上,具體的信息可以參考官方文檔):

                      private final String ALIPAY_AUTH_CODE_START = "auth_code=";
                      private final String ALIPAY_AUTH_CODE_END = "&";
                      private String getAlipayAuthCode(String response) {
                          String result = response.substring(response.indexOf(ALIPAY_AUTH_CODE_START)
                                  + ALIPAY_AUTH_CODE_START.length(), response.length() - 1);
                          return result.substring(0, result.indexOf(ALIPAY_AUTH_CODE_END));
                      }
                      public static AlipayUserInfoShareResponse signAuthStr(String authCode) throws AlipayApiException {
                          AlipayClient alipayClient = new DefaultAlipayClient(
                                  "https://openapi.alipay.com/gateway.do", APP_ID
                                  , APP_PRIVATE_KEY, "json", CHARSET, ALIPAY_PUBLIC_KEY
                                  , "RSA2");
                          AlipaySystemOauthTokenRequest request = new AlipaySystemOauthTokenRequest();
                          request.setGrantType("authorization_code");
                          request.setCode(authCode);
                          AlipayUserInfoShareRequest userInfoRequest = new AlipayUserInfoShareRequest();
                          AlipaySystemOauthTokenResponse response =
                                  alipayClient.execute(request);
                          if (response.isSuccess()) {
                              AlipayUserInfoShareResponse userInfoResponse
                                      = alipayClient.execute(userInfoRequest, response.getAccessToken());
                              if (userInfoResponse.isSuccess()) {
                                  return userInfoResponse;
                              }
                              System.out.println("signAuthStr調(diào)用成功");
                          } else {
                              System.out.println("signAuthStr 調(diào)用失敗");
                          }
                          return null;
                      }
        
      • 獲得了支付寶用戶信息整個(gè)登錄流程也基本結(jié)束了拷呆,剩下的就是自己業(yè)務(wù)邏輯的處理了,因?yàn)檎麄€(gè)流程實(shí)在太復(fù)雜疫粥,寫的可能有很多不詳細(xì)的地方茬斧,還望諒解,發(fā)現(xiàn)不對的地方還望及時(shí)指正梗逮,有問題也可以評論指出项秉。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市慷彤,隨后出現(xiàn)的幾起案子娄蔼,更是在濱河造成了極大的恐慌怖喻,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,635評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件岁诉,死亡現(xiàn)場離奇詭異锚沸,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)涕癣,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評論 3 399
  • 文/潘曉璐 我一進(jìn)店門哗蜈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人属划,你說我怎么就攤上這事恬叹『蛏” “怎么了同眯?”我有些...
    開封第一講書人閱讀 168,083評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長唯鸭。 經(jīng)常有香客問我须蜗,道長,這世上最難降的妖魔是什么目溉? 我笑而不...
    開封第一講書人閱讀 59,640評論 1 296
  • 正文 為了忘掉前任明肮,我火速辦了婚禮,結(jié)果婚禮上缭付,老公的妹妹穿的比我還像新娘柿估。我一直安慰自己,他們只是感情好陷猫,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,640評論 6 397
  • 文/花漫 我一把揭開白布秫舌。 她就那樣靜靜地躺著,像睡著了一般绣檬。 火紅的嫁衣襯著肌膚如雪足陨。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,262評論 1 308
  • 那天娇未,我揣著相機(jī)與錄音墨缘,去河邊找鬼。 笑死零抬,一個(gè)胖子當(dāng)著我的面吹牛镊讼,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播平夜,決...
    沈念sama閱讀 40,833評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼蝶棋,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了褥芒?” 一聲冷哼從身側(cè)響起嚼松,我...
    開封第一講書人閱讀 39,736評論 0 276
  • 序言:老撾萬榮一對情侶失蹤嫡良,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后献酗,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體寝受,經(jīng)...
    沈念sama閱讀 46,280評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,369評論 3 340
  • 正文 我和宋清朗相戀三年罕偎,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了很澄。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,503評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡颜及,死狀恐怖甩苛,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情俏站,我是刑警寧澤讯蒲,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站肄扎,受9級特大地震影響墨林,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜犯祠,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,870評論 3 333
  • 文/蒙蒙 一旭等、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧衡载,春花似錦搔耕、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至猜揪,卻和暖如春惭墓,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背而姐。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評論 1 272
  • 我被黑心中介騙來泰國打工腊凶, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人拴念。 一個(gè)月前我還...
    沈念sama閱讀 48,909評論 3 376
  • 正文 我出身青樓钧萍,卻偏偏與公主長得像,于是被迫代替她去往敵國和親政鼠。 傳聞我的和親對象是個(gè)殘疾皇子风瘦,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,512評論 2 359

推薦閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法公般,內(nèi)部類的語法万搔,繼承相關(guān)的語法胡桨,異常的語法,線程的語...
    子非魚_t_閱讀 31,662評論 18 399
  • 支付寶出了新文檔 現(xiàn)在才知道 記載一下新版與舊版區(qū)別 1 訂單信息生成 舊版當(dāng)中訂單信息生成內(nèi)容較多 簽名在...
    云沐天閱讀 1,777評論 0 5
  • 你曾說:“聽風(fēng)說起過我” 我想:“是的” 我不大算是一個(gè)隨性的人物 沒有鮮明的臉部勾勒 襯托略尖的下巴 但這樣的我...
    顧琛_閱讀 171評論 0 0
  • 廿九站閱讀 560評論 9 5
  • 有那么一瞬間我感覺這個(gè)世界好假 如何去認(rèn)識這個(gè)世界 只不過是靠眨的眼睛 閉上眼睛眼前只是一片黑 只剩假象和想象 睜...
    果凍果吶閱讀 193評論 0 2