├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── composer.json ├── phpunit.xml.dist ├── src ├── AbstractAopGateway.php ├── AbstractLegacyGateway.php ├── AopAppGateway.php ├── AopF2FGateway.php ├── AopJsGateway.php ├── AopPageGateway.php ├── AopWapGateway.php ├── Common │ ├── Signer.php │ └── helpers.php ├── LegacyAppGateway.php ├── LegacyExpressGateway.php ├── LegacyWapGateway.php ├── Requests │ ├── AbstractAopRequest.php │ ├── AbstractLegacyRequest.php │ ├── AopCompletePurchaseRequest.php │ ├── AopCompleteRefundRequest.php │ ├── AopNotifyRequest.php │ ├── AopTradeAppPayRequest.php │ ├── AopTradeCancelRequest.php │ ├── AopTradeCloseRequest.php │ ├── AopTradeCreateRequest.php │ ├── AopTradeOrderSettleRequest.php │ ├── AopTradePagePayRequest.php │ ├── AopTradePayRequest.php │ ├── AopTradePreCreateRequest.php │ ├── AopTradeQueryRequest.php │ ├── AopTradeRefundQueryRequest.php │ ├── AopTradeRefundRequest.php │ ├── AopTradeWapPayRequest.php │ ├── AopTransferToAccountQueryRequest.php │ ├── AopTransferToAccountRequest.php │ ├── AopVerifyAppPayReturnRequest.php │ ├── DataServiceBillDownloadUrlQueryRequest.php │ ├── LegacyAppPurchaseRequest.php │ ├── LegacyCompletePurchaseRequest.php │ ├── LegacyCompleteRefundRequest.php │ ├── LegacyExpressPurchaseRequest.php │ ├── LegacyNotifyRequest.php │ ├── LegacyQueryRequest.php │ ├── LegacyRefundNoPwdRequest.php │ ├── LegacyRefundRequest.php │ ├── LegacyVerifyAppPayReturnRequest.php │ ├── LegacyVerifyNotifyIdRequest.php │ └── LegacyWapPurchaseRequest.php └── Responses │ ├── AbstractAopResponse.php │ ├── AbstractLegacyResponse.php │ ├── AbstractResponse.php │ ├── AopCompletePurchaseResponse.php │ ├── AopCompleteRefundResponse.php │ ├── AopNotifyResponse.php │ ├── AopTradeAppPayResponse.php │ ├── AopTradeCancelResponse.php │ ├── AopTradeCloseResponse.php │ ├── AopTradeCreateResponse.php │ ├── AopTradeOrderSettleResponse.php │ ├── AopTradePagePayResponse.php │ ├── AopTradePayResponse.php │ ├── AopTradePreCreateResponse.php │ ├── AopTradeQueryResponse.php │ ├── AopTradeRefundQueryResponse.php │ ├── AopTradeRefundResponse.php │ ├── AopTradeWapPayResponse.php │ ├── AopTransferToAccountQueryResponse.php │ ├── AopTransferToAccountResponse.php │ ├── DataServiceBillDownloadUrlQueryResponse.php │ ├── LegacyAppPurchaseResponse.php │ ├── LegacyCompletePurchaseResponse.php │ ├── LegacyCompleteRefundResponse.php │ ├── LegacyExpressPurchaseResponse.php │ ├── LegacyNotifyResponse.php │ ├── LegacyQueryResponse.php │ ├── LegacyRefundNoPwdResponse.php │ ├── LegacyRefundResponse.php │ ├── LegacyWapPurchaseResponse.php │ └── VerifyNotifyIdResponse.php └── tests ├── AbstractGatewayTestCase.php ├── AopAppGatewayTest.php ├── AopF2FGatewayTest.php ├── AopJsGatewayTest.php ├── AopWapGatewayTest.php ├── Assets ├── cacert.pem └── dist │ ├── aop │ ├── alipay_public_key.pem │ └── rsa_private_key.pem │ ├── cert │ ├── alipayCertPublicKey_RSA2.crt │ ├── alipayRootCert.crt │ ├── appCertPublicKey.crt │ └── appPrivateKey │ ├── common │ ├── rsa_private_key.pem │ ├── rsa_private_key_inline.pem │ ├── rsa_private_key_pkcs8.pem │ ├── rsa_public_key.pem │ └── rsa_public_key_inline.pem │ └── legacy │ ├── alipay_public_key.pem │ └── rsa_private_key.pem ├── Common └── SignerTest.php ├── LegacyAppGatewayTest.php ├── LegacyExpressGatewayTest.php ├── LegacyWapGatewayTest.php ├── Mock ├── AopF2F_Capture_Failure.txt ├── AopF2F_Purchase_Failure.txt ├── AopF2F_QueryBillDownloadUrl_Failure.txt ├── AopF2F_QueryRefund_Failure.txt ├── AopF2F_Query_Failure.txt ├── AopF2F_Refund_Failure.txt ├── AopF2F_Settle_Failure.txt ├── AopJs_Purchase_Failure.txt └── LegacyExpress_Query_Failure.txt └── bootstrap.php /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /vendor 3 | /public 4 | /.idea 5 | /.tmp 6 | composer.lock 7 | composer.phar 8 | config.php 9 | /tests/Assets/production 10 | /tests/Assets/sandbox 11 | -------------------------------------------------------------------------------- /.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) -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 2016-09-25 2 | 3 | - Publish v2.0.0, support Alipay Open Platform API -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | * Fork the project. 4 | * Switch to **develop** branch. 5 | * Make your feature addition or bug fix. 6 | * Add tests for it. This is important so I don't break it in a future version unintentionally. 7 | * Commit just the modifications, do not mess with the composer.json or CHANGELOG.md files. 8 | * 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) 9 | style and that all tests pass. 10 | * Send the pull request **develop** to **develop**. 11 | * Check that the Travis CI build passed. If not, rinse and repeat. 12 | -------------------------------------------------------------------------------- /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: Alipay 2 | 3 | [![travis][ico-travis]][link-travis] 4 | [![Latest Version on Packagist][ico-version]][link-packagist] 5 | [![Total Downloads][ico-downloads]][link-downloads] 6 | [![Code Coverage][ico-code-coverage]][link-code-coverage] 7 | [![Software License][ico-license]](LICENSE) 8 | 9 | 10 | **Alipay driver for the Omnipay PHP payment processing library** 11 | 12 | [Omnipay](https://github.com/omnipay/omnipay) is a framework agnostic, multi-gateway payment 13 | processing library for PHP. This package implements Alipay support for Omnipay. 14 | 15 | > Cross-border Alipay payment please use [`lokielse/omnipay-global-alipay`](https://github.com/lokielse/omnipay-global-alipay) 16 | 17 | > Legacy Version please use [`"lokielse/omnipay-alipay": "dev-legacy"`](https://github.com/lokielse/omnipay-alipay/tree/legacy) 18 | 19 | ## Installation 20 | 21 | composer require lokielse/omnipay-alipay 22 | 23 | ## Basic Usage 24 | 25 | The following gateways are provided by this package: 26 | 27 | | Gateway | Description |说明   | Links | 28 | |:--------------- |:--------------------------- |:--------- |:----------:| 29 | | Alipay_AopPage | Alipay Page Gateway |电脑网站支付 - new | [Usage][link-wiki-aop-page] [Doc][link-doc-aop-page] | 30 | | Alipay_AopApp | Alipay APP Gateway |APP支付 - new | [Usage][link-wiki-aop-app] [Doc][link-doc-aop-app] | 31 | | Alipay_AopF2F | Alipay Face To Face Gateway |当面付 - new | [Usage][link-wiki-aop-f2f] [Doc][link-doc-aop-f2f] | 32 | | Alipay_AopWap | Alipay WAP Gateway |手机网站支付 - new | [Usage][link-wiki-aop-wap] [Doc][link-doc-aop-wap] | 33 | | Alipay_AopJs | Alipay Js Gateway |JSAPI - new | [Usage][link-wiki-aop-js] [Doc][link-doc-aop-js] | 34 | | Alipay_LegacyApp | Alipay Legacy APP Gateway |APP支付 | [Usage][link-wiki-legacy-app] [Doc][link-doc-legacy-app] | 35 | | Alipay_LegacyExpress | Alipay Legacy Express Gateway |即时到账 | [Usage][link-wiki-legacy-express] [Doc][link-doc-legacy-express]| 36 | | Alipay_LegacyWap | Alipay Legacy WAP Gateway |手机网站支付 | [Usage][link-wiki-legacy-wap] [Doc][link-doc-legacy-wap] | 37 | 38 | ## Usage 39 | 40 | ### Purchase (购买) 41 | 42 | ```php 43 | /** 44 | * @var AopAppGateway $gateway 45 | */ 46 | $gateway = Omnipay::create('Alipay_AopPage'); 47 | $gateway->setSignType('RSA2'); // RSA/RSA2/MD5. Use certificate mode must set RSA2 48 | $gateway->setAppId('the_app_id'); 49 | $gateway->setPrivateKey('the_app_private_key'); 50 | $gateway->setAlipayPublicKey('the_alipay_public_key'); // Need not set this when used certificate mode 51 | $gateway->setReturnUrl('https://www.example.com/return'); 52 | $gateway->setNotifyUrl('https://www.example.com/notify'); 53 | 54 | // Must set cert path if you used certificate mode 55 | //$gateway->setAlipayRootCert('the_alipay_root_cert'); // alipayRootCert.crt 56 | //$gateway->setAlipayPublicCert('the_alipay_public_cert'); // alipayCertPublicKey_RSA2.crt 57 | //$gateway->setAppCert('the_app_public_cert'); // appCertPublicKey.crt 58 | //$gateway->setCheckAlipayPublicCert(true); 59 | 60 | /** 61 | * @var AopTradePagePayResponse $response 62 | */ 63 | $response = $gateway->purchase()->setBizContent([ 64 | 'subject' => 'test', 65 | 'out_trade_no' => date('YmdHis') . mt_rand(1000, 9999), 66 | 'total_amount' => '0.01', 67 | 'product_code' => 'FAST_INSTANT_TRADE_PAY', 68 | ])->send(); 69 | 70 | $url = $response->getRedirectUrl(); 71 | ``` 72 | 73 | For general usage instructions, please see the 74 | 75 | - [Omnipay Basic Documentation](https://github.com/thephpleague/omnipay) 76 | - [Omnipay Alipay Wiki](https://github.com/lokielse/omnipay-alipay/wiki) 77 | 78 | ## Related 79 | 80 | - [Laravel-Omnipay](https://github.com/ignited/laravel-omnipay) 81 | - [Omnipay-GlobalAlipay](https://github.com/lokielse/omnipay-global-alipay) 82 | - [Omnipay-WechatPay](https://github.com/lokielse/omnipay-wechatpay) 83 | - [Omnipay-UnionPay](https://github.com/lokielse/omnipay-unionpay) 84 | 85 | ## Support 86 | 87 | If you are having general issues with Omnipay, we suggest posting on 88 | [Stack Overflow](http://stackoverflow.com/). Be sure to add the 89 | [omnipay tag](http://stackoverflow.com/questions/tagged/omnipay) so it can be easily found. 90 | 91 | If you want to keep up to date with release anouncements, discuss ideas for the project, 92 | or ask more detailed questions, there is also a [mailing list](https://groups.google.com/forum/#!forum/omnipay) which 93 | you can subscribe to. 94 | 95 | If you believe you have found a bug, please report it using the [GitHub issue tracker](https://github.com/lokielse/omnipay-alipay/issues), 96 | or better yet, fork the library and submit a pull request. 97 | 98 | [ico-version]: https://img.shields.io/packagist/v/lokielse/omnipay-alipay.svg 99 | [ico-license]: https://img.shields.io/badge/license-MIT-brightgreen.svg 100 | [ico-travis]: https://img.shields.io/travis/lokielse/omnipay-alipay/master.svg 101 | [ico-scrutinizer]: https://img.shields.io/scrutinizer/coverage/g/lokielse/omnipay-alipay.svg 102 | [ico-code-coverage]: https://img.shields.io/codecov/c/github/lokielse/omnipay-alipay/master.svg 103 | [ico-code-quality]: https://img.shields.io/scrutinizer/g/lokielse/omnipay-alipay.svg 104 | [ico-downloads]: https://img.shields.io/packagist/dt/lokielse/omnipay-alipay.svg 105 | 106 | [link-packagist]: https://packagist.org/packages/lokielse/omnipay-alipay 107 | [link-travis]: https://travis-ci.org/lokielse/omnipay-alipay 108 | [link-scrutinizer]: https://scrutinizer-ci.com/g/lokielse/omnipay-alipay/code-structure 109 | [link-code-coverage]: https://codecov.io/github/lokielse/omnipay-alipay?branch=master 110 | [link-code-quality]: https://scrutinizer-ci.com/g/lokielse/omnipay-alipay 111 | [link-downloads]: https://packagist.org/packages/lokielse/omnipay-alipay 112 | [link-author]: https://github.com/lokielse 113 | [link-contributors]: ../../contributors 114 | 115 | [link-wiki-aop-page]: https://github.com/lokielse/omnipay-alipay/wiki/Aop-Page-Gateway 116 | [link-wiki-aop-app]: https://github.com/lokielse/omnipay-alipay/wiki/Aop-APP-Gateway 117 | [link-wiki-aop-f2f]: https://github.com/lokielse/omnipay-alipay/wiki/Aop-Face-To-Face-Gateway 118 | [link-wiki-aop-wap]: https://github.com/lokielse/omnipay-alipay/wiki/Aop-WAP-Gateway 119 | [link-wiki-aop-js]: https://github.com/lokielse/omnipay-alipay/wiki/Aop-JS-Gateway 120 | [link-wiki-legacy-app]: https://github.com/lokielse/omnipay-alipay/wiki/Legacy-APP-Gateway 121 | [link-wiki-legacy-express]: https://github.com/lokielse/omnipay-alipay/wiki/Legacy-Express-Gateway 122 | [link-wiki-legacy-wap]: https://github.com/lokielse/omnipay-alipay/wiki/Legacy-WAP-Gateway 123 | [link-doc-aop-page]: https://doc.open.alipay.com/doc2/detail.htm?treeId=270&articleId=105901&docType=1 124 | [link-doc-aop-app]: https://doc.open.alipay.com/docs/doc.htm?treeId=204&articleId=105051&docType=1 125 | [link-doc-aop-f2f]: https://doc.open.alipay.com/docs/doc.htm?treeId=194&articleId=105072&docType=1 126 | [link-doc-aop-wap]: https://doc.open.alipay.com/docs/doc.htm?treeId=203&articleId=105288&docType=1 127 | [link-doc-aop-js]: https://myjsapi.alipay.com/jsapi/native/trade-pay.html 128 | [link-doc-legacy-app]: https://doc.open.alipay.com/doc2/detail?treeId=59&articleId=103563&docType=1 129 | [link-doc-legacy-express]: https://doc.open.alipay.com/docs/doc.htm?treeId=108&articleId=103950&docType=1 130 | [link-doc-legacy-wap]: https://doc.open.alipay.com/docs/doc.htm?treeId=60&articleId=103564&docType=1 -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "lokielse/omnipay-alipay", 3 | "type": "library", 4 | "description": "Alipay gateway for Omnipay payment processing library", 5 | "keywords": [ 6 | "alipay", 7 | "gateway", 8 | "merchant", 9 | "omnipay", 10 | "pay", 11 | "payment", 12 | "purchase" 13 | ], 14 | "homepage": "https://github.com/lokielse/omnipay-alipay", 15 | "license": "MIT", 16 | "authors": [ 17 | { 18 | "name": "Loki Else", 19 | "email": "lokielse@gmail.com" 20 | } 21 | ], 22 | "autoload": { 23 | "psr-4": { 24 | "Omnipay\\Alipay\\": "src/", 25 | "Omnipay\\Alipay\\Tests\\": "tests/" 26 | }, 27 | "files": [ 28 | "src/Common/helpers.php" 29 | ] 30 | }, 31 | "require": { 32 | "ext-bcmath": "*", 33 | "ext-json": "*", 34 | "ext-openssl": "*", 35 | "omnipay/common": "^3.0", 36 | "php-http/guzzle6-adapter": "^2.0" 37 | }, 38 | "require-dev": { 39 | "omnipay/tests": "^3.0", 40 | "squizlabs/php_codesniffer": "^3.4" 41 | }, 42 | "minimum-stability": "dev", 43 | "prefer-stable": true 44 | } 45 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 14 | ./tests/ 15 | 16 | 17 | 18 | 20 | 21 | 22 | 23 | ./src 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/AbstractLegacyGateway.php: -------------------------------------------------------------------------------- 1 | 'UTF-8', 18 | 'signType' => 'MD5', 19 | 'paymentType' => '1', 20 | 'alipaySdk' => 'lokielse/omnipay-alipay', 21 | ]; 22 | } 23 | 24 | 25 | /** 26 | * @return mixed 27 | */ 28 | public function getPartner() 29 | { 30 | return $this->getParameter('partner'); 31 | } 32 | 33 | 34 | /** 35 | * @param $value 36 | * 37 | * @return $this 38 | */ 39 | public function setPartner($value) 40 | { 41 | return $this->setParameter('partner', $value); 42 | } 43 | 44 | 45 | /** 46 | * @return mixed 47 | */ 48 | public function getSignType() 49 | { 50 | return $this->getParameter('sign_type'); 51 | } 52 | 53 | 54 | /** 55 | * @param $value 56 | * 57 | * @return $this 58 | */ 59 | public function setSignType($value) 60 | { 61 | return $this->setParameter('sign_type', $value); 62 | } 63 | 64 | 65 | /** 66 | * @return mixed 67 | */ 68 | public function getPaymentType() 69 | { 70 | return $this->getParameter('payment_type'); 71 | } 72 | 73 | 74 | /** 75 | * @param $value 76 | * 77 | * @return $this 78 | */ 79 | public function setPaymentType($value) 80 | { 81 | return $this->setParameter('payment_type', $value); 82 | } 83 | 84 | 85 | /** 86 | * @return mixed 87 | */ 88 | public function getKey() 89 | { 90 | return $this->getParameter('key'); 91 | } 92 | 93 | 94 | /** 95 | * @param $value 96 | * 97 | * @return $this 98 | */ 99 | public function setKey($value) 100 | { 101 | return $this->setParameter('key', $value); 102 | } 103 | 104 | 105 | /** 106 | * @return mixed 107 | */ 108 | public function getPrivateKey() 109 | { 110 | return $this->getParameter('private_key'); 111 | } 112 | 113 | 114 | /** 115 | * @param $value 116 | * 117 | * @return $this 118 | */ 119 | public function setPrivateKey($value) 120 | { 121 | return $this->setParameter('private_key', $value); 122 | } 123 | 124 | 125 | /** 126 | * @return mixed 127 | */ 128 | public function getAlipayPublicKey() 129 | { 130 | return $this->getParameter('alipay_public_key'); 131 | } 132 | 133 | 134 | /** 135 | * @param $value 136 | * 137 | * @return $this 138 | */ 139 | public function setAlipayPublicKey($value) 140 | { 141 | return $this->setParameter('alipay_public_key', $value); 142 | } 143 | 144 | 145 | /** 146 | * @return mixed 147 | */ 148 | public function getSellerId() 149 | { 150 | return $this->getParameter('seller_id'); 151 | } 152 | 153 | 154 | /** 155 | * @param $value 156 | * 157 | * @return $this 158 | */ 159 | public function setSellerId($value) 160 | { 161 | return $this->setParameter('seller_id', $value); 162 | } 163 | 164 | 165 | /** 166 | * @return mixed 167 | */ 168 | public function getSellerEmail() 169 | { 170 | return $this->getParameter('seller_email'); 171 | } 172 | 173 | 174 | /** 175 | * @param $value 176 | * 177 | * @return $this 178 | */ 179 | public function setSellerEmail($value) 180 | { 181 | return $this->setParameter('seller_email', $value); 182 | } 183 | 184 | 185 | /** 186 | * @return mixed 187 | */ 188 | public function getSellerAccountName() 189 | { 190 | return $this->getParameter('seller_account_name'); 191 | } 192 | 193 | 194 | /** 195 | * @param $value 196 | * 197 | * @return $this 198 | */ 199 | public function setSellerAccountName($value) 200 | { 201 | return $this->setParameter('seller_account_name', $value); 202 | } 203 | 204 | 205 | /** 206 | * @return mixed 207 | */ 208 | public function getNotifyUrl() 209 | { 210 | return $this->getParameter('notify_url'); 211 | } 212 | 213 | 214 | /** 215 | * @param $value 216 | * 217 | * @return $this 218 | */ 219 | public function setNotifyUrl($value) 220 | { 221 | return $this->setParameter('notify_url', $value); 222 | } 223 | 224 | 225 | /** 226 | * @return mixed 227 | */ 228 | public function getReturnUrl() 229 | { 230 | return $this->getParameter('return_url'); 231 | } 232 | 233 | 234 | /** 235 | * @param $value 236 | * 237 | * @return $this 238 | */ 239 | public function setReturnUrl($value) 240 | { 241 | return $this->setParameter('return_url', $value); 242 | } 243 | 244 | 245 | /** 246 | * @return mixed 247 | */ 248 | public function getInputCharset() 249 | { 250 | return $this->getParameter('_input_charset'); 251 | } 252 | 253 | 254 | /** 255 | * @param $value 256 | * 257 | * @return $this 258 | */ 259 | public function setInputCharset($value) 260 | { 261 | return $this->setParameter('_input_charset', $value); 262 | } 263 | 264 | 265 | /** 266 | * @return mixed 267 | */ 268 | public function getItBPay() 269 | { 270 | return $this->getParameter('it_b_pay'); 271 | } 272 | 273 | 274 | /** 275 | * @param $value 276 | * 277 | * @return $this 278 | */ 279 | public function setItBPay($value) 280 | { 281 | return $this->setParameter('it_b_pay', $value); 282 | } 283 | 284 | 285 | /** 286 | * @return mixed 287 | */ 288 | public function getAlipaySdk() 289 | { 290 | return $this->getParameter('alipay_sdk'); 291 | } 292 | 293 | 294 | /** 295 | * @param $value 296 | * 297 | * @return $this 298 | */ 299 | public function setAlipaySdk($value) 300 | { 301 | return $this->setParameter('alipay_sdk', $value); 302 | } 303 | 304 | 305 | /** 306 | * @param array $parameters 307 | * 308 | * @return LegacyCompletePurchaseRequest|AbstractRequest 309 | */ 310 | public function completePurchase(array $parameters = []) 311 | { 312 | return $this->createRequest(LegacyCompletePurchaseRequest::class, $parameters); 313 | } 314 | 315 | 316 | /** 317 | * @param array $parameters 318 | * 319 | * @return LegacyRefundRequest|AbstractRequest 320 | */ 321 | public function refund(array $parameters = []) 322 | { 323 | return $this->createRequest(LegacyRefundRequest::class, $parameters); 324 | } 325 | 326 | 327 | /** 328 | * @param array $parameters 329 | * 330 | * @return LegacyRefundRequest|AbstractRequest 331 | */ 332 | public function completeRefund(array $parameters = []) 333 | { 334 | return $this->createRequest(LegacyCompleteRefundRequest::class, $parameters); 335 | } 336 | 337 | 338 | /** 339 | * @param array $parameters 340 | * 341 | * @return LegacyQueryRequest|AbstractRequest 342 | */ 343 | public function query(array $parameters = []) 344 | { 345 | return $this->createRequest(LegacyQueryRequest::class, $parameters); 346 | } 347 | } 348 | -------------------------------------------------------------------------------- /src/AopAppGateway.php: -------------------------------------------------------------------------------- 1 | createRequest(AopTradeAppPayRequest::class, $parameters); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/AopF2FGateway.php: -------------------------------------------------------------------------------- 1 | createRequest(AopTradePayRequest::class, $parameters); 44 | } 45 | 46 | 47 | /** 48 | * @param array $parameters 49 | * 50 | * @return AopTradePreCreateRequest|AbstractRequest 51 | */ 52 | public function purchase(array $parameters = []) 53 | { 54 | return $this->createRequest(AopTradePreCreateRequest::class, $parameters); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/AopJsGateway.php: -------------------------------------------------------------------------------- 1 | createRequest(AopTradeCreateRequest::class, $parameters); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/AopPageGateway.php: -------------------------------------------------------------------------------- 1 | getParameter('return_url'); 42 | } 43 | 44 | 45 | /** 46 | * @param $value 47 | * 48 | * @return $this 49 | */ 50 | public function setReturnUrl($value) 51 | { 52 | return $this->setParameter('return_url', $value); 53 | } 54 | 55 | 56 | /** 57 | * @param array $parameters 58 | * 59 | * @return AbstractRequest 60 | */ 61 | public function purchase(array $parameters = []) 62 | { 63 | return $this->createRequest(AopTradePagePayRequest::class, $parameters); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/AopWapGateway.php: -------------------------------------------------------------------------------- 1 | getParameter('return_url'); 42 | } 43 | 44 | 45 | /** 46 | * @param $value 47 | * 48 | * @return $this 49 | */ 50 | public function setReturnUrl($value) 51 | { 52 | return $this->setParameter('return_url', $value); 53 | } 54 | 55 | 56 | /** 57 | * @param array $parameters 58 | * 59 | * @return AbstractRequest 60 | */ 61 | public function purchase(array $parameters = []) 62 | { 63 | return $this->createRequest(AopTradeWapPayRequest::class, $parameters); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/Common/Signer.php: -------------------------------------------------------------------------------- 1 | params = $params; 36 | } 37 | 38 | 39 | public function signWithMD5($key) 40 | { 41 | $content = $this->getContentToSign(); 42 | 43 | return md5($content . $key); 44 | } 45 | 46 | 47 | public function getContentToSign() 48 | { 49 | $params = $this->getParamsToSign(); 50 | 51 | if ($this->encodePolicy == self::ENCODE_POLICY_QUERY) { 52 | return urldecode(http_build_query($params)); 53 | } elseif ($this->encodePolicy == self::ENCODE_POLICY_JSON) { 54 | return json_encode($params); 55 | } else { 56 | return null; 57 | } 58 | } 59 | 60 | 61 | /** 62 | * @return mixed 63 | */ 64 | public function getParamsToSign() 65 | { 66 | $params = $this->params; 67 | 68 | $this->unsetKeys($params); 69 | 70 | $params = $this->filter($params); 71 | 72 | if ($this->sort) { 73 | $this->sort($params); 74 | } 75 | 76 | return $params; 77 | } 78 | 79 | 80 | /** 81 | * @param $params 82 | */ 83 | protected function unsetKeys(&$params) 84 | { 85 | foreach ($this->getIgnores() as $key) { 86 | unset($params[$key]); 87 | } 88 | } 89 | 90 | 91 | /** 92 | * @return array 93 | */ 94 | public function getIgnores() 95 | { 96 | return $this->ignores; 97 | } 98 | 99 | 100 | /** 101 | * @param array $ignores 102 | * 103 | * @return $this 104 | */ 105 | public function setIgnores($ignores) 106 | { 107 | $this->ignores = $ignores; 108 | 109 | return $this; 110 | } 111 | 112 | 113 | private function filter($params) 114 | { 115 | return array_filter($params, 'strlen'); 116 | } 117 | 118 | 119 | /** 120 | * @param $params 121 | */ 122 | protected function sort(&$params) 123 | { 124 | ksort($params); 125 | } 126 | 127 | 128 | /** 129 | * @param string $privateKey 130 | * @param int $alg 131 | * 132 | * @return string 133 | * @throws Exception 134 | */ 135 | public function signWithRSA($privateKey, $alg = OPENSSL_ALGO_SHA1) 136 | { 137 | $content = $this->getContentToSign(); 138 | 139 | return $this->signContentWithRSA($content, $privateKey, $alg); 140 | } 141 | 142 | 143 | /** 144 | * @param string $content 145 | * @param string $privateKey 146 | * @param int $alg 147 | * 148 | * @return string 149 | * @throws Exception 150 | */ 151 | public function signContentWithRSA($content, $privateKey, $alg = OPENSSL_ALGO_SHA1) 152 | { 153 | $privateKey = $this->prefix($privateKey); 154 | $privateKey = $this->format($privateKey, self::KEY_TYPE_PRIVATE); 155 | $res = openssl_pkey_get_private($privateKey); 156 | 157 | $sign = null; 158 | 159 | try { 160 | openssl_sign($content, $sign, $res, $alg); 161 | } catch (Exception $e) { 162 | if ($e->getCode() == 2) { 163 | $message = $e->getMessage(); 164 | $message .= "\n应用私钥格式有误,见 https://github.com/lokielse/omnipay-alipay/wiki/FAQs"; 165 | throw new Exception($message, $e->getCode(), $e); 166 | } 167 | } 168 | 169 | openssl_free_key($res); 170 | 171 | return base64_encode($sign); 172 | } 173 | 174 | 175 | /** 176 | * Prefix the key path with 'file://' 177 | * 178 | * @param $key 179 | * 180 | * @return string 181 | */ 182 | private function prefix($key) 183 | { 184 | if (strtoupper(substr(PHP_OS, 0, 3)) != 'WIN' && is_file($key) && substr($key, 0, 7) != 'file://') { 185 | $key = 'file://' . $key; 186 | } 187 | 188 | return $key; 189 | } 190 | 191 | 192 | /** 193 | * Convert key to standard format 194 | * 195 | * @param $key 196 | * @param $type 197 | * 198 | * @return string 199 | */ 200 | public function format($key, $type) 201 | { 202 | if (is_file($key)) { 203 | $key = file_get_contents($key); 204 | } 205 | 206 | if (is_string($key) && strpos($key, '-----') === false) { 207 | $key = $this->convertKey($key, $type); 208 | } 209 | 210 | return $key; 211 | } 212 | 213 | 214 | /** 215 | * Convert one line key to standard format 216 | * 217 | * @param string $key 218 | * @param int $type 219 | * 220 | * @return string 221 | */ 222 | public function convertKey($key, $type) 223 | { 224 | $lines = []; 225 | 226 | if ($type == self::KEY_TYPE_PUBLIC) { 227 | $lines[] = '-----BEGIN PUBLIC KEY-----'; 228 | } else { 229 | $lines[] = '-----BEGIN RSA PRIVATE KEY-----'; 230 | } 231 | 232 | for ($i = 0; $i < strlen($key); $i += 64) { 233 | $lines[] = trim(substr($key, $i, 64)); 234 | } 235 | 236 | if ($type == self::KEY_TYPE_PUBLIC) { 237 | $lines[] = '-----END PUBLIC KEY-----'; 238 | } else { 239 | $lines[] = '-----END RSA PRIVATE KEY-----'; 240 | } 241 | 242 | return implode("\n", $lines); 243 | } 244 | 245 | 246 | public function verifyWithMD5($content, $sign, $key) 247 | { 248 | return md5($content . $key) == $sign; 249 | } 250 | 251 | 252 | /** 253 | * @param string $content 254 | * @param string $sign 255 | * @param string $publicKey 256 | * @param int $alg 257 | * 258 | * @return bool 259 | * @throws Exception 260 | */ 261 | public function verifyWithRSA($content, $sign, $publicKey, $alg = OPENSSL_ALGO_SHA1) 262 | { 263 | $publicKey = $this->prefix($publicKey); 264 | $publicKey = $this->format($publicKey, self::KEY_TYPE_PUBLIC); 265 | 266 | $res = openssl_pkey_get_public($publicKey); 267 | 268 | if (! $res) { 269 | $message = "The public key is invalid"; 270 | $message .= "\n支付宝公钥格式有误,见 https://github.com/lokielse/omnipay-alipay/wiki/FAQs"; 271 | throw new Exception($message); 272 | } 273 | 274 | $result = (bool) openssl_verify($content, base64_decode($sign), $res, $alg); 275 | 276 | openssl_free_key($res); 277 | 278 | return $result; 279 | } 280 | 281 | 282 | /** 283 | * @param boolean $sort 284 | * 285 | * @return Signer 286 | */ 287 | public function setSort($sort) 288 | { 289 | $this->sort = $sort; 290 | 291 | return $this; 292 | } 293 | 294 | 295 | /** 296 | * @param int $encodePolicy 297 | * 298 | * @return Signer 299 | */ 300 | public function setEncodePolicy($encodePolicy) 301 | { 302 | $this->encodePolicy = $encodePolicy; 303 | 304 | return $this; 305 | } 306 | } 307 | -------------------------------------------------------------------------------- /src/Common/helpers.php: -------------------------------------------------------------------------------- 1 | $value) { 150 | $names[] = "{$key}={$value}"; 151 | } 152 | 153 | return md5(implode(',', $names) . $ssl['serialNumber']); 154 | } 155 | } 156 | 157 | if (!function_exists('getPublicKey')) { 158 | /** 159 | * @param string $certPath 160 | * 161 | * @return string 162 | */ 163 | function getPublicKey($certPath) 164 | { 165 | $pkey = openssl_pkey_get_public(file_get_contents($certPath)); 166 | $keyData = openssl_pkey_get_details($pkey); 167 | $public_key = str_replace('-----BEGIN PUBLIC KEY-----', '', $keyData['key']); 168 | return trim(str_replace('-----END PUBLIC KEY-----', '', $public_key)); 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /src/LegacyAppGateway.php: -------------------------------------------------------------------------------- 1 | getParameter('rn_check'); 53 | } 54 | 55 | 56 | /** 57 | * @param $value 58 | * 59 | * @return $this 60 | */ 61 | public function setRnCheck($value) 62 | { 63 | return $this->setParameter('rn_check', $value); 64 | } 65 | 66 | 67 | /** 68 | * @param array $parameters 69 | * 70 | * @return AbstractRequest 71 | */ 72 | public function purchase(array $parameters = []) 73 | { 74 | return $this->createRequest(LegacyAppPurchaseRequest::class, $parameters); 75 | } 76 | 77 | 78 | /** 79 | * @param array $parameters 80 | * 81 | * @return LegacyRefundNoPwdRequest|AbstractRequest 82 | */ 83 | public function refundNoPwd(array $parameters = []) 84 | { 85 | return $this->createRequest(LegacyRefundNoPwdRequest::class, $parameters); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/LegacyExpressGateway.php: -------------------------------------------------------------------------------- 1 | createRequest(LegacyExpressPurchaseRequest::class, $parameters); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/LegacyWapGateway.php: -------------------------------------------------------------------------------- 1 | createRequest(LegacyWapPurchaseRequest::class, $parameters); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Requests/AbstractLegacyRequest.php: -------------------------------------------------------------------------------- 1 | endpoint; 30 | } 31 | 32 | 33 | /** 34 | * @return mixed 35 | */ 36 | public function getPartner() 37 | { 38 | return $this->getParameter('partner'); 39 | } 40 | 41 | 42 | /** 43 | * @param $value 44 | * 45 | * @return $this 46 | */ 47 | public function setPartner($value) 48 | { 49 | return $this->setParameter('partner', $value); 50 | } 51 | 52 | 53 | /** 54 | * @return mixed 55 | */ 56 | public function getInputCharset() 57 | { 58 | return $this->getParameter('_input_charset'); 59 | } 60 | 61 | 62 | /** 63 | * @param $value 64 | * 65 | * @return $this 66 | */ 67 | public function setInputCharset($value) 68 | { 69 | return $this->setParameter('_input_charset', $value); 70 | } 71 | 72 | 73 | /** 74 | * @return mixed 75 | */ 76 | public function getAlipaySdk() 77 | { 78 | return $this->getParameter('alipay_sdk'); 79 | } 80 | 81 | 82 | /** 83 | * @param $value 84 | * 85 | * @return $this 86 | */ 87 | public function setAlipaySdk($value) 88 | { 89 | return $this->setParameter('alipay_sdk', $value); 90 | } 91 | 92 | 93 | /** 94 | * @return mixed 95 | */ 96 | public function getPaymentType() 97 | { 98 | return $this->getParameter('payment_type'); 99 | } 100 | 101 | 102 | /** 103 | * @param $value 104 | * 105 | * @return $this 106 | */ 107 | public function setPaymentType($value) 108 | { 109 | return $this->setParameter('payment_type', $value); 110 | } 111 | 112 | 113 | /** 114 | * @return mixed 115 | */ 116 | public function getSignType() 117 | { 118 | return $this->signType; 119 | } 120 | 121 | 122 | /** 123 | * @param $value 124 | * 125 | * @return $this 126 | * @throws InvalidRequestException 127 | */ 128 | public function setSignType($value) 129 | { 130 | $this->signType = $value; 131 | 132 | return $this; 133 | } 134 | 135 | 136 | /** 137 | * @return mixed 138 | */ 139 | public function getAlipayPublicKey() 140 | { 141 | return $this->alipayPublicKey; 142 | } 143 | 144 | 145 | /** 146 | * @param $value 147 | * 148 | * @return $this 149 | */ 150 | public function setAlipayPublicKey($value) 151 | { 152 | $this->alipayPublicKey = $value; 153 | 154 | return $this; 155 | } 156 | 157 | 158 | protected function validateOne() 159 | { 160 | $keys = func_get_args(); 161 | 162 | $allEmpty = true; 163 | 164 | foreach ($keys as $key) { 165 | $value = $this->parameters->get($key); 166 | 167 | if (! empty($value)) { 168 | $allEmpty = false; 169 | break; 170 | } 171 | } 172 | 173 | if ($allEmpty) { 174 | throw new InvalidRequestException( 175 | sprintf('The parameters (%s) must provide one at least', implode(',', $keys)) 176 | ); 177 | } 178 | } 179 | 180 | 181 | protected function sign($params, $signType) 182 | { 183 | $signer = new Signer($params); 184 | 185 | $signType = strtoupper($signType); 186 | 187 | if ($signType == 'MD5') { 188 | if (! $this->getKey()) { 189 | throw new InvalidRequestException('The `key` is required for `MD5` sign_type'); 190 | } 191 | 192 | $sign = $signer->signWithMD5($this->getKey()); 193 | } elseif ($signType == 'RSA') { 194 | if (! $this->getPrivateKey()) { 195 | throw new InvalidRequestException('The `private_key` is required for `RSA` sign_type'); 196 | } 197 | 198 | $sign = $signer->signWithRSA($this->getPrivateKey()); 199 | } else { 200 | throw new InvalidRequestException('The signType is not allowed'); 201 | } 202 | 203 | return $sign; 204 | } 205 | 206 | 207 | /** 208 | * @return mixed 209 | */ 210 | public function getKey() 211 | { 212 | return $this->key; 213 | } 214 | 215 | 216 | /** 217 | * @param $value 218 | * 219 | * @return $this 220 | */ 221 | public function setKey($value) 222 | { 223 | $this->key = $value; 224 | 225 | return $this; 226 | } 227 | 228 | 229 | /** 230 | * @return mixed 231 | */ 232 | public function getPrivateKey() 233 | { 234 | return $this->privateKey; 235 | } 236 | 237 | 238 | /** 239 | * @param $value 240 | * 241 | * @return $this 242 | */ 243 | public function setPrivateKey($value) 244 | { 245 | $this->privateKey = $value; 246 | 247 | return $this; 248 | } 249 | 250 | 251 | protected function filter($data) 252 | { 253 | return array_filter($data, 'strlen'); 254 | } 255 | } 256 | -------------------------------------------------------------------------------- /src/Requests/AopCompletePurchaseRequest.php: -------------------------------------------------------------------------------- 1 | validateParams(); 22 | 23 | return $this->getParams(); 24 | } 25 | 26 | 27 | public function validateParams() 28 | { 29 | $this->validate('params'); 30 | } 31 | 32 | 33 | /** 34 | * @return mixed 35 | */ 36 | public function getParams() 37 | { 38 | return $this->getParameter('params'); 39 | } 40 | 41 | 42 | /** 43 | * Send the request with specified data 44 | * 45 | * @param mixed $data The data to send 46 | * 47 | * @return AopCompletePurchaseResponse 48 | */ 49 | public function sendData($data) 50 | { 51 | if (isset($data['result'])) { 52 | $request = new AopVerifyAppPayReturnRequest($this->httpClient, $this->httpRequest); 53 | $request->initialize($this->parameters->all()); 54 | $request->setEndpoint($this->getEndpoint()); 55 | $request->setResult($data['result']); 56 | $request->setAlipayPublicKey($this->getAlipayPublicKey()); 57 | $data = $request->send()->getData(); 58 | } else { 59 | $request = new AopNotifyRequest($this->httpClient, $this->httpRequest); 60 | $request->initialize(['params' => $data]); 61 | $request->setEndpoint($this->getEndpoint()); 62 | $request->setAlipayPublicKey($this->getAlipayPublicKey()); 63 | $data = $request->send()->getData(); 64 | 65 | if (! array_get($data, 'trade_status')) { 66 | $tn = array_get($data, 'trade_no'); 67 | 68 | $request = new AopTradeQueryRequest($this->httpClient, $this->httpRequest); 69 | $request->initialize($this->getParameters()); 70 | $request->setEndpoint($this->getEndpoint()); 71 | $request->setBizContent(['trade_no' => $tn]); 72 | $request->setPrivateKey($this->getPrivateKey()); 73 | 74 | // Must set cert path if you used certificate mode 75 | $request->setAlipayRootCert($this->getAlipayRootCert()); 76 | $request->setAppCert($this->getAppCert()); 77 | 78 | /** 79 | * @var AopTradeQueryResponse $response 80 | */ 81 | $response = $request->send(); 82 | 83 | $tradeStatus = $response->getAlipayResponse('trade_status'); 84 | 85 | $data['trade_status'] = $tradeStatus; 86 | } 87 | } 88 | 89 | return $this->response = new AopCompletePurchaseResponse($this, $data); 90 | } 91 | 92 | 93 | /** 94 | * @param $value 95 | * 96 | * @return $this 97 | */ 98 | public function setParams($value) 99 | { 100 | return $this->setParameter('params', $value); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/Requests/AopCompleteRefundRequest.php: -------------------------------------------------------------------------------- 1 | validateParams(); 20 | 21 | return $this->getParams(); 22 | } 23 | 24 | 25 | public function validateParams() 26 | { 27 | $this->validate('params'); 28 | } 29 | 30 | 31 | /** 32 | * @return mixed 33 | */ 34 | public function getParams() 35 | { 36 | return $this->getParameter('params'); 37 | } 38 | 39 | 40 | /** 41 | * Send the request with specified data 42 | * 43 | * @param mixed $data The data to send 44 | * 45 | * @return AopCompleteRefundResponse 46 | */ 47 | public function sendData($data) 48 | { 49 | $request = new AopNotifyRequest($this->httpClient, $this->httpRequest); 50 | $request->initialize(['params' => $data]); 51 | $request->setEndpoint($this->getEndpoint()); 52 | $request->setAlipayPublicKey($this->getAlipayPublicKey()); 53 | $data = $request->send()->getData(); 54 | 55 | if (!array_get($data, 'trade_status')) { 56 | $tn = array_get($data, 'trade_no'); 57 | 58 | $request = new AopTradeQueryRequest($this->httpClient, $this->httpRequest); 59 | $request->initialize($this->getParameters()); 60 | $request->setEndpoint($this->getEndpoint()); 61 | $request->setBizContent(['trade_no' => $tn]); 62 | $request->setPrivateKey($this->getPrivateKey()); 63 | 64 | /** 65 | * @var AopTradeQueryResponse $response 66 | */ 67 | $response = $request->send(); 68 | 69 | $tradeStatus = $response->getAlipayResponse('trade_status'); 70 | 71 | $data['trade_status'] = $tradeStatus; 72 | } 73 | return $this->response = new AopCompleteRefundResponse($this, $data); 74 | } 75 | 76 | 77 | /** 78 | * @param $value 79 | * 80 | * @return $this 81 | */ 82 | public function setParams($value) 83 | { 84 | return $this->setParameter('params', $value); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/Requests/AopNotifyRequest.php: -------------------------------------------------------------------------------- 1 | initParams(); 37 | 38 | $this->validateParams(); 39 | 40 | return $this->params->all(); 41 | } 42 | 43 | 44 | /** 45 | * @return array|mixed 46 | */ 47 | private function initParams() 48 | { 49 | $params = $this->getParams(); 50 | 51 | if (! $params) { 52 | $params = array_merge($_GET, $_POST); 53 | } 54 | 55 | $this->params = new ParameterBag($params); 56 | 57 | return $params; 58 | } 59 | 60 | 61 | /** 62 | * @return mixed 63 | */ 64 | public function getParams() 65 | { 66 | return $this->getParameter('params'); 67 | } 68 | 69 | 70 | /** 71 | * @param $value 72 | * 73 | * @return $this 74 | */ 75 | public function setParams($value) 76 | { 77 | return $this->setParameter('params', $value); 78 | } 79 | 80 | 81 | public function validateParams() 82 | { 83 | if (empty($this->params->all())) { 84 | throw new InvalidRequestException('The `params` or $_REQUEST is empty'); 85 | } 86 | 87 | if (! $this->params->has('sign_type')) { 88 | throw new InvalidRequestException('The `sign_type` is required'); 89 | } 90 | 91 | if (! $this->params->has('sign')) { 92 | throw new InvalidRequestException('The `sign` is required'); 93 | } 94 | } 95 | 96 | 97 | /** 98 | * Send the request with specified data 99 | * 100 | * @param mixed $data The data to send 101 | * 102 | * @return ResponseInterface 103 | * @throws InvalidRequestException 104 | */ 105 | public function sendData($data) 106 | { 107 | $this->verifySignature(); 108 | 109 | if ($this->params->has('notify_id')) { 110 | if ($this->verifyNotifyId) { 111 | $this->verifyNotifyId(); 112 | } 113 | } 114 | 115 | return $this->response = new AopNotifyResponse($this, $data); 116 | } 117 | 118 | 119 | /** 120 | * @throws InvalidRequestException 121 | * @throws Exception 122 | */ 123 | protected function verifySignature() 124 | { 125 | $signer = new Signer($this->params->all()); 126 | $signer->setSort($this->sort); 127 | $signer->setEncodePolicy($this->encodePolicy); 128 | $signer->setIgnores(['sign','sign_type']); 129 | $content = $signer->getContentToSign(); 130 | 131 | $sign = $this->params->get('sign'); 132 | $signType = $this->params->get('sign_type'); 133 | 134 | if ($signType == 'RSA2') { 135 | $match = (new Signer)->verifyWithRSA($content, $sign, $this->getAlipayPublicKey(), OPENSSL_ALGO_SHA256); 136 | } else { 137 | $match = (new Signer)->verifyWithRSA($content, $sign, $this->getAlipayPublicKey()); 138 | } 139 | 140 | if (! $match) { 141 | throw new InvalidRequestException('The signature is not match'); 142 | } 143 | } 144 | 145 | /** 146 | * @throws InvalidRequestException 147 | */ 148 | protected function verifyNotifyId() 149 | { 150 | if (! $this->getPartner()) { 151 | throw new InvalidRequestException('The partner is required for notify_id verify'); 152 | } 153 | 154 | $request = new LegacyVerifyNotifyIdRequest($this->httpClient, $this->httpRequest); 155 | $request->setPartner($this->getPartner()); 156 | $request->setNotifyId($this->params->get('notify_id')); 157 | 158 | /** 159 | * @var VerifyNotifyIdResponse $response 160 | */ 161 | $response = $request->send(); 162 | 163 | if (! $response->isSuccessful()) { 164 | throw new InvalidRequestException('The notify_id is not trusted'); 165 | } 166 | } 167 | 168 | 169 | /** 170 | * @return mixed 171 | */ 172 | public function getPartner() 173 | { 174 | return $this->getParameter('partner'); 175 | } 176 | 177 | 178 | /** 179 | * @param $value 180 | * 181 | * @return $this 182 | */ 183 | public function setPartner($value) 184 | { 185 | return $this->setParameter('partner', $value); 186 | } 187 | 188 | 189 | /** 190 | * @param boolean $value 191 | * 192 | * @return AopNotifyRequest 193 | */ 194 | public function setVerifyNotifyId($value) 195 | { 196 | $this->verifyNotifyId = $value; 197 | 198 | return $this; 199 | } 200 | 201 | 202 | /** 203 | * @param boolean $sort 204 | * 205 | * @return AopNotifyRequest 206 | */ 207 | public function setSort($sort) 208 | { 209 | $this->sort = $sort; 210 | 211 | return $this; 212 | } 213 | 214 | 215 | /** 216 | * @param string $encodePolicy 217 | * 218 | * @return AopNotifyRequest 219 | */ 220 | public function setEncodePolicy($encodePolicy) 221 | { 222 | $this->encodePolicy = $encodePolicy; 223 | 224 | return $this; 225 | } 226 | } 227 | -------------------------------------------------------------------------------- /src/Requests/AopTradeAppPayRequest.php: -------------------------------------------------------------------------------- 1 | response = new AopTradeAppPayResponse($this, $data); 30 | } 31 | 32 | 33 | /** 34 | * @return mixed 35 | */ 36 | public function getNotifyUrl() 37 | { 38 | return $this->getParameter('notify_url'); 39 | } 40 | 41 | 42 | /** 43 | * @param $value 44 | * 45 | * @return $this 46 | */ 47 | public function setNotifyUrl($value) 48 | { 49 | return $this->setParameter('notify_url', $value); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/Requests/AopTradeCancelRequest.php: -------------------------------------------------------------------------------- 1 | response = new AopTradeCancelResponse($this, $data); 32 | } 33 | 34 | 35 | public function validateParams() 36 | { 37 | parent::validateParams(); 38 | 39 | $this->validateBizContentOne( 40 | 'out_trade_no', 41 | 'trade_no' 42 | ); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Requests/AopTradeCloseRequest.php: -------------------------------------------------------------------------------- 1 | response = new AopTradeCloseResponse($this, $data); 32 | } 33 | 34 | 35 | public function validateParams() 36 | { 37 | parent::validateParams(); 38 | 39 | $this->validateBizContentOne( 40 | 'out_trade_no', 41 | 'trade_no' 42 | ); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Requests/AopTradeCreateRequest.php: -------------------------------------------------------------------------------- 1 | getParameter('notify_url'); 23 | } 24 | 25 | 26 | /** 27 | * @param $value 28 | * 29 | * @return $this 30 | */ 31 | public function setNotifyUrl($value) 32 | { 33 | return $this->setParameter('notify_url', $value); 34 | } 35 | 36 | 37 | /** 38 | * @return mixed 39 | */ 40 | public function getAppAuthToken() 41 | { 42 | return $this->getParameter('app_auth_token'); 43 | } 44 | 45 | 46 | /** 47 | * @param $value 48 | * 49 | * @return $this 50 | */ 51 | public function setAppAuthToken($value) 52 | { 53 | return $this->setParameter('app_auth_token', $value); 54 | } 55 | 56 | 57 | /** 58 | * @param mixed $data 59 | * 60 | * @return mixed|AopTradeCreateResponse|\Omnipay\Common\Message\ResponseInterface|\Psr\Http\Message\StreamInterface 61 | * @throws \Psr\Http\Client\Exception\NetworkException 62 | * @throws \Psr\Http\Client\Exception\RequestException 63 | */ 64 | public function sendData($data) 65 | { 66 | $data = parent::sendData($data); 67 | 68 | return $this->response = new AopTradeCreateResponse($this, $data); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/Requests/AopTradeOrderSettleRequest.php: -------------------------------------------------------------------------------- 1 | response = new AopTradeOrderSettleResponse($this, $data); 32 | } 33 | 34 | 35 | public function validateParams() 36 | { 37 | parent::validateParams(); 38 | 39 | $this->validateBizContent( 40 | 'out_request_no', 41 | 'trade_no', 42 | 'royalty_parameters' 43 | ); 44 | $this->validateBizContentOne( 45 | 'out_trade_no', 46 | 'trade_no' 47 | ); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/Requests/AopTradePagePayRequest.php: -------------------------------------------------------------------------------- 1 | response = new AopTradePagePayResponse($this, $data); 24 | } 25 | 26 | 27 | public function validateParams() 28 | { 29 | parent::validateParams(); 30 | 31 | $this->validateBizContent('subject', 'out_trade_no', 'total_amount', 'product_code'); 32 | } 33 | 34 | 35 | protected function getRequestUrl($data) 36 | { 37 | $url = sprintf('%s?%s', $this->getEndpoint(), http_build_query($data)); 38 | 39 | return $url; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/Requests/AopTradePayRequest.php: -------------------------------------------------------------------------------- 1 | response = new AopTradePayResponse($this, $data); 47 | 48 | if ($this->response->isWaitPay() && $this->polling) { 49 | $this->polling(); 50 | } 51 | 52 | return $this->response; 53 | } 54 | 55 | 56 | /** 57 | * @link https://img.alicdn.com/top/i1/LB14VRALXXXXXcnXXXXXXXXXXXX 58 | */ 59 | protected function polling() 60 | { 61 | $currentAttempt = 0; 62 | 63 | while ($currentAttempt++ < $this->pollingAttempts) { 64 | /** 65 | * Query Order Trade Status 66 | */ 67 | $this->query(); 68 | 69 | if ($this->response->getCode() >= 40000) { 70 | break; 71 | } elseif ($this->response->isPaid()) { 72 | break; 73 | } elseif ($this->response->isClosed()) { 74 | break; 75 | } 76 | 77 | sleep($this->pollingWait); 78 | } 79 | 80 | /** 81 | * Close Order 82 | */ 83 | if ($this->response->isWaitPay()) { 84 | $this->cancel(); 85 | } 86 | } 87 | 88 | 89 | protected function query() 90 | { 91 | $request = new AopTradeQueryRequest($this->httpClient, $this->httpRequest); 92 | $request->initialize($this->parameters->all()); 93 | $request->setEndpoint($this->getEndpoint()); 94 | $request->setPrivateKey($this->getPrivateKey()); 95 | $request->setBizContent( 96 | ['out_trade_no' => $this->getBizData('out_trade_no')] 97 | ); 98 | 99 | $this->response = $request->send(); 100 | } 101 | 102 | 103 | protected function cancel() 104 | { 105 | $request = new AopTradeCancelRequest($this->httpClient, $this->httpRequest); 106 | $request->initialize($this->parameters->all()); 107 | $request->setEndpoint($this->getEndpoint()); 108 | $request->setPrivateKey($this->getPrivateKey()); 109 | $request->setBizContent( 110 | ['out_trade_no' => $this->getBizData('out_trade_no')] 111 | ); 112 | 113 | $this->response = $request->send(); 114 | } 115 | 116 | 117 | public function validateParams() 118 | { 119 | parent::validateParams(); 120 | 121 | $this->validateBizContent( 122 | 'out_trade_no', 123 | 'scene', 124 | 'auth_code', 125 | 'subject' 126 | ); 127 | 128 | $this->validateBizContentOne( 129 | 'total_amount', 130 | 'discountable_amount', 131 | 'undiscountable_amount' 132 | ); 133 | } 134 | 135 | 136 | /** 137 | * @param boolean $polling 138 | * 139 | * @return \Omnipay\Alipay\Requests\AopTradePayRequest 140 | */ 141 | public function setPolling($polling) 142 | { 143 | $this->polling = $polling; 144 | 145 | return $this; 146 | } 147 | 148 | 149 | /** 150 | * @param int $pollingWait 151 | * 152 | * @return \Omnipay\Alipay\Requests\AopTradePayRequest 153 | */ 154 | public function setPollingWait($pollingWait) 155 | { 156 | $this->pollingWait = $pollingWait; 157 | 158 | return $this; 159 | } 160 | 161 | 162 | /** 163 | * @param int $pollingAttempts 164 | * 165 | * @return \Omnipay\Alipay\Requests\AopTradePayRequest 166 | */ 167 | public function setPollingAttempts($pollingAttempts) 168 | { 169 | $this->pollingAttempts = $pollingAttempts; 170 | 171 | return $this; 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /src/Requests/AopTradePreCreateRequest.php: -------------------------------------------------------------------------------- 1 | response = new AopTradePreCreateResponse($this, $data); 32 | } 33 | 34 | 35 | /** 36 | * @throws \Omnipay\Common\Exception\InvalidRequestException 37 | */ 38 | public function validateParams() 39 | { 40 | parent::validateParams(); 41 | 42 | $this->validateBizContent( 43 | 'out_trade_no', 44 | 'total_amount', 45 | 'subject' 46 | ); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/Requests/AopTradeQueryRequest.php: -------------------------------------------------------------------------------- 1 | response = new AopTradeQueryResponse($this, $data); 32 | } 33 | 34 | 35 | public function validateParams() 36 | { 37 | parent::validateParams(); 38 | 39 | $this->validateBizContentOne( 40 | 'trade_no', 41 | 'out_trade_no' 42 | ); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Requests/AopTradeRefundQueryRequest.php: -------------------------------------------------------------------------------- 1 | response = new AopTradeRefundQueryResponse($this, $data); 32 | } 33 | 34 | 35 | public function validateParams() 36 | { 37 | parent::validateParams(); 38 | 39 | $this->validateBizContent('out_request_no'); 40 | 41 | $this->validateBizContentOne( 42 | 'trade_no', 43 | 'out_trade_no' 44 | ); 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 $value 59 | * 60 | * @return $this 61 | */ 62 | public function setOutTradeNo($value) 63 | { 64 | return $this->setParameter('out_trade_no', $value); 65 | } 66 | 67 | 68 | /** 69 | * @return mixed 70 | */ 71 | public function getTradeNo() 72 | { 73 | return $this->getParameter('trade_no'); 74 | } 75 | 76 | 77 | /** 78 | * @param $value 79 | * 80 | * @return $this 81 | */ 82 | public function setTradeNo($value) 83 | { 84 | return $this->setParameter('trade_no', $value); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/Requests/AopTradeRefundRequest.php: -------------------------------------------------------------------------------- 1 | response = new AopTradeRefundResponse($this, $data); 34 | } 35 | 36 | 37 | public function validateParams() 38 | { 39 | parent::validateParams(); 40 | 41 | $this->validateBizContent('refund_amount'); 42 | 43 | $this->validateBizContentOne( 44 | 'out_trade_no', 45 | 'trade_no' 46 | ); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/Requests/AopTradeWapPayRequest.php: -------------------------------------------------------------------------------- 1 | response = new AopTradeWapPayResponse($this, $data); 24 | } 25 | 26 | 27 | public function validateParams() 28 | { 29 | parent::validateParams(); 30 | 31 | $this->validateBizContent( 32 | 'subject', 33 | 'out_trade_no', 34 | 'total_amount', 35 | 'product_code' 36 | ); 37 | } 38 | 39 | 40 | protected function getRequestUrl($data) 41 | { 42 | $url = sprintf('%s?%s', $this->getEndpoint(), http_build_query($data)); 43 | 44 | return $url; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/Requests/AopTransferToAccountQueryRequest.php: -------------------------------------------------------------------------------- 1 | response = new AopTransferToAccountQueryResponse($this, $data); 30 | } 31 | 32 | public function validateParams() 33 | { 34 | parent::validateParams(); 35 | 36 | $this->validateBizContentOne( 37 | 'out_biz_no', 38 | 'order_id' 39 | ); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/Requests/AopTransferToAccountRequest.php: -------------------------------------------------------------------------------- 1 | response = new AopTransferToAccountResponse($this, $data); 31 | } 32 | 33 | 34 | public function validateParams() 35 | { 36 | parent::validateParams(); 37 | 38 | $this->validateBizContent( 39 | 'out_biz_no', 40 | 'payee_type', 41 | 'payee_account', 42 | 'amount' 43 | ); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Requests/AopVerifyAppPayReturnRequest.php: -------------------------------------------------------------------------------- 1 | validate(); 29 | 30 | $result = $this->getResult(); 31 | 32 | if (substr($result, 0, 3) == '{\"') { 33 | $result = stripslashes($result); 34 | } 35 | 36 | $response = json_decode($result, true); 37 | 38 | $data = $response[$this->key]; 39 | $data['sign'] = $response['sign']; 40 | $data['sign_type'] = $response['sign_type']; 41 | 42 | return $data; 43 | } 44 | 45 | 46 | /** 47 | * @throws InvalidRequestException 48 | */ 49 | public function validate(...$args) 50 | { 51 | parent::validate( 52 | 'result' 53 | ); 54 | 55 | $result = $this->getResult(); 56 | 57 | if (! is_string($result)) { 58 | throw new InvalidRequestException('The result should be string'); 59 | } 60 | 61 | if (substr($result, 0, 3) == '{\"') { 62 | $result = stripslashes($result); 63 | } 64 | 65 | $data = json_decode($result, true); 66 | 67 | if (json_last_error() != JSON_ERROR_NONE) { 68 | throw new InvalidRequestException('The result should be a valid json string'); 69 | } 70 | 71 | if (! isset($data[$this->key])) { 72 | throw new InvalidRequestException("The result decode data should contain {$this->key}"); 73 | } 74 | } 75 | 76 | 77 | /** 78 | * @return mixed 79 | */ 80 | public function getResult() 81 | { 82 | return $this->getParameter('result'); 83 | } 84 | 85 | 86 | /** 87 | * @param $value 88 | * 89 | * @return $this 90 | */ 91 | public function setResult($value) 92 | { 93 | return $this->setParameter('result', $value); 94 | } 95 | 96 | 97 | /** 98 | * @return mixed 99 | */ 100 | public function getMemo() 101 | { 102 | return $this->getParameter('memo'); 103 | } 104 | 105 | 106 | /** 107 | * @param $value 108 | * 109 | * @return $this 110 | */ 111 | public function setMemo($value) 112 | { 113 | return $this->setParameter('memo', $value); 114 | } 115 | 116 | 117 | /** 118 | * @return mixed 119 | */ 120 | public function getResultStatus() 121 | { 122 | return $this->getParameter('resultStatus'); 123 | } 124 | 125 | 126 | /** 127 | * @param $value 128 | * 129 | * @return $this 130 | */ 131 | public function setResultStatus($value) 132 | { 133 | return $this->setParameter('resultStatus', $value); 134 | } 135 | 136 | 137 | /** 138 | * Send the request with specified data 139 | * 140 | * @param mixed $data The data to send 141 | * 142 | * @return ResponseInterface 143 | * @throws InvalidRequestException 144 | */ 145 | public function sendData($data) 146 | { 147 | $request = new AopNotifyRequest($this->httpClient, $this->httpRequest); 148 | $request->initialize($this->parameters->all()); 149 | $request->setEndpoint($this->getEndpoint()); 150 | $request->setParams($data); 151 | $request->setSort(false); 152 | $request->setEncodePolicy(Signer::ENCODE_POLICY_JSON); 153 | $request->setAlipayPublicKey($this->getAlipayPublicKey()); 154 | 155 | /** 156 | * @var AopNotifyResponse $response 157 | */ 158 | $response = $request->send(); 159 | 160 | return $response; 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /src/Requests/DataServiceBillDownloadUrlQueryRequest.php: -------------------------------------------------------------------------------- 1 | response = new DataServiceBillDownloadUrlQueryResponse($this, $data); 32 | } 33 | 34 | 35 | public function validateParams() 36 | { 37 | parent::validateParams(); 38 | 39 | $this->validateBizContent( 40 | 'bill_type', 41 | 'bill_date' 42 | ); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Requests/LegacyAppPurchaseRequest.php: -------------------------------------------------------------------------------- 1 | validateParams(); 30 | 31 | $params = $this->getParamsToSign(); 32 | 33 | $signer = new Signer($params); 34 | $sign = $signer->signWithRSA($this->privateKey); 35 | 36 | $resp['order_string'] = sprintf( 37 | '%s&sign="%s"&sign_type="RSA"', 38 | $signer->getContentToSign(), 39 | urlencode($sign) 40 | ); 41 | 42 | return $resp; 43 | } 44 | 45 | 46 | protected function validateParams() 47 | { 48 | $this->validate( 49 | 'partner', 50 | '_input_charset', 51 | 'sign_type', 52 | 'notify_url', 53 | 'out_trade_no', 54 | 'subject', 55 | 'total_fee', 56 | 'payment_type' 57 | ); 58 | } 59 | 60 | 61 | private function getParamsToSign() 62 | { 63 | $params = $this->parameters->all(); 64 | $params['service'] = $this->service; 65 | 66 | $params = array_filter($params, 'strlen'); 67 | 68 | $params = array_map( 69 | function ($v) { 70 | return sprintf('"%s"', $v); 71 | }, 72 | $params 73 | ); 74 | 75 | return $params; 76 | } 77 | 78 | 79 | /** 80 | * Send the request with specified data 81 | * 82 | * @param mixed $data The data to send 83 | * 84 | * @return ResponseInterface 85 | */ 86 | public function sendData($data) 87 | { 88 | return $this->response = new LegacyAppPurchaseResponse($this, $data); 89 | } 90 | 91 | 92 | /** 93 | * @return mixed 94 | */ 95 | public function getPartner() 96 | { 97 | return $this->getParameter('partner'); 98 | } 99 | 100 | 101 | /** 102 | * @param $value 103 | * 104 | * @return $this 105 | */ 106 | public function setPartner($value) 107 | { 108 | return $this->setParameter('partner', $value); 109 | } 110 | 111 | 112 | /** 113 | * @return mixed 114 | */ 115 | public function getInputCharset() 116 | { 117 | return $this->getParameter('_input_charset'); 118 | } 119 | 120 | 121 | /** 122 | * @param $value 123 | * 124 | * @return $this 125 | */ 126 | public function setInputCharset($value) 127 | { 128 | return $this->setParameter('_input_charset', $value); 129 | } 130 | 131 | 132 | /** 133 | * @return mixed 134 | */ 135 | public function getSignType() 136 | { 137 | return $this->getParameter('sign_type'); 138 | } 139 | 140 | 141 | /** 142 | * @param $value 143 | * 144 | * @return $this 145 | */ 146 | public function setSignType($value) 147 | { 148 | return $this->setParameter('sign_type', $value); 149 | } 150 | 151 | 152 | /** 153 | * @return mixed 154 | */ 155 | public function getNotifyUrl() 156 | { 157 | return $this->getParameter('notify_url'); 158 | } 159 | 160 | 161 | /** 162 | * @param $value 163 | * 164 | * @return $this 165 | */ 166 | public function setNotifyUrl($value) 167 | { 168 | return $this->setParameter('notify_url', $value); 169 | } 170 | 171 | 172 | /** 173 | * @return mixed 174 | */ 175 | public function getAppId() 176 | { 177 | return $this->getParameter('app_id'); 178 | } 179 | 180 | 181 | /** 182 | * @param $value 183 | * 184 | * @return $this 185 | */ 186 | public function setAppId($value) 187 | { 188 | return $this->setParameter('app_id', $value); 189 | } 190 | 191 | 192 | /** 193 | * @return mixed 194 | */ 195 | public function getAppEnv() 196 | { 197 | return $this->getParameter('appenv'); 198 | } 199 | 200 | 201 | /** 202 | * @param $value 203 | * 204 | * @return $this 205 | */ 206 | public function setAppEnv($value) 207 | { 208 | return $this->setParameter('appenv', $value); 209 | } 210 | 211 | 212 | /** 213 | * @return mixed 214 | */ 215 | public function getOutTradeNo() 216 | { 217 | return $this->getParameter('out_trade_no'); 218 | } 219 | 220 | 221 | /** 222 | * @param $value 223 | * 224 | * @return $this 225 | */ 226 | public function setOutTradeNo($value) 227 | { 228 | return $this->setParameter('out_trade_no', $value); 229 | } 230 | 231 | 232 | /** 233 | * @return mixed 234 | */ 235 | public function getSubject() 236 | { 237 | return $this->getParameter('subject'); 238 | } 239 | 240 | 241 | /** 242 | * @param $value 243 | * 244 | * @return $this 245 | */ 246 | public function setSubject($value) 247 | { 248 | return $this->setParameter('subject', $value); 249 | } 250 | 251 | 252 | /** 253 | * @return mixed 254 | */ 255 | public function getPaymentType() 256 | { 257 | return $this->getParameter('payment_type'); 258 | } 259 | 260 | 261 | /** 262 | * @param $value 263 | * 264 | * @return $this 265 | */ 266 | public function setPaymentType($value) 267 | { 268 | return $this->setParameter('payment_type', $value); 269 | } 270 | 271 | 272 | /** 273 | * @return mixed 274 | */ 275 | public function getSellerId() 276 | { 277 | return $this->getParameter('seller_id'); 278 | } 279 | 280 | 281 | /** 282 | * @param $value 283 | * 284 | * @return $this 285 | */ 286 | public function setSellerId($value) 287 | { 288 | return $this->setParameter('seller_id', $value); 289 | } 290 | 291 | 292 | /** 293 | * @return mixed 294 | */ 295 | public function getTotalFee() 296 | { 297 | return $this->getParameter('total_fee'); 298 | } 299 | 300 | 301 | /** 302 | * @param $value 303 | * 304 | * @return $this 305 | */ 306 | public function setTotalFee($value) 307 | { 308 | return $this->setParameter('total_fee', $value); 309 | } 310 | 311 | 312 | /** 313 | * @return mixed 314 | */ 315 | public function getBody() 316 | { 317 | return $this->getParameter('body'); 318 | } 319 | 320 | 321 | /** 322 | * @param $value 323 | * 324 | * @return $this 325 | */ 326 | public function setBody($value) 327 | { 328 | return $this->setParameter('body', $value); 329 | } 330 | 331 | 332 | /** 333 | * @return mixed 334 | */ 335 | public function getGoodsType() 336 | { 337 | return $this->getParameter('goods_type'); 338 | } 339 | 340 | 341 | /** 342 | * @param $value 343 | * 344 | * @return $this 345 | */ 346 | public function setGoodsType($value) 347 | { 348 | return $this->setParameter('goods_type', $value); 349 | } 350 | 351 | 352 | /** 353 | * @return mixed 354 | */ 355 | public function getHbFqParam() 356 | { 357 | return $this->getParameter('hb_fq_param'); 358 | } 359 | 360 | 361 | /** 362 | * @param $value 363 | * 364 | * @return $this 365 | */ 366 | public function setHbFqParam($value) 367 | { 368 | return $this->setParameter('hb_fq_param', $value); 369 | } 370 | 371 | 372 | /** 373 | * @return mixed 374 | */ 375 | public function getRnCheck() 376 | { 377 | return $this->getParameter('rn_check'); 378 | } 379 | 380 | 381 | /** 382 | * @param $value 383 | * 384 | * @return $this 385 | */ 386 | public function setRnCheck($value) 387 | { 388 | return $this->setParameter('rn_check', $value); 389 | } 390 | 391 | 392 | /** 393 | * @return mixed 394 | */ 395 | public function getItBPay() 396 | { 397 | return $this->getParameter('it_b_pay'); 398 | } 399 | 400 | 401 | /** 402 | * @param $value 403 | * 404 | * @return $this 405 | */ 406 | public function setItBPay($value) 407 | { 408 | return $this->setParameter('it_b_pay', $value); 409 | } 410 | 411 | 412 | /** 413 | * @return mixed 414 | */ 415 | public function getExternToken() 416 | { 417 | return $this->getParameter('extern_token'); 418 | } 419 | 420 | 421 | /** 422 | * @param $value 423 | * 424 | * @return $this 425 | */ 426 | public function setExternToken($value) 427 | { 428 | return $this->setParameter('extern_token', $value); 429 | } 430 | 431 | 432 | /** 433 | * @return mixed 434 | */ 435 | public function getPromoParams() 436 | { 437 | return $this->getParameter('promo_params'); 438 | } 439 | 440 | 441 | /** 442 | * @param $value 443 | * 444 | * @return $this 445 | */ 446 | public function setPromoParams($value) 447 | { 448 | return $this->setParameter('promo_params', $value); 449 | } 450 | 451 | 452 | /** 453 | * @return mixed 454 | */ 455 | public function getPrivateKey() 456 | { 457 | return $this->privateKey; 458 | } 459 | 460 | 461 | /** 462 | * @param $value 463 | * 464 | * @return $this 465 | */ 466 | public function setPrivateKey($value) 467 | { 468 | return $this->privateKey = $value; 469 | } 470 | } 471 | -------------------------------------------------------------------------------- /src/Requests/LegacyCompletePurchaseRequest.php: -------------------------------------------------------------------------------- 1 | getParams(); 22 | } 23 | 24 | 25 | /** 26 | * @return mixed 27 | */ 28 | public function getParams() 29 | { 30 | return $this->getParameter('params'); 31 | } 32 | 33 | 34 | /** 35 | * Send the request with specified data 36 | * 37 | * @param mixed $data The data to send 38 | * 39 | * @return ResponseInterface 40 | */ 41 | public function sendData($data) 42 | { 43 | if (array_get($data, 'result')) { 44 | $request = new LegacyVerifyAppPayReturnRequest($this->httpClient, $this->httpRequest); 45 | $request->initialize($this->parameters->all()); 46 | $request->setResult($data['result']); 47 | $request->setAlipayPublicKey($this->getAlipayPublicKey()); 48 | $data = $request->send()->getData(); 49 | 50 | $data = array_map( 51 | function ($v) { 52 | return substr($v, 1, mb_strlen($v) - 2) . ''; 53 | }, 54 | $data 55 | ); 56 | 57 | if (array_get($data, 'success') == 'true') { 58 | $data['trade_status'] = 'TRADE_SUCCESS'; 59 | } else { 60 | $data['trade_status'] = 'WAIT_BUYER_PAY'; 61 | } 62 | } else { 63 | $request = new LegacyNotifyRequest($this->httpClient, $this->httpRequest); 64 | $request->initialize($this->parameters->all()); 65 | $request->setAlipayPublicKey($this->getAlipayPublicKey()); 66 | $request->setVerifyNotifyId($this->verifyNotifyId); 67 | $request->setKey($this->getKey()); 68 | $response = $request->send(); 69 | 70 | $data = $response->getData(); 71 | } 72 | 73 | return $this->response = new LegacyCompletePurchaseResponse($this, $data); 74 | } 75 | 76 | 77 | /** 78 | * @param $value 79 | * 80 | * @return $this 81 | */ 82 | public function setParams($value) 83 | { 84 | return $this->setParameter('params', $value); 85 | } 86 | 87 | 88 | /** 89 | * @param boolean $verifyNotifyId 90 | * 91 | * @return \Omnipay\Alipay\Requests\LegacyCompletePurchaseRequest 92 | */ 93 | public function setVerifyNotifyId($verifyNotifyId) 94 | { 95 | $this->verifyNotifyId = $verifyNotifyId; 96 | 97 | return $this; 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/Requests/LegacyCompleteRefundRequest.php: -------------------------------------------------------------------------------- 1 | getParams(); 22 | } 23 | 24 | 25 | /** 26 | * @return mixed 27 | */ 28 | public function getParams() 29 | { 30 | return $this->getParameter('params'); 31 | } 32 | 33 | 34 | /** 35 | * Send the request with specified data 36 | * 37 | * @param mixed $data The data to send 38 | * 39 | * @return ResponseInterface 40 | */ 41 | public function sendData($data) 42 | { 43 | $request = new LegacyNotifyRequest($this->httpClient, $this->httpRequest); 44 | $request->initialize($this->parameters->all()); 45 | $request->setAlipayPublicKey($this->getAlipayPublicKey()); 46 | $request->setVerifyNotifyId($this->verifyNotifyId); 47 | $request->setKey($this->getKey()); 48 | $response = $request->send(); 49 | 50 | $data = $response->getData(); 51 | 52 | return $this->response = new LegacyCompletePurchaseResponse($this, $data); 53 | } 54 | 55 | 56 | /** 57 | * @param $value 58 | * 59 | * @return $this 60 | */ 61 | public function setParams($value) 62 | { 63 | return $this->setParameter('params', $value); 64 | } 65 | 66 | 67 | /** 68 | * @param boolean $verifyNotifyId 69 | * 70 | * @return $this 71 | */ 72 | public function setVerifyNotifyId($verifyNotifyId) 73 | { 74 | $this->verifyNotifyId = $verifyNotifyId; 75 | 76 | return $this; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/Requests/LegacyNotifyRequest.php: -------------------------------------------------------------------------------- 1 | initParams(); 34 | 35 | $this->validateParams(); 36 | 37 | return $this->params->all(); 38 | } 39 | 40 | 41 | /** 42 | * @return array|mixed 43 | */ 44 | private function initParams() 45 | { 46 | $params = $this->getParams(); 47 | 48 | if (! $params) { 49 | $params = array_merge($_GET, $_POST); 50 | } 51 | 52 | $this->params = new ParameterBag($params); 53 | 54 | return $params; 55 | } 56 | 57 | 58 | /** 59 | * @return mixed 60 | */ 61 | public function getParams() 62 | { 63 | return $this->getParameter('params'); 64 | } 65 | 66 | 67 | /** 68 | * @param $value 69 | * 70 | * @return $this 71 | */ 72 | public function setParams($value) 73 | { 74 | return $this->setParameter('params', $value); 75 | } 76 | 77 | 78 | public function validateParams() 79 | { 80 | if (empty($this->params->all())) { 81 | throw new InvalidRequestException('The `params` or $_REQUEST is empty'); 82 | } 83 | 84 | if (! $this->params->has('sign_type')) { 85 | throw new InvalidRequestException('The sign_type is required'); 86 | } 87 | 88 | if (! $this->params->has('sign')) { 89 | throw new InvalidRequestException('The sign is required'); 90 | } 91 | } 92 | 93 | 94 | /** 95 | * Send the request with specified data 96 | * 97 | * @param mixed $data The data to send 98 | * 99 | * @return ResponseInterface 100 | * @throws InvalidRequestException 101 | */ 102 | public function sendData($data) 103 | { 104 | $this->verifySignature(); 105 | 106 | if ($this->params->has('notify_id')) { 107 | if ($this->verifyNotifyId) { 108 | $this->verifyNotifyId(); 109 | } 110 | } 111 | 112 | return $this->response = new LegacyNotifyResponse($this, $data); 113 | } 114 | 115 | 116 | protected function verifySignature() 117 | { 118 | $signer = new Signer($this->params->all()); 119 | $signer->setSort($this->sort); 120 | $content = $signer->getContentToSign(); 121 | 122 | $sign = $this->params->get('sign'); 123 | $signType = strtoupper($this->params->get('sign_type')); 124 | 125 | if ($signType == 'MD5') { 126 | if (! $this->getKey()) { 127 | throw new InvalidRequestException('The `key` is required for `MD5` sign_type'); 128 | } 129 | 130 | $match = (new Signer)->verifyWithMD5($content, $sign, $this->getKey()); 131 | } elseif ($signType == 'RSA') { 132 | if (! $this->getAlipayPublicKey()) { 133 | throw new InvalidRequestException('The `alipay_public_key` is required for `RSA` sign_type'); 134 | } 135 | 136 | $match = (new Signer)->verifyWithRSA($content, $sign, $this->getAlipayPublicKey()); 137 | } else { 138 | throw new InvalidRequestException('The `sign_type` is invalid'); 139 | } 140 | 141 | if (! $match) { 142 | throw new InvalidRequestException('The signature is not match'); 143 | } 144 | } 145 | 146 | 147 | protected function verifyNotifyId() 148 | { 149 | $request = new LegacyVerifyNotifyIdRequest($this->httpClient, $this->httpRequest); 150 | $request->initialize($this->parameters->all()); 151 | $request->setPartner($this->getPartner()); 152 | $request->setNotifyId($this->params->get('notify_id')); 153 | 154 | /** 155 | * @var VerifyNotifyIdResponse $response 156 | */ 157 | $response = $request->send(); 158 | 159 | if (! $response->isSuccessful()) { 160 | throw new InvalidRequestException('The `notify_id` verify failed, which TTL is 60s'); 161 | } 162 | } 163 | 164 | 165 | /** 166 | * @param boolean $verifyNotifyId 167 | * 168 | * @return $this 169 | */ 170 | public function setVerifyNotifyId($verifyNotifyId) 171 | { 172 | $this->verifyNotifyId = $verifyNotifyId; 173 | 174 | return $this; 175 | } 176 | 177 | 178 | /** 179 | * @param boolean $sort 180 | * 181 | * @return \Omnipay\Alipay\Requests\LegacyNotifyRequest 182 | */ 183 | public function setSort($sort) 184 | { 185 | $this->sort = $sort; 186 | 187 | return $this; 188 | } 189 | } 190 | -------------------------------------------------------------------------------- /src/Requests/LegacyQueryRequest.php: -------------------------------------------------------------------------------- 1 | getEndpoint(), http_build_query($this->getData())); 31 | $result = $this->httpClient->request('GET', $url, [], '')->getBody(); 32 | 33 | $xml = simplexml_load_string($result); 34 | $json = json_encode($xml); 35 | $data = json_decode($json, true); 36 | 37 | return $this->response = new LegacyQueryResponse($this, $data); 38 | } 39 | 40 | 41 | /** 42 | * Get the raw data array for this message. The format of this varies from gateway to 43 | * gateway, but will usually be either an associative array, or a SimpleXMLElement. 44 | * 45 | * @return mixed 46 | * @throws \Omnipay\Common\Exception\InvalidRequestException 47 | */ 48 | public function getData() 49 | { 50 | $this->validateParams(); 51 | 52 | $data = [ 53 | 'service' => $this->service, 54 | 'partner' => $this->getPartner(), 55 | 'trade_no' => $this->getTradeNo(), 56 | 'out_trade_no' => $this->getOutTradeNo(), 57 | '_input_charset' => $this->getInputCharset(), 58 | 'sign_type' => $this->getSignType() 59 | ]; 60 | $data['sign'] = $this->sign($data, $this->getSignType()); 61 | 62 | return $data; 63 | } 64 | 65 | 66 | protected function validateParams() 67 | { 68 | $this->validate( 69 | 'partner', 70 | '_input_charset' 71 | ); 72 | 73 | $this->validateOne( 74 | 'trade_no', 75 | 'out_trade_no' 76 | ); 77 | } 78 | 79 | 80 | /** 81 | * @return mixed 82 | */ 83 | public function getTradeNo() 84 | { 85 | return $this->getParameter('trade_no'); 86 | } 87 | 88 | 89 | /** 90 | * @return mixed 91 | */ 92 | public function getOutTradeNo() 93 | { 94 | return $this->getParameter('out_trade_no'); 95 | } 96 | 97 | 98 | /** 99 | * @param $value 100 | * 101 | * @return $this 102 | */ 103 | public function setTradeNo($value) 104 | { 105 | return $this->setParameter('trade_no', $value); 106 | } 107 | 108 | 109 | /** 110 | * @param $value 111 | * 112 | * @return $this 113 | */ 114 | public function setOutTradeNo($value) 115 | { 116 | return $this->setParameter('out_trade_no', $value); 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /src/Requests/LegacyRefundNoPwdRequest.php: -------------------------------------------------------------------------------- 1 | setDefaults(); 28 | 29 | $this->validate( 30 | 'partner', 31 | '_input_charset', 32 | 'refund_date', 33 | 'batch_no', 34 | 'refund_items' 35 | ); 36 | 37 | $this->validateOne( 38 | 'seller_user_id', 39 | 'seller_email' 40 | ); 41 | 42 | $this->setBatchNum(count($this->getRefundItems())); 43 | $this->setRefundDetail($this->getDetailData()); 44 | 45 | $data = [ 46 | 'service' => $this->service, 47 | 'partner' => $this->getPartner(), 48 | 'notify_url' => $this->getNotifyUrl(), 49 | 'seller_user_id' => $this->getPartner(), 50 | 'refund_date' => $this->getRefundDate(), 51 | 'batch_no' => $this->getBatchNo(), 52 | 'batch_num' => $this->getBatchNum(), 53 | 'detail_data' => $this->getDetailData(), 54 | '_input_charset' => $this->getInputCharset(), 55 | ]; 56 | 57 | $data['sign'] = $this->sign($data, $this->getSignType()); 58 | $data['sign_type'] = $this->getSignType(); 59 | 60 | return $data; 61 | } 62 | 63 | 64 | protected function setDefaults() 65 | { 66 | if (!$this->getRefundDate()) { 67 | $this->setRefundDate(date('Y-m-d H:i:s')); 68 | } 69 | 70 | if (!$this->getBatchNo()) { 71 | $this->setBatchNo(date('Ymd') . mt_rand(1000, 9999)); 72 | } 73 | } 74 | 75 | 76 | /** 77 | * @return mixed 78 | */ 79 | public function getRefundDate() 80 | { 81 | return $this->getParameter('refund_date'); 82 | } 83 | 84 | 85 | /** 86 | * @param $value 87 | * 88 | * @return $this 89 | */ 90 | public function setRefundDate($value) 91 | { 92 | return $this->setParameter('refund_date', $value); 93 | } 94 | 95 | 96 | /** 97 | * @return mixed 98 | */ 99 | public function getBatchNo() 100 | { 101 | return $this->getParameter('batch_no'); 102 | } 103 | 104 | 105 | /** 106 | * @param $value 107 | * 108 | * @return $this 109 | */ 110 | public function setBatchNo($value) 111 | { 112 | return $this->setParameter('batch_no', $value); 113 | } 114 | 115 | 116 | /** 117 | * @param $value 118 | * 119 | * @return $this 120 | */ 121 | public function setBatchNum($value) 122 | { 123 | return $this->setParameter('batch_num', $value); 124 | } 125 | 126 | 127 | /** 128 | * @return mixed 129 | */ 130 | public function getRefundItems() 131 | { 132 | return $this->getParameter('refund_items'); 133 | } 134 | 135 | 136 | /** 137 | * @param $value 138 | * 139 | * @return $this 140 | */ 141 | protected function setRefundDetail($value) 142 | { 143 | return $this->setParameter('refund_detail', $value); 144 | } 145 | 146 | 147 | protected function getDetailData() 148 | { 149 | $strings = []; 150 | 151 | foreach ($this->getRefundItems() as $item) { 152 | $item = (array)$item; 153 | 154 | if (!isset($item['trade_no'])) { 155 | throw new InvalidRequestException('The field `trade_no` is not exist in item'); 156 | } 157 | 158 | if (!isset($item['amount'])) { 159 | throw new InvalidRequestException('The field `amount` is not exist in item'); 160 | } 161 | 162 | if (!isset($item['reason'])) { 163 | throw new InvalidRequestException('The field `reason` is not exist in item'); 164 | } 165 | 166 | $strings[] = implode('^', [ $item['trade_no'], $item['amount'], $item['reason'] ]); 167 | } 168 | 169 | return implode('#', $strings); 170 | } 171 | 172 | 173 | /** 174 | * @return mixed 175 | */ 176 | public function getPartner() 177 | { 178 | return $this->getParameter('partner'); 179 | } 180 | 181 | 182 | /** 183 | * @return mixed 184 | */ 185 | public function getNotifyUrl() 186 | { 187 | return $this->getParameter('notify_url'); 188 | } 189 | 190 | 191 | /** 192 | * @return mixed 193 | */ 194 | public function getBatchNum() 195 | { 196 | return $this->getParameter('batch_num'); 197 | } 198 | 199 | 200 | /** 201 | * @return mixed 202 | */ 203 | public function getInputCharset() 204 | { 205 | return $this->getParameter('_input_charset'); 206 | } 207 | 208 | 209 | /** 210 | * @return mixed 211 | */ 212 | public function getPaymentType() 213 | { 214 | return $this->getParameter('payment_type'); 215 | } 216 | 217 | 218 | /** 219 | * @param $value 220 | * 221 | * @return $this 222 | */ 223 | public function setPaymentType($value) 224 | { 225 | return $this->setParameter('payment_type', $value); 226 | } 227 | 228 | 229 | /** 230 | * Send the request with specified data 231 | * 232 | * @param mixed $data The data to send 233 | * 234 | * @return ResponseInterface 235 | */ 236 | public function sendData($data) 237 | { 238 | $url = sprintf('%s?%s', $this->getEndpoint(), http_build_query($this->getData())); 239 | 240 | $result = $this->httpClient->request('get', $url)->getBody(); 241 | 242 | $xml = simplexml_load_string($result); 243 | $json = json_encode($xml); 244 | $data = json_decode($json, true); 245 | 246 | return $this->response = new LegacyRefundNoPwdResponse($this, $data); 247 | } 248 | 249 | 250 | /** 251 | * @param $value 252 | * 253 | * @return $this 254 | */ 255 | public function setPartner($value) 256 | { 257 | return $this->setParameter('partner', $value); 258 | } 259 | 260 | 261 | /** 262 | * @param $value 263 | * 264 | * @return $this 265 | */ 266 | public function setInputCharset($value) 267 | { 268 | return $this->setParameter('_input_charset', $value); 269 | } 270 | 271 | 272 | /** 273 | * @param $value 274 | * 275 | * @return $this 276 | */ 277 | public function setNotifyUrl($value) 278 | { 279 | return $this->setParameter('notify_url', $value); 280 | } 281 | 282 | 283 | /** 284 | * @return mixed 285 | */ 286 | public function getSellerEmail() 287 | { 288 | return $this->getParameter('seller_email'); 289 | } 290 | 291 | 292 | /** 293 | * @param $value 294 | * 295 | * @return $this 296 | */ 297 | public function setSellerEmail($value) 298 | { 299 | return $this->setParameter('seller_email', $value); 300 | } 301 | 302 | 303 | /** 304 | * @return mixed 305 | */ 306 | public function getSellerId() 307 | { 308 | return $this->getSellerUserId(); 309 | } 310 | 311 | 312 | /** 313 | * @return mixed 314 | */ 315 | public function getSellerUserId() 316 | { 317 | return $this->getParameter('seller_user_id'); 318 | } 319 | 320 | 321 | /** 322 | * @param $value 323 | * 324 | * @return $this 325 | */ 326 | public function setSellerId($value) 327 | { 328 | return $this->setSellerUserId($value); 329 | } 330 | 331 | 332 | /** 333 | * @param $value 334 | * 335 | * @return $this 336 | */ 337 | public function setSellerUserId($value) 338 | { 339 | return $this->setParameter('seller_user_id', $value); 340 | } 341 | 342 | 343 | /** 344 | * @param $value 345 | * 346 | * @return $this 347 | */ 348 | public function setRefundItems($value) 349 | { 350 | return $this->setParameter('refund_items', $value); 351 | } 352 | 353 | 354 | /** 355 | * @return mixed 356 | */ 357 | protected function getRefundDetail() 358 | { 359 | return $this->getParameter('refund_detail'); 360 | } 361 | } 362 | -------------------------------------------------------------------------------- /src/Requests/LegacyRefundRequest.php: -------------------------------------------------------------------------------- 1 | setDefaults(); 28 | 29 | $this->validate( 30 | 'partner', 31 | '_input_charset', 32 | 'refund_date', 33 | 'batch_no', 34 | 'refund_items' 35 | ); 36 | 37 | $this->validateOne( 38 | 'seller_user_id', 39 | 'seller_email' 40 | ); 41 | 42 | $this->setBatchNum(count($this->getRefundItems())); 43 | $this->setRefundDetail($this->getDetailData()); 44 | 45 | $data = [ 46 | 'service' => $this->service, 47 | 'partner' => $this->getPartner(), 48 | 'notify_url' => $this->getNotifyUrl(), 49 | 'seller_user_id' => $this->getPartner(), 50 | 'refund_date' => $this->getRefundDate(), 51 | 'batch_no' => $this->getBatchNo(), 52 | 'batch_num' => $this->getBatchNum(), 53 | 'detail_data' => $this->getDetailData(), 54 | '_input_charset' => $this->getInputCharset() 55 | ]; 56 | 57 | $data['sign'] = $this->sign($data, $this->getSignType()); 58 | $data['sign_type'] = $this->getSignType(); 59 | 60 | return $data; 61 | } 62 | 63 | 64 | protected function setDefaults() 65 | { 66 | if (! $this->getRefundDate()) { 67 | $this->setRefundDate(date('Y-m-d H:i:s')); 68 | } 69 | 70 | if (! $this->getBatchNo()) { 71 | $this->setBatchNo(date('Ymd') . mt_rand(1000, 9999)); 72 | } 73 | } 74 | 75 | 76 | /** 77 | * @return mixed 78 | */ 79 | public function getRefundDate() 80 | { 81 | return $this->getParameter('refund_date'); 82 | } 83 | 84 | 85 | /** 86 | * @param $value 87 | * 88 | * @return $this 89 | */ 90 | public function setRefundDate($value) 91 | { 92 | return $this->setParameter('refund_date', $value); 93 | } 94 | 95 | 96 | /** 97 | * @return mixed 98 | */ 99 | public function getBatchNo() 100 | { 101 | return $this->getParameter('batch_no'); 102 | } 103 | 104 | 105 | /** 106 | * @param $value 107 | * 108 | * @return $this 109 | */ 110 | public function setBatchNo($value) 111 | { 112 | return $this->setParameter('batch_no', $value); 113 | } 114 | 115 | 116 | /** 117 | * @param $value 118 | * 119 | * @return $this 120 | */ 121 | public function setBatchNum($value) 122 | { 123 | return $this->setParameter('batch_num', $value); 124 | } 125 | 126 | 127 | /** 128 | * @return mixed 129 | */ 130 | public function getRefundItems() 131 | { 132 | return $this->getParameter('refund_items'); 133 | } 134 | 135 | 136 | /** 137 | * @param $value 138 | * 139 | * @return $this 140 | */ 141 | protected function setRefundDetail($value) 142 | { 143 | return $this->setParameter('refund_detail', $value); 144 | } 145 | 146 | 147 | protected function getDetailData() 148 | { 149 | $strings = []; 150 | 151 | foreach ($this->getRefundItems() as $item) { 152 | $item = (array) $item; 153 | 154 | if (! isset($item['out_trade_no'])) { 155 | throw new InvalidRequestException('The field `out_trade_no` is not exist in item'); 156 | } 157 | 158 | if (! isset($item['amount'])) { 159 | throw new InvalidRequestException('The field `amount` is not exist in item'); 160 | } 161 | 162 | if (! isset($item['reason'])) { 163 | throw new InvalidRequestException('The field `reason` is not exist in item'); 164 | } 165 | 166 | $strings[] = implode('^', [$item['out_trade_no'], $item['amount'], $item['reason']]); 167 | } 168 | 169 | return implode('#', $strings); 170 | } 171 | 172 | 173 | /** 174 | * @return mixed 175 | */ 176 | public function getPartner() 177 | { 178 | return $this->getParameter('partner'); 179 | } 180 | 181 | 182 | /** 183 | * @return mixed 184 | */ 185 | public function getNotifyUrl() 186 | { 187 | return $this->getParameter('notify_url'); 188 | } 189 | 190 | 191 | /** 192 | * @return mixed 193 | */ 194 | public function getBatchNum() 195 | { 196 | return $this->getParameter('batch_num'); 197 | } 198 | 199 | 200 | /** 201 | * @return mixed 202 | */ 203 | public function getInputCharset() 204 | { 205 | return $this->getParameter('_input_charset'); 206 | } 207 | 208 | 209 | /** 210 | * @return mixed 211 | */ 212 | public function getPaymentType() 213 | { 214 | return $this->getParameter('payment_type'); 215 | } 216 | 217 | 218 | /** 219 | * @param $value 220 | * 221 | * @return $this 222 | */ 223 | public function setPaymentType($value) 224 | { 225 | return $this->setParameter('payment_type', $value); 226 | } 227 | 228 | 229 | /** 230 | * Send the request with specified data 231 | * 232 | * @param mixed $data The data to send 233 | * 234 | * @return ResponseInterface 235 | */ 236 | public function sendData($data) 237 | { 238 | return $this->response = new LegacyRefundResponse($this, $data); 239 | } 240 | 241 | 242 | /** 243 | * @param $value 244 | * 245 | * @return $this 246 | */ 247 | public function setPartner($value) 248 | { 249 | return $this->setParameter('partner', $value); 250 | } 251 | 252 | 253 | /** 254 | * @param $value 255 | * 256 | * @return $this 257 | */ 258 | public function setInputCharset($value) 259 | { 260 | return $this->setParameter('_input_charset', $value); 261 | } 262 | 263 | 264 | /** 265 | * @param $value 266 | * 267 | * @return $this 268 | */ 269 | public function setNotifyUrl($value) 270 | { 271 | return $this->setParameter('notify_url', $value); 272 | } 273 | 274 | 275 | /** 276 | * @return mixed 277 | */ 278 | public function getSellerEmail() 279 | { 280 | return $this->getParameter('seller_email'); 281 | } 282 | 283 | 284 | /** 285 | * @param $value 286 | * 287 | * @return $this 288 | */ 289 | public function setSellerEmail($value) 290 | { 291 | return $this->setParameter('seller_email', $value); 292 | } 293 | 294 | 295 | /** 296 | * @return mixed 297 | */ 298 | public function getSellerId() 299 | { 300 | return $this->getSellerUserId(); 301 | } 302 | 303 | 304 | /** 305 | * @return mixed 306 | */ 307 | public function getSellerUserId() 308 | { 309 | return $this->getParameter('seller_user_id'); 310 | } 311 | 312 | 313 | /** 314 | * @param $value 315 | * 316 | * @return $this 317 | */ 318 | public function setSellerId($value) 319 | { 320 | return $this->setSellerUserId($value); 321 | } 322 | 323 | 324 | /** 325 | * @param $value 326 | * 327 | * @return $this 328 | */ 329 | public function setSellerUserId($value) 330 | { 331 | return $this->setParameter('seller_user_id', $value); 332 | } 333 | 334 | 335 | /** 336 | * @param $value 337 | * 338 | * @return $this 339 | */ 340 | public function setRefundItems($value) 341 | { 342 | return $this->setParameter('refund_items', $value); 343 | } 344 | 345 | 346 | /** 347 | * @return mixed 348 | */ 349 | protected function getRefundDetail() 350 | { 351 | return $this->getParameter('refund_detail'); 352 | } 353 | } 354 | -------------------------------------------------------------------------------- /src/Requests/LegacyVerifyAppPayReturnRequest.php: -------------------------------------------------------------------------------- 1 | validateParams(); 25 | 26 | $result = trim($this->getResult()); 27 | 28 | if (substr($result, -2, 2) == '\"') { 29 | $result = stripslashes($result); 30 | } 31 | 32 | parse_str($result, $data); 33 | 34 | $sign = trim($data['sign'], '"'); 35 | $sign = str_replace(' ', '+', $sign); 36 | $signType = trim($data['sign_type'], '"'); 37 | 38 | $data['sign'] = $sign; 39 | $data['sign_type'] = $signType; 40 | 41 | return $data; 42 | } 43 | 44 | 45 | /** 46 | * @throws InvalidRequestException 47 | */ 48 | public function validateParams() 49 | { 50 | $this->validate( 51 | 'result' 52 | ); 53 | 54 | $result = $this->getResult(); 55 | 56 | if (! is_string($result)) { 57 | throw new InvalidRequestException('The result should be string'); 58 | } 59 | 60 | parse_str($result, $data); 61 | 62 | if (! isset($data['sign'])) { 63 | throw new InvalidRequestException('The `result` is invalid'); 64 | } 65 | 66 | if (! isset($data['sign_type'])) { 67 | throw new InvalidRequestException('The `result` is invalid'); 68 | } 69 | } 70 | 71 | 72 | /** 73 | * @return mixed 74 | */ 75 | public function getResult() 76 | { 77 | return $this->getParameter('result'); 78 | } 79 | 80 | 81 | /** 82 | * Send the request with specified data 83 | * 84 | * @param mixed $data The data to send 85 | * 86 | * @return ResponseInterface 87 | * @throws InvalidRequestException 88 | */ 89 | public function sendData($data) 90 | { 91 | $request = new LegacyNotifyRequest($this->httpClient, $this->httpRequest); 92 | $request->initialize($this->parameters->all()); 93 | $request->setParams($data); 94 | $request->setSort(false); 95 | $request->setAlipayPublicKey($this->getAlipayPublicKey()); 96 | 97 | /** 98 | * @var LegacyNotifyResponse $response 99 | */ 100 | $response = $request->send(); 101 | 102 | return $response; 103 | } 104 | 105 | 106 | /** 107 | * @param $value 108 | * 109 | * @return $this 110 | */ 111 | public function setResult($value) 112 | { 113 | return $this->setParameter('result', $value); 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /src/Requests/LegacyVerifyNotifyIdRequest.php: -------------------------------------------------------------------------------- 1 | validate( 27 | 'partner', 28 | 'notify_id' 29 | ); 30 | 31 | $data = $this->parameters->all(); 32 | $data['service'] = $this->service; 33 | 34 | return $data; 35 | } 36 | 37 | 38 | /** 39 | * Send the request with specified data 40 | * 41 | * @param mixed $data The data to send 42 | * 43 | * @return ResponseInterface 44 | * @throws \Psr\Http\Client\Exception\NetworkException 45 | * @throws \Psr\Http\Client\Exception\RequestException 46 | */ 47 | public function sendData($data) 48 | { 49 | $url = sprintf('%s?%s', $this->getEndpoint(), http_build_query($data)); 50 | 51 | $response = $this->httpClient->request('GET', $url, [])->getBody(); 52 | 53 | $data = [ 54 | 'result' => $response 55 | ]; 56 | 57 | return $this->response = new VerifyNotifyIdResponse($this, $data); 58 | } 59 | 60 | 61 | /** 62 | * @return mixed 63 | */ 64 | public function getNotifyId() 65 | { 66 | return $this->getParameter('notify_id'); 67 | } 68 | 69 | 70 | /** 71 | * @param $value 72 | * 73 | * @return $this 74 | */ 75 | public function setNotifyId($value) 76 | { 77 | return $this->setParameter('notify_id', $value); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/Requests/LegacyWapPurchaseRequest.php: -------------------------------------------------------------------------------- 1 | validateParams(); 31 | 32 | $data = $this->filter($this->parameters->all()); 33 | 34 | $data['service'] = $this->service; 35 | $data['sign'] = $this->sign($data, $this->getSignType()); 36 | $data['sign_type'] = $this->getSignType(); 37 | 38 | return $data; 39 | } 40 | 41 | 42 | protected function validateParams() 43 | { 44 | $this->validate( 45 | 'partner', 46 | '_input_charset', 47 | 'sign_type', 48 | 'out_trade_no', 49 | 'subject', 50 | 'total_fee', 51 | 'seller_id', 52 | 'payment_type' 53 | ); 54 | } 55 | 56 | 57 | /** 58 | * @return mixed 59 | */ 60 | public function getSignType() 61 | { 62 | return $this->getParameter('sign_type'); 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 | return $this->response = new LegacyWapPurchaseResponse($this, $data); 76 | } 77 | 78 | 79 | /** 80 | * @return mixed 81 | */ 82 | public function getPartner() 83 | { 84 | return $this->getParameter('partner'); 85 | } 86 | 87 | 88 | /** 89 | * @param $value 90 | * 91 | * @return $this 92 | */ 93 | public function setPartner($value) 94 | { 95 | return $this->setParameter('partner', $value); 96 | } 97 | 98 | 99 | /** 100 | * @return mixed 101 | */ 102 | public function getInputCharset() 103 | { 104 | return $this->getParameter('_input_charset'); 105 | } 106 | 107 | 108 | /** 109 | * @param $value 110 | * 111 | * @return $this 112 | */ 113 | public function setInputCharset($value) 114 | { 115 | return $this->setParameter('_input_charset', $value); 116 | } 117 | 118 | 119 | /** 120 | * @param $value 121 | * 122 | * @return $this 123 | */ 124 | public function setSignType($value) 125 | { 126 | return $this->setParameter('sign_type', $value); 127 | } 128 | 129 | 130 | /** 131 | * @return mixed 132 | */ 133 | public function getNotifyUrl() 134 | { 135 | return $this->getParameter('notify_url'); 136 | } 137 | 138 | 139 | /** 140 | * @param $value 141 | * 142 | * @return $this 143 | */ 144 | public function setNotifyUrl($value) 145 | { 146 | return $this->setParameter('notify_url', $value); 147 | } 148 | 149 | 150 | /** 151 | * @return mixed 152 | */ 153 | public function getReturnUrl() 154 | { 155 | return $this->getParameter('return_url'); 156 | } 157 | 158 | 159 | /** 160 | * @param $value 161 | * 162 | * @return $this 163 | */ 164 | public function setReturnUrl($value) 165 | { 166 | return $this->setParameter('return_url', $value); 167 | } 168 | 169 | 170 | /** 171 | * @return mixed 172 | */ 173 | public function getOutTradeNo() 174 | { 175 | return $this->getParameter('out_trade_no'); 176 | } 177 | 178 | 179 | /** 180 | * @param $value 181 | * 182 | * @return $this 183 | */ 184 | public function setOutTradeNo($value) 185 | { 186 | return $this->setParameter('out_trade_no', $value); 187 | } 188 | 189 | 190 | /** 191 | * @return mixed 192 | */ 193 | public function getSubject() 194 | { 195 | return $this->getParameter('subject'); 196 | } 197 | 198 | 199 | /** 200 | * @param $value 201 | * 202 | * @return $this 203 | */ 204 | public function setSubject($value) 205 | { 206 | return $this->setParameter('subject', $value); 207 | } 208 | 209 | 210 | /** 211 | * @return mixed 212 | */ 213 | public function getTotalFee() 214 | { 215 | return $this->getParameter('total_fee'); 216 | } 217 | 218 | 219 | /** 220 | * @param $value 221 | * 222 | * @return $this 223 | */ 224 | public function setTotalFee($value) 225 | { 226 | return $this->setParameter('total_fee', $value); 227 | } 228 | 229 | 230 | /** 231 | * @return mixed 232 | */ 233 | public function getSellerId() 234 | { 235 | return $this->getParameter('seller_id'); 236 | } 237 | 238 | 239 | /** 240 | * @param $value 241 | * 242 | * @return $this 243 | */ 244 | public function setSellerId($value) 245 | { 246 | return $this->setParameter('seller_id', $value); 247 | } 248 | 249 | 250 | /** 251 | * @return mixed 252 | */ 253 | public function getPaymentType() 254 | { 255 | return $this->getParameter('payment_type'); 256 | } 257 | 258 | 259 | /** 260 | * @param $value 261 | * 262 | * @return $this 263 | */ 264 | public function setPaymentType($value) 265 | { 266 | return $this->setParameter('payment_type', $value); 267 | } 268 | 269 | 270 | /** 271 | * @return mixed 272 | */ 273 | public function getShowUrl() 274 | { 275 | return $this->getParameter('show_url'); 276 | } 277 | 278 | 279 | /** 280 | * @param $value 281 | * 282 | * @return $this 283 | */ 284 | public function setShowUrl($value) 285 | { 286 | return $this->setParameter('show_url', $value); 287 | } 288 | 289 | 290 | /** 291 | * @return mixed 292 | */ 293 | public function getBody() 294 | { 295 | return $this->getParameter('body'); 296 | } 297 | 298 | 299 | /** 300 | * @param $value 301 | * 302 | * @return $this 303 | */ 304 | public function setBody($value) 305 | { 306 | return $this->setParameter('body', $value); 307 | } 308 | 309 | 310 | /** 311 | * @return mixed 312 | */ 313 | public function getItBPay() 314 | { 315 | return $this->getParameter('it_b_pay'); 316 | } 317 | 318 | 319 | /** 320 | * @param $value 321 | * 322 | * @return $this 323 | */ 324 | public function setItBPay($value) 325 | { 326 | return $this->setParameter('it_b_pay', $value); 327 | } 328 | 329 | 330 | /** 331 | * @return mixed 332 | */ 333 | public function getExternToken() 334 | { 335 | return $this->getParameter('extern_token'); 336 | } 337 | 338 | 339 | /** 340 | * @param $value 341 | * 342 | * @return $this 343 | */ 344 | public function setExternToken($value) 345 | { 346 | return $this->setParameter('extern_token', $value); 347 | } 348 | 349 | 350 | /** 351 | * @return mixed 352 | */ 353 | public function getOtherfee() 354 | { 355 | return $this->getParameter('otherfee'); 356 | } 357 | 358 | 359 | /** 360 | * @param $value 361 | * 362 | * @return $this 363 | */ 364 | public function setOtherfee($value) 365 | { 366 | return $this->setParameter('otherfee', $value); 367 | } 368 | 369 | 370 | /** 371 | * @return mixed 372 | */ 373 | public function getAirticket() 374 | { 375 | return $this->getParameter('airticket'); 376 | } 377 | 378 | 379 | /** 380 | * @param $value 381 | * 382 | * @return $this 383 | */ 384 | public function setAirticket($value) 385 | { 386 | return $this->setParameter('airticket', $value); 387 | } 388 | 389 | 390 | /** 391 | * @return mixed 392 | */ 393 | public function getRnCheck() 394 | { 395 | return $this->getParameter('rn_check'); 396 | } 397 | 398 | 399 | /** 400 | * @param $value 401 | * 402 | * @return $this 403 | */ 404 | public function setRnCheck($value) 405 | { 406 | return $this->setParameter('rn_check', $value); 407 | } 408 | 409 | 410 | /** 411 | * @return mixed 412 | */ 413 | public function getBuyerCertNo() 414 | { 415 | return $this->getParameter('buyer_cert_no'); 416 | } 417 | 418 | 419 | /** 420 | * @param $value 421 | * 422 | * @return $this 423 | */ 424 | public function setBuyerCertNo($value) 425 | { 426 | return $this->setParameter('buyer_cert_no', $value); 427 | } 428 | 429 | 430 | /** 431 | * @return mixed 432 | */ 433 | public function getBuyerRealName() 434 | { 435 | return $this->getParameter('buyer_real_name'); 436 | } 437 | 438 | 439 | /** 440 | * @param $value 441 | * 442 | * @return $this 443 | */ 444 | public function setBuyerRealName($value) 445 | { 446 | return $this->setParameter('buyer_real_name', $value); 447 | } 448 | 449 | 450 | /** 451 | * @return mixed 452 | */ 453 | public function getScene() 454 | { 455 | return $this->getParameter('scene'); 456 | } 457 | 458 | 459 | /** 460 | * @param $value 461 | * 462 | * @return $this 463 | */ 464 | public function setScene($value) 465 | { 466 | return $this->setParameter('scene', $value); 467 | } 468 | 469 | 470 | /** 471 | * @return mixed 472 | */ 473 | public function getHbFqParam() 474 | { 475 | return $this->getParameter('hb_fq_param'); 476 | } 477 | 478 | 479 | /** 480 | * @param $value 481 | * 482 | * @return $this 483 | */ 484 | public function setHbFqParam($value) 485 | { 486 | return $this->setParameter('hb_fq_param', $value); 487 | } 488 | 489 | 490 | /** 491 | * @return mixed 492 | */ 493 | public function getGoodsType() 494 | { 495 | return $this->getParameter('goods_type'); 496 | } 497 | 498 | 499 | /** 500 | * @param $value 501 | * 502 | * @return $this 503 | */ 504 | public function setGoodsType($value) 505 | { 506 | return $this->setParameter('goods_type', $value); 507 | } 508 | 509 | 510 | /** 511 | * @return mixed 512 | */ 513 | public function getAppPay() 514 | { 515 | return $this->getParameter('app_pay'); 516 | } 517 | 518 | 519 | /** 520 | * @param $value 521 | * 522 | * @return $this 523 | */ 524 | public function setAppPay($value) 525 | { 526 | return $this->setParameter('app_pay', $value); 527 | } 528 | 529 | 530 | /** 531 | * @return mixed 532 | */ 533 | public function getPromoParams() 534 | { 535 | return $this->getParameter('promo_params'); 536 | } 537 | 538 | 539 | /** 540 | * @param $value 541 | * 542 | * @return $this 543 | */ 544 | public function setPromoParams($value) 545 | { 546 | return $this->setParameter('promo_params', $value); 547 | } 548 | } 549 | -------------------------------------------------------------------------------- /src/Responses/AbstractAopResponse.php: -------------------------------------------------------------------------------- 1 | getCode() == '10000'; 18 | } 19 | 20 | 21 | public function getCode() 22 | { 23 | return $this->getAlipayResponse('code'); 24 | } 25 | 26 | 27 | public function getAlipayResponse($key = null) 28 | { 29 | if ($key) { 30 | return array_get($this->data, "{$this->key}.{$key}"); 31 | } else { 32 | return array_get($this->data, $this->key); 33 | } 34 | } 35 | 36 | 37 | public function getMessage() 38 | { 39 | return $this->getAlipayResponse('msg'); 40 | } 41 | 42 | 43 | public function getSubCode() 44 | { 45 | return $this->getAlipayResponse('sub_code'); 46 | } 47 | 48 | 49 | public function getSubMessage() 50 | { 51 | return $this->getAlipayResponse('sub_msg'); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/Responses/AbstractLegacyResponse.php: -------------------------------------------------------------------------------- 1 | data; 13 | } else { 14 | return array_get($this->data, $key, $default); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Responses/AopCompletePurchaseResponse.php: -------------------------------------------------------------------------------- 1 | isSuccessful()) { 19 | return 'success'; 20 | } else { 21 | return 'fail'; 22 | } 23 | } 24 | 25 | 26 | /** 27 | * Is the response successful? 28 | * 29 | * @return boolean 30 | */ 31 | public function isSuccessful() 32 | { 33 | return true; 34 | } 35 | 36 | 37 | public function isPaid() 38 | { 39 | if (array_get($this->data, 'trade_status')) { 40 | if (array_get($this->data, 'trade_status') == 'TRADE_SUCCESS') { 41 | return true; 42 | } elseif (array_get($this->data, 'trade_status') == 'TRADE_FINISHED') { 43 | return true; 44 | } else { 45 | return false; 46 | } 47 | } elseif (array_get($this->data, 'code') == '10000') { 48 | return true; 49 | } else { 50 | return false; 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/Responses/AopCompleteRefundResponse.php: -------------------------------------------------------------------------------- 1 | isSuccessful()) { 28 | return 'success'; 29 | } else { 30 | return 'fail'; 31 | } 32 | } 33 | 34 | public function isRefunded() 35 | { 36 | $trade_status = array_get($this->data, 'trade_status'); 37 | if ($trade_status) { 38 | // 全额退款为 TRADE_CLOSED;非全额退款为 TRADE_SUCCESS 39 | if ($trade_status == 'TRADE_CLOSED' || $trade_status == 'TRADE_SUCCESS') { 40 | return true; 41 | } else { 42 | return false; 43 | } 44 | } elseif (array_get($this->data, 'code') == '10000') { 45 | return true; 46 | } 47 | return false; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/Responses/AopNotifyResponse.php: -------------------------------------------------------------------------------- 1 | isSuccessful()) { 19 | return 'success'; 20 | } else { 21 | return 'fail'; 22 | } 23 | } 24 | 25 | 26 | /** 27 | * Is the response successful? 28 | * 29 | * @return boolean 30 | */ 31 | public function isSuccessful() 32 | { 33 | return true; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Responses/AopTradeAppPayResponse.php: -------------------------------------------------------------------------------- 1 | data['order_string']; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Responses/AopTradeCancelResponse.php: -------------------------------------------------------------------------------- 1 | getAlipayResponse('trade_no'); 20 | } 21 | 22 | 23 | public function getOutTradeNo() 24 | { 25 | return $this->getAlipayResponse('out_trade_no'); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Responses/AopTradeOrderSettleResponse.php: -------------------------------------------------------------------------------- 1 | request->getEndpoint(), http_build_query($this->data)); 40 | } 41 | 42 | 43 | /** 44 | * Get the required redirect method (either GET or POST). 45 | */ 46 | public function getRedirectMethod() 47 | { 48 | return 'GET'; 49 | } 50 | 51 | 52 | /** 53 | * Gets the redirect form data array, if the redirect method is POST. 54 | */ 55 | public function getRedirectData() 56 | { 57 | return $this->getData(); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/Responses/AopTradePayResponse.php: -------------------------------------------------------------------------------- 1 | getCode() == '40004'; 20 | } 21 | 22 | 23 | public function isPaid() 24 | { 25 | return $this->getCode() == '10000'; 26 | } 27 | 28 | 29 | public function isWaitPay() 30 | { 31 | return $this->getCode() == '10003'; 32 | } 33 | 34 | 35 | public function isUnknownException() 36 | { 37 | return $this->getCode() == '20000'; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Responses/AopTradePreCreateResponse.php: -------------------------------------------------------------------------------- 1 | getAlipayResponse('qr_code'); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Responses/AopTradeQueryResponse.php: -------------------------------------------------------------------------------- 1 | getTradeStatus() == 'TRADE_SUCCESS') { 20 | return true; 21 | } elseif ($this->getTradeStatus() == 'TRADE_FINISHED') { 22 | return true; 23 | } else { 24 | return false; 25 | } 26 | } 27 | 28 | 29 | /** 30 | * @return mixed 31 | */ 32 | public function getTradeStatus() 33 | { 34 | return $this->getAlipayResponse('trade_status'); 35 | } 36 | 37 | 38 | public function isWaitPay() 39 | { 40 | return $this->getTradeStatus() == 'WAIT_BUYER_PAY'; 41 | } 42 | 43 | 44 | public function isClosed() 45 | { 46 | return $this->getTradeStatus() == 'TRADE_CLOSED'; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/Responses/AopTradeRefundQueryResponse.php: -------------------------------------------------------------------------------- 1 | request->getEndpoint(), http_build_query($this->data)); 40 | } 41 | 42 | 43 | /** 44 | * Get the required redirect method (either GET or POST). 45 | */ 46 | public function getRedirectMethod() 47 | { 48 | return 'GET'; 49 | } 50 | 51 | 52 | /** 53 | * Gets the redirect form data array, if the redirect method is POST. 54 | */ 55 | public function getRedirectData() 56 | { 57 | return $this->getData(); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/Responses/AopTransferToAccountQueryResponse.php: -------------------------------------------------------------------------------- 1 | data['order_string']; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Responses/LegacyCompletePurchaseResponse.php: -------------------------------------------------------------------------------- 1 | isSuccessful()) { 19 | return 'success'; 20 | } else { 21 | return 'fail'; 22 | } 23 | } 24 | 25 | 26 | /** 27 | * Is the response successful? 28 | * 29 | * @return boolean 30 | */ 31 | public function isSuccessful() 32 | { 33 | return true; 34 | } 35 | 36 | 37 | public function isPaid() 38 | { 39 | if (array_get($this->data, 'trade_status')) { 40 | if (array_get($this->data, 'trade_status') == 'TRADE_SUCCESS') { 41 | return true; 42 | } elseif (array_get($this->data, 'trade_status') == 'TRADE_FINISHED') { 43 | return true; 44 | } else { 45 | return false; 46 | } 47 | } elseif (array_get($this->data, 'code') == '10000') { 48 | return true; 49 | } else { 50 | return false; 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/Responses/LegacyCompleteRefundResponse.php: -------------------------------------------------------------------------------- 1 | isSuccessful()) { 19 | return 'success'; 20 | } else { 21 | return 'fail'; 22 | } 23 | } 24 | 25 | 26 | /** 27 | * Is the response successful? 28 | * 29 | * @return boolean 30 | */ 31 | public function isSuccessful() 32 | { 33 | return true; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Responses/LegacyExpressPurchaseResponse.php: -------------------------------------------------------------------------------- 1 | request->getEndpoint() . '?' . http_build_query($this->getRedirectData()); 37 | } 38 | 39 | 40 | /** 41 | * Gets the redirect form data array, if the redirect method is POST. 42 | */ 43 | public function getRedirectData() 44 | { 45 | return $this->data; 46 | } 47 | 48 | 49 | /** 50 | * Get the required redirect method (either GET or POST). 51 | */ 52 | public function getRedirectMethod() 53 | { 54 | return 'GET'; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/Responses/LegacyNotifyResponse.php: -------------------------------------------------------------------------------- 1 | isSuccessful()) { 19 | return 'success'; 20 | } else { 21 | return 'fail'; 22 | } 23 | } 24 | 25 | 26 | /** 27 | * Is the response successful? 28 | * 29 | * @return boolean 30 | */ 31 | public function isSuccessful() 32 | { 33 | return true; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Responses/LegacyQueryResponse.php: -------------------------------------------------------------------------------- 1 | data['is_success'] === 'T'; 16 | } 17 | 18 | /** 19 | * Is the trade paid? 20 | * 21 | * @return boolean 22 | */ 23 | public function isPaid() 24 | { 25 | $response = array_get($this->data, 'response'); 26 | if ($response) { 27 | $trade = array_get($response, 'trade'); 28 | if (array_get($trade, 'trade_status')) { 29 | if (array_get($trade, 'trade_status') == 'TRADE_SUCCESS') { 30 | return true; 31 | } elseif (array_get($trade, 'trade_status') == 'TRADE_FINISHED') { 32 | return true; 33 | } else { 34 | return false; 35 | } 36 | } else { 37 | return false; 38 | } 39 | } else { 40 | return false; 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Responses/LegacyRefundNoPwdResponse.php: -------------------------------------------------------------------------------- 1 | data['is_success'] === 'T'; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Responses/LegacyRefundResponse.php: -------------------------------------------------------------------------------- 1 | getRequest(); 34 | 35 | return $request->getEndpoint() . '?' . http_build_query($this->getRedirectData()); 36 | } 37 | 38 | 39 | /** 40 | * Gets the redirect form data array, if the redirect method is POST. 41 | */ 42 | public function getRedirectData() 43 | { 44 | return $this->data; 45 | } 46 | 47 | 48 | /** 49 | * Get the required redirect method (either GET or POST). 50 | */ 51 | public function getRedirectMethod() 52 | { 53 | return 'GET'; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/Responses/LegacyWapPurchaseResponse.php: -------------------------------------------------------------------------------- 1 | request->getEndpoint() . '?' . http_build_query($this->getRedirectData()); 37 | } 38 | 39 | 40 | /** 41 | * Gets the redirect form data array, if the redirect method is POST. 42 | */ 43 | public function getRedirectData() 44 | { 45 | return $this->data; 46 | } 47 | 48 | 49 | /** 50 | * Get the required redirect method (either GET or POST). 51 | */ 52 | public function getRedirectMethod() 53 | { 54 | return 'GET'; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/Responses/VerifyNotifyIdResponse.php: -------------------------------------------------------------------------------- 1 | data['result'] . '') === 'true'; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tests/AbstractGatewayTestCase.php: -------------------------------------------------------------------------------- 1 | gateway = new AopJsGateway($this->getHttpClient(), $this->getHttpRequest()); 23 | $this->gateway->setAppId($this->appId); 24 | $this->gateway->setPrivateKey(ALIPAY_AOP_PRIVATE_KEY); 25 | } 26 | 27 | 28 | public function testPurchase() 29 | { 30 | $this->setMockHttpResponse('AopJs_Purchase_Failure.txt'); 31 | 32 | /** 33 | * @var AopTradeCreateResponse $response 34 | */ 35 | $response = $this->gateway->purchase( 36 | [ 37 | 'biz_content' => [ 38 | 'subject' => 'test', 39 | 'out_trade_no' => date('YmdHis') . mt_rand(1000, 9999), 40 | 'total_amount' => '0.01', 41 | 'product_code' => '0.01', 42 | ] 43 | ] 44 | )->send(); 45 | 46 | $this->assertFalse($response->isSuccessful()); 47 | $this->assertArrayHasKey('code', $response->getAlipayResponse()); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /tests/AopWapGatewayTest.php: -------------------------------------------------------------------------------- 1 | gateway = new AopWapGateway($this->getHttpClient(), $this->getHttpRequest()); 26 | $this->gateway->setAppId($this->appId); 27 | $this->gateway->setPrivateKey($this->appPrivateKey); 28 | $this->gateway->setNotifyUrl('https://www.example.com/notify'); 29 | $this->gateway->setReturnUrl('https://www.example.com/return'); 30 | } 31 | 32 | 33 | public function testPurchase() 34 | { 35 | /** 36 | * @var AopTradeWapPayResponse $response 37 | */ 38 | $response = $this->gateway->purchase( 39 | [ 40 | 'biz_content' => [ 41 | 'out_trade_no' => date('YmdHis') . mt_rand(1000, 9999), 42 | 'total_amount' => 0.01, 43 | 'subject' => 'test', 44 | 'product_code' => 'QUICK_MSECURITY_PAY', 45 | ] 46 | ] 47 | )->send(); 48 | 49 | $this->assertTrue($response->isSuccessful()); 50 | $this->assertTrue($response->isRedirect()); 51 | $this->assertNotEmpty($response->getRedirectUrl()); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /tests/Assets/cacert.pem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lokielse/omnipay-alipay/9d64a9d23a10089deb992124c9362b428accd410/tests/Assets/cacert.pem -------------------------------------------------------------------------------- /tests/Assets/dist/aop/alipay_public_key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCnxj/9qwVfgoUh/y2W89L6BkRA 3 | FljhNhgPdyPuBV64bfQNN1PjbCzkIM6qRdKBoLPXmKKMiFYnkd6rAoprih3/PrQE 4 | B/VsW8OoM8fxn67UDYuyBTqA23MML9q1+ilIZwBC2AQ2UBVOrFXfFl75p6/B5Ksi 5 | NG9zpgmLCUYuLkxpLQIDAQAB 6 | -----END PUBLIC KEY----- -------------------------------------------------------------------------------- /tests/Assets/dist/aop/rsa_private_key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIICXwIBAAKBgQDjydSE0+XMEg4mtNbyplQNnWt+5lN5ADWExkx4+SPZ5z1woOsf 3 | eMjf2Y0rzhHWEoGP5IyMLeSFWEPR3X59tLIe50GDCzA9RRkrfR5Fc/a0NEKskSV7 4 | 44XOlCBvKp5NFZcNp4Ra+sdoY+C/+H67v4Wq0mRiq+n9pr6I98w4wwJoRQIDAQAB 5 | AoGBALNvJKpxZN6JBn61C3FfVmzXKXtwIib55C6wKkNNNlGLF1nmWPCUq9+xtsPf 6 | 8yrnrwnTZmdyK0ZjDiF+Ugrh0UCL+249L8WrpBlze15lnzzb6gTp+29HlT1RMVtK 7 | NlxCNGHqN0R4J9IH60yc+nHbYieriFvdu72byng5CyqJW2XtAkEA+xniufAXWEtC 8 | 3SLfCyFSkSUWHmlW60A8pYobZOQdri2BQnNRl8BlYjZoatK7zByhZZkVb2fG95gT 9 | OIUdLpshXwJBAOg7gpTFIo0LnG30BZpmH13Tiw2CKhUQrfjZQl0xFz8kswawZTt5 10 | aUTZ3qznADly6NtceD5wiJ3Nx+6ye8iUpNsCQQC8D/sbP5J8coG1lbRvZZmtU5Vp 11 | WYPb1dSWNwWlXqRMG5C/8BagDVzhXdZ+iy5UBO1sZmcDdToznhZnMmtUyKMJAkEA 12 | 1cgCm0UmW0T3Cdj7V3jvIwZcGWFbr+yc2lnV18gbKEt2ao/zgN5xY6pUbEJyWHBJ 13 | n7XuEzyw5uPKSxgPD0SWxQJBAPAVCnMjT0YfwZOxoPuXnzo9sY/VYGLAAH0hRVgZ 14 | xy4tthyp+XumufBCyQ/XuXZ+q1qiIJ4IiR0fgHhz1ZmtqSw= 15 | -----END RSA PRIVATE KEY----- -------------------------------------------------------------------------------- /tests/Assets/dist/cert/alipayCertPublicKey_RSA2.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDqDCCApCgAwIBAgIQICADBra3mwC1JWVfUFTzlzANBgkqhkiG9w0BAQsFADCBkTELMAkGA1UE 3 | BhMCQ04xGzAZBgNVBAoMEkFudCBGaW5hbmNpYWwgdGVzdDElMCMGA1UECwwcQ2VydGlmaWNhdGlv 4 | biBBdXRob3JpdHkgdGVzdDE+MDwGA1UEAww1QW50IEZpbmFuY2lhbCBDZXJ0aWZpY2F0aW9uIEF1 5 | dGhvcml0eSBDbGFzcyAyIFIxIHRlc3QwHhcNMjAwMzA2MTUyNzA5WhcNMjMwMzA1MTUyNzA5WjB6 6 | MQswCQYDVQQGEwJDTjEVMBMGA1UECgwM5rKZ566x546v5aKDMQ8wDQYDVQQLDAZBbGlwYXkxQzBB 7 | BgNVBAMMOuaUr+S7mOWunSjkuK3lm70p572R57uc5oqA5pyv5pyJ6ZmQ5YWs5Y+4LTIwODgxMDIx 8 | ODAyOTI1OTMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDAOgjVv2ZELU03L1fO6vv7 9 | CyN8dkTE5I51k6QcEOE8rEX5Xed4yNxCjU0iGzIDvgoJjnkzeJStI4C5asz1YWyDTvJl1svsz6GF 10 | lqBi9rkA2YdcY0vibuTKxMgYYrXC2PvOrBYARM8bBBmy4cnqodQgg77EA7PEQt0d+UtlS1VHRZ4w 11 | 0GZ/VzZcg1SfD6Yp4ovN7aXF2zWIFDB/K5bEnT22q6zJE6qdqKnc0PDljsJn4qmAB557LsnU8Pu8 12 | +vghkaV43amwhPBgPJsmB1NqfdmpR4OCFxKkuUJACLQPkIisDqXKqnsmFljS2QPvOSSDASlg/xZ3 13 | OJ3XNZmiWjPV6wdlAgMBAAGjEjAQMA4GA1UdDwEB/wQEAwIE8DANBgkqhkiG9w0BAQsFAAOCAQEA 14 | W7J0r2VDO1W/SmB8ttQf4AzRiWArPlnorBO9jjmo/LPU3ubwVOLe3SoMiBADkMG6SHarA0CH/imk 15 | Ek0WRr5ebcL2yGsNrEe/jXyhw9MMQ2nnMExp8M4D8XVOukYOUoe1wEO2qpfpkfDoSWgAYq63qRVC 16 | CukdNcr56DU2T3aUGqpydgHdevCQa6FaFFROFO3llh2wD8krELsUsT8lyFUzUHeV3A/06cQmlq30 17 | dsyEScrwgtn+GDGacCLZSU53nwolk4yz8Kw5/RMHfuMZ+Fe2wcq0p4hHTN8gkJHdZ50e18D1qLP9 18 | c9H9qTMANoA+yc5+cliQzZ7mKqRdw/LvQxO30g== 19 | -----END CERTIFICATE----- 20 | -----BEGIN CERTIFICATE----- 21 | MIIE4jCCAsqgAwIBAgIIddq/0OOwJzIwDQYJKoZIhvcNAQELBQAwejELMAkGA1UEBhMCQ04xFjAU 22 | BgNVBAoMDUFudCBGaW5hbmNpYWwxIDAeBgNVBAsMF0NlcnRpZmljYXRpb24gQXV0aG9yaXR5MTEw 23 | LwYDVQQDDChBbnQgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFIxMB4XDTE4MDMy 24 | MjE0MzAzMVoXDTM3MTEyNjE0MzAzMVowgYIxCzAJBgNVBAYTAkNOMRYwFAYDVQQKDA1BbnQgRmlu 25 | YW5jaWFsMSAwHgYDVQQLDBdDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTE5MDcGA1UEAwwwQW50IEZp 26 | bmFuY2lhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBDbGFzcyAxIFIxMIIBIjANBgkqhkiG9w0B 27 | AQEFAAOCAQ8AMIIBCgKCAQEA3OruCD7d4evJiEKxzJQYmwp5ziF7lT4fMpBb+WLme42Ulrkh4cJC 28 | DEOTUL29Yb8NyQ6cRe9UHLupI2HbByDZoSJl7nkxyi5NGJLaADC7wnFBJq39WMaVBzouFo0yQkkY 29 | NbbkJm+MsV4obu3l2xFGQx72bz6ThDJLpfYJbnGXqC4Bcyn8ubj1ddrJ0VsGdj/3Knmuo7XWLYqq 30 | N/qomK3LJIpfhVozi0b2FWQl+lE9urch+FVhXSg0AlRGn8FTOVNlKrY+hAKZGZhqC+J+BD4GL3hQ 31 | ZzVeNl0tMmSGz474lnt7DExNq33WfyJkn5UIoCfg8Tno7XTnocmBzbNYPq1aSQIDAQABo2MwYTAf 32 | BgNVHSMEGDAWgBRfdLQEwE8HWurlsdsio4dBspzhATAdBgNVHQ4EFgQUcQfiBGEW5OXyZesxD8ng 33 | 9Dya1ZEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQELBQADggIB 34 | AGkc6bDB4YQCa5D6IbgRtLfiqTQb5DeCp38uVKKrUl8ZCE5U+wXSu/fFhOkIs+Aq9tEOdPWgi7TA 35 | xPMMbfJRTAF20qK1qF/X6lwRYGSi7LBbEhmI7dYFKj7i7z6fupBMVaI4C4O8KJGfovp3qD/FkXyb 36 | 13Lo8vL85Ll0BFk89Qbim0qYhW2JRsf9G46vBeIZaoMm8iMv9vvlVgMs30R96W+gZBgvlIE4ah+o 37 | OEUd+G/V74vTbaXtWI8gkmwCzs/yUGW2g2ERHqZ3ksq4xwL+mNmqRNzq3aC9iA4p0uoHp/els89v 38 | WHCUaPjHmEnhx+M843/WVjN8LWpoeQ+wc7Wz1jfYy0e+JXidqWkPn7qorlEQTfzcFBZh+YHnV6oV 39 | tcG5iYatRKVTAPA+RrjJnEEzn6hAIPsiYsLmdA18f6ruuUUuKRukAEbCQ9q9L1gyOkaz2LxZj5kO 40 | FyemDa3pjqESuHuazztnOvs6u4YrH03CPyK3G/6MhCNEJTxGDYy+8bRtNsTGRUbdmhZm/u8tjYIr 41 | eNEy55f4WYlb72R6PODBLXmf4HWWPpyX1Zy9TEhmFsuPfelhBrdmBVM1iTwVFLW7gLqoEwzYhMt5 42 | KRPjmfCc2P2pcbpLnYNcbSYiykFsCa7jHG0137Jv8Z/QH2N9r4+xdER7SW40ndmD59ynmGvrWUMj 43 | -----END CERTIFICATE----- -------------------------------------------------------------------------------- /tests/Assets/dist/cert/alipayRootCert.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIICbTCCAhCgAwIBAgIQIBkEINPjNERrjd9hx1ZZIjAMBggqgRzPVQGDdQUAMIGE 3 | MQswCQYDVQQGEwJDTjEWMBQGA1UECgwNQW50IEZpbmFuY2lhbDElMCMGA1UECwwc 4 | Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgdGVzdDE2MDQGA1UEAwwtQW50IEZpbmFu 5 | Y2lhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBTMSB0ZXN0MB4XDTE5MDQxOTE5 6 | NDQ0MVoXDTM5MDQxNDE5NDQ0MVowgYQxCzAJBgNVBAYTAkNOMRYwFAYDVQQKDA1B 7 | bnQgRmluYW5jaWFsMSUwIwYDVQQLDBxDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSB0 8 | ZXN0MTYwNAYDVQQDDC1BbnQgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9y 9 | aXR5IFMxIHRlc3QwWTATBgcqhkjOPQIBBggqgRzPVQGCLQNCAAQttFDfX2FkiCmn 10 | nVncfD9BHp+RpOIimHw+OEjbmdHxBzEkyo4PVukRQjXlai5cnlDZkZi895lTs6NS 11 | iDalUOQio2AwXjAfBgNVHSMEGDAWgBQkX+t1ZzimuQ4wXp/iVx36380GuDAdBgNV 12 | HQ4EFgQUJF/rdWc4prkOMF6f4lcd+t/NBrgwDAYDVR0TBAUwAwEB/zAOBgNVHQ8B 13 | Af8EBAMCAQYwDAYIKoEcz1UBg3UFAANJADBGAiEA5qsICDDINhseAW8ynrCA5UYv 14 | GjeDP7kVF6DWM6CVi1QCIQD0bNAlXPFEG2vonwjMQ4MCChgz4ZutBTGU7SOVFxwf 15 | Pg== 16 | -----END CERTIFICATE----- 17 | 18 | -----BEGIN CERTIFICATE----- 19 | MIID9DCCAtygAwIBAgIQIBkEIlNpcBJZffwE5p9uBzANBgkqhkiG9w0BAQsFADCB 20 | hDELMAkGA1UEBhMCQ04xFjAUBgNVBAoMDUFudCBGaW5hbmNpYWwxJTAjBgNVBAsM 21 | HENlcnRpZmljYXRpb24gQXV0aG9yaXR5IHRlc3QxNjA0BgNVBAMMLUFudCBGaW5h 22 | bmNpYWwgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUjEgdGVzdDAeFw0xOTA0MjIw 23 | MzA3MjNaFw0yOTA0MTkwMzA3MjNaMIGEMQswCQYDVQQGEwJDTjEWMBQGA1UECgwN 24 | QW50IEZpbmFuY2lhbDElMCMGA1UECwwcQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg 25 | dGVzdDE2MDQGA1UEAwwtQW50IEZpbmFuY2lhbCBDZXJ0aWZpY2F0aW9uIEF1dGhv 26 | cml0eSBSMSB0ZXN0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxI/4 27 | d3bjLU2W3xPKI0Hwq1U9fUirj5XHIt6VgKLXeB127wuqLDFPhb4h5w0SQWXuEdIC 28 | MlvfD+9Sp7quzrtG9WgnAjyoYjzP5XDfqY96urf2hnzbKKWnNivbKKrmM9JTeN0f 29 | XihjAXPAZAqfP9MtAhB0QFI70n6pFFsWlX9lDK75n42XEubi0PbQ09XghWDd5HkO 30 | bX03YR03EUL7KGFSD18DaZwKmkkqMwh0jgiDG/buFRGOgxXRS84sC+SsC94wkrYm 31 | Dkoa5VyhbDng7u/KukEHWkKwXjjMkVsTIswQBmsa1iHsrR4QRYj2VEMMBCsgnxdC 32 | cDxeCnD0RSP4QUsc8wIDAQABo2AwXjAfBgNVHSMEGDAWgBTeufJUrK23wbIMgg0N 33 | AE4UaHXI4DAdBgNVHQ4EFgQU3rnyVKytt8GyDIINDQBOFGh1yOAwDAYDVR0TBAUw 34 | AwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQELBQADggEBABioNsaM6dkp 35 | easi1xWcW3Ca99eBb8Fr5aKXI22YpRG3mqO8XqBfk03gtFpQNQTJJFIMamNDE+ff 36 | 17DHk4LBeL0zVTKIRCKtBPEcV+Qq2gPuCl8wCyEj8uxUsrjVh2QkCYbNI/z9BimY 37 | gwu6uxUfGVXTjBqG42L7wCiScgCxnU5uO3lBJXUtFeVEuKRD4Clh5iT1BSTUjME4 38 | y+uWqzQFWkPSYeESvsrcf1vys0HVZ2xun83rfPefoame0V4aiZN8+ihy2sNw+oAm 39 | zNfHpsfMHOMtS3ROCjrxnng/WAeuZiFJcQMHhGyowD9Co9iAs1OdprrVx2grE9Xq 40 | 16t9mtiA0Q8= 41 | -----END CERTIFICATE----- 42 | 43 | -----BEGIN CERTIFICATE----- 44 | MIICYDCCAgSgAwIBAgIQIBkEJF9EFUQvCUO0atPBzDAMBggqhkjOPQQDAgUAMH8x 45 | CzAJBgNVBAYTAkNOMRYwFAYDVQQKDA1BbnQgRmluYW5jaWFsMSAwHgYDVQQLDBdD 46 | ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTE2MDQGA1UEAwwtQW50IEZpbmFuY2lhbCBD 47 | ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBFMSB0ZXN0MB4XDTE5MDQyNDAzMzIyM1oX 48 | DTI5MDQyMTAzMzIyM1owfzELMAkGA1UEBhMCQ04xFjAUBgNVBAoMDUFudCBGaW5h 49 | bmNpYWwxIDAeBgNVBAsMF0NlcnRpZmljYXRpb24gQXV0aG9yaXR5MTYwNAYDVQQD 50 | DC1BbnQgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEUxIHRlc3Qw 51 | WTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAS7f4oL6NONlSVi8NM5ZpWJS3K9iGXc 52 | WtSZgAgbzAX9SsVnjn9cnkZ6pForo4nBuZ6AlwOY741ejaVyrQet/T/Xo2AwXjAf 53 | BgNVHSMEGDAWgBSMAU4DTR4QZ60g8qDqc71e2s1H+DAdBgNVHQ4EFgQUjAFOA00e 54 | EGetIPKg6nO9XtrNR/gwDAYDVR0TBAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDAYI 55 | KoZIzj0EAwIFAANIADBFAiAo7BxEhi/IPnymbIrNTnmdwWlr3LY0mI1MWBBBxvst 56 | 7AIhAKJ+DTgkHPBjlqM1xvda14EP/cHn4IgjZWnzLKXKPcUP 57 | -----END CERTIFICATE----- -------------------------------------------------------------------------------- /tests/Assets/dist/cert/appCertPublicKey.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDjzCCAnegAwIBAgIQICADCEvwV98I644dDfTpfDANBgkqhkiG9w0BAQsFADCBkTELMAkGA1UE 3 | BhMCQ04xGzAZBgNVBAoMEkFudCBGaW5hbmNpYWwgdGVzdDElMCMGA1UECwwcQ2VydGlmaWNhdGlv 4 | biBBdXRob3JpdHkgdGVzdDE+MDwGA1UEAww1QW50IEZpbmFuY2lhbCBDZXJ0aWZpY2F0aW9uIEF1 5 | dGhvcml0eSBDbGFzcyAyIFIxIHRlc3QwHhcNMjAwMzA3MTkwNDQzWhcNMjMwMzA2MTkwNDQzWjBh 6 | MQswCQYDVQQGEwJDTjEVMBMGA1UECgwM5rKZ566x546v5aKDMQ8wDQYDVQQLDAZBbGlwYXkxKjAo 7 | BgNVBAMMITIwODgxMDIxODAyOTI1OTMtMjAxNjEwMTkwMDcyMzgyMTCCASIwDQYJKoZIhvcNAQEB 8 | BQADggEPADCCAQoCggEBANPPNDH9n7gq1ixju+NC6OqPmA+8tRpfFEsN7LiFZ+r1eZ+RXm6CTUjq 9 | RC1a/PUAlVolcFidiXTIJYVQeGuGQCTGWZl4n68rh5lr7+MZzoiuLprb+6Far6a3RPU4XFmT0B9s 10 | II5AG1CoxFtsHind7jiqv3Djt2mkhIyulEGp4cU4nueFtrea02MiywMy+3/EHUeAfdR+0N0hjE/v 11 | Dc1AprwD1RcGgsoGjtiZhmGHohIpfyweyX/2va9TI5dGoxsftTiqdHicUeSRNPXGlobT3A75gRgz 12 | VI1E8Xo2MeIN1MoosguppJHDUDwQfDU0zXRu02R8Nb7AaLnXIGZnokH1N2kCAwEAAaMSMBAwDgYD 13 | VR0PAQH/BAQDAgTwMA0GCSqGSIb3DQEBCwUAA4IBAQAGJom0By6Kz4GdEqf6VJROEfgB80IuKXWZ 14 | bpWNKlhCHEaDCrllFaW/zToMmqYlSacyf7itdMcuyrnUA1MYwTsErNapjc3zHKufbz+VOaxh2N24 15 | y/gIhq7ZESR2fMname2UpHaOuN2gUFIsj920aAUpnO8ci3rCJcnflbZmIDW9d7VS1PEWVC5JSeL0 16 | MT50l90uwkn1Xx8s+pG62/AsZ9c+H1dcaIU7QckjHSHT8Tff9/1z3brBVPl+uo/IeFm9g+5vZiSc 17 | kj3Hz8mpT+kJYNkhlzaGWWKcIToXptgU2l3p7vA+pIyLfaGSxF/v8ux61H+2p0/367EvDNYSKFHR 18 | tdti 19 | -----END CERTIFICATE----- -------------------------------------------------------------------------------- /tests/Assets/dist/cert/appPrivateKey: -------------------------------------------------------------------------------- 1 | MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDTzzQx/Z+4KtYsY7vjQujqj5gPvLUaXxRLDey4hWfq9XmfkV5ugk1I6kQtWvz1AJVaJXBYnYl0yCWFUHhrhkAkxlmZeJ+vK4eZa+/jGc6Iri6a2/uhWq+mt0T1OFxZk9AfbCCOQBtQqMRbbB4p3e44qr9w47dppISMrpRBqeHFOJ7nhba3mtNjIssDMvt/xB1HgH3UftDdIYxP7w3NQKa8A9UXBoLKBo7YmYZhh6ISKX8sHsl/9r2vUyOXRqMbH7U4qnR4nFHkkTT1xpaG09wO+YEYM1SNRPF6NjHiDdTKKLILqaSRw1A8EHw1NM10btNkfDW+wGi51yBmZ6JB9TdpAgMBAAECggEAVitHysapwdz7gNeaSpyf8T012cEl1HK16MrjcTYkzrvLHRWg20h7dJyJ3AHWQz5XhHMSv5pnn3EFgrT4KJZXZh6juQIPxM3qvong7/1Bvu1N3IZ+WmhwaVzJ2xFw0KiH1SDCJd0Cv8/JAoB7zQCSt88PTzf1GC9sFWe4vPYF+ZuPV+XdFL00BJqgsQZ6p3HZ9Tx2K+u52cxG45eLsNVvOhnioDlgJWskerBbcSf0BFp08zxRgenwpR53tLTeuStC31GZNNtEk4ioILDGqiSk7utf471n81gyP9l4C7WJn6P319ldunt08pNp9TVdJYxB0050micwDaTxdz/FxPAGGQKBgQD7IP4GVZWHul3j/gQ6C0kOea/ufZ9rmr9Ly+eedGQKVU/jpAwF60x+cbkFrPNPwn72muhN2lTTg5pny0wSrO2hJ1uferfB8bGX+jY60TkMzyF9zr9H950G5U+iDIh6CxKt2qKXPkFRZ7iwsBG1V/MkBTAdmdkIDFBa9XvbelO1AwKBgQDX6vdnnZY3TjgXSBhZM2Be8sbx2VJx8CdeL6odDpxbHT1HU1TRG4gPO2lm+kFGYgoJ2OMEn1HjkujoKhutHrGgcEiCUSKEja3cTWtNTEzVZg43VidL2jrOhmyLccNyAnSPOcDjFIw8fbt5ejKbakMx3P/vRggZIygbc3t8EmkoIwKBgQCZRU6lEREdcNqjL0LnJkIlipGdDqEBLMZ6fW3VIRZ51A3ZUyNfbXgXaFNTqnYqBPw2iN8lvQ6utZDErqi0cUTrabkbAewre9c3eaglh9K5BaZcQZYvV2pIbiaHMf0N97ojz+ASTRXSmGp5tExqkM49+sieGGsE5XcZvOAmWWfDfwKBgQCJj//UGgiMb984pgwtOJhbpd2uVEE8qj7KuR9up9JiEnzqJmNRXnMPEVET9LkFuIygvXfViBPKI90TnVBIudd9Wkw4Cq0tOn7cbs7ATq5c/0prYw5iO0VgMzCQnwhgaMQORENp6bt3Brwcpwf7EHaDHERLE5kxOr7gznCMGca5dQKBgQC41+0jl8I5PGJ1yU1pqNhZ15yDfoy51w6mgpiGnD+DwlFhJaASe1Cxju01L8mSUpynS5FEhEuBUDm67D85wLPaaJ17zAFhmC/2txB7nlGTAWDVpMNHevdYLQ+BYTbhsi08i4p61FeiBVCH0sjDn/MdLB3o4xgM7AAEc/c7PNK6Fg== -------------------------------------------------------------------------------- /tests/Assets/dist/common/rsa_private_key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIICXAIBAAKBgQCelrbv6Cdy3ZqGZhub5P6c3sS9DtoOsHOw+wqDqoSqQBx2dufD 3 | eyUvwq/SKg+6SWY086Ml2phl09Fh8p+1KqxxBiO4U327EsbuMMyYr6zUIk2MQTfZ 4 | wAw0t9m8ZZOJDiEN0Gpc3IqFIrLM2z+o2odq6oTCmmLf/3AVdxlHzKeWkwIDAQAB 5 | AoGAc69frWv9cuZCta3AkB0gutAqVfuCh9qh2kWWqut1sTfpS2V7tXacbtWnKjky 6 | leK7Iv9jUNa/+u/kOn4hkKebeAUyxJhK027FWNeh2Kqg4g/Q8eIPzDGOsBWDAfxb 7 | sZs0E3bq7omh1DOoM3oXwncY2k/m2iUFnLRW6xPKRQnEC2kCQQDQHO3PKexgEY3A 8 | YJpz4mb3RM5bYVE7aOfDbd7+vBiyaj0Jv5kAsnEz8jFMTq5QPwBWAB/EWRsFcNt8 9 | 95M6+n+XAkEAwxSERt4KEzGRnOwk5KSJfdja1z9q6h5aGZKp3VMzYgo4JXkJkLwZ 10 | fmT611v3Q4Whhboi4zvdm/OWjxNKfS7AZQJBAIMU5ZjpwA/WnqFAd6hsPwyaExwt 11 | lNvFvM00ZBOw6CFglyePvdBZlMHyV6jHmjXDKPQCSgADW+i2aBkzW1H3u+sCQHw+ 12 | uPCZwjjvPRqAnA6zbI4ma1rkHSf3JNNcwasgrn0mnRPgvuLbqjECB3DaNeVfWrxd 13 | DJNFMaN9xMpjMvH/sLECQAe2k13ZauYzS9ASw3skG6xM68ZRp5vUY0K/WBZuGL9e 14 | e5tTs9ubShd3IGvxSnptXhVAEqKr/qqSDp5Z67keW6M= 15 | -----END RSA PRIVATE KEY----- 16 | -------------------------------------------------------------------------------- /tests/Assets/dist/common/rsa_private_key_inline.pem: -------------------------------------------------------------------------------- 1 | MIICXAIBAAKBgQCelrbv6Cdy3ZqGZhub5P6c3sS9DtoOsHOw+wqDqoSqQBx2dufDeyUvwq/SKg+6SWY086Ml2phl09Fh8p+1KqxxBiO4U327EsbuMMyYr6zUIk2MQTfZwAw0t9m8ZZOJDiEN0Gpc3IqFIrLM2z+o2odq6oTCmmLf/3AVdxlHzKeWkwIDAQABAoGAc69frWv9cuZCta3AkB0gutAqVfuCh9qh2kWWqut1sTfpS2V7tXacbtWnKjkyleK7Iv9jUNa/+u/kOn4hkKebeAUyxJhK027FWNeh2Kqg4g/Q8eIPzDGOsBWDAfxbsZs0E3bq7omh1DOoM3oXwncY2k/m2iUFnLRW6xPKRQnEC2kCQQDQHO3PKexgEY3AYJpz4mb3RM5bYVE7aOfDbd7+vBiyaj0Jv5kAsnEz8jFMTq5QPwBWAB/EWRsFcNt895M6+n+XAkEAwxSERt4KEzGRnOwk5KSJfdja1z9q6h5aGZKp3VMzYgo4JXkJkLwZfmT611v3Q4Whhboi4zvdm/OWjxNKfS7AZQJBAIMU5ZjpwA/WnqFAd6hsPwyaExwtlNvFvM00ZBOw6CFglyePvdBZlMHyV6jHmjXDKPQCSgADW+i2aBkzW1H3u+sCQHw+uPCZwjjvPRqAnA6zbI4ma1rkHSf3JNNcwasgrn0mnRPgvuLbqjECB3DaNeVfWrxdDJNFMaN9xMpjMvH/sLECQAe2k13ZauYzS9ASw3skG6xM68ZRp5vUY0K/WBZuGL9ee5tTs9ubShd3IGvxSnptXhVAEqKr/qqSDp5Z67keW6M= -------------------------------------------------------------------------------- /tests/Assets/dist/common/rsa_private_key_pkcs8.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAJ6Wtu/oJ3LdmoZm 3 | G5vk/pzexL0O2g6wc7D7CoOqhKpAHHZ258N7JS/Cr9IqD7pJZjTzoyXamGXT0WHy 4 | n7UqrHEGI7hTfbsSxu4wzJivrNQiTYxBN9nADDS32bxlk4kOIQ3QalzcioUisszb 5 | P6jah2rqhMKaYt//cBV3GUfMp5aTAgMBAAECgYBzr1+ta/1y5kK1rcCQHSC60CpV 6 | +4KH2qHaRZaq63WxN+lLZXu1dpxu1acqOTKV4rsi/2NQ1r/67+Q6fiGQp5t4BTLE 7 | mErTbsVY16HYqqDiD9Dx4g/MMY6wFYMB/FuxmzQTduruiaHUM6gzehfCdxjaT+ba 8 | JQWctFbrE8pFCcQLaQJBANAc7c8p7GARjcBgmnPiZvdEzlthUTto58Nt3v68GLJq 9 | PQm/mQCycTPyMUxOrlA/AFYAH8RZGwVw23z3kzr6f5cCQQDDFIRG3goTMZGc7CTk 10 | pIl92NrXP2rqHloZkqndUzNiCjgleQmQvBl+ZPrXW/dDhaGFuiLjO92b85aPE0p9 11 | LsBlAkEAgxTlmOnAD9aeoUB3qGw/DJoTHC2U28W8zTRkE7DoIWCXJ4+90FmUwfJX 12 | qMeaNcMo9AJKAANb6LZoGTNbUfe76wJAfD648JnCOO89GoCcDrNsjiZrWuQdJ/ck 13 | 01zBqyCufSadE+C+4tuqMQIHcNo15V9avF0Mk0Uxo33EymMy8f+wsQJAB7aTXdlq 14 | 5jNL0BLDeyQbrEzrxlGnm9RjQr9YFm4Yv157m1Oz25tKF3cga/FKem1eFUASoqv+ 15 | qpIOnlnruR5bow== 16 | -----END PRIVATE KEY----- 17 | -------------------------------------------------------------------------------- /tests/Assets/dist/common/rsa_public_key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCelrbv6Cdy3ZqGZhub5P6c3sS9 3 | DtoOsHOw+wqDqoSqQBx2dufDeyUvwq/SKg+6SWY086Ml2phl09Fh8p+1KqxxBiO4 4 | U327EsbuMMyYr6zUIk2MQTfZwAw0t9m8ZZOJDiEN0Gpc3IqFIrLM2z+o2odq6oTC 5 | mmLf/3AVdxlHzKeWkwIDAQAB 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /tests/Assets/dist/common/rsa_public_key_inline.pem: -------------------------------------------------------------------------------- 1 | MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCelrbv6Cdy3ZqGZhub5P6c3sS9DtoOsHOw+wqDqoSqQBx2dufDeyUvwq/SKg+6SWY086Ml2phl09Fh8p+1KqxxBiO4U327EsbuMMyYr6zUIk2MQTfZwAw0t9m8ZZOJDiEN0Gpc3IqFIrLM2z+o2odq6oTCmmLf/3AVdxlHzKeWkwIDAQAB 2 | -------------------------------------------------------------------------------- /tests/Assets/dist/legacy/alipay_public_key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCnxj/9qwVfgoUh/y2W89L6BkRA 3 | FljhNhgPdyPuBV64bfQNN1PjbCzkIM6qRdKBoLPXmKKMiFYnkd6rAoprih3/PrQE 4 | B/VsW8OoM8fxn67UDYuyBTqA23MML9q1+ilIZwBC2AQ2UBVOrFXfFl75p6/B5Ksi 5 | NG9zpgmLCUYuLkxpLQIDAQAB 6 | -----END PUBLIC KEY----- -------------------------------------------------------------------------------- /tests/Assets/dist/legacy/rsa_private_key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIICXwIBAAKBgQDjydSE0+XMEg4mtNbyplQNnWt+5lN5ADWExkx4+SPZ5z1woOsf 3 | eMjf2Y0rzhHWEoGP5IyMLeSFWEPR3X59tLIe50GDCzA9RRkrfR5Fc/a0NEKskSV7 4 | 44XOlCBvKp5NFZcNp4Ra+sdoY+C/+H67v4Wq0mRiq+n9pr6I98w4wwJoRQIDAQAB 5 | AoGBALNvJKpxZN6JBn61C3FfVmzXKXtwIib55C6wKkNNNlGLF1nmWPCUq9+xtsPf 6 | 8yrnrwnTZmdyK0ZjDiF+Ugrh0UCL+249L8WrpBlze15lnzzb6gTp+29HlT1RMVtK 7 | NlxCNGHqN0R4J9IH60yc+nHbYieriFvdu72byng5CyqJW2XtAkEA+xniufAXWEtC 8 | 3SLfCyFSkSUWHmlW60A8pYobZOQdri2BQnNRl8BlYjZoatK7zByhZZkVb2fG95gT 9 | OIUdLpshXwJBAOg7gpTFIo0LnG30BZpmH13Tiw2CKhUQrfjZQl0xFz8kswawZTt5 10 | aUTZ3qznADly6NtceD5wiJ3Nx+6ye8iUpNsCQQC8D/sbP5J8coG1lbRvZZmtU5Vp 11 | WYPb1dSWNwWlXqRMG5C/8BagDVzhXdZ+iy5UBO1sZmcDdToznhZnMmtUyKMJAkEA 12 | 1cgCm0UmW0T3Cdj7V3jvIwZcGWFbr+yc2lnV18gbKEt2ao/zgN5xY6pUbEJyWHBJ 13 | n7XuEzyw5uPKSxgPD0SWxQJBAPAVCnMjT0YfwZOxoPuXnzo9sY/VYGLAAH0hRVgZ 14 | xy4tthyp+XumufBCyQ/XuXZ+q1qiIJ4IiR0fgHhz1ZmtqSw= 15 | -----END RSA PRIVATE KEY----- -------------------------------------------------------------------------------- /tests/Common/SignerTest.php: -------------------------------------------------------------------------------- 1 | params); 20 | $sign = $signer->signWithMD5($this->key); 21 | $this->assertEquals('7e63e20bcc6ad2ba695305e340592ffd', $sign); 22 | } 23 | 24 | 25 | public function testSignWithRSA() 26 | { 27 | $this->assertFileExists($this->privateKey); 28 | 29 | $signer = new Signer($this->params); 30 | $sign = $signer->signWithRSA($this->privateKey); 31 | $this->assertEquals( 32 | 'Uwz+4a4mKJBNDsGpC+nIZnHYsA30NpoxycIjvlAKC9sLS2t3a/5H7p7EEwSOAQQV2sAu54oIH7wZ4hXXkzYoqRO1T+51hYF+r+uEb9rGYyJzbg3xzV8WFUjypGgxNd8HCAKV9qhkEGdfZ94/VCxYkS+1qxkgqD0MzzHVR20C0NI=', 33 | $sign 34 | ); 35 | } 36 | 37 | 38 | public function testSort() 39 | { 40 | $params1 = [ 41 | 'aaa' => '111', 42 | 'bbb' => '2222', 43 | 'ccc' => '3333', 44 | ]; 45 | 46 | $params2 = [ 47 | 'bbb' => '2222', 48 | 'ccc' => '3333', 49 | 'aaa' => '111', 50 | ]; 51 | 52 | $signer = new Signer($params1); 53 | $sign1 = $signer->signWithMD5($this->key); 54 | 55 | $signer = new Signer($params2); 56 | $sign2 = $signer->signWithMD5($this->key); 57 | 58 | $this->assertEquals($sign1, $sign2); 59 | } 60 | 61 | 62 | public function testIgnore() 63 | { 64 | $this->assertSame(['sign', 'sign_type'], (new Signer())->getIgnores()); 65 | 66 | $params1 = [ 67 | 'aaa' => '111', 68 | 'bbb' => '2222', 69 | 'ccc' => '3333', 70 | 'apple' => 'jobs', 71 | ]; 72 | 73 | $params2 = [ 74 | 'bbb' => '2222', 75 | 'ccc' => '3333', 76 | 'aaa' => '111', 77 | ]; 78 | 79 | $signer = new Signer($params1); 80 | $signer->setIgnores(['apple']); 81 | $sign1 = $signer->signWithMD5($this->key); 82 | 83 | $signer = new Signer($params2); 84 | $signer->setIgnores(['apple']); 85 | $sign2 = $signer->signWithMD5($this->key); 86 | $this->assertEquals($sign1, $sign2); 87 | 88 | $signer = new Signer($params1); 89 | $signer->setIgnores([]); 90 | $sign3 = $signer->signWithMD5($this->key); 91 | 92 | $this->assertNotEquals($sign1, $sign3); 93 | } 94 | 95 | 96 | public function testGetParamsToSign() 97 | { 98 | $params1 = [ 99 | 'bbb' => '2222', 100 | 'ccc' => '3333', 101 | 'aaa' => '111', 102 | 'apple' => 'jobs', 103 | ]; 104 | 105 | $signer = new Signer($params1); 106 | $signer->setIgnores(['apple']); 107 | $params = $signer->getParamsToSign(); 108 | 109 | $this->assertSame( 110 | [ 111 | 'aaa' => '111', 112 | 'bbb' => '2222', 113 | 'ccc' => '3333', 114 | ], 115 | $params 116 | ); 117 | } 118 | 119 | 120 | public function testGetContentToSign() 121 | { 122 | $params1 = [ 123 | 'bbb' => '2222', 124 | 'ccc' => '3333', 125 | 'aaa' => '111', 126 | 's' => '"."', 127 | 'e' => '', 128 | 'apple' => 'jobs', 129 | ]; 130 | 131 | $signer = new Signer($params1); 132 | $signer->setIgnores(['apple']); 133 | $content = $signer->getContentToSign(); 134 | 135 | $this->assertEquals('aaa=111&bbb=2222&ccc=3333&s="."', $content); 136 | } 137 | 138 | 139 | public function testConvert() 140 | { 141 | $key = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCnxj/9qwVfgoUh/y2W89L6BkRAFljhNhgPdyPuBV64bfQNN1PjbCzkIM6qRdKBoLPXmKKMiFYnkd6rAoprih3/PrQEB/VsW8OoM8fxn67UDYuyBTqA23MML9q1+ilIZwBC2AQ2UBVOrFXfFl75p6/B5KsiNG9zpgmLCUYuLkxpLQIDAQAB'; 142 | 143 | $signer = new Signer(); 144 | $key = $signer->convertKey($key, Signer::KEY_TYPE_PUBLIC); 145 | 146 | $this->assertEquals( 147 | '-----BEGIN PUBLIC KEY----- 148 | MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCnxj/9qwVfgoUh/y2W89L6BkRA 149 | FljhNhgPdyPuBV64bfQNN1PjbCzkIM6qRdKBoLPXmKKMiFYnkd6rAoprih3/PrQE 150 | B/VsW8OoM8fxn67UDYuyBTqA23MML9q1+ilIZwBC2AQ2UBVOrFXfFl75p6/B5Ksi 151 | NG9zpgmLCUYuLkxpLQIDAQAB 152 | -----END PUBLIC KEY-----', 153 | $key 154 | ); 155 | } 156 | 157 | 158 | protected function setUp() 159 | { 160 | parent::setUp(); 161 | 162 | $this->params = [ 163 | 'aaa' => '111', 164 | 'bbb' => '2222', 165 | 'ccc' => '3333', 166 | 'dd' => '', 167 | 'eee' => null, 168 | 'fff' => false, 169 | 'ggg' => true, 170 | ]; 171 | 172 | $this->key = 'hello'; 173 | 174 | $this->privateKey = ALIPAY_ASSET_DIR . '/dist/aop/rsa_private_key.pem'; 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /tests/LegacyAppGatewayTest.php: -------------------------------------------------------------------------------- 1 | gateway = new LegacyAppGateway($this->getHttpClient(), $this->getHttpRequest()); 26 | } 27 | 28 | 29 | public function testCreateOrder() 30 | { 31 | $partner = '123456789'; 32 | $privateKey = ALIPAY_ASSET_DIR . '/dist/common/rsa_private_key.pem'; 33 | 34 | //$partner = ALIPAY_PARTNER; 35 | //$privateKey = ALIPAY_ASSET_DIR . '/dist/common/rsa_private_key.pem'; 36 | 37 | $this->assertFileExists($privateKey); 38 | 39 | $this->gateway = new LegacyAppGateway($this->getHttpClient(), $this->getHttpRequest()); 40 | $this->gateway->setPartner($partner); 41 | $this->gateway->setSellerId($partner); 42 | $this->gateway->setPrivateKey($privateKey); 43 | $this->gateway->setNotifyUrl('https://www.example.com/notify'); 44 | 45 | $this->options = [ 46 | 'out_trade_no' => '2014010122390001', 47 | //'out_trade_no' => date('YmdHis').mt_rand(1000,9999), 48 | 'subject' => 'test', 49 | 'total_fee' => '0.01', 50 | ]; 51 | 52 | /** 53 | * @var LegacyAppPurchaseResponse $response 54 | */ 55 | $response = $this->gateway->purchase($this->options)->send(); 56 | $this->assertEquals('e16fdd8098c197201986cd9c3a8fb276', md5($response->getOrderString())); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /tests/LegacyExpressGatewayTest.php: -------------------------------------------------------------------------------- 1 | gateway = new LegacyExpressGateway($this->getHttpClient(), $this->getHttpRequest()); 26 | $this->gateway->setPartner($this->partner); 27 | $this->gateway->setKey($this->key); 28 | $this->gateway->setSellerId($this->sellerId); 29 | $this->gateway->setNotifyUrl('https://www.example.com/notify'); 30 | $this->gateway->setReturnUrl('https://www.example.com/return'); 31 | $this->options = [ 32 | 'out_trade_no' => '2014010122390001', 33 | 'subject' => 'test', 34 | 'total_fee' => '0.01', 35 | ]; 36 | } 37 | 38 | 39 | public function testPurchase() 40 | { 41 | /** 42 | * @var LegacyExpressPurchaseResponse $response 43 | */ 44 | $response = $this->gateway->purchase($this->options)->send(); 45 | $this->assertTrue($response->isSuccessful()); 46 | $this->assertTrue($response->isRedirect()); 47 | $this->assertNotEmpty($response->getRedirectUrl()); 48 | } 49 | 50 | 51 | public function testRefund() 52 | { 53 | /** 54 | * @var LegacyRefundResponse $response 55 | */ 56 | $response = $this->gateway->refund( 57 | [ 58 | 'refund_items' => [ 59 | [ 60 | 'out_trade_no' => '2016092021001003280286716852', 61 | 'amount' => '1', 62 | 'reason' => 'test', 63 | ] 64 | ] 65 | ] 66 | )->send(); 67 | 68 | $this->assertTrue($response->isSuccessful()); 69 | $this->assertTrue($response->isRedirect()); 70 | $this->assertNotEmpty($response->getRedirectUrl()); 71 | } 72 | 73 | 74 | public function testQuery() 75 | { 76 | $this->setMockHttpResponse('LegacyExpress_Query_Failure.txt'); 77 | 78 | /** 79 | * @var LegacyQueryResponse $response 80 | */ 81 | $response = $this->gateway->query( 82 | [ 83 | 'out_trade_no' => '2016092021001003280286716850' 84 | ] 85 | )->send(); 86 | 87 | $this->assertFalse($response->isSuccessful()); 88 | } 89 | 90 | 91 | public function testCompletePurchaseWithMD5() 92 | { 93 | $str = 'buyer_email=aaa%40qq.com&buyer_id=2088202561123456&exterface=create_direct_pay_by_user&is_success=T¬ify_id=RqPnCoPT3K9%252Fvwbh3InWes5p8ZRYIdWn4DYfTZV%252FByZc5wcE2q9pffj29yQCHA%252BTNHUY¬ify_time=2016-09-24+21%3A03%3A57¬ify_type=trade_status_sync&out_trade_no=2016-09-24+15%3A03%3A078138&payment_type=1&seller_email=test%40qq.com&seller_id=20880114664123456&subject=test&total_fee=0.01&trade_no=201609242100100406123456789&trade_status=TRADE_SUCCESS&sign=ea00ba288bf6e1cd4a6e89c5f180df7d&sign_type=MD5'; 94 | 95 | parse_str($str, $data); 96 | 97 | $data['sign'] = (new Signer($data))->signWithMD5($this->key); 98 | $data['sign_type'] = 'MD5'; 99 | 100 | $this->gateway = new LegacyExpressGateway($this->getHttpClient(), $this->getHttpRequest()); 101 | $this->gateway->setPartner($this->partner); 102 | $this->gateway->setKey($this->key); 103 | $this->gateway->setSignType('RSA'); 104 | $this->gateway->setPrivateKey(ALIPAY_LEGACY_PRIVATE_KEY); 105 | $this->gateway->setSellerId($this->sellerId); 106 | $this->gateway->setNotifyUrl('https://www.example.com/notify'); 107 | $this->gateway->setReturnUrl('https://www.example.com/return'); 108 | 109 | /** 110 | * @var LegacyExpressPurchaseResponse $response 111 | */ 112 | $request = $this->gateway->completePurchase(['params' => $data]); 113 | $request->setVerifyNotifyId(false); 114 | $response = $request->send(); 115 | $this->assertTrue($response->isSuccessful()); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /tests/LegacyWapGatewayTest.php: -------------------------------------------------------------------------------- 1 | gateway = new LegacyWapGateway($this->getHttpClient(), $this->getHttpRequest()); 26 | $this->gateway->setPartner($this->partner); 27 | $this->gateway->setKey($this->key); 28 | $this->gateway->setSellerId($this->sellerId); 29 | $this->gateway->setNotifyUrl('https://www.example.com/notify'); 30 | $this->gateway->setReturnUrl('https://www.example.com/return'); 31 | $this->options = [ 32 | 'out_trade_no' => '2014010122390001', 33 | 'subject' => 'test', 34 | 'total_fee' => '0.01', 35 | 'show_url' => 'https://www.example.com/item/123456', 36 | ]; 37 | } 38 | 39 | 40 | public function testPurchase() 41 | { 42 | /** 43 | * @var LegacyWapPurchaseResponse $response 44 | */ 45 | $response = $this->gateway->purchase($this->options)->send(); 46 | 47 | $this->assertTrue($response->isRedirect()); 48 | $this->assertTrue($response->isSuccessful()); 49 | $this->assertNotEmpty($response->getRedirectUrl()); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /tests/Mock/AopF2F_Capture_Failure.txt: -------------------------------------------------------------------------------- 1 | HTTP/1.1 200 OK 2 | Content-Type: application/json 3 | 4 | {"alipay_trade_pay_response":{"code":"40002","msg":"Invalid Arguments","sub_code":"isv.invalid-app-id","sub_msg":"无效的AppID参数"}} -------------------------------------------------------------------------------- /tests/Mock/AopF2F_Purchase_Failure.txt: -------------------------------------------------------------------------------- 1 | HTTP/1.1 200 OK 2 | Content-Type: application/json 3 | 4 | {"alipay_trade_precreate_response":{"code":"40002","msg":"Invalid Arguments","sub_code":"isv.invalid-app-id","sub_msg":"无效的AppID参数"}} -------------------------------------------------------------------------------- /tests/Mock/AopF2F_QueryBillDownloadUrl_Failure.txt: -------------------------------------------------------------------------------- 1 | HTTP/1.1 200 OK 2 | Content-Type: application/json 3 | 4 | {"alipay_data_dataservice_bill_downloadurl_query_response":{"code":"40002","msg":"Invalid Arguments","sub_code":"isv.invalid-app-id","sub_msg":"无效的AppID参数"}} -------------------------------------------------------------------------------- /tests/Mock/AopF2F_QueryRefund_Failure.txt: -------------------------------------------------------------------------------- 1 | HTTP/1.1 200 OK 2 | Content-Type: application/json 3 | 4 | {"alipay_trade_fastpay_refund_query_response":{"code":"40002","msg":"Invalid Arguments","sub_code":"isv.invalid-app-id","sub_msg":"无效的AppID参数"}} -------------------------------------------------------------------------------- /tests/Mock/AopF2F_Query_Failure.txt: -------------------------------------------------------------------------------- 1 | HTTP/1.1 200 OK 2 | Content-Type: application/json 3 | 4 | {"alipay_trade_query_response":{"code":"40002","msg":"Invalid Arguments","sub_code":"isv.invalid-app-id","sub_msg":"无效的AppID参数"}} -------------------------------------------------------------------------------- /tests/Mock/AopF2F_Refund_Failure.txt: -------------------------------------------------------------------------------- 1 | HTTP/1.1 200 OK 2 | Content-Type: application/json 3 | 4 | {"alipay_trade_refund_response":{"code":"40002","msg":"Invalid Arguments","sub_code":"isv.invalid-app-id","sub_msg":"无效的AppID参数"}} -------------------------------------------------------------------------------- /tests/Mock/AopF2F_Settle_Failure.txt: -------------------------------------------------------------------------------- 1 | HTTP/1.1 200 OK 2 | Content-Type: application/json 3 | 4 | {"alipay_trade_order_settle_response":{"code":"40002","msg":"Invalid Arguments","sub_code":"isv.invalid-app-id","sub_msg":"无效的AppID参数"}} -------------------------------------------------------------------------------- /tests/Mock/AopJs_Purchase_Failure.txt: -------------------------------------------------------------------------------- 1 | HTTP/1.1 200 OK 2 | Content-Type: application/json 3 | 4 | {"alipay_trade_create_response":{"code":"40002","msg":"Invalid Arguments","sub_code":"isv.invalid-app-id","sub_msg":"无效的AppID参数"}} -------------------------------------------------------------------------------- /tests/Mock/LegacyExpress_Query_Failure.txt: -------------------------------------------------------------------------------- 1 | HTTP/1.1 200 OK 2 | Content-Type: application/json 3 | 4 | 5 | FILLEGAL_PARTNER -------------------------------------------------------------------------------- /tests/bootstrap.php: -------------------------------------------------------------------------------- 1 | add('Omnipay', __DIR__); 10 | 11 | define('ALIPAY_ASSET_DIR', realpath(__DIR__ . '/Assets')); 12 | 13 | $configFile = realpath(__DIR__ . '/../config.php'); 14 | 15 | if (file_exists($configFile) && false) { 16 | include_once $configFile; 17 | } else { 18 | define('ALIPAY_PARTNER', '2088011436420182'); 19 | define('ALIPAY_KEY', '18x8lAi0a1520st1hvxcnt7m4w1whkbs'); 20 | define('ALIPAY_SELLER_ID', '2088011436420182'); 21 | define('ALIPAY_PUBLIC_KEY', ALIPAY_ASSET_DIR . '/dist/aop/alipay_public_key.pem'); 22 | define('ALIPAY_LEGACY_PRIVATE_KEY', ALIPAY_ASSET_DIR . '/dist/legacy/rsa_private_key.pem'); 23 | define('ALIPAY_LEGACY_PUBLIC_KEY', ALIPAY_ASSET_DIR . '/dist/legacy/alipay_public_key.pem'); 24 | define('ALIPAY_AOP_PUBLIC_KEY', ALIPAY_ASSET_DIR . '/dist/aop/alipay_public_key.pem'); 25 | define('ALIPAY_AOP_PRIVATE_KEY', ALIPAY_ASSET_DIR . '/dist/aop/rsa_private_key.pem'); 26 | 27 | define('ALIPAY_APP_ID', '2088011436421111'); 28 | define('ALIPAY_APP_PRIVATE_KEY', ALIPAY_ASSET_DIR . '/dist/aop/rsa_private_key.pem'); 29 | define('ALIPAY_APP_ENCRYPT_KEY', 'aGVsbG93b3JsZGhleWhleWhleQ=='); 30 | } 31 | 32 | if (! function_exists('dd')) { 33 | function dd() 34 | { 35 | foreach (func_get_args() as $arg) { 36 | var_dump($arg); 37 | } 38 | exit(0); 39 | } 40 | } 41 | --------------------------------------------------------------------------------