回眸曾經的項目,與第三方支付相關,所帶來的溝通問題

導讀

筆者在校期間,經過自學java。學校裏也開過這門課,可是,講的都是一些基礎,好比java的表達式、基本類型、自定義類型等等。也都是很基礎的東西,就連lambda表達式都沒有。然而,讓咱們交的做業,是用java-web開發出的網站。我當時作的是與圖書共享相關的網站。當時滿腔熱血地想着去創業,可是,由於自身還沒離開學校,社會經驗不是特別足,因而,這件事就擱淺了。html

去年六月份畢業,參加了班級的散夥飯後,你們也都各奔東西。但大部分從事軟件開發的行業,有些人進入外包公司,有些人進入了遊戲公司。無論進入到什麼行業,在最初的一段時間中,遇到一個教你的人很重要。這樣,你能夠學校到不少東西。固然,你本身也得努力學習。前端

我依稀記得第一次作項目,那個項目作得真是一塌糊塗,權當我我的練手用了。對於我的來講,成長是很是快的,可是,對於企業來講,這是一種損失。真的是損失。由於,企業讓你來作事,不是讓你來試驗的。自從第一個項目失敗後,也不能說失敗吧,至少作得不夠完美。項目沒有達到鬆散耦合的程度。我在開發的過程當中,遇到了各類各樣的問題,在他人的幫助下,慢慢地適應了開發強度。vue

當時,我給本身定義的是java後端開發工程師,於是,接口都是經過postman來測試。咱們的持久層使用的hibernate框架,因而,仿照hibernate寫個框架,參考個人博客:模仿hibernate框架,詳解hibernate部分方法設計;同時使用spring容器集合該框架,因而,仿照了spring寫個框架,能夠參考個人博客:模擬spring框架,深刻講解spring的對象的建立;數據過濾的框架是Apache下的beanutils框架,因而,模擬beanutils寫個框架,參看個人博客:只因數據過濾,方可模擬beanutils框架java

框架能寫的出來,而這只是java端的,我並不知道前端的一些狀況,好比前端和後端是如何進行數據交互的,前端如何在頁面展現數據等等。因而,下載了前端的頁面。咱們前端的頁面放置在SVN上,後端代碼放置在git上。本身慢慢地根據前端頁面去摸索,神奇地是可以展現出數據。帶個人人看我作的還不錯,因而,教我先後端一塊兒開發。git

咱們這個是先後端分離的,前端調用後端的接口。在學校裏面也學過前端的一些知識,好比CSS三、HTML5,jQuery,JavaScript等等,那時並非項目開發,有些東西只是本身弄着玩的。但公司項目的開發和本身開發徹底不是一回事,須要掌握不少的前端知識。web

不久,作了個完整的前端項目,由於有學校的經驗,有些東西很快就掌握了,可是,其餘不少東西還不怎麼會,真的很腦大。但隨着項目的深刻,才發現本身在學校學的知識,仍是遠遠地不夠項目開發所用的。因而,不斷地充電,不斷地向前輩的學習,如今,前端的不少東西也知道了。算法

如今,回過頭看我寫的前端代碼,再看前輩給我寫的前端代碼,我發現我那時寫的真的垃圾,能夠用不堪入目這個詞來形容。可是,當時設計的頁面仍是蠻酷的,也獲得了老闆的承認。這是我值得驕傲的事。spring

我不斷地嘗試先後端的開發,也從中知道了vue.js,bootstrap,jQuery、echart等前端框架。也知道了本地ip和局域網ip的區別,以及如何用小米球作本地調試。從而更知道了,如何實現先後端分離。我愈來愈相信這句話,只要你努力,就會有人幫助你。json

隨着時間地推動,老闆接了一個項目,就是圖書共享的項目。我當時聽到這個項目後,我就感受到有點難過。這和我畢設所作的項目思想是一致的,若是,我當時可以勇敢一點,也許,我就推廣個人這個項目了。可是,我沒有。bootstrap

世界就是這麼殘酷,不容許你有絲毫地猶豫。因而,老闆再接下一個項目後,項目名爲雲碼兌換平臺。用戶收到某家公司給的代幣(福利),拿到代幣到這個平臺上兌換成錢。錢能夠存儲在本身的餘額中,這就至關於微信錢包,餘額能夠提現到銀行卡的中。也可使用餘額來購買商品。這分爲企業錢包和我的錢包,企業錢包和我的錢包是不同的。

我沒作個相似項目,因而,就接過來作了。老闆說這個項目對我來講,難度係數仍是比較大的。我就下定決心把這個項目給作好,由於我知道能夠從這個項目學到不少東西。咱們的第三方支付平臺是連連支付,杭州的一家公司。

支付

這個項目能夠說沒有任何人帶我,徹底由我本身參考連連給的文檔,邊學習邊嘗試着去開發。這樣,也培養了我調用第三方接口,參讀他們文檔的能力。能夠說,何嘗不是一種收穫呢?

咱們老總說過年前夕,只作支付相關的業務,也就是,用戶提交代幣兌換金額的申請,後臺管理員接收到這個申請後,從後臺給用戶打款。如圖所示:

clipboard.png

後臺管理員點擊批量打款時,服務端會作數據的篩選,曬選出狀態爲待轉讓的客戶打款,其餘狀況下一概不打款。就這麼一個小小的支付按鈕,其內部涉及太多的知識點。

我之因此懼怕,是由於對未知的恐懼。一開始作支付很是難,其實,作完以後,也沒有我想像的那麼難。可是,我仍是須要作一些準備工做。好比,下載連連支付的SDK。但要考慮到SDK是什麼SDK?SDK分爲兩種,一種是應用到java開發中,一種是應用到Android或iOS開發中。由於,連連那邊沒有將其區分開來,從而形成錢包項目的延誤。這個會在下文提到。

下載好連連支付的SDK後,咱們經過maven建立項目,使用的是阿里雲的中央倉庫,其並不存在連連SDK。於是,咱們須要配置本地的Maven庫。這個網上都有教程的,我在這裏就不細說了。

配置好了SDK後,咱們須要瞭解簽名機制,連連使用的RSA簽名機制,如圖所示:

RSA簽名原理

至於連連爲何使用RSA簽名,能夠參考個人這篇博客:支付與簽名原串的那些事,但選擇排序生成簽名原串

咱們將生成的pkcs8格式的公鑰上傳到連連商戶站,再從連連的商戶站下載其連連公鑰。私鑰用以加簽,公鑰用以驗籤,這用以提升數據的安全性。

私鑰怎麼加簽?每一個公司的加簽方式是不同的,支付寶有支付寶的加簽方式,微信有微信的加簽方式。這裏,我就說說連連支付的加簽方式。咱們在向連連發送支付請求前,須要封裝咱們的請求參數,將請求參數以必定格式的方式存儲,這就是簽名原串,如圖所示:

簽名原串

將簽名原串和咱們的pkcs8格式的私鑰共同加密,這就調用到jdk數字簽名的這幾個包:

import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

可是,加密時可能會報出Illegal Key Size的錯誤。當您使用Java版本爲6, 7或8時, 因爲連連提供的公鑰超出了加密過程當中使用到的AES加密方法的默認密鑰長度限制, 須要替換您的開發環境中的local_policy.jar和US_export_policy.jar這兩個jar包以去除密鑰長度限制,即${java_home}/jre/lib/security/ 不然會在加密時拋出異常 Illegal Key Size。

Jar包替換地址爲:

http://www.oracle.com/technet...

http://www.oracle.com/technet...

http://www.oracle.com/technet...

獲得加簽後的簽名字符串,再調用連連支付的LianLianPaySecurity.encrypt(JSON.toJSONString(preq), PaymentConstant.LIAN_PUBLIC_RSA_KEY);加密算法,該算法有兩個參數,一個是包括簽名的請求參數,一個是下載下來的連連公鑰。

若是請求連連支付成功的話,其會返回一段字符串,該字符串包含連連的簽名原串、私鑰簽名串等其餘信息。連連那邊的簽名串的加簽方式,和咱們這邊的是同樣的。咱們從連連下載下來的連連公鑰,其公鑰也是其由私鑰生成而來。其將請求參數封裝成簽名原串,將私鑰和簽名原串共同加簽成簽名串。

於是,咱們這邊拿到了連連的簽名原串和簽名串以後,就要進行驗簽了。怎麼驗籤呢?咱們這個時候,就用到了從連連的商戶站下載的連連公鑰了,如代碼所示:

/**
 * Created By zby on 17:28 2018/12/18
 * RSA簽名驗證
 * <p>
 * * @param reqObj: The obtained asynchronous notification body
 * * @param rsa_public: The public key provided by LianLian
 */
public static boolean checkSignRSA(String response) {
    logger.info("【響應參數】申請付款的響應參數爲:" + response);
    if (StringUtils.isBlank(response)) {
        return false;
    }
    JSONObject reqObj = JSONObject.parseObject(response);
    String lianPubkey = PaymentConstant.LIAN_PUBLIC_RSA_KEY;
    String lianSigned = reqObj.getString("sign");
    String lianSignSrc = genSignData(reqObj);
    ifNullThrow(lianPubkey, ResultCodeEnum.NOT_CONFIG_LIAN_PUBLIC_KEY_VALUE);
    try {
        if (TraderRSAUtil.checksign(lianPubkey, lianSigned, lianSignSrc)) {
            return true;
        } else {
            return false;
        }
    } catch (Exception e) {
        return false;
    }
}

底部調用的是TraderRSAUtil.checksign這個方法,其內部如代碼所示:

/**
 * 簽名驗證
 *
 * @param lianPubkey  下載好的連連公鑰
 * @param lianSignSrc 連連的簽名原串,也就是將返回串封裝成jsonObject
 * @param lianSigned  連連加密簽名簽名,包括簽名原串+私鑰
 * @return
 */
public static boolean checksign(String lianPubkey, String lianSigned,
                                String lianSignSrc) {
    try {
        //【1】獲取公鑰
        //獲取KeyFactory,指定RSA算法
        KeyFactory keyFactory = KeyFactory.getInstance(PaymentConstant.SIGN_TYPE);
        //將BASE64編碼的公鑰字符串進行解碼
        BASE64Decoder decoder = new BASE64Decoder();
        //將BASE64解碼後的字節數組,構形成X509EncodedKeySpec對象,生成公鑰對象
        PublicKey publicKey = keyFactory.generatePublic(new X509EncodedKeySpec(decoder.decodeBuffer(lianPubkey)));
        byte[] signed = decoder.decodeBuffer(lianSigned);
        //【2】使用公鑰,進行驗籤
        //獲取Signature實例,指定簽名算法(與以前一致)
        Signature signature = Signature.getInstance(PaymentConstant.MD5_WITH_RSA);
        //加載公鑰
        signature.initVerify(publicKey);
        //更新原數據
        signature.update(lianSignSrc.getBytes(BaseConstant.CHARSET));
        //公鑰驗籤(true-驗籤經過;false-驗籤失敗)
        return signature.verify(signed);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return false;
}

這就是一個支付的流程,不管是任何第三方支付,其都要有加簽和驗籤,由於,這是最基本的安全機制。只不過,各個公司的加簽和驗籤方式有所不一樣而已。

固然,有些東西就不必使用RSA加簽和驗簽了,好比連連那邊的綁定銀行卡的業務,其加簽方式就是用MD5加簽的。可是,支付涉及到了金額,這個,只要與錢相關的業務。都須要謹慎處理,也許,RSA不是最好的加密方式,但就目前而言,其仍是比較安全的。

錢包

爲何要作錢包呢?作任何事都要有其目的。

咱們作的是福利平臺。屆時,許多商戶會入駐該平臺,給其用戶提供不一樣的優惠卡或者錢,好比流量充值卡、話費充值卡,中石油的加油卡等。不一樣商戶提供不一樣的(虛擬)商品,不一樣的商品對應多少錢,好比話費卡30元,流量卡30元等。商戶須要在錢包中充錢(充值),便於用戶兌換。

用戶拿到這些卡消費時,商戶的錢包裏的錢會減小。用戶能夠經過代幣兌換這些充值卡,也能夠經過代幣兌換錢,商戶的錢就會變少,而用戶的錢包的錢增長,其能夠提現到銀行卡(提現),也能夠購買其餘產品(支付);在購買時,錢包餘額不夠,能夠充值到連連錢包(充值)。若是已經購買了,也能夠,申請退款(退款)。 同時,也能夠查看提現記錄(提現查詢),支付記錄(支付查詢);

總的來講,電子錢包能夠存儲用戶的金額,至關於微信支付中的餘額,也至關於咱們現實中的錢包。用戶能夠支配錢包金額(餘額),但並不是任意支配。由於用戶支配的額度不能超過錢包的額度。

今年都到了三月二十四號了,咱們的錢包已經作一個月了。可是,咱們這邊的產品經理可能和連連那邊的業務沒有溝通好,其所提供給咱們的web組件所有是走他們的頁面。我當時問他們的頁面支不支持響應式佈局,他們堅定地回答說不支持。如圖所示:

提現頁面

這在PC端的瀏覽器中看,界面仍是能夠的,可是,若是用手機端看的話,其會很是的彆扭,如圖所示:

手機端的提現界面

你會發現,這簡直不能使用。我當時和對方說,這種效果的用戶體驗很差。他們說咱們這邊提供的了手機端的SDK組件,我看了他們給的SDK組件,其徹底是Android開發和iOS開發的SDK組件。他們覺得咱們是Android開發,而咱們這是微信公衆號,是嵌入在微信中的h5頁面,天然是不能使用的。

這就是產品經理和業務沒有溝通好帶來的誤會,產品經理說他們那邊的業務不懂技術。他們那邊的業務覺得SDK就是SDK,不區分是否是Android和iOS,仍是服務端java的SDK。業務可能也沒問他那邊的技術。於是,浪費了這一個月的時間。咱們這是從開年就開始作錢包了,作到如今就遇到了這個問題。因此,不少東西都要從新作。

對於企業來講,這是一個損失。但對於我我的來講,這是一種成長。不管是技術方面,仍是與人溝通方面,都是一種成長。

咱們後來和他們說,web組件走不通了,能不能經過API的方式自定義界面,他們說他們這邊也是提供的,不過,是最近剛開放的API的接口。咱們這邊的產品經理很是生氣,說大家那邊沒有的話,就早點和咱們說嗎,省得浪費咱們的時間。

我在開發的起始階段,看了他們的SDK,也有和對方溝通。我說咱們這是公衆號開發,大家這個SDK好像有問題,他們那邊說你可使用web組件,當時,也沒有說到這個API的接口。

溝通問題

出現上述的問題,也不能說是誰的錯。其實,誰都沒有錯,然而,誰貌似都有錯。由於溝通的不及時,致使了上面的問題。

事情已經出了,生氣也沒用。於是,我就從這件事中吸收教訓。凡是,都要先溝通好,好比,就這個SDK的問題。是什麼樣的SDK?嵌入在java中的SDK,仍是純安卓的SDK。這個,就須要考慮清楚。溝通是很是重要,若是溝通的不及時,既浪費了人力和物力,也讓雙方都不開心。

於是,之後爲人處事,必定要學會溝通。不過,這對於我來講,也是一次小小的成長吧。在成長的過程當中,就會摔跟頭的。但站起來以後,回頭看看絆倒本身的是什麼?是石頭,仍是香蕉皮?之後,再遇到這樣的事情,能不能及時的溝通。

祝本身在成長的過程,愈挫愈勇吧。

相關文章
相關標籤/搜索