ProgramSubscribe.php 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. <?php
  2. namespace crmeb\services\subscribe;
  3. use EasyWeChat\Core\AbstractAPI;
  4. use EasyWeChat\Core\AccessToken;
  5. use EasyWeChat\Core\Exceptions\InvalidArgumentException;
  6. /**
  7. * 小程序订阅消息
  8. * Class ProgramSubscribe
  9. * @package crmeb\utils
  10. * @method $this
  11. * @method $this template(string $template_id) 设置模板id
  12. * @method $this withTemplateId(string $template_id) 设置模板id
  13. * @method $this andTemplateId(string $template_id) 设置模板id
  14. * @method $this andTemplate(string $template_id) 设置模板id
  15. * @method $this andUses(string $template_id) 设置模板id
  16. * @method $this to(string $touser) 设置opendid
  17. * @method $this andReceiver(string $touser) 设置opendid
  18. * @method $this withReceiver(string $touser) 设置opendid
  19. * @method $this with(array $data) 设置发送内容
  20. * @method $this andData(array $data) 设置发送内容
  21. * @method $this withData(array $data) 设置发送内容
  22. * @method $this data(array $data) 设置发送内容
  23. * @method $this withUrl(string $page) 设置跳转路径
  24. */
  25. class ProgramSubscribe extends AbstractAPI
  26. {
  27. /**
  28. * 添加模板接口
  29. */
  30. const API_SET_TEMPLATE_ADD = 'https://api.weixin.qq.com/wxaapi/newtmpl/addtemplate';
  31. /**
  32. * 删除模板消息接口
  33. */
  34. const API_SET_TEMPLATE_DEL = 'https://api.weixin.qq.com/wxaapi/newtmpl/deltemplate';
  35. /**
  36. * 获取模板消息列表
  37. */
  38. const API_GET_TEMPLATE_LIST = 'https://api.weixin.qq.com/wxaapi/newtmpl/gettemplate';
  39. /**
  40. * 获取模板消息分类
  41. */
  42. const API_GET_TEMPLATE_CATE = 'https://api.weixin.qq.com/wxaapi/newtmpl/getcategory';
  43. /**
  44. * 获取模板消息关键字
  45. */
  46. const API_GET_TEMPLATE_KEYWORKS = 'https://api.weixin.qq.com/wxaapi/newtmpl/getpubtemplatekeywords';
  47. /**
  48. * 获取公共模板
  49. */
  50. const API_GET_PUBLIC_TEMPLATE = 'https://api.weixin.qq.com/wxaapi/newtmpl/getpubtemplatetitles';
  51. /**
  52. * 发送模板消息
  53. */
  54. const API_SUBSCRIBE_SEND = 'https://api.weixin.qq.com/cgi-bin/message/subscribe/send';
  55. /**
  56. * Attributes
  57. * @var array
  58. */
  59. protected $message = [
  60. 'touser' => '',
  61. 'template_id' => '',
  62. 'page' => '',
  63. 'data' => [],
  64. ];
  65. /**
  66. * Message backup.
  67. *
  68. * @var array
  69. */
  70. protected $messageBackup;
  71. protected $required = ['template_id', 'touser'];
  72. /**
  73. * ProgramSubscribeService constructor.
  74. * @param AccessToken $accessToken
  75. */
  76. public function __construct(AccessToken $accessToken)
  77. {
  78. parent::__construct($accessToken);
  79. $this->messageBackup = $this->message;
  80. }
  81. /**
  82. * 获取当前拥有的模板列表
  83. * @return \EasyWeChat\Support\Collection|null
  84. * @throws \EasyWeChat\Core\Exceptions\HttpException
  85. */
  86. public function getTemplateList()
  87. {
  88. return $this->parseJSON('get', [self::API_GET_TEMPLATE_LIST]);
  89. }
  90. /**
  91. * 获取公众模板列表
  92. * @param string $ids
  93. * @param int $start
  94. * @param int $limit
  95. * @return \EasyWeChat\Support\Collection|null
  96. * @throws \EasyWeChat\Core\Exceptions\HttpException
  97. */
  98. public function getPublicTemplateList(string $ids, int $start = 0, int $limit = 10)
  99. {
  100. $params = [
  101. 'ids' => $ids,
  102. 'start' => $start,
  103. 'limit' => $limit
  104. ];
  105. return $this->parseJSON('get', [self::API_GET_PUBLIC_TEMPLATE, $params]);
  106. }
  107. /**
  108. * 获取模板分类
  109. * @return \EasyWeChat\Support\Collection|null
  110. * @throws \EasyWeChat\Core\Exceptions\HttpException
  111. */
  112. public function getTemplateCate()
  113. {
  114. return $this->parseJSON('get', [self::API_GET_TEMPLATE_CATE]);
  115. }
  116. /**
  117. * 获取模板标题下的关键词列表
  118. * @param string $tid 模板标题 id,可通过接口获取
  119. * @return \EasyWeChat\Support\Collection|null
  120. * @throws \EasyWeChat\Core\Exceptions\HttpException
  121. */
  122. public function getPublicTemplateKeywords(string $tid)
  123. {
  124. $params = [
  125. 'tid' => $tid
  126. ];
  127. return $this->parseJSON('get', [self::API_GET_TEMPLATE_KEYWORKS, $params]);
  128. }
  129. /**
  130. * 添加订阅模板消息
  131. * @param string $tid 模板标题 id,可通过接口获取,也可登录小程序后台查看获取
  132. * @param array $kidList 模板序列号 关键词顺序可以自由搭配(例如 [3,5,4] 或 [4,5,3]),最多支持5个,最少2个关键词组合
  133. * @param string $sceneDesc 服务场景描述,15个字以内
  134. * @return \EasyWeChat\Support\Collection|null
  135. * @throws \EasyWeChat\Core\Exceptions\HttpException
  136. */
  137. public function addTemplate(string $tid, array $kidList, string $sceneDesc = '')
  138. {
  139. $params = [
  140. 'tid' => $tid,
  141. 'kidList' => $kidList,
  142. 'sceneDesc' => $sceneDesc,
  143. ];
  144. return $this->parseJSON('json', [self::API_SET_TEMPLATE_ADD, $params]);
  145. }
  146. /**
  147. * 删除模板消息
  148. * @param string $priTmplId
  149. * @return \EasyWeChat\Support\Collection|null
  150. * @throws \EasyWeChat\Core\Exceptions\HttpException
  151. */
  152. public function delTemplate(string $priTmplId)
  153. {
  154. $params = [
  155. 'priTmplId' => $priTmplId
  156. ];
  157. return $this->parseJSON('json', [self::API_SET_TEMPLATE_DEL, $params]);
  158. }
  159. /**
  160. * 发送订阅消息
  161. * @param array $data
  162. * @return \EasyWeChat\Support\Collection|null
  163. * @throws InvalidArgumentException
  164. * @throws \EasyWeChat\Core\Exceptions\HttpException
  165. */
  166. public function send(array $data = [])
  167. {
  168. $params = array_merge($this->message, $data);
  169. foreach ($params as $key => $value) {
  170. if (in_array($key, $this->required, true) && empty($value) && empty($this->message[$key])) {
  171. throw new InvalidArgumentException("Attribute '$key' can not be empty!");
  172. }
  173. $params[$key] = empty($value) ? $this->message[$key] : $value;
  174. }
  175. $params['data'] = $this->formatData($params['data']);
  176. $this->message = $this->messageBackup;
  177. return $this->parseJSON('json', [self::API_SUBSCRIBE_SEND, $params]);
  178. }
  179. /**
  180. * 设置订阅消息发送data
  181. * @param array $data
  182. * @return array
  183. */
  184. protected function formatData(array $data)
  185. {
  186. $return = [];
  187. foreach ($data as $key => $item) {
  188. if (is_scalar($item)) {
  189. $value = $item;
  190. } elseif (is_array($item) && !empty($item)) {
  191. if (isset($item['value'])) {
  192. $value = strval($item['value']);
  193. } elseif (count($item) < 2) {
  194. $value = array_shift($item);
  195. } else {
  196. [$value] = $item;
  197. }
  198. } else {
  199. $value = 'error data item.';
  200. }
  201. $return[$key] = ['value' => $value];
  202. }
  203. return $return;
  204. }
  205. /**
  206. * Magic access..
  207. *
  208. * @param $method
  209. * @param $args
  210. * @return $this
  211. */
  212. public function __call($method, $args)
  213. {
  214. $map = [
  215. 'template' => 'template_id',
  216. 'templateId' => 'template_id',
  217. 'uses' => 'template_id',
  218. 'to' => 'touser',
  219. 'receiver' => 'touser',
  220. 'url' => 'page',
  221. 'link' => 'page',
  222. 'data' => 'data',
  223. 'with' => 'data',
  224. ];
  225. if (0 === stripos($method, 'with') && strlen($method) > 4) {
  226. $method = lcfirst(substr($method, 4));
  227. }
  228. if (0 === stripos($method, 'and')) {
  229. $method = lcfirst(substr($method, 3));
  230. }
  231. if (isset($map[$method])) {
  232. $this->message[$map[$method]] = array_shift($args);
  233. }
  234. return $this;
  235. }
  236. }