@@ -8,15 +8,64 @@ | |||
* @license https://www.dedebiz.com/license | |||
* @link https://www.dedebiz.com | |||
*/ | |||
if (!empty($_REQUEST['dopost'])) define('IS_DEDEAPI', TRUE); | |||
require_once(dirname(__FILE__)."/config.php"); | |||
require_once(DEDEINC.'/datalistcp.class.php'); | |||
CheckPurview('sys_Data'); | |||
$dopost = (empty($dopost)) ? '' : $dopost; | |||
$pid = (empty($pid)) ? 0 : intval($pid); | |||
$sql = "SELECT * FROM `#@__payment` ORDER BY `rank` ASC"; | |||
$dlist = new DataListCP(); | |||
$dlist->SetTemplet(DEDEADMIN."/templets/sys_payment.htm"); | |||
$dlist->SetSource($sql); | |||
$dlist->display(); | |||
if ($dopost === "get_payments") { | |||
$sql = "SELECT * FROM `#@__sys_payment`"; | |||
$dsql->SetQuery($sql); | |||
$dsql->Execute('payment'); | |||
$payments = array(); | |||
while ($myrow = $dsql->GetArray('payment')) { | |||
$payments[$myrow['code']] = $myrow; | |||
} | |||
echo json_encode(array( | |||
"code" => 0, | |||
"msg" => "", | |||
"data" => $payments, | |||
)); | |||
exit; | |||
} else if($dopost === "save_config") { | |||
$json = file_get_contents("php://input"); | |||
$config = json_decode($json); | |||
foreach($config as $key => $item) { | |||
$status = 0; | |||
$sortrank = 0; | |||
$configItem = array(); | |||
foreach($item as $kk => $ii) { | |||
if ($kk === "Enabled") { | |||
$status = $ii === true ? 1 : 0; | |||
} else if ($kk === "Sortrank") { | |||
$sortrank = intval($ii); | |||
} else { | |||
$configItem[$kk] = $ii; | |||
} | |||
} | |||
$cfg = json_encode($configItem); | |||
$upQuery = "UPDATE `#@__sys_payment` SET sortrank='$sortrank',status='$status',config='$cfg' WHERE code='$key'; "; | |||
if (!$dsql->ExecuteNoneQuery($upQuery)) { | |||
echo json_encode(array( | |||
"code" => -1, | |||
"msg" => "保存配置失败", | |||
)); | |||
exit; | |||
} | |||
} | |||
echo json_encode(array( | |||
"code" => 0, | |||
"msg" => "", | |||
"data" => "success", | |||
)); | |||
exit; | |||
} | |||
include DedeInclude('templets/sys_payment.htm'); | |||
?> |
@@ -1,5 +1,6 @@ | |||
<!DOCTYPE html> | |||
<html> | |||
<head> | |||
<meta charset="utf-8"> | |||
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1"> | |||
@@ -10,6 +11,7 @@ | |||
<script src="../static/web/js/jquery.min.js"></script> | |||
<script src="../static/web/js/bootstrap.min.js"></script> | |||
</head> | |||
<body> | |||
<table cellpadding="3" cellspacing="1" align="center" class="table maintable my-3"> | |||
<tr> | |||
@@ -17,7 +19,8 @@ | |||
<table cellspacing="0" cellpadding="0" class="table table-borderless w-100"> | |||
<tr> | |||
<td>支付接口设置</td> | |||
<td align="right"><span><a href="https://www.dedebiz.com/help" target="_blank" class="btn btn-success btn-sm">更多接口</a></span></td> | |||
<td align="right"><span><a href="https://www.dedebiz.com/help" target="_blank" | |||
class="btn btn-success btn-sm">更多接口</a></span></td> | |||
</tr> | |||
</table> | |||
</td> | |||
@@ -26,19 +29,24 @@ | |||
<td colspan="4"> | |||
<ul class="nav nav-tabs" id="myTab" role="tablist"> | |||
<li class="nav-item" role="presentation"> | |||
<button type="button" id="wechat-tab" class="nav-link active" data-toggle="tab" data-target="#wechat" role="tab" aria-controls="wechat" aria-selected="true">微信支付</button> | |||
<button type="button" id="wechat-tab" class="nav-link active" data-toggle="tab" | |||
data-target="#wechat" role="tab" aria-controls="wechat" aria-selected="true">微信支付</button> | |||
</li> | |||
<li class="nav-item" role="presentation"> | |||
<button type="button" id="alipay-tab" class="nav-link" data-toggle="tab" data-target="#alipay" role="tab" aria-controls="alipay" aria-selected="false">支付宝</button> | |||
<button type="button" id="alipay-tab" class="nav-link" data-toggle="tab" data-target="#alipay" | |||
role="tab" aria-controls="alipay" aria-selected="false">支付宝</button> | |||
</li> | |||
<li class="nav-item" role="presentation"> | |||
<button type="button" id="bank-tab" class="nav-link" data-toggle="tab" data-target="#bank" role="tab" aria-controls="bank" aria-selected="false">银行转帐</button> | |||
<button type="button" id="bank-tab" class="nav-link" data-toggle="tab" data-target="#bank" | |||
role="tab" aria-controls="bank" aria-selected="false">银行转帐</button> | |||
</li> | |||
<li class="nav-item" role="presentation"> | |||
<button type="button" id="balance-tab" class="nav-link" data-toggle="tab" data-target="#balance" role="tab" aria-controls="balance" aria-selected="false">余额支付</button> | |||
<button type="button" id="balance-tab" class="nav-link" data-toggle="tab" data-target="#balance" | |||
role="tab" aria-controls="balance" aria-selected="false">余额支付</button> | |||
</li> | |||
<li class="nav-item" role="presentation"> | |||
<button type="button" id="cod-tab" class="nav-link" data-toggle="tab" data-target="#cod" role="tab" aria-controls="cod" aria-selected="false">货到付款</button> | |||
<button type="button" id="cod-tab" class="nav-link" data-toggle="tab" data-target="#cod" | |||
role="tab" aria-controls="cod" aria-selected="false">货到付款</button> | |||
</li> | |||
</ul> | |||
<div class="tab-content py-3" id="myTabContent"> | |||
@@ -46,7 +54,8 @@ | |||
<form> | |||
<div class="form-group"> | |||
<label>描述</label> | |||
<p>微信支付是腾讯公司的支付业务品牌,微信支付商户平台支持线下场所、公众号、小程序、PC网站、APP、企业微信等经营场景快速接入微信支付。微信支付全面打通O2O生活消费领域,提供专业的互联网+行业解决方案,微信支付支持微信红包和微信理财通,是移动支付的首选。</p> | |||
<p>微信支付是腾讯公司的支付业务品牌,微信支付商户平台支持线下场所、公众号、小程序、PC网站、APP、企业微信等经营场景快速接入微信支付。微信支付全面打通O2O生活消费领域,提供专业的互联网+行业解决方案,微信支付支持微信红包和微信理财通,是移动支付的首选。 | |||
</p> | |||
</div> | |||
<div class="form-group"> | |||
<label for="iptWechatAppID">AppID</label> | |||
@@ -66,18 +75,23 @@ | |||
</div> | |||
<div class="form-group"> | |||
<label for="iptWechatSerialNo">商户证书序列号</label> | |||
<input type="appid" class="form-control" id="iptWechatSerialNo"> | |||
<input type="text" class="form-control" id="iptWechatSerialNo"> | |||
</div> | |||
<div class="form-group"> | |||
<label>商户证书文件</label> | |||
<div class="custom-file"> | |||
<input type="file" class="custom-file-input" id="iptWechatPrivateKey"> | |||
<label class="custom-file-label" data-browse="选择" for="iptWechatPrivateKey">选择商户证书文件...</label> | |||
<label class="custom-file-label" data-browse="选择" | |||
for="iptWechatPrivateKey">选择商户证书文件...</label> | |||
</div> | |||
</div> | |||
<div class="form-group"> | |||
<label for="iptWechatSortrank">排序(越小越靠前)</label> | |||
<input type="text" class="form-control" id="iptWechatSortrank" value="0"> | |||
</div> | |||
<div class="form-group form-check"> | |||
<input type="checkbox" class="form-check-input" id="WechatEnabled"> | |||
<label class="form-check-label" for="WechatEnabled"> 是否启用</label> | |||
<input type="checkbox" class="form-check-input" id="iptWechatEnabled"> | |||
<label class="form-check-label" for="iptWechatEnabled"> 是否启用</label> | |||
</div> | |||
</form> | |||
</div> | |||
@@ -85,7 +99,8 @@ | |||
<form> | |||
<div class="form-group"> | |||
<label for="iptAppID">描述</label> | |||
<p>支付宝,全球领先的独立第三方支付平台,致力于为广大用户提供安全快速的电子支付/网上支付/安全支付/手机支付体验,及转账收款/水电煤缴费/信用卡还款/AA收款等生活服务应用。</p> | |||
<p>支付宝,全球领先的独立第三方支付平台,致力于为广大用户提供安全快速的电子支付/网上支付/安全支付/手机支付体验,及转账收款/水电煤缴费/信用卡还款/AA收款等生活服务应用。 | |||
</p> | |||
</div> | |||
<div class="form-group"> | |||
<label for="iptAlipayAPPID">APPID</label> | |||
@@ -99,30 +114,37 @@ | |||
<label>应用公钥证书</label> | |||
<div class="custom-file"> | |||
<input type="file" class="custom-file-input" id="iptAlipayAppCertPublicKey"> | |||
<label class="custom-file-label" data-browse="选择" for="iptAlipayAppCertPublicKey">选择应用公钥证书文件...</label> | |||
<label class="custom-file-label" data-browse="选择" | |||
for="iptAlipayAppCertPublicKey">选择应用公钥证书文件...</label> | |||
</div> | |||
</div> | |||
<div class="form-group"> | |||
<label>支付宝公钥证书</label> | |||
<div class="custom-file"> | |||
<input type="file" class="custom-file-input" id="iptAlipayCertPublicKey"> | |||
<label class="custom-file-label" data-browse="选择" for="iptAlipayCertPublicKey">选择支付宝公钥证书文件...</label> | |||
<label class="custom-file-label" data-browse="选择" | |||
for="iptAlipayCertPublicKey">选择支付宝公钥证书文件...</label> | |||
</div> | |||
</div> | |||
<div class="form-group"> | |||
<label>支付宝根证书</label> | |||
<div class="custom-file"> | |||
<input type="file" class="custom-file-input" id="iptAlipayRootCert"> | |||
<label class="custom-file-label" data-browse="选择" for="iptAlipayRootCert">选择支付宝根证书文件...</label> | |||
<label class="custom-file-label" data-browse="选择" | |||
for="iptAlipayRootCert">选择支付宝根证书文件...</label> | |||
</div> | |||
</div> | |||
<div class="form-group"> | |||
<label for="iptAlipaySignType">签名类型</label> | |||
<input type="text" class="form-control" id="iptAlipaySignType" value="RSA2" disabled> | |||
</div> | |||
<div class="form-group"> | |||
<label for="iptAlipaySortrank">排序(越小越靠前)</label> | |||
<input type="text" class="form-control" id="iptAlipaySortrank" value="0"> | |||
</div> | |||
<div class="form-group form-check"> | |||
<input type="checkbox" class="form-check-input" id="AlipayEnabled"> | |||
<label class="form-check-label" for="AlipayEnabled"> 是否启用</label> | |||
<input type="checkbox" class="form-check-input" id="iptAlipayEnabled"> | |||
<label class="form-check-label" for="iptAlipayEnabled"> 是否启用</label> | |||
</div> | |||
</form> | |||
</div> | |||
@@ -134,19 +156,23 @@ | |||
</div> | |||
<div class="form-group"> | |||
<label for="iptBankAccountName">账户名</label> | |||
<input type="appid" class="form-control" id="iptBankAccountName"> | |||
<input type="text" class="form-control" id="iptBankAccountName"> | |||
</div> | |||
<div class="form-group"> | |||
<label for="iptBankAccountNO">账号</label> | |||
<input type="appid" class="form-control" id="iptBankAccountNO"> | |||
<input type="text" class="form-control" id="iptBankAccountNO"> | |||
</div> | |||
<div class="form-group"> | |||
<label for="iptBankName">开户行</label> | |||
<input type="appid" class="form-control" id="iptBankName"> | |||
<input type="text" class="form-control" id="iptBankName"> | |||
</div> | |||
<div class="form-group"> | |||
<label for="iptBankSortrank">排序(越小越靠前)</label> | |||
<input type="text" class="form-control" id="iptBankSortrank" value="0"> | |||
</div> | |||
<div class="form-group form-check"> | |||
<input type="checkbox" class="form-check-input" id="BankEnabled"> | |||
<label class="form-check-label" for="BankEnabled"> 是否启用</label> | |||
<input type="checkbox" class="form-check-input" id="iptBankEnabled"> | |||
<label class="form-check-label" for="iptBankEnabled"> 是否启用</label> | |||
</div> | |||
</form> | |||
</div> | |||
@@ -156,9 +182,13 @@ | |||
<label>描述</label> | |||
<p>支持采用积分进行支付。</p> | |||
</div> | |||
<div class="form-group"> | |||
<label for="iptBalanceSortrank">排序(越小越靠前)</label> | |||
<input type="text" class="form-control" id="iptBalanceSortrank" value="0"> | |||
</div> | |||
<div class="form-group form-check"> | |||
<input type="checkbox" class="form-check-input" id="BalanceEnabled"> | |||
<label class="form-check-label" for="BalanceEnabled">是否启用</label> | |||
<input type="checkbox" class="form-check-input" id="iptBalanceEnabled"> | |||
<label class="form-check-label" for="iptBalanceEnabled">是否启用</label> | |||
</div> | |||
</form> | |||
</div> | |||
@@ -168,13 +198,18 @@ | |||
<label>描述</label> | |||
<p>购买后直接发货,到货后再进行支付。</p> | |||
</div> | |||
<div class="form-group"> | |||
<label for="iptCodSortrank">排序(越小越靠前)</label> | |||
<input type="text" class="form-control" id="iptCodSortrank" value="0"> | |||
</div> | |||
<div class="form-group form-check"> | |||
<input type="checkbox" class="form-check-input" id="CodEnabled"> | |||
<label class="form-check-label" for="CodEnabled"> 是否启用</label> | |||
<input type="checkbox" class="form-check-input" id="iptCodEnabled"> | |||
<label class="form-check-label" for="iptCodEnabled"> 是否启用</label> | |||
</div> | |||
</form> | |||
</div> | |||
<div class="text-center"><button type="submit" class="btn btn-success">保存</button></div> | |||
<div class="text-center"><button id="btnSave" type="submit" class="btn btn-success">保存</button> | |||
</div> | |||
</div> | |||
</td> | |||
</tr> | |||
@@ -184,6 +219,134 @@ | |||
let fileName = $(this).val().split('\\').pop(); | |||
$(this).siblings('.custom-file-label').addClass("selected").html(fileName); | |||
}); | |||
let config = { | |||
Wechat: { | |||
AppID: '', | |||
AppSecret: '', | |||
MchID: '', | |||
APIV3Key: '', | |||
SerialNo: '', | |||
PrivateKey: '', | |||
Sortrank: 0, | |||
Enabled: true, | |||
}, | |||
Alipay: { | |||
APPID: '', | |||
PrivateKey: '', | |||
AppCertPublicKey: '', | |||
CertPublicKey: '', | |||
RootCert: '', | |||
SignType: 'RSA2', | |||
Sortrank: 0, | |||
Enabled: false, | |||
}, | |||
Bank: { | |||
AccountName: '', | |||
AccountNO: '', | |||
Name: '', | |||
Sortrank: 0, | |||
Enabled: true, | |||
}, | |||
Balance: { | |||
Sortrank: 0, | |||
Enabled: false, | |||
}, | |||
Cod: { | |||
Sortrank: 0, | |||
Enabled: true, | |||
} | |||
} | |||
//加载系统config | |||
function getPayments() { | |||
$.get("sys_payment.php?dopost=get_payments", function (data) { | |||
if (data.code === 0) { | |||
for (const key in data.data) { | |||
if (Object.hasOwnProperty.call(data.data, key)) { | |||
const element = data.data[key]; | |||
let itemConfig = {}; | |||
try { | |||
itemConfig = JSON.parse(element.config); | |||
} catch (error) { | |||
itemConfig = config[key] | |||
} | |||
itemConfig.Sortrank = element.sortrank; | |||
itemConfig.Enabled = element.status === 0? false : true; | |||
console.log("itemConfig=", itemConfig); | |||
for (const k1 in config[key]) { | |||
if (Object.hasOwnProperty.call(config[key], k1)) { | |||
const ee = config[key][k1]; | |||
if (typeof itemConfig[k1] === "undefined") { | |||
itemConfig[k1] = ee; | |||
} | |||
} | |||
} | |||
for (const k2 in itemConfig) { | |||
if (Object.hasOwnProperty.call(itemConfig, k2)) { | |||
const element = itemConfig[k2]; | |||
if ($(`#ipt${key}${k2}`).attr('type') === 'text') { | |||
$(`#ipt${key}${k2}`).val(element); | |||
} else if ($(`#ipt${key}${k2}`).attr('type') === 'checkbox') { | |||
$(`#ipt${key}${k2}`).prop('checked', element); | |||
} | |||
} | |||
} | |||
config[key] = itemConfig; | |||
} | |||
} | |||
} | |||
}) | |||
} | |||
//更新config | |||
function updateConfig() { | |||
for (const key in config) { | |||
if (Object.hasOwnProperty.call(config, key)) { | |||
const element = config[key]; | |||
for (const kk in element) { | |||
if (Object.hasOwnProperty.call(element, kk)) { | |||
const itemConfig = element[kk]; | |||
console.log(`#ipt${key}${kk}`, itemConfig); | |||
if ($(`#ipt${key}${kk}`).attr('type') === 'text') { | |||
let val = $(`#ipt${key}${kk}`).val(); | |||
if (kk === "Sortrank") { | |||
val = parseInt(val); | |||
} | |||
config[key][kk] = val; | |||
} else if ($(`#ipt${key}${kk}`).attr('type') === 'checkbox') { | |||
config[key][kk] = $(`#ipt${key}${kk}`).prop('checked'); | |||
} | |||
} | |||
} | |||
} | |||
} | |||
} | |||
//保存配置信息 | |||
function saveConfig() { | |||
$.ajax({ | |||
type: "post", | |||
url: 'sys_payment.php?dopost=save_config', | |||
data: JSON.stringify(config), | |||
contentType: "application/json; charset=utf-8", | |||
dataType: "json", | |||
success: function (data) { | |||
console.log(data); | |||
} | |||
}) | |||
} | |||
$(document).ready(function () { | |||
getPayments(); | |||
$("#btnSave").click(() => { | |||
updateConfig() | |||
saveConfig(); | |||
console.log(config) | |||
}) | |||
}) | |||
</script> | |||
</body> | |||
</html> |
@@ -556,9 +556,6 @@ INSERT INTO `#@__scores` VALUES ('2','列兵','1','0','1'), | |||
INSERT INTO `#@__member_stowtype` VALUES ('sys','系统收藏','archives_do.php'), | |||
('book','小说收藏','/book/book.php?bid'); | |||
INSERT INTO `#@__payment` VALUES ('2','bank','银行汇款/转帐','0','银行名称\t\n收款人信息:全称 ××× ;帐号或地址 ××× ;开户行 ×××\t\n注意事项:办理电汇时,请在电汇单“汇款用途”一栏处注明您的订单号','4','a:0:{}','1','1','0'), | |||
('1','cod','货到付款','0','开通城市:×××\t\n货到付款区域:×××','3','a:0:{}','1','1','0'); | |||
INSERT INTO `#@__softconfig` VALUES ('0','1','1','1','http://www.aaa.com | 下载地址一\t\nhttp://www.bbb.com | 下载地址二\t\nhttp://www.ccc.com | 下载地址三\t\n','<p>如果这个软件总是不能下载的请点击报告错误合作<br>\t\n下载本站资源,如果服务器暂不能下载请过一段时间重试<br>\t\n如果遇到什么问题,请联系我们,我们将在那里提供更多,更好的资源</p>','0','0','0','0'); | |||
INSERT INTO `#@__stepselect` VALUES ('1','血型','blood','1','1'), | |||
@@ -732,22 +732,6 @@ CREATE TABLE `#@__mytag` ( | |||
KEY `tagname` (`tagname`,`typeid`,`timeset`,`endtime`,`starttime`) | |||
) TYPE=MyISAM; | |||
DROP TABLE IF EXISTS `#@__payment`; | |||
CREATE TABLE `#@__payment` ( | |||
`id` tinyint(3) unsigned NOT NULL auto_increment, | |||
`code` varchar(20) NOT NULL default '', | |||
`name` varchar(120) NOT NULL default '', | |||
`fee` varchar(10) NOT NULL default '0', | |||
`description` text NOT NULL, | |||
`rank` tinyint(3) unsigned NOT NULL default '0', | |||
`config` text NOT NULL, | |||
`enabled` tinyint(1) unsigned NOT NULL default '0', | |||
`cod` tinyint(1) unsigned NOT NULL default '0', | |||
`online` tinyint(1) unsigned NOT NULL default '0', | |||
PRIMARY KEY (`id`), | |||
UNIQUE KEY `code` (`code`) | |||
) TYPE=MyISAM; | |||
DROP TABLE IF EXISTS `#@__plus`; | |||
CREATE TABLE `#@__plus` ( | |||
`aid` mediumint(8) unsigned NOT NULL auto_increment, | |||
@@ -934,6 +918,18 @@ CREATE TABLE `#@__sys_module` ( | |||
PRIMARY KEY (`id`) | |||
) TYPE=MyISAM; | |||
DROP TABLE IF EXISTS `#@__sys_payment`; | |||
CREATE TABLE `#@__sys_payment` ( | |||
`id` int(11) unsigned NOT NULL auto_increment, | |||
`code` varchar(20) NOT NULL DEFAULT '', | |||
`name` varchar(32) NOT NULL DEFAULT '', | |||
`short_name` varchar(32) DEFAULT '', | |||
`sortrank` int(3) unsigned NOT NULL DEFAULT '0', | |||
`config` text NOT NULL, | |||
`status` int(3) unsigned NOT NULL DEFAULT '0', | |||
PRIMARY KEY (`id`) | |||
) TYPE=MyISAM; | |||
DROP TABLE IF EXISTS `#@__sys_set`; | |||
CREATE TABLE `#@__sys_set` ( | |||
`id` smallint(5) unsigned NOT NULL auto_increment, | |||
@@ -107,4 +107,21 @@ ALTER TABLE `#@__member` ADD COLUMN `loginerr` tinyint NULL DEFAULT 0 AFTER `che | |||
ALTER TABLE `#@__member` ADD COLUMN `send_max` int NULL DEFAULT 0 AFTER `loginerr`; | |||
-- 6.2.3 | |||
INSERT INTO `#@__sysconfig` (`varname`, `info`, `groupid`, `type`, `value`) VALUES ('cfg_bizcore_api', 'DedeBIZ Core接口服务器', 1, 'string', 'http://localhost:8087'); | |||
INSERT INTO `#@__sysconfig` (`varname`, `info`, `groupid`, `type`, `value`) VALUES ('cfg_bizcore_api', 'DedeBIZ Core接口服务器', 1, 'string', 'http://localhost:8087'); | |||
-- 6.2.4 | |||
CREATE TABLE `#@__sys_payment` ( | |||
`id` int(11) unsigned NOT NULL auto_increment, | |||
`code` varchar(20) NOT NULL DEFAULT '', | |||
`name` varchar(32) NOT NULL DEFAULT '', | |||
`short_name` varchar(32) DEFAULT '', | |||
`sortrank` int(3) unsigned NOT NULL DEFAULT '0', | |||
`config` text NOT NULL, | |||
`status` int(3) unsigned NOT NULL DEFAULT '0', | |||
PRIMARY KEY (`id`) | |||
) TYPE=MyISAM; | |||
INSERT INTO `#@__sys_payment`(`id`, `code`, `name`, `short_name`, `sortrank`, `config`, `status`) VALUES (1, 'Wechat', '微信支付', '微信', 0, '{"AppID":"","AppSecret":"","MchID":"","APIV3Key":"","SerialNo":"","PrivateKey":"WechatPrivateKey"}', 0); | |||
INSERT INTO `#@__sys_payment`(`id`, `code`, `name`, `short_name`, `sortrank`, `config`, `status`) VALUES (2, 'Alipay', '支付宝支付', '支付宝', 1, '{"APPID":"","PrivateKey":"","AppCertPublicKey":"AlipayAppCertPublicKey","CertPublicKey":"AlipayCertPublicKey","RootCert":"AlipayRootCert","SignType":"RSA2"}', 0); | |||
INSERT INTO `#@__sys_payment`(`id`, `code`, `name`, `short_name`, `sortrank`, `config`, `status`) VALUES (3, 'Bank', '银行转账', '转账', 2, '{"AccountName":"","AccountNO":"","Name":""}', 0); | |||
INSERT INTO `#@__sys_payment`(`id`, `code`, `name`, `short_name`, `sortrank`, `config`, `status`) VALUES (4, 'Balance', '余额支付', '余额', 3, '[]', 0); | |||
INSERT INTO `#@__sys_payment`(`id`, `code`, `name`, `short_name`, `sortrank`, `config`, `status`) VALUES (5, 'Cod', '货到付款', '货到付款', 4, '[]', 0); |
@@ -7,10 +7,10 @@ | |||
* @link https://www.dedebiz.com | |||
*/ | |||
//系统默认运行模式为安全模式,模板管理、标签管理、数据库管理、模块管理等功能已暂停,如果您需要这些功能,DEDEBIZ_SAFE_MODE后面值`TRUE`改为`FALSE`恢复使用 | |||
define('DEDEBIZ_SAFE_MODE', TRUE); | |||
define('DEDEBIZ_SAFE_MODE', FALSE); | |||
//生产环境使用`production`,如果采用`dev`模式,会有一些php的报错信息提示,用于开发调试 | |||
if (!defined('DEDE_ENVIRONMENT')) { | |||
define('DEDE_ENVIRONMENT', 'production'); | |||
define('DEDE_ENVIRONMENT', 'dev'); | |||
} | |||
if (!defined('DEBUG_LEVEL')) { | |||
if (DEDE_ENVIRONMENT == 'production') { | |||
@@ -217,6 +217,8 @@ if ($cfg_sendmail_bysmtp == 'Y' && !empty($cfg_smtp_usermail)) { | |||
} | |||
//DedeBIZ商业化组件 | |||
require_once(DEDEINC.'/libraries/dedebiz.class.php'); | |||
//第三方SDKs | |||
require_once(DEDEINC.'/sdks/include.php'); | |||
//对全局分页传递参数进行过滤 | |||
if (isset($GLOBALS['PageNo'])) { | |||
$GLOBALS['PageNo'] = intval($GLOBALS['PageNo']); | |||
@@ -226,7 +228,11 @@ if (isset($GLOBALS['TotalResult'])) { | |||
} | |||
if (!isset($cfg_NotPrintHead)) { | |||
if (PHP_SAPI != 'cli') { | |||
header("Content-Type:text/html; charset={$cfg_soft_lang}"); | |||
if (defined('IS_DEDEAPI')) { | |||
header("Content-Type:text/json;"); | |||
} else { | |||
header("Content-Type:text/html; charset={$cfg_soft_lang}"); | |||
} | |||
} | |||
} | |||
//自动加载类库处理 | |||
@@ -0,0 +1,9 @@ | |||
/.git | |||
/.idea | |||
/.DS_Store | |||
/vendor | |||
/Cache | |||
/Test/cert | |||
/nbproject | |||
/composer.lock | |||
/_test/cert |
@@ -0,0 +1,35 @@ | |||
<?php | |||
namespace AliPay; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\BasicAliPay; | |||
/** | |||
* 支付宝App支付网关 | |||
* Class App | |||
* @package AliPay | |||
*/ | |||
class App extends BasicAliPay | |||
{ | |||
/** | |||
* App constructor. | |||
* @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'); | |||
} | |||
/** | |||
* 创建数据操作 | |||
* @param array $options | |||
* @return string | |||
*/ | |||
public function apply($options) | |||
{ | |||
$this->applyData($options); | |||
return http_build_query($this->options->get()); | |||
} | |||
} |
@@ -0,0 +1,34 @@ | |||
<?php | |||
namespace AliPay; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\BasicAliPay; | |||
/** | |||
* 支付宝电子面单下载 | |||
* Class Bill | |||
* @package AliPay | |||
*/ | |||
class Bill extends BasicAliPay | |||
{ | |||
/** | |||
* Bill constructor. | |||
* @param array $options | |||
*/ | |||
public function __construct(array $options) | |||
{ | |||
parent::__construct($options); | |||
$this->options->set('method', 'alipay.data.dataservice.bill.downloadurl.query'); | |||
} | |||
/** | |||
* 创建数据操作 | |||
* @param array $options | |||
* @return array|bool | |||
* @throws \WeChat\Exceptions\InvalidResponseException | |||
* @throws \WeChat\Exceptions\LocalCacheException | |||
*/ | |||
public function apply($options) | |||
{ | |||
return $this->getResult($options); | |||
} | |||
} |
@@ -0,0 +1,35 @@ | |||
<?php | |||
namespace AliPay; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\BasicAliPay; | |||
/** | |||
* 支付宝刷卡支付 | |||
* Class Pos | |||
* @package AliPay | |||
*/ | |||
class Pos extends BasicAliPay | |||
{ | |||
/** | |||
* Pos constructor. | |||
* @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 | |||
* @return array|bool | |||
* @throws \WeChat\Exceptions\InvalidResponseException | |||
* @throws \WeChat\Exceptions\LocalCacheException | |||
*/ | |||
public function apply($options) | |||
{ | |||
return $this->getResult($options); | |||
} | |||
} |
@@ -0,0 +1,34 @@ | |||
<?php | |||
namespace AliPay; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\BasicAliPay; | |||
/** | |||
* 支付宝扫码支付 | |||
* Class Scan | |||
* @package AliPay | |||
*/ | |||
class Scan extends BasicAliPay | |||
{ | |||
/** | |||
* Scan constructor. | |||
* @param array $options | |||
*/ | |||
public function __construct(array $options) | |||
{ | |||
parent::__construct($options); | |||
$this->options->set('method', 'alipay.trade.precreate'); | |||
} | |||
/** | |||
* 创建数据操作 | |||
* @param array $options | |||
* @return array|bool | |||
* @throws \WeChat\Exceptions\InvalidResponseException | |||
* @throws \WeChat\Exceptions\LocalCacheException | |||
*/ | |||
public function apply($options) | |||
{ | |||
return $this->getResult($options); | |||
} | |||
} |
@@ -0,0 +1,67 @@ | |||
<?php | |||
namespace AliPay; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\BasicAliPay; | |||
/** | |||
* 支付宝标准接口 | |||
* Class Trade | |||
* @package AliPay | |||
*/ | |||
class Trade extends BasicAliPay | |||
{ | |||
/** | |||
* 设置交易接口地址 | |||
* @param string $method | |||
* @return $this | |||
*/ | |||
public function setMethod($method) | |||
{ | |||
$this->options->set('method', $method); | |||
return $this; | |||
} | |||
/** | |||
* 获取交易接口地址 | |||
* @return string | |||
*/ | |||
public function getMethod() | |||
{ | |||
return $this->options->get('method'); | |||
} | |||
/** | |||
* 设置接口公共参数 | |||
* @param array $option | |||
* @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 | |||
* @return array|boolean | |||
* @throws \WeChat\Exceptions\InvalidResponseException | |||
* @throws \WeChat\Exceptions\LocalCacheException | |||
*/ | |||
public function apply($options) | |||
{ | |||
return $this->getResult($options); | |||
} | |||
} |
@@ -0,0 +1,91 @@ | |||
<?php | |||
namespace AliPay; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\BasicAliPay; | |||
use WeChat\Exceptions\InvalidArgumentException; | |||
/** | |||
* 支付宝转账到账户 | |||
* Class Transfer | |||
* @package AliPay | |||
*/ | |||
class Transfer extends BasicAliPay | |||
{ | |||
/** | |||
* 旧版 向指定支付宝账户转账 | |||
* @param array $options | |||
* @return array|bool | |||
* @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); | |||
} | |||
/** | |||
* 新版 向指定支付宝账户转账 | |||
* @param array $options | |||
* @return array|bool | |||
* @throws \WeChat\Exceptions\InvalidResponseException | |||
* @throws \WeChat\Exceptions\LocalCacheException | |||
*/ | |||
public function create($options = []) | |||
{ | |||
$this->setAppCertSnAndRootCertSn(); | |||
$this->options->set('method', 'alipay.fund.trans.uni.transfer'); | |||
return $this->getResult($options); | |||
} | |||
/** | |||
* 新版 转账业务单据查询接口 | |||
* @param array $options | |||
* @return array|bool | |||
* @throws \WeChat\Exceptions\InvalidResponseException | |||
* @throws \WeChat\Exceptions\LocalCacheException | |||
*/ | |||
public function queryResult($options = []) | |||
{ | |||
$this->setAppCertSnAndRootCertSn(); | |||
$this->options->set('method', 'alipay.fund.trans.common.query'); | |||
return $this->getResult($options); | |||
} | |||
/** | |||
* 新版 支付宝资金账户资产查询接口 | |||
* @param array $options | |||
* @return array|bool | |||
* @throws \WeChat\Exceptions\InvalidResponseException | |||
* @throws \WeChat\Exceptions\LocalCacheException | |||
*/ | |||
public function queryAccount($options = []) | |||
{ | |||
$this->setAppCertSnAndRootCertSn(); | |||
$this->options->set('method', 'alipay.fund.account.query'); | |||
return $this->getResult($options); | |||
} | |||
/** | |||
* 新版 设置网关应用公钥证书SN、支付宝根证书SN | |||
*/ | |||
protected function setAppCertSnAndRootCertSn() | |||
{ | |||
if (!$this->config->get('app_cert')) { | |||
throw new InvalidArgumentException("Missing Config -- [app_cert]"); | |||
} | |||
if (!$this->config->get('root_cert')) { | |||
throw new InvalidArgumentException("Missing Config -- [root_cert]"); | |||
} | |||
$this->options->set('app_cert_sn', $this->getCertSN($this->config->get('app_cert'))); | |||
$this->options->set('alipay_root_cert_sn', $this->getRootCertSN($this->config->get('root_cert'))); | |||
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]"); | |||
} | |||
} | |||
} |
@@ -0,0 +1,34 @@ | |||
<?php | |||
namespace AliPay; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\BasicAliPay; | |||
/** | |||
* 手机WAP网站支付支持 | |||
* Class Wap | |||
* @package AliPay | |||
*/ | |||
class Wap extends BasicAliPay | |||
{ | |||
/** | |||
* Wap constructor. | |||
* @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'); | |||
} | |||
/** | |||
* 创建数据操作 | |||
* @param array $options | |||
* @return string | |||
*/ | |||
public function apply($options) | |||
{ | |||
parent::applyData($options); | |||
return $this->buildPayHtml(); | |||
} | |||
} |
@@ -0,0 +1,34 @@ | |||
<?php | |||
namespace AliPay; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\BasicAliPay; | |||
/** | |||
* 支付宝网站支付 | |||
* Class Web | |||
* @package AliPay | |||
*/ | |||
class Web extends BasicAliPay | |||
{ | |||
/** | |||
* Web constructor. | |||
* @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'); | |||
} | |||
/** | |||
* 创建数据操作 | |||
* @param array $options | |||
* @return string | |||
*/ | |||
public function apply($options) | |||
{ | |||
parent::applyData($options); | |||
return $this->buildPayHtml(); | |||
} | |||
} |
@@ -0,0 +1,134 @@ | |||
<?php | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\DataArray; | |||
use WeChat\Exceptions\InvalidInstanceException; | |||
/** | |||
* 加载缓存器 | |||
* | |||
* Class We | |||
* @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 = []) 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\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 微信商户打款到银行卡 | |||
*/ | |||
class We | |||
{ | |||
/** | |||
* 定义当前版本 | |||
* @var string | |||
*/ | |||
const VERSION = '1.2.37'; | |||
/** | |||
* 静态配置 | |||
* @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"); | |||
} | |||
} |
@@ -0,0 +1,659 @@ | |||
<?php | |||
namespace WeChat; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\BasicWeChat; | |||
/** | |||
* 卡券管理 | |||
* Class Card | |||
* @package WeChat | |||
*/ | |||
class Card extends BasicWeChat | |||
{ | |||
/** | |||
* 创建卡券 | |||
* @param array $data | |||
* @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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, $data); | |||
} | |||
/** | |||
* 设置买单接口 | |||
* @param string $card_id | |||
* @param bool $is_open | |||
* @return array | |||
* @throws Exceptions\InvalidResponseException | |||
* @throws Exceptions\LocalCacheException | |||
*/ | |||
public function setPaycell($card_id, $is_open = true) | |||
{ | |||
$url = "https://api.weixin.qq.com/card/paycell/set?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['card_id' => $card_id, 'is_open' => $is_open]); | |||
} | |||
/** | |||
* 设置自助核销接口 | |||
* @param string $card_id | |||
* @param bool $is_open | |||
* @return array | |||
* @throws Exceptions\InvalidResponseException | |||
* @throws Exceptions\LocalCacheException | |||
*/ | |||
public function setConsumeCell($card_id, $is_open = true) | |||
{ | |||
$url = "https://api.weixin.qq.com/card/selfconsumecell/set?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['card_id' => $card_id, 'is_open' => $is_open]); | |||
} | |||
/** | |||
* 创建二维码接口 | |||
* @param array $data | |||
* @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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, $data); | |||
} | |||
/** | |||
* 导入自定义code | |||
* @param string $card_id | |||
* @param array $code | |||
* @return array | |||
* @throws Exceptions\InvalidResponseException | |||
* @throws Exceptions\LocalCacheException | |||
*/ | |||
public function deposit($card_id, array $code) | |||
{ | |||
$url = "https://api.weixin.qq.com/card/code/deposit?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['card_id' => $card_id, 'code' => $code]); | |||
} | |||
/** | |||
* 查询导入code数目 | |||
* @param string $card_id | |||
* @return array | |||
* @throws Exceptions\InvalidResponseException | |||
* @throws Exceptions\LocalCacheException | |||
*/ | |||
public function getDepositCount($card_id) | |||
{ | |||
$url = "https://api.weixin.qq.com/card/code/getdepositcount?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['card_id' => $card_id]); | |||
} | |||
/** | |||
* 核查code接口 | |||
* @param string $card_id 进行导入code的卡券ID | |||
* @param array $code 已经微信卡券后台的自定义code,上限为100个 | |||
* @return array | |||
* @throws Exceptions\InvalidResponseException | |||
* @throws Exceptions\LocalCacheException | |||
*/ | |||
public function checkCode($card_id, array $code) | |||
{ | |||
$url = "https://api.weixin.qq.com/card/code/checkcode?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['card_id' => $card_id, 'code' => $code]); | |||
} | |||
/** | |||
* 图文消息群发卡券 | |||
* @param string $card_id | |||
* @return array | |||
* @throws Exceptions\InvalidResponseException | |||
* @throws Exceptions\LocalCacheException | |||
*/ | |||
public function getNewsHtml($card_id) | |||
{ | |||
$url = "https://api.weixin.qq.com/card/mpnews/gethtml?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['card_id' => $card_id]); | |||
} | |||
/** | |||
* 设置测试白名单 | |||
* @param array $openids | |||
* @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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['openid' => $openids, 'username' => $usernames]); | |||
} | |||
/** | |||
* 线下核销查询Code | |||
* @param string $code 单张卡券的唯一标准 | |||
* @param string $card_id 卡券ID代表一类卡券。自定义code卡券必填 | |||
* @param bool $check_consume 是否校验code核销状态,填入true和false时的code异常状态返回数据不同 | |||
* @return array | |||
* @throws Exceptions\InvalidResponseException | |||
* @throws Exceptions\LocalCacheException | |||
*/ | |||
public function getCode($code, $card_id = null, $check_consume = null) | |||
{ | |||
$data = ['code' => $code]; | |||
is_null($card_id) || $data['card_id'] = $card_id; | |||
is_null($check_consume) || $data['check_consume'] = $check_consume; | |||
$url = "https://api.weixin.qq.com/card/code/get?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, $data); | |||
} | |||
/** | |||
* 线下核销核销Code | |||
* @param string $code 需核销的Code码 | |||
* @param null $card_id 券ID。创建卡券时use_custom_code填写true时必填。非自定义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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, $data); | |||
} | |||
/** | |||
* Code解码接口 | |||
* @param string $encrypt_code | |||
* @return array | |||
* @throws Exceptions\InvalidResponseException | |||
* @throws Exceptions\LocalCacheException | |||
*/ | |||
public function decrypt($encrypt_code) | |||
{ | |||
$url = "https://api.weixin.qq.com/card/code/decrypt?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['encrypt_code' => $encrypt_code]); | |||
} | |||
/** | |||
* 获取用户已领取卡券接口 | |||
* @param string $openid | |||
* @param null|string $card_id | |||
* @return array | |||
* @throws Exceptions\InvalidResponseException | |||
* @throws Exceptions\LocalCacheException | |||
*/ | |||
public function getCardList($openid, $card_id = null) | |||
{ | |||
$data = ['openid' => $openid]; | |||
is_null($card_id) || $data['card_id'] = $card_id; | |||
$url = "https://api.weixin.qq.com/card/user/getcardlist?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, $data); | |||
} | |||
/** | |||
* 查看卡券详情 | |||
* @param string $card_id | |||
* @return array | |||
* @throws Exceptions\InvalidResponseException | |||
* @throws Exceptions\LocalCacheException | |||
*/ | |||
public function getCard($card_id) | |||
{ | |||
$url = "https://api.weixin.qq.com/card/get?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['card_id' => $card_id]); | |||
} | |||
/** | |||
* 批量查询卡券列表 | |||
* @param int $offset 查询卡列表的起始偏移量,从0开始,即offset: 5是指从从列表里的第六个开始读取 | |||
* @param int $count 需要查询的卡片的数量(数量最大50) | |||
* @param array $status_list 支持开发者拉出指定状态的卡券列表 | |||
* @return array | |||
* @throws Exceptions\InvalidResponseException | |||
* @throws Exceptions\LocalCacheException | |||
*/ | |||
public function batchGet($offset, $count = 50, array $status_list = []) | |||
{ | |||
$data = ['offset' => $offset, 'count' => $count]; | |||
empty($status_list) || $data['status_list'] = $status_list; | |||
$url = "https://api.weixin.qq.com/card/batchget?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, $data); | |||
} | |||
/** | |||
* 更改卡券信息接口 | |||
* @param string $card_id | |||
* @param array $member_card | |||
* @return array | |||
* @throws Exceptions\InvalidResponseException | |||
* @throws Exceptions\LocalCacheException | |||
*/ | |||
public function updateCard($card_id, array $member_card) | |||
{ | |||
$url = "https://api.weixin.qq.com/card/update?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['card_id' => $card_id, 'member_card' => $member_card]); | |||
} | |||
/** | |||
* 修改库存接口 | |||
* @param string $card_id 卡券ID | |||
* @param null|integer $increase_stock_value 增加多少库存,支持不填或填0 | |||
* @param null|integer $reduce_stock_value 减少多少库存,可以不填或填0 | |||
* @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($increase_stock_value) || $data['increase_stock_value'] = $increase_stock_value; | |||
is_null($reduce_stock_value) || $data['reduce_stock_value'] = $reduce_stock_value; | |||
$url = "https://api.weixin.qq.com/card/modifystock?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, $data); | |||
} | |||
/** | |||
* 删除卡券接口 | |||
* @param string $card_id | |||
* @return array | |||
* @throws Exceptions\InvalidResponseException | |||
* @throws Exceptions\LocalCacheException | |||
*/ | |||
public function deleteCard($card_id) | |||
{ | |||
$url = "https://api.weixin.qq.com/card/delete?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['card_id' => $card_id]); | |||
} | |||
/** | |||
* 设置卡券失效接口 | |||
* @param string $code | |||
* @param string $card_id | |||
* @param null|string $reason | |||
* @return array | |||
* @throws Exceptions\InvalidResponseException | |||
* @throws Exceptions\LocalCacheException | |||
*/ | |||
public function unAvailable($code, $card_id, $reason = null) | |||
{ | |||
$data = ['code' => $code, 'card_id' => $card_id]; | |||
is_null($reason) || $data['reason'] = $reason; | |||
$url = "https://api.weixin.qq.com/card/code/unavailable?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, $data); | |||
} | |||
/** | |||
* 拉取卡券概况数据接口 | |||
* @param string $begin_date 查询数据的起始时间 | |||
* @param string $end_date 查询数据的截至时间 | |||
* @param string $cond_source 卡券来源(0为公众平台创建的卡券数据 1是API创建的卡券数据) | |||
* @return array | |||
* @throws Exceptions\InvalidResponseException | |||
* @throws Exceptions\LocalCacheException | |||
*/ | |||
public function getCardBizuininfo($begin_date, $end_date, $cond_source) | |||
{ | |||
$data = ['begin_date' => $begin_date, 'end_date' => $end_date, 'cond_source' => $cond_source]; | |||
$url = "https://api.weixin.qq.com/datacube/getcardbizuininfo?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, $data); | |||
} | |||
/** | |||
* 获取免费券数据接口 | |||
* @param string $begin_date 查询数据的起始时间 | |||
* @param string $end_date 查询数据的截至时间 | |||
* @param integer $cond_source 卡券来源,0为公众平台创建的卡券数据、1是API创建的卡券数据 | |||
* @param null $card_id 卡券ID | |||
* @return array | |||
* @throws Exceptions\InvalidResponseException | |||
* @throws Exceptions\LocalCacheException | |||
*/ | |||
public function getCardCardinfo($begin_date, $end_date, $cond_source, $card_id = null) | |||
{ | |||
$data = ['begin_date' => $begin_date, 'end_date' => $end_date, 'cond_source' => $cond_source]; | |||
is_null($card_id) || $data['card_id'] = $card_id; | |||
$url = "https://api.weixin.qq.com/datacube/getcardcardinfo?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($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'; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($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'; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, $data); | |||
} | |||
/** | |||
* 获取用户提交资料 | |||
* 根据activate_ticket获取到用户填写的信息 | |||
* @param string $activate_ticket | |||
* @return array | |||
* @throws Exceptions\InvalidResponseException | |||
* @throws Exceptions\LocalCacheException | |||
*/ | |||
public function getActivateMemberCardTempinfo($activate_ticket) | |||
{ | |||
$url = 'https://api.weixin.qq.com/card/membercard/activatetempinfo/get?access_token=ACCESS_TOKEN'; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['activate_ticket' => $activate_ticket]); | |||
} | |||
/** | |||
* 更新会员信息 | |||
* @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'; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, $data); | |||
} | |||
/** | |||
* 拉取会员卡概况数据接口 | |||
* @param string $begin_date 查询数据的起始时间 | |||
* @param string $end_date 查询数据的截至时间 | |||
* @param string $cond_source 卡券来源(0为公众平台创建的卡券数据 1是API创建的卡券数据) | |||
* @return array | |||
* @throws Exceptions\InvalidResponseException | |||
* @throws Exceptions\LocalCacheException | |||
*/ | |||
public function getCardMemberCardinfo($begin_date, $end_date, $cond_source) | |||
{ | |||
$data = ['begin_date' => $begin_date, 'end_date' => $end_date, 'cond_source' => $cond_source]; | |||
$url = "https://api.weixin.qq.com/datacube/getcardmembercardinfo?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, $data); | |||
} | |||
/** | |||
* 拉取单张会员卡数据接口 | |||
* @param string $begin_date 查询数据的起始时间 | |||
* @param string $end_date 查询数据的截至时间 | |||
* @param string $card_id 卡券id | |||
* @return array | |||
* @throws Exceptions\InvalidResponseException | |||
* @throws Exceptions\LocalCacheException | |||
*/ | |||
public function getCardMemberCardDetail($begin_date, $end_date, $card_id) | |||
{ | |||
$data = ['begin_date' => $begin_date, 'end_date' => $end_date, 'card_id' => $card_id]; | |||
$url = "https://api.weixin.qq.com/datacube/getcardmembercarddetail?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, $data); | |||
} | |||
/** | |||
* 拉取会员信息(积分查询)接口 | |||
* @param string $card_id 查询会员卡的cardid | |||
* @param string $code 所查询用户领取到的code值 | |||
* @return array | |||
* @throws Exceptions\InvalidResponseException | |||
* @throws Exceptions\LocalCacheException | |||
*/ | |||
public function getCardMemberCard($card_id, $code) | |||
{ | |||
$data = ['card_id' => $card_id, 'code' => $code]; | |||
$url = "https://api.weixin.qq.com/card/membercard/userinfo/get?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, $data); | |||
} | |||
/** | |||
* 删除支付后投放卡券规则 | |||
* @param integer $rule_id 支付即会员的规则名称 | |||
* @return array | |||
* @throws Exceptions\InvalidResponseException | |||
* @throws Exceptions\LocalCacheException | |||
*/ | |||
public function delPayGiftCard($rule_id) | |||
{ | |||
$url = "https://api.weixin.qq.com/card/paygiftcard/add?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['rule_id' => $rule_id]); | |||
} | |||
/** | |||
* 查询支付后投放卡券规则详情 | |||
* @param integer $rule_id 要查询规则id | |||
* @return array | |||
* @throws Exceptions\InvalidResponseException | |||
* @throws Exceptions\LocalCacheException | |||
*/ | |||
public function getPayGiftCard($rule_id) | |||
{ | |||
$url = "https://api.weixin.qq.com/card/paygiftcard/getbyid?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['rule_id' => $rule_id]); | |||
} | |||
/** | |||
* 批量查询支付后投放卡券规则 | |||
* @param integer $offset 起始偏移量 | |||
* @param integer $count 查询的数量 | |||
* @param bool $effective 是否仅查询生效的规则 | |||
* @return array | |||
* @throws Exceptions\InvalidResponseException | |||
* @throws Exceptions\LocalCacheException | |||
*/ | |||
public function batchGetPayGiftCard($offset = 0, $count = 10, $effective = true) | |||
{ | |||
$data = ['type' => 'RULE_TYPE_PAY_MEMBER_CARD', 'offset' => $offset, 'count' => $count, 'effective' => $effective]; | |||
$url = "https://api.weixin.qq.com/card/paygiftcard/batchget?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpGetForJson($url); | |||
} | |||
/** | |||
* 对优惠券批价 | |||
* @param string $card_id 需要来配置库存的card_id | |||
* @param integer $quantity 本次需要兑换的库存数目 | |||
* @return array | |||
* @throws Exceptions\InvalidResponseException | |||
* @throws Exceptions\LocalCacheException | |||
*/ | |||
public function getPayprice($card_id, $quantity) | |||
{ | |||
$url = "POST https://api.weixin.qq.com/card/pay/getpayprice?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['card_id' => $card_id, '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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpGetForJson($url); | |||
} | |||
/** | |||
* 确认兑换库存接口 | |||
* @param string $card_id 需要来兑换库存的card_id | |||
* @param integer $quantity 本次需要兑换的库存数目 | |||
* @param string $order_id 仅可以使用上面得到的订单号,保证批价有效性 | |||
* @return array | |||
* @throws Exceptions\InvalidResponseException | |||
* @throws Exceptions\LocalCacheException | |||
*/ | |||
public function payConfirm($card_id, $quantity, $order_id) | |||
{ | |||
$data = ['card_id' => $card_id, 'quantity' => $quantity, 'order_id' => $order_id]; | |||
$url = "https://api.weixin.qq.com/card/pay/confirm?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, $data); | |||
} | |||
/** | |||
* 充值券点接口 | |||
* @param integer $coin_count | |||
* @return array | |||
* @throws Exceptions\InvalidResponseException | |||
* @throws Exceptions\LocalCacheException | |||
*/ | |||
public function payRecharge($coin_count) | |||
{ | |||
$url = "https://api.weixin.qq.com/card/pay/recharge?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['coin_count' => $coin_count]); | |||
} | |||
/** | |||
* 查询订单详情接口 | |||
* @param string $order_id | |||
* @return array | |||
* @throws Exceptions\InvalidResponseException | |||
* @throws Exceptions\LocalCacheException | |||
*/ | |||
public function payGetOrder($order_id) | |||
{ | |||
$url = "https://api.weixin.qq.com/card/pay/getorder?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['order_id' => $order_id]); | |||
} | |||
/** | |||
* 查询券点流水详情接口 | |||
* @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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, $data); | |||
} | |||
} |
@@ -0,0 +1,356 @@ | |||
<?php | |||
namespace WeChat\Contracts; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Exceptions\InvalidArgumentException; | |||
use WeChat\Exceptions\InvalidResponseException; | |||
/** | |||
* 支付宝支付基类 | |||
* Class AliPay | |||
* @package AliPay\Contracts | |||
*/ | |||
abstract class BasicAliPay | |||
{ | |||
/** | |||
* 支持配置 | |||
* @var DataArray | |||
*/ | |||
protected $config; | |||
/** | |||
* 当前请求数据 | |||
* @var DataArray | |||
*/ | |||
protected $options; | |||
/** | |||
* DzContent数据 | |||
* @var DataArray | |||
*/ | |||
protected $params; | |||
/** | |||
* 静态缓存 | |||
* @var static | |||
*/ | |||
protected static $cache; | |||
/** | |||
* 正常请求网关 | |||
* @var string | |||
*/ | |||
protected $gateway = 'https://openapi.alipay.com/gateway.do?charset=utf-8'; | |||
/** | |||
* AliPay constructor. | |||
* @param array $options | |||
*/ | |||
public function __construct($options) | |||
{ | |||
$this->params = new DataArray([]); | |||
$this->config = new DataArray($options); | |||
if (empty($options['appid'])) { | |||
throw new InvalidArgumentException("Missing Config -- [appid]"); | |||
} | |||
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.alipaydev.com/gateway.do?charset=utf-8'; | |||
} | |||
$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']); | |||
} | |||
} | |||
/** | |||
* 静态创建对象 | |||
* @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 $out_trade_no | |||
* @return array|boolean | |||
* @throws \WeChat\Exceptions\InvalidResponseException | |||
* @throws \WeChat\Exceptions\LocalCacheException | |||
*/ | |||
public function query($out_trade_no = '') | |||
{ | |||
$this->options->set('method', 'alipay.trade.query'); | |||
return $this->getResult(['out_trade_no' => $out_trade_no]); | |||
} | |||
/** | |||
* 支付宝订单退款操作 | |||
* @param array|string $options 退款参数或退款商户订单号 | |||
* @param null $refund_amount 退款金额 | |||
* @return array|boolean | |||
* @throws \WeChat\Exceptions\InvalidResponseException | |||
* @throws \WeChat\Exceptions\LocalCacheException | |||
*/ | |||
public function refund($options, $refund_amount = null) | |||
{ | |||
if (!is_array($options)) $options = ['out_trade_no' => $options, 'refund_amount' => $refund_amount]; | |||
$this->options->set('method', 'alipay.trade.refund'); | |||
return $this->getResult($options); | |||
} | |||
/** | |||
* 关闭支付宝进行中的订单 | |||
* @param array|string $options | |||
* @return array|boolean | |||
* @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); | |||
$content = wordwrap($this->config->get('public_key'), 64, "\n", true); | |||
$res = "-----BEGIN PUBLIC KEY-----\n{$content}\n-----END PUBLIC KEY-----"; | |||
if (openssl_verify($string, base64_decode($data['sign']), $res, OPENSSL_ALGO_SHA256) !== 1) { | |||
throw new InvalidResponseException('Data signature verification failed.', 0, $data); | |||
} | |||
return $data; | |||
} | |||
/** | |||
* 验证接口返回的数据签名 | |||
* @param array $data 通知数据 | |||
* @param null|string $sign 数据签名 | |||
* @return array | |||
* @throws \WeChat\Exceptions\InvalidResponseException | |||
*/ | |||
protected function verify($data, $sign) | |||
{ | |||
$content = wordwrap($this->config->get('public_key'), 64, "\n", true); | |||
$res = "-----BEGIN PUBLIC KEY-----\n{$content}\n-----END PUBLIC KEY-----"; | |||
if ($this->options->get('sign_type') === 'RSA2') { | |||
if (openssl_verify(json_encode($data, 256), base64_decode($sign), $res, OPENSSL_ALGO_SHA256) !== 1) { | |||
throw new InvalidResponseException('Data signature verification failed.'); | |||
} | |||
} else { | |||
if (openssl_verify(json_encode($data, 256), base64_decode($sign), $res, OPENSSL_ALGO_SHA1) !== 1) { | |||
throw new InvalidResponseException('Data signature verification failed.'); | |||
} | |||
} | |||
return $data; | |||
} | |||
/** | |||
* 获取数据签名 | |||
* @return string | |||
*/ | |||
protected function getSign() | |||
{ | |||
$content = wordwrap($this->trimCert($this->config->get('private_key')), 64, "\n", true); | |||
$string = "-----BEGIN RSA PRIVATE KEY-----\n{$content}\n-----END RSA PRIVATE KEY-----"; | |||
if ($this->options->get('sign_type') === 'RSA2') { | |||
openssl_sign($this->getSignContent($this->options->get(), true), $sign, $string, OPENSSL_ALGO_SHA256); | |||
} else { | |||
openssl_sign($this->getSignContent($this->options->get(), true), $sign, $string, OPENSSL_ALGO_SHA1); | |||
} | |||
return base64_encode($sign); | |||
} | |||
/** | |||
* 去除证书前后内容及空白 | |||
* @param string $sign | |||
* @return string | |||
*/ | |||
protected function trimCert($sign) | |||
{ | |||
// if (file_exists($sign)) $sign = file_get_contents($sign); | |||
return preg_replace(['/\s+/', '/\-{5}.*?\-{5}/'], '', $sign); | |||
} | |||
/** | |||
* 数据签名处理 | |||
* @param array $data 需要进行签名数据 | |||
* @param boolean $needSignType 是否需要sign_type字段 | |||
* @return string | |||
*/ | |||
private function getSignContent(array $data, $needSignType = false) | |||
{ | |||
list($attrs,) = [[], ksort($data)]; | |||
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); | |||
} | |||
/** | |||
* 数据包生成及数据签名 | |||
* @param array $options | |||
*/ | |||
protected function applyData($options) | |||
{ | |||
$this->options->set('biz_content', json_encode($this->params->merge($options), 256)); | |||
$this->options->set('sign', $this->getSign()); | |||
} | |||
/** | |||
* 请求接口并验证访问数据 | |||
* @param array $options | |||
* @return array|boolean | |||
* @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']); | |||
} | |||
/** | |||
* 生成支付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("'", ''', $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>"; | |||
} | |||
/** | |||
* 新版 从证书中提取序列号 | |||
* @param string $sign | |||
* @return string | |||
*/ | |||
public function getCertSN($sign) | |||
{ | |||
// if (file_exists($sign)) $sign = file_get_contents($sign); | |||
$ssl = openssl_x509_parse($sign); | |||
return md5($this->_arr2str(array_reverse($ssl['issuer'])) . $ssl['serialNumber']); | |||
} | |||
/** | |||
* 新版 提取根证书序列号 | |||
* @param string $sign | |||
* @return string|null | |||
*/ | |||
public function getRootCertSN($sign) | |||
{ | |||
$sn = null; | |||
// if (file_exists($sign)) $sign = file_get_contents($sign); | |||
$array = explode("-----END CERTIFICATE-----", $sign); | |||
for ($i = 0; $i < count($array) - 1; $i++) { | |||
$ssl[$i] = openssl_x509_parse($array[$i] . "-----END CERTIFICATE-----"); | |||
if (strpos($ssl[$i]['serialNumber'], '0x') === 0) { | |||
$ssl[$i]['serialNumber'] = $this->_hex2dec($ssl[$i]['serialNumber']); | |||
} | |||
if ($ssl[$i]['signatureTypeLN'] == "sha1WithRSAEncryption" || $ssl[$i]['signatureTypeLN'] == "sha256WithRSAEncryption") { | |||
if ($sn == null) { | |||
$sn = md5($this->_arr2str(array_reverse($ssl[$i]['issuer'])) . $ssl[$i]['serialNumber']); | |||
} else { | |||
$sn = $sn . "_" . md5($this->_arr2str(array_reverse($ssl[$i]['issuer'])) . $ssl[$i]['serialNumber']); | |||
} | |||
} | |||
} | |||
return $sn; | |||
} | |||
/** | |||
* 新版 数组转字符串 | |||
* @param array $array | |||
* @return string | |||
*/ | |||
private function _arr2str($array) | |||
{ | |||
$string = []; | |||
if ($array && is_array($array)) { | |||
foreach ($array as $key => $value) { | |||
$string[] = $key . '=' . $value; | |||
} | |||
} | |||
return implode(',', $string); | |||
} | |||
/** | |||
* 新版 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; | |||
} | |||
/** | |||
* 应用数据操作 | |||
* @param array $options | |||
* @return mixed | |||
*/ | |||
abstract public function apply($options); | |||
} |
@@ -0,0 +1,218 @@ | |||
<?php | |||
namespace WeChat\Contracts; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Exceptions\InvalidArgumentException; | |||
use WeChat\Exceptions\InvalidDecryptException; | |||
use WeChat\Exceptions\InvalidResponseException; | |||
/** | |||
* 微信通知处理基本类 | |||
* Class BasicPushEvent | |||
* @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 | |||
* @throws \WeChat\Exceptions\InvalidResponseException | |||
*/ | |||
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 (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 = file_get_contents("php://input"); | |||
$this->encryptType = $this->input->get('encrypt_type'); | |||
if ($this->isEncrypt()) { | |||
if (empty($options['encodingaeskey'])) { | |||
throw new InvalidArgumentException("Missing Config -- [encodingaeskey]"); | |||
} | |||
if (!class_exists('Prpcrypt', false)) { | |||
require __DIR__ . '/Prpcrypt.php'; | |||
} | |||
$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()) { | |||
@ob_clean(); | |||
exit($this->input->get('echostr')); | |||
} else { | |||
throw new InvalidResponseException('Invalid interface request.', '0'); | |||
} | |||
} | |||
/** | |||
* 消息是否需要加密 | |||
* @return boolean | |||
*/ | |||
public function isEncrypt() | |||
{ | |||
return $this->encryptType === 'aes'; | |||
} | |||
/** | |||
* 回复消息 | |||
* @param array $data 消息内容 | |||
* @param boolean $return 是否返回XML内容 | |||
* @param boolean $isEncrypt 是否加密内容 | |||
* @return string | |||
* @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) { | |||
if (!class_exists('Prpcrypt', false)) { | |||
require __DIR__ . '/Prpcrypt.php'; | |||
} | |||
$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 string $str | |||
* @return bool | |||
*/ | |||
private function checkSignature($str = '') | |||
{ | |||
$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, $str]; | |||
sort($tmpArr, SORT_STRING); | |||
return sha1(implode($tmpArr)) === $signature; | |||
} | |||
/** | |||
* 获取公众号推送对象 | |||
* @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'); | |||
} | |||
} |
@@ -0,0 +1,235 @@ | |||
<?php | |||
namespace WeChat\Contracts; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Exceptions\InvalidArgumentException; | |||
use WeChat\Exceptions\InvalidResponseException; | |||
/** | |||
* Class BasicWeChat | |||
* @package WeChat\Contracts | |||
*/ | |||
class BasicWeChat | |||
{ | |||
/** | |||
* 当前微信配置 | |||
* @var DataArray | |||
*/ | |||
public $config; | |||
/** | |||
* 访问AccessToken | |||
* @var string | |||
*/ | |||
public $access_token = ''; | |||
/** | |||
* 当前请求方法参数 | |||
* @var array | |||
*/ | |||
protected $currentMethod = []; | |||
/** | |||
* 当前模式 | |||
* @var bool | |||
*/ | |||
protected $isTry = false; | |||
/** | |||
* 静态缓存 | |||
* @var static | |||
*/ | |||
protected static $cache; | |||
/** | |||
* 注册代替函数 | |||
* @var string | |||
*/ | |||
protected $GetAccessTokenCallback; | |||
/** | |||
* BasicWeChat constructor. | |||
* @param array $options | |||
*/ | |||
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 | |||
* @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); | |||
} | |||
/** | |||
* 获取访问 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); | |||
} | |||
/** | |||
* 清理删除 AccessToken | |||
* @return bool | |||
*/ | |||
public function delAccessToken() | |||
{ | |||
$this->access_token = ''; | |||
return Tools::delCache($this->config->get('appid') . '_access_token'); | |||
} | |||
/** | |||
* 以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()); | |||
} | |||
} | |||
/** | |||
* 以POST获取接口数据并转为数组 | |||
* @param string $url 接口地址 | |||
* @param array $data 请求数据 | |||
* @param bool $buildToJson | |||
* @return array | |||
* @throws \WeChat\Exceptions\InvalidResponseException | |||
* @throws \WeChat\Exceptions\LocalCacheException | |||
*/ | |||
protected function httpPostForJson($url, array $data, $buildToJson = true) | |||
{ | |||
try { | |||
$options = []; | |||
if ($buildToJson) $options['headers'] = ['Content-Type: application/json']; | |||
return Tools::json2arr(Tools::post($url, $buildToJson ? 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()); | |||
} | |||
} | |||
/** | |||
* 注册当前请求接口 | |||
* @param string $url 接口地址 | |||
* @param string $method 当前接口方法 | |||
* @param array $arguments 请求参数 | |||
* @return string | |||
* @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); | |||
} | |||
/** | |||
* 接口通用POST请求方法 | |||
* @param string $url 接口URL | |||
* @param array $data POST提交接口参数 | |||
* @param bool $isBuildJson | |||
* @return array | |||
* @throws \WeChat\Exceptions\InvalidResponseException | |||
* @throws \WeChat\Exceptions\LocalCacheException | |||
*/ | |||
public function callPostApi($url, array $data, $isBuildJson = true) | |||
{ | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, $data, $isBuildJson); | |||
} | |||
/** | |||
* 接口通用GET请求方法 | |||
* @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); | |||
} | |||
} |
@@ -0,0 +1,194 @@ | |||
<?php | |||
namespace WeChat\Contracts; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Exceptions\InvalidArgumentException; | |||
use WeChat\Exceptions\InvalidResponseException; | |||
/** | |||
* 微信支付基础类 | |||
* Class BasicPay | |||
* @package WeChat\Contracts | |||
*/ | |||
class BasicWePay | |||
{ | |||
/** | |||
* 商户配置 | |||
* @var DataArray | |||
*/ | |||
protected $config; | |||
/** | |||
* 当前请求数据 | |||
* @var DataArray | |||
*/ | |||
protected $params; | |||
/** | |||
* 静态缓存 | |||
* @var static | |||
*/ | |||
protected static $cache; | |||
/** | |||
* WeChat constructor. | |||
* @param array $options | |||
*/ | |||
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); | |||
} | |||
/** | |||
* 获取微信支付通知 | |||
* @return array | |||
* @throws \WeChat\Exceptions\InvalidResponseException | |||
*/ | |||
public function getNotify() | |||
{ | |||
$data = Tools::xml2arr(file_get_contents('php://input')); | |||
if (isset($data['sign']) && $this->getPaySign($data) === $data['sign']) { | |||
return $data; | |||
} | |||
throw new InvalidResponseException('Invalid Notify.', '0'); | |||
} | |||
/** | |||
* 获取微信支付通知回复内容 | |||
* @return string | |||
*/ | |||
public function getNotifySuccessReply() | |||
{ | |||
return Tools::arr2xml(['return_code' => 'SUCCESS', 'return_msg' => 'OK']); | |||
} | |||
/** | |||
* 生成支付签名 | |||
* @param array $data 参与签名的数据 | |||
* @param string $signType 参与签名的类型 | |||
* @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'))); | |||
} | |||
/** | |||
* 转换短链接 | |||
* @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]); | |||
} | |||
/** | |||
* 数组直接转xml数据输出 | |||
* @param array $data | |||
* @param bool $isReturn | |||
* @return string | |||
*/ | |||
public function toXml(array $data, $isReturn = false) | |||
{ | |||
$xml = Tools::arr2xml($data); | |||
if ($isReturn) { | |||
return $xml; | |||
} | |||
echo $xml; | |||
} | |||
/** | |||
* 以 Post 请求接口 | |||
* @param string $url 请求 | |||
* @param array $data 接口参数 | |||
* @param bool $isCert 是否需要使用双向证书 | |||
* @param string $signType 数据签名类型 MD5|SHA256 | |||
* @param bool $needSignType 是否需要传签名类型参数 | |||
* @param bool $needNonceStr | |||
* @return array | |||
* @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; | |||
} | |||
} |
@@ -0,0 +1,28 @@ | |||
<?php | |||
namespace WeChat\Contracts; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
/** | |||
* 企业微信基础类 | |||
* Class BasicWeWork | |||
* @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']; | |||
} | |||
} |
@@ -0,0 +1,115 @@ | |||
<?php | |||
namespace WeChat\Contracts; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use ArrayAccess; | |||
/** | |||
* Class DataArray | |||
* @package WeChat | |||
*/ | |||
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|null $offset | |||
* @return array|string|null | |||
*/ | |||
public function get($offset = null) | |||
{ | |||
return $this->offsetGet($offset); | |||
} | |||
/** | |||
* 合并数据到对象 | |||
* @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); | |||
} | |||
/** | |||
* 设置配置项值 | |||
* @param string $offset | |||
* @param string|array|null|integer $value | |||
*/ | |||
#[\ReturnTypeWillChange] | |||
public function offsetSet($offset, $value) | |||
{ | |||
if (is_null($offset)) { | |||
$this->config[] = $value; | |||
} else { | |||
$this->config[$offset] = $value; | |||
} | |||
} | |||
/** | |||
* 判断配置Key是否存在 | |||
* @param string $offset | |||
* @return bool | |||
*/ | |||
#[\ReturnTypeWillChange] | |||
public function offsetExists($offset) | |||
{ | |||
return isset($this->config[$offset]); | |||
} | |||
/** | |||
* 清理配置项 | |||
* @param string|null $offset | |||
*/ | |||
#[\ReturnTypeWillChange] | |||
public function offsetUnset($offset = null) | |||
{ | |||
if (is_null($offset)) { | |||
$this->config = []; | |||
} else { | |||
unset($this->config[$offset]); | |||
} | |||
} | |||
/** | |||
* 获取配置项参数 | |||
* @param string|null $offset | |||
* @return array|string|null | |||
*/ | |||
#[\ReturnTypeWillChange] | |||
public function offsetGet($offset = null) | |||
{ | |||
if (is_null($offset)) { | |||
return $this->config; | |||
} | |||
return isset($this->config[$offset]) ? $this->config[$offset] : null; | |||
} | |||
} |
@@ -0,0 +1,181 @@ | |||
<?php | |||
namespace WeChat\Contracts; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
/** | |||
* 错误消息处理 | |||
* Class DataError | |||
* @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; | |||
} | |||
} |
@@ -0,0 +1,65 @@ | |||
<?php | |||
namespace WeChat\Contracts; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
/** | |||
* 自定义CURL文件类 | |||
* Class MyCurlFile | |||
* @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); | |||
} | |||
} |
@@ -0,0 +1,177 @@ | |||
<?php | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
/** | |||
* PKCS7算法 - 加解密 | |||
* Class PKCS7Encoder | |||
*/ | |||
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); | |||
} | |||
} | |||
/** | |||
* 公众号消息 - 加解密 | |||
* Class 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]; | |||
} | |||
} | |||
/** | |||
* 对密文进行解密 | |||
* @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]; | |||
} | |||
} | |||
/** | |||
* 随机生成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; | |||
} | |||
} | |||
/** | |||
* 仅用作类内部使用 | |||
* 不用于官方API接口的errCode码 | |||
* Class ErrorCode | |||
*/ | |||
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; | |||
} | |||
} |
@@ -0,0 +1,458 @@ | |||
<?php | |||
namespace WeChat\Contracts; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Exceptions\InvalidArgumentException; | |||
use WeChat\Exceptions\InvalidResponseException; | |||
use WeChat\Exceptions\LocalCacheException; | |||
/** | |||
* 网络请求支持 | |||
* Class Tools | |||
* @package WeChat\Contracts | |||
*/ | |||
class Tools | |||
{ | |||
/** | |||
* 缓存路径 | |||
* @var null | |||
*/ | |||
public static $cache_path = null; | |||
/** | |||
* 缓存写入操作 | |||
* @var array | |||
*/ | |||
public static $cache_callable = [ | |||
'set' => null, // 写入缓存 | |||
'get' => null, // 获取缓存 | |||
'del' => null, // 删除缓存 | |||
'put' => null, // 写入文件 | |||
]; | |||
/** | |||
* 网络缓存 | |||
* @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; | |||
} | |||
/** | |||
* 根据文件后缀获取文件类型 | |||
* @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; | |||
} | |||
/** | |||
* 创建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; | |||
} | |||
/** | |||
* 数组转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 | |||
*/ | |||
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 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 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反解析处理 | |||
* @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原形转换为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 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); | |||
} | |||
/** | |||
* 以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); | |||
} | |||
/** | |||
* 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数据设置 | |||
if (strtolower($method) === 'post') { | |||
curl_setopt($curl, CURLOPT_POST, true); | |||
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, 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); | |||
list($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; | |||
} | |||
/** | |||
* 写入文件 | |||
* @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; | |||
} | |||
/** | |||
* 缓存配置与存储 | |||
* @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; | |||
} | |||
/** | |||
* 获取缓存内容 | |||
* @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 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 | |||
* @return string | |||
*/ | |||
private static function _getCacheName($name) | |||
{ | |||
if (empty(self::$cache_path)) { | |||
self::$cache_path = dirname(dirname(__DIR__)) . DIRECTORY_SEPARATOR . 'Cache' . DIRECTORY_SEPARATOR; | |||
} | |||
self::$cache_path = rtrim(self::$cache_path, '/\\') . DIRECTORY_SEPARATOR; | |||
file_exists(self::$cache_path) || mkdir(self::$cache_path, 0755, true); | |||
return self::$cache_path . $name; | |||
} | |||
} |
@@ -0,0 +1,233 @@ | |||
<?php | |||
namespace WeChat; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\BasicWeChat; | |||
use WeChat\Contracts\Tools; | |||
/** | |||
* 客服消息处理 | |||
* Class Custom | |||
* @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) | |||
{ | |||
$data = ['kf_account' => $kf_account, 'nickname' => $nickname]; | |||
$url = "https://api.weixin.qq.com/customservice/kfaccount/add?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, $data); | |||
} | |||
/** | |||
* 修改客服帐号 | |||
* @param string $kf_account 客服账号 | |||
* @param string $nickname 客服昵称 | |||
* @return array | |||
* @throws Exceptions\InvalidResponseException | |||
* @throws Exceptions\LocalCacheException | |||
*/ | |||
public function updateAccount($kf_account, $nickname) | |||
{ | |||
$data = ['kf_account' => $kf_account, 'nickname' => $nickname]; | |||
$url = "https://api.weixin.qq.com/customservice/kfaccount/update?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, $data); | |||
} | |||
/** | |||
* 删除客服帐号 | |||
* @param string $kf_account 客服账号 | |||
* @return array | |||
* @throws Exceptions\InvalidResponseException | |||
* @throws Exceptions\LocalCacheException | |||
*/ | |||
public function deleteAccount($kf_account) | |||
{ | |||
$data = ['kf_account' => $kf_account]; | |||
$url = "https://api.weixin.qq.com/customservice/kfaccount/del?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, $data); | |||
} | |||
/** | |||
* 邀请绑定客服帐号 | |||
* @param string $kf_account 完整客服帐号,格式为:帐号前缀@公众号微信号 | |||
* @param string $invite_wx 接收绑定邀请的客服微信号 | |||
* @return array | |||
* @throws Exceptions\InvalidResponseException | |||
* @throws Exceptions\LocalCacheException | |||
*/ | |||
public function inviteWorker($kf_account, $invite_wx) | |||
{ | |||
$url = 'https://api.weixin.qq.com/customservice/kfaccount/inviteworker?access_token=ACCESS_TOKEN'; | |||
return $this->callPostApi($url, ['kf_account' => $kf_account, '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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpGetForJson($url); | |||
} | |||
/** | |||
* 设置客服帐号的头像 | |||
* @param string $kf_account 客户账号 | |||
* @param string $image 头像文件位置 | |||
* @return array | |||
* @throws Exceptions\InvalidResponseException | |||
* @throws Exceptions\LocalCacheException | |||
*/ | |||
public function uploadHeadimg($kf_account, $image) | |||
{ | |||
$url = "http://api.weixin.qq.com/customservice/kfaccount/uploadheadimg?access_token=ACCESS_TOKEN&kf_account={$kf_account}"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['media' => Tools::createCurlFile($image)]); | |||
} | |||
/** | |||
* 客服接口-发消息 | |||
* @param array $data | |||
* @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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, $data); | |||
} | |||
/** | |||
* 删除群发【订阅号与服务号认证后均可用】 | |||
* @param integer $msg_id 发送出去的消息ID | |||
* @param null|integer $article_idx 要删除的文章在图文消息中的位置,第一篇编号为1,该字段不填或填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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, $data); | |||
} | |||
/** | |||
* 查询群发消息发送状态【订阅号与服务号认证后均可用】 | |||
* @param integer $msg_id 群发消息后返回的消息id | |||
* @return array | |||
* @throws Exceptions\InvalidResponseException | |||
* @throws Exceptions\LocalCacheException | |||
*/ | |||
public function massGet($msg_id) | |||
{ | |||
$url = "https://api.weixin.qq.com/cgi-bin/message/mass/get?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['msg_id' => $msg_id]); | |||
} | |||
/** | |||
* 获取群发速度 | |||
* @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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, []); | |||
} | |||
/** | |||
* 设置群发速度 | |||
* @param integer $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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['speed' => $speed]); | |||
} | |||
} |
@@ -0,0 +1,118 @@ | |||
<?php | |||
namespace WeChat; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\BasicWeChat; | |||
/** | |||
* 微信草稿箱管理 | |||
* Class Draft | |||
* @author taoxin | |||
* @package WeChat | |||
*/ | |||
class Draft extends BasicWeChat | |||
{ | |||
/** | |||
* 新建草稿 | |||
* @param $articles | |||
* @return array | |||
* @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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['articles' => $articles]); | |||
} | |||
/** | |||
* 获取草稿 | |||
* @param string $media_id | |||
* @param string $outType 返回处理函数 | |||
* @return array | |||
* @throws \WeChat\Exceptions\InvalidResponseException | |||
* @throws \WeChat\Exceptions\LocalCacheException | |||
*/ | |||
public function get($media_id, $outType = null) | |||
{ | |||
$url = "https://api.weixin.qq.com/cgi-bin/draft/get?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['media_id' => $media_id]); | |||
} | |||
/** | |||
* 删除草稿 | |||
* @param string $media_id | |||
* @return array | |||
* @throws \WeChat\Exceptions\InvalidResponseException | |||
* @throws \WeChat\Exceptions\LocalCacheException | |||
*/ | |||
public function delete($media_id) | |||
{ | |||
$url = "https://api.weixin.qq.com/cgi-bin/draft/delete?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['media_id' => $media_id]); | |||
} | |||
/** | |||
* 新增图文素材 | |||
* @param array $data 文件名称 | |||
* @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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, $data); | |||
} | |||
/** | |||
* 修改草稿 | |||
* @param string $media_id 要修改的图文消息的id | |||
* @param int $index 要更新的文章在图文消息中的位置(多图文消息时,此字段才有意义),第一篇为0 | |||
* @param $articles | |||
* @return array | |||
* @throws \WeChat\Exceptions\InvalidResponseException | |||
* @throws \WeChat\Exceptions\LocalCacheException | |||
*/ | |||
public function update($media_id, $index, $articles) | |||
{ | |||
$data = ['media_id' => $media_id, 'index' => $index, 'articles' => $articles]; | |||
$url = "https://api.weixin.qq.com/cgi-bin/draft/update?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpGetForJson($url); | |||
} | |||
/** | |||
* 获取草稿列表 | |||
* @param int $offset 从全部素材的该偏移位置开始返回,0表示从第一个素材返回 | |||
* @param int $count 返回素材的数量,取值在1到20之间 | |||
* @param int $no_content 1 表示不返回 content 字段,0 表示正常返回,默认为 0 | |||
* @return array | |||
* @throws \WeChat\Exceptions\InvalidResponseException | |||
* @throws \WeChat\Exceptions\LocalCacheException | |||
*/ | |||
public function batchGet($offset = 0, $count = 20, $no_content = 0) | |||
{ | |||
$url = "https://api.weixin.qq.com/cgi-bin/draft/batchget?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['no_content' => $no_content, 'offset' => $offset, 'count' => $count]); | |||
} | |||
} |
@@ -0,0 +1,27 @@ | |||
<?php | |||
namespace WeChat\Exceptions; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
/** | |||
* 接口参数异常 | |||
* Class InvalidArgumentException | |||
* @package WeChat | |||
*/ | |||
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; | |||
} | |||
} |
@@ -0,0 +1,27 @@ | |||
<?php | |||
namespace WeChat\Exceptions; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
/** | |||
* 加密解密异常 | |||
* Class InvalidResponseException | |||
* @package WeChat | |||
*/ | |||
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; | |||
} | |||
} |
@@ -0,0 +1,27 @@ | |||
<?php | |||
namespace WeChat\Exceptions; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
/** | |||
* 加载类异常 | |||
* Class InvalidInstanceException | |||
* @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; | |||
} | |||
} |
@@ -0,0 +1,28 @@ | |||
<?php | |||
namespace WeChat\Exceptions; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
/** | |||
* 返回异常 | |||
* Class InvalidResponseException | |||
* @package WeChat | |||
*/ | |||
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; | |||
} | |||
} |
@@ -0,0 +1,29 @@ | |||
<?php | |||
namespace WeChat\Exceptions; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
/*** | |||
* 本地缓存异常 | |||
* Class LocalCacheException | |||
* @package WeChat | |||
*/ | |||
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; | |||
} | |||
} |
@@ -0,0 +1,88 @@ | |||
<?php | |||
namespace WeChat; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\BasicWeChat; | |||
/** | |||
* 发布能力 | |||
* Class Freepublish | |||
* @author taoxin | |||
* @package WeChat | |||
*/ | |||
class Freepublish extends BasicWeChat | |||
{ | |||
/** | |||
* 发布接口 | |||
* 开发者需要先将图文素材以草稿的形式保存(见“草稿箱/新建草稿”,如需从已保存的草稿中选择,见“草稿箱/获取草稿列表”) | |||
* @param mixed $media_id 选择要发布的草稿的media_id | |||
* @return array | |||
* @throws \WeChat\Exceptions\InvalidResponseException | |||
* @throws \WeChat\Exceptions\LocalCacheException | |||
*/ | |||
public function submit($media_id) | |||
{ | |||
$url = "https://api.weixin.qq.com/cgi-bin/freepublish/submit?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['media_id' => $media_id]); | |||
} | |||
/** | |||
* 发布状态轮询接口 | |||
* @param mixed $publish_id | |||
* @return array | |||
* @throws \WeChat\Exceptions\InvalidResponseException | |||
* @throws \WeChat\Exceptions\LocalCacheException | |||
*/ | |||
public function get($publish_id) | |||
{ | |||
$url = "https://api.weixin.qq.com/cgi-bin/freepublish/get?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['publish_id' => $publish_id]); | |||
} | |||
/** | |||
* 删除发布 | |||
* 发布成功之后,随时可以通过该接口删除。此操作不可逆,请谨慎操作。 | |||
* @param mixed $article_id 成功发布时返回的 article_id | |||
* @param int $index 要删除的文章在图文消息中的位置,第一篇编号为1,该字段不填或填0会删除全部文章 | |||
* @return array | |||
* @throws \WeChat\Exceptions\InvalidResponseException | |||
* @throws \WeChat\Exceptions\LocalCacheException | |||
*/ | |||
public function delete($article_id, $index = 0) | |||
{ | |||
$url = "https://api.weixin.qq.com/cgi-bin/freepublish/delete?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['article_id' => $article_id, 'index' => $index]); | |||
} | |||
/** | |||
* 通过 article_id 获取已发布文章 | |||
* @param mixed $article_id 要获取的草稿的article_id | |||
* @return array | |||
* @throws \WeChat\Exceptions\InvalidResponseException | |||
* @throws \WeChat\Exceptions\LocalCacheException | |||
*/ | |||
public function getArticle($article_id) | |||
{ | |||
$url = "https://api.weixin.qq.com/cgi-bin/freepublish/getarticle?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['article_id' => $article_id]); | |||
} | |||
/** | |||
* 获取成功发布列表 | |||
* @param int $offset 从全部素材的该偏移位置开始返回,0表示从第一个素材返回 | |||
* @param int $count 返回素材的数量,取值在1到20之间 | |||
* @param int $no_content 1 表示不返回 content 字段,0 表示正常返回,默认为 0 | |||
* @return array | |||
* @throws \WeChat\Exceptions\InvalidResponseException | |||
* @throws \WeChat\Exceptions\LocalCacheException | |||
*/ | |||
public function batchGet($offset = 0, $count = 20, $no_content = 0) | |||
{ | |||
$url = "https://api.weixin.qq.com/cgi-bin/freepublish/batchget?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['no_content' => $no_content, 'offset' => $offset, 'count' => $count]); | |||
} | |||
} |
@@ -0,0 +1,52 @@ | |||
<?php | |||
namespace WeChat; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\BasicWeChat; | |||
/** | |||
* 接口调用频次限制 | |||
* Class Limit | |||
* @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 执行的检测动作 | |||
* @param string $operator 指定平台从某个运营商进行检测 | |||
* @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'; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpGetForJson($url); | |||
} | |||
} |
@@ -0,0 +1,188 @@ | |||
<?php | |||
namespace WeChat; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\BasicWeChat; | |||
use WeChat\Contracts\Tools; | |||
use WeChat\Exceptions\InvalidResponseException; | |||
/** | |||
* 微信素材管理 | |||
* Class Media | |||
* @package WeChat | |||
*/ | |||
class Media extends BasicWeChat | |||
{ | |||
/** | |||
* 新增临时素材 | |||
* @param string $filename 文件名称 | |||
* @param string $type 媒体文件类型(image|voice|video|thumb) | |||
* @return array | |||
* @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}"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['media' => Tools::createCurlFile($filename)], false); | |||
} | |||
/** | |||
* 获取临时素材 | |||
* @param string $media_id | |||
* @param string $outType 返回处理函数 | |||
* @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()); | |||
$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 文件名称 | |||
* @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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, $data); | |||
} | |||
/** | |||
* 更新图文素材 | |||
* @param string $media_id 要修改的图文消息的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) | |||
{ | |||
$data = ['media_id' => $media_id, 'index' => $index, 'articles' => $news]; | |||
$url = "https://api.weixin.qq.com/cgi-bin/material/update_news?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, $data); | |||
} | |||
/** | |||
* 上传图文消息内的图片获取URL | |||
* @param mixed $filename | |||
* @return array | |||
* @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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['media' => Tools::createCurlFile($filename)], false); | |||
} | |||
/** | |||
* 新增其他类型永久素材 | |||
* @param mixed $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}"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['media' => Tools::createCurlFile($filename), 'description' => Tools::arr2json($description)], false); | |||
} | |||
/** | |||
* 获取永久素材 | |||
* @param string $media_id | |||
* @param null|string $outType 输出类型 | |||
* @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()); | |||
$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 $media_id | |||
* @return array | |||
* @throws \WeChat\Exceptions\InvalidResponseException | |||
* @throws \WeChat\Exceptions\LocalCacheException | |||
*/ | |||
public function delMaterial($media_id) | |||
{ | |||
$url = "https://api.weixin.qq.com/cgi-bin/material/del_material?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['media_id' => $media_id]); | |||
} | |||
/** | |||
* 获取素材总数 | |||
* @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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpGetForJson($url); | |||
} | |||
/** | |||
* 获取素材列表 | |||
* @param string $type | |||
* @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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['type' => $type, 'offset' => $offset, 'count' => $count]); | |||
} | |||
} |
@@ -0,0 +1,95 @@ | |||
<?php | |||
namespace WeChat; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\BasicWeChat; | |||
/** | |||
* 微信菜单管理 | |||
* Class Menu | |||
* @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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpGetForJson($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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpGetForJson($url); | |||
} | |||
/** | |||
* 自定义菜单创建 | |||
* @param array $data | |||
* @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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, $data); | |||
} | |||
/** | |||
* 创建个性化菜单 | |||
* @param array $data | |||
* @return array | |||
* @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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, $data); | |||
} | |||
/** | |||
* 删除个性化菜单 | |||
* @param string $menuid | |||
* @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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['menuid' => $menuid]); | |||
} | |||
/** | |||
* 测试个性化菜单匹配结果 | |||
* @param string $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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['user_id' => $openid]); | |||
} | |||
} |
@@ -0,0 +1,86 @@ | |||
<?php | |||
namespace WeChat; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\BasicWeChat; | |||
/** | |||
* 微信网页授权 | |||
* Class Oauth | |||
* @package WeChat | |||
*/ | |||
class Oauth extends BasicWeChat | |||
{ | |||
/** | |||
* Oauth 授权跳转接口 | |||
* @param string $redirect_url 授权回跳地址 | |||
* @param string $state 为重定向后会带上state参数(填写a-zA-Z0-9的参数值,最多128字节) | |||
* @param string $scope 授权类类型(可选值snsapi_base|snsapi_userinfo) | |||
* @return string | |||
*/ | |||
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 获取 AccessToken 和 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); | |||
} | |||
/** | |||
* 刷新AccessToken并续期 | |||
* @param string $refresh_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 $access_token 网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同 | |||
* @param string $openid 用户的唯一标识 | |||
* @return array | |||
* @throws \WeChat\Exceptions\InvalidResponseException | |||
* @throws \WeChat\Exceptions\LocalCacheException | |||
*/ | |||
public function checkOauthAccessToken($access_token, $openid) | |||
{ | |||
$url = "https://api.weixin.qq.com/sns/auth?access_token={$access_token}&openid={$openid}"; | |||
return $this->httpGetForJson($url); | |||
} | |||
/** | |||
* 拉取用户信息(需scope为 snsapi_userinfo) | |||
* @param string $access_token 网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同 | |||
* @param string $openid 用户的唯一标识 | |||
* @param string $lang 返回国家地区语言版本,zh_CN 简体,zh_TW 繁体,en 英语 | |||
* @return array | |||
* @throws \WeChat\Exceptions\InvalidResponseException | |||
* @throws \WeChat\Exceptions\LocalCacheException | |||
*/ | |||
public function getUserInfo($access_token, $openid, $lang = 'zh_CN') | |||
{ | |||
$url = "https://api.weixin.qq.com/sns/userinfo?access_token={$access_token}&openid={$openid}&lang={$lang}"; | |||
return $this->httpGetForJson($url); | |||
} | |||
} |
@@ -0,0 +1,218 @@ | |||
<?php | |||
namespace WeChat; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\BasicWePay; | |||
use WePay\Bill; | |||
use WePay\Order; | |||
use WePay\Refund; | |||
use WePay\Transfers; | |||
use WePay\TransfersBank; | |||
/** | |||
* 微信支付商户 | |||
* Class Pay | |||
* @package WeChat\Contracts | |||
*/ | |||
class Pay extends BasicWePay | |||
{ | |||
/** | |||
* 统一下单 | |||
* @param array $options | |||
* @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 | |||
* @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 统一下单预支付码 | |||
* @return array | |||
*/ | |||
public function createParamsForJsApi($prepay_id) | |||
{ | |||
return Order::instance($this->config->get())->jsapiParams($prepay_id); | |||
} | |||
/** | |||
* 获取APP支付参数 | |||
* @param string $prepay_id 统一下单预支付码 | |||
* @return array | |||
*/ | |||
public function createParamsForApp($prepay_id) | |||
{ | |||
return Order::instance($this->config->get())->appParams($prepay_id); | |||
} | |||
/** | |||
* 获取支付规则二维码 | |||
* @param string $product_id 商户定义的商品id 或者订单号 | |||
* @return string | |||
*/ | |||
public function createParamsForRuleQrc($product_id) | |||
{ | |||
return Order::instance($this->config->get())->qrcParams($product_id); | |||
} | |||
/** | |||
* 查询订单 | |||
* @param array $options | |||
* @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 | |||
* @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 | |||
* @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 | |||
* @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 | |||
* @throws \WeChat\Exceptions\InvalidResponseException | |||
* @throws \WeChat\Exceptions\LocalCacheException | |||
*/ | |||
public function queryAuthCode($authCode) | |||
{ | |||
return Order::instance($this->config->get())->queryAuthCode($authCode); | |||
} | |||
/** | |||
* 下载对账单 | |||
* @param array $options 静音参数 | |||
* @param null|string $outType 输出类型 | |||
* @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 | |||
* @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 | |||
* @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 商户调用企业付款API时使用的商户订单号 | |||
* @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 | |||
* @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); | |||
} | |||
} |
@@ -0,0 +1,162 @@ | |||
<?php | |||
namespace WeChat; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\BasicWeChat; | |||
/** | |||
* 商店管理 | |||
* Class Product | |||
* @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') | |||
{ | |||
$data = ['keystandard' => $keystandard, 'keystr' => $keystr, 'status' => $status]; | |||
$url = "https://api.weixin.qq.com/scan/product/modstatus?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($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 = []) | |||
{ | |||
$data = ['openid' => $openids, 'username' => $usernames]; | |||
$url = "https://api.weixin.qq.com/scan/testwhitelist/set?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, $data); | |||
} | |||
/** | |||
* 获取商品二维码 | |||
* @param string $keystandard 商品编码标准 | |||
* @param string $keystr 商品编码内容 | |||
* @param integer $qrcode_size 二维码的尺寸(整型),数值代表边长像素数,不填写默认值为100 | |||
* @param array $extinfo 由商户自定义传入,建议仅使用大小写字母、数字及-_().*这6个常用字符 | |||
* @return array | |||
* @throws \WeChat\Exceptions\InvalidResponseException | |||
* @throws \WeChat\Exceptions\LocalCacheException | |||
*/ | |||
public function getQrcode($keystandard, $keystr, $qrcode_size, $extinfo = []) | |||
{ | |||
$data = ['keystandard' => $keystandard, 'keystr' => $keystr, 'qrcode_size' => $qrcode_size]; | |||
empty($extinfo) || $data['extinfo'] = $extinfo; | |||
$url = "https://api.weixin.qq.com/scan/product/getqrcode?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, $data); | |||
} | |||
/** | |||
* 查询商品信息 | |||
* @param string $keystandard 商品编码标准 | |||
* @param string $keystr 商品编码内容 | |||
* @return array | |||
* @throws \WeChat\Exceptions\InvalidResponseException | |||
* @throws \WeChat\Exceptions\LocalCacheException | |||
*/ | |||
public function getProduct($keystandard, $keystr) | |||
{ | |||
$data = ['keystandard' => $keystandard, 'keystr' => $keystr]; | |||
empty($extinfo) || $data['extinfo'] = $extinfo; | |||
$url = "https://api.weixin.qq.com/scan/product/get?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, $data); | |||
} | |||
/** | |||
* 批量查询商品信息 | |||
* @param integer $offset 批量查询的起始位置,从0开始,包含该起始位置 | |||
* @param integer $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 = '') | |||
{ | |||
$data = ['offset' => $offset, 'limit' => $limit]; | |||
is_null($status) || $data['status'] = $status; | |||
empty($keystr) || $data['keystr'] = $keystr; | |||
$url = "https://api.weixin.qq.com/scan/product/get?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($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) | |||
{ | |||
$data = ['keystandard' => $keystandard, 'keystr' => $keystr, 'extinfo' => $extinfo]; | |||
$url = "https://api.weixin.qq.com/scan/scanticket/check?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, $data); | |||
} | |||
} |
@@ -0,0 +1,63 @@ | |||
<?php | |||
namespace WeChat; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\BasicWeChat; | |||
/** | |||
* 二维码管理 | |||
* Class Qrcode | |||
* @package WeChat | |||
*/ | |||
class Qrcode extends BasicWeChat | |||
{ | |||
/** | |||
* 创建二维码ticket | |||
* @param string|integer $scene 场景 | |||
* @param int $expire_seconds 有效时间 | |||
* @return array | |||
* @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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, $data); | |||
} | |||
/** | |||
* 通过ticket换取二维码 | |||
* @param string $ticket 获取的二维码ticket,凭借此ticket可以在有效时间内换取二维码。 | |||
* @return string | |||
*/ | |||
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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['action' => 'long2short', 'long_url' => $longUrl]); | |||
} | |||
} |
@@ -0,0 +1,151 @@ | |||
<?php | |||
namespace WeChat; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\BasicPushEvent; | |||
/** | |||
* 公众号推送管理 | |||
* Class Receive | |||
* @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 | |||
* @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 图片媒体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 语音媒体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 视频媒体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 音乐图片缩略图的媒体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; | |||
} | |||
} |
@@ -0,0 +1,186 @@ | |||
<?php | |||
namespace WeChat; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\BasicWeChat; | |||
/** | |||
* 扫一扫接入管理 | |||
* Class Scan | |||
* @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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpGetForJson($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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($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') | |||
{ | |||
$data = ['keystandard' => $keystandard, 'keystr' => $keystr, 'status' => $status]; | |||
$url = "https://api.weixin.qq.com/scan/product/modstatus?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, $data); | |||
} | |||
/** | |||
* 设置测试人员白名单 | |||
* @param array $openids 测试人员的openid列表 | |||
* @param array $usernames 测试人员的微信号列表 | |||
* @return array | |||
* @throws \WeChat\Exceptions\InvalidResponseException | |||
* @throws \WeChat\Exceptions\LocalCacheException | |||
*/ | |||
public function setTestWhiteList($openids = [], $usernames = []) | |||
{ | |||
$data = ['openid' => $openids, 'username' => $usernames]; | |||
$url = "https://api.weixin.qq.com/scan/product/modstatus?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, $data); | |||
} | |||
/** | |||
* 获取商品二维码 | |||
* @param string $keystandard | |||
* @param string $keystr | |||
* @param null|string $extinfo | |||
* @param integer $qrcode_size | |||
* @return array | |||
* @throws \WeChat\Exceptions\InvalidResponseException | |||
* @throws \WeChat\Exceptions\LocalCacheException | |||
*/ | |||
public function getQrc($keystandard, $keystr, $extinfo = null, $qrcode_size = 64) | |||
{ | |||
$data = ['keystandard' => $keystandard, 'keystr' => $keystr, 'qrcode_size' => $qrcode_size]; | |||
is_null($extinfo) || $data['extinfo'] = $extinfo; | |||
$url = "https://api.weixin.qq.com/scan/product/getqrcode?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['keystandard' => $keystandard, 'keystr' => $keystr]); | |||
} | |||
/** | |||
* 批量查询商品信息 | |||
* @param integer $offset 批量查询的起始位置,从0开始,包含该起始位置。 | |||
* @param integer $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) | |||
{ | |||
$data = ['offset' => $offset, 'limit' => $limit]; | |||
is_null($status) || $data['status'] = $status; | |||
is_null($keystr) || $data['keystr'] = $keystr; | |||
$url = "https://api.weixin.qq.com/scan/product/getlist?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['keystandard' => $keystandard, 'keystr' => $keystr, 'extinfo' => $extinfo]); | |||
} | |||
} |
@@ -0,0 +1,102 @@ | |||
<?php | |||
namespace WeChat; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\BasicWeChat; | |||
use WeChat\Contracts\Tools; | |||
use WeChat\Exceptions\InvalidResponseException; | |||
/** | |||
* 微信前端支持 | |||
* Class Script | |||
* @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_TICKET接口 | |||
* @param string $type TICKET类型(wx_card|jsapi) | |||
* @param string $appid 强制指定有效APPID | |||
* @return string | |||
* @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; | |||
} | |||
/** | |||
* 获取JsApi使用签名 | |||
* @param string $url 网页的URL | |||
* @param string $appid 用于多个appid时使用(可空) | |||
* @param string $ticket 强制指定ticket | |||
* @param array $jsApiList 需初始化的 jsApiList | |||
* @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, | |||
]; | |||
} | |||
/** | |||
* 数据生成签名 | |||
* @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)); | |||
} | |||
} |
@@ -0,0 +1,350 @@ | |||
<?php | |||
namespace WeChat; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\BasicWeChat; | |||
use WeChat\Contracts\Tools; | |||
/** | |||
* 揺一揺周边 | |||
* Class Shake | |||
* @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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpGetForJson($url); | |||
} | |||
/** | |||
* 申请设备ID | |||
* @param string $quantity 申请的设备ID的数量,单次新增设备超过500个,需走人工审核流程 | |||
* @param string $apply_reason 申请理由,不超过100个汉字或200个英文字母 | |||
* @param null|string $comment 备注,不超过15个汉字或30个英文字母 | |||
* @param null|string $poi_id 设备关联的门店ID,关联门店后,在门店1KM的范围内有优先摇出信息的机会。 | |||
* @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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, $data); | |||
} | |||
/** | |||
* 查询设备ID申请审核状态 | |||
* @param integer $applyId 批次ID,申请设备ID时所返回的批次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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, $data); | |||
} | |||
/** | |||
* 删除页面 | |||
* @param integer $page_id 指定页面的id | |||
* @return array | |||
* @throws \WeChat\Exceptions\InvalidResponseException | |||
* @throws \WeChat\Exceptions\LocalCacheException | |||
*/ | |||
public function deletePage($page_id) | |||
{ | |||
$url = "https://api.weixin.qq.com/shakearound/page/delete?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['page_id' => $page_id]); | |||
} | |||
/** | |||
* 上传图片素材 | |||
* @param string $filename 图片名字 | |||
* @param string $type Icon:摇一摇页面展示的icon图;License:申请开通摇一摇周边功能时需上传的资质文件;若不传type,则默认type=icon | |||
* @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}"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['media' => Tools::createCurlFile($filename)]); | |||
} | |||
/** | |||
* 配置设备与页面的关联关系 | |||
* @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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, $data); | |||
} | |||
/** | |||
* 批量查询设备统计数据接口 | |||
* @param integer $date 指定查询日期时间戳,单位为秒 | |||
* @param integer $page_index 指定查询的结果页序号;返回结果按摇周边人数降序排序,每50条记录为一页 | |||
* @return array | |||
* @throws \WeChat\Exceptions\InvalidResponseException | |||
* @throws \WeChat\Exceptions\LocalCacheException | |||
*/ | |||
public function totalDeviceList($date, $page_index = 1) | |||
{ | |||
$url = "https://api.weixin.qq.com/shakearound/statistics/devicelist?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['date' => $date, 'page_index' => $page_index]); | |||
} | |||
/** | |||
* 以页面为维度的数据统计接口 | |||
* @param integer $page_id 指定页面的设备ID | |||
* @param integer $begin_date 起始日期时间戳,最长时间跨度为30天,单位为秒 | |||
* @param integer $end_date 结束日期时间戳,最长时间跨度为30天,单位为秒 | |||
* @return array | |||
* @throws \WeChat\Exceptions\InvalidResponseException | |||
* @throws \WeChat\Exceptions\LocalCacheException | |||
*/ | |||
public function totalPage($page_id, $begin_date, $end_date) | |||
{ | |||
$url = "https://api.weixin.qq.com/shakearound/statistics/page?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['page_id' => $page_id, 'begin_date' => $begin_date, 'end_date' => $end_date]); | |||
} | |||
/** | |||
* 编辑分组信息 | |||
* @param integer $group_id 分组唯一标识,全局唯一 | |||
* @param string $group_name 分组名称,不超过100汉字或200个英文字母 | |||
* @return array | |||
* @throws \WeChat\Exceptions\InvalidResponseException | |||
* @throws \WeChat\Exceptions\LocalCacheException | |||
*/ | |||
public function updateGroup($group_id, $group_name) | |||
{ | |||
$url = "https://api.weixin.qq.com/shakearound/device/group/update?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['group_id' => $group_id, 'group_name' => $group_name]); | |||
} | |||
/** | |||
* 删除分组 | |||
* @param integer $group_id 分组唯一标识,全局唯一 | |||
* @return array | |||
* @throws \WeChat\Exceptions\InvalidResponseException | |||
* @throws \WeChat\Exceptions\LocalCacheException | |||
*/ | |||
public function deleteGroup($group_id) | |||
{ | |||
$url = "https://api.weixin.qq.com/shakearound/device/group/delete?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['group_id' => $group_id]); | |||
} | |||
/** | |||
* 查询分组列表 | |||
* @param integer $begin 分组列表的起始索引值 | |||
* @param integer $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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['begin' => $begin, 'count' => $count]); | |||
} | |||
/** | |||
* 查询分组详情 | |||
* @param integer $group_id 分组唯一标识,全局唯一 | |||
* @param integer $begin 分组里设备的起始索引值 | |||
* @param integer $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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, $data); | |||
} | |||
} |
@@ -0,0 +1,111 @@ | |||
<?php | |||
namespace WeChat; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\BasicWeChat; | |||
/** | |||
* 用户标签管理 | |||
* Class Tags | |||
* @package WeChat | |||
*/ | |||
class Tags extends BasicWeChat | |||
{ | |||
/** | |||
* 获取粉丝标签列表 | |||
* @throws Exceptions\InvalidResponseException | |||
* @throws Exceptions\LocalCacheException | |||
*/ | |||
public function getTags() | |||
{ | |||
$url = "https://api.weixin.qq.com/cgi-bin/tags/get?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpGetForJson($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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['tag' => ['name' => $name]]); | |||
} | |||
/** | |||
* 更新粉丝标签 | |||
* @param integer $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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['tag' => ['name' => $name, 'id' => $id]]); | |||
} | |||
/** | |||
* 删除粉丝标签 | |||
* @param int $tagId | |||
* @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'; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['tag' => ['id' => $tagId]]); | |||
} | |||
/** | |||
* 批量为用户打标签 | |||
* @param array $openids | |||
* @param integer $tagId | |||
* @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'; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['openid_list' => $openids, 'tagid' => $tagId]); | |||
} | |||
/** | |||
* 批量为用户取消标签 | |||
* @param array $openids | |||
* @param integer $tagId | |||
* @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'; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['openid_list' => $openids, 'tagid' => $tagId]); | |||
} | |||
/** | |||
* 获取用户身上的标签列表 | |||
* @param string $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'; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['openid' => $openid]); | |||
} | |||
} |
@@ -0,0 +1,97 @@ | |||
<?php | |||
namespace WeChat; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\BasicWeChat; | |||
/** | |||
* 模板消息 | |||
* Class Template | |||
* @package WeChat | |||
*/ | |||
class Template extends BasicWeChat | |||
{ | |||
/** | |||
* 设置所属行业 | |||
* @param string $industry_id1 公众号模板消息所属行业编号 | |||
* @param string $industry_id2 公众号模板消息所属行业编号 | |||
* @return array | |||
* @throws Exceptions\InvalidResponseException | |||
* @throws Exceptions\LocalCacheException | |||
*/ | |||
public function setIndustry($industry_id1, $industry_id2) | |||
{ | |||
$url = "https://api.weixin.qq.com/cgi-bin/template/api_set_industry?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['industry_id1' => $industry_id1, 'industry_id2' => $industry_id2]); | |||
} | |||
/** | |||
* 获取设置的行业信息 | |||
* @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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpGetForJson($url); | |||
} | |||
/** | |||
* 获得模板ID | |||
* @param string $tpl_id 板库中模板的编号,有“TM**”和“OPENTMTM**”等形式 | |||
* @return array | |||
* @throws Exceptions\InvalidResponseException | |||
* @throws Exceptions\LocalCacheException | |||
*/ | |||
public function addTemplate($tpl_id) | |||
{ | |||
$url = "https://api.weixin.qq.com/cgi-bin/template/api_add_template?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['template_id_short' => $tpl_id]); | |||
} | |||
/** | |||
* 获取模板列表 | |||
* @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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpGetForJson($url); | |||
} | |||
/** | |||
* 删除模板ID | |||
* @param string $tpl_id 公众帐号下模板消息ID | |||
* @return array | |||
* @throws Exceptions\InvalidResponseException | |||
* @throws Exceptions\LocalCacheException | |||
*/ | |||
public function delPrivateTemplate($tpl_id) | |||
{ | |||
$url = "https://api.weixin.qq.com/cgi-bin/template/del_private_template?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['template_id' => $tpl_id]); | |||
} | |||
/** | |||
* 发送模板消息 | |||
* @param array $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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, $data); | |||
} | |||
} |
@@ -0,0 +1,134 @@ | |||
<?php | |||
namespace WeChat; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\BasicWeChat; | |||
/** | |||
* 微信粉丝管理 | |||
* Class User | |||
* @package WeChat | |||
*/ | |||
class User extends BasicWeChat | |||
{ | |||
/** | |||
* 设置用户备注名 | |||
* @param string $openid | |||
* @param string $remark | |||
* @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'; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['openid' => $openid, 'remark' => $remark]); | |||
} | |||
/** | |||
* 获取用户基本信息(包括UnionID机制) | |||
* @param string $openid | |||
* @param string $lang | |||
* @return array | |||
* @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}"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpGetForJson($url); | |||
} | |||
/** | |||
* 批量获取用户基本信息 | |||
* @param array $openids | |||
* @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]; | |||
} | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, $data); | |||
} | |||
/** | |||
* 获取用户列表 | |||
* @param string $next_openid | |||
* @return array | |||
* @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}"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpGetForJson($url); | |||
} | |||
/** | |||
* 获取标签下粉丝列表 | |||
* @param integer $tagid 标签ID | |||
* @param string $next_openid 第一个拉取的OPENID | |||
* @return array | |||
* @throws Exceptions\InvalidResponseException | |||
* @throws Exceptions\LocalCacheException | |||
*/ | |||
public function getUserListByTag($tagid, $next_openid = '') | |||
{ | |||
$url = 'https://api.weixin.qq.com/cgi-bin/user/tag/get?access_token=ACCESS_TOKEN'; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['tagid' => $tagid, 'next_openid' => $next_openid]); | |||
} | |||
/** | |||
* 获取公众号的黑名单列表 | |||
* @param string $begin_openid | |||
* @return array | |||
* @throws Exceptions\InvalidResponseException | |||
* @throws Exceptions\LocalCacheException | |||
*/ | |||
public function getBlackList($begin_openid = '') | |||
{ | |||
$url = "https://api.weixin.qq.com/cgi-bin/tags/members/getblacklist?access_token=ACCESS_TOKEN"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['begin_openid' => $begin_openid]); | |||
} | |||
/** | |||
* 批量拉黑用户 | |||
* @param array $openids | |||
* @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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['openid_list' => $openids]); | |||
} | |||
/** | |||
* 批量取消拉黑用户 | |||
* @param array $openids | |||
* @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"; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
return $this->httpPostForJson($url, ['openid_list' => $openids]); | |||
} | |||
} |
@@ -0,0 +1,271 @@ | |||
<?php | |||
namespace WeChat; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\BasicWeChat; | |||
/** | |||
* 门店 WIFI 管理 | |||
* Class Wifi | |||
* @package WeChat | |||
*/ | |||
class Wifi extends BasicWeChat | |||
{ | |||
/** | |||
* 获取 Wi-Fi 门店列表 | |||
* @param integer $pageindex 分页下标,默认从1开始 | |||
* @param integer $pagesize 每页的个数,默认10个,最大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 integer $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]); | |||
} | |||
/** | |||
* 修改门店网络信息 | |||
* @param integer $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 integer $shop_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 integer $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 integer $shop_id 门店ID | |||
* @param string $ssid 无线网络设备的ssid | |||
* @param bool $reset 重置secretkey,false-不重置,true-重置,默认为false | |||
* @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 null|integer $shop_id 根据门店id查询 | |||
* @param null|integer $pageindex 分页下标,默认从1开始 | |||
* @param null|integer $pagesize 每页的个数,默认10个,最大20个 | |||
* @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地址,格式冒号分隔,字符长度17个,并且字母小写,例如:00:1f:7a:ad:5c:a8 | |||
* @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 integer $shop_id 门店ID | |||
* @param string $ssid 已添加到门店下的无线网络名称 | |||
* @param integer $img_id 物料样式编号:0-纯二维码,可用于自由设计宣传材料;1-二维码物料,155mm×215mm(宽×高),可直接张贴 | |||
* @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 integer $shop_id 门店ID | |||
* @param integer $template_id 模板ID,0-默认模板,1-自定义url | |||
* @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 integer $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 integer $shop_id 门店ID | |||
* @param integer $bar_type 微信首页欢迎语的文本内容:0--欢迎光临+公众号名称;1--欢迎光临+门店名称;2--已连接+公众号名称+WiFi;3--已连接+门店名称+Wi-Fi。 | |||
* @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 integer $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,最长时间跨度为30天 | |||
* @param string $end_date 结束日期时间戳,格式yyyy-mm-dd,最长时间跨度为30天 | |||
* @param integer $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 integer $shop_id 门店ID,可设置为0,表示所有门店 | |||
* @param integer $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 integer $shop_id 门店ID,可设置为0,表示所有门店 | |||
* @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]); | |||
} | |||
} |
@@ -0,0 +1,107 @@ | |||
<?php | |||
namespace WeMini; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\BasicWeChat; | |||
use WeChat\Contracts\Tools; | |||
use WeChat\Exceptions\InvalidDecryptException; | |||
use WeChat\Exceptions\InvalidResponseException; | |||
use WXBizDataCrypt; | |||
/** | |||
* 数据加密处理 | |||
* Class Crypt | |||
* @package WeMini | |||
*/ | |||
class Crypt extends BasicWeChat | |||
{ | |||
/** | |||
* 数据签名校验 | |||
* @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); | |||
$errCode = $pc->decryptData($encryptedData, $iv, $data); | |||
if ($errCode == 0) { | |||
return json_decode($data, true); | |||
} | |||
return false; | |||
} | |||
/** | |||
* 登录凭证校验 | |||
* @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 $code 用户登录凭证(有效期五分钟) | |||
* @param string $iv 加密算法的初始向量 | |||
* @param string $encryptedData 加密数据( 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); | |||
} | |||
/** | |||
* 通过授权码换取手机号 | |||
* @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 支付用户唯一标识 | |||
* @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); | |||
} | |||
} |
@@ -0,0 +1,158 @@ | |||
<?php | |||
namespace WeMini; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\BasicWeChat; | |||
/** | |||
* 小程序即时配送 | |||
* Class Delivery | |||
* @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); | |||
} | |||
} |
@@ -0,0 +1,512 @@ | |||
<?php | |||
namespace WeMini; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\BasicWeChat; | |||
/** | |||
* 小程序导购助手 | |||
* Class Guide | |||
* @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 integer $page | |||
* @param integer $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); | |||
} | |||
/** | |||
* 新建可查询标签类型,支持新建4类可查询标签 | |||
* @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 | |||
* @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 integer $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 integer $type 操作类型 | |||
* @param integer $start 分页查询,起始位置 | |||
* @param integer $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 integer $type 操作类型 | |||
* @param integer $start 分页查询,起始位置 | |||
* @param integer $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); | |||
} | |||
} |
@@ -0,0 +1,55 @@ | |||
<?php | |||
namespace WeMini; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\BasicWeChat; | |||
/** | |||
* 小程序图像处理 | |||
* Class Image | |||
* @package WeMini | |||
*/ | |||
class Image extends BasicWeChat | |||
{ | |||
/** | |||
* 本接口提供基于小程序的图片智能裁剪能力 | |||
* @param string $img_url 要检测的图片 url,传这个则不用传 img 参数。 | |||
* @param string $img form-data 中媒体文件标识,有filename、filelength、content-type等信息,传这个则不用穿 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_TOCKEN"; | |||
return $this->callPostApi($url, ['img_url' => $img_url, 'img' => $img], true); | |||
} | |||
/** | |||
* 本接口提供基于小程序的条码/二维码识别的API | |||
* @param string $img_url 要检测的图片 url,传这个则不用传 img 参数。 | |||
* @param string $img form-data 中媒体文件标识,有filename、filelength、content-type等信息,传这个则不用穿 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_TOCKEN"; | |||
return $this->callPostApi($url, ['img_url' => $img_url, 'img' => $img], true); | |||
} | |||
/** | |||
* 本接口提供基于小程序的图片高清化能力 | |||
* @param string $img_url 要检测的图片 url,传这个则不用传 img 参数 | |||
* @param string $img form-data 中媒体文件标识,有filename、filelength、content-type等信息,传这个则不用穿 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_TOCKEN"; | |||
return $this->callPostApi($url, ['img_url' => $img_url, 'img' => $img], true); | |||
} | |||
} |
@@ -0,0 +1,156 @@ | |||
<?php | |||
namespace WeMini; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\BasicWeChat; | |||
/** | |||
* 小程序直播接口 | |||
* Class Live | |||
* @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 integer $start 起始拉取房间 | |||
* @param integer $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 | |||
* @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 array $data | |||
* @return array | |||
* @throws \WeChat\Exceptions\InvalidResponseException | |||
* @throws \WeChat\Exceptions\LocalCacheException | |||
*/ | |||
public function getGoods($data) | |||
{ | |||
$url = "https://api.weixin.qq.com/wxaapi/broadcast/goods/getapproved?access_token=ACCESS_TOKEN"; | |||
return $this->callPostApi($url, $data, true); | |||
} | |||
} |
@@ -0,0 +1,179 @@ | |||
<?php | |||
namespace WeMini; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\BasicWeChat; | |||
/** | |||
* 小程序物流助手 | |||
* Class Logistics | |||
* @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); | |||
} | |||
/** | |||
* 获取打印员。若需要使用微信打单 PC 软件,才需要调用 | |||
* @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/path/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); | |||
} | |||
/** | |||
* 配置面单打印员,若需要使用微信打单 PC 软件,才需要调用 | |||
* @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); | |||
} | |||
} |
@@ -0,0 +1,51 @@ | |||
<?php | |||
namespace WeMini; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\BasicWeChat; | |||
/** | |||
* 小程序动态消息 | |||
* Class Message | |||
* @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); | |||
} | |||
} |
@@ -0,0 +1,130 @@ | |||
<?php | |||
namespace WeMini; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\BasicWeChat; | |||
/** | |||
* 公众号小程序订阅消息支持 | |||
* Class Mini | |||
* @package WeChat | |||
*/ | |||
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 开发者自行组合好的模板关键词列表,关键词顺序可以自由搭配(例如 [3,5,4] 或 [4,5,3]),最多支持5个,最少2个关键词组合 | |||
* @param string $sceneDesc 服务场景描述,15个字以内 | |||
* @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); | |||
} | |||
} |
@@ -0,0 +1,90 @@ | |||
<?php | |||
namespace WeMini; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\BasicWeChat; | |||
/** | |||
* 小程序ORC服务 | |||
* Class Ocr | |||
* @package WeMini | |||
*/ | |||
class Ocr extends BasicWeChat | |||
{ | |||
/** | |||
* 本接口提供基于小程序的银行卡 OCR 识别 | |||
* @param array $data | |||
* @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_TOCKEN'; | |||
return $this->callPostApi($url, $data, true); | |||
} | |||
/** | |||
* 本接口提供基于小程序的营业执照 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_TOCKEN'; | |||
return $this->callPostApi($url, $data, true); | |||
} | |||
/** | |||
* 本接口提供基于小程序的驾驶证 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_TOCKEN'; | |||
return $this->callPostApi($url, $data, true); | |||
} | |||
/** | |||
* 本接口提供基于小程序的身份证 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_TOCKEN'; | |||
return $this->callPostApi($url, $data, true); | |||
} | |||
/** | |||
* 本接口提供基于小程序的通用印刷体 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_TOCKEN'; | |||
return $this->callPostApi($url, $data, true); | |||
} | |||
/** | |||
* 本接口提供基于小程序的行驶证 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_TOCKEN'; | |||
return $this->callPostApi($url, $data, true); | |||
} | |||
} |
@@ -0,0 +1,26 @@ | |||
<?php | |||
namespace WeMini; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\BasicWeChat; | |||
/** | |||
* 小程序运维中心 | |||
* Class Operation | |||
* @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); | |||
} | |||
} |
@@ -0,0 +1,92 @@ | |||
<?php | |||
namespace WeMini; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\BasicWeChat; | |||
/** | |||
* 微信小程序插件管理 | |||
* Class Plugs | |||
* @package WeMini | |||
*/ | |||
class Plugs extends BasicWeChat | |||
{ | |||
/** | |||
* 1.申请使用插件 | |||
* @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); | |||
} | |||
/** | |||
* 2.查询已添加的插件 | |||
* @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); | |||
} | |||
/** | |||
* 3.删除已添加的插件 | |||
* @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); | |||
} | |||
/** | |||
* 4.获取当前所有插件使用方(供插件开发者调用) | |||
* @param integer $page 拉取第page页的数据 | |||
* @param integer $num 表示每页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); | |||
} | |||
/** | |||
* 5.修改插件使用申请的状态(供插件开发者调用) | |||
* @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); | |||
} | |||
} |
@@ -0,0 +1,73 @@ | |||
<?php | |||
namespace WeMini; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\BasicWeChat; | |||
/** | |||
* 微信小程序地址管理 | |||
* Class Poi | |||
* @package WeMini | |||
*/ | |||
class Poi extends BasicWeChat | |||
{ | |||
/** | |||
* 添加地点 | |||
* @param string $related_name 经营资质主体 | |||
* @param string $related_credential 经营资质证件号 | |||
* @param string $related_address 经营资质地址 | |||
* @param string $related_proof_material 相关证明材料照片临时素材mediaid | |||
* @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 integer $page 起始页id(从1开始计数) | |||
* @param integer $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); | |||
} | |||
} |
@@ -0,0 +1,98 @@ | |||
<?php | |||
namespace WeMini; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\BasicWeChat; | |||
use WeChat\Contracts\Tools; | |||
/** | |||
* 微信小程序二维码管理 | |||
* Class Qrcode | |||
* @package WeMini | |||
*/ | |||
class Qrcode extends BasicWeChat | |||
{ | |||
/** | |||
* 获取小程序码(永久有效) | |||
* 接口A: 适用于需要的码数量较少的业务场景 | |||
* @param string $path 不能为空,最大长度 128 字节 | |||
* @param integer $width 二维码的宽度 | |||
* @param bool $auto_color 自动配置线条颜色,如果颜色依然是黑色,则说明不建议配置主色调 | |||
* @param array $line_color auto_color 为 false 时生效 | |||
* @param boolean $is_hyaline 是否需要透明底色 | |||
* @param null|string $outType 输出类型 | |||
* @return array|string | |||
* @throws \WeChat\Exceptions\InvalidResponseException | |||
* @throws \WeChat\Exceptions\LocalCacheException | |||
*/ | |||
public function createMiniPath($path, $width = 430, $auto_color = false, $line_color = ["r" => "0", "g" => "0", "b" => "0"], $is_hyaline = true, $outType = null) | |||
{ | |||
$url = 'https://api.weixin.qq.com/wxa/getwxacode?access_token=ACCESS_TOKEN'; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
$data = ['path' => $path, 'width' => $width, 'auto_color' => $auto_color, 'line_color' => $line_color, 'is_hyaline' => $is_hyaline]; | |||
$result = Tools::post($url, Tools::arr2json($data)); | |||
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); | |||
} | |||
/** | |||
* 获取小程序码(永久有效) | |||
* 接口B:适用于需要的码数量极多的业务场景 | |||
* @param string $scene 最大32个可见字符,只支持数字 | |||
* @param string $page 必须是已经发布的小程序存在的页面 | |||
* @param integer $width 二维码的宽度 | |||
* @param bool $auto_color 自动配置线条颜色,如果颜色依然是黑色,则说明不建议配置主色调 | |||
* @param array $line_color auto_color 为 false 时生效 | |||
* @param boolean $is_hyaline 是否需要透明底色 | |||
* @param null|string $outType 输出类型 | |||
* @return array|string | |||
* @throws \WeChat\Exceptions\InvalidResponseException | |||
* @throws \WeChat\Exceptions\LocalCacheException | |||
*/ | |||
public function createMiniScene($scene, $page, $width = 430, $auto_color = false, $line_color = ["r" => "0", "g" => "0", "b" => "0"], $is_hyaline = true, $outType = null) | |||
{ | |||
$url = 'https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=ACCESS_TOKEN'; | |||
$data = ['scene' => $scene, 'width' => $width, 'auto_color' => $auto_color, 'page' => $page, 'line_color' => $line_color, 'is_hyaline' => $is_hyaline]; | |||
$this->registerApi($url, __FUNCTION__, func_get_args()); | |||
$result = Tools::post($url, Tools::arr2json($data)); | |||
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); | |||
} | |||
/** | |||
* 获取小程序二维码(永久有效) | |||
* 接口C:适用于需要的码数量较少的业务场景 | |||
* @param string $path 不能为空,最大长度 128 字节 | |||
* @param integer $width 二维码的宽度 | |||
* @param null|string $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()); | |||
$result = Tools::post($url, Tools::arr2json(['path' => $path, 'width' => $width])); | |||
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); | |||
} | |||
} |
@@ -0,0 +1,65 @@ | |||
<?php | |||
namespace WeMini; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\BasicWeChat; | |||
/** | |||
* 小程序 URL-Scheme | |||
* Class 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 | |||
* @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 | |||
* @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); | |||
} | |||
} |
@@ -0,0 +1,25 @@ | |||
<?php | |||
namespace WeMini; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\BasicWeChat; | |||
/** | |||
* 小程序搜索 | |||
* Class Search | |||
* @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); | |||
} | |||
} |
@@ -0,0 +1,53 @@ | |||
<?php | |||
namespace WeMini; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\BasicWeChat; | |||
/** | |||
* 小程序内容安全 | |||
* Class Security | |||
* @package WeMini | |||
*/ | |||
class Security extends BasicWeChat | |||
{ | |||
/** | |||
* 校验一张图片是否含有违法违规内容 | |||
* @param string $media 要检测的图片文件,格式支持PNG、JPEG、JPG、GIF,图片尺寸不超过 750px x 1334px | |||
* @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); | |||
} | |||
/** | |||
* 异步校验图片/音频是否含有违法违规内容 | |||
* @param string $media_url | |||
* @param string $media_type | |||
* @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); | |||
} | |||
} |
@@ -0,0 +1,25 @@ | |||
<?php | |||
namespace WeMini; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\BasicWeChat; | |||
/** | |||
* 小程序生物认证 | |||
* Class Soter | |||
* @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); | |||
} | |||
} |
@@ -0,0 +1,90 @@ | |||
<?php | |||
namespace WeMini; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\BasicWeChat; | |||
/** | |||
* 公众号小程序模板消息支持 | |||
* Class Mini | |||
* @package WeChat | |||
*/ | |||
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 开发者自行组合好的模板关键词列表,关键词顺序可以自由搭配(例如[3,5,4]或[4,5,3]),最多支持10个关键词组合 | |||
* @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 发送的消息对象数组 | |||
* @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); | |||
} | |||
} |
@@ -0,0 +1,152 @@ | |||
<?php | |||
namespace WeMini; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\BasicWeChat; | |||
/** | |||
* 微信小程序数据接口 | |||
* Class Total | |||
* @package WeMini | |||
*/ | |||
class Total extends BasicWeChat | |||
{ | |||
/** | |||
* 数据分析接口 | |||
* @param string $begin_date 开始日期 | |||
* @param string $end_date 结束日期,限定查询1天数据,end_date允许设置的最大值为昨日 | |||
* @return array | |||
* @throws \WeChat\Exceptions\InvalidResponseException | |||
* @throws \WeChat\Exceptions\LocalCacheException | |||
*/ | |||
public function getWeanalysisAppidDailySummarytrend($begin_date, $end_date) | |||
{ | |||
$url = 'https://api.weixin.qq.com/datacube/getweanalysisappiddailysummarytrend?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 结束日期,限定查询1天数据,end_date允许设置的最大值为昨日 | |||
* @return array | |||
* @throws \WeChat\Exceptions\InvalidResponseException | |||
* @throws \WeChat\Exceptions\LocalCacheException | |||
*/ | |||
public function getWeanalysisAppidDailyVisittrend($begin_date, $end_date) | |||
{ | |||
$url = 'https://api.weixin.qq.com/datacube/getweanalysisappiddailyvisittrend?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 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 结束日期,限定查询1天数据,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 结束日期,限定查询1天数据,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 结束日期,限定查询1天数据,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,分别表示查询最近1/7/30天数据,end_date允许设置的最大值为昨日 | |||
* @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); | |||
} | |||
} |
@@ -0,0 +1,19 @@ | |||
<?php | |||
if (!defined('DEDEINC')) exit('dedebiz');/** | |||
* 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; | |||
} |
@@ -0,0 +1,58 @@ | |||
<?php | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
/** | |||
* 对微信小程序用户加密数据的解密示例代码 | |||
* Class WXBizDataCrypt | |||
* @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; | |||
} | |||
} | |||
@@ -0,0 +1,50 @@ | |||
<?php | |||
namespace WePay; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\BasicWePay; | |||
use WeChat\Contracts\Tools; | |||
use WeChat\Exceptions\InvalidResponseException; | |||
/** | |||
* 微信商户账单及评论 | |||
* Class Bill | |||
* @package WePay | |||
*/ | |||
class Bill extends BasicWePay | |||
{ | |||
/** | |||
* 下载对账单 | |||
* @param array $options 静音参数 | |||
* @param null|string $outType 输出类型 | |||
* @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 | |||
* @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); | |||
} | |||
} |
@@ -0,0 +1,52 @@ | |||
<?php | |||
namespace WePay; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\BasicWePay; | |||
/** | |||
* 微信商户代金券 | |||
* Class Coupon | |||
* @package WePay | |||
*/ | |||
class Coupon extends BasicWePay | |||
{ | |||
/** | |||
* 发放代金券 | |||
* @param array $options | |||
* @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 | |||
* @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 | |||
* @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); | |||
} | |||
} |
@@ -0,0 +1,54 @@ | |||
<?php | |||
namespace WePay; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\BasicWePay; | |||
/** | |||
* 微信扩展上报海关 | |||
* Class Custom | |||
* @package WePay | |||
*/ | |||
class Custom extends BasicWePay | |||
{ | |||
/** | |||
* 订单附加信息提交接口 | |||
* @param array $options | |||
* @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 | |||
* @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 | |||
* @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); | |||
} | |||
} |
@@ -0,0 +1,160 @@ | |||
<?php | |||
namespace WePay; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\BasicWePay; | |||
use WeChat\Contracts\Tools; | |||
/** | |||
* 微信商户订单 | |||
* Class Order | |||
* @package WePay | |||
*/ | |||
class Order extends BasicWePay | |||
{ | |||
/** | |||
* 统一下单 | |||
* @param array $options | |||
* @return array | |||
* @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 | |||
* @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 | |||
* @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及H5支付参数 | |||
* @param string $prepayId 统一下单预支付码 | |||
* @return array | |||
*/ | |||
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; | |||
} | |||
/** | |||
* 获取支付规则二维码 | |||
* @param string $productId 商户定义的商品id或者订单号 | |||
* @return string | |||
*/ | |||
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 统一下单预支付码 | |||
* @return array | |||
*/ | |||
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 | |||
* @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 | |||
* @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 | |||
* @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); | |||
} | |||
} |
@@ -0,0 +1,59 @@ | |||
<?php | |||
namespace WePay; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\BasicWePay; | |||
/** | |||
* 微信红包支持 | |||
* Class Redpack | |||
* @package WePay | |||
*/ | |||
class Redpack extends BasicWePay | |||
{ | |||
/** | |||
* 发放普通红包 | |||
* @param array $options | |||
* @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 | |||
* @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); | |||
} | |||
} |
@@ -0,0 +1,65 @@ | |||
<?php | |||
namespace WePay; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\BasicWePay; | |||
use WeChat\Contracts\Tools; | |||
use WeChat\Exceptions\InvalidDecryptException; | |||
use WeChat\Exceptions\InvalidResponseException; | |||
/** | |||
* 微信商户退款 | |||
* Class Refund | |||
* @package WePay | |||
*/ | |||
class Refund extends BasicWePay | |||
{ | |||
/** | |||
* 创建退款订单 | |||
* @param array $options | |||
* @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 | |||
* @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); | |||
} | |||
/** | |||
* 获取退款通知 | |||
* @return array | |||
* @throws \WeChat\Exceptions\InvalidDecryptException | |||
* @throws \WeChat\Exceptions\InvalidResponseException | |||
*/ | |||
public function getNotify() | |||
{ | |||
$data = Tools::xml2arr(file_get_contents("php://input")); | |||
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()); | |||
} | |||
} | |||
} |
@@ -0,0 +1,48 @@ | |||
<?php | |||
namespace WePay; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\BasicWePay; | |||
/** | |||
* 微信商户打款到零钱 | |||
* Class Transfers | |||
* @package WePay | |||
*/ | |||
class Transfers extends BasicWePay | |||
{ | |||
/** | |||
* 企业付款到零钱 | |||
* @param array $options | |||
* @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 商户调用企业付款API时使用的商户订单号 | |||
* @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); | |||
} | |||
} |
@@ -0,0 +1,111 @@ | |||
<?php | |||
namespace WePay; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\BasicWePay; | |||
use WeChat\Contracts\Tools; | |||
use WeChat\Exceptions\InvalidArgumentException; | |||
use WeChat\Exceptions\InvalidDecryptException; | |||
use WeChat\Exceptions\InvalidResponseException; | |||
/** | |||
* 微信商户打款到银行卡 | |||
* Class TransfersBank | |||
* @package WePay | |||
*/ | |||
class TransfersBank extends BasicWePay | |||
{ | |||
/** | |||
* 企业付款到银行卡 | |||
* @param array $options | |||
* @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); | |||
} | |||
/** | |||
* 商户企业付款到银行卡操作进行结果查询 | |||
* @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); | |||
} | |||
/** | |||
* RSA加密处理 | |||
* @param string $string | |||
* @param string $encrypted | |||
* @return string | |||
* @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); | |||
} | |||
/** | |||
* 获取签名文件内容 | |||
* @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']; | |||
} | |||
} |
@@ -0,0 +1,36 @@ | |||
<?php | |||
namespace WePayV3; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Exceptions\InvalidResponseException; | |||
use WePayV3\Contracts\BasicWePay; | |||
use WePayV3\Contracts\DecryptAes; | |||
/** | |||
* 平台证书管理 | |||
* Class Cert | |||
* @package WePayV3 | |||
*/ | |||
class Cert extends BasicWePay | |||
{ | |||
/** | |||
* 商户平台下载证书 | |||
* @return void | |||
* @throws \WeChat\Exceptions\InvalidResponseException | |||
*/ | |||
public function download() | |||
{ | |||
try { | |||
$aes = new DecryptAes($this->config['mch_v3_key']); | |||
$result = $this->doRequest('GET', '/v3/certificates'); | |||
foreach ($result['data'] as $vo) { | |||
$this->tmpFile($vo['serial_no'], $aes->decryptToString( | |||
$vo['encrypt_certificate']['associated_data'], | |||
$vo['encrypt_certificate']['nonce'], | |||
$vo['encrypt_certificate']['ciphertext'] | |||
)); | |||
} | |||
} catch (\Exception $exception) { | |||
throw new InvalidResponseException($exception->getMessage(), $exception->getCode()); | |||
} | |||
} | |||
} |
@@ -0,0 +1,222 @@ | |||
<?php | |||
namespace WePayV3\Contracts; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\Tools; | |||
use WeChat\Exceptions\InvalidArgumentException; | |||
use WeChat\Exceptions\InvalidResponseException; | |||
use WePayV3\Cert; | |||
/** | |||
* 微信支付基础类 | |||
* Class BasicWePay | |||
* @package WePayV3 | |||
*/ | |||
abstract class BasicWePay | |||
{ | |||
/** | |||
* 接口基础地址 | |||
* @var string | |||
*/ | |||
protected $base = 'https://api.mch.weixin.qq.com'; | |||
/** | |||
* 实例对象静态缓存 | |||
* @var array | |||
*/ | |||
static $cache = []; | |||
/** | |||
* 配置参数 | |||
* @var array | |||
*/ | |||
protected $config = [ | |||
'appid' => '', // 微信绑定APPID,需配置 | |||
'mch_id' => '', // 微信商户编号,需要配置 | |||
'mch_v3_key' => '', // 微信商户密钥,需要配置 | |||
'cert_serial' => '', // 商户证书序号,无需配置 | |||
'cert_public' => '', // 商户公钥内容,需要配置 | |||
'cert_private' => '', // 商户密钥内容,需要配置 | |||
]; | |||
/** | |||
* BasicWePayV3 constructor. | |||
* @param array $options [mch_id, mch_v3_key, cert_public, cert_private] | |||
*/ | |||
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_private'])) { | |||
throw new InvalidArgumentException("Missing Config -- [cert_private]"); | |||
} | |||
if (empty($options['cert_public'])) { | |||
throw new InvalidArgumentException("Missing Config -- [cert_public]"); | |||
} | |||
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']; | |||
$this->config['cert_serial'] = openssl_x509_parse($this->config['cert_public'])['serialNumberHex']; | |||
if (empty($this->config['cert_serial'])) { | |||
throw new InvalidArgumentException("Failed to parse certificate public key"); | |||
} | |||
} | |||
/** | |||
* 静态创建对象 | |||
* @param array $config | |||
* @return static | |||
*/ | |||
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 $method 请求访问 | |||
* @param string $pathinfo 请求路由 | |||
* @param string $jsondata 请求数据 | |||
* @param bool $verify 是否验证 | |||
* @return array | |||
* @throws \WeChat\Exceptions\InvalidResponseException | |||
*/ | |||
public function doRequest($method, $pathinfo, $jsondata = '', $verify = false) | |||
{ | |||
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) | |||
); | |||
list($header, $content) = $this->_doRequestCurl($method, $this->base . $pathinfo, [ | |||
'data' => $jsondata, 'header' => [ | |||
"Accept: application/json", "Content-Type: application/json", | |||
'User-Agent: https://thinkadmin.top', "Authorization: WECHATPAY2-SHA256-RSA2048 {$token}", | |||
], | |||
]); | |||
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 { | |||
$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 json_decode($content, true); | |||
} | |||
/** | |||
* 通过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 签名内容 | |||
* @return string | |||
*/ | |||
protected function signBuild($data) | |||
{ | |||
$pkeyid = openssl_pkey_get_private($this->config['cert_private']); | |||
openssl_sign($data, $signature, $pkeyid, 'sha256WithRSAEncryption'); | |||
return base64_encode($signature); | |||
} | |||
/** | |||
* 验证内容签名 | |||
* @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 = '') | |||
{ | |||
$cert = $this->tmpFile($serial); | |||
if (empty($cert)) { | |||
Cert::instance($this->config)->download(); | |||
$cert = $this->tmpFile($serial); | |||
} | |||
return @openssl_verify($data, base64_decode($sign), openssl_x509_read($cert), 'sha256WithRSAEncryption'); | |||
} | |||
/** | |||
* 写入或读取临时文件 | |||
* @param string $name | |||
* @param null|string $content | |||
* @return string | |||
* @throws \WeChat\Exceptions\LocalCacheException | |||
*/ | |||
protected function tmpFile($name, $content = null) | |||
{ | |||
if (is_null($content)) { | |||
return base64_decode(Tools::getCache($name) ?: ''); | |||
} else { | |||
return Tools::setCache($name, base64_encode($content), 7200); | |||
} | |||
} | |||
} |
@@ -0,0 +1,68 @@ | |||
<?php | |||
namespace WePayV3\Contracts; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Exceptions\InvalidArgumentException; | |||
use WeChat\Exceptions\InvalidDecryptException; | |||
/** | |||
* Aes 解密工具类 | |||
* Class DecryptAes | |||
* @package WePayV3\Contracts | |||
*/ | |||
class DecryptAes | |||
{ | |||
private $aesKey; | |||
const KEY_LENGTH_BYTE = 32; | |||
const AUTH_TAG_LENGTH_BYTE = 16; | |||
/** | |||
* 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'); | |||
} | |||
} |
@@ -0,0 +1,95 @@ | |||
<?php | |||
namespace WePayV3; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\Tools; | |||
use WeChat\Exceptions\InvalidArgumentException; | |||
use WePayV3\Contracts\BasicWePay; | |||
use WePayV3\Contracts\DecryptAes; | |||
/** | |||
* 订单支付接口 | |||
* Class Order | |||
* @package WePayV3 | |||
*/ | |||
class Order extends BasicWePay | |||
{ | |||
const WXPAY_H5 = 'h5'; | |||
const WXPAY_APP = 'app'; | |||
const WXPAY_JSAPI = 'jsapi'; | |||
const WXPAY_NATIVE = 'native'; | |||
/** | |||
* 创建支付订单 | |||
* @param string $type 支付类型 | |||
* @param array $data 支付参数 | |||
* @return array | |||
* @throws \WeChat\Exceptions\InvalidResponseException | |||
*/ | |||
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 { | |||
// 创建预支付码 | |||
$result = $this->doRequest('POST', $types[$type], json_encode($data, JSON_UNESCAPED_UNICODE), true); | |||
if (empty($result['prepay_id'])) return $result; | |||
// 支付参数签名 | |||
$time = (string)time(); | |||
$appid = $this->config['appid']; | |||
$prepayId = $result['prepay_id']; | |||
$nonceStr = Tools::createNoncestr(); | |||
if ($type === 'app') { | |||
$sign = $this->signBuild(join("\n", [$appid, $time, $nonceStr, $prepayId, ''])); | |||
return ['partnerId' => $this->config['mch_id'], 'prepayId' => $prepayId, 'package' => 'Sign=WXPay', 'nonceStr' => $nonceStr, 'timeStamp' => $time, 'sign' => $sign]; | |||
} elseif ($type === 'jsapi') { | |||
$sign = $this->signBuild(join("\n", [$appid, $time, $nonceStr, "prepay_id={$prepayId}", ''])); | |||
return ['appId' => $appid, 'timeStamp' => $time, 'nonceStr' => $nonceStr, 'package' => "prepay_id={$prepayId}", 'signType' => 'RSA', 'paySign' => $sign]; | |||
} else { | |||
return $result; | |||
} | |||
} | |||
} | |||
/** | |||
* 支付订单查询 | |||
* @param string $orderNo 订单单号 | |||
* @return array | |||
* @throws \WeChat\Exceptions\InvalidResponseException | |||
*/ | |||
public function query($orderNo) | |||
{ | |||
$pathinfo = "/v3/pay/transactions/out-trade-no/{$orderNo}"; | |||
return $this->doRequest('GET', "{$pathinfo}?mchid={$this->config['mch_id']}", '', true); | |||
} | |||
/** | |||
* 支付通知 | |||
* @return array | |||
* @throws \WeChat\Exceptions\InvalidDecryptException | |||
*/ | |||
public function notify(array $parameters = []) | |||
{ | |||
if (empty($parameters)) { | |||
$body = file_get_contents('php://input'); | |||
$data = json_decode($body, true); | |||
} else { | |||
$data = $parameters; | |||
} | |||
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; | |||
} | |||
} |
@@ -0,0 +1,61 @@ | |||
<?php | |||
namespace WePayV3; | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
use WeChat\Contracts\Tools; | |||
use WeChat\Exceptions\InvalidDecryptException; | |||
use WeChat\Exceptions\InvalidResponseException; | |||
use WePayV3\Contracts\BasicWePay; | |||
/** | |||
* 订单退款接口 | |||
* Class Refund | |||
* @package WePayV3 | |||
*/ | |||
class Refund extends BasicWePay | |||
{ | |||
/** | |||
* 创建退款订单 | |||
* @param array $data 退款参数 | |||
* @return array | |||
* @throws \WeChat\Exceptions\InvalidResponseException | |||
*/ | |||
public function create($data) | |||
{ | |||
return $this->doRequest('POST', '/v3/ecommerce/refunds/apply', json_encode($data, JSON_UNESCAPED_UNICODE), true); | |||
} | |||
/** | |||
* 退款订单查询 | |||
* @param string $refundNo 退款单号 | |||
* @return array | |||
* @throws \WeChat\Exceptions\InvalidResponseException | |||
*/ | |||
public function query($refundNo) | |||
{ | |||
$pathinfo = "/v3/ecommerce/refunds/out-refund-no/{$refundNo}"; | |||
return $this->doRequest('GET', "{$pathinfo}?sub_mchid={$this->config['mch_id']}", '', true); | |||
} | |||
/** | |||
* 获取退款通知 | |||
* @return array | |||
* @throws \WeChat\Exceptions\InvalidDecryptException | |||
* @throws \WeChat\Exceptions\InvalidResponseException | |||
*/ | |||
public function notify() | |||
{ | |||
$data = Tools::xml2arr(file_get_contents("php://input")); | |||
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()); | |||
} | |||
} | |||
} |
@@ -0,0 +1,26 @@ | |||
<?php | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
// 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' => time(), // 商户订单号 | |||
'total_amount' => '1', // 支付金额 | |||
'subject' => '支付宝订单标题', // 支付订单描述 | |||
]); | |||
echo $result; | |||
} catch (\Exception $e) { | |||
echo $e->getMessage(); | |||
} | |||
@@ -0,0 +1,24 @@ | |||
<?php | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
// 1. 手动加载入口文件 | |||
include "../include.php"; | |||
// 2. 准备公众号配置参数 | |||
$config = include "./alipay.php"; | |||
try { | |||
// 实例支付对象 | |||
// $pay = new \AliPay\Bill($config); | |||
// $pay = \We::AliPayBill($config); | |||
$pay = \AliPay\Bill::instance($config); | |||
// 请参考(请求参数):https://docs.open.alipay.com/api_15/alipay.data.dataservice.bill.downloadurl.query | |||
$result = $pay->apply([ | |||
'bill_date' => '2020-07-03', // 账单时间(日账单yyyy-MM-dd,月账单 yyyy-MM) | |||
'bill_type' => 'signcustomer', // 账单类型(trade指商户基于支付宝交易收单的业务账单,signcustomer是指基于商户支付宝余额收入及支出等资金变动的帐务账单) | |||
]); | |||
echo '<pre>'; | |||
var_export($result); | |||
} catch (Exception $e) { | |||
echo $e->getMessage(); | |||
} |
@@ -0,0 +1,27 @@ | |||
<?php | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
// 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(); | |||
} |
@@ -0,0 +1,29 @@ | |||
<?php | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
// 1. 手动加载入口文件 | |||
include "../include.php"; | |||
// 2. 准备公众号配置参数 | |||
$config = include "./alipay.php"; | |||
try { | |||
// 实例支付对象 | |||
// $pay = We::AliPayPos($config); | |||
// $pay = new \AliPay\Pos($config); | |||
$pay = \AliPay\Pos::instance($config); | |||
// 参数链接:https://docs.open.alipay.com/api_1/alipay.trade.pay | |||
$result = $pay->apply([ | |||
'out_trade_no' => '4312412343', // 订单号 | |||
'total_amount' => '13', // 订单金额,单位:元 | |||
'subject' => '订单商品标题', // 订单商品标题 | |||
'auth_code' => '123456', // 授权码 | |||
]); | |||
echo '<pre>'; | |||
var_export($result); | |||
} catch (Exception $e) { | |||
echo $e->getMessage(); | |||
} | |||
@@ -0,0 +1,27 @@ | |||
<?php | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
// 1. 手动加载入口文件 | |||
include "../include.php"; | |||
// 2. 准备公众号配置参数 | |||
$config = include "./alipay.php"; | |||
// 原商户订单号 | |||
$out_trade_no = '56737188841424'; | |||
// 申请退款金额 | |||
$refund_fee = '1.00'; | |||
try { | |||
// 实例支付对象 | |||
// $pay = We::AliPayApp($config); | |||
// $pay = new \AliPay\App($config); | |||
$pay = \AliPay\App::instance($config); | |||
// 参考链接:https://docs.open.alipay.com/api_1/alipay.trade.refund | |||
$result = $pay->refund($out_trade_no, $refund_fee); | |||
echo '<pre>'; | |||
var_export($result); | |||
} catch (Exception $e) { | |||
echo $e->getMessage(); | |||
} |
@@ -0,0 +1,28 @@ | |||
<?php | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
// 1. 手动加载入口文件 | |||
include "../include.php"; | |||
// 2. 准备公众号配置参数 | |||
$config = include "./alipay.php"; | |||
try { | |||
// 实例支付对象 | |||
// $pay = We::AliPayScan($config); | |||
// $pay = new \AliPay\Scan($config); | |||
$pay = \AliPay\Scan::instance($config); | |||
// 参考链接:https://docs.open.alipay.com/api_1/alipay.trade.precreate | |||
$result = $pay->apply([ | |||
'out_trade_no' => '14321412', // 订单号 | |||
'total_amount' => '13', // 订单金额,单位:元 | |||
'subject' => '订单商品标题', // 订单商品标题 | |||
]); | |||
echo '<pre>'; | |||
var_export($result); | |||
} catch (Exception $e) { | |||
echo $e->getMessage(); | |||
} | |||
@@ -0,0 +1,25 @@ | |||
<?php | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
// 1. 手动加载入口文件 | |||
include "../include.php"; | |||
// 2. 准备公众号配置参数 | |||
$config = include "./alipay.php"; | |||
try { | |||
// 实例支付对象 | |||
// $pay = We::AliPayTransfer($config); | |||
// $pay = new \AliPay\Transfer($config); | |||
$pay = \AliPay\Transfer::instance($config); | |||
// 参考链接:https://docs.open.alipay.com/api_28/alipay.fund.account.query/ | |||
$result = $pay->queryAccount([ | |||
'alipay_user_id' => $config['appid'], // 订单号 | |||
'account_scene_code' => 'SCENE_000_000_000', | |||
]); | |||
echo '<pre>'; | |||
var_export($result); | |||
} catch (Exception $e) { | |||
echo $e->getMessage(); | |||
} | |||
@@ -0,0 +1,32 @@ | |||
<?php | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
// 1. 手动加载入口文件 | |||
include "../include.php"; | |||
// 2. 准备公众号配置参数 | |||
$config = include "./alipay.php"; | |||
try { | |||
// 实例支付对象 | |||
// $pay = We::AliPayTransfer($config); | |||
// $pay = new \AliPay\Transfer($config); | |||
$pay = \AliPay\Transfer::instance($config); | |||
// 参考链接:https://docs.open.alipay.com/api_28/alipay.fund.trans.uni.transfer/ | |||
$result = $pay->create([ | |||
'out_biz_no' => time(), // 订单号 | |||
'trans_amount' => '10', // 转账金额 | |||
'product_code' => 'TRANS_ACCOUNT_NO_PWD', | |||
'biz_scene' => 'DIRECT_TRANSFER', | |||
'payee_info' => [ | |||
'identity' => 'zoujingli@qq.com', | |||
'identity_type' => 'ALIPAY_LOGON_ID', | |||
'name' => '邹景立', | |||
], | |||
]); | |||
echo '<pre>'; | |||
var_export($result); | |||
} catch (Exception $e) { | |||
echo $e->getMessage(); | |||
} | |||
@@ -0,0 +1,26 @@ | |||
<?php | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
// 1. 手动加载入口文件 | |||
include "../include.php"; | |||
// 2. 准备公众号配置参数 | |||
$config = include "./alipay.php"; | |||
try { | |||
// 实例支付对象 | |||
// $pay = We::AliPayTransfer($config); | |||
// $pay = new \AliPay\Transfer($config); | |||
$pay = \AliPay\Transfer::instance($config); | |||
// 参考链接:https://docs.open.alipay.com/api_28/alipay.fund.trans.common.query/ | |||
$result = $pay->queryResult([ | |||
'out_biz_no' => '201808080001', // 订单号 | |||
'product_code' => 'TRANS_ACCOUNT_NO_PWD', | |||
'biz_scene' => 'DIRECT_TRANSFER', | |||
]); | |||
echo '<pre>'; | |||
var_export($result); | |||
} catch (Exception $e) { | |||
echo $e->getMessage(); | |||
} | |||
@@ -0,0 +1,31 @@ | |||
<?php | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
// 1. 手动加载入口文件 | |||
include "../include.php"; | |||
// 2. 准备公众号配置参数 | |||
$config = include "./alipay.php"; | |||
try { | |||
// 实例支付对象 | |||
// $pay = We::AliPayTransfer($config); | |||
// $pay = new \AliPay\Transfer($config); | |||
$pay = \AliPay\Transfer::instance($config); | |||
// 参考链接:https://docs.open.alipay.com/api_28/alipay.fund.trans.toaccount.transfer | |||
$result = $pay->apply([ | |||
'out_biz_no' => time(), // 订单号 | |||
'payee_type' => 'ALIPAY_LOGONID', // 收款方账户类型(ALIPAY_LOGONID | ALIPAY_USERID) | |||
'payee_account' => 'demo@sandbox.com', // 收款方账户 | |||
'amount' => '10', // 转账金额 | |||
'payer_show_name' => '未寒', // 付款方姓名 | |||
'payee_real_name' => '张三', // 收款方真实姓名 | |||
'remark' => '张三', // 转账备注 | |||
]); | |||
echo '<pre>'; | |||
var_export($result); | |||
} catch (Exception $e) { | |||
echo $e->getMessage(); | |||
} | |||
@@ -0,0 +1,30 @@ | |||
<?php | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
// 1. 手动加载入口文件 | |||
include "../include.php"; | |||
// 2. 准备公众号配置参数 | |||
$config = include "./alipay.php"; | |||
// 参考公共参数 https://docs.open.alipay.com/203/107090/ | |||
$config['notify_url'] = 'http://pay.thinkadmin.top/test/alipay-notify.php'; | |||
$config['return_url'] = 'http://pay.thinkadmin.top/test/alipay-success.php'; | |||
try { | |||
// 实例支付对象 | |||
// $pay = We::AliPayWap($config); | |||
// $pay = new \AliPay\Wap($config); | |||
$pay = \AliPay\Wap::instance($config); | |||
// 参考链接:https://docs.open.alipay.com/api_1/alipay.trade.wap.pay | |||
$result = $pay->apply([ | |||
'out_trade_no' => time(), // 商户订单号 | |||
'total_amount' => '1', // 支付金额 | |||
'subject' => '支付订单描述', // 支付订单描述 | |||
]); | |||
echo $result; | |||
} catch (Exception $e) { | |||
echo $e->getMessage(); | |||
} | |||
@@ -0,0 +1,31 @@ | |||
<?php | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
// 1. 手动加载入口文件 | |||
include "../include.php"; | |||
// 2. 准备公众号配置参数 | |||
$config = include "./alipay.php"; | |||
// 参考公共参数 https://docs.open.alipay.com/203/107090/ | |||
$config['notify_url'] = 'http://pay.thinkadmin.top/test/alipay-notify.php'; | |||
$config['return_url'] = 'http://pay.thinkadmin.top/test/alipay-success.php'; | |||
try { | |||
// 实例支付对象 | |||
// $pay = We::AliPayWeb($config); | |||
// $pay = new \AliPay\Web($config); | |||
$pay = \AliPay\Web::instance($config); | |||
// 参考链接:https://docs.open.alipay.com/api_1/alipay.trade.page.pay | |||
$result = $pay->apply([ | |||
'out_trade_no' => time(), // 商户订单号 | |||
'total_amount' => '1', // 支付金额 | |||
'subject' => '支付订单描述', // 支付订单描述 | |||
]); | |||
echo $result; | |||
} catch (Exception $e) { | |||
echo $e->getMessage(); | |||
} | |||
@@ -0,0 +1,23 @@ | |||
<?php | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
return [ | |||
// 沙箱模式 | |||
'debug' => true, | |||
// 签名类型(RSA|RSA2) | |||
'sign_type' => "RSA2", | |||
// 应用ID | |||
'appid' => '2016090900468879', | |||
// 应用私钥的内容 (1行填写,特别注意:这里的应用私钥通常由支付宝密钥管理工具生成) | |||
'private_key' => 'MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC3pbN7esinxgjE8uxXAsccgGNKIq+PR1LteNTFOy0fsete43ObQCrzd9DO0zaUeBUzpIOnxrKxez7QoZROZMYrinttFZ/V5rbObEM9E5AR5Tv/Fr4IBywoS8ZtN16Xb+fZmibfU91yq9O2RYSvscncU2qEYmmaTenM0QlUO80ZKqPsM5JkgCNdcYZTUeHclWeyER3dSImNtlSKiSBSSTHthb11fkudjzdiUXua0NKVWyYuAOoDMcpXbD6NJmYqEA/iZ/AxtQt08pv0Mow581GPB0Uop5+qA2hCV85DpagE94a067sKcRui0rtkJzHem9k7xVL+2RoFm1fv3RnUkMwhAgMBAAECggEAAetkddzxrfc+7jgPylUIGb8pyoOUTC4Vqs/BgZI9xYAJksNT2QKRsFvHPfItNt4Ocqy8h4tnIL3GCU43C564B4p6AcjhE85GiN/O0BudPOKlfuQQ9mqExqMMHuYeQfz0cmzPDTSGMwWiv9v4KBH2pyvkCCAzNF6uG+rvawb4/NNVuiI7C8Ku/wYsamtbgjMZVOFFdScYgIw1BgA99RUU/fWBLMnTQkoyowSRb9eSmEUHjt/WQt+/QgKAT2WmuX4RhaGy0qcQLbNaJNKXdJ+PVhQrSiasINNtqYMa8GsQuuKsk3X8TCg9K6/lowivt5ruhyWcP2sx93zY/LGzIHgHcQKBgQDoZlcs9RWxTdGDdtH8kk0J/r+QtMijNzWI0a+t+ZsWOyd3rw+uM/8O4JTNP4Y98TvvxhJXewITbfiuOIbW1mxh8bnO/fcz7+RXZKgPDeoTeNo717tZFZGBEyUdH9M9Inqvht7+hjVDIMCYBDomYebdk3Xqo4mDBjLRdVNGrhGmVQKBgQDKS/MgTMK8Ktfnu1KzwCbn/FfHTOrp1a1t1wWPv9AW0rJPYeaP6lOkgIoO/1odG9qDDhdB6njqM+mKY5Yr3N94PHamHbwJUCmbkqEunCWpGzgcQZ1Q254xk9D7UKq/XUqW2WDqDq80GQeNial+fBc46yelQzokwdA+JdIFKoyinQKBgQCBems9V/rTAtkk1nFdt6EGXZEbLS3PiXXhGXo4gqV+OEzf6H/i/YMwJb2hsK+5GQrcps0XQihA7PctEb9GOMa/tu5fva0ZmaDtc94SLR1p5d4okyQFGPgtIp594HpPSEN0Qb9BrUJFeRz0VP6U3dzDPGHo7V4yyqRLgIN6EIcy1QKBgAqdh6mHPaTAHspDMyjJiYEc5cJIj/8rPkmIQft0FkhMUB0IRyAALNlyAUyeK61hW8sKvz+vPR8VEEk5xpSQp41YpuU6pDZc5YILZLfca8F+8yfQbZ/jll6Foi694efezl4yE/rUQG9cbOAJfEJt4o4TEOaEK5XoMbRBKc8pl22lAoGARTq0qOr9SStihRAy9a+8wi2WEwL4QHcmOjH7iAuJxy5b5TRDSjlk6h+0dnTItiFlTXdfpO8KhWA8EoSJVBZ1kcACQDFgMIA+VM+yXydtzMotOn21W4stfZ4I6dHFiujMsnKpNYVpQh3oCrJf4SeXiQDdiSCodqb1HlKkEc6naHQ=', | |||
// 支付宝公钥内容 (1行填写,特别注意:这里不是应用公钥而是支付宝公钥,通常是上传应用公钥换取支付宝公钥,在网页可以复制) | |||
'public_key' => 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtU71NY53UDGY7JNvLYAhsNa+taTF6KthIHJmGgdio9bkqeJGhHk6ttkTKkLqFgwIfgAkHpdKiOv1uZw6gVGZ7TCu5LfHTqKrCd6Uz+N7hxhY+4IwicLgprcV1flXQLmbkJYzFMZqkXGkSgOsR2yXh4LyQZczgk9N456uuzGtRy7MoB4zQy34PLUkkxR6W1B2ftNbLRGXv6tc7p/cmDcrY6K1bSxnGmfRxFSb8lRfhe0V0UM6pKq2SGGSeovrKHN0OLp+Nn5wcULVnFgATXGCENshRlp96piPEBFwneXs19n+sX1jx60FTR7/rME3sW3AHug0fhZ9mSqW4x401WjdnwIDAQAB', | |||
// 应用公钥的内容(新版资金类接口转 app_cert_sn) | |||
'app_cert' => '', | |||
// 支付宝根证书内容(新版资金类接口转 alipay_root_cert_sn) | |||
'root_cert' => '', | |||
// 支付成功通知地址 | |||
'notify_url' => '', | |||
// 网页支付回跳地址 | |||
'return_url' => '', | |||
]; |
@@ -0,0 +1,34 @@ | |||
<?php | |||
if (!defined('DEDEINC')) exit('dedebiz'); | |||
// 配置缓存处理函数 | |||
//\WeChat\Contracts\Tools::$cache_callable = [ | |||
// 'set' => function ($name, $value, $expired = 360) { | |||
// var_dump(func_get_args()); | |||
// }, | |||
// 'get' => function ($name) { | |||
// var_dump(func_get_args()); | |||
// }, | |||
// 'del' => function ($name) { | |||
// var_dump(func_get_args()); | |||
// }, | |||
// 'put' => function ($name) { | |||
// var_dump(func_get_args()); | |||
// }, | |||
//]; | |||
return [ | |||
'token' => 'test', | |||
'appid' => 'wx60a43dd8161666d4', | |||
'appsecret' => 'b4e28746f1bd73b5c6684f5e01883c36', | |||
'encodingaeskey' => 'BJIUzE0gqlWy0GxfPp4J1oPTBmOrNDIGPNav1YFH5Z5', | |||
// 配置商户支付参数 | |||
'mch_id' => "1332187001", | |||
'mch_key' => 'A82DC5BD1F3359081049C568D8502BC5', | |||
// 配置商户支付双向证书目录 (p12 | key,cert 二选一,两者都配置时p12优先) | |||
'ssl_p12' => __DIR__ . DIRECTORY_SEPARATOR . 'cert' . DIRECTORY_SEPARATOR . '1332187001_20181030_cert.p12', | |||
// 'ssl_key' => __DIR__ . DIRECTORY_SEPARATOR . 'cert' . DIRECTORY_SEPARATOR . '1332187001_20181030_key.pem', | |||
// 'ssl_cer' => __DIR__ . DIRECTORY_SEPARATOR . 'cert' . DIRECTORY_SEPARATOR . '1332187001_20181030_cert.pem', | |||
// 配置缓存目录,需要拥有写权限 | |||
'cache_path' => '', | |||
]; |
@@ -0,0 +1,23 @@ | |||
<?php | |||
if (!defined('DEDEINC')) exit('dedebiz');include '../include.php'; | |||
// 小程序配置 | |||
$config = [ | |||
'appid' => 'wx6bb7b70258da09c6', | |||
'appsecret' => '78b7b8d65bd67b078babf951d4342b42', | |||
]; | |||
// 解码数据 | |||
$iv = 'ltM/wT7hsAl0TijEBI4v/g=='; | |||
$code = '013LyiTR0TwjC92QjJRR0mEsTR0LyiT3'; | |||
$decode = 'eIoVtIC2YzLCnrwiIs1IBbXMvC0vyL8bo1IhD38fUQIRbk3lgTWa0Hdw/Ty7NTs3iu7YlqqZBti+cxd6dCfeXBUQwTO2QpbHg0WTeDAdrihsHRHm4dCWdfTx8rzDloGbNOIsKdRElIhUH5YFdiTr5AYiufUDb34cwJ4GNWLAUq4bR0dmFeVEi+3nfwe2MAjGYDl4aq719VLsHodOggK6lXZvM5wjoDyuZsK2dPqJr3/Ji30Z0mdyFq32R4uR3rtJH/h+Rj0+/QmE9QYG7Y6Z48hgPE8cpnhRQNwH49jnC/zKZ9wtDkQ/J8J3Ed2i58zcuY01v8IV+pZ8oBUKXfO5ha+APOxtBSTzyHraU/2RGo8UWtOF6h64OQZhd/UQQy362eyc/qoq8sF9JnEFRP0mRmTDJ+u9oyDhxswCu6x8V73ERWaJeEGSCyjiGpep7/DxZ6eSSBq36OB0BWBkJqsq9Q=='; | |||
$sessionKey = 'OetNxl86B/yMpbwG6wtMEw=='; | |||
// $mini = \We::WeMiniCrypt($config); | |||
// $mini = new WeMini\Crypt($config); | |||
$mini = \WeMini\Crypt::instance($config); | |||
echo '<pre>'; | |||
//print_r($mini->session($code)); | |||
print_r($mini->decode($iv, $sessionKey, $decode)); | |||
//print_r($mini->userInfo($code, $iv, $decode)); |
@@ -0,0 +1,24 @@ | |||
<?php | |||
if (!defined('DEDEINC')) exit('dedebiz');include '../include.php'; | |||
// 小程序配置 | |||
$config = [ | |||
'appid' => 'wx6bb7b70258da09c6', | |||
'appsecret' => '78b7b8d65bd67b078babf951d4342b42', | |||
]; | |||
//We::config($config); | |||
// $mini = We::WeMiniQrcode($config); | |||
// $mini = new WeMini\Qrcode($config); | |||
$mini = \WeMini\Qrcode::instance($config); | |||
//echo '<pre>'; | |||
try { | |||
header('Content-type:image/jpeg'); //输出的类型 | |||
// echo $mini->createDefault('pages/index?query=1'); | |||
// echo $mini->createMiniScene('432432', 'pages/index/index'); | |||
echo $mini->createMiniPath('pages/index?query=1'); | |||
} catch (Exception $e) { | |||
var_dump($e->getMessage()); | |||
} |