php版微信js-sdk支付接口类用法示例


Posted in PHP onOctober 12, 2016

本文实例讲述了php版微信js-sdk支付接口类用法。分享给大家供大家参考,具体如下:

这个支付类是根据官方的文档修改而来!主要实现生成JS API 、Native的package签名包和Native响应的XML格式数据。注释都标上了各方法的用意。由于package包签名,略复杂,这个要自己多花时间去对应去看和log出文件来一一对比!当然只要你用上教程的类,设置好对应的参数就可以正确的生成package参数等

<?php
if (isset($argc) && $argc >= 1 && $argv[0] == __FILE__) {
  //初始化pay的必要信息
  $pay = new WechatPay(array(
    WechatPay::APPID => 'wx99dabzpiuq83985b8',
    WechatPay::APPSERCER => 'ac12e7e4abaer63hkoa0cc36a9663fa',
    WechatPay::PARTNERKEY => 'bae4sfa3562rsfaq23s2045',
    WechatPay::PARTNERID => '1268969802',
    WechatPay::PAYSIGNKEY => '9Fqsxb3PK4IVOCEc4yCquy5zecS9LeeMjF2Nn4B4YKoOxPwaQdFwMezKT8oNlBYaWcuT',
    WechatPay::SIGNTYPE => 'sha1',
  ));
  //设置package 必要的参数 jsapi native都通用
  $pay->setParams(WechatPay::BANK_TYPE, "WX");
  $pay->setParams(WechatPay::BODY, "test");
  $pay->setParams(WechatPay::PARTNER, $pay->partnerid);
  $pay->setParams(WechatPay::OUT_TRADE_NO, commonUtil::createNoncestr());
  $pay->setParams(WechatPay::TOTAL_FEE, "1");
  $pay->setParams(WechatPay::FEE_TYPE, "1");
  $pay->setParams(WechatPay::TIMESTAMP, time());
  $pay->setParams(WechatPay::NOTIFY_URL, "http://www.demo.com/notify");
  $pay->setParams(WechatPay::SPBILL_CREATE_IP, "127.0.0.1");
  $pay->setParams(WechatPay::INPUT_CHARSET, "UTF-8");
  //JSAPI的签名json
  print_r($pay->createJsApiPackage());
  //生成native XML
  print_r($pay->createNativePackage());
  //生成native URL
  print_r($pay->createNativeUrl("9701"));
}

JS API生成的package签名包参数:

{
  "appId":"wx9998ff5f4dede5b7",
  "package":"bank_type=WX&body=test&fee_type=1&input_charset=UTF-8¬ify_url=http%3A%2F%2Fwww.demo.com%2Fnotify&out_trade_no=Vf5qsSwtu0hc2loH&partner=wx9998ff5f4dede5b7&spbill_create_ip=127.0.0.1×tamp=1409295711&total_fee=1&sign=FEE0167BD0D89A88BF6850590EA889B6",
  "timeStamp":1409295711,
  "nonceStr":"Vf5qsSwtu0hc2loH",
  "paySign":"f816264c750923863c370a1739640244b0c2d39c",
  "signType":"sha1"
}

Native 响应的XML格式:

<xml>
  <AppId><![CDATA[wx9998ff5f4dede5b7]]></AppId>
  <Package>
    <![CDATA[bank_type=WX&body=test&fee_type=1&input_charset=UTF-8¬ify_url=http%3A%2F%2Fwww.demo.com%2Fnotify&out_trade_no=GDl3what4sALDEAd&partner=wx9998ff5f4dede5b7&spbill_create_ip=127.0.0.1×tamp=1409296124&total_fee=1&sign=BF949B85570644B939B369FD44B0C4A9]]>
  </Package>
  <TimeStamp>1409296124</TimeStamp>
  <NonceStr><![CDATA[GDl3what4sALDEAd]]></NonceStr>
  <RetCode>0</RetCode>
  <RetErrMsg><![CDATA[ok]]></RetErrMsg>
  <AppSignature><![CDATA[ca4a2467b817a62c38a9801fcf451f51692027bf]]></AppSignature>
  <SignMethod><![CDATA[sha1]]></SignMethod>
</xml>

Native的URL链接:

weixin://wxpay/bizpayurl?appid=wx9998ff5f4dede5b7&noncestr=VY7cVA6mtVrc1BVq&productid=9701&sign=43508b65b50e1d7e1089be66d55a709469155d73×tamp=1409296323

无论哪一种方式,我们都要通过setParams来设置必要初始化参数和商品价格和状态等!

WechatPay class:

<?php
class WechatPay {
  const
    BANK_TYPE = 'bank_type',
    BODY = 'body',
    PARTNER = 'partner',
    OUT_TRADE_NO = 'out_trade_no',
    TIMESTAMP = 'timestamp',
    TOTAL_FEE = 'total_fee',
    FEE_TYPE = 'fee_type',
    NOTIFY_URL = 'notify_url',
    SPBILL_CREATE_IP = 'spbill_create_ip',
    INPUT_CHARSET = 'input_charset',
    APPID = 'appid',
    APPSERCER = 'appsercer',
    PAYSIGNKEY = 'appkey',
    PARTNERID = 'partnerid',
    PARTNERKEY = 'partnerkey',
    SIGNTYPE = 'signtype';
  public
    $params = array(), $partnerid = '';
  static protected
    $_instance;
  protected
    $_appid, $_appkey, $_signtype, $_partnerkey, $_appsercer;
  static public function getInstance(array $options = array()) {
    if (empty(self::$_instance)) {
      self::$_instance = new self ($options);
    }
    return self::$_instance;
  }
  public function __construct(array $options = array()){
    $this->_appid = $options[self::APPID];
    $this->_appkey = $options[self::PAYSIGNKEY];
    $this->_signtype = $options[self::SIGNTYPE];
    $this->_partnerkey = $options[self::PARTNERKEY];
    $this->_appsercer = $options[self::APPSERCER];
    $this->partnerid = $options[self::APPID];
  }
  public function setParams($param, $paramValue) {
    $this->params[CommonUtil::trimString($param)] = CommonUtil::trimString($paramValue);
  }
  public function getParams($param) {
    return $this->params[$param];
  }
  protected function createNoncestr( $length = 16 ) {
    $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    $str ="";
    for ( $i = 0; $i < $length; $i++ ) {
      $str.= substr($chars, mt_rand(0, strlen($chars)-1), 1);
    }
    return $str;
  }
  public function checkParams(){
    //必要的9个参与签名的参数
    if($this->params[self::BANK_TYPE] == null || $this->params[self::BODY] == null || $this->params[self::PARTNER] == null ||
      $this->params[self::OUT_TRADE_NO] == null || $this->params[self::TOTAL_FEE] == null || $this->params[self::FEE_TYPE] == null ||
      $this->params[self::NOTIFY_URL] == null || $this->params[self::SPBILL_CREATE_IP] == null || $this->params[self::INPUT_CHARSET] == null
    ) {
      return false;
    }
    return true;
  }
  /*
   * 生成package包
   * @params 初始化类时用setParams方法定义必要的9个参数
   * 排序后格式化url query形式 再md5SignUtil类签名,再给合URL
   */
  protected function getPackageSign(){
    try {
      if (null == $this->_partnerkey || "" == $this->_partnerkey ) {
        throw new Exception("密钥不能为空!" . "<br>");
      }
      $commonUtil = new CommonUtil();
      ksort($this->params);
      $unSignParaString = $commonUtil->formatUrlQuery($this->params, false);
      $paraString = $commonUtil->formatUrlQuery($this->params, true);
      $md5SignUtil = new MD5SignUtil();
      return $paraString . "&sign=" . $md5SignUtil->sign($unSignParaString,commonUtil::trimString($this->_partnerkey));
    } catch (Exception $e) {
      echo ($e->getMessage());
    }
  }
  /*
   * 生成签名方法
   * @params appid appkey package timestamp noncestr 等参数而native事例代码中加上retcode reterrmsg两个参数
   */
  public function getPaySign($signObj){
    foreach ($signObj as $k => $v){
      $signParams[strtolower($k)] = $v;
    }
    try {
      if ($this->_appkey == "") {
        throw new Exception("APPKEY为空!" . "<br>");
      }
      $signParams["appkey"] = $this->_appkey;
      ksort($signParams, SORT_STRING);
      $commonUtil = new CommonUtil();
      $signString = $commonUtil->formatPayUrlQuery($signParams, false);
      return sha1($signString);
    } catch (Exception $e) {
      echo ($e->getMessage());
    }
  }
  //JS API 签名 其中nonceStr是作为订单号 灌穿整个支付流程
  public function createJsApiPackage(){
    try {
      if($this->checkParams() == false) {
        throw new Exception("生成package参数缺失!" . "<br>");
      }
      $payObj["appId"] = $this->_appid;
      $payObj["package"] = $this->getPackageSign();
      $payObj["timeStamp"] = $this->getParams(self::TIMESTAMP);
      $payObj["nonceStr"] = $this->getParams(self::OUT_TRADE_NO);
      $payObj["paySign"] = $this->getPaySign($payObj);
      $payObj["signType"] = $this->_signtype;
      return json_encode($payObj);
    } catch (Exception $e) {
      die($e->getMessage());
    }
  }
  /*
   * 构建发货状态数组 主要三个参数openid transid orderid
   */
  public function createDeliverPost(Array $params) {
    $deliver = array();
    $deliver['appid'] = $this->_appid;
    $deliver['openid'] = $params['openid'];
    $deliver['transid'] = $params['transid'];
    $deliver['out_trade_no'] = $params['out_trade_no'];
    $deliver['deliver_timestamp'] = current_time('timestamp');
    $deliver['deliver_status'] = 1;
    $deliver['deliver_msg'] = 'OK';
    $deliver['app_signature'] = $this->getPaySign($deliver);
    $deliver['sign_method'] = 'sha1';
    return $deliver;
  }
  /*
   * 生成扫描或者点击原生URL后,响应的XML格式
   * @params $retcode $reterrmsg 定义该商品的状态
   */
  public function createNativePackage($retcode = 0, $reterrmsg = "ok") {
    try {
      if ($this->checkParams() == false && $retcode == 0) {  //如果是正常的返回, 检查财付通的参数
        throw new Exception("生成package参数缺失!" . "<br>");
      }
      $nativeObj["AppId"] = $this->_appid;
      $nativeObj["Package"] = $this->getPackageSign();
      $nativeObj["TimeStamp"] = $this->getParams(self::TIMESTAMP);
      $nativeObj["NonceStr"] = $this->getParams(self::OUT_TRADE_NO);
      $nativeObj["RetCode"] = $retcode;
      $nativeObj["RetErrMsg"] = $reterrmsg;
      $nativeObj["AppSignature"] = $this->getPaySign($nativeObj);
      $nativeObj["SignMethod"] = $this->_signtype;
      $commonUtil = new CommonUtil();
      $xml = $commonUtil->arrayToXml($nativeObj);
      exit($xml);
    }catch (Exception $e) {
      echo ($e->getMessage());
    }
  }
  /*
   * 生成原生URL 以订单号为参数 这是灌穿整个支付流程
   */
  public function createNativeUrl($productid) {
    $commonUtil = new CommonUtil();
    $nativeObj["appid"] = $this->_appid;
    $nativeObj["productid"] = urlencode($productid);
    $nativeObj["timestamp"] = time();
    $nativeObj["nonceStr"] = commonUtil::createNoncestr();
    $nativeObj["sign"] = $this->getPaySign($nativeObj);
    $nativeString = $commonUtil->formatPayUrlQuery($nativeObj, false);
    return "weixin://wxpay/bizpayurl?".$nativeString;
  }
  /*
   * 取IP地址
   */
  public function getIp(){
    switch(true) {
      case !empty($_SERVER["HTTP_CLIENT_IP"]):
        $ip = $_SERVER["HTTP_CLIENT_IP"];
        break;
      case !empty($_SERVER["HTTP_X_FORWARDED_FOR"]):
        $ip = $_SERVER["HTTP_X_FORWARDED_FOR"];
        break;
      case !empty($_SERVER["REMOTE_ADDR"]):
        $ip = $_SERVER["REMOTE_ADDR"];
        break;
      default:
        $ip = "127.0.0.1";
    }
    return $ip;
  }
}
class MD5SignUtil {
  public function sign($content, $key) {
    try {
      if (null == $key) {
        throw new Exception("财付通签名key不能为空!" . "<br>");
      }
      if (null == $content) {
        throw new Exception("财付通签名内容不能为空" . "<br>");
      }
      $signStr = $content . "&key=" . $key;
      return strtoupper(md5($signStr));
    } catch (Exception $e) {
      echo ($e->getMessage());
    }
  }
  public static function verifySignature($content, $sign, $md5Key) {
    $signStr = $content . "&key=" . $md5Key;
    $calculateSign = strtolower(md5($signStr));
    $tenpaySign = strtolower($sign);
    return $calculateSign == $tenpaySign;
  }
}
class CommonUtil {
  public function genAllUrl($toURL, $paras) {
    $allUrl = null;
    if (null == $toURL) {
      die("toURL is null");
    }
    if (strripos($toURL,"?") =="") {
      $allUrl = $toURL . "?" . $paras;
    } else {
      $allUrl = $toURL . "&" . $paras;
    }
    return $allUrl;
  }
  //订单号,可根据实际自定义
  static public function createOrderNo() {
    $nonce = CommonUtil::createNoncestr(4);
    return strtoupper(date('ymds').substr(microtime(),2,4).$nonce);
  }
  //随机字符串
  static public function createNoncestr( $length = 16 ) {
    $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    $str ="";
    for ( $i = 0; $i < $length; $i++ ) {
      $str.= substr($chars, mt_rand(0, strlen($chars)-1), 1);
    }
    return $str;
  }
  public function splitParaStr($src, $token) {
    $resMap = array();
    $items = explode($token,$src);
    foreach ($items as $item){
      $paraAndValue = explode("=",$item);
      if ($paraAndValue != "") {
        $resMap[$paraAndValue[0]] = $paraAndValue[1];
      }
    }
    return $resMap;
  }
  static function trimString($value) {
    $ret = null;
    if (null != $value) {
      $ret = $value;
      if (strlen($ret) == 0) {
        $ret = null;
      }
    }
    return $ret;
  }
  public function formatUrlQuery($paraMap, $urlencode) {
    $buff = "";
    ksort($paraMap, SORT_STRING);
    foreach ($paraMap as $k => $v) {
      if (null != $v && "null" != $v && "sign" != $k) {
        if($urlencode) {
          $v = urlencode($v);
        }
        $buff .= $k . "=" . $v . "&";
      }
    }
    $reqPar = '';
    if (strlen($buff) > 0) {
      $reqPar = substr($buff, 0, strlen($buff)-1);
    }
    return $reqPar;
  }
  public function formatPayUrlQuery($paraMap, $urlencode) {
    $buff = "";
    ksort($paraMap, SORT_STRING);
    foreach ($paraMap as $k => $v) {
      if($urlencode){
        $v = urlencode($v);
      }
      $buff .= strtolower($k) . "=" . $v . "&";
    }
    $reqPar = '';
    if (strlen($buff) > 0) {
      $reqPar = substr($buff, 0, strlen($buff)-1);
    }
    return $reqPar;
  }
  /*
   * 输出一级数组的xml格式
   */
  public function arrayToXml($arr) {
    $xml = "<xml>";
    foreach ($arr as $key=>$val) {
      if ($key == 'TimeStamp' || $key == 'RetCode') {
        $xml.="<".$key.">".$val."</".$key.">";
      } else
        $xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
    }
    $xml .= "</xml>";
    return $xml;
  }
}

希望本文所述对大家PHP程序设计有所帮助。

PHP 相关文章推荐
PHP中对用户身份认证实现两种方法
Jun 04 PHP
理解PHP中的stdClass类
Apr 18 PHP
php实现粘贴截图并完成上传功能
May 17 PHP
学习php设计模式 php实现合成模式(composite)
Dec 08 PHP
全新Mac配置PHP开发环境教程
Feb 03 PHP
Symfony2安装第三方Bundles实例详解
Feb 04 PHP
php文件上传类完整实例
May 14 PHP
PHP实现生成带背景的图形验证码功能
Oct 03 PHP
详解PHP防止直接访问.php 文件的实现方法
Jul 28 PHP
详解php伪造Referer请求反盗链资源
Jan 24 PHP
PHP中通过getopt解析GNU C风格命令行选项
Nov 18 PHP
PHP获取当前时间不准确问题解决方案
Aug 14 PHP
php版微信支付api.mch.weixin.qq.com域名解析慢原因与解决方法
Oct 12 #PHP
如何使用php等比例缩放图片
Oct 12 #PHP
php与python实现的线程池多线程爬虫功能示例
Oct 12 #PHP
php实现的SSO单点登录系统接入功能示例分析
Oct 12 #PHP
php用户密码加密算法分析【Discuz加密算法】
Oct 12 #PHP
基于php实现的php代码加密解密类完整实例
Oct 12 #PHP
php fseek函数读取大文件两种方法
Oct 12 #PHP
You might like
德劲1102收音机的打理维修案例
2021/03/02 无线电
php 什么是PEAR?(第二篇)
2009/03/19 PHP
php修改NetBeans默认字体的大小
2013/07/02 PHP
windows的文件系统机制引发的PHP路径爆破问题分析
2014/07/28 PHP
浅谈Javascript 执行顺序
2013/12/18 Javascript
jQuery+ajax中getJSON() 用法实例
2014/12/22 Javascript
探讨JavaScript中的Rest参数和参数默认值
2015/07/29 Javascript
canvas学习之API整理笔记(二)
2016/12/29 Javascript
判断颜色是否合法的正则表达式(详解)
2017/05/03 Javascript
前端常见跨域解决方案(全)
2017/09/19 Javascript
node创建Vue项目步骤详解
2020/03/06 Javascript
浅谈Vue2.4.0 $attrs与inheritAttrs的具体使用
2020/03/08 Javascript
[01:43]3.19DOTA2发布会 三代刀塔人第三代
2014/03/25 DOTA
[01:55]2014DOTA2国际邀请赛快报:国土生病 紧急去医院治疗
2014/07/10 DOTA
python解析xml文件操作实例
2014/10/05 Python
介绍Python中内置的itertools模块
2015/04/29 Python
Python编写生成验证码的脚本的教程
2015/05/04 Python
用Python实现读写锁的示例代码
2018/11/05 Python
Python之循环结构
2019/01/15 Python
Python计算一个点到所有点的欧式距离实现方法
2019/07/04 Python
Python scipy的二维图像卷积运算与图像模糊处理操作示例
2019/09/06 Python
Python GUI编程学习笔记之tkinter中messagebox、filedialog控件用法详解
2020/03/30 Python
详解Anaconda安装tensorflow报错问题解决方法
2020/11/01 Python
CSS3感应鼠标的背景闪烁和图片缩放动画效果
2014/05/14 HTML / CSS
CSS3 文字动画效果
2020/11/12 HTML / CSS
几道数据库的概念性面试题
2014/05/30 面试题
超市总经理岗位职责
2014/02/02 职场文书
学习雷锋做美德少年寄语大全
2014/04/09 职场文书
小学教师师德演讲稿
2014/05/06 职场文书
社区优秀志愿者先进事迹
2014/05/09 职场文书
励志演讲稿800字
2014/08/21 职场文书
个人委托书如何写
2014/09/25 职场文书
2015年教师节演讲稿范文
2015/03/19 职场文书
中标通知书
2015/04/17 职场文书
物业保安辞职信
2015/05/12 职场文书
简爱电影观后感
2015/06/10 职场文书