es
parent
954f715e9e
commit
bd168b14c9
@ -0,0 +1,244 @@ |
||||
<?php |
||||
declare (strict_types=1); |
||||
|
||||
namespace app\admin\controller; |
||||
|
||||
use app\common\library\wxserver\Wholesaler; |
||||
use app\job\controller\Wxholesaler as WxserverJob; |
||||
use PHPQRCode\QRcode; |
||||
use think\db\exception\DbException; |
||||
use think\facade\Db; |
||||
use think\response\Json; |
||||
|
||||
class Wxwholesaler extends Controller |
||||
{ |
||||
/** |
||||
* @notes:生成授权二维码 |
||||
* @return Json |
||||
* @author: wanghousheng |
||||
*/ |
||||
public function qrcode(): Json |
||||
{ |
||||
$obj = new Wholesaler(); |
||||
$url = $this->request->domain(true) . '/api/wxserver/redirect'; |
||||
$jumUrl = $obj->jumpH5Url($url); |
||||
$savePath = root_path() . "public/wxserve"; |
||||
!is_dir($savePath) && mkdir($savePath, 0755, true); |
||||
$savePath .= '/auth_qrcode.png'; |
||||
QRcode::png($jumUrl, $savePath, 'L', 8, 1); |
||||
return $this->renderSuccess(['img_url' => $this->request->domain(true) . '/wxserve/auth_qrcode.png?time=' . time()]); |
||||
} |
||||
|
||||
/** |
||||
* @notes:授权列表 |
||||
* @return Json |
||||
* @throws DbException |
||||
* @author: wanghousheng |
||||
*/ |
||||
public function authList(): Json |
||||
{ |
||||
$store_ids = []; |
||||
$where = []; |
||||
$store_id = intval($this->request->get('store_id')); |
||||
if ($store_id) { |
||||
$where[] = ['store_id', '=', $store_id]; |
||||
} |
||||
$nick_name = $this->request->get('nick_name'); |
||||
if ($nick_name) { |
||||
$where[] = ['nick_name', 'like', "%$nick_name%"]; |
||||
} |
||||
$appid = $this->request->get('appid'); |
||||
if ($appid) { |
||||
$where[] = ['nick_name', '=', "%$appid%"]; |
||||
} |
||||
$result = Db::table('yoshop_wxwholesaler_account') |
||||
->where($where) |
||||
->paginate(15); |
||||
$list = $result->items(); |
||||
$total = $result->total(); |
||||
if ($total) { |
||||
foreach ($list as &$item) { |
||||
$store_ids[] = $item['store_id']; |
||||
$item['create_time'] = date('Y-m-d H:i:s', $item['create_time']); |
||||
if ($item['exp_info']) { |
||||
$item['exp_info'] = json_decode($item['exp_info'], true); |
||||
if (!empty($item['exp_info']['exp_time'])) { |
||||
$item['exp_info']['exp_time'] = date('Y-m-d H:i:s', $item['exp_info']['exp_time']); |
||||
} |
||||
} else { |
||||
$item['exp_info']['exp_time'] = '无'; |
||||
$item['exp_info']['exp_version'] = '无'; |
||||
} |
||||
if ($item['release_info']) { |
||||
$item['release_info'] = json_decode($item['release_info'], true); |
||||
if (!empty($item['release_info']['release_time'])) { |
||||
$item['release_info']['release_time'] = date('Y-m-d H:i:s', $item['release_info']['release_time']); |
||||
} |
||||
} else { |
||||
$item['release_info']['release_time'] = '无'; |
||||
$item['release_info']['release_version'] = '无'; |
||||
} |
||||
if (!empty($item['experience_code'])) { |
||||
$item['experience_code'] = $this->request->domain(true) . $item['experience_code'] . '?time=' . time(); |
||||
} |
||||
if ($item['audit_status'] == 0) { |
||||
$item['audit_status_text'] = '--'; |
||||
} elseif ($item['audit_status'] == 1) { |
||||
$item['audit_status_text'] = '审核中'; |
||||
} elseif ($item['audit_status'] == 2) { |
||||
$item['audit_status_text'] = '审核通过'; |
||||
} elseif ($item['audit_status'] == 3) { |
||||
$item['audit_status_text'] = '审核失败'; |
||||
} elseif ($item['audit_status'] == 4) { |
||||
$item['audit_status_text'] = '延时审核'; |
||||
} |
||||
unset($item['access_token']); |
||||
unset($item['refresh_token']); |
||||
unset($item['signature']); |
||||
} |
||||
$store_list = Db::table('yoshop_store') |
||||
->whereIn('store_id', $store_ids) |
||||
->column('store_name', 'store_id'); |
||||
foreach ($list as &$item) { |
||||
$item['store_name'] = $store_list[$item['store_id']] ?? ''; |
||||
} |
||||
} |
||||
return $this->renderSuccess(['list' => $list, 'total' => $total]); |
||||
} |
||||
|
||||
/** |
||||
* @notes:草稿箱列表 |
||||
* @return Json |
||||
* @author: wanghousheng |
||||
*/ |
||||
public function templatedraftlist(): Json |
||||
{ |
||||
$type = intval($this->request->get('type', 0)); |
||||
$obj = new Wholesaler(); |
||||
$list = $obj->getTemplateDraftList($type); |
||||
return $this->renderSuccess($list); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* @notes:添加草稿到模板中 |
||||
* @return Json |
||||
* @author: wanghousheng |
||||
*/ |
||||
public function addTotemplate(): Json |
||||
{ |
||||
$draft_id = $this->request->get('draft_id'); |
||||
if ($draft_id) { |
||||
$obj = new Wholesaler(); |
||||
$res = $obj->addTotemplate($draft_id); |
||||
if ($res) { |
||||
return $this->renderSuccess('success'); |
||||
} |
||||
} |
||||
return $this->renderError('操作失败'); |
||||
} |
||||
|
||||
/** |
||||
* @notes:获取模板列表 |
||||
* @return Json |
||||
* @author: wanghousheng |
||||
*/ |
||||
public function templatelist(): Json |
||||
{ |
||||
$type = intval($this->request->get('type', 0)); |
||||
$obj = new Wholesaler(); |
||||
$list = $obj->getTemplatelist($type); |
||||
return $this->renderSuccess($list); |
||||
} |
||||
|
||||
/** |
||||
* @notes:删除模板 |
||||
* @return Json |
||||
* @author: wanghousheng |
||||
*/ |
||||
public function delTemplatelist(): Json |
||||
{ |
||||
$template_id = $this->request->get('template_id'); |
||||
if ($template_id) { |
||||
$obj = new Wholesaler(); |
||||
$res = $obj->deleTetemplate($template_id); |
||||
if ($res) { |
||||
return $this->renderSuccess('success'); |
||||
} |
||||
} |
||||
return $this->renderError('操作失败'); |
||||
} |
||||
|
||||
/** |
||||
* @notes:提交体验版 |
||||
* @return Json |
||||
* @author: wanghousheng |
||||
*/ |
||||
public function commit(): Json |
||||
{ |
||||
$appid = $this->request->get('appid'); |
||||
$template_id = $this->request->get('template_id'); |
||||
$appids = explode(',', $appid); |
||||
if ($appids && $template_id) { |
||||
foreach ($appids as $item) { |
||||
WxserverJob::dispatch(['appid' => $item, 'template_id' => $template_id]); |
||||
} |
||||
return $this->renderSuccess('success'); |
||||
} |
||||
return $this->renderError('操作失败'); |
||||
} |
||||
|
||||
/** |
||||
* @notes:获取版本信息 |
||||
* @return Json |
||||
* @author: wanghousheng |
||||
*/ |
||||
public function getVersion(): Json |
||||
{ |
||||
$appid = $this->request->get('appid'); |
||||
if ($appid) { |
||||
$obj = new Wholesaler(); |
||||
if ($obj->getVersioninfo($appid)) { |
||||
return $this->renderSuccess('success'); |
||||
} |
||||
} |
||||
return $this->renderError('操作失败'); |
||||
} |
||||
|
||||
/** |
||||
* @notes:提交正式版审核 |
||||
* @return Json |
||||
* @author: wanghousheng |
||||
*/ |
||||
public function audit(): Json |
||||
{ |
||||
$appid = $this->request->get('appid'); |
||||
$appids = explode(',', $appid); |
||||
if ($appids) { |
||||
foreach ($appids as $item) { |
||||
WxserverJob::dispatch(['appid' => $item]); |
||||
} |
||||
return $this->renderSuccess('success'); |
||||
} |
||||
return $this->renderError('操作失败'); |
||||
} |
||||
|
||||
/** |
||||
* @notes:发布正式版前检查 |
||||
* @return Json |
||||
* @author: wanghousheng |
||||
*/ |
||||
public function auditBeforeCheck(): Json |
||||
{ |
||||
$msg = '操作失败'; |
||||
$appid = $this->request->get('appid'); |
||||
if ($appid) { |
||||
$obj = new Wholesaler(); |
||||
$msg = $obj->privacyInfo($appid); |
||||
if ($msg == 'ok') { |
||||
return $this->renderSuccess('success'); |
||||
} |
||||
} |
||||
return $this->renderError($msg); |
||||
} |
||||
} |
@ -0,0 +1,100 @@ |
||||
<?php |
||||
declare (strict_types=1); |
||||
|
||||
namespace app\api\controller; |
||||
|
||||
use app\common\model\WxwholesalerAccount; |
||||
use think\db\exception\DataNotFoundException; |
||||
use think\db\exception\DbException; |
||||
use think\db\exception\ModelNotFoundException; |
||||
|
||||
class Wxwholesaler |
||||
{ |
||||
|
||||
public function verifyTicket() |
||||
{ |
||||
$xmlData = file_get_contents("php://input"); |
||||
$obj = new \app\common\library\wxserver\Wholesaler(); |
||||
$obj->getVerifyTicket($xmlData); |
||||
echo 'success'; |
||||
} |
||||
|
||||
/** |
||||
* @notes:授权回调 |
||||
* @throws DataNotFoundException |
||||
* @throws DbException |
||||
* @throws ModelNotFoundException |
||||
* @author: wanghousheng |
||||
*/ |
||||
public function redirect() |
||||
{ |
||||
$authorization_code = $this->request->get('auth_code'); |
||||
if ($authorization_code) { |
||||
$obj = new \app\common\library\wxserver\Wholesaler(); |
||||
$obj->authorizationInfo($authorization_code, $this->request->domain(true)); |
||||
} |
||||
echo 'success'; |
||||
} |
||||
|
||||
public function callback($appid) |
||||
{ |
||||
$obj = new \app\common\library\wxserver\Wholesaler(); |
||||
$signature = $this->request->get('signature'); |
||||
$timestamp = $this->request->get('timestamp'); |
||||
$nonce = $this->request->get('nonce'); |
||||
if ($signature && $timestamp && $nonce) { |
||||
if ($obj->checkSignature($signature, $timestamp, $nonce)) { |
||||
$xmlData = file_get_contents("php://input"); |
||||
if ($xmlData) { |
||||
$data = $obj->decryptXml($xmlData); |
||||
if (!empty($data['MsgType'])) { |
||||
if ($data['MsgType'] == 'event' && !empty($data['Event'])) { |
||||
$up = []; |
||||
if ($data['Event'] == 'weapp_audit_success') { |
||||
$up['audit_status'] = 2; |
||||
$obj->release($appid);//审核通过发布版本 |
||||
} elseif ($data['Event'] == 'weapp_audit_fail') { |
||||
$up['audit_status'] = 3; |
||||
} elseif ($data['Event'] == 'weapp_audit_delay') { |
||||
$up['audit_status'] = 4; |
||||
} |
||||
if (!empty($data['Reason'])) { |
||||
$up['audit_reason'] = $data['Reason']; |
||||
} |
||||
if ($up && $appid) { |
||||
$model = new WxwholesalerAccount(); |
||||
$model->update($up, ['appid' => $appid]); |
||||
} |
||||
echo 'success'; |
||||
} elseif ($data['MsgType'] == 'text' && !empty($data['Content'])) { |
||||
if ($data['Content'] == 'TESTCOMPONENT_MSG_TYPE_TEXT') { |
||||
$data['Content'] = 'TESTCOMPONENT_MSG_TYPE_TEXT_callback'; |
||||
} elseif (strpos($data['Content'], 'QUERY_AUTH_CODE:') !== false) { |
||||
$query_auth_code = trim(str_replace("QUERY_AUTH_CODE:", "", $data['Content'])); |
||||
$obj->apiText($query_auth_code, $data['FromUserName']); |
||||
} |
||||
echo $this->responseText($data); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
private function responseText($data): string |
||||
{ |
||||
$template = "<xml> |
||||
<ToUserName><![CDATA[%s]]></ToUserName> |
||||
<FromUserName><![CDATA[%s]]></FromUserName> |
||||
<CreateTime>%s</CreateTime> |
||||
<MsgType><![CDATA[%s]]></MsgType> |
||||
<Content><![CDATA[%s]]></Content> |
||||
</xml>"; |
||||
$fromUser = $data['ToUserName']; |
||||
$toUser = $data['FromUserName']; |
||||
$content = !empty($data['Content']) ? $data['Content'] : 'success'; |
||||
$time = time(); |
||||
$msgType = 'text'; |
||||
return sprintf($template, $toUser, $fromUser, $time, $msgType, $content); |
||||
} |
||||
} |
@ -1,8 +1,835 @@ |
||||
<?php |
||||
declare (strict_types=1); |
||||
|
||||
namespace app\common\library\wxserver; |
||||
|
||||
use app\common\model\WxwholesalerAccount; |
||||
use cores\exception\BaseException; |
||||
use Qiniu\Http\Client; |
||||
use think\db\exception\DataNotFoundException; |
||||
use think\db\exception\DbException; |
||||
use think\db\exception\ModelNotFoundException; |
||||
use think\facade\Cache; |
||||
use think\facade\Db; |
||||
|
||||
class Wholesaler |
||||
{ |
||||
|
||||
const APPID = 'wxc03d95d3597e348a'; |
||||
const SECRET = 'e2720e31673906be6e92afd377b927ba'; |
||||
const TOKEN = 'obUzmSA4MvMjOblZ5NCpgecTZYaGtAg6';//消息校验Token |
||||
const KEY = '2tujZuThOCzcuoBcBmeqMPjL6phcsv2dY7pgwYJwdtX'; //消息加解密Key |
||||
protected WxBizMsgCrypt $crypt; |
||||
|
||||
public function __construct() |
||||
{ |
||||
$this->crypt = new WxBizMsgCrypt(self::TOKEN, self::KEY, self::APPID); |
||||
} |
||||
|
||||
public function checkSignature($signature, $timestamp, $nonce): bool |
||||
{ |
||||
$token = self::TOKEN; |
||||
$tmpArr = array($token, $timestamp, $nonce); |
||||
sort($tmpArr, SORT_STRING); |
||||
$tmpStr = implode($tmpArr); |
||||
$tmpStr = sha1($tmpStr); |
||||
|
||||
if ($tmpStr == $signature) { |
||||
return true; |
||||
} else { |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* @notes:保存Ticket |
||||
* @param string $xml |
||||
* @return mixed|string |
||||
* @author: wanghousheng |
||||
*/ |
||||
public function getVerifyTicket(string $xml) |
||||
{ |
||||
$ticket = ''; |
||||
$xmlData = $this->crypt->fromXml($xml); |
||||
if (!empty($xmlData['Encrypt'])) { |
||||
//解密 |
||||
$encryptXml = $this->crypt->decryptMsg($xmlData['Encrypt']); |
||||
$data = $this->crypt->fromXml($encryptXml); |
||||
if (!empty($data['ComponentVerifyTicket'])) { |
||||
$ticket = $data['ComponentVerifyTicket']; |
||||
} |
||||
} |
||||
return $ticket; |
||||
} |
||||
|
||||
public function decryptXml($xml) |
||||
{ |
||||
$data = []; |
||||
$xmlData = $this->crypt->fromXml($xml); |
||||
if (!empty($xmlData['Encrypt'])) { |
||||
$encryptXml = $this->crypt->decryptMsg($xmlData['Encrypt']); |
||||
$data = $this->crypt->fromXml($encryptXml); |
||||
} |
||||
return $data; |
||||
} |
||||
|
||||
public function getStableAccessToken() |
||||
{ |
||||
$url = 'https://api.weixin.qq.com/cgi-bin/stable_token'; |
||||
$data['grant_type'] = 'client_credential'; |
||||
$data['appid'] = self::APPID; |
||||
$data['secret'] = self::SECRET; |
||||
$result = $this->curlPost($url, json_encode($data), 10); |
||||
$result = json_decode($result, true); |
||||
if (!empty($result['access_token'])) { |
||||
return $result['access_token']; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* @notes:获取令牌 |
||||
* @return mixed|string |
||||
* @author: wanghousheng |
||||
*/ |
||||
public function getComponentAccessToken() |
||||
{ |
||||
if (Cache::has('wholesaler_component_access_token')) { |
||||
return Cache::get('wholesaler_component_access_token'); |
||||
} |
||||
$url = 'https://api.weixin.qq.com/cgi-bin/component/api_component_token'; |
||||
$ticket = Cache::get('component_verify_ticket'); |
||||
if (!empty($ticket)) { |
||||
$data = []; |
||||
$data['component_appid'] = self::APPID; |
||||
$data['component_appsecret'] = self::SECRET; |
||||
$data['component_verify_ticket'] = $ticket; |
||||
$result = $this->curlPost($url, json_encode($data), 10); |
||||
$result = json_decode($result, true); |
||||
if (!empty($result['component_access_token'])) { |
||||
Cache::set('wholesaler_component_access_token', $result['component_access_token'], 6200); |
||||
return $result['component_access_token']; |
||||
} |
||||
} |
||||
return ''; |
||||
} |
||||
|
||||
/** |
||||
* @notes:生成H5授权链接 |
||||
* @param string $redirect_uri //授权后重定向的回调链接地址 |
||||
* @param string $biz_appid //业务公众号appid |
||||
* @return string |
||||
* @author: wanghousheng |
||||
*/ |
||||
public function jumpH5Url(string $redirect_uri, string $biz_appid = ''): string |
||||
{ |
||||
$url = ''; |
||||
$auth_code = $this->getPreAuthCode(); |
||||
if ($auth_code) { |
||||
$url = "https://open.weixin.qq.com/wxaopen/safe/bindcomponent?action=bindcomponent&no_scan=1"; |
||||
$url .= "&component_appid=" . self::APPID . "&pre_auth_code=" . $auth_code . "&redirect_uri=" . $redirect_uri; |
||||
$url .= '&auth_type=3&biz_appid=' . $biz_appid . "#wechat_redirect"; |
||||
} |
||||
return $url; |
||||
} |
||||
|
||||
/** |
||||
* @notes:获取预授权码 |
||||
* @return false|mixed |
||||
* @author: wanghousheng |
||||
*/ |
||||
public function getPreAuthCode() |
||||
{ |
||||
$token = $this->getComponentAccessToken(); |
||||
if ($token) { |
||||
$url = 'https://api.weixin.qq.com/cgi-bin/component/api_create_preauthcode?component_access_token=' . $token; |
||||
$data['component_appid'] = self::APPID; |
||||
$result = $this->curlPost($url, json_encode($data)); |
||||
$result = json_decode($result, true); |
||||
if ($result && !empty($result['pre_auth_code'])) { |
||||
return $result['pre_auth_code']; |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
private function getRefreshToken($appid) |
||||
{ |
||||
$model = new WxwholesalerAccount(); |
||||
return $model->where(['appid' => $appid])->value('refresh_token'); |
||||
} |
||||
|
||||
private function storeId($appid) |
||||
{ |
||||
$model = new WxwholesalerAccount(); |
||||
return $model->where(['appid' => $appid])->value('store_id'); |
||||
} |
||||
|
||||
/** |
||||
* @notes:获取体验码 |
||||
* @param $appid |
||||
* @return string |
||||
* @author: wanghousheng |
||||
*/ |
||||
public function getQrcode($appid): string |
||||
{ |
||||
$savePath = root_path() . "public/wxserve/experience"; |
||||
!is_dir($savePath) && mkdir($savePath, 0755, true); |
||||
$savePath .= '/' . $appid . '.jpg'; |
||||
if (file_exists($savePath)) { |
||||
return '/wxserve/experience/' . $appid . '.jpg'; |
||||
} |
||||
$access_token = $this->authorizerAccessToken($appid); |
||||
if ($access_token) { |
||||
$url = 'https://api.weixin.qq.com/wxa/get_qrcode?access_token=' . $access_token; |
||||
$client = new Client(); |
||||
$response = $client->get($url); |
||||
$res = $response->body(); |
||||
if ($res) { |
||||
$newFile = fopen($savePath, "a"); |
||||
fwrite($newFile, $res); |
||||
fclose($newFile); |
||||
return '/wxserve/experience/' . $appid . '.jpg'; |
||||
} |
||||
} |
||||
return ''; |
||||
} |
||||
|
||||
/** |
||||
* @notes:发布体验版 |
||||
* @param $appid |
||||
* @param $template_id |
||||
* @return bool |
||||
* @throws BaseException |
||||
* @author: wanghousheng |
||||
*/ |
||||
public function commit($appid, $template_id): bool |
||||
{ |
||||
$version = ''; |
||||
$access_token = $this->authorizerAccessToken($appid); |
||||
//获取模板 |
||||
$templatelist = $this->getTemplatelist(); |
||||
if ($templatelist) { |
||||
foreach ($templatelist as $value) { |
||||
if (!empty($value['user_version']) && $value['template_id'] == $template_id) { |
||||
$version = $value['user_version']; |
||||
break; |
||||
} |
||||
} |
||||
} |
||||
if ($version == '') { |
||||
throwError('模板不存在'); |
||||
} |
||||
$data['template_id'] = $template_id; |
||||
$data['user_version'] = $version; |
||||
$data['user_desc'] = 'updated'; |
||||
$ext_json['extAppid'] = $appid; |
||||
$ext_json['ext']['store_id'] = $this->storeId($appid); |
||||
$ext_json['window'] = []; |
||||
$data['ext_json'] = json_encode($ext_json); |
||||
$url = 'https://api.weixin.qq.com/wxa/commit?access_token=' . $access_token; |
||||
$result = $this->curlPost($url, json_encode($data)); |
||||
$result = json_decode($result, true); |
||||
if ($result && !empty($result['errmsg']) && $result['errmsg'] == 'ok') { |
||||
//体验码 |
||||
$qr_code = $this->getQrcode($appid); |
||||
if ($qr_code) { |
||||
$model = new WxwholesalerAccount(); |
||||
$model->update(['experience_code' => $qr_code], ['appid' => $appid]); |
||||
} |
||||
return true; |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* @notes:发布已经审核通过的小程序 |
||||
* @param $appid |
||||
* @return bool |
||||
* @author: wanghousheng |
||||
*/ |
||||
public function release($appid): bool |
||||
{ |
||||
$access_token = $this->authorizerAccessToken($appid); |
||||
if ($access_token) { |
||||
$url = 'https://api.weixin.qq.com/wxa/release?access_token=' . $access_token; |
||||
$result = $this->curlPost($url, '{}'); |
||||
$result = json_decode($result, true); |
||||
if ($result && !empty($result['errmsg']) && $result['errmsg'] == 'ok') { |
||||
return true; |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* @notes:获取版本信息 |
||||
* @param $appid |
||||
* @return bool |
||||
* @author: wanghousheng |
||||
*/ |
||||
public function getVersioninfo($appid): bool |
||||
{ |
||||
$access_token = $this->authorizerAccessToken($appid); |
||||
$url = 'https://api.weixin.qq.com/wxa/getversioninfo?access_token=' . $access_token; |
||||
$result = $this->curlPost($url, '{}'); |
||||
$result = json_decode($result, true); |
||||
if ($result && !empty($result['errmsg']) && $result['errmsg'] == 'ok') { |
||||
$up = []; |
||||
if (!empty($result['exp_info'])) { |
||||
$up['exp_info'] = json_encode($result['exp_info']); |
||||
} |
||||
if (!empty($result['release_info'])) { |
||||
$up['release_info'] = json_encode($result['release_info']); |
||||
} |
||||
if ($up) { |
||||
$model = new WxwholesalerAccount(); |
||||
$model->update($up, ['appid' => $appid]); |
||||
} |
||||
return true; |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* @notes:获取隐私接口检测结果 |
||||
* @param $appid |
||||
* @return mixed|string |
||||
* @author: wanghousheng |
||||
*/ |
||||
public function privacyInfo($appid) |
||||
{ |
||||
$errmsg = ''; |
||||
$access_token = $this->authorizerAccessToken($appid); |
||||
$url = 'https://api.weixin.qq.com/wxa/security/get_code_privacy_info?access_token=' . $access_token; |
||||
$result = $this->curlGet($url); |
||||
$result = json_decode($result, true); |
||||
if ($result && !empty($result['errmsg'])) { |
||||
$errmsg = $result['errmsg']; |
||||
} |
||||
return $errmsg; |
||||
} |
||||
|
||||
/** |
||||
* @notes:获取/刷新接口调用令牌 |
||||
* @param $appid |
||||
* @return false|mixed |
||||
* @author: wanghousheng |
||||
*/ |
||||
public function authorizerAccessToken($appid) |
||||
{ |
||||
if (Cache::has($appid . '_wholesaler_authorizer_access_token')) { |
||||
return Cache::get($appid . '_wholesaler_authorizer_access_token'); |
||||
} |
||||
$refresh_token = $this->getRefreshToken($appid); |
||||
if ($refresh_token) { |
||||
$token = $this->getComponentAccessToken(); |
||||
if ($token) { |
||||
$url = 'https://api.weixin.qq.com/cgi-bin/component/api_authorizer_token?component_access_token=' . $token; |
||||
$data['component_appid'] = self::APPID; |
||||
$data['authorizer_appid'] = $appid; |
||||
$data['authorizer_refresh_token'] = $refresh_token; |
||||
$result = $this->curlPost($url, json_encode($data)); |
||||
$result = json_decode($result, true); |
||||
if ($result && !empty($result['authorizer_access_token'])) { |
||||
Cache::set($appid . '_wholesaler_authorizer_access_token', $result['authorizer_access_token'], 6200); |
||||
return $result['authorizer_access_token']; |
||||
} |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
private function getAuditStatusText($status): string |
||||
{ |
||||
$status = intval($status); |
||||
switch ($status) { |
||||
case 0: |
||||
$text = '未提交审核'; |
||||
break; |
||||
case 1: |
||||
$text = '审核中'; |
||||
break; |
||||
case 2: |
||||
$text = '审核驳回'; |
||||
break; |
||||
case 3: |
||||
$text = '审核通过'; |
||||
break; |
||||
case 4: |
||||
$text = '提审中'; |
||||
break; |
||||
case 5: |
||||
$text = '提审失败'; |
||||
break; |
||||
default: |
||||
$text = '未知'; |
||||
break; |
||||
} |
||||
return $text; |
||||
} |
||||
|
||||
/** |
||||
* @notes:获取草稿箱列表 |
||||
* @return array|mixed |
||||
* @author: wanghousheng |
||||
*/ |
||||
public function getTemplatedraftlist($type) |
||||
{ |
||||
if (!$type && Cache::has('wx_wholesaler_drafttemplatelist')) { |
||||
return Cache::get('wx_wholesaler_drafttemplatelist'); |
||||
} |
||||
$token = $this->getComponentAccessToken(); |
||||
$list = []; |
||||
if ($token) { |
||||
$url = 'https://api.weixin.qq.com/wxa/gettemplatedraftlist?access_token=' . $token; |
||||
$result = $this->curlGet($url); |
||||
$result = json_decode($result, true); |
||||
if ($result && !empty($result['draft_list'])) { |
||||
$draft_list = $result['draft_list']; |
||||
foreach ($draft_list as $value) { |
||||
$list[] = [ |
||||
'create_time' => date('Y-m-d H:i:s', $value['create_time']), |
||||
'user_version' => $value['user_version'], |
||||
'user_desc' => $value['user_desc'], |
||||
'id' => $value['draft_id'], |
||||
]; |
||||
} |
||||
Cache::set('wx_wholesaler_drafttemplatelist', $list, 7200); |
||||
} |
||||
} |
||||
return $list; |
||||
} |
||||
|
||||
/** |
||||
* @notes:添加草稿箱到模板中 |
||||
* @param $draft_id |
||||
* @return bool |
||||
* @author: wanghousheng |
||||
*/ |
||||
public function addTotemplate($draft_id): bool |
||||
{ |
||||
$token = $this->getComponentAccessToken(); |
||||
if ($token) { |
||||
$url = 'https://api.weixin.qq.com/wxa/addtotemplate?access_token=' . $token; |
||||
$data['draft_id'] = $draft_id; |
||||
$data['template_type'] = 1; |
||||
$res = $this->curlPost($url, json_encode($data)); |
||||
$res = json_decode($res, true); |
||||
if ($res && !empty($res['errmsg']) && $res['errmsg'] == 'ok') { |
||||
Cache::delete('wx_wholesaler_templatelist'); |
||||
return true; |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* @notes:删除模板 |
||||
* @param $template_id |
||||
* @return bool |
||||
* @author: wanghousheng |
||||
*/ |
||||
public function deleTetemplate($template_id): bool |
||||
{ |
||||
$token = $this->getComponentAccessToken(); |
||||
if ($token) { |
||||
$url = 'https://api.weixin.qq.com/wxa/deletetemplate?access_token=' . $token; |
||||
$data['template_id'] = $template_id; |
||||
$res = $this->curlPost($url, json_encode($data)); |
||||
$res = json_decode($res, true); |
||||
if ($res && !empty($res['errmsg']) && $res['errmsg'] == 'ok') { |
||||
Cache::delete('wx_wholesaler_templatelist'); |
||||
return true; |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* @notes:代码模板列表 |
||||
* @param int $type |
||||
* @return array |
||||
* @author: wanghousheng |
||||
*/ |
||||
public function getTemplatelist(int $type = 0): array |
||||
{ |
||||
if (!$type && Cache::has('wx_wholesaler_templatelist')) { |
||||
return Cache::get('wx_wholesaler_templatelist'); |
||||
} |
||||
$token = $this->getComponentAccessToken(); |
||||
$list = []; |
||||
if ($token) { |
||||
$url = 'https://api.weixin.qq.com/wxa/gettemplatelist?access_token=' . $token . '&template_type=1'; |
||||
$result = $this->curlGet($url); |
||||
$result = json_decode($result, true); |
||||
if ($result && !empty($result['template_list'])) { |
||||
$template_list = $result['template_list']; |
||||
foreach ($template_list as $value) { |
||||
$list[] = [ |
||||
'create_time' => date('Y-m-d H:i:s', $value['create_time']), |
||||
'user_version' => $value['user_version'], |
||||
'user_desc' => $value['user_desc'], |
||||
'template_id' => $value['template_id'], |
||||
'audit_status' => $value['audit_status'], |
||||
'audit_status_text' => $this->getAuditStatusText($value['audit_status']), |
||||
'reason' => !empty($value['reason']) ? $value['reason'] : '', |
||||
'draft_id' => $value['draft_id'], |
||||
]; |
||||
} |
||||
Cache::set('wx_wholesaler_templatelist', $list, 7200); |
||||
} |
||||
} |
||||
return $list; |
||||
} |
||||
|
||||
/** |
||||
* @notes:设置域名 |
||||
* @param $appid |
||||
* @param $domain |
||||
* @return bool |
||||
* @author: wanghousheng |
||||
*/ |
||||
public function setDomain($appid, $domain) |
||||
{ |
||||
$token = $this->authorizerAccessToken($appid); |
||||
if ($token) { |
||||
$url = "https://api.weixin.qq.com/wxa/modify_domain_directly?access_token=$token"; |
||||
$data['action'] = 'set'; |
||||
$data['requestdomain'] = $domain; |
||||
$data['uploaddomain'] = $domain; |
||||
$data['downloaddomain'] = $domain; |
||||
$result = $this->curlPost($url, json_encode($data)); |
||||
$result = json_decode($result, true); |
||||
if ($result && !empty($result['errmsg']) && $result['errmsg'] == 'ok') { |
||||
return true; |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* @notes:设置隐私 |
||||
* @param $appid |
||||
* @return bool |
||||
* @author: wanghousheng |
||||
*/ |
||||
public function getPrivacySetting($appid): bool |
||||
{ |
||||
$token = $this->authorizerAccessToken($appid); |
||||
if ($token) { |
||||
$url = "https://api.weixin.qq.com/cgi-bin/component/setprivacysetting?access_token=$token"; |
||||
$setting_list = [ |
||||
['privacy_key' => 'PhoneNumber', 'privacy_text' => '用于用户一键登录'], |
||||
['privacy_key' => 'Location', 'privacy_text' => '用于用户选择自提点'], |
||||
['privacy_key' => 'AlbumWriteOnly', 'privacy_text' => '用于用户保存海报'], |
||||
['privacy_key' => 'Address', 'privacy_text' => '用于用户快速获取微信地址'], |
||||
['privacy_key' => 'Invoice', 'privacy_text' => '用于用户申请开票'], |
||||
['privacy_key' => 'Album', 'privacy_text' => '用于用户上传图片'], |
||||
['privacy_key' => 'Clipboard', 'privacy_text' => '用于用户复制粘贴'], |
||||
]; |
||||
$data['setting_list'] = $setting_list; |
||||
$data['owner_setting']['contact_qq'] = '527264601'; |
||||
$data['owner_setting']['notice_method'] = '公告'; |
||||
$result = $this->curlPost($url, json_encode($data)); |
||||
$result = json_decode($result, true); |
||||
if ($result && !empty($result['errmsg']) && $result['errmsg'] == 'ok') { |
||||
return true; |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
public function apiText($authorization_code, $touser) |
||||
{ |
||||
$url = 'https://api.weixin.qq.com/cgi-bin/component/api_query_auth?component_access_token=' . $this->getComponentAccessToken(); |
||||
$data['component_appid'] = self::APPID; |
||||
$data['authorization_code'] = $authorization_code; |
||||
$result = $this->curlPost($url, json_encode($data)); |
||||
$result = json_decode($result, true); |
||||
if (!empty($result['authorization_info']['authorizer_access_token'])) { |
||||
$token = $result['authorization_info']['authorizer_access_token']; |
||||
$url = 'https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=' . $token; |
||||
$data = [ |
||||
'touser' => $touser, |
||||
'msgtype' => 'text', |
||||
'text' => ['content' => $authorization_code . '_from_api'], |
||||
]; |
||||
$this->curlPost($url, json_encode($data)); |
||||
} |
||||
|
||||
} |
||||
|
||||
/** |
||||
* @notes:获取授权信息 |
||||
* @param $authorization_code |
||||
* @param string $domain |
||||
* @throws DataNotFoundException |
||||
* @throws DbException |
||||
* @throws ModelNotFoundException |
||||
* @author: wanghousheng |
||||
*/ |
||||
public function authorizationInfo($authorization_code, string $domain = '') |
||||
{ |
||||
$url = 'https://api.weixin.qq.com/cgi-bin/component/api_query_auth?component_access_token=' . $this->getComponentAccessToken(); |
||||
$data = []; |
||||
$data['component_appid'] = self::APPID; |
||||
$data['authorization_code'] = $authorization_code; |
||||
$result = $this->curlPost($url, json_encode($data)); |
||||
$result = json_decode($result, true); |
||||
if ($result && !empty($result['authorization_info']) && !empty($result['authorization_info']['authorizer_appid'])) { |
||||
$url = 'https://api.weixin.qq.com/cgi-bin/component/api_get_authorizer_info?component_access_token=' . $this->getComponentAccessToken(); |
||||
$data = []; |
||||
$data['component_appid'] = self::APPID; |
||||
$data['authorizer_appid'] = $result['authorization_info']['authorizer_appid']; |
||||
$res = $this->curlPost($url, json_encode($data)); |
||||
$res = json_decode($res, true); |
||||
if ($res && !empty($res['authorizer_info']) && !empty($res['authorization_info'])) { |
||||
$authorizer_info = $res['authorizer_info']; |
||||
$authorization_info = $res['authorization_info']; |
||||
$model = new WxwholesalerAccount(); |
||||
$appid = $authorization_info['authorizer_appid']; |
||||
$insert_data['access_token'] = $result['authorization_info']['authorizer_access_token']; |
||||
$insert_data['refresh_token'] = $authorization_info['authorizer_refresh_token']; |
||||
$insert_data['nick_name'] = $authorizer_info['nick_name']; |
||||
$insert_data['head_image'] = $authorizer_info['head_img']; |
||||
$insert_data['user_name'] = $authorizer_info['user_name']; |
||||
$insert_data['qrcode_image'] = $authorizer_info['qrcode_url']; |
||||
$insert_data['principal_name'] = $authorizer_info['principal_name']; |
||||
$insert_data['signature'] = $authorizer_info['signature']; |
||||
$insert_data['store_id'] = $this->getStoreId($authorization_info['authorizer_appid']); |
||||
$insert_data['update_time'] = time(); |
||||
$exit_id = $model->where(['appid' => $appid])->value('id'); |
||||
if ($exit_id) { |
||||
$model->update($insert_data, ['id' => $exit_id]); |
||||
} else { |
||||
$insert_data['appid'] = $appid; |
||||
$insert_data['create_time'] = time(); |
||||
$model->insertGetId($insert_data); |
||||
} |
||||
$this->setOther($appid, $domain); |
||||
} |
||||
} |
||||
} |
||||
|
||||
private function setOther($appid, $domain) |
||||
{ |
||||
$up = []; |
||||
//设置域名信息 |
||||
if ($this->setDomain($appid, $domain)) { |
||||
$up['domain_status'] = 1; |
||||
} |
||||
//设置隐私 |
||||
if ($this->getPrivacySetting($appid)) { |
||||
$up['privacy_status'] = 1; |
||||
} |
||||
//设置业务域名 |
||||
if ($this->modifyJumpDomain($appid)) { |
||||
$up['jump_domain_status'] = 1; |
||||
} |
||||
if ($up) { |
||||
$model = new WxwholesalerAccount(); |
||||
$model->update($up, ['appid' => $appid]); |
||||
} |
||||
} |
||||
|
||||
private function modifyJumpDomain($appid, $domain): bool |
||||
{ |
||||
$token = $this->authorizerAccessToken($appid); |
||||
if ($token) { |
||||
$url = "https://api.weixin.qq.com/wxa/setwebviewdomain?access_token=$token"; |
||||
$data['action'] = 'set'; |
||||
$data['webviewdomain'] = $domain; |
||||
$result = $this->curlPost($url, json_encode($data)); |
||||
$result = json_decode($result, true); |
||||
if ($result && !empty($result['errmsg']) && $result['errmsg'] == 'ok') { |
||||
return true; |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* @notes:获取店铺ID |
||||
* @param $appid |
||||
* @return int|mixed |
||||
* @throws DataNotFoundException |
||||
* @throws DbException |
||||
* @throws ModelNotFoundException |
||||
* @author: wanghousheng |
||||
*/ |
||||
public function getStoreId($appid) |
||||
{ |
||||
$list = Db::table('yoshop_wxapp_setting')->where(['key' => 'basic'])->select(); |
||||
if (!$list->isEmpty()) { |
||||
$list = $list->toArray(); |
||||
foreach ($list as $value) { |
||||
if ($value['values']) { |
||||
$item = json_decode($value['values'], true); |
||||
if (!empty($item['app_id']) && $item['app_id'] == $appid) { |
||||
$store_id = Db::table('yoshop_store')->where(['store_id' => $value['store_id'], 'is_recycle' => 0])->value('store_id'); |
||||
if ($store_id) { |
||||
return $store_id; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
public function submitAudit($appid): bool |
||||
{ |
||||
$access_token = $this->authorizerAccessToken($appid); |
||||
if ($access_token) { |
||||
$url = 'https://api.weixin.qq.com/wxa/submit_audit?access_token=' . $access_token; |
||||
$data['item_list'] = $this->getAllCategory($appid); |
||||
if (!empty($data['item_list'])) { |
||||
$data = '{}'; |
||||
} else { |
||||
$data = json_encode($data); |
||||
} |
||||
$result = $this->curlPost($url, $data); |
||||
$result = json_decode($result, true); |
||||
if (!empty($result) && intval($result['errcode']) == 0 && !empty($result['auditid'])) { |
||||
$model = new WxwholesalerAccount(); |
||||
$up['audit_status'] = 1; |
||||
$up['audit_reason'] = ''; |
||||
$up['audit_time'] = date('Y-m-d H:i:s'); |
||||
$up['auditid'] = $result['auditid']; |
||||
$model->update($up, ['appid' => $appid]); |
||||
return true; |
||||
} |
||||
|
||||
} |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* @notes:检测审核状态 |
||||
* @param $appid |
||||
* @param $auditid |
||||
* @return array|mixed |
||||
* @author: wanghousheng |
||||
*/ |
||||
public function getAuditStatus($appid, $auditid) |
||||
{ |
||||
$access_token = $this->authorizerAccessToken($appid); |
||||
if ($access_token && $auditid) { |
||||
$url = 'https://api.weixin.qq.com/wxa/get_auditstatus?access_token=' . $access_token; |
||||
$data['auditid'] = $auditid; |
||||
$result = $this->curlPost($url, json_encode($data)); |
||||
$result = json_decode($result, true); |
||||
if (!empty($result) && intval($result['errcode']) == 0 && isset($result['status'])) { |
||||
$status = intval($result['status']); |
||||
$up = []; |
||||
if ($status == 0) { |
||||
$up['audit_status'] = 2; |
||||
} elseif ($status == 1) { |
||||
$up['audit_status'] = 3; |
||||
} elseif ($status == 2) { |
||||
$up['audit_status'] = 1; |
||||
} elseif ($status == 4) { |
||||
$up['audit_status'] = 4; |
||||
} |
||||
if (!empty($result['reason'])) { |
||||
$up['audit_reason'] = $result['reason']; |
||||
} |
||||
if ($up) { |
||||
$model = new WxwholesalerAccount(); |
||||
$model->update($up, ['appid' => $appid]); |
||||
} |
||||
return $result; |
||||
} |
||||
} |
||||
return []; |
||||
} |
||||
|
||||
public function getAllCategory($appid): array |
||||
{ |
||||
$data = []; |
||||
$access_token = $this->authorizerAccessToken($appid); |
||||
if ($access_token) { |
||||
$url = 'https://api.weixin.qq.com/wxa/get_category?access_token=' . $access_token; |
||||
$result = $this->curlGet($url); |
||||
$result = json_decode($result, true); |
||||
if ($result && !empty($result['category_list'])) { |
||||
$category_list = $result['category_list']; |
||||
foreach ($category_list as $value) { |
||||
$arr = []; |
||||
if (!empty($value['first_class'])) { |
||||
$arr['first_class'] = $value['first_class']; |
||||
} |
||||
if (!empty($value['second_class'])) { |
||||
$arr['second_class'] = $value['second_class']; |
||||
} |
||||
if (!empty($value['third_class'])) { |
||||
$arr['third_class'] = $value['third_class']; |
||||
} |
||||
if (!empty($value['first_id'])) { |
||||
$arr['first_id'] = $value['first_id']; |
||||
} |
||||
if (!empty($value['second_id'])) { |
||||
$arr['second_id'] = $value['second_id']; |
||||
} |
||||
if (!empty($value['third_id'])) { |
||||
$arr['third_id'] = $value['third_id']; |
||||
} |
||||
if ($arr) { |
||||
$data[] = $arr; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
return $data; |
||||
} |
||||
|
||||
private function curlPost($url, $post_data, $timeout = 5) |
||||
{ |
||||
$ch = curl_init(); |
||||
if (stripos($url, 'https://') !== false) { |
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); |
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); |
||||
curl_setopt($ch, CURLOPT_SSLVERSION, 1); |
||||
} |
||||
if (is_string($post_data)) { |
||||
$strPOST = $post_data; |
||||
} else { |
||||
$aPOST = array(); |
||||
foreach ($post_data as $key => $val) { |
||||
$aPOST[] = $key . '=' . urlencode($val); |
||||
} |
||||
$strPOST = join('&', $aPOST); |
||||
} |
||||
curl_setopt($ch, CURLOPT_HTTP_VERSION, 1); |
||||
curl_setopt($ch, CURLOPT_URL, $url); |
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); |
||||
curl_setopt($ch, CURLOPT_POST, true); |
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $strPOST); |
||||
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout); |
||||
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); |
||||
$result = curl_exec($ch); |
||||
$aStatus = curl_getinfo($ch); |
||||
curl_close($ch); |
||||
if (intval($aStatus['http_code']) == 200) { |
||||
return $result; |
||||
} else { |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
protected function curlGet(string $url, array $data = []) |
||||
{ |
||||
if (!empty($data)) { |
||||
$url = $url . '?' . http_build_query($data); |
||||
} |
||||
$ch = curl_init(); |
||||
curl_setopt($ch, CURLOPT_URL, $url); |
||||
curl_setopt($ch, CURLOPT_HEADER, 0); |
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); |
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); |
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); |
||||
$result = curl_exec($ch); |
||||
curl_close($ch); |
||||
return $result; |
||||
} |
||||
} |
@ -0,0 +1,58 @@ |
||||
<?php |
||||
|
||||
namespace app\job\controller; |
||||
|
||||
use app\common\library\wxserver\Wholesaler as Server; |
||||
use cores\BaseJob; |
||||
use cores\exception\BaseException; |
||||
use cores\traits\QueueTrait; |
||||
|
||||
class Wxholesaler extends BaseJob |
||||
{ |
||||
use QueueTrait; |
||||
|
||||
/** |
||||
* 消费队列任务:输出测试信息 |
||||
* @param array $data 参数 |
||||
* @return bool 返回结果 |
||||
* @throws BaseException |
||||
*/ |
||||
public function handle(array $data): bool |
||||
{ |
||||
if (!empty($data['appid'])) { |
||||
if (!empty($data['template_id'])) { |
||||
$this->sendTestVersion($data['appid'], $data['template_id']); |
||||
} else { |
||||
$this->sendOfficialVersion($data['appid']); |
||||
} |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* @notes:发布正式版 |
||||
* @param $appid |
||||
* @author: wanghousheng |
||||
*/ |
||||
private function sendOfficialVersion($appid) |
||||
{ |
||||
$obj = new Server(); |
||||
$res = $obj->privacyInfo($appid); |
||||
if ($res == 'ok') { |
||||
$obj->submitAudit($appid); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* @notes:发布体验版 |
||||
* @param $appid |
||||
* @param $template_id |
||||
* @throws BaseException |
||||
* @author: wanghousheng |
||||
*/ |
||||
private function sendTestVersion($appid, $template_id) |
||||
{ |
||||
$obj = new Server(); |
||||
$res = $obj->commit($appid, $template_id); |
||||
} |
||||
} |
Loading…
Reference in new issue