最近,业务上有个需求,用到了微信的企业付款到银行卡这个接口。网上找了些资料,总之是坑比较多吧,但是这也算是微信文档的通病了。为此,我整理了一下企业付款到银行卡的使用类。商户可以将商户号余额付款至指定的收款银行账户。通过指定收款银行账户户名、卡号,以及收款银行信息即可实现付款。
文档地址:
https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=24_1&index=1
使用条件
- 商户号(或同主体其他非服务商商户号)已入驻90日
- 商户号(或同主体其他非服务商商户号)有30天连续正常交易
- 登录微信支付商户平台-产品中心,开通企业付款。
功能说明
- 企业付款至银行卡只支持新资金流类型账户
- 目前企业付款到银行卡支持17家银行,更多银行逐步开放中
- 付款到账实效为1-3日,最快次日到账
- 每笔按付款金额收取手续费,按金额0.1%收取,最低1元,最高25元,如果商户开通了运营账户,手续费和付款的金额都从运营账户出。如果没有开通,则都从基本户出。
- 每个商户号每天可以出款100万,单商户给同一银行卡付款每天限额5万
- 发票:在账户中心-发票信息页面申请开票的商户会按月收到发票(已申请的无需重复申请)。企业付款到银行卡发票与交易手续费发票为拆分单独开具。
代码
<?php
namespace Jykj\\Balance\\Weixin;
/***************************************************************
* 企业付款到零钱、企业付款到银行卡、查询企业付款;证书的加密,解密。有问题邮件联系我
* Copyright notice
*
* (c) Wang Hongbin <wanghongbin@ngoos.org>, 极益科技
*
* @Author: Wang Hongbin
* @Email: wanghongbin@ngoos.org
* @Date: 2018-06-13 11:29:39
* @Last Modified by: Wang Hongbin
* @Last Modified time: 2018-06-13 16:50:46
***************************************************************/
class WxPubApi
{
private $params;
private $paths = ""; // 证书存放路径
private $cpath = ""; // 公钥路径
private $kpath = ""; // 私钥路径
const KEY = ''1111111111111111111111111111qq''; // 32位
const MCHID = ''1111111111''; // 商户号
const APPID = ''wxdwdq1312312qweqw'';
const SECRET = ''asdddddddddddddddddddddddddddd'';
const PAYURL = ''https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers'';
const SEPAYURL = "https://api.mch.weixin.qq.com/mmpaymkttransfers/gettransferinfo";
const BANKPAY = "https://api.mch.weixin.qq.com/mmpaysptrans/pay_bank";
const PKURL = "https://fraud.mch.weixin.qq.com/risk/getpublickey";
public function __construct(){
$this->paths = dirname(__FILE__).''/cert/'';
$this->cpath = dirname(__FILE__).''/cert/apiclient_cert.pem'';
$this->kpath = dirname(__FILE__).''/cert/apiclient_key.pem'';
}
/**
* 付款到零钱
* @param [type] $data [description]
* @return [type] [description]
*/
public function createComPay($data){
//构建原始数据
$this->params = [
''mch_appid'' => self::APPID,//APPid,
''mchid'' => self::MCHID,//商户号,
''nonce_str'' => strtoupper(md5(time())), //随机字符串
''partner_trade_no'' => $data[''trade_no''], //商户订单号
''openid'' => $data[''openid''], //用户openid
''check_name'' => ''NO_CHECK'',//校验用户姓名选项 NO_CHECK:不校验真实姓名 FORCE_CHECK:强校验真实姓名
//''re_user_name'' => '''',//收款用户姓名 如果check_name设置为FORCE_CHECK,则必填用户真实姓名
''amount'' => $data[''price''],//金额 单位分
''desc'' => $data[''desc''],//付款描述
''spbill_create_ip'' => $_SERVER[''SERVER_ADDR''],//调用接口机器的ip地址
];
//将数据发送到接口地址
return $this->SendData(self::PAYURL);
}
/**
* 转账到银行卡
* @param [type] $data [description]
* @return [type] [description]
*/
public function createBankPay($data){
$this->params = [
''mch_id'' => self::MCHID,//商户号
''partner_trade_no'' => date(''YmdHis''),//商户付款单号
''nonce_str'' => strtoupper(md5(time())), //随机串
''enc_bank_no'' => $data[''enc_bank_no''],//收款方银行卡号RSA加密
''enc_true_name'' => $data[''enc_true_name''],//收款方姓名RSA加密
''bank_code'' => $data[''bank_code''],//收款方开户行
''amount'' => $data[''amount''],//付款金额
];
//将数据发送到接口地址
return $this->SendData(self::BANKPAY);
}
/**
* 查询订单
* @param [type] $oid [description]
* @return [type] [description]
*/
public function searchPayByOrder($oid){
$this->params = [
''nonce_str'' => md5(time()),//随机串
''partner_trade_no'' => $oid, //商户订单号
''mch_id'' => self::MCHID,//商户号
''appid'' => self::APPID //APPID
];
//将数据发送到接口地址
return $this->SendData(self::SEPAYURL);
}
/**
* 获取公钥
* @return [type] [description]
*/
public function getRsaPuyKey(){
$this->params = [
''mch_id'' => self::MCHID,//商户ID
''nonce_str'' => strtoupper(MD5(time())),
''sign_type'' => ''MD5''
];
//将数据发送到接口地址
$pubkey = $this->SendData(self::PKURL);
file_put_contents($this->paths.''pubkey.pem'', $pubkey[''pub_key'']);
return $pubkey;
}
public function getSign($params=array()){
//去除空值
$params = array_filter($params);
if(isset($params[''sign''])) unset($params[''sign'']);
//按照键名字典排序
ksort($params);
//生成url格式的字符串
$str = $this->arrToUrl($params).''&key=''.self::KEY;
$params[''sign''] = strtoupper(md5($str));
return $params;
}
public function arrToUrl($arr){
return urldecode(http_build_query($arr));
}
/**
* 获取随机数
* @param integer $length [description]
* @return [type] [description]
*/
public function getRandomKeys($length=30)
{
$str = ''ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyz'';
$key = null;
for ($i = 0; $i < $length; $i++) {
$key .= $pattern{mt_rand(0, 30)}; //生成php随机数
}
return $key;
}
//数组转xml
public function ArrToXml($arr){
if(!is_array($arr) || count($arr) == 0) return '''';
$xml = "<xml>";
foreach ($arr as $key=>$val){
if (is_numeric($val)){
$xml.="<".$key.">".$val."</".$key.">";
}else{
$xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
}
}
$xml.="</xml>";
return $xml;
}
//Xml转数组
public function XmlToArr($xml){
if($xml == '''') return '''';
libxml_disable_entity_loader(true);
$arr = json_decode(json_encode(simplexml_load_string($xml, ''SimpleXMLElement'', LIBXML_NOCDATA)), true);
return $arr;
}
/**
* 下面是写死的东西不需要改变 //通用发送CURL接口
* @param [type] $data [description]
* @param [type] $url [description]
*/
public function SendCurl($data,$url){
$ch = curl_init();
//接口地址
$MENU_URL = $url;
curl_setopt($ch,CURLOPT_URL, $MENU_URL);
curl_setopt($ch,CURLOPT_CUSTOMREQUEST,"POST");
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch,CURLOPT_SSL_VERIFYHOST, FALSE);
//证书地址,微信支付下面
curl_setopt($ch,CURLOPT_SSLCERT,$this->cpath);
curl_setopt($ch,CURLOPT_SSLKEY,$this->kpath);
// curl_setopt($ch, CURLOPT_USERAGENT, ''Mozilla/5.0 (compatible; MSIE 5.01;
// Windows NT 5.0)'');
//curl_setopt ( $ch, CURLOPT_FOLLOWLOCATION, 1 );
curl_setopt($ch,CURLOPT_AUTOREFERER,1);
curl_setopt($ch,CURLOPT_POSTFIELDS, $data);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
$info = curl_exec($ch);
if (curl_errno($ch)) {
//echo ''Errno'' . curl_error ( $ch );
exit(''CURL执行失败'');
}
curl_close($ch);
return $info;
}
/**
* 发送数据包
* @param [type] $url [description]
* @return [type] [description]
*/
public function SendData($url){
$params = $this->getSign($this->params);
$xmldata = $this->ArrToXml($params);
$returnData = $this->SendCurl($xmldata,$url);
return $this->XmlToArr($returnData);
}
}
/**
* 公钥,秘钥的加密,解密
*/
class WxRSA
{
private $public_key_resource = ''''; //公钥资源
private $private_key_resource = ''''; //私钥资源
/**
* 构造函数
* @param [string] $public_key [公钥数据字符串]
* @param [string] $private_key [私钥数据字符串]
*/
public function __construct($public_key,$private_key) {
$this->public_key_resource = !empty($public_key) ? openssl_pkey_get_public($this->get_public_key($public_key)) : false;
$this->private_key_resource = !empty($private_key) ? openssl_pkey_get_private($this->get_private_key($private_key)) : false;
}
/**
* 获取私有key字符串 重新格式化 为保证任何key都可以识别
*/
public function get_private_key($private_key){
$search = [
"-----BEGIN RSA PRIVATE KEY-----",
"-----END RSA PRIVATE KEY-----",
"\\n",
"\\r",
"\\r\\n"
];
$private_key=str_replace($search,"",$private_key);
return $search[0] . PHP_EOL . wordwrap($private_key, 64, "\\n", true) . PHP_EOL . $search[1];
}
/**
* 获取公共key字符串 重新格式化 为保证任何key都可以识别
*/
public function get_public_key($public_key){
$search = [
"-----BEGIN PUBLIC KEY-----",
"-----END PUBLIC KEY-----",
"\\n",
"\\r",
"\\r\\n"
];
$public_key=str_replace($search,"",$public_key);
return $search[0] . PHP_EOL . wordwrap($public_key, 64, "\\n", true) . PHP_EOL . $search[1];
}
/**
* 生成一对公私钥 成功返回 公私钥数组 失败 返回 false
*/
public function create_key() {
$res = openssl_pkey_new();
if($res == false) return false;
openssl_pkey_export($res, $private_key);
$public_key = openssl_pkey_get_details($res);
return array(''public_key''=>$public_key["key"],''private_key''=>$private_key);
}
/**
* 用私钥加密
*/
public function private_encrypt($input) {
openssl_private_encrypt($input,$output,$this->private_key_resource);
return base64_encode($output);
}
/**
* 解密 私钥加密后的密文
*/
public function public_decrypt($input) {
openssl_public_decrypt(base64_decode($input),$output,$this->public_key_resource);
return $output;
}
/**
* 用公钥加密
*/
public function public_encrypt($input) {
openssl_public_encrypt($input,$output,$this->public_key_resource,OPENSSL_PKCS1_OAEP_PADDING);
return base64_encode($output);
}
/**
* 解密 公钥加密后的密文
*/
public function private_decrypt($input) {
openssl_private_decrypt(base64_decode($input),$output,$this->private_key_resource,OPENSSL_PKCS1_OAEP_PADDING);
return $output;
}
}
评论 (0)