支付宝有密退款MD5和RSA两种方式

前面我已经做了手机端和电脑端的支付,这两天整了一下退款,万万没想到啊,一样的道理我却走了半天弯路麻蛋啊,MD5和RSA两种方式我全试了,单笔数据集detail_data写对了就好使了。。。,多谢支付宝接入人员的提醒

先看一下 官方文档,技术人员给我的,很有用的:https://docs.open.alipay.com/62/104744

说的已经很明白了,不可为空的你就传参就是了,关于代码方面有不懂的看我          支付宝手机网页唤醒app支付     逻辑代码以及log走的流程和参数都在这,

我只说需要改动的地方,后续会提供demo,还有记得先支付,无支付,不退款

MD5方式:

AlipayConfig中调用的接口名:public static String service = "refund_fastpay_by_platform_pwd";

并且加一个    //退款日期 时间格式 yyyy-MM-dd HH:mm:ss——public static String refund_date = UtilDate.getDateFormatter(); 后续会用到

index  退款界面和支付界面当然不一样

<%
/* *
 *功能:支付宝即时到账交易接口调试入口页面
 *版本:3.4
 *日期:2016-03-08
 *说明:
 *以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。
 **********************************************
 */
%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>



    
    支付宝即时到账批量退款有密接口




    
请扫码关注
接收重要信息
即时到账批量退款有密接口(refund_fastpay_by_platform_pwd)
支付宝即时到账批量退款有密接口快速通道
退款批次号:

注意:退款批次号(batch_no),必填(时间格式是yyyyMMddHHmmss+数字或者字母)
退款笔数:

注意:退款笔数(batch_num),必填(值为您退款的笔数,取值1~1000间的整数)
退款详细数据:

注意:退款详细数据(WIDdetail_data),必填(支付宝交易号^退款金额^备注)多笔请用#隔开

话说我就不知道那个batch_no退款批次号是什么,其实是自己定义的,还以为是订单号。。。按他说的格式定义就行,还需要退款笔数和单笔数据集detail_data,这里我已经给出了示范

然后也是请求到alipayapi

<%
		请求参数//

        //批次号,必填,格式:当天日期[8位]+序列号[3至24位],如:201603081000001

        String batch_no = new String(request.getParameter("WIDbatch_no").getBytes("ISO-8859-1"),"UTF-8");

        //退款笔数,必填,参数detail_data的值中,“#”字符出现的数量加1,最大支持1000笔(即“#”字符出现的数量999个)

        String batch_num = new String(request.getParameter("WIDbatch_num").getBytes("ISO-8859-1"),"UTF-8");

        //退款详细数据,必填,格式(支付宝交易号^退款金额^备注),多笔请用#隔开
        String detail_data = new String(request.getParameter("WIDdetail_data").getBytes("ISO-8859-1"),"UTF-8");

		
		
		//
		
		//把请求参数打包成数组
		Map sParaTemp = new HashMap();
		sParaTemp.put("service", AlipayConfig.service);
       	 	sParaTemp.put("partner", AlipayConfig.partner);
        	sParaTemp.put("_input_charset", AlipayConfig.input_charset);
        	sParaTemp.put("MD5", AlipayConfig.sign_type);
		sParaTemp.put("notify_url", AlipayConfig.notify_url);
		sParaTemp.put("seller_user_id", AlipayConfig.seller_user_id);
		sParaTemp.put("refund_date", AlipayConfig.refund_date);
		sParaTemp.put("batch_no", batch_no);
		sParaTemp.put("batch_num", batch_num);
		sParaTemp.put("detail_data", detail_data);
		
		//建立请求
		String sHtmlText = AlipaySubmit.buildRequest(sParaTemp,"get","确认");
		out.println(sHtmlText);
	%>

该打包的打包,就按文档需求的那个整,然后请求buildRequest去签名并且发送链接就行了,其他都一样

话说我走的弯路在哪呢,没找到一个好的文档所以就没有规范,然后我开始用的RSA方式,并且那个detail_data格式不对,大家不要和我犯一样的错误哦,正确的单笔退款方式是:订单号也就是流水号也就是交易号^钱数^退款说明,这个确实挺重要,卡个跟头

支付宝有密退款MD5和RSA两种方式_第1张图片


支付宝有密退款MD5和RSA两种方式_第2张图片

支付宝有密退款MD5和RSA两种方式_第3张图片




RSA方式

这个方式麻烦的地方在于先生成公匙私匙,好吧,说说怎么生成的吧

生成工具,很好使的生成工具,关于这方面的说明也不少了,直接去这看看吧http://blog.csdn.net/zhouhui520w/article/details/49885135,说的挺详细的,注意pkcs8格式的生成并且无空格无回车,将公匙上传到支付宝中,我相信你能上传上去,有一步是私匙验证公匙是否匹配,不用管它,前面做对了就一定是匹配的

AlipayConfig中我贴一下代码:

public class AlipayConfig {
	
//↓↓↓↓↓↓↓↓↓↓请在这里配置您的基本信息↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

	// 合作身份者ID,签约账号,以2088开头由16位纯数字组成的字符串,查看地址:https://b.alipay.com/order/pidAndKey.htm
	public static String partner = "";
	
	// 收款支付宝账号,以2088开头由16位纯数字组成的字符串,一般情况下收款账号就是签约账号
	public static String seller_user_id = partner;

	// 商户的私钥,需要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 = 
"MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAt97DHzJ+6ETQ8AY/k31hrF9L1wZVr/kpiF2gnP/sOAIZqNioR6sZMh54kdBZB8+jWjOhpMHZfqJ3JI2A+5mCs0tUl4rBpWmww8OjEGRoixamCc6Hsr9/Gn4pMUMURtVMEXdHeLNQPr/xNd7dbYKxRYiGoCZAVAgMBAAECgYEArdX6OmhnpxLCBdrNZD0B/icLBU1WqtScpJAIMQZLrzcN+XEzKiN4JKxDyWLN7PIHBoIpIDX9a0OLO3uDfcVqJ1eL1hMPDsvlxV72FWzUlkFZcBdVgm800CjB3F2z414zPNGWbo2/RQOp9JkEnnF0ekdOqdMBufoQk3W9ofv/UMECQQD7KXatki/rB6HxDXY3tjg91zE69hTJKvYLN8Cq/rkrAoT5XU2fcwg2CyRXVGgc+DlS+zKf5Bchcp2i6yQK+A3xAkEA1VAwWCCv6WE+Rrbe4aLkWc6p+57E90LPo3a6u96aCIBeZT0oTp2lXlQ4gmWCH6jFeeQHxOUJ8FvIWL+hLx0QZQI/LSFGMeoSsiis8KN6mogjkvkX34BYO818aIecFx2uKAxL2ILrb7s7vnpCDW8dRhdUNZTtg814Woo9yQh3cYEhAkEAukZyUSMKOtTuWzYqYAOtQTeVfONiwUGYrPhrjM+Q10eyJtpHLo+/7yXAyy31ecwZ1p1oo2oXScv8onOFP+0zeQJBAMGyDyZqBcbzrUVFRbSAMvno8GqEflNuPJv4/uiy5pI0qHn0GA/dmab/lUX7BA4dsXyoBoRHyheeYgo9J0lwUtQ=";
	
	// 支付宝公钥,查看地址:https://b.alipay.com/order/pidAndKey.htm 
	public static String alipay_public_key  = 
"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDRSCwhfuhE0PAGP5N9YaxfS9cGVa/5KYhdoJz/7DgCGajYqEerGTIeeJHQWQfPo1ozoaTB2X6idySNgPuZgrNLVJeKwaVpsMPDoxBkaIsWpgnOh7K/fxp+KTFDFEbVTBF3R3izUD6/8TXe3W2CsUWIhqAmQFQIDAQAB";

	// 服务器异步通知页面路径  需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
	public static String notify_url = "http://域名/Refund/jsp/notify_url.jsp";

	// 页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
	public static String return_url = "http://域名/Refund/jsp/return_url.jsp";

	// 签名方式
	public static String sign_type = "RSA";
	
	// 调试用,创建TXT日志文件夹路径,见AlipayCore.java类中的logResult(String sWord)打印方法。
	public static String log_path = "C:\\";
		
	// 字符编码格式 目前支持 gbk 或 utf-8
	public static String input_charset = "utf-8";
		
	 //退款日期 时间格式 yyyy-MM-dd HH:mm:ss
    public static String refund_date = UtilDate.getDateFormatter();
		
	// 调用的接口名,无需修改
	public static String service = "refund_fastpay_by_platform_pwd";


//↑↑↑↑↑↑↑↑↑↑请在这里配置您的基本信息↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑

}

上面的信息形式是正确的,签名方式是RSA,将公匙和pkcs8私匙上传,要无空格无回车,再贴一下RSA.java

package com.alipay.sign;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.Cipher;

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 ali_public_key 支付宝公钥
	* @param input_charset 编码格式
	* @return 布尔值
	*/
	public static boolean verify(String content, String sign, String ali_public_key, String input_charset)
	{
		try 
		{
			KeyFactory keyFactory = KeyFactory.getInstance("RSA");
	        byte[] encodedKey = Base64.decode(ali_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;
	}
	
	/**
	* 解密
	* @param content 密文
	* @param private_key 商户私钥
	* @param input_charset 编码格式
	* @return 解密后的字符串
	*/
	public static String decrypt(String content, String private_key, String input_charset) throws Exception {
        PrivateKey prikey = getPrivateKey(private_key);

        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, prikey);

        InputStream ins = new ByteArrayInputStream(Base64.decode(content));
        ByteArrayOutputStream writer = new ByteArrayOutputStream();
        //rsa解密的字节大小最多是128,将需要解密的内容,按128位拆开解密
        byte[] buf = new byte[128];
        int bufl;

        while ((bufl = ins.read(buf)) != -1) {
            byte[] block = null;

            if (buf.length == bufl) {
                block = buf;
            } else {
                block = new byte[bufl];
                for (int i = 0; i < bufl; i++) {
                    block[i] = buf[i];
                }
            }

            writer.write(cipher.doFinal(block));
        }

        return new String(writer.toByteArray(), input_charset);
    }

	
	/**
	* 得到私钥
	* @param key 密钥字符串(经过base64编码)
	* @throws Exception
	*/
	public static PrivateKey getPrivateKey(String key) throws Exception {

		byte[] keyBytes;
		
		keyBytes = Base64.decode(key);
		
		PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
		
		KeyFactory keyFactory = KeyFactory.getInstance("RSA");
		
		PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
		
		return privateKey;
	}
}

这就是RSA的加密方式了,需要Base64.java工具类有点长就不贴了,在demo中有,其他的都一样了

退款两种加密方式的demo 对照着看一下就懂了,我相信你可以的

这个demo忘了在哪找的了,就按这个做就行,真是没做过就不会,做过就很简单

你可能感兴趣的:(pay)