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

Posted 硝烟漫过十八岁

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了支付宝app支付java后台流程及原理分析相关的知识,希望对你有一定的参考价值。

 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>();  
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);  
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                     //response.getWriter().write("SUCCESS");
46                 return "success";
47             }else{
48                 //response.getWriter().write("fail");
49                 return "fail";
50             }
51         }else{
52             return "fail";
53         }
54     } else {  //验签不通过   
55         //response.getWriter().write("fail");
56         System.err.println("验签失败");
57         return "fail";
58     }
59 }  

    
         5.第3个同步通知接口

 1 /**
 2 * 支付宝支付成功后.通知页面
 3 *@param request
 4 *@return
 5 *@throws UnsupportedEncodingException
 6  */
 7 @RequestMapping(value="api/alipay/return_url",method={RequestMethod.POST,RequestMethod.GET})
 8 @ResponseBody
 9 public Model returnUrl(HttpServletRequest request,Model model) throws UnsupportedEncodingException {  
10     System.err.println("同步通知。。。");
11     try {
12          //1.从支付宝同步的request域中取值
13          Map properties = request.getParameterMap();  
14          //2.封装成Map  
15          Map<String, String> returnMap = new HashMap<String, String>();  
16          Iterator entries = properties.entrySet().iterator();  
17          Map.Entry entry;  
18          String name = "";  
19          String value = "";  
20          while (entries.hasNext()) {  
21              entry = (Map.Entry) entries.next();  
22              name = (String) entry.getKey();  
23              Object valueObj = entry.getValue();  
24              //对返回的值进行判断
25              if(null == valueObj){  
26                  value = "";  
27              }else if(valueObj instanceof String[]){  
28                  String[] values = (String[])valueObj;  
29                  for(int i=0;i<values.length;i++){  
30                      value = values[i] + ",";  
31                  }  
32                  value = value.substring(0, value.length()-1);  
33              }else{  
34                  value = valueObj.toString();  
35              }  
36              returnMap.put(name, value);  
37          }
38          //3.返回到手机端
39          model.addAttribute("returnMap", returnMap);
40          model.addAttribute("msg", "查询成功");
41          model.addAttribute("status", 0);
42     } catch (Exception e) {
43         model.addAttribute("msg", "查询失败");
44         model.addAttribute("status", 1);
45     }
46     
47      return model;  
48 }

    
    二、流程分析:
         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.本人由于能力水平有限.有不到之处请大家多多指教!!!
























以上是关于支付宝app支付java后台流程及原理分析的主要内容,如果未能解决你的问题,请参考以下文章

android 集成支付宝app支付(原生态)-包括android前端与java后台

android 集成支付宝app支付(原生态)-包括android前端与java后台

android 集成支付宝app支付(原生态)-包括android前端与java后台

android 集成支付宝app支付(原生态)-包括android前端与java后台

各支付SDK流程

微信支付宝各种支付退款