1.先封装类
class Wxtrans{
/**
* 以post方式提交xml到对应的接口url
*
* @param string $xml 需要post的xml数据
* @param string $url url
* @param bool $useCert 是否需要证书,默认不需要
* @param int $second url执行超时时间,默认30s
* @throws WxPayException
*/
public 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,false);
curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,2);//严格校验
//
//设置header
curl_setopt($ch, CURLOPT_HEADER, FALSE);
//要求结果为字符串且输出到屏幕上
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$cpy_sslcert_path = '../plugins/payment/weixin/wxtrans/apiclient_cert.pem';
$cpy_sslkey_path = '../plugins/payment/weixin/wxtrans/apiclient_key.pem';
if($useCert == true){
//设置证书
//使用证书:cert 与 key 分别属于两个.pem文件
curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
curl_setopt($ch,CURLOPT_SSLCERT, $cpy_sslcert_path);
curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
curl_setopt($ch,CURLOPT_SSLKEY, $cpy_sslkey_path);
}
//post提交方式
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
//运行curl
$data = curl_exec($ch);
// if (curl_errno ( $ch )) {
// echo 'Errno' . curl_error ( $ch );
// }
//返回结果
if($data){
curl_close($ch);
return $data;
} else {
$error = curl_errno($ch);
curl_close($ch);
return false;
}
}
/**
* 作用:格式化参数,签名过程需要使用
*/
public function formatBizQueryParaMap($paraMap, $urlencode)
{
$buff = "";
ksort($paraMap);
foreach ($paraMap as $k => $v)
{
if($urlencode)
{
$v = urlencode($v);
}
$buff .= $k . "=" . $v . "&";
}
$reqPar;
if (strlen($buff) > 0)
{
$reqPar = substr($buff, 0, strlen($buff)-1);
}
return $reqPar;
}
/**
* 作用:生成签名
* $obj 数组
* $key 商户key
*/
public function getSign($Obj){
foreach ($Obj as $k => $v){
$Parameters[$k] = $v;
}
ksort($Parameters);
$String = $this->formatBizQueryParaMap($Parameters, false);//方法如下
$key = config('APP_KEY');
$String = $String."&key=".$key;
$String = md5($String);
$result_ = strtoupper($String);
return $result_;
}
public function getTrans($openid,$amount,$desc,$partner_trade_no){
//封装数据
$cpy_appid = config('APP_APPID'); //公众号appid
$cpy_mchid = config('APP_MCHID'); //商户id
$cpy_nonce_str = $this->genRandomString(); //随机字符串
$cpy_order_str = $partner_trade_no; // 唯一订单号
$cpy_openid = $openid; //公众号appid 所获取的用户openid
$ip = $_SERVER['SERVER_ADDR'];
$dataArr = array(
'mch_appid' => $cpy_appid,
'mchid' => $cpy_mchid,
'nonce_str' => $cpy_nonce_str,
'partner_trade_no' => $cpy_order_str,
'openid' => $cpy_openid,
'check_name' => 'NO_CHECK',
're_user_name' => 'test', //填写对应openid真实姓名
'amount' => $amount, //以分为单位,必须大于100
'desc' => $desc,
'spbill_create_ip' => $ip,
);
//生成签名
$sign=$this->getSign($dataArr);
$xml = '<info>
<mch_appid>'.$dataArr['mch_appid'].'</mch_appid>
<mchid>'.$dataArr['mchid'].'</mchid>
<nonce_str>'.$dataArr['nonce_str'].'</nonce_str>
<partner_trade_no>'.$dataArr['partner_trade_no'].'</partner_trade_no>
<openid>'.$dataArr['openid'].'</openid>
<check_name>'.$dataArr['check_name'].'</check_name>
<re_user_name>'.$dataArr['re_user_name'].'</re_user_name>
<amount>'.$dataArr['amount'].'</amount>
<desc>'.$dataArr['desc'].'</desc>
<spbill_create_ip>'.$dataArr['spbill_create_ip'].'</spbill_create_ip>
<sign>'.$sign.'</sign>
</info>';
$url = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers';
$data = $this->postXmlCurl($xml, $url, true);
return $this->xmlToArray($data);
}
function xmlToArray($xml){
//禁止引用外部xml实体
libxml_disable_entity_loader(true);
$xmlstring = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
$val = json_decode(json_encode($xmlstring),true);
return $val;
}
private function genRandomString($len = 32) {
$chars = array(
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k",
"l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v",
"w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G",
"H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R",
"S", "T", "U", "V", "W", "X", "Y", "Z", "0", "1", "2",
"3", "4", "5", "6", "7", "8", "9"
);
$charsLen = count($chars) - 1;
// 将数组打乱
shuffle($chars);
$output = "";
for ($i = 0; $i < $len; $i++) {
$output .= $chars[mt_rand(0, $charsLen)];
}
return $output;
}
//生成订单号
public function getordersn(){
$yCode = array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J');
$orderSn = $yCode[intval(date('Y')) - 2011] . strtoupper(dechex(date('m'))) . date('d') . substr(time(), -5) . substr(microtime(), 2, 5) . sprintf('%02d', rand(0, 99));
return $orderSn;
}
}
2.调用里面的getTrans方法
$trans =new Wxtrans();
$data = $trans->getTrans($userinfo['openid'],$userinfo['cash_real']*100,$desc,$userinfo['partner_trade_no']);
// $data = $trans->getTrans('oPfEGwVBZB3L4v0RHT7eDOJXhgtg',100);
$return_code = $data['return_code'];
$result_code = $data['result_code'];
if($userinfo['cash_real']<1){
$this->error( '打款金额必须大于1元!', '');
}
$update_time = time();
if($return_code == 'SUCCESS'&&$result_code !== 'FAIL'){
$res = db('v_cash')->where(['id'=>$id,'uid'=>$uid])->update(['status' => $status,'payment_no'=>$data['payment_no'],'update_time'=>$update_time]);
if($res){
$this->success( '处理成功', url('lists'));
}else{
$this->error( '更新状态失败', '');
}
}else{
$this->error( '企业付款参数错误或账户余额不足', '');
}