| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330 |
- <?php
- namespace app\models\intracityService;
- use app\models\Option;
- use app\models\StoreMini;
- use app\utils\Wechat\WechatMini;
- use EasyWeChat\Factory;
- use EasyWeChat\Kernel\BaseClient;
- use app\utils\phpseclib\phpseclib\Crypt\RSA;
- use yii\base\Model;
- use app\models\WechatIntracityService;
- class IndexController extends Model
- {
- public $params;
- public $app;
- public $id;
- public $wechatService;
- public $store_id;
- public $base_uri = "https://api.weixin.qq.com/";
- private $param = [
- 'app_id' => '',
- 'url' => '',
- 'local_sym_key' => '',//API对称密钥
- 'local_sym_sn' => '',//API对称密钥编号
- 'local_sn' => '',//平台证书编号
- 'local_key' => '',
- 'local_certificate' => '',//平台证书
- 'store_id' => '',
- 'out_store_id' => '',
- ];
- private $key =[
- 'rsa_sn'=>'',
- 'rsa_private_key'=>''
- ];
- public function rules()
- {
- return [
- [['store_id'], 'integer']
- ];
- }
- public function getWechatApp($store_id)
- {
- $this->store_id = $store_id;
- $result = $this->initData($store_id);
- $this->param['local_sym_sn'] = $result['local_sym_sn'];
- $this->param['local_sym_key'] = $result['local_sym_key'];
- $this->key['rsa_sn'] = $result['rsa_sn'];
- $this->key['rsa_private_key'] = $result['rsa_private_key'];
- if (empty($this->param['local_sym_sn']) ||
- empty($this->param['local_sym_key']) ||
- empty($this->key['rsa_sn']) ||
- empty($this->key['rsa_private_key'])
- ) {
- $this->app = null;
- } else {
- $this->app = (new WechatMini())::getWechatConfig($this->store_id);
- }
- $storeMini = StoreMini::findOne(['is_use' => 1, 'store_id' => $store_id]);
- if ($storeMini) {
- $this->param['app_id'] = Option::get("platform_third_appid", 0, 'saas')['value'];
- } else {
- if ($this->app) {
- $this->param['app_id'] = $this->app->getConfig()['app_id'];
- }
- }
- }
- public function initData($store_id) {
- $keys = [
- 'local_sym_sn',
- 'local_sym_key',
- 'rsa_sn',
- 'rsa_private_key'
- ];
- // if (is_open_platform()) {
- // $store_id = 0;
- // }
- $storeMini = StoreMini::findOne(['is_use' => 1, 'store_id' => $store_id]);
- if ($storeMini) {
- $delivery_data = Option::get($keys, 0, 'delivery');
- } else {
- $delivery_data = Option::get($keys, $store_id, 'delivery');
- }
- if ($delivery_data) {
- $arr = [];
- foreach ($delivery_data as $value) {
- $index = array_search($value['name'], $keys);
- unset($keys[$index]);
- $arr[$value['name']] = $value['value'];
- }
- foreach ($keys as $key) {
- $arr[$key] = '';
- }
- $delivery_data = $arr;
- } else {
- $delivery_data = [
- 'local_sym_sn' => '',
- 'local_sym_key' => '',
- 'rsa_sn' => '',
- 'rsa_private_key' => ''
- ];
- }
- return $delivery_data;
- }
- public function getUrlData($store_id, $url_, $data = [], $type = 0) {
- $this->getWechatApp($store_id);
- $app = $this->app;
- try {
- if (empty($app)) {
- throw new \Exception();
- }
- $access_token = $app->access_token->getToken();
- } catch (\Exception $e) {
- return [
- 'code' => 1,
- 'msg' => '未获取到配置信息'
- ];
- }
- $accessToken = $access_token['authorizer_access_token'] ?? $access_token['access_token'];
- $url_ = $this->base_uri . $url_;
- $url = $url_ . "?access_token=" . $accessToken;
- $newRe = $this->getRequestParam($data, $url_, ['app_id' => $this->param['app_id']]);
- if (!$type) {
- $signature = $this->getSignature($newRe, $url_, ['app_id' => $this->param['app_id']]);
- $headerArray =['wechatmp_appid' => $this->param['app_id'], 'wechatmp_timeStamp'=>$newRe['ts'], 'wechatmp_signature'=>$signature];
- }
- $result = $this->curlPost($url, $newRe['reqData'] ?: '', $headerArray ?: []);
- $headers = $this->httpParseHeaders($result['header']);
- $result = json_decode($result['body'], true);
- if (!$type) {
- $result = $this->decryptToString($url_, $headers['Wechatmp-TimeStamp'], $result, $this->param['app_id']);
- }
- if ($result['errcode'] === 10000) {
- return retry(3, function () use ($store_id, $url_, $data, $type) {
- return $this->getUrlData($store_id, $url_, $data, $type);
- });
- }
- return $result;
- }
- //加密
- public function getRequestParam($req = [], $url_ = '', $params_data = [])
- {
- $param = $this->param;
- $time = time();
- //16位随机字符串
- $nonce = base64_encode(random_bytes(16));
- $addReq = ["_n" => $nonce, "_appid" => $params_data['app_id'], "_timestamp" => $time];
- $realReq = array_merge($addReq, $req);
- $realReq = json_encode($realReq);
- //额外参数
- $aad = $url_ . "|" . $params_data['app_id'] . "|" . $time . "|" . $param['local_sym_sn'];
- //12位随机字符
- $iv = random_bytes(12);
- $cipher = openssl_encrypt($realReq, "aes-256-gcm", base64_decode($param['local_sym_key']), OPENSSL_RAW_DATA, $iv, $tag, $aad);
- $iv = base64_encode($iv);
- $data = base64_encode($cipher);
- $authTag = base64_encode($tag);
- $reqData = ["iv" => $iv, "data" => $data, "authtag" => $authTag];
- return ['ts' => $time, 'reqData' => json_encode($reqData)];
- }
- //加签
- public function getSignature($newRe, $url_, $params_data = [])
- {
- $keys = $this->key;
- $time = $newRe['ts'];
- $url = $url_;
- $appId = $params_data['app_id'];
- $reqData = $newRe['reqData'];
- $payload = $url . "\n" . $appId . "\n" . $time . "\n" . $reqData;
- // mb_internal_encoding($payload);
- // $payload = mb_convert_encoding($payload, 'UTF-8', "auto");
- // $key = openssl_pkey_get_private($keys['key']);
- //
- // $signature = '';
- // openssl_sign($payload, $signature, $key, OPENSSL_ALGO_SHA256);
- // openssl_free_key($key);
- $signature = RSA::loadPrivateKey($keys['rsa_private_key'])
- ->withPadding(RSA::SIGNATURE_PSS)
- ->withHash('sha256')
- ->withMGFHash('sha256')
- ->sign($payload);
- return base64_encode($signature);
- }
- //请求
- public function curlPost($url, $field, $header)
- {
- $headerArray = array('Content-Type: application/json;charset=utf-8',
- 'Accept:application/json',
- 'Content-Length:' . strlen($field),
- 'Wechatmp-Appid:' . $header['wechatmp_appid'],
- 'Wechatmp-TimeStamp:' . $header['wechatmp_timeStamp'],
- 'Wechatmp-Signature:' . $header['wechatmp_signature']
- );
- $curl = curl_init();
- curl_setopt($curl, CURLOPT_HTTPHEADER, $headerArray);
- curl_setopt($curl, CURLOPT_URL, $url);
- curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
- curl_setopt($curl, CURLOPT_POST, 1);
- curl_setopt($curl, CURLOPT_POSTFIELDS, $field);
- //输出响应头部
- curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
- curl_setopt($curl, CURLOPT_HEADER, true);
- $str = curl_exec($curl);
- $headerSize = curl_getinfo($curl, CURLINFO_HEADER_SIZE);
- $headers = substr($str, 0, $headerSize);
- $body = substr($str, $headerSize);
- curl_close($curl);
- return ['body' => $body, 'header' => $headers];
- // $header_ = array('Content-Type: application/json;charset=utf-8',
- // 'Accept:application/json',
- // 'Content-Length:' . strlen($field),
- // 'Wechatmp-Appid:' . $header['wechatmp_appid'],
- // 'Wechatmp-TimeStamp:' . $header['wechatmp_timeStamp'],
- // 'Wechatmp-Signature:' . $header['wechatmp_signature']
- //
- // );
- // $ch = curl_init();
- // curl_setopt($ch, CURLOPT_POST, 1);
- // curl_setopt($ch, CURLOPT_URL, $url);
- // curl_setopt($ch, CURLOPT_POSTFIELDS, $field);
- // curl_setopt($ch, CURLOPT_HTTPHEADER, $header_);
- // ob_start();
- // curl_exec($ch);
- // $return_content = ob_get_contents();
- // ob_end_clean();
- // return $return_content;
- }
- //解析加密信息
- public function decryptToString($url, $ts, $result_, $app_id)
- {
- try {
- $param = $this->param;
- $message = $url . '|' . $app_id . '|' . $ts . '|' . $param['local_sym_sn'];
- $iv = base64_decode($result_['iv']);
- $data = base64_decode($result_['data']);
- $authTag = base64_decode($result_['authtag']);
- $result = openssl_decrypt($data, "aes-256-gcm", base64_decode($param['local_sym_key']), OPENSSL_RAW_DATA, $iv, $authTag, $message);
- if (!$result) {
- throw new \Exception(openssl_error_string(), 10000);
- }
- return json_decode($result, true);
- } catch (\Exception $e) {
- return [
- 'errcode' => $e->getCode() ?: 1,
- 'errmsg' => $e->getMessage()
- ];
- }
- // $config = self::$config;
- }
- /**
- * Name:解析头部信息
- * User: zcw
- * Date: 2023/7/14
- * Time: 10:28
- * @param $headerString
- * @return array
- */
- private function httpParseHeaders($headerString)
- {
- $headers = [];
- $lines = explode("\r\n", $headerString);
- foreach ($lines as $line) {
- $line = trim($line);
- if (!empty($line)) {
- $parts = explode(':', $line, 2);
- $key = trim($parts[0]);
- $value = isset($parts[1]) ? trim($parts[1]) : '';
- $headers[$key] = $value;
- }
- }
- return $headers;
- }
- }
|