发布: 初始化 WeChatDeveloper 2.0 开源版

This commit is contained in:
Anyon 2026-05-04 13:56:46 +08:00
parent 5aff97be52
commit 872eef4eee
186 changed files with 3268 additions and 17575 deletions

34
.github/workflows/ci.yml vendored Normal file
View File

@ -0,0 +1,34 @@
name: CI
on:
push:
branches:
- master
- '2.0'
pull_request:
permissions:
contents: read
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.4'
extensions: json, openssl, simplexml
coverage: none
- name: Validate composer metadata
run: composer validate --strict
- name: Install dependencies
run: composer install --no-interaction --prefer-dist --no-progress
- name: Run tests
run: composer test

View File

@ -1,11 +1,12 @@
name: Create Release
on:
push:
# Sequence of patterns matched against refs/tags
tags:
- 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10
- 'v*'
name: Create Release
permissions: write-all
permissions:
contents: write
jobs:
release:
@ -16,50 +17,34 @@ jobs:
with:
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 18
- name: Install dependencies
run: npm install -g gen-git-log
- name: Find Last Tag
id: last_tag
- name: Resolve previous tag
id: tags
shell: bash
run: |
# 获取所有标签,按版本排序(降序)
Tags=$(git tag --list --sort=-version:refname)
# 获取最新的标签(即列表中的第一个)
LATEST_TAG=$(echo "$Tags" | awk 'NR==1 {print $1; exit}')
# 获取倒数第二个标签(如果存在)
if [[ -n "$Tags" ]]; then
# 使用 tail 获取除了最后一个标签之外的所有标签,然后用 head 获取第一个
SECOND_LATEST_TAG=$(echo "$Tags" | tail -n +2 | head -n 1)
else
SECOND_LATEST_TAG=""
current="${GITHUB_REF_NAME}"
previous="$(git tag --list 'v*' --sort=-version:refname | grep -v "^${current}$" | head -n 1 || true)"
echo "current=${current}" >> "$GITHUB_OUTPUT"
echo "previous=${previous}" >> "$GITHUB_OUTPUT"
- name: Build release notes
shell: bash
run: |
current="${{ steps.tags.outputs.current }}"
previous="${{ steps.tags.outputs.previous }}"
if [ -n "$previous" ]; then
git log --pretty='- %s (%h)' "${previous}..${current}" > RELEASE_NOTES.md
else
git log --pretty='- %s (%h)' "${current}" > RELEASE_NOTES.md
fi
if [ ! -s RELEASE_NOTES.md ]; then
echo "- Release ${current}" > RELEASE_NOTES.md
fi
# 设置输出变量
echo "::set-output name=tag_last::${LATEST_TAG:-v1.0.0}"
echo "::set-output name=tag_second::${SECOND_LATEST_TAG:-v1.0.0}"
- name: Generate Release Notes
run: |
rm -rf log
newTag=${{ steps.last_tag.outputs.tag_last }}
git-log -m tag -f -S ${{ steps.last_tag.outputs.tag_second }} -v ${newTag#v}
- name: Create Release
id: create_release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Create GitHub release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ steps.last_tag.outputs.tag_last }}
release_name: Release ${{ steps.last_tag.outputs.tag_last }}
body_path: log/${{steps.last_tag.outputs.tag_last}}.md
tag_name: ${{ steps.tags.outputs.current }}
name: Release ${{ steps.tags.outputs.current }}
body_path: RELEASE_NOTES.md
draft: false
prerelease: false
prerelease: false

18
.gitignore vendored
View File

@ -1,9 +1,9 @@
/.git
/.idea
/.DS_Store
/vendor
/Cache
/Test/cert
/nbproject
/composer.lock
/_test/cert
.DS_Store
.idea/
vendor/
composer.lock
.phpunit.cache/
Cache/
Test/cert/
_test/cert/
nbproject/

View File

@ -1,49 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace AliPay;
use WeChat\Contracts\BasicAliPay;
/**
* 支付宝App支付网关
* @package AliPay
*/
class App extends BasicAliPay
{
/**
* 构造函数
* @param array $options 支付宝配置参数
*/
public function __construct(array $options)
{
parent::__construct($options);
$this->options->set('method', 'alipay.trade.app.pay');
$this->params->set('product_code', 'QUICK_MSECURITY_PAY');
}
/**
* 生成APP支付参数字符串
* @param array $options 订单参数out_trade_no, total_amount, subject等
* @return string URL编码后的参数字符串用于APP调起支付
*/
public function apply($options)
{
$this->applyData($options);
return http_build_query($this->options->get());
}
}

View File

@ -1,48 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace AliPay;
use WeChat\Contracts\BasicAliPay;
/**
* 支付宝电子面单下载
* @package AliPay
*/
class Bill extends BasicAliPay
{
/**
* 构造函数
* @param array $options 支付宝配置参数
*/
public function __construct(array $options)
{
parent::__construct($options);
$this->options->set('method', 'alipay.data.dataservice.bill.downloadurl.query');
}
/**
* 获取账单下载地址
* @param array $options 账单参数bill_type, bill_date 等)
* @return array 包含 bill_download_url 的响应数据
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function apply($options)
{
return $this->getResult($options);
}
}

View File

@ -1,49 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace AliPay;
use WeChat\Contracts\BasicAliPay;
/**
* 支付宝刷卡支付
* @package AliPay
*/
class Pos extends BasicAliPay
{
/**
* 构造函数
* @param array $options 支付宝配置参数
*/
public function __construct(array $options)
{
parent::__construct($options);
$this->options->set('method', 'alipay.trade.pay');
$this->params->set('product_code', 'FACE_TO_FACE_PAYMENT');
}
/**
* 刷卡支付(条码/声波)下单
* @param array $options 订单参数out_trade_no, auth_code, subject, total_amount 等)
* @return array 支付结果
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function apply($options)
{
return $this->getResult($options);
}
}

View File

@ -1,48 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace AliPay;
use WeChat\Contracts\BasicAliPay;
/**
* 支付宝扫码支付
* @package AliPay
*/
class Scan extends BasicAliPay
{
/**
* 构造函数
* @param array $options 支付宝配置参数
*/
public function __construct(array $options)
{
parent::__construct($options);
$this->options->set('method', 'alipay.trade.precreate');
}
/**
* 预创建扫码支付订单(返回二维码地址)
* @param array $options 订单参数out_trade_no, subject, total_amount 等)
* @return array 包含 qr_code 的预下单结果
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function apply($options)
{
return $this->getResult($options);
}
}

View File

@ -1,81 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace AliPay;
use WeChat\Contracts\BasicAliPay;
/**
* 支付宝标准接口
* @package AliPay
*/
class Trade extends BasicAliPay
{
/**
* 设置交易接口方法名
* @param string $method alipay.trade.close
* @return $this
*/
public function setMethod($method)
{
$this->options->set('method', $method);
return $this;
}
/**
* 获取当前交易接口方法名
* @return string
*/
public function getMethod()
{
return $this->options->get('method');
}
/**
* 设置公共参数(透传到 options
* @param array $option key-value 公共参数
* @return Trade
*/
public function setOption($option = [])
{
foreach ($option as $key => $vo) {
$this->options->set($key, $vo);
}
return $this;
}
/**
* 获取当前公共参数
* @return array|string|null
*/
public function getOption()
{
return $this->options->get();
}
/**
* 执行当前设置的交易接口
* @param array $options 业务参数(写入 biz_content
* @return array 接口返回结果
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function apply($options)
{
return $this->getResult($options);
}
}

View File

@ -1,79 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace AliPay;
use WeChat\Contracts\BasicAliPay;
/**
* 支付宝转账到账户
* @package AliPay
*/
class Transfer extends BasicAliPay
{
/**
* 旧版向支付宝账户转账toaccount.transfer
* @param array $options 转账参数out_biz_no, payee_type, payee_account, amount, remark 等)
* @return array 转账结果
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function apply($options)
{
$this->options->set('method', 'alipay.fund.trans.toaccount.transfer');
return $this->getResult($options);
}
/**
* 新版统一转账接口uni.transfer
* @param array $options 转账参数out_biz_no, trans_amount, product_code, payee_info 等)
* @return array 转账结果
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function create($options = [])
{
$this->options->set('method', 'alipay.fund.trans.uni.transfer');
return $this->getResult($options);
}
/**
* 新版:转账业务单据查询
* @param array $options 查询参数out_biz_no order_id
* @return array 查询结果
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function queryResult($options = [])
{
$this->options->set('method', 'alipay.fund.trans.common.query');
return $this->getResult($options);
}
/**
* 新版:资金账户余额查询
* @param array $options 查询参数alipay_user_id user_id可选 account_type
* @return array 账户余额等信息
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function queryAccount($options = [])
{
$this->options->set('method', 'alipay.fund.account.query');
return $this->getResult($options);
}
}

View File

@ -1,48 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace AliPay;
use WeChat\Contracts\BasicAliPay;
/**
* 手机WAP网站支付支持
* @package AliPay
*/
class Wap extends BasicAliPay
{
/**
* 构造函数
* @param array $options 支付宝配置参数
*/
public function __construct(array $options)
{
parent::__construct($options);
$this->options->set('method', 'alipay.trade.wap.pay');
$this->params->set('product_code', 'QUICK_WAP_WAY');
}
/**
* 生成 WAP 支付表单 HTML
* @param array $options 订单参数out_trade_no, total_amount, subject, quit_url, return_url 等)
* @return string 自动提交的支付表单 HTML
*/
public function apply($options)
{
parent::applyData($options);
return $this->buildPayHtml();
}
}

View File

@ -1,48 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace AliPay;
use WeChat\Contracts\BasicAliPay;
/**
* 支付宝网站支付
* @package AliPay
*/
class Web extends BasicAliPay
{
/**
* 构造函数
* @param array $options 支付宝配置参数
*/
public function __construct(array $options)
{
parent::__construct($options);
$this->options->set('method', 'alipay.trade.page.pay');
$this->params->set('product_code', 'FAST_INSTANT_TRADE_PAY');
}
/**
* 生成网站支付表单HTML
* @param array $options 订单参数out_trade_no, total_amount, subject等
* @return string 支付表单HTML自动提交到支付宝
*/
public function apply($options)
{
parent::applyData($options);
return $this->buildPayHtml();
}
}

View File

450
README.md Normal file
View File

@ -0,0 +1,450 @@
# WeChatDeveloper
WeChatDeveloper 是一个面向 **微信****支付宝** 的轻量 PHP SDK根命名空间为 `We`
它只维护基础认证、通用 HTTP 调用、签名验签、回调解密和统一异常,不内置业务表结构、不绑定具体框架,也不维护海量接口别名。业务系统按官方文档传入接口 path、参数和配置即可。
## 特性
- 支持微信公众号、小程序、微信开放平台、微信支付 APIv3。
- 支持支付宝开放平台与支付网关调用。
- 统一入口 `We\Client`,按通道创建客户端。
- 配置对象实现 `ConfigInterface`,构造时完成基础校验。
- 缓存只依赖 `StoreCacheInterface`,可用于单机文件缓存或集群 Redis 适配。
- 开放平台授权方 refresh token 通过 `StoreTokenInterface` 由业务系统存取。
- 返回值默认是数组,失败时抛出 `WechatException` 或其子类。
## 环境要求
- PHP `>= 8.4`
- `ext-json`
- `ext-openssl`
- `ext-simplexml`
- `guzzlehttp/guzzle`
- `psr/simple-cache`
## 安装
稳定版发布后:
```bash
composer require zoujingli/wechat-developer:^2.0
```
开发版:
```bash
composer require zoujingli/wechat-developer:2.0.x-dev
```
源码开发:
```bash
cd WeChatDeveloper
composer install
composer test
```
## 快速开始
```php
<?php
declare(strict_types=1);
use We\Client;
use We\Config\WechatPlatformConfig;
$client = new Client();
$official = $client->wechatPlatform(new WechatPlatformConfig(
appid: 'wx_appid',
appSecret: 'app_secret',
));
$users = $official->get('cgi-bin/user/get', [
'next_openid' => '',
]);
```
`post()``get()``call()` 的 path 与官方文档保持一致,通常不需要前导 `/`
```php
$menu = $official->post('cgi-bin/menu/create', [
'button' => [
[
'type' => 'click',
'name' => '今日推荐',
'key' => 'TODAY',
],
],
]);
```
## 入口 Client
```php
use GuzzleHttp\ClientInterface;
use We\Client;
use We\Contract\StoreCacheInterface;
use We\Contract\StoreTokenInterface;
new Client(
?StoreCacheInterface $cache = null,
?StoreTokenInterface $authorizers = null,
?ClientInterface $http = null,
string $cacheKeyPrefix = Client::DEFAULT_CACHE_KEY_PREFIX,
);
```
参数说明:
| 参数 | 说明 |
|------|------|
| `$cache` | SDK 运行态缓存,主要保存 access token不传时默认使用 `FileCacheStore`。 |
| `$authorizers` | 微信开放平台代调用时,读取和回写授权方 refresh token。 |
| `$http` | 可注入自定义 Guzzle HTTP 客户端,便于统一超时、代理或单元测试。 |
| `$cacheKeyPrefix` | 缓存键前缀,默认 `wechat_developer`;生产环境建议按项目设置。 |
也可以用字符串通道创建客户端:
```php
$official = $client->get('wechat.platform', WechatPlatformConfig::fromArray($config));
```
支持的通道:
| 通道 | 工厂方法 | 配置对象 |
|------|----------|----------|
| `wechat.platform` | `wechatPlatform()` | `WechatPlatformConfig` |
| `wechat.wxapp` | `wechatWxapp()` | `WechatWxappConfig` |
| `wechat.service` | `wechatService()` | `WechatServiceConfig` |
| `wechat.payment` | `wechatPayment()` | `WechatPaymentConfig` |
| `alipay.platform` | `alipayPlatform()` | `AlipayPlatformConfig` |
| `alipay.payment` | `alipayPayment()` | `AlipayPaymentConfig` |
## 配置对象
所有配置对象都实现 `ConfigInterface`
```php
interface ConfigInterface
{
public static function fromArray(array $data): static;
public function validate(): void;
}
```
构造函数会调用 `validate()`。缺少必填字段时会抛出 `WechatException`
示例:
```php
use We\Config\WechatWxappConfig;
$config = WechatWxappConfig::fromArray([
'appid' => 'wx_appid',
'appsecret' => 'app_secret',
'storage_scope' => 'tenant:1',
]);
```
`storage_scope` 是可选的缓存分桶标识。同一个 appid 在多租户或多业务账号下需要隔离 token 时可以设置。
## 缓存与锁
access token 统一通过 `StoreCacheInterface` 存储:
```php
interface StoreCacheInterface
{
public function get(string $key, mixed $default = null): mixed;
public function set(string $key, mixed $value, int $ttl): void;
public function del(string $key): void;
public function lock(string $key, int $ttl, callable $callback): mixed;
}
```
内置实现:
| 类 | 说明 |
|----|------|
| `We\Support\FileCacheStore` | 默认单机文件缓存,使用 JSON 文件保存数据,刷新锁使用 `flock`。 |
| `We\Support\PsrSimpleCacheStore` | PSR-16 缓存适配器,适合 Redis、Memcached 或框架缓存。锁能力需由构造参数注入。 |
| `We\Support\NullCacheStore` | 空缓存,适合测试或明确不缓存的场景。 |
单机文件缓存:
```php
use We\Client;
use We\Support\FileCacheStore;
$client = new Client(
cache: new FileCacheStore(__DIR__ . '/runtime/wechat-cache'),
cacheKeyPrefix: 'my_app',
);
```
PSR-16 缓存:
```php
use Psr\SimpleCache\CacheInterface;
use We\Client;
use We\Support\PsrSimpleCacheStore;
/** @var CacheInterface $cache */
$client = new Client(
cache: new PsrSimpleCacheStore(
cache: $cache,
locker: static function (string $key, int $ttl, callable $callback): mixed {
// 在这里接入 Redis SET NX、框架锁或其他原子锁。
return $callback();
},
),
);
```
如果使用 `PsrSimpleCacheStore` 且未配置锁回调,调用 `lock()` 会抛出明确异常。集群部署时必须使用共享缓存和可用的原子锁,避免并发刷新 access token。
缓存键固定为:
```text
{cacheKeyPrefix}:{channel}:{logicalKey}
```
例如:
```text
my_app:wechat.platform:wechat:app:wx123:official:access_token
```
完整键由 `CacheKey` 生成,微信 token 逻辑键由 `TokenCacheKey` 生成。
## 微信开放平台授权方 Token
开放平台代调用授权方接口时SDK 需要读取授权方 refresh token并在刷新后把新 token 回写业务存储。业务系统实现 `StoreTokenInterface` 即可:
```php
use We\Contract\StoreTokenInterface;
final class AuthorizerTokenStore implements StoreTokenInterface
{
public function refreshToken(string $authorizerAppid): string
{
// 从数据库读取 authorizer_refresh_token。
return 'authorizer_refresh_token';
}
public function saveAuthorizerToken(string $authorizerAppid, array $payload): void
{
// 保存 authorizer_access_token、authorizer_refresh_token、expires_in 等平台返回数据。
}
}
```
注入到根 Client
```php
$client = new Client(
cache: $cache,
authorizers: new AuthorizerTokenStore(),
);
```
## 微信公众号
```php
use We\Config\WechatPlatformConfig;
$official = $client->wechatPlatform(new WechatPlatformConfig(
appid: 'wx_appid',
appSecret: 'app_secret',
token: 'message_token',
encodingAesKey: 'encoding_aes_key',
));
$accessToken = $official->accessToken();
$result = $official->post('cgi-bin/message/custom/send', [
'touser' => 'openid',
'msgtype' => 'text',
'text' => ['content' => 'hello'],
]);
```
安全模式消息解密:
```php
$plain = $official->post('decrypt_message', [
'body' => $rawBody,
'msg_signature' => $signature,
'timestamp' => $timestamp,
'nonce' => $nonce,
]);
```
## 微信小程序
```php
use We\Config\WechatWxappConfig;
$wxapp = $client->wechatWxapp(new WechatWxappConfig(
appid: 'wx_appid',
appSecret: 'app_secret',
));
$result = $wxapp->get('sns/jscode2session', [
'js_code' => 'login_code',
'grant_type' => 'authorization_code',
]);
```
## 微信开放平台
```php
use We\Config\WechatServiceConfig;
$service = $client->wechatService(new WechatServiceConfig(
componentAppid: 'component_appid',
componentAppSecret: 'component_secret',
componentToken: 'component_token',
componentEncodingAesKey: 'component_encoding_aes_key',
));
$componentToken = $service->componentAccessToken($componentVerifyTicket);
$preAuth = $service->createPreAuthCode($componentToken);
$url = $service->authorizationUrl((string) $preAuth['pre_auth_code'], $redirectUri);
```
代授权方调用:
```php
$result = $service->post('cgi-bin/menu/get', [], [
'authorizer_appid' => 'authorizer_appid',
'component_access_token' => $componentToken,
]);
```
## 微信支付 APIv3
```php
use We\Config\WechatPaymentConfig;
$payment = $client->wechatPayment(new WechatPaymentConfig(
appid: 'wx_appid',
mchId: 'mch_id',
apiV3Key: 'api_v3_key',
merchantSerial: 'merchant_serial',
merchantPrivateKey: file_get_contents(__DIR__ . '/apiclient_key.pem'),
platformPublicKey: file_get_contents(__DIR__ . '/wechatpay_public.pem'),
platformSerial: 'platform_serial',
));
$refund = $payment->post('v3/refund/domestic/refunds', [
'out_trade_no' => 'T202605020001',
'out_refund_no' => 'R202605020001',
'amount' => [
'refund' => 1,
'total' => 1,
'currency' => 'CNY',
],
]);
```
回调验签与解密:
```php
$data = $payment->post('decrypt_notification', [], [
'headers' => $headers,
'body' => $body,
]);
```
## 支付宝
```php
use We\Config\AlipayPlatformConfig;
$alipay = $client->alipayPlatform(new AlipayPlatformConfig(
appid: 'app_id',
privateKey: file_get_contents(__DIR__ . '/merchant_private_key.pem'),
alipayPublicKey: file_get_contents(__DIR__ . '/alipay_public_key.pem'),
));
$auth = $alipay->get('auth', [
'redirect_uri' => 'https://example.com/callback',
'scope' => 'auth_user',
'state' => 'state',
]);
$response = $alipay->post('alipay.user.info.share', [], [
'auth_token' => 'auth_token',
]);
```
支付宝支付:
```php
use We\Config\AlipayPaymentConfig;
$pay = $client->alipayPayment(AlipayPaymentConfig::fromArray([
'appid' => 'app_id',
'private_key' => file_get_contents(__DIR__ . '/merchant_private_key.pem'),
'alipay_public_key' => file_get_contents(__DIR__ . '/alipay_public_key.pem'),
]));
$page = $pay->post('page', [
'out_trade_no' => 'P202605020001',
'total_amount' => '0.01',
'subject' => 'Test Order',
'product_code' => 'FAST_INSTANT_TRADE_PAY',
]);
```
## 异常处理
SDK 抛出的异常基类为:
```php
We\Exception\WechatException
```
签名相关异常使用:
```php
We\Exception\SignatureException
```
建议在业务边界统一捕获并转换成应用自己的响应格式。不要把 app secret、access token、private key、回调密文等敏感内容写入日志。
## 测试
```bash
cd WeChatDeveloper
composer test
```
或在项目根目录:
```bash
vendor/bin/phpunit -c phpunit.xml
```
## 设计边界
WeChatDeveloper 只处理协议层和 HTTP 编排:
- 不提供账号、租户、菜单草稿、订单、授权记录等业务表。
- 不托管密钥加密存储。
- 不绑定 Hyperf、Laravel、Symfony 等框架。
- 不保证覆盖每一个官方接口别名,通用接口通过官方 path 调用。
这种边界使 SDK 更适合作为开源底层包被后台系统、SaaS 平台或命令行工具组合使用。
## License
MIT

149
We.php
View File

@ -1,149 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
use WeChat\Contracts\DataArray;
use WeChat\Exceptions\InvalidInstanceException;
/**
* 加载缓存器
*
* @library WeChatDeveloper
* @author Anyon<zoujingli@qq.com>
* @date 2018/05/24 13:23
*
* ----- AliPay ----
* @method \AliPay\App AliPayApp($options) static 支付宝App支付网关
* @method \AliPay\Bill AliPayBill($options) static 支付宝电子面单下载
* @method \AliPay\Pos AliPayPos($options) static 支付宝刷卡支付
* @method \AliPay\Scan AliPayScan($options) static 支付宝扫码支付
* @method \AliPay\Trade AliPayTrade($options) static 支付宝标准接口
* @method \AliPay\Transfer AliPayTransfer($options) static 支付宝转账到账户
* @method \AliPay\Wap AliPayWap($options) static 支付宝手机网站支付
* @method \AliPay\Web AliPayWeb($options) static 支付宝网站支付
*
* ----- WeChat -----
* @method \WeChat\Card WeChatCard($options = []) static 微信卡券管理
* @method \WeChat\Custom WeChatCustom($options = []) static 微信客服消息
* @method \WeChat\Limit WeChatLimit($options = []) static 接口调用频次限制
* @method \WeChat\Media WeChatMedia($options = []) static 微信素材管理
* @method \WeChat\Menu WeChatMenu($options = []) static 微信菜单管理
* @method \WeChat\Oauth WeChatOauth($options = []) static 微信网页授权
* @method \WeChat\Pay WeChatPay($options = []) static 微信支付商户
* @method \WeChat\Product WeChatProduct($options = []) static 微信商店管理
* @method \WeChat\Qrcode WeChatQrcode($options = []) static 微信二维码管理
* @method \WeChat\Receive WeChatReceive($options = [], $showEchoStr = true) static 微信推送管理
* @method \WeChat\Scan WeChatScan($options = []) static 微信扫一扫接入管理
* @method \WeChat\Script WeChatScript($options = []) static 微信前端支持
* @method \WeChat\Shake WeChatShake($options = []) static 微信揺一揺周边
* @method \WeChat\Tags WeChatTags($options = []) static 微信用户标签管理
* @method \WeChat\Template WeChatTemplate($options = []) static 微信模板消息
* @method \WeChat\User WeChatUser($options = []) static 微信粉丝管理
* @method \WeChat\Wifi WeChatWifi($options = []) static 微信门店WIFI管理
* @method \WeChat\Draft WeChatDraft($options = []) static 微信草稿箱
* @method \WeChat\Freepublish WeChatFreepublish($options = []) static 微信发布能力
*
* ----- WeMini -----
* @method \WeMini\Crypt WeMiniCrypt($options = []) static 小程序数据加密处理
* @method \WeMini\Delivery WeMiniDelivery($options = []) static 小程序即时配送
* @method \WeMini\Shipping WeMiniShipping($options = []) static 小程序发货信息
* @method \WeMini\Guide WeMiniGuide($options = []) static 小程序导购助手
* @method \WeMini\Image WeMiniImage($options = []) static 小程序图像处理
* @method \WeMini\Live WeMiniLive($options = []) static 小程序直播接口
* @method \WeMini\Logistics WeMiniLogistics($options = []) static 小程序物流助手
* @method \WeMini\Message WeMiniMessage($options = []) static 小程序动态消息
* @method \WeMini\Newtmpl WeMiniNewtmpl($options = []) static 小程序订阅消息
* @method \WeMini\Ocr WeMiniOcr($options = []) static 小程序ORC服务
* @method \WeMini\Operation WeMiniOperation($options = []) static 小程序运维中心
* @method \WeMini\Plugs WeMiniPlugs($options = []) static 小程序插件管理
* @method \WeMini\Poi WeMiniPoi($options = []) static 小程序地址管理
* @method \WeMini\Qrcode WeMiniQrcode($options = []) static 小程序二维码管理
* @method \WeMini\Scheme WeMiniScheme($options = []) static 小程序 URL-Scheme
* @method \WeMini\Search WeMiniSearch($options = []) static 小程序搜索
* @method \WeMini\Security WeMiniSecurity($options = []) static 小程序内容安全
* @method \WeMini\Soter WeMiniSoter($options = []) static 小程序生物认证
* @method \WeMini\Template WeMiniTemplate($options = []) static 小程序模板消息支持
* @method \WeMini\Total WeMiniTotal($options = []) static 小程序数据接口
*
* ----- WePay -----
* @method \WePay\Bill WePayBill($options = []) static 微信商户账单及评论
* @method \WePay\Order WePayOrder($options = []) static 微信商户订单
* @method \WePay\Coupon WePayCoupon($options = []) static 微信商户代金券
* @method \WePay\Custom WePayCustom($options = []) static 微信商户海关
* @method \WePay\Refund WePayRefund($options = []) static 微信商户退款
* @method \WePay\Redpack WePayRedpack($options = []) static 微信红包支持
* @method \WePay\Transfers WePayTransfers($options = []) static 微信商户打款到零钱
* @method \WePay\TransfersBank WePayTransfersBank($options = []) static 微信商户打款到银行卡
* @method \WePay\ProfitSharing WePayProfitSharing($options = []) static 微信分账
*/
class We
{
/**
* 定义当前版本
* @var string
*/
const VERSION = '1.2.54';
/**
* 静态配置
* @var DataArray
*/
private static $config;
/**
* 设置及获取参数
* @param array $option
* @return array
*/
public static function config($option = null)
{
if (is_array($option)) {
self::$config = new DataArray($option);
}
if (self::$config instanceof DataArray) {
return self::$config->get();
}
return [];
}
/**
* 静态魔术加载方法
* @param string $name 静态类名
* @param array $arguments 参数集合
* @return mixed
* @throws InvalidInstanceException
*/
public static function __callStatic($name, $arguments)
{
if (substr($name, 0, 6) === 'WeChat') {
$class = 'WeChat\\' . substr($name, 6);
} elseif (substr($name, 0, 6) === 'WeMini') {
$class = 'WeMini\\' . substr($name, 6);
} elseif (substr($name, 0, 6) === 'AliPay') {
$class = 'AliPay\\' . substr($name, 6);
} elseif (substr($name, 0, 7) === 'WePayV3') {
$class = 'WePayV3\\' . substr($name, 7);
} elseif (substr($name, 0, 5) === 'WePay') {
$class = 'WePay\\' . substr($name, 5);
}
if (!empty($class) && class_exists($class)) {
$option = array_shift($arguments);
$config = is_array($option) ? $option : self::$config->get();
return new $class($config);
}
throw new InvalidInstanceException("class {$name} not found");
}
}

View File

@ -1,641 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeChat;
use WeChat\Contracts\BasicWeChat;
/**
* 卡券管理
* @package WeChat
*/
class Card extends BasicWeChat
{
/**
* 创建卡券
* @param array $data 卡券数据card 对象)
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function create(array $data)
{
$url = "https://api.weixin.qq.com/card/create?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data);
}
/**
* 设置买单开关
* @param string $cardId 卡券ID
* @param bool $isOpen 是否开启
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function setPaycell($cardId, $isOpen = true)
{
$url = "https://api.weixin.qq.com/card/paycell/set?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['card_id' => $cardId, 'is_open' => $isOpen]);
}
/**
* 设置自助核销
* @param string $cardId 卡券ID
* @param bool $isOpen 是否开启
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function setConsumeCell($cardId, $isOpen = true)
{
$url = "https://api.weixin.qq.com/card/selfconsumecell/set?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['card_id' => $cardId, 'is_open' => $isOpen]);
}
/**
* 创建卡券二维码
* @param array $data 二维码参数action_name, card 等)
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function createQrc(array $data)
{
$url = "https://api.weixin.qq.com/card/qrcode/create?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data);
}
/**
* 创建卡券货架
* @param array $data 货架参数
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function createLandingPage(array $data)
{
$url = "https://api.weixin.qq.com/card/landingpage/create?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data);
}
/**
* 导入自定义 code
* @param string $cardId 卡券ID
* @param array $code code 列表最多10万
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function deposit($cardId, array $code)
{
$url = "https://api.weixin.qq.com/card/code/deposit?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['card_id' => $cardId, 'code' => $code]);
}
/**
* 查询已导入 code 数量
* @param string $cardId 卡券ID
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function getDepositCount($cardId)
{
$url = "https://api.weixin.qq.com/card/code/getdepositcount?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['card_id' => $cardId]);
}
/**
* 校验导入的 code
* @param string $cardId 卡券ID
* @param array $code 自定义 code 列表(<=100
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function checkCode($cardId, array $code)
{
$url = "https://api.weixin.qq.com/card/code/checkcode?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['card_id' => $cardId, 'code' => $code]);
}
/**
* 获取图文群发卡券的 HTML
* @param string $cardId 卡券ID
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function getNewsHtml($cardId)
{
$url = "https://api.weixin.qq.com/card/mpnews/gethtml?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['card_id' => $cardId]);
}
/**
* 设置测试白名单
* @param array $openids 测试 openid 列表
* @param array $usernames 测试微信号列表
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function setTestWhiteList($openids = [], $usernames = [])
{
$url = "https://api.weixin.qq.com/card/testwhitelist/set?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['openid' => $openids, 'username' => $usernames]);
}
/**
* 查询 Code 状态
* @param string $code 卡券 code
* @param string $cardId 卡券ID自定义 code 必填)
* @param bool $checkConsume 是否校验核销状态
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function getCode($code, $cardId = null, $checkConsume = null)
{
$data = ['code' => $code];
is_null($cardId) || $data['card_id'] = $cardId;
is_null($checkConsume) || $data['check_consume'] = $checkConsume;
$url = "https://api.weixin.qq.com/card/code/get?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data);
}
/**
* 核销 Code
* @param string $code 待核销的 code
* @param null|string $card_id 卡券ID自定义 code 必填)
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function consume($code, $card_id = null)
{
$data = ['code' => $code];
is_null($card_id) || $data['card_id'] = $card_id;
$url = "https://api.weixin.qq.com/card/code/consume?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data);
}
/**
* 解码加密 Code
* @param string $encryptCode 加密 code
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function decrypt($encryptCode)
{
$url = "https://api.weixin.qq.com/card/code/decrypt?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['encrypt_code' => $encryptCode]);
}
/**
* 获取用户已领取卡券
* @param string $openid 用户 openid
* @param null|string $cardId 卡券ID可选
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function getCardList($openid, $cardId = null)
{
$data = ['openid' => $openid];
is_null($cardId) || $data['card_id'] = $cardId;
$url = "https://api.weixin.qq.com/card/user/getcardlist?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data);
}
/**
* 查看卡券详情
* @param string $cardId 卡券ID
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function getCard($cardId)
{
$url = "https://api.weixin.qq.com/card/get?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['card_id' => $cardId]);
}
/**
* 批量查询卡券
* @param int $offset 起始偏移量
* @param int $count 拉取数量(<=50
* @param array $statusList 状态过滤
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function batchGet($offset, $count = 50, array $statusList = [])
{
$data = ['offset' => $offset, 'count' => $count];
empty($statusList) || $data['status_list'] = $statusList;
$url = "https://api.weixin.qq.com/card/batchget?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data);
}
/**
* 更新会员卡信息
* @param string $cardId 卡券ID
* @param array $memberCard 会员卡内容
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function updateCard($cardId, array $memberCard)
{
$url = "https://api.weixin.qq.com/card/update?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['card_id' => $cardId, 'member_card' => $memberCard]);
}
/**
* 修改库存
* @param string $card_id 卡券ID
* @param int|null $increase_stock_value 增加库存
* @param int|null $reduce_stock_value 减少库存
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function modifyStock($card_id, $increase_stock_value = null, $reduce_stock_value = null)
{
$data = ['card_id' => $card_id];
is_null($reduce_stock_value) || $data['reduce_stock_value'] = $reduce_stock_value;
is_null($increase_stock_value) || $data['increase_stock_value'] = $increase_stock_value;
$url = "https://api.weixin.qq.com/card/modifystock?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data);
}
/**
* 变更 Code
* @param string $code code
* @param string $new_code code
* @param null|string $card_id 卡券ID
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function updateCode($code, $new_code, $card_id = null)
{
$data = ['code' => $code, 'new_code' => $new_code];
is_null($card_id) || $data['card_id'] = $card_id;
$url = "https://api.weixin.qq.com/card/code/update?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data);
}
/**
* 删除卡券
* @param string $cardId 卡券ID
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function deleteCard($cardId)
{
$url = "https://api.weixin.qq.com/card/delete?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['card_id' => $cardId]);
}
/**
* 设置卡券失效
* @param string $code 卡券 code
* @param string $cardId 卡券ID
* @param null|string $reason 失效原因
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function unAvailable($code, $cardId, $reason = null)
{
$data = ['code' => $code, 'card_id' => $cardId];
is_null($reason) || $data['reason'] = $reason;
$url = "https://api.weixin.qq.com/card/code/unavailable?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data);
}
/**
* 拉取卡券概况数据
* @param string $beginDate 开始日期
* @param string $endDate 结束日期
* @param string $condSource 卡券来源 0|1
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function getCardBizuininfo($beginDate, $endDate, $condSource)
{
$url = "https://api.weixin.qq.com/datacube/getcardbizuininfo?access_token=ACCESS_TOKEN";
$data = ['begin_date' => $beginDate, 'end_date' => $endDate, 'cond_source' => $condSource];
return $this->callPostApi($url, $data);
}
/**
* 获取免费券数据
* @param string $beginDate 开始日期
* @param string $endDate 结束日期
* @param int $condSource 卡券来源 0|1
* @param null|string $cardId 卡券ID
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function getCardCardinfo($beginDate, $endDate, $condSource, $cardId = null)
{
$url = "https://api.weixin.qq.com/datacube/getcardcardinfo?access_token=ACCESS_TOKEN";
$data = ['begin_date' => $beginDate, 'end_date' => $endDate, 'cond_source' => $condSource];
is_null($cardId) || $data['card_id'] = $cardId;
return $this->callPostApi($url, $data);
}
/**
* 激活会员卡
* @param array $data 激活参数
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function activateMemberCard(array $data)
{
$url = 'https://api.weixin.qq.com/card/membercard/activate?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data);
}
/**
* 设置开卡字段(激活表单)
* @param array $data 表单字段
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function setActivateMemberCardUser(array $data)
{
$url = 'https://api.weixin.qq.com/card/membercard/activateuserform/set?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data);
}
/**
* 获取用户提交的激活资料
* @param string $activateTicket 激活 ticket
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function getActivateMemberCardTempinfo($activateTicket)
{
$url = 'https://api.weixin.qq.com/card/membercard/activatetempinfo/get?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, ['activate_ticket' => $activateTicket]);
}
/**
* 更新会员信息
* @param array $data 更新参数
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function updateMemberCardUser(array $data)
{
$url = 'https://api.weixin.qq.com/card/membercard/updateuser?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data);
}
/**
* 拉取会员卡概况数据
* @param string $beginDate 开始日期
* @param string $endDate 结束日期
* @param string $condSource 卡券来源 0|1
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function getCardMemberCardinfo($beginDate, $endDate, $condSource)
{
$url = "https://api.weixin.qq.com/datacube/getcardmembercardinfo?access_token=ACCESS_TOKEN";
$data = ['begin_date' => $beginDate, 'end_date' => $endDate, 'cond_source' => $condSource];
return $this->callPostApi($url, $data);
}
/**
* 拉取单张会员卡数据
* @param string $beginDate 开始日期
* @param string $endDate 结束日期
* @param string $cardId 卡券ID
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function getCardMemberCardDetail($beginDate, $endDate, $cardId)
{
$url = "https://api.weixin.qq.com/datacube/getcardmembercarddetail?access_token=ACCESS_TOKEN";
$data = ['begin_date' => $beginDate, 'end_date' => $endDate, 'card_id' => $cardId];
return $this->callPostApi($url, $data);
}
/**
* 查询会员信息(积分)
* @param string $cardId 会员卡ID
* @param string $code 用户 code
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function getCardMemberCard($cardId, $code)
{
$data = ['card_id' => $cardId, 'code' => $code];
$url = "https://api.weixin.qq.com/card/membercard/userinfo/get?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data);
}
/**
* 支付后投放卡券规则
* @param array $data 规则参数
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function payGiftCard(array $data)
{
$url = "https://api.weixin.qq.com/card/paygiftcard/add?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data);
}
/**
* 删除支付后投放卡券规则
* @param int $ruleId 规则ID
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function delPayGiftCard($ruleId)
{
$url = "https://api.weixin.qq.com/card/paygiftcard/add?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['rule_id' => $ruleId]);
}
/**
* 查询支付后投放卡券规则
* @param int $ruleId 规则ID
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function getPayGiftCard($ruleId)
{
$url = "https://api.weixin.qq.com/card/paygiftcard/getbyid?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['rule_id' => $ruleId]);
}
/**
* 批量查询支付后投放规则
* @param int $offset 起始偏移
* @param int $count 数量
* @param bool $effective 是否仅查询生效规则
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function batchGetPayGiftCard($offset = 0, $count = 10, $effective = true)
{
$url = "https://api.weixin.qq.com/card/paygiftcard/batchget?access_token=ACCESS_TOKEN";
$data = ['type' => 'RULE_TYPE_PAY_MEMBER_CARD', 'offset' => $offset, 'count' => $count, 'effective' => $effective];
return $this->callPostApi($url, $data);
}
/**
* 创建支付后立减金活动
* @param array $data 活动参数
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function addActivity(array $data)
{
$url = "https://api.weixin.qq.com/card/mkt/activity/create?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data);
}
/**
* 开通券点账户
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function payActivate()
{
$url = "https://api.weixin.qq.com/card/pay/activate?access_token=ACCESS_TOKEN";
return $this->callGetApi($url);
}
/**
* 预估优惠券库存价格
* @param string $cardId 卡券ID
* @param int $quantity 兑换数量
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function getPayprice($cardId, $quantity)
{
$url = "POST https://api.weixin.qq.com/card/pay/getpayprice?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['card_id' => $cardId, 'quantity' => $quantity]);
}
/**
* 查询券点余额
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function getCoinsInfo()
{
$url = "https://api.weixin.qq.com/card/pay/getcoinsinfo?access_token=ACCESS_TOKEN";
return $this->callGetApi($url);
}
/**
* 确认兑换库存
* @param string $cardId 卡券ID
* @param int $quantity 数量
* @param string $orderId 批价返回的订单号
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function payConfirm($cardId, $quantity, $orderId)
{
$url = "https://api.weixin.qq.com/card/pay/confirm?access_token=ACCESS_TOKEN";
$data = ['card_id' => $cardId, 'quantity' => $quantity, 'order_id' => $orderId];
return $this->callPostApi($url, $data);
}
/**
* 充值券点
* @param int $coinCount 充值数量
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function payRecharge($coinCount)
{
$url = "https://api.weixin.qq.com/card/pay/recharge?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['coin_count' => $coinCount]);
}
/**
* 查询券点订单详情
* @param string $orderId 订单号
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function payGetOrder($orderId)
{
$url = "https://api.weixin.qq.com/card/pay/getorder?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['order_id' => $orderId]);
}
/**
* 查询券点流水
* @param array $data 查询参数
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function payGetList(array $data)
{
$url = "https://api.weixin.qq.com/card/pay/getorderlist?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data);
}
/**
* 获取开卡插件参数
* @param array $data 入口参数
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function getActivateUrl(array $data)
{
$url = "https://api.weixin.qq.com/card/membercard/activate/geturl?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data);
}
}

View File

@ -1,531 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeChat\Contracts;
use WeChat\Exceptions\InvalidArgumentException;
use WeChat\Exceptions\InvalidResponseException;
/**
* 支付宝支付基类
* @package WeChat\Contracts
*/
abstract class BasicAliPay
{
/**
* 静态缓存
* @var static
*/
protected static $cache;
/**
* 支持配置
* @var DataArray
*/
protected $config;
/**
* 当前请求数据
* @var DataArray
*/
protected $options;
/**
* DzContent数据
* @var DataArray
*/
protected $params;
/**
* 正常请求网关
* @var string
*/
protected $gateway = 'https://openapi.alipay.com/gateway.do?charset=utf-8';
/**
* 构造函数
* @param array $options 必填appid、public_key、private_key可选app_cert、root_cert、cache_path
*/
public function __construct($options)
{
if (empty($options['appid'])) {
throw new InvalidArgumentException('Missing Config -- [appid]');
}
if (empty($options['public_key']) && !empty($options['alipay_cert_path']) && is_file($options['alipay_cert_path'])) {
$options['public_key'] = file_get_contents($options['alipay_cert_path']);
}
if (empty($options['private_key']) && !empty($options['private_key_path']) && is_file($options['private_key_path'])) {
$options['private_key'] = file_get_contents($options['private_key_path']);
}
if (empty($options['public_key'])) {
throw new InvalidArgumentException('Missing Config -- [public_key]');
}
if (empty($options['private_key'])) {
throw new InvalidArgumentException('Missing Config -- [private_key]');
}
if (!empty($options['debug'])) {
$this->gateway = 'https://openapi-sandbox.dl.alipaydev.com/gateway.do?charset=utf-8';
}
$this->params = new DataArray([]);
$this->config = new DataArray($options);
$this->options = new DataArray([
'app_id' => $this->config->get('appid'),
'charset' => empty($options['charset']) ? 'utf-8' : $options['charset'],
'format' => 'JSON',
'version' => '1.0',
'sign_type' => empty($options['sign_type']) ? 'RSA2' : $options['sign_type'],
'timestamp' => date('Y-m-d H:i:s'),
]);
if (isset($options['notify_url']) && $options['notify_url'] !== '') {
$this->options->set('notify_url', $options['notify_url']);
}
if (isset($options['return_url']) && $options['return_url'] !== '') {
$this->options->set('return_url', $options['return_url']);
}
if (isset($options['app_auth_token']) && $options['app_auth_token'] !== '') {
$this->options->set('app_auth_token', $options['app_auth_token']);
}
// 证书模式读取证书
$appCertPath = $this->config->get('app_cert_path');
$aliRootPath = $this->config->get('alipay_root_path');
if (!$this->config->get('app_cert') && !empty($appCertPath) && is_file($appCertPath)) {
$this->config->set('app_cert', file_get_contents($appCertPath));
}
if (!$this->config->get('root_cert') && !empty($aliRootPath) && is_file($aliRootPath)) {
$this->config->set('root_cert', file_get_contents($aliRootPath));
}
}
/**
* 静态创建对象
* @param array $config
* @return static
*/
public static function instance(array $config)
{
$key = md5(get_called_class() . serialize($config));
if (isset(self::$cache[$key])) return self::$cache[$key];
return self::$cache[$key] = new static($config);
}
/**
* 查询支付宝订单状态
* @param string $outTradeNo 商户订单号
* @return array 订单查询结果
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function query($outTradeNo = '')
{
$this->options->set('method', 'alipay.trade.query');
return $this->getResult(['out_trade_no' => $outTradeNo]);
}
/**
* 请求接口并验证访问数据
* @param array $options 请求参数
* @return array 接口响应数据
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
protected function getResult($options)
{
$this->applyData($options);
$method = str_replace('.', '_', $this->options['method']) . '_response';
$data = json_decode(Tools::get($this->gateway, $this->options->get()), true);
if (!isset($data[$method]['code']) || $data[$method]['code'] !== '10000') {
throw new InvalidResponseException(
"Error: " .
(empty($data[$method]['code']) ? '' : "{$data[$method]['msg']} [{$data[$method]['code']}]\r\n") .
(empty($data[$method]['sub_code']) ? '' : "{$data[$method]['sub_msg']} [{$data[$method]['sub_code']}]\r\n"),
$data[$method]['code'], $data
);
}
return $data[$method];
// 返回结果签名检查
// return $this->verify($data[$method], $data['sign']);
}
/**
* 数据包生成及数据签名
* @param array $options
*/
protected function applyData($options)
{
if ($this->config->get('app_cert') && $this->config->get('root_cert')) {
$this->setAppCertSnAndRootCertSn();
}
$this->options->set('biz_content', json_encode($this->params->merge($options), 256));
$this->options->set('sign', $this->getSign());
}
/**
* 新版 设置网关应用公钥证书SN、支付宝根证书SN
*/
protected function setAppCertSnAndRootCertSn()
{
if (!($appCert = $this->config->get('app_cert'))) {
throw new InvalidArgumentException('Missing Config -- [app_cert|app_cert_path]');
}
if (!($rootCert = $this->config->get('root_cert'))) {
throw new InvalidArgumentException('Missing Config -- [root_cert|alipay_root_path]');
}
$this->options->set('app_cert_sn', $this->getAppCertSN($appCert));
$this->options->set('alipay_root_cert_sn', $this->getRootCertSN($rootCert));
if (!$this->options->get('app_cert_sn')) {
throw new InvalidArgumentException('Missing options -- [app_cert_sn]');
}
if (!$this->options->get('alipay_root_cert_sn')) {
throw new InvalidArgumentException('Missing options -- [alipay_root_cert_sn]');
}
}
/**
* 新版 从证书中提取序列号
* @param string $sign
* @return string
*/
private function getAppCertSN($sign)
{
$ssl = openssl_x509_parse($sign, true);
$issuer = isset($ssl['issuer']) && is_array($ssl['issuer']) ? $ssl['issuer'] : [];
return md5($this->_arr2str(array_reverse($issuer)) . $ssl['serialNumber']);
}
/**
* 新版 数组转字符串
* @param array $array
* @return string
*/
private function _arr2str($array)
{
$string = [];
if ($array && is_array($array)) {
foreach ($array as $key => $value) {
$string[] = $key . '=' . $value;
}
}
return join(',', $string);
}
/**
* 新版 提取根证书序列号
* @param string $sign
* @return string|null
*/
private function getRootCertSN($sign)
{
if (strlen($sign) < 500 && file_exists($sign)) {
$sign = file_get_contents($sign);
}
$sn = null;
$array = explode('-----END CERTIFICATE-----', $sign);
for ($i = 0; $i < count($array) - 1; $i++) {
$ssl[$i] = openssl_x509_parse($array[$i] . '-----END CERTIFICATE-----', true);
if (strpos($ssl[$i]['serialNumber'], '0x') === 0) {
$ssl[$i]['serialNumber'] = $this->_hex2dec($ssl[$i]['serialNumberHex']);
}
if ($ssl[$i]['signatureTypeLN'] == 'sha1WithRSAEncryption' || $ssl[$i]['signatureTypeLN'] == 'sha256WithRSAEncryption') {
$issuer = isset($ssl[$i]['issuer']) && is_array($ssl[$i]['issuer']) ? $ssl[$i]['issuer'] : [];
if ($sn == null) {
$sn = md5($this->_arr2str(array_reverse($issuer)) . $ssl[$i]['serialNumber']);
} else {
$sn = $sn . '_' . md5($this->_arr2str(array_reverse($issuer)) . $ssl[$i]['serialNumber']);
}
}
}
return $sn;
}
/**
* 新版 0x转高精度数字
* @param string $hex
* @return int|string
*/
private function _hex2dec($hex)
{
list($dec, $len) = [0, strlen($hex)];
for ($i = 1; $i <= $len; $i++) {
$dec = bcadd($dec, bcmul(strval(hexdec($hex[$i - 1])), bcpow('16', strval($len - $i))));
}
return $dec;
}
/**
* 获取数据签名
* @return string
*/
protected function getSign()
{
if ($this->options->get('sign_type') === 'RSA2') {
openssl_sign($this->getSignContent($this->options->get(), true), $sign, $this->getAppPrivateKey(), OPENSSL_ALGO_SHA256);
} else {
openssl_sign($this->getSignContent($this->options->get(), true), $sign, $this->getAppPrivateKey(), OPENSSL_ALGO_SHA1);
}
return base64_encode($sign);
}
/**
* 数据签名处理
* @param array $data 需要进行签名数据
* @param boolean $needSignType 是否需要sign_type字段
* @return string
*/
private function getSignContent(array $data, $needSignType = false)
{
ksort($data);
$attrs = array();
if (isset($data['sign'])) unset($data['sign']);
if (empty($needSignType)) unset($data['sign_type']);
foreach ($data as $key => $value) {
if ($value === '' || is_null($value)) continue;
$attrs[] = "{$key}={$value}";
}
return join('&', $attrs);
}
/**
* 获取应用私钥内容
* @return string
*/
private function getAppPrivateKey()
{
$content = wordwrap($this->trimCert($this->config->get('private_key')), 64, "\n", true);
return "-----BEGIN RSA PRIVATE KEY-----\n{$content}\n-----END RSA PRIVATE KEY-----";
}
/**
* 去除证书前后内容及空白
* @param string $sign
* @return string
*/
protected function trimCert($sign)
{
return preg_replace(['/\s+/', '/-{5}.*?-{5}/'], '', $sign);
}
/**
* 支付宝订单退款操作
* @param array|string $options 退款参数或退款商户订单号
* @param string|null $refundAmount 退款金额
* @return array 退款结果
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function refund($options, $refundAmount = null)
{
if (!is_array($options)) $options = ['out_trade_no' => $options, 'refund_amount' => $refundAmount];
$this->options->set('method', 'alipay.trade.refund');
return $this->getResult($options);
}
/**
* 支付宝订单退款查询
* @param array|string $options 退款参数或退款商户订单号
* @param array|null $queryOptions 查询选项
* @return array 退款查询结果
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function refundQuery($options, $queryOptions = null)
{
if (!is_array($options)) $options = ['out_trade_no' => $options];
empty($queryOptions) || $options['query_options'] = $queryOptions;
$this->options->set('method', 'alipay.trade.fastpay.refund.query');
return $this->getResult($options);
}
/**
* 关闭支付宝进行中的订单
* @param array|string $options 订单参数或商户订单号
* @return array 关闭结果
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function close($options)
{
if (!is_array($options)) $options = ['out_trade_no' => $options];
$this->options->set('method', 'alipay.trade.close');
return $this->getResult($options);
}
/**
* 获取通知数据
*
* @param boolean $needSignType 是否需要sign_type字段
* @param array $parameters
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function notify($needSignType = false, array $parameters = [])
{
$data = empty($parameters) ? $_POST : $parameters;
if (empty($data) || empty($data['sign'])) {
throw new InvalidResponseException('Illegal push request.', 0, $data);
}
$string = $this->getSignContent($data, $needSignType);
if (openssl_verify($string, base64_decode($data['sign']), $this->getAliPublicKey(), OPENSSL_ALGO_SHA256) !== 1) {
throw new InvalidResponseException('Data signature verification failed.', 0, $data);
}
return $data;
}
/**
* 获取支付公钥内容
* @return string
*/
public function getAliPublicKey()
{
$cert = $this->config->get('public_key');
if (strpos(trim($cert), '-----BEGIN CERTIFICATE-----') !== false) {
$pkey = openssl_pkey_get_public($cert);
$keyData = openssl_pkey_get_details($pkey);
return trim($keyData['key']);
} else {
$content = wordwrap($this->trimCert($cert), 64, "\n", true);
return "-----BEGIN PUBLIC KEY-----\n{$content}\n-----END PUBLIC KEY-----";
}
}
/**
* 应用数据操作
* @param array $options
* @return mixed
*/
abstract public function apply($options);
/**
* 通用接口调用(支付宝开放平台)
* @param string $apiMethod API 方法名(如 alipay.trade.query必填
* @param array|string $data 业务参数,数组会写入 biz_content字符串尝试解析为 JSON
* @param string $method GET|POST|PUT|DELETE|PATCH默认 GETPOST 会放入表单)
* @param bool $verify 是否验证返回签名
* @return array 返回解析后的响应体
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function callApi($apiMethod, $data = [], $method = 'GET', $verify = false)
{
$method = strtoupper($method);
// 验证API方法名必填
if (empty($apiMethod)) {
throw new \WeChat\Exceptions\InvalidArgumentException("Missing required parameter -- [apiMethod]");
}
// 使用gateway作为URL
$url = $this->gateway;
// 设置API方法
$this->options->set('method', $apiMethod);
// 处理数据格式并合并参数
$params = [];
if (is_array($data)) {
$params = $data;
} elseif (is_string($data) && !empty($data)) {
$decoded = json_decode($data, true);
if (json_last_error() === JSON_ERROR_NONE) {
$params = $decoded;
}
}
if (!empty($params)) {
$this->params->merge($params);
}
// 处理签名(默认自动签名)
if ($this->config->get('app_cert') && $this->config->get('root_cert')) {
$this->setAppCertSnAndRootCertSn();
}
$this->options->set('biz_content', json_encode($this->params->get(), 256));
$this->options->set('sign', $this->getSign());
// 统一处理响应(减少重复代码)
$methodKey = str_replace('.', '_', $this->options->get('method')) . '_response';
$self = $this;
$processResponse = function ($response) use ($verify, $methodKey, $self) {
$data = json_decode($response, true);
if (json_last_error() !== JSON_ERROR_NONE) {
return $response; // JSON解析失败返回原始响应
}
// 验证响应签名
if ($verify && isset($data['sign']) && isset($data[$methodKey])) {
return $self->verify($data[$methodKey], $data['sign']);
}
// 检查错误
if (isset($data[$methodKey])) {
if (isset($data[$methodKey]['code']) && $data[$methodKey]['code'] !== '10000') {
$msg = isset($data[$methodKey]['msg']) ? "{$data[$methodKey]['msg']} [{$data[$methodKey]['code']}]\r\n" : '';
$subMsg = isset($data[$methodKey]['sub_msg']) ? "{$data[$methodKey]['sub_msg']} [{$data[$methodKey]['sub_code']}]\r\n" : '';
throw new InvalidResponseException("Error: " . $msg . $subMsg, $data[$methodKey]['code'], $data);
}
return $data[$methodKey];
}
return $data;
};
// GET/HEAD/OPTIONS请求
if (in_array($method, ['GET', 'HEAD', 'OPTIONS'])) {
$queryParams = array_merge($this->options->get(), $params);
$response = Tools::get($url, $queryParams);
return $processResponse($response);
}
// POST/PUT/PATCH/DELETE请求
$postData = array_merge($this->options->get(), $params);
$response = Tools::doRequest($method, $url, ['data' => $postData]);
return $processResponse($response);
}
/**
* 验证接口返回的数据签名
* @param array $data 通知数据
* @param null|string $sign 数据签名
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
protected function verify($data, $sign)
{
unset($data['sign']);
if ($this->options->get('sign_type') === 'RSA2') {
if (openssl_verify(json_encode($data, 256), base64_decode($sign), $this->getAliPublicKey(), OPENSSL_ALGO_SHA256) !== 1) {
throw new InvalidResponseException('Data signature verification failed by RSA2.');
}
} else {
if (openssl_verify(json_encode($data, 256), base64_decode($sign), $this->getAliPublicKey(), OPENSSL_ALGO_SHA1) !== 1) {
throw new InvalidResponseException('Data signature verification failed by RSA.');
}
}
return $data;
}
/**
* 生成支付HTML代码
* @return string
*/
protected function buildPayHtml()
{
$html = "<form id='alipaysubmit' name='alipaysubmit' action='{$this->gateway}' method='post'>";
foreach ($this->options->get() as $key => $value) {
$value = str_replace("'", '&apos;', $value);
$html .= "<input type='hidden' name='{$key}' value='{$value}'/>";
}
$html .= "<input type='submit' value='ok' style='display:none;'></form>";
return "{$html}<script>document.forms['alipaysubmit'].submit();</script>";
}
}

View File

@ -1,242 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeChat\Contracts;
use WeChat\Exceptions\InvalidArgumentException;
use WeChat\Exceptions\InvalidDecryptException;
use WeChat\Exceptions\InvalidResponseException;
use WeChat\Prpcrypt\Prpcrypt;
/**
* 微信通知处理基本类
* @package WeChat\Contracts
*/
class BasicPushEvent
{
/**
* 公众号APPID
* @var string
*/
protected $appid;
/**
* 公众号推送XML内容
* @var string
*/
protected $postxml;
/**
* 公众号推送加密类型
* @var string
*/
protected $encryptType;
/**
* 公众号的推送请求参数
* @var DataArray
*/
protected $input;
/**
* 当前公众号配置对象
* @var DataArray
*/
protected $config;
/**
* 公众号推送内容对象
* @var DataArray
*/
protected $receive;
/**
* 准备回复的消息内容
* @var array
*/
protected $message;
/**
* BasicPushEvent constructor.
* @param array $options 配置参数
* @param boolean $showEchoStr 回显内容
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function __construct(array $options, $showEchoStr = true)
{
if (empty($options['appid'])) {
throw new InvalidArgumentException("Missing Config -- [appid]");
}
if (empty($options['appsecret'])) {
throw new InvalidArgumentException("Missing Config -- [appsecret]");
}
if (empty($options['token'])) {
throw new InvalidArgumentException("Missing Config -- [token]");
}
// 参数初始化
$this->config = new DataArray($options);
$this->input = new DataArray($_REQUEST);
$this->appid = $this->config->get('appid');
// 推送消息处理
if ($_SERVER['REQUEST_METHOD'] == "POST") {
$this->postxml = Tools::getRawInput();
$this->encryptType = $this->input->get('encrypt_type');
if ($this->isEncrypt()) {
if (empty($options['encodingaeskey'])) {
throw new InvalidArgumentException("Missing Config -- [encodingaeskey]");
}
$prpcrypt = new Prpcrypt($this->config->get('encodingaeskey'));
$result = Tools::xml2arr($this->postxml);
$array = $prpcrypt->decrypt($result['Encrypt']);
if (intval($array[0]) > 0) {
throw new InvalidResponseException($array[1], $array[0]);
}
list($this->postxml, $this->appid) = [$array[1], $array[2]];
}
$this->receive = new DataArray(Tools::xml2arr($this->postxml));
} elseif ($_SERVER['REQUEST_METHOD'] == "GET" && $this->checkSignature()) {
$this->receive = new DataArray([]);
if ($showEchoStr && ob_clean()) {
echo($this->input->get('echostr'));
}
} else {
throw new InvalidResponseException('Invalid interface request.', '0');
}
}
/**
* 消息是否需要加密
* @return boolean
*/
public function isEncrypt()
{
return $this->encryptType === 'aes';
}
/**
* 验证来自微信服务器
* @return bool
*/
private function checkSignature()
{
$nonce = $this->input->get('nonce');
$timestamp = $this->input->get('timestamp');
$msg_signature = $this->input->get('msg_signature');
$signature = empty($msg_signature) ? $this->input->get('signature') : $msg_signature;
$tmpArr = [$this->config->get('token'), $timestamp, $nonce, ''];
sort($tmpArr, SORT_STRING);
return sha1(implode($tmpArr)) === $signature;
}
/**
* 获取回显字串
* @return string
*/
public function getEchoStr()
{
if ($_SERVER['REQUEST_METHOD'] == "GET" && $this->checkSignature()) {
return $this->input->get('echostr');
} else {
return '';
}
}
/**
* 回复消息
* @param array $data 消息内容
* @param boolean $return 是否返回XML内容
* @param boolean $isEncrypt 是否加密内容
* @return string|void
* @throws \WeChat\Exceptions\InvalidDecryptException
*/
public function reply(array $data = [], $return = false, $isEncrypt = false)
{
$xml = Tools::arr2xml(empty($data) ? $this->message : $data);
if ($this->isEncrypt() || $isEncrypt) {
$prpcrypt = new Prpcrypt($this->config->get('encodingaeskey'));
// 如果是第三方平台,加密得使用 component_appid
$component_appid = $this->config->get('component_appid');
$appid = empty($component_appid) ? $this->appid : $component_appid;
$array = $prpcrypt->encrypt($xml, $appid);
if ($array[0] > 0) throw new InvalidDecryptException('Encrypt Error.', '0');
list($timestamp, $encrypt) = [time(), $array[1]];
$nonce = rand(77, 999) * rand(605, 888) * rand(11, 99);
$tmpArr = [$this->config->get('token'), $timestamp, $nonce, $encrypt];
sort($tmpArr, SORT_STRING);
$signature = sha1(implode($tmpArr));
$format = "<xml><Encrypt><![CDATA[%s]]></Encrypt><MsgSignature><![CDATA[%s]]></MsgSignature><TimeStamp>%s</TimeStamp><Nonce><![CDATA[%s]]></Nonce></xml>";
$xml = sprintf($format, $encrypt, $signature, $timestamp, $nonce);
}
if ($return) return $xml;
@ob_clean();
echo $xml;
}
/**
* 获取公众号推送对象
* @param null|string $field 指定获取字段
* @return array
*/
public function getReceive($field = null)
{
return $this->receive->get($field);
}
/**
* 获取当前微信OPENID
* @return string
*/
public function getOpenid()
{
return $this->receive->get('FromUserName');
}
/**
* 获取当前推送消息类型
* @return string
*/
public function getMsgType()
{
return $this->receive->get('MsgType');
}
/**
* 获取当前推送消息ID
* @return string
*/
public function getMsgId()
{
return $this->receive->get('MsgId');
}
/**
* 获取当前推送时间
* @return integer
*/
public function getMsgTime()
{
return $this->receive->get('CreateTime');
}
/**
* 获取当前推送公众号
* @return string
*/
public function getToOpenid()
{
return $this->receive->get('ToUserName');
}
}

View File

@ -1,292 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeChat\Contracts;
use WeChat\Exceptions\InvalidArgumentException;
use WeChat\Exceptions\InvalidResponseException;
/**
* 微信基础类
* @package WeChat\Contracts
*/
class BasicWeChat
{
/**
* 静态缓存
* @var static
*/
protected static $cache;
/**
* 当前微信配置
* @var DataArray
*/
public $config;
/**
* 访问AccessToken
* @var string
*/
public $access_token = '';
/**
* 当前请求方法参数
* @var array
*/
protected $currentMethod = [];
/**
* 当前模式
* @var bool
*/
protected $isTry = false;
/**
* 注册代替函数
* @var string
*/
protected $GetAccessTokenCallback;
/**
* 构造函数
* @param array $options 必填appid、appsecret可选GetAccessTokenCallback、cache_path
*/
public function __construct(array $options)
{
if (empty($options['appid'])) {
throw new InvalidArgumentException("Missing Config -- [appid]");
}
if (empty($options['appsecret'])) {
throw new InvalidArgumentException("Missing Config -- [appsecret]");
}
if (isset($options['GetAccessTokenCallback']) && is_callable($options['GetAccessTokenCallback'])) {
$this->GetAccessTokenCallback = $options['GetAccessTokenCallback'];
}
if (!empty($options['cache_path'])) {
Tools::$cache_path = $options['cache_path'];
}
$this->config = new DataArray($options);
}
/**
* 静态创建对象
* @param array $config 配置appid、appsecret 等)
* @return static
*/
public static function instance(array $config)
{
$key = md5(get_called_class() . serialize($config));
if (isset(self::$cache[$key])) return self::$cache[$key];
return self::$cache[$key] = new static($config);
}
/**
* 接口通用POST请求方法
* @param string $url 接口URL
* @param array $data POST提交接口参数
* @param bool $toJson 是否转换为JSON参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function callPostApi($url, array $data, $toJson = true, array $options = [])
{
$this->registerApi($url, __FUNCTION__, func_get_args());
return $this->httpPostForJson($url, $data, $toJson, $options);
}
/**
* 注册当前请求接口(自动处理 ACCESS_TOKEN
* @param string $url 接口地址(引用传递,会被修改)
* @param string $method 当前接口方法名
* @param array $arguments 请求参数
* @return string 替换 ACCESS_TOKEN 后的 URL
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
protected function registerApi(&$url, $method, $arguments = [])
{
$this->currentMethod = ['method' => $method, 'arguments' => $arguments];
if (empty($this->access_token)) $this->access_token = $this->getAccessToken();
return $url = str_replace('ACCESS_TOKEN', urlencode($this->access_token), $url);
}
/**
* 获取访问 AccessToken
* @return string
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getAccessToken()
{
if (!empty($this->access_token)) {
return $this->access_token;
}
$cache = $this->config->get('appid') . '_access_token';
$this->access_token = Tools::getCache($cache);
if (!empty($this->access_token)) {
return $this->access_token;
}
// 处理开放平台授权公众号获取AccessToken
if (!empty($this->GetAccessTokenCallback) && is_callable($this->GetAccessTokenCallback)) {
$this->access_token = call_user_func_array($this->GetAccessTokenCallback, [$this->config->get('appid'), $this]);
if (!empty($this->access_token)) {
Tools::setCache($cache, $this->access_token, 7000);
}
return $this->access_token;
}
list($appid, $secret) = [$this->config->get('appid'), $this->config->get('appsecret')];
$url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$appid}&secret={$secret}";
$result = Tools::json2arr(Tools::get($url));
if (!empty($result['access_token'])) {
Tools::setCache($cache, $result['access_token'], 7000);
}
return $this->access_token = $result['access_token'];
}
/**
* 设置外部接口 AccessToken
* @param string $accessToken
* @throws \WeChat\Exceptions\LocalCacheException
* @author 高一平 <iam@gaoyiping.com>
*
* 当用户使用自己的缓存驱动时,直接实例化对象后可直接设置 AccessToken
* - 多用于分布式项目时保持 AccessToken 统一
* - 使用此方法后就由用户来保证传入的 AccessToken 为有效 AccessToken
*/
public function setAccessToken($accessToken)
{
if (!is_string($accessToken)) {
throw new InvalidArgumentException("Invalid AccessToken type, need string.");
}
$cache = $this->config->get('appid') . '_access_token';
Tools::setCache($cache, $this->access_token = $accessToken);
}
/**
* 以POST获取接口数据并转为数组
* @param string $url 接口地址
* @param array $data 请求数据
* @param bool $toJson 转换JSON
* @param array $options 请求扩展数据
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
protected function httpPostForJson($url, array $data, $toJson = true, array $options = [])
{
try {
$options['headers'] = isset($options['headers']) ? $options['headers'] : [];
if ($toJson) $options['headers'][] = 'Content-Type: application/json';
return Tools::json2arr(Tools::post($url, $toJson ? Tools::arr2json($data) : $data, $options));
} catch (InvalidResponseException $exception) {
if (!$this->isTry && in_array($exception->getCode(), ['40014', '40001', '41001', '42001'])) {
$this->delAccessToken();
$this->isTry = true;
return call_user_func_array([$this, $this->currentMethod['method']], $this->currentMethod['arguments']);
}
throw new InvalidResponseException($exception->getMessage(), $exception->getCode());
}
}
/**
* 清理删除 AccessToken
* @return bool
*/
public function delAccessToken()
{
$this->access_token = '';
return Tools::delCache($this->config->get('appid') . '_access_token');
}
/**
* 通用 GET 请求(自动处理 ACCESS_TOKEN
* @param string $url 接口 URL
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function callGetApi($url)
{
$this->registerApi($url, __FUNCTION__, func_get_args());
return $this->httpGetForJson($url);
}
/**
* 以GET获取接口数据并转为数组
* @param string $url 接口地址
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
protected function httpGetForJson($url)
{
try {
return Tools::json2arr(Tools::get($url));
} catch (InvalidResponseException $exception) {
if (isset($this->currentMethod['method']) && empty($this->isTry)) {
if (in_array($exception->getCode(), ['40014', '40001', '41001', '42001'])) {
$this->delAccessToken();
$this->isTry = true;
return call_user_func_array([$this, $this->currentMethod['method']], $this->currentMethod['arguments']);
}
}
throw new InvalidResponseException($exception->getMessage(), $exception->getCode());
}
}
/**
* 通用接口调用
* @param string $url 完整 URL 或相对路径,支持 ACCESS_TOKEN 占位符自动替换
* @param array|string $data GET 参数或请求体,数组自动 JSON字符串原样发送
* @param string $method GET|POST|PUT|DELETE|PATCH|HEAD|OPTIONS默认 GET
* @return array 解析后的数组
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function callApi($url, $data = [], $method = 'GET')
{
$method = strtoupper($method);
// 自动处理ACCESS_TOKEN
if (strpos($url, 'ACCESS_TOKEN') !== false) {
if (empty($this->access_token)) {
$this->access_token = $this->getAccessToken();
}
$url = str_replace('ACCESS_TOKEN', urlencode($this->access_token), $url);
}
// GET/HEAD/OPTIONS请求无请求体
if (in_array($method, ['GET', 'HEAD', 'OPTIONS'])) {
if (!empty($data) && is_array($data)) {
$url .= (strpos($url, '?') !== false ? '&' : '?') . http_build_query($data);
}
return $this->httpGetForJson($url);
}
// POST/PUT/PATCH/DELETE请求有请求体
$postData = is_array($data) ? $data : [];
$toJson = is_array($data);
// POST请求使用原有方法支持自动重试
if ($method === 'POST') {
return $this->httpPostForJson($url, $postData, $toJson, []);
}
// PUT/PATCH/DELETE请求直接调用
$requestData = is_string($data) ? $data : Tools::arr2json($postData);
$response = Tools::doRequest($method, $url, ['data' => $requestData]);
return Tools::json2arr($response);
}
}

View File

@ -1,280 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeChat\Contracts;
use WeChat\Exceptions\InvalidArgumentException;
use WeChat\Exceptions\InvalidResponseException;
/**
* 微信支付基础类
* @package WeChat\Contracts
*/
class BasicWePay
{
/**
* 静态缓存
* @var static
*/
protected static $cache;
/**
* 商户配置
* @var DataArray
*/
protected $config;
/**
* 当前请求数据
* @var DataArray
*/
protected $params;
/**
* 构造函数
* @param array $options 必填appid、mch_id、mch_key可选sub_appid、sub_mch_id、cache_path
*/
public function __construct(array $options)
{
if (empty($options['appid'])) {
throw new InvalidArgumentException("Missing Config -- [appid]");
}
if (empty($options['mch_id'])) {
throw new InvalidArgumentException("Missing Config -- [mch_id]");
}
if (empty($options['mch_key'])) {
throw new InvalidArgumentException("Missing Config -- [mch_key]");
}
if (!empty($options['cache_path'])) {
Tools::$cache_path = $options['cache_path'];
}
$this->config = new DataArray($options);
// 商户基础参数
$this->params = new DataArray([
'appid' => $this->config->get('appid'),
'mch_id' => $this->config->get('mch_id'),
'nonce_str' => Tools::createNoncestr(),
]);
// 商户参数支持
if ($this->config->get('sub_appid')) {
$this->params->set('sub_appid', $this->config->get('sub_appid'));
}
if ($this->config->get('sub_mch_id')) {
$this->params->set('sub_mch_id', $this->config->get('sub_mch_id'));
}
}
/**
* 静态创建对象
* @param array $config 商户配置
* @return static
*/
public static function instance(array $config)
{
$key = md5(get_called_class() . serialize($config));
if (isset(self::$cache[$key])) return self::$cache[$key];
return self::$cache[$key] = new static($config);
}
/**
* 获取微信支付异步通知并验签
* @param string|array $xml 可选,默认读取原始输入
* @return array 验签通过的通知数据
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function getNotify($xml = '')
{
$data = is_array($xml) ? $xml : Tools::xml2arr(empty($xml) ? Tools::getRawInput() : $xml);
if (isset($data['sign']) && $this->getPaySign($data) === $data['sign']) {
return $data;
}
throw new InvalidResponseException('Invalid Notify.', '0');
}
/**
* 生成支付签名
* @param array $data 待签名数据
* @param string $signType MD5|HMAC-SHA256
* @param string $buff 签名前缀(内部使用)
* @return string 大写签名
*/
public function getPaySign(array $data, $signType = 'MD5', $buff = '')
{
ksort($data);
if (isset($data['sign'])) unset($data['sign']);
foreach ($data as $k => $v) {
if ('' === $v || null === $v) continue;
$buff .= "{$k}={$v}&";
}
$buff .= ("key=" . $this->config->get('mch_key'));
if (strtoupper($signType) === 'MD5') {
return strtoupper(md5($buff));
}
return strtoupper(hash_hmac('SHA256', $buff, $this->config->get('mch_key')));
}
/**
* 获取微信支付通知成功回复 XML
* @return string
*/
public function getNotifySuccessReply()
{
return Tools::arr2xml(['return_code' => 'SUCCESS', 'return_msg' => 'OK']);
}
/**
* 转换短链接tools/shorturl
* @param string $longUrl 需转换的URL签名用原串传输需URLencode
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function shortUrl($longUrl)
{
$url = 'https://api.mch.weixin.qq.com/tools/shorturl';
return $this->callPostApi($url, ['long_url' => $longUrl]);
}
/**
* 基础 POST 调用(自动签名,可选双向证书)
* @param string $url 请求地址
* @param array $data 接口参数
* @param bool $isCert 是否需要双向证书(退款等场景)
* @param string $signType MD5|HMAC-SHA256
* @param bool $needSignType 是否追加 sign_type 字段
* @param bool $needNonceStr 是否自动附加 nonce_str
* @return array XML 解析结果
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
protected function callPostApi($url, array $data, $isCert = false, $signType = 'HMAC-SHA256', $needSignType = true, $needNonceStr = true)
{
$option = [];
if ($isCert) {
$option['ssl_p12'] = $this->config->get('ssl_p12');
$option['ssl_cer'] = $this->config->get('ssl_cer');
$option['ssl_key'] = $this->config->get('ssl_key');
if (is_string($option['ssl_p12']) && file_exists($option['ssl_p12'])) {
$content = file_get_contents($option['ssl_p12']);
if (openssl_pkcs12_read($content, $certs, $this->config->get('mch_id'))) {
$option['ssl_key'] = Tools::pushFile(md5($certs['pkey']) . '.pem', $certs['pkey']);
$option['ssl_cer'] = Tools::pushFile(md5($certs['cert']) . '.pem', $certs['cert']);
} else throw new InvalidArgumentException("P12 certificate does not match MCH_ID --- ssl_p12");
}
if (empty($option['ssl_cer']) || !file_exists($option['ssl_cer'])) {
throw new InvalidArgumentException("Missing Config -- ssl_cer", '0');
}
if (empty($option['ssl_key']) || !file_exists($option['ssl_key'])) {
throw new InvalidArgumentException("Missing Config -- ssl_key", '0');
}
}
$params = $this->params->merge($data);
if (!$needNonceStr) unset($params['nonce_str']);
if ($needSignType) $params['sign_type'] = strtoupper($signType);
$params['sign'] = $this->getPaySign($params, $signType);
$result = Tools::xml2arr(Tools::post($url, Tools::arr2xml($params), $option));
if ($result['return_code'] !== 'SUCCESS') {
throw new InvalidResponseException($result['return_msg'], '0');
}
return $result;
}
/**
* 数组转 XML 输出
* @param array $data 待转换数据
* @param bool $isReturn true 返回字符串false 直接输出
* @return string|void
*/
public function toXml(array $data, $isReturn = false)
{
$xml = Tools::arr2xml($data);
if ($isReturn) return $xml;
echo $xml;
}
/**
* 通用接口V2调用
* @param string $url 完整 URL
* @param array|string $data 请求参数,数组自动补全商户参数并签名;字符串原样发送
* @param string $method GET|POST|PUT|DELETE|PATCH默认 POSTGET/HEAD/OPTIONS 不带签名)
* @param bool $isCert 是否启用双向证书
* @param string $signType MD5|HMAC-SHA256默认 HMAC-SHA256
* @return array XML 解析结果
* @throws \WeChat\Exceptions\InvalidArgumentException
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function callApi($url, $data = [], $method = 'POST', $isCert = false, $signType = 'HMAC-SHA256')
{
$method = strtoupper($method);
// 处理数据格式
$requestData = is_array($data) ? $data : (is_string($data) ? $data : []);
// GET/HEAD/OPTIONS请求无请求体不签名
if (in_array($method, ['GET', 'HEAD', 'OPTIONS'])) {
if (!empty($requestData) && is_array($requestData)) {
$url .= (strpos($url, '?') !== false ? '&' : '?') . http_build_query($requestData);
}
$response = Tools::get($url);
$result = Tools::xml2arr($response);
if (isset($result['return_code']) && $result['return_code'] !== 'SUCCESS') {
throw new InvalidResponseException($result['return_msg'], '0');
}
return $result;
}
// POST/PUT/PATCH/DELETE请求有请求体
$option = [];
if ($isCert) {
$option['ssl_p12'] = $this->config->get('ssl_p12');
$option['ssl_cer'] = $this->config->get('ssl_cer');
$option['ssl_key'] = $this->config->get('ssl_key');
if (is_string($option['ssl_p12']) && file_exists($option['ssl_p12'])) {
$content = file_get_contents($option['ssl_p12']);
if (openssl_pkcs12_read($content, $certs, $this->config->get('mch_id'))) {
$option['ssl_key'] = Tools::pushFile(md5($certs['pkey']) . '.pem', $certs['pkey']);
$option['ssl_cer'] = Tools::pushFile(md5($certs['cert']) . '.pem', $certs['cert']);
} else {
throw new InvalidArgumentException("P12 certificate does not match MCH_ID --- ssl_p12");
}
}
if (empty($option['ssl_cer']) || !file_exists($option['ssl_cer'])) {
throw new InvalidArgumentException("Missing Config -- ssl_cer", '0');
}
if (empty($option['ssl_key']) || !file_exists($option['ssl_key'])) {
throw new InvalidArgumentException("Missing Config -- ssl_key", '0');
}
}
// 合并参数并处理签名(默认自动签名)
if (is_array($requestData)) {
$params = $this->params->merge($requestData);
$params['sign_type'] = strtoupper($signType);
$params['sign'] = $this->getPaySign($params, $signType);
$option['data'] = Tools::arr2xml($params);
} else {
$option['data'] = $requestData;
}
// 使用doRequest支持PUT/DELETE/PATCH
$response = Tools::doRequest($method, $url, $option);
$result = Tools::xml2arr($response);
if (isset($result['return_code']) && $result['return_code'] !== 'SUCCESS') {
throw new InvalidResponseException($result['return_msg'], '0');
}
return $result;
}
}

View File

@ -1,42 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeChat\Contracts;
/**
* 企业微信基础类
* @package WeChat\Contracts
*/
class BasicWeWork extends BasicWeChat
{
/**
* 获取访问 AccessToken
* @return string
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getAccessToken()
{
if ($this->access_token) return $this->access_token;
$ckey = $this->config->get('appid') . '_access_token';
if ($this->access_token = Tools::getCache($ckey)) return $this->access_token;
list($appid, $secret) = [$this->config->get('appid'), $this->config->get('appsecret')];
$result = Tools::json2arr(Tools::get("https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={$appid}&corpsecret={$secret}"));
if (isset($result['access_token']) && $result['access_token']) Tools::setCache($ckey, $result['access_token'], 7000);
return $this->access_token = $result['access_token'];
}
}

View File

@ -1,130 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeChat\Contracts;
use ArrayAccess;
/**
* 数据处理类
* @package WeChat\Contracts
*/
class DataArray implements ArrayAccess
{
/**
* 当前配置值
* @var array
*/
private $config = [];
/**
* Config constructor.
* @param array $options
*/
public function __construct(array $options)
{
$this->config = $options;
}
/**
* 设置配置项值
* @param string $offset
* @param string|array|null|integer $value
*/
public function set($offset, $value)
{
$this->offsetSet($offset, $value);
}
/**
* 设置配置项值
* @param string $offset
* @param string|array|null|integer $value
* @return void
*/
#[\ReturnTypeWillChange]
public function offsetSet($offset, $value)
{
if (is_null($offset)) {
$this->config[] = $value;
} else {
$this->config[$offset] = $value;
}
}
/**
* 获取配置项参数
* @param string|null $offset
* @return array|string|null|mixed
*/
public function get($offset = null)
{
return $this->offsetGet($offset);
}
/**
* 获取配置项参数
* @param string|null $offset
* @return mixed
*/
#[\ReturnTypeWillChange]
public function offsetGet($offset = null)
{
if (is_null($offset)) return $this->config;
return isset($this->config[$offset]) ? $this->config[$offset] : null;
}
/**
* 合并数据到对象
* @param array $data 需要合并的数据
* @param bool $append 是否追加数据
* @return array
*/
public function merge(array $data, $append = false)
{
if ($append) {
return $this->config = array_merge($this->config, $data);
}
return array_merge($this->config, $data);
}
/**
* 判断配置Key是否存在
* @param string $offset
* @return bool
*/
#[\ReturnTypeWillChange]
public function offsetExists($offset)
{
return isset($this->config[$offset]);
}
/**
* 清理配置项
* @param string|null $offset
* @return void
*/
#[\ReturnTypeWillChange]
public function offsetUnset($offset = null)
{
if (is_null($offset)) {
$this->config = [];
} else {
unset($this->config[$offset]);
}
}
}

View File

@ -1,195 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeChat\Contracts;
/**
* 错误消息处理
* @package WeChat\Contracts
*/
class DataError
{
/**
* 接口代码错误
* @var array
*/
static $message = [
-1 => '系统繁忙,此时请开发者稍候再试',
0 => '请求成功',
40001 => '获取 access_token 时 AppSecret 错误,或者 access_token 无效。请开发者认真比对 AppSecret 的正确性,或查看是否正在为恰当的公众号调用接口',
40002 => '不合法的凭证类型',
40003 => '不合法的 OpenID ,请开发者确认 OpenID (该用户)是否已关注公众号,或是否是其他公众号的 OpenID',
40004 => '不合法的媒体文件类型',
40005 => '不合法的文件类型',
40006 => '不合法的文件大小',
40007 => '不合法的媒体文件 id',
40008 => '不合法的消息类型',
40009 => '不合法的图片文件大小',
40010 => '不合法的语音文件大小',
40011 => '不合法的视频文件大小',
40012 => '不合法的缩略图文件大小',
40013 => '不合法的 AppID ,请开发者检查 AppID 的正确性,避免异常字符,注意大小写',
40014 => '不合法的 access_token ,请开发者认真比对 access_token 的有效性(如是否过期),或查看是否正在为恰当的公众号调用接口',
40015 => '不合法的菜单类型',
40016 => '不合法的按钮个数',
40017 => '不合法的按钮个数',
40018 => '不合法的按钮名字长度',
40019 => '不合法的按钮 KEY 长度',
40020 => '不合法的按钮 URL 长度',
40021 => '不合法的菜单版本号',
40022 => '不合法的子菜单级数',
40023 => '不合法的子菜单按钮个数',
40024 => '不合法的子菜单按钮类型',
40025 => '不合法的子菜单按钮名字长度',
40026 => '不合法的子菜单按钮 KEY 长度',
40027 => '不合法的子菜单按钮 URL 长度',
40028 => '不合法的自定义菜单使用用户',
40029 => '不合法的 oauth_code',
40030 => '不合法的 refresh_token',
40031 => '不合法的 openid 列表',
40032 => '不合法的 openid 列表长度',
40033 => '不合法的请求字符,不能包含 \\uxxxx 格式的字符',
40035 => '不合法的参数',
40038 => '不合法的请求格式',
40039 => '不合法的 URL 长度',
40050 => '不合法的分组 id',
40051 => '分组名字不合法',
40060 => '删除单篇图文时,指定的 article_idx 不合法',
40117 => '分组名字不合法',
40118 => 'media_id 大小不合法',
40119 => 'button 类型错误',
40120 => 'button 类型错误',
40121 => '不合法的 media_id 类型',
40132 => '微信号不合法',
40137 => '不支持的图片格式',
40155 => '请勿添加其他公众号的主页链接',
41001 => '缺少 access_token 参数',
41002 => '缺少 appid 参数',
41003 => '缺少 refresh_token 参数',
41004 => '缺少 secret 参数',
41005 => '缺少多媒体文件数据',
41006 => '缺少 media_id 参数',
41007 => '缺少子菜单数据',
41008 => '缺少 oauth code',
41009 => '缺少 openid',
42001 => 'access_token 超时,请检查 access_token 的有效期,请参考基础支持 - 获取 access_token 中,对 access_token 的详细机制说明',
42002 => 'refresh_token 超时',
42003 => 'oauth_code 超时',
42007 => '用户修改微信密码, accesstoken 和 refreshtoken 失效,需要重新授权',
43001 => '需要 GET 请求',
43002 => '需要 POST 请求',
43003 => '需要 HTTPS 请求',
43004 => '需要接收者关注',
43005 => '需要好友关系',
43019 => '需要将接收者从黑名单中移除',
44001 => '多媒体文件为空',
44002 => 'POST 的数据包为空',
44003 => '图文消息内容为空',
44004 => '文本消息内容为空',
45001 => '多媒体文件大小超过限制',
45002 => '消息内容超过限制',
45003 => '标题字段超过限制',
45004 => '描述字段超过限制',
45005 => '链接字段超过限制',
45006 => '图片链接字段超过限制',
45007 => '语音播放时间超过限制',
45008 => '图文消息超过限制',
45009 => '接口调用超过限制',
45010 => '创建菜单个数超过限制',
45011 => 'API 调用太频繁,请稍候再试',
45015 => '回复时间超过限制',
45016 => '系统分组,不允许修改',
45017 => '分组名字过长',
45018 => '分组数量超过上限',
45047 => '客服接口下行条数超过上限',
46001 => '不存在媒体数据',
46002 => '不存在的菜单版本',
46003 => '不存在的菜单数据',
46004 => '不存在的用户',
47001 => '解析 JSON/XML 内容错误',
48001 => 'api 功能未授权,请确认公众号已获得该接口,可以在公众平台官网 - 开发者中心页中查看接口权限',
48002 => '粉丝拒收消息(粉丝在公众号选项中,关闭了 “ 接收消息 ” ',
48004 => 'api 接口被封禁,请登录 mp.weixin.qq.com 查看详情',
48005 => 'api 禁止删除被自动回复和自定义菜单引用的素材',
48006 => 'api 禁止清零调用次数,因为清零次数达到上限',
48008 => '没有该类型消息的发送权限',
50001 => '用户未授权该 api',
50002 => '用户受限,可能是违规后接口被封禁',
61451 => '参数错误 (invalid parameter)',
61452 => '无效客服账号 (invalid kf_account)',
61453 => '客服帐号已存在 (kf_account exsited)',
61454 => '客服帐号名长度超过限制 ( 仅允许 10 个英文字符,不包括 @ 及 @ 后的公众号的微信号 )(invalid kf_acount length)',
61455 => '客服帐号名包含非法字符 ( 仅允许英文 + 数字 )(illegal character in kf_account)',
61456 => '客服帐号个数超过限制 (10 个客服账号 )(kf_account count exceeded)',
61457 => '无效头像文件类型 (invalid file type)',
61450 => '系统错误 (system error)',
61500 => '日期格式错误',
65301 => '不存在此 menuid 对应的个性化菜单',
65302 => '没有相应的用户',
65303 => '没有默认菜单,不能创建个性化菜单',
65304 => 'MatchRule 信息为空',
65305 => '个性化菜单数量受限',
65306 => '不支持个性化菜单的帐号',
65307 => '个性化菜单信息为空',
65308 => '包含没有响应类型的 button',
65309 => '个性化菜单开关处于关闭状态',
65310 => '填写了省份或城市信息,国家信息不能为空',
65311 => '填写了城市信息,省份信息不能为空',
65312 => '不合法的国家信息',
65313 => '不合法的省份信息',
65314 => '不合法的城市信息',
65316 => '该公众号的菜单设置了过多的域名外跳(最多跳转到 3 个域名的链接)',
65317 => '不合法的 URL',
9001001 => 'POST 数据参数不合法',
9001002 => '远端服务不可用',
9001003 => 'Ticket 不合法',
9001004 => '获取摇周边用户信息失败',
9001005 => '获取商户信息失败',
9001006 => '获取 OpenID 失败',
9001007 => '上传文件缺失',
9001008 => '上传素材的文件类型不合法',
9001009 => '上传素材的文件尺寸不合法',
9001010 => '上传失败',
9001020 => '帐号不合法',
9001021 => '已有设备激活率低于 50% ,不能新增设备',
9001022 => '设备申请数不合法,必须为大于 0 的数字',
9001023 => '已存在审核中的设备 ID 申请',
9001024 => '一次查询设备 ID 数量不能超过 50',
9001025 => '设备 ID 不合法',
9001026 => '页面 ID 不合法',
9001027 => '页面参数不合法',
9001028 => '一次删除页面 ID 数量不能超过 10',
9001029 => '页面已应用在设备中,请先解除应用关系再删除',
9001030 => '一次查询页面 ID 数量不能超过 50',
9001031 => '时间区间不合法',
9001032 => '保存设备与页面的绑定关系参数错误',
9001033 => '门店 ID 不合法',
9001034 => '设备备注信息过长',
9001035 => '设备申请参数不合法',
9001036 => '查询起始值 begin 不合法',
];
/**
* 异常代码解析描述
* @param string $code
* @return string
*/
public static function toMessage($code)
{
return isset(self::$message[$code]) ? self::$message[$code] : $code;
}
}

View File

@ -1,78 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeChat\Contracts;
/**
* 自定义CURL文件类
* @package WeChat\Contracts
*/
class MyCurlFile extends \stdClass
{
/**
* 当前数据类型
* @var string
*/
public $datatype = 'MY_CURL_FILE';
/**
* MyCurlFile constructor.
* @param string|array $filename
* @param string $mimetype
* @param string $postname
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function __construct($filename, $mimetype = '', $postname = '')
{
if (is_array($filename)) {
foreach ($filename as $k => $v) $this->{$k} = $v;
} else {
$this->mimetype = $mimetype;
$this->postname = $postname;
$this->extension = pathinfo($filename, PATHINFO_EXTENSION);
if (empty($this->extension)) $this->extension = 'tmp';
if (empty($this->mimetype)) $this->mimetype = Tools::getExtMine($this->extension);
if (empty($this->postname)) $this->postname = pathinfo($filename, PATHINFO_BASENAME);
$this->content = base64_encode(file_get_contents($filename));
$this->tempname = md5($this->content) . ".{$this->extension}";
}
}
/**
* 获取文件上传信息
* @return \CURLFile|string
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function get()
{
$this->filename = Tools::pushFile($this->tempname, base64_decode($this->content));
if (class_exists('CURLFile')) {
return new \CURLFile($this->filename, $this->mimetype, $this->postname);
} else {
return "@{$this->tempname};filename={$this->postname};type={$this->mimetype}";
}
}
/**
* 通用销毁函数清理缓存文件
* 提前删除过期因此放到了网络请求之后
*/
public function __destruct()
{
// Tools::delCache($this->tempname);
}
}

View File

@ -1,528 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeChat\Contracts;
use WeChat\Exceptions\InvalidArgumentException;
use WeChat\Exceptions\InvalidResponseException;
use WeChat\Exceptions\LocalCacheException;
// =====================================================
// 配置缓存处理函数 ( 适配其他环境 )
// -----------------------------------------------------
// 数据缓存 (set|get|del) 操作可以将缓存写到任意位置或Redis
// 文件缓存 (put) 只能写在本地服务器,还需要返回可读的文件路径
// 未配置自定义缓存处理机制时,默认在 cache_path 写入文件缓存
// // =====================================================
// \WeChat\Contracts\Tools::$cache_callable = [
// 'set' => function ($name, $value, $expired = 360) {
// var_dump(func_get_args());
// return $value;
// },
// 'get' => function ($name) {
// var_dump(func_get_args());
// return $value;
// },
// 'del' => function ($name) {
// var_dump(func_get_args());
// return true;
// },
// 'put' => function ($name) {
// var_dump(func_get_args());
// return $filePath;
// },
// ];
/**
* 网络请求支持
* @package WeChat\Contracts
*/
class Tools
{
/**
* 缓存路径
* @var null
*/
public static $cache_path = null;
/**
* 缓存读写配置
* @var array
*/
public static $cache_callable = [
'set' => null, // 写入缓存 ($name,$value='',$expired=3600):string
'get' => null, // 获取缓存 ($name):mixed|null
'del' => null, // 删除缓存 ($name):boolean
'put' => null, // 写入文件 ($name,$content):string
];
/**
* 网络缓存
* @var array
*/
private static $cache_curl = [];
/**
* 产生随机字符串
* @param int $length 指定字符长度
* @param string $str 字符串前缀
* @return string
*/
public static function createNoncestr($length = 32, $str = "")
{
$chars = "abcdefghijklmnopqrstuvwxyz0123456789";
for ($i = 0; $i < $length; $i++) {
$str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
}
return $str;
}
/**
* 获取输入对象
* @return string
*/
public static function getRawInput()
{
if (empty($GLOBALS['HTTP_RAW_POST_DATA'])) {
return file_get_contents('php://input');
} else {
return $GLOBALS['HTTP_RAW_POST_DATA'];
}
}
/**
* 设置输入内容
* @param string $rawInput
* @return void
*/
public static function setRawInput($rawInput)
{
$GLOBALS['HTTP_RAW_POST_DATA'] = $rawInput;
}
/**
* 数组转XML内容
* @param array $data
* @return string
*/
public static function arr2xml($data)
{
return "<xml>" . self::_arr2xml($data) . "</xml>";
}
/**
* XML内容生成
* @param array $data 数据
* @param string $content
* @return string
*/
private static function _arr2xml($data, $content = '')
{
foreach ($data as $key => $val) {
is_numeric($key) && $key = 'item';
$content .= "<{$key}>";
if (is_array($val) || is_object($val)) {
$content .= self::_arr2xml($val);
} elseif (is_string($val)) {
$content .= '<![CDATA[' . preg_replace("/[\\x00-\\x08\\x0b-\\x0c\\x0e-\\x1f]/", '', $val) . ']]>';
} else {
$content .= $val;
}
$content .= "</{$key}>";
}
return $content;
}
/**
* 解析XML文本内容
* @param string $xml
* @return array|false
*/
public static function xml3arr($xml)
{
$state = xml_parse($parser = xml_parser_create(), $xml, true);
return xml_parser_free($parser) && $state ? self::xml2arr($xml) : false;
}
/**
* 解析XML内容到数组
* @param string $xml
* @return array
*/
public static function xml2arr($xml)
{
if (PHP_VERSION_ID < 80000) {
$backup = libxml_disable_entity_loader(true);
$data = (array)simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
libxml_disable_entity_loader($backup);
} else {
$data = (array)simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
}
return json_decode(json_encode($data), true);
}
/**
* 数组转xml内容
* @param array $data
* @return null|string
*/
public static function arr2json($data)
{
$json = json_encode($data, JSON_UNESCAPED_UNICODE);
return $json === '[]' ? '{}' : $json;
}
/**
* 数组对象Emoji编译处理
* @param array $data
* @return array
*/
public static function buildEnEmojiData(array $data)
{
foreach ($data as $key => $value) {
if (is_array($value)) {
$data[$key] = self::buildEnEmojiData($value);
} elseif (is_string($value)) {
$data[$key] = self::emojiEncode($value);
} else {
$data[$key] = $value;
}
}
return $data;
}
/**
* Emoji原形转换为String
* @param string $content
* @return string
*/
public static function emojiEncode($content)
{
return json_decode(preg_replace_callback("/(\\\u[ed][0-9a-f]{3})/i", function ($string) {
return addslashes($string[0]);
}, json_encode($content)));
}
/**
* 数组对象Emoji反解析处理
* @param array $data
* @return array
*/
public static function buildDeEmojiData(array $data)
{
foreach ($data as $key => $value) {
if (is_array($value)) {
$data[$key] = self::buildDeEmojiData($value);
} elseif (is_string($value)) {
$data[$key] = self::emojiDecode($value);
} else {
$data[$key] = $value;
}
}
return $data;
}
/**
* Emoji字符串转换为原形
* @param string $content
* @return string
*/
public static function emojiDecode($content)
{
return json_decode(preg_replace_callback('/\\\\\\\\/i', function () {
return '\\';
}, json_encode($content)));
}
/**
* 解析JSON内容到数组
* @param string $json
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public static function json2arr($json)
{
$result = json_decode($json, true);
if (empty($result)) {
throw new InvalidResponseException('invalid response.', '0');
}
if (!empty($result['errcode'])) {
throw new InvalidResponseException($result['errmsg'], $result['errcode'], $result);
}
return $result;
}
/**
* 以get访问模拟访问
* @param string $url 访问URL
* @param array $query GET数
* @param array $options
* @return boolean|string
* @throws \WeChat\Exceptions\LocalCacheException
*/
public static function get($url, $query = [], $options = [])
{
$options['query'] = $query;
return self::doRequest('get', $url, $options);
}
/**
* CURL模拟网络请求
* @param string $method 请求方法
* @param string $url 请求方法
* @param array $options 请求参数[headers,data,ssl_cer,ssl_key]
* @return boolean|string
* @throws \WeChat\Exceptions\LocalCacheException
*/
public static function doRequest($method, $url, $options = [])
{
$curl = curl_init();
// GET参数设置
if (!empty($options['query'])) {
$url .= (stripos($url, '?') !== false ? '&' : '?') . http_build_query($options['query']);
}
// CURL头信息设置
if (!empty($options['headers'])) {
curl_setopt($curl, CURLOPT_HTTPHEADER, $options['headers']);
}
// POST/PUT/PATCH/DELETE数据设置
$methodLower = strtolower($method);
if (in_array($methodLower, ['post', 'put', 'patch', 'delete'])) {
if ($methodLower === 'post') {
curl_setopt($curl, CURLOPT_POST, true);
} else {
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, strtoupper($method));
}
curl_setopt($curl, CURLOPT_POSTFIELDS, self::_buildHttpData($options['data']));
}
// 证书文件设置
if (!empty($options['ssl_cer'])) if (file_exists($options['ssl_cer'])) {
curl_setopt($curl, CURLOPT_SSLCERTTYPE, 'PEM');
curl_setopt($curl, CURLOPT_SSLCERT, $options['ssl_cer']);
} else throw new InvalidArgumentException("Certificate files that do not exist. --- [ssl_cer]");
// 证书文件设置
if (!empty($options['ssl_key'])) if (file_exists($options['ssl_key'])) {
curl_setopt($curl, CURLOPT_SSLKEYTYPE, 'PEM');
curl_setopt($curl, CURLOPT_SSLKEY, $options['ssl_key']);
} else throw new InvalidArgumentException("Certificate files that do not exist. --- [ssl_key]");
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_TIMEOUT, isset($options['timeout']) ? intval($options['timeout']) : 60);
curl_setopt($curl, CURLOPT_HEADER, false);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
$content = curl_exec($curl);
curl_close($curl);
// 清理 CURL 缓存文件
if (!empty(self::$cache_curl)) foreach (self::$cache_curl as $key => $file) {
Tools::delCache($file);
unset(self::$cache_curl[$key]);
}
return $content;
}
/**
* POST数据过滤处理
* @param array $data 需要处理的数据
* @param boolean $build 是否编译数据
* @return array|string
* @throws \WeChat\Exceptions\LocalCacheException
*/
private static function _buildHttpData($data, $build = true)
{
if (!is_array($data)) return $data;
foreach ($data as $key => $value) if ($value instanceof \CURLFile) {
$build = false;
} elseif (is_object($value) && isset($value->datatype) && $value->datatype === 'MY_CURL_FILE') {
$build = false;
$mycurl = new MyCurlFile((array)$value);
$data[$key] = $mycurl->get();
self::$cache_curl[] = $mycurl->tempname;
} elseif (is_array($value) && isset($value['datatype']) && $value['datatype'] === 'MY_CURL_FILE') {
$build = false;
$mycurl = new MyCurlFile($value);
$data[$key] = $mycurl->get();
self::$cache_curl[] = $mycurl->tempname;
} elseif (is_string($value) && class_exists('CURLFile', false) && stripos($value, '@') === 0) {
if (($filename = realpath(trim($value, '@'))) && file_exists($filename)) {
$build = false;
$data[$key] = self::createCurlFile($filename);
}
}
return $build ? http_build_query($data) : $data;
}
/**
* 创建CURL文件对象
* @param mixed $filename
* @param string $mimetype
* @param string $postname
* @return \CURLFile|string
* @throws \WeChat\Exceptions\LocalCacheException
*/
public static function createCurlFile($filename, $mimetype = null, $postname = null)
{
if (is_string($filename) && file_exists($filename)) {
if (is_null($postname)) $postname = basename($filename);
if (is_null($mimetype)) $mimetype = self::getExtMine(pathinfo($filename, 4));
if (class_exists('CURLFile')) {
return new \CURLFile($filename, $mimetype, $postname);
} else {
return "@{$filename};filename={$postname};type={$mimetype}";
}
}
return $filename;
}
/**
* 根据文件后缀获取文件类型
* @param string|array $ext 文件后缀
* @param array $mine 文件后缀MINE信息
* @return string
* @throws \WeChat\Exceptions\LocalCacheException
*/
public static function getExtMine($ext, $mine = [])
{
$mines = self::getMines();
foreach (is_string($ext) ? explode(',', $ext) : $ext as $e) {
$mine[] = isset($mines[strtolower($e)]) ? $mines[strtolower($e)] : 'application/octet-stream';
}
return join(',', array_unique($mine));
}
/**
* 获取所有文件扩展的类型
* @return array
* @throws \WeChat\Exceptions\LocalCacheException
*/
private static function getMines()
{
$mines = self::getCache('all_ext_mine');
if (empty($mines)) {
$content = file_get_contents('http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types');
preg_match_all('#^([^\s]{2,}?)\s+(.+?)$#ism', $content, $matches, PREG_SET_ORDER);
foreach ($matches as $match) foreach (explode(" ", $match[2]) as $ext) $mines[$ext] = $match[1];
self::setCache('all_ext_mine', $mines);
}
return $mines;
}
/**
* 获取缓存内容
* @param string $name 缓存名称
* @return null|mixed
*/
public static function getCache($name)
{
if (is_callable(self::$cache_callable['get'])) {
return call_user_func_array(self::$cache_callable['get'], func_get_args());
}
$file = self::_getCacheName($name);
if (file_exists($file) && is_file($file) && ($content = file_get_contents($file))) {
$data = unserialize($content);
if (isset($data['expired']) && (intval($data['expired']) === 0 || intval($data['expired']) >= time())) {
return $data['value'];
}
self::delCache($name);
}
return null;
}
/**
* 应用缓存目录
* @param string $name
* @return string
*/
private static function _getCacheName($name)
{
if (empty(self::$cache_path)) {
self::$cache_path = dirname(dirname(__DIR__)) . DIRECTORY_SEPARATOR . 'Cache' . DIRECTORY_SEPARATOR;
}
$cachePath = rtrim((string)self::$cache_path, '/\\') . DIRECTORY_SEPARATOR;
if (!file_exists($cachePath)) {
mkdir($cachePath, 0755, true);
}
return $cachePath . $name;
}
/**
* 移除缓存文件
* @param string $name 缓存名称
* @return boolean
*/
public static function delCache($name)
{
if (is_callable(self::$cache_callable['del'])) {
return call_user_func_array(self::$cache_callable['del'], func_get_args());
}
$file = self::_getCacheName($name);
return !file_exists($file) || @unlink($file);
}
/**
* 缓存配置与存储
* @param string $name 缓存名称
* @param string $value 缓存内容
* @param int $expired 缓存时间(0表示永久缓存)
* @return string
* @throws \WeChat\Exceptions\LocalCacheException
*/
public static function setCache($name, $value = '', $expired = 3600)
{
if (is_callable(self::$cache_callable['set'])) {
return call_user_func_array(self::$cache_callable['set'], func_get_args());
}
$file = self::_getCacheName($name);
$data = ['name' => $name, 'value' => $value, 'expired' => time() + intval($expired)];
if (!file_put_contents($file, serialize($data))) {
throw new LocalCacheException('local cache error.', '0');
}
return $file;
}
/**
* 以post访问模拟访问
* @param string $url 访问URL
* @param array $data POST数据
* @param array $options
* @return boolean|string
* @throws \WeChat\Exceptions\LocalCacheException
*/
public static function post($url, $data = [], $options = [])
{
$options['data'] = $data;
return self::doRequest('post', $url, $options);
}
/**
* 写入文件
* @param string $name 文件名称
* @param string $content 文件内容
* @return string
* @throws \WeChat\Exceptions\LocalCacheException
*/
public static function pushFile($name, $content)
{
if (is_callable(self::$cache_callable['put'])) {
return call_user_func_array(self::$cache_callable['put'], func_get_args());
}
$file = self::_getCacheName($name);
if (!file_put_contents($file, $content)) {
throw new LocalCacheException('local file write error.', '0');
}
return $file;
}
}

View File

@ -1,228 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeChat;
use WeChat\Contracts\BasicWeChat;
use WeChat\Contracts\Tools;
/**
* 客服消息处理
* @package WeChat
*/
class Custom extends BasicWeChat
{
/**
* 添加客服帐号
* @param string $kf_account 客服账号,格式 账号前缀@公众号微信号
* @param string $nickname 客服昵称
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function addAccount($kf_account, $nickname)
{
$url = "https://api.weixin.qq.com/customservice/kfaccount/add?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['kf_account' => $kf_account, 'nickname' => $nickname]);
}
/**
* 修改客服帐号
* @param string $kfAccount 客服账号
* @param string $nickname 客服昵称
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function updateAccount($kfAccount, $nickname)
{
$url = "https://api.weixin.qq.com/customservice/kfaccount/update?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['kf_account' => $kfAccount, 'nickname' => $nickname]);
}
/**
* 删除客服帐号
* @param string $kfAccount 客服账号
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function deleteAccount($kfAccount)
{
$url = "https://api.weixin.qq.com/customservice/kfaccount/del?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['kf_account' => $kfAccount]);
}
/**
* 邀请绑定客服帐号
* @param string $kfAccount 客服账号,格式 账号前缀@公众号微信号
* @param string $invite_wx 接收绑定邀请的客服微信号
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function inviteWorker($kfAccount, $invite_wx)
{
$url = 'https://api.weixin.qq.com/customservice/kfaccount/inviteworker?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, ['kf_account' => $kfAccount, 'invite_wx' => $invite_wx]);
}
/**
* 获取客服账号列表
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function getAccountList()
{
$url = "https://api.weixin.qq.com/cgi-bin/customservice/getkflist?access_token=ACCESS_TOKEN";
return $this->callGetApi($url);
}
/**
* 设置客服头像
* @param string $kf_account 客服账号
* @param string $image 本地图片路径
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function uploadHeadimg($kf_account, $image)
{
$url = "https://api.weixin.qq.com/customservice/kfaccount/uploadheadimg?access_token=ACCESS_TOKEN&kf_account={$kf_account}";
return $this->callPostApi($url, ['media' => Tools::createCurlFile($image)], false);
}
/**
* 发送客服消息
* @param array $data 消息体touser, msgtype, content 等)
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function send(array $data)
{
$url = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data);
}
/**
* 设置客服输入状态
* @param string $openid 用户 openid
* @param string $command Typing|CancelTyping
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function typing($openid, $command = 'Typing')
{
$url = "https://api.weixin.qq.com/cgi-bin/message/custom/typing?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['touser' => $openid, 'command' => $command]);
}
/**
* 根据标签群发
* @param array $data 群发参数
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function massSendAll(array $data)
{
$url = "https://api.weixin.qq.com/cgi-bin/message/mass/sendall?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data);
}
/**
* 根据 OpenID 列表群发
* @param array $data 群发参数
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function massSend(array $data)
{
$url = "https://api.weixin.qq.com/cgi-bin/message/mass/send?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data);
}
/**
* 删除群发
* @param int $msg_id 群发消息ID
* @param null|int $article_idx 图文位置0 删除全部
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function massDelete($msg_id, $article_idx = null)
{
$data = ['msg_id' => $msg_id];
is_null($article_idx) || $data['article_idx'] = $article_idx;
$url = "https://api.weixin.qq.com/cgi-bin/message/mass/delete?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data);
}
/**
* 群发预览
* @param array $data 预览参数
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function massPreview(array $data)
{
$url = "https://api.weixin.qq.com/cgi-bin/message/mass/preview?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data);
}
/**
* 查询群发状态
* @param int $msgId 群发消息ID
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function massGet($msgId)
{
$url = "https://api.weixin.qq.com/cgi-bin/message/mass/get?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['msg_id' => $msgId]);
}
/**
* 获取群发速度
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function massGetSeed()
{
$url = "https://api.weixin.qq.com/cgi-bin/message/mass/speed/get?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, []);
}
/**
* 设置群发速度
* @param int $speed 速度级别
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function massSetSeed($speed)
{
$url = "https://api.weixin.qq.com/cgi-bin/message/mass/speed/set?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['speed' => $speed]);
}
}

View File

@ -1,123 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeChat;
use WeChat\Contracts\BasicWeChat;
/**
* 微信草稿箱管理
* @author taoxin
* @package WeChat
*/
class Draft extends BasicWeChat
{
/**
* 新建草稿
* @param array $articles 图文数组 articles
* @return array 草稿 media_id
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function add($articles)
{
$url = "https://api.weixin.qq.com/cgi-bin/draft/add?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['articles' => $articles]);
}
/**
* 获取草稿
* @param string $mediaId 草稿 media_id
* @param string $outType 可选回调处理
* @return array 草稿内容
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function get($mediaId, $outType = null)
{
$url = "https://api.weixin.qq.com/cgi-bin/draft/get?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['media_id' => $mediaId]);
}
/**
* 删除草稿
* @param string $mediaId 草稿 media_id
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function delete($mediaId)
{
$url = "https://api.weixin.qq.com/cgi-bin/draft/delete?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['media_id' => $mediaId]);
}
/**
* 新增图文素材
* @param array $data 图文 articles
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function addNews($data)
{
$url = "https://api.weixin.qq.com/cgi-bin/material/add_news?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data);
}
/**
* 修改草稿
* @param string $media_id 草稿 media_id
* @param int $index 文章序号0 开始)
* @param array $articles 文章内容
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function update($media_id, $index, $articles)
{
$url = "https://api.weixin.qq.com/cgi-bin/draft/update?access_token=ACCESS_TOKEN";
$data = ['media_id' => $media_id, 'index' => $index, 'articles' => $articles];
return $this->callPostApi($url, $data);
}
/**
* 获取草稿总数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getCount()
{
$url = "https://api.weixin.qq.com/cgi-bin/draft/count?access_token=ACCESS_TOKEN";
return $this->callGetApi($url);
}
/**
* 获取草稿列表
* @param int $offset 起始位置
* @param int $count 拉取数量 1-20
* @param int $noContent 1 不返回 content0 返回
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function batchGet($offset = 0, $count = 20, $noContent = 0)
{
$url = "https://api.weixin.qq.com/cgi-bin/draft/batchget?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['no_content' => $noContent, 'offset' => $offset, 'count' => $count]);
}
}

View File

@ -1,41 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeChat\Exceptions;
/**
* 接口参数异常
* @package WeChat\Exceptions
*/
class InvalidArgumentException extends \InvalidArgumentException
{
/**
* @var array
*/
public $raw = [];
/**
* InvalidArgumentException constructor.
* @param string $message
* @param integer $code
* @param array $raw
*/
public function __construct($message, $code = 0, $raw = [])
{
parent::__construct($message, intval($code));
$this->raw = $raw;
}
}

View File

@ -1,41 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeChat\Exceptions;
/**
* 加密解密异常
* @package WeChat\Exceptions
*/
class InvalidDecryptException extends \Exception
{
/**
* @var array
*/
public $raw = [];
/**
* InvalidDecryptException constructor.
* @param string $message
* @param integer $code
* @param array $raw
*/
public function __construct($message, $code = 0, $raw = [])
{
parent::__construct($message, intval($code));
$this->raw = $raw;
}
}

View File

@ -1,41 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeChat\Exceptions;
/**
* 加载类异常
* @package WeChat\Exceptions
*/
class InvalidInstanceException extends \Exception
{
/**
* @var array
*/
public $raw = [];
/**
* InvalidResponseException constructor.
* @param string $message
* @param integer $code
* @param array $raw
*/
public function __construct($message, $code = 0, $raw = [])
{
parent::__construct($message, intval($code));
$this->raw = $raw;
}
}

View File

@ -1,42 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeChat\Exceptions;
/**
* 返回异常
* @package WeChat\Exceptions
*/
class InvalidResponseException extends \Exception
{
/**
* @var array
*/
public $raw = [];
/**
* InvalidResponseException constructor.
* @param string $message
* @param integer $code
* @param array $raw
*/
public function __construct($message, $code = 0, $raw = [])
{
parent::__construct($message, intval($code));
$this->raw = $raw;
}
}

View File

@ -1,43 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeChat\Exceptions;
/***
* 本地缓存异常
* @package WeChat\Exceptions
*/
class LocalCacheException extends \Exception
{
/**
* @var array
*/
public $raw = [];
/**
* LocalCacheException constructor.
* @param string $message
* @param integer $code
* @param array $raw
*/
public function __construct($message, $code = 0, $raw = [])
{
parent::__construct($message, intval($code));
$this->raw = $raw;
}
}

View File

@ -1,95 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeChat;
use WeChat\Contracts\BasicWeChat;
/**
* 发布能力
* @author taoxin
* @package WeChat
*/
class Freepublish extends BasicWeChat
{
/**
* 提交发布
* @param string $mediaId 草稿 media_id
* @return array publish_id
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function submit($mediaId)
{
$url = "https://api.weixin.qq.com/cgi-bin/freepublish/submit?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['media_id' => $mediaId]);
}
/**
* 查询发布状态
* @param string $publishId 发布任务 ID
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function get($publishId)
{
$url = "https://api.weixin.qq.com/cgi-bin/freepublish/get?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['publish_id' => $publishId]);
}
/**
* 删除已发布文章
* @param string $articleId 发布返回的 article_id
* @param int $index 图文序号1 开始0 删除全部
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function delete($articleId, $index = 0)
{
$url = "https://api.weixin.qq.com/cgi-bin/freepublish/delete?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['article_id' => $articleId, 'index' => $index]);
}
/**
* 获取已发布文章
* @param string $articleId article_id
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getArticle($articleId)
{
$url = "https://api.weixin.qq.com/cgi-bin/freepublish/getarticle?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['article_id' => $articleId]);
}
/**
* 获取已发布列表
* @param int $offset 起始偏移
* @param int $count 数量 1-20
* @param int $noContent 1 不返回 content
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function batchGet($offset = 0, $count = 20, $noContent = 0)
{
$url = "https://api.weixin.qq.com/cgi-bin/freepublish/batchget?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['no_content' => $noContent, 'offset' => $offset, 'count' => $count]);
}
}

View File

@ -1,65 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeChat;
use WeChat\Contracts\BasicWeChat;
/**
* 接口调用频次限制
* @package WeChat
*/
class Limit extends BasicWeChat
{
/**
* 清空公众号 API 调用次数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function clearQuota()
{
$url = 'https://api.weixin.qq.com/cgi-bin/clear_quota?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, ['appid' => $this->config->get('appid')]);
}
/**
* 网络检测
* @param string $action ping|dns|all
* @param string $operator DEFAULT|CT|CU|CM
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function ping($action = 'all', $operator = 'DEFAULT')
{
$url = 'https://api.weixin.qq.com/cgi-bin/callback/check?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, ['action' => $action, 'check_operator' => $operator]);
}
/**
* 获取微信服务器 IP
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getCallbackIp()
{
$url = 'https://api.weixin.qq.com/cgi-bin/getcallbackip?access_token=ACCESS_TOKEN';
return $this->callGetApi($url);
}
}

View File

@ -1,195 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeChat;
use WeChat\Contracts\BasicWeChat;
use WeChat\Contracts\Tools;
use WeChat\Exceptions\InvalidResponseException;
/**
* 微信素材管理
* @package WeChat
*/
class Media extends BasicWeChat
{
/**
* 新增临时素材
* @param string $filename 本地文件路径
* @param string $type 媒体类型 image|voice|video|thumb
* @return array 上传结果media_id 等)
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function add($filename, $type = 'image')
{
if (!in_array($type, ['image', 'voice', 'video', 'thumb'])) {
throw new InvalidResponseException('Invalid Media Type.', '0');
}
$url = "https://api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type={$type}";
return $this->callPostApi($url, ['media' => Tools::createCurlFile($filename)], false);
}
/**
* 获取临时素材
* @param string $media_id 媒体 ID
* @param string $outType 可选:回调处理或 'url' 仅返回 URL
* @return array|string
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function get($media_id, $outType = null)
{
$url = "https://api.weixin.qq.com/cgi-bin/media/get?access_token=ACCESS_TOKEN&media_id={$media_id}";
$this->registerApi($url, __FUNCTION__, func_get_args());
if ($outType == 'url') return $url;
$result = Tools::get($url);
if (is_array($json = json_decode($result, true))) {
if (!$this->isTry && isset($json['errcode']) && in_array($json['errcode'], ['40014', '40001', '41001', '42001'])) {
[$this->delAccessToken(), $this->isTry = true];
return call_user_func_array([$this, $this->currentMethod['method']], $this->currentMethod['arguments']);
}
return Tools::json2arr($result);
}
return is_null($outType) ? $result : $outType($result);
}
/**
* 新增永久图文素材
* @param array $data 图文列表 articles
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function addNews($data)
{
$url = "https://api.weixin.qq.com/cgi-bin/material/add_news?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data);
}
/**
* 更新图文素材
* @param string $media_id 图文 media_id
* @param int $index 文章位置0 开始)
* @param array $news 文章内容
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function updateNews($media_id, $index, $news)
{
$url = "https://api.weixin.qq.com/cgi-bin/material/update_news?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['media_id' => $media_id, 'index' => $index, 'articles' => $news]);
}
/**
* 上传图文消息内的图片,获取 URL
* @param string $filename 本地文件
* @return array url
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function uploadImg($filename)
{
$url = "https://api.weixin.qq.com/cgi-bin/media/uploadimg?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['media' => Tools::createCurlFile($filename)], false);
}
/**
* 新增其他类型永久素材
* @param string $filename 本地文件路径
* @param string $type 媒体类型 image|voice|video|thumb
* @param array $description 视频描述等
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function addMaterial($filename, $type = 'image', $description = [])
{
if (!in_array($type, ['image', 'voice', 'video', 'thumb'])) {
throw new InvalidResponseException('Invalid Media Type.', '0');
}
$url = "https://api.weixin.qq.com/cgi-bin/material/add_material?access_token=ACCESS_TOKEN&type={$type}";
return $this->callPostApi($url, ['media' => Tools::createCurlFile($filename), 'description' => Tools::arr2json($description)], false);
}
/**
* 获取永久素材
* @param string $media_id 媒体 ID
* @param null|string $outType 回调处理或 'url' 返回地址
* @return array|string
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getMaterial($media_id, $outType = null)
{
$url = "https://api.weixin.qq.com/cgi-bin/material/get_material?access_token=ACCESS_TOKEN";
$this->registerApi($url, __FUNCTION__, func_get_args());
if ($outType == 'url') return $url;
$result = Tools::post($url, ['media_id' => $media_id]);
if (is_array($json = json_decode($result, true))) {
if (!$this->isTry && isset($json['errcode']) && in_array($json['errcode'], ['40014', '40001', '41001', '42001'])) {
[$this->delAccessToken(), $this->isTry = true];
return call_user_func_array([$this, $this->currentMethod['method']], $this->currentMethod['arguments']);
}
return Tools::json2arr($result);
}
return is_null($outType) ? $result : $outType($result);
}
/**
* 删除永久素材
* @param string $mediaId 媒体 ID
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function delMaterial($mediaId)
{
$url = "https://api.weixin.qq.com/cgi-bin/material/del_material?access_token=ACCESS_TOKEN";
return $this->httpPostForJson($url, ['media_id' => $mediaId]);
}
/**
* 获取素材总数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getMaterialCount()
{
$url = "https://api.weixin.qq.com/cgi-bin/material/get_materialcount?access_token=ACCESS_TOKEN";
return $this->callGetApi($url);
}
/**
* 获取素材列表
* @param string $type image|voice|video|news
* @param int $offset 起始位置
* @param int $count 拉取数量
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function batchGetMaterial($type = 'image', $offset = 0, $count = 20)
{
if (!in_array($type, ['image', 'voice', 'video', 'news'])) {
throw new InvalidResponseException('Invalid Media Type.', '0');
}
$url = "https://api.weixin.qq.com/cgi-bin/material/batchget_material?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['type' => $type, 'offset' => $offset, 'count' => $count]);
}
}

View File

@ -1,103 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeChat;
use WeChat\Contracts\BasicWeChat;
/**
* 微信菜单管理
* @package WeChat
*/
class Menu extends BasicWeChat
{
/**
* 查询自定义菜单接口
* @return array 菜单配置信息
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function get()
{
$url = "https://api.weixin.qq.com/cgi-bin/menu/get?access_token=ACCESS_TOKEN";
return $this->callGetApi($url);
}
/**
* 删除自定义菜单接口
* @return array 操作结果
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function delete()
{
$url = "https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=ACCESS_TOKEN";
return $this->callGetApi($url);
}
/**
* 创建自定义菜单接口
* @param array $data 菜单配置button数组最多3个一级菜单每个一级菜单最多5个二级菜单
* @return array 操作结果
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function create(array $data)
{
$url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data);
}
/**
* 创建个性化菜单接口
* @param array $data 菜单配置button数组和matchrule匹配规则
* @return array 返回menuid
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function addConditional(array $data)
{
$url = "https://api.weixin.qq.com/cgi-bin/menu/addconditional?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data);
}
/**
* 删除个性化菜单接口
* @param string $menuid 菜单ID
* @return array 操作结果
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function delConditional($menuid)
{
$url = "https://api.weixin.qq.com/cgi-bin/menu/delconditional?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['menuid' => $menuid]);
}
/**
* 测试个性化菜单匹配结果接口
* @param string $openid 用户openid
* @return array 该用户匹配的菜单配置
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function tryConditional($openid)
{
$url = "https://api.weixin.qq.com/cgi-bin/menu/trymatch?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['user_id' => $openid]);
}
}

View File

@ -1,100 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeChat;
use WeChat\Contracts\BasicWeChat;
/**
* 微信网页授权
* @package WeChat
*/
class Oauth extends BasicWeChat
{
/**
* 构造网页授权跳转链接
* @param string $redirect_url 回调地址
* @param string $state 自定义状态(<=128 字节)
* @param string $scope snsapi_base|snsapi_userinfo
* @return string 跳转 URL
*/
public function getOauthRedirect($redirect_url, $state = '', $scope = 'snsapi_base')
{
$appid = $this->config->get('appid');
$redirect_uri = urlencode($redirect_url);
return "https://open.weixin.qq.com/connect/oauth2/authorize?appid={$appid}&redirect_uri={$redirect_uri}&response_type=code&scope={$scope}&state={$state}#wechat_redirect";
}
/**
* 通过 code 换取 access_token/refresh_token/openid
* @param string $code 授权 code不传则取 GET 参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getOauthAccessToken($code = '')
{
$appid = $this->config->get('appid');
$appsecret = $this->config->get('appsecret');
$code = $code ? $code : (isset($_GET['code']) ? $_GET['code'] : '');
$url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid={$appid}&secret={$appsecret}&code={$code}&grant_type=authorization_code";
return $this->httpGetForJson($url);
}
/**
* 刷新网页授权 access_token
* @param string $refresh_token 刷新 token
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getOauthRefreshToken($refresh_token)
{
$appid = $this->config->get('appid');
$url = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid={$appid}&grant_type=refresh_token&refresh_token={$refresh_token}";
return $this->httpGetForJson($url);
}
/**
* 校验网页授权 access_token 是否有效
* @param string $accessToken 网页授权 access_token
* @param string $openid 用户 openid
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function checkOauthAccessToken($accessToken, $openid)
{
$url = "https://api.weixin.qq.com/sns/auth?access_token={$accessToken}&openid={$openid}";
return $this->httpGetForJson($url);
}
/**
* 拉取用户信息snsapi_userinfo
* @param string $accessToken 网页授权 access_token
* @param string $openid 用户 openid
* @param string $lang zh_CN|zh_TW|en
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getUserInfo($accessToken, $openid, $lang = 'zh_CN')
{
$url = "https://api.weixin.qq.com/sns/userinfo?access_token={$accessToken}&openid={$openid}&lang={$lang}";
return $this->httpGetForJson($url);
}
}

View File

@ -1,232 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeChat;
use WeChat\Contracts\BasicWePay;
use WePay\Bill;
use WePay\Order;
use WePay\Refund;
use WePay\Transfers;
use WePay\TransfersBank;
/**
* 微信支付商户聚合入口V2
* @package WeChat\Contracts
*/
class Pay extends BasicWePay
{
/**
* 统一下单
* @param array $options 下单参数out_trade_no, body, total_fee, notify_url, trade_type 等)
* @return array 预支付信息
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function createOrder(array $options)
{
return Order::instance($this->config->get())->create($options);
}
/**
* 刷卡支付(被扫)
* @param array $options 支付参数auth_code, out_trade_no, total_fee 等)
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function createMicropay($options)
{
return Order::instance($this->config->get())->micropay($options);
}
/**
* 生成 JSAPI/H5 支付参数
* @param string $prepay_id 统一下单返回的 prepay_id
* @return array 前端调起参数
*/
public function createParamsForJsApi($prepay_id)
{
return Order::instance($this->config->get())->jsapiParams($prepay_id);
}
/**
* 生成 APP 支付参数
* @param string $prepay_id 统一下单返回的 prepay_id
* @return array APP 支付参数
*/
public function createParamsForApp($prepay_id)
{
return Order::instance($this->config->get())->appParams($prepay_id);
}
/**
* 生成 Native 支付二维码 URL
* @param string $product_id 商品 ID 或订单号
* @return string
*/
public function createParamsForRuleQrc($product_id)
{
return Order::instance($this->config->get())->qrcParams($product_id);
}
/**
* 查询订单
* @param array $options 查询参数transaction_id out_trade_no
* @return array 订单详情
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function queryOrder(array $options)
{
return Order::instance($this->config->get())->query($options);
}
/**
* 关闭订单
* @param string $out_trade_no 商户订单号
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function closeOrder($out_trade_no)
{
return Order::instance($this->config->get())->close($out_trade_no);
}
/**
* 申请退款
* @param array $options 退款参数out_trade_no/transaction_idout_refund_nototal_feerefund_fee 等)
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function createRefund(array $options)
{
return Refund::instance($this->config->get())->create($options);
}
/**
* 查询退款
* @param array $options 查询参数transaction_id/out_trade_no/out_refund_no/refund_id 四选一)
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function queryRefund(array $options)
{
return Refund::instance($this->config->get())->query($options);
}
/**
* 交易保障上报
* @param array $options 上报参数interface_url, execute_time, return_code 等)
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function report(array $options)
{
return Order::instance($this->config->get())->report($options);
}
/**
* 授权码查询 openid
* @param string $authCode 扫码支付授权码
* @return array openid
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function queryAuthCode($authCode)
{
return Order::instance($this->config->get())->queryAuthCode($authCode);
}
/**
* 下载对账单
* @param array $options 账单参数bill_date, bill_type 等)
* @param null|string $outType 输出处理回调,为 null 返回原始内容
* @return bool|string
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function billDownload(array $options, $outType = null)
{
return Bill::instance($this->config->get())->download($options, $outType);
}
/**
* 拉取订单评价数据(需证书)
* @param array $options 查询参数bill_date, offset, limit 等)
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function billCommtent(array $options)
{
return Bill::instance($this->config->get())->comment($options);
}
/**
* 企业付款到零钱
* @param array $options 付款参数partner_trade_no, openid, amount, desc 等)
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function createTransfers(array $options)
{
return Transfers::instance($this->config->get())->create($options);
}
/**
* 查询企业付款到零钱
* @param string $partner_trade_no 商户付款单号
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function queryTransfers($partner_trade_no)
{
return Transfers::instance($this->config->get())->query($partner_trade_no);
}
/**
* 企业付款到银行卡
* @param array $options 付款参数partner_trade_no, enc_bank_no, enc_true_name, bank_code, amount 等)
* @return array
* @throws \WeChat\Exceptions\InvalidDecryptException
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function createTransfersBank(array $options)
{
return TransfersBank::instance($this->config->get())->create($options);
}
/**
* 查询企业付款到银行卡结果
* @param string $partner_trade_no 商户付款单号
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function queryTransFresBank($partner_trade_no)
{
return TransfersBank::instance($this->config->get())->query($partner_trade_no);
}
}

View File

@ -1,165 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeChat;
use WeChat\Contracts\BasicWeChat;
/**
* 商店管理
* @package WeChat
*/
class Product extends BasicWeChat
{
/**
* 提交审核/取消发布商品
* @param string $keystandard 商品编码标准
* @param string $keystr 商品编码内容
* @param string $status on 提交审核 | off 取消发布
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function modStatus($keystandard, $keystr, $status = 'on')
{
$url = "https://api.weixin.qq.com/scan/product/modstatus?access_token=ACCESS_TOKEN";
$data = ['keystandard' => $keystandard, 'keystr' => $keystr, 'status' => $status];
return $this->callPostApi($url, $data);
}
/**
* 设置测试人员白名单
* @param array $openids openid 列表
* @param array $usernames 微信号列表
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function setTestWhiteList(array $openids = [], array $usernames = [])
{
$url = "https://api.weixin.qq.com/scan/testwhitelist/set?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['openid' => $openids, 'username' => $usernames]);
}
/**
* 获取商品二维码
* @param string $keystandard 编码标准
* @param string $keystr 编码内容
* @param int $qrcode_size 边长像素默认100
* @param array $extinfo 自定义扩展
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getQrcode($keystandard, $keystr, $qrcode_size, $extinfo = [])
{
$url = "https://api.weixin.qq.com/scan/product/getqrcode?access_token=ACCESS_TOKEN";
$data = ['keystandard' => $keystandard, 'keystr' => $keystr, 'qrcode_size' => $qrcode_size];
empty($extinfo) || $data['extinfo'] = $extinfo;
return $this->callPostApi($url, $data);
}
/**
* 查询商品信息
* @param string $keystandard 商品编码标准
* @param string $keystr 商品编码内容
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getProduct($keystandard, $keystr)
{
$url = "https://api.weixin.qq.com/scan/product/get?access_token=ACCESS_TOKEN";
$data = ['keystandard' => $keystandard, 'keystr' => $keystr];
empty($extinfo) || $data['extinfo'] = $extinfo;
return $this->callPostApi($url, $data);
}
/**
* 批量查询商品信息
* @param int $offset 起始位置
* @param int $limit 数量
* @param null|string $status on|off|check|reject|all
* @param string $keystr 模糊编码过滤
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getProductList($offset, $limit = 10, $status = null, $keystr = '')
{
$url = "https://api.weixin.qq.com/scan/product/get?access_token=ACCESS_TOKEN";
$data = ['offset' => $offset, 'limit' => $limit];
is_null($status) || $data['status'] = $status;
empty($keystr) || $data['keystr'] = $keystr;
return $this->callPostApi($url, $data);
}
/**
* 更新商品信息
* @param array $data 商品数据
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function updateProduct(array $data)
{
$url = "https://api.weixin.qq.com/scan/product/update?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data);
}
/**
* 清除商品信息
* @param string $keystandard 商品编码标准
* @param string $keystr 商品编码内容
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function clearProduct($keystandard, $keystr)
{
$url = "https://api.weixin.qq.com/scan/product/clear?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['keystandard' => $keystandard, 'keystr' => $keystr]);
}
/**
* 检查 wxticket 参数
* @param string $ticket
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function scanTicketCheck($ticket)
{
$url = "https://api.weixin.qq.com/scan/scanticket/check?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['ticket' => $ticket]);
}
/**
* 清除扫码记录
* @param string $keystandard 商品编码标准
* @param string $keystr 商品编码内容
* @param string $extinfo 获取二维码时的 extinfo
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function clearScanticket($keystandard, $keystr, $extinfo)
{
$url = "https://api.weixin.qq.com/scan/scanticket/check?access_token=ACCESS_TOKEN";
$data = ['keystandard' => $keystandard, 'keystr' => $keystr, 'extinfo' => $extinfo];
return $this->callPostApi($url, $data);
}
}

View File

@ -1,52 +0,0 @@
<?php
namespace WeChat\Prpcrypt;
/**
* 仅用作类内部使用
* 不用于官方API接口的errCode码
*/
class ErrorCode
{
public static $OK = 0;
public static $ParseXmlError = 40002;
public static $IllegalAesKey = 40004;
public static $IllegalBuffer = 40008;
public static $EncryptAESError = 40006;
public static $DecryptAESError = 40007;
public static $EncodeBase64Error = 40009;
public static $DecodeBase64Error = 40010;
public static $GenReturnXmlError = 40011;
public static $ValidateAppidError = 40005;
public static $ComputeSignatureError = 40003;
public static $ValidateSignatureError = 40001;
public static $errCode = [
'0' => '处理成功',
'40001' => '校验签名失败',
'40002' => '解析xml失败',
'40003' => '计算签名失败',
'40004' => '不合法的AESKey',
'40005' => '校验AppID失败',
'40006' => 'AES加密失败',
'40007' => 'AES解密失败',
'40008' => '公众平台发送的xml不合法',
'40009' => 'Base64编码失败',
'40010' => 'Base64解码失败',
'40011' => '公众帐号生成回包xml失败',
];
/**
* 获取错误消息内容
* @param string $code 错误代码
* @return bool
*/
public static function getErrText($code)
{
if (isset(self::$errCode[$code])) {
return self::$errCode[$code];
}
return false;
}
}

View File

@ -1,45 +0,0 @@
<?php
namespace WeChat\Prpcrypt;
/**
* PKCS7算法 - 加解密
*/
class PKCS7Encoder
{
public static $blockSize = 32;
/**
* 对需要加密的明文进行填充补位
* @param string $text 需要进行填充补位操作的明文
* @return string 补齐明文字符串
*/
function encode($text)
{
$amount_to_pad = PKCS7Encoder::$blockSize - (strlen($text) % PKCS7Encoder::$blockSize);
if ($amount_to_pad == 0) {
$amount_to_pad = PKCS7Encoder::$blockSize;
}
list($pad_chr, $tmp) = [chr($amount_to_pad), ''];
for ($index = 0; $index < $amount_to_pad; $index++) {
$tmp .= $pad_chr;
}
return $text . $tmp;
}
/**
* 对解密后的明文进行补位删除
* @param string $text 解密后的明文
* @return string 删除填充补位后的明文
*/
function decode($text)
{
$pad = ord(substr($text, -1));
if ($pad < 1 || $pad > PKCS7Encoder::$blockSize) {
$pad = 0;
}
return substr($text, 0, strlen($text) - $pad);
}
}

View File

@ -1,97 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2022 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// +----------------------------------------------------------------------
// | github开源项目https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeChat\Prpcrypt;
/**
* 公众号消息 - 加解密
*/
class Prpcrypt
{
public $key;
/**
* Prpcrypt constructor.
* @param $key
*/
function __construct($key)
{
$this->key = base64_decode("{$key}=");
}
/**
* 对明文进行加密
* @param string $text 需要加密的明文
* @param string $appid 公众号APPID
* @return array
*/
public function encrypt($text, $appid)
{
try {
$random = $this->getRandomStr();
$iv = substr($this->key, 0, 16);
$pkcEncoder = new PKCS7Encoder();
$text = $pkcEncoder->encode($random . pack("N", strlen($text)) . $text . $appid);
$encrypted = openssl_encrypt($text, 'AES-256-CBC', substr($this->key, 0, 32), OPENSSL_ZERO_PADDING, $iv);
return [ErrorCode::$OK, $encrypted];
} catch (\Exception $e) {
return [ErrorCode::$EncryptAESError, null];
}
}
/**
* 随机生成16位字符串
* @param string $str
* @return string 生成的字符串
*/
function getRandomStr($str = "")
{
$str_pol = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
$max = strlen($str_pol) - 1;
for ($i = 0; $i < 16; $i++) {
$str .= $str_pol[mt_rand(0, $max)];
}
return $str;
}
/**
* 对密文进行解密
* @param string $encrypted 需要解密的密文
* @return array
*/
public function decrypt($encrypted)
{
try {
$iv = substr($this->key, 0, 16);
$decrypted = openssl_decrypt($encrypted, 'AES-256-CBC', substr($this->key, 0, 32), OPENSSL_ZERO_PADDING, $iv);
} catch (\Exception $e) {
return [ErrorCode::$DecryptAESError, null];
}
try {
$pkcEncoder = new PKCS7Encoder();
$result = $pkcEncoder->decode($decrypted);
if (strlen($result) < 16) {
return [ErrorCode::$DecryptAESError, null];
}
$content = substr($result, 16, strlen($result));
$len_list = unpack("N", substr($content, 0, 4));
$xml_len = $len_list[1];
return [0, substr($content, 4, $xml_len), substr($content, $xml_len + 4)];
} catch (\Exception $e) {
return [ErrorCode::$IllegalBuffer, null];
}
}
}

View File

@ -1,75 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeChat;
use WeChat\Contracts\BasicWeChat;
/**
* 二维码管理
* @package WeChat
*/
class Qrcode extends BasicWeChat
{
/**
* 创建二维码 ticket
* @param string|int $scene 场景值(字符串或数字)
* @param int $expire_seconds 过期时间0 表示永久
* @return array ticket、url
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function create($scene, $expire_seconds = 0)
{
if (is_integer($scene)) { // 二维码场景类型
$data = ['action_info' => ['scene' => ['scene_id' => $scene]]];
} else {
$data = ['action_info' => ['scene' => ['scene_str' => $scene]]];
}
if ($expire_seconds > 0) { // 临时二维码
$data['expire_seconds'] = $expire_seconds;
$data['action_name'] = is_integer($scene) ? 'QR_SCENE' : 'QR_STR_SCENE';
} else { // 永久二维码
$data['action_name'] = is_integer($scene) ? 'QR_LIMIT_SCENE' : 'QR_LIMIT_STR_SCENE';
}
$url = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data);
}
/**
* 通过 ticket 换取二维码 URL
* @param string $ticket 二维码 ticket
* @return string 图片 URL
*/
public function url($ticket)
{
return "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=" . urlencode($ticket);
}
/**
* 长链接转短链接
* @param string $longUrl 长链接
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function shortUrl($longUrl)
{
$url = "https://api.weixin.qq.com/cgi-bin/shorturl?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['action' => 'long2short', 'long_url' => $longUrl]);
}
}

View File

@ -1,165 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeChat;
use WeChat\Contracts\BasicPushEvent;
/**
* 公众号推送管理
* @package WeChat
*/
class Receive extends BasicPushEvent
{
/**
* 转发到多客服
* @param string $account 可选客服账号
* @return $this
*/
public function transferCustomerService($account = '')
{
$this->message = [
'CreateTime' => time(),
'ToUserName' => $this->getOpenid(),
'FromUserName' => $this->getToOpenid(),
'MsgType' => 'transfer_customer_service',
];
empty($account) || $this->message['TransInfo'] = ['KfAccount' => $account];
return $this;
}
/**
* 设置文本消息
* @param string $content 文本内容
* @return $this
*/
public function text($content = '')
{
$this->message = [
'MsgType' => 'text',
'CreateTime' => time(),
'Content' => $content,
'ToUserName' => $this->getOpenid(),
'FromUserName' => $this->getToOpenid(),
];
return $this;
}
/**
* 设置图文消息
* @param array $newsData Articles 列表
* @return $this
*/
public function news($newsData = [])
{
$this->message = [
'CreateTime' => time(),
'MsgType' => 'news',
'Articles' => $newsData,
'ToUserName' => $this->getOpenid(),
'FromUserName' => $this->getToOpenid(),
'ArticleCount' => count($newsData),
];
return $this;
}
/**
* 设置图片消息
* @param string $mediaId 图片 media_id
* @return $this
*/
public function image($mediaId = '')
{
$this->message = [
'MsgType' => 'image',
'CreateTime' => time(),
'ToUserName' => $this->getOpenid(),
'FromUserName' => $this->getToOpenid(),
'Image' => ['MediaId' => $mediaId],
];
return $this;
}
/**
* 设置语音消息
* @param string $mediaid 语音 media_id
* @return $this
*/
public function voice($mediaid = '')
{
$this->message = [
'CreateTime' => time(),
'MsgType' => 'voice',
'ToUserName' => $this->getOpenid(),
'FromUserName' => $this->getToOpenid(),
'Voice' => ['MediaId' => $mediaid],
];
return $this;
}
/**
* 设置视频消息
* @param string $mediaid 视频 media_id
* @param string $title 标题
* @param string $description 描述
* @return $this
*/
public function video($mediaid = '', $title = '', $description = '')
{
$this->message = [
'CreateTime' => time(),
'MsgType' => 'video',
'ToUserName' => $this->getOpenid(),
'FromUserName' => $this->getToOpenid(),
'Video' => [
'Title' => $title,
'MediaId' => $mediaid,
'Description' => $description,
],
];
return $this;
}
/**
* 设置音乐消息
* @param string $title 标题
* @param string $desc 描述
* @param string $musicurl 音乐链接
* @param string $hgmusicurl 高清链接
* @param string $thumbmediaid 缩略图 media_id
* @return $this
*/
public function music($title, $desc, $musicurl, $hgmusicurl = '', $thumbmediaid = '')
{
$this->message = [
'CreateTime' => time(),
'MsgType' => 'music',
'ToUserName' => $this->getOpenid(),
'FromUserName' => $this->getToOpenid(),
'Music' => [
'Title' => $title,
'Description' => $desc,
'MusicUrl' => $musicurl,
'HQMusicUrl' => $hgmusicurl,
],
];
if ($thumbmediaid) {
$this->message['Music']['ThumbMediaId'] = $thumbmediaid;
}
return $this;
}
}

View File

@ -1,187 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeChat;
use WeChat\Contracts\BasicWeChat;
/**
* 扫一扫接入管理
* @package WeChat
*/
class Scan extends BasicWeChat
{
/**
* 获取商户信息
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getMerchantInfo()
{
$url = "https://api.weixin.qq.com/scan/merchantinfo/get?access_token=ACCESS_TOKEN";
return $this->callGetApi($url);
}
/**
* 创建商品
* @param array $data 商品数据
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function addProduct(array $data)
{
$url = "https://api.weixin.qq.com/scan/product/create?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data);
}
/**
* 商品发布/取消
* @param string $keystandard 商品编码标准
* @param string $keystr 商品编码内容
* @param string $status on 提交审核 | off 取消
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function modProduct($keystandard, $keystr, $status = 'on')
{
$url = "https://api.weixin.qq.com/scan/product/modstatus?access_token=ACCESS_TOKEN";
$data = ['keystandard' => $keystandard, 'keystr' => $keystr, 'status' => $status];
return $this->callPostApi($url, $data);
}
/**
* 设置测试人员白名单
* @param array $openids openid 列表
* @param array $usernames 微信号列表
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function setTestWhiteList($openids = [], $usernames = [])
{
$url = "https://api.weixin.qq.com/scan/product/modstatus?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['openid' => $openids, 'username' => $usernames]);
}
/**
* 获取商品二维码
* @param string $keystandard 编码标准
* @param string $keystr 编码内容
* @param null|string $extinfo 自定义标识
* @param int $qrcode_size 边长像素
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getQrc($keystandard, $keystr, $extinfo = null, $qrcode_size = 64)
{
$url = "https://api.weixin.qq.com/scan/product/getqrcode?access_token=ACCESS_TOKEN";
$data = ['keystandard' => $keystandard, 'keystr' => $keystr, 'qrcode_size' => $qrcode_size];
is_null($extinfo) || $data['extinfo'] = $extinfo;
return $this->callPostApi($url, $data);
}
/**
* 查询商品信息
* @param string $keystandard 商品编码标准
* @param string $keystr 商品编码内容
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getProductInfo($keystandard, $keystr)
{
$url = "https://api.weixin.qq.com/scan/product/get?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['keystandard' => $keystandard, 'keystr' => $keystr]);
}
/**
* 批量查询商品信息
* @param int $offset 起始位置
* @param int $limit 数量
* @param string $status on|off|check|reject|all
* @param string $keystr 关键词过滤
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getProductList($offset = 1, $limit = 10, $status = null, $keystr = null)
{
$url = "https://api.weixin.qq.com/scan/product/getlist?access_token=ACCESS_TOKEN";
$data = ['offset' => $offset, 'limit' => $limit];
is_null($status) || $data['status'] = $status;
is_null($keystr) || $data['keystr'] = $keystr;
return $this->callPostApi($url, $data);
}
/**
* 更新商品信息
* @param array $data 商品数据
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function updateProduct(array $data)
{
$url = "https://api.weixin.qq.com/scan/product/update?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data);
}
/**
* 清除商品信息
* @param string $keystandard 商品编码标准
* @param string $keystr 商品编码内容
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function clearProduct($keystandard, $keystr)
{
$url = "https://api.weixin.qq.com/scan/product/clear?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['keystandard' => $keystandard, 'keystr' => $keystr]);
}
/**
* 检查 wxticket 参数
* @param string $ticket
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function checkTicket($ticket)
{
$url = "https://api.weixin.qq.com/scan/scanticket/check?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['ticket' => $ticket]);
}
/**
* 清除扫码记录
* @param string $keystandard 商品编码标准
* @param string $keystr 商品编码内容
* @param string $extinfo 二维码接口时的 extinfo
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function clearScanTicket($keystandard, $keystr, $extinfo)
{
$url = "https://api.weixin.qq.com/scan/scanticket/check?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['keystandard' => $keystandard, 'keystr' => $keystr, 'extinfo' => $extinfo]);
}
}

View File

@ -1,116 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeChat;
use WeChat\Contracts\BasicWeChat;
use WeChat\Contracts\Tools;
use WeChat\Exceptions\InvalidResponseException;
/**
* 微信前端支持
* @package WeChat
*/
class Script extends BasicWeChat
{
/**
* 删除JSAPI授权TICKET
* @param string $type TICKET类型(wx_card|jsapi)
* @param string $appid 强制指定有效APPID
* @return void
*/
public function delTicket($type = 'jsapi', $appid = null)
{
is_null($appid) && $appid = $this->config->get('appid');
$cache_name = "{$appid}_ticket_{$type}";
Tools::delCache($cache_name);
}
/**
* 获取 JSAPI 签名
* @param string $url 当前页面 URL不含 #
* @param string $appid 可选指定 appid
* @param string $ticket 可选指定 ticket
* @param array $jsApiList 需注入的 API 列表
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getJsSign($url, $appid = null, $ticket = null, $jsApiList = null)
{
list($url,) = explode('#', $url);
is_null($ticket) && $ticket = $this->getTicket('jsapi');
is_null($appid) && $appid = $this->config->get('appid');
is_null($jsApiList) && $jsApiList = [
'updateAppMessageShareData', 'updateTimelineShareData', 'onMenuShareTimeline', 'onMenuShareAppMessage', 'onMenuShareQQ', 'onMenuShareWeibo', 'onMenuShareQZone',
'startRecord', 'stopRecord', 'onVoiceRecordEnd', 'playVoice', 'pauseVoice', 'stopVoice', 'onVoicePlayEnd', 'uploadVoice', 'downloadVoice',
'chooseImage', 'previewImage', 'uploadImage', 'downloadImage', 'translateVoice', 'getNetworkType', 'openLocation', 'getLocation',
'hideOptionMenu', 'showOptionMenu', 'hideMenuItems', 'showMenuItems', 'hideAllNonBaseMenuItem', 'showAllNonBaseMenuItem',
'closeWindow', 'scanQRCode', 'chooseWXPay', 'openProductSpecificView', 'addCard', 'chooseCard', 'openCard',
];
$data = ["url" => $url, "timestamp" => '' . time(), "jsapi_ticket" => $ticket, "noncestr" => Tools::createNoncestr(16)];
return [
'debug' => false,
"appId" => $appid,
"nonceStr" => $data['noncestr'],
"timestamp" => $data['timestamp'],
"signature" => $this->getSignature($data, 'sha1'),
'jsApiList' => $jsApiList,
];
}
/**
* 获取 JSAPI_TICKET
* @param string $type jsapi|wx_card
* @param string $appid 可选指定 appid
* @return string ticket
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getTicket($type = 'jsapi', $appid = null)
{
is_null($appid) && $appid = $this->config->get('appid');
$cache_name = "{$appid}_ticket_{$type}";
$ticket = Tools::getCache($cache_name);
if (empty($ticket)) {
$url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type={$type}";
$this->registerApi($url, __FUNCTION__, func_get_args());
$result = $this->httpGetForJson($url);
if (empty($result['ticket'])) {
throw new InvalidResponseException('Invalid Resoponse Ticket.', '0');
}
$ticket = $result['ticket'];
Tools::setCache($cache_name, $ticket, 7000);
}
return $ticket;
}
/**
* 数据生成签名
* @param array $data 待签名数据
* @param string $method 签名方法
* @param array $params 额外参数
* @return bool|string
*/
protected function getSignature($data, $method = "sha1", $params = [])
{
ksort($data);
if (!function_exists($method)) return false;
foreach ($data as $k => $v) $params[] = "{$k}={$v}";
return $method(join('&', $params));
}
}

View File

@ -1,340 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeChat;
use WeChat\Contracts\BasicWeChat;
use WeChat\Contracts\Tools;
/**
* 揺一揺周边
* @package WeChat
*/
class Shake extends BasicWeChat
{
/**
* 申请开通摇一摇
* @param array $data 资质信息
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function register(array $data)
{
$url = "https://api.weixin.qq.com/shakearound/account/register?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data);
}
/**
* 查询审核状态
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function auditStatus()
{
$url = "https://api.weixin.qq.com/shakearound/account/auditstatus?access_token=ACCESS_TOKEN";
return $this->callGetApi($url);
}
/**
* 申请设备 ID
* @param string $quantity 数量(>500 走人工审核)
* @param string $apply_reason 理由
* @param null|string $comment 备注
* @param null|string $poi_id 门店ID
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function createApply($quantity, $apply_reason, $comment = null, $poi_id = null)
{
$data = ['quantity' => $quantity, 'apply_reason' => $apply_reason];
is_null($poi_id) || $data['poi_id'] = $poi_id;
is_null($comment) || $data['comment'] = $comment;
$url = "https://api.weixin.qq.com/shakearound/device/applyid?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data);
}
/**
* 查询设备 ID 申请状态
* @param int $applyId 批次ID
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getApplyStatus($applyId)
{
$url = "https://api.weixin.qq.com/shakearound/device/applyid?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['apply_id' => $applyId]);
}
/**
* 编辑设备信息
* @param array $data 设备参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function updateApply(array $data)
{
$url = "https://api.weixin.qq.com/shakearound/device/update?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data);
}
/**
* 设备绑定门店
* @param array $data 绑定参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function bindLocation(array $data)
{
$url = "https://api.weixin.qq.com/shakearound/device/bindlocation?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data);
}
/**
* 查询设备列表
* @param array $data 查询参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function search(array $data)
{
$url = "https://api.weixin.qq.com/shakearound/device/search?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data);
}
/**
* 创建页面
* @param array $data 页面参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function createPage(array $data)
{
$url = "https://api.weixin.qq.com/shakearound/page/add?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data);
}
/**
* 编辑页面
* @param array $data 页面参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function updatePage(array $data)
{
$url = "https://api.weixin.qq.com/shakearound/page/update?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data);
}
/**
* 查询页面列表
* @param array $data 查询参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function searchPage(array $data)
{
$url = "https://api.weixin.qq.com/shakearound/page/search?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data);
}
/**
* 删除页面
* @param int $pageId 页面ID
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function deletePage($pageId)
{
$url = "https://api.weixin.qq.com/shakearound/page/delete?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['page_id' => $pageId]);
}
/**
* 上传图片素材
* @param string $filename 图片路径
* @param string $type icon|license
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function upload($filename, $type = 'icon')
{
$url = "https://api.weixin.qq.com/shakearound/material/add?access_token=ACCESS_TOKEN&type={$type}";
return $this->callPostApi($url, ['media' => Tools::createCurlFile($filename)], false);
}
/**
* 配置设备与页面关联
* @param array $data 关联参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function bindPage(array $data)
{
$url = "https://api.weixin.qq.com/shakearound/device/bindpage?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data);
}
/**
* 查询设备与页面关联
* @param array $data 查询参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function queryPage(array $data)
{
$url = "https://api.weixin.qq.com/shakearound/relation/search?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data);
}
/**
* 设备维度数据统计
* @param array $data 查询参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function totalDevice(array $data)
{
$url = "https://api.weixin.qq.com/shakearound/statistics/device?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data);
}
/**
* 批量查询设备统计
* @param int $date 日期时间戳(秒)
* @param int $pageIndex 页码
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function totalDeviceList($date, $pageIndex = 1)
{
$url = "https://api.weixin.qq.com/shakearound/statistics/devicelist?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['date' => $date, 'page_index' => $pageIndex]);
}
/**
* 页面维度数据统计
* @param int $pageId 页面ID
* @param int $beginDate 起始时间戳
* @param int $endDate 结束时间戳
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function totalPage($pageId, $beginDate, $endDate)
{
$url = "https://api.weixin.qq.com/shakearound/statistics/page?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['page_id' => $pageId, 'begin_date' => $beginDate, 'end_date' => $endDate]);
}
/**
* 编辑分组信息
* @param int $groupId 分组ID
* @param string $groupName 分组名称
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function updateGroup($groupId, $groupName)
{
$url = "https://api.weixin.qq.com/shakearound/device/group/update?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['group_id' => $groupId, 'group_name' => $groupName]);
}
/**
* 删除分组
* @param int $groupId 分组ID
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function deleteGroup($groupId)
{
$url = "https://api.weixin.qq.com/shakearound/device/group/delete?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['group_id' => $groupId]);
}
/**
* 查询分组列表
* @param int $begin 起始索引
* @param int $count 数量(<=1000
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getGroupList($begin = 0, $count = 10)
{
$url = "https://api.weixin.qq.com/shakearound/device/group/getlist?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['begin' => $begin, 'count' => $count]);
}
/**
* 查询分组详情
* @param int $group_id 分组ID
* @param int $begin 设备起始索引
* @param int $count 数量(<=1000
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getGroupDetail($group_id, $begin = 0, $count = 100)
{
$url = "https://api.weixin.qq.com/shakearound/device/group/getdetail?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['group_id' => $group_id, 'begin' => $begin, 'count' => $count]);
}
/**
* 分组添加设备
* @param array $data 设备参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function addDeviceGroup(array $data)
{
$url = "https://api.weixin.qq.com/shakearound/device/group/adddevice?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data);
}
/**
* 分组移除设备
* @param array $data 设备参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function deleteDeviceGroup(array $data)
{
$url = "https://api.weixin.qq.com/shakearound/device/group/deletedevice?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data);
}
}

View File

@ -1,119 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeChat;
use WeChat\Contracts\BasicWeChat;
/**
* 用户标签管理
* @package WeChat
*/
class Tags extends BasicWeChat
{
/**
* 获取标签列表
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function getTags()
{
$url = "https://api.weixin.qq.com/cgi-bin/tags/get?access_token=ACCESS_TOKEN";
return $this->callGetApi($url);
}
/**
* 创建标签
* @param string $name 标签名称
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function createTags($name)
{
$url = "https://api.weixin.qq.com/cgi-bin/tags/create?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['tag' => ['name' => $name]]);
}
/**
* 更新标签
* @param int $id 标签ID
* @param string $name 标签名称
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function updateTags($id, $name)
{
$url = "https://api.weixin.qq.com/cgi-bin/tags/update?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['tag' => ['name' => $name, 'id' => $id]]);
}
/**
* 删除标签
* @param int $tagId 标签ID
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function deleteTags($tagId)
{
$url = 'https://api.weixin.qq.com/cgi-bin/tags/delete?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, ['tag' => ['id' => $tagId]]);
}
/**
* 批量为用户打标签
* @param array $openids openid 列表
* @param int $tagId 标签ID
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function batchTagging(array $openids, $tagId)
{
$url = 'https://api.weixin.qq.com/cgi-bin/tags/members/batchtagging?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, ['openid_list' => $openids, 'tagid' => $tagId]);
}
/**
* 批量取消用户标签
* @param array $openids openid 列表
* @param int $tagId 标签ID
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function batchUntagging(array $openids, $tagId)
{
$url = 'https://api.weixin.qq.com/cgi-bin/tags/members/batchuntagging?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, ['openid_list' => $openids, 'tagid' => $tagId]);
}
/**
* 获取用户标签列表
* @param string $openid 用户 openid
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function getUserTagId($openid)
{
$url = 'https://api.weixin.qq.com/cgi-bin/tags/getidlist?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, ['openid' => $openid]);
}
}

View File

@ -1,104 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeChat;
use WeChat\Contracts\BasicWeChat;
/**
* 模板消息
* @package WeChat
*/
class Template extends BasicWeChat
{
/**
* 设置模板消息所属行业
* @param string $industryId1 行业编号
* @param string $industryId2 行业编号
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function setIndustry($industryId1, $industryId2)
{
$url = "https://api.weixin.qq.com/cgi-bin/template/api_set_industry?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['industry_id1' => $industryId1, 'industry_id2' => $industryId2]);
}
/**
* 获取已设置的行业信息
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function getIndustry()
{
$url = "https://api.weixin.qq.com/cgi-bin/template/get_industry?access_token=ACCESS_TOKEN";
return $this->callGetApi($url);
}
/**
* 领取模板 ID
* @param string $templateIdShort 模板编号(如 TM** OPENTMTM**
* @param array $keywordNameList 选用关键词
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function addTemplate($templateIdShort, $keywordNameList = [])
{
$url = "https://api.weixin.qq.com/cgi-bin/template/api_add_template?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['template_id_short' => $templateIdShort, 'keyword_name_list' => $keywordNameList]);
}
/**
* 获取私有模板列表
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function getAllPrivateTemplate()
{
$url = "https://api.weixin.qq.com/cgi-bin/template/get_all_private_template?access_token=ACCESS_TOKEN";
return $this->callGetApi($url);
}
/**
* 删除模板
* @param string $tplId 模板 ID
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function delPrivateTemplate($tplId)
{
$url = "https://api.weixin.qq.com/cgi-bin/template/del_private_template?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['template_id' => $tplId]);
}
/**
* 发送模板消息
* @param array $data 消息内容touser, template_id, data 等)
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function send(array $data)
{
$url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data);
}
}

View File

@ -1,139 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeChat;
use WeChat\Contracts\BasicWeChat;
/**
* 微信粉丝管理
* @package WeChat
*/
class User extends BasicWeChat
{
/**
* 设置用户备注名接口
* @param string $openid 用户openid
* @param string $remark 备注名长度不超过30字符
* @return array 操作结果
* @throws Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function updateMark($openid, $remark)
{
$url = 'https://api.weixin.qq.com/cgi-bin/user/info/updateremark?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, ['openid' => $openid, 'remark' => $remark]);
}
/**
* 获取用户基本信息接口包括UnionID
* @param string $openid 用户openid
* @param string $lang 返回国家地区语言版本zh_CN, zh_TW, en
* @return array 用户信息nickname, headimgurl, sex, province, city, country, unionid等
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function getUserInfo($openid, $lang = 'zh_CN')
{
$url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid={$openid}&lang={$lang}";
return $this->callGetApi($url);
}
/**
* 批量获取用户基本信息接口
* @param array $openids 用户openid列表最多100个
* @param string $lang 返回国家地区语言版本
* @return array 用户信息列表
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function getBatchUserInfo(array $openids, $lang = 'zh_CN')
{
$url = 'https://api.weixin.qq.com/cgi-bin/user/info/batchget?access_token=ACCESS_TOKEN';
$data = ['user_list' => []];
foreach ($openids as $openid) {
$data['user_list'][] = ['openid' => $openid, 'lang' => $lang];
}
return $this->callPostApi($url, $data);
}
/**
* 获取用户列表接口
* @param string $next_openid 第一个拉取的openid不填默认从头开始拉取
* @return array 用户列表total, count, data.openid, next_openid
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function getUserList($next_openid = '')
{
$url = "https://api.weixin.qq.com/cgi-bin/user/get?access_token=ACCESS_TOKEN&next_openid={$next_openid}";
return $this->callGetApi($url);
}
/**
* 获取标签下粉丝列表接口
* @param integer $tagid 标签ID
* @param string $nextOpenid 第一个拉取的openid不填默认从头开始拉取
* @return array 粉丝列表count, data.openid, next_openid
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function getUserListByTag($tagid, $nextOpenid = '')
{
$url = 'https://api.weixin.qq.com/cgi-bin/user/tag/get?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, ['tagid' => $tagid, 'next_openid' => $nextOpenid]);
}
/**
* 获取公众号黑名单列表接口
* @param string $beginOpenid 第一个拉取的openid不填默认从头开始拉取
* @return array 黑名单列表total, count, data.openid, next_openid
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function getBlackList($beginOpenid = '')
{
$url = "https://api.weixin.qq.com/cgi-bin/tags/members/getblacklist?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['begin_openid' => $beginOpenid]);
}
/**
* 批量拉黑用户接口
* @param array $openids 用户openid列表最多20个
* @return array 操作结果
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function batchBlackList(array $openids)
{
$url = "https://api.weixin.qq.com/cgi-bin/tags/members/batchblacklist?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['openid_list' => $openids]);
}
/**
* 批量取消拉黑用户接口
* @param array $openids 用户openid列表最多20个
* @return array 操作结果
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function batchUnblackList(array $openids)
{
$url = "https://api.weixin.qq.com/cgi-bin/tags/members/batchunblacklist?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['openid_list' => $openids]);
}
}

View File

@ -1,285 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeChat;
use WeChat\Contracts\BasicWeChat;
/**
* 门店 WIFI 管理
* @package WeChat
*/
class Wifi extends BasicWeChat
{
/**
* 获取 Wi-Fi 门店列表
* @param int $pageindex 页码从1开始
* @param int $pagesize 每页数量(<=20
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function getShopList($pageindex = 1, $pagesize = 2)
{
$url = 'https://api.weixin.qq.com/bizwifi/shop/list?access_token=ACCESS_TOKEN';
$this->registerApi($url, __FUNCTION__, func_get_args());
return $this->httpPostForJson($url, ['pageindex' => $pageindex, 'pagesize' => $pagesize]);
}
/**
* 查询门店 Wi-Fi 信息
* @param int $shop_id 门店ID
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function getShopWifi($shop_id)
{
$url = 'https://api.weixin.qq.com/bizwifi/shop/list?access_token=ACCESS_TOKEN';
$this->registerApi($url, __FUNCTION__, func_get_args());
return $this->httpPostForJson($url, ['shop_id' => $shop_id]);
}
/**
* 修改门店 Wi-Fi
* @param int $shop_id 门店ID
* @param string $old_ssid SSID
* @param string $ssid SSID
* @param string $password 可选密码
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function upShopWifi($shop_id, $old_ssid, $ssid, $password = null)
{
$data = ['shop_id' => $shop_id, 'old_ssid' => $old_ssid, 'ssid' => $ssid];
is_null($password) || $data['password'] = $password;
$url = 'https://api.weixin.qq.com/bizwifi/shop/update?access_token=ACCESS_TOKEN';
$this->registerApi($url, __FUNCTION__, func_get_args());
return $this->httpPostForJson($url, $data);
}
/**
* 清空门店网络与设备
* @param int $shop_id 门店ID
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function clearShopWifi($shop_id)
{
$url = 'https://api.weixin.qq.com/bizwifi/shop/clean?access_token=ACCESS_TOKEN';
$this->registerApi($url, __FUNCTION__, func_get_args());
return $this->httpPostForJson($url, ['shop_id' => $shop_id]);
}
/**
* 添加密码型设备
* @param int $shop_id 门店ID
* @param string $ssid SSID
* @param null|string $password 密码
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function addShopWifi($shop_id, $ssid, $password = null)
{
$data = ['shop_id' => $shop_id, 'ssid' => $ssid, 'password' => $password];
$url = 'https://api.weixin.qq.com/bizwifi/device/add?access_token=ACCESS_TOKEN';
$this->registerApi($url, __FUNCTION__, func_get_args());
return $this->httpPostForJson($url, $data);
}
/**
* 添加 portal 型设备
* @param int $shop_id 门店ID
* @param string $ssid SSID
* @param bool $reset 是否重置 secretkey
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function addShopPortal($shop_id, $ssid, $reset = false)
{
$data = ['shop_id' => $shop_id, 'ssid' => $ssid, 'reset' => $reset];
$url = 'https://api.weixin.qq.com/bizwifi/apportal/register?access_token=ACCESS_TOKEN';
$this->registerApi($url, __FUNCTION__, func_get_args());
return $this->httpPostForJson($url, $data);
}
/**
* 查询设备
* @param int|null $shop_id 门店ID
* @param int|null $pageindex 页码
* @param int|null $pagesize 数量
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function queryShopWifi($shop_id = null, $pageindex = null, $pagesize = null)
{
$data = [];
is_null($pagesize) || $data['pagesize'] = $pagesize;
is_null($pageindex) || $data['pageindex'] = $pageindex;
is_null($shop_id) || $data['shop_id'] = $shop_id;
$url = 'https://api.weixin.qq.com/bizwifi/device/list?access_token=ACCESS_TOKEN';
$this->registerApi($url, __FUNCTION__, func_get_args());
return $this->httpPostForJson($url, $data);
}
/**
* 删除设备
* @param string $bssid 设备 MAC冒号分隔小写
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function delShopWifi($bssid)
{
$url = 'https://api.weixin.qq.com/bizwifi/device/delete?access_token=ACCESS_TOKEN';
$this->registerApi($url, __FUNCTION__, func_get_args());
return $this->httpPostForJson($url, ['bssid' => $bssid]);
}
/**
* 获取物料二维码
* @param int $shop_id 门店ID
* @param string $ssid SSID
* @param int $img_id 物料样式 0|1
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function getQrc($shop_id, $ssid, $img_id = 1)
{
$url = 'https://api.weixin.qq.com/bizwifi/qrcode/get?access_token=ACCESS_TOKEN';
$this->registerApi($url, __FUNCTION__, func_get_args());
return $this->httpPostForJson($url, ['shop_id' => $shop_id, 'ssid' => $ssid, 'img_id' => $img_id]);
}
/**
* 设置商家主页
* @param int $shop_id 门店ID
* @param int $template_id 0 默认 | 1 自定义链接
* @param null|string $url 自定义链接template_id=1 必填)
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function setHomePage($shop_id, $template_id, $url = null)
{
$data = ['shop_id' => $shop_id, 'template_id' => $template_id];
!is_null($url) && $data['struct'] = ['url' => $url];
$url = 'https://api.weixin.qq.com/bizwifi/homepage/set?access_token=ACCESS_TOKEN';
$this->registerApi($url, __FUNCTION__, func_get_args());
return $this->httpPostForJson($url, $data);
}
/**
* 查询商家主页
* @param int $shop_id 门店ID
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function getHomePage($shop_id)
{
$url = 'https://api.weixin.qq.com/bizwifi/homepage/get?access_token=ACCESS_TOKEN';
$this->registerApi($url, __FUNCTION__, func_get_args());
return $this->httpPostForJson($url, ['shop_id' => $shop_id]);
}
/**
* 设置微信首页欢迎语
* @param int $shop_id 门店ID
* @param int $bar_type 0|1|2|3
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function setBar($shop_id, $bar_type = 1)
{
$url = 'https://api.weixin.qq.com/bizwifi/bar/set?access_token=ACCESS_TOKEN';
$this->registerApi($url, __FUNCTION__, func_get_args());
return $this->httpPostForJson($url, ['shop_id' => $shop_id, 'bar_type' => $bar_type]);
}
/**
* 设置连网完成页
* @param int $shop_id 门店ID
* @param string $finishpage_url 完成页 URL
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function setFinishPage($shop_id, $finishpage_url)
{
$url = 'https://api.weixin.qq.com/bizwifi/finishpage/set?access_token=ACCESS_TOKEN';
$this->registerApi($url, __FUNCTION__, func_get_args());
return $this->httpPostForJson($url, ['shop_id' => $shop_id, 'finishpage_url' => $finishpage_url]);
}
/**
* Wi-Fi 数据统计
* @param string $begin_date 开始日期 yyyy-mm-dd
* @param string $end_date 结束日期 yyyy-mm-dd
* @param int $shop_id 门店ID-1 总统计
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function staticList($begin_date, $end_date, $shop_id = -1)
{
$url = 'https://api.weixin.qq.com/bizwifi/statistics/list?access_token=ACCESS_TOKEN';
$this->registerApi($url, __FUNCTION__, func_get_args());
return $this->httpPostForJson($url, ['shop_id' => $shop_id, 'begin_date' => $begin_date, 'end_date' => $end_date]);
}
/**
* 设置门店卡券投放
* @param int $shop_id 门店ID0 表示全部
* @param int $card_id 卡券ID
* @param string $card_describe 描述(<=18 字符)
* @param string $start_time 开始时间戳
* @param string $end_time 结束时间戳
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function setCouponput($shop_id, $card_id, $card_describe, $start_time, $end_time)
{
$data = ['shop_id' => $shop_id, 'card_id' => $card_id, 'card_describe' => $card_describe, 'start_time' => $start_time, 'end_time' => $end_time];
$url = 'https://api.weixin.qq.com/bizwifi/couponput/set?access_token=ACCESS_TOKEN';
$this->registerApi($url, __FUNCTION__, func_get_args());
return $this->httpPostForJson($url, $data);
}
/**
* 查询门店卡券投放
* @param int $shop_id 门店ID0 表示全部
* @return array
* @throws Exceptions\InvalidResponseException
* @throws Exceptions\LocalCacheException
*/
public function getCouponput($shop_id)
{
$url = 'https://api.weixin.qq.com/bizwifi/couponput/get?access_token=ACCESS_TOKEN';
$this->registerApi($url, __FUNCTION__, func_get_args());
return $this->httpPostForJson($url, ['shop_id' => $shop_id]);
}
}

View File

@ -1,122 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeMini;
use WeChat\Contracts\BasicWeChat;
use WeChat\Contracts\Tools;
use WeChat\Exceptions\InvalidDecryptException;
use WeChat\Exceptions\InvalidResponseException;
use WXBizDataCrypt;
/**
* 小程序数据加解密
* @package WeMini
*/
class Crypt extends BasicWeChat
{
/**
* 通过 code 解密用户信息
* @param string $code 登录凭证
* @param string $iv 初始向量
* @param string $encryptedData 加密数据
* @return array
* @throws \WeChat\Exceptions\InvalidDecryptException
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function userInfo($code, $iv, $encryptedData)
{
$result = $this->session($code);
if (empty($result['session_key'])) {
throw new InvalidResponseException('Code 换取 SessionKey 失败', 403);
}
$userinfo = $this->decode($iv, $result['session_key'], $encryptedData);
if (empty($userinfo)) {
throw new InvalidDecryptException('用户信息解析失败', 403);
}
return array_merge($result, $userinfo);
}
/**
* code 换取 session_key
* @param string $code 登录 code
* @return array
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function session($code)
{
$appid = $this->config->get('appid');
$secret = $this->config->get('appsecret');
$url = "https://api.weixin.qq.com/sns/jscode2session?appid={$appid}&secret={$secret}&js_code={$code}&grant_type=authorization_code";
return json_decode(Tools::get($url), true);
}
/**
* 解密数据
* @param string $iv 初始向量
* @param string $sessionKey 会话密钥
* @param string $encryptedData 加密数据
* @return bool|array
*/
public function decode($iv, $sessionKey, $encryptedData)
{
require_once __DIR__ . DIRECTORY_SEPARATOR . 'crypt' . DIRECTORY_SEPARATOR . 'wxBizDataCrypt.php';
$pc = new WXBizDataCrypt($this->config->get('appid'), $sessionKey);
$data = '';
$errCode = $pc->decryptData($encryptedData, $iv, $data);
if ($errCode == 0) {
return json_decode($data, true);
}
return false;
}
/**
* 通过 code 获取手机号
* @param string $code 授权码
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getPhoneNumber($code)
{
$url = 'https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=ACCESS_TOKEN';
$this->registerApi($url, __FUNCTION__, func_get_args());
return $this->httpPostForJson($url, ['code' => $code], true);
}
/**
* 支付后获取用户 UnionId
* @param string $openid 用户 openid
* @param null|string $transaction_id 微信支付订单号
* @param null|string $mch_id 商户号
* @param null|string $out_trade_no 商户订单号
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getPaidUnionId($openid, $transaction_id = null, $mch_id = null, $out_trade_no = null)
{
$url = "https://api.weixin.qq.com/wxa/getpaidunionid?access_token=ACCESS_TOKEN&openid={$openid}";
if (!is_null($mch_id)) $url .= "&mch_id={$mch_id}";
if (!is_null($out_trade_no)) $url .= "&out_trade_no={$out_trade_no}";
if (!is_null($transaction_id)) $url .= "&transaction_id={$transaction_id}";
$this->registerApi($url, __FUNCTION__, func_get_args());
return $this->callGetApi($url);
}
}

View File

@ -1,221 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeMini;
use WeChat\Contracts\BasicWeChat;
/**
* 小程序客服服务
* @package WeMini
*/
class Custom extends BasicWeChat
{
/**
* 发送小程序客服消息
* @param array $data
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function sendCustomMessage($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 创建商户
* @param array $data
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function businessRegister($data)
{
$url = 'https://api.weixin.qq.com/cgibin/business/register?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 更新商户信息
* @param array $data
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function businessUpdate($data)
{
$url = 'https://api.weixin.qq.com/cgibin/business/update?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 拉取单个商户信息
* @param array $data
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function businessGet($data)
{
$url = 'https://api.weixin.qq.com/cgibin/business/get?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 拉取多个商户信息
* @param array $data
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function businessList($data)
{
$url = 'https://api.weixin.qq.com/cgibin/business/list?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 发送客服消息
* @param array $data
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function businessSend($data)
{
$url = 'https://api.weixin.qq.com/cgibin/message/custom/business/send?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 客服输入状态
* @param array $data
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function businessTyping($data)
{
$url = 'https://api.weixin.qq.com/cgibin/message/custom/business/typing?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 获取客服基本信息
* @param string $business_id 客服子商户的business_id对于普通小程序客服不需要填business_id
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getKfList($business_id = '')
{
$url = 'https://api.weixin.qq.com/cgi-bin/customservice/getkflist?access_token=ACCESS_TOKEN';
if (!empty($business_id)) {
$url .= '&business_id=' . $business_id;
}
return $this->callGetApi($url);
}
/**
* 获取在线客服列表
* @param string $business_id 客服子商户的business_id对于普通小程序客服不需要填business_id
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getOnlineKfList($business_id = '')
{
$url = 'https://api.weixin.qq.com/cgi-bin/customservice/getonlinekflist?access_token=ACCESS_TOKEN';
if (!empty($business_id)) {
$url .= '&business_id=' . $business_id;
}
return $this->callGetApi($url);
}
/**
* 客服输入状态
* @param array $data
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function addKfAccount($data)
{
$url = 'https://api.weixin.qq.com/customservice/kfaccount/add?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 删除客服账号
* @param string $kf_openid 客服openid
* @param string $business_id 客服子商户的business_id对于普通小程序客服不需要填business_id
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function delKfAccount($kf_openid, $business_id = '')
{
$url = 'https://api.weixin.qq.com/customservice/kfaccount/del?access_token=ACCESS_TOKEN&kf_openid=' . $kf_openid;
if (!empty($business_id)) {
$url .= '&business_id=' . $business_id;
}
return $this->callGetApi($url);
}
/**
* 设置客服管理员
* @param string $kf_openid 客服openid
* @param string $business_id 客服子商户的business_id对于普通小程序客服不需要填business_id
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function setKfAdmin($kf_openid, $business_id = '')
{
$url = 'https://api.weixin.qq.com/customservice/kfaccount/setadmin?access_token=ACCESS_TOKEN&kf_openid=' . $kf_openid;
if (!empty($business_id)) {
$url .= '&business_id=' . $business_id;
}
return $this->callGetApi($url);
}
/**
* 取消客服管理员
* @param string $kf_openid 客服openid
* @param string $business_id 客服子商户的business_id对于普通小程序客服不需要填business_id
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function cancelKfAdmin($kf_openid, $business_id = '')
{
$url = 'https://api.weixin.qq.com/customservice/kfaccount/canceladmin?access_token=ACCESS_TOKEN&kf_openid=' . $kf_openid;
if (!empty($business_id)) {
$url .= '&business_id=' . $business_id;
}
return $this->callGetApi($url);
}
}

View File

@ -1,171 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeMini;
use WeChat\Contracts\BasicWeChat;
/**
* 小程序即时配送
* @package WeMini
*/
class Delivery extends BasicWeChat
{
/**
* 异常件退回确认收货
* @param array $data 请求参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function abnormalConfirm($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/express/local/business/order/confirm_return?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 下配送单
* @param array $data 订单信息
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function addOrder($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/express/local/business/order/add?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 待接单订单加小费
* @param array $data 订单与小费信息
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function addTip($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/express/local/business/order/addtips?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 取消配送单
* @param array $data 订单信息
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function cancelOrder($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/express/local/business/order/cancel?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 获取配送公司列表
* @param array $data 请求参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getAllImmeDelivery($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/express/local/business/delivery/getall?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 拉取已绑定账号
* @param array $data 请求参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getBindAccount($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/express/local/business/shop/get?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 查询配送单
* @param array $data 订单信息
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getOrder($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/express/local/business/order/get?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 模拟更新配送单状态
* @param array $data 模拟参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function mockUpdateOrder($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/express/local/business/test_update_order?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 预下单
* @param array $data 订单信息
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function preAddOrder($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/express/local/business/order/pre_add?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 预取消配送单
* @param array $data 订单信息
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function preCancelOrder($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/express/local/business/order/precancel?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 重新下单
* @param array $data 订单信息
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function reOrder($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/express/local/business/order/readd?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
}

View File

@ -1,527 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeMini;
use WeChat\Contracts\BasicWeChat;
/**
* 小程序导购助手
* @package WeMini
*/
class Guide extends BasicWeChat
{
/**
* 添加导购
* @param array $data 导购账号信息
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function addGuideAcct($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/guide/addguideacct?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 删除导购
* @param array $data 导购账号
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function delGuideAcct($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/guide/delguideacct?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 获取导购信息
* @param array $data 导购账号
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getGuideAcct($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/guide/getguideacct?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 获取敏感词与自动回复配置
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getGuideAcctConfig()
{
$url = 'https://api.weixin.qq.com/cgi-bin/guide/getguideacctconfig?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, [], true);
}
/**
* 拉取导购列表
* @param int $page 页码
* @param int $num 数量
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getGuideAcctList($page = 0, $num = 10)
{
$url = 'https://api.weixin.qq.com/cgi-bin/guide/getguideacctconfig?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, ['page' => $page, 'num' => $num], true);
}
/**
* 获取导购聊天记录
* @param array $data 查询条件
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getGuideBuyerChatRecord($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/guide/getguideacct?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 获取导购快捷回复
* @param array $data 导购信息
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getGuideConfig($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/guide/getguideconfig?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 生成导购二维码
* @param array $data 导购信息
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function guideCreateQrCode($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/guide/guidecreateqrcode?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 推送小程序路径菜单
* @param array $data 请求参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function pushShowWxaPathMenu($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/guide/pushshowwxapathmenu?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 设置敏感词与自动回复
* @param array $data 配置数据
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function setGuideAcctConfig($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/guide/setguideacctconfig?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 设置导购快捷回复
* @param array $data 快捷回复数据
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function setGuideConfig($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/guide/setguideconfig?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 更新导购昵称或头像
* @param array $data 导购信息
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function updateGuideAcct($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/guide/setguideconfig?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 添加展示标签
* @param array $data 标签数据
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function addGuideBuyerDisplayTag($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/guide/addguidebuyerdisplaytag?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 为粉丝添加可查询标签
* @param array $data 标签数据
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function addGuideBuyerTag($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/guide/addguidebuyertag?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 添加标签可选值
* @param array $data 选项数据
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function addGuideTagOption($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/guide/addguidetagoption?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 删除粉丝标签
* @param array $data 标签数据
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function delGuideBuyerTag($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/guide/delguidebuyertag?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 查询展示标签
* @param array $data 查询参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getGuideBuyerDisplayTag($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/guide/getguidebuyerdisplaytag?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 查询粉丝标签
* @param array $data 查询参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getGuideBuyerTag($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/guide/getguidebuyertag?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 查询标签可选值
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getGuideTagOption()
{
$url = 'https://api.weixin.qq.com/cgi-bin/guide/getguidetagoption?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, [], true);
}
/**
* 新建可查询标签类型
* @param array $data 标签数据
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function newGuideTagOption($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/guide/newguidetagoption?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 标签筛选粉丝
* @param array $data 标签查询条件
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function queryGuideBuyerByTag($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/guide/queryguidebuyerbytag?access_token=ACCESS_TOKEN';
$this->registerApi($url, __FUNCTION__, func_get_args());
return $this->callPostApi($url, $data, true);
}
/**
* 导购添加粉丝
* @param array $data 绑定数据
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function addGuideBuyerRelation($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/guide/addguidebuyerrelation?access_token=ACCESS_TOKEN';
$this->registerApi($url, __FUNCTION__, func_get_args());
return $this->callPostApi($url, $data, true);
}
/**
* 删除导购粉丝
* @param array $data 解绑数据
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function delGuideBuyerRelation($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/guide/delguidebuyerrelation?access_token=ACCESS_TOKEN';
$this->registerApi($url, __FUNCTION__, func_get_args());
return $this->callPostApi($url, $data, true);
}
/**
* 查询粉丝绑定关系
* @param array $data 查询参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getGuideBuyerRelation($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/guide/getguidebuyerrelation?access_token=ACCESS_TOKEN';
$this->registerApi($url, __FUNCTION__, func_get_args());
return $this->callPostApi($url, $data, true);
}
/**
* 通过粉丝查询绑定关系
* @param string $openid 粉丝 openid
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getGuideBuyerRelationByBuyer($openid)
{
$url = 'https://api.weixin.qq.com/cgi-bin/guide/getguidebuyerrelation?access_token=ACCESS_TOKEN';
$this->registerApi($url, __FUNCTION__, func_get_args());
return $this->callPostApi($url, ['openid' => $openid], true);
}
/**
* 拉取导购粉丝列表
* @param array $data 查询参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getGuideBuyerRelationList($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/guide/getguidebuyerrelationlist?access_token=ACCESS_TOKEN';
$this->registerApi($url, __FUNCTION__, func_get_args());
return $this->callPostApi($url, $data, true);
}
/**
* 粉丝迁移导购
* @param array $data 迁移数据
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function rebindGuideAcctForBuyer($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/guide/rebindguideacctforbuyer?access_token=ACCESS_TOKEN';
$this->registerApi($url, __FUNCTION__, func_get_args());
return $this->callPostApi($url, $data, true);
}
/**
* 更新粉丝昵称
* @param array $data 昵称数据
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function updateGuideBuyerRelation($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/guide/updateguidebuyerrelation?access_token=ACCESS_TOKEN';
$this->registerApi($url, __FUNCTION__, func_get_args());
return $this->callPostApi($url, $data, true);
}
/**
* 删除卡片素材
* @param array $data 素材信息
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function delGuideCardMaterial($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/guide/delguidecardmaterial?access_token=ACCESS_TOKEN';
$this->registerApi($url, __FUNCTION__, func_get_args());
return $this->callPostApi($url, $data, true);
}
/**
* 删除图片素材
* @param array $data 素材信息
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function delGuideImageMaterial($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/guide/delguideimagematerial?access_token=ACCESS_TOKEN';
$this->registerApi($url, __FUNCTION__, func_get_args());
return $this->callPostApi($url, $data, true);
}
/**
* 删除文字素材
* @param array $data 素材信息
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function delGuideWordMaterial($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/guide/delguidewordmaterial?access_token=ACCESS_TOKEN';
$this->registerApi($url, __FUNCTION__, func_get_args());
return $this->callPostApi($url, $data, true);
}
/**
* 获取卡片素材
* @param int $type 类型
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getGuideCardMaterial($type = 0)
{
$url = 'https://api.weixin.qq.com/cgi-bin/guide/getguidecardmaterial?access_token=ACCESS_TOKEN';
$this->registerApi($url, __FUNCTION__, func_get_args());
return $this->callPostApi($url, ['type' => $type], true);
}
/**
* 获取图片素材
* @param int $type 类型
* @param int $start 起始
* @param int $num 数量
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getGuideImageMaterial($type = 0, $start = 0, $num = 10)
{
$url = 'https://api.weixin.qq.com/cgi-bin/guide/getguideimagematerial?access_token=ACCESS_TOKEN';
$this->registerApi($url, __FUNCTION__, func_get_args());
return $this->callPostApi($url, ['type' => $type, 'start' => $start, 'num' => $num], true);
}
/**
* 获取文字素材
* @param int $type 类型
* @param int $start 起始
* @param int $num 数量
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getGuideWordMaterial($type = 0, $start = 0, $num = 10)
{
$url = 'https://api.weixin.qq.com/cgi-bin/guide/getguidewordmaterial?access_token=ACCESS_TOKEN';
$this->registerApi($url, __FUNCTION__, func_get_args());
return $this->callPostApi($url, ['type' => $type, 'start' => $start, 'num' => $num], true);
}
/**
* 添加卡片素材
* @param array $data 素材数据
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function setGuideCardMaterial($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/guide/setguidecardmaterial?access_token=ACCESS_TOKEN';
$this->registerApi($url, __FUNCTION__, func_get_args());
return $this->callPostApi($url, $data, true);
}
/**
* 添加图片素材
* @param array $data 素材数据
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function setGuideImageMaterial($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/guide/setguideimagematerial?access_token=ACCESS_TOKEN';
$this->registerApi($url, __FUNCTION__, func_get_args());
return $this->callPostApi($url, $data, true);
}
/**
* 添加文字素材
* @param array $data 素材数据
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function setGuideWordMaterial($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/guide/setguidewordmaterial?access_token=ACCESS_TOKEN';
$this->registerApi($url, __FUNCTION__, func_get_args());
return $this->callPostApi($url, $data, true);
}
}

View File

@ -1,69 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeMini;
use WeChat\Contracts\BasicWeChat;
/**
* 小程序图像处理
* @package WeMini
*/
class Image extends BasicWeChat
{
/**
* 图片智能裁剪
* @param string $img_url 图片 URL img 二选一)
* @param string $img form-data 媒体文件(与 img_url 二选一)
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function aiCrop($img_url, $img)
{
$url = "https://api.weixin.qq.com/cv/img/aicrop?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['img_url' => $img_url, 'img' => $img], true);
}
/**
* 条码/二维码识别
* @param string $img_url 图片 URL img 二选一)
* @param string $img form-data 媒体文件(与 img_url 二选一)
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function scanQRCode($img_url, $img)
{
$url = "https://api.weixin.qq.com/cv/img/qrcode?img_url=ENCODE_URL&access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['img_url' => $img_url, 'img' => $img], true);
}
/**
* 图片高清化
* @param string $img_url 图片 URL img 二选一)
* @param string $img form-data 媒体文件(与 img_url 二选一)
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function superresolution($img_url, $img)
{
$url = "https://api.weixin.qq.com/cv/img/qrcode?img_url=ENCODE_URL&access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['img_url' => $img_url, 'img' => $img], true);
}
}

View File

@ -1,208 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeMini;
use WeChat\Contracts\BasicWeChat;
/**
* 小程序运费险
* @package WeMini
*/
class Insurance extends BasicWeChat
{
/**
* 开通无忧退货
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function open()
{
$url = 'https://api.weixin.qq.com/wxa/business/insurance_freight/open?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, [], true);
}
/**
* 查询开通状态
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function queryOpen()
{
$url = 'https://api.weixin.qq.com/wxa/business/insurance_freight/query_open?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, [], true);
}
/**
* 发货投保
* @param array $data 投保数据
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function createOrder($data)
{
$url = 'https://api.weixin.qq.com/wxa/business/insurance_freight/createorder?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 退货理赔
* @param array $data 理赔数据
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function claim($data)
{
$url = 'https://api.weixin.qq.com/wxa/business/insurance_freight/claim?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 申请充值订单号
* @param array $data 充值请求
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function createChargeId($data)
{
$url = 'https://api.weixin.qq.com/wxa/business/insurance_freight/createchargeid?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 申请支付
* @param array $data 支付数据
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function applyPay($data)
{
$url = 'https://api.weixin.qq.com/wxa/business/insurance_freight/applypay?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 拉取充值订单
* @param array $data 查询参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getPayOrderList($data)
{
$url = 'https://api.weixin.qq.com/wxa/business/insurance_freight/getpayorderlist?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 保险退款
* @param array $data 退款参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function refund($data)
{
$url = 'https://api.weixin.qq.com/wxa/business/insurance_freight/refund?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 获取保费摘要
* @param array $data 查询参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getSummary($data)
{
$url = 'https://api.weixin.qq.com/wxa/business/insurance_freight/getsummary?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 拉取保单信息
* @param array $data 查询参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getOrderList($data)
{
$url = 'https://api.weixin.qq.com/wxa/business/insurance_freight/getorderlist?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 设置告警余额
* @param array $data 配置参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function updateNotifyFunds($data)
{
$url = 'https://api.weixin.qq.com/wxa/business/insurance_freight/update_notify_funds?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 创建退货 ID
* @param array $data 退货参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function returnAdd($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/express/delivery/no_worry_return/add?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 查询退货 ID 状态
* @param array $data 查询参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function returnGet($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/express/delivery/no_worry_return/get?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 解绑退货 ID
* @param array $data 解绑参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function returnUbind($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/express/delivery/no_worry_return/unbind?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
}

View File

@ -1,517 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeMini;
use WeChat\Contracts\BasicWeChat;
/**
* 小程序直播
* @package WeMini
*/
class Live extends BasicWeChat
{
/**
* 创建直播间
* @param array $data 房间信息
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function create($data)
{
$url = 'https://api.weixin.qq.com/wxaapi/broadcast/room/create?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 获取直播房间列表
* @param int $start 起始
* @param int $limit 数量
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getLiveList($start = 0, $limit = 10)
{
$url = 'https://api.weixin.qq.com/wxa/business/getliveinfo?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, ['start' => $start, 'limit' => $limit], true);
}
/**
* 获取直播/回放信息
* @param array $data 查询参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getLiveInfo($data = [])
{
$url = 'https://api.weixin.qq.com/wxa/business/getliveinfo?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 直播间导入商品
* @param array $data 商品列表
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function addLiveGoods($data = [])
{
$url = 'https://api.weixin.qq.com/wxaapi/broadcast/room/addgoods?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 商品添加并提审
* @param array $data 商品信息
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function addGoods($data)
{
$url = "https://api.weixin.qq.com/wxaapi/broadcast/goods/add?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data, true);
}
/**
* 撤回商品审核
* @param array $data 商品信息
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function resetAuditGoods($data)
{
$url = "https://api.weixin.qq.com/wxaapi/broadcast/goods/resetaudit?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data, true);
}
/**
* 重新提交商品审核
* @param array $data 商品信息
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function auditGoods($data)
{
$url = "https://api.weixin.qq.com/wxaapi/broadcast/goods/audit?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data, true);
}
/**
* 删除商品
* @param array $data 商品信息
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function deleteGoods($data)
{
$url = "https://api.weixin.qq.com/wxaapi/broadcast/goods/delete?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data, true);
}
/**
* 更新商品
* @param array $data 商品信息
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function updateGoods($data)
{
$url = "https://api.weixin.qq.com/wxaapi/broadcast/goods/update?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data, true);
}
/**
* 获取商品状态
* @param array $data 商品ID列表
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function stateGoods($data)
{
$url = "https://api.weixin.qq.com/wxa/business/getgoodswarehouse?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data, true);
}
/**
* 获取商品列表
* @param int $offset 起始
* @param int $status 0 未审 |1 审核中 |2 通过 |3 驳回
* @param int $limit 数量(<=100)
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getGoods($offset, $status, $limit = 30)
{
$url = "https://api.weixin.qq.com/wxaapi/broadcast/goods/getapproved?access_token=ACCESS_TOKEN&offset={$offset}&limit={$limit}&status={$status}";
return $this->callGetApi($url);
}
/**
* 删除直播间
* @param array $data 房间信息
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function delLive($data)
{
$url = "https://api.weixin.qq.com/wxaapi/broadcast/room/deleteroom?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data, true);
}
/**
* 编辑直播间
* @param array $data 房间信息
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function editLive($data)
{
$url = "https://api.weixin.qq.com/wxaapi/broadcast/room/editroom?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data, true);
}
/**
* 获取推流地址
* @param string $roomId 房间ID
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getPushUrl($roomId)
{
$url = "https://api.weixin.qq.com/wxaapi/broadcast/room/getpushurl?access_token=ACCESS_TOKEN&roomId={$roomId}";
return $this->callGetApi($url);
}
/**
* 获取直播间分享码
* @param string $roomId 房间ID
* @param string $params 自定义参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getShareCode($roomId, $params = '')
{
$url = "https://api.weixin.qq.com/wxaapi/broadcast/room/getsharedcode?access_token=ACCESS_TOKEN&roomId={$roomId}&params={$params}";
return $this->callGetApi($url);
}
/**
* 添加小助手
* @param array $data 助手信息
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function addAssistant($data)
{
$url = "https://api.weixin.qq.com/wxaapi/broadcast/room/addassistant?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data, true);
}
/**
* 修改小助手
* @param array $data 助手信息
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function modifyAssistant($data)
{
$url = "https://api.weixin.qq.com/wxaapi/broadcast/room/modifyassistant?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data, true);
}
/**
* 删除小助手
* @param array $data 助手信息
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function removeAssistant($data)
{
$url = "https://api.weixin.qq.com/wxaapi/broadcast/room/removeassistant?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data, true);
}
/**
* 查询小助手列表
* @param string $roomId 房间ID
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getAssistantList($roomId)
{
$url = "https://api.weixin.qq.com/wxaapi/broadcast/room/getassistantlist?access_token=ACCESS_TOKEN&roomId={$roomId}";
return $this->callGetApi($url);
}
/**
* 添加主播副号
* @param array $data 副号信息
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function addSubAnchor($data)
{
$url = "https://api.weixin.qq.com/wxaapi/broadcast/room/addsubanchor?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data, true);
}
/**
* 修改主播副号
* @param array $data 副号信息
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function modifySubAnchor($data)
{
$url = "https://api.weixin.qq.com/wxaapi/broadcast/room/modifysubanchor?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data, true);
}
/**
* 删除主播副号
* @param array $data 副号信息
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function delSubAnchor($data)
{
$url = "https://api.weixin.qq.com/wxaapi/broadcast/room/deletesubanchor?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data, true);
}
/**
* 查询主播副号
* @param string $roomId 房间ID
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getSubAnchor($roomId)
{
$url = "https://api.weixin.qq.com/wxaapi/broadcast/room/getsubanchor?access_token=ACCESS_TOKEN&roomId={$roomId}";
return $this->callGetApi($url);
}
/**
* 开关官方收录
* @param array $data 房间配置
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function updateFeedPublic($data)
{
$url = "https://api.weixin.qq.com/wxaapi/broadcast/room/updatefeedpublic?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data, true);
}
/**
* 开关回放
* @param array $data 房间配置
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function updateReplay($data)
{
$url = "https://api.weixin.qq.com/wxaapi/broadcast/room/updatereplay?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data, true);
}
/**
* 开关客服
* @param array $data 房间配置
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function updateKf($data)
{
$url = "https://api.weixin.qq.com/wxaapi/broadcast/room/updatekf?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data, true);
}
/**
* 开关全局禁言
* @param array $data 房间配置
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function updateComment($data)
{
$url = "https://api.weixin.qq.com/wxaapi/broadcast/room/updatecomment?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data, true);
}
/**
* 上下架商品
* @param array $data 商品参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function goodsOnsale($data)
{
$url = "https://api.weixin.qq.com/wxaapi/broadcast/goods/onsale?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data, true);
}
/**
* 删除直播间商品
* @param array $data 商品参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function goodsDeleteInRoom($data)
{
$url = "https://api.weixin.qq.com/wxaapi/broadcast/goods/deleteInRoom?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data, true);
}
/**
* 推送商品
* @param array $data 商品参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function goodsPush($data)
{
$url = "https://api.weixin.qq.com/wxaapi/broadcast/goods/push?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data, true);
}
/**
* 商品排序
* @param array $data 排序参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function goodsSort($data)
{
$url = "https://api.weixin.qq.com/wxaapi/broadcast/goods/sort?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data, true);
}
/**
* 下载商品讲解视频
* @param array $data 商品信息
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getVideo($data)
{
$url = "https://api.weixin.qq.com/wxaapi/broadcast/goods/getVideo?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data, true);
}
/**
* 获取长期订阅用户
* @param array $data 查询参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getFollowers($data)
{
$url = "https://api.weixin.qq.com/wxa/business/get_wxa_followers?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data, true);
}
/**
* 长订阅群发
* @param array $data 消息参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function pushMessage($data)
{
$url = "https://api.weixin.qq.com/wxa/business/push_message?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data, true);
}
/**
* 设置成员角色
* @param array $data 角色参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function addRole($data)
{
$url = "https://api.weixin.qq.com/wxaapi/broadcast/role/addrole?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data, true);
}
/**
* 解除成员角色
* @param array $data 角色参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function delRole($data)
{
$url = "https://api.weixin.qq.com/wxaapi/broadcast/role/deleterole?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data, true);
}
/**
* 查询成员角色
* @param int $role 角色过滤,-1 全部
* @param int $offset 起始
* @param int $limit 数量
* @param string $keyword 关键词
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getRole($role = -1, $offset = 0, $limit = 30, $keyword = '')
{
$url = "https://api.weixin.qq.com/wxaapi/broadcast/role/getrolelist?access_token=ACCESS_TOKEN&offset={$offset}&limit={$limit}&keyword={$keyword}&role={$role}";
return $this->callGetApi($url);
}
}

View File

@ -1,236 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeMini;
use WeChat\Contracts\BasicWeChat;
/**
* 小程序物流助手
* @package WeMini
*/
class Logistics extends BasicWeChat
{
/**
* 生成运单
* @param array $data 运单参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function addOrder($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/express/business/order/add?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 取消运单
* @param array $data 取消参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function cancelOrder($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/express/business/order/cancel?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 获取快递公司列表
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getAllDelivery()
{
$url = 'https://api.weixin.qq.com/cgi-bin/express/business/delivery/getall?access_token=ACCESS_TOKEN';
return $this->callGetApi($url);
}
/**
* 获取运单数据
* @param array $data 查询参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getOrder($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/express/business/order/get?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 查询运单轨迹
* @param array $data 查询参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getPath($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/express/business/path/get?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 获取打印员列表(需使用微信打单时调用)
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getPrinter()
{
$url = 'https://api.weixin.qq.com/cgi-bin/express/business/printer/getall?access_token=ACCESS_TOKEN';
return $this->callGetApi($url);
}
/**
* 获取电子面单余额(加盟类快递)
* @param array $data 查询参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getQuota($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/express/business/quota/get?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 模拟更新订单状态(测试用)
* @param array $data 模拟参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function testUpdateOrder($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/express/business/test_update_order?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 配置面单打印员(微信打单)
* @param array $data 配置参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function updatePrinter($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/express/business/printer/update?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 获取面单联系人信息
* @param array $data 查询参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getContact($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/express/delivery/contact/get?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 预览面单模板(调试用)
* @param array $data 模板参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function previewTemplate($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/express/delivery/template/preview?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 更新商户审核结果
* @param array $data 审核结果
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function updateBusiness($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/express/delivery/service/business/update?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 更新运单轨迹
* @param array $data 轨迹参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function updatePath($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/express/delivery/path/update?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 绑定/解绑物流账号
* @param array $data 账号参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function bindAccount($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/express/business/account/bind?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 获取已绑定的物流账号列表
* @param array $data 查询参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getAllAccount($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/express/business/account/getall?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 批量获取运单数据
* @param array $data 查询参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function batchGetOrder($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/express/business/order/batchget?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
}

View File

@ -1,54 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeMini;
use WeChat\Contracts\BasicWeChat;
/**
* 小程序服务市场
* @package WeMini
*/
class Market extends BasicWeChat
{
/**
* 调用上架服务
* @param array $data 服务参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function invoke($data)
{
$url = 'https://api.weixin.qq.com/wxa/servicemarket?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 拉取服务结果
* @param array $data 查询参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function retrieve($data)
{
$url = 'https://api.weixin.qq.com/wxa/servicemarketretrieve?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
}

View File

@ -1,54 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeMini;
use WeChat\Contracts\BasicWeChat;
use WeChat\Contracts\Tools;
/**
* 小程序素材操作
* @package WeMini
*/
class Media extends BasicWeChat
{
/**
* 获取客服消息内的临时素材
* @param string $media_id 媒体 ID
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function get($media_id)
{
$url = 'https://api.weixin.qq.com/cgi-bin/media/get?access_token=ACCESS_TOKEN&media_id=' . $media_id;
return $this->callGetApi($url);
}
/**
* 新增图片素材
* @param string $filename 本地文件
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function upload($filename)
{
$url = 'https://api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=image';
return $this->callPostApi($url, ['media' => Tools::createCurlFile($filename)], false);
}
}

View File

@ -1,65 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeMini;
use WeChat\Contracts\BasicWeChat;
/**
* 小程序动态消息
* @package WeMini
*/
class Message extends BasicWeChat
{
/**
* 创建动态消息 activity_id
* @param array $data 请求参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function createActivityId($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/message/wxopen/activityid/create?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 修改动态消息
* @param array $data 消息数据
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function setUpdatableMsg($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/message/wxopen/updatablemsg/send?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 统一服务消息下发
* @param array $data 消息内容
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function uniformSend($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/message/wxopen/template/uniform_send?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
}

View File

@ -1,144 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeMini;
use WeChat\Contracts\BasicWeChat;
/**
* 小程序订阅消息
* @package WeMini
*/
class Newtmpl extends BasicWeChat
{
/**
* 添加账号类目
* @param array $data 类目信息
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function addCategory($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/wxopen/addcategory?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 获取账号类目
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getCategory()
{
$url = 'https://api.weixin.qq.com/wxaapi/newtmpl/getcategory?access_token=ACCESS_TOKEN';
return $this->callGetApi($url);
}
/**
* 删除账号类目
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function deleteCategory()
{
$url = 'https://api.weixin.qq.com/cgi-bin/wxopen/deletecategory?access_token=TOKEN';
return $this->callPostApi($url, [], true);
}
/**
* 获取类目下公共模板标题
* @param string $ids 类目ID逗号分隔
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getPubTemplateTitleList($ids)
{
$url = 'https://api.weixin.qq.com/wxaapi/newtmpl/getpubtemplatetitles?access_token=ACCESS_TOKEN';
$url .= '&' . http_build_query(['ids' => $ids, 'start' => '0', 'limit' => '30']);
return $this->callGetApi($url);
}
/**
* 获取模板标题关键词
* @param string $tid 模板标题ID
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getPubTemplateKeyWordsById($tid)
{
$url = 'https://api.weixin.qq.com/wxaapi/newtmpl/getpubtemplatekeywords?access_token=ACCESS_TOKEN';
$url .= '&' . http_build_query(['tid' => $tid]);
return $this->callGetApi($url);
}
/**
* 组合模板并入库
* @param string $tid 模板标题ID
* @param array $kidList 关键词ID列表
* @param string $sceneDesc 场景描述
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function addTemplate($tid, array $kidList, $sceneDesc = '')
{
$url = 'https://api.weixin.qq.com/wxaapi/newtmpl/addtemplate?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, ['tid' => $tid, 'kidList' => $kidList, 'sceneDesc' => $sceneDesc], false);
}
/**
* 获取个人模板列表
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getTemplateList()
{
$url = 'https://api.weixin.qq.com/wxaapi/newtmpl/gettemplate?access_token=ACCESS_TOKEN';
return $this->callGetApi($url);
}
/**
* 删除个人模板
* @param string $priTmplId 模板ID
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function delTemplate($priTmplId)
{
$url = 'https://api.weixin.qq.com/wxaapi/newtmpl/deltemplate?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, ['priTmplId' => $priTmplId], true);
}
/**
* 发送订阅消息
* @param array $data 消息数据
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function send(array $data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
}

View File

@ -1,104 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeMini;
use WeChat\Contracts\BasicWeChat;
/**
* 小程序ORC服务
* @package WeMini
*/
class Ocr extends BasicWeChat
{
/**
* 银行卡 OCR
* @param array $data 图片参数img_url img
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function bankcard($data)
{
$url = 'https://api.weixin.qq.com/cv/ocr/bankcard?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, false);
}
/**
* 营业执照 OCR
* @param array $data 图片参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function businessLicense($data)
{
$url = 'https://api.weixin.qq.com/cv/ocr/bizlicense?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, false);
}
/**
* 驾驶证 OCR
* @param array $data 图片参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function driverLicense($data)
{
$url = 'https://api.weixin.qq.com/cv/ocr/drivinglicense?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, false);
}
/**
* 身份证 OCR
* @param array $data 图片参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function idcard($data)
{
$url = 'https://api.weixin.qq.com/cv/ocr/idcard?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, false);
}
/**
* 通用印刷体 OCR
* @param array $data 图片参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function printedText($data)
{
$url = 'https://api.weixin.qq.com/cv/ocr/comm?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, false);
}
/**
* 行驶证 OCR
* @param array $data 图片参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function vehicleLicense($data)
{
$url = 'https://api.weixin.qq.com/cv/ocr/driving?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, false);
}
}

View File

@ -1,69 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeMini;
use WeChat\Contracts\BasicWeChat;
/**
* 小程序运维中心
* @package WeMini
*/
class Operation extends BasicWeChat
{
/**
* 实时日志查询
* @param array $data 查询参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function realtimelogSearch($data)
{
$url = 'https://api.weixin.qq.com/wxaapi/userlog/userlog_search?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 获取反馈媒体文件
* @param array $data query 参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getFeedbackmedia($data)
{
$query = http_build_query($data);
$url = 'https://api.weixin.qq.com/cgi-bin/media/getfeedbackmedia?' . $query . '&access_token=ACCESS_TOKEN';
return $this->callGetApi($url);
}
/**
* 获取用户反馈列表
* @param array $data query 参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getFeedback($data)
{
$query = http_build_query($data);
$url = 'https://api.weixin.qq.com/wxaapi/userlog/userlog_search?' . $query . '&access_token=ACCESS_TOKEN';
return $this->callGetApi($url);
}
}

View File

@ -1,105 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeMini;
use WeChat\Contracts\BasicWeChat;
/**
* 小程序插件管理
* @package WeMini
*/
class Plugs extends BasicWeChat
{
/**
* 申请使用插件
* @param string $plugin_appid 插件 appid
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function apply($plugin_appid)
{
$url = 'https://api.weixin.qq.com/wxa/plugin?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, ['action' => 'apply', 'plugin_appid' => $plugin_appid], true);
}
/**
* 查询已添加插件
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getList()
{
$url = 'https://api.weixin.qq.com/wxa/plugin?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, ['action' => 'list'], true);
}
/**
* 删除插件
* @param string $plugin_appid 插件 appid
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function unbind($plugin_appid)
{
$url = 'https://api.weixin.qq.com/wxa/plugin?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, ['action' => 'unbind', 'plugin_appid' => $plugin_appid], true);
}
/**
* 获取插件使用方或修改申请状态
* @param array $data 请求参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function devplugin($data)
{
$url = 'https://api.weixin.qq.com/wxa/devplugin?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 获取插件使用方列表(开发者)
* @param int $page 页码
* @param int $num 每页数量
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function devApplyList($page = 1, $num = 10)
{
$url = 'https://api.weixin.qq.com/wxa/plugin?access_token=ACCESS_TOKEN';
$data = ['action' => 'dev_apply_list', 'page' => $page, 'num' => $num];
return $this->callPostApi($url, $data, true);
}
/**
* 修改插件申请状态(开发者)
* @param string $action dev_agree|dev_refuse|dev_delete
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function devAgree($action = 'dev_agree')
{
$url = 'https://api.weixin.qq.com/wxa/plugin?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, ['action' => $action], true);
}
}

View File

@ -1,87 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeMini;
use WeChat\Contracts\BasicWeChat;
/**
* 小程序地址管理
* @package WeMini
*/
class Poi extends BasicWeChat
{
/**
* 添加附近地点
* @param string $related_name 经营主体
* @param string $related_credential 证件号
* @param string $related_address 地址
* @param string $related_proof_material 证明材料 media_id
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function addBearByPoi($related_name, $related_credential, $related_address, $related_proof_material)
{
$url = 'https://api.weixin.qq.com/wxa/addnearbypoi?access_token=ACCESS_TOKEN';
$data = [
'related_name' => $related_name, 'related_credential' => $related_credential,
'related_address' => $related_address, 'related_proof_material' => $related_proof_material,
];
return $this->callPostApi($url, $data, true);
}
/**
* 查看地点列表
* @param int $page 页码从1开始
* @param int $page_rows 每页数量(<=1000)
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getNearByPoiList($page = 1, $page_rows = 1000)
{
$url = "https://api.weixin.qq.com/wxa/getnearbypoilist?page={$page}&page_rows={$page_rows}&access_token=ACCESS_TOKEN";
return $this->callGetApi($url);
}
/**
* 删除附近地点
* @param string $poi_id 地点ID
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function delNearByPoiList($poi_id)
{
$url = "https://api.weixin.qq.com/wxa/delnearbypoi?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['poi_id' => $poi_id], true);
}
/**
* 设置附近小程序展示
* @param string $poi_id 地点ID
* @param string $status 0 取消 | 1 展示
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function setNearByPoiShowStatus($poi_id, $status)
{
$url = "https://api.weixin.qq.com/wxa/setnearbypoishowstatus?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, ['poi_id' => $poi_id, 'status' => $status], true);
}
}

View File

@ -1,119 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeMini;
use WeChat\Contracts\BasicWeChat;
use WeChat\Contracts\Tools;
/**
* 微信小程序二维码
* @package WeMini
*/
class Qrcode extends BasicWeChat
{
/**
* 默认线条颜色
* @var string[]
*/
private $lineColor = ["r" => "0", "g" => "0", "b" => "0"];
/**
* 获取小程序码(永久有效)
* 接口A: 适用于需要的码数量较少的业务场景
* @param string $path 不能为空,最大长度 128 字节
* @param integer $width 二维码的宽度
* @param bool $autoColor 自动配置线条颜色,如果颜色依然是黑色,则说明不建议配置主色调
* @param null|array $lineColor auto_color false 时生效
* @param boolean $isHyaline 透明底色
* @param string|null $outType 输出类型
* @param array $extra 其他参数
* @return string|array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function createMiniPath($path, $width = 430, $autoColor = false, $lineColor = null, $isHyaline = true, $outType = null, array $extra = [])
{
$url = 'https://api.weixin.qq.com/wxa/getwxacode?access_token=ACCESS_TOKEN';
$this->registerApi($url, __FUNCTION__, func_get_args());
$lineColor = empty($lineColor) ? $this->lineColor : $lineColor;
$data = ['path' => $path, 'width' => $width, 'auto_color' => $autoColor, 'line_color' => $lineColor, 'is_hyaline' => $isHyaline];
return $this->parseResult(Tools::post($url, Tools::arr2json(array_merge($data, $extra))), $outType);
}
/**
* 解释接口数据
* @param bool|string $result
* @param null|string $outType
* @return array|mixed
* @throws \WeChat\Exceptions\InvalidResponseException
*/
private function parseResult($result, $outType)
{
if (is_array($json = json_decode($result, true))) {
if (!$this->isTry && isset($json['errcode']) && in_array($json['errcode'], ['40014', '40001', '41001', '42001'])) {
[$this->delAccessToken(), $this->isTry = true];
return call_user_func_array([$this, $this->currentMethod['method']], $this->currentMethod['arguments']);
}
return Tools::json2arr($result);
} else {
return is_null($outType) ? $result : $outType($result);
}
}
/**
* 获取小程序码(永久有效)
* 接口B适用于需要的码数量极多的业务场景
* @param string $scene 最大32个可见字符只支持数字
* @param string $page 必须是已经发布的小程序存在的页面
* @param integer $width 二维码的宽度
* @param bool $autoColor 自动配置线条颜色,如果颜色依然是黑色,则说明不建议配置主色调
* @param null|array $lineColor auto_color false 时生效
* @param bool $isHyaline 是否需要透明底色
* @param null|string $outType 输出类型
* @param array $extra 其他参数
* @return array|string
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function createMiniScene($scene, $page = '', $width = 430, $autoColor = false, $lineColor = null, $isHyaline = true, $outType = null, array $extra = [])
{
$url = 'https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=ACCESS_TOKEN';
$this->registerApi($url, __FUNCTION__, func_get_args());
$lineColor = empty($lineColor) ? $this->lineColor : $lineColor;
$data = ['scene' => $scene, 'width' => $width, 'page' => $page, 'auto_color' => $autoColor, 'line_color' => $lineColor, 'is_hyaline' => $isHyaline, 'check_path' => false];
if (empty($page)) unset($data['page']);
return $this->parseResult(Tools::post($url, Tools::arr2json(array_merge($data, $extra))), $outType);
}
/**
* 获取小程序二维码(永久有效)
* 接口C适用于需要的码数量较少的业务场景
* @param string $path 不能为空,最大长度 128 字节
* @param integer $width 二维码的宽度
* @param string|null $outType 输出类型
* @return array|string
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function createDefault($path, $width = 430, $outType = null)
{
$url = 'https://api.weixin.qq.com/cgi-bin/wxaapp/createwxaqrcode?access_token=ACCESS_TOKEN';
$this->registerApi($url, __FUNCTION__, func_get_args());
return $this->parseResult(Tools::post($url, Tools::arr2json(['path' => $path, 'width' => $width])), $outType);
}
}

View File

@ -1,79 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeMini;
use WeChat\Contracts\BasicWeChat;
/**
* 小程序 URL-Scheme
* @package WeMini
*/
class Scheme extends BasicWeChat
{
/**
* 创建 URL-Scheme
* @param array $data 场景参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function create($data)
{
$url = 'https://api.weixin.qq.com/wxa/generatescheme?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 查询 URL-Scheme
* @param string $scheme Scheme 字符串
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function query($scheme)
{
$url = 'https://api.weixin.qq.com/wxa/queryscheme?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, ['scheme' => $scheme], true);
}
/**
* 创建 URL-Link
* @param array $data 场景参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function urlLink($data)
{
$url = "https://api.weixin.qq.com/wxa/generate_urllink?access_token=ACCESS_TOKEN";
return $this->callPostApi($url, $data, true);
}
/**
* 查询 URL-Link
* @param string $urllink URL-Link 字符串
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function urlQuery($urllink)
{
$url = 'https://api.weixin.qq.com/wxa/query_urllink?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, ['url_link' => $urllink], true);
}
}

View File

@ -1,39 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeMini;
use WeChat\Contracts\BasicWeChat;
/**
* 小程序搜索
* @package WeMini
*/
class Search extends BasicWeChat
{
/**
* 提交页面 URL 及参数
* @param array $pages 页面列表
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function submitPages($pages)
{
$url = 'https://api.weixin.qq.com/cgi-bin/guide/getguideacct?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, ['pages' => $pages], true);
}
}

View File

@ -1,67 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeMini;
use WeChat\Contracts\BasicWeChat;
/**
* 小程序内容安全
* @package WeMini
*/
class Security extends BasicWeChat
{
/**
* 图片内容安全校验
* @param string $media 图片文件
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function imgSecCheck($media)
{
$url = 'https://api.weixin.qq.com/wxa/img_sec_check?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, ['media' => $media], false, ['headers' => ['Content-Type: application/octet-stream']]);
}
/**
* 异步校验媒体(图片/音频)
* @param string $media_url 媒体 URL
* @param string $media_type 1 音频 | 2 图片
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function mediaCheckAsync($media_url, $media_type)
{
$url = 'https://api.weixin.qq.com/wxa/media_check_async?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, ['media_url' => $media_url, 'media_type' => $media_type], true);
}
/**
* 文本内容安全校验
* @param string $content 文本内容
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function msgSecCheck($content)
{
$url = 'https://api.weixin.qq.com/wxa/msg_sec_check?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, ['content' => $content], true);
}
}

View File

@ -1,117 +0,0 @@
<?php
namespace WeMini;
use WeChat\Contracts\BasicWeChat;
/**
* 小程序发货信息管理
* @package WeMini
*/
class Shipping extends BasicWeChat
{
/**
* 录入发货信息
* @param array $data 发货数据
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function upload($data)
{
$url = 'https://api.weixin.qq.com/wxa/sec/order/upload_shipping_info?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 合单发货录入
* @param array $data 发货数据
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function combined($data)
{
$url = 'https://api.weixin.qq.com/wxa/sec/order/upload_combined_shipping_info?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 查询发货状态
* @param array $data 查询参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function query($data)
{
$url = 'https://api.weixin.qq.com/wxa/sec/order/get_order?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 查询发货订单列表
* @param array $data 查询参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function qlist($data)
{
$url = 'https://api.weixin.qq.com/wxa/sec/order/get_order_list?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 提醒确认收货
* @param array $data 提醒参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function confirm($data)
{
$url = 'https://api.weixin.qq.com/wxa/sec/order/notify_confirm_receive?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 设置消息跳转路径
* @param array $data 路径参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function setJump($data)
{
$url = 'https://api.weixin.qq.com/wxa/sec/order/set_msg_jump_path?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 查询是否开通发货管理
* @param array $data 查询参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function isTrade($data)
{
$url = 'https://api.weixin.qq.com/wxa/sec/order/is_trade_managed?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 查询交易结算确认状态
* @param array $data 查询参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function isCompleted($data)
{
$url = 'https://api.weixin.qq.com/wxa/sec/order/is_trade_management_confirmation_completed?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
}

View File

@ -1,94 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeMini;
use WeChat\Contracts\BasicWeChat;
/**
* 小程序购物订单
* @package WeMini
*/
class Shopping extends BasicWeChat
{
/**
* 上传购物详情
* @param array $data 订单数据
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function uploadShoppingInfo($data)
{
$url = 'https://api.weixin.qq.com/user-order/orders?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 上传物流信息
* @param array $data 物流数据
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function uploadShippingInfo($data)
{
$url = 'https://api.weixin.qq.com/user-order/orders?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 上传合单购物详情
* @param array $data 订单数据
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function uploadCombinedShoppingInfo($data)
{
$url = 'https://api.weixin.qq.com/user-order/orders?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 上传合单物流
* @param array $data 物流数据
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function uploadCombinedShippingInfo($data)
{
$url = 'https://api.weixin.qq.com/user-order/orders?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
/**
* 校验购物订单上传结果
* @param array $data 校验参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function ShoppingInfoVerifyUploadResult($data)
{
$url = 'https://api.weixin.qq.com/user-order/shoppinginfo/verify?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
}

View File

@ -1,39 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeMini;
use WeChat\Contracts\BasicWeChat;
/**
* 小程序生物认证
* @package WeMini
*/
class Soter extends BasicWeChat
{
/**
* SOTER 签名验证
* @param array $data 签名数据
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function verifySignature($data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/soter/verify_signature?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
}

View File

@ -1,104 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeMini;
use WeChat\Contracts\BasicWeChat;
/**
* 小程序模板消息
* @package WeMini
*/
class Template extends BasicWeChat
{
/**
* 获取模板库标题列表
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getTemplateLibraryList()
{
$url = 'https://api.weixin.qq.com/cgi-bin/wxopen/template/library/list?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, ['offset' => '0', 'count' => '20'], true);
}
/**
* 获取模板关键词库
* @param string $template_id 模板标题ID
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getTemplateLibrary($template_id)
{
$url = 'https://api.weixin.qq.com/cgi-bin/wxopen/template/library/get?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, ['id' => $template_id], true);
}
/**
* 组合关键词并添加模板
* @param string $template_id 模板标题ID
* @param array $keyword_id_list 关键词 ID 列表
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function addTemplate($template_id, array $keyword_id_list)
{
$url = 'https://api.weixin.qq.com/cgi-bin/wxopen/template/add?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, ['id' => $template_id, 'keyword_id_list' => $keyword_id_list], true);
}
/**
* 获取帐号模板列表
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getTemplateList()
{
$url = 'https://api.weixin.qq.com/cgi-bin/wxopen/template/list?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, ['offset' => '0', 'count' => '20'], true);
}
/**
* 删除模板
* @param string $template_id 模板 ID
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function delTemplate($template_id)
{
$url = 'https://api.weixin.qq.com/cgi-bin/wxopen/template/del?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, ['template_id' => $template_id], true);
}
/**
* 发送模板消息
* @param array $data 消息体touser, template_id, form_id, data 等)
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function send(array $data)
{
$url = 'https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, $data, true);
}
}

View File

@ -1,166 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WeMini;
use WeChat\Contracts\BasicWeChat;
/**
* 小程序数据统计
* @package WeMini
*/
class Total extends BasicWeChat
{
/**
* 概况趋势(日)
* @param string $beginDate 开始日期
* @param string $endDate 结束日期,需同一天
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getWeanalysisAppidDailySummarytrend($beginDate, $endDate)
{
$url = 'https://api.weixin.qq.com/datacube/getweanalysisappiddailysummarytrend?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, ['begin_date' => $beginDate, 'end_date' => $endDate], true);
}
/**
* 访问趋势(日)
* @param string $beginDate 开始日期
* @param string $endDate 结束日期,需同一天
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getWeanalysisAppidDailyVisittrend($beginDate, $endDate)
{
$url = 'https://api.weixin.qq.com/datacube/getweanalysisappiddailyvisittrend?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, ['begin_date' => $beginDate, 'end_date' => $endDate], true);
}
/**
* 访问趋势(周)
* @param string $begin_date 周一
* @param string $end_date 周日
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getWeanalysisAppidWeeklyVisittrend($begin_date, $end_date)
{
$url = 'https://api.weixin.qq.com/datacube/getweanalysisappidweeklyvisittrend?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, ['begin_date' => $begin_date, 'end_date' => $end_date], true);
}
/**
* 访问趋势(月)
* @param string $begin_date 月首日
* @param string $end_date 月末日
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getWeanalysisAppidMonthlyVisittrend($begin_date, $end_date)
{
$url = 'https://api.weixin.qq.com/datacube/getweanalysisappidmonthlyvisittrend?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, ['begin_date' => $begin_date, 'end_date' => $end_date], true);
}
/**
* 访问分布
* @param string $begin_date 开始日期
* @param string $end_date 结束日期,需同一天
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getWeanalysisAppidVisitdistribution($begin_date, $end_date)
{
$url = 'https://api.weixin.qq.com/datacube/getweanalysisappidvisitdistribution?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, ['begin_date' => $begin_date, 'end_date' => $end_date], true);
}
/**
* 留存(日)
* @param string $begin_date 开始日期
* @param string $end_date 结束日期,需同一天
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getWeanalysisAppidDailyRetaininfo($begin_date, $end_date)
{
$url = 'https://api.weixin.qq.com/datacube/getweanalysisappiddailyretaininfo?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, ['begin_date' => $begin_date, 'end_date' => $end_date], true);
}
/**
* 留存(周)
* @param string $begin_date 周一
* @param string $end_date 周日
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getWeanalysisAppidWeeklyRetaininfo($begin_date, $end_date)
{
$url = 'https://api.weixin.qq.com/datacube/getweanalysisappidweeklyretaininfo?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, ['begin_date' => $begin_date, 'end_date' => $end_date], true);
}
/**
* 留存(月)
* @param string $begin_date 月首日
* @param string $end_date 月末日
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getWeanalysisAppidMonthlyRetaininfo($begin_date, $end_date)
{
$url = 'https://api.weixin.qq.com/datacube/getweanalysisappidmonthlyretaininfo?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, ['begin_date' => $begin_date, 'end_date' => $end_date], true);
}
/**
* 访问页面数据
* @param string $begin_date 开始日期
* @param string $end_date 结束日期,需同一天
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getWeanalysisAppidVisitPage($begin_date, $end_date)
{
$url = 'https://api.weixin.qq.com/datacube/getweanalysisappidvisitpage?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, ['begin_date' => $begin_date, 'end_date' => $end_date], true);
}
/**
* 用户画像
* @param string $begin_date 开始日期
* @param string $end_date 结束日期间隔为0/6/29
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function getWeanalysisAppidUserportrait($begin_date, $end_date)
{
$url = 'https://api.weixin.qq.com/datacube/getweanalysisappiduserportrait?access_token=ACCESS_TOKEN';
return $this->callPostApi($url, ['begin_date' => $begin_date, 'end_date' => $end_date], true);
}
}

View File

@ -1,20 +0,0 @@
<?php
/**
* error code 说明.
* <ul>
* <li>-41001: encodingAesKey 非法</li>
* <li>-41003: aes 解密失败</li>
* <li>-41004: 解密后得到的buffer非法</li>
* <li>-41005: base64加密失败</li>
* <li>-41016: base64解密失败</li>
* </ul>
*/
class ErrorCode
{
public static $OK = 0;
public static $IllegalAesKey = -41001;
public static $IllegalIv = -41002;
public static $IllegalBuffer = -41003;
public static $DecodeBase64Error = -41004;
}

View File

@ -1,57 +0,0 @@
<?php
/**
* 对微信小程序用户加密数据的解密示例代码
* @copyright Copyright (c) 1998-2014 Tencent Inc.
*/
class WXBizDataCrypt
{
private $appid;
private $sessionKey;
/**
* 构造函数
* @param $sessionKey string 用户在小程序登录后获取的会话密钥
* @param $appid string 小程序的appid
*/
public function __construct($appid, $sessionKey)
{
$this->appid = $appid;
$this->sessionKey = $sessionKey;
include_once __DIR__ . DIRECTORY_SEPARATOR . "errorCode.php";
}
/**
* 检验数据的真实性,并且获取解密后的明文.
* @param $encryptedData string 加密的用户数据
* @param $iv string 与用户数据一同返回的初始向量
* @param $data string 解密后的原文
*
* @return int 成功0失败返回对应的错误码
*/
public function decryptData($encryptedData, $iv, &$data)
{
if (strlen($this->sessionKey) != 24) {
return ErrorCode::$IllegalAesKey;
}
$aesKey = base64_decode($this->sessionKey);
if (strlen($iv) != 24) {
return ErrorCode::$IllegalIv;
}
$aesIV = base64_decode($iv);
$aesCipher = base64_decode($encryptedData);
$result = openssl_decrypt($aesCipher, "AES-128-CBC", $aesKey, 1, $aesIV);
$dataObj = json_decode($result);
if ($dataObj == null) {
return ErrorCode::$IllegalBuffer;
}
// 兼容新版本无 watermark 的情况
if (isset($dataObj->watermark) && $dataObj->watermark->appid != $this->appid) {
return ErrorCode::$IllegalBuffer;
}
$data = $result;
return ErrorCode::$OK;
}
}

View File

@ -1,64 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WePay;
use WeChat\Contracts\BasicWePay;
use WeChat\Contracts\Tools;
use WeChat\Exceptions\InvalidResponseException;
/**
* 微信商户账单及评论
* @package WePay
*/
class Bill extends BasicWePay
{
/**
* 下载对账单
* @param array $options 账单参数bill_date, bill_type 等)
* @param null|string $outType 输出处理回调,为 null 则返回原始内容
* @return bool|string 原始账单文本或回调结果
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function download(array $options, $outType = null)
{
$this->params->set('sign_type', 'MD5');
$params = $this->params->merge($options);
$params['sign'] = $this->getPaySign($params, 'MD5');
$result = Tools::post('https://api.mch.weixin.qq.com/pay/downloadbill', Tools::arr2xml($params));
if (is_array($jsonData = Tools::xml3arr($result))) {
if ($jsonData['return_code'] !== 'SUCCESS') {
throw new InvalidResponseException($jsonData['return_msg'], '0');
}
}
return is_null($outType) ? $result : $outType($result);
}
/**
* 拉取订单评价数据(需证书)
* @param array $options 查询参数bill_date, offset, limit 等)
* @return array 评价数据
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function comment(array $options)
{
$url = 'https://api.mch.weixin.qq.com/billcommentsp/batchquerycomment';
return $this->callPostApi($url, $options, true);
}
}

View File

@ -1,66 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WePay;
use WeChat\Contracts\BasicWePay;
/**
* 微信商户代金券
* @package WePay
*/
class Coupon extends BasicWePay
{
/**
* 发放代金券(需证书)
* @param array $options 代金券参数coupon_stock_id, openid, partner_trade_no, op_user_id 等)
* @return array 发券结果
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function create(array $options)
{
$url = "https://api.mch.weixin.qq.com/mmpaymkttransfers/send_coupon";
return $this->callPostApi($url, $options, true, 'MD5');
}
/**
* 查询代金券批次
* @param array $options 查询参数coupon_stock_id 等)
* @return array 批次详情
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function queryStock(array $options)
{
$url = "https://api.mch.weixin.qq.com/mmpaymkttransfers/query_coupon_stock";
return $this->callPostApi($url, $options, false);
}
/**
* 查询单个代金券信息
* @param array $options 查询参数coupon_id, openid, stock_id 等)
* @return array 代金券详情
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function queryInfo(array $options)
{
$url = "https://api.mch.weixin.qq.com/mmpaymkttransfers/query_coupon_stock";
return $this->callPostApi($url, $options, false);
}
}

View File

@ -1,68 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WePay;
use WeChat\Contracts\BasicWePay;
/**
* 微信扩展上报海关
* @package WePay
*/
class Custom extends BasicWePay
{
/**
* 海关申报:订单附加信息提交
* @param array $options 申报参数transaction_id out_trade_nocustomsmch_customs_no 等)
* @return array 申报结果
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function add(array $options = [])
{
$url = 'https://api.mch.weixin.qq.com/cgi-bin/mch/customs/customdeclareorder';
return $this->callPostApi($url, $options, false, 'MD5', false, false);
}
/**
* 海关申报:订单附加信息查询
* @param array $options 查询参数transaction_id out_trade_nocustomsmch_customs_no 等)
* @return array 申报状态
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function get(array $options = [])
{
$url = 'https://api.mch.weixin.qq.com/cgi-bin/mch/customs/customdeclarequery';
return $this->callPostApi($url, $options, false, 'MD5', true, false);
}
/**
* 海关申报:重推申报信息
* @param array $options 重推参数transaction_id out_trade_nocustomsmch_customs_no 等)
* @return array 重推结果
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function reset(array $options = [])
{
$url = 'https://api.mch.weixin.qq.com/cgi-bin/mch/newcustoms/customdeclareredeclare';
return $this->callPostApi($url, $options, false, 'MD5', true, false);
}
}

View File

@ -1,174 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WePay;
use WeChat\Contracts\BasicWePay;
use WeChat\Contracts\Tools;
/**
* 微信商户订单
* @package WePay
*/
class Order extends BasicWePay
{
/**
* 统一下单接口
* @param array $options 订单参数out_trade_no, body, total_fee, notify_url, trade_type等
* @return array 返回prepay_id等支付参数
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function create(array $options)
{
$url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
return $this->callPostApi($url, $options, false, 'MD5');
}
/**
* 刷卡支付接口(被扫支付)
* @param array $options 支付参数auth_code, out_trade_no, body, total_fee等
* @return array 支付结果
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function micropay(array $options)
{
$url = 'https://api.mch.weixin.qq.com/pay/micropay';
return $this->callPostApi($url, $options, false, 'MD5');
}
/**
* 查询订单接口
* @param array $options 查询参数transaction_id或out_trade_no二选一
* @return array 订单详情
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function query(array $options)
{
$url = 'https://api.mch.weixin.qq.com/pay/orderquery';
return $this->callPostApi($url, $options);
}
/**
* 关闭订单接口
* @param string $outTradeNo 商户订单号
* @return array 关闭结果
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function close($outTradeNo)
{
$url = 'https://api.mch.weixin.qq.com/pay/closeorder';
return $this->callPostApi($url, ['out_trade_no' => $outTradeNo]);
}
/**
* 生成JSAPI支付参数用于前端调起支付
* @param string $prepayId 统一下单返回的prepay_id
* @return array JSAPI支付所需参数appId, timeStamp, nonceStr, package, signType, paySign
*/
public function jsapiParams($prepayId)
{
$option = [];
$option["appId"] = $this->config->get('appid');
$option["timeStamp"] = (string)time();
$option["nonceStr"] = Tools::createNoncestr();
$option["package"] = "prepay_id={$prepayId}";
$option["signType"] = "MD5";
$option["paySign"] = $this->getPaySign($option, 'MD5');
$option['timestamp'] = $option['timeStamp'];
return $option;
}
/**
* 生成Native支付二维码URL
* @param string $productId 商品ID或订单号
* @return string 支付二维码URLweixin://wxpay/bizpayurl?xxx
*/
public function qrcParams($productId)
{
$data = [
'appid' => $this->config->get('appid'),
'mch_id' => $this->config->get('mch_id'),
'time_stamp' => (string)time(),
'nonce_str' => Tools::createNoncestr(),
'product_id' => (string)$productId,
];
$data['sign'] = $this->getPaySign($data, 'MD5');
return "weixin://wxpay/bizpayurl?" . http_build_query($data);
}
/**
* 生成APP支付参数用于移动应用调起支付
* @param string $prepayId 统一下单返回的prepay_id
* @return array APP支付所需参数appid, partnerid, prepayid, package, timestamp, noncestr, sign
*/
public function appParams($prepayId)
{
$data = [
'appid' => $this->config->get('appid'),
'partnerid' => $this->config->get('mch_id'),
'prepayid' => (string)$prepayId,
'package' => 'Sign=WXPay',
'timestamp' => (string)time(),
'noncestr' => Tools::createNoncestr(),
];
$data['sign'] = $this->getPaySign($data, 'MD5');
return $data;
}
/**
* 撤销订单接口(刷卡支付专用,需要证书)
* @param array $options 撤销参数transaction_id或out_trade_no二选一
* @return array 撤销结果
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function reverse(array $options)
{
$url = 'https://api.mch.weixin.qq.com/secapi/pay/reverse';
return $this->callPostApi($url, $options, true);
}
/**
* 授权码查询openid接口
* @param string $authCode 授权码(用户微信中的条码或二维码信息)
* @return array 包含openid等信息
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function queryAuthCode($authCode)
{
$url = 'https://api.mch.weixin.qq.com/tools/authcodetoopenid';
return $this->callPostApi($url, ['auth_code' => $authCode], false, 'MD5', false);
}
/**
* 交易保障接口(用于上报交易数据)
* @param array $options 上报参数interface_url, execute_time, return_code, result_code等
* @return array 上报结果
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function report(array $options)
{
$url = 'https://api.mch.weixin.qq.com/payitil/report';
return $this->callPostApi($url, $options);
}
}

View File

@ -1,144 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WePay;
use WeChat\Contracts\BasicWePay;
/**
* 微信分账
* @package WePay
*/
class ProfitSharing extends BasicWePay
{
/**
* 请求单次分账(需证书)
* @param array $options 分账参数transaction_id, out_order_no, receivers 等)
* @return array 分账结果
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function profitSharing(array $options)
{
$url = 'https://api.mch.weixin.qq.com/secapi/pay/profitsharing';
return $this->callPostApi($url, $options, true);
}
/**
* 请求多次分账(需证书)
* @param array $options 分账参数transaction_id, out_order_no, receivers 等)
* @return array 分账结果
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function multiProfitSharing(array $options)
{
$url = 'https://api.mch.weixin.qq.com/secapi/pay/multiprofitsharing';
return $this->callPostApi($url, $options, true);
}
/**
* 查询分账结果
* @param array $options 查询参数transaction_id out_order_no
* @return array 分账状态
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function profitSharingQuery(array $options)
{
$url = 'https://api.mch.weixin.qq.com/pay/profitsharingquery';
return $this->callPostApi($url, $options);
}
/**
* 添加分账接收方
* @param array $options 接收方信息type, account, name, relation_type 等)
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function profitSharingAddReceiver(array $options)
{
$url = 'https://api.mch.weixin.qq.com/pay/profitsharingaddreceiver';
return $this->callPostApi($url, $options);
}
/**
* 删除分账接收方
* @param array $options 接收方信息type, account
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function profitSharingRemoveReceiver(array $options)
{
$url = 'https://api.mch.weixin.qq.com/pay/profitsharingremovereceiver';
return $this->callPostApi($url, $options);
}
/**
* 完结分账(需证书)
* @param array $options 完结参数transaction_id, out_order_no, description 等)
* @return array 完结结果
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function profitSharingFinish(array $options)
{
$url = 'https://api.mch.weixin.qq.com/secapi/pay/profitsharingfinish';
return $this->callPostApi($url, $options, true);
}
/**
* 查询订单待分账金额
* @param array $options 查询参数transaction_id
* @return array 待分账金额
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function profitSharingOrderAmountQuery(array $options)
{
$url = 'https://api.mch.weixin.qq.com/pay/profitsharingorderamountquery';
return $this->callPostApi($url, $options);
}
/**
* 分账回退(需证书)
* @param array $options 回退参数out_return_no, out_order_no, return_account_type 等)
* @return array 回退结果
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function profitSharingReturn(array $options)
{
$url = 'https://api.mch.weixin.qq.com/secapi/pay/profitsharingreturn';
return $this->callPostApi($url, $options, true);
}
/**
* 回退结果查询
* @param array $options 查询参数out_return_no out_order_no
* @return array 回退状态
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function profitSharingReturnQuery(array $options)
{
$url = 'https://api.mch.weixin.qq.com/pay/profitsharingreturnquery';
return $this->callPostApi($url, $options);
}
}

View File

@ -1,73 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WePay;
use WeChat\Contracts\BasicWePay;
/**
* 微信红包支持
* @package WePay
*/
class Redpack extends BasicWePay
{
/**
* 发放普通红包(需证书)
* @param array $options 红包参数mch_billno, send_name, re_openid, total_amount, total_num, wishing 等)
* @return array 红包发送结果
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function create(array $options)
{
$this->params->offsetUnset('appid');
$this->params->set('wxappid', $this->config->get('appid'));
$url = "https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack";
return $this->callPostApi($url, $options, true, 'MD5', false);
}
/**
* 发放裂变红包(需证书)
* @param array $options 红包参数mch_billno, send_name, re_openid, total_amount, total_num total_num>1
* @return array 红包发送结果
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function groups(array $options)
{
$this->params->offsetUnset('appid');
$this->params->set('wxappid', $this->config->get('appid'));
$url = "https://api.mch.weixin.qq.com/mmpaymkttransfers/sendgroupredpack";
return $this->callPostApi($url, $options, true, 'MD5', false);
}
/**
* 查询红包记录
* @param string $mchBillno 商户红包订单号
* @return array 红包状态信息
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function query($mchBillno)
{
$this->params->offsetUnset('wxappid');
$this->params->set('appid', $this->config->get('appid'));
$url = "https://api.mch.weixin.qq.com/mmpaymkttransfers/gethbinfo";
return $this->callPostApi($url, ['mch_billno' => $mchBillno, 'bill_type' => 'MCHT'], true, 'MD5', false);
}
}

View File

@ -1,80 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WePay;
use WeChat\Contracts\BasicWePay;
use WeChat\Contracts\Tools;
use WeChat\Exceptions\InvalidDecryptException;
use WeChat\Exceptions\InvalidResponseException;
/**
* 微信商户退款
* @package WePay
*/
class Refund extends BasicWePay
{
/**
* 申请退款接口(需要证书)
* @param array $options 退款参数transaction_id或out_trade_no, out_refund_no, total_fee, refund_fee等
* @return array 退款结果
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function create(array $options)
{
$url = 'https://api.mch.weixin.qq.com/secapi/pay/refund';
return $this->callPostApi($url, $options, true);
}
/**
* 查询退款接口
* @param array $options 查询参数transaction_id, out_trade_no, out_refund_no, refund_id四选一
* @return array 退款详情
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function query(array $options)
{
$url = 'https://api.mch.weixin.qq.com/pay/refundquery';
return $this->callPostApi($url, $options);
}
/**
* 解析退款通知自动解密req_info
* @param string|array $xml 退款通知XML数据为空则从POST获取
* @return array 解密后的退款通知数据
* @throws \WeChat\Exceptions\InvalidDecryptException
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function getNotify($xml = '')
{
$data = is_array($xml) ? $xml : Tools::xml2arr(empty($xml) ? Tools::getRawInput() : $xml);
if (!isset($data['return_code']) || $data['return_code'] !== 'SUCCESS') {
throw new InvalidResponseException('获取退款通知XML失败');
}
try {
$key = md5($this->config->get('mch_key'));
$decrypt = base64_decode($data['req_info']);
$response = openssl_decrypt($decrypt, 'aes-256-ecb', $key, OPENSSL_RAW_DATA);
$data['result'] = Tools::xml2arr($response);
return $data;
} catch (\Exception $exception) {
throw new InvalidDecryptException($exception->getMessage(), $exception->getCode());
}
}
}

View File

@ -1,62 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WePay;
use WeChat\Contracts\BasicWePay;
/**
* 微信商户打款到零钱
* @package WePay
*/
class Transfers extends BasicWePay
{
/**
* 企业付款到零钱(需证书)
* @param array $options 付款参数partner_trade_no, openid, amount, desc, check_name 等)
* @return array 付款结果
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function create(array $options)
{
$this->params->offsetUnset('appid');
$this->params->offsetUnset('mch_id');
$this->params->set('mchid', $this->config->get('mch_id'));
$this->params->set('mch_appid', $this->config->get('appid'));
$url = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers';
return $this->callPostApi($url, $options, true, 'MD5', false);
}
/**
* 查询企业付款到零钱结果
* @param string $partnerTradeNo 商户付款单号
* @return array 付款状态
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function query($partnerTradeNo)
{
$this->params->offsetUnset('mchid');
$this->params->offsetUnset('mch_appid');
$this->params->set('appid', $this->config->get('appid'));
$this->params->set('mch_id', $this->config->get('mch_id'));
$url = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/gettransferinfo';
return $this->callPostApi($url, ['partner_trade_no' => $partnerTradeNo], true, 'MD5', false);
}
}

View File

@ -1,125 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WePay;
use WeChat\Contracts\BasicWePay;
use WeChat\Contracts\Tools;
use WeChat\Exceptions\InvalidArgumentException;
use WeChat\Exceptions\InvalidDecryptException;
use WeChat\Exceptions\InvalidResponseException;
/**
* 微信商户打款到银行卡
* @package WePay
*/
class TransfersBank extends BasicWePay
{
/**
* 企业付款到银行卡(需证书,敏感字段 RSA 加密)
* @param array $options 付款参数partner_trade_no, enc_bank_no, enc_true_name, bank_code, amount, desc 等)
* @return array 付款结果
* @throws \WeChat\Exceptions\InvalidDecryptException
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function create(array $options)
{
if (!isset($options['partner_trade_no'])) {
throw new InvalidArgumentException('Missing Options -- [partner_trade_no]');
}
if (!isset($options['enc_bank_no'])) {
throw new InvalidArgumentException('Missing Options -- [enc_bank_no]');
}
if (!isset($options['enc_true_name'])) {
throw new InvalidArgumentException('Missing Options -- [enc_true_name]');
}
if (!isset($options['bank_code'])) {
throw new InvalidArgumentException('Missing Options -- [bank_code]');
}
if (!isset($options['amount'])) {
throw new InvalidArgumentException('Missing Options -- [amount]');
}
$this->params->offsetUnset('appid');
return $this->callPostApi('https://api.mch.weixin.qq.com/mmpaysptrans/pay_bank', [
'amount' => $options['amount'],
'bank_code' => $options['bank_code'],
'partner_trade_no' => $options['partner_trade_no'],
'enc_bank_no' => $this->rsaEncode($options['enc_bank_no']),
'enc_true_name' => $this->rsaEncode($options['enc_true_name']),
'desc' => isset($options['desc']) ? $options['desc'] : '',
], true, 'MD5', false);
}
/**
* RSA 加密银行卡号/姓名
* @param string $string 待加密字符串
* @param string $encrypted
* @return string base64 编码密文
* @throws \WeChat\Exceptions\InvalidDecryptException
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
private function rsaEncode($string, $encrypted = '')
{
$search = ['-----BEGIN RSA PUBLIC KEY-----', '-----END RSA PUBLIC KEY-----', "\n", "\r"];
$pkc1 = str_replace($search, '', $this->getRsaContent());
$publicKey = '-----BEGIN PUBLIC KEY-----' . PHP_EOL .
wordwrap('MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A' . $pkc1, 64, PHP_EOL, true) . PHP_EOL .
'-----END PUBLIC KEY-----';
if (!openssl_public_encrypt("{$string}", $encrypted, $publicKey, OPENSSL_PKCS1_OAEP_PADDING)) {
throw new InvalidDecryptException('Rsa Encrypt Error.');
}
return base64_encode($encrypted);
}
/**
* 获取 RSA 公钥内容
* @return string 公钥内容
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
private function getRsaContent()
{
$cacheKey = "pub_ras_key_" . $this->config->get('mch_id');
if (($pub_key = Tools::getCache($cacheKey))) {
return $pub_key;
}
$data = $this->callPostApi('https://fraud.mch.weixin.qq.com/risk/getpublickey', [], true, 'MD5');
if (!isset($data['return_code']) || $data['return_code'] !== 'SUCCESS' || $data['result_code'] !== 'SUCCESS') {
$error = 'ResultError:' . $data['return_msg'];
$error .= isset($data['err_code_des']) ? ' - ' . $data['err_code_des'] : '';
throw new InvalidResponseException($error, 20000, $data);
}
Tools::setCache($cacheKey, $data['pub_key'], 600);
return $data['pub_key'];
}
/**
* 查询企业付款到银行卡结果
* @param string $partnerTradeNo 商户订单号
* @return array 付款状态
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function query($partnerTradeNo)
{
$this->params->offsetUnset('appid');
$url = 'https://api.mch.weixin.qq.com/mmpaysptrans/query_bank';
return $this->callPostApi($url, ['partner_trade_no' => $partnerTradeNo], true, 'MD5', false);
}
}

View File

@ -1,66 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WePayV3;
use WeChat\Exceptions\InvalidResponseException;
use WePayV3\Contracts\BasicWePay;
use WePayV3\Contracts\DecryptAes;
/**
* 平台证书管理
* @package WePayV3
*/
class Cert extends BasicWePay
{
/**
* 自动配置平台证书
* @var bool
*/
protected $autoCert = false;
/**
* 下载并缓存平台证书
* @return void
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function download()
{
try {
$certs = [];
$result = $this->doRequest('GET', '/v3/certificates');
if (empty($result['data']) && !empty($result['message'])) {
throw new InvalidResponseException($result['message']);
}
$decrypt = new DecryptAes($this->config['mch_v3_key']);
foreach ($result['data'] as $vo) {
$certs[$vo['serial_no']] = [
'expire' => strtotime($vo['expire_time']),
'serial' => $vo['serial_no'],
'content' => $decrypt->decryptToString(
$vo['encrypt_certificate']['associated_data'],
$vo['encrypt_certificate']['nonce'],
$vo['encrypt_certificate']['ciphertext']
)
];
}
$this->tmpFile("{$this->config['mch_id']}_certs", $certs);
} catch (\Exception $exception) {
throw new InvalidResponseException($exception->getMessage(), $exception->getCode());
}
}
}

View File

@ -1,146 +0,0 @@
<?php
namespace WePayV3;
use WePayV3\Contracts\BasicWePay;
/**
* 消费者投诉 2.0
* @package WePayV3
*/
class Complaints extends BasicWePay
{
/**
* 查询投诉列表
* @param int $offset 分页起始
* @param int $limit 分页大小
* @param string $begin_date 开始日期YYYY-MM-DD
* @param string $end_date 结束日期YYYY-MM-DD
* @return array|string 投诉列表
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function complaintList($offset, $limit, $begin_date, $end_date)
{
$mchId = $this->config['mch_id'];
$pathinfo = "/v3/merchant-service/complaints-v2?limit={$limit}&offset={$offset}&begin_date={$begin_date}&end_date={$end_date}&complainted_mchid={$mchId}";
return $this->doRequest('GET', $pathinfo, '', true);
}
/**
* 查询投诉详情
* @param string $complaint_id 投诉单号
* @return array|string 投诉详情
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function complaintDetails($complaint_id)
{
$pathinfo = "/v3/merchant-service/complaints-v2/{$complaint_id}";
return $this->doRequest('GET', $pathinfo, '', true);
}
/**
* 查询投诉协商历史
* @param string $complaint_id 投诉单号
* @return array|string 协商记录
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function negotiationHistory($complaint_id)
{
$pathinfo = "/v3/merchant-service/complaints-v2/{$complaint_id}/negotiation-historys";
return $this->doRequest('GET', $pathinfo, '', true);
}
/**
* 创建投诉通知回调地址
* @param string $url 回调地址
* @return array|string
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function CreateComplaintsNotify($url)
{
return $this->doRequest('POST', '/v3/merchant-service/complaint-notifications', json_encode(['url' => $url], JSON_UNESCAPED_UNICODE), true);
}
/**
* 查询投诉通知回调地址
* @return array|string
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function queryComplaintsNotify()
{
return $this->doRequest('GET', '/v3/merchant-service/complaint-notifications', '', true);
}
/**
* 更新投诉通知回调地址
* @param string $url 回调地址
* @return array|string
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function updateComplaintsNotify($url)
{
return $this->doRequest('PUT', '/v3/merchant-service/complaint-notifications', json_encode(['url' => $url], JSON_UNESCAPED_UNICODE), true);
}
/**
* 删除投诉通知回调地址
* @return array|string
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function deleteComplaintsNotify()
{
return $this->doRequest('DELETE', '/v3/merchant-service/complaint-notifications', '', true);
}
/**
* 回复投诉
* @param string $complaint_id 投诉单号
* @param array $content 回复内容(含跳转链接、文本等)
* @return array|string
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function replyInfo($complaint_id, array $content)
{
$content['complainted_mchid'] = $this->config['mch_id'];
$pathinfo = "/v3/merchant-service/complaints-v2/{$complaint_id}/response";
return $this->doRequest('POST', $pathinfo, json_encode($content, JSON_UNESCAPED_UNICODE), true);
}
/**
* 标记投诉处理完成
* @param string $complaint_id 投诉单号
* @return array|string
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function completeComplaints($complaint_id)
{
$mchId = $this->config['mch_id'];
$pathinfo = "/v3/merchant-service/complaints-v2/{$complaint_id}/complete";
return $this->doRequest('POST', $pathinfo, json_encode(['complainted_mchid' => $mchId], JSON_UNESCAPED_UNICODE), true);
}
/**
* 下载投诉图片
* @param string $pathinfo 文件路径(接口返回的下载地址 path
* @return array|string
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function downLoadImg($pathinfo)
{
return $this->doRequest('GET', $pathinfo, '', true, false);
}
/**
* 上传投诉相关图片
* @param array $imginfo 图片上传参数(文件流对应的 media 字段等)
* @return array|string
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function uploadImg(array $imginfo)
{
return $this->doRequest('POST', '/v3/merchant-service/images/upload', json_encode($imginfo, JSON_UNESCAPED_UNICODE), true);
}
}

View File

@ -1,535 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WePayV3\Contracts;
use WeChat\Contracts\Tools;
use WeChat\Exceptions\InvalidArgumentException;
use WeChat\Exceptions\InvalidDecryptException;
use WeChat\Exceptions\InvalidResponseException;
use WePayV3\Cert;
/**
* 微信支付基础类
* @package WePayV3\Contracts
*/
abstract class BasicWePay
{
/**
* 实例对象静态缓存
* @var array
*/
protected static $cache = [];
/**
* 接口基础地址
* @var string
*/
protected $base = 'https://api.mch.weixin.qq.com';
/**
* 自动配置平台证书
* @var bool
*/
protected $autoCert = true;
/**
* 配置参数
* @var array
*/
protected $config = [
'appid' => '', // 微信绑定APPID需配置
'mch_id' => '', // 微信商户编号,需要配置
'mch_v3_key' => '', // 微信商户密钥,需要配置
'cert_serial' => '', // 商户证书序号,无需配置
'cert_public' => '', // 商户公钥内容,需要配置
'cert_private' => '', // 商户密钥内容,需要配置
'cert_package' => [], // 平台证书或支付证书配置
'mp_cert_serial' => '', // 平台证书序号,无需配置 ( 指定平台证书或支付公钥 )
'mp_cert_content' => '', // 平台证书内容,无需配置 ( 指定平台证书或支付公钥 )
];
/**
* BasicWePayV3 constructor.
* @param array $options [mch_id, mch_v3_key, cert_public, cert_private]
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function __construct(array $options = [])
{
if (empty($options['mch_id'])) {
throw new InvalidArgumentException("Missing Config -- [mch_id]");
}
if (empty($options['mch_v3_key'])) {
throw new InvalidArgumentException("Missing Config -- [mch_v3_key]");
}
if (empty($options['cert_public'])) {
throw new InvalidArgumentException("Missing Config -- [cert_public]");
}
if (empty($options['cert_private'])) {
throw new InvalidArgumentException("Missing Config -- [cert_private]");
}
if (stripos($options['cert_public'], '-----BEGIN CERTIFICATE-----') === false) {
if (file_exists($options['cert_public'])) {
$options['cert_public'] = file_get_contents($options['cert_public']);
} else {
throw new InvalidArgumentException("File Non-Existent -- [cert_public]");
}
}
if (stripos($options['cert_private'], '-----BEGIN PRIVATE KEY-----') === false) {
if (file_exists($options['cert_private'])) {
$options['cert_private'] = file_get_contents($options['cert_private']);
} else {
throw new InvalidArgumentException("File Non-Existent -- [cert_private]");
}
}
$this->config['appid'] = isset($options['appid']) ? $options['appid'] : '';
$this->config['mch_id'] = $options['mch_id'];
$this->config['mch_v3_key'] = $options['mch_v3_key'];
$this->config['cert_public'] = $options['cert_public'];
$this->config['cert_private'] = $options['cert_private'];
if (empty($options['cert_serial'])) {
$this->config['cert_serial'] = openssl_x509_parse($this->config['cert_public'], true)['serialNumberHex'];
} else {
$this->config['cert_serial'] = $options['cert_serial'];
}
if (empty($this->config['cert_serial'])) {
throw new InvalidArgumentException('Failed to parse certificate public key');
}
if (!empty($options['cache_path'])) {
Tools::$cache_path = $options['cache_path'];
}
// 批量设置自定义证书
if (isset($options['cert_package']) && is_array($options['cert_package'])) {
foreach ($options['cert_package'] as $key => $cert) {
$this->withCertContent($key, $cert);
}
}
// 自动配置平台证书或支付公钥
if (empty($options['mp_cert_serial']) || empty($options['mp_cert_content'])) {
if ($this->autoCert && !$this->withCertPayment()) {
$this->_autoCert();
}
} elseif ($this->withCertContent($options['mp_cert_serial'], $options['mp_cert_content'])) {
$this->config['mp_cert_serial'] = $options['mp_cert_serial'];
$this->config['mp_cert_content'] = $options['mp_cert_content'];
}
// 服务商参数支持
// if (!empty($options['sp_appid'])) {
// $this->config['sp_appid'] = $options['sp_appid'];
// }
// if (!empty($options['sp_mchid'])) {
// $this->config['sp_mchid'] = $options['sp_mchid'];
// }
// if (!empty($options['sub_appid'])) {
// $this->config['sub_appid'] = $options['sub_appid'];
// }
// if (!empty($options['sub_mch_id'])) {
// $this->config['sub_mch_id'] = $options['sub_mch_id'];
// }
}
/**
* 设置证书内容
* @param string $key 证书ID或序号
* @param string $cert 证书文本内容
* @return string
* @throws \WeChat\Exceptions\InvalidResponseException
*/
private function withCertContent($key, $cert)
{
if (substr(trim($cert), 0, 5) == '-----') {
$this->config['cert_package'][$key] = $cert;
} elseif (file_exists($cert)) {
$this->config['cert_package'][$key] = file_get_contents($cert);
} else {
throw new InvalidResponseException("证书设置失败!");
}
return $cert;
}
/**
* 获取支付证书
* @return mixed|string
*/
private function withCertPayment()
{
foreach ($this->config['cert_package'] as $key => $cert) {
if (strpos($key, 'PUB_KEY_ID_') === 0) {
if (empty($this->config['mp_cert_serial']) || empty($this->config['mp_cert_content'])) {
$this->config['mp_cert_serial'] = $key;
$this->config['mp_cert_content'] = $cert;
}
return $cert;
}
}
return '';
}
/**
* 自动配置平台证书
* @return void
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
protected function _autoCert()
{
$certs = $this->tmpFile("{$this->config['mch_id']}_certs");
if (is_array($certs)) foreach ($certs as $k => $v) {
if ($v['expire'] < time()) unset($certs[$k]);
}
if (empty($certs)) {
Cert::instance($this->config)->download();
$certs = $this->tmpFile("{$this->config['mch_id']}_certs");
}
if (empty($certs) || !is_array($certs)) {
throw new InvalidResponseException("读取平台证书失败!");
}
foreach ($certs as $k => $v) if ($v['expire'] > time() + 10) {
$this->config['cert_package'][$k] = $v['content'];
if (empty($this->config['mp_cert_serial'])) {
$this->config['mp_cert_serial'] = $k;
$this->config['mp_cert_content'] = $v['content'];
}
}
if (empty($this->config['cert_package'])) {
throw new InvalidResponseException("自动配置平台证书失败!");
}
}
/**
* 写入或读取临时文件
* @param string $name
* @param null|array|string $content
* @param integer $expire
* @return array|string
* @throws \WeChat\Exceptions\LocalCacheException
*/
protected function tmpFile($name, $content = null, $expire = 7200)
{
if (is_null($content)) {
$text = Tools::getCache($name);
if (empty($text)) return '';
$json = json_decode(Tools::getCache($name) ?: '', true);
return isset($json[0]) ? $json[0] : '';
} else {
return Tools::setCache($name, json_encode([$content], JSON_UNESCAPED_UNICODE), $expire);
}
}
/**
* 静态创建对象
* @param array $config
* @return static
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public static function instance($config)
{
$key = md5(get_called_class() . serialize($config));
if (isset(self::$cache[$key])) return self::$cache[$key];
return self::$cache[$key] = new static($config);
}
/**
* 模拟发起上传请求
* @param string $pathinfo 请求路由
* @param string $filename 文件本地路径
* @param boolean $verify 是否验证
* @param boolean $isjson 返回JSON
* @return array|string
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function doUpload($pathinfo, $filename, $verify = false, $isjson = true)
{
$filedata = file_get_contents($filename);
$fileinfo = [
'sha256' => hash("sha256", $filedata),
'filename' => basename($filename)
];
$jsondata = json_encode($fileinfo);
list($time, $nonce) = [time(), uniqid() . rand(1000, 9999)];
$signstr = join("\n", ['POST', $pathinfo, $time, $nonce, $jsondata, '']);
// 生成签名
$sign = $this->signBuild($signstr);
// 生成数据签名TOKEN
$token = sprintf('mchid="%s",nonce_str="%s",timestamp="%d",serial_no="%s",signature="%s"',
$this->config['mch_id'], $nonce, $time, $this->config['cert_serial'], $sign
);
$location = (preg_match('|^https?://|', $pathinfo) ? '' : $this->base) . $pathinfo;
$boundary = mt_rand(100000000000000000, 999999999999999999);
$header = [
'Accept: application/json',
"Content-Type: multipart/form-data; boundary={$boundary}",
'User-Agent: https://thinkadmin.top',
"Authorization: WECHATPAY2-SHA256-RSA2048 {$token}",
"serial_no: {$this->config['mp_cert_serial']}",
"nonce_str: {$nonce}",
"signature: {$sign}"
];
$line = [];
$line[] = "--{$boundary}";
$line[] = "Content-Disposition: form-data; name=\"meta\"";
$line[] = "Content-Type: application/json";
$line[] = "";
$line[] = $jsondata;
$line[] = "--{$boundary}";
$line[] = "Content-Disposition: form-data; name=\"file\"; filename=\"{$fileinfo['filename']}\";";
$line[] = "Content-Type: image/jpg";
$line[] = "";
$line[] = $filedata;
$line[] = "--{$boundary}--";
$postdata = join("\r\n", $line);
list($header, $content) = $this->_doRequestCurl('POST', $location, [
'data' => $postdata, 'header' => $header,
]);
if ($verify) {
$headers = [];
foreach (explode("\n", $header) as $line) {
if (stripos($line, 'Wechatpay') !== false) {
list($name, $value) = explode(':', $line);
list(, $keys) = explode('wechatpay-', strtolower($name));
$headers[$keys] = trim($value);
}
}
try {
if (empty($headers)) {
return $isjson ? json_decode($content, true) : $content;
}
$string = join("\n", [$headers['timestamp'], $headers['nonce'], $content, '']);
if (!$this->signVerify($string, $headers['signature'], $headers['serial'])) {
throw new InvalidResponseException('验证响应签名失败');
}
} catch (\Exception $exception) {
throw new InvalidResponseException($exception->getMessage(), $exception->getCode());
}
}
return $isjson ? json_decode($content, true) : $content;
}
/**
* 生成数据签名
* @param string $data 签名内容
* @return string
*/
protected function signBuild($data)
{
$pkeyid = openssl_pkey_get_private($this->config['cert_private']);
if ($pkeyid === false) {
throw new InvalidArgumentException("Invalid private key -- [cert_private]");
}
$signature = '';
if (!openssl_sign($data, $signature, $pkeyid, 'sha256WithRSAEncryption')) {
$this->freeKey($pkeyid);
throw new InvalidArgumentException("Failed to sign data with private key");
}
$this->freeKey($pkeyid);
return base64_encode($signature);
}
/**
* 兼容释放 OpenSSL 密钥资源
* @param mixed $pkey
* @return void
*/
protected function freeKey($pkey)
{
// PHP 8+ 中 openssl_free_key 已废弃,交由运行时回收即可。
if (version_compare(PHP_VERSION, '8.0.0', '<') && function_exists('openssl_free_key')) {
openssl_free_key($pkey);
}
}
/**
* 通过CURL模拟网络请求
* @param string $method 请求方法
* @param string $location 请求方法
* @param array $options 请求参数 [data, header]
* @return array [header,content]
*/
private function _doRequestCurl($method, $location, $options = [])
{
$curl = curl_init();
// POST数据设置
if (strtolower($method) === 'post') {
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $options['data']);
}
// CURL头信息设置
if (!empty($options['header'])) {
curl_setopt($curl, CURLOPT_HTTPHEADER, $options['header']);
}
curl_setopt($curl, CURLOPT_URL, $location);
curl_setopt($curl, CURLOPT_HEADER, true);
curl_setopt($curl, CURLOPT_TIMEOUT, 60);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
$content = curl_exec($curl);
$headerSize = curl_getinfo($curl, CURLINFO_HEADER_SIZE);
curl_close($curl);
return [substr($content, 0, $headerSize), substr($content, $headerSize)];
}
/**
* 验证内容签名
* @param string $data 签名内容
* @param string $sign 原签名值
* @param string $serial 证书序号
* @return int
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
protected function signVerify($data, $sign, $serial)
{
if (stripos($serial, 'PUB_KEY_ID_') !== false && !empty($this->config['cert_package'][$serial])) {
return openssl_verify($data, base64_decode($sign), $this->config['cert_package'][$serial], OPENSSL_ALGO_SHA256);
} else {
return openssl_verify($data, base64_decode($sign), openssl_x509_read($this->_getCert($serial)), 'sha256WithRSAEncryption');
}
}
/**
* 获取平台证书
* @param string $serial
* @return string
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
protected function _getCert($serial = '')
{
$certs = $this->tmpFile("{$this->config['mch_id']}_certs");
if (empty($certs) || empty($certs[$serial]['serial']) || empty($certs[$serial]['content'])) {
Cert::instance($this->config)->download();
$certs = $this->tmpFile("{$this->config['mch_id']}_certs");
}
foreach ($certs as $cert) {
if (!empty($cert['serial']) && !empty($cert['content']) && $cert['expire'] > time()) {
$this->config['cert_package'][$cert['serial']] = $cert['content'];
if (empty($this->config['mp_cert_serial']) && (empty($serial) || $serial === $cert['serial'])) {
$this->config['mp_cert_serial'] = $cert['serial'];
$this->config['mp_cert_content'] = $cert['content'];
}
}
}
if (isset($this->config['cert_package'][$serial])) {
return $this->config['cert_package'][$serial];
} elseif (!empty($this->config['mp_cert_content'])) {
return $this->config['mp_cert_content'];
} elseif ($cert = $this->withCertPayment()) {
return $cert;
} else {
throw new InvalidResponseException("读取平台证书失败!");
}
}
/**
* 通用接口调用(微信支付 V3
* @param string $url 完整 URL 或相对路径(如 /v3/pay/transactions/jsapi
* @param array|string $data 请求体,数组自动 JSON字符串原样发送
* @param string $method GET|POST|PUT|DELETE|PATCH|HEAD|OPTIONS默认 POST
* @param bool $verify 是否验证返回签名
* @return array 解析后的数组
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function callApi($url, $data = '', $method = 'POST', $verify = false)
{
$method = strtoupper($method);
// 处理数据
if (is_array($data)) {
$data = json_encode($data, JSON_UNESCAPED_UNICODE);
}
return $this->doRequest($method, $url, $data, $verify, true);
}
/**
* 模拟发起请求
* @param string $method 请求访问
* @param string $pathinfo 请求路由
* @param string $jsondata 请求数据
* @param boolean $verify 是否验证
* @param boolean $isjson 返回JSON
* @return array|string
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function doRequest($method, $pathinfo, $jsondata = '', $verify = false, $isjson = true)
{
list($time, $nonce) = [time(), uniqid() . rand(1000, 9999)];
$signstr = join("\n", [$method, $pathinfo, $time, $nonce, $jsondata, '']);
// 生成数据签名TOKEN
$token = sprintf('mchid="%s",nonce_str="%s",timestamp="%d",serial_no="%s",signature="%s"',
$this->config['mch_id'], $nonce, $time, $this->config['cert_serial'], $this->signBuild($signstr)
);
$location = (preg_match('|^https?://|', $pathinfo) ? '' : $this->base) . $pathinfo;
list($header, $content) = $this->_doRequestCurl($method, $location, [
'data' => $jsondata, 'header' => [
'Accept: application/json',
'Content-Type: application/json',
'User-Agent: https://thinkadmin.top',
"Authorization: WECHATPAY2-SHA256-RSA2048 {$token}",
"Wechatpay-Serial: {$this->config['mp_cert_serial']}"
],
]);
if ($verify) {
$headers = [];
foreach (explode("\n", $header) as $line) {
if (stripos($line, 'Wechatpay') !== false) {
list($name, $value) = explode(':', $line);
list(, $keys) = explode('wechatpay-', strtolower($name));
$headers[$keys] = trim($value);
}
}
try {
if (empty($headers)) {
return $isjson ? json_decode($content, true) : $content;
}
$string = join("\n", [$headers['timestamp'], $headers['nonce'], $content, '']);
if (!$this->signVerify($string, $headers['signature'], $headers['serial'])) {
throw new InvalidResponseException('验证响应签名失败');
}
} catch (\Exception $exception) {
throw new InvalidResponseException($exception->getMessage(), $exception->getCode());
}
}
return $isjson ? json_decode($content, true) : $content;
}
/**
* RSA加密处理-平台证书
* @param string $string
* @return string
* @throws \WeChat\Exceptions\InvalidDecryptException
*/
protected function rsaEncode($string)
{
$publicKey = $this->config['mp_cert_content'];
if (openssl_public_encrypt($string, $encrypted, $publicKey, OPENSSL_PKCS1_OAEP_PADDING)) {
return base64_encode($encrypted);
} else {
throw new InvalidDecryptException('Rsa Encrypt Error.');
}
}
}

View File

@ -1,81 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WePayV3\Contracts;
use WeChat\Exceptions\InvalidArgumentException;
use WeChat\Exceptions\InvalidDecryptException;
/**
* Aes 解密工具类
* @package WePayV3\Contracts
*/
class DecryptAes
{
const KEY_LENGTH_BYTE = 32;
const AUTH_TAG_LENGTH_BYTE = 16;
private $aesKey;
/**
* Constructor
* @param string $aesKey
*/
public function __construct($aesKey)
{
if (strlen($aesKey) != self::KEY_LENGTH_BYTE) {
throw new InvalidArgumentException('无效的ApiV3Key长度应为32个字节');
}
$this->aesKey = $aesKey;
}
/**
* Decrypt AEAD_AES_256_GCM ciphertext
* @param string $associatedData AES GCM additional authentication data
* @param string $nonceStr AES GCM nonce
* @param string $ciphertext AES GCM cipher text
* @return string|bool Decrypted string on success or FALSE on failure
* @throws \WeChat\Exceptions\InvalidDecryptException
*/
public function decryptToString($associatedData, $nonceStr, $ciphertext)
{
$ciphertext = \base64_decode($ciphertext);
if (strlen($ciphertext) <= self::AUTH_TAG_LENGTH_BYTE) {
return false;
}
try {
// ext-sodium (default installed on >= PHP 7.2)
if (function_exists('\sodium_crypto_aead_aes256gcm_is_available') && \sodium_crypto_aead_aes256gcm_is_available()) {
return \sodium_crypto_aead_aes256gcm_decrypt($ciphertext, $associatedData, $nonceStr, $this->aesKey);
}
// ext-libsodium (need install libsodium-php 1.x via pecl)
if (function_exists('\Sodium\crypto_aead_aes256gcm_is_available') && \Sodium\crypto_aead_aes256gcm_is_available()) {
return \Sodium\crypto_aead_aes256gcm_decrypt($ciphertext, $associatedData, $nonceStr, $this->aesKey);
}
// openssl (PHP >= 7.1 support AEAD)
if (PHP_VERSION_ID >= 70100 && in_array('aes-256-gcm', \openssl_get_cipher_methods())) {
$ctext = substr($ciphertext, 0, -self::AUTH_TAG_LENGTH_BYTE);
$authTag = substr($ciphertext, -self::AUTH_TAG_LENGTH_BYTE);
return \openssl_decrypt($ctext, 'aes-256-gcm', $this->aesKey, \OPENSSL_RAW_DATA, $nonceStr, $authTag, $associatedData);
}
} catch (\Exception $exception) {
throw new InvalidDecryptException($exception->getMessage(), $exception->getCode());
} catch (\SodiumException $exception) {
throw new InvalidDecryptException($exception->getMessage(), $exception->getCode());
}
throw new InvalidDecryptException('AEAD_AES_256_GCM 需要 PHP 7.1 以上或者安装 libsodium-php');
}
}

View File

@ -1,155 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WePayV3;
use WeChat\Exceptions\InvalidResponseException;
use WePayV3\Contracts\BasicWePay;
/**
* 微信支付代金券 (V3)
* @package WePayV3
*/
class Coupon extends BasicWePay
{
/**
* 创建代金券批次
* @param array $data 批次参数stock_name, belong_merchant 等)
* @return array|string
* @throws InvalidResponseException
*/
public function stocksCreate(array $data)
{
$path = "/v3/marketing/favor/coupon-stocks";
return $this->doRequest('POST', $path, json_encode($data), true);
}
/**
* 激活代金券批次
* @param string $stock_id 批次号
* @param string $stock_creator_mchid 创建批次的商户号
* @return array|string
* @throws InvalidResponseException
*/
public function stocksStart($stock_id, $stock_creator_mchid)
{
$path = "/v3/marketing/favor/stocks/{$stock_id}/start";
return $this->doRequest('POST', $path, json_encode(['stock_creator_mchid' => $stock_creator_mchid]), true);
}
/**
* 暂停代金券批次
* @param string $stock_id 批次号
* @param string $stock_creator_mchid 创建批次的商户号
* @return array|string
* @throws InvalidResponseException
*/
public function stocksPause($stock_id, $stock_creator_mchid)
{
$path = "/v3/marketing/favor/stocks/{$stock_id}/pause";
return $this->doRequest('POST', $path, json_encode(['stock_creator_mchid' => $stock_creator_mchid]), true);
}
/**
* 重启代金券批次
* @param string $stock_id 批次号
* @param string $stock_creator_mchid 创建批次的商户号
* @return array|string
* @throws InvalidResponseException
*/
public function stocksRestart($stock_id, $stock_creator_mchid)
{
$path = "/v3/marketing/favor/stocks/{$stock_id}/restart";
return $this->doRequest('POST', $path, json_encode(['stock_creator_mchid' => $stock_creator_mchid]), true);
}
/**
* 查询批次详情
* @param string $stock_id 批次号
* @param string $stock_creator_mchid 创建批次的商户号
* @return array|string 批次详情
* @throws InvalidResponseException
*/
public function stocksDetail($stock_id, $stock_creator_mchid)
{
$path = "/v3/marketing/favor/stocks/{$stock_id}?stock_creator_mchid={$stock_creator_mchid}";
return $this->doRequest('GET', $path, '', true);
}
/**
* 代金券批次可用商品
* @param array $param 包含 stock_id
* @return array|string
* @throws InvalidResponseException
*/
public function stocksItems(array $param)
{
$path = "/v3/marketing/favor/stocks/{$param['stock_id']}/items ";
return $this->doRequest('POST', $path, json_encode($param), true);
}
/**
* 设置消息通知地址
* @param array $param 回调参数notify_url, switch 等)
* @return array|string
* @throws InvalidResponseException
*/
public function setCallbacks(array $param)
{
$path = "/v3/marketing/favor/callbacks";
return $this->doRequest('POST', $path, json_encode($param), true);
}
/**
* 发放代金券
* @param array $param 请求参数openid, stock_id 等)
* @return array|string
* @throws InvalidResponseException
*/
public function couponsSend(array $param)
{
$path = "/v3/marketing/favor/users/{$param['openid']}/coupons";
return $this->doRequest('POST', $path, json_encode($param), true);
}
/**
* 查询用户名下券(按商户号)
* @param array $param 请求参数openid, appid, stock_id 等)
* @return array|string 券列表
* @throws InvalidResponseException
*/
public function couponsList(array $param)
{
$path = "/v3/marketing/favor/users/{$param['openid']}/coupons";
return $this->doRequest('POST', $path, json_encode($param), true);
}
/**
* 查询单张代金券详情
* @param string $openid 用户 openid
* @param string $coupon_id 代金券 id
* @param string $appid 公众账号或小程序 appid
* @return array|string
* @throws InvalidResponseException
*/
public function couponsDetail($openid, $coupon_id, $appid)
{
$path = "/v3/marketing/favor/users/{$openid}/coupons/{$coupon_id}?appid={$appid}";
return $this->doRequest('GET', $path, '', true);
}
}

View File

@ -1,775 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WePayV3;
use WeChat\Contracts\Tools;
use WePayV3\Contracts\BasicWePay;
/**
* 收付通(特约/二级商户、合单、分账等)
* @package WePayV3
*/
class Ecommerce extends BasicWePay
{
/**
* 提交进件申请
* @param array $data 进件参数(含证件、账户、联系人,敏感字段自动 RSA
* @return array
* @throws \WeChat\Exceptions\InvalidDecryptException
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function ecommerceApplyments($data)
{
if (isset($data['id_card_info'])) {
if (isset($data['id_card_info']['id_card_name'])) $data['id_card_info']['id_card_name'] = $this->rsaEncode($data['id_card_info']['id_card_name']);
if (isset($data['id_card_info']['id_card_number'])) $data['id_card_info']['id_card_number'] = $this->rsaEncode($data['id_card_info']['id_card_number']);
}
if (isset($data['id_doc_info'])) {
if (isset($data['id_doc_info']['id_doc_name'])) $data['id_doc_info']['id_doc_name'] = $this->rsaEncode($data['id_doc_info']['id_doc_name']);
if (isset($data['id_doc_info']['id_doc_number'])) $data['id_doc_info']['id_doc_number'] = $this->rsaEncode($data['id_doc_info']['id_doc_number']);
}
if (isset($data['contact_info'])) {
if (isset($data['contact_info']['contact_name'])) $data['contact_info']['contact_name'] = $this->rsaEncode($data['contact_info']['contact_name']);
if (isset($data['contact_info']['contact_id_card_number'])) $data['contact_info']['contact_id_card_number'] = $this->rsaEncode($data['contact_info']['contact_id_card_number']);
if (isset($data['contact_info']['mobile_phone'])) $data['contact_info']['mobile_phone'] = $this->rsaEncode($data['contact_info']['mobile_phone']);
}
if (isset($data['account_info'])) {
if (isset($data['account_info']['account_name'])) $data['account_info']['account_name'] = $this->rsaEncode($data['account_info']['account_name']);
if (isset($data['account_info']['account_number'])) $data['account_info']['account_number'] = $this->rsaEncode($data['account_info']['account_number']);
}
if (!empty($data['ubo_info_list'])) {
$data['ubo_info_list'] = array_map(function ($item) {
$item['ubo_id_doc_name'] = $this->rsaEncode($item['ubo_id_doc_name']);
$item['ubo_id_doc_number'] = $this->rsaEncode($item['ubo_id_doc_number']);
$item['ubo_id_doc_address'] = $this->rsaEncode($item['ubo_id_doc_address']);
return $item;
}, $data['ubo_info_list']);
}
return $this->doRequest('POST', '/v3/ecommerce/applyments/', json_encode($data, JSON_UNESCAPED_UNICODE), true);
}
/**
* 按业务申请编号查询进件状态
* @param string $out_request_no 业务申请编号
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function ecommerceApplymentsByRequestNo($out_request_no)
{
$pathinfo = "/v3/ecommerce/applyments/out-request-no/{$out_request_no}";
return $this->doRequest('GET', $pathinfo, '', true);
}
/**
* 按申请单 ID 查询进件状态
* @param string $applyment_id 微信支付申请单号
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function ecommerceApplymentsByApplymentId($applyment_id)
{
$pathinfo = "/v3/ecommerce/applyments/{$applyment_id}";
return $this->doRequest('GET', $pathinfo, '', true);
}
/**
* 修改结算账户
* @param string $sub_mchid 特约/二级商户号
* @param array $data 账户参数(敏感字段需 RSA
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function modifySettlement($sub_mchid, $data)
{
$pathinfo = "/v3/apply4sub/sub_merchants/{$sub_mchid}/modify-settlement";
return $this->doRequest('POST', $pathinfo, json_encode($data, JSON_UNESCAPED_UNICODE), true);
}
/**
* 查询结算账户修改状态
* @param string $sub_mchid 特约/二级商户号
* @param string $application_no 修改结算账户申请单号
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function modifySettlementResult($sub_mchid, $application_no)
{
$pathinfo = "/v3/apply4sub/sub_merchants/{$sub_mchid}/application/{$application_no}";
return $this->doRequest('GET', $pathinfo, '', true);
}
/**
* 查询结算账户
* @param string $sub_mchid 特约/二级商户号
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function getSettlement($sub_mchid)
{
$pathinfo = "/v3/apply4sub/sub_merchants/{$sub_mchid}/settlement";
return $this->doRequest('GET', $pathinfo, '', true);
}
/**
* 上传进件所需图片/文件
* @param string $filename 本地文件路径
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function mediaUpload($filename)
{
return $this->doUpload('/v3/merchant/media/upload', $filename, true);
}
/**
* 合作方 APP 下单
* @param array $data 下单参数sp_mchid, sub_mchid, description, out_trade_no, notify_url 等)
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function transactionsApp($data)
{
$pathinfo = "/v3/pay/partner/transactions/app";
return $this->doRequest('POST', $pathinfo, json_encode($data, JSON_UNESCAPED_UNICODE), true);
}
/**
* 合作方 JSAPI 下单
* @param array $data 下单参数(含 payer.openid 等)
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function transactionsJsapi($data)
{
$pathinfo = "/v3/pay/partner/transactions/jsapi";
return $this->doRequest('POST', $pathinfo, json_encode($data, JSON_UNESCAPED_UNICODE), true);
}
/**
* 合作方 Native 下单
* @param array $data 下单参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function transactionsNative($data)
{
$pathinfo = "/v3/pay/partner/transactions/native";
return $this->doRequest('POST', $pathinfo, json_encode($data, JSON_UNESCAPED_UNICODE), true);
}
/**
* 合作方 H5 下单
* @param array $data 下单参数(含 scene_info 等)
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function transactionsH5($data)
{
$pathinfo = "/v3/pay/partner/transactions/h5";
return $this->doRequest('POST', $pathinfo, json_encode($data, JSON_UNESCAPED_UNICODE), true);
}
/**
* 订单查询(按微信交易号)
* @param string $transaction_id 微信订单号
* @param string $sub_mchid 二级商户号
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function getTransactionsById($transaction_id, $sub_mchid)
{
$pathinfo = "/v3/pay/partner/transactions/id/{$transaction_id}";
$pathinfo = $pathinfo . "?sp_mchid={$this->config['mch_id']}&sub_mchid={$sub_mchid}";
return $this->doRequest('GET', $pathinfo, '', true);
}
/**
* 订单查询(按商户订单号)
* @param string $out_trade_no 商户订单号
* @param string $sub_mchid 二级商户号
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function getTransactionsByTradeNo($out_trade_no, $sub_mchid)
{
$pathinfo = "/v3/pay/partner/transactions/out-trade-no/{$out_trade_no}";
$pathinfo = $pathinfo . "?sp_mchid={$this->config['mch_id']}&sub_mchid={$sub_mchid}";
return $this->doRequest('GET', $pathinfo, '', true);
}
/**
* 关闭订单
* @param string $out_trade_no 商户订单号
* @param array $data 包含 sub_mchid
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function transactionsClose($out_trade_no, $data)
{
$pathinfo = "/v3/pay/partner/transactions/out-trade-no/{$out_trade_no}/close";
return $this->doRequest('POST', $pathinfo, json_encode($data, JSON_UNESCAPED_UNICODE), true);
}
/**
* 合单 JSAPI 下单
* @param array $data 合单参数combine_out_trade_no, sub_orders 等)
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function combineTransactionsJsapi($data)
{
$pathinfo = "/v3/combine-transactions/jsapi";
return $this->doRequest('POST', $pathinfo, json_encode($data, JSON_UNESCAPED_UNICODE), true);
}
/**
* 合单 APP 下单
* @param array $data 合单参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function combineTransactionsApp($data)
{
$pathinfo = "/v3/combine-transactions/app";
return $this->doRequest('POST', $pathinfo, json_encode($data, JSON_UNESCAPED_UNICODE), true);
}
/**
* 合单 H5 下单
* @param array $data 合单参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function combineTransactionsH5($data)
{
$pathinfo = "/v3/combine-transactions/h5";
return $this->doRequest('POST', $pathinfo, json_encode($data, JSON_UNESCAPED_UNICODE), true);
}
/**
* 合单 Native 下单
* @param array $data 合单参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function combineTransactionsNative($data)
{
$pathinfo = "/v3/combine-transactions/native";
return $this->doRequest('POST', $pathinfo, json_encode($data, JSON_UNESCAPED_UNICODE), true);
}
/**
* 合单查询
* @param string $combine_out_trade_no 合单商户订单号
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function getCombineTransactionsByTradeNo($combine_out_trade_no)
{
$pathinfo = "/v3/combine-transactions/out-trade-no/{$combine_out_trade_no}";
return $this->doRequest('GET', $pathinfo, '', true);
}
/**
* 合单关单
* @param string $combine_out_trade_no 合单商户订单号
* @param array $data 包含 sub_orders
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function combineTransactionsClose($combine_out_trade_no, $data)
{
$pathinfo = "/v3/combine-transactions/out-trade-no/{$combine_out_trade_no}/close";
return $this->doRequest('POST', $pathinfo, json_encode($data, JSON_UNESCAPED_UNICODE), true);
}
/**
* 电商平台发起分账
* @param array $data 分账参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function profitsharingOrders($data)
{
$pathinfo = "/v3/ecommerce/profitsharing/orders";
return $this->doRequest('POST', $pathinfo, json_encode($data, JSON_UNESCAPED_UNICODE), true);
}
/**
* 查询分账结果
* @param array $param 查询参数sub_mchid, transaction_id, out_order_no 等)
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function queryProfitsharingOrders($param = [])
{
$pathinfo = "/v3/ecommerce/profitsharing/orders?" . http_build_query($param);
return $this->doRequest('GET', $pathinfo, '', true);
}
/**
* 请求分账回退
* @param array $data 回退参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function profitsharingReturnOrders($data)
{
$pathinfo = "/v3/ecommerce/profitsharing/returnorders";
return $this->doRequest('POST', $pathinfo, json_encode($data, JSON_UNESCAPED_UNICODE), true);
}
/**
* 查询分账回退结果
* @param array $param 查询参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function queryProfitsharingReturnOrders($param = [])
{
$pathinfo = "/v3/ecommerce/profitsharing/returnorders?" . http_build_query($param);
return $this->doRequest('GET', $pathinfo, '', true);
}
/**
* 完结分账
* @param array $data 完结参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function profitsharingFinishOrder($data)
{
$pathinfo = "/v3/ecommerce/profitsharing/finish-order";
return $this->doRequest('POST', $pathinfo, json_encode($data, JSON_UNESCAPED_UNICODE), true);
}
/**
* 查询订单待分金额
* @param string $transaction_id 微信订单号
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function profitsharingReturnOrdersAmounts($transaction_id)
{
$pathinfo = "/v3/ecommerce/profitsharing/orders/{$transaction_id}/amounts";
return $this->doRequest('GET', $pathinfo, '', true);
}
/**
* 添加分账接收方
* @param array $data 接收方参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function profitsharingReceiversAdd($data)
{
$pathinfo = "/v3/ecommerce/profitsharing/receivers/add";
return $this->doRequest('POST', $pathinfo, json_encode($data, JSON_UNESCAPED_UNICODE), true);
}
/**
* 删除分账接收方
* @param array $data 接收方参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function profitsharingReceiversDelete($data)
{
$pathinfo = "/v3/ecommerce/profitsharing/receivers/delete";
return $this->doRequest('POST', $pathinfo, json_encode($data, JSON_UNESCAPED_UNICODE), true);
}
/**
* 请求补差
* @param array $data 补差参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function subsidiesCreate($data)
{
$pathinfo = "/v3/ecommerce/subsidies/create";
return $this->doRequest('POST', $pathinfo, json_encode($data, JSON_UNESCAPED_UNICODE), true);
}
/**
* 补差回退
* @param array $data 回退参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function subsidiesReturn($data)
{
$pathinfo = "/v3/ecommerce/subsidies/return";
return $this->doRequest('POST', $pathinfo, json_encode($data, JSON_UNESCAPED_UNICODE), true);
}
/**
* 取消补差
* @param array $data 取消参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function subsidiesCancel($data)
{
$pathinfo = "/v3/ecommerce/subsidies/cancel";
return $this->doRequest('POST', $pathinfo, json_encode($data, JSON_UNESCAPED_UNICODE), true);
}
/**
* 申请退款
* @param array $data 退款参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function refundsApply($data)
{
$pathinfo = "/v3/ecommerce/refunds/apply";
return $this->doRequest('POST', $pathinfo, json_encode($data, JSON_UNESCAPED_UNICODE), true);
}
/**
* 查询单笔退款(按微信退款号)
* @param string $refund_id 微信退款号
* @param string $sub_mchid 二级商户号
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function queryRefundsById($refund_id, $sub_mchid)
{
$pathinfo = "/v3/ecommerce/refunds/id/{$refund_id}?sub_mchid={$$sub_mchid}";
return $this->doRequest('GET', $pathinfo, '', true);
}
/**
* 查询单笔退款(按商户退款号)
* @param string $out_refund_no 商户退款单号
* @param string $sub_mchid 二级商户号
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function queryRefundsByNo($out_refund_no, $sub_mchid)
{
$pathinfo = "/v3/ecommerce/refunds/out-refund-no/{$out_refund_no}?sub_mchid={$sub_mchid}";
return $this->doRequest('GET', $pathinfo, '', true);
}
/**
* 查询垫付回补结果
* @param string $refund_id 微信退款号
* @param string $sub_mchid 二级商户号
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function queryRefundsReturnAdvance($refund_id, $sub_mchid)
{
$pathinfo = "/v3/ecommerce/refunds/{$refund_id}/return-advance?sub_mchid={$sub_mchid}";
return $this->doRequest('GET', $pathinfo, '', true);
}
/**
* 垫付退款回补
* @param string $refund_id 微信退款号
* @param array $data 回补参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function refundsReturnAdvance($refund_id, $data)
{
$pathinfo = "/v3/ecommerce/refunds/{$refund_id}/return-advance";
return $this->doRequest('POST', $pathinfo, json_encode($data, JSON_UNESCAPED_UNICODE), true);
}
/**
* 查询二级商户账户实时余额API(余额查询)
* @param string $sub_mchid
* @param string $account_type 二级商户账户类型 BASIC: 基本账户 FEES: 手续费账户 OPERATION: 运营账户 DEPOSIT: 保证金账户
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function fundBalance($sub_mchid, $account_type = 'BASIC')
{
$pathinfo = "/v3/ecommerce/fund/balance/{$sub_mchid}?account_type={$account_type}";
return $this->doRequest('GET', $pathinfo, '', true);
}
/**
* 查询二级商户账户日终余额API(余额查询)
* @param string $sub_mchid
* @param array $query
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function fundEnddayBalance($sub_mchid, $query)
{
$pathinfo = "/v3/ecommerce/fund/enddaybalance/{$sub_mchid}?" . http_build_query($query);
return $this->doRequest('GET', $pathinfo, '', true);
}
/**
* 查询收付通平台账户实时余额API(余额查询)
* @param string $account_type
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function merchantFundBalance($account_type)
{
$pathinfo = "/v3/merchant/fund/balance/{$account_type}";
return $this->doRequest('GET', $pathinfo, '', true);
}
/**
* 查询收付通平台账户日终余额API(余额查询)
* @param string $account_type
* @param array $query
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function merchantEnddayBalance($account_type, $query)
{
$pathinfo = "/v3/merchant/fund/enddaybalance/{$account_type}?" . http_build_query($query);
return $this->doRequest('GET', $pathinfo, '', true);
}
/**
* 二级商户预约提现(商户提现)
* @param array $data POST请求参数
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function fundWithdraw($data)
{
$pathinfo = "/v3/ecommerce/fund/withdraw";
return $this->doRequest('POST', $pathinfo, json_encode($data, JSON_UNESCAPED_UNICODE), true);
}
/**
* 二级商户查询预约提现状态(根据商户预约提现单号查询)(商户提现)
* @param string $out_request_no
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function queryFundWithdrawByNo($out_request_no)
{
$pathinfo = "/v3/ecommerce/fund/withdraw/out-request-no/{$out_request_no}";
return $this->doRequest('GET', $pathinfo, '', true);
}
/**
* 二级商户查询预约提现状态(根据微信支付预约提现单号查询)(商户提现)
* @param string $withdraw_id
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function queryFundWithdrawById($withdraw_id)
{
$pathinfo = "/v3/ecommerce/fund/withdraw/{$withdraw_id}";
return $this->doRequest('GET', $pathinfo, '', true);
}
/**
* 收付通平台预约提现(商户提现)
* @param array $data
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function merchantFundWithdraw($data)
{
$pathinfo = "/v3/merchant/fund/withdraw";
return $this->doRequest('POST', $pathinfo, json_encode($data, JSON_UNESCAPED_UNICODE), true);
}
/**
* 收付通平台查询预约提现状态(根据商户预约提现单号查询)(商户提现)
* @param string $out_request_no
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function queryMerchantFundWithdrawByNo($out_request_no)
{
$pathinfo = "/v3/merchant/fund/withdraw/out-request-no/{$out_request_no}";
return $this->doRequest('GET', $pathinfo, '', true);
}
/**
* 收付通平台查询预约提现状态(根据微信支付预约提现单号查询)(商户提现)
* @param string $withdraw_id
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function queryMerchantFundWithdrawById($withdraw_id)
{
$pathinfo = "/v3/merchant/fund/withdraw/withdraw-id/{$withdraw_id}";
return $this->doRequest('GET', $pathinfo, '', true);
}
/**
* 按日下载提现异常文件(商户提现)
* @param $bill_type
* @param array $param
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function fundWithdrawBill($bill_type, $param = [])
{
$pathinfo = "/v3/merchant/fund/withdraw/bill-type/{$bill_type}?" . http_build_query($param);
return $this->doRequest('GET', $pathinfo, '', true);
}
/**
* 申请交易账单(下载账单)
* @param $bill_type
* @param array $param
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function tradeBill($bill_type, $param = [])
{
$pathinfo = "/v3/bill/tradebill?" . http_build_query($param);
return $this->doRequest('GET', $pathinfo, '', true);
}
/**
* 申请资金账单(下载账单)
* @param $bill_type
* @param array $param
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function fundFlowBill($bill_type, $param = [])
{
$pathinfo = "/v3/bill/fundflowbill?" . http_build_query($param);
return $this->doRequest('GET', $pathinfo, '', true);
}
/**
* 申请分账账单(下载账单)
* @param string $bill_type
* @param array $param
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function profitsharingBill($bill_type, $param = [])
{
$pathinfo = "/v3/profitsharing/bills?" . http_build_query($param);
return $this->doRequest('GET', $pathinfo, '', true);
}
/**
* 申请二级商户资金账单(下载账单)
* @param string $bill_type
* @param array $param
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function subFundFlowBill($bill_type, $param = [])
{
$pathinfo = "/v3/ecommerce/bill/fundflowbill?" . http_build_query($param);
return $this->doRequest('GET', $pathinfo, '', true);
}
/**
* 查询支持个人业务的银行列表
* @param int $offset
* @param int $limit
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function personalBanking($offset, $limit)
{
$pathinfo = "/v3/capital/capitallhh/banks/personal-banking?" . http_build_query(['offset' => $offset, 'limit' => $limit]);
return $this->doRequest('GET', $pathinfo, '', true);
}
/**
* 查询省份列表
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function provinces()
{
$pathinfo = "/v3/capital/capitallhh/areas/provinces";
return $this->doRequest('GET', $pathinfo, '', true);
}
/**
* 查询城市列表
* @param int $code
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function cities($code)
{
$pathinfo = "/v3/capital/capitallhh/areas/provinces/{$code}/cities";
return $this->doRequest('GET', $pathinfo, '', true);
}
/**
* 查询支行列表
* @param int $code
* @param $city
* @param $offset
* @param $limit
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function branches($code, $city, $offset, $limit)
{
$pathinfo = "/v3/capital/capitallhh/banks/{$code}/branches?" . http_build_query(['city_code' => $city, 'offset' => $offset, 'limit' => $limit]);
return $this->doRequest('GET', $pathinfo, '', true);
}
/**
* 查询支持对公业务的银行列表
* @param int $offset
* @param int $limit
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function corporateBanking($offset, $limit)
{
$pathinfo = "/v3/capital/capitallhh/banks/corporate-banking?" . http_build_query(['offset' => $offset, 'limit' => $limit]);
return $this->doRequest('GET', $pathinfo, '', true);
}
/**
* 通过支付预订单ID获取支付参数
* @param string $prepay_id 支付预订单ID
* @param string $type 类型
* @return array
*/
public function getJsApiParameters($prepay_id, $type = 'jsapi')
{
// 支付参数签名
$time = strval(time());
$appid = $this->config['appid'];
$nonceStr = Tools::createNoncestr();
if ($type === Order::WXPAY_APP) {
$sign = $this->signBuild(join("\n", [$appid, $time, $nonceStr, $prepay_id, '']));
return ['partnerId' => $this->config['mch_id'], 'prepayId' => $prepay_id, 'package' => 'Sign=WXPay', 'nonceStr' => $nonceStr, 'timeStamp' => $time, 'sign' => $sign];
} elseif ($type === Order::WXPAY_JSAPI) {
$sign = $this->signBuild(join("\n", [$appid, $time, $nonceStr, "prepay_id={$prepay_id}", '']));
return ['appId' => $appid, 'timestamp' => $time, 'timeStamp' => $time, 'nonceStr' => $nonceStr, 'package' => "prepay_id={$prepay_id}", 'signType' => 'RSA', 'paySign' => $sign];
} else {
return [];
}
}
}

View File

@ -1,208 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WePayV3;
use WeChat\Contracts\Tools;
use WeChat\Exceptions\InvalidArgumentException;
use WeChat\Exceptions\InvalidResponseException;
use WePayV3\Contracts\BasicWePay;
use WePayV3\Contracts\DecryptAes;
/**
* 直连商户 | 订单支付接口
* @package WePayV3
*/
class Order extends BasicWePay
{
const WXPAY_H5 = 'h5';
const WXPAY_APP = 'app';
const WXPAY_JSAPI = 'jsapi';
const WXPAY_NATIVE = 'native';
/**
* 创建支付订单V3
* @param string $type 支付类型 h5|app|jsapi|native
* @param array $data 支付参数按各场景必填appid, mchid, description, out_trade_no, notify_url 等)
* @return array 预支付结果或前端调起参数
* @throws \WeChat\Exceptions\InvalidResponseException
* @document https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_1.shtml
*/
public function create($type, $data)
{
$types = [
'h5' => '/v3/pay/transactions/h5',
'app' => '/v3/pay/transactions/app',
'jsapi' => '/v3/pay/transactions/jsapi',
'native' => '/v3/pay/transactions/native',
];
if (empty($types[$type])) {
throw new InvalidArgumentException("Payment {$type} not defined.");
} else {
// 自动填充 mchid 和 appid如果未提供
if (empty($data['mchid']) && !empty($this->config['mch_id'])) {
$data['mchid'] = $this->config['mch_id'];
}
if (empty($data['appid']) && !empty($this->config['appid'])) {
$data['appid'] = $this->config['appid'];
}
// 创建预支付码
$result = $this->doRequest('POST', $types[$type], json_encode($data, JSON_UNESCAPED_UNICODE), true);
if (empty($result['h5_url']) && empty($result['code_url']) && empty($result['prepay_id'])) {
$message = isset($result['code']) ? "[ {$result['code']} ] " : '';
$message .= isset($result['message']) ? $result['message'] : json_encode($result, JSON_UNESCAPED_UNICODE);
throw new InvalidResponseException($message);
}
// 支付参数签名
$time = strval(time());
$appid = $this->config['appid'];
$nonceStr = Tools::createNoncestr();
if ($type === self::WXPAY_APP) {
$sign = $this->signBuild(join("\n", [$appid, $time, $nonceStr, $result['prepay_id'], '']));
return ['appId' => $appid, 'partnerId' => $this->config['mch_id'], 'prepayId' => $result['prepay_id'], 'package' => 'Sign=WXPay', 'nonceStr' => $nonceStr, 'timeStamp' => $time, 'sign' => $sign];
} elseif ($type === self::WXPAY_JSAPI) {
$sign = $this->signBuild(join("\n", [$appid, $time, $nonceStr, "prepay_id={$result['prepay_id']}", '']));
return ['appId' => $appid, 'timestamp' => $time, 'timeStamp' => $time, 'nonceStr' => $nonceStr, 'package' => "prepay_id={$result['prepay_id']}", 'signType' => 'RSA', 'paySign' => $sign];
} else {
return $result;
}
}
}
/**
* 支付订单查询
* @param string $tradeNo 商户订单号 out_trade_no
* @return array 订单详情
* @throws \WeChat\Exceptions\InvalidResponseException
* @document https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_2.shtml
*/
public function query($tradeNo)
{
$pathinfo = "/v3/pay/transactions/out-trade-no/{$tradeNo}";
return $this->doRequest('GET', "{$pathinfo}?mchid={$this->config['mch_id']}", '', true);
}
/**
* 关闭支付订单
* @param string $tradeNo 商户订单号 out_trade_no
* @return array 关闭结果
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function close($tradeNo)
{
$data = ['mchid' => $this->config['mch_id']];
$path = "/v3/pay/transactions/out-trade-no/{$tradeNo}/close";
return $this->doRequest('POST', $path, json_encode($data, JSON_UNESCAPED_UNICODE), true);
}
/**
* 创建退款订单V3
* @param array $data 退款参数out_trade_no transaction_idout_refund_noamount 等)
* @return array 退款结果
* @throws \WeChat\Exceptions\InvalidResponseException
* @document https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_9.shtml
*/
public function createRefund($data)
{
$path = '/v3/refund/domestic/refunds';
return $this->doRequest('POST', $path, json_encode($data, JSON_UNESCAPED_UNICODE), true);
}
/**
* 退款订单查询
* @param string $refundNo 商户退款单号 out_refund_no
* @return array 退款详情
* @throws \WeChat\Exceptions\InvalidResponseException
* @document https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_10.shtml
*/
public function queryRefund($refundNo)
{
$path = "/v3/refund/domestic/refunds/{$refundNo}";
return $this->doRequest('GET', $path, '', true);
}
/**
* 获取退款通知
* @param mixed $data
* @return array
* @throws \WeChat\Exceptions\InvalidDecryptException
* @deprecated 直接使用 Notify 方法
*/
public function notifyRefund($data = [])
{
return $this->notify($data);
}
/**
* 支付/退款通知解析(自动解密 resource
* @param array|null $data 通知原文,为空则从输入流读取
* @return array 解析后的通知数据,包含 result 字段(明文)
* @throws \WeChat\Exceptions\InvalidDecryptException
*/
public function notify($data = [])
{
if (empty($data)) {
$data = json_decode(Tools::getRawInput(), true);
}
if (isset($data['resource'])) {
$aes = new DecryptAes($this->config['mch_v3_key']);
$data['result'] = $aes->decryptToString(
$data['resource']['associated_data'],
$data['resource']['nonce'],
$data['resource']['ciphertext']
);
}
return $data;
}
/**
* 申请交易账单
* @param array|string $params 账单参数bill_date, bill_type 等)或已拼好的查询串
* @return array 含下载地址的申请结果
* @throws \WeChat\Exceptions\InvalidResponseException
* @document https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_3_6.shtml
*/
public function tradeBill($params)
{
$path = '/v3/bill/tradebill?' . is_array($params) ? http_build_query($params) : $params;
return $this->doRequest('GET', $path, '', true);
}
/**
* 申请资金账单
* @param array|string $params 账单参数bill_date, account_type 等)或已拼好的查询串
* @return array 含下载地址的申请结果
* @throws \WeChat\Exceptions\InvalidResponseException
* @document https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_3_7.shtml
*/
public function fundflowBill($params)
{
$path = '/v3/bill/fundflowbill?' . is_array($params) ? http_build_query($params) : $params;
return $this->doRequest('GET', $path, '', true);
}
/**
* 下载账单文件
* @param string $fileurl 申请账单返回的 download_url
* @return string 二进制内容gzip/CSV/Excel
* @throws \WeChat\Exceptions\InvalidResponseException
* @document https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_6_1.shtml
*/
public function downloadBill($fileurl)
{
return $this->doRequest('GET', $fileurl, '', false, false);
}
}

View File

@ -1,114 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WePayV3;
use WePayV3\Contracts\BasicWePay;
/**
* 商家分账 (V3)
* @package WePayV3
*/
class ProfitSharing extends BasicWePay
{
/**
* 请求分账
* @param array $options 分账参数transaction_id, out_order_no, receivers 等)
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function create(array $options)
{
$options['appid'] = $this->config['appid'];
return $this->doRequest('POST', '/v3/profitsharing/orders', json_encode($options, JSON_UNESCAPED_UNICODE), true);
}
/**
* 查询分账结果
* @param string $outOrderNo 商户分账单号
* @param string $transactionId 微信订单号
* @return array 分账状态
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function query($outOrderNo, $transactionId)
{
$pathinfo = "/v3/profitsharing/orders/{$outOrderNo}?&transaction_id={$transactionId}";
return $this->doRequest('GET', $pathinfo, '', true);
}
/**
* 解冻剩余资金
* @param array $options 解冻参数transaction_id, out_order_no, description
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function unfreeze(array $options)
{
return $this->doRequest('POST', '/v3/profitsharing/orders/unfreeze', json_encode($options, JSON_UNESCAPED_UNICODE), true);
}
/**
* 查询剩余待分金额
* @param string $transactionId 微信订单号
* @return array 待分金额
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function amounts($transactionId)
{
$pathinfo = "/v3/profitsharing/transactions/{$transactionId}/amounts";
return $this->doRequest('GET', $pathinfo, '', true);
}
/**
* 添加分账接收方
* @param array $options 接收方信息type, account, name name RSA
* @return array
* @throws \WeChat\Exceptions\InvalidDecryptException
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function addReceiver(array $options)
{
$options['appid'] = $this->config['appid'];
if (isset($options['name'])) {
$options['name'] = $this->rsaEncode($options['name']);
}
return $this->doRequest('POST', "/v3/profitsharing/receivers/add", json_encode($options, JSON_UNESCAPED_UNICODE), true);
}
/**
* 删除分账接收方
* @param array $options 接收方信息type, account
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function deleteReceiver(array $options)
{
$options['appid'] = $this->config['appid'];
return $this->doRequest('POST', "/v3/profitsharing/receivers/delete", json_encode($options, JSON_UNESCAPED_UNICODE), true);
}
/**
* 请求分账回退
* @param array $options 回退参数out_return_no, out_order_no, return_account 等)
* @return array 回退结果
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function backspace(array $options)
{
$options['appid'] = $this->config['appid'];
return $this->doRequest('POST', "/v3/profitsharing/return-orders", json_encode($options, JSON_UNESCAPED_UNICODE), true);
}
}

View File

@ -1,82 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WePayV3;
use WePayV3\Contracts\BasicWePay;
/**
* 订单退款接口
* 注意:直连商户退款接口集成在 Order
* @deprecated
* @class Refund
* @package WePayV3
*/
class Refund extends BasicWePay
{
/**
* 创建退款订单(兼容入口,转调 Order::createRefund
* @param array $data 退款参数out_trade_no transaction_idout_refund_noamount 等)
* @return array 退款结果
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function create($data)
{
return Order::instance($this->config)->createRefund($data);
// return $this->doRequest('POST', '/v3/ecommerce/refunds/apply', json_encode($data, JSON_UNESCAPED_UNICODE), true);
}
/**
* 退款订单查询(兼容入口)
* @param string $refundNo 商户退款单号 out_refund_no
* @return array 退款详情
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function query($refundNo)
{
return Order::instance($this->config)->queryRefund($refundNo);
// $pathinfo = "/v3/ecommerce/refunds/out-refund-no/{$refundNo}";
// return $this->doRequest('GET', "{$pathinfo}?sub_mchid={$this->config['mch_id']}", '', true);
}
/**
* 获取退款通知(兼容入口,转调 Order::notify
* @param mixed $xml 通知原文
* @return array 解密后的通知数据
* @throws \WeChat\Exceptions\InvalidDecryptException
* @throws \WeChat\Exceptions\InvalidResponseException
* @throws \WeChat\Exceptions\LocalCacheException
*/
public function notify($xml = [])
{
return Order::instance($this->config)->notify($xml);
// $data = Tools::xml2arr(empty($xml) ? Tools::getRawInput() : $xml);
// if (!isset($data['return_code']) || $data['return_code'] !== 'SUCCESS') {
// throw new InvalidResponseException('获取退款通知XML失败');
// }
// try {
// $key = md5($this->config['mch_v3_key']);
// $decrypt = base64_decode($data['req_info']);
// $response = openssl_decrypt($decrypt, 'aes-256-ecb', $key, OPENSSL_RAW_DATA);
// $data['result'] = Tools::xml2arr($response);
// return $data;
// } catch (\Exception $exception) {
// throw new InvalidDecryptException($exception->getMessage(), $exception->getCode());
// }
}
}

View File

@ -1,137 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
namespace WePayV3;
use WePayV3\Contracts\BasicWePay;
/**
* 商家转账到零钱 (V3)
* @package WePayV3
*/
class Transfers extends BasicWePay
{
/**
* 商家转账到零钱(单笔)
* @param array $body 转账参数out_bill_no, transfer_amount, openid/user_name 等,敏感字段需 RSA
* @return array|string
* @throws \WeChat\Exceptions\InvalidDecryptException
* @throws \WeChat\Exceptions\InvalidResponseException
* @link https://pay.weixin.qq.com/doc/v3/merchant/4012716434
*/
public function bills($body)
{
if (empty($body['appid'])) {
$body['appid'] = $this->config['appid'];
}
if (!empty($body['user_name'])) {
$body['user_name'] = $this->rsaEncode($body['user_name']);
}
return $this->doRequest('POST', '/v3/fund-app/mch-transfer/transfer-bills', json_encode($body, JSON_UNESCAPED_UNICODE), true);
}
/**
* 查询转账结果
* @param string $out_bill_no 商户转账单号
* @return array|string 转账状态
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function billsQuery($out_bill_no)
{
return $this->doRequest('GET', "/v3/fund-app/mch-transfer/transfer-bills/out-bill-no/{$out_bill_no}", '', true);
}
/**
* 发起商家批量转账
* @param array $body 批量参数out_batch_no, transfer_detail_list 等,姓名需 RSA
* @return array
* @throws \WeChat\Exceptions\InvalidDecryptException
* @throws \WeChat\Exceptions\InvalidResponseException
* @link https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter4_3_1.shtml
*/
public function batchs($body)
{
if (empty($body['appid'])) {
$body['appid'] = $this->config['appid'];
}
if (isset($body['transfer_detail_list']) && is_array($body['transfer_detail_list'])) {
foreach ($body['transfer_detail_list'] as &$item) if (isset($item['user_name'])) {
$item['user_name'] = $this->rsaEncode($item['user_name']);
}
if (empty($body['total_num'])) {
$body['total_num'] = count($body['transfer_detail_list']);
}
if (empty($body['total_amount'])) {
$body['total_amount'] = array_sum(array_column($body['transfer_detail_list'], 'transfer_amount'));
}
}
return $this->doRequest('POST', '/v3/transfer/batches', json_encode($body, JSON_UNESCAPED_UNICODE), true);
}
/**
* 查询批量转账批次
* @param string $batchId 微信批次单号(二选一)
* @param string $outBatchNo 商户批次单号(二选一)
* @param bool $needQueryDetail 是否拉取明细
* @param int $offset 明细起始位置
* @param int $limit 最大明细条数
* @param string $detailStatus 明细状态 ALL|SUCCESS|FAIL
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function query($batchId = '', $outBatchNo = '', $needQueryDetail = true, $offset = 0, $limit = 20, $detailStatus = 'ALL')
{
if (empty($batchId)) {
$pathinfo = "/v3/transfer/batches/out-batch-no/{$outBatchNo}";
} else {
$pathinfo = "/v3/transfer/batches/batch-id/{$batchId}";
}
$params = http_build_query([
'limit' => $limit,
'offset' => $offset,
'detail_status' => $detailStatus,
'need_query_detail' => $needQueryDetail ? 'true' : 'false',
]);
return $this->doRequest('GET', "{$pathinfo}?{$params}", '', true);
}
/**
* 通过微信明细单号查询明细
* @param string $batchId 微信批次单号
* @param string $detailId 微信明细单号
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function detailBatchId($batchId, $detailId)
{
$pathinfo = "/v3/transfer/batches/batch-id/{$batchId}/details/detail-id/{$detailId}";
return $this->doRequest('GET', $pathinfo, '', true);
}
/**
* 通过商家明细单号查询明细
* @param string $outBatchNo 商户批次单号
* @param string $outDetailNo 商户明细单号
* @return array
* @throws \WeChat\Exceptions\InvalidResponseException
*/
public function detailOutBatchNo($outBatchNo, $outDetailNo)
{
$pathinfo = "/v3/transfer/batches/out-batch-no/{$outBatchNo}/details/out-detail-no/{$outDetailNo}";
return $this->doRequest('GET', $pathinfo, '', true);
}
}

View File

@ -1,46 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
// 1. 手动加载入口文件
include "../include.php";
// 2. 准备公众号配置参数
$config = include "./alipay.php";
try {
// 实例支付对象
// $pay = \We::AliPayApp($config);
// $pay = new \AliPay\App($config);
$pay = \AliPay\App::instance($config);
// 请参考请求参数https://docs.open.alipay.com/api_1/alipay.trade.app.pay
$result = $pay->apply([
'out_trade_no' => strval(time()), // 商户订单号
'total_amount' => '1', // 支付金额
'subject' => '支付宝订单标题', // 支付订单描述
]);
echo $result . PHP_EOL . '<br></br>' . PHP_EOL;
// 请求关闭订单
$result = $pay->close([
'out_trade_no' => strval(time())
]);
echo PHP_EOL . PHP_EOL . $result;
} catch (\Exception $e) {
echo $e->getMessage();
}

View File

@ -1,47 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
// 1. 手动加载入口文件
include "../include.php";
// 2. 准备公众号配置参数
$config = include "./alipay.php";
try {
// 实例支付对象
// $pay = new \AliPay\Bill($config);
// $pay = \We::AliPayBill($config);
$pay = \AliPay\Bill::instance($config);
/**
* 账单类型,商户通过接口或商户经开放平台授权后其所属服务商通过接口可以获取以下账单类型,支持:
* trade商户基于支付宝交易收单的业务账单
* signcustomer基于商户支付宝余额收入及支出等资金变动的账务账单
* merchant_act营销活动账单包含营销活动的发放核销记录
* trade_zft_merchant直付通二级商户查询交易的业务账单
* zft_acc直付通平台商查询二级商户流水使用返回所有二级商户流水。
*/
// 请参考请求参数https://docs.open.alipay.com/api_15/alipay.data.dataservice.bill.downloadurl.query
$result = $pay->apply([
'bill_date' => date('Y-m-d', strtotime('-1 month')), // 账单时间(日账单yyyy-MM-dd,月账单 yyyy-MM)
'bill_type' => 'trade',
]);
echo '<pre>';
var_export($result);
} catch (Exception $e) {
echo $e->getMessage();
}

View File

@ -1,163 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
/**
* 支付宝通用接口测试
* 测试 callApi() 万能接口方法
*/
try {
// 1. 手动加载入口文件
include "../include.php";
// 2. 准备支付宝配置参数
$config = include "./alipay.php";
// 3. 创建接口实例
$alipay = \We::AliPayWeb($config);
echo "<h2>=== 支付宝通用接口测试 ===</h2>";
// ============================================
// 测试1: GET请求 - 查询订单
// ============================================
echo "<h3>测试1: GET请求 - 查询订单</h3>";
try {
$result = $alipay->callApi(
'alipay.trade.query', // API方法名必填第一参数
[
'out_trade_no' => time() - 3600, // 使用一个可能存在的订单号
],
'GET',
false // 不验证响应签名
);
echo '<pre>';
var_export($result);
echo '</pre>';
} catch (Exception $e) {
echo "错误: " . $e->getMessage() . PHP_EOL;
}
// ============================================
// 测试2: GET请求 - 查询订单(验证签名)
// ============================================
echo "<h3>测试2: GET请求 - 查询订单(验证签名)</h3>";
try {
$result = $alipay->callApi(
'alipay.trade.query', // API方法名
[
'out_trade_no' => time() - 3600,
],
'GET',
true // 验证响应签名
);
echo '<pre>';
var_export($result);
echo '</pre>';
} catch (Exception $e) {
echo "错误: " . $e->getMessage() . PHP_EOL;
}
// ============================================
// 测试3: POST请求 - 订单退款
// ============================================
echo "<h3>测试3: POST请求 - 订单退款</h3>";
echo "<p style='color: orange;'>注意:此测试需要有效的订单号</p>";
try {
$result = $alipay->callApi(
'alipay.trade.refund', // API方法名第一参数
[
'out_trade_no' => time() - 3600,
'refund_amount' => '0.01',
],
'POST',
false // 不验证响应签名
);
echo '<pre>';
var_export($result);
echo '</pre>';
} catch (Exception $e) {
echo "错误: " . $e->getMessage() . PHP_EOL;
echo "<p style='color: gray;'>这是正常的,因为退款需要有效的订单号</p>";
}
// ============================================
// 测试4: GET请求 - 退款查询
// ============================================
echo "<h3>测试4: GET请求 - 退款查询</h3>";
try {
$result = $alipay->callApi(
'alipay.trade.fastpay.refund.query', // API方法名
[
'out_trade_no' => time() - 3600,
'out_request_no' => time() - 3600,
],
'GET',
false // 不验证响应签名
);
echo '<pre>';
var_export($result);
echo '</pre>';
} catch (Exception $e) {
echo "错误: " . $e->getMessage() . PHP_EOL;
}
// ============================================
// 测试5: POST请求 - 关闭订单
// ============================================
echo "<h3>测试5: POST请求 - 关闭订单</h3>";
try {
$result = $alipay->callApi(
'alipay.trade.close', // API方法名
[
'out_trade_no' => time() - 3600,
],
'POST',
false // 不验证响应签名
);
echo '<pre>';
var_export($result);
echo '</pre>';
} catch (Exception $e) {
echo "错误: " . $e->getMessage() . PHP_EOL;
}
// ============================================
// 测试6: PUT请求 - 更新资源(示例)
// ============================================
echo "<h3>测试6: PUT请求 - 更新资源(示例)</h3>";
echo "<p style='color: gray;'>注意此示例仅展示PUT请求用法实际API可能不支持</p>";
try {
// PUT请求示例如果API支持
// $result = $alipay->callApi(
// 'alipay.some.method', // API方法名
// ['key' => 'value'],
// 'PUT',
// false
// );
echo '<pre>PUT请求用法示例已注释</pre>';
} catch (Exception $e) {
echo "错误: " . $e->getMessage() . PHP_EOL;
}
echo "<h3 style='color: green;'>=== 所有测试完成 ===</h3>";
} catch (Exception $e) {
// 出错啦,处理下吧
echo "<h3 style='color: red;'>错误: " . $e->getMessage() . "</h3>";
echo "<pre>" . $e->getTraceAsString() . "</pre>";
}

View File

@ -1,41 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | WeChatDeveloper
// +----------------------------------------------------------------------
// | 版权所有 2014~2026 ThinkAdmin [ thinkadmin.top ]
// +----------------------------------------------------------------------
// | 官方网站: https://thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// | 免责声明 ( https://thinkadmin.top/disclaimer )
// +----------------------------------------------------------------------
// | gitee 代码仓库https://gitee.com/zoujingli/WeChatDeveloper
// | github 代码仓库https://github.com/zoujingli/WeChatDeveloper
// +----------------------------------------------------------------------
// 1. 手动加载入口文件
include "../include.php";
// 2. 准备公众号配置参数
$config = include "./alipay.php";
try {
// 实例支付对象
// $pay = \We::AliPayApp($config);
// $pay = new \AliPay\App($config);
$pay = \AliPay\App::instance($config);
$data = $pay->notify();
if (in_array($data['trade_status'], ['TRADE_SUCCESS', 'TRADE_FINISHED'])) {
// @todo 更新订单状态,支付完成
file_put_contents('notify.txt', "收到来自支付宝的异步通知\r\n", FILE_APPEND);
file_put_contents('notify.txt', '订单号:' . $data['out_trade_no'] . "\r\n", FILE_APPEND);
file_put_contents('notify.txt', '订单金额:' . $data['total_amount'] . "\r\n\r\n", FILE_APPEND);
} else {
file_put_contents('notify.txt', "收到异步通知\r\n", FILE_APPEND);
}
} catch (\Exception $e) {
// 异常处理
echo $e->getMessage();
}

Some files were not shown because too many files have changed in this diff Show More