前言: 最近公司做产品,有这样几个需求
- 微信退款
- 微信企业给用户转账到零钱
- 通过微信给用户转账到银行卡
- 支付宝退款
- 支付宝转账到余额
根据上述需求,本人呢,做了几天的研究与学习,在此期间不免会出现摇头抓脑壳的现象,但是最终还是收获了一些经验教训,不过在几天的研究中,得出一个结论,微信开发文档真的有够坑的,让初次接触的我是狠狠的抓了好几次脑壳,为了避免在后续的开发中再次遇到这种情况,我决定记录下这段时间的研究成果,俗话说的好,好记忆不如烂笔头,当然在本页不会介绍关于支付宝方面的开发,因为个人觉得支付宝的开发文档很人性化,相当节省时间,简单到直接拷贝源码,就可以直接使用,可能这样会减少你在研究技术中获得的提升快感,但是在公司那么急促的开始时间来说,不得不给支付宝点一万个赞,虽然微信开发文档相对支付宝来说差一些,但是你却能在研究中得到一定的提升,所以,综合来说各有各的好吧
准备工作
第一、开通微信转账功能,设置API可访问IP地址(必须)
注意:如果是本地测试IP地址,请使用你本地路由的公网地址,否则会提示IP地址无权访问
- 开发企业转账时需要的前提条件 微信企业转账官方开发文档点此前往
- 设置可被允许访问的接口IP地址
第二、下载官方的开发SDK(注:当前介绍官方的v3.0.9版本,但该版本存在BUG,将会影响支付功能,稍后会介绍下如何解决)
- 下载官方SDK(按照自己的开发习惯下载相应的SDK,本文主要介绍JAVA版本的)
- 下载地址 微信官网SDK下载地址
第三、下载API安全证书(微信转账,退款都是需要证书的)
第四、证书使用方法
- 微信官网证书使用说明
- 本文通过JAVA代码从外部文件中读取证书来实现开发功能
- 证书存在地址
- 加载证书
/**
* 证书地址:resource下
*/
public static final String CERT_PATH = "/cert/apiclient_cert.p12";
/**
* 获取证书
*/
public InputStream getCertStream() {
ClassPathResource cl = new ClassPathResource(CERT_PATH);
try {
return cl.getInputStream();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
第五、编写WeChatPayConfig.java(需要继承SDK的WXPayConfig.java)
package com.casom.pay.config;
import java.io.IOException;
import java.io.InputStream;
import org.springframework.core.io.ClassPathResource;
import com.github.wxpay.sdk.IWXPayDomain;
import com.github.wxpay.sdk.WXPayConfig;
public class WeChatPayConfig extends WXPayConfig {
/**
* 微信支付回调地址
*/
public static final String NOTITY_URL = "自己设置的回调地址";
/**
* 证书地址:resource下
*/
public static final String CERT_PATH = "/cert/apiclient_cert.p12";
/**
* pkcs8公钥
*/
public String RSA_PKCS8 = "/rsa/pkcs8.pem";
/**
* 填充算法
*/
public String FILLING_ALGORITHM = "RSA/ECB/OAEPWITHSHA-1ANDMGF1PADDING";
/**
* SECRETKEY
*/
private String key = "公司的SECRETKEY";
/**
* 申请商户号的appid或商户号绑定的appid
*/
public String getAppID() {
return "公司的APPID";
}
/**
* 商户号
*/
public String getMchID() {
return "公司商户号";
}
/**
* SECRETKEY
*/
public String getKey() {
return this.key;
}
/**
* 获取证书
*/
public InputStream getCertStream() {
ClassPathResource cl = new ClassPathResource(CERT_PATH);
try {
return cl.getInputStream();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* 接口域名
*/
@Override
public IWXPayDomain getWXPayDomain() { // 这个方法需要这样实现, 否则无法正常初始化WXPay
IWXPayDomain iwxPayDomain = new IWXPayDomain() {
@Override
public void report(String domain, long elapsedTimeMillis, Exception ex) {
}
@Override
public DomainInfo getDomain(WXPayConfig config) {
return new IWXPayDomain.DomainInfo(doam_api, true);
}
};
return iwxPayDomain;
}
}
第六、开发企业微信转账到用户零钱
- 请求接口参数可在微信官网查看,这里不做介绍
- 微信官网企业转账开发文档(转账至微信零钱)
- 在下载的SDK包的WXPayConstants类中加入下列代码(转账到微信零钱和银行都需要用到此类)
/**
* RSA获取路径
*/
public static final String DOMAIN_APIRSA = "fraud.mch.weixin.qq.com";
/**
* 转账到零钱
*/
public static final String TRANSFER_TO_WECHAT_WALLET_URL_SUFFIX = "/mmpaymkttransfers/promotion/transfers";
/**
* 转账到银行卡
*/
public static final String TRANSFER_TO_BANK_URL_SUFFIX = "/mmpaysptrans/pay_bank";
/**
* 获取公钥
*/
public static final String RSA_GET_PUBLIC_KEY = "/risk/getpublickey";
- 在下载的SDK包的WXPay类中加入下列方法
/**
* 企业转账
* @param reqData
* @param isTransBank(true:转账到银行卡,false:转账到微信零钱)
* @return
* @throws Exception
*/
public Map<String,String> trans(Map<String, String> reqData,boolean isTransBank) throws Exception{
return this.trans(reqData, isTransBank, this.config.getHttpConnectTimeoutMs(), this.config.getHttpReadTimeoutMs());
}
/**
* 企业转账
* @param reqData
* @param isTransBank(true:转账到银行卡,false:转账到微信零钱)
* @param connectTimeoutMs
* @param readTimeoutMs
* @return
* @throws Exception
*/
public Map<String, String> trans(Map<String, String> reqData,boolean isTransBank, int connectTimeoutMs, int readTimeoutMs) throws Exception {
String url;
if (isTransBank) {
url = WXPayConstants.TRANSFER_TO_BANK_URL_SUFFIX;
}
else {
url = WXPayConstants.TRANSFER_TO_WECHAT_WALLET_URL_SUFFIX;
}
//返回结果转化为Map格式
return WXPayUtil.xmlToMap(this.requestWithCert(url, reqData, connectTimeoutMs, readTimeoutMs));
}
- 在自己的Controller或者Service中添加下列代码(下列代码都是以Map对象接收,自己可以创建对象来接收请求参数和返回结果)
/**
* 企业转账到零钱
* @param partner_trade_no 商户订单号(唯一)
* @param amount 转账金额
* @param desc 转账备注
* @param card_code (如果转账到银行卡:则表示银行卡号;如果转账到微信零钱:则表示微信用户的openid)
* @param real_name 真实姓名
* @param spbill_create_ip 服务端或者客户端操作IP(与在商户号中设置的没有任何关系)
* @return
*/
public JSONObject transfer(String partner_trade_no, BigDecimal amount, String desc, String card_code, String re