阿里App支付服务端接口开发(含后台异步回调,退款)

1.引入相关包文件

maven导入方式:

<dependency>
	<groupId>com.alipay</groupId>
	<artifactId>sdk-java</artifactId>
	<version>20180104135026</version>
</dependency>

maven 制作 alipay-sdk-java包到本地仓库(方法参考): https://blog.csdn.net/lipeng32768/article/details/50845547

现在支付宝好像已经可以在maven中搜到

 <dependency>
 <groupId>com.alipay.sdk</groupId>

  <artifactId>alipay-sdk-java</artifactId>

<version>3.0.0</version>

</dependency>

jar包导入方式:

下载sdk集成支付宝接口需要引入的文件是:
alipay-sdk-java*.jar
commons-logging-1.1.1.jar

2.代码展示:

aliplatform.properties

appid:****
url:https://openapi.alipay.com/gateway.do
format:json
charset:UTF-8
alipay_public_key:****
app_private_key:*******
sign_type:RSA2
notify_url:http://**/app/alipayNotify
pid:****

controller(app接口)

@Controller
@Api(value = "Api控制器", description ="App支付宝接口")
@RequestMapping(value = "/app")
public class AliPayController  extends BaseController{
	
	private  static final Properties  properties = PropertiesUtils.getPprVue("aliplatform.properties");  
	/**
	 *对应阿里的参数在配置文件
	 */
	private static final String APP_ID = properties.getProperty("appid"); //
	private static final String URL =properties.getProperty("url");
	private static final String FORMAT = properties.getProperty("format");
	private static final String CHARSET =properties.getProperty("charset");
	private static final String ALIPAY_PUBLIC_KEY =properties.getProperty("alipay_public_key");
	private static final String APP_PRIVATE_KEY =properties.getProperty("app_private_key");
	//private static final String APP_PUBLIC_KEY =properties.getProperty("app_public_key");
	private static final String SIGN_TYPE = properties.getProperty("sign_type");
	private static final String NOTIFY_URL = properties.getProperty("notify_url");
	
	 @RequestMapping(value = "/alipayOrder", method = RequestMethod.POST)
	 @ResponseBody
	 public ResBean orderPay(){
		 PageData pd = new PageData();
		 pd = this.getPageData();
		 String orderInfo = alipay(pd);
		 if(!"".equals(orderInfo)){
			 
			 return new ResBean(1,"请求成功",orderInfo);	
		 }
		 return new ResBean(0,"请求失败",orderInfo);		
	 }
	 
	 @RequestMapping(value = "/alipayNotify", method = RequestMethod.POST)
	 @ResponseBody
	 public void AlipayCallBack(HttpServletRequest request) throws Exception{
	      Map<String,String> params = new HashMap<String,String>();
		 Map requestParams = request.getParameterMap();
		 for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
			 String name = (String) iter.next();
			 String[] values = (String[]) requestParams.get(name);
			 String valueStr = "";
			 for (int i = 0; i < values.length; i++) {
				 valueStr = (i == values.length - 1) ? valueStr + values[i]:valueStr + values[i] + ",";
			 }
			 //乱码解决,这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化//
			 valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk");
			 params.put(name, valueStr);
		 }
         //获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表(以下仅供参考)//
		 // 商户订单号
		 //String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"),"UTF-8");
		 // 支付宝交易号
		 //String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"),"UTF-8");
		 // 交易状态
		 String trade_status = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"),"UTF-8");//异步通知ID
		 String notify_id=request.getParameter("notify_id");//sign
		 String sign=request.getParameter("sign");
		 if(notify_id!=""&&notify_id!=null){
		 	 if(AlipayNotify.verifyResponse(notify_id).equals("true")){//判断成功之后使用getResponse方法判断是否是支付宝发来的异步通知。
                 if(AlipayNotify.getSignVeryfy(params, sign)){//使用支付宝公钥验签
                 	if(trade_status.equals("TRADE_FINISHED") || trade_status.equals("TRADE_SUCCESS")){
                 		//业务处理
					}
					 return "success";
				 }else{//验证签名失败
					 return "sign fail";
				 }
			 }else{//验证是否来自支付宝的通知失败
				 return "response fail" ;
			 }
		 }else{
			 return "no notify message" ;
		 }
	 }
	 

@RequestMapping(value = "/aliorderPayRefund", method = RequestMethod.POST)
	@ResponseBody
	public ResBean orderPayRefund(){
		AlipayTradeRefundRequest request = new AlipayTradeRefundRequest(); // 统一收单交易退款接口
		AlipayTradeRefundModel model = new AlipayTradeRefundModel();
		model.setOutTradeNo("tradePay000002"); //与预授权转支付商户订单号相同,代表对该笔交易退款
		model.setRefundAmount("0.01");//退款金额
		model.setRefundReason("预授权退款测试");//退款理由
		model.setOutRequestNo("refund0000001");//标识一次退款请求,同一笔交易多次退款需要保证唯一,如部分退款则此参数必传。
		request.setBizModel(model);
		Map<String, Object> restmap = new HashMap<>();// 返回支付宝退款信息
		//实例化客户端
		AlipayClient alipayClient = new DefaultAlipayClient(URL, APP_ID, APP_PRIVATE_KEY, FORMAT, CHARSET, ALIPAY_PUBLIC_KEY, "RSA2");
		try {
			AlipayTradeRefundResponse alipayResponse = alipayClient.sdkExecute(request);
			if (alipayResponse.isSuccess()) {
				logger.info("退款成功");
				restmap.put("out_trade_no", alipayResponse.getOutTradeNo());
				restmap.put("trade_no", alipayResponse.getTradeNo());
				restmap.put("buyer_logon_id", alipayResponse.getBuyerLogonId());// 用户的登录id
				restmap.put("gmt_refund_pay", alipayResponse.getGmtRefundPay()); // 退款支付时间
				restmap.put("buyer_user_id", alipayResponse.getBuyerUserId());// 买家在支付宝的用户id
				restmap.put("refundType", "success");
			} else {
				logger.info("退款失败");
				restmap.put("refundType", "fail");
				return new ResBean(0,"请求失败",restmap);;
			}
		} catch (AlipayApiException e) {
			e.printStackTrace();
		}
		return new ResBean(1,"请求成功",restmap);;
	}
	 
	 private String alipay(PageData pd){
		 
		    //实例化客户端
			AlipayClient alipayClient = new DefaultAlipayClient(URL, APP_ID, APP_PRIVATE_KEY, FORMAT, CHARSET, ALIPAY_PUBLIC_KEY, "RSA2");
			//实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay
			AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
			//SDK已经封装掉了公共参数,这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
			AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
			model.setBody(pd.getString("BODY")); //商品描述
			model.setSubject(pd.getString("TITLE")); // 商品标题
			model.setOutTradeNo(OrderIdUtil.getOrderId()); //订单号
			model.setTimeoutExpress("30m");//	该笔订单允许的最晚付款时间,逾期将关闭交易。取值范围:1m~15d。m-分钟,h-小时,d-天,1c-当天(1c-当天的情况下,无论交易何时创建,都在0点关闭)。 该参数数值不接受小数点, 如 1.5h,可转换为 90m。注:若为空,则默认为15d。
			model.setTotalAmount(pd.getString("TOTAL_AMOUNT"));//订单总金额,单位为元,精确到小数点后两位,取值范围[0.01,100000000]
			model.setProductCode("QUICK_MSECURITY_PAY");//销售产品码,商家和支付宝签约的产品码,为固定值QUICK_MSECURITY_PAY
			request.setBizModel(model);
			request.setNotifyUrl(NOTIFY_URL);//支付宝异步调用后台的url
			try {
			        //这里和普通的接口调用不同,使用的是sdkExecute
			        AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
			       // System.out.println(response.getBody());//就是orderString 可以直接给客户端请求,无需再做处理。
			        return response.getBody();  
			} catch (AlipayApiException e) {
			        e.printStackTrace();
			        return ""; 
			}
		
		 
	 }
}

3.关于回调方法AlipayCallBack()

当支付完成后,支付宝会调用notify_url中的地址执行,就是后台中的AlipayCallBack方法,这里会用到支付宝的一些类

AlipayCore、AlipayNotify、Base64、RSA,这些在支付宝中都能找到,AlipayConfig(配置类)这个可以根据自己格式需求做,不一定一定要封装成类。

AlipayCore

package com.shanreal.controller.app.saunaroom.pay;

import java.io.FileWriter;
import java.io.IOException;
import java.util.*;

public class AlipayCore {
    /**
     *  
     * 除去数组中的空值和签名参数
     *
     * @param sArray 签名参数组
     * @return 去掉空值与签名参数后的新签名参数组
     */
    public static Map<String, String> paraFilter(Map<String, String> sArray) {
        Map<String, String> result = new HashMap<String, String>();
        if (sArray == null || sArray.size() <= 0) {
            return result;
        }
        for (String key : sArray.keySet()) {
            String value = sArray.get(key);
            if (value == null || value.equals("") || key.equalsIgnoreCase("sign")
                    || key.equalsIgnoreCase("sign_type")) {
                continue;
            }
            result.put(key, value);
        }
        return result;
    }

    /**
     *  
     *      * 把数组所有元素,并按照“参数=参数值”的模式用“&”字符拼接成字符串
     *      * @param params 需要参与字符拼接的参数组
     *      * @param sorts   是否需要排序 true 或者 false
     *      * @return 拼接后字符串
     *      
     */
    public static String createLinkString(Map<String, String> params) {
        List<String> keys = new ArrayList<String>(params.keySet());
        Collections.sort(keys);

        String prestr = "";
        for (int i = 0; i < keys.size(); i++) {
            String key = keys.get(i);
            String value = params.get(key);
            if (i == keys.size() - 1) {//拼接时,不包括最后一个&字符
                prestr = prestr + key + "=" + value;
            } else {
                prestr = prestr + key + "=" + value + "&";
            }
        }
        return prestr;
    }

    /**
     *  
     *      * 写日志,方便测试(看网站需求,也可以改成把记录存入数据库)
     *      * @param sWord 要写入日志里的文本内容
     *      
     */
    public static void logResult(String sWord, String filename) {
        FileWriter writer = null;
        try {
            writer = new FileWriter(AlipayConfig.log_path + "alipay_log_" + System.currentTimeMillis() + filename + ".txt");
            writer.write(sWord);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (writer != null) {
                try {
                    writer.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }


            }
        }

    }

}

AlipayNotify

package com.shanreal.controller.app.saunaroom.pay;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Map;

/* *
 *类名:AlipayNotify
 *功能:支付宝通知处理类
 *详细:处理支付宝各接口通知返回
 *版本:3.3
 *日期:2012-08-17
 *说明:
 *以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。
 *该代码仅供学习和研究支付宝接口使用,只是提供一个参考

 *************************注意*************************
 *调试通知返回时,可查看或改写log日志的写入TXT里的数据,来检查通知返回是否正常
 */
public class AlipayNotify {

    /**
     * 支付宝消息验证地址
     */
    private static final String HTTPS_VERIFY_URL = "https://mapi.alipay.com/gateway.do?service=notify_verify&";

    /**
     * 验证消息是否是支付宝发出的合法消息
     * @param params 通知返回来的参数数组
     * @return 验证结果
     */
    public static boolean verify(Map<String, String> params) {

        //判断responsetTxt是否为true,isSign是否为true
        //responsetTxt的结果不是true,与服务器设置问题、合作身份者ID、notify_id一分钟失效有关
        //isSign不是true,与安全校验码、请求时的参数格式(如:带自定义参数等)、编码格式有关
        String responseTxt = "false";
        if(params.get("notify_id") != null) {
            String notify_id = params.get("notify_id");
            responseTxt = verifyResponse(notify_id);
        }
        String sign = "";
        if(params.get("sign") != null) {sign = params.get("sign");}
        boolean isSign = getSignVeryfy(params, sign);

        //写日志记录(若要调试,请取消下面两行注释)
        //String sWord = "responseTxt=" + responseTxt + "\n isSign=" + isSign + "\n 返回回来的参数:" + AlipayCore.createLinkString(params);
        //AlipayCore.logResult(sWord);

        if (isSign && responseTxt.equals("true")) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 根据反馈回来的信息,生成签名结果
     * @param Params 通知返回来的参数数组
     * @param sign 比对的签名结果
     * @return 生成的签名结果
     */
    public static boolean getSignVeryfy(Map<String, String> Params, String sign) {
        //过滤空值、sign与sign_type参数
        Map<String, String> sParaNew = AlipayCore.paraFilter(Params);
        //获取待签名字符串
        String preSignStr = AlipayCore.createLinkString(sParaNew);
        //获得签名验证结果
        boolean isSign = false;
        if(AlipayConfig.sign_type.equals("RSA")){
            isSign = RSA.verify(preSignStr, sign, AlipayConfig.alipay_public_key, AlipayConfig.input_charset);
        }
        return isSign;
    }

    /**
     * 获取远程服务器ATN结果,验证返回URL
     * @param notify_id 通知校验ID
     * @return 服务器ATN结果
     * 验证结果集:
     * invalid命令参数不对 出现这个错误,请检测返回处理中partner和key是否为空
     * true 返回正确信息
     * false 请检查防火墙或者是服务器阻止端口问题以及验证时间是否超过一分钟
     */
    public static String verifyResponse(String notify_id) {
        //获取远程服务器ATN结果,验证是否是支付宝服务器发来的请求

        String partner = AlipayConfig.partner;
        String veryfy_url = HTTPS_VERIFY_URL + "partner=" + partner + "¬ify_id=" + notify_id;

        return checkUrl(veryfy_url);
    }

    /**
     * 获取远程服务器ATN结果
     * @param urlvalue 指定URL路径地址
     * @return 服务器ATN结果
     * 验证结果集:
     * invalid命令参数不对 出现这个错误,请检测返回处理中partner和key是否为空
     * true 返回正确信息
     * false 请检查防火墙或者是服务器阻止端口问题以及验证时间是否超过一分钟
     */
    private static String checkUrl(String urlvalue) {
        String inputLine = "";

        try {
            URL url = new URL(urlvalue);
            HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
            BufferedReader in = new BufferedReader(new InputStreamReader(urlConnection
                    .getInputStream()));
            inputLine = in.readLine().toString();
        } catch (Exception e) {
            e.printStackTrace();
            inputLine = "";
        }

        return inputLine;
    }
}

RSA

package com.shanreal.controller.app.saunaroom.pay;

import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

public class RSA {
    public static final String SIGN_ALGORITHMS = "SHA1WithRSA";

    /*** RSA签名* @param content 待签名数据* @param privateKey 商户私钥* @param input_charset 编码格式* @return 签名值*/
    public static String sign(String content, String privateKey, String input_charset) {
        try {
            PKCS8EncodedKeySpec priPKCS8
                    = new PKCS8EncodedKeySpec(Base64.decode(privateKey));
            KeyFactory keyf
                    = KeyFactory.getInstance("RSA");
            PrivateKey priKey
                    = keyf.generatePrivate(priPKCS8);
            java.security.Signature signature = java.security.Signature
                    .getInstance(SIGN_ALGORITHMS);
            signature.initSign(priKey);
            signature.update(content.getBytes(input_charset));
            byte[] signed = signature.sign();

            return Base64.encode(signed);
        } catch (Exception e)
        {
            e.printStackTrace();
        }

        return null;
    }

    /*** RSA验签名检查* @param content 待签名数据* @param sign 签名值* @param alipay_public_key 支付宝公钥* @param input_charset 编码格式* @return 布尔值*/
    public static boolean verify(String content, String sign, String alipay_public_key, String input_charset) {
        try {
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            byte[] encodedKey = Base64.decode(alipay_public_key);
            PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));
            java.security.Signature signature = java.security.Signature.getInstance(SIGN_ALGORITHMS);
            signature.initVerify(pubKey);
            signature.update(content.getBytes(input_charset));
            boolean bverify = signature.verify(Base64.decode(sign));
            return bverify;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }
}

Base64

package com.shanreal.controller.app.saunaroom.pay;

public final class Base64 {

    private static final int BASELENGTH = 128;
    private static final int LOOKUPLENGTH = 64;
    private static final int TWENTYFOURBITGROUP = 24;
    private static final int EIGHTBIT = 8;
    private static final int SIXTEENBIT = 16;
    private static final int FOURBYTE = 4;
    private static final int SIGN = -128;
    private static char PAD = '=';
    private static byte[] base64Alphabet = new byte[BASELENGTH];
    private static char[] lookUpBase64Alphabet = new char[LOOKUPLENGTH];

    static {
        for (int i = 0; i < BASELENGTH; ++i) {
            base64Alphabet[i] = -1;
        }
        for (int i = 'Z'; i >= 'A'; i--) {
            base64Alphabet[i] = (byte) (i - 'A');
        }
        for (int i = 'z'; i >= 'a'; i--) {
            base64Alphabet[i] = (byte) (i - 'a' + 26);
        }

        for (int i = '9'; i >= '0'; i--) {
            base64Alphabet[i] = (byte) (i - '0' + 52);
        }

        base64Alphabet['+'] = 62;
        base64Alphabet['/'] = 63;

        for (int i = 0; i <= 25; i++) {
            lookUpBase64Alphabet[i] = (char) ('A' + i);
        }

        for (int i = 26, j = 0; i <= 51; i++, j++) {
            lookUpBase64Alphabet[i] = (char) ('a' + j);
        }

        for (int i = 52, j = 0; i <= 61; i++, j++) {
            lookUpBase64Alphabet[i] = (char) ('0' + j);
        }
        lookUpBase64Alphabet[62] = (char) '+';
        lookUpBase64Alphabet[63] = (char) '/';

    }

    private static boolean isWhiteSpace(char octect) {
        return (octect == 0x20 || octect == 0xd || octect == 0xa || octect == 0x9);
    }

    private static boolean isPad(char octect) {
        return (octect == PAD);
    }

    private static boolean isData(char octect) {
        return (octect < BASELENGTH && base64Alphabet[octect] != -1);
    }

    /**
     * Encodes hex octects into Base64
     *
     * @param binaryData
     *            Array containing binaryData
     * @return Encoded Base64 array
     */
    public static String encode(byte[] binaryData) {

        if (binaryData == null) {
            return null;
        }

        int lengthDataBits = binaryData.length * EIGHTBIT;
        if (lengthDataBits == 0) {
            return "";
        }

        int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP;
        int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP;
        int numberQuartet = fewerThan24bits != 0 ? numberTriplets + 1
                : numberTriplets;
        char encodedData[] = null;

        encodedData = new char[numberQuartet * 4];

        byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0;

        int encodedIndex = 0;
        int dataIndex = 0;

        for (int i = 0; i < numberTriplets; i++) {
            b1 = binaryData[dataIndex++];
            b2 = binaryData[dataIndex++];
            b3 = binaryData[dataIndex++];

            l = (byte) (b2 & 0x0f);
            k = (byte) (b1 & 0x03);

            byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2)
                    : (byte) ((b1) >> 2 ^ 0xc0);
            byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4)
                    : (byte) ((b2) >> 4 ^ 0xf0);
            byte val3 = ((b3 & SIGN) == 0) ? (byte) (b3 >> 6)
                    : (byte) ((b3) >> 6 ^ 0xfc);

            encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
            encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)];
            encodedData[encodedIndex++] = lookUpBase64Alphabet[(l << 2) | val3];
            encodedData[encodedIndex++] = lookUpBase64Alphabet[b3 & 0x3f];
        }

        // form integral number of 6-bit groups
        if (fewerThan24bits == EIGHTBIT) {
            b1 = binaryData[dataIndex];
            k = (byte) (b1 & 0x03);

            byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2)
                    : (byte) ((b1) >> 2 ^ 0xc0);
            encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
            encodedData[encodedIndex++] = lookUpBase64Alphabet[k << 4];
            encodedData[encodedIndex++] = PAD;
            encodedData[encodedIndex++] = PAD;
        } else if (fewerThan24bits == SIXTEENBIT) {
            b1 = binaryData[dataIndex];
            b2 = binaryData[dataIndex + 1];
            l = (byte) (b2 & 0x0f);
            k = (byte) (b1 & 0x03);

            byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2)
                    : (byte) ((b1) >> 2 ^ 0xc0);
            byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4)
                    : (byte) ((b2) >> 4 ^ 0xf0);

            encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
            encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)];
            encodedData[encodedIndex++] = lookUpBase64Alphabet[l << 2];
            encodedData[encodedIndex++] = PAD;
        }

        return new String(encodedData);
    }

    /**
     * Decodes Base64 data into octects
     *
     * @param encoded
     *            string containing Base64 data
     * @return Array containind decoded data.
     */
    public static byte[] decode(String encoded) {

        if (encoded == null) {
            return null;
        }

        char[] base64Data = encoded.toCharArray();
        // remove white spaces
        int len = removeWhiteSpace(base64Data);

        if (len % FOURBYTE != 0) {
            return null;// should be divisible by four
        }

        int numberQuadruple = (len / FOURBYTE);

        if (numberQuadruple == 0) {
            return new byte[0];
        }

        byte decodedData[] = null;
        byte b1 = 0, b2 = 0, b3 = 0, b4 = 0;
        char d1 = 0, d2 = 0, d3 = 0, d4 = 0;

        int i = 0;
        int encodedIndex = 0;
        int dataIndex = 0;
        decodedData = new byte[(numberQuadruple) * 3];

        for (; i < numberQuadruple - 1; i++) {

            if (!isData((d1 = base64Data[dataIndex++]))
                    || !isData((d2 = base64Data[dataIndex++]))
                    || !isData((d3 = base64Data[dataIndex++]))
                    || !isData((d4 = base64Data[dataIndex++]))) {
                return null;
            }// if found "no data" just return null

            b1 = base64Alphabet[d1];
            b2 = base64Alphabet[d2];
            b3 = base64Alphabet[d3];
            b4 = base64Alphabet[d4];

            decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
            decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
            decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);
        }

        if (!isData((d1 = base64Data[dataIndex++]))
                || !isData((d2 = base64Data[dataIndex++]))) {
            return null;// if found "no data" just return null
        }

        b1 = base64Alphabet[d1];
        b2 = base64Alphabet[d2];

        d3 = base64Data[dataIndex++];
        d4 = base64Data[dataIndex++];
        if (!isData((d3)) || !isData((d4))) {// Check if they are PAD characters
            if (isPad(d3) && isPad(d4)) {
                if ((b2 & 0xf) != 0)// last 4 bits should be zero
                {
                    return null;
                }
                byte[] tmp = new byte[i * 3 + 1];
                System.arraycopy(decodedData, 0, tmp, 0, i * 3);
                tmp[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
                return tmp;
            } else if (!isPad(d3) && isPad(d4)) {
                b3 = base64Alphabet[d3];
                if ((b3 & 0x3) != 0)// last 2 bits should be zero
                {
                    return null;
                }
                byte[] tmp = new byte[i * 3 + 2];
                System.arraycopy(decodedData, 0, tmp, 0, i * 3);
                tmp[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
                tmp[encodedIndex] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
                return tmp;
            } else {
                return null;
            }
        } else { // No PAD e.g 3cQl
            b3 = base64Alphabet[d3];
            b4 = base64Alphabet[d4];
            decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
            decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
            decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);

        }

        return decodedData;
    }

    /**
     * remove WhiteSpace from MIME containing encoded Base64 data.
     *
     * @param data
     *            the byte array of base64 data (with WS)
     * @return the new length
     */
    private static int removeWhiteSpace(char[] data) {
        if (data == null) {
            return 0;
        }

        // count characters that's not whitespace
        int newSize = 0;
        int len = data.length;
        for (int i = 0; i < len; i++) {
            if (!isWhiteSpace(data[i])) {
                data[newSize++] = data[i];
            }
        }
        return newSize;
    }
}
AlipayConfig
package com.shanreal.controller.app.saunaroom.pay;

public class AlipayConfig {
    // 合作身份者ID,签约账号,以2088开头由16位纯数字组成的字符串,查看地址:https://b.alipay.com/order/pidAndKey.html
    public static String partner = "xxxxxxxxxxxxxxxx";

    //商户的私钥,需要PKCS8格式,RSA公私钥生成:https://doc.open.alipay.com/doc2/detail.htm?spm=a219a.7629140.0.0.nBDxfy&treeId=58&articleId=103242&docType=1
    public static String private_key = "xxxxxxx";

    //沙箱环境
    //public static String private_key="xxxxxxxxx" ;

    // 收款支付宝账号,以2088开头由16位纯数字组成的字符串,一般情况下收款账号就是签约账号
    public static String seller_id = "xxxxxxxxxxxxx" ;

    // 支付宝的公钥,查看地址:https://b.alipay.com/order/pidAndKey.htm
    public static String alipay_public_key  = "xxxxxxxxxxxxxxxx";

    // 调试用,创建TXT日志文件夹路径
    public static String log_path = "D:\\";

    // 字符编码格式 目前支持 gbk 或 utf-8
    public static String input_charset = "utf-8";

    // 签名方式 不需修改
    public static String sign_type = "RSA";

    // 支付类型 ,无需修改
    public static String payment_type = "1";

    // 调用的接口名,无需修改
    public static String service = "create_direct_pay_by_user";

    //支付宝回调地址
    public static String notify_url = "http://xxxxxxxx/xxxxxxx/app/alipayNotify" ;
}

转载:

支付回调:https://blog.csdn.net/xingzizhanlan/article/details/52709899

支付集成:https://blog.csdn.net/harvic880925/article/details/49779061

没有更多推荐了,返回首页