微信支付,支付寶支付,銀聯支付——三大支付總結

codeGoogle發表於2017-07-18

銀聯支付,支付寶支付,微信支付的三大總結,之前也有寫過兩篇。

微信支付,支付寶支付,銀聯支付——三大支付總結:

blog.csdn.net/androidstar…

支付寶植入總結:

android 支付寶的植入 《曾經踩過的坑》

微信支付總結:

Android 微信支付總結

備註:出於安全考慮,驗籤我們都是放到後臺進行驗籤的。對於我們移動端節省了很多的勞動力。

之前有做過支付寶支付和微信支付,所以這次做起來碰到的問題很少,key申請下來之後很快就搞定了。吼吼

效果圖:

Markdown
Markdown

由於用魯大師去截圖獲取gif,魯大師一針一針繪製圖片的時候應該沒做好處理,導致跳轉到相應的介面出現黑屏現象。在手機上正常跳轉,無黑屏現象。大家不用擔心這個

準備

需要以公司名義,在支付寶,微信等平臺上開通公司賬戶並且認證,如:支付過程中需要公司的帳號和商戶號。

支付寶支付

如果碰到一些坑的話,請參考我之前寫過的意一篇支付寶踩坑的文章:

android 支付寶的植入 《曾經踩過的坑》

    1. 首先支付寶申請並整合支付寶SDK 這裡不再詳細介紹
參考文件:

 https://doc.open.alipay.com/doc2/detail.htm?treeId=54&articleId=104509&docType=1複製程式碼
    1. 獲取訂單資訊(根據自己公司的實際情況:可以在服務端完成,也可以在本地完成)

      如:

      price=12.5&num=12 //價格為12.5,數量為12

    1. 客戶端拿這些訂單資訊向伺服器後臺進行請求,返回支付簽名資訊signInfo
    1. app攜帶支付資訊,呼叫支付介面請求支付寶客戶端,從而調起支付介面
        /**
         * 支付寶進行請求
         *
         * @param signInfo
         */
        private void payToOrderService(final String signInfo) {
            new Thread() {
                @Override
                public void run() {
                    super.run();
                    PayTask payTask = new PayTask(MyScannerPayActivity.this);
                    // String result = payTask.pay(signInfo, true);
                    Map<String, String> result = payTask.payV2(signInfo, true);
                    Message message = mHandler.obtainMessage();
                    message.what = SDK_PAY_FLAG;
                    message.obj = result;
                    mHandler.sendMessage(message);

                }
            }.start();
        }複製程式碼
    1. 使用者操作,輸入密碼支付,支付成功;直接返回取消支付;出現錯誤,支付失敗;進入支付介面,但輸入密碼支付,支付待確認;
    1. 支付寶客戶端將支付結果告訴app客戶端,商戶伺服器通知app伺服器支付結果;
    1. app客戶端處理支付結果;
    1. app伺服器處理支付結果。

處理結果通知:

private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case SDK_PAY_FLAG:
                    PayResult payResult = null;
                    try {
                        payResult = new PayResult((Map<String, String>) msg.obj);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                    /**
                     對於支付結果,請商戶依賴服務端的非同步通知結果。同步通知結果,僅作為支付結束的通知。
                     */
                    String resultInfo = payResult.getResult();// 同步返回需要驗證的資訊
                    String resultStatus = payResult.getResultStatus();
                    // 判斷resultStatus 為9000則代表支付成功
                    if (TextUtils.equals(resultStatus, PAY_OK)) {

                        ActivityUtils.showActivity(MyScannerPayActivity.this, ScannerPaySuccessActivity.class);
                        finish();
                    } else if (TextUtils.equals(resultStatus, PAY_FAILED)) {//------------------------->支付失敗
                        // 該筆訂單真實的支付結果,需要依賴服務端的非同步通知。
                        Toast.makeText(MyScannerPayActivity.this, "" + payResult.getMemo(), Toast.LENGTH_LONG).show();
                    } else if (TextUtils.equals(resultStatus, PAY_CANCLE)) {//-------------------------->交易取消
                        Toast.makeText(MyScannerPayActivity.this, "" + payResult.getMemo(), Toast.LENGTH_LONG).show();
                    } else if (TextUtils.equals(resultStatus, PAY_NET_ERR)) {//------------------------->網路出現錯誤
                        Toast.makeText(MyScannerPayActivity.this, "" + payResult.getMemo(), Toast.LENGTH_LONG).show();
                    } else if (TextUtils.equals(resultStatus, PAY_WAIT_CONFIRM)) {//--------------------->交替等待
                    }
                    break;
            }
        }
    };複製程式碼

銀聯支付

先看一下官方給我們的銀聯支付流程圖:複製程式碼

Markdown
Markdown

大家不要被這張圖片搞懵逼的了,其實很簡單,這裡我將其分為5小步。

  • 第一步:根據官方文件選擇符合自己的sdk

    官方文件:

    open.unionpay.com/ajweb/help/…

  • 第二步:將相對應的.so檔案copy到 自己的工程裡面去。

    特別注意:

    .so檔案要放在src/main 目錄下,和Java檔案並行。還有就是把用到的許可權複製到自己專案中)

  • 第三步: 和支付寶一樣,APP客戶端帶著這些訂單號向伺服器後臺請求訂單號orderNo

  • 第四步:伺服器後臺接收到購買資訊之後,將資訊提交給銀聯後臺,銀聯接收到後臺之後給伺服器返回tn號

  • 第五步:開啟呼叫銀聯支付。APP客戶端帶著這個流水號,也就是第三步中伺服器返回的tn號,呼叫銀聯SDK所提供的方法

    注意:

    這個訂單流水號為21位純數字號

    呼叫方法: UPPayAssistEx.startPay(this, null, null, tn, mMode);

結果返回

處理銀聯手機支付控制元件返回的支付結果

呼叫銀聯支付後,返回app的時候用了,看返回結果傳,成功,失敗,或者是什麼返回。

如圖所示:複製程式碼

Markdown
Markdown
Markdown
Markdown

最後注意在呼叫:

/*****************************************************************
 * mMode引數解釋: "00" - 啟動銀聯正式環境 "01" - 連線銀聯測試環境
 *****************************************************************/
private final String mMode = "00";複製程式碼

注意:

tn值就是上面第三後臺給的tn,給到伺服器那裡,
這裡我這邊是通過後臺請求下來的,關於mMode,看第一步驟,自己改一下就行了,00開發環境,01測試環境。但是要注意,這個只是個回撥介面方法。

總感覺銀聯支付的SDK呼叫起來怪怪的,貌似回到了原始深林。

微信支付:

接入流程圖:

Markdown
Markdown

  • 接入流程:

    1. 申請開發者賬號
      地址:open.weixin.qq.com/
      進入管理中心,建立移動應用
    2. 申請支付能力
    3. 程式碼整合微信支付
  • 程式碼整合微信支付

    • 1.客戶端程式碼得到使用者購買的商品資訊,將之傳給自己公司app伺服器,引數包含但不限於以下:
    HashMap<String ,String> params = getHeadMap();
    params.put("appid", appID);// 微信appid,選擇性上傳,伺服器寫死亦可
    params.put("money", money);// 支付金額,單位:分
    params.put("goodName", goodsName);// 商品名稱
    params.put("productNum", String.valueOf(12));// 商品的數量複製程式碼
 - 2.app伺服器呼叫微信“統一下單”介面,得到prePayId訂單號並返回prePayId給手機客戶端;

    3.手機客戶端使用prePayId及商品資訊調起微信客戶端進行支付;

    3.1使用者操作:輸入密碼進行支付;返回鍵取消支付;網路無連線支付失敗等;

    4.微信客戶端回撥支付結果給我們們的APP客戶端;

    5.微信伺服器非同步通知我們們公司app伺服器支付結果(伺服器的工作,與客戶端無關)複製程式碼

相關的支付呼叫程式碼:

    IWXAPI mWxApi = WXAPIFactory.createWXAPI(mContext, WX_APPID, true);
    mWxApi.registerApp(WX_APPID);
            /**
             * 請求app伺服器得到的回撥結果
             */
            @Override
            public void onGet(JSONObject jsonObject) {
                if (mWxApi != null) {
                    PayReq req = new PayReq();

                    req.appId = WX_APPID;// 微信開放平臺稽核通過的應用APPID
                    try {
                        req.partnerId = jsonObject.getString("partnerid");// 微信支付分配的商戶號
                        req.prepayId = jsonObject.getString("prepayid");// 預支付訂單號,app伺服器呼叫“統一下單”介面獲取
                        req.nonceStr = jsonObject.getString("noncestr");// 隨機字串,不長於32位,伺服器小哥會給我們生成
                        req.timeStamp = jsonObject.getString("timestamp");// 時間戳,app伺服器小哥給出
                        req.packageValue = jsonObject.getString("package");// 固定值Sign=WXPay,可以直接寫死,伺服器返回的也是這個固定值
                        req.sign = jsonObject.getString("sign");// 簽名,伺服器小哥給出,他會根據:https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=4_3指導得到這個
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                    mWxApi.sendReq(req);
                    Log.d("發起微信支付申請");
                }

            }複製程式碼
注意事項:
  • 1.首先如果要使用微信支付的話

    • 必須先到微信開放平臺註冊應用,具體地址為open.weixin.qq.com/

    • 註冊時需要填應用的包名和簽名,注意這裡的簽名是App正式版的簽名,可以找一個已上線的包或打一個正式包,使用微信提供的工具(簽名工具下載地址為open.weixin.qq.com/zh_CN/htmle…

    • 待稽核通過後,會得到一個AppID和AppSecret,AppID分享和支付都要用到,AppSecret沒什麼實際用途,此時微信分享能力是直接擁有的,支付能力還要額外申請,其中涉及到財務資訊等

    • 最好讓公司財務部門去申請,申請成功後會拿到一個商戶id,後面生成sign時會用到。
    • 只有所有稽核都通過後,才可呼叫微信支付功能,這點是前提。
  • 2.微信分享和微信支付SDK是同一個架包,名為libammsdk.jar。

  • 3.官方開發文件中有一處錯誤,需要注意下,如下圖最後一行引數req應該為request,照搬程式碼的估計IDE也不會放過你,哈哈

    Markdown
    Markdown

    • 4.測試微信支付時,務必對自己的App做正式簽名,因為一開始就在微信平臺註冊過簽名資訊,微信SDK會做校驗,只有這樣才能調起微信分享和微信支付,直接debug版的包則絕對調不起來,這點務必注意,很多人是跌在這裡了!當初做微信分享曾遇到過,所以會很留心,也因為如此,如果微信分享能調起來,微信支付不行,那就不要懷疑簽名問題了。
  • 5.還是簽名,網上有人說要注意大小寫,這點其實是不必的。在微信開放平臺看到稽核通過的App的簽名是大寫的,而用微信簽名獲取工具獲得的則顯示小寫,這個沒關係,不要貿然改動平臺註冊資訊,不然又可能導致漫長的稽核等待,上面也說了,微信分享如可以,那就不是簽名問題。

  • 6.來說下官方demo,這東西害人不淺啊!很多人蔘考其寫法,如生成sign放在客戶端啊,調支付的Activity新增intent-filter啊,最主要的還是簽名問題。其實客戶端邏輯很簡單,直接上手整合即可,demo看看邏輯就行,照抄小心掉坑裡。

  • 7.網上有人說需要給呼叫支付的Activity配置如下intent-filter(見下圖),可能也是被demo誤導了

  • 8.對於errCode返回-1,有人說清除微信快取或切換賬戶就好了,這種解決方案治標不治本啊,根本不能算解決方案。雖然我沒遇到能用這方法解決的問題,但目測是簽名的問題,建議還得找到真正的問題所在。

  • 9.生成sign時特別需要注意:

    • 首先將key-value鍵值對拼成字串,注意key都要小寫,如appid,noncestr,package,partnerid,prepayid,timestamp,key,並且名字得按上述名稱
    • 我們遇到的錯誤就是因為partnerid寫成了partnerId,prepayid寫成了PrepayId,當然我們是在服務端寫的,如果在客戶端生成sign的話,也需要注意大小寫及名稱,詳細資訊請參考官方文件。
    • 還有這裡的key並非AppID或AppSectet,而是在商戶平臺設定的,官方描述為“key設定路徑:微信商戶平臺(pay.weixin.qq.com)-->賬戶設定-->API安全-->金鑰設定”。對於noncestr,申請prepayid和生成sign時兩次需要用到,由於iOS同事看到相關文章說noncestr前後需要一致,因此這個隨機字串我們是設定成一樣的了,這樣做Android平臺也是OK的,不過個人感覺這裡可以不一致,由於這個邏輯在伺服器端,我並沒有驗證,方便的同學可以驗證下。
  • 10.req.packageValue=”Sign=WXPay”,一般都是這樣寫死這個引數值。也有人說寫成req.packageValue=”prepay_id=” + prepayid,經測試Android兩種寫法都是可以調起微信支付的,至少最新版本SDK是可以的,以後則不清楚,官方也建議寫Sign=WXPay,據說iOS只支援這種寫法。

Android整合微信支付的出現-1等錯誤需要注意的要點

  • 1.微信支付和支付寶支付是現在APP常用的支付方式,但是真正接入過兩種支付方式的猿友會很明顯的感覺到微信支付真心比支付寶麻煩很多,會出現很多莫名其妙的錯誤,但是官方的文件卻很難給出較好的解決方案.

  • 2.前幾天公司的APP需要支付功能然後也需要這個-1問題,簡直感覺微信支付喪心病狂,這裡總結下自己出現的問題和一些其他網友出現的問題做個總結

reso.errCode = -1 官方的描述: -1 錯誤 可能的原因:簽名錯誤、未註冊APPID、專案設定APPID不正確、註冊的APPID與設定的不匹配、其他異常等。

1.簽名錯誤:
  • (1).簽名的引數集合沒有按照引數名ASCII碼從小到大排序(字典序)

  • (2).簽名的是時候漏了使用key,(key的由來可以看下面第三條的分析)

  • (3).簽名的KEY錯誤. 這裡用來簽名的key是申請支付功能以後,微信給你的一個商戶賬號裡面設定的.具體key設定路徑:微信商戶平臺(pay.weixin.qq.com)–>賬戶設定–>API安全–>金鑰設定

  • (4).簽名後的key沒有進行轉化成大寫或者其他例如前面的簽名引數先排好序最後才加上key(key欄位不參與ASCII碼的大小排序,而是直接放到最後)

  • (5),還有一些其他的格式錯誤請參看官方文件的詳細說明 微信官方的簽名說明,請認真對比.

  • (6),簽名問題的終極大招—–使用官方的簽名認證工具一一對比.注:最好在連線生成的key和最終MD5之後的結果 在log下列印出來,可以方便檢視出錯的位置 介面除錯工具

2.APPID錯誤
  • (1)APPID是在open.weixin.qq.com上建立的應用,可以通過 點選管理中心–>應用詳情 來檢視APPID

    image
    image

  • (2)建立APP時候上傳的證照與現在使用的不一致.商戶在微信開放平臺申請開發應用後,微信開放平臺會生成APP的唯一標識APPID。由於需要保證支付安全,需要在開放平臺繫結商戶應用包名和應用簽名,設定好後才能正常發起支付。設定介面在【開放平臺】中的欄目【 管理中心 –> 修改應用 –> 修改開發資訊】裡面

image
image

應用包名:是在APP專案配置檔案AndroidManifest.xml中宣告的package值,例如DEMO中的package=”com.nmm.paydemo”。

應用簽名:根據專案的應用包名和編譯使用的keystore,可由簽名工具生成一個32位的md5串,在除錯的手機上安裝簽名工具後,執行可生成應用簽名串,如圖8.9所示,綠色串即應用簽名。簽名工具下載地址

對比檢視應用簽名是否一致,特別注意,一般上傳都是使用release版本的key所以在測試的時候就需要使用簽名版的apk,普通的debug版本key是不一致的

微信支付相關的demo地址:

github.com/androidstar…

以上是我之前做微信支付的時候的一些總結,今天再次拿出來供大家參考

之前的歷史文章:
>

支付寶植入總結:

android 支付寶的植入 《曾經踩過的坑》

微信支付總結:

Android 微信支付總結

相信自己,沒有做不到的,只有想不到的

如果你覺得此文對您有所幫助,歡迎入群 QQ交流群 :232203809
微信公眾號:終端研發部

Markdown
Markdown

(歡迎關注學習和交流)

相關文章