關於php接ICBC的支付接口的解決方案

一:背景: 目前項目使用的是php語言開發,需要接入中國工商銀行的ICBC的線上支付接口。

二:遇到的問題:支付時需要對數據簽名,但是銀行那邊不提供php版本的程序,只有java版本的,以下是對接人回復的郵件:

三:思路:

目前大概有3種解決方案:

1.  通過使用一個叫 php-java-bridge 的插件,在php中調用java的函數

2. 把java的函數改寫成php版本

3. 在服務器配置javaWeb環境,通過http請求把簽名的參數傳入,從而獲取簽名

四: 具體做法:

我採取的是第3種方法,畢竟對java不太熟悉,不想在語言層面作文章。

我使用到的是ubuntu14.04 作爲服務器,首先配置javaWeb的環境

1. 因爲php的環境已經配置好了,所以 php環境的配置環境可以參考: http://www.cnblogs.com/weishuan/p/4402744.html

   2.  tomcat 的環境配置:

sudo apt update

sudo apt install tomcat7 //安裝tomcat7

sudo apt install default-jdk //javac 編譯

安裝好之後,默認的端口是8080,可以通過 http://www.服務器url:8080 驗證

如果需要修改端口號,可以修改 /var/lib/tomcat7/config/server.xml

//原來的配置
<Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443"
               maxHttpHeaderSize="102400" />

//修改後的配置
<Connector port="8888(修改後的端口)" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443"
               maxHttpHeaderSize="102400" />

接下來就是java的代碼

getSign.java

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;

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

import cn.com.infosec.icbc.ReturnValue;

/**
 * Servlet implementation class getSign
 */
@WebServlet("/getSign")
public class getSign extends HttpServlet {
    private static final long serialVersionUID = 1L;

    /**
     * @see HttpServlet#HttpServlet()
     */
    public getSign() {
        super();
    }

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

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        PrintWriter out = response.getWriter();
        String type  = request.getParameter("type");  //區分是調用哪個函數

        if (type != null) {

            String interfaceName = request.getParameter("interfaceName");
            String interfaceVersion = request.getParameter("interfaceVersion");
            String areaCode = request.getParameter("areaCode");
            String merID = request.getParameter("merID");
            String merAcct = request.getParameter("merAcct");
            String merURL = request.getParameter("merURL");
            String notifyType = request.getParameter("notifyType");
            String orderid = request.getParameter("orderid");
            String amount = request.getParameter("amount");
            String curType = request.getParameter("curType");
            String resultType = request.getParameter("resultType");
            String orderDate = request.getParameter("orderDate");
            String merCerFileKeyPath = request.getParameter("merCerFileKeyPath");
            String keyPass = request.getParameter("keyPass");

            StringBuilder tranData = new StringBuilder();
            tranData.append(interfaceName).append(interfaceVersion).append(areaCode).append(merID).append(merAcct).append(merURL).append(notifyType).append(orderid).append(amount).append(curType).append(resultType).append(orderDate);

            String MerSign = getMerSignMsgBase64(tranData.toString(), merCerFilePath, keyPass);
            out.print(MerSign);

        } else {
            String merCerFileCrtPath = request.getParameter("merCerFileCrtPath");
            String merCertBase64 = getMerCertBase64(merCerFilePath);
            out.print(merCertBase64);
        }
    }

    public static String getMerSignMsgBase64(String tranData,String merCerFilePath,String keyPass) {
        byte[] tranByteSrc = tranData.toString().getBytes();
        char[] keyPasss = keyPass.toCharArray();
        File merSineFile = new File(merCerFilePath);
        FileInputStream fileInputStream;
        try {
            fileInputStream = new FileInputStream(merSineFile.getAbsolutePath());
            byte[] sineBytes = new byte[fileInputStream.available()];
            fileInputStream.read(sineBytes);
            fileInputStream.close();
            byte[] sign =ReturnValue.sign(tranByteSrc,tranByteSrc.length,sineBytes,keyPasss);
            byte[] EncSign = ReturnValue.base64enc(sign);
            String merSignMsgBase64 = new String(EncSign,"UTF-8").toString();

            merSignMsgBase64= merSignMsgBase64.replace("\n", "");
            merSignMsgBase64= merSignMsgBase64.replace("\r", "");
            return merSignMsgBase64;
        } catch (Exception e) {
            System.out.println("getMerSignMsgBase64"+e.getMessage());
            e.printStackTrace();
        }
            return "";
        }

    public static String getMerCertBase64(String merCerFilePath) {

        File merCerFile = new File(merCerFilePath);
        FileInputStream fileInputStream;

        try {
            fileInputStream = new FileInputStream(merCerFile.getAbsolutePath());
            System.out.println(merCerFile.getAbsolutePath());
            byte[] bytes = new byte[fileInputStream.available()];
            fileInputStream.read(bytes);
            fileInputStream.close();
            byte[] EncCerts=ReturnValue.base64enc(bytes);
            String merCertBase64=new String(EncCerts).toString();
            merCertBase64= merCertBase64.replace("\n", "");
            merCertBase64= merCertBase64.replace("\r", "");
            System.out.println("IcbcOpayFileReader.getMerCertBase64:"+merCertBase64);
            return merCertBase64;
        } catch (FileNotFoundException e) {
            System.out.println("getMerCertBase64"+e.getMessage());
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return "";
    }

}

通過http的post或者get方法接收參數,簽名後返回字符串。

部署java的代碼,在/var/lib/tomcat7/webapps/目錄下,新建一個icbc的文件夾:

先看web.xml裏面的內容

<?xml version="1.0" encoding="UTF-8"?>
<!--
 Licensed to the Apache Software Foundation (ASF) under one or more
  contributor license agreements.  See the NOTICE file distributed with
  this work for additional information regarding copyright ownership.
  The ASF licenses this file to You under the Apache License, Version 2.0
  (the "License"); you may not use this file except in compliance with
  the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
-->
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                      http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
  version="3.1"
  metadata-complete="true">

  <servlet>
    <!--servlet名称,可以自定义-->
    <servlet-name>icbc</servlet-name>
    <!-- servlet类名: 包名+简单类名-->
    <servlet-class>getSign</servlet-class>
  </servlet>

  <servlet-mapping>
    <!--servlet名称,应与上面的名称保持一致,因为是通过下面的servlet访问名称来定位到上面的servlet名称,再通过上面的名称定位到servlet类的位置-->
    <servlet-name>icbc</servlet-name>
    <!-- servlet的访问名称: /名称 -->
    <url-pattern>/getSign</url-pattern>
  </servlet-mapping>

</web-app>

關於getSign.class的編譯,先確保工行的兩個jar包放在lib的目錄里,然後在getSign.java所在的路徑執行以下目錄

javac -cp /var/lib/tomcat7/webapps/icbc/WEB-INF/lib/InfosecCrypto_Java1_02_JDK13+.jar:/var/lib/tomcat7/webapps/icbc/WEB-INF/lib/icbc.jar:/usr/share/tomcat7/lib/servlet-api.jar -d /var/lib/tomcat7/webapps/icbc/WEB-INF/classes/ getSign.java

新建一個 /var/www/icbc/ 的文件,把 getSign.java 丟進去,爲了方便,我新建一個腳本文件 javac_icbc.sh

if javac -cp /var/lib/tomcat7/webapps/icbc/WEB-INF/lib/InfosecCrypto_Java1_02_JDK13+.jar:/var/lib/tomcat7/webapps/icbc/WEB-INF/lib/icbc.jar:/usr/share/tomcat7/lib/servlet-api.jar -d /var/lib/tomcat7/webapps/icbc/WEB-INF/classes/ getSign.java
then
        echo "javac -cp /var/lib/tomcat7/webapps/icbc/WEB-INF/lib/InfosecCrypto_Java1_02_JDK13+.jar:/var/lib/tomcat7/webapps/icbc/WEB-INF/lib/icbc.jar:/usr/share/tomcat7/lib/servlet-api.jar -d /var/lib/tomcat7/webapps/icbc/WEB-INF/classes/ getSign.java"

        echo "------  编译成功,重启tomcat 服务器 --------"
        if sudo /etc/init.d/tomcat7 restart
        then
                echo "------ 服务器重启成功 ---------"
        else
                echo "------ 服务器重启失败, 请手动输入下面命令重启 ------"
                echo "sudo /etc/init.d/tomcat7 restart"
        fi
else
        echo "------ 编译失败,请查看 /var/lib/tomcat7/webapps/icbc/WEB-INF/lib/ 文件夹是否存在以下2个文件: --------"
        echo "1. InfosecCrypto_Java1_02_JDK13+.jar"
        echo "2. icbc.jar"
fi

然後添加執行權限:

sudo chmod +x javac_icbc.sh

在執行文件編譯之前,請確保 /var/lib/tomcat7/webapps/icbc/ 具有讀寫權限

sudo chmod -R 777 /var/lib/tomcat7/webapps/icbc/
sudo chmod -R 777 /var/lib/tomcat7/webapps/icbc/*

然後執行javac_icbc.sh

./javac_icbc.sh

最後,測試一下環境是否配置成功

確保你的公鑰和私鑰都有權限

sudo chmod -R 777 私鑰.key
sudo chmod -R 777 公鑰.crt

新建一個index.php文件測試一下:

<?php
    $interfaceName = "ICBC_MYEBANK_B2C";
    $interfaceVersion = "3.0.0.0";
    $areaCode = "0119";
    $merID = "工行提供";
    $merAcct = "工行提供"";
    $merURL = "你的回調地址";
    $notifyType = "HS";
    $curType = "MOP";
    $resultType = "2";
    $merCerFileKeyPath = "私鑰.key的路徑";
    $merCerFileCrtPath = "公鑰.crt的路徑";
    $keyPass = "12345678";

    $orderid = "201812345678";
    $amount = "1000";//以分爲單位
    $orderDate = "20180123162333";

    $url = "http://localhost:8080/icbc/getSign?type=1&interfaceName=".$interfaceName."&interfaceVersion=".$interfaceVersion."&areaCode=".$areaCode."&merID=".$merID."&merAcct=".$merAcct."&merURL=".$merURL."&notifyType=".$notifyType."&orderid=".$orderid."&amount=".$amount."&curType=".$curType."&resultType=".$resultType."&orderDate=".$orderDate."&merCerFileKeyPath=".$merCerFileKeyPath."&keyPass=".$keyPass;

    $url = "http://localhost:8080/icbc/getSign?merCerFileCrtPath=".$merCerFileCrtPath;

    function _request($url){
        $ch=curl_init();
        curl_setopt($ch,CURLOPT_HEADER,0);
        curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
        curl_setopt($ch,CURLOPT_URL,$url);
        $result=curl_exec($ch);
        curl_close($ch);
        return $result;
    }

echo _request($getBaseUrl);
echo "<br>";
echo "-----------";
echo _request($getSignUrl);

最後能獲取簽名:

最後的最後 :

在開發過程中,我遇到了一個問題, 通過post或者get 方法時,傳遞的參數過多,超出tomcat的緩衝區,目前還沒解決。

org.apache.coyote.http11.AbstractHttp11Processor process
信息: Error parsing HTTP request header
Note: further occurrences of HTTP header parsing errors will be logged at DEBUG level.

百度和google 發現是:Tomcat的header缓冲区大小不够,只需要在server.xml中增加maxHttpHeaderSize字段即可

但是我加了還是報錯,無奈只能把post的參數減少,把固定的參數寫死在java文件中。

原文地址:https://www.cnblogs.com/weishuan/p/8372063.html

时间: 2024-10-21 01:43:04

關於php接ICBC的支付接口的解決方案的相关文章

在线支付接口详解

当我们在商城购物时,可能会用到在线支付,你会发现无论你是哪个银行的银行卡接口中都会支持,在做项目开 发时,也经常会用到支付接口,我们当然希望支持所有的网银,但这需要我们针对每个银行开发一套接口吗?不是不可以而是没必要,使用第三方的支付接口就可以 满足,第三方支付平台已经与各大银行进行签约,网站主只需要在此平台申请一个账号即可支持几乎所有的种类的银行卡信用卡的交易,当然是可能支付少量的手续 费的.什么是第三方支付呢? 所谓第三方支付,就是一些和各大银行签约.并具备一定实力和信誉保障的第三方独立机构

如何接入中国工商银行网上银行B2C在线支付接口

中国工商银行网上银行B2C在线支付接口说明,亲测可行. 工具/原料 merID:银行提供.唯一确定一个商户的代码,由商户在工行开户时,由工行告知商户. merAcct:银行提供 , 商城收费入账账号 (只能交易时指定). 懂得html代码跟PHP的程序员一名 方法/步骤 1 到银行开户,说明要做B2C在线支付接口,此时银行会提供给你 merID  .merAcct  这两个 2 由程序员按照一下步骤来做即可,在商城提交表单的页面添加以下控件. 3 <html xmlns=http://www.w

UnionPay,ChinaPay 最新 银联支付接口C#\Asp.net\MVC 版本

1.概念普及 一.理解什么是UnionPay.ChinaPay 这两个概念如果搞不清楚,绝对够你瞎折腾一段时间的. UnionPay:中国银联,最大的机构:他本身也提供系统接口但都是B2B的,对于单个商户他们不提供客服,也不提供技术解决,更不会提供商户后台(可查消费记录等):但他的技术接口文档比较齐全,而且也可以使用,警惕不要使用这些接口. ChinaPay:银联电子支付公司,第三方的支付公司,UnionPay的所有接口和服务都托管给类似的第三方公司,ChinaPay再向商户服务,ChinaPa

【Java EE 学习 21 下】【 使用易宝支付接口实现java网上支付功能】

一.网上支付分为两种情况,一种方法是使用直接和银行的支付接口,另外一种方法是使用第三方支付平台和银行对接完成支付. 1.直接和银行对接. 2.使用第三方支付平台 3.常见的第三方支付平台 二.使用易宝支付接口实现java网上支付功能(农业银行). 1.完整源代码:https://github.com/kdyzm/day21_2_pay 2.实现过程的时序图 3.技术要点 (1)使用GET请求的时候必须将全部参数都带上,参数名称参考开发者文档中的请求参数列表 (2)使用PaymentUtil类实现

PHP商城网站绑定中国银联在线支付接口

PHP商城网站绑定中国银联在线支付接口用的越来越广泛,我们公司这几年给客户建立过很多的商城网站,今天就分析下怎么为自己的PHP商城网站接入中国银联在线支付端的接口.在使用前我们必须先申请成为中国银联在线支付的商户. 第一步:下载中国银联官方PHP支付接口文件 进入中国银联在线官方网站的商户服务网站,下载PHP的技术资料端口文件(https://online.unionpay.com/mer/pages/merser/index.jsp这是中国银联在线支付商户服务网站),点击右上角的“文档下载”

API开发第五篇:服务端整合支付宝快捷移动支付接口

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"><span style="white-space:pre"> </span>在开发中需要使用支付宝的快捷移动支付接口,通过文档知道,当完成客户端请求完成后,支付宝服务器会异步通知客户端的服务器.这里的关键是提供给支付宝的这个用于异步通知的con

【网站国际化必备】Asp.Net MVC 集成Paypal(贝宝)快速结账 支付接口 ,附源码demo

开篇先给大家讲段历史故事,博主是湖北襄阳人.襄阳物华天宝,人杰地灵,曾用名襄樊.在2800多年的历史文化中出现了一代名相诸葛亮(卧龙),三国名士庞统(凤雏),魏晋隐士司马徽(水镜先生),唐代大诗人孟浩然(孟襄阳),张继.杜审言,文学家皮日休,北宋著名书画家米芾(米襄阳),“允冠百王”的光武帝刘秀,东方圣人释道安等一大批历史文化名人.小说<三国演义>120回故事中有30多回提到襄阳. 相传诸葛亮的老婆黄月英黄头发黑皮肤,但知识广博.诸葛亮发明木牛流马,就是从黄月英的传授的技巧上发展出来.不仅如此

那些年我们赚过的外快(POS(移动支付)接口开发)

老规矩上前戏了.在我写博文"那些年我们赚过的外快"前后算起来大大小小也接了些私活,这次是因为好久没写博客了,趁热分享一下.最近回了离老家近的二线城市成都工作,收入那是下降很多啊,刚开始老婆还没说什么,随着开始还房贷和债务,生活开始捉襟见肘了.哎,最近都在发愁怎么增加收入!自己的想法是:1.争取多做几个安卓app出来发布到各大市场,靠植入广告赚点白菜钱.(还没验证过是否可行) 2.把之前积累好多年的行业管理软件的需求整理成几个软件,或基于云服务打造几款共享软件.(竞争很激烈啊,容易死在沙

怎样选择给网站选择支付接口

大部分的网站主在给网站选择支付接口时,重点考虑的是以下几个问题: 支付成功率怎样! 帐目是否清晰! 支付成本是否够低! 系统是否安全! 深层次的需求:1.支付记录能否删除,确保用户隐私. 2.能否进行委托分帐结算,相当于分批次结算到不同的帐户.3.能否降低企业成本接入一家就可以支持大部分的第三方平台. 虽然目前互联网上在线支付接口种类很多,不过常见在线支付接口就这几种: 1. 支付宝支付接口集成:支付宝支付接口集成是指支付宝支付平台接口程序与你的商务网站无缝整合,从而让你的网站立即拥有在线收款的