有学有练才叫学习:学而不思则罔,思而不学则殆:学而不习,纸上谈兵,习而不进,画地为牢!

ThinkPHP微信支付

php cat 6个月前 (04-22) 48次浏览 已收录 0个评论 扫描二维码

微信支付前期准备工作

1.已经认证的微信服务号(略)

2.拥有微信支付权限

3.下载微信官方SDK,并解压到ThinkPHP/ThinkPHP/Library/Vendor/WxPay/下

SDK下载地址: https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=11_1

4.下载商户证书,解压到服务器下,本例放置于pay/cert/下

5.配置账号信息Vendor/Wxpay/lib/WxPay.Config.php

/**
 *       配置账号信息
 */
class WxPayConfig
{
  //=======【基本信息设置】=====================================
  //
  /**
    * TODO: 修改这里配置为您自己申请的商户信息
    * 微信公众号信息配置
    * 
    * APPID:绑定支付的APPID(必须配置,开户邮件中可查看)
    * 
    * MCHID:商户号(必须配置,开户邮件中可查看)
    * 
    * KEY:商户支付密钥,参考开户邮件设置(必须配置,登录商户平台自行设置)
    * 设置地址:https://pay.weixin.qq.com/index.php/account/api_cert
    * 
    * APPSECRET:公众帐号secert(仅JSAPI支付的时候需要配置, 登录公众平台,进入开发者中心可设置),
    * 获取地址:https://mp.weixin.qq.com/advanced/advanced?action=dev&t=advanced/dev&token=2005451881&lang=zh_CN
    * @var string
    */
  const APPID = '8888888888888888';
  const MCHID = '8888888888';
  const KEY = '88888888888888888888888888888';
  const APPSECRET = '88888888888888888888888888';
  //=======【证书路径设置】=====================================
  /**
    * TODO:设置商户证书路径
    * 证书路径,注意应该填写绝对路径(仅退款、撤销订单时需要,可登录商户平台下载,
    * API证书下载地址:https://pay.weixin.qq.com/index.php/account/api_cert,下载之前需要安装商户操作证书)
    * @var path
    */
  const SSLCERT_PATH = '/www/pay/cert/apiclient_cert.pem';
  const SSLKEY_PATH = '/www/pay/cert/apiclient_key.pem';
  const CAINFO_PATH = '/www/pay/cert/rootca.pem';
  //=======【curl代理设置】===================================
  /**
    * TODO:这里设置代理机器,只有需要代理的时候才设置,不需要代理,请设置为0.0.0.0和0
    * 本例程通过curl使用HTTP POST方法,此处可修改代理服务器,
    * 默认CURL_PROXY_HOST=0.0.0.0和CURL_PROXY_PORT=0,此时不开启代理(如有需要才设置)
    * @var unknown_type
    */
  const CURL_PROXY_HOST = "0.0.0.0";
  const CURL_PROXY_PORT = 0;
  
  //=======【上报信息配置】===================================
  /**
    * TODO:接口调用上报等级,默认紧错误上报(注意:上报超时间为【1s】,上报无论成败【永不抛出异常】,
    * 不会影响接口调用流程),开启上报之后,方便微信监控请求调用的质量,建议至少
    * 开启错误上报。
    * 上报等级,0.关闭上报; 1.仅错误出错上报; 2.全量上报
    * @var int
    */
  const REPORT_LEVENL = 1;
}

扫码支付模式二

业务流程:

1、用户在页面下订单,数据提交到数据库,自动跳转到支付页面

数据模拟:

$data = array(
  'id' => 1,
  'name' => 'XXX商品',
  'price' => 100, // 单位:分
  'time' => '20161012100000',
  'payment_status' => 0, // 支付状态 未支付
  'status' => 0, // 订单状态 未处理
);

2、支付页面接收参数,获取数据数据信息,调用微信支付,生成二维码,并展示在支付页面上

3、用户在规定时间内通过扫码方式进行支付

4、用户支付完成后,接收微信服务器发送的通知,处理业务逻辑并回应微信服务器

update table set payment_status = 1 where id = 1; // 设置为已支付状态

5、完成支付!

支付页面代码:

class IndexController extends Controller {
  // 控制器初始化方法
  public function _initialize() {
    // 自动加载类
    vendor( 'WxPay.lib.WxPay#Api' );
    vendor( 'WxPay.example.WxPay#NativePay' );
    vendor( 'WxPay.example.log' );
  }

  public function index(){
    $id = I('get.id');
    
    // 此处获取订单数据信息,计算出商品总金额
    [ code.... ]
    // 实例化支付模型
    $notify = new \NativePay();
    $total_fee = 1; // 通过计算得出的商品总金额,单位:分,此处为模拟数据
    /**
     * 流程:
     * 1、调用统一下单,取得code_url,生成二维码
     * 2、用户扫描二维码,进行支付
     * 3、支付完成之后,微信服务器会通知支付成功
     * 4、在支付成功通知中需要查单确认是否真正支付成功(见:notify.php)
     */
    $input = new \WxPayUnifiedOrder();
    $input->SetBody("购买xxxx支付"); // 支付标题
    $input->SetAttach("{$id}"); // 商家数据包
    $input->SetOut_trade_no(\WxPayConfig::MCHID.date("YmdHis")); // 支付订单号
    $input->SetTotal_fee("{$total_fee}"); // 支付总价 (单位: 分)
    $input->SetTime_start(date("YmdHis")); // 支付链接生成时间
    $input->SetTime_expire(date("YmdHis", time() + 600)); // 支付链接过期时间
    $input->SetGoods_tag("goods_tag"); // 商品标签
    $input->SetNotify_url("http://www.xxxx.com/notify.html"); // 支付回调地址
    $input->SetTrade_type("NATIVE"); // 支付模式
    $input->SetProduct_id("{$info['sn_code']}"); // 商品ID
    $result = $notify->GetPayUrl($input); // 获取URL
    $url = urlencode($result["code_url"]);
    $return_info['url'] = $url;
    
    exit(I('get.jsoncallback') . "(" . json_encode($return_info) . ")");
    /**
     * 页面通过Ajax请求获取微信支付返回数据,
     * 接收数据并再次请求prcode方法获取二维码 并输出到页面上
     */
  }

  // 输出二维码
  public function qrcode() {
    Vendor( 'WxPay.example.phpqrcode.phpqrcode');
    $url = I('get.data','urldecode');
    $qr = new \QRcode;
    $qr::png($url);
  }

  // 接收微信端返回的数据 , 支付回调地址
  // 微信支付服务器会在半小时内请求8次这个方法(好像是这样的,具体忘了),直到此方法返回"SUCCESS"状态后终止
  public function notify() {
    header("content-type:text/xml");
    $xml = $GLOBALS['HTTP_RAW_POST_DATA'];
    //将XML转为array
    //禁止引用外部xml实体
    libxml_disable_entity_loader(true);
    $data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);

    if($data['result_code'] == "SUCCESS" && $data['return_code'] == "SUCCESS" ) {
      // 此处处理你的业务逻辑,如更新订单支付状态
      [ code.... ]

      // 返回成功状态码,告诉微信端别再请求这个页面了!
      echo "SUCCESS";
      exit;
    }
  }
}

JsApi

业务流程:

1、用户在微信客户端访问页面,授权服务器获取用户资料,并下订单,数据提交到数据库,自动跳转到支付页面

2、支付页面接收参数,生成支付链接

3、用户在规定时间内进行支付

4、用户完成支付后,接收微信服务器发送的通知,处理业务逻辑并回应微信服务器

5、完成支付并返回用户之前访问的页面

代码如下:

class JsApiController extends Controller {
  public function _initialize() {
    // 自动加载类
    Vendor('WxPay.lib.WxPay#Api');
    Vendor('WxPay.example.WxPay#JsApiPay');
    Vendor('WxPay.example.log');
  }

  public function index() {
    // 获取订单信息,计算出商品总金额
    [ code.... ]
    $total_fee = 1; // 数据模拟
    
    // 获取用户openid
    $tools = new \JsApiPay();
    $openId = $tools->GetOpenid();
    // 统一下单        
    $input = new \WxPayUnifiedOrder();
    $input->SetBody("商品xxxx支付");
    $input->SetAttach("{$id}");
    $input->SetOut_trade_no(\WxPayConfig::MCHID.date("YmdHis"));
    $input->SetTotal_fee("{$total_fee}");
    $input->SetTime_start(date("YmdHis"));
    $input->SetTime_expire(date("YmdHis", time() + 600));
    $input->SetGoods_tag("goods_tag");
    $input->SetNotify_url("http://www.xxx.com/notify.html");
    $input->SetTrade_type("JSAPI");
    $input->SetOpenid($openId);
    $order = \WxPayApi::unifiedOrder($input);
    $jsApiParameters = $tools->GetJsApiParameters($order);
    $this->assign('jsApiParameters',$jsApiParameters);
    $this->display();
  }

  // 接收微信端返回的数据
  public function notify() {
    $xml = $GLOBALS['HTTP_RAW_POST_DATA'];
    //将XML转为array
    //禁止引用外部xml实体
    libxml_disable_entity_loader(true);
    $data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
    if($data['result_code'] == "SUCCESS" && $data['return_code'] == "SUCCESS" ) {
      // 此处处理你的业务逻辑
      [ code.... ]
      
      // 返回成功状态码,告诉微信端别再请求这个页面了!
      echo "SUCCESS";
      exit;
    }
  }
}

index.html:

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>订单支付</title>
  <meta name="viewport" content="width=device-width, initial-scale=1"/>
  <script type="text/javascript">
    //调用微信JS api 支付
    function jsApiCall()
    {
      WeixinJSBridge.invoke(
        'getBrandWCPayRequest',
        {$jsApiParameters},
        function(res){
          if(res.err_msg == "get_brand_wcpay_request:ok" ) {
            alert("支付成功");
            window.location.href = "{$url}";
          } else {
            alert("支付失败");
            window.location.href= "{$url}";
          }
        }
      );
    }

    function callpay()
    {
      if (typeof WeixinJSBridge == "undefined"){
        if( document.addEventListener ){
          document.addEventListener('WeixinJSBridgeReady', jsApiCall, false);
        }else if (document.attachEvent){
          document.attachEvent('WeixinJSBridgeReady', jsApiCall); 
          document.attachEvent('onWeixinJSBridgeReady', jsApiCall);
        }
      }else{
        jsApiCall();
      }
    }
  </script>
</head>
<body onload="callpay()">
<!--
  <font color="#9ACD32"><b>该笔订单支付金额为<span style="color:#f00;font-size:50px">1分</span>钱</b></font><br/><br/>
  <div>
    <button style="width:210px; height:50px; border-radius: 15px;background-color:#FE6714; border:0px #FE6714 solid; cursor: pointer;  color:white;  font-size:16px;" type="button" onclick="callpay()" >立即支付</button>
  </div>
-->
</body>
</html>

 

喜欢 (0)
cat
关于作者:
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址