您的位置:首页 > 其它

新浪支付接口对接的总结

2016-12-23 11:43 148 查看
最近需要对接新浪支付,看到一篇文章感觉不错,先转载参考。

原文:http://blog.csdn.net/lzlovez/article/details/51167286

1.接口介入方式

这种接口介入的方式,各大平台都差不多的,支付宝啊,微信支付啊,融宝支付啊,银盈通啊。都是系统必要的参数,和接口需要的参数,拼一起然互加密。

新浪支付生成 sign 的方式,签名的方式可以是 RSA 的加密方式和 MD5 的加密的方式,不过新浪推荐的是MD5的加密方式,但是给的demo里面是RSA的方式,所有自己用的也会是RSA的加密方式。

简单的例子 创建激活会员

[java] view
plain copy







public static SinaPayResponse createActivateMember(Map<String, Object> data) throws Exception {

SinaPayResponse response = new SinaPayResponse();

if (data == null || data.size() == 0) {

response.setCode(ResponceCodeEnum.MissingParameter.getCode());

response.setErrorMsg("传入的参数为空");

return response;

}

// 用户标识信息

if (data.get("identity_id") == null || data.get("identity_id").equals("")) {

response.setCode(ResponceCodeEnum.MissingParameter.getCode());

response.setErrorMsg("传入的参数:用户标识信息(identity_id)为空");

return response;

}

Map<String, Object> map = new HashMap<String, Object>();

map.put("identity_id", data.get("identity_id"));

// 用户标识类型,目前只支持UID

map.put("identity_type", SinaPayConfig.IDENTITY_TYPE);

// 1: 个人会员;2: 企业会员。默认是1

if (data.get("member_type") != null && !data.get("member_type").equals("")) {

map.put("member_type", data.get("member_type"));

}

// 系统参数

map.put("service", SinaPayConfig.CREATE_ACTIVATE_MEMBER);

String str = SinaUtils.createLinkString(map, true);

String res = "";

try {

res = CallServiceUtil.sendPost(SinaPayConfig.MEMBER_TSET_URL, str);

} catch (Exception e) {

response.setCode(ResponceCodeEnum.connectionTimedOut.getCode());

response.setErrorMsg("请求超时");

return response;

}

String result = URLDecoder.decode(res, SinaUtils.CHARSET);

Map<String, String> resultMap = GsonUtil.fronJson2Map(result);

if (SinaPayConfig.APPLY_SUCCESS.equals(resultMap.get("response_code"))) { // 成功

response.setCode(ResponceCodeEnum.success.getCode());

response.setErrorMsg("请求成功");

response.setResponseMap(resultMap);

return response;

} else {

response.setCode(ResponceCodeEnum.requestFails.getCode());

response.setErrorMsg(resultMap.get("response_message"));

response.setResponseMap(resultMap);

return response;

}

}

String str = SinaUtils.createLinkString(map, true); 这一步是在吧我们需要的参数,包括 系统的参数,也包括接口需要的参数,生成 待签名的 字符串

[java] view
plain copy







/**

* 把参数重新排序下

*

* @param map

* @param b

* @return

* @throws Exception

*/

public static String createLinkString(Map<String, Object> map, boolean encode) throws Exception {

map.put("version", SinaPayConfig.VERSION);

map.put("request_time", SinaTimeUtils.getTime());

map.put("partner_id", SinaPayConfig.PARTNER_ID);

map.put("_input_charset", SinaUtils.CHARSET);

String content = SinaUtils.getContent(map);

map.put("sign", SinaUtils.getSign(content));

map.put("sign_type", SinaPayConfig.SIGN_TYPE);

List<String> keys = new ArrayList<String>(map.keySet());

Collections.sort(keys);

String prestr = "";

String charset = (String) map.get("_input_charset");

for (int i = 0; i < keys.size(); i++) {

String key = keys.get(i);

String value = (String) map.get(key);

if (encode) {

try {

value = URLEncoder.encode(URLEncoder.encode(value, charset), charset);

} catch (UnsupportedEncodingException e) {

e.printStackTrace();

}

}

if (i == keys.size() - 1) {

prestr = prestr + key + "=" + value;

} else {

prestr = prestr + key + "=" + value + "&";

}

}

return prestr;

}

res = CallServiceUtil.sendPost(SinaPayConfig.MEMBER_TSET_URL, str); 这一步是在请求接口,返回结果

[java] view
plain copy







public static String sendPost(String url, String param) {

PrintWriter out = null;

BufferedReader in = null;

String result = "";

try {

URL realUrl = new URL(url);

URLConnection conn = realUrl.openConnection();

conn.setRequestProperty("accept", "*/*");

conn.setRequestProperty("connection", "Keep-Alive");

conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");

conn.setDoOutput(true);

conn.setDoInput(true);

out = new PrintWriter(conn.getOutputStream());

out.print(param);

out.flush();

in = new BufferedReader(new InputStreamReader(conn.getInputStream()));

String line;

while ((line = in.readLine()) != null) {

result += line;

}

} catch (Exception e) {

System.out.println("POST请求异常:" + e);

e.printStackTrace();

} finally {

try {

if (out != null) {

out.close();

}

if (in != null) {

in.close();

}

} catch (IOException ex) {

ex.printStackTrace();

}

}

return result;

}

这个时候返回的结果是经过URLencode的代码,所以需要 处理下

String result = URLDecoder.decode(res, SinaUtils.CHARSET);

Map<String, String> resultMap = GsonUtil.fronJson2Map(result); 这一步是在把得到的结果的传,转成Map

[java] view
plain copy







public static <T> T fronJson2Map(String json) {

return gson.fromJson(json, new TypeToken<Map<String, String>>() {

}.getType());

}

大部分的接口都是这样的调用的方式,有些接口需要的一些参数涉及用户的隐私,所以需要对参数进行RSA加密

[java] view
plain copy







/**

* 比如一些参数需要加密的话

*

* @param string 待加密的信息

* @throws Exception

* @throws

*/

public static String getRSAEncodeDoc(String data) throws Exception {

byte[] data_byte = RSA.encryptByPublicKey(data.getBytes(CHARSET), SinaPayConfig.ENCRYPT);

return Base64.encode(data_byte);

}

这个是 RSA 的类

[java] view
plain copy







package com.sinapay.util;

import java.io.ByteArrayOutputStream;

import java.io.UnsupportedEncodingException;

import java.security.InvalidKeyException;

import java.security.Key;

import java.security.KeyFactory;

import java.security.KeyPair;

import java.security.KeyPairGenerator;

import java.security.NoSuchAlgorithmException;

import java.security.PrivateKey;

import java.security.PublicKey;

import java.security.Signature;

import java.security.SignatureException;

import java.security.cert.Certificate;

import java.security.interfaces.RSAPrivateKey;

import java.security.interfaces.RSAPublicKey;

import java.security.spec.PKCS8EncodedKeySpec;

import java.security.spec.X509EncodedKeySpec;

import java.util.HashMap;

import java.util.Map;

import javax.crypto.Cipher;

import org.apache.commons.codec.binary.Base64;

/**

*

* <p>RSA签名,加解密处理核心文件,注意:密钥长度1024</p>

* @author leelun

* @version $Id: RSA.java, v 0.1 2013-11-15 下午2:33:53 lilun Exp $

*/

public class RSA {

/**

* 签名算法

*/

public static final String SIGNATURE_ALGORITHM = "SHA1withRSA";

/**

* 加密算法RSA

*/

public static final String KEY_ALGORITHM = "RSA";

/**

* RSA最大加密明文大小

*/

private static final int MAX_ENCRYPT_BLOCK = 117;

/**

* RSA最大解密密文大小

*/

private static final int MAX_DECRYPT_BLOCK = 128;

/**

* 获取公钥的key

*/

private static final String PUBLIC_KEY = "RSAPublicKey";

/**

* 获取私钥的key

*/

private static final String PRIVATE_KEY = "RSAPrivateKey";

/**

* <p>

* 生成密钥对(公钥和私钥)

* </p>

*

* @return

* @throws Exception

*/

public static Map<String, Object> genKeyPair() throws Exception {

KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);

keyPairGen.initialize(1024);

KeyPair keyPair = keyPairGen.generateKeyPair();

RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();

RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();

Map<String, Object> keyMap = new HashMap<String, Object>(2);

keyMap.put(PUBLIC_KEY, publicKey);

keyMap.put(PRIVATE_KEY, privateKey);

return keyMap;

}

public static void main(String[] args) throws Exception {

Map<String, Object> genKeyPair = genKeyPair();

String base64publicKey = getPublicKey(genKeyPair);

System.out.println("公钥 \n" + base64publicKey);

String base64privateKey = getPrivateKey(genKeyPair);

System.out.println("私钥\n" + base64privateKey);

String passwd = "cat123113";

String charsetName = "utf-8";

String encryptByPublicKey = Base64.encodeBase64String((encryptByPublicKey(

passwd.getBytes(charsetName), base64publicKey)));

System.out.println("加密\n" + encryptByPublicKey);

byte[] decryptByPrivateKey = decryptByPrivateKey(Base64.decodeBase64(encryptByPublicKey),

base64privateKey);

String string = new String(decryptByPrivateKey, "utf-8");

System.out.println("解密后\n" + string);

}

/**

* 签名字符串

*

* @param text

* 需要签名的字符串

* @param privateKey 私钥(BASE64编码)

*

* @param charset

* 编码格式

* @return 签名结果(BASE64编码)

*/

public static String sign(String text, String privateKey, String charset) throws Exception {

byte[] keyBytes = Base64.decodeBase64(privateKey);

PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);

KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);

PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec);

Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);

signature.initSign(privateK);

signature.update(getContentBytes(text, charset));

byte[] result = signature.sign();

return Base64.encodeBase64String(result);

}

public static String sign(String text, PrivateKey privateKey, String charset)

throws SignatureException,

InvalidKeyException {

try {

Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);

signature.initSign(privateKey);

signature.update(getContentBytes(text, charset));

byte[] result = signature.sign();

return Base64.encodeBase64String(result);

} catch (NoSuchAlgorithmException e) {

//不可能发生,

return null;

}

}

/**

* 签名字符串

*

* @param text

* 需要签名的字符串

* @param sign

* 客户签名结果

* @param publicKey

* 公钥(BASE64编码)

* @param charset

* 编码格式

* @return 验签结果

*/

public static boolean verify(String text, String sign, String publicKey, String charset)

throws Exception {

byte[] keyBytes = Base64.decodeBase64(publicKey);

X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);

KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);

PublicKey publicK = keyFactory.generatePublic(keySpec);

Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);

signature.initVerify(publicK);

signature.update(getContentBytes(text, charset));

return signature.verify(Base64.decodeBase64(sign));

}

/**

* <P>

* 私钥解密

* </p>

*

* @param encryptedData 已加密数据

* @param privateKey 私钥(BASE64编码)

* @return

* @throws Exception

*/

public static byte[] decryptByPrivateKey(byte[] encryptedData, String privateKey)

throws Exception {

byte[] keyBytes = Base64.decodeBase64(privateKey);

PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);

KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);

Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);

Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());

cipher.init(Cipher.DECRYPT_MODE, privateK);

int inputLen = encryptedData.length;

ByteArrayOutputStream out = new ByteArrayOutputStream();

int offSet = 0;

byte[] cache;

int i = 0;

// 对数据分段解密

while (inputLen - offSet > 0) {

if (inputLen - offSet > MAX_DECRYPT_BLOCK) {

cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);

} else {

cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);

}

out.write(cache, 0, cache.length);

i++;

offSet = i * MAX_DECRYPT_BLOCK;

}

byte[] decryptedData = out.toByteArray();

out.close();

return decryptedData;

}

/**

* <p>

* 公钥解密

* </p>

*

* @param encryptedData 已加密数据

* @param publicKey 公钥(BASE64编码)

* @return

* @throws Exception

*/

public static byte[] decryptByPublicKey(byte[] encryptedData, String publicKey)

throws Exception {

byte[] keyBytes = Base64.decodeBase64(publicKey);

X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);

KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);

Key publicK = keyFactory.generatePublic(x509KeySpec);

Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());

cipher.init(Cipher.DECRYPT_MODE, publicK);

int inputLen = encryptedData.length;

ByteArrayOutputStream out = new ByteArrayOutputStream();

int offSet = 0;

byte[] cache;

int i = 0;

// 对数据分段解密

while (inputLen - offSet > 0) {

if (inputLen - offSet > MAX_DECRYPT_BLOCK) {

cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);

} else {

cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);

}

out.write(cache, 0, cache.length);

i++;

offSet = i * MAX_DECRYPT_BLOCK;

}

byte[] decryptedData = out.toByteArray();

out.close();

return decryptedData;

}

/**

* <p>

* 公钥加密

* </p>

*

* @param data 源数据

* @param publicKey 公钥(BASE64编码)

* @return

* @throws Exception

*/

public static byte[] encryptByPublicKey(byte[] data, String publicKey) throws Exception {

byte[] keyBytes = Base64.decodeBase64(publicKey);

X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);

KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);

Key publicK = keyFactory.generatePublic(x509KeySpec);

// 对数据加密

Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());

cipher.init(Cipher.ENCRYPT_MODE, publicK);

int inputLen = data.length;

ByteArrayOutputStream out = new ByteArrayOutputStream();

int offSet = 0;

byte[] cache;

int i = 0;

// 对数据分段加密

while (inputLen - offSet > 0) {

if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {

cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);

} else {

cache = cipher.doFinal(data, offSet, inputLen - offSet);

}

out.write(cache, 0, cache.length);

i++;

offSet = i * MAX_ENCRYPT_BLOCK;

}

byte[] encryptedData = out.toByteArray();

out.close();

return encryptedData;

}

/**

* <p>

* 公钥加密

* </p>

*

* @param data 源数据

* @param cert 证书

* @return

* @throws Exception

*/

public static byte[] encryptByPublicKey(byte[] data, Certificate cert) throws Exception {

// 对数据加密

PublicKey uk = cert.getPublicKey();

Cipher cipher = Cipher.getInstance(uk.getAlgorithm());

cipher.init(Cipher.ENCRYPT_MODE, uk);

int inputLen = data.length;

ByteArrayOutputStream out = new ByteArrayOutputStream();

int offSet = 0;

byte[] cache;

int i = 0;

// 对数据分段加密

while (inputLen - offSet > 0) {

if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {

cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);

} else {

cache = cipher.doFinal(data, offSet, inputLen - offSet);

}

out.write(cache, 0, cache.length);

i++;

offSet = i * MAX_ENCRYPT_BLOCK;

}

byte[] encryptedData = out.toByteArray();

out.close();

return encryptedData;

}

/**

* <p>

* 私钥加密

* </p>

*

* @param data 源数据

* @param privateKey 私钥(BASE64编码)

* @return

* @throws Exception

*/

public static byte[] encryptByPrivateKey(byte[] data, String privateKey) throws Exception {

byte[] keyBytes = Base64.decodeBase64(privateKey);

PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);

KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);

Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);

Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());

cipher.init(Cipher.ENCRYPT_MODE, privateK);

int inputLen = data.length;

ByteArrayOutputStream out = new ByteArrayOutputStream();

int offSet = 0;

byte[] cache;

int i = 0;

// 对数据分段加密

while (inputLen - offSet > 0) {

if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {

cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);

} else {

cache = cipher.doFinal(data, offSet, inputLen - offSet);

}

out.write(cache, 0, cache.length);

i++;

offSet = i * MAX_ENCRYPT_BLOCK;

}

byte[] encryptedData = out.toByteArray();

out.close();

return encryptedData;

}

/**

* @param content

* @param charset

* @return

* @throws SignatureException

* @throws UnsupportedEncodingException

*/

private static byte[] getContentBytes(String content, String charset) {

if (charset == null || "".equals(charset)) {

return content.getBytes();

}

try {

return content.getBytes(charset);

} catch (UnsupportedEncodingException e) {

throw new RuntimeException("签名过程中出现错误,指定的编码集不对,您目前指定的编码集是:" + charset);

}

}

/**

* <p>

* 获取私钥

* </p>

*

* @param keyMap 密钥对

* @return

* @throws Exception

*/

public static String getPrivateKey(Map<String, Object> keyMap) throws Exception {

Key key = (Key) keyMap.get(PRIVATE_KEY);

return Base64.encodeBase64String(key.getEncoded());

}

/**

* <p>

* 获取公钥

* </p>

*

* @param keyMap 密钥对

* @return

* @throws Exception

*/

public static String getPublicKey(Map<String, Object> keyMap) throws Exception {

Key key = (Key) keyMap.get(PUBLIC_KEY);

return Base64.encodeBase64String(key.getEncoded());

}

}

大概就是这么多了,可能还有些要注意的地方

1.在 请求审核企业会员资质(audit_member_infos)中需要上传 一个zip的压缩包,里面需要的内容都是定好了的,比如上传了8个文件,每个文件都以名称和后缀的形式放在一起,然后压缩成zip包,zip包的命名和 这个接口需要的传的参数 fileName 要一样,然后,用工具类,对zip包进行 MD5 摘要计算,计算的代码

[java] view
plain copy







public static String getFileMD5(File file) {

if (!file.isFile()){

return null;

}

MessageDigest digest = null;

FileInputStream in=null;

byte buffer[] = new byte[1024];

int len;

try {

digest = MessageDigest.getInstance("MD5");

in = new FileInputStream(file);

while ((len = in.read(buffer, 0, 1024)) != -1) {

digest.update(buffer, 0, len);

}

in.close();

} catch (Exception e) {

e.printStackTrace();

return null;

}

然后调用它给的一个上传文件的工具类,上传的代码

[java] view
plain copy







String file_path = data.get("file_path").toString();

File file = new File(file_path);

String filemd5 = Tools.getFileMD5(file);

System.out.println(filemd5);

System.out.println("-------------------------start------------------------------");

System.out.println("链接sftp");

sftp s = new sftp();

try {

s.upload("/upload/", file_path, s.connectSFTP());

System.out.print("sftp文件上传成功!");

s.ls("/upload/", s.connectSFTP());

} catch (SftpException e) {

e.printStackTrace();

System.out.print("sftp文件上传失败!");

response.setCode(ResponceCodeEnum.fileUploadFail.getCode());

response.setErrorMsg("sftp文件上传失败!");

return response;

}

System.out.println("sftp关闭");

System.out.println("-------------------------end------------------------------");

sftp 类

[java] view
plain copy







package com.sinapay.util;

import java.io.File;

import java.io.FileInputStream;

import java.util.Properties;

import java.util.Vector;

import com.jcraft.jsch.Channel;

import com.jcraft.jsch.ChannelSftp;

import com.jcraft.jsch.JSch;

import com.jcraft.jsch.JSchException;

import com.jcraft.jsch.Session;

import com.jcraft.jsch.SftpException;

public class sftp {

protected String host = "";// 新浪的给的服务器地址

protected String username = "";//用户名

protected String password;

protected String privateKey = "c:\\data\\id_rsa";// 秘钥的位置

protected String passphrase;

protected int port = 50022;// 端口

public ChannelSftp connectSFTP() {

JSch jsch = new JSch();

Channel channel = null;

try {

if (privateKey != null && !"".equals(privateKey)) {

if (passphrase != null && "".equals(passphrase)) {

jsch.addIdentity(privateKey, passphrase);

} else {

jsch.addIdentity(privateKey);

}

}

Session session = jsch.getSession(username, host, port);

if (password != null && !"".equals(password)) {

session.setPassword(password);

}

Properties sshConfig = new Properties();

sshConfig.put("StrictHostKeyChecking", "no");// do not verify host key

session.setConfig(sshConfig);

session.setServerAliveInterval(92000);

session.connect();

channel = session.openChannel("sftp");

channel.connect();

} catch (JSchException e) {

e.printStackTrace();

}

return (ChannelSftp) channel;

}

public void upload(String directory, String uploadFile, ChannelSftp sftp) {

try {

sftp.cd(directory);

File file = new File(uploadFile);

sftp.put(new FileInputStream(file), file.getName());

} catch (Exception e) {

e.printStackTrace();

}

}

@SuppressWarnings("rawtypes")

public void ls(String directory, ChannelSftp sftp) throws SftpException {

sftp.cd(directory);

Vector v = sftp.ls("*.*");

for (int i = 0; i < v.size(); i++) {

System.out.println(v.get(i));

}

}

public void download(String directory, String downloadFile, String saveFile, ChannelSftp sftp) {

try {

sftp.cd(directory);

sftp.get(downloadFile, saveFile);

} catch (Exception e) {

e.printStackTrace();

}

}

public void delete(String directory, String deleteFile, ChannelSftp sftp) {

try {

sftp.cd(directory);

sftp.rm(deleteFile);

} catch (Exception e) {

e.printStackTrace();

}

}

public void disconnected(ChannelSftp sftp) {

if (sftp != null) {

try {

sftp.getSession().disconnect();

} catch (JSchException e) {

e.printStackTrace();

}

sftp.disconnect();

}

}

}

其他的都是接口调用了,都没啥了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  新浪支付 支付 新浪