PHP---微信支付【Native支付】

最近在整合一些第三方平台代码,首先就是微信支付相关:

微信支付相关文档:

https://pay.weixin.qq.com/wiki/doc/api/index.html

Native支付文档:

https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_1

SDK下载地址:

https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=11_1

扫码支付模式一

适用场景:商店打印二维码支付

<?php

const MCHID = ''; // 商户号
const APPID = ''; // 公众号APPID
const KEY = ''; // API密钥
const APPSECRET = ''; // APPSECRET

include('phpqrcode/phpqrcode.php');

// 扫码支付模式一
// 适用场景:商店打印二维码支付
$product_id = "10000";
$url = generateScanUrl($product_id);
QRcode::png($url);

// 生成扫码URL
function generateScanUrl($product_id){
  $params = [
    'appid' => APPID,
    'mch_id' => MCHID,
    'nonce_str' => uniqid(), // 随机字符串
    'time_stamp' => strval(time()),
    'product_id' => $product_id
  ];
  $params['sign'] = generateSign($params,KEY); // 签名
  $prefix = 'weixin://wxpay/bizpayurl?'; // 微信网关地址
  $url = $prefix . http_build_query($params);
  return $url;
}

// 生成签名
function generateSign($params,$key,$encrypt = 'md5'){
  ksort($params); // 将集合排序
  $params['key'] = $key; // 拼接KEY
  $str = http_build_query($params); // 转化为URL字符串
  return strtoupper(md5(urldecode($str))); // md5加密
}

然后访问即可看到支付二维码:

扫码支付二:订单挂钩

<?php

const MCHID = '1601870095'; // 商户号
const APPID = 'wx1868670b98dbcd5c'; // 公众号APPID
const KEY = 'sadlkjdgLKJ3213KJHKJHfasdf324234'; // API密钥
const APPSECRET = 'sadlkjdgLKJ3213KJHKJHfasdf324234'; // APPSECRET

const API_URL = 'https://api.mch.weixin.qq.com/pay/unifiedorder'; // 网关

include('phpqrcode/phpqrcode.php');

// 扫码支付二:订单挂钩
// 需要预支付单号 - 调用统一下单接口
$params = [
  'body' => '我是一个支付的标题',
  'detail' => '我是一个支付的描述',
  'out_trade_no' => time() . mt_rand(1000,9999), // 生产订单号 通常在加入购物车 还未支付的时候生成
  'total_fee' => 100,// 单位是分
  'notify_url' => 'http://danzhao.ynzzwl.com/huidiao.php',// 微信回调 - 必须是外网的地址
  // 'openid' => '',特定人支付 选填
  'appid' => APPID,
  'mch_id' => MCHID,
  // 'spbill_create_ip' => '127.0.0.1' // 防止钓鱼,指定IP
  'trade_type' => 'NATIVE' // 交易类型 [JSAPI,NATIVE,APP]
];
$result = prepare($params);
$url = $result['code_url'];
QRcode::png($url); // 生成支付二维码

// 统一下单
function prepare($config){
  $config['nonce_str'] = uniqid();
  $config['sign'] = generateSign($config,KEY); // 签名
  $xml = toXml($config); // 转化为XML格式
  // 统一下单
  $result = curlPost('https://api.mch.weixin.qq.com/pay/unifiedorder', $xml);
  return xmlToArray($result);
}

// 生成签名
function generateSign($params,$key,$encrypt = 'md5'){
  ksort($params); // 将集合排序
  $params['key'] = $key; // 拼接KEY
  $str = http_build_query($params); // 转化为URL字符串
  return strtoupper(md5(urldecode($str))); // md5加密
}

// toXml
function toXml($params){
  $xml = "<xml>";
  foreach($params as $key => $value){
    if(is_numeric($value)){
      $xml .= "<$key>$value</$key>";
    }else{
      $xml .= "<$key><![CDATA[$value]]></$key>";
    }
  }
  $xml .= "</xml>";
  return $xml;
}

// xml to array
function xmlToArray($xml){ 
  if(!$xml){ throw new WxPayException("xml数据异常!"); }
  libxml_disable_entity_loader(true); // 禁止引用外部xml实体
  return json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
}

function curlPost($url = '', $postData = '', $options = array())
{
    if (is_array($postData)) {
      $postData = http_build_query($postData);
    }
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
    curl_setopt($ch, CURLOPT_TIMEOUT, 30); //设置cURL允许执行的最长秒数
    if (!empty($options)) {
      curl_setopt_array($ch, $options);
    }
    //https请求 不验证证书和host
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
    $data = curl_exec($ch);
    curl_close($ch); 
    return $data;
}

支付回调:

<?php

// 回调接受微信支付成功回调
// 1、怎么调试
$info = file_get_contents("php://input");
// 2、安全性:a、同一微信多次回调如何处理;别人伪造微信支付回调怎么处理。
// 安全性:别人能够伪造请求,但是不能伪造签名,可以写一个方法来校验签名;其次是比对订单金额;
// 或者是指定IP是微信的IP
// 判断订单状态是否是已经支付完成,支付完成,下面这些代码都无需执行
$order = xmlToArray($info);
$trade['order'] = $order['out_trade_no'];
$trade['total_fee'] = $order['total_fee'];
// 3、针对微信的消息做处理
// 签名处理
$mySign = generateSign($order,KEY);
if($trade['total_fee'] == '10' && $mySign == $order['sign']){
  // 更改订单状态 更改订单状态之前需要先去查询订单状态,如果是已支付,就不需要处理了
  // 具体代码
  // 通知微信我们已接收到信息,不要再给我们发该条订单的请求,不然会给你发9次消息
  // 频率:15,15,30,180,1800,1800,1800,3600
  echo "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
}else{
  // 不做任何处理
}

function generateSign($params,$key,$encrypt = 'md5'){
  // 将集合排序
  ksort($params);
  $params['key'] = $key; // 拼接KEY
  // 转化为URL字符串
  $str = http_build_query($params);
  // md5 加密
  return strtoupper(md5(urldecode($str)));
}

微信支付回调非常重要,具体可以参考【官方示例代码】具体位于:示例代码 / example / notify.php

示例:

打完收工!

posted @ 2022-07-16 09:29  帅到要去报警  阅读(1304)  评论(0编辑  收藏  举报