java第三方支付接口(云通付)

个人学习总结,为java后台接口,不足之处请指教。
基于云通付实现的支付,所以先去云通付官网注册账号。得到相应的合作身份者PID、MD5密钥、商户号。(后面会用到)
下载相应jar包。将下载文件解压,把解压文件中的工具包拷贝到自己的项目中。这里写图片描述
新建一个PayController类
先建立一个方法,是从用户点击“确认订单”的按钮后跳转到方法

@RequestMapping("page/{orderNo}")
    @IsLogin
    public String list(@PathVariable String orderNo, HttpServletRequest request, Model model)
            throws PayException {
        Integer loginUserId = LoginIdentityUtil.getFromLoginId(request);
        // 根据订单号去获取订单信息:
        PayRequestVo payRequestVo = orderService.buildPayRequestVo(orderNo, loginUserId);
        model.addAttribute("payRequestVo", payRequestVo);
        model.addAttribute("gateway", PayConstant.GATEWAY_NEW);
        return "pay/pay";
    }

该方法主要是生成签名,以及将支付请求的数据返回到页面,进行支付请求
页面主要Form表单如下,自动进行提交到“云通付”的支付网关

<!DOCTYPE html >
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>支付跳转中...</title>
</head>
<body style="background:#F3F3F4">
<br />
<br />
<div style="display: none">
    <form id='paysubmit' name='paysubmit' action='${gateway}' accept-charset='utf-8' method='post'>

        <input type='text' name='sign' value='${payRequestVo.sign}'/>

        <input type='text' name='body' value='${payRequestVo.body}'/>

        <input type='text' name='user_seller' value='${payRequestVo.userSeller}'/>

        <input type='text' name='total_fee' value='${payRequestVo.totalFee}'/>

        <input type='text' name='subject' value='${payRequestVo.subject}'/>

        <input type='text' name='notify_url' value='${payRequestVo.notifyUrl}'/>

        <input type='text' name='out_order_no' value='${payRequestVo.outOrderNo}'/>

        <input type='text' name='partner' value='${payRequestVo.partner}'/>

        <input type='text' name='return_url' value='${payRequestVo.returnUrl}'/>

        <input type='submit' value='支付进行中...' />
    </form>
</div>
<script type="text/javascript">
    document.forms['paysubmit'].submit();
</script>
</body>
</html>

跳转到付款页面这里写图片描述
付款回调方法,同步和异步

@RequestMapping("notify_url")
    @IsLogin
    public String notifyUrl(HttpServletRequest request, Model model,
                            PayCallbackDto payCallbackDto) {
        String result = commonHanlerCallback(request, model, payCallbackDto);
        return result;
    }

    @RequestMapping("return_url")
    @IsLogin
    public String returnUrl( HttpServletRequest request, Model model,
                             PayCallbackDto payCallbackDto) {
        String result = commonHanlerCallback(request, model, payCallbackDto);
        return result;
    }

    private String commonHanlerCallback(HttpServletRequest request, Model model,
                                        PayCallbackDto payCallbackDto) {
        Integer loginUserId = LoginIdentityUtil.getFromLoginId(request);
        Integer resultCode = Constant.SUCCESS_CODE;
        String resultMessage = "支付成功";
        try {
            Map<String, Object> result = orderService.handlerPayCallback(loginUserId, payCallbackDto);
            model.addAllAttributes(result);
        } catch (Exception e) {
            resultCode = Constant.ERROR_CODE;
            resultMessage = e.getMessage();
        }
        model.addAttribute("resultCode", resultCode);
        model.addAttribute("resultMessage", resultMessage);
        return "pay/success";
    }

Controller层接受云通付返回的数据,用PayCallbackDto类接收

public class PayCallbackDto {
    private BigDecimal total_fee; // 交易金额
    private String out_order_no; // 商户订单号
    private String sign; // 服务端校验码
    private String trade_no; // 云通付交易订单号
    private String trade_status; // 交易结果(TRADE_SUCCESS说明支付成功)
}

Service要走如下流程
1) 回调参数验证
2) 签名认证:将out_order_no、total_fee、trade_status、云通付PID、云通付KEY的值连接起来,进行md5加密,而后与sign进行对比
3) 支付状态验证trade_status= TRADE_SUCCESS
4) 订单验证
5) 订单金额比对
6) 更新订单状态

/**
     * 支付回调处理
     * @param loginUserId
     * @param payCallbackDto
     */
    public Map<String, Object> handlerPayCallback(Integer loginUserId, PayCallbackDto payCallbackDto) {
//      1)  回调参数验证
//      2)  签名认证:将out_order_no、total_fee、trade_status、云通付KEY、云通付PID 的值连接起来,进行md5加密,而后与sign进行对比
//      3)  支付状态验证trade_status= TRADE_SUCCESS
//      4)  订单验证
//      5)  订单金额比对
//      6)  更新订单状态
        AssertUtil.isTrue(loginUserId == null || loginUserId < 1, "请登录");
        String total_fee = payCallbackDto.getTotal_fee(); //    交易金额
        AssertUtil.isTrue(total_fee == null, PayConstant.CALLBACK_FAILURE);
        String out_order_no = payCallbackDto.getOut_order_no(); // 商户订单号
        AssertUtil.isTrue(StringUtils.isBlank(out_order_no), PayConstant.CALLBACK_FAILURE);
        String sign = payCallbackDto.getSign(); // 服务端校验码
        AssertUtil.isTrue(StringUtils.isBlank(sign), PayConstant.CALLBACK_FAILURE);
        String trade_no = payCallbackDto.getTrade_no(); // 云通付交易订单号
        AssertUtil.isTrue(StringUtils.isBlank(trade_no), PayConstant.CALLBACK_FAILURE);
        String trade_status = payCallbackDto.getTrade_status(); // 交易结果(TRADE_SUCCESS说明支付成功)
        AssertUtil.isTrue(StringUtils.isBlank(trade_status), PayConstant.CALLBACK_FAILURE);

        // 签名认证
        Md5Util md5Util = new Md5Util();

//      String key = PayConstant.KEY;
//      String pid = PayConstant.PARTNER;
//      String signMd5 = md5Util.encode(out_order_no + total_fee + trade_status + pid + key, null);

        String preStr = out_order_no + total_fee + trade_status + PayConstant.PARTNER + PayConstant.KEY;

        String signNew = md5Util.encode(preStr, null);
        AssertUtil.isTrue(!signNew.equals(sign), "签名验证失败,请联系客服");




        // 回调状态验证
        AssertUtil.isTrue(!trade_status.equals(PayConstant.TRADE_SUCCESS), PayConstant.CALLBACK_FAILURE);

        // 订单验证
        Order order = orderDao.findOrderByOrderNo(out_order_no, loginUserId);
        AssertUtil.isTrue(order == null, "订单异常,请联系客服");
        AssertUtil.isTrue(order.getStatus() != OrderStatus.pendingPayment.getStatus(), "订单状态异常,请联系客服");

        // 支付金额验证
        BigDecimal amount = order.getAmount();
        // 将金额精度精确到2位 四舍五入在转化为字符串
        String priceStr = MathUtil.setScale(amount).toString();
        AssertUtil.isTrue(!total_fee.equals(priceStr), "订单金额不准备去,请联系客服");

//      更新订单状态
        orderDao.updateStatus(out_order_no, OrderStatus.pendingShipment.getStatus());
        Map<String, Object> result = new HashMap<>();
        result.put("orderNo", out_order_no);
        result.put("money", priceStr);

        return  result;
    }

注意
集成到项目是,发起支付请求时需要配置一个本地的hosts, 将云通付上绑定的域名配置到本地,因为第三方网关请求的都是访问域名, 以win7为例
这里写图片描述
a) 找到hosts的文件目录在C:\Windows\System32\drivers\etc这里写图片描述
b) 以超级管理员的身份用记事本打开hosts
这里写图片描述
c) 配置一个host, 输入127.0.0.1 www.XXXX.com
d) 这样你访问项目的时候就可以用www.XXXX.com:8080访问了
验证签名时,要注意金额的小数点位数, 不然会提示签名失败
记得如果是拷贝到本地项目的话,要根据自己的项目情况修改PayConstant里面的回调url的路径

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值