使用jsapi微信支付需要两次加密过程,首先通过自己的业务参数来进行加密,去生成签名请求微信服务器、微信服务器会返回给你一个结果、根据返回的结果判断是否需要二次加密、代码如下。
$WecatPay = new \app\lib\WecatPay();
$request = \think\Request::instance();
$openId = input("post.openid"); // openId 前端小程序发送给你的
$nowTime = date("Y-m-d H:i:s");
$appId = \think\Config::get('wecat.appid');
$secert = \think\Config::get('wecat.secert');
$mch_id = \think\Config::get('wecat.mch_id');
$url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
$nonceStr = getRandomStr(32);
$time = time();
settype($time,'string');
$orderNum = $WecatPay->getOrderNumber('HXFIB');// orderNum 为随机生成的订单号,根据个人业务场景来生成
由于微信服务端需要一个字符串时间戳,而php的time()函数获取到的为整数类型、所以在这里使用settype方法转为strting类型参数。
将业务参数存入数组中,并调用生成签名方法(此处WecatPay类为个人封装的工具类)
$data = array(
'appid' => $appId,
'body' => '微信(在线支付)',
'mch_id' => $mch_id,
'nonce_str' => $nonceStr,
'notify_url' => '这里填写你的回调地址',
'out_trade_no' => $orderNum,
'openid' => $openId,
'spbill_create_ip' => $request->ip(),
'total_fee' => $BusinessOnePayNumber * 100,
'trade_type' => 'JSAPI'
);
$data['sign'] = $WecatPay->MakeSign($data);
生成签名方法如下
/**
* 生成sign签名
* @param array $data
* @return string
*/
public function MakeSign($data) {
$key = \think\Config::get('wecat.pay_key');
ksort($data);
$buff = '';
foreach ($data as $k => $v) {
if ($k != 'sign' && $v != '' && !is_array($v)) {
$buff .= $k . '=' . $v . '&';
}
}
$buff = trim($buff, '&');
$str = $buff . '&key=' . $key;
$str = md5($str);
return strtoupper($str);
}
方法返回生成的签名,在上步代码逻辑中已将签名存到$data数组中。
将业务数组转换为xml格式
$xmldata = $WecatPay->xml($data); //调用工具类转换方法
/**
* array 转 xml
* @param string $param
*/
public function xml($param) {
ksort($param);
$data_xml = "<xml>";
foreach ($param as $key => $val) {
if (is_numeric($val)) {
$data_xml .= '<' . $key . '>' . $val . '</' . $key . '>';
} else {
$data_xml .= '<' . $key . '><![CDATA[' . $val . ']]></' . $key . '>';
}
}
$data_xml .= '</xml>';
return $data_xml;
}
发送请求,并根据结果判断是否需要二次加密
$res = \app\lib\HttpServer::sendHttp($url,$xmldata,1);
$result = $WecatPay->xmlToArray($res);
if ($result['return_code'] == 'SUCCESS'){
$info = array(
'appId' => $appId,
'timeStamp' => $time,
'nonceStr' => $nonceStr,
'package' => 'prepay_id='.$result['prepay_id'],
'signType' => 'MD5'
);
$sign = $WecatPay->MakeSign($info); // 二次签名加密
returnCode(1,[
'nonceStr' => $info['nonceStr'],
'openid' => $openId,
'orderNum' => $orderNum,
'package' => $result['prepay_id'],
'paySign' => $sign,
'fibPriceInfoId' => null,
'timeStamp' => $time,
'tradenum' => $orderNum
]);
}else{
returnCode(-1,[],'发起支付请求失败!');
}
/**
* 发送请求
* @param string $url
* @param boolean $params
* @param number $ispost
* @param array $header
* @param boolean $verify
* @return boolean|mixed
*/
public static function sendHttp($url, $params = false, $ispost = 0, $header = [], $verify = false) {
$httpInfo = array();
$ch = curl_init();
if (!empty($header)) {
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
}
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 60);
curl_setopt($ch, CURLOPT_TIMEOUT, 60);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
if ($verify === true) {
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
} else {
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
}
if ($ispost) {
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
curl_setopt($ch, CURLOPT_URL, $url);
} else {
if (is_array($params)) {
$params = http_build_query($params);
}
if ($params) {
curl_setopt($ch, CURLOPT_URL, $url . '?' . $params);
} else {
curl_setopt($ch, CURLOPT_URL, $url);
}
}
$response = curl_exec($ch);
if ($response === FALSE) {
trace("cURL Error: " . curl_errno($ch) . ',' . curl_error($ch), 'error');
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$httpInfo = array_merge($httpInfo, curl_getinfo($ch));
trace($httpInfo, 'error');
return false;
}
curl_close($ch);
return $response;
}
//将XML转为array
public function xmlToArray($xml) {
//禁止引用外部xml实体
libxml_disable_entity_loader(true);
$values = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
return $values;
}