支付寶報關接口開發

1,開通海關報關產品 ,不能登錄賬號,登陸賬號是看不到產品的

地址:https://b.alipay.com/order/productDetail.htm?productId=2015112418944074
在這裏插入圖片描述

2,產品開通成功後,查看報關的開發文檔

地址:https://docs.open.alipay.com/155/104778/
在這裏插入圖片描述

3,官方提供了項目demo,支持三種語言

在這裏插入圖片描述

4,整合到springboot 項目,使用MD5加密方式

(1),application.yml裏面添加,根據自己的參數修改裏面值

alipay:
  #合作身份者ID
  partnerId: 2088***********
  #商戶的私鑰 根據加密類型,填寫:MD5 ,RSA
  privateKey: ***********
  #字符編碼格式
  inputCharset: utf-8
  #簽名方式
  ignType: MD5
  #廣州總署海關
  customs: ZONGSHU
  #商戶海關備案號
  mchCustomsNo: ***********
  #商戶海關備案名稱
  mchCustomsName: ***********
  #接口名稱
  service: alipay.acquire.customs
  #接口地址
  payGateWay: https://mapi.alipay.com/gateway.do?

(2)下面代碼是工具類,httpclient的一些代碼

package io.renren.utils.alipay;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.StringUtils;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

public class AlipayUtil {
    /**
     * 生成請求url
     * @param params
     * @param key
     * @param paygateway
     * @param input_charset
     * @return
     */
    public static String createUrl( Map<String,String> params ,String key, String paygateway,String input_charset,String sign_type) {
        String prestr = "";
        prestr = prestr + key;
        String sign = DigestUtils.md5Hex(getContent(params, key));
        String parameter = "";
        parameter = parameter + paygateway;

        List<String> keys = new ArrayList<>(params.keySet());
        for (int i = 0; i < keys.size(); i++) {
            try {
                parameter = parameter + keys.get(i) + "="
                        + URLEncoder.encode(params.get(keys.get(i)), input_charset) + "&";
            } catch (UnsupportedEncodingException e) {

                e.printStackTrace();
            }
        }

        parameter = parameter + "sign=" + sign + "&sign_type="+sign_type;

        return parameter;

    }
    /**
     * 拼接請求參數
     * @param params
     * @param privateKey
     * @return
     */
    private static String getContent(Map params, String privateKey) {
        Map map = params;
        List keys = new ArrayList(map.keySet());
        Collections.sort(keys);

        String prestr = "";

        for (int i = 0; i < keys.size(); i++) {
            String key = (String) keys.get(i);
            String value = (String) map.get(key);

            if (i == keys.size() - 1) {
                prestr = prestr + key + "=" + value;
            } else {
                prestr = prestr + key + "=" + value + "&";
            }
        }
        String p = "";
        if(StringUtils.isNotBlank(privateKey)){
            p = prestr+privateKey;

        } else {
            p = prestr;
        }
        return p;
    }
}
package io.renren.utils.alipay.httpClient;

import org.apache.commons.httpclient.*;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.multipart.*;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.httpclient.util.IdleConnectionTimeoutThread;

import java.io.File;
import java.io.IOException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;

public class HttpProtocolHandler {

    private static String              DEFAULT_CHARSET                     = "GBK";

    /** 連接超時時間,由bean factory設置,缺省爲8秒鐘 */
    private int                        defaultConnectionTimeout            = 8000;

    /** 迴應超時時間, 由bean factory設置,缺省爲30秒鐘 */
    private int                        defaultSoTimeout                    = 30000;

    /** 閒置連接超時時間, 由bean factory設置,缺省爲60秒鐘 */
    private int                        defaultIdleConnTimeout              = 60000;

    private int                        defaultMaxConnPerHost               = 30;

    private int                        defaultMaxTotalConn                 = 80;

    /** 默認等待HttpConnectionManager返回連接超時(只有在達到最大連接數時起作用):1秒*/
    private static final long          defaultHttpConnectionManagerTimeout = 3 * 1000;

    /**
     * HTTP連接管理器,該連接管理器必須是線程安全的.
     */
    private HttpConnectionManager connectionManager;

    private static HttpProtocolHandler httpProtocolHandler                 = new HttpProtocolHandler();

    /**
     * 工廠方法
     *
     * @return
     */
    public static HttpProtocolHandler getInstance() {
        return httpProtocolHandler;
    }

    /**
     * 私有的構造方法
     */
    private HttpProtocolHandler() {
        // 創建一個線程安全的HTTP連接池
        connectionManager = new MultiThreadedHttpConnectionManager();
        connectionManager.getParams().setDefaultMaxConnectionsPerHost(defaultMaxConnPerHost);
        connectionManager.getParams().setMaxTotalConnections(defaultMaxTotalConn);

        IdleConnectionTimeoutThread ict = new IdleConnectionTimeoutThread();
        ict.addConnectionManager(connectionManager);
        ict.setConnectionTimeout(defaultIdleConnTimeout);

        ict.start();
    }

    /**
     * 執行Http請求
     *
     * @param request 請求數據
     * @param strParaFileName 文件類型的參數名
     * @param strFilePath 文件路徑
     * @return
     * @throws HttpException, IOException
     */
    public HttpResponse execute(HttpRequest request, String strParaFileName, String strFilePath) throws HttpException, IOException {
        HttpClient httpclient = new HttpClient(connectionManager);

        // 設置連接超時
        int connectionTimeout = defaultConnectionTimeout;
        if (request.getConnectionTimeout() > 0) {
            connectionTimeout = request.getConnectionTimeout();
        }
        httpclient.getHttpConnectionManager().getParams().setConnectionTimeout(connectionTimeout);

        // 設置迴應超時
        int soTimeout = defaultSoTimeout;
        if (request.getTimeout() > 0) {
            soTimeout = request.getTimeout();
        }
        httpclient.getHttpConnectionManager().getParams().setSoTimeout(soTimeout);

        // 設置等待ConnectionManager釋放connection的時間
        httpclient.getParams().setConnectionManagerTimeout(defaultHttpConnectionManagerTimeout);

        String charset = request.getCharset();
        charset = charset == null ? DEFAULT_CHARSET : charset;
        HttpMethod method = null;

        //get模式且不帶上傳文件
        if (request.getMethod().equals(HttpRequest.METHOD_GET)) {
            method = new GetMethod(request.getUrl());
            method.getParams().setCredentialCharset(charset);

            // parseNotifyConfig會保證使用GET方法時,request一定使用QueryString
            method.setQueryString(request.getQueryString());
        } else if(strParaFileName.equals("") && strFilePath.equals("")) {
            //post模式且不帶上傳文件
            method = new PostMethod(request.getUrl());
            ((PostMethod) method).addParameters(request.getParameters());
            method.addRequestHeader("Content-Type", "application/x-www-form-urlencoded; text/html; charset=" + charset);
        }
        else {
            //post模式且帶上傳文件
            method = new PostMethod(request.getUrl());
            List<Part> parts = new ArrayList<Part>();
            for (int i = 0; i < request.getParameters().length; i++) {
                parts.add(new StringPart(request.getParameters()[i].getName(), request.getParameters()[i].getValue(), charset));
            }
            //增加文件參數,strParaFileName是參數名,使用本地文件
            parts.add(new FilePart(strParaFileName, new FilePartSource(new File(strFilePath))));

            // 設置請求體
            ((PostMethod) method).setRequestEntity(new MultipartRequestEntity(parts.toArray(new Part[0]), new HttpMethodParams()));
        }

        // 設置Http Header中的User-Agent屬性
        method.addRequestHeader("User-Agent", "Mozilla/4.0");
        HttpResponse response = new HttpResponse();

        try {
            httpclient.executeMethod(method);
            if (request.getResultType().equals(HttpResultType.STRING)) {
                response.setStringResult(method.getResponseBodyAsString());
            } else if (request.getResultType().equals(HttpResultType.BYTES)) {
                response.setByteResult(method.getResponseBody());
            }
            response.setResponseHeaders(method.getResponseHeaders());
        } catch (UnknownHostException ex) {

            return null;
        } catch (IOException ex) {

            return null;
        } catch (Exception ex) {

            return null;
        } finally {
            method.releaseConnection();
        }
        return response;
    }

    /**
     * 將NameValuePairs數組轉變爲字符串
     *
     * @param nameValues
     * @return
     */
    protected String toString(NameValuePair[] nameValues) {
        if (nameValues == null || nameValues.length == 0) {
            return "null";
        }

        StringBuffer buffer = new StringBuffer();

        for (int i = 0; i < nameValues.length; i++) {
            NameValuePair nameValue = nameValues[i];

            if (i == 0) {
                buffer.append(nameValue.getName() + "=" + nameValue.getValue());
            } else {
                buffer.append("&" + nameValue.getName() + "=" + nameValue.getValue());
            }
        }

        return buffer.toString();
    }
}
package io.renren.utils.alipay.httpClient;

import org.apache.commons.httpclient.NameValuePair;

/* *
 *類名:HttpRequest
 *功能:Http請求對象的封裝
 *詳細:封裝Http請求
 *版本:3.3
 *日期:2011-08-17
 *說明:
 *以下代碼只是爲了方便商戶測試而提供的樣例代碼,商戶可以根據自己網站的需要,按照技術文檔編寫,並非一定要使用該代碼。
 *該代碼僅供學習和研究支付寶接口使用,只是提供一個參考。
 */

public class HttpRequest {

    /** HTTP GET method */
    public static final String METHOD_GET        = "GET";

    /** HTTP POST method */
    public static final String METHOD_POST       = "POST";

    /**
     * 待請求的url
     */
    private String             url               = null;

    /**
     * 默認的請求方式
     */
    private String             method            = METHOD_POST;

    private int                timeout           = 0;

    private int                connectionTimeout = 0;

    /**
     * Post方式請求時組裝好的參數值對
     */
    private NameValuePair[]    parameters        = null;

    /**
     * Get方式請求時對應的參數
     */
    private String             queryString       = null;

    /**
     * 默認的請求編碼方式
     */
    private String             charset           = "GBK";

    /**
     * 請求發起方的ip地址
     */
    private String             clientIp;

    /**
     * 請求返回的方式
     */
    private HttpResultType     resultType        = HttpResultType.BYTES;

    public HttpRequest(HttpResultType resultType) {
        super();
        this.resultType = resultType;
    }

    /**
     * @return Returns the clientIp.
     */
    public String getClientIp() {
        return clientIp;
    }

    /**
     * @param clientIp The clientIp to set.
     */
    public void setClientIp(String clientIp) {
        this.clientIp = clientIp;
    }

    public NameValuePair[] getParameters() {
        return parameters;
    }

    public void setParameters(NameValuePair[] parameters) {
        this.parameters = parameters;
    }

    public String getQueryString() {
        return queryString;
    }

    public void setQueryString(String queryString) {
        this.queryString = queryString;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getMethod() {
        return method;
    }

    public void setMethod(String method) {
        this.method = method;
    }

    public int getConnectionTimeout() {
        return connectionTimeout;
    }

    public void setConnectionTimeout(int connectionTimeout) {
        this.connectionTimeout = connectionTimeout;
    }

    public int getTimeout() {
        return timeout;
    }

    public void setTimeout(int timeout) {
        this.timeout = timeout;
    }

    /**
     * @return Returns the charset.
     */
    public String getCharset() {
        return charset;
    }

    /**
     * @param charset The charset to set.
     */
    public void setCharset(String charset) {
        this.charset = charset;
    }

    public HttpResultType getResultType() {
        return resultType;
    }

    public void setResultType(HttpResultType resultType) {
        this.resultType = resultType;
    }

}

package io.renren.utils.alipay.httpClient;

import io.renren.config.AlipayConfig;
import org.apache.commons.httpclient.Header;
import org.springframework.beans.factory.annotation.Autowired;

import java.io.UnsupportedEncodingException;

/* *
 *類名:HttpResponse
 *功能:Http返回對象的封裝
 *詳細:封裝Http返回信息
 *版本:3.3
 *日期:2011-08-17
 *說明:
 *以下代碼只是爲了方便商戶測試而提供的樣例代碼,商戶可以根據自己網站的需要,按照技術文檔編寫,並非一定要使用該代碼。
 *該代碼僅供學習和研究支付寶接口使用,只是提供一個參考。
 */
public class HttpResponse {
    @Autowired
    private AlipayConfig alipayConfig;
    /**
     * 返回中的Header信息
     */
    private Header[] responseHeaders;

    /**
     * String類型的result
     */
    private String   stringResult;

    /**
     * btye類型的result
     */
    private byte[]   byteResult;

    public Header[] getResponseHeaders() {
        return responseHeaders;
    }

    public void setResponseHeaders(Header[] responseHeaders) {
        this.responseHeaders = responseHeaders;
    }

    public byte[] getByteResult() {
        if (byteResult != null) {
            return byteResult;
        }
        if (stringResult != null) {
            return stringResult.getBytes();
        }
        return null;
    }

    public void setByteResult(byte[] byteResult) {
        this.byteResult = byteResult;
    }

    public String getStringResult() throws UnsupportedEncodingException {
        if (stringResult != null) {
            return stringResult;
        }
        if (byteResult != null) {
            return new String(byteResult, alipayConfig.getInputCharset());
        }
        return null;
    }

    public void setStringResult(String stringResult) {
        this.stringResult = stringResult;
    }

}

/*
 * Alipay.com Inc.
 * Copyright (c) 2004-2005 All Rights Reserved.
 */
package io.renren.utils.alipay.httpClient;

/* *
 *類名:HttpResultType
 *功能:表示Http返回的結果字符方式
 *詳細:表示Http返回的結果字符方式
 *版本:3.3
 *日期:2012-08-17
 *說明:
 *以下代碼只是爲了方便商戶測試而提供的樣例代碼,商戶可以根據自己網站的需要,按照技術文檔編寫,並非一定要使用該代碼。
 *該代碼僅供學習和研究支付寶接口使用,只是提供一個參考。
 */
public enum HttpResultType {
    /**
     * 字符串方式
     */
    STRING,

    /**
     * 字節數組方式
     */
    BYTES
}

(3)下面是serviceImpl調用接口,發送請求,測試的話可以寫個main方法傳參數即可

/*支付寶海關報文*/
    @Override
    public Result alipayOffical(Map<String, String> params) throws Exception {
        Map<String, String> sParaTemp = new HashMap<>();
        sParaTemp.put("service", alipayConfig.getService());
        sParaTemp.put("partner", alipayConfig.getPartnerId());
        sParaTemp.put("_input_charset", alipayConfig.getInputCharset());
        sParaTemp.put("out_request_no", params.get("out_request_no"));
        sParaTemp.put("trade_no", params.get("trade_no"));
        sParaTemp.put("merchant_customs_code", alipayConfig.getMchCustomsNo());
        sParaTemp.put("merchant_customs_name", alipayConfig.getMchCustomsName());
        sParaTemp.put("amount", params.get("amount"));
        sParaTemp.put("customs_place", alipayConfig.getCustoms());

        String createUrl = AlipayUtil.createUrl(sParaTemp, alipayConfig.getPrivateKey(),
                alipayConfig.getPayGateWay(), alipayConfig.getInputCharset(), alipayConfig.getIgnType());
        HttpProtocolHandler httpProtocolHandler = HttpProtocolHandler.getInstance();
        HttpRequest request = new HttpRequest(HttpResultType.STRING);
        //設置編碼集
        request.setCharset(alipayConfig.getInputCharset());
        request.setUrl(createUrl);
        System.out.println(request.getUrl());
        HttpResponse response = httpProtocolHandler.execute(request, "", "");
        String param = response.getStringResult();
        System.out.println("支付寶報關響應數據----" + param);

        int isSuccessBegin = param.indexOf("<is_success>");
        int isSuccessEnd = param.indexOf("</is_success>");
        String isSuccess = param.substring(isSuccessBegin + 12, isSuccessEnd);

        if ("T".equals(isSuccess)) {
            int resultCodeBegin = param.indexOf("<result_code>");
            int resultCodeEnd = param.indexOf("</result_code>");
            String resultCode = param.substring(resultCodeBegin + 13, resultCodeEnd);
            if ("SUCCESS".equals(resultCode)) {
                System.out.println("支付寶海關支付報關成功!");
                return new Result().ok("SUCCESS");
            } else {
                System.out.println("支付寶海關支付報關失敗!---請求成功---業務處理失敗");
                return new Result().error("FAIL");
            }
        } else {
            System.out.println("支付寶海關支付報關失敗!---請求失敗");
            return new Result().error("FAIL");
        }
    }

(4)業務正常受理並報關成功返回樣例

<?xml version="1.0" encoding="utf-8"?>
<alipay>
    <is_success>T</is_success>
    <request>
        <param name="trade_no">2015051446800462</param>
        <param name="merchant_customs_code">hanguo</param>
        <param name="sign_type">MD5</param>
        <param name="merchant_customs_name">jwyhanguo_card</param>
        <param name="sign">2118ac8fad6bc1d9e88a6cd017c18d37</param>
        <param name="amount">2</param>
        <param name="_input_charset">UTF-8</param>
        <param name="customs_place">HANGZHOU</param>
        <param name="service">alipay.acquire.customs</param>
        <param name="out_request_no">9193457120563834</param>
        <param name="partner">2088101142878662</param>
    </request>
    <response>
        <alipay>
            <result_code>SUCCESS</result_code>
            <trade_no>2013111511001004390000105126</trade_no>
            <alipay_declare_no>2013112611001004680073956707</alipay_declare_no>
        </alipay>
    </response>
    <sign>3afc92ac4708425ab74ecb2c4e58ef56</sign>
    <sign_type>MD5</sign_type>
</alipay>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章