简述
微信支付也早已提供了代付功能,支持企业向用户付款,分别未付款到零钱和付款到银行卡两种方式。在我们平常开发的项目中一般都会用到微信支付功能,相应的项目中也会提供提现功能。企业付款到零钱和企业付款到银行卡是两个接口,功能不一样,Api限制也不一样,本篇博文主要讲述开发微信企业付款到银行卡的步骤详解,关于企业付款到零钱等下篇再进行讲述。
这里还是主要说付款至用户银行卡,微信上线的企业付款至银行卡功能,商户可以将商户号余额付款至指定的收款银行账户,通过指定收款银行账户户名、卡号,以及收款银行信息就可以实现付款功能。目前企业付款到银行卡仅支持17家银行,更多银行在逐步开放中,但是看着常用的银行基本都有,这个不影响使用。
步骤
第一步、开通微信付款到个人银行卡这个功能产品
第二步、下载API安全证书
微信企业付款到零钱要求必传证书,需要到https://pay.weixin.qq.com 账户中心->账户设置->API安全->下载证书,下载下来的证书文件一共有三个,还有一个证书使用说明文档,这里就不进行解释了。然后保存,配置好代码中的证书路径。
第三步、获取RSA加密公钥
调用获取RSA公钥API获取RSA公钥,落地成本地文件,假设为public.pem,确定public.pem文件的存放路径,同时修改代码中文件的输入路径,加载RSA公钥,用标准的RSA加密库对敏感信息进行加密,选择RSA_PKCS1_OAEP_PADDING填充模式, 得到进行rsa加密并转base64之后的密文,将密文传给微信侧相应字段,如付款接口(enc_bank_no/enc_true_name)
下面代码默认输出PKCS#1格式的公钥,我们需要这个,所以先写一个接口去请求一下,然后将证书文件保存一下。请求下面这个接口方法会返回证书信息。
/**
* 获得RSA加密公钥
*/
public function GetRsa()
{
$data = [
'mch_id' => $this->mch_id,
'nonce_str' => self::CreateNonceStr(32),
'sign_type' => 'MD5',
];
$data['sign'] = self::MakeSign($data, $this->api_key);
$xml = self::ArrayToXml($data);
$url = 'https://fraud.mch.weixin.qq.com/risk/getpublickey';
$arr = self::CurlPostSsl($url, $xml, $this->certificate_path);
var_dump(self::XmlToArray(strstr($arr, '<xml>')));
exit;
}
第四步、RSA密钥PKCS#1转PKCS#8
PKCS#1 转 PKCS#8:
openssl rsa -RSAPublicKey_in -in -pubout
PKCS#8 转 PKCS#1:
openssl rsa -pubin -in -RSAPublicKey_out
这个命令需要在服务器执行,如果报错的话,说明你姿势不对,亲重新查找原因再次尝试。
openssl rsa -RSAPublicKey_in -in pkcs1.pem -pubout > pkcs8.pem
这样提示writing RSA key就说明成功了,当然敲这个命令的时候要进入你放证书以及上面的公钥的目录,放在一个不可直接访问的目录!
第五步、进行代码配置
准备工作到此就做完了,下面可以进行代码配置。
/**
* 构造函数
* @desc 用于设置基本信息
* 1、设置APP ID(应用id)
* 2、设置MCH ID(商户id)
* 3、设置API KEY(API接口密钥)
* 4、设置Certificate Path(证书路径地址)
* @other 这些数据也可以直接从数据库中获取,然后赋值;或者从配置文件中获取、赋值;根据个人习惯。
*/
public function __construct($parameter = array())
{
$this->mch_appid = !empty($parameter['mch_appid']) ? $parameter['mch_appid'] : '';
$this->mch_id = !empty($parameter['mch_id']) ? $parameter['mch_id'] : '';
$this->api_key = !empty($parameter['api_key']) ? $parameter['api_key'] : '';
$this->certificate_path = !empty($parameter['certificate_path']) ? $parameter['certificate_path'] : '';
if (empty($this->mch_appid)) {
throw new Exception("App Id has not been set up!");
}
if (empty($this->mch_id)) {
throw new Exception("Mch Id has not been set up!");
}
if (empty($this->api_key)) {
throw new Exception("Api Key has not been set up!");
}
if (empty($this->certificate_path)) {
throw new Exception("Certificate Path has not been set up!");
}
}
第六步、调用代付提交
企业付款到个人银行卡API的请求参数以及返回结果等具体可查看微信开发文档:企业付款待银行卡API。
/**
* 企业付款到银行卡
* @param $bank_no string 银行卡号
* @param $true_name string 真实姓名
* @param $bank_code string 银行代码(可在开发文档中查看)
* @param $amount float 金额数值(元)
* @param $partner_trade_no string 代付单号
* @return mixed
*/
public function WxPayToBank($bank_no, $true_name, $bank_code, $amount, $partner_trade_no)
{
$paybank = [
'mch_id' => $this->mch_id,
'partner_trade_no' => $partner_trade_no,
'nonce_str' => self::CreateNonceStr(),
'enc_bank_no' => self::RSAEncrypt($bank_no, $this->certificate_path),
'enc_true_name' => self::RSAEncrypt($true_name, $this->certificate_path),
'bank_code' => $bank_code,
'amount' => intval($amount) * 100,
'desc' => "提现处理!"
];
$paybank['sign'] = self::MakeSign($paybank, $this->api_key);
$xml = self::ArrayToXml($paybank);
$url = "https://api.mch.weixin.qq.com/mmpaysptrans/pay_bank";
$data = self::CurlPostSsl($url, $xml, $this->certificate_path);
return self::XmlToArray(strstr($data, '<xml>'));
}
第七步、查询代付结果
由于微信代付到账是T+1,并不是实时到账且没有异步通知,所以就需要我们进行结果查询。
/**
* 代付结果查询
* @param $partner_trade_no string 代付单号
* @return mixed
*/
public function QueryPayResult($partner_trade_no)
{
$paybank = [
'mch_id' => $this->mch_id,
'partner_trade_no' => $partner_trade_no,
'nonce_str' => self::CreateNonceStr(),
];
$paybank['sign'] = self::MakeSign($paybank, $this->api_key);
$xml = self::ArrayToXml($paybank);
$url = "https://api.mch.weixin.qq.com/mmpaysptrans/query_bank";
$data = self::CurlPostSsl($url, $xml, $this->certificate_path);
return self::XmlToArray(strstr($data, '<xml>'));
}