Using jsapi WeChat payment requires two encryption processes. First, encrypt it through your own business parameters to generate a signature request to the WeChat server. The WeChat server will return a result to you. According to the returned result, it is judged whether secondary encryption is required. The code is as follows.
$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 为随机生成的订单号,根据个人业务场景来生成
Since the WeChat server needs a string timestamp, and the PHP time() function obtains an integer type, so use the settype method to convert it to a strting type parameter here.
Store the business parameters in the array, and call the signature generation method (here, the WecatPay class is a tool class encapsulated by individuals)
$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);
The method of generating the signature is as follows
/**
* 生成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);
}
The method returns the generated signature, which has been stored in the $data array in the previous code logic.
Convert business array to xml format
$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;
}
Send a request and judge whether secondary encryption is required based on the result
$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;
}