@@ -8,15 +8,64 @@ | |||||
* @license https://www.dedebiz.com/license | * @license https://www.dedebiz.com/license | ||||
* @link https://www.dedebiz.com | * @link https://www.dedebiz.com | ||||
*/ | */ | ||||
if (!empty($_REQUEST['dopost'])) define('IS_DEDEAPI', TRUE); | |||||
require_once(dirname(__FILE__)."/config.php"); | require_once(dirname(__FILE__)."/config.php"); | ||||
require_once(DEDEINC.'/datalistcp.class.php'); | require_once(DEDEINC.'/datalistcp.class.php'); | ||||
CheckPurview('sys_Data'); | CheckPurview('sys_Data'); | ||||
$dopost = (empty($dopost)) ? '' : $dopost; | $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> | <!DOCTYPE html> | ||||
<html> | <html> | ||||
<head> | <head> | ||||
<meta charset="utf-8"> | <meta charset="utf-8"> | ||||
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1"> | <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/jquery.min.js"></script> | ||||
<script src="../static/web/js/bootstrap.min.js"></script> | <script src="../static/web/js/bootstrap.min.js"></script> | ||||
</head> | </head> | ||||
<body> | <body> | ||||
<table cellpadding="3" cellspacing="1" align="center" class="table maintable my-3"> | <table cellpadding="3" cellspacing="1" align="center" class="table maintable my-3"> | ||||
<tr> | <tr> | ||||
@@ -17,7 +19,8 @@ | |||||
<table cellspacing="0" cellpadding="0" class="table table-borderless w-100"> | <table cellspacing="0" cellpadding="0" class="table table-borderless w-100"> | ||||
<tr> | <tr> | ||||
<td>支付接口设置</td> | <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> | </tr> | ||||
</table> | </table> | ||||
</td> | </td> | ||||
@@ -26,19 +29,24 @@ | |||||
<td colspan="4"> | <td colspan="4"> | ||||
<ul class="nav nav-tabs" id="myTab" role="tablist"> | <ul class="nav nav-tabs" id="myTab" role="tablist"> | ||||
<li class="nav-item" role="presentation"> | <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> | ||||
<li class="nav-item" role="presentation"> | <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> | ||||
<li class="nav-item" role="presentation"> | <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> | ||||
<li class="nav-item" role="presentation"> | <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> | ||||
<li class="nav-item" role="presentation"> | <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> | </li> | ||||
</ul> | </ul> | ||||
<div class="tab-content py-3" id="myTabContent"> | <div class="tab-content py-3" id="myTabContent"> | ||||
@@ -46,7 +54,8 @@ | |||||
<form> | <form> | ||||
<div class="form-group"> | <div class="form-group"> | ||||
<label>描述</label> | <label>描述</label> | ||||
<p>微信支付是腾讯公司的支付业务品牌,微信支付商户平台支持线下场所、公众号、小程序、PC网站、APP、企业微信等经营场景快速接入微信支付。微信支付全面打通O2O生活消费领域,提供专业的互联网+行业解决方案,微信支付支持微信红包和微信理财通,是移动支付的首选。</p> | |||||
<p>微信支付是腾讯公司的支付业务品牌,微信支付商户平台支持线下场所、公众号、小程序、PC网站、APP、企业微信等经营场景快速接入微信支付。微信支付全面打通O2O生活消费领域,提供专业的互联网+行业解决方案,微信支付支持微信红包和微信理财通,是移动支付的首选。 | |||||
</p> | |||||
</div> | </div> | ||||
<div class="form-group"> | <div class="form-group"> | ||||
<label for="iptWechatAppID">AppID</label> | <label for="iptWechatAppID">AppID</label> | ||||
@@ -66,18 +75,23 @@ | |||||
</div> | </div> | ||||
<div class="form-group"> | <div class="form-group"> | ||||
<label for="iptWechatSerialNo">商户证书序列号</label> | <label for="iptWechatSerialNo">商户证书序列号</label> | ||||
<input type="appid" class="form-control" id="iptWechatSerialNo"> | |||||
<input type="text" class="form-control" id="iptWechatSerialNo"> | |||||
</div> | </div> | ||||
<div class="form-group"> | <div class="form-group"> | ||||
<label>商户证书文件</label> | <label>商户证书文件</label> | ||||
<div class="custom-file"> | <div class="custom-file"> | ||||
<input type="file" class="custom-file-input" id="iptWechatPrivateKey"> | <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> | </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"> | <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> | </div> | ||||
</form> | </form> | ||||
</div> | </div> | ||||
@@ -85,7 +99,8 @@ | |||||
<form> | <form> | ||||
<div class="form-group"> | <div class="form-group"> | ||||
<label for="iptAppID">描述</label> | <label for="iptAppID">描述</label> | ||||
<p>支付宝,全球领先的独立第三方支付平台,致力于为广大用户提供安全快速的电子支付/网上支付/安全支付/手机支付体验,及转账收款/水电煤缴费/信用卡还款/AA收款等生活服务应用。</p> | |||||
<p>支付宝,全球领先的独立第三方支付平台,致力于为广大用户提供安全快速的电子支付/网上支付/安全支付/手机支付体验,及转账收款/水电煤缴费/信用卡还款/AA收款等生活服务应用。 | |||||
</p> | |||||
</div> | </div> | ||||
<div class="form-group"> | <div class="form-group"> | ||||
<label for="iptAlipayAPPID">APPID</label> | <label for="iptAlipayAPPID">APPID</label> | ||||
@@ -99,30 +114,37 @@ | |||||
<label>应用公钥证书</label> | <label>应用公钥证书</label> | ||||
<div class="custom-file"> | <div class="custom-file"> | ||||
<input type="file" class="custom-file-input" id="iptAlipayAppCertPublicKey"> | <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> | </div> | ||||
<div class="form-group"> | <div class="form-group"> | ||||
<label>支付宝公钥证书</label> | <label>支付宝公钥证书</label> | ||||
<div class="custom-file"> | <div class="custom-file"> | ||||
<input type="file" class="custom-file-input" id="iptAlipayCertPublicKey"> | <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> | </div> | ||||
<div class="form-group"> | <div class="form-group"> | ||||
<label>支付宝根证书</label> | <label>支付宝根证书</label> | ||||
<div class="custom-file"> | <div class="custom-file"> | ||||
<input type="file" class="custom-file-input" id="iptAlipayRootCert"> | <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> | </div> | ||||
<div class="form-group"> | <div class="form-group"> | ||||
<label for="iptAlipaySignType">签名类型</label> | <label for="iptAlipaySignType">签名类型</label> | ||||
<input type="text" class="form-control" id="iptAlipaySignType" value="RSA2" disabled> | <input type="text" class="form-control" id="iptAlipaySignType" value="RSA2" disabled> | ||||
</div> | </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"> | <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> | </div> | ||||
</form> | </form> | ||||
</div> | </div> | ||||
@@ -134,19 +156,23 @@ | |||||
</div> | </div> | ||||
<div class="form-group"> | <div class="form-group"> | ||||
<label for="iptBankAccountName">账户名</label> | <label for="iptBankAccountName">账户名</label> | ||||
<input type="appid" class="form-control" id="iptBankAccountName"> | |||||
<input type="text" class="form-control" id="iptBankAccountName"> | |||||
</div> | </div> | ||||
<div class="form-group"> | <div class="form-group"> | ||||
<label for="iptBankAccountNO">账号</label> | <label for="iptBankAccountNO">账号</label> | ||||
<input type="appid" class="form-control" id="iptBankAccountNO"> | |||||
<input type="text" class="form-control" id="iptBankAccountNO"> | |||||
</div> | </div> | ||||
<div class="form-group"> | <div class="form-group"> | ||||
<label for="iptBankName">开户行</label> | <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> | ||||
<div class="form-group form-check"> | <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> | </div> | ||||
</form> | </form> | ||||
</div> | </div> | ||||
@@ -156,9 +182,13 @@ | |||||
<label>描述</label> | <label>描述</label> | ||||
<p>支持采用积分进行支付。</p> | <p>支持采用积分进行支付。</p> | ||||
</div> | </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"> | <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> | </div> | ||||
</form> | </form> | ||||
</div> | </div> | ||||
@@ -168,13 +198,18 @@ | |||||
<label>描述</label> | <label>描述</label> | ||||
<p>购买后直接发货,到货后再进行支付。</p> | <p>购买后直接发货,到货后再进行支付。</p> | ||||
</div> | </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"> | <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> | </div> | ||||
</form> | </form> | ||||
</div> | </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> | </div> | ||||
</td> | </td> | ||||
</tr> | </tr> | ||||
@@ -184,6 +219,134 @@ | |||||
let fileName = $(this).val().split('\\').pop(); | let fileName = $(this).val().split('\\').pop(); | ||||
$(this).siblings('.custom-file-label').addClass("selected").html(fileName); | $(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> | </script> | ||||
</body> | </body> | ||||
</html> | </html> |
@@ -556,9 +556,6 @@ INSERT INTO `#@__scores` VALUES ('2','列兵','1','0','1'), | |||||
INSERT INTO `#@__member_stowtype` VALUES ('sys','系统收藏','archives_do.php'), | INSERT INTO `#@__member_stowtype` VALUES ('sys','系统收藏','archives_do.php'), | ||||
('book','小说收藏','/book/book.php?bid'); | ('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 `#@__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'), | INSERT INTO `#@__stepselect` VALUES ('1','血型','blood','1','1'), | ||||
@@ -732,22 +732,6 @@ CREATE TABLE `#@__mytag` ( | |||||
KEY `tagname` (`tagname`,`typeid`,`timeset`,`endtime`,`starttime`) | KEY `tagname` (`tagname`,`typeid`,`timeset`,`endtime`,`starttime`) | ||||
) TYPE=MyISAM; | ) 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`; | DROP TABLE IF EXISTS `#@__plus`; | ||||
CREATE TABLE `#@__plus` ( | CREATE TABLE `#@__plus` ( | ||||
`aid` mediumint(8) unsigned NOT NULL auto_increment, | `aid` mediumint(8) unsigned NOT NULL auto_increment, | ||||
@@ -934,6 +918,18 @@ CREATE TABLE `#@__sys_module` ( | |||||
PRIMARY KEY (`id`) | PRIMARY KEY (`id`) | ||||
) TYPE=MyISAM; | ) 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`; | DROP TABLE IF EXISTS `#@__sys_set`; | ||||
CREATE TABLE `#@__sys_set` ( | CREATE TABLE `#@__sys_set` ( | ||||
`id` smallint(5) unsigned NOT NULL auto_increment, | `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`; | ALTER TABLE `#@__member` ADD COLUMN `send_max` int NULL DEFAULT 0 AFTER `loginerr`; | ||||
-- 6.2.3 | -- 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 | * @link https://www.dedebiz.com | ||||
*/ | */ | ||||
//系统默认运行模式为安全模式,模板管理、标签管理、数据库管理、模块管理等功能已暂停,如果您需要这些功能,DEDEBIZ_SAFE_MODE后面值`TRUE`改为`FALSE`恢复使用 | //系统默认运行模式为安全模式,模板管理、标签管理、数据库管理、模块管理等功能已暂停,如果您需要这些功能,DEDEBIZ_SAFE_MODE后面值`TRUE`改为`FALSE`恢复使用 | ||||
define('DEDEBIZ_SAFE_MODE', TRUE); | |||||
define('DEDEBIZ_SAFE_MODE', FALSE); | |||||
//生产环境使用`production`,如果采用`dev`模式,会有一些php的报错信息提示,用于开发调试 | //生产环境使用`production`,如果采用`dev`模式,会有一些php的报错信息提示,用于开发调试 | ||||
if (!defined('DEDE_ENVIRONMENT')) { | if (!defined('DEDE_ENVIRONMENT')) { | ||||
define('DEDE_ENVIRONMENT', 'production'); | |||||
define('DEDE_ENVIRONMENT', 'dev'); | |||||
} | } | ||||
if (!defined('DEBUG_LEVEL')) { | if (!defined('DEBUG_LEVEL')) { | ||||
if (DEDE_ENVIRONMENT == 'production') { | if (DEDE_ENVIRONMENT == 'production') { | ||||
@@ -217,6 +217,8 @@ if ($cfg_sendmail_bysmtp == 'Y' && !empty($cfg_smtp_usermail)) { | |||||
} | } | ||||
//DedeBIZ商业化组件 | //DedeBIZ商业化组件 | ||||
require_once(DEDEINC.'/libraries/dedebiz.class.php'); | require_once(DEDEINC.'/libraries/dedebiz.class.php'); | ||||
//第三方SDKs | |||||
require_once(DEDEINC.'/sdks/include.php'); | |||||
//对全局分页传递参数进行过滤 | //对全局分页传递参数进行过滤 | ||||
if (isset($GLOBALS['PageNo'])) { | if (isset($GLOBALS['PageNo'])) { | ||||
$GLOBALS['PageNo'] = intval($GLOBALS['PageNo']); | $GLOBALS['PageNo'] = intval($GLOBALS['PageNo']); | ||||
@@ -226,7 +228,11 @@ if (isset($GLOBALS['TotalResult'])) { | |||||
} | } | ||||
if (!isset($cfg_NotPrintHead)) { | if (!isset($cfg_NotPrintHead)) { | ||||
if (PHP_SAPI != 'cli') { | 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()); | |||||
} |