微信的开发文档花里胡哨的看的眼花....我参考多种方法总结出来一个比较简单的单文件支付文件
以下为thinkphp5的示例
需要有授权登陆方可使用!!!!
注意命名空间,代码需要根据业务逻辑修改!!!
param();
unset($data['/shop/Pay/wexinpay_js_html']);
// 此处根据实际业务情况生成订单 然后拿着订单去支付(请根据实际业务更改)
$order_sn = date('Ymd') . substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8);
// 组合url
$url = url("shop/Pay/getParameters", array('out_trade_no' => $order_sn));
// 前往支付
echo json_encode($url);
}
/**
* 公众号支付 必须以get形式传递 out_trade_no 参数
*/
/**
* 获取jssdk需要用到的数据
* @return array jssdk需要用到的数据
*/
public function getParameters()
{
header("Access-Control-Allow-Origin: *");
$out_trade_no = request()->param('out_trade_no');
$openid='xxxxxx';//获取客户微信id
// 订单数据 请根据订单号out_trade_no 从数据库中查出实际的body、total_fee、out_trade_no、product_id
$order = array(
'body' => 'test',// 商品描述(需要根据自己的业务修改)
'total_fee' => 1,// 订单金额 以(分)为单位(需要根据自己的业务修改)
'out_trade_no' => $out_trade_no,// 订单号(需要根据自己的业务修改)
'product_id' => 1,// 商品id(需要根据自己的业务修改)
'trade_type' => 'JSAPI',// JSAPI公众号支付
'openid' => $openid// 获取到的openid
);
// 统一下单 获取prepay_id
$unified_order = $this->unifiedOrder($order);
// 获取当前时间戳
$time = time();
// 组合jssdk需要用到的数据
$data = array(
'appId' => 'wxpay.APPID', //appid
'timeStamp' => strval($time), //时间戳
'nonceStr' => $unified_order['nonce_str'],// 随机字符串
'package' => 'prepay_id=' . $unified_order['prepay_id'],// 预支付交易会话标识
'signType' => 'MD5'//加密方式
);
// 生成签名
$data['paySign'] = $this->makeSign($data);
echo json_encode($data);
exit();
// }
}
/**
* 统一下单
* @param array $order 订单 必须包含支付所需要的参数 body(产品描述)、total_fee(订单金额)、out_trade_no(订单号)、product_id(产品id)、trade_type(类型:JSAPI,NATIVE,APP)
*/
public function unifiedOrder($order)
{
// 生成随机加密盐
$nonce_str = $this->makeCode(32);
// 获取配置项
$config = array(
'appid' => 'wxpay.APPID',//appid
'mch_id' => 'wxpay.MCHID',//mch_id
'nonce_str' => $nonce_str,
'spbill_create_ip' => '192.168.0.1',
'notify_url' => 'XXXXXXXXX/Pay/isnotify'//你的域名
);
// 合并配置数据和订单数据
$data = array_merge($order, $config);
// 生成签名
$sign = $this->makeSign($data);
$data['sign'] = $sign;
$xml = $this->toXml($data);
$url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';//接收xml数据的文件
$header[] = "Content-type: text/xml";//定义content-type为xml,注意是数组
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 兼容本地没有指定curl.cainfo路径的错误
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
$response = curl_exec($ch);
if (curl_errno($ch)) {
// 显示报错信息;终止继续执行
die(curl_error($ch));
}
curl_close($ch);
$result = $this->toArray($response);
// 显示错误信息
if ($result['return_code'] == 'FAIL') {
die($result['return_msg']);
}
$result['sign'] = $sign;
$result['nonce_str'] = $nonce_str;
return $result;
}
/**
* 验证
* @return array 返回数组格式的notify数据
*/
public function notify()
{
// 获取xml
$xml = file_get_contents('php://input', 'r');
// 转成php数组
$data = $this->toArray($xml);
// 保存原sign
$data_sign = $data['sign'];
// sign不参与签名
unset($data['sign']);
$sign = $this->makeSign($data);
// 判断签名是否正确 判断支付状态
if ($sign === $data_sign && $data['return_code'] == 'SUCCESS' && $data['result_code'] == 'SUCCESS') {
$result = $data;
} else {
$result = false;
}
// 返回状态给微信服务器
if ($result) {
$str = ' ';
} else {
$str = ' ';
}
echo $str;
return $result;
}
public function isnotify()
{
$result = $this->notify();
if ($result) {
// // 验证成功 修改数据库的订单状态等 $result['out_trade_no']为订单id
$order = $result['out_trade_no'];
// 操作数据库修改购买状态
} else {
// 验证失败 那就没交易成功
$order = $result['out_trade_no'];
}
}
/**
* 输出xml字符
* @throws WxPayException
**/
public function toXml($data)
{
if (!is_array($data) || count($data) <= 0) {
throw new WxPayException("数组数据异常!");
}
$xml = "";
foreach ($data as $key => $val) {
if (is_numeric($val)) {
$xml .= "<" . $key . ">" . $val . "" . $key . ">";
} else {
$xml .= "<" . $key . ">" . $key . ">";
}
}
$xml .= " ";
return $xml;
}
/**
* 生成签名
* @return 签名,本函数不覆盖sign成员变量,如要设置签名需要调用SetSign方法赋值
*/
public function makeSign($data)
{
// 去空
$data = array_filter($data);
//签名步骤一:按字典序排序参数
ksort($data);
$string_a = http_build_query($data);
$string_a = urldecode($string_a);
//签名步骤二:在string后加入KEY
$string_sign_temp = $string_a . "&key=" . config('wxpay.KEY');
//签名步骤三:MD5加密
$sign = md5($string_sign_temp);
// 签名步骤四:所有字符转为大写
$result = strtoupper($sign);
return $result;
}
/**
* 将xml转为array
* @param string $xml xml字符串
* @return array 转换得到的数组
*/
public function toArray($xml)
{
//禁止引用外部xml实体
libxml_disable_entity_loader(true);
$result = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
return $result;
}
/**
* 生成随机串
* @param $count 随机串个数
*/
public function makeCode($count)
{
$chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
$nonce_str = '';
for ($i = 0; $i < $count; $i++) {
$nonce_str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
}
return $nonce_str;
}
/**
* curl 请求http
*/
public function curl_get_contents($url)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url); //设置访问的url地址
// curl_setopt($ch,CURLOPT_HEADER,1); //是否显示头部信息
curl_setopt($ch, CURLOPT_TIMEOUT, 5); //设置超时
curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']); //用户访问代理 User-Agent
curl_setopt($ch, CURLOPT_REFERER, $_SERVER['HTTP_HOST']); //设置 referer
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); //跟踪301
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); //返回结果
$r = curl_exec($ch);
curl_close($ch);
return $r;
}
/**
* 生成10位绝不重复订单号
*/
function order_number()
{
static $ORDERSN = array(); //静态变量
$ors = date('ymd') . substr(time(), -5) . substr(microtime(), 2, 5); //生成16位数字基本号
if (isset($ORDERSN[$ors])) { //判断是否有基本订单号
$ORDERSN[$ors]++; //如果存在,将值自增1
} else {
$ORDERSN[$ors] = 1;
}
return $ors . str_pad($ORDERSN[$ors], 2, '0', STR_PAD_LEFT); //链接字符串
}
}
前端进行请求获取参数调起微信支付
调用支付
可以使用,大致逻辑没问题......新手,勿喷