一、寶付私密金鑰加密,公開金鑰解密
由於對RSA加密解密原理不是很熟悉,寶付也沒有Golang的Demo提供。Go語言庫裡一般都是私密金鑰解密、公開金鑰加密,或者私密金鑰簽名、公開金鑰驗簽。寶付需要反過來,這裡也到好找到了https://github.com/farmerx/gorsa的實現,但始終寶付那邊提示簽名驗證失敗。然後就繼續找其他的實現了,這就慘了各種Google完全無解。最後回過頭來只能,使用加解密原文,跟.Net平台的結果進行比對。一通折騰或者叫折磨之後,發現其實只是每次加密多了117個位元組的全是0,後面的加密結果居然是跟其他平台一樣的。由此對armerxgorsa做了如下修改,成功。
這個前後花了3天時間。雖然解決問題的方式最終很簡單,但是找到這條路的過程可真是披荊斬棘。
二、通聯密鑰解析
寶付的密鑰直接使用Go語言套件就可以解析了,但是通聯的就棘手了。給出的P12檔案是Windows下的,繼續Bing。好在很快就有了結果,當然還是最大同性交流平台https://github.com/ikaiguang/go-allinpay。雖然參考代碼有了,不過還是遇到麻煩事。讓朋友Mac電腦上密鑰轉換出來的pem檔案總是解析失敗,1.2K,比能解析的大一些。
這個時候想起來Win10包含Linux子系統了,之前已經安裝過,但還沒怎麼玩過。剛好可以嘗試下。操作依然很微軟——生產力平台。1.WIndows功能裡啟用2.Win10軟體市集裡搜尋Ubuntu,安裝即可。3.直接使用Linux 子系統做一些事情啦!
找到待轉換密鑰所在路徑,執行以下命令。
openssl pkcs12 -nocerts -nodes -in 20060400000491004.p12 -out 20060400000491004.pemopenssl x509 -inform DER -in allinpay-pdsDev.cer -out allinpay-pdsDev.pem
三、富友金賬戶密鑰
有前面這些個坑,基本上平的差不多之後,對支付平台的加解密基本熟悉了,然後對接金賬戶就輕鬆多了。簡單的嘗試了一下,密鑰。最終直接使用Java版本的即可,只不過私密金鑰使用PKCS1解析,公開金鑰使用PKIXPublicKey進行解析。
func init() { carFile, err := ioutil.ReadFile("Assets/prkey.key") if err != nil { return } pemBlock, _ := pem.Decode(carFile) if pemBlock == nil { return } parsedKey, err := x509.ParsePKCS1PrivateKey(pemBlock.Bytes) if err != nil { return } jzhSignaKey = parsedKey verify, err := ioutil.ReadFile("Assets/pbkey.key") if err != nil { return } block, _ := pem.Decode(verify) if block == nil { return } pub, err := x509.ParsePKIXPublicKey(block.Bytes) if err != nil { return } jzhVerfyKey = pub.(*rsa.PublicKey)}
四、擷取XML中的子內容
基本上加解密趟完之後,其他的都是小問題了。熟悉Golang的基本庫就可以了。從富友返回的XML裡截取出驗簽所需的明文,很是懷念大.Net 的優良封裝。一個方法就好了,起初也想照著這個套路來找Golang的實現,貌似Golang裡的XML解析,不藉助其他第三方庫的情況下,主要就兩種1.解析為Struct;2.不知道XML實際內容按XML基本屬性解析。
最後使用Regex,截取的。
var plainTxt=xmlDoc.Element("plain")?.ToString(SaveOptions.DisableFormatting)
五、業務介面對接
其他就剩下主要業務介面的具體對接實現了。主要樣本如下:完成了金賬戶的註冊、寶付的裸扣、通聯快捷代扣。代碼開源在 https://github.com/KendoCross/KendoPay 上,未來打算繼續完善和對接易寶等其他各大支付平台。
package kendopayimport ( "fmt" "testing" "time")//金賬戶註冊func TestJzhReg(t *testing.T) { jzhRegInfo := JzhRegister{ CstmNM: "王道", CertifTP: "0", CertifID: "612429198812220777", MobileNo: "13410100777", // 手機號碼 CityID: "5840", // 開戶行地區 BankID: "113", //銀行 BankNm: "深圳支行", //支行名稱 ActNo: "6230580000144090777", //賬戶 Remark: "胡亂備忘", //備忘 } Register(jzhRegInfo) fmt.Println("---------------------金賬戶註冊------------------------------------------") fmt.Println()}//通聯快捷支付func TestTLQuickPay(t *testing.T) { // 請求參數 fastTrx := QuickTradeReqFASTTRX{ BUSINESS_CODE: "19900", // 業務代碼 SUBMIT_TIME: time.Now().Format("20060102150405"), // 提交時間(YYYYMMDDHHMMSS) AGRMNO: "AIP9549180803000001424", // 協議號(簽約時返回的協議號) ACCOUNT_NO: "6214850219949549", // 帳號(借記卡或信用卡) ACCOUNT_NAME: "幸福", // 帳號名(借記卡或信用卡上的所有人姓名) AMOUNT: "12345", // 金額(整數,單位分) CURRENCY: "CNY", // 貨幣類型(人民幣:CNY, 港元:HKD,美元:USD。不填時,預設為人民幣) ID_TYPE: "0", // 開戶證件類型(0身份證,1戶口簿,2護照,3軍官證,4士兵證...) ID: "370613198705308692", // 證件號 TEL: "18689262774", // 手機號 CUST_USERID: "github.com/ikaiguang", // 自訂使用者號(商戶自訂的使用者號,開發人員可當作備忘欄位使用) SUMMARY: "交易附言", // 交易附言(填入網銀的交易備忘) REMARK: "不備忘", // 備忘(供商戶填入參考資訊) } result, err := Allinpay.Collect(fastTrx) if err != nil { fmt.Printf("%#v \n", err) } fmt.Println(result) fmt.Println("---------------------通聯快捷支付------------------------------------------") fmt.Println()}//寶付裸扣func TestBFBareCollect(t *testing.T) { Baofoo.BareCollect() fmt.Println("---------------------寶付裸扣------------------------------------------") fmt.Println()}