微信企业付款到银行卡

微信官方文档:https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=24_2

1.第一步准备好商户的证书,在商户后台下载

191325_OMQ7_736174.png

191418_TGDV_736174.png

2第二步准备好微信RSA公钥

微信官方地址:https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=24_7

192008_1hDH_736174.png

这里简单实例展示,需要的自行拆分封装

$mch_id     =   123456;//自己的商户号
		$str        =   md5(rand(1000,9999));//随机字符串
		$sign_type  =   "MD5";//加密类型
		$key        =   "abcde";//商户的key
		$stringA    =   "mch_id={$mch_id}&nonce_str={$str}&sign_type={$sign_type}&key={$key}";
		$md5_str    =   MD5($stringA);//md5加密
		$sign       =   strtoupper($md5_str);//转大写
		$url        =   "https://fraud.mch.weixin.qq.com/risk/getpublickey";//微信生成RSA公钥接口地址
$xml=<<<EOF
<xml>
<mch_id>{$mch_id}</mch_id>
<nonce_str>{$str}</nonce_str>
<sign_type>MD5</sign_type>
<sign>$sign</sign>
</xml>
EOF;
		$apiclient_key   =   './Xcxpay/Certificate/Jw/apiclient_cert.pem';//证书路径 在商户平台下载
		$apiclient_cert  =   './Xcxpay/Certificate/Jw/apiclient_key.pem';//证书路径 在商户平台下载
		$ch = curl_init();
		curl_setopt($ch, CURLOPT_TIMEOUT, 30);
		curl_setopt($ch,CURLOPT_URL, $url);
		curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,TRUE);
		curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,2);//严格校验
		curl_setopt($ch, CURLOPT_HEADER, FALSE);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
		//使用证书:cert 与 key 分别属于两个.pem文件
		curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
//		curl_setopt($ch,CURLOPT_SSLCERT, 'apiclient_key证书的路径');//上面第一步在商户后台下载的证书
		curl_setopt($ch,CURLOPT_SSLCERT, $apiclient_key);//上面第一步在商户后台下载的证书
		curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
//		curl_setopt($ch,CURLOPT_SSLKEY, 'apiclient_cert证书的路径');//上面第一步在商户后台下载的证书
		curl_setopt($ch,CURLOPT_SSLKEY, $apiclient_cert);//上面第一步在商户后台下载的证书
		curl_setopt($ch, CURLOPT_POST, TRUE);
		curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
		$data = curl_exec($ch);
		//返回结果
		if($data){
			curl_close($ch);
		} else {
			$error = curl_errno($ch);
			curl_close($ch);
		}
		libxml_disable_entity_loader(true);
		$result     =   json_decode(json_encode(simplexml_load_string($data, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
		print_r($result);

成功后返回的数据

192318_zkq1_736174.png

把pub_key的内容保存成为一个文件, 已 .pem后缀的文件 例如 wx_public.pem 等等需要用到这个文件

如:

193103_rte9_736174.png

193129_jz9Z_736174.png

再将wx_public.pem 格式转换

openssl rsa -RSAPublicKey_in -in 刚刚保存的文件 -pubout > 新的文件

194047_Slv9_736174.png

得到新的pem文件,等等要用到。这个文件主要是要来RAS加密 银行卡号和姓名

 

新建一个类

class Wxyxk
{
	public $value=array(
		'mch_id'=>'',
		'partner_trade_no'=>'',
		'nonce_str'=>'',
		'enc_bank_no'=>'',
		'enc_true_name'=>'',
		'bank_code'=>'',
		'amount'=>'',
		'desc'=>'',
	);
	public $app_id;
	public $mch_id;
	public $key;
	public $url = "https://api.mch.weixin.qq.com/mmpaysptrans/pay_bank";
	public $apiclient_cert;
	public $apiclient_key;
	public $public_pem;

	public function __construct($mch_id, $key)
	{
		$this->mch_id       =   $this->value['mch_id']      =   $mch_id;
		$this->key          =   $key;
	}

	public function sendRed()
	{

		foreach($this->value as $k=>$v){
			if(empty($v)){
				return $k.' 不能为空';
			}
		}

		if(empty($this->apiclient_cert) || empty($this->apiclient_key) || empty($this->key)){
			return '证书路径和key不能为空';
		}
		$this->MakeSign();
		$xml = $this->ToXml();
		$result_xml = $this->postXmlCurl($xml,$this->url);
		$result = $this->FromXml($result_xml);
//		$this->wirteLog($this->setMsg($result));

		return $result;
	}

	public function getOrderStatus($order_on)
	{
		$url            =   "https://api.mch.weixin.qq.com/mmpaysptrans/query_bank";
		$rand_str       =   md5(rand(100000,99999));
		$data           =   array("mch_id"=>$this->mch_id,"nonce_str"=>$rand_str,'partner_trade_no'=>$order_on);
		$str            =   "mch_id={$this->mch_id}&nonce_str={$rand_str}&partner_trade_no={$order_on}&key={$this->key}";
		$sign           =   strtoupper(md5($str));
		$data['sign']   =   $sign;

		$xml = "<xml>";
		foreach ($data as $key=>$val) {
			if (is_numeric($val)){
				$xml    .=  "<".$key.">".$val."</".$key.">";
			}else{
				$xml    .=  "<".$key."><![CDATA[".$val."]]></".$key.">";
			}
		}
		$xml            .=  "</xml>";

		$result_xml     =   $this->postXmlCurl($xml, $url);
		$result         = $this->FromXml($result_xml);
		return $result;

	}


	/**
	 * 输出xml字符
	 * @throws WxPayException
	 **/
	public function ToXml()
	{
		if(!is_array($this->value)
			|| count($this->value) <= 0)
		{
			throw new WxPayException("数组数据异常!");
		}

		$xml = "<xml>";
		foreach ($this->value as $key=>$val)
		{
			if (is_numeric($val)){
				$xml.="<".$key.">".$val."</".$key.">";
			}else{
				$xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
			}
		}
		$xml.="</xml>";
		return $xml;
	}


	public function createXml($data)
	{
		if(!is_array($data)
			|| count($data) <= 0)
		{
			throw new WxPayException("数组数据异常!");
		}

		$xml = "<xml>";
		foreach ($data as $key=>$val)
		{
			if (is_numeric($val)){
				$xml.="<".$key.">".$val."</".$key.">";
			}else{
				$xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
			}
		}
		$xml.="</xml>";
		return $xml;
	}

	public function createMakeSign($data)
	{
		$buff = "";
		foreach ($data as $k => $v)
		{
			if($k != "sign" && $v != "" && !is_array($v)){
				$buff .= $k . "=" . $v . "&";
			}
		}

		$buff = trim($buff, "&");
		$buff = $buff . "&key=".$this->key;
		$string = md5($buff);
		//签名步骤四:所有字符转为大写
		$result = strtoupper($string);
		return  $result;
	}



	/**
	 * 生成签名
	 * @return 签名,本函数不覆盖sign成员变量,如要设置签名需要调用SetSign方法赋值
	 */
	public function MakeSign()
	{
		//签名步骤一:按字典序排序参数
		ksort($this->value);
		$string = $this->ToUrlParams();
		//签名步骤二:在string后加入KEY
		$string = $string . "&key=".$this->key;
		//签名步骤三:MD5加密
		$string = md5($string);
		//签名步骤四:所有字符转为大写
		$result = strtoupper($string);
		$this->value['sign'] = $result;
		return $result;
	}

	/**
	 * 格式化参数格式化成url参数
	 */
	public function ToUrlParams()
	{
		$buff = "";
		foreach ($this->value as $k => $v)
		{
			if($k != "sign" && $v != "" && !is_array($v)){
				$buff .= $k . "=" . $v . "&";
			}
		}

		$buff = trim($buff, "&");
		return $buff;
	}


	public function FromXml($xml)
	{
		if(!$xml){
			throw new \Exception("xml数据异常!");
		}
		//将XML转为array
		//禁止引用外部xml实体
		libxml_disable_entity_loader(true);
		$this->values = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
		return $this->values;
	}

	/**
	 * 以post方式提交xml到对应的接口url
	 *
	 * @param string $xml  需要post的xml数据
	 * @param string $url  url
	 * @param bool $useCert 是否需要证书,默认不需要
	 * @param int $second   url执行超时时间,默认30s
	 * @throws WxPayException
	 */
	private function postXmlCurl($xml, $url, $useCert = false, $second = 30)
	{
		$ch = curl_init();
		//设置超时
		curl_setopt($ch, CURLOPT_TIMEOUT, $second);
		curl_setopt($ch,CURLOPT_URL, $url);
		curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,TRUE);
		curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,2);//严格校验
		//设置header
		curl_setopt($ch, CURLOPT_HEADER, FALSE);
		//要求结果为字符串且输出到屏幕上
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
//        if($useCert == true){
		//设置证书
		//使用证书:cert 与 key 分别属于两个.pem文件
		curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
		curl_setopt($ch,CURLOPT_SSLCERT, $this->apiclient_key);
		curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
		curl_setopt($ch,CURLOPT_SSLKEY, $this->apiclient_cert);
//        }
		//post提交方式
		curl_setopt($ch, CURLOPT_POST, TRUE);
		curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
		//运行curl
		$data = curl_exec($ch);
		//返回结果
		if($data){
			curl_close($ch);
			return $data;
		} else {
			$error = curl_errno($ch);
			curl_close($ch);
//            throw new \Exception("curl出错,错误码:$error");
		}
	}


	public function RAS($str)
	{
		$public_pem     =   file_get_contents($this->public_pem);
		openssl_public_encrypt($str,$decrypted,$public_pem,OPENSSL_PKCS1_OAEP_PADDING);
		return base64_encode($decrypted);
	}


	public function partnerTradeNo($value)
	{
		$this->value['partner_trade_no']    =   $value;
	}
	public function nonceStr($value)
	{
		$this->value['nonce_str']           =   $value;
	}
	public function encBankNo($value)
	{
		$this->value['enc_bank_no']         =    $this->RAS($value);
	}
	public function encTrueName($value)
	{
		$this->value['enc_true_name']       =    $this->RAS($value);
	}
	public function bankCode($value)
	{
		$this->value['bank_code']           =    $value;
	}
	public function amount($value)
	{
		$this->value['amount']              =    $value;
	}
	public function desc($value)
	{
		$this->value['desc']                =    $value;
	}

}
<?php
        require './Xcxpay/Wxyxk.php';//引入刚刚的类
	    $mch_id                 =   '123456';
	    $key                    =   "1111111111";
	    $model                  =   new Wxyxk($mch_id,$key);
	    $model->apiclient_key   =   './Xcxpay/Certificate/Jw/apiclient_cert.pem';//证书路径 在商户平台下载 第一步获取的证书
	    $model->apiclient_cert  =   './Xcxpay/Certificate/Jw/apiclient_key.pem';//证书路径 在商户平台下载 第一步获取的证书
	    $model->public_pem      =   "./Xcxpay/Certificate/Jw/wx_public8.pem";//第二步获取的 微信RAS公匙
	    $model->partnerTradeNo($order_on);//订单号
		$model->nonceStr(md5(rand(1000,9999)));
		$model->encBankNo($employee_bank_info['bank_no']);//银行卡号
		$model->encTrueName($employee_bank_info['name']);//银行卡持卡人姓名
		$model->bankCode($employee_bank_info['bank_code']);//微信银行卡id 见下图
		$model->amount($amount);//金额
		$model->desc($declare);//订单说明
	    $result                 =   $model->sendRed();

200616_h5bc_736174.png

 

转载于:https://my.oschina.net/u/736174/blog/1601354

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值