支付宝app支付java后台流程、原理分析(含nei wang chuan tou)

 java版支付宝app支付流程及原理分析

  本实例是基于springmvc框架编写
     一、流程步骤
         1.执行流程
           当手机端app(就是你公司开发的app)在支付页面时,调起服务端(后台第1个创建订单接口)接口,后台把需要调起支付宝支付的参数返回给手机端,手机端拿到
         这些参数后,拉起支付宝支付环境完成支付,完成支付后会调异步通知(第2个接口),此时需要给支付宝返回成功或者失败信息,成功后会调用同步通知(第3个接口)
         返回支付成功页面,完成整个支付流程。
        
         2.支付的配置文件AlipayConfig           

 1 public class AlipayConfig {
 2     // 1.商户appid
 3     public static String APPID = "20170812********";    
 4     
 5     // 2.私钥 pkcs8格式的
 6     public static String RSA_PRIVATE_KEY ="";
 7     
 8     // 3.支付宝公钥
 9     public static String ALIPAY_PUBLIC_KEY = "";
10     
11     // 4.服务器异步通知页面路径 需http://或者https://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
12     public static String notify_url = "http://www.xxx.com/alipay/notify_url.do";
13     
14     // 5.页面跳转同步通知页面路径 需http://或者https://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问 商户可以自定义同步跳转地址
15     public static String return_url = "http://www.xxx.com/alipay/return_url.do";
16     
17     // 6.请求网关地址
18     public static String URL = "https://openapi.alipay.com/gateway.do";    
19     
20     // 7.编码
21     public static String CHARSET = "UTF-8";
22     
23     // 8.返回格式
24     public static String FORMAT = "json";
25     
26     // 9.加密类型
27     public static String SIGNTYPE = "RSA2";
28     
29 }

 

 
         3.第1个创建订单接口

 

 1 /**
 2 *@param userId        充值人
 3 *@param tradeMoney    充值money(RMB)
 4 *@throws AlipayApiException  ModelAndView
 5  */
 6  @RequestMapping(value="api/alipay/createOrder",method={RequestMethod.POST,RequestMethod.GET})
 7  @ResponseBody
 8  public Model alipay(
 9         @RequestParam("userId")String userId,
10         @RequestParam("tradeMoney")String tradeMoney,Model m) throws AlipayApiException{
11     
12     String orderStr = "";         
13     try {
14         
15         /****** 1.封装你的交易订单开始 *****/                                        //自己用
16         
17         此处封装你的订单数据,订单状态可以设置为等待支付
18         
19         /****** 1.封装你的交易订单结束 *****/
20         
21         Map<String,String> orderMap = new LinkedHashMap<String,String>();            //订单实体
22         Map<String,String> bizModel = new LinkedHashMap<String,String>();            //公共实体
23         
24         /****** 2.商品参数封装开始 *****/                                            //手机端用                
25         // 商户订单号,商户网站订单系统中唯一订单号,必填
26         orderMap.put("out_trade_no",trade.getOrderNumber());
27         // 订单名称,必填
28         orderMap.put("subject","手机网站支付购买游戏币");
29         // 付款金额,必填
30         orderMap.put("total_amount",tradeMoney);
31         // 商品描述,可空
32         orderMap.put("body","您购买游戏币"+tradeMoney +"元");
33         // 超时时间 可空
34         orderMap.put("timeout_express","30m");
35         // 销售产品码 必填
36         orderMap.put("product_code","QUICK_WAP_PAY");
37         
38         /****** 2.商品参数封装结束 *****/    
39         
40         /******--------------- 3.公共参数封装 开始 ------------------------*****/        //支付宝用
41         //1.商户appid
42         bizModel.put("app_id",AlipayConfig.APPID);
43         //2.请求网关地址
44         bizModel.put("method",AlipayConfig.URL);
45         //3.请求格式
46         bizModel.put("format",AlipayConfig.FORMAT);
47         //4.回调地址
48         bizModel.put("return_url",AlipayConfig.return_url);
49         //5.私钥
50         bizModel.put("private_key",AlipayConfig.RSA_PRIVATE_KEY);
51         //6.商家id
52         bizModel.put("seller_id","2088102170411333");
53         //7.加密格式
54         bizModel.put("sign_type",AlipayConfig.SIGNTYPE+"");
55         
56         /******--------------- 3.公共参数封装 结束 ------------------------*****/
57         
58         //实例化客户端  
59         AlipayClient client = new DefaultAlipayClient(AlipayConfig.URL, AlipayConfig.APPID, AlipayConfig.RSA_PRIVATE_KEY, AlipayConfig.FORMAT, AlipayConfig.CHARSET, AlipayConfig.ALIPAY_PUBLIC_KEY,AlipayConfig.SIGNTYPE);
60         
61         //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay 
62         AlipayTradeAppPayRequest ali_request = new AlipayTradeAppPayRequest();  
63         
64         //SDK已经封装掉了公共参数,这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。  
65         AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();  
66         model.setPassbackParams(URLEncoder.encode((String)orderMap.get("body").toString()));;  //描述信息  添加附加数据  
67         model.setBody(orderMap.get("body"));                        //商品信息
68         model.setSubject(orderMap.get("subject"));                  //商品名称
69         model.setOutTradeNo(orderMap.get("out_trade_no"));          //商户订单号(自动生成)
70         model.setTimeoutExpress(orderMap.get("timeout_express"));     //交易超时时间
71         model.setTotalAmount(orderMap.get("total_amount"));         //支付金额
72         model.setProductCode(orderMap.get("product_code"));         //销售产品码
73         model.setSellerId("20881021********");                        //商家id
74         ali_request.setBizModel(model);  
75         ali_request.setNotifyUrl(AlipayConfig.notify_url);          //回调地址  
76         
77         AlipayTradeAppPayResponse response = client.sdkExecute(ali_request);  
78         orderStr = response.getBody();  
79         System.err.println(orderStr);                                //就是orderString 可以直接给客户端请求,无需再做处理。  
80         
81         m.addAttribute("result",orderStr);
82         m.addAttribute("status",0);
83         m.addAttribute("msg","订单生成成功");
84         
85     } catch (Exception e) {
86          m.addAttribute("status",1);
87          m.addAttribute("msg","订单生成失败");
88     }
89     
90     return m;
91 }

   
         4.第2个异步回调接口

 1   /**
 2  * 支付宝支付成功后.回调该接口
 3  * @param request
 4  * @return
 5  * @throws IOException
 6  */  
 7 @RequestMapping(value="api/alipay/notify_url",method={RequestMethod.POST,RequestMethod.GET})
 8 @ResponseBody
 9 public String notify(HttpServletRequest request,HttpServletResponse response) throws IOException {  
10     Map<String, String> params = new HashMap<String, String>();  
       Map<String, String[]> requestParams = request.getParameterMap();  
       Trade trade =null;
11 //1.从支付宝回调的request域中取值 12 Map<String, String[]> requestParams = request.getParameterMap(); 13 14 for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext();) { 15 String name = iter.next(); 16 String[] values = requestParams.get(name); 17 String valueStr = ""; 18 for (int i = 0; i < values.length; i++) { 19 valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ","; 20 } 21 // 乱码解决,这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化 22 // valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk"); 23 params.put(name, valueStr); 24 } 25 //2.封装必须参数 26 String out_trade_no = request.getParameter("out_trade_no"); // 商户订单号 27 String orderType = request.getParameter("body"); // 订单内容 28 String tradeStatus = request.getParameter("trade_status"); //交易状态 29 30 //3.签名验证(对支付宝返回的数据验证,确定是支付宝返回的) 31 boolean signVerified = false; 32 try { 33 //3.1调用SDK验证签名 34 signVerified = AlipaySignature.rsaCheckV1(params, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.CHARSET, AlipayConfig.SIGNTYPE);35 } catch (AlipayApiException e) { 36 e.printStackTrace(); 37 } 38 //4.对验签进行处理 39 if (signVerified) { //验签通过 40 if(tradeStatus.equals("TRADE_SUCCESS")) { //只处理支付成功的订单: 修改交易表状态,支付成功 41 Trade trade = tradeService.selectByOrderNumber(out_trade_no); 42 trade.setTradeStatus((byte)3); //支付完成 43 int returnResult = tradeService.updateByPrimaryKeySelective(trade); //更新交易表中状态 44 if(returnResult>0){ 45 return "success"; 47 }else{ 48 return "fail"; 50 } 51 }else{ 52 return "fail"; 53 } 54 } else { //验签不通过 55 System.err.println("验签失败"); 57 return "fail"; 58 } 59 }

    
         5.第3个同步通知接口

 1    /**
 2     * 支付宝支付成功后.通知页面
 3     *@author Zhao
 4     *@date 2017年11月2日
 5     *@param request
 6     *@return
 7     *@throws UnsupportedEncodingException
 8      */
 9     @RequestMapping(value="api/alipay/return_url",method={RequestMethod.POST,RequestMethod.GET})
10     @ResponseBody
11     public Model returnUrl(@RequestParam("id") String id,HttpServletRequest request,Model model) throws UnsupportedEncodingException {  
12         System.err.println("。。。。。。 同步通知 。。。。。。");
13         System.err.println("。。。。。。 同步通知 。。。。。。");
14         System.err.println("。。。。。。 同步通知 。。。。。。");
15         Map  returnMap = new HashMap();  
16         try {
17             
18             Trade trade = tradeService.selectByOrderNumber(id);
19              // 返回值Map  
20             if(trade !=null && trade.getTradeStatus() == 2){
21                 User user = userService.selectByPrimaryKey(trade.gettUserId());
22                 returnMap.put("tradeType", trade.getTradeType());             //支付方式
23                 returnMap.put("phoneNum", user.getPhoneNumber());             //支付帐号
24                 returnMap.put("tradeMoney", trade.getTradeMoney()+"");        //订单金额
25                 
26             }else{
27                  model.addAttribute("msg", "查询失败");
28                  model.addAttribute("status", 0);
29             }
30              model.addAttribute("returnMap", returnMap);
31              System.err.println(returnMap);
32              model.addAttribute("msg", "查询成功");
33              model.addAttribute("status", 0);
34         } catch (Exception e) {
35             model.addAttribute("msg", "查询失败");
36             model.addAttribute("status", 1);
37         }
38          
39          return model;  
40     }

    二、测试

  支付宝在app端支付成功后,要调用异步通知,因些需要访问的url必须是外网可以访问的,在这里推荐一款内网穿透工具natapp,需要用身份证号验证,测试个支付是没问题的

   附:

    1. natapp官网: https://natapp.cn

    2.natapp 1分钟新手图文教程: https://natapp.cn/article/natapp_newbie

    
    三、流程分析:
         1.配置文件AlipayConfig注意事项:
             (1)注意沙箱环境和正式环境的不同:
                商户appid    :
                    沙箱:进入沙箱环境会自动分配
                    正式:商户唯一的标识
                请求网关地址:
                    沙箱:https://openapi.alipaydev.com/gateway.do
                    正式:https://openapi.alipay.com/gateway.do
             (2)公钥和私钥
                 公钥和私钥是自己生成的不要配错,与支付宝的公钥不要混淆了。(详情见:https://docs.open.alipay.com/204/105297)
         2. 本案例只是对支付进行说明,退款等功能可进行举一反三编写。
   3.本人由于能力水平有限.有不到之处请大家多多指教!!!

转载于:https://www.cnblogs.com/MrRightZhao/p/7852511.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/428508.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python实现决策树数据直接赋值导入_决策树在python中的数据实现

我为python决策树算法实现完成了以下代码&#xff1a;from csv import readerdef load_csv(filename):file open(filename, "rb")lines reader(file)dataset list(lines)return dataset# Split a dataset based on an attribute and an attribute valuedef test_s…

互评Beta版本(Hello World!——SkyHunter)

1 基于NABCD评论作品&#xff0c;及改进建议 SkyHunter这款游戏我很喜欢&#xff0c;小时候总玩飞机类的游戏&#xff0c;这款游戏我上课的时候试玩了&#xff0c;在我电脑上运行是很好玩的&#xff0c;音乐震撼&#xff0c;画面玄幻&#xff0c;富有金属音乐的味道&#xff0c…

time是python的标准库吗_python3关于date和time的标准库

python3中关于日期和时间的标准库datetime和time&#xff0c;之前都是用的时候随用随查&#xff0c;今天系统的看一下用这两个库可以做些什么。1、time标准库#首先添加一个time对象&#xff0c;看一下该对象的属性和方法>>> import time,datetime>>> a time…

unshift() 方法将一个或多个元素添加到数组的开头,并返回新数组的长度

var arr [1, 2];arr.unshift(0); //result of call is 3, the new array length //arr is [0, 1, 2]arr.unshift(-2, -1); // 5 //arr is [-2, -1, 0, 1, 2]arr.unshift( [-3] ); //arr is [[-3], -2, -1, 0, 1, 2]语法 arr.unshift(element1, ..., elementN)参数列表 elemen…

acctype mysql assoc_DedeCMS V5.3二次开发经验分享

DedeCMS V5.3二次开发经验分享写在前面,DedeCMS系统的模板是非固定的&#xff0c;用户可以在新建栏目时可以自行选择栏目模板&#xff0c;官方仅提供最基本的默认模板&#xff0c;即是内置系统模型的各个模板&#xff0c;由于DedeCMS支持自定义频道模型&#xff0c;用户自定义新…

markdown基础语法整理

标题级别(一共六级) &#xff08;建议在#后加一个空格比较标准&#xff09; 通过在文字下方添加“”和“-”&#xff0c;他们分别表示一级标题和二级标题。在文字开头加上 “#”&#xff0c;通过“#”数量表示几级标题。&#xff08;共1~6级标题&#xff0c;级别越小字体越大&a…

mysql connector配置_mysql connector odbc配置注意事项

官方下载&#xff1a;http://dev.mysql.com/downloads/connector/odbc/有64位和32位版本&#xff0c;要根据自己的office版本是32还是64的安装1、版本匹配问题&#xff1a;[Microsoft][ODBC 驱动程序管理器] 在指定的 DSN 中&#xff0c;驱动程序和应用程序之间的体系结构不匹配…

安卓源码下载

SetupSecurityPortingTuningCompatibilityReference转到源代码SetupGetting StartedDownloading and Building RequirementsEstablishing a Build EnvironmentDownloading the SourcePreparing to BuildCompiling with JackUsing Reference BoardsRunning BuildsBuilding Kerne…

mysql 创建查询 删除_MYSQL数据库查询删除创建企业基本知识

数据查询语言(DQL)从表中获取数据select where (位置) order by(排序) group by haveby查询用户&#xff1a;select user,host,password from mysql.user;select user,host,password from mysql.usser order by(排序) 参数 (如user)asc(升序)select user,host&#xff0…

mysql 端口time_wait_linux上大量tcp端口处于TIME_WAIT的问题

最近发现在连接监控数据库的时候偶尔会连不上&#xff0c;报错&#xff1a;Couldnt connect to host:3306/tcp: IO::Socket::INET: connect: Cannot assign requested address查看了一下发现系统中存在大量处于TIME_WAIT状态的tcp端口$netstat -n | awk /^tcp/ {S[$NF]} END {f…

mysql常用命令英文词汇_MySQL中文全文索引插件 mysqlcft 1.0.0 安装使用文档

MySQL在高并发连接、数据库记录数较多的情况下&#xff0c;SELECT ... WHERE ... LIKE %...%的全文搜索方式不仅效率差&#xff0c;而且以通配符%和_开头作查询时&#xff0c;使用不到索引&#xff0c;需要全表扫描&#xff0c;对数据库的压力也很大。MySQL针对这一问题提供了一…

SDN第二次作业

1、为什么需要SDN&#xff1f;SDN特点&#xff1f; 需要SDN的原因主要是&#xff1a;随着网络规模的不断扩大,封闭的网络设备内置了过多的复杂协议,增加了运营商定制优化网络的难度,科研人员无法在真实环境中规模部署新协议.同时,互联网流量的快速增长(预计到2018年,全球流量将…

mysql数据库sysdate_MySql数据库知识点复习

文章目录1. MySql数据类型1.1 数值类型1.2 字符串类型1.3 日期类型2.表记录的操作2.1 字段约束2.2 drop、delete、truncate之间的区别&#xff1f;3. MySql常见的函数4. 外键和表关系4.1 外键介绍4.2 添加外键4.3 表关系4.4 关联查询、外连接查询1. MySql数据类型1.1 数值类型M…

python函数-基础知识

一、含义函数是程序内的“小程序”二、示例 #!/usr/bin/env python #coding:utf-8 def hello():print(Hello world!)print(Hello people!) hello() 以上内容&#xff0c;定义了一个叫 hello() 的函数&#xff0c;执行该函数。第一行是 def 语句&#xff0c;它定义了一个名为 he…

python task done_python queue task_done()问题

我对python多线程队列有问题。我有一个脚本&#xff0c;其中producer从输入队列获取元素&#xff0c;生成一些元素并将它们放入输出队列&#xff0c;consumer从输出队列获取元素并打印它们&#xff1a;import threadingimport Queueclass Producer(threading.Thread):def __ini…

dobbo 简单框架

转载于:https://www.cnblogs.com/huangjianping/p/7986881.html

python实现多人聊天udp_python—多任务版udp聊天机器人

将多任务(多线程)引入到udp聊天机器人&#xff0c;可以实现同时发送消息和接收消息1 import socket2 import threading345 def udp_send(udp_socket,ip,port):6 while true:7 try:8 # 获取发送的信息9 data input(请输入要发送的信息&#xff1a;)10 udp_socket.sendto(data.e…

kafka 集群的部署安装

这里我们罗列一下我们的环境 10.19.18.88 zk1 10.19.16.84 zk2 10.19.11.44 zk3这里公司需要接入kafka用于zipkin来定位调用链 kafka 的地址是http://kafka.apache.org/ zipkin 的地址是https://github.com/openzipkin/zipkin/tree/master/zipkin-server#environment-variables…

Ubuntu 16.04 设置MySQL远程访问权限

第一步&#xff1a;修改配置文件的端口绑定 打开的目录可能会根据MySQL的版本稍有不同&#xff0c;可以先尝试打开/etc/mysql/my.cnf这个配置文件&#xff0c;若该文件不存在或文件内容为空&#xff0c;则尝试下面的文件路径。 sudo vi /etc/mysql/mysql.conf.d/mysqld.cnf 在下…

spring mysql整合_springboot mybatis mysql 整合

1、pom文件配置mysqlmysql-connector-javaruntimeorg.springframework.bootspring-boot-starter-testtestorg.mybatis.spring.bootmybatis-spring-boot-starter1.2.0org.springframework.bootspring-boot-starter-jdbc2、mybatis 数据库连接配置spring.datasource.driver-class…