免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 5842 | 回复: 1
打印 上一主题 下一主题

微信支付之APP支付 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2015-06-30 09:42 |只看该作者 |倒序浏览
微信开放平台移动应用集成微信支付功能。
具体使用请移步:http://www.360us.net/article/23.html
仅仅是消费功能,其他功能没有加。

开放平台的微信支付和公众号的微信支付是不一样的,这里说明一下。

WechatAppPay
  1. <?php
  2. namespace common\services\WechatPay;

  3. class WechatAppPay extends WechatPayBase
  4. {
  5.     //package参数
  6.     public $package = [];
  7.      
  8.     //异步通知参数
  9.     public $notify = [];
  10.      
  11.     //推送预支付订单参数
  12.     protected $config = [];
  13.      
  14.     //存储access token和获取时间的文件
  15.     protected $file;
  16.      
  17.     //access token
  18.     protected $accessToken;
  19.      
  20.     //取access token的url
  21.     const ACCESS_TOKEN_URL = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s';
  22.      
  23.     //生成预支付订单提交地址
  24.     const POST_ORDER_URL = 'https://api.weixin.qq.com/pay/genprepay?access_token=%s';
  25.      
  26.     public function __construct()
  27.     {
  28.         $this->file = __DIR__ . '/payAccessToken.txt';
  29.     }
  30.      
  31.     /**
  32.      * 创建APP支付最终返回参数
  33.      * @throws \Exception
  34.      * @return multitype:string NULL
  35.      */
  36.     public function createAppPayData()
  37.     {
  38.         $this->generateConfig();
  39.          
  40.         $prepayid = $this->getPrepayid();
  41.          
  42.         try{
  43.             $array = [
  44.                 'appid' => $this->appid,
  45.                 'appkey' => $this->paySignkey,
  46.                 'noncestr' => $this->getRandomStr(),
  47.                 'package' => 'Sign=WXPay',
  48.                 'partnerid' => $this->partnerId,
  49.                 'prepayid' => $prepayid,
  50.                 'timestamp' => (string)time(),
  51.             ];
  52.             
  53.             $array['sign'] = $this->sha1Sign($array);
  54.             unset($array['appkey']);
  55.         } catch(\Exception $e) {
  56.             throw new \Exception($e->getMessage());
  57.         }
  58.          
  59.         return $array;
  60.     }
  61.      
  62.     /**
  63.      * 验证支付成功后的通知参数
  64.      *
  65.      * @throws \Exception
  66.      * @return boolean
  67.      */
  68.     public function verifyNotify()
  69.     {
  70.         try{
  71.             $staySignStr = $this->notify;
  72.             unset($staySignStr['sign']);
  73.             $sign = $this->signData($staySignStr);
  74.             
  75.             return $this->notify['sign'] === $sign;
  76.         } catch(\Exception $e) {
  77.             throw new \Exception($e->getMessage());
  78.         }
  79.     }
  80.      
  81.     /**
  82.      * 魔术方法,给添加支付参数进来
  83.      *
  84.      * @param string $name  参数名
  85.      * @param string $value  参数值
  86.      */
  87.     public function __set($name, $value)
  88.     {
  89.         $this->$name = $value;
  90.     }
  91.      
  92.     /**
  93.      * 设置access token
  94.      * @param string $token
  95.      * @throws \Exception
  96.      * @return boolean
  97.      */
  98.     public function setAccessToken()
  99.     {
  100.         try{
  101.             if(!file_exists($this->file) || !is_file($this->file)) {
  102.                 $f = fopen($this->file, 'a');
  103.                 fclose($f);
  104.             }
  105.             $content = file_get_contents($this->file);
  106.             if(!empty($content)) {
  107.                 $info = json_decode($content, true);
  108.                 if( time() - $info['getTime'] < 7150 ) {
  109.                     $this->accessToken = $info['accessToken'];
  110.                     return true;
  111.                 }
  112.             }
  113.             
  114.             //文件内容为空或access token已失效,重新获取
  115.             $this->outputAccessTokenToFile();
  116.         } catch(\Exception $e) {
  117.             throw new \Exception($e->getMessage());
  118.         }
  119.          
  120.         return true;
  121.     }
  122.      
  123.     /**
  124.      * 写入access token 到文件
  125.      * @throws \Exception
  126.      * @return boolean
  127.      */
  128.     protected function outputAccessTokenToFile()
  129.     {
  130.         try{
  131.             $f = fopen($this->file, 'wb');
  132.             $token = [
  133.                 'accessToken' => $this->getAccessToken(),
  134.                 'getTime' => time(),
  135.             ];
  136.             flock($f, LOCK_EX);
  137.             fwrite($f, json_encode($token));
  138.             flock($f, LOCK_UN);
  139.             fclose($f);
  140.             
  141.             $this->accessToken = $token['accessToken'];
  142.         } catch(\Exception $e) {
  143.             throw new \Exception($e->getMessage());
  144.         }
  145.          
  146.         return true;
  147.     }
  148.      
  149.     /**
  150.      * 取access token
  151.      *
  152.      * @throws \Exception
  153.      * @return string
  154.      */
  155.     protected function getAccessToken()
  156.     {
  157.         $url = sprintf(self::ACCESS_TOKEN_URL, $this->appid, $this->appSecret);
  158.         $result = json_decode( $this->getUrl($url), true );
  159.          
  160.         if(isset($result['errcode'])) {
  161.             throw new \Exception("get access token failed:{$result['errmsg']}");
  162.         }
  163.          
  164.         return $result['access_token'];
  165.     }
  166.      
  167.     /**
  168.      * 取预支付会话标识
  169.      *
  170.      * @throws \Exception
  171.      * @return string
  172.      */
  173.     protected function getPrepayid()
  174.     {
  175.         $data = json_encode($this->config);
  176.         $url = sprintf(self::POST_ORDER_URL, $this->accessToken);
  177.         $result = json_decode( $this->postUrl($url, $data), true );
  178.          
  179.         if( isset($result['errcode']) && $result['errcode'] != 0 ) {
  180.             throw new \Exception($result['errmsg']);
  181.         }
  182.          
  183.         if( !isset($result['prepayid']) ) {
  184.             throw new \Exception('get prepayid failed, url request error.');
  185.         }
  186.          
  187.         return $result['prepayid'];
  188.     }
  189.      
  190.     /**
  191.      * 组装预支付参数
  192.      *
  193.      * @throws \Exception
  194.      */
  195.     protected function generateConfig()
  196.     {
  197.         try{
  198.             $this->config = [
  199.                     'appid' => $this->appid,
  200.                     'traceid' => $this->traceid,
  201.                     'noncestr' => $this->getRandomStr(),
  202.                     'timestamp' => time(),
  203.                     'package' => $this->generatePackage(),
  204.                     'sign_method' => $this->sign_method,
  205.             ];
  206.             $this->config['app_signature'] = $this->generateSign();
  207.         } catch(\Exception $e) {
  208.             throw new \Exception($e->getMessage());
  209.         }
  210.     }
  211.      
  212.     /**
  213.      * 生成package字段
  214.      *
  215.      * 生成规则:
  216.      * 1、生成sign的值signValue
  217.      * 2、对package参数再次拼接成查询字符串,值需要进行urlencode
  218.      * 3、将sign=signValue拼接到2生成的字符串后面得到最终的package字符串
  219.      *
  220.      * 第2步urlencode空格需要编码成%20而不是+
  221.      *
  222.      * RFC 1738会把 空格编码成+
  223.      * RFC 3986会把空格编码成%20
  224.      *
  225.      * @return string
  226.      */
  227.     protected function generatePackage()
  228.     {
  229.         $this->package['sign'] = $this->signData($this->package);
  230.          
  231.         return http_build_query($this->package, '', '&', PHP_QUERY_RFC3986);
  232.     }
  233.      
  234.     /**
  235.      * 生成签名
  236.      *
  237.      * @return string
  238.      */
  239.     protected function generateSign()
  240.     {
  241.         $signArray = [
  242.             'appid' => $this->appid,
  243.             'appkey' => $this->paySignkey,
  244.             'noncestr' => $this->config['noncestr'],
  245.             'package' => $this->config['package'],
  246.             'timestamp' => $this->config['timestamp'],
  247.             'traceid' => $this->traceid,
  248.         ];
  249.         return $this->sha1Sign($signArray);
  250.     }
  251.      
  252.     /**
  253.      * 签名数据
  254.      *
  255.      * 生成规则:
  256.      * 1、字典排序,拼接成查询字符串格式,不需要urlencode
  257.      * 2、上一步得到的字符串最后拼接上key=paternerKey
  258.      * 3、MD5哈希字符串并转换成大写得到sign的值signValue
  259.      *
  260.      * @param array $data 待签名数据
  261.      * @return string 最终签名结果
  262.      */
  263.     protected function signData($data)
  264.     {
  265.         ksort($data);
  266.         $str = $this->arrayToString($data);
  267.         $str .= "&key={$this->partnerKey}";
  268.         return strtoupper( $this->signMd5($str) );
  269.     }
  270.      
  271.     /**
  272.      * sha1签名
  273.      * 签名规则
  274.      * 1、字典排序
  275.      * 2、拼接查询字符串
  276.      * 3、sha1运算
  277.      *
  278.      * @param array $arr
  279.      * @return string
  280.      */
  281.     protected function sha1Sign($arr)
  282.     {
  283.         ksort($arr);
  284.          
  285.         return sha1( $this->arrayToString($arr) );
  286.     }

  287. }
复制代码

论坛徽章:
59
2015七夕节徽章
日期:2015-08-24 11:17:25ChinaUnix专家徽章
日期:2015-07-20 09:19:30每周论坛发贴之星
日期:2015-07-20 09:19:42ChinaUnix元老
日期:2015-07-20 11:04:38荣誉版主
日期:2015-07-20 11:05:19巳蛇
日期:2015-07-20 11:05:26CU十二周年纪念徽章
日期:2015-07-20 11:05:27IT运维版块每日发帖之星
日期:2015-07-20 11:05:34操作系统版块每日发帖之星
日期:2015-07-20 11:05:36程序设计版块每日发帖之星
日期:2015-07-20 11:05:40数据库技术版块每日发帖之星
日期:2015-07-20 11:05:432015年辞旧岁徽章
日期:2015-07-20 11:05:44
2 [报告]
发表于 2015-07-10 10:17 |只看该作者
我是不敢使用你这个来支付了。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP