在线支付

1.支付方案:

支付方案1:网站直接与银行对接

在线支付_第1张图片

 

此种模式下,网站需要针对不同的银行开发不同的支付程序,编程工作量很大,并且银行接入规范一旦发生变动,网站程序也要跟着改,维护工作量极大。

 

支付方案2:通过第三方支付公司与银行对接

在线支付_第2张图片

 

 

这种方式接方式的优缺点:

优点:系统只需要与第三方支付公司打交道,第三方支付公司根据用户选择的支付银行,并根据支付银行的接入规范,引导用户与银行对接,从而实现支付。此种方案最大的优点,系统只需要与第三方支付公司交互,开发工作量极低。

缺点:由于通过第三方支付公司引导用户支付的,所以用户支付的钱会支付给第三方支付公司,网站再与第三方支付公司定期进行资金结算。所以如果金额较大,资金安全是个大问题。并且这种支付模型也会收取一定的手续费,因此此种支付方案只适合月金额在百万以下的公司。

2.常见第三方支付公司

在线支付_第3张图片

易宝支付: http://www.yeepay.com/

接入免费,只从交易金额中扣除1%的手续费。像盛大、 e龙网、巴巴运动网使用了易宝支付。

首信易支付:http://www.beijing.com.cn/

每年需要交纳一定的接口使用费,并且从交易金额中扣除1%的手续费。像当当网、红孩子、京东商城使用了首信易支付。

在线支付_第4张图片

 

 

3.支付时序图:

在线支付_第5张图片

4.接入步骤:

 

1. 网站必须在第三方进行注册,以便第三方确定接入的商户.

    商户编号 -- 注册账号
        String p1_MerId = "10001126856";

2. 第三方提供公共的访问接口,供网站将重定向请求发送到第三方

image

 

在线支付_第6张图片

网站将用户请求重定向到第三方时需要对请求参数进行加密,加密秘钥与第三方接收请求时解密的秘钥相同,以保证数据的正确性.

//#####第三方提供的加密key值
        String keyValue = "69cl522AV6q613Ii4W6u8K6XuW8vM1N6bFgyv769220IuYe9u37N4y7rI4Pl";

 

3.商户(网站)接收支付成功数据的地址  --最后从第三方回到网站的地址,需要是公网的IP
        String  p8_Url = "http://公网IP:8080/pay/CallbackServlet";

5.Java代码实现

 

支付页面:pay.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" 
    pageEncoding="UTF-8"%> 
DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 
<html> 
<head> 
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 
<title>Insert title heretitle> 
head> 
<body> 
    <%@ include file="/WEB-INF/pages/user/header.jsp" %> 
    <form action="${pageContext.request.contextPath}/user/PayServlet" method="post"> 
        <table> 
            <tr> 
                <td>商品编号:td> 
                <td colspan="3"><input type="text" name="orderId" />td> 
            tr> 
            <tr> 
                <td>价格:td> 
                <td colspan="3"><input type="text" name="amount" />td> 
            tr> 
            <tr> 
                <td colspan="4">请选择在线支付银行:td> 
            tr> 
            <tr> 
                <td><input type="radio" name="frpId" value="ICBC-NET"/>中国工商银行 td> 
                <td><input type="radio" name="frpId" value="ABC-NET"/>中国农业银行td> 
                <td><input type="radio" name="frpId" value="CMBCHINA-NET"/>招商银行td> 
                <td><input type="radio" name="frpId" value="BOC-NET"/> 中国银行 td> 
            tr> 
            <tr> 
                <td><input type="radio" name="frpId" value="CCB-NET"/>建设银行td> 
                <td><input type="radio" name="frpId" value="BCCB-NET"/> 北京银行td> 
                <td><input type="radio" name="frpId" value="CMBC-NET"/>中国民生银行总td> 
                <td><input type="radio" name="frpId" value="HXB-NET"/>华夏银行 td> 
            tr> 
            <tr> 
                <td><input type="radio" name="frpId" value="POST-NET"/> 中国邮政 td> 
                <td><input type="radio" name="frpId" value="ECITIC-NET"/>中信银行td> 
                <td><input type="radio" name="frpId" value="BOCO-NET"/>交通银行td> 
                <td><input type="radio" name="frpId" value="CEB-NET"/>中国光大银行td> 
            tr> 
            <tr> 
                <td><input type="radio" name="frpId" value="CITI-NET"/>美国花旗银行td> 
            tr> 
            <tr> 
                <td colspan="4"><input type="submit" value="付款"/> td> 
            tr> 
        table> 
         <br/> 
        <br/>
    form> 
body> 
html>

 

支付请求处理servlet:PayServlet.java

 

package com.itheima.ebook.web.servlet; 

import java.io.IOException; 

import javax.servlet.ServletException; 
import javax.servlet.http.HttpServlet; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 

import com.itheima.ebook.utils.PaymentUtil; 

public class PayServlet extends HttpServlet { 

    public void doGet(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException { 
        this.doPost(request, response); 
    } 

    //为第三方 准备参数 
    public void doPost(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException { 
        //1获得实际值 
        // * 订单号 
        String orderId = request.getParameter("orderId"); 
        // * 价格 
        String amount = request.getParameter("amount"); 
        // * 支付银行 
        String frpId = request.getParameter("frpId"); 
        //2准备参数 
        // 2.1 业务类型 
        String p0_Cmd = "Buy"; 
        // 2.2 商户编号 -- 注册账号 
        String p1_MerId = "10001126856"; 
        // 2.3商户订单号  -- 单号必须在自身账户交易中唯一 
        String p2_Order = orderId; 
        // 2.4 支付金额 
        String  p3_Amt = amount; 
        // 2.5交易币种 
        String p4_Cur = "CNY" ; 
        // 2.6 商品名称 
        String p5_Pid = "itheima"; 
        // 2.7商品种类 
        String p6_Pcat = ""; 
        // 2.8 商品描述 
        String p7_Pdesc = ""; 
        // 2.9 商户接收支付成功数据的地址  --最后从第三方回到网站的地址,注意:必须是公网ip地址 
        String  p8_Url = "http://localhost:8080/ebookstore/CallbackServlet"; 
        // 2.10 送货地址 
        String p9_SAF = "0"; 
        // 2.11商户扩展信息 
        String pa_MP = ""; 
        // 2.12 支付通道编码 -- 选择银行在第三方公司的编号 
        String pd_FrpId = frpId; 
        // 2.13 应答机制 -- 必须提供外网IP地址(当前唯一) 
        String pr_NeedResponse = "1"; 
        //#####第三方提供的加密key值 
        String keyValue = "69cl522AV6q613Ii4W6u8K6XuW8vM1N6bFgyv769220IuYe9u37N4y7rI4Pl"; 
        // 2.14  签名数据 , 将以上13个参数进行加密结果 
        String hmac = PaymentUtil.buildHmac(p0_Cmd, p1_MerId, p2_Order, p3_Amt, p4_Cur, p5_Pid, p6_Pcat, p7_Pdesc, p8_Url, p9_SAF, pa_MP, pd_FrpId, pr_NeedResponse, keyValue); 
        //3重定向到第三方 
        String url = "https://www.yeepay.com/app-merchant-proxy/node" + 
                    "?p0_Cmd=" + p0_Cmd + 
                    "&p1_MerId=" + p1_MerId+ 
                    "&p2_Order=" + p2_Order+ 
                    "&p3_Amt=" + p3_Amt+ 
                    "&p4_Cur=" + p4_Cur+ 
                    "&p5_Pid=" + p5_Pid+ 
                    "&p6_Pcat=" + p6_Pcat+ 
                    "&p7_Pdesc=" + p7_Pdesc+ 
                    "&p8_Url=" + p8_Url+ 
                    "&p9_SAF=" + p9_SAF+ 
                    "&pa_MP=" + pa_MP+ 
                    "&pd_FrpId=" + pd_FrpId+ 
                    "&pr_NeedResponse=" + pr_NeedResponse+ 
                    "&hmac=" + hmac; 
        response.sendRedirect(url); 
    } 

}

 

支付工具类:PaymentUtil.java

 

package com.itheima.ebook.utils; 

import java.io.UnsupportedEncodingException; 
import java.security.MessageDigest; 
import java.security.NoSuchAlgorithmException; 
import java.util.Arrays; 

public class PaymentUtil { 

    private static String encodingCharset = "UTF-8"; 
    /** 
     * 生成hmac方法 
     * 
     * @param p0_Cmd 业务类型 
     * @param p1_MerId 商户编号 
     * @param p2_Order 商户订单号 
     * @param p3_Amt 支付金额 
     * @param p4_Cur 交易币种 
     * @param p5_Pid 商品名称 
     * @param p6_Pcat 商品种类 
     * @param p7_Pdesc 商品描述 
     * @param p8_Url 商户接收支付成功数据的地址 
     * @param p9_SAF 送货地址 
     * @param pa_MP 商户扩展信息 
     * @param pd_FrpId 银行编码 
     * @param pr_NeedResponse 应答机制 
     * @param keyValue 商户密钥 
     * @return 
     */ 
    public static String buildHmac(String p0_Cmd,String p1_MerId, 
            String p2_Order, String p3_Amt, String p4_Cur,String p5_Pid, String p6_Pcat, 
            String p7_Pdesc,String p8_Url, String p9_SAF,String pa_MP,String pd_FrpId, 
            String pr_NeedResponse,String keyValue) { 
        StringBuilder sValue = new StringBuilder(); 
        // 业务类型 
        sValue.append(p0_Cmd); 
        // 商户编号 
        sValue.append(p1_MerId); 
        // 商户订单号 
        sValue.append(p2_Order); 
        // 支付金额 
        sValue.append(p3_Amt); 
        // 交易币种 
        sValue.append(p4_Cur); 
        // 商品名称 
        sValue.append(p5_Pid); 
        // 商品种类 
        sValue.append(p6_Pcat); 
        // 商品描述 
        sValue.append(p7_Pdesc); 
        // 商户接收支付成功数据的地址 
        sValue.append(p8_Url); 
        // 送货地址 
        sValue.append(p9_SAF); 
        // 商户扩展信息 
        sValue.append(pa_MP); 
        // 银行编码 
        sValue.append(pd_FrpId); 
        // 应答机制 
        sValue.append(pr_NeedResponse); 
        return PaymentUtil.hmacSign(sValue.toString(), keyValue); 
    } 
    /** 
     * 返回校验hmac方法 
     * 
     * @param hmac 支付网关发来的加密验证码 
     * @param p1_MerId 商户编号 
     * @param r0_Cmd 业务类型 
     * @param r1_Code 支付结果 
     * @param r2_TrxId 易宝支付交易流水号 
     * @param r3_Amt 支付金额 
     * @param r4_Cur 交易币种 
     * @param r5_Pid 商品名称 
     * @param r6_Order 商户订单号 
     * @param r7_Uid 易宝支付会员ID 
     * @param r8_MP 商户扩展信息 
     * @param r9_BType 交易结果返回类型 
     * @param keyValue 密钥 
     * @return 
     */ 
    public static boolean verifyCallback(String hmac, String p1_MerId, 
            String r0_Cmd, String r1_Code, String r2_TrxId, String r3_Amt, 
            String r4_Cur, String r5_Pid, String r6_Order, String r7_Uid, 
            String r8_MP, String r9_BType, String keyValue) { 
        StringBuilder sValue = new StringBuilder(); 
        // 商户编号 
        sValue.append(p1_MerId); 
        // 业务类型 
        sValue.append(r0_Cmd); 
        // 支付结果 
        sValue.append(r1_Code); 
        // 易宝支付交易流水号 
        sValue.append(r2_TrxId); 
        // 支付金额 
        sValue.append(r3_Amt); 
        // 交易币种 
        sValue.append(r4_Cur); 
        // 商品名称 
        sValue.append(r5_Pid); 
        // 商户订单号 
        sValue.append(r6_Order); 
        // 易宝支付会员ID 
        sValue.append(r7_Uid); 
        // 商户扩展信息 
        sValue.append(r8_MP); 
        // 交易结果返回类型 
        sValue.append(r9_BType); 
        String sNewString = PaymentUtil.hmacSign(sValue.toString(), keyValue); 
        return sNewString.equals(hmac); 
    } 
    /** 
     * @param aValue 
     * @param aKey 
     * @return 
     */ 
    public static String hmacSign(String aValue, String aKey) { 
        byte k_ipad[] = new byte[64]; 
        byte k_opad[] = new byte[64]; 
        byte keyb[]; 
        byte value[]; 
        try { 
            keyb = aKey.getBytes(encodingCharset); 
            value = aValue.getBytes(encodingCharset); 
        } catch (UnsupportedEncodingException e) { 
            keyb = aKey.getBytes(); 
            value = aValue.getBytes(); 
        } 

        Arrays.fill(k_ipad, keyb.length, 64, (byte) 54); 
        Arrays.fill(k_opad, keyb.length, 64, (byte) 92); 
        for (int i = 0; i < keyb.length; i++) { 
            k_ipad[i] = (byte) (keyb[i] ^ 0x36); 
            k_opad[i] = (byte) (keyb[i] ^ 0x5c); 
        } 

        MessageDigest md = null; 
        try { 
            md = MessageDigest.getInstance("MD5"); 
        } catch (NoSuchAlgorithmException e) { 

            return null; 
        } 
        md.update(k_ipad); 
        md.update(value); 
        byte dg[] = md.digest(); 
        md.reset(); 
        md.update(k_opad); 
        md.update(dg, 0, 16); 
        dg = md.digest(); 
        return toHex(dg); 
    } 

    public static String toHex(byte input[]) { 
        if (input == null) 
            return null; 
        StringBuffer output = new StringBuffer(input.length * 2); 
        for (int i = 0; i < input.length; i++) { 
            int current = input[i] & 0xff; 
            if (current < 16) 
                output.append("0"); 
            output.append(Integer.toString(current, 16)); 
        } 

        return output.toString(); 
    } 

    /** 
     * 
     * @param args 
     * @param key 
     * @return 
     */ 
    public static String getHmac(String[] args, String key) { 
        if (args == null || args.length == 0) { 
            return (null); 
        } 
        StringBuffer str = new StringBuffer(); 
        for (int i = 0; i < args.length; i++) { 
            str.append(args[i]); 
        } 
        return (hmacSign(str.toString(), key)); 
    } 

    /** 
     * @param aValue 
     * @return 
     */ 
    public static String digest(String aValue) { 
        aValue = aValue.trim(); 
        byte value[]; 
        try { 
            value = aValue.getBytes(encodingCharset); 
        } catch (UnsupportedEncodingException e) { 
            value = aValue.getBytes(); 
        } 
        MessageDigest md = null; 
        try { 
            md = MessageDigest.getInstance("SHA"); 
        } catch (NoSuchAlgorithmException e) { 
            e.printStackTrace(); 
            return null; 
        } 
        return toHex(md.digest(value)); 

    } 
//    public static void main(String[] args) { 
//        System.out.println(hmacSign("AnnulCard1000043252120080620160450.0http://localhost/SZXpro/callback.asp杩?4564868265473632445648682654736324511","8UPp0KE8sq73zVP370vko7C39403rtK1YwX40Td6irH216036H27Eb12792t")); 
//    } 
}

转载于:https://www.cnblogs.com/fujianyi/p/4095960.html

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