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

java版支付宝app支付流程及原理分析
仅作保存 这个支付宝没有经过使用

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

     2.支付的配置文件AlipayConfig           

复制代码
public class AlipayConfig {
// 1.商户appid
public static String APPID = “20170812********”;

 // 2.私钥 pkcs8格式的
 public static String RSA_PRIVATE_KEY ="";
 
 // 3.支付宝公钥
 public static String ALIPAY_PUBLIC_KEY = "";
 
 // 4.服务器异步通知页面路径 需http://或者https://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
 public static String notify_url = "http://www.xxx.com/alipay/notify_url.do";
 
 // 5.页面跳转同步通知页面路径 需http://或者https://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问 商户可以自定义同步跳转地址
 public static String return_url = "http://www.xxx.com/alipay/return_url.do";
 
 // 6.请求网关地址
 public static String URL = "https://openapi.alipay.com/gateway.do";    
 
 // 7.编码
 public static String CHARSET = "UTF-8";
 
 // 8.返回格式
 public static String FORMAT = "json";
 
 // 9.加密类型
 public static String SIGNTYPE = "RSA2";

}
复制代码

     3.第1个创建订单接口

复制代码
/**
*@param userId 充值人
*@param tradeMoney 充值money(RMB)
*@throws AlipayApiException ModelAndView
*/
@RequestMapping(value=“api/alipay/createOrder”,method={RequestMethod.POST,RequestMethod.GET})
@ResponseBody
public Model alipay(
@RequestParam(“userId”)String userId,
@RequestParam(“tradeMoney”)String tradeMoney,Model m) throws AlipayApiException{

 String orderStr = "";         
 try {
     
     /****** 1.封装你的交易订单开始 *****/                                        //自己用
     
     此处封装你的订单数据,订单状态可以设置为等待支付
     
     /****** 1.封装你的交易订单结束 *****/
     
     Map<String,String> orderMap = new LinkedHashMap<String,String>();            //订单实体
     Map<String,String> bizModel = new LinkedHashMap<String,String>();            //公共实体
     
     /****** 2.商品参数封装开始 *****/                                            //手机端用                
     // 商户订单号,商户网站订单系统中唯一订单号,必填
     orderMap.put("out_trade_no",trade.getOrderNumber());
     // 订单名称,必填
     orderMap.put("subject","手机网站支付购买游戏币");
     // 付款金额,必填
     orderMap.put("total_amount",tradeMoney);
     // 商品描述,可空
     orderMap.put("body","您购买游戏币"+tradeMoney +"元");
     // 超时时间 可空
     orderMap.put("timeout_express","30m");
     // 销售产品码 必填
     orderMap.put("product_code","QUICK_WAP_PAY");
     
     /****** 2.商品参数封装结束 *****/    
     
     /******--------------- 3.公共参数封装 开始 ------------------------*****/        //支付宝用
     //1.商户appid
     bizModel.put("app_id",AlipayConfig.APPID);
     //2.请求网关地址
     bizModel.put("method",AlipayConfig.URL);
     //3.请求格式
     bizModel.put("format",AlipayConfig.FORMAT);
     //4.回调地址
     bizModel.put("return_url",AlipayConfig.return_url);
     //5.私钥
     bizModel.put("private_key",AlipayConfig.RSA_PRIVATE_KEY);
     //6.商家id
     bizModel.put("seller_id","2088102170411333");
     //7.加密格式
     bizModel.put("sign_type",AlipayConfig.SIGNTYPE+"");
     
     /******--------------- 3.公共参数封装 结束 ------------------------*****/
     
     //实例化客户端  
     AlipayClient client = new DefaultAlipayClient(AlipayConfig.URL, AlipayConfig.APPID, AlipayConfig.RSA_PRIVATE_KEY, AlipayConfig.FORMAT, AlipayConfig.CHARSET, AlipayConfig.ALIPAY_PUBLIC_KEY,AlipayConfig.SIGNTYPE);
     
     //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay 
     AlipayTradeAppPayRequest ali_request = new AlipayTradeAppPayRequest();  
     
     //SDK已经封装掉了公共参数,这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。  
     AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();  
     model.setPassbackParams(URLEncoder.encode((String)orderMap.get("body").toString()));;  //描述信息  添加附加数据  
     model.setBody(orderMap.get("body"));                        //商品信息
     model.setSubject(orderMap.get("subject"));                  //商品名称
     model.setOutTradeNo(orderMap.get("out_trade_no"));          //商户订单号(自动生成)
     model.setTimeoutExpress(orderMap.get("timeout_express"));     //交易超时时间
     model.setTotalAmount(orderMap.get("total_amount"));         //支付金额
     model.setProductCode(orderMap.get("product_code"));         //销售产品码
     model.setSellerId("20881021********");                        //商家id
     ali_request.setBizModel(model);  
     ali_request.setNotifyUrl(AlipayConfig.notify_url);          //回调地址  
     
     AlipayTradeAppPayResponse response = client.sdkExecute(ali_request);  
     orderStr = response.getBody();  
     System.err.println(orderStr);                                //就是orderString 可以直接给客户端请求,无需再做处理。  
     
     m.addAttribute("result",orderStr);
     m.addAttribute("status",0);
     m.addAttribute("msg","订单生成成功");
     
 } catch (Exception e) {
      m.addAttribute("status",1);
      m.addAttribute("msg","订单生成失败");
 }
 
 return m;

}

     4.第2个异步回调接口

/**

  • 支付宝支付成功后.回调该接口

  • @param request

  • @return

  • @throws IOException
    */
    @RequestMapping(value=“api/alipay/notify_url”,method={RequestMethod.POST,RequestMethod.GET})
    @ResponseBody
    public String notify(HttpServletRequest request,HttpServletResponse response) throws IOException {
    Map<String, String> params = new HashMap<String, String>();
    Map<String, String[]> requestParams = request.getParameterMap();
    Trade trade =null;
    //1.从支付宝回调的request域中取值
    Map<String, String[]> requestParams = request.getParameterMap();

    for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext()😉 {
    String name = iter.next();
    String[] values = requestParams.get(name);
    String valueStr = “”;
    for (int i = 0; i < values.length; i++) {
    valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + “,”;
    }
    // 乱码解决,这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
    // valueStr = new String(valueStr.getBytes(“ISO-8859-1”), “gbk”);
    params.put(name, valueStr);
    }
    //2.封装必须参数
    String out_trade_no = request.getParameter(“out_trade_no”); // 商户订单号
    String orderType = request.getParameter(“body”); // 订单内容
    String tradeStatus = request.getParameter(“trade_status”); //交易状态

    //3.签名验证(对支付宝返回的数据验证,确定是支付宝返回的)
    boolean signVerified = false;
    try {
    //3.1调用SDK验证签名
    signVerified = AlipaySignature.rsaCheckV1(params, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.CHARSET, AlipayConfig.SIGNTYPE);35 } catch (AlipayApiException e) {
    e.printStackTrace();
    }
    //4.对验签进行处理
    if (signVerified) { //验签通过
    if(tradeStatus.equals(“TRADE_SUCCESS”)) { //只处理支付成功的订单: 修改交易表状态,支付成功
    Trade trade = tradeService.selectByOrderNumber(out_trade_no);
    trade.setTradeStatus((byte)3); //支付完成
    int returnResult = tradeService.updateByPrimaryKeySelective(trade); //更新交易表中状态
    if(returnResult>0){
    return “success”;
    }else{
    return “fail”;
    }
    }else{
    return “fail”;
    }
    } else { //验签不通过
    System.err.println(“验签失败”);
    return “fail”;
    }
    }
    代码

    5.第3个同步通知接口

代码
/**
* 支付宝支付成功后.通知页面
*@author Zhao
*@date 2017年11月2日
*@param request
*@return
*@throws UnsupportedEncodingException
*/
@RequestMapping(value=“api/alipay/return_url”,method={RequestMethod.POST,RequestMethod.GET})
@ResponseBody
public Model returnUrl(@RequestParam(“id”) String id,HttpServletRequest request,Model model) throws UnsupportedEncodingException {
System.err.println("。。。。。。 同步通知 。。。。。。");
System.err.println("。。。。。。 同步通知 。。。。。。");
System.err.println("。。。。。。 同步通知 。。。。。。");
Map returnMap = new HashMap();
try {

         Trade trade = tradeService.selectByOrderNumber(id);
          // 返回值Map  
         if(trade !=null && trade.getTradeStatus() == 2){
             User user = userService.selectByPrimaryKey(trade.gettUserId());
             returnMap.put("tradeType", trade.getTradeType());             //支付方式
             returnMap.put("phoneNum", user.getPhoneNumber());             //支付帐号
             returnMap.put("tradeMoney", trade.getTradeMoney()+"");        //订单金额
             
         }else{
              model.addAttribute("msg", "查询失败");
              model.addAttribute("status", 0);
         }
          model.addAttribute("returnMap", returnMap);
          System.err.println(returnMap);
          model.addAttribute("msg", "查询成功");
          model.addAttribute("status", 0);
     } catch (Exception e) {
         model.addAttribute("msg", "查询失败");
         model.addAttribute("status", 1);
     }
      
      return model;  
 }

复制代码
二、测试

支付宝在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

还有微信支付后端java https://www.cnblogs.com/MrRightZhao/p/7930916.html

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值