• 0
  • 0

微信小程序操作类

2019-07-23 843 0 admin 所属分类:PHP 记录

WXLittle.class.php 代码如下

/**
 *   微信小程序操作表
 *   wxtoken 表结构
 *   id
 *   access_token
 *   addtime
 *   wxticket 表结构
 *   id
 *   ticket
 *   addtime
 */
class WXLittle {
	private $appid;
	private $appserect;
	private $mch_id;
	private $mchkey; //微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置
	private $curl;
	private $msg;
	protected $errs = array(
		'-1' => '系统繁忙,此时请开发者稍候再试',
		'0' => '请求成功',
		'40001' => 'AppSecret错误或者AppSecret不属于这个公众号,请开发者确认AppSecret的正确性',
		'40002' => '请确保grant_type字段值为client_credential',
		'40164' => '调用接口的IP地址不在白名单中,请在接口IP白名单中进行设置。',
	);
	function __construct($appid, $appserect) {
		$this->appid = $appid;
		$this->appserect = $appserect;
		$this->curl = new Curl();
	}

	public function setMchInfo($appid, $key) {
		$this->mch_id = $appid;
		$this->mchkey = $key;
	}

	/*
		获取小程序token
	*/
	public function getAccessToken() {
		$addtime = TIMESTAMP - 7200;
		$url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$this->appid}&secret={$this->appserect}";
		$row = C::t(PT_WXTOKEN)->getNew($addtime, 2);
		if ($row) {
			/*
				access_token	string	获取到的凭证
				expires_in	number	凭证有效时间,单位:秒
				errcode	number	错误码
				errmsg	string	错误信息
			 */
			return $row['access_token'];
		} else {
			$result = $this->curl->doGet($url);
			if (!$result) {
				$this->msg = "无法获取令牌内容";
				return false;
			}
			$result = json_decode($result, true);
			if (!$result) {
				$this->msg = "解析令牌内容失败";
				return false;
			}
			if ($result['access_token']) {
				C::t(PT_WXTOKEN)->addToken($result['access_token'], 2);
				return $result['access_token'];
			} else {
				$this->msg = "获取令牌失败" . $result['errmsg'];
				return false;
			}
		}
	}

	// 创建小程序二维码  https://developers.weixin.qq.com/miniprogram/dev/api/open-api/qr-code/getWXACodeUnlimit.html
	public function createWXAQRCode($access_token, $scene, $path, $width, $auto_color = false, $line_color = null, $is_hyaline = false) {
		$url = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token={$access_token}";
		$data = array(
			'scene' => $scene,
			'path' => $path,
			'width' => $width,
			'auto_color' => $auto_color,
			'line_color' => $line_color,
			'is_hyaline' => $is_hyaline,
		);
		$data = json_encode($data);
		$content = curlPost($url, $data);
		if (!$content) {
			$this->msg = "无法获取小程序二维码";
			return false;
		}
		$result = json_decode($content, true);
		if (!$result) {
			//获取图片上传路径
			$dir = getUploadDir('table');
			//图片二进制数据 直接保存
			$name = md5(uniqid()) . '.jpg';
			$file = $dir . $name;
			$tarDir = dirname($file);
			if (!is_dir($tarDir)) {
				dmkdir($tarDir);
			}
			file_put_contents($file, $content);
			return $file;
		} else {

			$this->msg = $result['errmsg'];
			return false;
		}
	}

	// 小程序code码换openid等 openid session_key unionid
	public function code2session($code) {
		$url = "https://api.weixin.qq.com/sns/jscode2session?appid={$this->appid}&secret={$this->appserect}&js_code={$code}&grant_type=authorization_code";
		$result = $this->curl->doGet($url);
		if (!$result) {
			$this->msg = "无法获取会话信息";
			return false;
		}
		$json = json_decode($result, true);
		if ($json['errcode']) {
			$this->msg = $json['errMsg'];
			return false;
		}
		return $json;
	}

	//获取预付款订单号
	public function getPreorder(&$params) {
		$url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
		$str = '<xml>
		   <appid>%s</appid>
		   <mch_id>%s</mch_id>
		   <device_info>%s</device_info>
		   <nonce_str>%s</nonce_str>
		   <sign>%s</sign>
		   <sign_type>%s</sign_type>
		   <body>%s</body>
		   <detail>%s</detail>
		   <attach>%s</attach>
		   <out_trade_no>%s</out_trade_no>
		   <fee_type>%s</fee_type>
		   <total_fee>%s</total_fee>
		   <spbill_create_ip>%s</spbill_create_ip>
		   <time_start>%s</time_start>
		   <time_expire>%s</time_expire>
		   <goods_tag>%s</goods_tag>
		   <notify_url>%s</notify_url>
		   <trade_type>%s</trade_type>
		   <product_id>%s</product_id>
		   <limit_pay>%s</limit_pay>
		   <openid>%s</openid>
		</xml>';
		$params['appid'] = $this->appid;
		$params['mch_id'] = $this->mch_id;
		ksort($params);
		$string = $this->ToUrlParams($params);
		$string .= "&key={$this->mchkey}";
		if (strtoupper($params['sign_type']) == 'MD5') {
			$sign = md5($string);
		} else {
			$sign = hash_hmac($string);
		}

		$params['sign'] = $sign;
		$data = sprintf(
			$str,
			$params['appid'],
			$params['mch_id'],
			$params['device_info'],
			$params['nonce_str'],
			$params['sign'],
			$params['sign_type'],
			$params['body'],
			$params['detail'],
			$params['attach'],
			$params['out_trade_no'],
			$params['fee_type'],
			$params['total_fee'],
			$params['spbill_create_ip'],
			$params['time_start'],
			$params['time_expire'],
			$params['goods_tag'],
			$params['notify_url'],
			$params['trade_type'],
			$params['product_id'],
			$params['limit_pay'],
			$params['openid']
		);
		$result = curlPost($url, $data);
		$return = toXmlTree($result);
		if (!$return) {
			$this->msg = '无法获取预付订单号';
			return false;
		}
		$vals = $return['vals'];
		$index = $return['index'];
		$prepay_id = getXmlValue($vals, 'prepay_id');
		if (!$prepay_id) {
			$this->msg = getXmlValue($vals, 'return_msg');
			return false;
		}
		return $prepay_id;
	}

	// 二次签名 数据返回给小程序
	public function resignAgain($package, $timeStamp, $nonceStr, $signType = 'MD5') {
		$params = array('package' => $package, 'timeStamp' => $timeStamp, 'nonceStr' => $nonceStr, 'appId' => $this->appid, 'signType' => $signType);
		ksort($params);
		$string = $this->ToUrlParams($params);
		$string .= "&key={$this->mchkey}";
		if (strtoupper($params['signType']) == 'MD5') {
			$sign = md5($string);
		} else {
			$sign = hash_hmac($string);
		}
		return $sign;
	}

	// 微信支付退款
	public function returnmoney(&$params) {
		$url = 'https://api.mch.weixin.qq.com/secapi/pay/refund';
		$str = '<xml>
		   <appid>%s</appid>
		   <mch_id>%s</mch_id>
		   <nonce_str>%s</nonce_str>
		   <sign>%s</sign>
		   <sign_type>%s</sign_type>
		   <transaction_id>%s</transaction_id>
		   <out_trade_no>%s</out_trade_no>
		   <out_refund_no>%s</out_refund_no>
		   <total_fee>%s</total_fee>
		   <refund_fee>%s</refund_fee>
		   <refund_fee_type>%s</refund_fee_type>
		   <refund_desc>%s</refund_desc>
		   <refund_account>%s</refund_account>
		   <notify_url>%s</notify_url>
		</xml>';
		$params['appid'] = $this->appid;
		$params['mch_id'] = $this->mch_id;
		ksort($params);
		$string = $this->ToUrlParams($params);
		$string .= "&key={$this->mchkey}";
		if (strtoupper($params['sign_type']) == 'MD5') {
			$sign = md5($string);
		} else {
			$sign = hash_hmac($string);
		}

		$params['sign'] = $sign;
		$data = sprintf(
			$str,
			$params['appid'],
			$params['mch_id'],
			$params['nonce_str'],
			$params['sign'],
			$params['sign_type'],
			$params['transaction_id'],
			$params['out_trade_no'],
			$params['out_refund_no'],
			$params['total_fee'],
			$params['refund_fee'],
			$params['refund_fee_type'],
			$params['refund_desc'],
			$params['refund_account'],
			$params['notify_url']
		);

		$flag = $this->curl_post_ssl($url, $data, $msg);
		if (!$flag) {
			$this->msg = $msg;
			return false;
		}

		$return = toXmlTree($msg);
		if (!$return) {
			$this->msg = '无法获取退款信息';
			return false;
		}

		$vals = $return['vals'];
		$index = $return['index'];

		$return_code = getXmlValue($vals, 'return_code');
		if ($return_code != "SUCCESS") {
			$this->msg = getXmlValue($vals, 'return_msg');
			return false;
		}

		$result_code = getXmlValue($vals, 'result_code');
		if ($result_code != "SUCCESS") {
			$this->msg = getXmlValue($vals, 'err_code_des');
			return false;
		}
		return true;
	}

	protected function curl_post_ssl($url, $vars,&$msg = '', $second = 30,  $fileDir = "C:/cert/", $aHeader = array()) {
		$ch = curl_init();
		//超时时间
		curl_setopt($ch, CURLOPT_TIMEOUT, $second);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
		//这里设置代理,如果有的话
		//curl_setopt($ch,CURLOPT_PROXY, '10.206.30.98');
		//curl_setopt($ch,CURLOPT_PROXYPORT, 8080);
		curl_setopt($ch, CURLOPT_URL, $url);
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
		curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

		//以下两种方式需选择一种

		//第一种方法,cert 与 key 分别属于两个.pem文件
		//默认格式为PEM,可以注释
		curl_setopt($ch, CURLOPT_SSLCERTTYPE, 'PEM');
		curl_setopt($ch, CURLOPT_SSLCERT, $fileDir . '/1269973401_20181119_cert.pem');
		//默认格式为PEM,可以注释
		curl_setopt($ch, CURLOPT_SSLKEYTYPE, 'PEM');
		curl_setopt($ch, CURLOPT_SSLKEY, $fileDir . '/1269973401_20181119_key.pem');

		//第二种方式,两个文件合成一个.pem文件
		// curl_setopt($ch, CURLOPT_SSLCERT, getcwd() . '/all.pem');

		if (count($aHeader) >= 1) {
			curl_setopt($ch, CURLOPT_HTTPHEADER, $aHeader);
		}

		curl_setopt($ch, CURLOPT_POST, 1);
		curl_setopt($ch, CURLOPT_POSTFIELDS, $vars);
		$data = curl_exec($ch);
		if ($data) {
			curl_close($ch);
			$msg = $data;
			return true;
		} else {
			$error = curl_errno($ch);
			$msg = "call faild, errorCode:$error\n";
			curl_close($ch);
			return false;
		}
	}

	// 获取消息内容
	public function getMsg() {
		return $this->msg;
	}

	/**
	 * 格式化参数格式化成url参数
	 */
	public function ToUrlParams($data) {
		$buff = "";
		foreach ($data as $k => $v) {
			if ($k != "sign" && $v != "" && !is_array($v)) {
				$buff .= $k . "=" . $v . "&";
			}
		}

		$buff = trim($buff, "&");
		return $buff;
	}

}

相关函数

// CURL发送
function curlPost($url, $jsonData) {
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_HEADER, 0);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
    curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonData);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
    $result = curl_exec($ch);
    curl_close($ch);
    return $result;
}

function curlGet($url) {
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_HEADER, 1);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
    $result = curl_exec($ch);
    curl_close($ch);
    return $result;
}

function getUploadDir($type) {
    global $identifier;
    if ($type) {
        return "./data/attachment/{$identifier}/image/{$type}/";
    } else {
        return "./data/attachment/{$identifier}/image/upload/";
    }
}
// xml格式转换成json格式
function xmlTojson($xmlstr) {
    $xml = simplexml_load_string($xmlstr);
    $json = json_decode(json_encode($xml), true);
    return $json;
}
//解析成xml树
function toXmlTree($xml) {
    $p = xml_parser_create();
    xml_parse_into_struct($p, $xml, $vals, $index);
    xml_parser_free($p);
    return array('vals' = > $vals, 'index' = > $index);
}
//与 toXmlTree 配合解析 节点元素
function getXmlValue($vals, $key) {
    $value = null;
    $key = strtoupper($key);
    foreach($vals as $k = > $v) {
        if ($v['tag'] == $key) {
            $value = $v['value'];
        }
    }
    return $value;
}

function guid() {
    if (function_exists('com_create_guid')) {
        return com_create_guid();
    } else {
        mt_srand((double) microtime() * 10000); //optional for php 4.2.0 and up.
        $charid = strtoupper(md5(uniqid(rand(), true)));
        $hyphen = chr(45);
        $uuid = chr(123).substr($charid, 0, 8).$hyphen.substr($charid, 8, 4).$hyphen.substr($charid, 12, 4).$hyphen.substr($charid, 16, 4).$hyphen.substr($charid, 20, 12).chr(125);
        return $uuid;
    }
}


返回顶部