回眸曾经的项目,与第三方支付相关,所带来的沟通问题

导读

笔者在校期间,经过自学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。这个,就须要考虑清楚。沟通是很是重要,若是沟通的不及时,既浪费了人力和物力,也让双方都不开心。

于是,之后为人处事,必定要学会沟通。不过,这对于我来讲,也是一次小小的成长吧。在成长的过程当中,就会摔跟头的。但站起来以后,回头看看绊倒本身的是什么?是石头,仍是香蕉皮?之后,再遇到这样的事情,能不能及时的沟通。

祝本身在成长的过程,愈挫愈勇吧。

相关文章
相关标签/搜索