微信支付的准备工作
2018-03-16 10:54
232 查看
最近忙于研究微信支付的相关内容,自己有踏入了不少的坑。在这里说一下吧,
微信提供的网站有:
微信开放平台:https://open.weixin.qq.com/
用于微信中绑定开发的App,小程序等,实现App支付。
微信公众平台:https://mp.weixin.qq.com/
用于申请微信公众号,小程序的,
微信支付平台:https://pay.weixin.qq.com/
用于查询微信公众号微信支付的订单,可以申请h5支付
一、申请微信服务号
想要开始微信支付,必须要有一个微信服务号,
然后配置微信服务器,等等。
对于微信支付的类型:
扫码支付、公众号支付、App支付、h5支付。
对于扫码支付、公众号支付只需要申请公众号就可以获取,
对于App支付、h5支付,则需要进一步的去申请权限。
关于支付的一些字段:
appid 开发者ID
mch_id 商户号
AppSecret 开发者密码,API秘钥
这些在申请时,会都发到你的邮箱中。
二、开发时,准备的工具类:
1.微信的传输数据为xml
这里借用的是com.thoughtworks.xstream.jar包
public static <T> String beanToXml(T xml){ XStream stream = new XStream(); stream.alias("xml", xml.getClass()); return stream.toXML(xml).replace("__", "_"); } public static <T> void beanToXml(T xml,OutputStream out) throws UnsupportedEncodingException, IOException{ String content = beanToXml(xml); out.write(content.getBytes("utf-8")); } public static <T> T xmlToBean(String xmlStr,Class<T> clazz){ XStream stream = new XStream(); stream.alias("xml", clazz); stream.alias("root", clazz); stream.ignoreUnknownElements(); @SuppressWarnings("unchecked") T t = (T) stream.fromXML(xmlStr); return t; } @SuppressWarnings("unchecked") public static <T> T xmlToBean(String xmlStr,T obj){ XStream stream = new XStream(); stream.alias("xml", obj.getClass()); stream.alias("root", obj.getClass()); stream.ignoreUnknownElements(); return (T) stream.fromXML(xmlStr, obj); } public static <T> T xmlToBean(InputStream in,Class<T> clazz){ XStream stream = new XStream(); stream.alias("xml", clazz); stream.alias("root", clazz); stream.ignoreUnknownElements(); @SuppressWarnings("unchecked") T t = (T) stream.fromXML(in); return t; }
2.对传输的数据按照属性ASCII顺序排列形成键值对的格式,
再加上秘钥,获取签名
public static <T> String getSignTemp(T t){ if(t == null){ throw new RuntimeException("参数不能为空"); } StringBuilder sb = new StringBuilder(); //1.对参数按照key=value的格式,并按照参数名ASCII字典序排序 try { Class<?> clazz = t.getClass(); Field[] fields = clazz.getDeclaredFields(); List<Field> list = new ArrayList<>(Arrays.asList(fields)); Collections.sort(list, new Comparator<Field>(){ @Override public int compare(Field o1, Field o2) { return o1.getName().compareTo(o2.getName()); } }); for(Field field : list){ String name = field.getName(); //序列号省略 if(name.contains("serialVersionUID")){ continue; } //签名省略 if(name.equals("sign")){ continue; } field.setAccessible(true); if(field.get(t) == null){ continue; } if(field.getType() == String.class && StringUtils.isEmpty(field.get(t))){ continue; } if(name.equals("packageValue")){ name = "package"; } sb.append(name).append("=").append(field.get(t)).append("&"); } //2.拼接API密钥 // sb.append("key=").append(PayConstant.KEY); sb.append("key=").append(PayConstant.APP_SECRET); } catch (Exception e) { throw new RuntimeException("获取参数字符串失败", e); } //3.返回拼接文本 return sb.toString(); } public static String Md5Digest(String str) { if(StringUtils.isEmpty(str)){ throw new RuntimeException("字符串不能为空"); } byte[] data = DigestUtils.md5(str); //将字节数组转为16进制字符串 StringBuffer sb = new StringBuffer(); for(byte b:data){ String sHex = Integer.toHexString(b&0xff); if(sHex.length()==1){ sHex = "0"+sHex; } sb.append(sHex); } String content = sb.toString().toUpperCase(); return content; }
3.对于支付退款时,需要使用https请求,并且要使用证书验证
构造https请求
String pwd = PayConstant.MCH_ID; // 1.获取证书 输入流, 获取证书密码 // InputStream in = new FileInputStream(PayConstant.API_FILE_PATH); InputStream in = HttpUtil.class.getClassLoader().getResourceAsStream("apiclient_cert.p12"); char[] password = pwd.toCharArray(); // 2.实例化密钥库 & 初始化密钥工厂 KeyStore key = KeyStore.getInstance("PKCS12"); key.load(in, password); KeyManagerFactory keyManager = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); keyManager.init(key, password); // 3.创建 SSLContext SSLContext ssl = SSLContext.getInstance("TLS");; ssl.init(keyManager.getKeyManagers(), null, new SecureRandom()); SSLConnectionSocketFactory sslFactory = new SSLConnectionSocketFactory( ssl, new String[]{"TLSv1"}, null, new DefaultHostnameVerifier()); // 4.创建连接管理类 BasicHttpClientConnectionManager connManager = new BasicHttpClientConnectionManager( RegistryBuilder.<ConnectionSocketFactory>create() .register("http", PlainConnectionSocketFactory.getSocketFactory()) .register("https", sslFactory) .build(), null, null, null ); HttpClient httpClient = HttpClientBuilder.create() .setConnectionManager(connManager) .build();
4.对于申请退款时,返回的数据需要进行AES解密。
注意:这里可能会报秘钥的长度非法,
这里因为java当前jre只支持秘钥128位的,而秘钥 192、256位的,则会报错。
因此这里需要从官网下载对秘钥长度没有限制的jar,把之前的替换了就可以了。
把里面的两个jar包:local_policy.jar 和 US_export_policy.jar 替换掉原来 Jdk 安装目录 $\Java\jre{6|7|8}\lib\security 下的两个jar 包接可以了
下载地址:
jdk1.7:http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html
jdk1.8:http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html
/** * 密钥算法 */ private static final String ALGORITHM = "AES"; /** * 加解密算法/工作模式/填充方式 */ private static final String ALGORITHM_MODE_PADDING = "AES/ECB/PKCS5Padding"; /** * 生成Key */ public static SecretKey key = new SecretKeySpec( MyDigestUtils.Md5Digest("2IBtBXdrqC3kCBs4gaceL7nl2nnFadQv") .toLowerCase().getBytes(), ALGORITHM); /** * 加密 * @param data * @return * @throws Exception */ public static String encryptData(String data) throws Exception{ Cipher cipher = Cipher.getInstance(ALGORITHM_MODE_PADDING); cipher.init(Cipher.ENCRYPT_MODE, key); byte[] s = cipher.doFinal(data.getBytes("utf-8")); return Base64Utils.encodeToString(s); } /** * 解密 * @param base64Data * @return * @throws Exception */ public static String decryptData(String base64Data) throws Exception{ Cipher cipher = Cipher.getInstance(ALGORITHM_MODE_PADDING); cipher.init(Cipher.DECRYPT_MODE, key); byte[] data = cipher.doFinal(Base64Utils.decodeFromString(base64Data)); return new String(data, "utf-8"); }
相关文章推荐
- 微信支付开发准备工作和详细步骤
- [一分钟先生]梁鹏远:从技术走向管理的准备工作
- 不得不爱开源 Wijmo jQuery 插件集(2)-【准备工作】(附30种Theme演示和源码)
- DirectX 9.0c游戏开发手记之RPG编程自学日志之3: Preparing for the Book (准备工作)(中)
- Azkaban的Web Server源码探究系列21: Flow执行前的准备工作
- 英语面试技巧以及准备工作
- gsoap中文文档(7 准备工作)
- 幼儿园面试前的准备工作
- Unity之Tango开发准备工作
- Step 1:准备工作
- 移动端重构系列1——前期准备工作
- Windows8.1驱动编写以及内核调试(一) 做好准备工作并编写第一个驱动程序
- 基于Oracle的EntityFramework的WEBAPI2的实现(一)——准备工作
- CodeSmith学习记录 --准备工作
- uboot移植(一):移植前的准备工作
- Unity编辑器开发(一):准备工作
- cocos2d-x 2x 菜鸟编塔防 01 准备工作
- Exchange2010迁移前的准备工作
- 准备工作 第一篇:如何加载dll
- 面试之前需要做的准备工作