Home > php教程 > php手册 > 微信支付之APP支付

微信支付之APP支付

WBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWB
Release: 2016-06-06 19:37:41
Original
1081 people have browsed it

微信开放平台移动应用集成微信支付功能。 具体使用请移步:http://www.360us.net/article/23.html 仅仅是消费功能,其他功能没有加。 开放平台的微信支付和公众号的微信支付是不一样的,这里说明一下。 无 ?phpnamespace common\services\WechatPay;class Wec

微信开放平台移动应用集成微信支付功能。
具体使用请移步:http://www.360us.net/article/23.html
仅仅是消费功能,其他功能没有加。

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

273

274

275

276

277

278

279

280

281

282

283

284

285

286

287

288

289

<?php

namespace common\services\WechatPay;

 

class WechatAppPay extends WechatPayBase

{

    //package参数

    public $package = [];

     

    //异步通知参数

    public $notify = [];

     

    //推送预支付订单参数

    protected $config = [];

     

    //存储access token和获取时间的文件

    protected $file;

     

    //access token

    protected $accessToken;

     

    //取access token的url

    const ACCESS_TOKEN_URL = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s';

     

    //生成预支付订单提交地址

    const POST_ORDER_URL = 'https://api.weixin.qq.com/pay/genprepay?access_token=%s';

     

    public function __construct()

    {

        $this->file = __DIR__ . '/payAccessToken.txt';

    }

     

    /**

     * 创建APP支付最终返回参数

     * @throws \Exception

     * @return multitype:string NULL

     */

    public function createAppPayData()

    {

        $this->generateConfig();

         

        $prepayid = $this->getPrepayid();

         

        try{

            $array = [

                'appid' => $this->appid,

                'appkey' => $this->paySignkey,

                'noncestr' => $this->getRandomStr(),

                'package' => 'Sign=WXPay',

                'partnerid' => $this->partnerId,

                'prepayid' => $prepayid,

                'timestamp' => (string)time(),

            ];

             

            $array['sign'] = $this->sha1Sign($array);

            unset($array['appkey']);

        } catch(\Exception $e) {

            throw new \Exception($e->getMessage());

        }

         

        return $array;

    }

     

    /**

     * 验证支付成功后的通知参数

     *

     * @throws \Exception

     * @return boolean

     */

    public function verifyNotify()

    {

        try{

            $staySignStr = $this->notify;

            unset($staySignStr['sign']);

            $sign = $this->signData($staySignStr);

             

            return $this->notify['sign'] === $sign;

        } catch(\Exception $e) {

            throw new \Exception($e->getMessage());

        }

    }

     

    /**

     * 魔术方法,给添加支付参数进来

     *

     * @param string $name  参数名

     * @param string $value  参数值

     */

    public function __set($name, $value)

    {

        $this->$name = $value;

    }

     

    /**

     * 设置access token

     * @param string $token

     * @throws \Exception

     * @return boolean

     */

    public function setAccessToken()

    {

        try{

            if(!file_exists($this->file) || !is_file($this->file)) {

                $f = fopen($this->file, 'a');

                fclose($f);

            }

            $content = file_get_contents($this->file);

            if(!empty($content)) {

                $info = json_decode($content, true);

                if( time() - $info['getTime'] < 7150 ) {

                    $this->accessToken = $info['accessToken'];

                    return true;

                }

            }

             

            //文件内容为空或access token已失效,重新获取

            $this->outputAccessTokenToFile();

        } catch(\Exception $e) {

            throw new \Exception($e->getMessage());

        }

         

        return true;

    }

     

    /**

     * 写入access token 到文件

     * @throws \Exception

     * @return boolean

     */

    protected function outputAccessTokenToFile()

    {

        try{

            $f = fopen($this->file, 'wb');

            $token = [

                'accessToken' => $this->getAccessToken(),

                'getTime' => time(),

            ];

            flock($f, LOCK_EX);

            fwrite($f, json_encode($token));

            flock($f, LOCK_UN);

            fclose($f);

             

            $this->accessToken = $token['accessToken'];

        } catch(\Exception $e) {

            throw new \Exception($e->getMessage());

        }

         

        return true;

    }

     

    /**

     * 取access token

     *

     * @throws \Exception

     * @return string

     */

    protected function getAccessToken()

    {

        $url = sprintf(self::ACCESS_TOKEN_URL, $this->appid, $this->appSecret);

        $result = json_decode( $this->getUrl($url), true );

         

        if(isset($result['errcode'])) {

            throw new \Exception("get access token failed:{$result['errmsg']}");

        }

         

        return $result['access_token'];

    }

     

    /**

     * 取预支付会话标识

     *

     * @throws \Exception

     * @return string

     */

    protected function getPrepayid()

    {

        $data = json_encode($this->config);

        $url = sprintf(self::POST_ORDER_URL, $this->accessToken);

        $result = json_decode( $this->postUrl($url, $data), true );

         

        if( isset($result['errcode']) && $result['errcode'] != 0 ) {

            throw new \Exception($result['errmsg']);

        }

         

        if( !isset($result['prepayid']) ) {

            throw new \Exception('get prepayid failed, url request error.');

        }

         

        return $result['prepayid'];

    }

     

    /**

     * 组装预支付参数

     *

     * @throws \Exception

     */

    protected function generateConfig()

    {

        try{

            $this->config = [

                    'appid' => $this->appid,

                    'traceid' => $this->traceid,

                    'noncestr' => $this->getRandomStr(),

                    'timestamp' => time(),

                    'package' => $this->generatePackage(),

                    'sign_method' => $this->sign_method,

            ];

            $this->config['app_signature'] = $this->generateSign();

        } catch(\Exception $e) {

            throw new \Exception($e->getMessage());

        }

    }

     

    /**

     * 生成package字段

     *

     * 生成规则:

     * 1、生成sign的值signValue

     * 2、对package参数再次拼接成查询字符串,值需要进行urlencode

     * 3、将sign=signValue拼接到2生成的字符串后面得到最终的package字符串

     *

     * 第2步urlencode空格需要编码成%20而不是+

     *

     * RFC 1738会把 空格编码成+

     * RFC 3986会把空格编码成%20

     *

     * @return string

     */

    protected function generatePackage()

    {

        $this->package['sign'] = $this->signData($this->package);

         

        return http_build_query($this->package, '', '&', PHP_QUERY_RFC3986);

    }

     

    /**

     * 生成签名

     *

     * @return string

     */

    protected function generateSign()

    {

        $signArray = [

            'appid' => $this->appid,

            'appkey' => $this->paySignkey,

            'noncestr' => $this->config['noncestr'],

            'package' => $this->config['package'],

            'timestamp' => $this->config['timestamp'],

            'traceid' => $this->traceid,

        ];

        return $this->sha1Sign($signArray);

    }

     

    /**

     * 签名数据

     *

     * 生成规则:

     * 1、字典排序,拼接成查询字符串格式,不需要urlencode

     * 2、上一步得到的字符串最后拼接上key=paternerKey

     * 3、MD5哈希字符串并转换成大写得到sign的值signValue

     *

     * @param array $data 待签名数据

     * @return string 最终签名结果

     */

    protected function signData($data)

    {

        ksort($data);

        $str = $this->arrayToString($data);

        $str .= "&key={$this->partnerKey}";

        return strtoupper( $this->signMd5($str) );

    }

     

    /**

     * sha1签名

     * 签名规则

     * 1、字典排序

     * 2、拼接查询字符串

     * 3、sha1运算

     *

     * @param array $arr

     * @return string

     */

    protected function sha1Sign($arr)

    {

        ksort($arr);

         

        return sha1( $this->arrayToString($arr) );

    }

 

}

Copy after login
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Latest Issues
Popular Recommendations
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template