看完一个外挂 我竖起了大拇指 | Yuema约吗 记录技术点点滴滴 | 从外挂看程序化运营 孰是孰非 与技术何干?骚年大胆玩起来

 Yuema约吗?一起学技术,一起成长!他山之石,可以攻玉系列

程序的世界,就是有坑的地方!分享踩坑的心得与体验!每天分享一点点!
关注公众号,可获取每日分享!小手点点,即可关注!

这两天在分析一个外挂,当我看到这个外挂的时候,我惊呆了!分布式、策略配置、机器学习、机器视觉、钩子、自动化,高大上的关键词都踩到了!我不由得竖起了大拇指!真的很想膜拜一下外挂幕后的大码农!

抓TA?

这是一个让人非常难过的消息,外挂作者要被当成非法入侵计算机系统,被抓起来!这已经超出技术的范围,单纯从技术上来讲,外挂实现了官方平台未曾实现的功能,而且技术玩得都不简单,没有一定的功力,是组装不出强大的外挂。从非技术角度来讲,有人的地方就有江湖,触及到多方利益的时候,就得谈谈法律,谈谈期限了

猫鼠游戏

写外挂,就是与官方平台玩猫鼠游戏,见不得光,还得与官方平台的防挂机制不断的斗争。(行文中暴露了我倒戈外挂,政治立场不坚定,哈哈)真的很佩服外挂作者们所付出的努力,他们玩的技术与AI何等的神似。我看到的这个外挂,曾经应该是一个全自动的外挂,被官方防外挂机制,毁灭成半自动了。不过,看外挂作者并没有放弃努力。机器视觉、机器学习都用上了。这场游戏的过程,外挂作者得不断跟进官方程序,不断更新,不断的绕过防刷机制!想想,累不?

外挂博弈

抢火车票外挂,抓不抓?携程也提供抢火车票,抓不抓?很多互联网都蹭火车票流量,抓否?

外挂 vs AI

如果狠TA,就叫邪恶外挂,如果喜欢TA,就叫智慧AI.无所谓对与错,在于我们看问题的角度。不要狠外挂,对于技术人来讲,掌握了外挂技术,也是一笔财富!

作者:钟代麒

出处:http://www.jishudao.com/
版权归作者所有,转载请注明出处

蚂蚁金服支付宝花呗分期支付接入实战分享|分分钟钟快速接入demo 企业开通接入花呗支付就是这么easy 想分就分 花呗技术走一波

 Yuema约吗?一起学技术,一起成长!他山之石,可以攻玉系列

程序的世界,就是有坑的地方!分享踩坑的心得与体验!每天分享一点点!
关注公众号,可获取每日分享!小手点点,即可关注!

今天的目标是接通平安银行,正好看到花呗,就玩了一下花呗。还是很快的,在原来的支付基础上,做一些小的改动就可以支付花呗支付。当然,是两方面的事情,一要到支付宝后台签约花呗动作,并在开放平台将花呗支付能力加到应里,感觉有点怪怪,就一口气把所有的“能力”都追加了进去。二是代码啦!

先睹为快,体验链接直接拍上

#更新日志 2019.09.18 增加花呗支付demo https://i.zuime.com/order/alipay/payqrhb

这个码是直接设置了花呗分期的,可以直接扫码,会有分期付款的提示。感觉手续续还是不低哦~具体可以自己扫码感受一下。

代码小调整

public String tradePagePayQrHb(AlipayOrderBean orderBean) throws Exception {    AlipayClient alipayClient = buildAlipayClient();    AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();    AlipayTradePagePayModel model = new AlipayTradePagePayModel();    //request.setReturnUrl(returnUrl);    request.setNotifyUrl(notifyUrl);    model.setOutTradeNo(orderBean.getOutTradeNo());    model.setSubject(orderBean.getSubject());    model.setTotalAmount(orderBean.getTotalAmount());    model.setBody(orderBean.getBody());    model.setProductCode(orderBean.getProductCode());    model.setQrPayMode("4");    model.setQrcodeWidth(200L);    //model.setTimeExpire("2m");    model.setTimeoutExpress("2m");    ExtendParams params = new ExtendParams(); //花呗分期控制    params.setHbFqNum("3");    params.setHbFqSellerPercent("0");    model.setExtendParams(params);    request.setBizModel(model);    request.setNeedEncrypt(true);    return alipayClient.pageExecute(request).getBody();  }

花呗分期支付调的接口也是AlipayTradePagePay,只是传参数的时候多传了一下花呗分期参数。

    ExtendParams params = new ExtendParams(); //花呗分期控制    params.setHbFqNum("3");    params.setHbFqSellerPercent("0");    model.setExtendParams(params);

代码均为测试练习代码,请勿直接用于生产环境,代码经过Github.com的ci检查,能正常编译通过,可正常访问。本次花呗分期体验​连接:https://i.zuime.com/order/alipay/payqrhb

没有比较,就没有伤害

综合平安银行对接与支付宝对接,感觉真的是两种完全不同的体验​!传统厂商与互联网企业,完全两种不一样的研发​体验。

支付宝花呗接入,搞定

源代码获取,关注公众号,回复​”alipay”

作者:钟代麒

出处:http://www.jishudao.com/
版权归作者所有,转载请注明出处

平安银行对接|银企对接扫雷排坑实战经验分享 感受一下财大气粗的银行对接 感受一下等长报文的痛苦 未曾经历无以感受他人在坑中崩溃状

 Yuema约吗?一起学技术,一起成长!他山之石,可以攻玉系列

程序的世界,就是有坑的地方!分享踩坑的心得与体验!每天分享一点点!
关注公众号,可获取每日分享!小手点点,即可关注!

今天先是练习了一下支付宝花呗分期对接,很快就搞定了,可以通过以下网址体验​。

http://i.zuime.com/order/alipay/payqrhb

花呗对接完,我就琢磨着平安银行对接,先扫扫雷,至少要将一个接口调​通。向同事要到一堆文档、一个PinganController.cs、一个平安前置软件​。打开前置软件word文档一看,106页,还有好几个文档,这要是一行一行看过来,不仅时间没了,而且不好抓重点。由于就后厚着脸皮问同事了​。

一、平安银行企业前置程序

这个企业前置程序就相当一个请求代理,由平安银行提供​。默认使用的是jdk1.6,也支持1.8,要手动修改一下启动脚本​。尴尬的是,修改完jdk之后,还是跑不起来。一直追着同事问,然后拿到一个新的前置程序​,启动成功。

二、掉等长报文的坑

参考同事的.net版本,感觉有些东西还是要转化来转化去,就直接拿java demo,copy过来改改。结果4001查询余额的交易老是报企业未开通银企​互联。实在是想不到法子,换了好几个对接测试账号,无一​幸免。那就建个空白的工程,把PinganController.cs贴进去,跑起来,4001交易成功​,查到了余额。ps:同事给个cs文件,也是​醉了。.Net成功了,那Java也得成功​啊。梦想是这样子,同事跑来一顿指点,坑在java的demo未做4001报文​名的等长处理。

#net 大概是这么写的,意会一下String xxcode = mmcode =="4001"? "4001    ":mmcode;

java版本则未​做这种特殊处理。修正完之后,​跑起来了。

小目标达成,休息​

小结

相比alipay的对接,平安银行的对接,简直没谁了,要不是有同事踩过一次坑,我不知道在坑里要爬多少天。传统银行跟第三方支付,有种预感觉,还有很多坑即将出现~

作者:钟代麒

出处:http://www.jishudao.com/
版权归作者所有,转载请注明出处

企业微信机器人邂逅jenkins 打造定时饭点通知机器人 准点提醒,呵护脆弱的胃

 Yuema约吗?一起学技术,一起成长!他山之石,可以攻玉系列

程序的世界,就是有坑的地方!分享踩坑的心得与体验!每天分享一点点!
关注公众号,可获取每日分享!小手点点,即可关注!

距离上一版企业微信机器人分享,已经很久很久了,有小伙伴一直问企业微信机器人开发。其实,整体上分两大类。一类是企业微信后台的应用开发,那种是可以做成交互性质的机器人,更麻烦更麻烦,二类是从群聊面板创建的“强势机器人”只发信息,不能进行交互,很简单很简单。

玩转企业微信群聊机器人 用机器人定时提醒饭点 订餐时间 任务时间 下班时间 任务代办事项 每个人都可以快速拥有的一个Robot

今天,要使用jenkins 打造一个更加精致的小机器人。之前的windows作业,有点不友好,弹窗执行。今天的jenkins,无代码,全是配置。jenkins安全,可以参考之前jblog自动构建的文章完成。

JBlog自动构建环境搭建 实战练习jenkins+sh+spring+java+github webhook 自动构建博客系统

jenkins部署提示

1.下载jar包wget http://mirrors.jenkins.io/war-stable/latest/jenkins.war2.启动jar包  nohup java -Dhudson.util.ProcessTree.disable=true -jar jenkins.war  --httpPort=8080 &nohup java -jar /data/jenkins.war --httpPort=8080 &

脚本

官方的示例代码简单的修改一下,就成了本次作业所需要的脚本代码。

curl 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=33ee91a3-b911-41f9-b86e-006416fe6b70' -H 'Content-Type: application/json' -d '{ "msgtype": "text", "text": {  "content": "饭点到,赶紧脱离工作状态,准备出发!" } }'

作业创建

  1. 选择新建作业
  2. 选择构建一个自由风格的软件项目
  3. 在构建操作中增加脚本,将脚本帖进去。
  4. 构建触发器,选择定时构建,比如早上11点45触发,则输入45 11 * * 1-5,也可以点开旁边的问号查看详细的定时构建周期配置说明。

验证

可以手动点击构建,可以看到机器人在群里发送信息。

饭点到,赶紧脱离工作状态,准备出发!

定时构建在会指定的周期进行构建,执行脚本,发出信息。

结束语

今天分享的jenkins+企业微信机器人打造饭点提醒机器人,比之前的分享更加友好些,无语堆代码,只需要使用第三方开源的产品结合企业微信机人官方demo即可实现,非常简单。如果要实现更复杂的机器人,则需要写更复杂的脚本,留个悬念~

关注公众号,期待吧!

作者:钟代麒

出处:http://www.jishudao.com/
版权归作者所有,转载请注明出处

支付宝当面付&支付宝网站支付的扫码支付 支付宝RSA2接口集成进阶 网站扫码支付的两种方式 探路支付宝集成的一点小分享 实战经验

 Yuema约吗?一起学技术,一起成长!他山之石,可以攻玉系列

程序的世界,就是有坑的地方!分享踩坑的心得与体验!每天分享一点点!
关注公众号,可获取每日分享!小手点点,即可关注!

源代码获取

关注公众号[Yuema约吗],回复“alipay”,获取完整示例代码。

今天的小目标是调通支付宝网站支付扫码支付,从最早的一个对接文档变成电脑网站支付、手机网站支付、当面付等支付产品,​不断的在变。对接不再是一个单纯的技术问题,各种签约折腾,​人在江湖,身不由已!今天完成了网站扫码支付的扫雷,文章尾部有获取本次分享的源代码​途径,可以​获取尝试。

​需求

网站支持支付宝扫码支付,要求,直接展示出支付宝二维码,让​客户能直接扫码支付。

困境

扫不到一个合适的产品,预期找到的支付产品应该是扫码支付,但是网站支付、当面付都有些出入。支付宝定义当面付是线下支付产品,这真的是好强势的支付宝​,还管我在哪里扫码。网站支付,就直接跳到支付宝了,不符合​产品需求。

惯性思维

扫码支付,先获取二维码,再支付。网站支付获取的一个页面​啊。第一感觉就是先pass掉网站支付,找新出路。实际上错了,

出路一 当面付

谁挖的坑就找谁,联系支付宝客服咨询了一下,客服说二维收款可以拍当面付的二维码。

由于是赶紧给支付宝开放平台的应用开当面付的权限,提示要签约,拍门脸照片,提申请。照着签约提示,​完成申请。吃完饭回来,通过了。接上,调用支付宝的预生成订单(当面付)接口,拿到的qrcode.

https://qr.alipay.com/bax02697tajnyczwadpl60d0

​坑:这虽然是一个qrcode,但是不是一张图片!​也不是一个iframe。是要把这个连接生成一张图片。找到一个开源的QRCode.js库,​转化成功。

晒代码

<html><head><script src="/jquery/jquery-3.2.1.min.js"></script><script src="/js/qrcode.min.js"></script></head><body><div id="qrcode"></div><div>200001568703071983</div><div><a href="/order/alipay/pay/query?tradeNo=200001568703071983" target="_blank">查询结果</a></div></body><script type="text/javascript">new QRCode(document.getElementById("qrcode"), "https://qr.alipay.com/bax02725xew4ndcdoxvb2030");</script></html>

后台代码

/**   * 预生成订单(当面付)   *    * @param out_trade_no   * @param total_amount   * @return   */  public String precreate(String outTradeNo, String subject, String totalAmount) throws Exception {    AlipayClient alipayClient = buildAlipayClient();    AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();    AlipayTradePrecreateModel model = new AlipayTradePrecreateModel();    model.setOutTradeNo(outTradeNo);    model.setTotalAmount(totalAmount);    model.setSubject(subject);    model.setBody("这是一个 body这是一个 body这是一个 body这是一个 body这是一个 body这是一个 body这是一个 body这是一个 body这是一个 body");    model.setTimeoutExpress("1m");    request.setBizModel(model);    request.setNeedEncrypt(true);    request.setReturnUrl(returnUrl);    request.setNotifyUrl(notifyUrl);    AlipayTradePrecreateResponse response = alipayClient.certificateExecute(request);    // 在这里检查订单的状态值    return response.getQrCode();  }

效果图

体验地址: https://i.zuime.com/order/alipay/pay/qrcode

当面付的效果能满足产品需求,需要自己再完善一下样式,加个支付宝的LOGO。需要前端​加点戏。

出路二 网站支付

如果仔细查网站支付的接口文档,会发现,有参数控制支付页面的显示效果,当我们调整为合适的参数值,就能在iframe里,显示一个二维码大小的窗口,让用户有种页面上拍了个二维码的真实错觉。

两个核心参数

qr_pay_modeqrcode_width

这两个参数取值为”4″,200L的时候,效果不错​。​先看看效果。

效果地址:https://i.zuime.com/order/alipay/payqr

代码

/**   * 网站支付二维码模式   * @param orderBean   * @return   * @throws Exception   */  public String tradePagePayQr(AlipayOrderBean orderBean) throws Exception {    AlipayClient alipayClient = buildAlipayClient();    AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();    AlipayTradePagePayModel model = new AlipayTradePagePayModel();    //request.setReturnUrl(returnUrl);    request.setNotifyUrl(notifyUrl);    model.setOutTradeNo(orderBean.getOutTradeNo());    model.setSubject(orderBean.getSubject());    model.setTotalAmount(orderBean.getTotalAmount());    model.setBody(orderBean.getBody());    model.setProductCode(orderBean.getProductCode());    model.setQrPayMode("4");    model.setQrcodeWidth(200L);    //model.setTimeExpire("2m");    model.setTimeoutExpress("2m");    request.setBizModel(model);    request.setNeedEncrypt(true);    return alipayClient.pageExecute(request).getBody();  }

小结:

实现网站扫码支付,可以采用支付宝的网站支付产品或当面付产品,当面付的二维码是自主生成,灵活性更强;网站支付中二维码模式是支付宝返回的一个完整的HTML页面,灵活性更低,简单粗暴,需要使用iframe来​承载。如果个性化需求不强烈,网站扫码支付可以使用支付宝的网站支付产品,传参的时候,调整为二维码模式。

源代码获取

关注公众号[Yuema约吗],回复“alipay”,获取​完整示例代码。

相关阅读

支付宝RSA2支付|小实验 接通支付回调与支付通知接口 return & notify 完美踩坑,记录一次心酸旅行时光码农生活

支付宝RSA2支付&转帐接口集成续集|继续拿jblog当实验田练习支付宝RSA2集成 & 网银直连 直连网银 转账到银行卡下线了

jblog集成RSA2支付宝接口经验分享 | 无坑不支付 证书最绕人 | 蚂蚁沙盒更愁人

作者:钟代麒

出处:http://www.jishudao.com/
版权归作者所有,转载请注明出处

支付宝RSA2支付|小实验 接通支付回调与支付通知接口 return & notify 完美踩坑,记录一次心酸旅行时光码农生活

小实验目标

对接支付宝,实现支付、转账功能。上一次做实验已经接通了支付、转账以及相关的查询接口,但是没有接上同步通知与异步通知。今天的小实现目标就是把这2个也接通!

小实验约束

由于涉及到转账功能,所以采用了目前阿里蚂蚁金服最高级别的RSA2进行验签。

小实验参考资料

电脑网站支付 Demo

https://docs.open.alipay.com/270/106291/

那些年我们踩过的坑

神坑之一:SHA256WithRSA vs SHA1WithRSA

本次小实验的坑在于支付宝提供的rsaCertCheckV2无法正常验签,RSA2对就的是SIGN_SHA256RSA_ALGORITHMS(SHA256WithRSA),而支付宝sdk对应的rsaCertCheckV2使用的却是SIGN_ALGORITHMS(SHA1WithRSA),不明白这个坑是怎么挖出来的。通过二次组装skd提供的方法,实现了一个能正常验签的rsaCertCheckV2。

神坑之二:SignCheckContent到底是V1还是V2

按RSA2对应V2的直观感受,拿AlipaySignature.getSignCheckContentV2获取得到待签名的内容,结果签名通不过,使用AlipaySignature.getSignCheckContentV1反而通过了。

神坑之三:换java jar包

ps:有网友说要替换local_policy.jar、US_export_policy.jar,因为我之前已经换过了,所以没有踩到这个坑~

实验成果

异常通过接口(Nofity),调通,拿到可供测试的参数:

{"gmt_create":"2019-09-16 17:57:47","charset":"UTF-8","gmt_payment":"2019-09-16 17:57:51","notify_time":"2019-09-16 17:57:51","subject":"醉么商城订单Zuime1568627848379","sign":"CcQEj2Jm6vk2ECjXxsD0Dq7kJVd9c6OZb8QtSnL39GvpXf+nLpMBlsFjnkBQOfVLLX8Nl3cZ6aND47hIujgl3FB2TWJwxOoPCNpv+VSlKQJvwEE9vdycQV+iQ8CZE4ibX6yXdd4VVF+TyjrwJExYbxSvMa6VAprzEcGUkpVYOpV1BUGWuKK/7k1F6eNj6RbEDG34rBet96G7rYGLQs2f3CPpxuBrOhfzVAgNEbpX9blX+LwjMEYPhXAJpqykHUxIs953sEnwIHTKqwqUxtVHqVpYyc2qeAhK3p4FL5tjhz1Aji0CN+NNdwcBKR4uCO9j/bRHCA+aAZwkAsaTlidgmg==","buyer_id":"2088002249904873","body":"醉么商城订单Zuime1568627848379","invoice_amount":"1.00","version":"1.0","notify_id":"2019091600222175751004870502101657","fund_bill_list":"[{\"amount\":\"1.00\",\"fundChannel\":\"ALIPAYACCOUNT\"}]","notify_type":"trade_status_sync","out_trade_no":"200001568627848379","total_amount":"1.00","trade_status":"TRADE_SUCCESS","trade_no":"2019091622001404870517313294","auth_app_id":"2016052201429140","receipt_amount":"1.00","point_amount":"0.00","buyer_pay_amount":"1.00","app_id":"2016052201429140","sign_type":"RSA2","seller_id":"2088021741763089"}out_trade_no: 200001568627848379trade_no: 2019091622001404870517313294trade_status: TRADE_SUCCESS

同步通知(return),调通,验签通过,拿到 trade_no

https://i.zuime.com/order/alipay/return?charset=UTF-8&out_trade_no=200001568627848379&method=alipay.trade.page.pay.return&total_amount=1.00&sign=EUXE9Hj%2FetIMQQ5sZrxEzzM6YiDbz91a9lE7v4zjxG4iMT8o6%2Fh6UiHiHc9fA4wiIoaQ8zswJbnpDeda%2BxdK6Q97ZUBBIr5kKF%2BYd4X2%2FgWhvDSD2flwic2%2Ff0JTm0Louy%2B1H6TZ80zaV9cYi68YiQunrDgVF1EOHvE0v%2B%2F42Gs6bvA7p7V%2FN8YnjEnR0smzI2hRJoY09DDC5Yk0%2BNmLyPQgEvar1L7rR6RAlPf4f8mDHH1gU%2B3D8WCtuERT%2FscrWER06V4rteSYj5NQaQ%2F6UyZ%2Fc%2FpBwgcxB6ojVmQKi2LSqEEEt%2BYIH7SpI5QhtiK4ycl2PVK%2FpghR%2FzHjh3cGWQ%3D%3D&trade_no=2019091622001404870517313294&auth_app_id=2016052201429140&version=1.0&app_id=2016052201429140&sign_type=RSA2&seller_id=2088021741763089&timestamp=2019-09-16+17%3A58%3A02
签名通过,tradeNo 200001568627848379

完美调通支付宝RSA2接口的Demo源代码可关注公众号【Yuema约吗】,回复“alipay”获取。

核心代码片段

/**   * 修复支付宝SDK的RSA2验签Bug   * @param params   * @return   * @throws Exception   */  public boolean rsaCertCheckV2(Map<String, String> params) throws Exception{    //获取        String sign = params.get("sign");        String content = AlipaySignature.getSignCheckContentV1(params);    return AlipaySignature.rsaCertCheck(content,sign, alipayCertPath, AlipayConstants.CHARSET_UTF8,AlipayConstants.SIGN_TYPE_RSA2);  }

今天实验覆盖的是return与notify,结合上一次分享,已经覆盖了接支付宝所需的接口。想了解支付、转账相关接口实验数据与踩坑经验分享,可查看上一篇分享。

支付宝RSA2支付&转帐接口集成续集|继续拿jblog当实验田练习支付宝RSA2集成 & 网银直连 直连网银 转账到银行卡下线了

PS: 我不知道使用沙盒进行测试的小伙伴是怎么配置的,卡死在支付宝证书这块,沙盒管理界面没有下载的入口,导致无法进行RSA2的沙盒实验,现在使用的是正式帐号^_^​

支付宝RSA2支付&转帐接口集成续集|继续拿jblog当实验田练习支付宝RSA2集成 & 网银直连 直连网银 转账到银行卡下线了

续集开始

经过一阵折腾,一阵折腾,目前支付宝RSA2支付接口、查询支付结果接口、转帐接口、查询转账接口都调通了。

在线体验

支付

https://i.zuime.com/order/alipay

支付结果查询

https://i.zuime.com/order/alipay/pay/query?tradeNo=200001568282831558

转账

https://i.zuime.com/order/alipay/transfer

​转账结果查询

https://i.zuime.com/order/alipay/transfer/query?bizNo=T00011568284758838

支付单查询结果

{"alipay_trade_query_response":{"code":"10000","msg":"Success","buyer_logon_id":"z***","buyer_pay_amount":"0.00","buyer_user_id":"208","invoice_amount":"0.00","out_trade_no":"200001568282831558","point_amount":"0.00","receipt_amount":"0.00","send_pay_date":"2019-09-12 18:08:04","total_amount":"1.00","trade_no":"2019091222001404870598378129","trade_status":"TRADE_SUCCESS"},"alipay_cert_sn":"d129f75444e247d1fd7641eca25e8e8e","sign":"dksLpk0DN6FOMGpys2vsR6TfjFay3abv4aGh5lbikEuG7TBo2e2OSP4ilxjg9CR061wks7fLsQkriqomu0Yt36nq5HHex5BO+WInV4YiC+4HA1fxfNCIzXNFXGIIrNxO+H/AnpGbzU7uIjJfK3k56qKLnW9sWy0J83kdIUjohyrUkdIWqYFHiQrsb6P2akxV6743haC718QjzCuU6U7lpLRD9bncQ8OH7NXOSLUN396t8O7tBkLuIsHL6Q9TlbxW41sjzUpWUs2JBA3KPy32zxpsubl918HVM2s5eIdHkP6xYBUtSPU9ZMVl6tTbeya+n302tuVeW0c52Uf5lJYEOw=="}

转帐结果

{"alipay_fund_trans_order_query_response":{"code":"10000","msg":"Success","order_fee":"0.00","order_id":"20190912110070001506080013570558","out_biz_no":"T00011568280515442","pay_date":"2019-09-12 17:28:37","status":"SUCCESS"},"alipay_cert_sn":"d129f75444e247d1fd7641eca25e8e8e","sign":"JanJ5dR9SRIP/3MCFuqGc7iPCOs2DsaQQ6AI3fYPZDXHHpUVm865iEQAuPFavXIDB0huhWnz+sE38krPgD/srSJGOCxbEF0C7e0mTqNPDUSFGxaQ7nQX3t1iIorvKylNvqT7/+3A5qm837gtwKU98Z1Xzi7b6OsqAT+1UwEOdAs1QIysUK8kt515au9J/0pNC95ObkQEq4i+hCHzt+CFXFag7EThairmT4a9ZDegFpwBrFgHODYT6N3dqS9gE5hg9ULJh0tkAjKROQFsYiaBW+YIqzgAS/d+xjt37DLNwYhGMYxPYdlN/FwDg37Ao5wNkSqfYPJEamfbMK1VBDwVXA=="}

转帐查询结果

{"alipay_fund_trans_order_query_response":{"code":"10000","msg":"Success","order_fee":"0.00","order_id":"20190912110070001506080013570558","out_biz_no":"T00011568280515442","pay_date":"2019-09-12 17:28:37","status":"SUCCESS"},"alipay_cert_sn":"d129f75444e247d1fd7641eca25e8e8e","sign":"JanJ5dR9SRIP/3MCFuqGc7iPCOs2DsaQQ6AI3fYPZDXHHpUVm865iEQAuPFavXIDB0huhWnz+sE38krPgD/srSJGOCxbEF0C7e0mTqNPDUSFGxaQ7nQX3t1iIorvKylNvqT7/+3A5qm837gtwKU98Z1Xzi7b6OsqAT+1UwEOdAs1QIysUK8kt515au9J/0pNC95ObkQEq4i+hCHzt+CFXFag7EThairmT4a9ZDegFpwBrFgHODYT6N3dqS9gE5hg9ULJh0tkAjKROQFsYiaBW+YIqzgAS/d+xjt37DLNwYhGMYxPYdlN/FwDg37Ao5wNkSqfYPJEamfbMK1VBDwVXA=="}

获取实验Demo源代码,关注公众号,回复alipay


经验分享

  1. 以下接口蚂蚁金服支付宝答复已经下线,不再接受新签约单笔转账可以转账到用户的银行账户

    网银直连 直连网银

  2. 沙盒问题:RSA2所需要的支付宝公钥证书找不到

所使用的Alipay SDK POM

        <!-- https://mvnrepository.com/artifact/com.alipay.sdk/alipay-sdk-java -->        <dependency>            <groupId>com.alipay.sdk</groupId>            <artifactId>alipay-sdk-java</artifactId>            <version>4.6.0.ALL</version>        </dependency>

官方电脑网站支付 Demo

https://docs.open.alipay.com/270/106291/

官方展示的代码是java jsp版本,非RSA2证书版本

RAS证书版本对接所用到参数

APPID应用私钥 (private key)应用公钥证书(public key cert)支付宝公钥(alipay public key)支付宝公钥证书(alipay public key cert)支付宝根证书(alipay root cert)AES Key

 示范代码片段

构建一个配置好证书的AlipayClient,之后与alipay gateway交互通过TA来进行。展示的版本是配置Aes key的,对发出去的报文进行了加密​。加密解密都是一个Aes key​。看sdk源代码,这两个key是分开的,但是使用的时候又当一成是一样的使用了。

构建AlipayClient

private AlipayClient buildAlipayClient() throws Exception {    // 构造client    CertAlipayRequest certAlipayRequest = new CertAlipayRequest();    // 设置网关地址    certAlipayRequest.setServerUrl(gateway);    // 设置应用Id    certAlipayRequest.setAppId(appId);    // 设置应用私钥    certAlipayRequest.setPrivateKey(privateKey);    // 设置请求格式,固定值json    certAlipayRequest.setFormat(AlipayConstants.FORMAT_JSON);    // 设置字符集    certAlipayRequest.setCharset(AlipayConstants.CHARSET_UTF8);    // 设置签名类型    certAlipayRequest.setSignType(AlipayConstants.SIGN_TYPE_RSA2);    // 设置应用公钥证书路径    certAlipayRequest.setCertPath(appCertPath);    // 设置支付宝公钥证书路径    certAlipayRequest.setAlipayPublicCertPath(alipayCertPath);    // 设置支付宝根证书路径    certAlipayRequest.setRootCertPath(alipayRootCertPath);    // 构造client    certAlipayRequest.setEncryptor(aesKey);    certAlipayRequest.setEncryptType(AlipayConstants.ENCRYPT_TYPE_AES);    return new DefaultAlipayClient(certAlipayRequest);  }

调用接口

所有的接口调用,命名都跟官方文档的一样,有规律可​循。来来来,先看一​小段代码片段。以查询​转账结果为例。

转账查询代码

  public String transferQuery(String bizNo) throws Exception{    AlipayClient alipayClient = buildAlipayClient();    AlipayFundTransOrderQueryRequest request = new AlipayFundTransOrderQueryRequest();    AlipayFundTransOrderQueryModel model = new AlipayFundTransOrderQueryModel();    model.setOutBizNo(bizNo);    request.setBizModel(model); //划重点    request.setNeedEncrypt(true);//划重点    AlipayFundTransOrderQueryResponse response= alipayClient.certificateExecute(request);    // 在这里检查订单的状态值    return  response.getBody();  }

官方文档的https://docs.open.alipay.com/api_28/alipay.fund.trans.order.query的接口命名正好是sdk中的xxxModel,xxxRequeset,xxxResponse,按着接口命名来,调用起来​就顺了。
之于,网上DIY一个AlipayOrderBean,自己设置JsonFeild指定实体的json别名,也是做重复工作了,sdk已经配置好了,只需要直接调用即可。从内部系统到外部系统,这个地方还值得考虑一下​。
Aes加密解密,sdk 内置了,只要配置一下aes密钥就好,不需要自己重复造个轮子​啦。可参考上面的示例代码片段。
最大的坑
支付宝公钥证书(alipay public key cert),这个是要求提供的,在沙盒环境配置界面,找不到下载入口。​怎么破?直接使用的正式环境,还好有个正式上线的商户账号​。正式的帐号可以通过安装一个开源商城,快速通过审核获取到​。^_^
最不习惯的变化
好久没有接支付的,变得越来越快了,网银直连下线了不说,现在竟然中tradePagePay,返回的不是跳转地址了,直接一个完整的html,看到这个返回结果,顿时崩溃,以为见到鬼了~
开源与分享
本次支付宝对接采用了RSA2+AES,踩的坑也不少,做为实验练习代码demo已经整合在jblog中,后续还会完善​。从产品的角度来讲,代码谈不上。做为免费开源的代码来讲,可以防坑~~
获取源代码,关注公众号回复 code

jblog集成RSA2支付宝接口经验分享 | 无坑不支付 证书最绕人 | 蚂蚁沙盒更愁人

本次集成支付宝采用了最高规格的RSA2证书版本,折腾了许久,踩了一堆坑。也算是暂时接通了一下即时到账接口。采用RSA2证书版,主要是看中转帐功能。

查看效果:https://i.zuime.com

说明:本次实验的是直接下单,到支付宝支付,返回​。这条​线是通的。

采坑​记录:

返回错误:

{“alipay_trade_query_response”:{“code”:”40006″,”msg”:”Insufficient Permissions”,”sub_code”:”isv.insufficient-isv-permissions”,”sub_msg”:”ISV权限不足,建议在开发者中心检查应用是否上线”},”alipay_cert_sn”:”d129f75444e247d1fd7641eca25e8e8e”,”sign”:”T0OOwb6ij+QLwMYDeGyt5gTnopwth0RyyskjE2/OVd8mPNvDAEfcWHqtZ3eYRXwTTsKjKJZ9HceCXHtc8ZpjG4BJMVjDWO3MrOxXSEnBgPKZOIAS/2zL7EDrruaEc78CewFf5Id0IkY+tRTI61DaETuspfxF6JaZnu25n2qVc55H32GOFnWl3EWE6rS2nBgVBxGQKBo/KasOeafaJMuxP6/cLm4nLVO57bdcMwiZP+eNHNWurFru2AXyWELLrJdyjyQMqEri13SPdcrd0S3L+vA0KyC/bPavPAObJFKhVO1Z2xQ5YZBpYh6cOha8Mhd59s99CzlkuB/Zz6qvNvaVkw==”}

问题:

蚂蚁金服沙箱测试:无效的AppID参数

https://blog.csdn.net/JinglongSource/article/details/88703105

{“alipay_trade_query_response”:{“code”:”40002″,”msg”:”Invalid Arguments”,”sub_code”:”isv.app-cert-not-exist”,”sub_msg”:”应用公钥证书不存在”}}

{“alipay_trade_query_response”:{“code”:”40004″,”msg”:”Business Failed”,”sub_code”:”ACQ.INVALID_PARAMETER”,”sub_msg”:”参数无效”},”alipay_cert_sn”:”d129f75444e247d1fd7641eca25e8e8e”,”sign”:”FyFMLDXe7mnjI61eTVeMdsQLPYm4kdrGbWuPPu1vWDzryusC/NPD2K+pHzDdU9/0BHsImaejLbbcrs4Im+CbEEtB98I0L72nwG9mktx3ZM3OAqJ933cQPjc9xKv8d5aWU61kIzPjc19nBciGtdwUQqHPMus1V1egoMNl+DHt4F73ckEGe+j0VsXxRorj0iONEnGLwVg3sgcqwUVyxgelibcWCE5UNULZvBpTo88AXu07hnYQ9Bi9Amtuv7og8jPcGmPE8x874eblJDZWW8DNmLTZB5KMNYJb+LG1lfMBUK9cmzS/L5hQk7lp17D5cr1HMA9CBKgX7rQ27+V4kZ07jA==”}

{“alipay_trade_query_response”:{“code”:”40004″,”msg”:”Business Failed”,”sub_code”:”ACQ.INVALID_PARAMETER”,”sub_msg”:”参数无效:支付宝订单号和外部订单号不能同时为空”,”buyer_pay_amount”:”0.00″,”invoice_amount”:”0.00″,”point_amount”:”0.00″,”receipt_amount”:”0.00″},”alipay_cert_sn”:”d129f75444e247d1fd7641eca25e8e8e”,”sign”:”pfAb0deXjEFFIUhm56wCwZtbGc2Hw49glCp5zILfOIUxtmWUnSEJIGTRw2t/NMbbJNUmdJDgN2KB0+Mbek4LjtkBzvKdpjjR9dGNmEQHHkm+0aNdjVfjaKHJSq8mY6pseXelLKhFbGZCXwZ8MjXX/0njpFNRqUWEkyz0XsxDurfWtQWUKU7n4COB1qi7SsqEML07/AxGzQvAHwB4CJz4MNNUmqqSumwg9eHcOkDUcISYR+9nESQ3ob1f6l0IRX19ycMuPkLS+Nsm8gOBGinxtEkEASjvRsVFb85Z46f8I9EHl1E3+S1eqAmB1oY6kirOrFQAZMhhzrPodN8ksP2YnA==”}

The attribute value is undefined for the annotation type JSONField

{“alipay_trade_query_response”:{“code”:”40004″,”msg”:”Business Failed”,”sub_code”:”ACQ.TRADE_NOT_EXIST”,”sub_msg”:”交易不存在”,”buyer_pay_amount”:”0.00″,”invoice_amount”:”0.00″,”out_trade_no”:”Test1568206863310″,”point_amount”:”0.00″,”receipt_amount”:”0.00″},”alipay_cert_sn”:”d129f75444e247d1fd7641eca25e8e8e”,”sign”:”OPDujMVlLZbyxgbkNI9Mq+wunxBbIYrYoMxc+QcNVUY91whTIKePgly6AsZkd4pZA6hHf7y0uRvYcuGnAVGB5jBxmnMo+H8lcBkHySeLLMeQqeJPkejOo/3BJtYIb2ccMffdZ6MWFZd1fGlCsBEG8QD9mGUyA2K9vB3ooZqcgvI+2jWV0iFBVkzAYsYZk938pmjpFHEtLFDrqCGIc/6Bae6oO1Yfguk8RaAnB91fqVD+3Pli46/oLK7HVHTBlmBSf6NzzE05ijZgp1G4l9POAfN6RXMHu46oNx1fuC5HGfS4ySKsJ2H5Cj9rlXr8m/mZ7pLRplgLYKWq9xEzCFciPQ==”}

明天再续~~

Yuema约吗一起学习成长之路 他山之石,可以攻玉系列|springcloud(八):配置中心服务化和高可用

 Yuema约吗?一起学技术,一起成长!他山之石,可以攻玉系列

他山之石,可以攻玉!对,就是转载文章!文章由大佬推荐,以技术为圈,画个Spring的大圆!

作者博客【纯洁的微笑】的个人介绍: 2009年,因为数学建模接触编程。2010年,经过培训走入程序员行业。2010年-2013年,在西安工作过三年,主要集中在通讯领域。2013年,清明节开始北漂,北京六年主要在第三方支付和互联网金融公司从业。2014年,从零参与组建一个互联网金融公司,2015年成为互联网金融公司技术负责人。2016年,开始写博客;2017年,开通微信公众号;2018年,第三方支付公司研发副总。2019年,选择成为一名自由职业者,开始探索更多可能性。

纯洁的微笑博客发布于2017/05/22 并不影响保质期。一起了解一下Spring Cloud

在前两篇的介绍中,客户端都是直接调用配置中心的server端来获取配置文件信息。这样就存在了一个问题,客户端和服务端的耦合性太高,如果server端要做集群,客户端只能通过原始的方式来路由,server端改变IP地址的时候,客户端也需要修改配置,不符合springcloud服务治理的理念。springcloud提供了这样的解决方案,我们只需要将server端当做一个服务注册到eureka中,client端去eureka中去获取配置中心server端的服务既可。

这篇文章我们基于配置中心git版本的内容来改造

server端改造

1、添加依赖

<dependencies>
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-config-server</artifactId>
	</dependency>
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-eureka</artifactId>
	</dependency>
</dependencies>

需要多引入spring-cloud-starter-eureka包,来添加对eureka的支持。

2、配置文件

server:
server:
  port: 8001
spring:
  application:
    name: spring-cloud-config-server
  cloud:
    config:
      server:
        git:
          uri: https://github.com/ityouknow/spring-cloud-starter/     # 配置git仓库的地址
          search-paths: config-repo                             # git仓库地址下的相对地址,可以配置多个,用,分割。
          username: username                                        # git仓库的账号
          password: password                                    # git仓库的密码
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8000/eureka/   ## 注册中心eurka地址

增加了eureka注册中心的配置

3、启动类

启动类添加@EnableDiscoveryClient激活对注册中心的支持

@EnableDiscoveryClient
@EnableConfigServer
@SpringBootApplication
public class ConfigServerApplication {

	public static void main(String[] args) {
		SpringApplication.run(ConfigServerApplication.class, args);
	}
}

这样server端的改造就完成了。先启动eureka注册中心,在启动server端,在浏览器中访问:http://localhost:8000/ 就会看到server端已经注册了到注册中心了。

按照上篇的测试步骤对server端进行测试服务正常。

客户端改造

1、添加依赖

<dependencies>
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-config</artifactId>
	</dependency>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-web</artifactId>
	</dependency>
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-eureka</artifactId>
	</dependency>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-test</artifactId>
		<scope>test</scope>
	</dependency>
</dependencies>

需要多引入spring-cloud-starter-eureka包,来添加对eureka的支持。

2、配置文件

spring.application.name=spring-cloud-config-client
server.port=8002

spring.cloud.config.name=neo-config
spring.cloud.config.profile=dev
spring.cloud.config.label=master
spring.cloud.config.discovery.enabled=true
spring.cloud.config.discovery.serviceId=spring-cloud-config-server

eureka.client.serviceUrl.defaultZone=http://localhost:8000/eureka/

主要是去掉了spring.cloud.config.uri直接指向server端地址的配置,增加了最后的三个配置:

  • spring.cloud.config.discovery.enabled :开启Config服务发现支持
  • spring.cloud.config.discovery.serviceId :指定server端的name,也就是server端spring.application.name的值
  • eureka.client.serviceUrl.defaultZone :指向注册中心的地址

这三个配置文件都需要放到bootstrap.properties的配置中

3、启动类

启动类添加@EnableDiscoveryClient激活对配置中心的支持

@EnableDiscoveryClient
@SpringBootApplication
public class ConfigClientApplication {

	public static void main(String[] args) {
		SpringApplication.run(ConfigClientApplication.class, args);
	}
}

启动client端,在浏览器中访问:http://localhost:8000/ 就会看到server端和client端都已经注册了到注册中心了。

高可用

为了模拟生产集群环境,我们改动server端的端口为8003,再启动一个server端来做服务的负载,提供高可用的server端支持。

如上图就可发现会有两个server端同时提供配置中心的服务,防止某一台down掉之后影响整个系统的使用。

我们先单独测试服务端,分别访问:http://localhost:8001/neo-config/devhttp://localhost:8003/neo-config/dev返回信息:

{
    "name": "neo-config",
    "profiles": [
        "dev"
    ],
    "label": null,
    "version": null,
    "state": null,
    "propertySources": [
        {
            "name": "https://github.com/ityouknow/spring-cloud-starter/config-repo/neo-config-dev.properties",
            "source": {
                "neo.hello": "hello im dev"
            }
        }
    ]
}

说明两个server端都正常读取到了配置信息。

再次访问:http://localhost:8002/hello,返回:hello im dev update。说明客户端已经读取到了server端的内容,我们随机停掉一台server端的服务,再次访问http://localhost:8002/hello,返回:hello im dev update,说明达到了高可用的目的。

示例代码-github

示例代码-码云​

作者:纯洁的微笑
出处:http://www.ityouknow.com/
版权归作者所有,转载请注明出处

Yuema约吗一起学习成长之路 他山之石,可以攻玉系列|springcloud(七):配置中心svn示例和refresh

 Yuema约吗?一起学技术,一起成长!他山之石,可以攻玉系列

他山之石,可以攻玉!对,就是转载文章!文章由大佬推荐,以技术为圈,画个Spring的大圆!

作者博客【纯洁的微笑】的个人介绍: 2009年,因为数学建模接触编程。2010年,经过培训走入程序员行业。2010年-2013年,在西安工作过三年,主要集中在通讯领域。2013年,清明节开始北漂,北京六年主要在第三方支付和互联网金融公司从业。2014年,从零参与组建一个互联网金融公司,2015年成为互联网金融公司技术负责人。2016年,开始写博客;2017年,开通微信公众号;2018年,第三方支付公司研发副总。2019年,选择成为一名自由职业者,开始探索更多可能性。

纯洁的微笑博客发布于2017/05/23 并不影响保质期。一起了解一下Spring Cloud

上一篇springcloud(六):配置中心git示例留了一个小问题,当重新修改配置文件提交后,客户端获取的仍然是修改前的信息,这个问题我们先放下,待会再讲。国内很多公司都使用的svn来做代码的版本控制,我们先介绍以下如何使用svn+Spring Cloud Config来做配置中心。

svn版本

同样先示例server端的代码,基本步骤一样。

1、添加依赖

<dependencies>
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-config-server</artifactId>
	</dependency>
	<dependency>
		<groupId>org.tmatesoft.svnkit</groupId>
		<artifactId>svnkit</artifactId>
	</dependency>
</dependencies>

需要多引入svnkitr包

2、配置文件

server:
  port: 8001

spring:
  cloud:
    config:
      server:
        svn:
          uri: http://192.168.0.6/svn/repo/config-repo
          username: username
          password: password
        default-label: trunk
  profiles:
    active: subversion
  application:
    name: spring-cloud-config-server

和git版本稍有区别,需要显示声明subversion.

3、启动类

启动类没有变化,添加@EnableConfigServer激活对配置中心的支持

@EnableConfigServer
@SpringBootApplication
public class ConfigServerApplication {

	public static void main(String[] args) {
		SpringApplication.run(ConfigServerApplication.class, args);
	}
}

4、测试

服务端测试

访问:http://localhost:8001/neo-config-dev.properties,返回:neo.hello: hello im dev,说明服务端可以正常读取到svn代码库中的配置信息。修改配置文件neo-config-dev.properties中配置信息为:neo.hello=hello im dev update,再次在浏览器访问http://localhost:8001/neo-config-dev.properties,返回:neo.hello: hello im dev update。说明server端会自动读取最新提交的内容

客户端测试

客户端直接使用上一篇示例项目spring-cloud-config-client来测试,配置基本不用变动。启动项目后访问:http://localhost:8002/hello,返回:hello im dev update说明已经正确的从server端获取到了参数。同样修改svn配置并提交,再次访问http://localhost:8002/hello“依然获取的是旧的信息,和git版本的问题一样。

refresh

现在来解决上一篇的遗留问题,这个问题在svn版本中依然存在。Spring Cloud Config分服务端和客户端,服务端负责将git(svn)中存储的配置文件发布成REST接口,客户端可以从服务端REST接口获取配置。但客户端并不能主动感知到配置的变化,从而主动去获取新的配置。客户端如何去主动获取新的配置信息呢,springcloud已经给我们提供了解决方案,每个客户端通过POST方法触发各自的/refresh

修改spring-cloud-config-client项目已到达可以refresh的功能。

1、添加依赖

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

增加了spring-boot-starter-actuator包,spring-boot-starter-actuator是一套监控的功能,可以监控程序在运行时状态,其中就包括/refresh的功能。

2、 开启更新机制

需要给加载变量的类上面加载@RefreshScope,在客户端执行/refresh的时候就会更新此类下面的变量值。

@RestController
@RefreshScope // 使用该注解的类,会在接到SpringCloud配置中心配置刷新的时候,自动将新的配置更新到该类对应的字段中。
class HelloController {

    @Value("${neo.hello}")
    private String hello;

    @RequestMapping("/hello")
    public String from() {
        return this.hello;
    }
}

3、测试

springboot 1.5.X 以上默认开通了安全认证,所以需要在配置文件application.properties添加以下配置

management.security.enabled=false

OK 这样就改造完了,以post请求的方式来访问http://localhost:8002/refresh 就会更新修改后的配置文件。

我们再次来测试,首先访问http://localhost:8002/hello,返回:hello im dev,我将库中的值修改为hello im dev update。在win上面打开cmd执行curl -X POST http://localhost:8002/refresh,返回["neo.hello"]说明已经更新了neo.hello的值。我们再次访问http://localhost:8002/hello,返回:hello im dev update,客户端已经得到了最新的值。

每次手动刷新客户端也很麻烦,有没有什么办法只要提交代码就自动调用客户端来更新呢,github的webhook是一个好的办法。

4、webhook

WebHook是当某个事件发生时,通过发送http post请求的方式来通知信息接收方。Webhook来监测你在Github.com上的各种事件,最常见的莫过于push事件。如果你设置了一个监测push事件的Webhook,那么每当你的这个项目有了任何提交,这个Webhook都会被触发,这时Github就会发送一个HTTP POST请求到你配置好的地址。

如此一来,你就可以通过这种方式去自动完成一些重复性工作,比如,你可以用Webhook来自动触发一些持续集成(CI)工具的运作,比如Travis CI;又或者是通过 Webhook 去部署你的线上服务器。下图就是github上面的webhook配置。

  • Payload URL :触发后回调的URL
  • Content type :数据格式,两种一般使用json
  • Secret :用作给POST的body加密的字符串。采用HMAC算法
  • events :触发的事件列表。
events事件类型 描述
push 仓库有push时触发。默认事件
create 当有分支或标签被创建时触发
delete 当有分支或标签被删除时触发

svn也有类似的hook机制,每次提交后会触发post-commit脚本,我们可以在这里写一些post请求

这样我们就可以利用hook的机制去触发客户端的更新,但是当客户端越来越多的时候hook支持的已经不够优雅,另外每次增加客户端都需要改动hook也是不现实的。其实Spring Cloud给了我们更好解决方案,后面文章来介绍。

示例代码-github

示例代码-码云

作者:纯洁的微笑
出处:http://www.ityouknow.com/
版权归作者所有,转载请注明出处