ThinkPHP V5.0 接入微信支付
微信支付接口
组装访问数组
$data['body'] = '商城购买商品';//订单标题 $data['out_trade_no'] = generate_rand_str(8, 0);//平台订单号(非小程序订单,自己平台生成的) $data['notify_url'] = $this->request->domain().'';//微信支付回调地址,不带参数 $data['total_fee'] = $price;//价格,单位(元) $data['openid'] = $this->user['openid'];//用户openid $res = $this->unifiedorder($config['wechat_appid'],$config['wechat_mch_id'],$config['wechat_key'],$data);//访问统一下单
统一下单
/** * 统一下单方法 * $appid 小程序id * $mchid 商户号 * $key 微信支付key * $data 信息数组 * */ public function unifiedorder($appid,$mch_id,$key,$data) { $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';//微信统一下单访问url $parameters = array( 'appid' => $appid, //小程序ID 'mch_id' => $mch_id, //商户号 'nonce_str' => generate_rand_str(8, 0), //随机字符串 'body' => $data['body'], //商品描述 'out_trade_no' => $data['out_trade_no'], //商户订单号 'total_fee' => floatval($data['total_fee'] * 100), //总金额 单位 分 'spbill_create_ip' => $_SERVER['REMOTE_ADDR'], //终端IP 'notify_url' => $data['notify_url'].'index.php/callback', //通知地址 确保外网能正常访问 'openid' => $data['openid'], //用户id 'trade_type' => 'JSAPI'//交易类型//要是返回该产品权限未开通请在产品中心开通jsAPi他包含的小程序支付 ); //统一下单签名 $parameters['sign'] = $this->getSign($parameters,$key); $xmlData = $this->arrayToXml($parameters); $return = $this->xmlToArray($this->postXmlCurl($xmlData, $url, 60)); return $return; }
生成随机数
/**
* 生成随机字符串
* @param int $length 生成长度
* @param int $type 生成类型:0-小写字母+数字,1-小写字母,2-大写字母,3-数字,4-小写+大写字母,5-小写+大写+数字
* @return string
*/
function generate_rand_str($length = 8, $type = 0) {
$a = 'abcdefghijklmnopqrstuvwxyz';
$A = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
$n = '0123456789';
switch ($type) {
case 1: $chars = $a; break;
case 2: $chars = $A; break;
case 3: $chars = $n; break;
case 4: $chars = $a.$A; break;
case 5: $chars = $a.$A.$n; break;
default: $chars = $a.$n;
}
$str = '';
for ($i = 0; $i < $length; $i++) {
$str .= $chars[ mt_rand(0, strlen($chars) - 1) ];
}
return $str;
}
生成签名
/**
* 生成签名
* @param array $Obj 访问数组
* @param string $key 商户key
* @return string
*/
public function getSign($Obj,$key) {
foreach ($Obj as $k => $v) {
$Parameters[$k] = $v;
}
//签名步骤一:按字典序排序参数
ksort($Parameters);
$String = $this->formatBizQueryParaMap($Parameters, false);
//签名步骤二:在string后加入KEY
$String = $String . "&key=" . $key;
//签名步骤三:MD5加密
$String = md5($String);
//签名步骤四:所有字符转为大写
$result_ = strtoupper($String);
return $result_;
}
格式化参数,签名过程需要使用
//作用:格式化参数,签名过程需要使用
public function formatBizQueryParaMap($paraMap, $urlencode) {
$buff = "";
ksort($paraMap);
foreach ($paraMap as $k => $v) {
if ($urlencode) {
$v = urlencode($v);
}
$buff .= $k . "=" . $v . "&";
}
$reqPar = array();
if (strlen($buff) > 0) {
$reqPar = substr($buff, 0, strlen($buff) - 1);
}
return $reqPar;
}
数组转换成xml
//数组转换成xml
public function arrayToXml($arr) {
$xml = "<root>";
foreach ($arr as $key => $val) {
if (is_array($val)) {
$xml .= "<" . $key . ">" . $this->arrayToXml($val) . "</" . $key . ">";
} else {
$xml .= "<" . $key . ">" . $val . "</" . $key . ">";
}
}
$xml .= "</root>";
return $xml;
}
xml格式访问
public function postXmlCurl($xml, $url, $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, FALSE); //严格校验
//设置header
curl_setopt($ch, CURLOPT_HEADER, FALSE);
//要求结果为字符串且输出到屏幕上
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
//post提交方式
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 20);
curl_setopt($ch, CURLOPT_TIMEOUT, 40);
set_time_limit(0);
//运行curl
$data = curl_exec($ch);
//返回结果
curl_close($ch);
return $data;
}
将xml转换成数组
public 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;
}
微信支付成功回调接口
//微信支付回调
public function callback()
{
$postXml = file_get_contents("php://input");//获取回调的xml格式
$attr = $this->xmlToArray($postXml);//将获取的xml转为数组
if($attr['result_code'] == 'SUCCESS'){
//在此书写支付成功后的逻辑
return true;
}else{
//在此书写支付失败后的逻辑
return false;
}
}