diff --git a/src/Card/Card.php b/src/Card/Card.php new file mode 100644 index 000000000..fe5d77976 --- /dev/null +++ b/src/Card/Card.php @@ -0,0 +1,730 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +/** + * Card.php. + * + * @author overtrue + * @copyright 2016 overtrue + * + * @link https://github.com/overtrue + * @link http://overtrue.me + */ +namespace EasyWeChat\Card; + +use Doctrine\Common\Cache\Cache; +use Doctrine\Common\Cache\FilesystemCache; +use EasyWeChat\Core\AbstractAPI; +use Psr\Http\Message\ResponseInterface; + +class Card extends AbstractAPI +{ + /** + * Cache. + * + * @var Cache + */ + protected $cache; + + /** + * Ticket cache prefix. + */ + const TICKET_CACHE_PREFIX = 'overtrue.wechat.card_api_ticket.'; + + const API_GET_COLORS = 'https://api.weixin.qq.com/card/getcolors'; + const API_CREATE = 'https://api.weixin.qq.com/card/create'; + const API_QRCODE_CREATE = 'https://api.weixin.qq.com/card/qrcode/create'; + const API_QRCODE_SHOW = 'https://mp.weixin.qq.com/cgi-bin/showqrcode'; + const API_GET_CARD_TICKET = 'https://api.weixin.qq.com/cgi-bin/ticket/getticket'; + const API_LANDING_PAGE = 'https://api.weixin.qq.com/card/landingpage/create'; + const API_DEPOSIT = 'https://api.weixin.qq.com/card/code/deposit'; + const API_GET_DEPOSIT_COUNT = 'https://api.weixin.qq.com/card/code/getdepositcount'; + const API_CHECK_CODE = 'https://api.weixin.qq.com/card/code/checkcode'; + const API_GET_HTML = 'https://api.weixin.qq.com/card/mpnews/gethtml'; + const API_TEST_WHITE_LIST = 'https://api.weixin.qq.com/card/testwhitelist/set'; + const API_CODE_GET = 'https://api.weixin.qq.com/card/code/get'; + const API_CONSUME = 'https://api.weixin.qq.com/card/code/consume'; + const API_DECRYPT = 'https://api.weixin.qq.com/card/code/decrypt'; + const API_GET_CARD_LIST = 'https://api.weixin.qq.com/card/user/getcardlist'; + const API_CARD_GET = 'https://api.weixin.qq.com/card/get'; + const API_BATCH_GET = 'https://api.weixin.qq.com/card/batchget'; + const API_UPDATE = 'https://api.weixin.qq.com/card/update'; + const API_PAY_CELL_SET = 'https://api.weixin.qq.com/card/paycell/set'; + const API_MODIFY_STOCK = 'https://api.weixin.qq.com/card/modifystock'; + const API_CODE_UPDATE = 'https://api.weixin.qq.com/card/code/update'; + const API_CARD_DELETE = 'https://api.weixin.qq.com/card/delete'; + const API_UNAVAILABLE = 'https://api.weixin.qq.com/card/code/unavailable'; + const API_CARD_BIZ_UIN_INFO = 'https://api.weixin.qq.com/datacube/getcardbizuininfo'; + const API_CARD_CARD_INFO = 'https://api.weixin.qq.com/datacube/getcardcardinfo'; + const API_CARD_MEMBER_CARD_INFO = 'https://api.weixin.qq.com/datacube/getcardmembercardinfo'; + const API_CARD_ACTIVATE = 'https://api.weixin.qq.com/card/membercard/activate'; + const API_ACTIVATE_USER_FORM = 'https://api.weixin.qq.com/card/membercard/activateuserform/set'; + const API_MEMBER_USER_INFO = 'https://api.weixin.qq.com/card/membercard/userinfo/get'; + const API_UPDATE_USER = 'https://api.weixin.qq.com/card/membercard/updateuser'; + const API_SUB_MERCHANT = 'https://api.weixin.qq.com/card/submerchant/submit'; + const API_GET_APPLY_PROTOCOL = 'https://api.weixin.qq.com/card/getapplyprotocol'; + + /** + * 获取卡券颜色. + * + * @return array + */ + public function getColors() + { + return $this->parseJSON('get', [self::API_GET_COLORS]); + } + + /** + * 创建卡券. + * + * @param string $cardType + * @param array $baseInfo + * @param array $especial + * @param array $advancedInfo + * + * @return bool|array + */ + public function create($cardType = 'member_card', $baseInfo = [], $especial = [], $advancedInfo = []) + { + $card = []; + $card['card'] = []; + $card['card']['card_type'] = strtoupper($cardType); + + $type = strtolower($cardType); + + $cardInfo = [ + 'base_info' => $baseInfo, + ]; + + $card['card'][$type] = []; + $card['card'][$type] = array_merge($cardInfo, $especial, $advancedInfo); + + if (is_string($cardType) && is_array($baseInfo) && is_array($especial)) { + return $this->parseJSON('json', [self::API_CREATE, $card]); + } + + return false; + } + + /** + * 创建二维码. + * + * @param array $cards + * + * @return array|bool + */ + public function QRCode($cards = []) + { + return $this->parseJSON('json', [self::API_QRCODE_CREATE, $cards]); + } + + /** + * ticket 换取二维码图片. + * + * @param string $ticket + * + * @return array + */ + public function showQRCode($ticket = null) + { + $params = [ + 'ticket' => $ticket, + ]; + + $http = $this->getHttp(); + + /** @var ResponseInterface $response */ + $response = $http->get(self::API_QRCODE_SHOW, $params); + + return [ + 'status' => $response->getStatusCode(), + 'reason' => $response->getReasonPhrase(), + 'headers' => $response->getHeaders(), + 'body' => strval($response->getBody()), + 'url' => self::API_QRCODE_SHOW.'?'.http_build_query($params), + ]; + } + + /** + * 通过ticket换取二维码 链接. + * + * @param string $ticket + * + * @return string + */ + public function getQRCodeUrl($ticket) + { + $params = '?ticket='.$ticket; + + return self::API_QRCODE_SHOW.$params; + } + + /** + * 获取 卡券 Api_ticket. + * + * @param bool $refresh 是否强制刷新 + * + * @return string $apiTicket + */ + public function getAPITicket($refresh = false) + { + $key = self::TICKET_CACHE_PREFIX.$this->getAccessToken()->getAppId(); + + $ticket = $this->getCache()->fetch($key); + + if (!$ticket || $refresh) { + $result = $this->parseJSON('get', [self::API_GET_CARD_TICKET, ['type' => 'wx_card']]); + + $this->getCache()->save($key, $result['ticket'], $result['expires_in'] - 500); + + return $result['ticket']; + } + + return $ticket; + } + + /** + * 微信卡券:JSAPI 卡券Package - 基础参数没有附带任何值 - 再生产环境中需要根据实际情况进行修改. + * + * @param array $cards + * @param int $timestamp + * @param string $apiTicket + * + * @return string + */ + public function wxCardPackage(array $cards, $timestamp = null, $apiTicket = null) + { + if (empty($timestamp) || $timestamp === '') { + $timestamp = time(); + } + + if (empty($apiTicket) || $apiTicket === '') { + $apiTicket = $this->getAPITicket(); + } + + $result = []; + foreach ($cards as $index => $card) { + if (empty($card['code']) || !isset($card['code'])) { + $card['code'] = ''; + } + + if (empty($card['openid']) || !isset($card['openid'])) { + $card['openid'] = ''; + } + + $arrays = [$apiTicket, $timestamp, $card['card_id'], $card['code'], $card['openid']]; + sort($arrays, SORT_STRING); + $string = sha1(implode($arrays)); + + $result['cardList'][$index]['cardId'] = $card['card_id']; + $result['cardList'][$index]['cardExt']['code'] = $card['code']; + $result['cardList'][$index]['cardExt']['openid'] = $card['openid']; + + $result['cardList'][$index]['cardExt']['timestamp'] = $timestamp; + $result['cardList'][$index]['cardExt']['signature'] = $string; + + if (!empty($card['outer_id'])) { + $result['cardList'][$index]['cardExt']['outer_id'] = $card['outer_id']; + } + + $result['cardList'][$index]['cardExt'] = json_encode($result['cardList'][$index]['cardExt']); + } + + return json_encode($result); + } + + /** + * 创建货架接口. + * + * @param string $banner + * @param string $pageTitle + * @param bool $canShare + * @param string $scene [SCENE_NEAR_BY 附近,SCENE_MENU 自定义菜单,SCENE_QRCODE 二维码,SCENE_ARTICLE 公众号文章, + * SCENE_H5 h5页面,SCENE_IVR 自动回复,SCENE_CARD_CUSTOM_CELL 卡券自定义cell] + * @param array $cardList + * + * @return array + */ + public function createLandingPage($banner, $pageTitle, $canShare, $scene, $cardList) + { + $params = [ + 'banner' => $banner, + 'page_title' => $pageTitle, + 'can_share' => $canShare, + 'scene' => $scene, + 'card_list' => $cardList, + ]; + + return $this->parseJSON('json', [self::API_LANDING_PAGE, $params]); + } + + /** + * 导入code接口. + * + * @param string $cardId + * @param array $code + * + * @return array + */ + public function deposit($cardId, $code) + { + $params = [ + 'card_id' => $cardId, + 'code' => $code, + ]; + + return $this->parseJSON('json', [self::API_DEPOSIT, $params]); + } + + /** + * 查询导入code数目. + * + * @param string $cardId + * + * @return array + */ + public function getDepositedCount($cardId) + { + $params = [ + 'card_id' => $cardId, + ]; + + return $this->parseJSON('json', [self::API_GET_DEPOSIT_COUNT, $params]); + } + + /** + * 核查code接口. + * + * @param string $cardId + * @param array $code + * + * @return array + */ + public function checkCode($cardId, $code) + { + $params = [ + 'card_id' => $cardId, + 'code' => $code, + ]; + + return $this->parseJSON('json', [self::API_CHECK_CODE, $params]); + } + + /** + * 图文消息群发卡券. + * + * @param string $cardId + * + * @return array + */ + public function getHtml($cardId) + { + $params = [ + 'card_id' => $cardId, + ]; + + return $this->parseJSON('json', [self::API_GET_HTML, $params]); + } + + /** + * 设置测试白名单. + * + * @param array $openid + * @param array $username + * + * @return array + */ + public function setTestWhitelist($openid, $username) + { + $params = [ + 'openid' => $openid, + 'username' => $username, + ]; + + return $this->parseJSON('json', [self::API_TEST_WHITE_LIST, $params]); + } + + /** + * 查询Code接口. + * + * @param string $code + * @param bool $checkConsume + * @param string $cardId + * + * @return array + */ + public function getCode($code, $checkConsume, $cardId) + { + $params = [ + 'code' => $code, + 'check_consume' => $checkConsume, + 'card_id' => $cardId, + ]; + + return $this->parseJSON('json', [self::API_CODE_GET, $params]); + } + + /** + * 核销Code接口. + * + * @param string $cardId + * @param string $code + * + * @return array + */ + public function consume($cardId, $code) + { + $params = [ + 'card_id' => $cardId, + 'code' => $code, + ]; + + return $this->parseJSON('json', [self::API_CONSUME, $params]); + } + + /** + * Code解码接口. + * + * @param string $encryptedCode + * + * @return array + */ + public function decryptCode($encryptedCode) + { + $params = [ + 'encrypt_code' => $encryptedCode, + ]; + + return $this->parseJSON('json', [self::API_DECRYPT, $params]); + } + + /** + * 获取用户已领取卡券接口. + * + * @param string $openid + * @param string $cardId + * + * @return array + */ + public function getUserCards($openid, $cardId = '') + { + $params = [ + 'openid' => $openid, + 'card_id' => $cardId, + ]; + + return $this->parseJSON('json', [self::API_GET_CARD_LIST, $params]); + } + + /** + * 查看卡券详情. + * + * @param string $cardId + * + * @return array + */ + public function getCard($cardId) + { + $params = [ + 'card_id' => $cardId, + ]; + + return $this->parseJSON('json', [self::API_CARD_GET, $params]); + } + + /** + * 批量查询卡列表. + * + * @param int $offset + * @param int $count + * @param string $statusList + * + * @return array + */ + public function lists($offset = 0, $count = 10, $statusList = 'CARD_STATUS_VERIFY_OK') + { + $params = [ + 'offset' => $offset, + 'count' => $count, + 'status_list' => $statusList, + ]; + + return $this->parseJSON('json', [self::API_BATCH_GET, $params]); + } + + /** + * 更改卡券信息接口 and 设置跟随推荐接口. + * + * @param string $cardId + * @param string $type + * @param array $baseInfo + * @param array $especial + * + * @return array + */ + public function update($cardId, $type, $baseInfo = [], $especial = []) + { + $card = []; + $card['card_id'] = $cardId; + $card[$type] = []; + + $cardInfo = []; + $cardInfo['base_info'] = $baseInfo; + + $card[$type] = array_merge($cardInfo, $especial); + + return $this->parseJSON('json', [self::API_UPDATE, $card]); + } + + /** + * 设置微信买单接口. + * 设置买单的card_id必须已经配置了门店,否则会报错. + * + * @param string $cardId + * @param bool $isOpen + * + * @return array + */ + public function setPayCell($cardId, $isOpen = true) + { + $params = [ + 'card_id' => $cardId, + 'is_open' => $isOpen, + ]; + + return $this->parseJSON('json', [self::API_PAY_CELL_SET, $params]); + } + + /** + * 修改库存接口. + * + * @param string $cardId + * @param string $stock + * @param int $value + * + * @return array + */ + public function modifyStock($cardId, $stock = 'increase', $value = 0) + { + $params = [ + 'card_id' => $cardId, + ]; + + if ($stock === 'increase') { + $params['increase_stock_value'] = intval($value); + } elseif ($stock === 'reduce') { + $params['reduce_stock_value'] = intval($value); + } else { + return false; + } + + return $this->parseJSON('json', [self::API_MODIFY_STOCK, $params]); + } + + /** + * 更改Code接口. + * + * @param string $code + * @param string $newCode + * @param array $cardId + * + * @return array + */ + public function updateCode($code, $newCode, $cardId = []) + { + $params = [ + 'code' => $code, + 'new_code' => $newCode, + 'card_id' => $cardId, + ]; + + return $this->parseJSON('json', [self::API_CODE_UPDATE, $params]); + } + + /** + * 删除卡券接口. + * + * @param string $cardId + * + * @return array + */ + public function delete($cardId) + { + $params = [ + 'card_id' => $cardId, + ]; + + return $this->parseJSON('json', [self::API_CARD_DELETE, $params]); + } + + /** + * 设置卡券失效. + * + * @param string $code + * @param string $cardId + * + * @return array + */ + public function disable($code, $cardId = '') + { + $params = [ + 'code' => $code, + 'card_id' => $cardId, + ]; + + return $this->parseJSON('json', [self::API_UNAVAILABLE, $params]); + } + + /** + * 会员卡接口激活. + * + * @param array $activate + * + * @return array + */ + public function activate($activate = []) + { + return $this->parseJSON('json', [self::API_CARD_ACTIVATE, $activate]); + } + + /** + * 设置开卡字段接口. + * + * @param string $cardId + * @param array $requiredForm + * @param array $optionalForm + * + * @return array + */ + public function activateUserForm($cardId, $requiredForm = [], $optionalForm = []) + { + $card = []; + $card['card_id'] = $cardId; + + $params = array_merge($card, $requiredForm, $optionalForm); + + return $this->parseJSON('json', [self::API_ACTIVATE_USER_FORM, $params]); + } + + /** + * 拉取会员信息接口. + * + * @param string $cardId + * @param string $code + * + * @return array + */ + public function getMemberCardUser($cardId, $code) + { + $params = [ + 'card_id' => $cardId, + 'code' => $code, + ]; + + return $this->parseJSON('json', [self::API_MEMBER_USER_INFO, $params]); + } + + /** + * 更新会员信息. + * + * @param array $updateUser + * + * @return array + */ + public function updateMemberCardUser($updateUser = []) + { + $params = $updateUser; + + return $this->parseJSON('json', [self::API_UPDATE_USER, $params]); + } + + /** + * 添加子商户. + * + * @param string $brandName + * @param string $logoUrl + * @param string $protocol + * @param int $endTime + * @param int $primaryCategoryId + * @param int $secondaryCategoryId + * @param string $agreementMediaId + * @param string $operatorMediaId + * @param string $appId + * + * @return array + */ + public function subMerchant($brandName, $logoUrl, $protocol, $endTime, $primaryCategoryId, $secondaryCategoryId, $agreementMediaId, $operatorMediaId, $appId = '') + { + $params = [ + 'info' => [ + 'brand_name' => $brandName, + 'logo_url' => $logoUrl, + 'protocol' => $protocol, + 'end_time' => $endTime, + 'primary_category_id' => $primaryCategoryId, + 'secondary_category_id' => $secondaryCategoryId, + 'agreement_media_id' => $agreementMediaId, + 'operator_media_id' => $operatorMediaId, + 'app_id' => $appId, + ], + ]; + + return $this->parseJSON('json', [self::API_SUB_MERCHANT, $params]); + } + + /** + * 卡券开放类目查询接口. + * + * @return array|bool + */ + public function getApplyProtocol() + { + return $this->parseJSON('get', [self::API_GET_APPLY_PROTOCOL]); + } + + /** + * Set cache manager. + * + * @param \Doctrine\Common\Cache\Cache $cache + * + * @return $this + */ + public function setCache(Cache $cache) + { + $this->cache = $cache; + + return $this; + } + + /** + * Return cache manager. + * + * @return \Doctrine\Common\Cache\Cache + */ + public function getCache() + { + return $this->cache ?: $this->cache = new FilesystemCache(sys_get_temp_dir()); + } + + /** + * Set current url. + * + * @param string $url + * + * @return array + */ + public function setUrl($url) + { + $this->url = $url; + + return $this; + } +} diff --git a/src/Card/composer.json b/src/Card/composer.json index a623d4503..8bac543a2 100644 --- a/src/Card/composer.json +++ b/src/Card/composer.json @@ -5,8 +5,8 @@ "license": "MIT", "authors": [ { - "name": "overtrue", - "email": "anzhengchao@gmail.com" + "name": "wangniuniu", + "email": "1098484600@qq.com" } ], "autoload": { diff --git a/src/Foundation/Application.php b/src/Foundation/Application.php index 5c526a1ee..a42a1cd37 100644 --- a/src/Foundation/Application.php +++ b/src/Foundation/Application.php @@ -60,6 +60,7 @@ * @property \EasyWeChat\Payment\MerchantPay\MerchantPay $merchant_pay * @property \EasyWeChat\Reply\Reply $reply * @property \EasyWeChat\Broadcast\Broadcast $broadcast + * @property \EasyWeChat\Card\Card $card */ class Application extends Container { @@ -85,6 +86,7 @@ class Application extends Container ServiceProviders\POIServiceProvider::class, ServiceProviders\ReplyServiceProvider::class, ServiceProviders\BroadcastServiceProvider::class, + ServiceProviders\CardServiceProvider::class, ]; /** @@ -207,10 +209,10 @@ private function registerBase() $this['access_token'] = function () { return new AccessToken( - $this['config']['app_id'], - $this['config']['secret'], - $this['cache'] - ); + $this['config']['app_id'], + $this['config']['secret'], + $this['cache'] + ); }; } diff --git a/src/Foundation/ServiceProviders/CardServiceProvider.php b/src/Foundation/ServiceProviders/CardServiceProvider.php new file mode 100644 index 000000000..3d3931649 --- /dev/null +++ b/src/Foundation/ServiceProviders/CardServiceProvider.php @@ -0,0 +1,50 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +/** + * JsServiceProvider.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\Card\Card; +use Pimple\Container; +use Pimple\ServiceProviderInterface; + +/** + * Class JsServiceProvider. + */ +class CardServiceProvider 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['card'] = function ($pimple) { + $card = new Card($pimple['access_token']); + $card->setCache($pimple['cache']); + + return $card; + }; + } +} diff --git a/tests/Card/CardTest.php b/tests/Card/CardTest.php new file mode 100644 index 000000000..669ab444d --- /dev/null +++ b/tests/Card/CardTest.php @@ -0,0 +1,621 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +use EasyWeChat\Card\Card; +use EasyWeChat\Core\Http; + +class CardTest extends TestCase +{ + /** + * @return \Mockery\MockInterface|Card + */ + public function getCard() + { + $card = Mockery::mock('EasyWeChat\Card\Card[parseJSON]', [$this->getMockAccessToken()]); + $card->shouldReceive('parseJSON')->andReturnUsing(function ($method, $params) { + return [ + 'api' => $params[0], + 'params' => empty($params[1]) ? null : $params[1], + ]; + }); + + return $card; + } + + public function getMockCache() + { + return Mockery::mock('Doctrine\Common\Cache\Cache'); + } + + public function getMockHttp() + { + $http = Mockery::mock(Http::class.'[get]', function ($mock) { + $mock->shouldReceive('get')->andReturn(json_encode([ + 'access_token' => 'thisIsATokenFromHttp', + 'expires_in' => 7200, + ])); + }); + + return $http; + } + + public function getMockAccessToken() + { + $accessToken = Mockery::mock('EasyWeChat\Core\AccessToken[getTokenFromServer]', ['foo', 'bar']); + $accessToken->shouldReceive('getTokenFromServer')->andReturn([ + 'access_token' => 'foobar', + 'expires_in' => 7200, + ]); + + return $accessToken; + } + + //获取卡券颜色 + public function testGetColors() + { + $card = $this->getCard(); + + $result = $card->getColors(); + $this->assertStringStartsWith(Card::API_GET_COLORS, $result['api']); + } + + //创建卡券 + public function testCreate() + { + $card = $this->getCard(); + + $cardType = 'GROUPON'; + + $baseInfo = [ + 'logo_url' => 'http://mmbiz.qpic.cn/mmbiz/2aJY6aCPatSeibYAyy7yct9zJXL9WsNVL4JdkTbBr184gNWS6nibcA75Hia9CqxicsqjYiaw2xuxYZiaibkmORS2oovdg/0', + 'brand_name' => '测试商户造梦空间', + 'code_type' => 'CODE_TYPE_QRCODE', + 'title' => '测试', + 'sub_title' => '测试副标题', + 'color' => 'Color010', + 'notice' => '测试使用时请出示此券', + 'service_phone' => '15311931577', + 'description' => "测试不可与其他优惠同享\n如需团购券发票,请在消费时向商户提出\n店内均可使用,仅限堂食", + + 'date_info' => [ + 'type' => 'DATE_TYPE_FIX_TERM', + 'fixed_term' => 90, //表示自领取后多少天内有效,不支持填写0 + 'fixed_begin_term' => 0, //表示自领取后多少天开始生效,领取后当天生效填写0。 + ], + + 'sku' => [ + 'quantity' => '0', //自定义code时设置库存为0 + ], + + 'location_id_list' => ['461907340'], //获取门店位置poi_id,具备线下门店的商户为必填 + + 'get_limit' => 1, + 'use_custom_code' => true, //自定义code时必须为true + 'get_custom_code_mode' => 'GET_CUSTOM_CODE_MODE_DEPOSIT', //自定义code时设置 + 'bind_openid' => false, + 'can_share' => true, + 'can_give_friend' => false, + 'center_title' => '顶部居中按钮', + 'center_sub_title' => '按钮下方的wording', + 'center_url' => 'http://www.qq.com', + 'custom_url_name' => '立即使用', + 'custom_url' => 'http://www.qq.com', + 'custom_url_sub_title' => '6个汉字tips', + 'promotion_url_name' => '更多优惠', + 'promotion_url' => 'http://www.qq.com', + 'source' => '造梦空间', + ]; + + $especial = [ + 'deal_detail' => 'deal_detail', + ]; + + $type = strtolower($cardType); + + $result = $card->create($cardType, $baseInfo, $especial); + $this->assertStringStartsWith(Card::API_CREATE, $result['api']); + $this->assertEquals($cardType, $result['params']['card']['card_type']); + $this->assertEquals($baseInfo, $result['params']['card'][$type]['base_info']); + } + + //创建二维码 + public function testQRCode() + { + $card = $this->getCard(); + + //领取单张卡券 + $cards = [ + 'action_name' => 'QR_CARD', + 'expire_seconds' => 1800, + 'action_info' => [ + 'card' => [ + 'card_id' => 'pdkJ9uFS2WWCFfbbEfsAzrzizVyY', + 'is_unique_code' => false, + 'outer_id' => 1, + ], + ], + ]; + + //领取多张卡券 + $cards = [ + 'action_name' => 'QR_MULTIPLE_CARD', + 'action_info' => [ + 'multiple_card' => [ + 'card_list' => [ + ['card_id' => 'pdkJ9uFS2WWCFfbbEfsAzrzizVyY'], + ], + ], + ], + ]; + + $result = $card->QRCode($cards); + $this->assertStringStartsWith(Card::API_QRCODE_CREATE, $result['api']); + $this->assertEquals($cards, $result['params']); + } + + //ticket 换取二维码图片 + public function testShowQRCode() + { + $card = $this->getCard(); + + $ticket = 'gQFF8DoAAAAAAAAAASxodHRwOi8vd2VpeGluLnFxLmNvbS9xL01VTzN0T0hsS1BwUlBBYUszbVN5AAIEughxVwMEAKd2AA=='; + $card->showQRCode($ticket); + } + + //通过ticket换取二维码 链接 + public function testGetQRCodeUrl() + { + $card = $this->getCard(); + + $ticket = 'gQFF8DoAAAAAAAAAASxodHRwOi8vd2VpeGluLnFxLmNvbS9xL01VTzN0T0hsS1BwUlBBYUszbVN5AAIEughxVwMEAKd2AA=='; + $card->getQRCodeUrl($ticket); + } + + //获取 卡券 Api_ticket + public function testGetAPITicket() + { + $http = $this->getMockHttp(); + $cache = $this->getMockCache(); + + $cache->shouldReceive('fetch')->andReturn('foo'); + $accessToken = $this->getMockAccessToken(); + $card = new Card($accessToken); + $card->setCache($cache); + $card->setHttp($http); + $card->setUrl('http://easywechat.org'); + + $cache->shouldReceive('save')->andReturn('foo'); + $this->assertNull($card->getAPITicket(true)); + } + + //微信卡券:JSAPI 卡券Package - 基础参数没有附带任何值 - 再生产环境中需要根据实际情况进行修改 + public function testWxCardPackage() + { + $cardList = [ + ['card_id' => 'pdkJ9uLRSbnB3UFEjZAgUxAJrjeY', 'outer_id' => 2], + ['card_id' => 'pdkJ9uJ37aU-tyRj4_grs8S45k1c', 'outer_id' => 3], + ]; + + $http = $this->getMockHttp(); + $cache = $this->getMockCache(); + $cache->shouldReceive('fetch')->andReturnUsing(function ($key) { + return 'overtrue.ticket'; + }); + $cache->shouldReceive('set')->andReturnUsing(function ($key, $ticket, $expires) { + return $ticket; + }); + + $http->shouldReceive('get')->andReturn(['ticket' => 'overtrue.ticket', 'expires_in' => 7200]); + $accessToken = $this->getMockAccessToken(); + $card = new Card($accessToken); + $card->setCache($cache); + $card->setHttp($http); + + $cache->shouldReceive('save')->andReturn('foo'); + $card->wxCardPackage($cardList); + } + + //创建货架接口 + public function testCreateLandingPage() + { + $card = $this->getCard(); + + $banner = 'http://mmbiz.qpic.cn/mmbiz/iaL1LJM1mF9aRKPZJkmG8xXhiaHqkKSVMMWeN3hLut7X7hicFN'; + $pageTitle = '惠城优惠大派送'; + $canShare = true; + + /** @var string $scene SCENE_NEAR_BY 附近, SCENE_MENU 自定义菜单, SCENE_QRCODE 二维码, SCENE_ARTICLE 公众号文章, SCENE_H5 h5页面, SCENE_IVR 自动回复, SCENE_CARD_CUSTOM_CELL 卡券自定义cell */ + $scene = 'SCENE_NEAR_BY'; + + $cardList = [ + ['card_id' => 'pdkJ9uLRSbnB3UFEjZAgUxAJrjeY', 'thumb_url' => 'http://test.digilinx.cn/wxApi/Uploads/test.png'], + ['card_id' => 'pdkJ9uJ37aU-tyRj4_grs8S45k1c', 'thumb_url' => 'http://test.digilinx.cn/wxApi/Uploads/aa.jpg'], + ]; + + $result = $card->createLandingPage($banner, $pageTitle, $canShare, $scene, $cardList); + $this->assertStringStartsWith(Card::API_LANDING_PAGE, $result['api']); + $this->assertEquals($banner, $result['params']['banner']); + $this->assertEquals($pageTitle, $result['params']['page_title']); + $this->assertEquals($canShare, $result['params']['can_share']); + $this->assertEquals($scene, $result['params']['scene']); + $this->assertEquals($cardList, $result['params']['card_list']); + } + + //导入code接口 + public function testDeposit() + { + $card = $this->getCard(); + + $cardId = 'pdkJ9uLCEF_HSKO7JdQOUcZ-PUzo'; + $code = ['11111', '22222', '33333']; + + $result = $card->deposit($cardId, $code); + $this->assertStringStartsWith(Card::API_DEPOSIT, $result['api']); + $this->assertEquals($cardId, $result['params']['card_id']); + $this->assertEquals($code, $result['params']['code']); + } + + //查询导入code数目 + public function testGetDepositedCount() + { + $card = $this->getCard(); + + $cardId = 'pdkJ9uLCEF_HSKO7JdQOUcZ-PUzo'; + + $result = $card->getDepositedCount($cardId); + $this->assertStringStartsWith(Card::API_GET_DEPOSIT_COUNT, $result['api']); + $this->assertEquals($cardId, $result['params']['card_id']); + } + + //核查code接口 + public function testCheckCode() + { + $card = $this->getCard(); + + $cardId = 'pdkJ9uLCEF_HSKO7JdQOUcZ-PUzo'; + + $code = ['807732265476', '22222', '33333']; + + $result = $card->checkCode($cardId, $code); + $this->assertStringStartsWith(Card::API_CHECK_CODE, $result['api']); + $this->assertEquals($cardId, $result['params']['card_id']); + $this->assertEquals($code, $result['params']['code']); + } + + //图文消息群发卡券 + public function testGetHtml() + { + $card = $this->getCard(); + + $cardId = 'pdkJ9uLCEF_HSKO7JdQOUcZ-PUzo'; + + $result = $card->getHtml($cardId); + $this->assertStringStartsWith(Card::API_GET_HTML, $result['api']); + $this->assertEquals($cardId, $result['params']['card_id']); + } + + //设置测试白名单 + public function testSetTestWhitelist() + { + $card = $this->getCard(); + + $openid = []; + $username = ['tianye0327']; + + $result = $card->setTestWhitelist($openid, $username); + $this->assertStringStartsWith(Card::API_TEST_WHITE_LIST, $result['api']); + $this->assertEquals($openid, $result['params']['openid']); + $this->assertEquals($username, $result['params']['username']); + } + + //查询Code接口 + public function testGetCode() + { + $card = $this->getCard(); + + $code = '736052543512'; + $checkConsume = true; + $cardId = 'pdkJ9uDgnm0pKfrTb1yV0dFMO_Gk'; + + $result = $card->getCode($code, $checkConsume, $cardId); + $this->assertStringStartsWith(Card::API_CODE_GET, $result['api']); + $this->assertEquals($code, $result['params']['code']); + $this->assertEquals($checkConsume, $result['params']['check_consume']); + $this->assertEquals($cardId, $result['params']['card_id']); + } + + //核销Code接口 + public function testConsume() + { + $card = $this->getCard(); + + $cardId = 'pdkJ9uDmhkLj6l5bm3cq9iteQBck'; + $code = '789248558333'; + + $result = $card->consume($cardId, $code); + $this->assertStringStartsWith(Card::API_CONSUME, $result['api']); + $this->assertEquals($cardId, $result['params']['card_id']); + $this->assertEquals($code, $result['params']['code']); + } + + //Code解码接口 + public function testDecryptCode() + { + $card = $this->getCard(); + + $encryptedCode = 'XXIzTtMqCxwOaawoE91+VJdsFmv7b8g0VZIZkqf4GWA60Fzpc8ksZ/5ZZ0DVkXdE'; + $result = $card->decryptCode($encryptedCode); + $this->assertStringStartsWith(Card::API_DECRYPT, $result['api']); + $this->assertEquals($encryptedCode, $result['params']['encrypt_code']); + } + + //获取用户已领取卡券接口 + public function testGetUserCards() + { + $card = $this->getCard(); + + $openid = 'odkJ9uDUz26RY-7DN1mxkznfo9xU'; + $cardId = ''; //卡券ID。不填写时默认查询当前appid下的卡券。 + + $result = $card->getUserCards($openid, $cardId); + $this->assertStringStartsWith(Card::API_GET_CARD_LIST, $result['api']); + $this->assertEquals($openid, $result['params']['openid']); + $this->assertEquals($cardId, $result['params']['card_id']); + } + + //查看卡券详情 + public function testGetCard() + { + $card = $this->getCard(); + + $cardId = 'pdkJ9uLRSbnB3UFEjZAgUxAJrjeY'; + + $result = $card->getCard($cardId); + $this->assertStringStartsWith(Card::API_CARD_GET, $result['api']); + $this->assertEquals($cardId, $result['params']['card_id']); + } + + //批量查询卡列表 + public function testLists() + { + $card = $this->getCard(); + + $offset = 0; + $count = 10; + $statusList = 'CARD_STATUS_VERIFY_OK'; + + $result = $card->lists($offset, $count, $statusList); + $this->assertStringStartsWith(Card::API_BATCH_GET, $result['api']); + $this->assertEquals($offset, $result['params']['offset']); + $this->assertEquals($count, $result['params']['count']); + $this->assertEquals($statusList, $result['params']['status_list']); + } + + //更改卡券信息接口 and 设置跟随推荐接口 + public function testUpdate() + { + $card = $this->getCard(); + + $cardId = 'pdkJ9uCzKWebwgNjxosee0ZuO3Os'; + + $type = 'groupon'; + + $baseInfo = [ + 'logo_url' => 'http://mmbiz.qpic.cn/mmbiz/2aJY6aCPatSeibYAyy7yct9zJXL9WsNVL4JdkTbBr184gNWS6nibcA75Hia9CqxicsqjYiaw2xuxYZiaibkmORS2oovdg/0', + 'center_title' => '顶部居中按钮', + 'center_sub_title' => '按钮下方的wording', + 'center_url' => 'http://www.baidu.com', + 'custom_url_name' => '立即使用', + 'custom_url' => 'http://www.qq.com', + 'custom_url_sub_title' => '6个汉字tips', + 'promotion_url_name' => '更多优惠', + 'promotion_url' => 'http://www.qq.com', + ]; + + $result = $card->update($cardId, $type, $baseInfo); + $this->assertStringStartsWith(Card::API_UPDATE, $result['api']); + $this->assertEquals($cardId, $result['params']['card_id']); + $this->assertEquals($baseInfo, $result['params'][$type]['base_info']); + } + + //设置微信买单接口 + public function testSetPayCell() + { + $card = $this->getCard(); + + $cardId = 'pdkJ9uH7u11R-Tu1kilbaW_zDFow'; + $isOpen = true; + + $result = $card->setPayCell($cardId, $isOpen); + $this->assertStringStartsWith(Card::API_PAY_CELL_SET, $result['api']); + $this->assertEquals($cardId, $result['params']['card_id']); + $this->assertEquals($isOpen, $result['params']['is_open']); + } + + //修改库存接口 + public function testModifyStock() + { + $card = $this->getCard(); + + $cardId = 'pdkJ9uLRSbnB3UFEjZAgUxAJrjeY'; + $stock = 'increase'; //increase 增加 reduce 减少 + $value = 100; + + $result = $card->modifyStock($cardId, $stock, $value); + $this->assertStringStartsWith(Card::API_MODIFY_STOCK, $result['api']); + $this->assertEquals($cardId, $result['params']['card_id']); + } + + //更改Code接口 + //为确保转赠后的安全性,微信允许自定义Code的商户对已下发的code进行更改。 + //注:为避免用户疑惑,建议仅在发生转赠行为后(发生转赠后,微信会通过事件推送的方式告知商户被转赠的卡券Code)对用户的Code进行更改。 + public function testUpdateCode() + { + $card = $this->getCard(); + + $code = '148246271394'; + $newCode = '659266965266'; + $cardId = ''; + + $result = $card->updateCode($code, $newCode, $cardId); + $this->assertStringStartsWith(Card::API_CODE_UPDATE, $result['api']); + $this->assertEquals($code, $result['params']['code']); + $this->assertEquals($newCode, $result['params']['new_code']); + $this->assertEquals($cardId, $result['params']['card_id']); + } + + //删除卡券接口 + public function testDelete() + { + $card = $this->getCard(); + + $cardId = 'pdkJ9uItT7iUpBp4GjZp8Cae0Vig'; + + $result = $card->delete($cardId); + $this->assertStringStartsWith(Card::API_CARD_DELETE, $result['api']); + $this->assertEquals($cardId, $result['params']['card_id']); + } + + //设置卡券失效 + public function testDisable() + { + $card = $this->getCard(); + + $code = '736052543512'; + $cardId = ''; + + $result = $card->disable($code, $cardId); + $this->assertStringStartsWith(Card::API_UNAVAILABLE, $result['api']); + $this->assertEquals($code, $result['params']['code']); + $this->assertEquals($cardId, $result['params']['card_id']); + } + + //会员卡接口激活 + public function testActivate() + { + $card = $this->getCard(); + + $activate = [ + 'membership_number' => '357898858', //会员卡编号,由开发者填入,作为序列号显示在用户的卡包里。可与Code码保持等值。 + 'code' => '916679873278', //创建会员卡时获取的初始code。 + 'activate_begin_time' => '1397577600', //激活后的有效起始时间。若不填写默认以创建时的 data_info 为准。Unix时间戳格式 + 'activate_end_time' => '1422724261', //激活后的有效截至时间。若不填写默认以创建时的 data_info 为准。Unix时间戳格式。 + 'init_bonus' => '持白金会员卡到店消费,可享8折优惠。', //初始积分,不填为0。 + 'init_balance' => '持白金会员卡到店消费,可享8折优惠。', //初始余额,不填为0。 + 'init_custom_field_value1' => '白银', //创建时字段custom_field1定义类型的初始值,限制为4个汉字,12字节。 + 'init_custom_field_value2' => '9折', //创建时字段custom_field2定义类型的初始值,限制为4个汉字,12字节。 + 'init_custom_field_value3' => '200', //创建时字段custom_field3定义类型的初始值,限制为4个汉字,12字节。 + ]; + + $result = $card->activate($activate); + $this->assertStringStartsWith(Card::API_CARD_ACTIVATE, $result['api']); + $this->assertEquals($activate, $result['params']); + } + + //设置开卡字段接口 + public function testActivateUserForm() + { + $card = $this->getCard(); + + $cardId = 'pdkJ9uJYAyfLXsUCwI2LdH2Pn1AU'; + + $requiredForm = []; + $requiredForm['common_field_id_list'] = [ + 'USER_FORM_INFO_FLAG_MOBILE', + 'USER_FORM_INFO_FLAG_LOCATION', + 'USER_FORM_INFO_FLAG_BIRTHDAY', + ]; + $requiredForm['custom_field_list'] = ['喜欢的食物']; + + $optionalForm = []; + $optionalForm['common_field_id_list'] = [ + 'USER_FORM_INFO_FLAG_EMAIL', + ]; + $optionalForm['custom_field_list'] = ['喜欢的电影']; + + $result = $card->activateUserForm($cardId, $requiredForm, $optionalForm); + $this->assertStringStartsWith(Card::API_ACTIVATE_USER_FORM, $result['api']); + $this->assertEquals($cardId, $result['params']['card_id']); + } + + //拉取会员信息接口 + public function testGetMemberCardUser() + { + $card = $this->getCard(); + + $cardId = 'pbLatjtZ7v1BG_ZnTjbW85GYc_E8'; + $code = '916679873278'; + + $result = $card->getMemberCardUser($cardId, $code); + $this->assertStringStartsWith(Card::API_MEMBER_USER_INFO, $result['api']); + $this->assertEquals($cardId, $result['params']['card_id']); + $this->assertEquals($code, $result['params']['code']); + } + + //更新会员信息 + public function testUpdateMemberCardUser() + { + $card = $this->getCard(); + + $updateUser = [ + 'code' => '916679873278', //卡券Code码。 + 'card_id' => 'pbLatjtZ7v1BG_ZnTjbW85GYc_E8', //卡券ID。 + 'record_bonus' => '消费30元,获得3积分', //商家自定义积分消耗记录,不超过14个汉字。 + 'bonus' => '100', //需要设置的积分全量值,传入的数值会直接显示,如果同时传入add_bonus和bonus,则前者无效。 + 'balance' => '持白金会员卡到店消费,可享8折优惠。', //需要设置的余额全量值,传入的数值会直接显示,如果同时传入add_balance和balance,则前者无效。 + 'record_balance' => '持白金会员卡到店消费,可享8折优惠。', //商家自定义金额消耗记录,不超过14个汉字。 + 'custom_field_value1' => '100', //创建时字段custom_field1定义类型的最新数值,限制为4个汉字,12字节。 + 'custom_field_value2' => '200', //创建时字段custom_field2定义类型的最新数值,限制为4个汉字,12字节。 + 'custom_field_value3' => '300', //创建时字段custom_field3定义类型的最新数值,限制为4个汉字,12字节。 + ]; + + $result = $card->updateMemberCardUser($updateUser); + $this->assertStringStartsWith(Card::API_UPDATE_USER, $result['api']); + $this->assertEquals($updateUser, $result['params']); + } + + //添加子商户 + public function testSubMerchant() + { + $card = $this->getCard(); + + $brandName = 'aaaaaa'; + $appId = ''; + $logoUrl = 'http://mmbiz.qpic.cn/mmbiz/iaL1LJM1mF9aRKPZJkmG8xXhiaHqkKSVMMWeN3hLut7X7hicFNjakmxibMLGWpXrEXB33367o7zHN0CwngnQY7zb7g/0'; + $protocol = 'qIqwTfzAdJ_1-VJFT0fIV53DSY4sZY2WyhkzZzbV498Qgdp-K5HJtZihbHLS0Ys0'; + $agreementMediaId = ''; + $operatorMediaId = ''; + $endTime = 1438990559; + $primaryCategoryId = 1; + $secondaryCategoryId = 101; + + $result = $card->subMerchant($brandName, $logoUrl, $protocol, $endTime, $primaryCategoryId, $secondaryCategoryId, $agreementMediaId, $operatorMediaId, $appId); + $this->assertStringStartsWith(Card::API_SUB_MERCHANT, $result['api']); + $this->assertEquals($brandName, $result['params']['info']['brand_name']); + $this->assertEquals($appId, $result['params']['info']['app_id']); + $this->assertEquals($logoUrl, $result['params']['info']['logo_url']); + $this->assertEquals($protocol, $result['params']['info']['protocol']); + $this->assertEquals($agreementMediaId, $result['params']['info']['agreement_media_id']); + $this->assertEquals($operatorMediaId, $result['params']['info']['operator_media_id']); + $this->assertEquals($endTime, $result['params']['info']['end_time']); + $this->assertEquals($primaryCategoryId, $result['params']['info']['primary_category_id']); + $this->assertEquals($secondaryCategoryId, $result['params']['info']['secondary_category_id']); + } + + //卡券开放类目查询接口 + public function testGetApplyProtocol() + { + $card = $this->getCard(); + + $result = $card->getApplyProtocol(); + $this->assertStringStartsWith(Card::API_GET_APPLY_PROTOCOL, $result['api']); + } +}