diff --git a/.gitignore b/.gitignore index e2308312f..ffa689275 100644 --- a/.gitignore +++ b/.gitignore @@ -4,5 +4,5 @@ sftp-config.json composer.lock /*.php /.idea -/examples +/coverage /.split diff --git a/build/easywechat-delete-branch.sh b/build/easywechat-delete-branch.sh index a09441685..732bb39d2 100644 --- a/build/easywechat-delete-branch.sh +++ b/build/easywechat-delete-branch.sh @@ -43,5 +43,6 @@ delete_branch support delete_branch url delete_branch user delete_branch broadcast +delete_branch reply rm -rf ./.tmp \ No newline at end of file diff --git a/build/easywechat-split.sh b/build/easywechat-split.sh index ed6c1031c..b870eeaeb 100644 --- a/build/easywechat-split.sh +++ b/build/easywechat-split.sh @@ -53,4 +53,5 @@ split poi src/POI:git@github.com:easywechat/poi.git $TAGS split support src/Support:git@github.com:easywechat/support.git $TAGS split url src/Url:git@github.com:easywechat/url.git $TAGS split user src/User:git@github.com:easywechat/user.git $TAGS -split broadcast src/User:git@github.com:easywechat/broadcast.git $TAGS \ No newline at end of file +split broadcast src/User:git@github.com:easywechat/broadcast.git $TAGS +split reply src/User:git@github.com:easywechat/reply.git $TAGS \ No newline at end of file diff --git a/phpunit.xml.dist b/phpunit.xml.dist index b66a600ea..084078ba2 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -20,6 +20,8 @@ src/ src/ + src/Encryption + src/Support diff --git a/src/Core/AbstractAPI.php b/src/Core/AbstractAPI.php index 34f013639..7f0985c6c 100644 --- a/src/Core/AbstractAPI.php +++ b/src/Core/AbstractAPI.php @@ -60,8 +60,6 @@ abstract class AbstractAPI public function __construct(AccessToken $accessToken) { $this->setAccessToken($accessToken); - - $this->registerHttpMiddleware(); } /** @@ -71,7 +69,15 @@ public function __construct(AccessToken $accessToken) */ public function getHttp() { - return $this->http ?: $this->http = new Http(); + if (is_null($this->http)) { + $this->http = new Http(); + } + + if (count($this->http->getMiddlewares()) === 0) { + $this->registerHttpMiddlewares(); + } + + return $this->http; } /** @@ -134,14 +140,14 @@ public function parseJSON($method, array $args) /** * Set request access_token query. */ - protected function registerHttpMiddleware() + protected function registerHttpMiddlewares() { // access token - $this->getHttp()->addMiddleware($this->accessTokenMiddleware()); + $this->http->addMiddleware($this->accessTokenMiddleware()); // log - $this->getHttp()->addMiddleware($this->logMiddleware()); + $this->http->addMiddleware($this->logMiddleware()); // retry - $this->getHttp()->addMiddleware($this->retryMiddleware()); + $this->http->addMiddleware($this->retryMiddleware()); } /** @@ -149,7 +155,7 @@ protected function registerHttpMiddleware() * * @return \Closure */ - public function accessTokenMiddleware() + protected function accessTokenMiddleware() { return function (callable $handler) { return function (RequestInterface $request, array $options) use ($handler) { @@ -172,7 +178,7 @@ public function accessTokenMiddleware() * * @return \Closure */ - public function logMiddleware() + protected function logMiddleware() { return Middleware::tap(function (RequestInterface $request) { Log::debug("Request: {$request->getMethod()} {$request->getUri()}"); diff --git a/src/Core/AccessToken.php b/src/Core/AccessToken.php index f7ffc53a7..ab8f04c27 100644 --- a/src/Core/AccessToken.php +++ b/src/Core/AccessToken.php @@ -207,7 +207,7 @@ public function getTokenFromServer() $token = $http->parseJSON($http->get(self::API_TOKEN_GET, $params)); if (empty($token['access_token'])) { - throw new HttpException('Request AccessToken fail.'.json_encode($token, JSON_UNESCAPED_UNICODE)); + throw new HttpException('Request AccessToken fail. response: '.json_encode($token, JSON_UNESCAPED_UNICODE)); } return $token; diff --git a/src/Foundation/Application.php b/src/Foundation/Application.php index c45209490..951463378 100644 --- a/src/Foundation/Application.php +++ b/src/Foundation/Application.php @@ -60,6 +60,7 @@ class Application extends Container ServiceProviders\StatsServiceProvider::class, ServiceProviders\PaymentServiceProvider::class, ServiceProviders\POIServiceProvider::class, + ServiceProviders\ReplyServiceProvider::class, ServiceProviders\BroadcastServiceProvider::class, ]; diff --git a/src/Foundation/ServiceProviders/ReplyServiceProvider.php b/src/Foundation/ServiceProviders/ReplyServiceProvider.php new file mode 100644 index 000000000..d882a925e --- /dev/null +++ b/src/Foundation/ServiceProviders/ReplyServiceProvider.php @@ -0,0 +1,47 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +/** + * ReplyServiceProvider.php. + * + * This file is part of the wechat. + * + * (c) overtrue + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ +namespace EasyWeChat\Foundation\ServiceProviders; + +use EasyWeChat\Reply\Reply; +use Pimple\Container; +use Pimple\ServiceProviderInterface; + +/** + * Class ReplyServiceProvider. + */ +class ReplyServiceProvider implements ServiceProviderInterface +{ + /** + * Registers services on the given container. + * + * This method should only be used to configure services and parameters. + * It should not get services. + * + * @param Container $pimple A container instance + */ + public function register(Container $pimple) + { + $pimple['reply'] = function ($pimple) { + return new Reply($pimple['access_token']); + }; + } +} diff --git a/src/Menu/Menu.php b/src/Menu/Menu.php index 5cd8a4edf..4afb1102e 100644 --- a/src/Menu/Menu.php +++ b/src/Menu/Menu.php @@ -38,7 +38,7 @@ class Menu extends AbstractAPI /** * Get all menus. * - * @return array + * @return \EasyWeChat\Support\Collection */ public function all() { @@ -48,7 +48,7 @@ public function all() /** * Get current menus. * - * @return array + * @return \EasyWeChat\Support\Collection */ public function current() { @@ -60,6 +60,8 @@ public function current() * * @param array $buttons * @param array $matchRule + * + * @return bool */ public function add(array $buttons, array $matchRule = []) { @@ -83,7 +85,7 @@ public function add(array $buttons, array $matchRule = []) public function destroy($menuId = null) { if ($menuId !== null) { - return $this->parseJSON('post', [self::API_CONDITIONAL_DELETE, ['menuid' => $menuId]]); + return $this->parseJSON('json', [self::API_CONDITIONAL_DELETE, ['menuid' => $menuId]]); } return $this->parseJSON('get', [self::API_DELETE]); @@ -98,6 +100,6 @@ public function destroy($menuId = null) */ public function test($userId) { - return $this->parseJSON('post', [self::API_CONDITIONAL_TEST, ['user_id' => $userId]]); + return $this->parseJSON('json', [self::API_CONDITIONAL_TEST, ['user_id' => $userId]]); } } diff --git a/src/Message/AbstractMessage.php b/src/Message/AbstractMessage.php index a4c97fca0..39fc34d74 100644 --- a/src/Message/AbstractMessage.php +++ b/src/Message/AbstractMessage.php @@ -20,7 +20,6 @@ */ namespace EasyWeChat\Message; -use EasyWeChat\Support\Arr; use EasyWeChat\Support\Attribute; /** @@ -63,16 +62,6 @@ abstract class AbstractMessage extends Attribute */ protected $properties = []; - /** - * Constructor. - * - * @param array $attributes - */ - public function __construct(array $attributes = []) - { - parent::__construct(Arr::only($attributes, $this->properties)); - } - /** * Return type name message. * diff --git a/src/Payment/API.php b/src/Payment/API.php index 7377e61c5..99b9da8a3 100644 --- a/src/Payment/API.php +++ b/src/Payment/API.php @@ -48,6 +48,7 @@ class API extends AbstractAPI const API_DOWNLOAD_BILL = 'https://api.mch.weixin.qq.com/pay/downloadbill'; const API_REPORT = 'https://api.mch.weixin.qq.com/payitil/report'; const API_URL_SHORTEN = 'https://api.mch.weixin.qq.com/tools/shorturl'; + const API_AUTH_CODE_TO_OPENID = 'https://api.mch.weixin.qq.com/tools/authcodetoopenid'; // order id types. const TRANSCATION_ID = 'transcation_id'; @@ -324,6 +325,18 @@ public function report($api, $timeConsuming, $resultCode, $returnCode, array $ot return $this->request(self::API_REPORT, $params); } + /** + * Get openid by auth code. + * + * @param string $authCode + * + * @return \EasyWeChat\Support\Collection + */ + public function authCodeToOpenId($authCode) + { + return $this->request(self::API_AUTH_CODE_TO_OPENID, ['auth_code' => $authCode]); + } + /** * Merchant setter. * diff --git a/src/Payment/Payment.php b/src/Payment/Payment.php index aefd03bb2..576c64501 100644 --- a/src/Payment/Payment.php +++ b/src/Payment/Payment.php @@ -20,6 +20,7 @@ */ namespace EasyWeChat\Payment; +use EasyWeChat\Core\AccessToken; use EasyWeChat\Core\Exceptions\FaultException; use EasyWeChat\Support\Url as UrlHelper; use EasyWeChat\Support\XML; @@ -140,13 +141,17 @@ public function configForPayment($prepayId, $json = true) /** * Generate js config for share user address. * - * @param string $accessToken - * @param bool $json + * @param string|accessToken $accessToken + * @param bool $json * * @return string|array */ public function configForShareAddress($accessToken, $json = true) { + if ($accessToken instanceof AccessToken) { + $accessToken = $accessToken->getToken(); + } + $params = [ 'appId' => $this->merchant->app_id, 'scope' => 'jsapi_address', diff --git a/src/Reply/LICENSE b/src/Reply/LICENSE new file mode 100644 index 000000000..3a1dc92bc --- /dev/null +++ b/src/Reply/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2015 Easy WeChat + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/src/Reply/README.md b/src/Reply/README.md new file mode 100644 index 000000000..45b0102ce --- /dev/null +++ b/src/Reply/README.md @@ -0,0 +1,2 @@ +# Reply +微信 SDK 自动回复模块 diff --git a/src/Reply/Reply.php b/src/Reply/Reply.php new file mode 100644 index 000000000..62a426daa --- /dev/null +++ b/src/Reply/Reply.php @@ -0,0 +1,41 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +/** + * Reply.php. + * + * @author overtrue + * @copyright 2015 overtrue + * + * @link https://github.com/overtrue + * @link http://overtrue.me + */ +namespace EasyWeChat\Reply; + +use EasyWeChat\Core\AbstractAPI; + +/** + * Class Reply. + */ +class Reply extends AbstractAPI +{ + const API_GET_CURRENT_SETTING = 'https://api.weixin.qq.com/cgi-bin/get_current_autoreply_info'; + + /** + * Get current auto reply settings. + * + * @return \EasyWeChat\Support\Collection + */ + public function current() + { + return $this->parseJSON('get', [self::API_GET_CURRENT_SETTING]); + } +} diff --git a/src/Reply/composer.json b/src/Reply/composer.json new file mode 100644 index 000000000..3917bc529 --- /dev/null +++ b/src/Reply/composer.json @@ -0,0 +1,25 @@ +{ + "name": "easywechat/reply", + "description": "reply module for EasyWeChat SDK.", + "keywords": ["wechat", "weixin", "SDK", "easywechat"], + "license": "MIT", + "authors": [ + { + "name": "overtrue", + "email": "anzhengchao@gmail.com" + } + ], + "autoload": { + "psr-4": { + "EasyWeChat\\Reply\\": "." + } + }, + "minimum-stability":"dev", + "require-dev": { + "phpunit/phpunit": "4.8.*", + "mockery/mockery": "^1.0@dev" + }, + "require": { + "easywechat/core" : "dev-master" + } +} diff --git a/src/Support/Attribute.php b/src/Support/Attribute.php index e43134c27..721621062 100644 --- a/src/Support/Attribute.php +++ b/src/Support/Attribute.php @@ -55,7 +55,9 @@ abstract class Attribute extends Collection */ public function __construct($attributes = []) { - parent::__construct($attributes); + foreach ($attributes as $key => $value) { + $this->set($key, $value); + } } /** @@ -68,7 +70,7 @@ public function __construct($attributes = []) */ public function setAttribute($attribute, $value) { - $this->add($attribute, $value); + $this->set($attribute, $value); return $this; } diff --git a/src/User/User.php b/src/User/User.php index 7e182a7fd..cabe41ffe 100644 --- a/src/User/User.php +++ b/src/User/User.php @@ -71,7 +71,7 @@ public function batchGet(array $openIds, $lang = 'zh_CN') ]; }, $openIds); - return $this->parseJSON('get', [self::API_BATCH_GET, $params]); + return $this->parseJSON('json', [self::API_BATCH_GET, $params]); } /** @@ -129,6 +129,6 @@ public function getGroup($openId) { $params = ['openid' => $openId]; - return $this->parseJSON('get', [self::API_GROUP, $params]); + return $this->parseJSON('json', [self::API_GROUP, $params]); } } diff --git a/tests/Broadcast/BroadcastBroadcastTest.php b/tests/Broadcast/BroadcastBroadcastTest.php index 4245dcdb8..127c49787 100755 --- a/tests/Broadcast/BroadcastBroadcastTest.php +++ b/tests/Broadcast/BroadcastBroadcastTest.php @@ -126,4 +126,95 @@ public function testStatus() $this->assertStringStartsWith(Broadcast::API_GET, $response['api']); $this->assertEquals('MSG_ID', $response['params']['msg_id']); } + + public function testAlias() + { + $broadcast = Mockery::mock(Broadcast::class.'[send,preview]', [Mockery::mock('EasyWeChat\Core\AccessToken')]); + $broadcast->shouldReceive('send')->andReturnUsing(function ($api, $message, $to) { + return compact('api', 'message', 'to'); + }); + + $broadcast->shouldReceive('preview')->andReturnUsing(function ($msgType, $message, $to, $by) { + return compact('msgType', 'message', 'to', 'by'); + }); + + ////////// send ///////// + + // sendText + $result = $broadcast->sendText('hello', 'overtrue'); + $this->assertEquals(['api' => Broadcast::MSG_TYPE_TEXT, 'message' => 'hello', 'to' => 'overtrue'], $result); + + // sendNews + $result = $broadcast->sendNews('hello', 'overtrue'); + $this->assertEquals(['api' => Broadcast::MSG_TYPE_NEWS, 'message' => 'hello', 'to' => 'overtrue'], $result); + + // sendVoice + $result = $broadcast->sendVoice('hello', 'overtrue'); + $this->assertEquals(['api' => Broadcast::MSG_TYPE_VOICE, 'message' => 'hello', 'to' => 'overtrue'], $result); + + // sendImage + $result = $broadcast->sendImage('hello', 'overtrue'); + $this->assertEquals(['api' => Broadcast::MSG_TYPE_IMAGE, 'message' => 'hello', 'to' => 'overtrue'], $result); + + // sendVideo + $result = $broadcast->sendVideo('hello', 'overtrue'); + $this->assertEquals(['api' => Broadcast::MSG_TYPE_VIDEO, 'message' => 'hello', 'to' => 'overtrue'], $result); + + // sendCard + $result = $broadcast->sendCard('hello', 'overtrue'); + $this->assertEquals(['api' => Broadcast::MSG_TYPE_CARD, 'message' => 'hello', 'to' => 'overtrue'], $result); + + ////////// preview ///////// + // previewText + $result = $broadcast->previewText('hello', 'overtrue'); + $this->assertEquals(['msgType' => Broadcast::MSG_TYPE_TEXT, 'message' => 'hello', 'to' => 'overtrue', 'by' => Broadcast::PREVIEW_BY_OPENID], $result); + + // previewNews + $result = $broadcast->previewNews('hello', 'overtrue'); + $this->assertEquals(['msgType' => Broadcast::MSG_TYPE_NEWS, 'message' => 'hello', 'to' => 'overtrue', 'by' => Broadcast::PREVIEW_BY_OPENID], $result); + + // previewVoice + $result = $broadcast->previewVoice('hello', 'overtrue'); + $this->assertEquals(['msgType' => Broadcast::MSG_TYPE_VOICE, 'message' => 'hello', 'to' => 'overtrue', 'by' => Broadcast::PREVIEW_BY_OPENID], $result); + + // previewImage + $result = $broadcast->previewImage('hello', 'overtrue'); + $this->assertEquals(['msgType' => Broadcast::MSG_TYPE_IMAGE, 'message' => 'hello', 'to' => 'overtrue', 'by' => Broadcast::PREVIEW_BY_OPENID], $result); + + // previewVideo + $result = $broadcast->previewVideo('hello', 'overtrue'); + $this->assertEquals(['msgType' => Broadcast::MSG_TYPE_VIDEO, 'message' => 'hello', 'to' => 'overtrue', 'by' => Broadcast::PREVIEW_BY_OPENID], $result); + + // previewCard + $result = $broadcast->previewCard('hello', 'overtrue'); + $this->assertEquals(['msgType' => Broadcast::MSG_TYPE_CARD, 'message' => 'hello', 'to' => 'overtrue', 'by' => Broadcast::PREVIEW_BY_OPENID], $result); + + // previewByName + $result = $broadcast->previewByName(Broadcast::MSG_TYPE_TEXT, 'hello', 'overtrue'); + $this->assertEquals(['msgType' => Broadcast::MSG_TYPE_TEXT, 'message' => 'hello', 'to' => 'overtrue', 'by' => Broadcast::PREVIEW_BY_NAME], $result); + + // previewTextByName + $result = $broadcast->previewTextByName('hello', 'overtrue'); + $this->assertEquals(['msgType' => Broadcast::MSG_TYPE_TEXT, 'message' => 'hello', 'to' => 'overtrue', 'by' => Broadcast::PREVIEW_BY_NAME], $result); + + // previewNewsByName + $result = $broadcast->previewNewsByName('hello', 'overtrue'); + $this->assertEquals(['msgType' => Broadcast::MSG_TYPE_NEWS, 'message' => 'hello', 'to' => 'overtrue', 'by' => Broadcast::PREVIEW_BY_NAME], $result); + + // previewVoiceByName + $result = $broadcast->previewVoiceByName('hello', 'overtrue'); + $this->assertEquals(['msgType' => Broadcast::MSG_TYPE_VOICE, 'message' => 'hello', 'to' => 'overtrue', 'by' => Broadcast::PREVIEW_BY_NAME], $result); + + // previewImageByName + $result = $broadcast->previewImageByName('hello', 'overtrue'); + $this->assertEquals(['msgType' => Broadcast::MSG_TYPE_IMAGE, 'message' => 'hello', 'to' => 'overtrue', 'by' => Broadcast::PREVIEW_BY_NAME], $result); + + // previewVideoByName + $result = $broadcast->previewVideoByName('hello', 'overtrue'); + $this->assertEquals(['msgType' => Broadcast::MSG_TYPE_VIDEO, 'message' => 'hello', 'to' => 'overtrue', 'by' => Broadcast::PREVIEW_BY_NAME], $result); + + // previewCardByName + $result = $broadcast->previewCardByName('hello', 'overtrue'); + $this->assertEquals(['msgType' => Broadcast::MSG_TYPE_CARD, 'message' => 'hello', 'to' => 'overtrue', 'by' => Broadcast::PREVIEW_BY_NAME], $result); + } } diff --git a/tests/Core/CoreAbstractAPITest.php b/tests/Core/CoreAbstractAPITest.php new file mode 100644 index 000000000..724d917b2 --- /dev/null +++ b/tests/Core/CoreAbstractAPITest.php @@ -0,0 +1,96 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +use EasyWeChat\Core\AbstractAPI; +use EasyWeChat\Core\AccessToken; +use EasyWeChat\Core\Http; +use EasyWeChat\Support\Collection; + +class FooAPI extends AbstractAPI +{ + public function getHttpInstance() + { + return $this->http; + } +} + +class CoreAbstractAPITest extends PHPUnit_Framework_TestCase +{ + /** + * Test __construct. + */ + public function testConstruct() + { + $accessToken = Mockery::mock(AccessToken::class); + + $api = new FooAPI($accessToken); + $this->assertEquals($accessToken, $api->getAccessToken()); + } + + public function testHttpInstance() + { + $accessToken = Mockery::mock(AccessToken::class); + + $api = new FooAPI($accessToken); + + $this->assertNull($api->getHttpInstance()); + + $api->getHttp(); + $this->assertInstanceOf(Http::class, $api->getHttpInstance()); + + $middlewares = $api->getHttp()->getMiddlewares(); + $this->assertCount(3, $middlewares); + + $http = Mockery::mock(Http::class.'[getMiddlewares]', function ($mock) { + $mock->shouldReceive('getMiddlewares')->andReturn([1, 2, 3]); + }); + $api->setHttp($http); + $this->assertEquals($http, $api->getHttp()); + } + + public function testParseJSON() + { + $accessToken = Mockery::mock(AccessToken::class); + + $api = new FooAPI($accessToken); + $http = Mockery::mock(Http::class.'[getMiddlewares,get,parseJSON]', function ($mock) { + $mock->shouldReceive('getMiddlewares')->andReturn([1, 2, 3]); + $mock->shouldReceive('get')->andReturnUsing(function () { + return func_get_args(); + }); + $mock->shouldReceive('parseJSON')->andReturnUsing(function ($json) { + return $json; + }); + }); + $api->setHttp($http); + + $collection = $api->parseJSON('get', ['foo', ['bar']]); + + $this->assertInstanceOf(Collection::class, $collection); + $this->assertEquals(['foo', ['bar']], $collection->all()); + + // test error + $http = Mockery::mock(Http::class.'[getMiddlewares,get,parseJSON]', function ($mock) { + $mock->shouldReceive('getMiddlewares')->andReturn([1, 2, 3]); + $mock->shouldReceive('get')->andReturnUsing(function () { + return func_get_args(); + }); + $mock->shouldReceive('parseJSON')->andReturnUsing(function ($json) { + return ['errcode' => 24000]; + }); + }); + $api->setHttp($http); + + $this->setExpectedException(\EasyWeChat\Core\Exceptions\HttpException::class, 'Unknown', 24000); + $collection = $api->parseJSON('get', ['foo', ['bar']]); + $this->fail(); + } +} diff --git a/tests/Core/CoreAccessTokenTest.php b/tests/Core/CoreAccessTokenTest.php index 89e30121f..201a657b2 100755 --- a/tests/Core/CoreAccessTokenTest.php +++ b/tests/Core/CoreAccessTokenTest.php @@ -75,5 +75,47 @@ public function testNonCachedGetToken() $this->assertEquals('thisIsATokenFromHttp', $accessToken->getToken()); $this->assertEquals('thisIsATokenFromHttp', $cacheObj->token); $this->assertEquals(5700, $cacheObj->expire); + + $http = Mockery::mock(Http::class.'[get]', function ($mock) { + $mock->shouldReceive('get')->andReturn(json_encode([ + 'foo' => 'bar', // without "access_token" + ])); + }); + + $accessToken = new AccessToken('appId', 'secret', $cache); + $accessToken->setHttp($http); + + $this->setExpectedException(\EasyWeChat\Core\Exceptions\HttpException::class, 'Request AccessToken fail. response: {"foo":"bar"}'); + $accessToken->getToken(); + $this->fail(); + } + + public function testGetterAndSetter() + { + $accessToken = new AccessToken('appId', 'secret'); + + $this->assertEquals('secret', $accessToken->getSecret()); + $this->assertEquals('appId', $accessToken->getAppId()); + + $this->assertInstanceOf(\Doctrine\Common\Cache\FilesystemCache::class, $accessToken->getCache()); + + $cache = Mockery::mock(Cache::class, function ($mock) { + $mock->shouldReceive('fetch')->andReturn('thisIsACachedToken'); + $mock->shouldReceive('save')->andReturnUsing(function ($key, $token, $expire) { + return $token; + }); + }); + + $accessToken->setCache($cache); + $this->assertEquals($cache, $accessToken->getCache()); + + $this->assertEquals('access_token', $accessToken->getQueryName()); + $this->assertArrayHasKey('access_token', $accessToken->getQueryFields()); + + $accessToken->setQueryName('foo'); + + $this->assertEquals('foo', $accessToken->getQueryName()); + $this->assertArrayHasKey('foo', $accessToken->getQueryFields()); + $this->assertArrayNotHasKey('access_token', $accessToken->getQueryFields()); } } diff --git a/tests/Core/CoreHttpTest.php b/tests/Core/CoreHttpTest.php index f4502a305..412c5e05f 100755 --- a/tests/Core/CoreHttpTest.php +++ b/tests/Core/CoreHttpTest.php @@ -16,6 +16,13 @@ class CoreHttpTest extends PHPUnit_Framework_TestCase { + public function testConstruct() + { + $http = new Http(); + + $this->assertInstanceOf(Client::class, $http->getClient()); + } + /** * Get guzzle mock client. * diff --git a/tests/Message/MessageArticleTest.php b/tests/Message/MessageArticleTest.php new file mode 100644 index 000000000..1df9f30ca --- /dev/null +++ b/tests/Message/MessageArticleTest.php @@ -0,0 +1,42 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +use EasyWeChat\Message\Article; + +class MessageArticleTest extends PHPUnit_Framework_TestCase +{ + /** + * Test get attributes. + */ + public function testAttributes() + { + $attributes = [ + 'title' => 'TITLE', + 'thumb_media_id' => 'THUMB_MEDIA_ID', + 'author' => 'AUTHOR', + 'digest' => 'DIGEST', + 'show_cover_pic' => 'SHOW_COVER_PIC', + 'content' => 'CONTENT', + 'content_source_url' => 'CONTENT_SOURCE_URL', + ]; + $article = new Article($attributes); + + $return = $article->only([ + 'title', 'thumb_media_id', 'author', 'digest', + 'show_cover_pic', 'content', 'content_source_url', + ]); + + $this->assertEquals($return, $attributes); + + $this->assertEquals($article->show_cover, $attributes['show_cover_pic']); + $this->assertEquals($article->source_url, $attributes['content_source_url']); + } +} diff --git a/tests/Message/MessageMaterialTest.php b/tests/Message/MessageMaterialTest.php new file mode 100644 index 000000000..48a924c55 --- /dev/null +++ b/tests/Message/MessageMaterialTest.php @@ -0,0 +1,26 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +use EasyWeChat\Message\Material; + +class MessageMaterialTest extends PHPUnit_Framework_TestCase +{ + /** + * Test get attributes. + */ + public function testAttributes() + { + $material = new Material('text', 'mediaId'); + + $this->assertEquals('text', $material->type); + $this->assertEquals('mediaId', $material->media_id); + } +} diff --git a/tests/Payment/PaymentAPITest.php b/tests/Payment/PaymentAPITest.php index 628766ac6..5841aeca7 100755 --- a/tests/Payment/PaymentAPITest.php +++ b/tests/Payment/PaymentAPITest.php @@ -183,6 +183,19 @@ public function testUrlShorten() $this->assertEquals('http://easywechat.org', $response['params']['long_url']); } + /** + * Test authCodeToOpenId(). + */ + public function testAuthCodeToOpenId() + { + $api = $this->getAPI(); + + $response = $api->authCodeToOpenId('authcode'); + + $this->assertEquals(API::API_AUTH_CODE_TO_OPENID, $response['api']); + $this->assertEquals('authcode', $response['params']['auth_code']); + } + /** * Test setMerchant() and getMerchant. */ diff --git a/tests/Payment/PaymentPaymentTest.php b/tests/Payment/PaymentPaymentTest.php index c8fb38441..a8592ab89 100755 --- a/tests/Payment/PaymentPaymentTest.php +++ b/tests/Payment/PaymentPaymentTest.php @@ -9,6 +9,7 @@ * with this source code in the file LICENSE. */ +use EasyWeChat\Core\AccessToken; use EasyWeChat\Core\Exceptions\FaultException; use EasyWeChat\Payment\API; use EasyWeChat\Payment\Merchant; @@ -114,6 +115,65 @@ public function testHandleNotify() ]), $response->getContent()); } + /** + * test configForPayment. + */ + public function testConfigForPayment() + { + $payment = $this->getPayment(); + + $json = $payment->configForPayment('prepayId'); + + $array = json_decode($json, true); + $this->assertEquals('wxTestAppId', $array['appId']); + $this->assertEquals('prepay_id=prepayId', $array['package']); + $this->assertEquals('MD5', $array['signType']); + $this->assertArrayHasKey('timeStamp', $array); + $this->assertArrayHasKey('nonceStr', $array); + $this->assertArrayHasKey('paySign', $array); + } + + /** + * test configForShareAddress. + */ + public function testConfigForShareAddress() + { + $payment = $this->getPayment(); + + $json = $payment->configForShareAddress('accessToken'); + + $array = json_decode($json, true); + $this->assertEquals('wxTestAppId', $array['appId']); + $this->assertEquals('jsapi_address', $array['scope']); + $this->assertEquals('SHA1', $array['signType']); + $this->assertArrayHasKey('timeStamp', $array); + $this->assertArrayHasKey('nonceStr', $array); + $this->assertArrayHasKey('addrSign', $array); + + $log = new stdClass(); + $log->called = false; + $accessToken = Mockery::mock(AccessToken::class.'[getToken]', ['foo', 'bar']); + + $accessToken->shouldReceive('getToken')->andReturnUsing(function () use ($log) { + $log->called = true; + + return 'mockToken'; + }); + + $json = $payment->configForShareAddress($accessToken); + $this->assertTrue($log->called); + } + + /** + * test getNotify. + */ + public function testGetNotify() + { + $payment = $this->getPayment(); + + $this->assertInstanceOf(Notify::class, $payment->getNotify()); + } + /** * Test setMerchant()、getMerchant()、setAPI() and getAPI(). */ diff --git a/tests/Reply/ReplyReplyTest.php b/tests/Reply/ReplyReplyTest.php new file mode 100644 index 000000000..37be0ac21 --- /dev/null +++ b/tests/Reply/ReplyReplyTest.php @@ -0,0 +1,40 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +use EasyWeChat\Reply\Reply; + +class ReplyReplyTest extends PHPUnit_Framework_TestCase +{ + public function getReply() + { + $reply = Mockery::mock('EasyWeChat\Reply\Reply[parseJSON]', [Mockery::mock('EasyWeChat\Core\AccessToken')]); + $reply->shouldReceive('parseJSON')->andReturnUsing(function ($method, $params) { + return [ + 'api' => $params[0], + 'params' => empty($params[1]) ? null : $params[1], + ]; + }); + + return $reply; + } + + /** + * Test current(). + */ + public function testCurrent() + { + $reply = $this->getReply(); + + $response = $reply->current(); + $this->assertStringStartsWith(Reply::API_GET_CURRENT_SETTING, $response['api']); + $this->assertEmpty($response['params']); + } +}