JAVA实现的支付宝扫描二维码支付_weixin_33720078的博客-程序员宅基地

技术标签: java  数据库  

支付项目采用springMvc+Dubbo架构实现,只对外提供接口

前期酝酿准备

最近项目中要上线支付功能、前段时间刚开发完微信的扫码支付、不得不说微信开发团队的文档真是一个烂。但总算是对照着API把功能交付上线了。

前几天公司申请下来了企业支付宝,得空所以也把支付宝的扫码支付给集成进去。这里又不得不说,是支付宝的文档写的不咋地还是自己没有仔细阅读,总之翻遍了API最终在沙箱里面运行成功(切记、认真读文档,不然各种BUG等着你)

什么是扫码支付?

扫码支付,指用户打开支付宝钱包中的“扫一扫”功能,扫描商家展示在某收银场景下的二维码并进行支付的模式。该模式适用于线下实体店支付、面对面支付等场景。

业务流程:
LB1KXhmLXXXXXaIapXXXXXXXXXX.png
使用步骤:
LB1UHBDLXXXXXbdXFXXXXXXXXXX.png
用户登陆支付宝钱包,点击首页“付款-扫码付”,进入扫一扫界面;
收银员在商家收银系统操作生成支付宝订单,用户确认支付金额,并生成二维码;
用户使用钱包的“扫码付”,扫收银员提供的二维码,确认支付;
用户付款后商家收银系统会拿到支付成功或者失败的结果。

具体产品介绍

如何快速接入?

前面的大家可以大体了解一下

开放平台服务端SDK下载地址(这里选择JAVA版本)、点击下载、里面有详细的API测试方法。

如何集成到项目中去?

下载DEMO解压、仔细阅读里面的readme.txt文件、里面有详细的项目结构。

参数配置zfbinfo.properties(沙箱环境网关参数不同)


  1. # 支付宝网关名、partnerId和appId
  2. #open_api_domain = https://openapi.alipay.com/gateway.do
  3. #支付宝沙箱环境
  4. open_api_domain = https://openapi.alipaydev.com/gateway.do
  5. mcloud_api_domain = http://mcloudmonitor.com/gateway.do
  6. pid = 此处请填写你的PID
  7. appid = 此处请填写你当面付的APPID
  8. # RSA私钥、公钥和支付宝公钥
  9. private_key = 此处请填写你的商户私钥且转PKCS8格式
  10. public_key = 此处请填写你的商户公钥
  11. alipay_public_key = MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDDI6d306Q8fIfCOaTXyiUeJHkrIvYISRcc73s3vF1ZT7XN8RNPwJxo8pWaJMmvyTn9N4HQ632qJBVHf8sxHi/fEsraprwCtzvzQETrNRwVxLO5jVmRGi60j8Ue1efIlzPXV9je9mkjzOmdssymZkh2QhUrCmZYI/FCEa3/cNMW0QIDAQAB
  12. # 当面付最大查询次数和查询间隔(毫秒)
  13. max_query_retry = 5
  14. query_duration = 5000
  15. # 当面付最大撤销次数和撤销间隔(毫秒)
  16. max_cancel_retry = 3
  17. cancel_duration = 2000
  18. # 交易保障线程第一次调度延迟和调度间隔(秒)
  19. heartbeat_delay = 5
  20. heartbeat_duration = 900

RSA私钥、公钥和支付宝公钥 获取方法。
生成与配置密钥

这里我选择的是方式一,使用支付宝提供的一键生成工具(内附使用说明)。

如果是JAVA程序public_key参数对应rsa_private_key_pkcs8.pem文件里面的内容,
public_key参数对用rsa_public_key.pem文件里面的内容。然后把公钥复制到沙箱中的RSA(SHA1)密钥中生成支付宝公钥、对应的是alipay_public_key参数。

如何生成二维码订单?

然后你就可以运行Main.java 中的额main方法进行测试了,运行结果如下:


  1. [acts_pay]|2016-11-04 15:23:35:530|Configs{支付宝openapi网关: https://openapi.alipaydev.com/gateway.do
  2. , 支付宝mcloudapi网关域名: http://mcloudmonitor.com/gateway.do
  3. , pid: 2088102169116018
  4. , appid: 2016073000123724
  5. , 商户RSA私钥: MIICdw******rLZis=
  6. , 商户RSA公钥: MIGfMA******IDAQAB
  7. , 支付宝RSA公钥: MIGfMA******IDAQAB
  8. , 查询重试次数: 5
  9. , 查询间隔(毫秒): 5000
  10. , 撤销尝试次数: 3
  11. , 撤销重试间隔(毫秒): 2000
  12. , 交易保障调度延迟(秒): 5
  13. , 交易保障调度间隔(秒): 900
  14. }
  15. [acts_pay]|2016-11-04 15:23:35:719|trade.precreate bizContent:{"out_trade_no":"tradeprecreate14782442155652020005","seller_id":"","total_amount":"0.01","undiscountable_amount":"0","subject":"xxx品牌xxx门店当面付扫码消费","body":"购买商品3件共20.00元","goods_detail":[{"goods_id":"goods_id001","goods_name":"xxx小面包","quantity":1,"price":"10"},{"goods_id":"goods_id002","goods_name":"xxx牙刷","quantity":2,"price":"5"}],"operator_id":"test_operator_id","store_id":"test_store_id","extend_params":{"sys_service_provider_id":"2088100200300400500"}}
  16. [acts_pay]|2016-11-04 15:23:37:875|{"alipay_trade_precreate_response":{"code":"10000","msg":"Success","out_trade_no":"tradeprecreate14782442155652020005","qr_code":"https:\/\/qr.alipay.com\/bax03938xgzra2b5pijd00d2"},"sign":"LA2d5txq43c3t12sCsNEEGvu3plXUrqrd/uyzOy4HIMM5eRkWXaFkL+wqVNcYX/Jfn6no72yqiAUvYAivaWZkXZA3UxTRYlW+0EwZ96HrpnjFCK+QGOSDZuoiA2AyQlFgM/cQwdgTFGI+R2X9QZWxft1z3zYVG1uRGEZXed5RPQ="}
  17. [acts_pay]|2016-11-04 15:23:37:878|支付宝预下单成功: )
  18. [acts_pay]|2016-11-04 15:23:37:878|code:10000, msg:Success
  19. [acts_pay]|2016-11-04 15:23:37:878|body:{"alipay_trade_precreate_response":{"code":"10000","msg":"Success","out_trade_no":"tradeprecreate14782442155652020005","qr_code":"https:\/\/qr.alipay.com\/bax03938xgzra2b5pijd00d2"},"sign":"LA2d5txq43c3t12sCsNEEGvu3plXUrqrd/uyzOy4HIMM5eRkWXaFkL+wqVNcYX/Jfn6no72yqiAUvYAivaWZkXZA3UxTRYlW+0EwZ96HrpnjFCK+QGOSDZuoiA2AyQlFgM/cQwdgTFGI+R2X9QZWxft1z3zYVG1uRGEZXed5RPQ="}
  20. [acts_pay]|2016-11-04 15:23:37:878|filePath:D:\qr.png

最后下载沙箱钱包就可以完成手机支付了。

下载地址

如何实现异步通知?

相关参数说明

用户会用手机扫码给支付宝付款,然后支付宝收到之后会发送一条支付成功的消息给我们设置的notify_url


  1. import java.io.BufferedOutputStream;
  2. import java.util.Enumeration;
  3. import java.util.HashMap;
  4. import java.util.Map;
  5. import javax.servlet.http.HttpServletRequest;
  6. import javax.servlet.http.HttpServletResponse;
  7. import org.springframework.beans.factory.annotation.Autowired;
  8. import org.springframework.stereotype.Controller;
  9. import org.springframework.web.bind.annotation.RequestMapping;
  10. import org.springframework.web.bind.annotation.RequestMethod;
  11. import com.acts.web.acc.service.IWeixinPayService;
  12. import com.acts.web.common.utils.LogUtil;
  13. import com.alipay.api.AlipayApiException;
  14. import com.alipay.api.internal.util.AlipaySignature;
  15. import com.alipay.demo.trade.config.Configs;
  16. @Controller
  17. @RequestMapping(value = "alipay")
  18. public class AliPayController {
  19. //初始化参数 不然signVerified会验证失败
  20. static {
  21. Configs.init("zfbinfo.properties");
  22. }
  23. /**
  24. * 支付宝支付回调
  25. * @Author 小柒
  26. * @param request
  27. * @param response
  28. * @throws Exception
  29. * void
  30. * @Date 2016年10月31日 更新日志 2016年10月31日 小柒 首次创建
  31. *
  32. */
  33. @SuppressWarnings("unchecked")
  34. @RequestMapping(value = "pay",method = RequestMethod.POST)
  35. public void alipay_notify(HttpServletRequest request, HttpServletResponse response) throws Exception {
  36. LogUtil.info("支付宝付款异步通知!");
  37. String message = "success";
  38. Map<String, String> params = new HashMap<String, String>();
  39. // 取出所有参数是为了验证签名
  40. Enumeration<String> parameterNames = request.getParameterNames();
  41. while (parameterNames.hasMoreElements()) {
  42. String parameterName = parameterNames.nextElement();
  43. params.put(parameterName, request.getParameter(parameterName));
  44. }
  45. //验证签名
  46. boolean signVerified = false;
  47. try {
  48. signVerified = AlipaySignature.rsaCheckV1(params, Configs.getAlipayPublicKey(), "UTF-8");
  49. } catch (AlipayApiException e) {
  50. e.printStackTrace();
  51. message = "failed";
  52. }
  53. if (signVerified) {
  54. LogUtil.info("验证签名成功!");
  55. // 若参数中的appid和填入的appid不相同,则为异常通知
  56. if (!Configs.getAppid().equals(params.get("app_id"))) {
  57. LogUtil.info("与付款时的appid不同,此为异常通知,应忽略!");
  58. message = "failed";
  59. }else{
  60. String outtradeno = params.get("out_trade_no");
  61. LogUtil.info(outtradeno + "号订单回调通知。");
  62. //在数据库中查找订单号对应的订单,并将其金额与数据库中的金额对比,若对不上,也为异常通知
  63. String status = params.get("trade_status");
  64. if (status.equals("WAIT_BUYER_PAY")) { // 如果状态是正在等待用户付款
  65. } else if (status.equals("TRADE_CLOSED")) { // 如果状态是未付款交易超时关闭,或支付完成后全额退款
  66. } else if (status.equals("TRADE_SUCCESS") || status.equals("TRADE_FINISHED")) { // 如果状态是已经支付成功
  67. //成功 更新状态
  68. } else {
  69. weixinpayBack.updateAccOrder(outtradeno);
  70. }
  71. LogUtil.info(outtradeno + "订单的状态已经修改为" + status);
  72. }
  73. } else { // 如果验证签名没有通过
  74. message = "failed";
  75. LogUtil.info("验证签名失败!");
  76. }
  77. BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
  78. out.write(message.getBytes());
  79. out.flush();
  80. out.close();
  81. }
  82. }
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_33720078/article/details/90591314

智能推荐

Spring基础_椰子Tyshawn的博客-程序员宅基地

Spring体系结构Spring 框架是一个分层架构,它包含一系列的功能要素并被分为大约20个模块。这些模块分为Core Container、Data Access/Integration、Web、AOP(Aspect Oriented Programming)、Instrumentation和测试部分,如下图所示: 面向接口编程结构设计中,分清层次及调用关系,每层只向外(上层...

使用git教程-一篇就够了_ForFuture Code的博客-程序员宅基地

将本地仓库与远程github中的仓库关联  要关联一个远程库,使用命令git remote add origin [email protected]:path/repo-name.git;git remote add origin [email protected]:gqzdev/vue-start.git   关联后,使用命令git push -u origin master第一次推送m...

SVN工具05:客户端使用说明_hanchao5272的博客-程序员宅基地

超级连接:SVN配置与使用说明-序章SVN客户端使用检出服务器端版本库到本地1. 在visualSVN Server左侧菜单中,右键点击版本库中trunk目录,在右键菜单中,点击Copy URL to Cilpboard(将URL复制到剪切板),获取URL地址。如下图所示: 2. 在本地某目录创建文件夹作为本地库存放地址,命名随意。3. 右键点击本地库文件夹,在右键菜...

ubuntu 20.04 意外升级内核 导致virtualbox 无法启动虚拟机_平凡之路漫漫的博客-程序员宅基地_ubuntu20 virtualbox

参考: https://blog.csdn.net/chunlongyuan/article/details/8565874 《virtualbox无法启动Kernel driver not installed (rc=-1908)》 https://www.linuxidc.com/Linux/2017-11/148871.htm 《Virtualbox提示“Kernel driver not installed (rc=-1908)”问题修复一例》 # 下面...

No.1 数组的反转_Starry....的博客-程序员宅基地_数组反转时间复杂度

emmm..... ,作为本人第一篇博客的话,还是有一些话想对自己说,学无止境,干一行爱一行,我希望我能在程序员的路上每天都有很多新的挑战,让我的生活不再无聊,热爱生活的每一天,希望能够进入自己心目中最好的BAT去学习,认识更多志同道合的朋友,一起挑战新的东西。加油!小梅你不能放弃!!!一个简简单单的数组反转,既考察了我们的基础,对数组的认识,又更好的让我们了解到了时间复杂度和空间复杂度。我当初在做这道题的时候想到了两种解法,但都是数组的方法。方法一:引入一个外部数组变量,用于保存...

centos 6.5 安装配置LAMP(linux,apache,mysql,php)环境_阿树不上树的博客-程序员宅基地

一、安装apahce1、更新yumyum update输入y更新2、安装apacheyum install httpd输入y安装3、可选择安装apache的帮助文档yum install httpd-manual访问文档:http://localhost/manual/howto/cgi4、启动apache/etc/init.

随便推点

Linux pwn入门教程,pwn堆入门系列教程1_逆光的温暖的博客-程序员宅基地

pwn堆入门系列教程1因为自己学堆的时候,找不到一个系统的教程,我将会按照ctf-wiki的目录一步步学下去,尽量做到每周有更新,方便跟我一样刚入门堆的人学习,第一篇教程研究了4天吧,途中没人指导。。很尴尬,自己一个很容易的点研究了很久才懂,把踩过的坑也总结下,方便后人不再踩坑学习链接环境搭建off by one原理(引用ctf-wiki)off-by-one 是指单字节缓冲区溢出,这种漏洞的产生...

SQLite在指定列后面插入字段_mysql列修改怎么操作?-mysql教程_weixin_39563132的博客-程序员宅基地

mysql修改列的方法:1、使用“ALTER TABLE 表名 MODIFY 字段名称 字段类型 [完整性约束条件]”来修改列的数据类型;2、使用“ALTER TABLE 表名 CHANGE 旧列名 新列名 新数据类型;”来修改列的名称。(推荐教程:mysql视频教程)修改字段属性--数据类型:-- 修改字段属性-- ALTER TABLE tb_name MODIFY 字段名称 字段类型 [...

Keras2.2.2离线安装依赖包依赖Keras2.1.6解决方法。_eva1244的博客-程序员宅基地

离线使用pip install 本地的whl包,结果发现keras2.2.2安装失败,照着提示依赖找到了Keras_Applications-1.0.4与Keras_Preprocessing-1.0.2,结果依赖了Keras 2.1.6方法一:老老实实安装Keras 2.1.6,再安装Keras_Applications-1.0.4与Keras_Preprocessing-1.0.2,再...

arduino+oled显示字_jun_军的博客-程序员宅基地

OLED 显示屏有四个引脚,分别是:SDA(数据线) SCK(时钟线) VDD(3.3V) GND在UNO开发板上I2C接口,SDA对应D4,SCK对应D5在MEGA2560开发板上I2C接口,SDA对应D20, SCL对应D21首先下载一个外部库u8glib然后去#include "U8glib.h" U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT...

用 M1 MacBook 当主力开发机:程序员使用半个月后如是说_程序员的成长之路的博客-程序员宅基地

程序员的成长之路互联网/程序员/技术/资料共享关注阅读本文大概需要 3.5 分钟。来自:量子位MacBook换成ARM芯片后,它还是程序员的开发利器吗?经过国外程序员半个多月来的尝试,一...

王霸雄图荣华敝屣,谈笑间尽归尘土|基于Python3双队列数据结构搭建股票/外汇交易匹配撮合系统_v3u.cn的博客-程序员宅基地

原文转载自「刘悦的技术博客」https://v3u.cn/a_id_192如果你爱他,那么送他去股市,因为那里是天堂;如果你恨他,送他去股市,因为那里是地狱。在过去的一年里,新冠疫情持续冲击世界经济,全球主要股票市场的波动都相对频繁,尤其是A股,正所谓:曾经跌停难为鬼,除非解套才做人;抄底时难抛亦难,反弹无力百花残。对于波谲云诡的股票市场,新投资人还是需要谨慎入场,本次我们来利用双队列的数据结构实现实时在线交易匹配引擎,探索股票交易的奥秘。首先需要明确一点,证券交易和传统的B2C电商系统交易完全

推荐文章

热门文章

相关标签