java h5端 支付宝支付

h5端接入支付宝支付接口–spring cloud

常量配置AlipayConfig

    // 请求网关地址
    public static final String URL = "https://openapi.alipay.com/gateway.do";

    // 编码格式
    public static final String CHARSET = "UTF-8";
    // 返回格式
    public static final String FORMAT = "json";
    // 加密类型RSA2
    public static final String SIGNTYPE = "RSA2";
    //h5 appid
    public static final String h5APPID="*****";
    //h5 支付公钥
    public  static  final  String h5_ALIPAY_PUBLIC_KEY="";
    //h5 应用私钥
    public static final String h5_PRIVATE_KEY="";

回调地址和通知页面地址在application.yml 配置

#h5端 阿里云支付回调(官方)这里配置回调用于处理支付成功后的逻辑
h5_alis_gf_notify_url: http://7dtuqg.natappfree.cc/uncheck/h5AliNotifyUrl
#h5端 阿里云支付成功跳转(官方)这里配置支付完后跳转的页面
h5_alis_gf_query_url: https://7dtuqg.natappfree.cc/paySuccess

支付宝支付业务层接口

public interface AliPayAppService {
 
    //查询订单状态
    Map<String,Object> getStatus(OrderVo orderVo);
    //统一下单拉起支付
    Map<String,Object>geth5AliPayOrderStr(OrderVo orderVo);
    //支付完回调
    String h5AliNotifyUrl(Map<String, String> conversionParams);
}

支付实现 AliPayAppServiceImpl

   //支付回调地址
   @Value(value="${h5_alis_gf_notify_url}")
    private String h5_alis_gf_notify_url;
    //支付成功地址
    @Value(value="${h5_alis_gf_query_url}")
    private String h5_alis_gf_query_url;
/**
     *
     * @param orderVo 订单实体类
     * @return
     */
    @Override
    public Map<String, Object> geth5AliPayOrderStr(OrderVo orderVo) {
        /*********************** 先校验订单有效性*********************************/
      

        Map<String, Object> map = new HashMap<>();
        // 最终返回加签之后的,app需要传给支付宝app的订单信息字符串
        String orderString = "0";
        logger.info("h5支付宝下单,商户订单号为:" + orderVo.geteName());

         //这个类对应的表存储支付完回调信息的
        Alipaymentorder alipaymentOrder = new Alipaymentorder();




        if (orderVo.geteId() != null) {
            alipaymentOrder.setOrderId(orderVo.geteId().longValue()); // 商户订单主键
        }
        alipaymentOrder.setOutTradeNo(orderVo.geteName());// 商户订单号
        alipaymentOrder.setTradeStatus(0);// 交易状态
        //这个金额正式的需要根据订单号去查
       alipaymentOrder.setTotalAmount(new BigDecimal(0.01));// 订单金额
     
        alipaymentOrder.setRefundFee(0.00); // 总退款金额

        try {
            // 实例化客户端(参数:网关地址、商户appid、商户私钥、格式、编码、支付宝公钥、加密类型),为了取得预付订单信息
            AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.URL, AlipayConfig.h5APPID,
                    AlipayConfig.h5_PRIVATE_KEY, AlipayConfig.FORMAT, AlipayConfig.CHARSET,
                    AlipayConfig.h5_ALIPAY_PUBLIC_KEY, AlipayConfig.SIGNTYPE);

            // 实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay
            AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest();

            // SDK已经封装掉了公共参数,这里只需要传入业务参数。以下方法为sdk的model入参方式
            AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();

            model.setSubject("此订单"); // 商品名称
            model.setOutTradeNo(orderVo.geteName()); // 商户订单号
            // model.setTimeoutExpress("30m"); //交易超时时间

           model.setTotalAmount("0.01");

            /****************************/

            model.setProductCode("QUICK_WAP_WAY"); // 销售产品码(固定值)
            request.setBizModel(model);


            request.setNotifyUrl(h5_alis_gf_notify_url); // 异步回调地址(后台)
            request.setReturnUrl(h5_alis_gf_query_url);//设置支付成功跳转页面的地址
            //ali_request.setReturnUrl(AlipayAppConfig.return_url); // 同步回调地址(APP)
            //Requestcontent 是一个请求报文表与支付业务无关
            Requestcontent requestcontent=new Requestcontent();
            requestcontent.setContent(request.toString());//报文内容
            requestcontent.setContentType(Constants.CALLBACK_ALI_APP);//支付方式
            requestcontent.setContenTime(new Date());//时间
            requestcontent.setEntrydetailId(orderVo.geteName());//订单号
            requestcontentMapper.insertSelective(requestcontent);//添加报文
            // 这里和普通的接口调用不同,使用的是sdkExecute
            AlipayTradeWapPayResponse alipayTradeAppPayResponse = alipayClient.sdkExecute(request); // 返回支付宝订单信息(预处理)

            if(alipayTradeAppPayResponse.isSuccess()){
                // 如果商家订单表没有该订单数据则添加
                if (alipaymentorderService.getAlipaymentorder(orderVo.geteName()).size() == 0) {
                    alipaymentorderService.addAlipaymentorder(alipaymentOrder); //创建新的商户支付宝订单
                }
                DateAndStrUtil strUtil = DateAndStrUtil.getDateAndStr();
                //DateAndStrUtil 是一个时间工具类 requestTimestamp格式为yyyy-MM-dd HH:mm:ss
                String requestTimestamp = strUtil.dateToStr(new Date());
                orderString = alipayTradeAppPayResponse.getBody();
                map.put("orderString", "https://openapi.alipay.com/gateway.do?"+orderString+"×tamp="+requestTimestamp);
                //前端直接访问orderString", "https://openapi.alipay.com/gateway.do?"+orderString+"×tamp="+requestTimestamp 即可拉起支付
                return Utils.packageResponseData(MapConstants.mapSuccessCode, "拉起成功", map);
            }else{
                return Utils.packageResponseData(MapConstants.mapErrorCode, "拉起失败", map);
            }



        } catch (Exception e) {
            e.printStackTrace();
            logger.info("与支付宝交互出错,未能生成订单,请检查代码!");
            return Utils.packageResponseData(MapConstants.mapErrorCode, "拉起失败", map);

        }



    }
    
     /**
     *功能描述: h5 支付宝查询订单状态
     * @author 
     * @date 2020/7/2
     * @param orderVo
     * @return java.util.Map
     */

    @Override
    public Map<String, Object> getStatus(OrderVo orderVo) {

        Map<String,Object> map=new HashMap<>();

        if(Strings.isNullOrEmpty(orderVo.geteName())) {
            return Utils.packageResponseData(MapConstants.mapNullCode, "订单号不能为空", map);
        }
        AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.URL, AlipayConfig.h5APPID,
                AlipayConfig.h5_PRIVATE_KEY, AlipayConfig.FORMAT, AlipayConfig.CHARSET,
                AlipayConfig.h5_ALIPAY_PUBLIC_KEY, AlipayConfig.SIGNTYPE);

        // 实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay
        AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
        request.setBizContent("{" + "\"out_trade_no\" : \"" + orderVo.geteName() + "\"}");
        try {
            AlipayTradeQueryResponse response = alipayClient.execute(request);
            if (response.isSuccess()) {
             switch (response.getTradeStatus()) // 判断交易结果
				{
					case "TRADE_FINISHED": // 交易结束并不可退款
						 map.put("status",3);
						break;
					case "TRADE_SUCCESS": // 交易支付成功
						 map.put("status",2);
						break;
					case "TRADE_CLOSED": // 未付款交易超时关闭或支付完成后全额退款
						 map.put("status",1);
						break;
					case "WAIT_BUYER_PAY": // 交易创建并等待买家付款
						 map.put("status",0);
						break;
					default:
						break;
				}
                return Utils.packageResponseData(MapConstants.mapSuccessCode, "查询成功", map);

            } else {
                logger.info("调用支付宝查询接口失败!");
                return Utils.packageResponseData(MapConstants.mapErrorCode, "调用支付宝查询接口失败!", map);

            }

        } catch (Exception e) {
            e.printStackTrace();
            return Utils.packageResponseData(MapConstants.mapErrorCode, "查询失败", map);
        }

    }
//h5官方支付宝异步请求逻辑处理
 @Override
    public String h5AliNotifyUrl(Map<String, String> conversionParams) {
        logger.info("h5官方支付宝异步请求逻辑处理");
     
        // 签名验证(对支付宝返回的数据验证,确定是支付宝返回的)
        boolean signVerified = false;

        try {
            // 调用SDK验证签名
            signVerified = AlipaySignature.rsaCheckV1(conversionParams, AlipayConfig.h5_ALIPAY_PUBLIC_KEY,
                    AlipayConfig.CHARSET, AlipayConfig.SIGNTYPE);

        } catch (AlipayApiException e) {
            logger.info("验签失败 !");
            e.printStackTrace();
        }

        // 对验签进行处理
        if (signVerified) {
            System.out.println("h5支付宝回调验签通过");
            // 验签通过
            // 获取需要保存的数据
            String appId = conversionParams.get("app_id");
            
            Alipaymentorder alipaymentOrder=getAlipayMent(conversionParams);

            if (AlipayConfig.h5APPID.equals(appId)) {
                EntrydetailExample entrydetailExample=new EntrydetailExample();
                entrydetailExample.createCriteria().andENameEqualTo(alipaymentOrder.getOutTradeNo());
                List<Entrydetail> list=entrydetailMapper.selectByExample(entrydetailExample);
                alipaymentOrder.setUserId(list.get(0).geteUid());
                //更新回调表中的内容
                int returnResult = alipaymentorderService.updateAlipaymentorder(alipaymentOrder); // 更新交易表中状态
                    // 修改交易表状态,支付成功
                    if (returnResult > 0) {
                        logger.info("======h5官方支付宝更新商户订单表成功======");
                  
                       return "SUCCESS";//如果不反回将会持续回调24小时

                     
                    } else {
                        logger.info("更新表状态失败");
                     
                        return "FAILED";
                    }


            } else {
                logger.info("支付宝官方建议校验的值(out_trade_no、total_amount、sellerId、app_id),不一致!返回fail");
            
                return "FAILED";
            }

        } else { // 验签不通过
            logger.info("验签不通过 !");
         
            return "FAILED";

        }
    }
    //回调用到的getAlipayMent方法
    public Alipaymentorder getAlipayMent(Map<String, String> conversionParams){
      DateAndStrUtil dateAndStrUtil = new DateAndStrUtil();
      String appId = conversionParams.get("app_id");// 支付宝分配给开发者的应用Id
      String notifyTime = conversionParams.get("notify_time");// 通知时间:yyyy-MM-dd HH:mm:ss
      String gmtCreate = conversionParams.get("gmt_create");// 交易创建时间:yyyy-MM-dd HH:mm:ss
      String gmtPayment = conversionParams.get("gmt_payment");// 交易付款时间

      String tradeNo = conversionParams.get("trade_no");// 支付宝的交易号
      String outTradeNo = conversionParams.get("out_trade_no");// 获取商户之前传给支付宝的订单号(商户系统的唯一订单号)

      String totalAmount = conversionParams.get("total_amount");// 订单金额:本次交易支付的订单金额,单位为人民币(元)
      String receiptAmount = conversionParams.get("receipt_amount");// 实收金额:商家在交易中实际收到的款项,单位为元

      String buyerPayAmount = conversionParams.get("buyer_pay_amount");// 付款金额:用户在交易中支付的金额
      String tradeStatus = conversionParams.get("trade_status");// 获取交易状态

      // 支付宝官方建议校验的值(out_trade_no、total_amount、sellerId、app_id)
      List<Alipaymentorder> alipaymentOrderList = alipaymentorderService.getAlipaymentorder(outTradeNo);
      Alipaymentorder alipaymentOrder = alipaymentOrderList.get(0);
      alipaymentOrder.setNotifyTime(dateAndStrUtil.strToDate(notifyTime));  // 通知时间
      alipaymentOrder.setGmtCreate(dateAndStrUtil.strToDate(gmtCreate));      // 交易创建时间
      alipaymentOrder.setGmtPayment(dateAndStrUtil.strToDate(gmtPayment));  // 交易付款时间
      //alipaymentOrder.setGmt_refund(DateUtils.parse(gmtRefund));  // 交易退款时间
      //alipaymentOrder.setGmt_close(DateUtils.parse(gmtClose));	  // 交易结束时间
      alipaymentOrder.setTradeNo(tradeNo);    // 支付宝交易号
      //alipaymentOrder.setOut_biz_no(outBizNo);  // 商户业务号(商户业务ID,主要是退款通知中返回退款申请的流水号)

      alipaymentOrder.setTotalAmount(new BigDecimal(totalAmount));  //订单金额:本次交易支付的订单金额,单位为人民币(元)
      alipaymentOrder.setReceiptAmount(new BigDecimal(receiptAmount)); // 实收金额:商家在交易中实际收到的款项,单位为元
      //alipaymentOrder.setInvoiceAmount(Double.parseDouble(invoiceAmount)); // 开票金额:用户在交易中支付的可开发票的金额
      alipaymentOrder.setBuyerPayAmount(new BigDecimal(buyerPayAmount)); // 付款金额:用户在交易中支付的金额
      Utils.getStatus(alipaymentOrder,tradeStatus);
      return alipaymentOrder;
  }
  

Utils 工具类

public class Utils {


public static  void getStatus(Alipaymentorder alipaymentorder,String status){



       switch (status) // 判断交易结果
       {
           case "TRADE_FINISHED": // 交易结束并不可退款
               alipaymentorder.setTradeStatus(3);
               break;
           case "TRADE_SUCCESS": // 交易支付成功
               alipaymentorder.setTradeStatus(2);
               break;
           case "TRADE_CLOSED": // 未付款交易超时关闭或支付完成后全额退款
               alipaymentorder.setTradeStatus(1);
               break;
           case "WAIT_BUYER_PAY": // 交易创建并等待买家付款
               alipaymentorder.setTradeStatus(0);
               break;
           default:
               break;
       }
   }


   /**
    *
    * Map转String
    * @param map
    * @return
    */
   public static String getMapToString(Map<String,String> map){
       Set<String> keySet = map.keySet();
       //将set集合转换为数组
       String[] keyArray = keySet.toArray(new String[keySet.size()]);
       //给数组排序(升序)
       Arrays.sort(keyArray);
       //因为String拼接效率会很低的,所以转用StringBuilder
       StringBuilder sb = new StringBuilder();
       for (int i = 0; i < keyArray.length; i++) {
           // 参数值为空,则不参与签名 这个方法trim()是去空格
           if ((String.valueOf(map.get(keyArray[i]))).trim().length() > 0) {
               sb.append(keyArray[i]).append(":").append(String.valueOf(map.get(keyArray[i])).trim());
           }
           if(i != keyArray.length-1){
               sb.append(",");
           }
       }
       return sb.toString();
   }





}

支付控制层 AliPayAppController

  /**
    *功能描述:H5支付宝拉起支付
    * @author 666
    * @date 2020/7/6
    * @return java.util.Map
    */
   @RequestMapping(value="/geth5AliPayOrderStr",method= RequestMethod.POST)
   public Map<String,Object> geth5AliPayOrderStr(@RequestBody OrderVo orderVo){

       return  aliPayAppService.geth5AliPayOrderStr(orderVo);
   }
    /**
    *功能描述:查询订单状态
    * @author 666
    * @date 2020/7/2
    * @param orderVo
    * @return java.util.Map
    */

   @RequestMapping(value = "/getStatus", method = RequestMethod.POST)
   public Map<String, Object> getStatus(@RequestBody OrderVo orderVo) {

       return aliPayAppService.getStatus(orderVo);

   }
   /**
    * h5支付宝官方回调
    * @param request
    * @param response
    * @return
    */
   @RequestMapping(value="/h5AliNotifyUrl",method= RequestMethod.POST)
   public String h5AliNotifyUrl(HttpServletRequest request, HttpServletResponse response){

       logger.info("h5官方支付宝异步返回支付结果开始");

       String map = aliPayAppService.h5AliNotifyUrl(Utils.map(request,response));

       return map;
   }

最后附上alipaymentorder表:

CREATE TABLE `alipaymentorder` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
`order_id` bigint(20) DEFAULT NULL COMMENT '商家订单主键',
`out_trade_no` varchar(255) DEFAULT NULL COMMENT '商户订单号',
`notify_time` datetime DEFAULT NULL COMMENT '通知时间',
`gmt_create` datetime DEFAULT NULL COMMENT '交易创建时间',
`gmt_payment` datetime DEFAULT NULL COMMENT '交易付款时间',
`gmt_refund` datetime DEFAULT NULL COMMENT '交易退款时间',
`gmt_close` datetime DEFAULT NULL COMMENT '交易结束时间',
`trade_no` varchar(255) DEFAULT NULL COMMENT '支付宝的交易号',
`out_biz_no` varchar(255) DEFAULT NULL COMMENT '商户业务号(商户业务ID,主要是退款通知中返回退款申请的流水号)',
`seller_email` varchar(255) DEFAULT NULL COMMENT '卖家账号',
`seller_id` varchar(255) DEFAULT NULL COMMENT '卖家用户号',
`buyer_logon_id` varchar(255) DEFAULT NULL COMMENT '买家账号',
`total_amount` decimal(10,2) DEFAULT NULL COMMENT '订单金额',
`receipt_amount` decimal(10,2) DEFAULT NULL COMMENT '实收金额',
`buyer_pay_amount` decimal(10,2) DEFAULT NULL COMMENT '付款金额:用户在交易中支付的金额',
`trade_status` int(255) DEFAULT NULL COMMENT '交易状态',
`refund_fee` double(10,2) DEFAULT NULL COMMENT '总退款金额',
`buyer_id` varchar(255) DEFAULT NULL COMMENT '买家唯一用户号',
`fund_change` varchar(255) DEFAULT NULL COMMENT '本次退款是否发生了资金变化',
`store_name` varchar(255) DEFAULT NULL COMMENT '交易在支付时候的门店名称',
`trade_type` int(255) DEFAULT NULL COMMENT '1.代表微信 2.代表支付宝 3.代表苹果内购',
`user_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=206 DEFAULT CHARSET=utf8 COMMENT='商户支付宝订单表';

第一次发微博欢迎大家一起交流一起学习


你可能感兴趣的:(支付)