├── .gitignore ├── .travis.yml ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── composer.json ├── phpunit.xml.dist ├── src ├── AppGateway.php ├── BaseAbstractGateway.php ├── Gateway.php ├── Helper.php ├── JsGateway.php ├── Message │ ├── BaseAbstractRequest.php │ ├── BaseAbstractResponse.php │ ├── CloseOrderRequest.php │ ├── CloseOrderResponse.php │ ├── CompletePurchaseRequest.php │ ├── CompletePurchaseResponse.php │ ├── CompleteRefundRequest.php │ ├── CompleteRefundResponse.php │ ├── CouponTransfersRequest.php │ ├── CouponTransfersResponse.php │ ├── CreateMicroOrderRequest.php │ ├── CreateMicroOrderResponse.php │ ├── CreateOrderRequest.php │ ├── CreateOrderResponse.php │ ├── DownloadBillRequest.php │ ├── DownloadBillResponse.php │ ├── GetPublicKeyRequest.php │ ├── GetPublicKeyResponse.php │ ├── PayBankRequest.php │ ├── PayBankResponse.php │ ├── PromotionTransferRequest.php │ ├── PromotionTransferResponse.php │ ├── QueryBankRequest.php │ ├── QueryBankResponse.php │ ├── QueryOpenIdByAuthCodeRequest.php │ ├── QueryOpenIdByAuthCodeResponse.php │ ├── QueryOrderRequest.php │ ├── QueryOrderResponse.php │ ├── QueryRefundRequest.php │ ├── QueryRefundResponse.php │ ├── QueryTransferRequest.php │ ├── QueryTransferResponse.php │ ├── RefundOrderRequest.php │ ├── RefundOrderResponse.php │ ├── ShortenUrlRequest.php │ └── ShortenUrlResponse.php ├── MwebGateway.php ├── NativeGateway.php └── PosGateway.php └── tests ├── GatewayTest.php ├── HelperTest.php └── bootstrap.php /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor 2 | /public 3 | /.idea 4 | composer.lock 5 | composer.phar 6 | phpunit.xml 7 | .php_cs 8 | 9 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | php: 4 | - 7.1 5 | 6 | before_script: 7 | - composer install -n --dev --prefer-source 8 | 9 | script: 10 | - vendor/bin/phpcs --standard=PSR2 src 11 | - vendor/bin/phpunit --coverage-text --coverage-clover=coverage.xml 12 | 13 | after_success: 14 | - bash <(curl -s https://codecov.io/bash) -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | * Fork the project. 4 | * Make your feature addition or bug fix. 5 | * Add tests for it. This is important so I don't break it in a future version unintentionally. 6 | * Commit just the modifications, do not mess with the composer.json or CHANGELOG.md files. 7 | * Ensure your code is nicely formatted in the [PSR-2](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md) 8 | style and that all tests pass. 9 | * Send the pull request. 10 | * Check that the Travis CI build passed. If not, rinse and repeat. -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016-2017 Loki Else 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Omnipay: WechatPay 2 | 3 | **WechatPay driver for the Omnipay PHP payment processing library** 4 | 5 | [![Build Status](https://travis-ci.org/lokielse/omnipay-wechatpay.png?branch=master)](https://travis-ci.org/lokielse/omnipay-wechatpay) 6 | [![Latest Stable Version](https://poser.pugx.org/lokielse/omnipay-wechatpay/version.png)](https://packagist.org/packages/lokielse/omnipay-wechatpay) 7 | [![Total Downloads](https://poser.pugx.org/lokielse/omnipay-wechatpay/d/total.png)](https://packagist.org/packages/lokielse/omnipay-wechatpay) 8 | 9 | [Omnipay](https://github.com/omnipay/omnipay) is a framework agnostic, multi-gateway payment 10 | processing library for PHP 5.3+. This package implements WechatPay support for Omnipay. 11 | 12 | ## Installation 13 | 14 | Omnipay is installed via [Composer](http://getcomposer.org/). To install: 15 | 16 | composer require lokielse/omnipay-wechatpay 17 | 18 | ## Basic Usage 19 | 20 | The following gateways are provided by this package: 21 | 22 | 23 | * WechatPay (Wechat Common Gateway) 微信支付通用网关 24 | * WechatPay_App (Wechat App Gateway) 微信APP支付网关 25 | * WechatPay_Native (Wechat Native Gateway) 微信原生扫码支付支付网关 26 | * WechatPay_Js (Wechat Js API/MP Gateway) 微信网页、公众号、小程序支付网关 27 | * WechatPay_Pos (Wechat Micro/POS Gateway) 微信刷卡支付网关 28 | * WechatPay_Mweb (Wechat H5 Gateway) 微信H5支付网关 29 | 30 | ## Usage 31 | 32 | ### Create Order [doc](https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_1) 33 | 34 | ```php 35 | //gateways: WechatPay_App, WechatPay_Native, WechatPay_Js, WechatPay_Pos, WechatPay_Mweb 36 | $gateway = Omnipay::create('WechatPay_App'); 37 | $gateway->setAppId($config['app_id']); 38 | $gateway->setMchId($config['mch_id']); 39 | $gateway->setApiKey($config['api_key']); 40 | 41 | $order = [ 42 | 'body' => 'The test order', 43 | 'out_trade_no' => date('YmdHis').mt_rand(1000, 9999), 44 | 'total_fee' => 1, //=0.01 45 | 'spbill_create_ip' => 'ip_address', 46 | 'fee_type' => 'CNY' 47 | ]; 48 | 49 | /** 50 | * @var Omnipay\WechatPay\Message\CreateOrderRequest $request 51 | * @var Omnipay\WechatPay\Message\CreateOrderResponse $response 52 | */ 53 | $request = $gateway->purchase($order); 54 | $response = $request->send(); 55 | 56 | //available methods 57 | $response->isSuccessful(); 58 | $response->getData(); //For debug 59 | $response->getAppOrderData(); //For WechatPay_App 60 | $response->getJsOrderData(); //For WechatPay_Js 61 | $response->getCodeUrl(); //For Native Trade Type 62 | ``` 63 | 64 | ### Notify [doc](https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_7&index=3) 65 | ```php 66 | $gateway = Omnipay::create('WechatPay'); 67 | $gateway->setAppId($config['app_id']); 68 | $gateway->setMchId($config['mch_id']); 69 | $gateway->setApiKey($config['api_key']); 70 | 71 | $response = $gateway->completePurchase([ 72 | 'request_params' => file_get_contents('php://input') 73 | ])->send(); 74 | 75 | if ($response->isPaid()) { 76 | //pay success 77 | var_dump($response->getRequestData()); 78 | }else{ 79 | //pay fail 80 | } 81 | ``` 82 | 83 | ### Query Order [doc](https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_1) 84 | ```php 85 | $response = $gateway->query([ 86 | 'transaction_id' => '1217752501201407033233368018', //The wechat trade no 87 | ])->send(); 88 | 89 | var_dump($response->isSuccessful()); 90 | var_dump($response->getData()); 91 | ``` 92 | 93 | 94 | ### Close Order [doc](https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_3&index=5) 95 | ```php 96 | $response = $gateway->close([ 97 | 'out_trade_no' => '201602011315231245', //The merchant trade no 98 | ])->send(); 99 | 100 | var_dump($response->isSuccessful()); 101 | var_dump($response->getData()); 102 | ``` 103 | 104 | ### Refund [doc](https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_4&index=6) 105 | ```php 106 | $gateway->setCertPath($certPath); 107 | $gateway->setKeyPath($keyPath); 108 | 109 | $response = $gateway->refund([ 110 | 'transaction_id' => '1217752501201407033233368018', //The wechat trade no 111 | 'out_refund_no' => $outRefundNo, 112 | 'total_fee' => 1, //=0.01 113 | 'refund_fee' => 1, //=0.01 114 | ])->send(); 115 | 116 | var_dump($response->isSuccessful()); 117 | var_dump($response->getData()); 118 | ``` 119 | 120 | ### QueryRefund [doc](https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_5&index=7) 121 | ```php 122 | $response = $gateway->queryRefund([ 123 | 'refund_id' => '1217752501201407033233368018', //Your site trade no, not union tn. 124 | ])->send(); 125 | 126 | var_dump($response->isSuccessful()); 127 | var_dump($response->getData()); 128 | ``` 129 | 130 | ### Shorten URL (for `WechatPay_Native`) [doc](https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_9&index=8) 131 | ```php 132 | $response = $gateway->shortenUrl([ 133 | 'long_url' => $longUrl 134 | ])->send(); 135 | 136 | var_dump($response->isSuccessful()); 137 | var_dump($response->getData()); 138 | var_dump($response->getShortUrl()); 139 | ``` 140 | 141 | ### Query OpenId (for `WechatPay_Pos`) [doc](https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_13&index=9) 142 | ```php 143 | $response = $gateway->queryOpenId([ 144 | 'auth_code' => $authCode 145 | ])->send(); 146 | 147 | var_dump($response->isSuccessful()); 148 | var_dump($response->getData()); 149 | var_dump($response->getOpenId()); 150 | ``` 151 | 152 | For general usage instructions, please see the main [Omnipay](https://github.com/omnipay/omnipay) 153 | repository. 154 | 155 | ## Related 156 | 157 | - [Laravel-Omnipay](https://github.com/ignited/laravel-omnipay) 158 | - [Omnipay-Alipay](https://github.com/lokielse/omnipay-alipay) 159 | - [Omnipay-UnionPay](https://github.com/lokielse/omnipay-unionpay) 160 | 161 | ## Support 162 | 163 | If you are having general issues with Omnipay, we suggest posting on 164 | [Stack Overflow](http://stackoverflow.com/). Be sure to add the 165 | [omnipay tag](http://stackoverflow.com/questions/tagged/omnipay) so it can be easily found. 166 | 167 | If you want to keep up to date with release anouncements, discuss ideas for the project, 168 | or ask more detailed questions, there is also a [mailing list](https://groups.google.com/forum/#!forum/omnipay) which 169 | you can subscribe to. 170 | 171 | If you believe you have found a bug, please report it using the [GitHub issue tracker](https://github.com/lokielse/omnipay-wechatpay/issues), 172 | or better yet, fork the library and submit a pull request. 173 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "lokielse/omnipay-wechatpay", 3 | "type": "library", 4 | "description": "Wechat gateway for Omnipay payment processing library", 5 | "keywords": [ 6 | "wechat", 7 | "gateway", 8 | "php", 9 | "omnipay", 10 | "pay", 11 | "sdk", 12 | "app", 13 | "payment", 14 | "purchase", 15 | "微信支付" 16 | ], 17 | "homepage": "https://github.com/lokielse/omnipay-wechatpay", 18 | "license": "MIT", 19 | "authors": [ 20 | { 21 | "name": "Loki Else", 22 | "email": "lokielse@gmail.com" 23 | } 24 | ], 25 | "autoload": { 26 | "psr-4": { 27 | "Omnipay\\WechatPay\\": "src/" 28 | } 29 | }, 30 | "require": { 31 | "omnipay/common": "^3.0", 32 | "php-http/guzzle6-adapter": "*" 33 | }, 34 | "require-dev": { 35 | "omnipay/tests": "^3.0", 36 | "squizlabs/php_codesniffer": "3.*" 37 | } 38 | } -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 14 | ./tests/ 15 | 16 | 17 | 18 | 20 | 21 | 22 | 23 | ./src 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/AppGateway.php: -------------------------------------------------------------------------------- 1 | setParameter('trade_type', $tradeType); 12 | } 13 | 14 | 15 | public function setAppId($appId) 16 | { 17 | $this->setParameter('app_id', $appId); 18 | } 19 | 20 | 21 | public function getAppId() 22 | { 23 | return $this->getParameter('app_id'); 24 | } 25 | 26 | 27 | public function setApiKey($apiKey) 28 | { 29 | $this->setParameter('api_key', $apiKey); 30 | } 31 | 32 | 33 | public function getApiKey() 34 | { 35 | return $this->getParameter('api_key'); 36 | } 37 | 38 | 39 | public function setMchId($mchId) 40 | { 41 | $this->setParameter('mch_id', $mchId); 42 | } 43 | 44 | 45 | public function getMchId() 46 | { 47 | return $this->getParameter('mch_id'); 48 | } 49 | 50 | /** 51 | * 子商户id 52 | * 53 | * @return mixed 54 | */ 55 | public function getSubMchId() 56 | { 57 | return $this->getParameter('sub_mch_id'); 58 | } 59 | 60 | 61 | /** 62 | * @param mixed $subMchId 63 | */ 64 | public function setSubMchId($mchId) 65 | { 66 | $this->setParameter('sub_mch_id', $mchId); 67 | } 68 | 69 | 70 | /** 71 | * 子商户 app_id 72 | * 73 | * @return mixed 74 | */ 75 | public function getSubAppId() 76 | { 77 | return $this->getParameter('sub_appid'); 78 | } 79 | 80 | 81 | /** 82 | * @param mixed $subAppId 83 | */ 84 | public function setSubAppId($subAppId) 85 | { 86 | $this->setParameter('sub_appid', $subAppId); 87 | } 88 | 89 | public function setNotifyUrl($url) 90 | { 91 | $this->setParameter('notify_url', $url); 92 | } 93 | 94 | 95 | public function getNotifyUrl() 96 | { 97 | return $this->getParameter('notify_url'); 98 | } 99 | 100 | 101 | /** 102 | * @return mixed 103 | */ 104 | public function getCertPath() 105 | { 106 | return $this->getParameter('cert_path'); 107 | } 108 | 109 | 110 | /** 111 | * @param mixed $certPath 112 | */ 113 | public function setCertPath($certPath) 114 | { 115 | $this->setParameter('cert_path', $certPath); 116 | } 117 | 118 | 119 | /** 120 | * @return mixed 121 | */ 122 | public function getKeyPath() 123 | { 124 | return $this->getParameter('key_path'); 125 | } 126 | 127 | 128 | /** 129 | * @param mixed $keyPath 130 | */ 131 | public function setKeyPath($keyPath) 132 | { 133 | $this->setParameter('key_path', $keyPath); 134 | } 135 | 136 | 137 | /** 138 | * @param array $parameters 139 | * 140 | * @return \Omnipay\WechatPay\Message\CreateOrderRequest 141 | */ 142 | public function purchase($parameters = array()) 143 | { 144 | $parameters['trade_type'] = $this->getTradeType(); 145 | 146 | return $this->createRequest('\Omnipay\WechatPay\Message\CreateOrderRequest', $parameters); 147 | } 148 | 149 | 150 | public function getTradeType() 151 | { 152 | return $this->getParameter('trade_type'); 153 | } 154 | 155 | 156 | /** 157 | * @param array $parameters 158 | * 159 | * @return \Omnipay\WechatPay\Message\CompletePurchaseRequest 160 | */ 161 | public function completePurchase($parameters = array()) 162 | { 163 | return $this->createRequest('\Omnipay\WechatPay\Message\CompletePurchaseRequest', $parameters); 164 | } 165 | 166 | public function completeRefund($parameters = array()) 167 | { 168 | return $this->createRequest('\Omnipay\WechatPay\Message\CompleteRefundRequest', $parameters); 169 | } 170 | 171 | 172 | /** 173 | * @param array $parameters 174 | * 175 | * @return \Omnipay\WechatPay\Message\QueryOrderRequest 176 | */ 177 | public function query($parameters = array()) 178 | { 179 | return $this->createRequest('\Omnipay\WechatPay\Message\QueryOrderRequest', $parameters); 180 | } 181 | 182 | 183 | /** 184 | * @param array $parameters 185 | * 186 | * @return \Omnipay\WechatPay\Message\CloseOrderRequest 187 | */ 188 | public function close($parameters = array()) 189 | { 190 | return $this->createRequest('\Omnipay\WechatPay\Message\CloseOrderRequest', $parameters); 191 | } 192 | 193 | 194 | /** 195 | * @param array $parameters 196 | * 197 | * @return \Omnipay\WechatPay\Message\RefundOrderRequest 198 | */ 199 | public function refund($parameters = array()) 200 | { 201 | return $this->createRequest('\Omnipay\WechatPay\Message\RefundOrderRequest', $parameters); 202 | } 203 | 204 | 205 | /** 206 | * @param array $parameters 207 | * 208 | * @return \Omnipay\WechatPay\Message\QueryOrderRequest 209 | */ 210 | public function queryRefund($parameters = array()) 211 | { 212 | return $this->createRequest('\Omnipay\WechatPay\Message\QueryRefundRequest', $parameters); 213 | } 214 | 215 | 216 | /** 217 | * @param array $parameters 218 | * 219 | * @return \Omnipay\WechatPay\Message\PromotionTransferRequest 220 | */ 221 | public function transfer($parameters = array()) 222 | { 223 | return $this->createRequest('\Omnipay\WechatPay\Message\PromotionTransferRequest', $parameters); 224 | } 225 | 226 | 227 | /** 228 | * @param array $parameters 229 | * 230 | * @return \Omnipay\WechatPay\Message\QueryTransferRequest 231 | */ 232 | public function queryTransfer($parameters = array()) 233 | { 234 | return $this->createRequest('\Omnipay\WechatPay\Message\QueryTransferRequest', $parameters); 235 | } 236 | 237 | 238 | /** 239 | * @param array $parameters 240 | * 241 | * @return \Omnipay\WechatPay\Message\DownloadBillRequest 242 | */ 243 | public function downloadBill($parameters = array()) 244 | { 245 | return $this->createRequest('\Omnipay\WechatPay\Message\DownloadBillRequest', $parameters); 246 | } 247 | 248 | /** 249 | * @param array $parameters 250 | * 251 | * @return \Omnipay\WechatPay\Message\PayBankRequest 252 | */ 253 | public function payBank($parameters = array()) 254 | { 255 | return $this->createRequest('\Omnipay\WechatPay\Message\PayBankRequest', $parameters); 256 | } 257 | 258 | /** 259 | * @param array $parameters 260 | * 261 | * @return \Omnipay\WechatPay\Message\GetPublicKeyRequest 262 | */ 263 | public function getPublicKey($parameters = array()) 264 | { 265 | return $this->createRequest('\Omnipay\WechatPay\Message\GetPublicKeyRequest', $parameters); 266 | } 267 | 268 | /** 269 | * @param array $parameters 270 | * 271 | * @return \Omnipay\WechatPay\Message\QueryBankRequest 272 | */ 273 | public function queryBank($parameters = array()) 274 | { 275 | return $this->createRequest('\Omnipay\WechatPay\Message\QueryBankRequest', $parameters); 276 | } 277 | 278 | /** 279 | * @param array $parameters 280 | * 281 | * @return \Omnipay\WechatPay\Message\CouponTransfersResponse 282 | */ 283 | public function sendCoupon($parameters = array()) 284 | { 285 | return $this->createRequest('\Omnipay\WechatPay\Message\CouponTransfersRequest', $parameters); 286 | } 287 | } 288 | -------------------------------------------------------------------------------- /src/Gateway.php: -------------------------------------------------------------------------------- 1 | "; 10 | foreach ($arr as $key => $val) { 11 | if (is_numeric($val)) { 12 | $xml .= "<" . $key . ">" . $val . ""; 13 | } else { 14 | $xml .= "<" . $key . ">"; 15 | } 16 | } 17 | $xml .= ""; 18 | 19 | return $xml; 20 | } 21 | 22 | 23 | public static function xml2array($xml) 24 | { 25 | libxml_disable_entity_loader(true); 26 | 27 | $data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true); 28 | 29 | if (! is_array($data)) { 30 | $data = []; 31 | } 32 | 33 | return $data; 34 | } 35 | 36 | 37 | public static function sign($data, $key) 38 | { 39 | unset($data['sign']); 40 | 41 | ksort($data); 42 | 43 | $query = urldecode(http_build_query($data)); 44 | $query .= "&key={$key}"; 45 | 46 | return strtoupper(md5($query)); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/JsGateway.php: -------------------------------------------------------------------------------- 1 | getParameter('app_id'); 20 | } 21 | 22 | 23 | /** 24 | * @param mixed $appId 25 | */ 26 | public function setAppId($appId) 27 | { 28 | $this->setParameter('app_id', $appId); 29 | } 30 | 31 | 32 | /** 33 | * @return mixed 34 | */ 35 | public function getApiKey() 36 | { 37 | return $this->getParameter('api_key'); 38 | } 39 | 40 | 41 | /** 42 | * @param mixed $apiKey 43 | */ 44 | public function setApiKey($apiKey) 45 | { 46 | $this->setParameter('api_key', $apiKey); 47 | } 48 | 49 | 50 | /** 51 | * @return mixed 52 | */ 53 | public function getMchId() 54 | { 55 | return $this->getParameter('mch_id'); 56 | } 57 | 58 | 59 | /** 60 | * @param mixed $mchId 61 | */ 62 | public function setMchId($mchId) 63 | { 64 | $this->setParameter('mch_id', $mchId); 65 | } 66 | 67 | /** 68 | * @return mixed 69 | */ 70 | public function getSubMchId() 71 | { 72 | return $this->getParameter('sub_mch_id'); 73 | } 74 | 75 | 76 | /** 77 | * @param mixed $subMchId 78 | */ 79 | public function setSubMchId($mchId) 80 | { 81 | $this->setParameter('sub_mch_id', $mchId); 82 | } 83 | 84 | /** 85 | * 子商户 app_id 86 | * 87 | * @return mixed 88 | */ 89 | public function getSubAppId() 90 | { 91 | return $this->getParameter('sub_appid'); 92 | } 93 | 94 | 95 | /** 96 | * @param mixed $subAppId 97 | */ 98 | public function setSubAppId($subAppId) 99 | { 100 | $this->setParameter('sub_appid', $subAppId); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/Message/BaseAbstractResponse.php: -------------------------------------------------------------------------------- 1 | getData(); 22 | 23 | return isset($data['result_code']) && $data['result_code'] == 'SUCCESS'; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Message/CloseOrderRequest.php: -------------------------------------------------------------------------------- 1 | validate('app_id', 'mch_id', 'out_trade_no'); 30 | 31 | $data = array( 32 | 'appid' => $this->getAppId(), 33 | 'mch_id' => $this->getMchId(), 34 | 'sub_appid' => $this->getSubAppId(), 35 | 'sub_mch_id' => $this->getSubMchId(), 36 | 'out_trade_no' => $this->getOutTradeNo(), 37 | 'nonce_str' => md5(uniqid()), 38 | ); 39 | 40 | $data = array_filter($data); 41 | 42 | $data['sign'] = Helper::sign($data, $this->getApiKey()); 43 | 44 | return $data; 45 | } 46 | 47 | 48 | /** 49 | * @return mixed 50 | */ 51 | public function getOutTradeNo() 52 | { 53 | return $this->getParameter('out_trade_no'); 54 | } 55 | 56 | 57 | /** 58 | * @param mixed $outTradeNo 59 | */ 60 | public function setOutTradeNo($outTradeNo) 61 | { 62 | $this->setParameter('out_trade_no', $outTradeNo); 63 | } 64 | 65 | 66 | /** 67 | * Send the request with specified data 68 | * 69 | * @param mixed $data The data to send 70 | * 71 | * @return ResponseInterface 72 | */ 73 | public function sendData($data) 74 | { 75 | $body = Helper::array2xml($data); 76 | $response = $this->httpClient->request('POST', $this->endpoint, [], $body)->getBody(); 77 | $payload = Helper::xml2array($response); 78 | 79 | return $this->response = new CloseOrderResponse($this, $payload); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/Message/CloseOrderResponse.php: -------------------------------------------------------------------------------- 1 | setParameter('request_params', $requestParams); 20 | } 21 | 22 | 23 | /** 24 | * Send the request with specified data 25 | * 26 | * @param mixed $data The data to send 27 | * 28 | * @return ResponseInterface 29 | */ 30 | public function sendData($data) 31 | { 32 | $data = $this->getData(); 33 | $sign = Helper::sign($data, $this->getApiKey()); 34 | 35 | $responseData = array(); 36 | 37 | if (isset($data['sign']) && $data['sign'] && $sign === $data['sign']) { 38 | $responseData['sign_match'] = true; 39 | } else { 40 | $responseData['sign_match'] = false; 41 | } 42 | 43 | if ($responseData['sign_match'] && isset($data['result_code']) && $data['result_code'] == 'SUCCESS') { 44 | $responseData['paid'] = true; 45 | } else { 46 | $responseData['paid'] = false; 47 | } 48 | 49 | return $this->response = new CompletePurchaseResponse($this, $responseData); 50 | } 51 | 52 | 53 | /** 54 | * Get the raw data array for this message. The format of this varies from gateway to 55 | * gateway, but will usually be either an associative array, or a SimpleXMLElement. 56 | * 57 | * @return mixed 58 | */ 59 | public function getData() 60 | { 61 | $data = $this->getRequestParams(); 62 | 63 | if (is_string($data)) { 64 | $data = Helper::xml2array($data); 65 | } 66 | 67 | return $data; 68 | } 69 | 70 | 71 | public function getRequestParams() 72 | { 73 | return $this->getParameter('request_params'); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/Message/CompletePurchaseResponse.php: -------------------------------------------------------------------------------- 1 | isPaid(); 24 | } 25 | 26 | 27 | public function isPaid() 28 | { 29 | $data = $this->getData(); 30 | 31 | return $data['paid']; 32 | } 33 | 34 | 35 | public function isSignMatch() 36 | { 37 | $data = $this->getData(); 38 | 39 | return $data['sign_match']; 40 | } 41 | 42 | 43 | public function getRequestData() 44 | { 45 | return $this->request->getData(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/Message/CompleteRefundRequest.php: -------------------------------------------------------------------------------- 1 | setParameter('request_params', $requestParams); 18 | } 19 | 20 | public function sendData($data) 21 | { 22 | $data = $this->getData(); 23 | $sign = Helper::sign($data, $this->getApiKey()); 24 | 25 | $responseData = array(); 26 | 27 | if (isset($data['sign']) && $data['sign'] && $sign === $data['sign']) { 28 | $responseData['sign_match'] = true; 29 | } else { 30 | $responseData['sign_match'] = false; 31 | } 32 | 33 | if ($responseData['sign_match'] && isset($data['refund_status']) && $data['refund_status'] == 'SUCCESS') { 34 | $responseData['refunded'] = true; 35 | } else { 36 | $responseData['refunded'] = false; 37 | } 38 | 39 | return $this->response = new CompleteRefundResponse($this, $responseData); 40 | } 41 | 42 | public function getData() 43 | { 44 | $data = $this->getRequestParams(); 45 | 46 | if (is_string($data)) { 47 | $data = Helper::xml2array($data); 48 | } 49 | 50 | // 微信: 退款结果对重要的数据进行了加密 51 | if (isset($data['req_info'])) { 52 | $encrypted_data = openssl_decrypt( 53 | base64_decode($data['req_info']), 54 | 'AES-256-ECB', 55 | md5($this->getApiKey()), 56 | OPENSSL_RAW_DATA 57 | ); 58 | 59 | if (is_string($encrypted_data)) { 60 | unset($data['req_info']); 61 | $data = array_merge($data, Helper::xml2array($encrypted_data)); 62 | } 63 | } 64 | 65 | return $data; 66 | } 67 | 68 | 69 | public function getRequestParams() 70 | { 71 | return $this->getParameter('request_params'); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/Message/CompleteRefundResponse.php: -------------------------------------------------------------------------------- 1 | isRefunded(); 18 | } 19 | 20 | public function isRefunded() 21 | { 22 | $data = $this->getData(); 23 | 24 | return $data['refunded']; 25 | } 26 | 27 | 28 | public function isSignMatch() 29 | { 30 | $data = $this->getData(); 31 | 32 | return $data['sign_match']; 33 | } 34 | 35 | 36 | public function getRequestData() 37 | { 38 | return $this->request->getData(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Message/CouponTransfersRequest.php: -------------------------------------------------------------------------------- 1 | validate('coupon_stock_id', 'openid_count', 'partner_trade_no', 'openid', 'app_id', 'mch_id', 'cert_path', 'key_path'); 31 | 32 | $data = array( 33 | 'coupon_stock_id' => $this->getCouponStockId(), 34 | 'openid_count' => $this->getOpenIdCount(), 35 | 'partner_trade_no' => $this->getPartnerTradeNo(), 36 | 'openid' => $this->getOpenId(), 37 | 'appid' => $this->getAppId(), 38 | 'mch_id' => $this->getMchId(), 39 | 'nonce_str' => md5(uniqid()), 40 | ); 41 | $data = array_filter($data); 42 | 43 | $data['sign'] = Helper::sign($data, $this->getApiKey()); 44 | 45 | return $data; 46 | } 47 | 48 | /** 49 | * @return mixed 50 | */ 51 | public function getCouponStockId() 52 | { 53 | return $this->getParameter('coupon_stock_id'); 54 | } 55 | 56 | /** 57 | * @param mixed $couponStockId 58 | */ 59 | public function setCouponStockId($couponStockId) 60 | { 61 | $this->setParameter('coupon_stock_id', $couponStockId); 62 | } 63 | 64 | /** 65 | * @return mixed 66 | */ 67 | public function getOpenIdCount() 68 | { 69 | return $this->getParameter('openid_count'); 70 | } 71 | 72 | /** 73 | * @param mixed $openidCount 74 | */ 75 | public function setOpenIdCount($openIdCount) 76 | { 77 | $this->setParameter('openid_count', $openIdCount); 78 | } 79 | 80 | /** 81 | * @return mixed 82 | */ 83 | public function getPartnerTradeNo() 84 | { 85 | return $this->getParameter('partner_trade_no'); 86 | } 87 | 88 | /** 89 | * @param mixed $partnerTradeNo 90 | */ 91 | public function setPartnerTradeNo($partnerTradeNo) 92 | { 93 | $this->setParameter('partner_trade_no', $partnerTradeNo); 94 | } 95 | 96 | /** 97 | * @return mixed 98 | */ 99 | public function getOpenId() 100 | { 101 | return $this->getParameter('openid'); 102 | } 103 | 104 | /** 105 | * @param mixed $openId 106 | */ 107 | public function setOpenId($openid) 108 | { 109 | $this->setParameter('openid', $openid); 110 | } 111 | 112 | 113 | /** 114 | * @return mixed 115 | */ 116 | public function getCertPath() 117 | { 118 | return $this->getParameter('cert_path'); 119 | } 120 | 121 | 122 | /** 123 | * @param mixed $certPath 124 | */ 125 | public function setCertPath($certPath) 126 | { 127 | $this->setParameter('cert_path', $certPath); 128 | } 129 | 130 | 131 | /** 132 | * @return mixed 133 | */ 134 | public function getKeyPath() 135 | { 136 | return $this->getParameter('key_path'); 137 | } 138 | 139 | 140 | /** 141 | * @param mixed $keyPath 142 | */ 143 | public function setKeyPath($keyPath) 144 | { 145 | $this->setParameter('key_path', $keyPath); 146 | } 147 | 148 | 149 | /** 150 | * Send the request with specified data 151 | * 152 | * @param mixed $data The data to send 153 | * 154 | * @return ResponseInterface 155 | */ 156 | public function sendData($data) 157 | { 158 | $body = Helper::array2xml($data); 159 | $client = new Client(); 160 | 161 | $options = [ 162 | 'body' => $body, 163 | 'verify' => true, 164 | 'cert' => $this->getCertPath(), 165 | 'ssl_key' => $this->getKeyPath(), 166 | ]; 167 | $response = $client->request('POST', $this->endpoint, $options)->getBody(); 168 | $responseData = Helper::xml2array($response); 169 | 170 | return $this->response = new CouponTransfersResponse($this, $responseData); 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /src/Message/CouponTransfersResponse.php: -------------------------------------------------------------------------------- 1 | validate('app_id', 'mch_id', 'body', 'out_trade_no', 'total_fee', 'auth_code'); 29 | 30 | $data = array( 31 | 'appid' => $this->getAppId(),//* 32 | 'mch_id' => $this->getMchId(), 33 | 'sub_mch_id' => $this->getSubMchId(), 34 | 'device_info' => $this->getDeviceInfo(),//* 35 | 'body' => $this->getBody(),//* 36 | 'detail' => $this->getDetail(), 37 | 'attach' => $this->getAttach(), 38 | 'out_trade_no' => $this->getOutTradeNo(),//* 39 | 'fee_type' => $this->getFeeType(), 40 | 'total_fee' => $this->getTotalFee(),//* 41 | 'spbill_create_ip' => $this->getSpbillCreateIp(),//* 42 | 'goods_tag' => $this->getGoodsTag(), 43 | 'limit_pay' => $this->getLimitPay(), 44 | 'auth_code' => $this->getAuthCode(),//* 45 | 'nonce_str' => md5(uniqid()),//* 46 | ); 47 | 48 | $data = array_filter($data); 49 | 50 | $data['sign'] = Helper::sign($data, $this->getApiKey()); 51 | 52 | return $data; 53 | } 54 | 55 | 56 | /** 57 | * @return mixed 58 | */ 59 | public function getAuthCode() 60 | { 61 | return $this->getParameter('auth_code'); 62 | } 63 | 64 | 65 | public function setAuthCode($authCode) 66 | { 67 | $this->setParameter('auth_code', $authCode); 68 | } 69 | 70 | 71 | /** 72 | * Send the request with specified data 73 | * 74 | * @param mixed $data The data to send 75 | * 76 | * @return ResponseInterface 77 | */ 78 | public function sendData($data) 79 | { 80 | $request = $this->httpClient->request('POST', $this->endpoint, [], Helper::array2xml($data)); 81 | $response = $request->getBody(); 82 | $responseData = Helper::xml2array($response); 83 | 84 | return $this->response = new CreateOrderResponse($this, $responseData); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/Message/CreateMicroOrderResponse.php: -------------------------------------------------------------------------------- 1 | isSuccessful()) { 25 | $data = [ 26 | 'app_id' => $this->request->getAppId(), 27 | 'mch_id' => $this->request->getMchId(), 28 | 'prepay_id' => $this->getPrepayId(), 29 | 'package' => 'Sign=WXPay', 30 | 'nonce' => md5(uniqid()), 31 | 'timestamp' => time() . '', 32 | ]; 33 | 34 | $data['sign'] = Helper::sign($data, $this->request->getApiKey()); 35 | } else { 36 | $data = null; 37 | } 38 | 39 | return $data; 40 | } 41 | 42 | 43 | public function getPrepayId() 44 | { 45 | if ($this->isSuccessful()) { 46 | return $this->getData()['prepay_id']; 47 | } else { 48 | return null; 49 | } 50 | } 51 | 52 | 53 | public function getCodeUrl() 54 | { 55 | if ($this->isSuccessful() && $this->request->getTradeType() == 'NATIVE') { 56 | return $this->getData()['code_url']; 57 | } else { 58 | return null; 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/Message/CreateOrderRequest.php: -------------------------------------------------------------------------------- 1 | validate( 29 | 'app_id', 30 | 'mch_id', 31 | 'body', 32 | 'out_trade_no', 33 | 'total_fee', 34 | 'notify_url', 35 | 'trade_type', 36 | 'spbill_create_ip' 37 | ); 38 | 39 | $tradeType = strtoupper($this->getTradeType()); 40 | 41 | if ($tradeType == 'JSAPI') { 42 | $this->validate('open_id'); 43 | } 44 | 45 | $data = array( 46 | 'appid' => $this->getAppId(),//* 47 | 'mch_id' => $this->getMchId(), 48 | 'sub_appid' => $this->getSubAppId(), 49 | 'sub_mch_id' => $this->getSubMchId(), 50 | 'device_info' => $this->getDeviceInfo(),//* 51 | 'body' => $this->getBody(),//* 52 | 'detail' => $this->getDetail(), 53 | 'attach' => $this->getAttach(), 54 | 'out_trade_no' => $this->getOutTradeNo(),//* 55 | 'fee_type' => $this->getFeeType(), 56 | 'total_fee' => $this->getTotalFee(),//* 57 | 'spbill_create_ip' => $this->getSpbillCreateIp(),//* 58 | 'time_start' => $this->getTimeStart(),//yyyyMMddHHmmss 59 | 'time_expire' => $this->getTimeExpire(),//yyyyMMddHHmmss 60 | 'goods_tag' => $this->getGoodsTag(), 61 | 'notify_url' => $this->getNotifyUrl(), //* 62 | 'trade_type' => $this->getTradeType(), //* 63 | 'limit_pay' => $this->getLimitPay(), 64 | 'openid' => $this->getOpenId(),//*(trade_type=JSAPI) 65 | 'nonce_str' => md5(uniqid()),//* 66 | ); 67 | 68 | $data = array_filter($data); 69 | 70 | $data['sign'] = Helper::sign($data, $this->getApiKey()); 71 | 72 | return $data; 73 | } 74 | 75 | 76 | /** 77 | * @return mixed 78 | */ 79 | public function getTradeType() 80 | { 81 | return $this->getParameter('trade_type'); 82 | } 83 | 84 | 85 | /** 86 | * @return mixed 87 | */ 88 | public function getDeviceInfo() 89 | { 90 | return $this->getParameter('device_Info'); 91 | } 92 | 93 | 94 | /** 95 | * @return mixed 96 | */ 97 | public function getBody() 98 | { 99 | return $this->getParameter('body'); 100 | } 101 | 102 | 103 | /** 104 | * @return mixed 105 | */ 106 | public function getDetail() 107 | { 108 | return $this->getParameter('detail'); 109 | } 110 | 111 | 112 | /** 113 | * @return mixed 114 | */ 115 | public function getAttach() 116 | { 117 | return $this->getParameter('attach'); 118 | } 119 | 120 | 121 | /** 122 | * @return mixed 123 | */ 124 | public function getOutTradeNo() 125 | { 126 | return $this->getParameter('out_trade_no'); 127 | } 128 | 129 | 130 | /** 131 | * @return mixed 132 | */ 133 | public function getFeeType() 134 | { 135 | return $this->getParameter('fee_type'); 136 | } 137 | 138 | 139 | /** 140 | * @return mixed 141 | */ 142 | public function getTotalFee() 143 | { 144 | return $this->getParameter('total_fee'); 145 | } 146 | 147 | 148 | /** 149 | * @return mixed 150 | */ 151 | public function getSpbillCreateIp() 152 | { 153 | return $this->getParameter('spbill_create_ip'); 154 | } 155 | 156 | 157 | /** 158 | * @return mixed 159 | */ 160 | public function getTimeStart() 161 | { 162 | return $this->getParameter('time_start'); 163 | } 164 | 165 | 166 | /** 167 | * @return mixed 168 | */ 169 | public function getTimeExpire() 170 | { 171 | return $this->getParameter('time_expire'); 172 | } 173 | 174 | 175 | /** 176 | * @return mixed 177 | */ 178 | public function getGoodsTag() 179 | { 180 | return $this->getParameter('goods_tag'); 181 | } 182 | 183 | 184 | /** 185 | * @return mixed 186 | */ 187 | public function getNotifyUrl() 188 | { 189 | return $this->getParameter('notify_url'); 190 | } 191 | 192 | 193 | /** 194 | * @return mixed 195 | */ 196 | public function getLimitPay() 197 | { 198 | return $this->getParameter('limit_pay'); 199 | } 200 | 201 | 202 | /** 203 | * @return mixed 204 | */ 205 | public function getOpenId() 206 | { 207 | return $this->getParameter('open_id'); 208 | } 209 | 210 | 211 | /** 212 | * @param mixed $deviceInfo 213 | */ 214 | public function setDeviceInfo($deviceInfo) 215 | { 216 | $this->setParameter('device_Info', $deviceInfo); 217 | } 218 | 219 | 220 | /** 221 | * @param mixed $body 222 | */ 223 | public function setBody($body) 224 | { 225 | $this->setParameter('body', $body); 226 | } 227 | 228 | 229 | /** 230 | * @param mixed $detail 231 | */ 232 | public function setDetail($detail) 233 | { 234 | $this->setParameter('detail', $detail); 235 | } 236 | 237 | 238 | /** 239 | * @param mixed $attach 240 | */ 241 | public function setAttach($attach) 242 | { 243 | $this->setParameter('attach', $attach); 244 | } 245 | 246 | 247 | /** 248 | * @param mixed $outTradeNo 249 | */ 250 | public function setOutTradeNo($outTradeNo) 251 | { 252 | $this->setParameter('out_trade_no', $outTradeNo); 253 | } 254 | 255 | 256 | /** 257 | * @param mixed $feeType 258 | */ 259 | public function setFeeType($feeType) 260 | { 261 | $this->setParameter('fee_type', $feeType); 262 | } 263 | 264 | 265 | /** 266 | * @param mixed $totalFee 267 | */ 268 | public function setTotalFee($totalFee) 269 | { 270 | $this->setParameter('total_fee', $totalFee); 271 | } 272 | 273 | 274 | /** 275 | * @param mixed $spbillCreateIp 276 | */ 277 | public function setSpbillCreateIp($spbillCreateIp) 278 | { 279 | $this->setParameter('spbill_create_ip', $spbillCreateIp); 280 | } 281 | 282 | 283 | /** 284 | * @param mixed $timeStart 285 | */ 286 | public function setTimeStart($timeStart) 287 | { 288 | $this->setParameter('time_start', $timeStart); 289 | } 290 | 291 | 292 | /** 293 | * @param mixed $timeExpire 294 | */ 295 | public function setTimeExpire($timeExpire) 296 | { 297 | $this->setParameter('time_expire', $timeExpire); 298 | } 299 | 300 | 301 | /** 302 | * @param mixed $goodsTag 303 | */ 304 | public function setGoodsTag($goodsTag) 305 | { 306 | $this->setParameter('goods_tag', $goodsTag); 307 | } 308 | 309 | 310 | public function setNotifyUrl($notifyUrl) 311 | { 312 | $this->setParameter('notify_url', $notifyUrl); 313 | } 314 | 315 | 316 | /** 317 | * @param mixed $tradeType 318 | */ 319 | public function setTradeType($tradeType) 320 | { 321 | $this->setParameter('trade_type', $tradeType); 322 | } 323 | 324 | 325 | /** 326 | * @param mixed $limitPay 327 | */ 328 | public function setLimitPay($limitPay) 329 | { 330 | $this->setParameter('limit_pay', $limitPay); 331 | } 332 | 333 | 334 | /** 335 | * @param mixed $openId 336 | */ 337 | public function setOpenId($openId) 338 | { 339 | $this->setParameter('open_id', $openId); 340 | } 341 | 342 | 343 | /** 344 | * Send the request with specified data 345 | * 346 | * @param mixed $data The data to send 347 | * 348 | * @return ResponseInterface 349 | * @throws \Psr\Http\Client\Exception\NetworkException 350 | * @throws \Psr\Http\Client\Exception\RequestException 351 | */ 352 | public function sendData($data) 353 | { 354 | $body = Helper::array2xml($data); 355 | $response = $this->httpClient->request('POST', $this->endpoint, [], $body)->getBody(); 356 | $payload = Helper::xml2array($response); 357 | 358 | return $this->response = new CreateOrderResponse($this, $payload); 359 | } 360 | } 361 | -------------------------------------------------------------------------------- /src/Message/CreateOrderResponse.php: -------------------------------------------------------------------------------- 1 | isSuccessful()) { 25 | $data = [ 26 | 'appid' => $this->request->getAppId(), 27 | 'partnerid' => $this->request->getMchId(), 28 | 'prepayid' => $this->getPrepayId(), 29 | 'package' => 'Sign=WXPay', 30 | 'noncestr' => md5(uniqid()), 31 | 'timestamp' => time(), 32 | ]; 33 | 34 | $data['sign'] = Helper::sign($data, $this->request->getApiKey()); 35 | } else { 36 | $data = null; 37 | } 38 | 39 | return $data; 40 | } 41 | 42 | 43 | public function getPrepayId() 44 | { 45 | if ($this->isSuccessful()) { 46 | $data = $this->getData(); 47 | 48 | return $data['prepay_id']; 49 | } else { 50 | return null; 51 | } 52 | } 53 | 54 | 55 | public function getJsOrderData() 56 | { 57 | if ($this->isSuccessful()) { 58 | $data = [ 59 | 'appId' => $this->request->getAppId(), 60 | 'package' => 'prepay_id=' . $this->getPrepayId(), 61 | 'nonceStr' => md5(uniqid()), 62 | 'timeStamp' => time() . '', 63 | ]; 64 | 65 | $data['signType'] = 'MD5'; 66 | $data['paySign'] = Helper::sign($data, $this->request->getApiKey()); 67 | } else { 68 | $data = null; 69 | } 70 | 71 | return $data; 72 | } 73 | 74 | 75 | public function getCodeUrl() 76 | { 77 | if ($this->isSuccessful() && $this->request->getTradeType() == 'NATIVE') { 78 | $data = $this->getData(); 79 | 80 | return $data['code_url']; 81 | } else { 82 | return null; 83 | } 84 | } 85 | 86 | 87 | public function getMwebUrl() 88 | { 89 | if ($this->isSuccessful() && $this->request->getTradeType() == 'MWEB') { 90 | $data = $this->getData(); 91 | 92 | return $data['mweb_url']; 93 | } else { 94 | return null; 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/Message/DownloadBillRequest.php: -------------------------------------------------------------------------------- 1 | validate('app_id', 'mch_id', 'bill_date'); 30 | 31 | $data = array( 32 | 'appid' => $this->getAppId(), 33 | 'mch_id' => $this->getMchId(), 34 | 'sub_appid' => $this->getSubAppId(), 35 | 'sub_mch_id' => $this->getSubMchId(), 36 | 'device_info' => $this->getDeviceInfo(), 37 | 'bill_date' => $this->getBillDate(), 38 | 'bill_type' => $this->getBillType(),//<> 39 | 'nonce_str' => md5(uniqid()), 40 | ); 41 | 42 | $data = array_filter($data); 43 | 44 | $data['sign'] = Helper::sign($data, $this->getApiKey()); 45 | 46 | return $data; 47 | } 48 | 49 | 50 | /** 51 | * @return mixed 52 | */ 53 | public function getDeviceInfo() 54 | { 55 | return $this->getParameter('device_Info'); 56 | } 57 | 58 | 59 | /** 60 | * @param mixed $deviceInfo 61 | */ 62 | public function setDeviceInfo($deviceInfo) 63 | { 64 | $this->setParameter('device_Info', $deviceInfo); 65 | } 66 | 67 | 68 | /** 69 | * @return mixed 70 | */ 71 | public function getBillDate() 72 | { 73 | return $this->getParameter('bill_date'); 74 | } 75 | 76 | 77 | /** 78 | * @param mixed $billDate 79 | */ 80 | public function setBillDate($billDate) 81 | { 82 | $this->setParameter('bill_date', $billDate); 83 | } 84 | 85 | 86 | /** 87 | * @return mixed 88 | */ 89 | public function getBillType() 90 | { 91 | return $this->getParameter('bill_type'); 92 | } 93 | 94 | 95 | /** 96 | * @param mixed $billType 97 | */ 98 | public function setBillType($billType) 99 | { 100 | $this->setParameter('bill_type', $billType); 101 | } 102 | 103 | 104 | /** 105 | * Send the request with specified data 106 | * 107 | * @param mixed $data The data to send 108 | * 109 | * @return ResponseInterface 110 | */ 111 | public function sendData($data) 112 | { 113 | $responseData = $this->post($this->endpoint, $data, 120); 114 | 115 | return $this->response = new DownloadBillResponse($this, $responseData); 116 | } 117 | 118 | 119 | private function post($url, $data = array(), $timeout = 3) 120 | { 121 | $ch = curl_init($url); 122 | 123 | curl_setopt($ch, CURLOPT_POST, true); 124 | curl_setopt($ch, CURLOPT_POSTFIELDS, Helper::array2xml($data)); 125 | curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); 126 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 127 | 128 | $result = curl_exec($ch); 129 | 130 | if (preg_match('#return_code#', $result)) { 131 | $result = Helper::xml2array($result); 132 | } else { 133 | $result = array(['return_code' => 'SUCCESS', 'raw' => $result]); 134 | } 135 | 136 | return $result; 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /src/Message/DownloadBillResponse.php: -------------------------------------------------------------------------------- 1 | validate('mch_id', 'cert_path', 'key_path'); 30 | 31 | $data = array( 32 | 'mch_id' => $this->getMchId(), 33 | 'nonce_str' => md5(uniqid()), 34 | ); 35 | 36 | $data = array_filter($data); 37 | 38 | $data['sign'] = Helper::sign($data, $this->getApiKey()); 39 | 40 | return $data; 41 | } 42 | 43 | 44 | /** 45 | * @return mixed 46 | */ 47 | public function getCertPath() 48 | { 49 | return $this->getParameter('cert_path'); 50 | } 51 | 52 | 53 | /** 54 | * @param mixed $certPath 55 | */ 56 | public function setCertPath($certPath) 57 | { 58 | $this->setParameter('cert_path', $certPath); 59 | } 60 | 61 | 62 | /** 63 | * @return mixed 64 | */ 65 | public function getKeyPath() 66 | { 67 | return $this->getParameter('key_path'); 68 | } 69 | 70 | 71 | /** 72 | * @param mixed $keyPath 73 | */ 74 | public function setKeyPath($keyPath) 75 | { 76 | $this->setParameter('key_path', $keyPath); 77 | } 78 | 79 | 80 | /** 81 | * Send the request with specified data 82 | * 83 | * @param mixed $data The data to send 84 | * 85 | * @return ResponseInterface 86 | */ 87 | public function sendData($data) 88 | { 89 | $body = Helper::array2xml($data); 90 | $client = new Client(); 91 | 92 | $options = [ 93 | 'body' => $body, 94 | 'verify' => true, 95 | 'cert' => $this->getCertPath(), 96 | 'ssl_key' => $this->getKeyPath(), 97 | ]; 98 | $response = $client->request('POST', $this->endpoint, $options)->getBody(); 99 | $responseData = Helper::xml2array($response); 100 | 101 | return $this->response = new GetPublicKeyResponse($this, $responseData); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/Message/GetPublicKeyResponse.php: -------------------------------------------------------------------------------- 1 | validate('mch_id', 'partner_trade_no', 'enc_bank_no', 'enc_true_name', 'bank_code', 'amount', 'desc', 'cert_path', 'key_path'); 30 | 31 | $data = array( 32 | 'mch_id' => $this->getMchId(), 33 | 'partner_trade_no' => $this->getPartnerTradeNo(), 34 | 'enc_bank_no' => $this->getEncBankNo(), 35 | 'enc_true_name' => $this->getEncTrueName(), 36 | 'bank_code' => $this->getBankCode(), 37 | 'amount' => $this->getAmount(), 38 | 'desc' => $this->getDesc(), 39 | 'nonce_str' => md5(uniqid()), 40 | ); 41 | 42 | $data = array_filter($data); 43 | 44 | $data['sign'] = Helper::sign($data, $this->getApiKey()); 45 | 46 | return $data; 47 | } 48 | 49 | 50 | /** 51 | * @return mixed 52 | */ 53 | public function getPartnerTradeNo() 54 | { 55 | return $this->getParameter('partner_trade_no'); 56 | } 57 | 58 | 59 | /** 60 | * @param mixed $partnerTradeNo 61 | */ 62 | public function setPartnerTradeNo($partnerTradeNo) 63 | { 64 | $this->setParameter('partner_trade_no', $partnerTradeNo); 65 | } 66 | 67 | 68 | /** 69 | * @return mixed 70 | */ 71 | public function getEncBankNo() 72 | { 73 | return $this->getParameter('enc_bank_no'); 74 | } 75 | 76 | 77 | /** 78 | * @param mixed $encBankNo 79 | */ 80 | public function setEncBankNo($encBankNo) 81 | { 82 | $this->setParameter('enc_bank_no', $encBankNo); 83 | } 84 | 85 | 86 | /** 87 | * @return mixed 88 | */ 89 | public function getEncTrueName() 90 | { 91 | return $this->getParameter('enc_true_name'); 92 | } 93 | 94 | 95 | /** 96 | * @param mixed $encTrueName 97 | */ 98 | public function setEncTrueName($encTrueName) 99 | { 100 | $this->setParameter('enc_true_name', $encTrueName); 101 | } 102 | 103 | 104 | /** 105 | * @return mixed 106 | */ 107 | public function getBankCode() 108 | { 109 | return $this->getParameter('bank_code'); 110 | } 111 | 112 | 113 | /** 114 | * @param mixed $bankCode 115 | */ 116 | public function setBankCode($bankCode) 117 | { 118 | $this->setParameter('bank_code', $bankCode); 119 | } 120 | 121 | 122 | /** 123 | * @return mixed 124 | */ 125 | public function getAmount() 126 | { 127 | return $this->getParameter('amount'); 128 | } 129 | 130 | 131 | /** 132 | * @param mixed $amount 133 | */ 134 | public function setAmount($amount) 135 | { 136 | $this->setParameter('amount', $amount); 137 | } 138 | 139 | 140 | /** 141 | * @return mixed 142 | */ 143 | public function getDesc() 144 | { 145 | return $this->getParameter('desc'); 146 | } 147 | 148 | 149 | /** 150 | * @param mixed $desc 151 | */ 152 | public function setDesc($desc) 153 | { 154 | $this->setParameter('desc', $desc); 155 | } 156 | 157 | 158 | /** 159 | * @return mixed 160 | */ 161 | public function getCertPath() 162 | { 163 | return $this->getParameter('cert_path'); 164 | } 165 | 166 | 167 | /** 168 | * @param mixed $certPath 169 | */ 170 | public function setCertPath($certPath) 171 | { 172 | $this->setParameter('cert_path', $certPath); 173 | } 174 | 175 | 176 | /** 177 | * @return mixed 178 | */ 179 | public function getKeyPath() 180 | { 181 | return $this->getParameter('key_path'); 182 | } 183 | 184 | 185 | /** 186 | * @param mixed $keyPath 187 | */ 188 | public function setKeyPath($keyPath) 189 | { 190 | $this->setParameter('key_path', $keyPath); 191 | } 192 | 193 | 194 | /** 195 | * Send the request with specified data 196 | * 197 | * @param mixed $data The data to send 198 | * 199 | * @return ResponseInterface 200 | */ 201 | public function sendData($data) 202 | { 203 | $body = Helper::array2xml($data); 204 | $client = new Client(); 205 | 206 | $options = [ 207 | 'body' => $body, 208 | 'verify' => true, 209 | 'cert' => $this->getCertPath(), 210 | 'ssl_key' => $this->getKeyPath(), 211 | ]; 212 | $response = $client->request('POST', $this->endpoint, $options)->getBody(); 213 | $responseData = Helper::xml2array($response); 214 | 215 | return $this->response = new PayBankResponse($this, $responseData); 216 | } 217 | } 218 | -------------------------------------------------------------------------------- /src/Message/PayBankResponse.php: -------------------------------------------------------------------------------- 1 | validate('app_id', 'mch_id', 'partner_trade_no', 'cert_path', 'key_path'); 31 | 32 | $data = array( 33 | 'mch_appid' => $this->getAppId(), 34 | 'mchid' => $this->getMchId(), 35 | 'device_info' => $this->getDeviceInfo(), // 36 | 'partner_trade_no' => $this->getPartnerTradeNo(), 37 | 'openid' => $this->getOpenId(), 38 | 'check_name' => $this->getCheckName(), // 39 | 're_user_name' => $this->getReUserName(), 40 | 'amount' => $this->getAmount(), 41 | 'desc' => $this->getDesc(), 42 | 'spbill_create_ip' => $this->getSpbillCreateIp(), 43 | 'nonce_str' => md5(uniqid()), 44 | ); 45 | 46 | $data = array_filter($data); 47 | 48 | $data['sign'] = Helper::sign($data, $this->getApiKey()); 49 | 50 | return $data; 51 | } 52 | 53 | 54 | /** 55 | * @return mixed 56 | */ 57 | public function getDeviceInfo() 58 | { 59 | return $this->getParameter('device_Info'); 60 | } 61 | 62 | 63 | /** 64 | * @param mixed $deviceInfo 65 | */ 66 | public function setDeviceInfo($deviceInfo) 67 | { 68 | $this->setParameter('device_Info', $deviceInfo); 69 | } 70 | 71 | 72 | /** 73 | * @return mixed 74 | */ 75 | public function getPartnerTradeNo() 76 | { 77 | return $this->getParameter('partner_trade_no'); 78 | } 79 | 80 | 81 | /** 82 | * @param mixed $partnerTradeNo 83 | */ 84 | public function setPartnerTradeNo($partnerTradeNo) 85 | { 86 | $this->setParameter('partner_trade_no', $partnerTradeNo); 87 | } 88 | 89 | 90 | /** 91 | * @return mixed 92 | */ 93 | public function getOpenId() 94 | { 95 | return $this->getParameter('open_id'); 96 | } 97 | 98 | 99 | /** 100 | * @param mixed $openId 101 | */ 102 | public function setOpenId($openId) 103 | { 104 | $this->setParameter('open_id', $openId); 105 | } 106 | 107 | 108 | /** 109 | * @return mixed 110 | */ 111 | public function getCheckName() 112 | { 113 | return $this->getParameter('check_name'); 114 | } 115 | 116 | 117 | /** 118 | * @param mixed $checkName 119 | */ 120 | public function setCheckName($checkName) 121 | { 122 | $this->setParameter('check_name', $checkName); 123 | } 124 | 125 | 126 | /** 127 | * @return mixed 128 | */ 129 | public function getReUserName() 130 | { 131 | return $this->getParameter('re_user_name'); 132 | } 133 | 134 | 135 | /** 136 | * @param mixed $reUserNamme 137 | */ 138 | public function setReUserName($reUserName) 139 | { 140 | $this->setParameter('re_user_name', $reUserName); 141 | } 142 | 143 | 144 | /** 145 | * @return mixed 146 | */ 147 | public function getAmount() 148 | { 149 | return $this->getParameter('amount'); 150 | } 151 | 152 | 153 | /** 154 | * @param mixed $amount 155 | */ 156 | public function setAmount($amount) 157 | { 158 | $this->setParameter('amount', $amount); 159 | } 160 | 161 | 162 | /** 163 | * @return mixed 164 | */ 165 | public function getDesc() 166 | { 167 | return $this->getParameter('desc'); 168 | } 169 | 170 | 171 | /** 172 | * @param mixed $desc 173 | */ 174 | public function setDesc($desc) 175 | { 176 | $this->setParameter('desc', $desc); 177 | } 178 | 179 | 180 | /** 181 | * @return mixed 182 | */ 183 | public function getSpbillCreateIp() 184 | { 185 | return $this->getParameter('spbill_create_ip'); 186 | } 187 | 188 | 189 | /** 190 | * @param mixed $spbill_create_ip 191 | */ 192 | public function setSpbillCreateIp($spbillCreateIp) 193 | { 194 | $this->setParameter('spbill_create_ip', $spbillCreateIp); 195 | } 196 | 197 | 198 | /** 199 | * @return mixed 200 | */ 201 | public function getCertPath() 202 | { 203 | return $this->getParameter('cert_path'); 204 | } 205 | 206 | 207 | /** 208 | * @param mixed $certPath 209 | */ 210 | public function setCertPath($certPath) 211 | { 212 | $this->setParameter('cert_path', $certPath); 213 | } 214 | 215 | 216 | /** 217 | * @return mixed 218 | */ 219 | public function getKeyPath() 220 | { 221 | return $this->getParameter('key_path'); 222 | } 223 | 224 | 225 | /** 226 | * @param mixed $keyPath 227 | */ 228 | public function setKeyPath($keyPath) 229 | { 230 | $this->setParameter('key_path', $keyPath); 231 | } 232 | 233 | 234 | /** 235 | * Send the request with specified data 236 | * 237 | * @param mixed $data The data to send 238 | * 239 | * @return ResponseInterface 240 | */ 241 | public function sendData($data) 242 | { 243 | $body = Helper::array2xml($data); 244 | $client = new Client(); 245 | 246 | $options = [ 247 | 'body' => $body, 248 | 'verify' => true, 249 | 'cert' => $this->getCertPath(), 250 | 'ssl_key' => $this->getKeyPath(), 251 | ]; 252 | $response = $client->request('POST', $this->endpoint, $options)->getBody(); 253 | $responseData = Helper::xml2array($response); 254 | 255 | return $this->response = new PromotionTransferResponse($this, $responseData); 256 | } 257 | } 258 | -------------------------------------------------------------------------------- /src/Message/PromotionTransferResponse.php: -------------------------------------------------------------------------------- 1 | validate('mch_id', 'partner_trade_no', 'cert_path', 'key_path'); 30 | 31 | $data = array( 32 | 'mch_id' => $this->getMchId(), 33 | 'partner_trade_no' => $this->getPartnerTradeNo(), 34 | 'nonce_str' => md5(uniqid()), 35 | ); 36 | 37 | $data = array_filter($data); 38 | 39 | $data['sign'] = Helper::sign($data, $this->getApiKey()); 40 | 41 | return $data; 42 | } 43 | 44 | 45 | /** 46 | * @return mixed 47 | */ 48 | public function getPartnerTradeNo() 49 | { 50 | return $this->getParameter('partner_trade_no'); 51 | } 52 | 53 | 54 | /** 55 | * @param mixed $partnerTradeNo 56 | */ 57 | public function setPartnerTradeNo($partnerTradeNo) 58 | { 59 | $this->setParameter('partner_trade_no', $partnerTradeNo); 60 | } 61 | 62 | 63 | /** 64 | * @return mixed 65 | */ 66 | public function getCertPath() 67 | { 68 | return $this->getParameter('cert_path'); 69 | } 70 | 71 | 72 | /** 73 | * @param mixed $certPath 74 | */ 75 | public function setCertPath($certPath) 76 | { 77 | $this->setParameter('cert_path', $certPath); 78 | } 79 | 80 | 81 | /** 82 | * @return mixed 83 | */ 84 | public function getKeyPath() 85 | { 86 | return $this->getParameter('key_path'); 87 | } 88 | 89 | 90 | /** 91 | * @param mixed $keyPath 92 | */ 93 | public function setKeyPath($keyPath) 94 | { 95 | $this->setParameter('key_path', $keyPath); 96 | } 97 | 98 | 99 | /** 100 | * Send the request with specified data 101 | * 102 | * @param mixed $data The data to send 103 | * 104 | * @return ResponseInterface 105 | */ 106 | public function sendData($data) 107 | { 108 | $body = Helper::array2xml($data); 109 | $client = new Client(); 110 | 111 | $options = [ 112 | 'body' => $body, 113 | 'verify' => true, 114 | 'cert' => $this->getCertPath(), 115 | 'ssl_key' => $this->getKeyPath(), 116 | ]; 117 | $response = $client->request('POST', $this->endpoint, $options)->getBody(); 118 | $responseData = Helper::xml2array($response); 119 | 120 | return $this->response = new QueryBankResponse($this, $responseData); 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/Message/QueryBankResponse.php: -------------------------------------------------------------------------------- 1 | validate('app_id', 'mch_id', 'auth_code'); 30 | 31 | $data = array( 32 | 'appid' => $this->getAppId(), 33 | 'mch_id' => $this->getMchId(), 34 | 'sub_mch_id' => $this->getSubMchId(), 35 | 'auth_code' => $this->getAuthCode(), 36 | 'nonce_str' => md5(uniqid()), 37 | ); 38 | 39 | $data = array_filter($data); 40 | 41 | $data['sign'] = Helper::sign($data, $this->getApiKey()); 42 | 43 | return $data; 44 | } 45 | 46 | 47 | /** 48 | * @return mixed 49 | */ 50 | public function getAuthCode() 51 | { 52 | return $this->getParameter('auth_code'); 53 | } 54 | 55 | 56 | /** 57 | * @param mixed $authCode 58 | */ 59 | public function setAuthCode($authCode) 60 | { 61 | $this->setParameter('auth_code', $authCode); 62 | } 63 | 64 | 65 | /** 66 | * Send the request with specified data 67 | * 68 | * @param mixed $data The data to send 69 | * 70 | * @return ResponseInterface 71 | */ 72 | public function sendData($data) 73 | { 74 | $request = $this->httpClient->request('POST', $this->endpoint, [], Helper::array2xml($data)); 75 | $response = $request->getBody(); 76 | $responseData = Helper::xml2array($response); 77 | 78 | return $this->response = new CloseOrderResponse($this, $responseData); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/Message/QueryOpenIdByAuthCodeResponse.php: -------------------------------------------------------------------------------- 1 | getData(); 16 | 17 | return isset($data['openid']) ? $data['openid'] : null; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Message/QueryOrderRequest.php: -------------------------------------------------------------------------------- 1 | validate('app_id', 'mch_id'); 30 | 31 | if (! $this->getTransactionId() && ! $this->getOutTradeNo()) { 32 | throw new InvalidRequestException("The 'transaction_id' or 'out_trade_no' parameter is required"); 33 | } 34 | 35 | $data = array( 36 | 'appid' => $this->getAppId(), 37 | 'mch_id' => $this->getMchId(), 38 | 'sub_appid' => $this->getSubAppId(), 39 | 'sub_mch_id' => $this->getSubMchId(), 40 | 'transaction_id' => $this->getTransactionId(), 41 | 'out_trade_no' => $this->getOutTradeNo(), 42 | 'nonce_str' => md5(uniqid()), 43 | ); 44 | 45 | $data = array_filter($data); 46 | 47 | $data['sign'] = Helper::sign($data, $this->getApiKey()); 48 | 49 | return $data; 50 | } 51 | 52 | 53 | /** 54 | * @return mixed 55 | */ 56 | public function getOutTradeNo() 57 | { 58 | return $this->getParameter('out_trade_no'); 59 | } 60 | 61 | 62 | /** 63 | * @param mixed $outTradeNo 64 | */ 65 | public function setOutTradeNo($outTradeNo) 66 | { 67 | $this->setParameter('out_trade_no', $outTradeNo); 68 | } 69 | 70 | 71 | /** 72 | * @return mixed 73 | */ 74 | public function getTransactionId() 75 | { 76 | return $this->getParameter('transaction_id'); 77 | } 78 | 79 | 80 | public function setTransactionId($transactionId) 81 | { 82 | $this->setParameter('transaction_id', $transactionId); 83 | } 84 | 85 | 86 | /** 87 | * Send the request with specified data 88 | * 89 | * @param mixed $data The data to send 90 | * 91 | * @return ResponseInterface 92 | * @throws \Psr\Http\Client\Exception\NetworkException 93 | * @throws \Psr\Http\Client\Exception\RequestException 94 | */ 95 | public function sendData($data) 96 | { 97 | $body = Helper::array2xml($data); 98 | $response = $this->httpClient->request('POST', $this->endpoint, [], $body)->getBody(); 99 | $payload = Helper::xml2array($response); 100 | 101 | return $this->response = new QueryOrderResponse($this, $payload); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/Message/QueryOrderResponse.php: -------------------------------------------------------------------------------- 1 | validate('app_id', 'mch_id'); 30 | 31 | $queryIdEmpty = ! $this->getTransactionId() && ! $this->getOutTradeNo(); 32 | $queryIdEmpty = ($queryIdEmpty && ! $this->getOutRefundNo() && ! $this->getRefundId()); 33 | 34 | if ($queryIdEmpty) { 35 | $message = "The 'transaction_id' or 'out_trade_no' or 'out_refund_no' or 'refund_id' parameter is required"; 36 | throw new InvalidRequestException($message); 37 | } 38 | 39 | $data = array( 40 | 'appid' => $this->getAppId(), 41 | 'mch_id' => $this->getMchId(), 42 | 'sub_appid' => $this->getSubAppId(), 43 | 'sub_mch_id' => $this->getSubMchId(), 44 | 'device_info' => $this->getDeviceInfo(), 45 | 'transaction_id' => $this->getTransactionId(), 46 | 'out_trade_no' => $this->getOutTradeNo(), 47 | 'out_refund_no' => $this->getOutRefundNo(), 48 | 'refund_id' => $this->getRefundId(), 49 | 'nonce_str' => md5(uniqid()), 50 | ); 51 | 52 | $data = array_filter($data); 53 | 54 | $data['sign'] = Helper::sign($data, $this->getApiKey()); 55 | 56 | return $data; 57 | } 58 | 59 | 60 | /** 61 | * @return mixed 62 | */ 63 | public function getOutTradeNo() 64 | { 65 | return $this->getParameter('out_trade_no'); 66 | } 67 | 68 | 69 | /** 70 | * @param mixed $outTradeNo 71 | */ 72 | public function setOutTradeNo($outTradeNo) 73 | { 74 | $this->setParameter('out_trade_no', $outTradeNo); 75 | } 76 | 77 | 78 | /** 79 | * @return mixed 80 | */ 81 | public function getTransactionId() 82 | { 83 | return $this->getParameter('transaction_id'); 84 | } 85 | 86 | 87 | public function setTransactionId($transactionId) 88 | { 89 | $this->setParameter('transaction_id', $transactionId); 90 | } 91 | 92 | 93 | /** 94 | * @return mixed 95 | */ 96 | public function getDeviceInfo() 97 | { 98 | return $this->getParameter('device_Info'); 99 | } 100 | 101 | 102 | /** 103 | * @param mixed $deviceInfo 104 | */ 105 | public function setDeviceInfo($deviceInfo) 106 | { 107 | $this->setParameter('device_Info', $deviceInfo); 108 | } 109 | 110 | 111 | /** 112 | * @return mixed 113 | */ 114 | public function getOutRefundNo() 115 | { 116 | return $this->getParameter('out_refund_no'); 117 | } 118 | 119 | 120 | /** 121 | * @param mixed $outRefundNo 122 | */ 123 | public function setOutRefundNo($outRefundNo) 124 | { 125 | $this->setParameter('out_refund_no', $outRefundNo); 126 | } 127 | 128 | 129 | /** 130 | * @return mixed 131 | */ 132 | public function getRefundId() 133 | { 134 | return $this->getParameter('refund_id'); 135 | } 136 | 137 | 138 | /** 139 | * @param mixed $refundId 140 | */ 141 | public function setRefundId($refundId) 142 | { 143 | $this->setParameter('refund_id', $refundId); 144 | } 145 | 146 | 147 | /** 148 | * Send the request with specified data 149 | * 150 | * @param mixed $data The data to send 151 | * 152 | * @return ResponseInterface 153 | */ 154 | public function sendData($data) 155 | { 156 | $request = $this->httpClient->request('POST', $this->endpoint, [], Helper::array2xml($data)); 157 | $response = $request->getBody(); 158 | $responseData = Helper::xml2array($response); 159 | 160 | return $this->response = new QueryRefundResponse($this, $responseData); 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /src/Message/QueryRefundResponse.php: -------------------------------------------------------------------------------- 1 | validate('app_id', 'mch_id', 'partner_trade_no', 'cert_path', 'key_path'); 31 | 32 | $data = array( 33 | 'appid' => $this->getAppId(), 34 | 'mch_id' => $this->getMchId(), 35 | 'partner_trade_no' => $this->getPartnerTradeNo(), 36 | 'nonce_str' => md5(uniqid()), 37 | ); 38 | 39 | $data = array_filter($data); 40 | 41 | $data['sign'] = Helper::sign($data, $this->getApiKey()); 42 | 43 | return $data; 44 | } 45 | 46 | 47 | /** 48 | * @return mixed 49 | */ 50 | public function getPartnerTradeNo() 51 | { 52 | return $this->getParameter('partner_trade_no'); 53 | } 54 | 55 | 56 | /** 57 | * @param mixed $partnerTradeNo 58 | */ 59 | public function setPartnerTradeNo($partnerTradeNo) 60 | { 61 | $this->setParameter('partner_trade_no', $partnerTradeNo); 62 | } 63 | 64 | 65 | /** 66 | * @return mixed 67 | */ 68 | public function getCertPath() 69 | { 70 | return $this->getParameter('cert_path'); 71 | } 72 | 73 | 74 | /** 75 | * @param mixed $certPath 76 | */ 77 | public function setCertPath($certPath) 78 | { 79 | $this->setParameter('cert_path', $certPath); 80 | } 81 | 82 | 83 | /** 84 | * @return mixed 85 | */ 86 | public function getKeyPath() 87 | { 88 | return $this->getParameter('key_path'); 89 | } 90 | 91 | 92 | /** 93 | * @param mixed $keyPath 94 | */ 95 | public function setKeyPath($keyPath) 96 | { 97 | $this->setParameter('key_path', $keyPath); 98 | } 99 | 100 | 101 | /** 102 | * Send the request with specified data 103 | * 104 | * @param mixed $data The data to send 105 | * 106 | * @return ResponseInterface 107 | */ 108 | public function sendData($data) 109 | { 110 | $body = Helper::array2xml($data); 111 | $client = new Client(); 112 | 113 | $options = [ 114 | 'body' => $body, 115 | 'verify' => true, 116 | 'cert' => $this->getCertPath(), 117 | 'ssl_key' => $this->getKeyPath(), 118 | ]; 119 | $response = $client->request('POST', $this->endpoint, $options)->getBody(); 120 | $responseData = Helper::xml2array($response); 121 | 122 | return $this->response = new QueryTransferResponse($this, $responseData); 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/Message/QueryTransferResponse.php: -------------------------------------------------------------------------------- 1 | validate('app_id', 'mch_id', 'out_trade_no', 'cert_path', 'key_path'); 31 | 32 | $data = [ 33 | 'appid' => $this->getAppId(), 34 | 'mch_id' => $this->getMchId(), 35 | 'sub_appid' => $this->getSubAppId(), 36 | 'sub_mch_id' => $this->getSubMchId(), 37 | 'device_info' => $this->getDeviceInfo(),//<> 38 | 'transaction_id' => $this->getTransactionId(), 39 | 'out_trade_no' => $this->getOutTradeNo(), 40 | 'out_refund_no' => $this->getOutRefundNo(), 41 | 'total_fee' => $this->getTotalFee(), 42 | 'refund_fee' => $this->getRefundFee(), 43 | 'refund_fee_type' => $this->getRefundFee(),//<> 44 | 'op_user_id' => $this->getOpUserId() ?: $this->getMchId(), 45 | 'refund_account' => $this->getRefundAccount(), 46 | 'nonce_str' => md5(uniqid()), 47 | ]; 48 | 49 | $data = array_filter($data); 50 | 51 | $data['sign'] = Helper::sign($data, $this->getApiKey()); 52 | 53 | return $data; 54 | } 55 | 56 | /** 57 | * @return mixed 58 | */ 59 | public function getRefundAccount() 60 | { 61 | return $this->getParameter('refund_account'); 62 | } 63 | 64 | /** 65 | * @param mixed $refundAccount 66 | */ 67 | public function setRefundAccount($refundAccount) 68 | { 69 | $this->setParameter('refund_account', $refundAccount); 70 | } 71 | 72 | 73 | /** 74 | * @return mixed 75 | */ 76 | public function getOutTradeNo() 77 | { 78 | return $this->getParameter('out_trade_no'); 79 | } 80 | 81 | 82 | /** 83 | * @param mixed $outTradeNo 84 | */ 85 | public function setOutTradeNo($outTradeNo) 86 | { 87 | $this->setParameter('out_trade_no', $outTradeNo); 88 | } 89 | 90 | 91 | /** 92 | * @return mixed 93 | */ 94 | public function getOpUserId() 95 | { 96 | return $this->getParameter('op_user_id'); 97 | } 98 | 99 | 100 | /** 101 | * @param mixed $opUserId 102 | */ 103 | public function setOpUserId($opUserId) 104 | { 105 | $this->setParameter('op_user_id', $opUserId); 106 | } 107 | 108 | 109 | /** 110 | * @return mixed 111 | */ 112 | public function getOutRefundNo() 113 | { 114 | return $this->getParameter('out_refund_no'); 115 | } 116 | 117 | 118 | /** 119 | * @param mixed $outRefundNo 120 | */ 121 | public function setOutRefundNo($outRefundNo) 122 | { 123 | $this->setParameter('out_refund_no', $outRefundNo); 124 | } 125 | 126 | 127 | /** 128 | * @return mixed 129 | */ 130 | public function getDeviceInfo() 131 | { 132 | return $this->getParameter('device_Info'); 133 | } 134 | 135 | 136 | /** 137 | * @param mixed $deviceInfo 138 | */ 139 | public function setDeviceInfo($deviceInfo) 140 | { 141 | $this->setParameter('device_Info', $deviceInfo); 142 | } 143 | 144 | 145 | /** 146 | * @return mixed 147 | */ 148 | public function getTransactionId() 149 | { 150 | return $this->getParameter('transaction_id'); 151 | } 152 | 153 | 154 | public function setTransactionId($transactionId) 155 | { 156 | $this->setParameter('transaction_id', $transactionId); 157 | } 158 | 159 | 160 | /** 161 | * @return mixed 162 | */ 163 | public function getTotalFee() 164 | { 165 | return $this->getParameter('total_fee'); 166 | } 167 | 168 | 169 | /** 170 | * @param mixed $totalFee 171 | */ 172 | public function setTotalFee($totalFee) 173 | { 174 | $this->setParameter('total_fee', $totalFee); 175 | } 176 | 177 | 178 | /** 179 | * @return mixed 180 | */ 181 | public function getRefundFee() 182 | { 183 | return $this->getParameter('refund_fee'); 184 | } 185 | 186 | 187 | /** 188 | * @param mixed $refundFee 189 | */ 190 | public function setRefundFee($refundFee) 191 | { 192 | $this->setParameter('refund_fee', $refundFee); 193 | } 194 | 195 | 196 | /** 197 | * @return mixed 198 | */ 199 | public function getRefundType() 200 | { 201 | return $this->getParameter('refund_fee_type'); 202 | } 203 | 204 | 205 | /** 206 | * @param mixed $refundFeeType 207 | */ 208 | public function setRefundType($refundFeeType) 209 | { 210 | $this->setParameter('refund_fee_type', $refundFeeType); 211 | } 212 | 213 | 214 | /** 215 | * @return mixed 216 | */ 217 | public function getCertPath() 218 | { 219 | return $this->getParameter('cert_path'); 220 | } 221 | 222 | 223 | /** 224 | * @param mixed $certPath 225 | */ 226 | public function setCertPath($certPath) 227 | { 228 | $this->setParameter('cert_path', $certPath); 229 | } 230 | 231 | 232 | /** 233 | * @return mixed 234 | */ 235 | public function getKeyPath() 236 | { 237 | return $this->getParameter('key_path'); 238 | } 239 | 240 | 241 | /** 242 | * @param mixed $keyPath 243 | */ 244 | public function setKeyPath($keyPath) 245 | { 246 | $this->setParameter('key_path', $keyPath); 247 | } 248 | 249 | 250 | /** 251 | * Send the request with specified data 252 | * 253 | * @param mixed $data The data to send 254 | * 255 | * @return ResponseInterface 256 | * @throws \GuzzleHttp\Exception\GuzzleException 257 | */ 258 | public function sendData($data) 259 | { 260 | $body = Helper::array2xml($data); 261 | 262 | $client = new Client(); 263 | 264 | $options = [ 265 | 'body' => $body, 266 | 'verify' => true, 267 | 'cert' => $this->getCertPath(), 268 | 'ssl_key' => $this->getKeyPath(), 269 | ]; 270 | 271 | $result = $client->request('POST', $this->endpoint, $options)->getBody()->getContents(); 272 | 273 | $responseData = Helper::xml2array($result); 274 | 275 | return $this->response = new RefundOrderResponse($this, $responseData); 276 | } 277 | } 278 | -------------------------------------------------------------------------------- /src/Message/RefundOrderResponse.php: -------------------------------------------------------------------------------- 1 | validate('app_id', 'mch_id', 'long_url'); 30 | 31 | $data = array( 32 | 'appid' => $this->getAppId(), 33 | 'mch_id' => $this->getMchId(), 34 | 'sub_mch_id'=> $this->getSubMchId(), 35 | 'long_url' => $this->getLongUrl(), 36 | 'nonce_str' => md5(uniqid()), 37 | ); 38 | 39 | $data = array_filter($data); 40 | 41 | $data['sign'] = Helper::sign($data, $this->getApiKey()); 42 | 43 | return $data; 44 | } 45 | 46 | 47 | /** 48 | * @return mixed 49 | */ 50 | public function getLongUrl() 51 | { 52 | return $this->getParameter('long_url'); 53 | } 54 | 55 | 56 | /** 57 | * @param mixed $longUrl 58 | */ 59 | public function setLongUrl($longUrl) 60 | { 61 | $this->setParameter('long_url', $longUrl); 62 | } 63 | 64 | 65 | /** 66 | * Send the request with specified data 67 | * 68 | * @param mixed $data The data to send 69 | * 70 | * @return ResponseInterface 71 | */ 72 | public function sendData($data) 73 | { 74 | $request = $this->httpClient->request('POST', $this->endpoint, [], Helper::array2xml($data)); 75 | $response = $request->getBody(); 76 | $responseData = Helper::xml2array($response); 77 | 78 | return $this->response = new ShortenUrlResponse($this, $responseData); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/Message/ShortenUrlResponse.php: -------------------------------------------------------------------------------- 1 | getData(); 16 | 17 | return isset($data['short_url']) ? $data['short_url'] : null; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/MwebGateway.php: -------------------------------------------------------------------------------- 1 | createRequest('\Omnipay\WechatPay\Message\ShortenUrlRequest', $parameters); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/PosGateway.php: -------------------------------------------------------------------------------- 1 | getTradeType(); 25 | 26 | return $this->createRequest('\Omnipay\WechatPay\Message\CreateMicroOrderRequest', $parameters); 27 | } 28 | 29 | 30 | /** 31 | * @param array $parameters 32 | * 33 | * @return \Omnipay\WechatPay\Message\QueryOpenIdByAuthCodeRequest 34 | */ 35 | public function queryOpenId($parameters = array()) 36 | { 37 | return $this->createRequest('\Omnipay\WechatPay\Message\QueryOpenIdByAuthCodeRequest', $parameters); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /tests/GatewayTest.php: -------------------------------------------------------------------------------- 1 | gateway = Omnipay::create('WechatPay'); 30 | $this->gateway->setAppId('123456789'); 31 | $this->gateway->setMchId('4567891011'); 32 | $this->gateway->setApiKey('XXSXXXSXXSXXSX'); 33 | $this->gateway->setNotifyUrl('http://example.com/notify'); 34 | $this->gateway->setTradeType('APP'); 35 | } 36 | 37 | 38 | public function testPurchase() 39 | { 40 | if ($this->fuckTimeout) { 41 | return; 42 | } 43 | 44 | $order = array( 45 | 'outTrade_No' => '1112',//date('YmdHis'), //Should be format 'YmdHis' 46 | 'totalfee' => '0.01', //Order Title 47 | 'body' => 'test', //Your order ID 48 | 'spbill_create_ip' => '114.119.110.120', //Order Total Fee 49 | ); 50 | 51 | /** 52 | * @var CreateOrderResponse $response 53 | */ 54 | $response = $this->gateway->purchase($order)->send(); 55 | $this->assertFalse($response->isSuccessful()); 56 | $this->assertFalse($response->isRedirect()); 57 | } 58 | 59 | 60 | public function testCompletePurchase() 61 | { 62 | if ($this->fuckTimeout) { 63 | return; 64 | } 65 | 66 | $options = array( 67 | 'request_params' => array( 68 | 'appid' => '123456', 69 | 'mch_id' => '789456', 70 | 'result_code' => 'SUCCESS' 71 | ), 72 | ); 73 | 74 | /** 75 | * @var CompletePurchaseResponse $response 76 | */ 77 | $response = $this->gateway->completePurchase($options)->send(); 78 | $this->assertFalse($response->isSuccessful()); 79 | } 80 | 81 | 82 | public function testQuery() 83 | { 84 | if ($this->fuckTimeout) { 85 | return; 86 | } 87 | 88 | $options = array( 89 | 'transaction_id' => '3474813271258769001041842579301293446', 90 | ); 91 | 92 | /** 93 | * @var QueryOrderResponse $response 94 | */ 95 | $response = $this->gateway->query($options)->send(); 96 | $this->assertFalse($response->isSuccessful()); 97 | } 98 | 99 | 100 | public function testClose() 101 | { 102 | if ($this->fuckTimeout) { 103 | return; 104 | } 105 | 106 | $options = array( 107 | 'out_trade_no' => '1234567891023', 108 | ); 109 | 110 | /** 111 | * @var CloseOrderResponse $response 112 | */ 113 | $response = $this->gateway->query($options)->send(); 114 | $this->assertFalse($response->isSuccessful()); 115 | } 116 | 117 | 118 | public function testRefund() 119 | { 120 | if ($this->fuckTimeout) { 121 | return; 122 | } 123 | 124 | $options = array( 125 | 'transaction_id' => '1234567891023', 126 | 'out_refund_no' => '1234567891023', 127 | 'total_fee' => '100', 128 | 'refund_fee' => '100', 129 | ); 130 | 131 | /** 132 | * @var RefundOrderResponse $response 133 | */ 134 | $response = $this->gateway->query($options)->send(); 135 | $this->assertFalse($response->isSuccessful()); 136 | } 137 | 138 | 139 | public function testQueryRefund() 140 | { 141 | if ($this->fuckTimeout) { 142 | return; 143 | } 144 | 145 | $options = array( 146 | 'transaction_id' => '1234567891023', 147 | ); 148 | 149 | /** 150 | * @var RefundOrderResponse $response 151 | */ 152 | $response = $this->gateway->query($options)->send(); 153 | $this->assertFalse($response->isSuccessful()); 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /tests/HelperTest.php: -------------------------------------------------------------------------------- 1 | '; 11 | 12 | $array = \Omnipay\WechatPay\Helper::xml2array($xml); 13 | 14 | $this->assertArrayHasKey('return_code', $array); 15 | } 16 | 17 | 18 | /** @test */ 19 | public function it_should_return_an_empty_array_if_xml_is_empty() 20 | { 21 | $array = \Omnipay\WechatPay\Helper::xml2array(''); 22 | 23 | $this->assertEquals([], $array); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /tests/bootstrap.php: -------------------------------------------------------------------------------- 1 | add('Omnipay', __DIR__); 10 | --------------------------------------------------------------------------------