增加docke部署

This commit is contained in:
2026-04-10 16:44:13 +08:00
parent e2f8054794
commit cd4ddb606d
5076 changed files with 701092 additions and 0 deletions

View File

@@ -0,0 +1,27 @@
<?php
use phprs\ezsql\Sql;
class Message{
public function __construct($msg){
$this->msg = $msg;
}
public $msg;
}
/**
*
* @author caoym
* @path("/hw")
*/
class HelloWorld
{
/**
* @route({"GET","/"})
*/
public function doSomething1() {
return new Message('Hello World!');
}
/**
* @property({"default":"@db"}) 注入pdo实例
*/
//private $db;
}

View File

@@ -0,0 +1,291 @@
<?php
/**
* a sample for showing annotations
*/
use phprs\util\Verify;
use phprs\util\exceptions\Forbidden;
use phprs\util\Logger;
use phprs\util\exceptions\NotFound;
use phprs\ezsql\Sql;
use phprs\util\exceptions\BadRequest;
/**
* @author caoym
*/
class AliasConflict extends \Exception
{
}
/**
* @author caoym
*/
class AccountConflict extends \Exception
{
}
/**
*
* users manager
* @path("/users")
*/
class Users
{
/**
* create user
* @route({"POST","/"})
* @param({"account", "$._POST.mobile"}) cell-phone number, required
* @param({"password", "$._POST.password"}) password, required
* @param({"alias", "$._POST.alias"}) user's alias, required
* @param({"avatar", "$._FILES.avatar.tmp_name"}) user's avatar, optional
* @param({"token", "$._COOKIE.token"})
*
* @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie invalid
*
* @throws({"AliasConflict","res", "409 Conflict",{"error":"AliasConflict"}}) alias conflict
*
* @throws({"AccountConflict","res", "409 Conflict",{"error":"AccountConflict"}}) account conflict
*
* @return({"cookie","uid","$uid","+365 days","/"}) uid
* @return user's id
* {"uid":"1233"}
*/
public function createUser(&$uid, $token, $account, $alias, $password, $avatar = null){
$tokens = $this->factory->create('Tokens');
$token = $tokens->getToken($token);
Verify::isTrue(!$token['uid'], new BadRequest('invalid token'));
Verify::isTrue($token['account'] == $account, new Forbidden('invalid mobile '.$account));
if($avatar){
$avatar = $this->uploadAvatar($avatar);
}else{
$avatar = '';
}
$pdo = $this->db;
$pdo->beginTransaction();
try {
//is account conflict
$res = Sql::select('uid')->from('uc_members')->where(
'username = ? OR email = ? OR mobile = ?', $account,$account,$account
)->forUpdate()->get($pdo);
Verify::isTrue(count($res) ==0, new AccountConflict("account $account conflict"));
//is avatar conflict
$res = Sql::select('uid')->from('pre_common_member_profile')->where('realname = ?', $alias)->forUpdate()->get($pdo);
Verify::isTrue(count($res) ==0, new AliasConflict("alias $alias conflict"));
$uid = Sql::insertInto('uc_members')->values(['username'=>$account,
'password'=>$password,
'regdate'=>Sql::native('UNIX_TIMESTAMP(now())'),
'salt'=>''
])->exec($pdo)->lastInsertId();
Sql::insertInto('pre_common_member_profile')->values([
'realname'=>$alias,
'uid'=>$uid,
'avatar'=>$avatar
])->exec($pdo);
$pdo->commit();
} catch (Exception $e) {
Logger::warning("createUser($account) failed with ".$e->getMessage());
$pdo->rollBack();
throw $e;
}
$token['uid'] = $uid;
$tokens->updateToken($token, $token);
return ['uid'=>$uid];
}
/**
* modify user's information
* @route({"POST","/current"})
*
* @param({"password", "$._POST.password"}) modify password, optional
* @param({"alias", "$._POST.alias"}) modify alias, optional
* @param({"avatar", "$._FILES.avatar.tmp_name"}) modify avatar, optional
* @param({"token", "$._COOKIE.token"}) used for auth
*
* @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden", {"error":"Forbidden"}}) invalid cookie
*
* @throws({"AliasConflict","status", "409 Conflict", {"error":"AliasConflict"}}) alias conflict
*
*/
public function updateUser($token, $alias=null, $password=null, $avatar=null ){
$token = $this->factory->create('Tokens')->getToken($token);
Verify::isTrue(isset($token['uid']) && $token['uid']!=0, new Forbidden("invalid uid {$token['uid']}"));
if($avatar){
$avatar = $this->uploadAvatar($avatar);
}
$uid = $token['uid'];
$pdo = $this->db;
$pdo->beginTransaction();
try {
if($alias || $avatar){
$sets = array();
$params = array();
if($alias){
$res = Sql::select('uid')->from('pre_common_member_profile')->where('realname = ? AND uid <> ?', $alias, $uid)->forUpdate()->get($pdo);
Verify::isTrue(count($res) ==0, new AliasConflict("alias $alias conflict"));
$params['realname'] = $alias;
}
if($avatar){
$params['avatar'] = $avatar;
}
Sql::update('pre_common_member_profile')->setArgs($params)->where('uid = ?',$uid)->exec($pdo);
}
if($password !== null){
Sql::update('uc_members')->setArgs([
'password'=>$password,
'salt'=>''
])->where('uid=?',$uid)->exec($pdo);
}
$pdo->commit();
} catch (Exception $e) {
Logger::warning("updateUser($uid) failed with ".$e->getMessage());
$pdo->rollBack();
throw $e;
}
}
/**
* get users info
* @route({"GET","/"})
* @param({"uids","$._GET.uids"}) users id
* @return("body")
* response like this:
* [
* {
* "uid":"id",
* "avatar":"http://xxxxx/avatar.jpg",
* "alias":"caoym",
* }
* ...
* ]
*/
public function getUserByIds($uids, $asDict=false) {
if(count($uids) == 0){
return [];
}
$res = Sql::select('uc_members.uid',
'pre_common_member_profile.realname as alias',
'pre_common_member_profile.avatar',
'pre_common_member_profile.level',
'pre_common_member_profile.ext')
->from('uc_members')
->leftJoin('pre_common_member_profile')
->on('uc_members.uid=pre_common_member_profile.uid')
->where('uc_members.uid IN (?)', $uids)
->get($this->db ,$asDict?'uid':null);
return $res;
}
/**
* get current user info
* @route({"GET","/current"})
*
* @param({"token", "$._COOKIE.token"})
* @return("body")
* response like this:
* {
* "uid":"id",
* "avatar":"http://xxxxx/avatar.jpg",
* "alias":"caoym"
* }
* ...
*/
public function getCurrentUser($token){
$tokens = $this->factory->create('Tokens');
$token = $tokens->getToken($token);
$uid = $token['uid'];
Verify::isTrue($token['uid'] , new Forbidden('invalid uid '.$uid));
$res = $this->getUserByIds([$uid]);
Verify::isTrue(count($res) !=0, new NotFound("user $uid not found"));
return $res[0];
}
public function getUserByAccount($account){
return $this->getUser(['uc_members.username'=>$account]);
}
public function getUserByAlias($alias){
return $this->getUser(['pre_common_member_profile.realname'=>$alias]);
}
private function getUser($cond){
$res = Sql::select('uc_members.uid',
'pre_common_member_profile.realname as alias',
'pre_common_member_profile.avatar',
'pre_common_member_profile.level',
'pre_common_member_profile.ext')
->from('uc_members')
->leftJoin('pre_common_member_profile')
->on('uc_members.uid=pre_common_member_profile.uid')
->whereArgs($cond)
->get($this->db);
if(count($res)){
$ext = json_decode($res[0]['ext'],true);
unset($res[0]['ext']);
if(isset($ext['education'])) $res[0]['education'] = $ext['education'];
if(isset($ext['company'])) $res[0]['company'] = $ext['company'];
if(isset($ext['fields'])) $res[0]['fields'] = $ext['fields'];
}
return count($res)>0 ? $res[0]:false;
}
public function verifyPassword($account, $password){
$res = Sql::select('uid, password, salt')->from('uc_members')
->where('username = ? or email = ?', $account, $account)
->get($this->db);
if(count($res) == 0){
return false;
}
if($res[0]['password'] == $password ){
return $res[0]['uid'];
}
return false;
}
public function deleteUserByAccount($account){
$this->db->beginTransaction();
try {
$res = Sql::select('uid')->from('uc_members')->where('username=?',$account)->forUpdate()->get($this->db);
if (count($res) == 0){
$this->db->rollBack();
return false;
}
$uid = $res[0]['uid'];
Sql::deleteFrom('pre_common_member_profile')->where('uid=?',$uid)->exec($this->db);
Sql::deleteFrom('uc_members')->where('uid=?',$uid)->exec($this->db);
$this->db->commit();
} catch (Exception $e) {
$this->db->rollBack();
throw $e;
}
return true;
}
private function uploadAvatar($file){
$name = md5_file($file);
return $this->oss->upload("avatars", $name, $file);
}
/** @inject("ioc_factory") */
private $factory;
/**
* @property({"default":"@db"})
* @var PDO
*/
public $db;
// 此处删除了代码
}

View File

@@ -0,0 +1,319 @@
<?php
require_once dirname(dirname(dirname(__DIR__))) . '/env_config.php';
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, PATCH, DELETE");
header("Access-Control-Allow-Headers: Content-Type, Authorization, Content-Length, X-Requested-With");
header("Access-Control-Allow-Credentials: true");
header("Content-Type: text/html; charset=utf-8");
/**
* 门店相关活动
*/
use phprs\util\Verify;
use phprs\util\exceptions\Forbidden;
use phprs\util\Logger;
use phprs\util\exceptions\NotFound;
use phprs\ezsql\Sql;
use phprs\util\exceptions\BadRequest;
require_once 'apiBase.php';
/**
*
* 门店相关活动
* @path("/activity")
*/
class Activity extends apiBase {
/**
* 获取单个活动详细信息(错误代码16000-16050)
* @route({"POST","/"})
* @param({"devkey","$._POST.devkey"}) 开发者key
* @param({"market_key","$._POST.market_key"}) market_key
* @param({"activity_key","$._POST.activity_key"}) activity_key
* @param({"sign","$._POST.sign"}) sign
* @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用
* @return("body")
*/
public function getActivity($devkey='',$market_key='',$activity_key='',$sign='') {
$result = array();
$verify_result = $this->verifyMarketApi($devkey);
if( is_error_api($verify_result) ){
return $verify_result;
}
if( empty($market_key) ) {
$result["error"] = '1';
$result["error_code"] = 11001;
$result["msg"] = "未传入market_key参数";
return $result;
}
$marketList = Sql::select('a.*')
->from('syweb_market a')
->where('a.market_key=?',$market_key)
->get($this->db ,null);
if( empty($marketList) || count($marketList)<=0 ) {
$result["error"] = '1';
$result["error_code"] = 11002;
$result["msg"] = "market_key无效";
return $result;
}
$marketList = $marketList[0];
if( empty($activity_key) ) {
$result["error"] = '1';
$result["error_code"] = 16001;
$result["msg"] = "未传入activity_key参数";
return $result;
}
$activityList = Sql::select('a.*')
->from('syweb_business_activity a')
->where('a.activity_key=?',$activity_key)
->get($this->db ,null);
if( empty($activityList) || count($activityList)<=0 ) {
$result["error"] = '1';
$result["error_code"] = 16002;
$result["msg"] = "指定的门店活动不存在或已经被删除!";
return $result;
}
$activityList = $activityList[0];
if( !empty($activityList) ) {
if( !empty($activityList["logo"]) ) {
$activityList["logo"] = env('SITE_OPEN_URL', 'http://open.daoqijuyou77.cn').$activityList["logo"];
}
if( !empty($activityList["url"]) ) {
$activityList["url"] = str_replace("%market_key",$market_key,$activityList["url"]);
$activityList["url"] = str_replace("%activity_key",$activity_key,$activityList["url"]);
}
$activityList["titleimg_list"] = iunserializer($activityList["titleimg_list"]);
$titleImgList = array();
if( !empty($activityList["titleimg_list"]) && count($activityList["titleimg_list"])>0 ) {
foreach ($activityList["titleimg_list"] as $key => $value) {
if( !empty($value) ) {
$titleImgList[] = env('SITE_OPEN_URL', 'http://open.daoqijuyou77.cn').$value;
}
}
}
$activityList["titleimg_list"] = $titleImgList;
}
$result["error"] = '0';
$result["data"] = $activityList;
$result["msg"] = "获取单个活动详细信息成功!";
return $result;
}
/**
* 获取活动分类信息(错误代码16000-16050)
* @route({"POST","/class"})
* @param({"devkey","$._POST.devkey"}) 开发者key
* @param({"market_key","$._POST.market_key"}) market_key
* @param({"parent_key","$._POST.parent_key"}) parent_key
* @param({"sign","$._POST.sign"}) sign
* @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用
* @return("body")
*/
public function getClassList($devkey='',$market_key='',$parent_key='',$sign='') {
$result = array();
$verify_result = $this->verifyMarketApi($devkey);
if( is_error_api($verify_result) ){
return $verify_result;
}
if( empty($market_key) ) {
$result["error"] = '1';
$result["error_code"] = 11001;
$result["msg"] = "未传入market_key参数";
return $result;
}
$marketList = Sql::select('a.*')
->from('syweb_market a')
->where('a.market_key=?',$market_key)
->get($this->db ,null);
if( empty($marketList) || count($marketList)<=0 ) {
$result["error"] = '1';
$result["error_code"] = 11002;
$result["msg"] = "market_key无效";
return $result;
}
$marketList = $marketList[0];
if( empty($parent_key) ) {
$parent_key = "";
}
$class_list = $this->selectClass($parent_key,$marketList["business_key"]);
$result["error"] = '0';
$result["data"] = $class_list;
$result["msg"] = "获取活动分类信息成功!";
return $result;
}
/**
* 获取活动信息列表(错误代码16051-16100)
* @route({"POST","/list"})
* @param({"devkey","$._POST.devkey"}) 开发者key
* @param({"market_key","$._POST.market_key"}) market_key
* @param({"type","$._POST.type"}) type
* @param({"class_key","$._POST.class_key"}) class_key
* @param({"keywords","$._POST.keywords"}) keywords
* @param({"pageno","$._POST.pageno"}) pageno
* @param({"pagesize","$._POST.pagesize"}) pagesize
* @param({"sign","$._POST.sign"}) sign
* @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用
* @return("body")
*/
public function getActivityList($devkey='',$market_key='',$type=0,$class_key='',$keywords='',$pageno=0,$pagesize=0,$sign='') {
$result = array();
$verify_result = $this->verifyMarketApi($devkey);
if( is_error_api($verify_result) ){
return $verify_result;
}
if( empty($market_key) ) {
$result["error"] = '1';
$result["error_code"] = 11001;
$result["msg"] = "未传入market_key参数";
return $result;
}
$marketList = Sql::select('a.*')
->from('syweb_market a')
->where('a.market_key=?',$market_key)
->get($this->db ,null);
if( empty($marketList) || count($marketList)<=0 ) {
$result["error"] = '1';
$result["error_code"] = 11002;
$result["msg"] = "market_key无效";
return $result;
}
$marketList = $marketList[0];
// 组装查询条件 begin
$conditionStr = " activity_key in (select activity_key from syweb_business_activity_market where market_key='".$marketList["market_key"]."')";
$orderStr = " id desc ";
if( !empty($type) && is_numeric($type) ){
if( $type==1 ) {
$orderStr = " access_count desc ";
} else if( $type==3 ) {
$orderStr = " id desc ";
} else if( $type==3 ) {
$conditionStr .= " and is_recommond=1 ";
} else if( $type==4 ) {
// 暂时未实现
}
}
if( !empty($class_key) ) {
$conditionStr .= " and class_key='".$class_key."'";
}
if( !empty($keywords) ) {
$conditionStr .= " and activity_name like '%".$keywords."%'";
}
// 组装查询条件 end
// 分页 begin
$pindex = max(1, intval($pageno));
if($psize){
$psize = intval($pagesize);
} else {
$psize = 20;
}
// 分页 end
$pdo = $this->db;
$pdo->beginTransaction();
$total = Sql::select(' COUNT(id) as num ')
->from('syweb_business_activity')
->where($conditionStr)
->get($this->db ,null);
$list = array();
if (!empty($total) && !empty($total[0]["num"])) {
$list = Sql::select("*")
->from('syweb_business_activity')
->where($conditionStr)
->orderBy($orderStr)
->limit(($pindex - 1) * $psize,$psize)
->get($this->db ,null);
}
$pdo->commit();
if( $list ){
foreach ($list as &$item) {
if( !empty($item["logo"]) ) {
$item["logo"] = env('SITE_OPEN_URL', 'http://open.daoqijuyou77.cn').$item["logo"];
}
$item["url"] = str_replace("%market_key",$market_key,$item["url"]);
$item["url"] = str_replace("%activity_key",$item["activity_key"],$item["url"]);
}
$page_count = 0;
if( (int)$total[0]["num"] % $psize > 0 ) {
$page_count = (int)$total[0]["num"] / $psize + 1;
} else {
$page_count = (int)$total[0]["num"];
}
$result["error"] = '0';
$result["msg"] = '数据获取成功。';
$result["data"]["content"] = $list;
$result["data"]["pager"]["total"] = (int)$total[0]["num"];// 总记录数
$result["data"]["pager"]["pindex"] = $pindex;// 当前页索引
$result["data"]["pager"]["psize"] = $psize;// 每页记录条数
$result["data"]["pager"]["page_count"] = $page_count;// 总共的页数
return $result;
} else {
$list = array();
$result["error"] = '0';
$result["msg"] = '未查询到任何数据记录。';
$result["data"]["content"] = $list;
$result["data"]["pager"]["total"] = (int)$total[0]["num"];// 总记录数
$result["data"]["pager"]["pindex"] = $pindex;// 当前页索引
$result["data"]["pager"]["psize"] = $psize;// 每页记录条数
$result["data"]["pager"]["page_count"] = 0;// 总共的页数
return $result;
}
}
/**
* 使用递归的方式查询分类
*
**/
private function selectClass($parent_key,$business_key) {
$class_list = Sql::select('a.*')
->from('syweb_activity_class a')
->where('a.parent_key=? and a.business_key=?',$parent_key,$business_key)
->get($this->db ,null);
if( !empty($class_list) && count($class_list)>0 ) {
foreach ($class_list as &$classInfo) {
$sub_class_list = $this->selectClass($classInfo["class_key"],$business_key);
if( !empty($sub_class_list) && count($sub_class_list)>0 ) {
$classInfo["has_sub"] = 1;
$classInfo["sub_class_list"] = $sub_class_list;
} else {
$classInfo["has_sub"] = 0;
}
}
}
return $class_list;
}
/** @inject("ioc_factory") */
private $factory;
/**
* @property({"default":"@db"})
* @var PDO
*/
public $db;
// 此处删除了代码
}

View File

@@ -0,0 +1,469 @@
<?php
// 加载环境变量配置
require_once dirname(dirname(dirname(__DIR__))) . '/env_config.php';
use phprs\util\Verify;
use phprs\util\exceptions\Forbidden;
use phprs\util\Logger;
use phprs\util\exceptions\NotFound;
use phprs\ezsql\Sql;
use phprs\util\exceptions\BadRequest;
/// 接口返回用的信息类
class returnObject
{
public $error; /// 返回值: 0成功; 非0失败;
public $error_code; /// 错误号
public $msg; /// 错误信息
public $data; /// 返回的数据
public function returnObject($error = 0, $error_code = 0, $msg = null, $data = null)
{
$this->error = $error;
$this->error_code = $error_code;
$this->msg = $msg;
$this->data = $data;
}
public function to_array()
{
return (array)$this;
}
public function to_string()
{
return json_encode($this, JSON_UNESCAPED_UNICODE);
}
public function from_array($array)
{
foreach ($array as $key => $value)
{
if (property_exists($this, $key))
{
$this->$key = $value;
}
}
return true;
}
public function from_string($string)
{
return $this->from_array((array)json_decode($string));
}
}
/**
* 错误码
* 获取优惠券12000--12050
* 更新用户积分13000-13050
* 友乐牛牛用户登录13100-13150
* 基类
* @path("/apiBase")
*/
class apiBase
{
public static $domain;
//public static $domain = 'api.tscce.cn';
public $appid; // 开发者应用ID
// 静态初始化 domain
public static function initDomain() {
if (empty(self::$domain)) {
self::$domain = env('SITE_SDK_DOMAIN', 'sdk.tscce.cn');
}
}
public $devkey; // 开发者Key
public $businessid; // 商家ID
public $sid; // 开发者SID
public $scode; // 开发者SCODE
public $market_key; // 门店Key
public $appInfo; // 开发者应用信息
public $devInfo; // 开发者信息
public $marketInfo; // 商家信息
public $userInfo; // 全局用户信息
public $businessInfo;
public function __construct()
{
}
protected function getLocaleUrl($always_http = false)
{
$is_https =
(isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ||
(isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') ||
(isset($_SERVER['REQUEST_SCHEME']) && $_SERVER['REQUEST_SCHEME'] == 'https');
$request_scheme = $is_https ? 'https://' : 'http://';
$hostname = $_SERVER['SERVER_NAME'];
$hostport = (($is_https && '443' == $_SERVER['SERVER_PORT']) || (!$is_https && '80' == $_SERVER['SERVER_PORT'])) ? '' : ':' . intval($_SERVER['SERVER_PORT']);
if ($always_http)
return 'http://' . $hostname . $hostport;
else
return $request_scheme . $hostname . $hostport;
}
protected function getFullUrl($relatively_url, $always_http = false)
{
if (mb_strstr($relatively_url, '/', false, USEDCHARSET) == $relatively_url)
return $this->getLocaleUrl($always_http) . $relatively_url;
else
return $this->getLocaleUrl($always_http) . '/' . $relatively_url;
}
public function init($appid = '', $devkey = '', $sid = '', $scode = '', $market_key = '')
{
$this->appid = $appid;
$this->devkey = $devkey;
$this->sid = $sid;
$this->scode = $scode;
$this->market_key = $market_key;
}
public function verifyMarketApi($devkey = '')
{
$this->devkey = $devkey;
if (empty($this->devkey))
{
return new returnObject(1, 10002, '未传入devkey参数');
}
$devList = Sql::select('syweb_admin.*')
->from('syweb_admin')
->where('syweb_admin.type=2 and syweb_admin.admin_key=? and syweb_admin.status=1', $this->devkey)
->get($this->db, null);
if (empty($devList) || count($devList) <= 0)
{
return new returnObject(1, 10003, 'devkey无效');
}
$this->devInfo = $devList[0];
return new returnObject(0);
}
/*******************************
* name: verify
* note: 验证参数是否有效
*******************************/
public function verify()
{
if (empty($this->appid))
return new returnObject(1, 10001, '未传入appid参数');
if (empty($this->devkey))
return new returnObject(1, 10002, '未传入devkey参数');
$devList = Sql::select('a.*')
->from('syweb_admin a')
->where('a.type=2 and a.admin_key=? and a.status=1', $this->devkey)
->get($this->db, null);
if (empty($devList) || count($devList) <= 0)
return new returnObject(1, 10003, 'devkey无效');
$this->devInfo = $devList[0];
/*
$appBaseList = Sql::select('a.*')
->from('syweb_app_base a')
->where('a.ref_key=? and a.dev_key=? and a.status=10', $this->appid, $this->devInfo['admin_key'])
->get($this->db, null);
if (empty($appBaseList) || count($appBaseList) <= 0)
{
return new returnObject(1, 10004, '指定的应用不存在或未被审核');
}
$appBaseKey = $appBaseList[0]["app_key"];
$appList = Sql::select('a.*')
->from('syweb_app a')
->where('a.ref_key=? and a.dev_key=? and a.status=10', $appBaseKey, $this->devInfo['admin_key'])
->get($this->db, null);
if (empty($appList) || count($appList) <= 0)
{
return new returnObject(1, 10004, '指定的应用不存在或未被审核');
}
$this->appInfo = $appList[0];
*/
$appList = Sql::select('b.*')
->from('syweb_app_base a, syweb_app b')
->where('a.app_key = b.ref_key and a.status = b.status and a.dev_key = b.dev_key and a.ref_key = ? and a.dev_key = ? and a.status = 10', $this->appid, $this->devInfo['admin_key'])
->get($this->db, null);
if (empty($appList) || count($appList) <= 0)
return new returnObject(1, 10004, '指定的应用不存在或未被审核');
$this->appInfo = $appList[0];
if (empty($this->sid))
return new returnObject(1, 10005, '请传入sid');
if (empty($this->scode))
return new returnObject(1, 10006, '请传入scode');
// 当前时间戳通过sid和scode获取用户信息必须保障sid未过期
$nowTime = time();
// 根据sid 查询用户信息
$userList = Sql::select('a.*')
->from('syweb_users a')
->where('a.sid=? and a.scode=? and a.sid_expire_time>?', $this->sid, $this->scode, $nowTime)
->get($this->db, null);
if (!empty($userList) && count($userList) > 0)
{
$this->userInfo = $userList[0];
// 延长SID过期时间 begin
$updateData = array();
$sid_expire_time = time() + (2 * 24 * 60 * 60);
$updateData['sid_expire_time'] = $sid_expire_time;
$pdo = $this->db;
$pdo->beginTransaction();
Sql::update('syweb_users')->setArgs($updateData)->where('id=?', $this->userInfo['id'])->exec($pdo);
$pdo->commit();
// 延长SID过期时间 end
// 判断SID对应的门店Key和传入的门店Key是否一致
if (!empty($market_key))
{
if ($this->userInfo['market_key'] != $market_key)
return new returnObject(1, 10011, '指定的SID和market_key不符');
}
$marketList = Sql::select('a.*')
->from('syweb_market a')
->where('a.market_key=?', $this->userInfo['market_key'])
->get($this->db, null);
if (empty($marketList) || count($marketList) <= 0)
return new returnObject(1, 10007, '指定的门店Key不存在或未被审核');
$this->market_key = $this->userInfo['market_key'];
$this->marketInfo = $marketList[0];
if (!empty($this->marketInfo) && !empty($this->marketInfo['templatemsg']))
$this->marketInfo['templatemsg'] = iunserializer($this->marketInfo['templatemsg']);
switch ($this->userInfo['auth_type'])
{
case AUTHTYPE_WECHAT:
{
$weixin_user_list = Sql::select('syweb_users_weixin.*')
->from('syweb_users_weixin')
->where('syweb_users_weixin.uid=?', $this->userInfo["id"])
->get($this->db, null);
if (!empty($weixin_user_list) && count($weixin_user_list) > 0)
{
$this->userInfo['weixin'] = $weixin_user_list[0];
return new returnObject(0);
}
else
return new returnObject(1, 10009, '未找到指定的微信用户信息');
break;
}
case AUTHTYPE_QQ:
{
$qq_user_list = Sql::select('syweb_users_qq.*')
->from('syweb_users_qq')
->where('syweb_users_qq.uid=?', $this->userInfo["id"])
->get($this->db, null);
if (!empty($qq_user_list) && count($qq_user_list) > 0)
{
$this->userInfo['qq'] = $qq_user_list[0];
return new returnObject(0);
}
else
return new returnObject(1, 10010, '未找到指定的QQ用户信息');
break;
}
case AUTHTYPE_JKX:
{
$jkx_user_list = Sql::select('a.*')
->from('syweb_users_jkx a')
->where('a.uid=?', $this->userInfo["id"])
->get($this->db, null);
if (!empty($jkx_user_list) && count($jkx_user_list) > 0)
{
$this->userInfo['jkx'] = $jkx_user_list[0];
return new returnObject(0);
}
else
return new returnObject(1, 10011, '未找到指定的聚开心用户信息');
break;
}
case AUTHTYPE_NIUNIUGAME:
{
$app_user_list = Sql::select('a.*')
->from('syweb_users_ylnn a')
->where('a.uid=?', $this->userInfo["id"])
->get($this->db, null);
if (!empty($app_user_list) && count($app_user_list) > 0)
{
$this->userInfo['app'] = $app_user_list[0];
return new returnObject(0);
}
else
return new returnObject(1, 10011, '未找到指定的应用认证用户信息');
break;
}
default:
{
return new returnObject(1, 10012, '未知的用户认证方式' . $this->userInfo['auth_type']);
break;
}
}
}
else
{
return new returnObject(1, 10008, '用户未登录或登录信息过期');
}
}
public function ToUrlParams($paramers)
{
$buff = "";
foreach ($paramers as $k => $v)
{
if ($k != "sign" && $v != "" && !is_array($v))
{
$buff .= $k . "=" . $v . "&";
}
}
$buff = trim($buff, "&");
return $buff;
}
/**
* @param string $market_key
* @return array|null
*/
public function verify_admin($market_key)
{
if (empty($this->appid))
return new returnObject(1, 10001, '未传入appid参数');
if (empty($this->devkey))
return new returnObject(1, 10002, '未传入devkey参数');
if (empty($market_key))
return new returnObject(1, 10011, '未传入market_key参数');
$devList = Sql::select('a.*')
->from('syweb_admin a')
->where('a.type=2 and a.admin_key=? and a.status=1', $this->devkey)
->get($this->db, null);
if (empty($devList) || count($devList) <= 0)
return new returnObject(1, 10003, 'devkey无效');
$this->devInfo = $devList[0];
/*
$appBaseList = Sql::select('a.*')
->from('syweb_app_base a')
->where('a.ref_key=? and a.dev_key=? and a.status=10', $this->appid, $this->devInfo['admin_key'])
->get($this->db, null);
if (empty($appBaseList) || count($appBaseList) <= 0)
{
return new returnObject(1, 10004, '指定的应用不存在或未被审核');
}
$appBaseKey = $appBaseList[0]["app_key"];
$appList = Sql::select('a.*')
->from('syweb_app a')
->where('a.ref_key=? and a.dev_key=? and a.status=10', $appBaseKey, $this->devInfo['admin_key'])
->get($this->db, null);
if (empty($appList) || count($appList) <= 0)
{
return new returnObject(1, 10004, '指定的应用不存在或未被审核');
}
$this->appInfo = $appList[0];
*/
$appList = Sql::select('b.*')
->from('syweb_app_base a, syweb_app b')
->where('a.app_key = b.ref_key and a.status = b.status and a.dev_key = b.dev_key and a.ref_key = ? and a.dev_key = ? and a.status = 10', $this->appid, $this->devInfo['admin_key'])
->get($this->db, null);
if (empty($appList) || count($appList) <= 0)
return new returnObject(1, 10004, '指定的应用不存在或未被审核');
$this->appInfo = $appList[0];
$marketList = Sql::select('a.*')
->from('syweb_market a')
->where('a.market_key=?', $market_key)
->get($this->db, null);
if (empty($marketList) || count($marketList) <= 0)
return new returnObject(1, 10007, '指定的门店Key不存在或未被审核');
$this->market_key = $market_key;
$this->marketInfo = $marketList[0];
if (!empty($this->marketInfo) && !empty($this->marketInfo['templatemsg']))
$this->marketInfo['templatemsg'] = iunserializer($this->marketInfo['templatemsg']);
return new returnObject(0);
}
/**
* @功能 带参数跳转到指定地址
* @param string $forwardUrl
* @param mixed $paramers
**/
public function forwardUrl($forwardUrl, $paramers)
{
$paramerStr = "";
if (!empty($paramers) && count($paramers) > 0)
{
foreach ($paramers as $key => $value)
{
if (empty($paramerStr))
{
$paramerStr = $key . "=" . $value;
}
else
{
$paramerStr .= "&" . $key . "=" . $value;
}
}
}
if (!empty($paramerStr))
{
if (strstr($forwardUrl, '?'))
{
if (strstr($forwardUrl, '&'))
{
$forwardUrl .= '&' . $paramerStr;
}
else
{
$forwardUrl .= $paramerStr;
}
}
else
{
$forwardUrl .= '?' . $paramerStr;
}
}
header('Location: ' . $forwardUrl);
exit();
}
/** @inject("ioc_factory") */
private $factory;
/**
* @property({"default":"@db"})
* @var PDO
*/
public $db;
}
// 类定义后立即初始化静态 domain
apiBase::initDomain();

View File

@@ -0,0 +1,90 @@
<?php
header('Access-Control-Allow-Origin:*');// 指定允许其他域名访问
header('Access-Control-Allow-Methods:POST');// 响应类型
header('Access-Control-Allow-Headers:x-requested-with,content-type');
/**
* 获取信息接口
*/
use phprs\util\Verify;
use phprs\util\exceptions\Forbidden;
use phprs\util\Logger;
use phprs\util\exceptions\NotFound;
use phprs\ezsql\Sql;
use phprs\util\exceptions\BadRequest;
/**
*
* 获取信息接口
* @path("/appport")
*/
class Appport
{
/**
* 通过scode和sid获取AccessToken
* @route({"GET","/token"})
* @param({"scode","$._GET.scode"}) 客户端生成的Scode
* @param({"sid","$._GET.sid"}) 服务器返回的sid
* @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用
*/
public function getAccessToken($scode,$sid) {
// 当前时间戳通过sid和scode获取用户信息必须保障sid未过期
$nowtime = time();
// 根据sid 查询用户信息
$res = Sql::select('syweb_users_qq.access_id,syweb_users_qq.access_key')
->from('syweb_users_qq')
->where('syweb_users_qq.sid=? and syweb_users_qq.scode=? and syweb_users_qq.sid_expire_time>?', $sid,$scode,$nowtime)
->get($this->db ,null);
if(count($res)>0){
$result[0]["error"] = "0";
$result[0]["access_id"] = $res[0]["access_id"];
$result[0]["access_key"] = $res[0]["access_key"];
}else{
$result[0]["error"] = "0";
$result[0]["error_code"] = 1; // 用户未登录或登录信息过期
}
return $result;
}
/**
* 通过AccessToken获取sid
* @route({"GET","/token_login"})
* @param({"access_id","$._GET.access_id"})
* @param({"access_key","$._GET.access_key"})
* @param({"scode","$._GET.scode"}) 客户端生成的Scode
* @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用
*/
public function token_login($access_id,$access_key,$scode) {
// 当前时间戳通过sid和scode获取用户信息必须保障sid未过期
$nowTime = time();
$res = Sql::select('syweb_users_qq.sid')
->from('syweb_users_qq')
->where('syweb_users_qq.access_id=? and syweb_users_qq.access_key=? and syweb_users_qq.scode=? and access_expire_time>?', $access_id,$access_key,$scode,$nowTime)
->get($this->db ,null);
$result = array();
if(count($res)>0){ // 存在对应的用户
$result[0]["error"] = "0";
$result[0]["sid"] = $res[0]['sid'];
}else{
$result[0]["error"] = "1";
$result[0]["error_code"] = 1;// 无效的AccessToken
}
return $result;
}
/** @inject("ioc_factory") */
private $factory;
/**
* @property({"default":"@db"})
* @var PDO
*/
public $db;
// 此处删除了代码
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,85 @@
<?php
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, PATCH, DELETE");
header("Access-Control-Allow-Headers: Content-Type, Authorization, Content-Length, X-Requested-With");
header("Access-Control-Allow-Credentials: true");
header("Content-Type: text/html; charset=utf-8");
/**
* 门店幻灯相关接口
*/
use phprs\util\Verify;
use phprs\util\exceptions\Forbidden;
use phprs\util\Logger;
use phprs\util\exceptions\NotFound;
use phprs\ezsql\Sql;
use phprs\util\exceptions\BadRequest;
require_once 'apiBase.php';
/**
*
* 幻灯片管理
* @path("/commendpic")
*/
class Commendpic extends apiBase {
/**
* 获取门店幻灯片(错误代码15051-15100)
* @route({"POST","/list"})
* @param({"devkey","$._POST.devkey"}) 开发者key
* @param({"market_key","$._POST.market_key"}) market_key
* @param({"sign","$._POST.sign"}) sign
* @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用
* @return("body")
*/
public function getCommendPicList($devkey='',$market_key='',$sign='') {
$result = array();
$verify_result = $this->verifyMarketApi($devkey);
if( is_error_api($verify_result) ){
return $verify_result;
}
if( empty($market_key) ) {
$result["error"] = '1';
$result["error_code"] = 11001;
$result["msg"] = "未传入market_key参数";
return $result;
}
$marketList = Sql::select('a.*')
->from('syweb_market a')
->where('a.market_key=?',$market_key)
->get($this->db ,null);
if( empty($marketList) || count($marketList)<=0 ) {
$result["error"] = '1';
$result["error_code"] = 11002;
$result["msg"] = "market_key无效";
return $result;
}
$marketList = $marketList[0];
$commendpicList = Sql::select('a.*')
->from('syweb_market_commend_pic a')
->where('a.market_key=?',$marketList["market_key"])
->get($this->db ,null);
if( !empty($commendpicList) && count($commendpicList)>0 ) {
foreach ($commendpicList as &$picInfo) {
$picInfo["pic_path"] = env('SITE_OPEN_URL', 'http://open.tscce.cn').$picInfo["pic_path"];
}
}
$result["error"] = '0';
$result["data"] = $commendpicList;
$result["msg"] = "获取门店轮播信息成功!";
return $result;
}
/** @inject("ioc_factory") */
private $factory;
/**
* @property({"default":"@db"})
* @var PDO
*/
public $db;
// 此处删除了代码
}

View File

@@ -0,0 +1,195 @@
<?php
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, PATCH, DELETE");
header("Access-Control-Allow-Headers: Content-Type, Authorization, Content-Length, X-Requested-With");
header("Access-Control-Allow-Credentials: true");
header("Content-Type: text/html; charset=utf-8");
/**
* 优惠券接口
*/
use phprs\util\Verify;
use phprs\util\exceptions\Forbidden;
use phprs\util\Logger;
use phprs\util\exceptions\NotFound;
use phprs\ezsql\Sql;
use phprs\util\exceptions\BadRequest;
require_once 'apiBase.php';
/**
*
* 优惠券接口
* @path("/coupon")
*/
class Coupon extends apiBase{
public $activityInfo; // 当前活动信息
public function commonVerify($appid,$devkey,$sid,$scode,$market_key,$activity_key) {
$result = array();
// 验证公共参数是否合法
parent::init($appid,$devkey,$sid,$scode,$market_key);
$verify_result = parent::verify();
// 判断公共验证是否存在错误
if( is_error_api($verify_result) ){
return $verify_result;
}
if( empty($activity_key) ) {
$result["error"] = '1';
$result["error_code"] = 13000;
$result["msg"] = "请传入对应的活动Key";
return $result;
}
$activityList = Sql::select('a.*')
->from('syweb_business_activity a')
->where('a.activity_key=?',$activity_key)
->get($this->db ,null);
if( empty($activityList) || count($activityList)<=0 ) {
$result["error"] = '1';
$result["error_code"] = 13001;
$result["msg"] = "指定的活动不存在或已经下架";
return $result;
}
$this->activityInfo = $activityList[0];
$activityMarketList = Sql::select('a.*')
->from('syweb_business_activity_market a')
->where('a.activity_key=? and a.market_key=?',$activity_key,$market_key)
->get($this->db ,null);
if( empty($activityMarketList) || count($activityMarketList)<=0 ) {
$result["error"] = '1';
$result["error_code"] = 13002;
$result["msg"] = "当前门店未参与该活动!";
return $result;
}
}
/**
* 获取优惠券(错误代码12000--12050)
* @route({"POST","/exchange"})
* @param({"appid","$._POST.appid"}) 所属应用
* @param({"devkey","$._POST.devkey"}) 开发者Key
* @param({"sid","$._POST.sid"}) 临时会员ID
* @param({"scode","$._POST.scode"}) 客户端票据
* @param({"market_key","$._POST.market_key"}) market_key
* @param({"activity_key","$._POST.activity_key"}) activity_key
* @param({"useprice","$._POST.useprice"}) useprice
* @param({"price","$._POST.price"}) price
* @param({"validDay","$._POST.validDay"}) validDay
* @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用
*/
public function exchange($appid='', $devkey='',$sid='',$scode='',$market_key='',$activity_key='',$useprice=0,$price=0,$validDay=0) {
$result = array();
$P = $_POST;
// 判断公共验证是否存在错误
$verify_result = $this->commonVerify($appid,$devkey,$sid,$scode,$market_key,$activity_key);
if( is_error_api($verify_result) ){
return json_encode($verify_result,JSON_UNESCAPED_UNICODE);
}
if( $this->userInfo["auth_type"]==0 ) {
$result["error"] = "1";
$result["error_code"] = 12000;
$result["msg"] = "创建优惠券失败";
return json_encode($result,JSON_UNESCAPED_UNICODE);
} else if( $this->userInfo["auth_type"]==1 ) {
$result["error"] = "1";
$result["error_code"] = 12000;
$result["msg"] = "创建优惠券失败";
return json_encode($result,JSON_UNESCAPED_UNICODE);
} else if( $this->userInfo["auth_type"]==2 ) {
if ( !is_numeric($useprice) ) {
$result["error"] = "1";
$result["error_code"] = 12001;
$result["msg"] = "满多少可用必须为数字!";
return json_encode($result,JSON_UNESCAPED_UNICODE);
}
if ( !is_numeric($price) ) {
$result["error"] = "1";
$result["error_code"] = 12002;
$result["msg"] = "减免金额必须为数字!";
return json_encode($result,JSON_UNESCAPED_UNICODE);
}
if ( !is_numeric($validDay) ) {
$result["error"] = "1";
$result["error_code"] = 12003;
$result["msg"] = "有效天数必须为数字!";
return json_encode($result,JSON_UNESCAPED_UNICODE);
}
$appid = "G3CI8FQF";
$appkey = "28de5f4a54cbbb62b2264ab555ff7f62";
$url = "http://www.0792it.com/partnerApi/GetSpidFromUid.ashx";
$url .= "?appid=".$appid;
$url .= "&appkey=".$appkey;
$url .= "&uid=".$this->userInfo["openid"];
$response = ihttp_get($url);
if( empty($response) ) {
$result["error"] = "1";
$result["error_code"] = 12004;
$result["msg"] = "获取授权信息错误,登录失败!";
return json_encode($result,JSON_UNESCAPED_UNICODE);
}
$response = @json_decode($response['content'], true);
$spid = $response["spid"];
$accessToken = $response["accessToken"];
// 开始获取用户信息
$url = "http://www.0792it.com/partnerApi/CreatShopCoupon.ashx";
$paramers = array();
$paramers["accessToken"] = $accessToken;
$paramers["GameName"] = $this->activityInfo["activity_name"];
$paramers["s_price"] = $price;
$paramers["s_useprice"] = $useprice;
$paramers["Shopid"] = $this->marketInfo["jkx_market_key"];
$paramers["spid"] = $spid;
$paramers["validDay"] = $validDay;
$paramers["secret"] = "ecd10d48daf3138b88727bc65ca3e0bd";
$paramerStr = $this->ToUrlParams($paramers);
$sign = md5($paramerStr);
$paramerStr .= "&sign=".$sign;
$url .= "?".$paramerStr;
$response = ihttp_get($url);
if( empty($response) ) {
$result["error"] = "1";
$result["error_code"] = 12005;
$result["msg"] = "创建优惠券失败!";
return json_encode($result,JSON_UNESCAPED_UNICODE);
}
$response = @json_decode($response['content'], true);
$retCode = $response["RetCode"];
if( $retCode==1 || $retCode==3 || $retCode==5 ) {
$result["error"] = '1';
$result["error_code"] = 12005;
$result["msg"] = "创建优惠券失败,错误消息为:".$response["RetMsg"];
return json_encode($result,JSON_UNESCAPED_UNICODE);
}
$result["error"] = '0';
$result["msg"] = "创建优惠券成功!";
return json_encode($result,JSON_UNESCAPED_UNICODE);
}
}
/** @inject("ioc_factory") */
private $factory;
/**
* @property({"default":"@db"})
* @var PDO
*/
public $db;
// 此处删除了代码
}

View File

@@ -0,0 +1,215 @@
<?php
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, PATCH, DELETE");
header("Access-Control-Allow-Headers: Content-Type, Authorization, Content-Length, X-Requested-With");
header("Access-Control-Allow-Credentials: true");
header("Content-Type: text/html; charset=utf-8");
/**
* 用户积分接口
*/
use phprs\util\Verify;
use phprs\util\exceptions\Forbidden;
use phprs\util\Logger;
use phprs\util\exceptions\NotFound;
use phprs\ezsql\Sql;
use phprs\util\exceptions\BadRequest;
require_once 'apiBase.php';
/**
*
* 用户积分接口
* @path("/jifen")
*/
class Jifen extends apiBase{
/**
* 更新用户积分(错误代码13000-13050)
* @route({"POST","/update"})
* @param({"appid","$._POST.appid"}) 所属应用
* @param({"devkey","$._POST.devkey"}) 开发者Key
* @param({"sid","$._POST.sid"}) 临时会员ID
* @param({"scode","$._POST.scode"}) 客户端票据
* @param({"jifencount","$._POST.jifencount"}) 变更积分数量
* @param({"content","$._POST.content"}) 操作说明
* @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用
*/
public function jifenUpdate($appid='', $devkey='',$sid='',$scode='',$jifencount='',$content='') {
// 验证公共参数是否合法
parent::init($appid,$devkey,$sid,$scode);
$verify_result = parent::verify();
if( is_error_api($verify_result) ){
return json_encode($verify_result,JSON_UNESCAPED_UNICODE);
}
$result = array();
if ( !is_numeric($jifencount) ) {
$result["error"] = "1";
$result["error_code"] = 13000;
$result["msg"] = "请正确传入变更积分的数量";
return json_encode($result,JSON_UNESCAPED_UNICODE);
}
$old_jifen = $this->userInfo["market_jifen"];
if( empty($old_jifen) || !is_numeric($old_jifen) ){
$old_jifen = 0;
$this->userInfo["market_jifen"] = 0;
}
$old_jifen = $old_jifen + $jifencount;
$this->userInfo["market_jifen"] = $old_jifen;
if( $old_jifen<0 ){
$old_jifen = 0;
$this->userInfo["market_jifen"] = 0;
}
$updateSql = Sql::update('syweb_users');
$updateSql->set("market_jifen",$old_jifen);
$condition = array();
$conditionStr = "";
if( empty($conditionStr) ){
$conditionStr = " id= ".$this->userInfo["id"];
}else{
$conditionStr .= " and id= ".$this->userInfo["id"];
}
if(!empty($conditionStr)){
$updateSql->where($conditionStr);
}
$pdo = $this->db;
$pdo->beginTransaction();
$updateCount = $updateSql->exec($pdo);
$pdo->commit();
// 假如是聚开心授权的话,还需要同步修改聚开心那边
if( $this->userInfo["auth_type"]==2 ) {
$appid = "G3CI8FQF";
$appkey = "28de5f4a54cbbb62b2264ab555ff7f62";
$url = "http://www.0792it.com/partnerApi/GetSpidFromUid.ashx";
$url .= "?appid=".$appid;
$url .= "&appkey=".$appkey;
$url .= "&uid=".$this->userInfo["openid"];
$response = ihttp_get($url);
if( empty($response) ) {
$result["error"] = "1";
$result["error_code"] = 13001;
$result["msg"] = "获取授权信息错误,登录失败!";
return json_encode($result,JSON_UNESCAPED_UNICODE);
}
$response = @json_decode($response['content'], true);
$spid = $response["spid"];
$accessToken = $response["accessToken"];
// 开始获取用户信息
$url = "http://www.0792it.com/partnerApi/SetIntegral.ashx";
$url .= "?spid=".$spid;
$url .= "&accessToken=".$accessToken;
$act = 1;
if( $jifencount<0 ) {
$jifencount = -$jifencount;
$act = 2;
}
$url .= "&point=".$jifencount;
$url .= "&act=".$act;
$url .= "&content=".$content;
$sign = "accessToken=".$accessToken."&act=".$act."&content=".$content."&point=".$jifencount."&spid=".$spid."&secret=ecd10d48daf3138b88727bc65ca3e0bd";
$sign = md5($sign);
$url .= "&sign=".$sign;
$response = ihttp_get($url);
if( empty($response) ) {
$result["error"] = "1";
$result["error_code"] = 13001;
$result["msg"] = "获取授权信息错误,登录失败!";
return json_encode($result,JSON_UNESCAPED_UNICODE);
}
$response = @json_decode($response['content'], true);
$retCode = $response["RetCode"];
if( $retCode==1 ) {
$result["error"] = '1';
$result["error_code"] = 13002;
$result["msg"] = "同步聚开心积分错误,错误消息为:" + $response["RetMsg"];
return json_encode($result,JSON_UNESCAPED_UNICODE);
}
$jkxUserList = Sql::select('a.*')
->from('syweb_users_jkx a')
->where('a.uid=?',$this->userInfo["id"])
->get($this->db ,null);
if( empty($jkxUserList) || count($jkxUserList)<=0 ) {
$result["error"] = '1';
$result["error_code"] = 13003;
$result["msg"] = "子账户无效";
return json_encode($result,JSON_UNESCAPED_UNICODE);
}
$jkxUserInfo = $jkxUserList[0];
$updateSql = Sql::update('syweb_users_jkx');
if( $act==1 ) {
$updateSql->set("integral",$jkxUserInfo["integral"] + $jifencount);
} else {
$updateSql->set("integral",$jkxUserInfo["integral"] - $jifencount);
}
$conditionStr = " id= ".$jkxUserInfo["id"];
$updateSql->where($conditionStr);
$pdo = $this->db;
$pdo->beginTransaction();
$updateSql->exec($pdo);
$pdo->commit();
}
$result["error"] = '0';
$result["message"] = '积分修改成功。';
return json_encode($result,JSON_UNESCAPED_UNICODE);
}
/**
* 查询用户积分余额(错误代码11051-11100)
* @route({"POST","/"})
* @param({"appid","$._POST.appid"}) 应用appid
* @param({"devkey","$._POST.devkey"}) 开发者key
* @param({"sid","$._POST.sid"}) 服务器返回的sid
* @param({"scode","$._POST.scode"}) 客户端生成的scode
* @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用
*/
public function queryUserJifen($appid="",$devkey="",$sid="",$scode="") {
// 验证公共参数是否合法
parent::init($appid,$devkey,$sid,$scode);
$verify_result = parent::verify();
if( !is_error_api($verify_result) ){
$result = array();
$jifen_count = $this->userInfo['jifen_account'];
if( !empty($jifen_count) && is_numeric($jifen_count) ){
$result["error"] = "0";
$result["jifen_count"] = $jifen_count;
return json_encode($result,JSON_UNESCAPED_UNICODE);
} else {
$result["error"] = "0";
$result["jifen_count"] = 0;
return json_encode($result,JSON_UNESCAPED_UNICODE);
}
}else{
return json_encode($verify_result,JSON_UNESCAPED_UNICODE);
}
}
/** @inject("ioc_factory") */
private $factory;
/**
* @property({"default":"@db"})
* @var PDO
*/
public $db;
// 此处删除了代码
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,55 @@
<?php
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, PATCH, DELETE");
header("Access-Control-Allow-Headers: Content-Type, Authorization, Content-Length, X-Requested-With");
header("Access-Control-Allow-Credentials: true");
header("Content-Type: text/html; charset=utf-8");
/**
* 登录相关接口
*/
use phprs\util\Verify;
use phprs\util\exceptions\Forbidden;
use phprs\util\Logger;
use phprs\util\exceptions\NotFound;
use phprs\ezsql\Sql;
use phprs\util\exceptions\BadRequest;
require_once 'apiBase.php';
/**
*
* 登录管理
* @path("/back_login")
*/
class LoginBack extends apiBase
{
/**
* 获得登录方式
* @route({"GET","/"})
* @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用
* @return("body")
*/
public function getLoginType()
{
$result = array();
$result[0]["name"] = "微信登录";
$result[0]["url"] = $this->getFullUrl('/api/login/weixin');
$result[0]["third"] = "weixin";
//$result[1]["name"] = "QQ登录";
//$result[1]["url"] = $this->getFullUrl('/api/login/qq');
//$result[1]["third"] = "qq";
return $result;
}
/** @inject("ioc_factory") */
private $factory;
/**
* @property({"default":"@db"})
* @var PDO
*/
public $db;
// 此处删除了代码
}

View File

@@ -0,0 +1,529 @@
<?php
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, PATCH, DELETE");
header("Access-Control-Allow-Headers: Content-Type, Authorization, Content-Length, X-Requested-With");
header("Access-Control-Allow-Credentials: true");
header("Content-Type: text/html; charset=utf-8");
/**
* 后台应用管理员登录
*/
use phprs\util\Verify;
use phprs\util\exceptions\Forbidden;
use phprs\util\Logger;
use phprs\util\exceptions\NotFound;
use phprs\ezsql\Sql;
use phprs\util\exceptions\BadRequest;
/**
*
* 应用管理员登录接口
* @path("/manager")
*/
class Manager {
/**
* 后台管理员通过账号密码登录
* @route({"POST","/"})
* @param({"appid","$._POST.appid"}) 应用appid
* @param({"devkey","$._POST.devkey"}) 开发者key
* @param({"username","$._POST.username"}) 用户名
* @param({"password","$._POST.password"}) 用户密码
* @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用
*/
public function login($appid,$devkey,$username,$password) {
if(empty($appid)){
$result["status"] = '0';
$result["message"] = '请传入appid参数。';
return $result;
}
if(empty($devkey)){
$result["status"] = '0';
$result["message"] = '请传入devkey参数。';
return $result;
}
if(empty($username)){
$result["status"] = '0';
$result["message"] = '请传入username参数。';
return $result;
}
if(empty($password)){
$result["status"] = '0';
$result["message"] = '请传入password参数。';
return $result;
}
// 加密管理员密码
$password = md5($password);
$res = Sql::select('syweb_admin.*')
->from('syweb_admin,syweb_app')
->where('syweb_admin.app_id=syweb_app.id and syweb_app.appid=? and syweb_admin.username=? and syweb_admin.password=? and syweb_admin.type=3', $appid,$username,$password)
->get($this->db ,null);
if(count($res)>0){
$result[0]["error"] = "0";
$result[0]["data"] = $res[0];
}else{
$result[0]["error"] = "1";
$result[0]["error_code"] = 1; // 用户名或密码不存在
}
return $result;
}
/**
* 增加应用管理员(错误代码10200-10250)
* @route({"POST","/add"})
* @param({"appid","$._POST.appid"}) 应用appid
* @param({"devkey","$._POST.devkey"}) 开发者key
* @param({"username","$._POST.username"}) 用户名账号
* @param({"nickname","$._POST.nickname"}) 用户昵称
* @param({"password","$._POST.password"}) 用户密码
* @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用
*/
public function add($appid="",$devkey="",$username="",$nickname="",$password="") {
$result = array();
$insertData = array();
if( empty($appid) ){
$result["error"] = '1';
$result["error_code"] = 10001;
$result["msg"] = "未传入appid参数";
return $result;
}
if( empty($devkey) ){
$result["error"] = '1';
$result["error_code"] = 10002;
$result["msg"] = "未传入devkey参数";
return $result;
}
$devList = Sql::select('syweb_admin.*')
->from('syweb_admin')
->where('syweb_admin.type=2 and syweb_admin.devkey=? and syweb_admin.status=1',$devkey)
->get($this->db ,null);
if( empty($devList) || count($devList)<=0 ){
$result["error"] = '1';
$result["error_code"] = 10003;
$result["msg"] = "devkey无效";
return $result;
}
$devInfo = $devList[0];
$appList = Sql::select('syweb_app.*')
->from('syweb_app')
->where('syweb_app.appid=? and syweb_app.dev_id=? and status=1', $appid,$devInfo['id'])
->get($this->db ,null);
if( empty($appList) || count($appList)<=0 ){
$result["error"] = '1';
$result["error_code"] = 10004;
$result["msg"] = "指定的应用不存在或未被审核";
return $result;
}
$appInfo = $appList[0];
$insertData['app_id'] = $appInfo["id"];
if( empty($username) ){
$result["error"] = '1';
$result["error_code"] = 10200;
$result["msg"] = '请输入管理员账号。';
return $result;
}
if( !checklen($username) ){
$result["error"] = '1';
$result["error_code"] = 10201;
$result["msg"] = '管理员用户名必须是大于5位小于15位';
return $result;
}
$managerInfo = Sql::select('syweb_admin.*')
->from('syweb_admin')
->where('syweb_admin.username=?', $username)
->get($this->db ,null);
if( !empty($managerInfo) && count($managerInfo)>0 ){
$result["error"] = '1';
$result["error_code"] = 10202;
$result["msg"] = '指定的管理员账号已经存在。';
return $result;
}
$insertData['username'] = $username;
if( empty($password) ){
$result["error"] = '1';
$result["error_code"] = 10203;
$result["msg"] = '请传入管理员密码!';
return $result;
}
if( !checklen($password) ){
$result["error"] = '1';
$result["error_code"] = 10204;
$result["msg"] = '管理员密码必须是大于8位小于16位';
return $result;
}
$insertData['password'] = md5($password);
if( empty($nickname) ){
$result["error"] = '1';
$result["error_code"] = 10205;
$result["msg"] = '请输入管理员昵称!';
return $result;
}
$insertData['nickname'] = $nickname;
$insertData['type'] = 3;
$insertData['status'] = 1;
$insertData['createtime'] = time();
$pdo = $this->db;
$pdo->beginTransaction();
$managerId = Sql::insertInto('syweb_admin')->values($insertData)->exec($pdo)->lastInsertId();
$pdo->commit();
if ( !empty($managerId) && is_numeric($managerId) && $managerId>0 ) {
unset($insertData["password"]);
unset($insertData["type"]);
$insertData["id"] = $managerId;
$result["error"] = '0';
$result["data"] = $insertData;
$result["msg"] = "添加管理员成功。";
return $result;
}else{
$result["error"] = '1';
$result["error_code"] = 10206;
$result["msg"] = '添加管理员失败。';
return $result;
}
}
/**
* 修改应用管理员(错误代码10200-10250)
* @route({"POST","/edit"})
* @param({"appid","$._POST.appid"}) 应用appid
* @param({"devkey","$._POST.devkey"}) 开发者key
* @param({"username","$._POST.username"}) 用户名账号
* @param({"nickname","$._POST.nickname"}) 用户昵称
* @param({"password","$._POST.password"}) 用户密码
* @param({"oldpassword","$._POST.oldpassword"}) 用户原始密码
* @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用
*/
public function edit($appid="",$devkey="",$username="",$nickname="",$password="",$oldpassword="") {
$result = array();
$updateData = array();
if( empty($appid) ){
$result["error"] = '1';
$result["error_code"] = 10001;
$result["msg"] = "未传入appid参数";
return $result;
}
if( empty($devkey) ){
$result["error"] = '1';
$result["error_code"] = 10002;
$result["msg"] = "未传入devkey参数";
return $result;
}
$devList = Sql::select('syweb_admin.*')
->from('syweb_admin')
->where('syweb_admin.type=2 and syweb_admin.devkey=? and syweb_admin.status=1',$devkey)
->get($this->db ,null);
if( empty($devList) || count($devList)<=0 ){
$result["error"] = '1';
$result["error_code"] = 10003;
$result["msg"] = "devkey无效";
return $result;
}
$devInfo = $devList[0];
$appList = Sql::select('syweb_app.*')
->from('syweb_app')
->where('syweb_app.appid=? and syweb_app.dev_id=? and status=1', $appid,$devInfo['id'])
->get($this->db ,null);
if( empty($appList) || count($appList)<=0 ){
$result["error"] = '1';
$result["error_code"] = 10004;
$result["msg"] = "指定的应用不存在或未被审核";
return $result;
}
$appInfo = $appList[0];
if( empty($username) ){
$result["error"] = '1';
$result["error_code"] = 10200;
$result["msg"] = '请输入要修改的管理员账号。';
return $result;
}
$managerInfo = Sql::select('syweb_admin.*')
->from('syweb_admin')
->where('syweb_admin.username=?',$username)
->get($this->db ,null);
if( empty($managerInfo) || count($managerInfo)<0 ){
$result["error"] = '1';
$result["error_code"] = 10201;
$result["msg"] = '指定的管理员账号不存在。';
return $result;
}
if( empty($password) && empty($nickname) ){
$result["error"] = '1';
$result["error_code"] = 10202;
$result["msg"] = '请指定修改昵称或是密码';
return $result;
}
if( !empty($password) && !checklen($password) ){
$result["error"] = '1';
$result["error_code"] = 10203;
$result["msg"] = '管理员密码必须是大于8位小于16位';
return $result;
}
if( !empty($password) && empty($oldpassword) ){
$result["error"] = '1';
$result["error_code"] = 10204;
$result["msg"] = '要修改密码必须提供原密码。';
return $result;
}
if( !empty($password) ){
$managerInfo = Sql::select('syweb_admin.*')
->from('syweb_admin')
->where('syweb_admin.username=? and syweb_admin.password=?',$username,md5($oldpassword))
->get($this->db ,null);
if( empty($managerInfo) || count($managerInfo)<0 ){
$result["error"] = '1';
$result["error_code"] = 10205;
$result["msg"] = '原始密码不符。';
return $result;
}
}
$fieldsCount = 0;
$updateSql = Sql::update('syweb_admin');
if ( !empty($nickname) ) {
$updateSql->set("nickname",$nickname);
$fieldsCount = $fieldsCount +1;
}
if ( !empty($password) ) {
$updateSql->set("password",md5($password));
$fieldsCount = $fieldsCount +1;
}
// 修改限定条件 begin
$condition = array();
$conditionStr = " username='".$username."'";
if(!empty($conditionStr)){
$updateSql->where($conditionStr);
}
// 修改限定条件 end
$pdo = $this->db;
$pdo->beginTransaction();
if($fieldsCount>0){
$updateCount = $updateSql->exec($pdo);
}
$pdo->commit();
if( !$updateCount ){
$result["error"] = '0';
$result["msg"] = '数据修改成功。';
return $result;
}else{
$result["error"] = '1';
$result["error_code"] = 10206;
$result["msg"] = '数据修改失败。';
return $result;
}
}
/**
* 增加应用管理员(错误代码10300-10350)
* @route({"POST","/delete"})
* @param({"appid","$._POST.appid"}) 应用appid
* @param({"devkey","$._POST.devkey"}) 开发者key
* @param({"username","$._POST.username"}) 用户名账号
* @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用
*/
public function delete($appid="",$devkey="",$username="") {
$result = array();
$insertData = array();
if( empty($appid) ){
$result["error"] = '1';
$result["error_code"] = 10001;
$result["msg"] = "未传入appid参数";
return $result;
}
if( empty($devkey) ){
$result["error"] = '1';
$result["error_code"] = 10002;
$result["msg"] = "未传入devkey参数";
return $result;
}
$devList = Sql::select('syweb_admin.*')
->from('syweb_admin')
->where('syweb_admin.type=2 and syweb_admin.devkey=? and syweb_admin.status=1',$devkey)
->get($this->db ,null);
if( empty($devList) || count($devList)<=0 ){
$result["error"] = '1';
$result["error_code"] = 10003;
$result["msg"] = "devkey无效";
return $result;
}
$devInfo = $devList[0];
$appList = Sql::select('syweb_app.*')
->from('syweb_app')
->where('syweb_app.appid=? and syweb_app.dev_id=? and status=1', $appid,$devInfo['id'])
->get($this->db ,null);
if( empty($appList) || count($appList)<=0 ){
$result["error"] = '1';
$result["error_code"] = 10004;
$result["msg"] = "指定的应用不存在或未被审核";
return $result;
}
$appInfo = $appList[0];
$insertData['app_id'] = $appInfo["id"];
if( empty($username) ){
$result["error"] = '1';
$result["error_code"] = 10300;
$result["msg"] = '请输入要删除的管理员账号。';
return $result;
}
$managerInfo = Sql::select('syweb_admin.*')
->from('syweb_admin')
->where('syweb_admin.username=?', $username)
->get($this->db ,null);
if( empty($managerInfo) || count($managerInfo)<=0 ){
$result["error"] = '1';
$result["error_code"] = 10301;
$result["msg"] = '指定的管理员账号不存在。';
return $result;
}
$condition .= " `username` = '".$username."'";
$pdo = $this->db;
$pdo->beginTransaction();
$delResult = Sql::deleteFrom('syweb_admin')->where($condition)->exec($this->db);
$pdo->commit();
$managerInfo = Sql::select('syweb_admin.*')
->from('syweb_admin')
->where('syweb_admin.username=?', $username)
->get($this->db ,null);
if( empty($managerInfo) || count($managerInfo)<=0 ){
$result["error"] = '0';
$result["msg"] = "删除管理员成功。";
return $result;
}else{
$result["error"] = '1';
$result["error_code"] = 10302;
$result["msg"] = '删除管理员失败。';
}
}
/**
* 查询指定应用中的管理员列表
* @route({"POST","/list"})
* @param({"appid","$._POST.appid"}) 应用appid
* @param({"devkey","$._POST.devkey"}) 开发者key
* @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用
*/
public function queryList($appid="",$devkey="") {
$fields = " syweb_admin.id,syweb_admin.username,syweb_admin.nickname,syweb_admin.app_id,syweb_admin.createtime ";
if( empty($appid) ){
$result["status"] = '0';
$result["message"] = '请传入appid参数。';
return $result;
}
$appInfo = Sql::select('syweb_app.*')
->from('syweb_app')
->where('syweb_app.appid=?', $appid)
->get($this->db ,null);
if(empty($appInfo) && count($appInfo)<=0){
$result["status"] = '0';
$result["message"] = '指定的应用不存在请检查appid参数。';
return $result;
}
if(empty($devkey)){
$result["status"] = '0';
$result["message"] = '请传入devkey参数。';
return $result;
}
$managerList = Sql::select($fields)
->from('syweb_admin,syweb_app')
->where('syweb_admin.app_id=syweb_app.id and syweb_app.appid=? and syweb_admin.type=3', $appid)
->get($this->db ,null);
if(!empty($managerList) && count($managerList)>0){
$result["status"] = '0';
$result["data"] = $managerList;
return $result;
} else {
$result["status"] = '0';
$result["data"] = array();
return $result;
}
}
/**
* 根据用户名查询用户详细信息
* @route({"POST","/query"})
* @param({"appid","$._POST.appid"}) 应用appid
* @param({"devkey","$._POST.devkey"}) 开发者key
* @param({"username","$._POST.username"}) 用户名
* @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用
*/
public function query($appid,$devkey,$username) {
if(empty($appid)){
$result["status"] = '0';
$result["message"] = '请传入appid参数。';
return $result;
}
$appInfo = Sql::select('syweb_app.*')
->from('syweb_app')
->where('syweb_app.appid=?', $appid)
->get($this->db ,null);
if(empty($appInfo) || count($appInfo)<=0){
$result["status"] = '0';
$result["message"] = '指定的应用不存在请检查appid参数。';
return $result;
}
if(empty($devkey)){
$result["status"] = '0';
$result["message"] = '请传入devkey参数。';
return $result;
}
if(empty($username)){
$result["status"] = '0';
$result["message"] = '请传入username参数。';
return $result;
}
$res = Sql::select('syweb_admin.id,syweb_admin.username,syweb_admin.nickname,syweb_admin.app_id,syweb_admin.createtime')
->from('syweb_admin,syweb_app')
->where('syweb_admin.app_id=syweb_app.id and syweb_app.appid=? and syweb_admin.username=? and syweb_admin.type=3', $appid,$username)
->get($this->db ,null);
if(count($res)>0){
$result[0]["error"] = "0";
$result[0]["data"] = $res[0];
}else{
$result[0]["error"] = "1";
$result[0]["error_code"] = 1; // 指定的用户不存在
}
return $result;
}
/** @inject("ioc_factory") */
private $factory;
/**
* @property({"default":"@db"})
* @var PDO
*/
public $db;
}

View File

@@ -0,0 +1,82 @@
<?php
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, PATCH, DELETE");
header("Access-Control-Allow-Headers: Content-Type, Authorization, Content-Length, X-Requested-With");
header("Access-Control-Allow-Credentials: true");
header("Content-Type: text/html; charset=utf-8");
/**
* 门店相关接口
*/
use phprs\util\Verify;
use phprs\util\exceptions\Forbidden;
use phprs\util\Logger;
use phprs\util\exceptions\NotFound;
use phprs\ezsql\Sql;
use phprs\util\exceptions\BadRequest;
require_once 'apiBase.php';
/**
*
* 登录管理
* @path("/market")
*/
class Market extends apiBase {
/**
* 获取商户信息(错误代码15000-15050)
* @route({"POST","/"})
* @param({"devkey","$._POST.devkey"}) 开发者key
* @param({"market_key","$._POST.market_key"}) market_key
* @param({"sign","$._POST.sign"}) sign
* @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用
* @return("body")
*/
public function getMarketInfo($devkey='',$market_key='',$sign='') {
$result = array();
$verify_result = $this->verifyMarketApi($devkey);
if( is_error_api($verify_result) ){
return $verify_result;
}
if( empty($market_key) ) {
$result["error"] = '1';
$result["error_code"] = 11001;
$result["msg"] = "未传入market_key参数";
return $result;
}
$marketList = Sql::select('syweb_market.*')
->from('syweb_market')
->where('syweb_market.market_key=?',$market_key)
->get($this->db ,null);
if( empty($marketList) || count($marketList)<=0 ) {
$result["error"] = '1';
$result["error_code"] = 11002;
$result["msg"] = "market_key无效";
return $result;
}
$marketList = $marketList[0];
$data = array();
$data["market_key"] = $marketList["market_key"];
$data["market_name"] = $marketList["market_name"];
if( !empty($marketList["head_image"]) ) {
$data["head_image"] = env('SITE_OPEN_URL', 'http://open.tscce.cn').$marketList["head_image"];
}
$result["error"] = '0';
$result["data"] = $data;
$result["msg"] = "获取门店信息成功!";
return $result;
}
/** @inject("ioc_factory") */
private $factory;
/**
* @property({"default":"@db"})
* @var PDO
*/
public $db;
// 此处删除了代码
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,205 @@
<?php
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, PATCH, DELETE");
header("Access-Control-Allow-Headers: Content-Type, Authorization, Content-Length, X-Requested-With");
header("Access-Control-Allow-Credentials: true");
header("Content-Type: text/html; charset=utf-8");
/**
* 登录相关接口
*/
use phprs\util\Verify;
use phprs\util\exceptions\Forbidden;
use phprs\util\Logger;
use phprs\util\exceptions\NotFound;
use phprs\ezsql\Sql;
use phprs\util\exceptions\BadRequest;
require_once 'apiBase.php';
/**
*
* 订单管理
* @path("/order")
*/
class Order extends apiBase{
/**
* 购买订单生成(错误代码12701-12750)
* @route({"POST","/add"})
* @param({"appid","$._POST.appid"}) 所属公众号
* @param({"devkey","$._POST.devkey"}) 外部应用ID
* @param({"sid","$._POST.sid"}) 临时会员ID
* @param({"scode","$._POST.scode"}) 客户端票据
* @param({"goodsprice","$._POST.goodsprice"}) 商品费用
* @param({"dispatchprice","$._POST.dispatchprice"}) 运费
* @param({"title","$._POST.title"}) 支付主题
* @param({"sendtype","$._POST.sendtype"}) 1为快递2为自提
* @param({"address","$._POST.address"}) 收货地址
* @param({"goodstype","$._POST.goodstype"}) 商品类型(1实体商品2虚拟商品)
* @param({"remark","$._POST.remark"}) 订单留言
* @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用
*/
public function orderAdd($appid='', $devkey='',$sid='',$scode='',$goodsprice='',$dispatchprice='',$title='',$sendtype='',$address='{=NULL=}',$goodstype='',$remark='') {
// 验证公共参数是否合法
parent::init($appid,$devkey,$sid,$scode);
$verify_result = parent::verify();
if( !is_error_api($verify_result) ){
$result = array();
if ( !is_numeric($goodsprice) ) {
$result["error"] = "1";
$result["error_code"] = 12701;
$result["msg"] = "请正确传入goodsprice";
return $result;
}
if ( !is_numeric($dispatchprice) ) {
$result["error"] = "1";
$result["error_code"] = 12702;
$result["msg"] = "请正确传入dispatchprice";
return $result;
}
if(empty($title)){
$result["error"] = "1";
$result["error_code"] = 12703;
$result["msg"] = "请传入title";
return $result;
}
if( !is_numeric($sendtype) ){
$result["error"] = "1";
$result["error_code"] = 12704;
$result["msg"] = "请正确传入sendtype";
return $result;
}
if(intval($goodstype)==1 && intval($sendtype)==1){
if ( $address=='{=NULL=}' ){
$result["error"] = "1";
$result["error_code"] = 12705;
$result["msg"] = "请传入收货地址";
return $result;
}
}
if( !is_numeric($goodstype) ){
$result["error"] = "1";
$result["error_code"] = 12706;
$result["msg"] = "请正确传入goodstype";
return $result;
}
// 生成随机订单编号 begin
$ordersn = date('ymd') . random(10, 1);//订单编号
while(true){
$order_list = Sql::select('syweb_order.*')
->from('syweb_order')
->where('syweb_order.ordersn=?', $ordersn)
->get($this->db ,null);
if (!empty($order_list) && count($order_list)>0) {
$ordersn = date('ymd') . random(10, 1);//订单编号
}else{
break;
}
}
// 生成随机订单编号 begin
if( $this->userInfo["auth_type"]==0 ){
$openId = $this->userInfo["openid"]; // 微信用户的openId
$data = array(
'app_id' => $this->appInfo["id"],// 所属应用
'business_id' => $this->businessInfo["id"],// 所属商家
'from_user' => $openId,// 购买用户
'ordersn' => $ordersn,//订单编号
'title' => $title,//订单标题
'price' => $goodsprice + $dispatchprice,//总价
'status' => 0,//订单状态
'sendtype' => intval($sendtype),// 1为快递2为自提
'paytype' => '0',
'goodstype' => intval($goodstype),// 商品类型(1实体商品2虚拟商品)
'remark' => $remark,//留言
'address' => $address,// 收货地址
'goodsprice' => $goodsprice,//商品价格
'dispatchprice' => $dispatchprice,//运费
'paydetail' => '',
'createtime' => TIMESTAMP//订单创建时间
);
$pdo = $this->db;
$pdo->beginTransaction();
$orderid = Sql::insertInto('syweb_order')->values($data)->exec($pdo)->lastInsertId();
$pdo->commit();
if (!empty($orderid)) {
$result["error"] = "0";
$result["order"] = $data;
return $result;
}else{
$result["error"] = "1";
$result["error_code"] = 12707; // 订单生成失败
$result["msg"] = "订单生成失败";
return $result;
}
}else{
// QQ登录状态
}
}else{
return $verify_result;
}
}
/**
* 根据订单ID查询订单详情(错误代码12751-12800)
* @route({"POST","/"})
* @param({"appid","$._POST.appid"}) 所属公众号
* @param({"devkey","$._POST.devkey"}) 外部应用ID
* @param({"sid","$._POST.sid"}) 临时会员ID
* @param({"scode","$._POST.scode"}) 客户端票据
* @param({"orderSN","$._POST.orderSN"}) 订单编号
* @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用
*/
public function getOrder($appid='',$devkey='',$sid='',$scode='',$orderSN='') {
// 验证公共参数是否合法
parent::init($appid,$devkey,$sid,$scode);
$verify_result = parent::verify();
if( !is_error_api($verify_result) ){
$result = array();
if ( empty($orderSN) ) {
$result["error"] = "1";
$result["error_code"] = 12751;
$result["msg"] = "请传入orderSN";
return $result;
}
if( $this->userInfo["auth_type"]==0 ){
$openId =$this->userInfo["openid"]; // 微信用户的openId
$orderInfo = Sql::select('syweb_order.*')
->from('syweb_order')
->where('syweb_order.app_id=? and syweb_order.business_id=? and syweb_order.ordersn=?', $this->appInfo['id'],$this->businessInfo['id'],$orderSN)
->get($this->db ,null);
if (!empty($orderInfo)) {
$result["error"] = "0";
$result["order"] = $orderInfo;
return $result;
}else{
$result["error"] = "1";
$result["error_code"] = 12752;
$result["msg"] = "订单不存在或已经被删除。";
return $result;
}
}else{
// QQ登录状态
}
}else{
return $verify_result;
}
}
/** @inject("ioc_factory") */
private $factory;
/**
* @property({"default":"@db"})
* @var PDO
*/
public $db;
// 此处删除了代码
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,149 @@
<?php
header('Access-Control-Allow-Origin:*');// 指定允许其他域名访问
header('Access-Control-Allow-Methods:POST');// 响应类型
header('Access-Control-Allow-Headers:x-requested-with,content-type');
/**
* 获取票据接口
*/
use phprs\util\Verify;
use phprs\util\exceptions\Forbidden;
use phprs\util\Logger;
use phprs\util\exceptions\NotFound;
use phprs\ezsql\Sql;
use phprs\util\exceptions\BadRequest;
/**
*
* 获取信息接口
* @path("/permission")
*/
class Permission {
/**
* 通过devkey和appid换取票据
* @route({"POST","/ticket"})
* @param({"appid","$._POST.appid"}) 应用appid
* @param({"devkey","$._POST.devkey"}) 开发者key
* @param({"domain","$._POST.domain"}) 域名
* @param({"nocestr","$._POST.nocestr"}) 随机字符串
* @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用
*/
public function getTicket($appid,$devkey,$domain,$nocestr) {
// 当前时间戳通过sid和scode获取用户信息必须保障sid未过期
$nowtime = time();
$ticket = md5($appid.'=='.$devkey.'=='.$domain.'=='.$nocestr);
$insertData = array();
$insertData['appid'] = $appid;
$insertData['devkey'] = $appid;
$insertData['domain'] = $appid;
$insertData['nocestr'] = $appid;
$insertData['ticket'] = $appid;
$expire_time = time();
$expire_date = date('H:i:s',strtotime("+20 minute"));
$expire_time = strtotime($expire_date);
$insertData['expiretime'] = $expire_time; // 票据过期时间
$pdo = $this->db;
$pdo->beginTransaction();
$id = Sql::insertInto('syweb_ticket')->values($insertData)->exec($pdo)->lastInsertId();
$pdo->commit();
// 根据sid 查询用户信息
$res = Sql::select('syweb_ticket.*')
->from('syweb_ticket')
->where('syweb_ticket.id=?', $id)
->get($this->db ,null);
if(count($res)>0){
$result[0]["error"] = "0";
$result[0]["ticket"] = $ticket;
}else{
$result[0]["error"] = "1";
$result[0]["error_code"] = 1; // 获取授权票据失败
}
return $result;
}
/**
* 验证开发者权限
* @route({"POST","/check_auth"})
* @param({"appid","$._POST.appid"}) 应用appid
* @param({"devkey","$._POST.devkey"}) 开发者key
* @param({"ticket","$._POST.ticket"}) 服务器授予的票据
* @param({"authcode","$._POST.authcode"}) 权限代码
* @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用
*/
public function checkPermission($appid="",$devkey="",$ticket="",$authcode="") {
// 当前时间戳
$nowtime = time();
$referer = $_SERVER["HTTP_REFERER"];// 客户端来源地址
if( empty($appid) ){
$result["error"] = '1';
$result["error_code"] = '1';
$result["message"] = '请传入appid参数。';
return json_encode($result,JSON_UNESCAPED_UNICODE);
}
$appInfo = Sql::select('syweb_app.*')
->from('syweb_app')
->where('syweb_app.appid=?', $appid)
->get($this->db ,null);
if(!empty($appInfo) && count($appInfo)>0){
$insertData['app_id'] = $appInfo[0]["id"];
} else {
$result["error"] = '1';
$result["error_code"] = '2';
$result["message"] = '指定的应用不存在请检查appid参数。';
return json_encode($result,JSON_UNESCAPED_UNICODE);
}
if(empty($devkey)){
$result["error"] = '1';
$result["error_code"] = '3';
$result["message"] = '请传入devkey参数。';
return json_encode($result,JSON_UNESCAPED_UNICODE);
}
// 根据sid 查询用户信息
// $res = Sql::select('syweb_ticket.*')
// ->from('syweb_ticket')
// ->where('syweb_ticket.appid=? and syweb_ticket.devkey=? and syweb_ticket.ticket=? and syweb_ticket.expiretime>?',$appid,$devkey,$ticket,$nowtime)
// ->get($this->db ,null);
//if(count($res)>0){
$res = Sql::select('syweb_api_apply.*')
->from('syweb_api_apply,syweb_interface')
->where('syweb_api_apply.interface_id=syweb_interface.id and syweb_api_apply.status=1 and syweb_interface.interface_code =? and dev_id in (select id from syweb_admin where devkey=? and type=2)',$authcode,$devkey)
->get($this->db ,null);
if(count($res)>0){
$result["error"] = '0';
$result["message"] = "用户具备接口权限。";// 用户具备该接口权限
}else{
$result["error"] = '1';
$result["error_code"] = '4';
$result["message"] = "用户不具备接口权限。";// 用户无该接口权限
}
//}else{
// $result[0]["error"] = "1";
// $result[0]["error_code"] = 1; // 用户票据过去或未获得票据
//}
return json_encode($result,JSON_UNESCAPED_UNICODE);
}
/** @inject("ioc_factory") */
private $factory;
/**
* @property({"default":"@db"})
* @var PDO
*/
public $db;
}

View File

@@ -0,0 +1,553 @@
<?php
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, PATCH, DELETE");
header("Access-Control-Allow-Headers: Content-Type, Authorization, Content-Length, X-Requested-With");
header("Access-Control-Allow-Credentials: true");
header("Content-Type: text/html; charset=utf-8");
/**
* 消息发送相关接口
*/
use phprs\util\Verify;
use phprs\util\exceptions\Forbidden;
use phprs\util\Logger;
use phprs\util\exceptions\NotFound;
use phprs\ezsql\Sql;
use phprs\util\exceptions\BadRequest;
require_once 'templateMessageBase.php';
class DataItem
{
var $value;
var $color;
public function __construct($value, $color = '#7B68EE')
{
$this->value = $value;
$this->color = $color;
}
}
/**
*
* 消息管理
* @path("/tplmessage")
*/
class templateMessage extends templateMessageBase
{
/**
* 模板消息发送(错误代码12500-12550)
* @route({"POST","/rawsend"})
* @param({"appid","$._POST.appid"}) 所属公众号
* @param({"devkey","$._POST.devkey"}) 外部应用ID
* @param({"market_key","$._POST.market_key"}) 门店key
* @param({"touser","$._POST.touser"}) 接收人的openid
* @param({"template_id","$._POST.tid"}) 模板编号
* @param({"data","$._POST.data"}) 模板参数
* @param({"url","$._POST.url"}) url
* @return string
*/
public function rawsend($appid, $devkey, $market_key, $touser, $template_id, $data, $url)
{
/// 验证公共参数是否合法
$this->init($appid, $devkey);
$verify_result = $this->verify_admin($market_key);
if (is_error_api($verify_result))
{
if ($verify_result instanceof returnObject)
return $verify_result;
$return = new returnObject();
$return->from_array((array)$verify_result);
return $verify_result;
}
/// 验证其他参数是否合法 begin
if (empty($template_id)) {
$result["error"] = "1";
$result["error_code"] = 12501;
$result["msg"] = "未传入tid参数";
return json_encode($result, JSON_UNESCAPED_UNICODE);
}
// 验证其他参数是否合法 end
if (AUTHTYPE_WECHAT != $this->userInfo["auth_type"]) {
// 非微信登录方式,无法发送模板消息
$result["error"] = "1";
$result["error_code"] = 12502;
$result["msg"] = "非微信登录方式,无法发送模板消息";
return json_encode($result, JSON_UNESCAPED_UNICODE);
}
/// 参数
if (empty($data))
$data = [];
else
$data = (array)json_decode($data);
$wechat = [
'appid' => $this->marketInfo['weixin_appid'], /// 微信公众号APPID
'secret' => $this->marketInfo['weixin_secret_appid'],
'mchid' => $this->marketInfo['weixin_mchid'], /// 微信公众号商户号
'signkey' => $this->marketInfo['weixin_paykey'], /// 支付秘钥
];
/// 初始化微信信息
parent::init_weixin($wechat['appid'], $wechat['secret']);
/// openid
$openid = $touser;
/// 发送模板消息
$sendResult = parent::SendMessage($openid, $template_id, $url, $data);
if (!is_error($sendResult)) {
$result["error"] = "0";
$result["msg"] = "发送模板消息成功。";
return json_encode($result, JSON_UNESCAPED_UNICODE);
} else {
$result["error"] = "1";
$result["error_code"] = 12505; // 发送模板消息失败
$result["msg"] = "发送模板消息失败";
return json_encode($result, JSON_UNESCAPED_UNICODE);
}
}
/**
* 购买订单模板消息发送(错误代码12500-12550)
* @route({"POST","/send"})
* @param({"appid","$._POST.appid"}) 所属公众号
* @param({"devkey","$._POST.devkey"}) 外部应用ID
* @param({"sid","$._POST.sid"}) sid
* @param({"scode","$._POST.scode"}) scode
* @param({"template_id","$._POST.tid"}) 模板编号
* @param({"data","$._POST.data"}) 模板参数
* @param({"url","$._POST.url"}) url
* @return string
*/
public function send($appid, $devkey, $sid, $scode, $template_id, $data, $url)
{
/// 验证公共参数是否合法
parent::init($appid, $devkey, $sid, $scode);
$verify_result = parent::verify();
if (is_error_api($verify_result))
return json_encode($verify_result, JSON_UNESCAPED_UNICODE);
/// 验证其他参数是否合法 begin
if (empty($template_id)) {
$result["error"] = "1";
$result["error_code"] = 12501;
$result["msg"] = "未传入tid参数";
return json_encode($result, JSON_UNESCAPED_UNICODE);
}
// 验证其他参数是否合法 end
if (AUTHTYPE_WECHAT != $this->userInfo["auth_type"]) {
// 非微信登录方式,无法发送模板消息
$result["error"] = "1";
$result["error_code"] = 12502;
$result["msg"] = "非微信登录方式,无法发送模板消息";
return json_encode($result, JSON_UNESCAPED_UNICODE);
}
/// 参数
if (empty($data))
$data = [];
else
$data = (array)json_decode($data);
$wechat = [
'appid' => $this->marketInfo['weixin_appid'], /// 微信公众号APPID
'secret' => $this->marketInfo['weixin_secret_appid'],
'mchid' => $this->marketInfo['weixin_mchid'], /// 微信公众号商户号
'signkey' => $this->marketInfo['weixin_paykey'], /// 支付秘钥
];
/// 初始化微信信息
parent::init_weixin($wechat['appid'], $wechat['secret']);
/// openid
$openid = $this->userInfo['openid'];
/// 发送模板消息
$sendResult = parent::SendMessage($openid, $template_id, $url, $data);
if (!is_error($sendResult)) {
$result["error"] = "0";
$result["msg"] = "发送模板消息成功。";
return json_encode($result, JSON_UNESCAPED_UNICODE);
} else {
$result["error"] = "1";
$result["error_code"] = 12505; // 发送模板消息失败
$result["msg"] = "发送模板消息失败";
return json_encode($result, JSON_UNESCAPED_UNICODE);
}
}
/**
* 购买订单模板消息发送(错误代码12500-12550)
* @route({"POST","/send/buy_succ_msg"})
* @param({"appid","$._POST.appid"}) 所属公众号
* @param({"devkey","$._POST.devkey"}) 外部应用ID
* @param({"sid","$._POST.sid"}) sid
* @param({"scode","$._POST.scode"}) scode
* @param({"first","$._POST.first"}) 头部内容
* @param({"productname","$._POST.productname"}) 产品名称
* @param({"price","$._POST.price"}) 订单价格
* @param({"time","$._POST.time"}) 时间
* @param({"remark","$._POST.remark"}) 购买正文
* @param({"target_url","$._POST.target_url"}) 跳转链接
* @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用
*/
public function sendBuySuccessMsg($appid = '', $devkey = '', $sid = '', $scode = '', $first = '', $productname = '', $price = '', $time = '', $remark = '', $target_url = '')
{
// 验证公共参数是否合法
parent::init($appid, $devkey, $sid, $scode);
$verify_result = parent::verify();
if (!is_error_api($verify_result)) {
// 验证其他参数是否合法 begin
if (empty($first)) {
$result["error"] = "1";
$result["error_code"] = 12500; // 未传入first参数
$result["msg"] = "未传入first参数";
return json_encode($result, JSON_UNESCAPED_UNICODE);
}
if (empty($productname)) {
$result["error"] = "1";
$result["error_code"] = 12501; // 未传入productname参数
$result["msg"] = "未传入productname参数";
return json_encode($result, JSON_UNESCAPED_UNICODE);
}
if (empty($price)) {
$result["error"] = "1";
$result["error_code"] = 12502; // 未传入price参数
$result["msg"] = "未传入price参数";
return json_encode($result, JSON_UNESCAPED_UNICODE);
}
if (empty($remark)) {
$result["error"] = "1";
$result["error_code"] = 12503; // 未传入remark参数
$result["msg"] = "未传入remark参数";
return json_encode($result, JSON_UNESCAPED_UNICODE);
}
// 验证其他参数是否合法 end
// 假如没有传入时间,则使用系统默认时间
if (empty($time)) {
$time = date('Y-m-d H:i', strtotime('now'));
}
if ($this->userInfo["auth_type"] == 0) {
$data = array(
'first' => new DataItem($first, '#ff0000'),
'product' => new DataItem($productname, '#ff0000'),
'price' => new DataItem($price, '#ff0000'),
'time' => new DataItem($time, '#ff0000'),
'remark' => new DataItem($remark, '#ff0000'),
);
// 初始化微信信息
parent::init_weixin($this->businessInfo['weixin_appid'], $this->businessInfo['weixin_secret_appid']);
// 发送模板消息
$openid = $this->userInfo["weixin"]['openid'];
$template_id = $this->businessInfo['templatemsg']['msg_buy_succ'];
$sendResult = parent::do_send($openid, $template_id, $data, $target_url);
if (!is_error($sendResult)) {
$result["error"] = "0";
$result["msg"] = "发送模板消息成功。";
return json_encode($result, JSON_UNESCAPED_UNICODE);
} else {
$result["error"] = "1";
$result["error_code"] = 12505; // 发送模板消息失败
$result["msg"] = "发送模板消息失败";
return json_encode($result, JSON_UNESCAPED_UNICODE);
}
} else {
// 非微信登录方式,无法发送模板消息
$result["error"] = "1";
$result["error_code"] = 12504;
$result["msg"] = "非微信登录方式,无法发送模板消息";
return json_encode($result, JSON_UNESCAPED_UNICODE);
}
} else {
return json_encode($verify_result, JSON_UNESCAPED_UNICODE);
}
}
/**
* 配送处理模板消息发送(错误代码12551-12600)
* @route({"POST","/send/dispatch_process_msg"})
* @param({"appid","$._POST.appid"}) 所属公众号
* @param({"devkey","$._POST.devkey"}) 外部应用ID
* @param({"sid","$._POST.sid"}) sid
* @param({"scode","$._POST.scode"}) scode
* @param({"first","$._POST.first"}) 头部内容
* @param({"time","$._POST.time"}) 时间
* @param({"ordersn","$._POST.ordersn"}) 订单号
* @param({"remark","$._POST.remark"}) 正文
* @param({"target_url","$._POST.target_url"}) 跳转链接
* @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用
*/
public function sendDispatchProcessMsg($appid = '', $devkey = '', $sid = '', $scode = '', $first = '', $time = '', $ordersn = '', $remark = '', $target_url = '')
{
// 验证公共参数是否合法
parent::init($appid, $devkey, $sid, $scode);
$verify_result = parent::verify();
if (!is_error_api($verify_result)) {
// 验证其他参数是否合法 begin
if (empty($first)) {
$result["error"] = "1";
$result["error_code"] = 12551; // 未传入first参数
$result["msg"] = "未传入first参数";
return json_encode($result, JSON_UNESCAPED_UNICODE);
}
if (empty($ordersn)) {
$result["error"] = "1";
$result["error_code"] = 12552; // 未传入ordersn参数
$result["msg"] = "未传入ordersn参数";
return json_encode($result, JSON_UNESCAPED_UNICODE);
}
if (empty($remark)) {
$result["error"] = "1";
$result["error_code"] = 12553; // 未传入remark参数
$result["msg"] = "未传入remark参数";
return json_encode($result, JSON_UNESCAPED_UNICODE);
}
// 验证其他参数是否合法 end
// 假如没有传入时间,则使用系统默认时间
if (empty($time)) {
$time = date('Y-m-d H:i', strtotime('now'));
}
if ($this->userInfo["auth_type"] == 0) {
$data = array(
'first' => new DataItem($first, '#ff0000'),
'keyword1' => new DataItem($time, '#ff0000'),
'keyword2' => new DataItem($ordersn, '#ff0000'),
'remark' => new DataItem($remark, '#ff0000'),
);
// 初始化微信信息
parent::init_weixin($this->businessInfo['weixin_appid'], $this->businessInfo['weixin_secret_appid']);
// 发送模板消息
$openid = $this->userInfo["weixin"]['openid'];
$template_id = $this->businessInfo['templatemsg']['msg_dispatch_process'];
$sendResult = parent::do_send($openid, $template_id, $data, $target_url);
if (!is_error($sendResult)) {
$result["error"] = "0";
$result["msg"] = "发送模板消息成功。";
return json_encode($result, JSON_UNESCAPED_UNICODE);
} else {
$result["error"] = "1";
$result["error_code"] = 12555; // 发送模板消息失败
$result["msg"] = "发送模板消息失败";
return json_encode($result, JSON_UNESCAPED_UNICODE);
}
} else {
// 非微信登录方式,无法发送模板消息
$result["error"] = "1";
$result["error_code"] = 12554;
$result["msg"] = "非微信登录方式,无法发送模板消息 ";
return json_encode($result, JSON_UNESCAPED_UNICODE);
}
} else {
return json_encode($verify_result, JSON_UNESCAPED_UNICODE);
}
}
/**
* 购买订单模板消息发送(错误代码12500-12550)
* @route({"POST","/send/admin/buy_succ_msg"})
* @param({"appid","$._POST.appid"}) 所属公众号
* @param({"devkey","$._POST.devkey"}) 外部应用ID
* @param({"businessid","$._POST.businessid"}) 商户ID
* @param({"openid","$._POST.openid"}) 微信openId
* @param({"first","$._POST.first"}) 头部内容
* @param({"productname","$._POST.productname"}) 产品名称
* @param({"price","$._POST.price"}) 订单价格
* @param({"time","$._POST.time"}) 时间
* @param({"remark","$._POST.remark"}) 购买正文
* @param({"target_url","$._POST.target_url"}) 跳转链接
* @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用
*/
public function sendBuySuccessMsgByAdmin($appid = '', $devkey = '', $businessid = '', $openid = '', $first = '', $productname = '', $price = '', $time = '', $remark = '', $target_url = '')
{
// 验证公共参数是否合法
parent::init($appid, $devkey, '', '');
$verify_result = parent::verify_admin($businessid);
if (!is_error_api($verify_result)) {
// 验证其他参数是否合法 begin
if (empty($first)) {
$result["error"] = "1";
$result["error_code"] = 12500; // 未传入first参数
$result["msg"] = "未传入first参数";
return json_encode($result, JSON_UNESCAPED_UNICODE);
}
if (empty($productname)) {
$result["error"] = "1";
$result["error_code"] = 12501; // 未传入productname参数
$result["msg"] = "未传入productname参数";
return json_encode($result, JSON_UNESCAPED_UNICODE);
}
if (empty($price)) {
$result["error"] = "1";
$result["error_code"] = 12502; // 未传入price参数
$result["msg"] = "未传入price参数";
return json_encode($result, JSON_UNESCAPED_UNICODE);
}
if (empty($remark)) {
$result["error"] = "1";
$result["error_code"] = 12503; // 未传入remark参数
$result["msg"] = "未传入remark参数";
return json_encode($result, JSON_UNESCAPED_UNICODE);
}
if (empty($openid)) {
$result["error"] = "1";
$result["error_code"] = 12506; // 未传入openid参数
$result["msg"] = "未传入openid参数";
return json_encode($result, JSON_UNESCAPED_UNICODE);
}
// 验证其他参数是否合法 end
// 假如没有传入时间,则使用系统默认时间
if (empty($time)) {
$time = date('Y-m-d H:i', strtotime('now'));
}
if ($this->userInfo["auth_type"] == 0) {
$data = array(
'first' => new DataItem($first, '#ff0000'),
'product' => new DataItem($productname, '#ff0000'),
'price' => new DataItem($price, '#ff0000'),
'time' => new DataItem($time, '#ff0000'),
'remark' => new DataItem($remark, '#ff0000'),
);
// 初始化微信信息
parent::init_weixin($this->businessInfo['weixin_appid'], $this->businessInfo['weixin_secret_appid']);
// 发送模板消息
$template_id = $this->businessInfo['templatemsg']['msg_buy_succ'];
$sendResult = parent::do_send($openid, $template_id, $data, $target_url);
if (!is_error($sendResult)) {
$result["error"] = "0";
$result["msg"] = "发送模板消息成功。";
return json_encode($result, JSON_UNESCAPED_UNICODE);
} else {
$result["error"] = "1";
$result["error_code"] = 12505; // 发送模板消息失败
$result["msg"] = "发送模板消息失败";
return json_encode($result, JSON_UNESCAPED_UNICODE);
}
} else {
// 非微信登录方式,无法发送模板消息
$result["error"] = "1";
$result["error_code"] = 12504;
$result["msg"] = "非微信登录方式,无法发送模板消息";
return json_encode($result, JSON_UNESCAPED_UNICODE);
}
} else {
return json_encode($verify_result, JSON_UNESCAPED_UNICODE);
}
}
/**
* 配送处理模板消息发送(错误代码12551-12600)
* @route({"POST","/send/admin/dispatch_process_msg"})
* @param({"appid","$._POST.appid"}) 所属公众号
* @param({"devkey","$._POST.devkey"}) 外部应用ID
* @param({"businessid","$._POST.businessid"}) 商户ID
* @param({"openid","$._POST.openid"}) 微信openId
* @param({"first","$._POST.first"}) 头部内容
* @param({"time","$._POST.time"}) 时间
* @param({"ordersn","$._POST.ordersn"}) 订单号
* @param({"remark","$._POST.remark"}) 正文
* @param({"target_url","$._POST.target_url"}) 跳转链接
* @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用
*/
public function sendDispatchProcessMsgByAdmin($appid = '', $devkey = '', $businessid = '', $openid = '', $first = '', $time = '', $ordersn = '', $remark = '', $target_url = '')
{
// 验证公共参数是否合法
parent::init($appid, $devkey, '', '');
$verify_result = parent::verify_admin($openid);
if (!is_error_api($verify_result)) {
// 验证其他参数是否合法 begin
if (empty($first)) {
$result["error"] = "1";
$result["error_code"] = 12551; // 未传入first参数
$result["msg"] = "未传入first参数";
return json_encode($result, JSON_UNESCAPED_UNICODE);
}
if (empty($ordersn)) {
$result["error"] = "1";
$result["error_code"] = 12552; // 未传入ordersn参数
$result["msg"] = "未传入ordersn参数";
return json_encode($result, JSON_UNESCAPED_UNICODE);
}
if (empty($remark)) {
$result["error"] = "1";
$result["error_code"] = 12553; // 未传入remark参数
$result["msg"] = "未传入remark参数";
return json_encode($result, JSON_UNESCAPED_UNICODE);
}
if (empty($openid)) {
$result["error"] = "1";
$result["error_code"] = 12556; // 未传入openid参数
$result["msg"] = "未传入openid参数";
return json_encode($result, JSON_UNESCAPED_UNICODE);
}
// 验证其他参数是否合法 end
// 假如没有传入时间,则使用系统默认时间
if (empty($time)) {
$time = date('Y-m-d H:i', strtotime('now'));
}
if ($this->userInfo["auth_type"] == 0) {
$data = array(
'first' => new DataItem($first, '#ff0000'),
'keyword1' => new DataItem($time, '#ff0000'),
'keyword2' => new DataItem($ordersn, '#ff0000'),
'remark' => new DataItem($remark, '#ff0000'),
);
// 初始化微信信息
parent::init_weixin($this->businessInfo['weixin_appid'], $this->businessInfo['weixin_secret_appid']);
// 发送模板消息
$template_id = $this->businessInfo['templatemsg']['msg_dispatch_process'];
$sendResult = parent::do_send($openid, $template_id, $data, $target_url);
if (!is_error($sendResult)) {
$result["error"] = "0";
$result["msg"] = "发送模板消息成功。";
return json_encode($result, JSON_UNESCAPED_UNICODE);
} else {
$result["error"] = "1";
$result["error_code"] = 12555; // 发送模板消息失败
$result["msg"] = "发送模板消息失败";
return json_encode($result, JSON_UNESCAPED_UNICODE);
}
} else {
// 非微信登录方式,无法发送模板消息
$result["error"] = "1";
$result["error_code"] = 12554;
$result["msg"] = "非微信登录方式,无法发送模板消息 ";
return json_encode($result, JSON_UNESCAPED_UNICODE);
}
} else {
return json_encode($verify_result, JSON_UNESCAPED_UNICODE);
}
}
/** @inject("ioc_factory") */
private $factory;
/**
* @property({"default":"@db"})
* @var PDO
*/
public $db;
// 此处删除了代码
}

View File

@@ -0,0 +1,58 @@
<?php
use phprs\util\Verify;
use phprs\util\exceptions\Forbidden;
use phprs\util\Logger;
use phprs\util\exceptions\NotFound;
use phprs\ezsql\Sql;
use phprs\util\exceptions\BadRequest;
require_once 'apiBase.php';
/**
*
* 基类
* @path("/templateMessageBase")
*/
class templateMessageBase extends apiBase{
protected $weixin_appid; // 微信APPID
protected $weixin_secret_appid; // 微信secret_appid
/** @var WeiXinAccount */
protected $weixinHandler; // 微信接口操作对象
public function __construct() {
}
public function init_weixin($weixin_appid,$weixin_secret_appid) {
$account = array();
$account["key"] = $weixin_appid;
$account["secret"] = $weixin_secret_appid;
$this->weixinHandler = new WeiXinAccount($account);
}
/**
* 发送自定义的模板消息
* @param string $touser 发送给谁(微信openId)
* @param string $template_id 模板的id(通过微信后台或接口, 增加的模板产生的唯一id)
* @param array $data 消息体数据
* @param string $url 跳转地址
* @param string $topcolor 颜色
* @return array|bool true if the method call succeeded, false otherwise.
*/
public function do_send($touser, $template_id, $data, $url='',$topcolor = '#7B68EE') {
$pdo = $this->db;
return $this->weixinHandler->sendTplNotice($this->db,$pdo,$touser,$template_id,$data,$url,$topcolor);
}
public function SendMessage($to_user, $template_id, $target_url, $parameter, $color = '#7b68ee') {
$pdo = $this->db;
return $this->weixinHandler->SendTemplateMessage($to_user, $template_id, $target_url, $parameter, $color, $this->db, $pdo);
}
/** @inject("ioc_factory") */
private $factory;
/**
* @property({"default":"@db"})
* @var PDO
*/
public $db;
}

View File

@@ -0,0 +1,59 @@
<?php
header('Access-Control-Allow-Origin:*');// 指定允许其他域名访问
header('Access-Control-Allow-Methods:POST');// 响应类型
header('Access-Control-Allow-Headers:x-requested-with,content-type');
use phprs\util\Verify;
use phprs\util\exceptions\Forbidden;
use phprs\util\Logger;
use phprs\util\exceptions\NotFound;
use phprs\ezsql\Sql;
use phprs\util\exceptions\BadRequest;
/**
*
* 测试接口
* @path("/test")
*/
class Test extends apiBase{
/**
* 支付回调
* @route({"POST","/pay_notify"})
* @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用
*/
public function payNotify() {
$input = file_get_contents('php://input');
if ( !empty($input) ){
$data = json_decode($input,true);
$testLogDir = dirname(dirname(__DIR__)) . '/logs';
if (!is_dir($testLogDir)) mkdir($testLogDir, 0777, true);
file_put_contents($testLogDir . '/pay_test2.txt', count($data));
file_put_contents($testLogDir . '/pay_test.txt', "接收到的参数为:".$data['orderNo']."===".$data['signkey']);
$result = array();
// 处理业务逻辑 begin
// 比如修改订单状态
// 处理业务逻辑 end
// 返回0表示已经完成了逻辑的处理
// 如果不返回0则系统会重新发起请求连续8次
$result["error"] = 0;
echo json_encode($result);
} else {
$testLogDir = dirname(dirname(__DIR__)) . '/logs';
if (!is_dir($testLogDir)) mkdir($testLogDir, 0777, true);
file_put_contents($testLogDir . '/pay_test1.txt', "接收到的内容为空");
$result["1"] = 0;
echo json_encode($result);
}
}
/** @inject("ioc_factory") */
private $factory;
/**
* @property({"default":"@db"})
* @var PDO
*/
public $db;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,417 @@
<?php
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, PATCH, DELETE");
header("Access-Control-Allow-Headers: Content-Type, Authorization, Content-Length, X-Requested-With");
header("Access-Control-Allow-Credentials: true");
header("Content-Type: text/html; charset=utf-8");
/**
* 获取用户信息接口
*/
use phprs\util\Verify;
use phprs\util\exceptions\Forbidden;
use phprs\util\Logger;
use phprs\util\exceptions\NotFound;
use phprs\ezsql\Sql;
use phprs\util\exceptions\BadRequest;
require_once 'apiBase.php';
/**
*
* 获取用户信息接口
* @path("/user")
*/
class User extends apiBase
{
/**
* 通过scode和sid获取用户信息
* @route({"GET","/"})
* @param({"appid","$._GET.appid"}) 应用appid
* @param({"devkey","$._GET.devkey"}) 开发者key
* @param({"market_key","$._GET.market_key"}) 商家Key
* @param({"sid","$._GET.sid"}) 服务器返回的sid
* @param({"scode","$._GET.scode"}) 客户端生成的Scode
* @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用
*/
public function getUserBySid($appid = "", $devkey = "", $market_key = "", $sid = "", $scode = "")
{
// 验证公共参数是否合法
parent::init($appid, $devkey, $sid, $scode, $market_key);
$verify_result = parent::verify();
if (!is_error_api($verify_result))
{
if (!empty($market_key))
{
if ($this->marketInfo["market_key"] != $market_key)
{
$result["error"] = "1";
$result["error_code"] = 10011;
$result["msg"] = "指定的SID和market_key不符.";
return $result;
}
}
switch ($this->userInfo["auth_type"])
{
case AUTHTYPE_WECHAT:
{
$userInfoBase = [
'openid' => $this->userInfo['weixin']['openid'],
'unionid' => $this->userInfo['weixin']['unionid'],
'country' => $this->userInfo['weixin']['country'],
'province' => $this->userInfo['weixin']['province'],
'city' => $this->userInfo['weixin']['city'],
'headImage' => $this->userInfo['weixin']['headimgurl'],
'nickName' => $this->userInfo['weixin']['nickname'],
'subscribe' => $this->userInfo['weixin']['subscribe'],
'subscribe_time' => $this->userInfo['weixin']['subscribe_time'],
'jifen' => $this->userInfo['jifen_account'],
];
$result["usertype"] = $this->userInfo["auth_type"];
$result["error"] = "0";
$result["data"] = $userInfoBase;
$result["dataContent"] = $this->userInfo["weixin"];
return $result;
}
case AUTHTYPE_QQ:
{
$userInfoBase = array();
$userInfoBase["headImage"] = $this->userInfo["qq"]["figureurl_qq_2"];
$userInfoBase["nickName"] = $this->userInfo["qq"]["nickname"];
$userInfoBase["jifen"] = $this->userInfo["jifen_account"];
$result["usertype"] = $this->userInfo["auth_type"];
$result["error"] = "0";
$result["data"] = $userInfoBase;
$result["dataContent"] = $this->userInfo["qq"];
return $result;
}
case AUTHTYPE_JKX:
{
$userInfoBase = array();
$userInfoBase["headImage"] = $this->userInfo["jkx"]["headimgurl"];
$userInfoBase["nickName"] = $this->userInfo["jkx"]["realname"];
$userInfoBase["jifen"] = $this->userInfo["jifen_account"];
$result["usertype"] = $this->userInfo["auth_type"];
$result["error"] = "0";
$result["data"] = $userInfoBase;
$result["dataContent"] = $this->userInfo["jkx"];
return $result;
}
//case AUTHTYPE_MEMBER:
//case AUTHTYPE_NIUNIUGAME:
default:
{
$result["usertype"] = $this->userInfo["auth_type"];
$result["error"] = "0";
return $result;
}
}
}
else
{
return $verify_result;
}
}
/**
* 通过scode和sid获取用户信息
* @route({"POST","/"})
* @param({"appid","$._POST.appid"}) 应用appid
* @param({"devkey","$._POST.devkey"}) 开发者key
* @param({"market_key","$._POST.market_key"}) 门店Key
* @param({"sid","$._POST.sid"}) 服务器返回的sid
* @param({"scode","$._POST.scode"}) 客户端生成的Scode
* @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用
*/
public function getUserByPostSid($appid = "", $devkey = "", $market_key = "", $sid = "", $scode = "")
{
// 验证公共参数是否合法
parent::init($appid, $devkey, $sid, $scode, $market_key);
$verify_result = parent::verify();
if (!is_error_api($verify_result))
{
if (!empty($market_key))
{
if ($this->marketInfo["market_key"] != $market_key)
{
$result["error"] = "1";
$result["error_code"] = 10011;
$result["msg"] = "指定的SID和market_key不符.";
return $result;
}
}
switch ($this->userInfo["auth_type"])
{
case AUTHTYPE_WECHAT:
{
$userInfoBase = [
'openid' => $this->userInfo['weixin']['openid'],
'unionid' => $this->userInfo['weixin']['unionid'],
'country' => $this->userInfo['weixin']['country'],
'province' => $this->userInfo['weixin']['province'],
'city' => $this->userInfo['weixin']['city'],
'headImage' => $this->userInfo['weixin']['headimgurl'],
'nickName' => $this->userInfo['weixin']['nickname'],
'subscribe' => $this->userInfo['weixin']['subscribe'],
'subscribe_time' => $this->userInfo['weixin']['subscribe_time'],
'jifen' => $this->userInfo['jifen_account'],
];
$result["usertype"] = $this->userInfo["auth_type"];
$result["error"] = "0";
$result["data"] = $userInfoBase;
$result["dataContent"] = $this->userInfo["weixin"];
return $result;
}
case AUTHTYPE_QQ:
{
$userInfoBase = array();
$userInfoBase["headImage"] = $this->userInfo["qq"]["figureurl_qq_2"];
$userInfoBase["nickName"] = $this->userInfo["qq"]["nickname"];
$userInfoBase["jifen"] = $this->userInfo["jifen_account"];
$result["usertype"] = $this->userInfo["auth_type"];
$result["error"] = "0";
$result["data"] = $userInfoBase;
$result["dataContent"] = $this->userInfo["qq"];
return $result;
}
case AUTHTYPE_JKX:
{
$userInfoBase = array();
$userInfoBase["headImage"] = $this->userInfo["jkx"]["headimgurl"];
$userInfoBase["nickName"] = $this->userInfo["jkx"]["realname"];
$userInfoBase["jifen"] = $this->userInfo["jifen_account"];
$result["usertype"] = $this->userInfo["auth_type"];
$result["error"] = "0";
$result["data"] = $userInfoBase;
$result["dataContent"] = $this->userInfo["jkx"];
return $result;
}
//case AUTHTYPE_MEMBER:
//case AUTHTYPE_NIUNIUGAME:
default:
{
$result["usertype"] = $this->userInfo["auth_type"];
$result["error"] = "0";
return $result;
}
}
}
else
{
return $verify_result;
}
}
/**
* 直接绑定子账户到主账户
* @route({"POST","/bind"})
* @param({"devkey","$._POST.devkey"}) 开发者key
* @param({"market_key","$._POST.market_key"}) 门店Key
* @param({"sid","$._POST.sid"}) 服务器返回的sid
* @param({"scode","$._POST.scode"}) 客户端生成的Scode
* @param({"mobile_phone","$._POST.mobile_phone"}) 手机号码
* @param({"email","$._POST.email"}) 邮箱
* @param({"sign","$._POST.sign"}) 签名值
* @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用
*/
public function bindMainAccount($devkey = "", $market_key = "", $sid = "", $scode = "", $mobile_phone = "", $email = "", $sign = "")
{
// 验证公共参数是否合法
parent::init($appid, $devkey, $sid, $scode);
$verify_result = parent::verify();
if (!is_error_api($verify_result))
{
if ($this->userInfo["auth_type"] == 0)
{
$userInfoBase = array();
$userInfoBase["headImage"] = $this->userInfo["weixin"]["headimgurl"];
$userInfoBase["nickName"] = $this->userInfo["weixin"]["nickname"];
$userInfoBase["jifen"] = $this->userInfo["jifen_account"];
$result["usertype"] = "0";
$result["error"] = "0";
$result["data"] = $userInfoBase;
$result["dataContent"] = $this->userInfo["weixin"];
return $result;
}
else
{
$userInfoBase = array();
$userInfoBase["headImage"] = $this->userInfo["qq"]["figureurl_qq_2"];
$userInfoBase["nickName"] = $this->userInfo["qq"]["nickname"];
$userInfoBase["jifen"] = $this->userInfo["jifen_account"];
$result["usertype"] = "1";
$result["error"] = "0";
$result["data"] = $userInfoBase;
$result["dataContent"] = $this->userInfo["qq"];
return $result;
}
}
else
{
return $verify_result;
}
}
/**
* 判断用户是否已经绑定为主账户
* @route({"POST","/bind/check"})
* @param({"devkey","$._POST.devkey"}) 开发者key
* @param({"market_key","$._POST.market_key"}) 门店Key
* @param({"sid","$._POST.sid"}) 服务器返回的sid
* @param({"scode","$._POST.scode"}) 客户端生成的Scode
* @param({"sign","$._POST.sign"}) 签名值
* @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用
*/
public function isBindMainAccount($devkey = "", $market_key = "", $sid = "", $scode = "", $sign = "")
{
// 验证公共参数是否合法
parent::init($appid, $devkey, $sid, $scode);
$verify_result = parent::verify();
if (!is_error_api($verify_result))
{
if ($this->userInfo["auth_type"] == 0)
{
$userInfoBase = array();
$userInfoBase["headImage"] = $this->userInfo["weixin"]["headimgurl"];
$userInfoBase["nickName"] = $this->userInfo["weixin"]["nickname"];
$userInfoBase["jifen"] = $this->userInfo["jifen_account"];
$result["usertype"] = "0";
$result["error"] = "0";
$result["data"] = $userInfoBase;
$result["dataContent"] = $this->userInfo["weixin"];
return $result;
}
else
{
$userInfoBase = array();
$userInfoBase["headImage"] = $this->userInfo["qq"]["figureurl_qq_2"];
$userInfoBase["nickName"] = $this->userInfo["qq"]["nickname"];
$userInfoBase["jifen"] = $this->userInfo["jifen_account"];
$result["usertype"] = "1";
$result["error"] = "0";
$result["data"] = $userInfoBase;
$result["dataContent"] = $this->userInfo["qq"];
return $result;
}
}
else
{
return $verify_result;
}
}
/**
* 将子账户从主账户中解绑
* @route({"POST","/unbind"})
* @param({"devkey","$._POST.devkey"}) 开发者key
* @param({"market_key","$._POST.market_key"}) 门店Key
* @param({"sid","$._POST.sid"}) 服务器返回的sid
* @param({"scode","$._POST.scode"}) 客户端生成的Scode
* @param({"sign","$._POST.sign"}) 签名值
* @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用
*/
public function unbindFromMainAccount($devkey = "", $market_key = "", $sid = "", $scode = "", $sign = "")
{
// 验证公共参数是否合法
parent::init($appid, $devkey, $sid, $scode);
$verify_result = parent::verify();
if (!is_error_api($verify_result))
{
if ($this->userInfo["auth_type"] == 0)
{
$userInfoBase = array();
$userInfoBase["headImage"] = $this->userInfo["weixin"]["headimgurl"];
$userInfoBase["nickName"] = $this->userInfo["weixin"]["nickname"];
$userInfoBase["jifen"] = $this->userInfo["jifen_account"];
$result["usertype"] = "0";
$result["error"] = "0";
$result["data"] = $userInfoBase;
$result["dataContent"] = $this->userInfo["weixin"];
return $result;
}
else
{
$userInfoBase = array();
$userInfoBase["headImage"] = $this->userInfo["qq"]["figureurl_qq_2"];
$userInfoBase["nickName"] = $this->userInfo["qq"]["nickname"];
$userInfoBase["jifen"] = $this->userInfo["jifen_account"];
$result["usertype"] = "1";
$result["error"] = "0";
$result["data"] = $userInfoBase;
$result["dataContent"] = $this->userInfo["qq"];
return $result;
}
}
else
{
return $verify_result;
}
}
/**
* 获取子账户的其他门店的账户信息,需要关联主账户
* @route({"POST","/other"})
* @param({"devkey","$._POST.devkey"}) 开发者key
* @param({"market_key","$._POST.market_key"}) 门店Key
* @param({"sid","$._POST.sid"}) 服务器返回的sid
* @param({"scode","$._POST.scode"}) 客户端生成的Scode
* @param({"sign","$._POST.sign"}) 签名值
* @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用
*/
public function getOtherMarket($devkey = "", $market_key = "", $sid = "", $scode = "", $sign = "")
{
// 验证公共参数是否合法
parent::init($appid, $devkey, $sid, $scode);
$verify_result = parent::verify();
if (!is_error_api($verify_result))
{
if ($this->userInfo["auth_type"] == 0)
{
$userInfoBase = array();
$userInfoBase["headImage"] = $this->userInfo["weixin"]["headimgurl"];
$userInfoBase["nickName"] = $this->userInfo["weixin"]["nickname"];
$userInfoBase["jifen"] = $this->userInfo["jifen_account"];
$result["usertype"] = "0";
$result["error"] = "0";
$result["data"] = $userInfoBase;
$result["dataContent"] = $this->userInfo["weixin"];
return $result;
}
else
{
$userInfoBase = array();
$userInfoBase["headImage"] = $this->userInfo["qq"]["figureurl_qq_2"];
$userInfoBase["nickName"] = $this->userInfo["qq"]["nickname"];
$userInfoBase["jifen"] = $this->userInfo["jifen_account"];
$result["usertype"] = "1";
$result["error"] = "0";
$result["data"] = $userInfoBase;
$result["dataContent"] = $this->userInfo["qq"];
return $result;
}
}
else
{
return $verify_result;
}
}
/** @inject("ioc_factory") */
private $factory;
/**
* @property({"default":"@db"})
* @var PDO
*/
public $db;
// 此处删除了代码
}

View File

@@ -0,0 +1,69 @@
<?php
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, PATCH, DELETE");
header("Access-Control-Allow-Headers: Content-Type, Authorization, Content-Length, X-Requested-With");
header("Access-Control-Allow-Credentials: true");
header("Content-Type: text/html; charset=utf-8");
use phprs\util\Verify;
use phprs\util\exceptions\Forbidden;
use phprs\util\Logger;
use phprs\util\exceptions\NotFound;
use phprs\ezsql\Sql;
use phprs\util\exceptions\BadRequest;
require_once 'apiBase.php';
/**
*
* 微信相关接口
* @path("/weixin")
*/
class weixinTools extends apiBase
{
/**
* 获得微信分享参数信息(错误代码12701-12750)
* @route({"POST","/wx_share_info"})
* @param({"appid","$._POST.appid"}) 所属公众号
* @param({"devkey","$._POST.devkey"}) 外部应用ID
* @param({"sid","$._POST.sid"}) 临时会员ID
* @param({"scode","$._POST.scode"}) 客户端票据
* @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用
*/
public function getWeixinShareInfo($appid = '', $devkey = '', $sid = '', $scode = '')
{
// 验证公共参数是否合法
parent::init($appid, $devkey, $sid, $scode);
$verify_result = parent::verify();
if (!is_error_api($verify_result))
{
$refererUrl = $_SERVER['HTTP_REFERER'];
if ($this->userInfo["auth_type"] == AUTHTYPE_WECHAT)
{
$account = array('key' => $this->marketInfo['weixin_appid']);
$weixin = new WeiXinAccount($account);
$share_config = $weixin->getAjaxJssdkConfig($refererUrl, $this->db, $this->db);
if (!is_error($share_config) && !empty($share_config))
return new returnObject(0, 0, '', $share_config);
else
return new returnObject(1, 12702, '获取微信分享参数失败。');
}
else
return new returnObject(1, 12701, '只有微信登录状态下能进行分享。');
}
else
return $verify_result;
}
/** @inject("ioc_factory") */
private $factory;
/**
* @property({"default":"@db"})
* @var PDO
*/
public $db;
// 此处删除了代码
}

View File

@@ -0,0 +1,368 @@
<?php
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, PATCH, DELETE");
header("Access-Control-Allow-Headers: Content-Type, Authorization, Content-Length, X-Requested-With");
header("Access-Control-Allow-Credentials: true");
header("Content-Type: text/html; charset=utf-8");
/**
* 地区管理接口
*/
use phprs\util\Verify;
use phprs\util\exceptions\Forbidden;
use phprs\util\Logger;
use phprs\util\exceptions\NotFound;
use phprs\ezsql\Sql;
use phprs\util\exceptions\BadRequest;
require_once 'apiBase.php';
/**
*
* 地区管理
* @path("/wcaddress")
*/
class WholeCountryAddress extends apiBase{
/**
* 根据上级地区Code查询下级地区列表
* @route({"POST","/"})
* @param({"appid","$._POST.appid"}) 应用appid
* @param({"devkey","$._POST.devkey"}) 开发者key
* @param({"parentcode","$._POST.parentcode"}) 地区指定代码parentcode
* @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用
* @return("body")
*/
public function getAddressListByParentCode($appid = "",$devkey="",$parentcode="{=NULL=}"){
$result = array();
if( empty($appid) ){
$result["error"] = '1';
$result["error_code"] = 10001; // 请传入APPID参数
return json_encode($result,JSON_UNESCAPED_UNICODE);
}
$appInfo = Sql::select('syweb_app.*')
->from('syweb_app')
->where('syweb_app.appid=?', $appid)
->get($this->db ,null);
if( empty($appInfo) || count($appInfo)<=0 ){
$result["error"] = '1';
$result["error_code"] = 10002; // 指定的应用不存在
return json_encode($result,JSON_UNESCAPED_UNICODE);
}
if( empty($devkey) ){
$result["error"] = '1';
$result["error_code"] = 10003; // 请传入DevKey参数
return json_encode($result,JSON_UNESCAPED_UNICODE);
}
if ( $parentcode=='{=NULL=}' ) {
$result[0]["error"] = "1";
$result[0]["error_code"] = 10006; // 请传入地区父ID
return json_encode($result,JSON_UNESCAPED_UNICODE);
}
$res = Sql::select('a.*')
->from('syweb_whole_country_address a')
->where('a.address_parent_code=?', $parentcode)
->get($this->db ,null);
if( !empty($res) && count($res)>0 ){
$result[0]["error"] = "0";
$result[0]["data"] = $res;
return json_encode($result,JSON_UNESCAPED_UNICODE);
}else{
$result[0]["error"] = "0";
$result[0]["data"] = array();
return json_encode($result,JSON_UNESCAPED_UNICODE);
}
}
/**
* 根据数据存储会员收货地址(错误代码12701-12750)
* @route({"POST","/save"})
* @param({"appid","$._POST.appid"}) 应用appid
* @param({"devkey","$._POST.devkey"}) 开发者key
* @param({"sid","$._POST.sid"}) 服务器返回的sid
* @param({"scode","$._POST.scode"}) 客户端生成的Scode
* @param({"id","$._POST.id"}) 收货地址系统编号
* @param({"province_code","$._POST.province_code"}) 省份地区编号
* @param({"city_code","$._POST.city_code"}) 城市编号
* @param({"country_code","$._POST.country_code"}) 县区编号
* @param({"street_code","$._POST.street_code"}) 街道编号
* @param({"address_detail","$._POST.address_detail"}) 详细地址
* @param({"realname","$._POST.realname"}) 收货人真实姓名
* @param({"tel","$._POST.tel"}) 收货人电话
* @param({"lng","$._POST.lng"}) 客户收货地址所在经度
* @param({"lat","$._POST.lat"}) 客户收货地址所在纬度
* @param({"isdefault","$._POST.isdefault"}) 是否设置为默认收货地址
* @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用
* @return("body")
*/
public function postUserAddress($appid='',$devkey='',$sid="",$scode="",$id="",$province_code="",$city_code="",$country_code="",$street_code="",$address_detail='',$realname='',$tel='',$lng='',$lat='',$isdefault=''){
// 验证公共参数是否合法
parent::init($appid,$devkey,$sid,$scode);
$verify_result = parent::verify();
if( !is_error_api($verify_result) ){
if ( !empty($isdefault) && $isdefault=="1" ) {
$isdefault = 1;
}else{
$isdefault = 0;
}
if( !empty($id) && is_numeric($id) ){
$updateSql = Sql::update('syweb_users_address');
$updateSql->set("province_code",$province_code);// 省份地区Code
$updateSql->set("city_code",$city_code);// 城市地区Code
$updateSql->set("country_code",$country_code);// 县区Code
$updateSql->set("street_code",$street_code);// 街道Code
$updateSql->set("address_detail",$address_detail);// 详细地址
$updateSql->set("realname",$realname);// 收货人姓名
$updateSql->set("tel",$tel);// 收货人联系电话
$updateSql->set("lng",$lng);// 经度
$updateSql->set("lat",$lat);// 纬度
$updateSql->where(" `id` = ".$id);
$pdo = $this->db;
$pdo->beginTransaction();
$updateCount = $updateSql->exec($pdo);
if( $isdefault==1 ){
// 修改会员默认收货地址 begin
$setDefaultAddressSql = Sql::update('syweb_users');
$setDefaultAddressSql->set("address_id",$id);
$setDefaultAddressSql->where(" `id` = ".$this->userInfo['id']);
$setDefaultAddressSql->exec($pdo);
// 修改会员默认收货地址 end
}
$pdo->commit();
$result["error"] = '0';
$result["message"] = '收货地址修改成功。';
return json_encode($result,JSON_UNESCAPED_UNICODE);
} else {
$insertData = array();
$insertData['uid'] = $this->userInfo['id'];// 会员用户ID
$insertData['business_id'] = $this->businessInfo["id"];// 商户ID
$insertData['province_code'] = $province_code;// 省份地区Code
$insertData['city_code'] = $city_code;// 城市地区Code
$insertData['country_code'] = $country_code;// 县区Code
$insertData['street_code'] = $street_code;// 街道Code
$insertData['address_detail'] = $address_detail;// 详细地址
$insertData['realname'] = $realname;// 收货人姓名
$insertData['tel'] = $tel;// 收货人联系电话
$insertData['lng'] = $lng;// 经度
$insertData['lat'] = $lat;// 纬度
$insertData['createtime'] = TIMESTAMP;
$pdo = $this->db;
$pdo->beginTransaction();
$addressId = Sql::insertInto('syweb_users_address')->values($insertData)->exec($pdo)->lastInsertId();
if( $isdefault==1 ){
// 修改会员默认收货地址 begin
$setDefaultAddressSql = Sql::update('syweb_users');
$setDefaultAddressSql->set("address_id",$addressId);
$setDefaultAddressSql->where(" `id` = ".$this->userInfo['id']);
$setDefaultAddressSql->exec($pdo);
// 修改会员默认收货地址 end
}
$pdo->commit();
if ( !empty($addressId) ) {
$result["error"] = '0';
$result["id"] = $addressId;
$result["message"] = '收货地址存储成功。';
return json_encode($result,JSON_UNESCAPED_UNICODE);
}else{
$result["status"] = '1';
$result["error_code"] = 12701; // 用户收货地址存储失败
$result["msg"] = "用户收货地址存储失败";
return json_encode($result,JSON_UNESCAPED_UNICODE);
}
}
}else{
return json_encode($verify_result,JSON_UNESCAPED_UNICODE);
}
}
/**
* 查询当前登录会员的收货地址列表(错误代码12751-12800)
* @route({"POST","/list"})
* @param({"appid","$._POST.appid"}) 应用appid
* @param({"devkey","$._POST.devkey"}) 开发者key
* @param({"sid","$._POST.sid"}) 服务器返回的sid
* @param({"scode","$._POST.scode"}) 客户端生成的scode
* @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用
*/
public function queryUserAddressList($appid='',$devkey='',$sid='',$scode='') {
// 验证公共参数是否合法
parent::init($appid,$devkey,$sid,$scode);
$verify_result = parent::verify();
if( !is_error_api($verify_result) ){
$result = array();
$fields = "a.id,a.province_code,(select address_name from syweb_whole_country_address where address_code=a.province_code) as province_name,a.city_code,(select address_name from syweb_whole_country_address where address_code=a.city_code) as city_name,a.country_code,(select address_name from syweb_whole_country_address where address_code=a.country_code) as country_name,a.street_code,(select address_name from syweb_whole_country_address where address_code=a.street_code) as street_name,a.address_detail,a.realname,a.tel,a.lng,a.lat,a.createtime";
$addressList = Sql::select($fields)
->from('syweb_users_address a')
->where('a.business_id=? and a.uid=?', $this->businessInfo['id'],$this->userInfo['id'])
->get($this->db ,null);
if(!empty($addressList) && count($addressList)>0){
foreach ($addressList as $key => &$row) {
if( $row['id']==$this->userInfo['address_id'] ){
$row['isdefault'] = 1;
}else{
$row['isdefault'] = 0;
}
}
$result["error"] = "0";
$result["data"] = $addressList;
return json_encode($result,JSON_UNESCAPED_UNICODE);
} else {
$result["error"] = '0';
$result["data"] = array();
return json_encode($result,JSON_UNESCAPED_UNICODE);
}
}else{
return json_encode($verify_result,JSON_UNESCAPED_UNICODE);
}
}
/**
* 根据收货地址的ID查询收货地址详细信息(错误代码12801-12850)
* @route({"POST","/info"})
* @param({"appid","$._POST.appid"}) 应用appid
* @param({"devkey","$._POST.devkey"}) 开发者key
* @param({"sid","$._POST.sid"}) 服务器返回的sid
* @param({"scode","$._POST.scode"}) 客户端生成的scode
* @param({"id","$._POST.id"}) 收货地址ID
* @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用
*/
public function queryUserAddressInfo($appid='',$devkey='',$sid='',$scode='',$id='') {
// 验证公共参数是否合法
parent::init($appid,$devkey,$sid,$scode);
$verify_result = parent::verify();
if( !is_error_api($verify_result) ){
$result = array();
if(empty($id) || !is_numeric($id)){
$result["error"] = "1";
$result["error_code"] = 12801; // 请传入地址ID
$result["msg"] = "请传入地址ID";
return json_encode($result,JSON_UNESCAPED_UNICODE);
}
$fields = "a.id,a.province_code,(select address_name from syweb_whole_country_address where address_code=a.province_code) as province_name,a.city_code,(select address_name from syweb_whole_country_address where address_code=a.city_code) as city_name,a.country_code,(select address_name from syweb_whole_country_address where address_code=a.country_code) as country_name,a.street_code,(select address_name from syweb_whole_country_address where address_code=a.street_code) as street_name,a.address_detail,a.realname,a.tel,a.lng,a.lat,a.createtime";
$addressInfo = Sql::select($fields)
->from('syweb_users_address a')
->where('a.business_id=? and a.uid=? and a.id=?', $this->businessInfo['id'],$this->userInfo['id'],$id)
->get($this->db ,null);
if(!empty($addressInfo) && count($addressInfo)>0){
if( $addressInfo[0]['id']==$this->userInfo['address_id'] ){
$addressInfo[0]['isdefault'] = 1;
}else{
$addressInfo[0]['isdefault'] = 0;
}
$result["error"] = "0";
$result["data"] = $addressInfo[0];
return json_encode($result,JSON_UNESCAPED_UNICODE);
} else {
$result["error"] = '0';
$result["data"] = array();
return json_encode($result,JSON_UNESCAPED_UNICODE);
}
}else{
return json_encode($verify_result,JSON_UNESCAPED_UNICODE);
}
}
/**
* 获取用户默认收货地址(错误代码12851-12900)
* @route({"POST","/defaddr"})
* @param({"appid","$._POST.appid"}) 应用appid
* @param({"devkey","$._POST.devkey"}) 开发者key
* @param({"sid","$._POST.sid"}) 服务器返回的sid
* @param({"scode","$._POST.scode"}) 客户端生成的scode
* @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用
*/
public function queryUserDefaultAddressDefault($appid='',$devkey='',$sid='',$scode='') {
// 验证公共参数是否合法
parent::init($appid,$devkey,$sid,$scode);
$verify_result = parent::verify();
if( !is_error_api($verify_result) ){
$result = array();
$defaultAddressId = $this->userInfo['address_id'];
if( !empty($defaultAddressId) && is_numeric($defaultAddressId) ){
$fields = "a.id,a.province_code,(select address_name from syweb_whole_country_address where address_code=a.province_code) as province_name,a.city_code,(select address_name from syweb_whole_country_address where address_code=a.city_code) as city_name,a.country_code,(select address_name from syweb_whole_country_address where address_code=a.country_code) as country_name,a.street_code,(select address_name from syweb_whole_country_address where address_code=a.street_code) as street_name,a.address_detail,a.realname,a.tel,a.lng,a.lat,a.createtime";
$addressInfo = Sql::select($fields)
->from('syweb_users_address a')
->where('a.business_id=? and a.uid=? and a.id=?', $this->businessInfo['id'],$this->userInfo['id'],$defaultAddressId)
->get($this->db ,null);
if(!empty($addressInfo) && count($addressInfo)>0){
$result[0]["error"] = "0";
$result[0]["data"] = $addressInfo[0];
return json_encode($result,JSON_UNESCAPED_UNICODE);
} else {
$result["error"] = '0';
$result["data"] = array();
return json_encode($result,JSON_UNESCAPED_UNICODE);
}
} else {
$result["error"] = '1';
$result["error_code"] = 12851; // 没有设置默认地址
$result["msg"] = "没有设置默认地址";
return json_encode($result,JSON_UNESCAPED_UNICODE);
}
}else{
return json_encode($verify_result,JSON_UNESCAPED_UNICODE);
}
}
/**
* 根据条件删除收货地址(错误代码12901-12950)
* @route({"POST","/delete"})
* @param({"appid","$._POST.appid"}) 应用appid
* @param({"devkey","$._POST.devkey"}) 开发者key
* @param({"sid","$._POST.sid"}) 服务器返回的sid
* @param({"scode","$._POST.scode"}) 客户端生成的scode
* @param({"id","$._POST.id"}) 收货地址系统编号
* @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用
* @return("body")
*/
public function postDelData($appid='',$devkey='',$sid='',$scode='',$id=''){
// 验证公共参数是否合法
parent::init($appid,$devkey,$sid,$scode);
$verify_result = parent::verify();
if( !is_error_api($verify_result) ){
$result = array();
if( empty($id) || !is_numeric($id) ){
$result["error"] = "1";
$result["error_code"] = 12901; // 请传入收货地址编号
$result["msg"] = "请传入收货地址编号";
return json_encode($result,JSON_UNESCAPED_UNICODE);
}
$condition .= " `id` = ".$id;
$pdo = $this->db;
$pdo->beginTransaction();
$delResult = Sql::deleteFrom('syweb_users_address')->where($condition)->exec($this->db);
$this->db->commit();
$result["error"] = "0";
$result["message"] = "删除收货地址成功!";
return json_encode($result,JSON_UNESCAPED_UNICODE);
}else{
return json_encode($verify_result,JSON_UNESCAPED_UNICODE);
}
}
/** @inject("ioc_factory") */
private $factory;
/**
* @property({"default":"@db"})
* @var PDO
*/
public $db;
// 此处删除了代码
}

View File

@@ -0,0 +1,54 @@
<?php
// 加载环境变量配置
require_once dirname(dirname(__DIR__)) . '/env_config.php';
$_db_host = env('API_DB_HOST', 'rm-bp1btyuwq77591x0jpo.mysql.rds.aliyuncs.com');
$_db_port = env('API_DB_PORT', '3306');
$_db_name = env('API_DB_NAME', 'youlehudong');
$_db_user = env('API_DB_USER', 'games');
$_db_pass = env('API_DB_PASSWORD', 'Games0791!!');
return [
"phprs\\Router"=>[
"properties"=>[
"export_apis"=>true, //Enable output api documents, if true, visit http://your-host:port/apis/ to get documents
//,"hooks":["MyHook1","MyHook2"] //Enable hooks
"url_begin"=>1, // if url is "/abc/123", then 1st path node "/abc/" will be ignored.
"api_path"=>__DIR__.'/apis/',
//"default_strict_matching"=>true, //sub path do not match the parent path route in strict mode.
]
],
"phprs\\Invoker"=>[
"properties"=>[
//"cache":"@invokeCache" //cache result of apis(the apis with @cache)
]
]
//if the property "cache" of phprs\\Invoker is set
/**
,
"invokeCache"=>[
"class"=>"phprs\\util\\RedisCache",
"singleton"=>true,
"properties"=>[
"serialize"=>true,
"host"=>"127.0.0.1",
"port"=>"6379"
]
]
*/
//db config sample, and ezphp can work with PDO simply
,
"db"=>[
"singleton"=>true,
"class"=>"PDO",
"pass_by_construct"=>true,
"properties"=>[
"dsn"=>"mysql:host={$_db_host}:{$_db_port};dbname={$_db_name};charset=utf8",
"username"=>$_db_user,
"password"=>$_db_pass
]
]
];

View File

@@ -0,0 +1,265 @@
<?php
define('USEDCHARSET', 'utf-8');
// 加载环境变量配置
require_once dirname(dirname(dirname(__DIR__))) . '/env_config.php';
// 域名配置(若 pay/common.php 已先定义则跳过)
if (!defined('SITE_API_DOMAIN')) define('SITE_API_DOMAIN', env('SITE_API_URL', 'https://api.tscce.cn'));
if (!defined('SITE_API2_DOMAIN')) define('SITE_API2_DOMAIN', env('SITE_API2_URL', 'https://api2.tscce.cn'));
/// 接口返回用的信息类
class ResultObject
{
public $error; /// 返回值: 0成功; 非0失败;
public $error_code; /// 错误号
public $msg; /// 错误信息
public $data; /// 返回的数据
public function ResultObject($string)
{
$this->error = 0;
$this->error_code = 0;
$this->msg = null;
$this->data = null;
$this->from_string($string);
}
public function to_array()
{
return (array)$this;
}
public function to_string()
{
return json_encode($this, JSON_UNESCAPED_UNICODE);
}
public function from_array($array)
{
foreach ($array as $key => $value)
{
if (property_exists($this, $key))
{
$this->$key = $value;
}
}
return true;
}
public function from_string($string)
{
return $this->from_array((array)json_decode($string));
}
}
/**
* @note 获取当前页面的完整连接
* @param $always_http bool
* @return string
*/
function getLocaleUrl($always_http = false)
{
$is_https =
(isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ||
(isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') ||
(isset($_SERVER['REQUEST_SCHEME']) && $_SERVER['REQUEST_SCHEME'] == 'https');
$request_scheme = $is_https ? 'https://' : 'http://';
$hostname = $_SERVER['SERVER_NAME'];
$hostport = (($is_https && '443' == $_SERVER['SERVER_PORT']) || (!$is_https && '80' == $_SERVER['SERVER_PORT'])) ? '' : ':' . intval($_SERVER['SERVER_PORT']);
if ($always_http)
return 'http://' . $hostname . $hostport;
else
return $request_scheme . $hostname . $hostport;
}
function getFullUrl($relatively_url, $always_http = false)
{
if (mb_strstr($relatively_url, '/', false, USEDCHARSET) == $relatively_url)
return getLocaleUrl($always_http) . $relatively_url;
else
return getLocaleUrl($always_http) . '/' . $relatively_url;
}
/**
* @date 2017-03-04
* @note 给参数按key的顺序排序。支持递归
* @param mixed $parameter 要排序的参数
* @return array
* @auth 应俊
*/
function SortParam($parameter)
{
$parameter = (array)$parameter;
foreach ($parameter as $k => $v)
{
if (is_array($v) || is_object($v))
{
$parameter[$k] = SortParam($v);
}
}
// 调用strcmp函数来排序该函数区分大小写。
uksort($parameter, 'strcmp');
return $parameter;
}
/**
* @date 2017-03-06
* @note 转换参数成字符串形式按key=value的形式用&分隔)。
* @param mixed $parameter 要转换的参数
* @return string
* @auth 应俊
*/
function ConvertParam($parameter)
{
$parameter = (array)$parameter;
$return = '';
foreach ($parameter as $k => $v)
{
if (is_array($v) || is_object($v))
{
$return .= sprintf('&%s={%s}', $k, ConvertParam($v));
}
else
{
$return .= sprintf('&%s=%s', $k, $v);
}
}
$sublen = mb_strlen('&', USEDCHARSET);
$retlen = mb_strlen($return, USEDCHARSET);
$return = mb_substr($return, $sublen, $retlen - $sublen, USEDCHARSET);
return $return;
}
/**
* @date 2017-03-04
* @note 为参数生成签名
* @param mixed $parameter 要签名的参数
* @param string $signkey 签名key
* @return string
* @auth 应俊
*/
function SignParameter($parameter, $signkey = '')
{
// 1先把参数按参数名key从小到大排序
$parameter = SortParam($parameter);
// 2连接参数成一个字符串按key=value的形式用&分隔)。
$return = ConvertParam($parameter);
// 3结尾加上key=签名key
$return .= '&key=' . $signkey;
// 4md5加密这个字符串
return md5($return);
}
/**
* @param mixed $data
* @return array|mixed
*/
function ChangePostData($data)
{
switch (gettype($data))
{
case 'array':
{
foreach ($data as $key => $value)
{
$data[$key] = ChangePostData($value);
}
break;
}
case 'object':
{
$array = (array)$data;
foreach ($array as $key => $value)
{
$data->$key = ChangePostData($value);
}
break;
}
default:
{
$data = preg_replace_callback('/\+/', function ($r) { return '%2B'; }, $data);
$data = preg_replace_callback('/\&/', function ($r) { return '%26'; }, $data);
break;
}
}
return $data;
}
/**
* @note 发送post请求
* @param string $url
* @param mixed $data
* @return string
*/
function SendPost($url, $data)
{
$data = http_build_query(ChangePostData($data));
$opts = array(
'http' => array(
'method' => 'POST',
'header' => "Content-type: application/x-www-form-urlencoded\r\n" . "Content-Length: " . strlen($data) . "\r\n",
'content' => $data,
),
);
$context = stream_context_create($opts);
// 抑制警告并捕获错误
$ret = @file_get_contents($url, false, $context);
// 如果请求失败,记录错误并返回空字符串
if ($ret === false) {
// 记录错误到日志文件用于调试
$error_msg = "SendPost failed: URL=$url, Data=" . print_r($data, true);
if (isset($http_response_header)) {
$error_msg .= ", Headers=" . print_r($http_response_header, true);
}
error_log($error_msg);
return '';
}
$ret = trim($ret, "\xEF\xBB\xBF");
return $ret;
}
/**
* @note 从参数中过滤不需要的参数
* @param array|null $ignores 要过滤的参数列表(参数名)
* @param array|null $parameters 目标参数列表
* @return array
*/
function GetAttachParameters($ignores = null, $parameters = null)
{
$return = (array)(empty($parameters) ? $_REQUEST : $parameters);
if (!empty($ignores))
{
foreach ($return as $k => $v)
{
if (in_array($k, $ignores))
unset($return[$k]);
}
}
return $return;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,217 @@
.body_bg{
background-color: #f1f1f1;
}
.body_bg>.yl_logo{
margin: 0 auto;
padding: 15% 20px;
text-align: center;
position: relative;
}
.body_bg>.yl_logo>img{
display: inline-block;
height: 45px;
}
.s_row{
position: relative;
margin: 0 auto 20px auto;
text-align: center;
width: 90%;
overflow: hidden;
}
.s_row .img_tb{
width: 15%;
height: 31px;
position: relative;
clear: both;
}
.s_row .img_tb img{
width: 22px;
height: 27px;
}
.s_row .img_tb img,
.s_row>input{
float: left;
}
.s_row>input{
display: block;
position: relative;
height: 31px;
padding: 12px 10px;
border-top: none;
border-left: none;
border-right: none;
border-bottom: 1px solid #bcbcbc;
line-height: 40px;
font-size: 16px;
color: #666;
background-color: #f1f1f1;
outline: 0;
margin-left: 5%;
width: 85%;
}
.s_row .duanxin{
margin-left: 11%;width: 60%;
}
.s_row .huoqu{
background-color: #02a7f1;
border: 1px solid #02a7f1;
color: #ffffff;
position: absolute;
top: 0;
right: 3%;
padding: 6px 14px;
}
.dr_btn{
text-align: center;
}
.dr_btn .btn{
width: 90%;
padding: 10px;
margin-bottom: 20px;
}
.dr_btn .btn-danger{
background-color: #cb4c02;
border: 1px solid #cb4c02;
}
.dr_btn .btn-info{
background-color: #5c8ceb;
border: 1px solid #5c8ceb;
margin-top: 18%;
}
.dr_btn .btn-info:hover,
.dr_btn .btn-info:active,
.dr_btn .btn-info:active:hover{
background-color: #5174c7;
border: 1px solid #5c8ceb;
}
.dr_btn .btn-default{
background-color: #969696;
border: 1px solid #969696;
color: #ffffff;
}
.wj_row{
text-align: center;
width: 90%;
margin: 0 auto 20% auto;
}
.wj_row a{
color: #7b94f1;
}
.wj_row .wjmm{
text-align: left;
display: inherit;
float: left;
}
.wj_row .zczh{
text-align: right;
display: inline-block;
float: right;
}
.sigma-content{
text-align: center;
background-color: #f1f1f1;
position: relative;
color: #bfbfbf;
width: 90%;
margin: 0 auto;
}
.sigma-middle-line:before{
content: '';
display: block;
height: 1px;
width: 100%;
background-color: #bfbfbf;/*颜色需与主题大背景色一致*/
position: relative;
top: 10px;/*调节线高*/
left: 0;
}
.sigma-line-text{
display: inline-block;
background: #f1f1f1;
padding: 0 18px 0 18px;
position: relative;
font-size: 14px;
font-weight: 500;
}
.fangshi{
width: 80%;
margin: 8% auto;
position: relative;
overflow: hidden;
text-align: center;
}
.fangshi .box{
display: inline-block;
width: 18.1%;
margin-left: 3%;
margin-right: 3%;
text-align: center;
color: #787878;
margin-bottom: 20px;
}
.fangshi .box:first-child{
margin-left: 0;
}
.fangshi .box:last-child{
margin-right: 0;
}
.fangshi .box img{
display: block;
max-width: 100%;
height: auto;
margin: 0 auto 5px auto;
}
.fangshi .box:active{
color: red;
font-size: 12px;
}
.fangshi .box:active img{
padding: 3px;
}
/**/
.hui{
color: #787878;
font-size: 16px;
line-height: 1.8;
}
.w_tongy{
height: 40px;
}
.w_tongy>input[type=checkbox]{
width: 5%;
}
.w_tongy .xieyi{
margin-left: 5%; line-height: 2.8; float: left;color: #666;
}
.w_tongy .xieyi .red{
color: red;
}
.huoqu_duanxin{
height: 35px;overflow: auto;
}
@media screen and (device-width: 320px) and (device-height: 568px) and (-webkit-device-pixel-ratio: 2)
{
.s_row .duanxin{
margin-left: 14%;
}
.s_row .huoqu{
right: 1%;
}
}
@media screen and (device-width: 768px) and (device-height: 1024px) and (-webkit-device-pixel-ratio: 2)
{
.s_row .duanxin{
margin-left: 8.5%;
}
.s_row .huoqu{
right: 2%;
}
.s_row>input{
width: 90%;
}
}

View File

@@ -0,0 +1,147 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<script language="JavaScript" src="js/jquery-2.1.4.min.js"></script>
<script language="JavaScript" src="js/common.js"></script>
<title>错误提示</title>
</head>
<style type="text/css">
body {
background-color: #eee;
}
* {
padding: 0;
margin: 0;
}
.container {
margin: 0 auto;
width: 100%;
}
.container .header {
min-height: 45px;
width: 100%;
}
.container .body {
width: 100%;
}
.container .header .header-nav.default {
position: relative;
}
.container .header .header-nav {
background-color: #ec6061;
height: 45px;
width: 100%;
}
.container .header .header-nav-c {
color: #ffffff;
font-size: 16px;
line-height: 45px;
padding: 0 50px;
text-align: center;
}
.container .body .login-box {
text-align: center;
}
.container .body .login-box img {
height: 160px;
margin-top: 50px;
}
.container .body .login-box .login-btn-group, .loading {
margin: 50px 30px;
text-align: left;
}
.container .body .login-box .login-btn-group .btn {
border-radius: 5px;
font-size: 14px;
margin-bottom: 10px;
padding: 7px 0;
}
.btn-block {
display: block;
width: 100%;
}
.btn-success {
background-color: #5cb85c;
border-color: #4cae4c;
color: #ffffff;
}
.btn {
background-image: none;
cursor: pointer;
font-weight: normal;
line-height: 1.4;
outline: medium none;
text-align: center;
vertical-align: middle;
white-space: nowrap;
}
.btn-danger {
background-color: #d9534f;
border-color: #d43f3a;
color: #ffffff;
}
a {
text-decoration: none;
}
.hide {
display: none;
}
</style>
<script type="text/javascript">
$(function () {
var error_code = getQueryString('error_code'); // 错误代码
var msg = getQueryString('msg'); // 错误消息
var html = '<strong><center>系统发生错误!</center></strong><p><br>错误代码: {error_code}<br>错误消息: {msg}</p>'.format({
'error_code': error_code,
'msg': decodeURIComponent(msg)
});
if (error_code && msg) {
$('.loading').addClass('hide');
$('.login-btn-group').html(html).removeClass('hide');
}
else {
$('.loading').html('出现异常错误,请稍后重试!');
}
});
</script>
<body>
<div class="container">
<div id="content">
<div class="header">
<div class="header-nav default">
<div class="header-nav-c">错误提示</div>
</div>
</div>
<div class="body">
<div class="login-box">
<img alt="login" src="http://game.mianwangkeji.com/images/youle.png">
<div class="login-btn-group hide"></div>
<div class="loading">Loading...</div>
</div>
</div>
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,147 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<script language="JavaScript" src="js/jquery-2.1.4.min.js"></script>
<script language="JavaScript" src="js/common.js"></script>
<title>错误提示</title>
</head>
<style type="text/css">
body {
background-color: #eee;
}
* {
padding: 0;
margin: 0;
}
.container {
margin: 0 auto;
width: 100%;
}
.container .header {
min-height: 45px;
width: 100%;
}
.container .body {
width: 100%;
}
.container .header .header-nav.default {
position: relative;
}
.container .header .header-nav {
background-color: #ec6061;
height: 45px;
width: 100%;
}
.container .header .header-nav-c {
color: #ffffff;
font-size: 16px;
line-height: 45px;
padding: 0 50px;
text-align: center;
}
.container .body .login-box {
text-align: center;
}
.container .body .login-box img {
height: 160px;
margin-top: 50px;
}
.container .body .login-box .login-btn-group, .loading {
margin: 50px 30px;
text-align: left;
}
.container .body .login-box .login-btn-group .btn {
border-radius: 5px;
font-size: 14px;
margin-bottom: 10px;
padding: 7px 0;
}
.btn-block {
display: block;
width: 100%;
}
.btn-success {
background-color: #5cb85c;
border-color: #4cae4c;
color: #ffffff;
}
.btn {
background-image: none;
cursor: pointer;
font-weight: normal;
line-height: 1.4;
outline: medium none;
text-align: center;
vertical-align: middle;
white-space: nowrap;
}
.btn-danger {
background-color: #d9534f;
border-color: #d43f3a;
color: #ffffff;
}
a {
text-decoration: none;
}
.hide {
display: none;
}
</style>
<script type="text/javascript">
$(function () {
var error_code = getQueryString('error_code'); // 错误代码
var msg = getQueryString('msg'); // 错误消息
var html = '<strong><center>系统发生错误!</center></strong><p><br>错误代码: {error_code}<br>错误消息: {msg}</p>'.format({
'error_code': error_code,
'msg': decodeURIComponent(msg)
});
if (error_code && msg) {
$('.loading').addClass('hide');
$('.login-btn-group').html(html).removeClass('hide');
}
else {
$('.loading').html('出现异常错误,请稍后重试!');
}
});
</script>
<body>
<div class="container">
<div id="content">
<div class="header">
<div class="header-nav default">
<div class="header-nav-c">错误提示</div>
</div>
</div>
<div class="body">
<div class="login-box">
<img alt="login" src="http://game.mianwangkeji.com/images/youle.png">
<div class="login-btn-group hide"></div>
<div class="loading">Loading...</div>
</div>
</div>
</div>
</div>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 477 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 467 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 682 B

View File

@@ -0,0 +1,216 @@
//var g_appid = '14919772144482';
//var g_devkey = '14915485974028';
var g_RequestAddress = 'https://api2.tscce.cn';
/**
* @note 字符串格式化
* @param fn_objs
* @returns object
* @constructor
*/
Overload = function (fn_objs) {
var is_match = function (x, y) {
if (x == y) {
return true;
}
if (x.indexOf("*") == -1) {
return false;
}
var x_arr = x.split(","), y_arr = y.split(",");
if (x_arr.length != y_arr.length) {
return false;
}
while (x_arr.length) {
var x_first = x_arr.shift(), y_first = y_arr.shift();
if (x_first != "*" && x_first != y_first) {
return false;
}
}
return true;
};
var ret = function () {
var args = arguments
, args_len = args.length
, args_types = []
, args_type
, fn_objs = args.callee._fn_objs
, match_fn = function () {
};
for (var i = 0; i < args_len; i++) {
var type = typeof args[i];
type == "object" && (args[i].length > -1) && (type = "array");
args_types.push(type);
}
args_type = args_types.join(",");
for (var k in fn_objs) {
if (is_match(k, args_type)) {
match_fn = fn_objs[k];
break;
}
}
return match_fn.apply(this, args);
};
ret._fn_objs = fn_objs;
return ret;
};
/**
* 通过对字符串进行伪重载实现对字符串对象的格式化功能
* @type {Object}
*/
String.prototype.format = Overload({
"array": function (params) {
var reg = /{(\d+)}/gm;
return this.replace(reg, function (match, name) {
return params[~~name];
});
},
"object": function (param) {
var reg = /{([^{}]+)}/gm;
return this.replace(reg, function (match, name) {
return param[name];
});
}
});
function getQueryString(name) {
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
var r = window.location.search.substr(1).match(reg);
if (r != null) {
return r[2];
}
return null;
}
//------------设置Cookie参数方法------------//
function setCookie(name, value) {
var Days = 30; //此 cookie 将被保存 30 天
var exp = new Date();
exp.setTime(exp.getTime() + Days * 24 * 60 * 60 * 1000);
document.cookie = name + "=" + value + ";expires=" + exp.toGMTString();
}
//------------获取Cookie参数方法------------//
function getCookie(name) {
var arr = document.cookie.match(new RegExp("(^| )" + name + "=([^;]*)(;|$)"));
if (arr != null) {
return arr[2];
}
return null;
}
//------------删除Cookie参数方法------------//
function delCookie(name) {
var exp = new Date();
exp.setTime(exp.getTime() - 1);
var cval = getCookie(name);
if (cval != null) {
document.cookie = name + "=" + cval + ";expires=" + exp.toGMTString();
}
}
/**
* 获取随机数
*/
function randomChar(length) {
var x = "0123456789qwertyuioplkjhgfdsazxcvbnm";
var tmp = "";
var timestamp = new Date().getTime();
for (var i = 0; i < length; i++) {
tmp += x.charAt(Math.ceil(Math.random() * 100000000) % x.length);
}
return timestamp + tmp;
}
function localeUrl() {
var url = window.location.origin + window.location.pathname;
var index = url.indexOf('?');
if (-1 == index)
return url;
else
return name.substr(0, index);
}
function extractPath(name) {
var index = name.lastIndexOf('/');
if (-1 == index)
return name;
else
return name.substr(0, index + 1);
}
function HttpRequest(args) {
var defaults =
{
url: g_RequestAddress,
async: true,
OnBeforeSend: function (/*XMLHttpRequest*/object) { },
OnComplete: function (/*XMLHttpRequest, textStatus*/object, status) { },
OnSuccess: function (/*data, textStatus*/message, status) { },
OnError: function (/*XMLHttpRequest, textStatus, errorThrown*/object, status, error) { },
},
settings = $.extend({}, defaults, args);
var data = {};
$.each(settings, function (name, value) {
if (
'async' != name &&
'url' != name &&
'OnBeforeSend' != name &&
'OnComplete' != name &&
'OnSuccess' != name &&
'OnError' != name
) {
data[name] = value;
}
});
//var succ = function (/*data, textStatus*/message, status) {
// var obj = eval("(" + decodeURIComponent(message) + ")");
// if (!obj) {
// //alert('pager6');
// window.location.href = PAGENAME_LOGIN + "?manager_id=" + getCookie(g_managerid);
// return false;
// }
// else if (1 == obj.error && 10008 == obj.error_code) {
// //alert('pager7');
// window.location.href = PAGENAME_LOGIN + "?manager_id=" + getCookie(g_managerid);
// return false;
// }
// else {
// return settings.OnSuccess(message, status);
// }
//};
$.ajax({
url: settings.url,
type: 'post',
async: settings.async,
data: data,
datatype: 'json',
timeout: 1000 * 7,
beforeSend: settings.OnBeforeSend,
success: settings.OnSuccess,
//success: succ,
error: settings.OnError,
complete: settings.OnComplete,
});
return settings;
}

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,240 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<link href="css/style.css" rel="stylesheet">
<link href="css/bootstrap.min.css" rel="stylesheet">
<script language="JavaScript" src="js/jquery-2.1.4.min.js"></script>
<script language="JavaScript" src="js/common.js"></script>
<title>授权登录</title>
</head>
<script>
function frm_submit(id) {
var frm = document.getElementById(id);
return frm.submit();
}
function bodyload(sender) {
/// appid
var app_id = getQueryString('app_id');
/// 开发者key
var dev_key = getQueryString('dev_key');
/// 门店key
var market_key = getQueryString('market_key');
/// 登陆方式
var login_type = getQueryString('login_type');
/// 回调页面地址
var redirect_uri = getQueryString('redirect_uri');
/// 错误页面地址
var error_uri = getQueryString('error_uri');
/// 随机数
var scode = randomChar(32);
if (!redirect_uri || '' == redirect_uri)
redirect_uri = localeUrl(); /// window.location.href;
if (!error_uri || '' == error_uri)
error_uri = extractPath(localeUrl()) + 'error.html';
HttpRequest({
'url': g_RequestAddress + '/api/login/querylist',
'market_key': market_key,
'logintype': login_type,
OnSuccess: function (/*data, textStatus*/message, status) {
if ('string' == typeof(message)) {
message = eval("(" + decodeURIComponent(message) + ")");
}
if (0 == message.length) {
alert('找不到支援的任何登录方式, 请联系相关管理员!');
return;
}
var type1 = new Array();
var type2 = new Array();
for (var i = 0; i < message.length; i++) {
if ('string' == typeof(message[i].component)) {
message[i].component = eval("(" + decodeURIComponent(message[i].component) + ")");
}
if (0 != message[i].is_third) {
type2.push(message[i]);
}
else
type1.push(message[i]);
}
/// 只存在一种三方的校验方式则直接跳转到目标连接
if (0 == type1.length && 1 == type2.length) {
window.location =
type2[0].url + '?' + (
'appid={appid}&' +
'devkey={devkey}&' +
'scode={scode}&' +
'market_key={market_key}&' +
'target={target}&' +
'fail_target={fail_target}'
).format({
'appid': app_id,
'devkey': dev_key,
'scode': scode,
'market_key': market_key,
'target': redirect_uri,
'fail_target': error_uri
});
}
else {
document.getElementById('splitter').style.display = (0 != type1.length && 0 != type2.length) ? 'inline' : 'none';
var
forms = '',
elements = '',
item = '',
url = '';
if (type1.length > 0) { /// 需要输入信息的登陆方式
for (var i = 0; i < type1.length; i++) {
item =
('<form style="display:none;" id="{frmid}" name="{frmname}" method="post" action="{url}">\r\n' +
' <input name="appid" type="text" value="{appid}" />\r\n' +
' <input name="devkey" type="text" value="{devkey}" />\r\n' +
' <input name="scode" type="text" value="{scode}" />\r\n' +
' <input name="market_key" type="text" value="{market_key}" />\r\n' +
' <input name="target" type="text" value="{target}" />\r\n' +
' <input name="fail_target" type="text" value="{fail_target}" />\r\n' +
'</form>');
forms += item.format({
'frmid': 'frm' + i,
'frmname': 'frm' + i,
'url': type1[i].url,
'appid': app_id,
'devkey': dev_key,
'scode': scode,
'market_key': market_key,
'target': redirect_uri,
'fail_target': error_uri
});
item =
'<p class="s_row">\r\n' +
' <span class="img_tb"><img src="img/zh.png"></span>\r\n' +
' <input type="text" placeholder="账号|手机号|邮箱" autofocus>\r\n' +
'</p>\r\n' +
'<p class="s_row" style="margin-bottom: 30px;">\r\n' +
' <span class="img_tb"><img src="img/mm.png"></span>\r\n' +
' <input type="text" placeholder="请输入密码">\r\n' +
'</p>\r\n' +
'<div class="dr_btn">\r\n' +
' <button onclick="frm_submit(\'frm' + i + '\')" class="btn btn-danger">登录</button>\r\n' +
'</div>\r\n' +
'<div class="wj_row">\r\n' +
' <a href="password.html" class="wjmm">忘记密码?</a>\r\n' +
' <a href="password_detail.html" class="zczh">没有帐号?立即注册>>></a>\r\n' +
'</div>\r\n';
elements += item;
}
$('#mainbody').append(forms);
$('#own').append(elements);
}
if (type2.length > 0) { /// 其他登录方式(三方认证方式)
elements = '';
for (var i = 0; i < type2.length; i++) {
item =
'<a class="box" href="{url}">\r\n' +
' <img src="{image}">\r\n' +
//' <label>{type_name}</label>\r\n' +
'</a>';
url = type2[i].url + '?' + (
'appid={appid}&' +
'devkey={devkey}&' +
'scode={scode}&' +
'market_key={market_key}&' +
'target={target}&' +
'fail_target={fail_target}'
).format({
'appid': app_id,
'devkey': dev_key,
'scode': scode,
'market_key': market_key,
'target': redirect_uri,
'fail_target': error_uri
});
elements += item.format({
'url': url,
'image': type2[i].image,
'type_name': type2[i].type_name
});
}
$('#third').append(elements);
}
}
}
});
}
</script>
<body class="body_bg" id="mainbody" onload="bodyload(this)">
<header class="yl_logo">
<img src="img/yl.png" class="img-responsive">
</header>
<div class="container-fluid">
<div class="fangshi" id="own">
<!--
<p class="s_row">
<span class="img_tb"><img src="img/zh.png"></span>
<input type="text" placeholder="账号|手机号|邮箱" autofocus>
</p>
<p class="s_row" style="margin-bottom: 30px;">
<span class="img_tb"><img src="img/mm.png"></span>
<input type="text" placeholder="请输入密码">
</p>
<div class="dr_btn">
<a href="javascript:;" class="btn btn-danger">登录</a>
</div>
<div class="wj_row">
<a href="password.html" class="wjmm">忘记密码?</a>
<a href="password_detail.html" class="zczh">没有帐号?立即注册>>></a>
</div>
-->
</div>
<div class="sigma-content" id="splitter" style="display:none">
<div class="sigma-middle-line">
<span class="sigma-line-text">更多登录方式</span>
</div>
</div>
<div class="fangshi" id="third">
<!--
<div class="box">
<img src="img/wx.png">
<label>微信</label>
</div>
<div class="box">
<img src="img/zfb.png">
<label>支付宝</label>
</div>
<div class="box">
<img src="img/QQ.png">
<label>QQ</label>
</div>
<div class="box">
<img src="img/jkx.png">
<label>聚开心</label>
</div>
-->
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,252 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<link href="css/style.css" rel="stylesheet">
<link href="css/bootstrap.min.css" rel="stylesheet">
<script language="JavaScript" src="js/jquery-2.1.4.min.js"></script>
<script language="JavaScript" src="js/common.js"></script>
<title>授权登录</title>
</head>
<?php
require_once dirname(__FILE__) . '/common.php';
/// 获取参数GET
$app_id = isset($_GET['app_id']) ? $_GET['app_id'] : ''; /// appid
$dev_key = isset($_GET['dev_key']) ? $_GET['dev_key'] : ''; /// 开发者key
$market_key = isset($_GET['market_key']) ? $_GET['market_key'] : ''; /// 门店key
$login_type = isset($_GET['login_type']) ? $_GET['login_type'] : ''; /// 登陆方式
$redirect_uri = isset($_GET['redirect_uri']) ? $_GET['redirect_uri'] : ''; /// 回调页面地址
$error_uri = isset($_GET['error_uri']) ? $_GET['error_uri'] : ''; /// 错误页面地址
$silence = isset($_GET['silence']) ? $_GET['silence'] : null; /// 是否静默方式登录
$scode = isset($_GET['scode']) ? $_GET['scode'] : md5(date('Ymdhis') . rand(1000, 9999)); /// 随机数
$forms = '';
/// 其他的参数
$attach_array = GetAttachParameters(array('app_id','dev_key','market_key','login_type','redirect_uri','error_uri',), $_GET);
$attach_param = ''; /// 链接用的附加参数
$attach_items = ''; /// 创建表单用的附加参数
foreach ($attach_array as $key => $value)
{
$attach_param .= "&{$key}={$value}";
$attach_items .= " <input name=\"{$key}\" type=\"text\" value=\"{$value}\" />" . PHP_EOL;
}
if (empty($redirect_uri))
$redirect_uri = rawurlencode(getLocaleUrl());
if (empty($error_uri))
$error_uri = rawurlencode(dirname(getLocaleUrl()) . '/error.php');
$data = array(
'market_key' => $market_key,
'logintype' => $login_type,
);
if (!is_null($silence))
$data['silence'] = $silence;
$api_url = getFullUrl('/api/login/querylist');
$response = SendPost($api_url, $data);
// 如果API调用失败直接从数据库查询登录方式
if (empty($response)) {
error_log("Login API Error: Empty response from $api_url, using database fallback");
try {
// 直接连接数据库获取登录方式(从环境变量读取)
require_once dirname(dirname(dirname(__DIR__))) . '/env_config.php';
$dsn = "mysql:host=" . env('API_DB_HOST', 'rm-bp1btyuwq77591x0jpo.mysql.rds.aliyuncs.com') . ":" . env('API_DB_PORT', '3306') . ";dbname=" . env('API_DB_NAME', 'youlehudong') . ";";
$username = env('API_DB_USER', 'games');
$passwd = env('API_DB_PASSWORD', 'Games0791!!');
$pdo = new PDO($dsn, $username, $passwd, array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
if (empty($market_key)) {
$condition = 'is_enabled = 1 and is_silence = ' . intval(empty($silence) ? 0 : $silence);
if (!empty($login_type))
$condition .= sprintf(' and type_id = %d', intval($login_type));
$stmt = $pdo->prepare("SELECT type_id,type_key,type_name,image,url,component,is_third,third_flag FROM syweb_logintype_base WHERE $condition");
$stmt->execute();
} else {
$condition = 'a.type_key = b.type_key and a.is_enabled = 1 and b.is_enabled = 1 and market_key = ? and a.is_silence = ' . intval(empty($silence) ? 0 : $silence);
if (!empty($login_type))
$condition .= sprintf(' and a.type_id = %d', intval($login_type));
$stmt = $pdo->prepare("SELECT a.type_id,a.type_key,a.type_name,a.image,a.url,a.component,a.is_third,a.third_flag FROM syweb_logintype_base a, syweb_logintype_market b WHERE $condition");
$stmt->execute(array($market_key));
}
$data = $stmt->fetchAll(PDO::FETCH_ASSOC);
// 处理URL为完整路径
foreach ($data as $key => &$value) {
$value['url'] = getFullUrl($value['url']);
}
$response = rawurlencode(json_encode($data, JSON_UNESCAPED_UNICODE));
} catch (Exception $e) {
error_log("Database fallback error: " . $e->getMessage());
// 最后的备用方案:返回默认微信登录配置
$default_login_types = array(
array(
'type_id' => 2,
'type_key' => '0002',
'type_name' => '微信登录',
'image' => 'img/wx.png',
'url' => getFullUrl('api/login/weixin'),
'component' => null,
'is_third' => 1,
'third_flag' => 'weixin'
)
);
$response = rawurlencode(json_encode($default_login_types, JSON_UNESCAPED_UNICODE));
}
}
$result = json_decode(rawurldecode($response));
if (empty($result)) /// 为空表示没有获取到任何登录方式
{
$html = <<<EOL
<script>
alert('找不到支援的任何登录方式, 请联系相关管理员!');
</script>
EOL;
}
else /// 正常
{
$third_array = array(); /// 三方认证方式(不需要输入账号密码的方式)
$owner_array = array(); /// 本地认证方式(需要输入账号密码的方式)
foreach ($result as $item)
{
$item = (array)$item;
if (0 != $item['is_third']) /// 三方认证方式
array_push($third_array, $item);
else /// 本地认证方式
array_push($owner_array, $item);
}
$third_count = count($third_array);
$owner_count = count($owner_array);
$third_html = '';
$owner_html = '';
$splitter = '';
$forms = '';
if (0 == $owner_count && 1 == $third_count) /// 只存在一种三方的校验方式则直接跳转到目标连接
{
$url = $third_array[0]['url'] . "?appid={$app_id}&devkey={$dev_key}&scode={$scode}&market_key={$market_key}&target={$redirect_uri}&fail_target={$error_uri}{$attach_param}";
header("Location: {$url}");
exit;
}
/// 如果两种方式都有,则需要分隔元素。
if (0 != $owner_count && 0 != $third_count)
$splitter = <<<EOL
<div class="sigma-content">
<div class="sigma-middle-line">
<span class="sigma-line-text">更多登录方式</span>
</div>
</div>
EOL;
if (0 != $owner_count) /// 如果本地验证方式不为空则需要用于输入账号密码的表单元素。
{
$owner_html = ' <div class="fangshi" id="owner">' . PHP_EOL;
$forms = '';
$index = 0;
foreach ($owner_array as $owner)
{
$index++;
/// 用来提交数据的表单
$forms .= <<<EOL
<form style="display:none;" id="frm{$index}" name="frm{$index}" method="post" action="{$owner['url']}">
<input name="appid" type="text" value="{$app_id}" />
<input name="devkey" type="text" value="{$dev_key}" />
<input name="scode" type="text" value="{$scode}" />
<input name="market_key" type="text" value="{$market_key}" />
<input name="target" type="text" value="{$redirect_uri}" />
<input name="fail_target" type="text" value="{$error_uri}" />
{$attach_items}
</form>
EOL;
/// 用来显示的页面元素
$owner_html .= <<<EOL
<p class="s_row">
<span class="img_tb"><img src="img/zh.png"></span>
<input type="text" placeholder="账号|手机号|邮箱" autofocus>
</p>
<p class="s_row" style="margin-bottom: 30px;">
<span class="img_tb"><img src="img/mm.png"></span>
<input type="text" placeholder="请输入密码">
</p>
<div class="dr_btn">
<button onclick="frm_submit(frm{$index})" class="btn btn-danger">登录</button>
</div>
<div class="wj_row">
<a href="password.php" class="wjmm">忘记密码?</a>
<a href="password_detail.php" class="zczh">没有帐号?立即注册>>></a>
</div>
EOL;
}
$owner_html .= ' </div>' . PHP_EOL;
}
if (0 != $third_count)
{
$third_html = ' <div class="fangshi" id="third">' . PHP_EOL;
$index = 0;
foreach ($third_array as $third)
{
$index++;
$url = $third['url'] . "?appid={$app_id}&devkey={$dev_key}&scode={$scode}&market_key={$market_key}&target={$redirect_uri}&fail_target={$error_uri}{$attach_param}";
$third_html .= <<<EOL
<a class="box" href="{$url}">
<img src="{$third['image']}">
<label>{$third['type_name']}</label>
</a>
EOL;
}
}
$html = $owner_html . $splitter . $third_html;
}
?>
<script>
function frm_submit(form) {
return form.submit();
}
</script>
<body class="body_bg">
<?php echo $forms; ?>
<header class="yl_logo">
<img src="img/yl.png" class="img-responsive">
</header>
<div class="container-fluid">
<?php echo $html; ?>
</div>
</body>
</html>

View File

@@ -0,0 +1,187 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<link href="css/style.css" rel="stylesheet">
<link href="css/bootstrap.min.css" rel="stylesheet">
<script language="JavaScript" src="js/jquery-2.1.4.min.js"></script>
<script language="JavaScript" src="js/common.js"></script>
<title>授权登录</title>
</head>
<?php
require_once dirname(__FILE__) . '/common.php';
/// 获取参数GET
$app_id = isset($_GET['app_id']) ? $_GET['app_id'] : ''; /// appid
$dev_key = isset($_GET['dev_key']) ? $_GET['dev_key'] : ''; /// 开发者key
$market_key = isset($_GET['market_key']) ? $_GET['market_key'] : ''; /// 门店key
$login_type = isset($_GET['login_type']) ? $_GET['login_type'] : ''; /// 登陆方式
$redirect_uri = isset($_GET['redirect_uri']) ? $_GET['redirect_uri'] : ''; /// 回调页面地址
$error_uri = isset($_GET['error_uri']) ? $_GET['error_uri'] : ''; /// 错误页面地址
$scode = isset($_GET['scode']) ? $_GET['scode'] : md5(date('Ymdhis') . rand(1000, 9999)); /// 随机数
$forms = '';
/// 其他的参数
$attach_array = GetAttachParameters(array('app_id','dev_key','market_key','login_type','redirect_uri','error_uri',), $_GET);
$attach_param = ''; /// 链接用的附加参数
$attach_items = ''; /// 创建表单用的附加参数
foreach ($attach_array as $key => $value)
{
$attach_param .= "&{$key}={$value}";
$attach_items .= " <input name=\"{$key}\" type=\"text\" value=\"{$value}\" />" . PHP_EOL;
}
if (empty($redirect_uri))
$redirect_uri = rawurlencode(getLocaleUrl());
if (empty($error_uri))
$error_uri = rawurlencode(dirname(getLocaleUrl()) . '/error.php');
$data = array(
'market_key' => $market_key,
'logintype' => $login_type,
);
$result = json_decode(rawurldecode(SendPost(SITE_API2_DOMAIN . '/api/login/querylist', $data)));
if (empty($result)) /// 为空表示没有获取到任何登录方式
{
$html = <<<EOL
<script>
alert('找不到支援的任何登录方式, 请联系相关管理员!');
</script>
EOL;
}
else /// 正常
{
$third_array = array(); /// 三方认证方式(不需要输入账号密码的方式)
$owner_array = array(); /// 本地认证方式(需要输入账号密码的方式)
foreach ($result as $item)
{
$item = (array)$item;
if (0 != $item['is_third']) /// 三方认证方式
array_push($third_array, $item);
else /// 本地认证方式
array_push($owner_array, $item);
}
$third_count = count($third_array);
$owner_count = count($owner_array);
$third_html = '';
$owner_html = '';
$splitter = '';
$forms = '';
if (0 == $owner_count && 1 == $third_count) /// 只存在一种三方的校验方式则直接跳转到目标连接
{
$url = $third_array[0]['url'] . "?appid={$app_id}&devkey={$dev_key}&scode={$scode}&market_key={$market_key}&target={$redirect_uri}&fail_target={$error_uri}{$attach_param}";
header("Location: {$url}");
exit;
}
/// 如果两种方式都有,则需要分隔元素。
if (0 != $owner_count && 0 != $third_count)
$splitter = <<<EOL
<div class="sigma-content">
<div class="sigma-middle-line">
<span class="sigma-line-text">更多登录方式</span>
</div>
</div>
EOL;
if (0 != $owner_count) /// 如果本地验证方式不为空则需要用于输入账号密码的表单元素。
{
$owner_html = ' <div class="fangshi" id="owner">' . PHP_EOL;
$forms = '';
$index = 0;
foreach ($owner_array as $owner)
{
$index++;
/// 用来提交数据的表单
$forms .= <<<EOL
<form style="display:none;" id="frm{$index}" name="frm{$index}" method="post" action="{$owner['url']}">
<input name="appid" type="text" value="{$app_id}" />
<input name="devkey" type="text" value="{$dev_key}" />
<!--<input name="sscode" type="text" value="{$scode}" />-->
<input name="market_key" type="text" value="{$market_key}" />
<input name="target" type="text" value="{$redirect_uri}" />
<input name="fail_target" type="text" value="{$error_uri}" />
{$attach_items}
</form>
EOL;
/// 用来显示的页面元素
$owner_html .= <<<EOL
<p class="s_row">
<span class="img_tb"><img src="img/zh.png"></span>
<input type="text" placeholder="账号|手机号|邮箱" autofocus>
</p>
<p class="s_row" style="margin-bottom: 30px;">
<span class="img_tb"><img src="img/mm.png"></span>
<input type="text" placeholder="请输入密码">
</p>
<div class="dr_btn">
<button onclick="frm_submit(frm{$index})" class="btn btn-danger">登录</button>
</div>
<div class="wj_row">
<a href="password.php" class="wjmm">忘记密码?</a>
<a href="password_detail.php" class="zczh">没有帐号?立即注册>>></a>
</div>
EOL;
}
$owner_html .= ' </div>' . PHP_EOL;
}
if (0 != $third_count)
{
$third_html = ' <div class="fangshi" id="third">' . PHP_EOL;
$index = 0;
foreach ($third_array as $third)
{
$index++;
$url = $third['url'] . "?appid={$app_id}&devkey={$dev_key}&scode={$scode}&market_key={$market_key}&target={$redirect_uri}&fail_target={$error_uri}{$attach_param}";
$third_html .= <<<EOL
<a class="box" href="{$url}">
<img src="{$third['image']}">
<label>{$third['type_name']}</label>
</a>
EOL;
}
}
$html = $owner_html . $splitter . $third_html;
}
?>
<script>
function frm_submit(form) {
return form.submit();
}
</script>
<body class="body_bg">
<?php echo $forms; ?>
<header class="yl_logo">
<img src="img/yl.png" class="img-responsive">
</header>
<div class="container-fluid">
<?php echo $html; ?>
</div>
</body>
</html>

View File

@@ -0,0 +1,24 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<link href="css/style.css" rel="stylesheet">
<link href="css/bootstrap.min.css" rel="stylesheet">
<title>密码找回</title>
</head>
<body class="body_bg">
<header class="yl_logo">
<img src="img/yl.png" class="img-responsive">
</header>
<div class="container-fluid">
<p class="hui">忘记了密码?我们会把重设的密码以短信的形式下发到您绑定的手机!</p>
<div class="dr_btn">
<a href="password_detail.html" class="btn btn-info">发送密码找回短信</a>
<a href="login.html" class="btn btn-default">返回</a>
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,24 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<link href="css/style.css" rel="stylesheet">
<link href="css/bootstrap.min.css" rel="stylesheet">
<title>密码找回</title>
</head>
<body class="body_bg">
<header class="yl_logo">
<img src="img/yl.png" class="img-responsive">
</header>
<div class="container-fluid">
<p class="hui">忘记了密码?我们会把重设的密码以短信的形式下发到您绑定的手机!</p>
<div class="dr_btn">
<a href="password_detail.html" class="btn btn-info">发送密码找回短信</a>
<a href="login.html" class="btn btn-default">返回</a>
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,71 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<link href="css/style.css" rel="stylesheet">
<link href="css/bootstrap.min.css" rel="stylesheet">
<title>密码找回</title>
</head>
<body class="body_bg">
<header class="yl_logo" style="padding-bottom: 10%;">
<img src="img/yl.png" class="img-responsive">
</header>
<div class="container-fluid">
<a href="login.html" class="pull-right" style="margin-right: 7%;color: #42b8f2;">已有账号?点此登录>>></a>
<p class="s_row">
<span class="img_tb"><img src="img/zh.png"></span>
<input type="text" placeholder="请输入账号" autofocus >
</p>
<p class="s_row">
<span class="img_tb"><img src="img/mm.png"></span>
<input type="text" placeholder="请输入密码">
</p>
<p class="s_row">
<span class="img_tb"><img src="img/mm.png"></span>
<input type="text" placeholder="再输入一次密码">
</p>
<p class="s_row">
<span class="img_tb"><img src="img/sj.png"></span>
<input type="text" placeholder="请输入手机号">
</p>
<p class="s_row huoqu_duanxin">
<input type="text" placeholder="请输入短信验证码" class="duanxin">
<a class="btn btn-default huoqu">获取</a>
</p>
<p class="s_row w_tongy">
<input type="checkbox"><label class="xieyi">同意<a href="javascript:;" class="red">用户协议</a></label>
</p>
<div class="sigma-content">
<div class="sigma-middle-line">
<span class="sigma-line-text">更多登录方式</span>
</div>
</div>
<div class="fangshi">
<div class="box">
<img src="img/wx.png">
<label>微信</label>
</div>
<div class="box">
<img src="img/zfb.png">
<label>支付宝</label>
</div>
<div class="box">
<img src="img/QQ.png">
<label>QQ</label>
</div>
<div class="box">
<img src="img/jkx.png">
<label>聚开心</label>
</div>
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,71 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<link href="css/style.css" rel="stylesheet">
<link href="css/bootstrap.min.css" rel="stylesheet">
<title>密码找回</title>
</head>
<body class="body_bg">
<header class="yl_logo" style="padding-bottom: 10%;">
<img src="img/yl.png" class="img-responsive">
</header>
<div class="container-fluid">
<a href="login.html" class="pull-right" style="margin-right: 7%;color: #42b8f2;">已有账号?点此登录>>></a>
<p class="s_row">
<span class="img_tb"><img src="img/zh.png"></span>
<input type="text" placeholder="请输入账号" autofocus >
</p>
<p class="s_row">
<span class="img_tb"><img src="img/mm.png"></span>
<input type="text" placeholder="请输入密码">
</p>
<p class="s_row">
<span class="img_tb"><img src="img/mm.png"></span>
<input type="text" placeholder="再输入一次密码">
</p>
<p class="s_row">
<span class="img_tb"><img src="img/sj.png"></span>
<input type="text" placeholder="请输入手机号">
</p>
<p class="s_row huoqu_duanxin">
<input type="text" placeholder="请输入短信验证码" class="duanxin">
<a class="btn btn-default huoqu">获取</a>
</p>
<p class="s_row w_tongy">
<input type="checkbox"><label class="xieyi">同意<a href="javascript:;" class="red">用户协议</a></label>
</p>
<div class="sigma-content">
<div class="sigma-middle-line">
<span class="sigma-line-text">更多登录方式</span>
</div>
</div>
<div class="fangshi">
<div class="box">
<img src="img/wx.png">
<label>微信</label>
</div>
<div class="box">
<img src="img/zfb.png">
<label>支付宝</label>
</div>
<div class="box">
<img src="img/QQ.png">
<label>QQ</label>
</div>
<div class="box">
<img src="img/jkx.png">
<label>聚开心</label>
</div>
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,18 @@
页面地址:
https://api.daoqijuyou77.cn/source/login/login.php
主要功能:
实现无关业务的支付调用
调用方式:
get/post
所需参数:
app_id: appid
dev_key: 开发者key
market_key: 门店key
login_type: 登陆方式
redirect_uri: 回调页面地址
error_uri: 错误页面地址
用户其他参数
调用示例:
https://api.daoqijuyou77.cn/source/login/login.php?app_id=14936872341446&dev_key=14915485974028&market_key=test&redirect_uri=https://www.baidu.com

View File

@@ -0,0 +1,269 @@
<?php
define('USEDCHARSET', 'utf-8');
// 加载环境变量配置
require_once dirname(dirname(dirname(__DIR__))) . '/env_config.php';
// 域名配置
define('SITE_API_DOMAIN', env('SITE_API_URL', 'https://api.tscce.cn'));
define('SITE_API2_DOMAIN', env('SITE_API2_URL', 'https://api2.tscce.cn'));
/// 接口返回用的信息类
class ResultObject
{
public $error; /// 返回值: 0成功; 非0失败;
public $error_code; /// 错误号
public $msg; /// 错误信息
public $data; /// 返回的数据
public function ResultObject($string)
{
$this->error = 0;
$this->error_code = 0;
$this->msg = null;
$this->data = null;
$this->from_string($string);
}
public function to_array()
{
return (array)$this;
}
public function to_string()
{
return json_encode($this, JSON_UNESCAPED_UNICODE);
}
public function from_array($array)
{
foreach ($array as $key => $value)
{
if (property_exists($this, $key))
{
$this->$key = $value;
}
}
return true;
}
public function from_string($string)
{
return $this->from_array((array)json_decode($string));
}
}
/**
* @note 获取当前页面的完整连接
* @return string
*/
function getLocaleUrl($always_http = false)
{
$is_https =
(isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ||
(isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') ||
(isset($_SERVER['REQUEST_SCHEME']) && $_SERVER['REQUEST_SCHEME'] == 'https');
$request_scheme = $is_https ? 'https://' : 'http://';
$hostname = $_SERVER['SERVER_NAME'];
$hostport = (($is_https && '443' == $_SERVER['SERVER_PORT']) || (!$is_https && '80' == $_SERVER['SERVER_PORT'])) ? '' : ':' . intval($_SERVER['SERVER_PORT']);
if ($always_http)
return 'http://' . $hostname . $hostport;
else
return $request_scheme . $hostname . $hostport;
}
function getFullUrl($relatively_url, $always_http = false)
{
if (mb_strstr($relatively_url, '/', false, USEDCHARSET) == $relatively_url)
return getLocaleUrl($always_http) . $relatively_url;
else
return getLocaleUrl($always_http) . '/' . $relatively_url;
}
/**
* @note 获取当前页面的域名
* @return string
*/
function GetLocalRootUrl()
{
$is_https =
(isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ||
(isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') ||
(isset($_SERVER['REQUEST_SCHEME']) && $_SERVER['REQUEST_SCHEME'] == 'https');
$request_scheme = $is_https ? 'https://' : 'http://';
$hostname = $_SERVER['SERVER_NAME'];
$hostport = (($is_https && '443' == $_SERVER['SERVER_PORT']) || (!$is_https && '80' == $_SERVER['SERVER_PORT'])) ? '' : ':' . intval($_SERVER['SERVER_PORT']);
return $request_scheme . $hostname . $hostport;
}
/**
* @date 2017-03-04
* @note 给参数按key的顺序排序。支持递归
* @param mixed $parameter 要排序的参数
* @return array
* @auth 应俊
*/
function SortParam($parameter)
{
$parameter = (array)$parameter;
foreach ($parameter as $k => $v)
{
if (is_array($v) || is_object($v))
{
$parameter[$k] = SortParam($v);
}
}
// 调用strcmp函数来排序该函数区分大小写。
uksort($parameter, 'strcmp');
return $parameter;
}
/**
* @date 2017-03-06
* @note 转换参数成字符串形式按key=value的形式用&分隔)。
* @param mixed $parameter 要转换的参数
* @return string
* @auth 应俊
*/
function ConvertParam($parameter)
{
$parameter = (array)$parameter;
$return = '';
foreach ($parameter as $k => $v)
{
if (is_array($v) || is_object($v))
{
$return .= sprintf('&%s={%s}', $k, ConvertParam($v));
}
else
{
$return .= sprintf('&%s=%s', $k, $v);
}
}
$sublen = mb_strlen('&', USEDCHARSET);
$retlen = mb_strlen($return, USEDCHARSET);
$return = mb_substr($return, $sublen, $retlen - $sublen, USEDCHARSET);
return $return;
}
/**
* @date 2017-03-04
* @note 为参数生成签名
* @param mixed $parameter 要签名的参数
* @param string $signkey 签名key
* @return string
* @auth 应俊
*/
function SignParameter($parameter, $signkey = '')
{
// 1先把参数按参数名key从小到大排序
$parameter = SortParam($parameter);
// 2连接参数成一个字符串按key=value的形式用&分隔)。
$return = ConvertParam($parameter);
// 3结尾加上key=签名key
$return .= '&key=' . $signkey;
// 4md5加密这个字符串
return md5($return);
}
/**
* @param mixed $data
* @return array|mixed
*/
function ChangePostData($data)
{
switch (gettype($data))
{
case 'array':
{
foreach ($data as $key => $value)
{
$data[$key] = ChangePostData($value);
}
break;
}
case 'object':
{
$array = (array)$data;
foreach ($array as $key => $value)
{
$data->$key = ChangePostData($value);
}
break;
}
default:
{
$data = preg_replace_callback('/\+/', function ($r) { return '%2B'; }, $data);
$data = preg_replace_callback('/\&/', function ($r) { return '%26'; }, $data);
break;
}
}
return $data;
}
/**
* @note 发送post请求
* @param string $url
* @param mixed $data
* @return string
*/
function SendPost($url, $data)
{
$data = http_build_query(ChangePostData($data));
$opts = array(
'http' => array(
'method' => 'POST',
'header' => "Content-type: application/x-www-form-urlencoded\r\n" . "Content-Length: " . strlen($data) . "\r\n",
'content' => $data,
),
);
$context = stream_context_create($opts);
$ret = file_get_contents($url, false, $context);
$ret = trim($ret, "\xEF\xBB\xBF");
return $ret;
}
/**
* @note 从参数中过滤不需要的参数
* @param array|null $ignores 要过滤的参数列表(参数名)
* @param array|null $parameters 目标参数列表
* @return array
*/
function GetAttachParameters($ignores = null, $parameters = null)
{
$return = (array)(empty($parameters) ? $_REQUEST : $parameters);
if (!empty($ignores))
{
foreach ($return as $k => $v)
{
if (in_array($k, $ignores))
unset($return[$k]);
}
}
return $return;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,354 @@
.body_bg {
background-color: #f1f1f1;
}
.body_bg > .yl_logo {
margin: 0 auto;
padding: 5% 20px;
text-align: center;
position: relative;
}
.body_bg > .yl_logo > img {
display: inline-block;
height: 45px;
}
.s_row {
position: relative;
margin: 0 auto 20px auto;
text-align: center;
width: 90%;
overflow: hidden;
}
.s_row .img_tb {
width: 15%;
height: 31px;
position: relative;
clear: both;
}
.s_row .img_tb img {
width: 22px;
height: 27px;
}
.s_row .img_tb img,
.s_row > input {
float: left;
}
.s_row > input {
display: block;
position: relative;
height: 31px;
padding: 12px 10px;
border-top: none;
border-left: none;
border-right: none;
border-bottom: 1px solid #bcbcbc;
line-height: 40px;
font-size: 16px;
color: #666;
background-color: #f1f1f1;
outline: 0;
margin-left: 5%;
width: 85%;
}
.s_row .duanxin {
margin-left: 11%;
width: 60%;
}
.s_row .huoqu {
background-color: #02a7f1;
border: 1px solid #02a7f1;
color: #ffffff;
position: absolute;
top: 0;
right: 3%;
padding: 6px 14px;
}
.dr_btn {
text-align: center;
}
.dr_btn .btn {
width: 90%;
padding: 10px;
margin-bottom: 20px;
}
.dr_btn .btn-danger {
background-color: #cb4c02;
border: 1px solid #cb4c02;
}
.dr_btn .btn-info {
background-color: #5c8ceb;
border: 1px solid #5c8ceb;
margin-top: 18%;
}
.dr_btn .btn-info:hover,
.dr_btn .btn-info:active,
.dr_btn .btn-info:active:hover {
background-color: #5174c7;
border: 1px solid #5c8ceb;
}
.dr_btn .btn-default {
background-color: #969696;
border: 1px solid #969696;
color: #ffffff;
}
.dr_btn .btn-green {
background-color: #1aab19;
border: 1px solid #129b0e;
}
.dr_btn .btn-blue {
background-color: #039bdd;
border: 1px solid #039bdd;
}
.dr_btn .btn-green,
.dr_btn .btn-blue {
font-size: 20px;
color: #ffffff;
}
.wx {
margin-top: 6%;
}
.wj_row {
text-align: center;
width: 90%;
margin: 0 auto 20% auto;
}
.wj_row a {
color: #7b94f1;
}
.wj_row .wjmm {
text-align: left;
display: inherit;
float: left;
}
.wj_row .zczh {
text-align: right;
display: inline-block;
float: right;
}
.sigma-content {
text-align: center;
background-color: #f1f1f1;
position: relative;
color: #bfbfbf;
width: 90%;
margin: 0 auto;
}
.sigma-middle-line:before {
content: '';
display: block;
height: 1px;
width: 100%;
background-color: #bfbfbf; /*颜色需与主题大背景色一致*/
position: relative;
top: 10px; /*调节线高*/
left: 0;
}
.sigma-line-text {
display: inline-block;
background: #f1f1f1;
padding: 0 18px 0 18px;
position: relative;
font-size: 14px;
font-weight: 500;
}
.fangshi {
width: 80%;
margin: 8% auto;
position: relative;
overflow: hidden;
}
.fangshi .box {
float: left;
width: 18.1%;
margin-left: 4.5%;
margin-right: 4.5%;
text-align: center;
color: #787878;
margin-bottom: 20px;
}
.fangshi .box:first-child {
margin-left: 0;
}
.fangshi .box:last-child {
margin-right: 0;
}
.fangshi .box img {
display: block;
max-width: 100%;
height: auto;
margin: 0 auto 5px auto;
}
.fangshi .box:active {
color: red;
font-size: 12px;
}
.fangshi .box:active img {
padding: 3px;
}
/**/
.hui {
color: #787878;
font-size: 16px;
line-height: 1.8;
}
.w_tongy {
height: 40px;
}
.w_tongy > input[type=checkbox] {
width: 5%;
}
.w_tongy .xieyi {
margin-left: 5%;
line-height: 2.8;
float: left;
color: #666;
}
.w_tongy .xieyi .red {
color: red;
}
.huoqu_duanxin {
height: 35px;
overflow: auto;
}
.neirong{
/* padding-top: 40px; */
}
.neirong ul{
/* padding-top: 15px; */
list-style-type: none;
padding-left: 0;
}
.neirong ul li{
padding: 12px 0;
/*text-align: center;*/
}
.neirong ul li .name{
text-align: right;
width: 98px;
display: inline-block;
}
.neirong ul li .input{
height: 35px;
line-height: 35px;
width: 63%;
border: none;
outline: none;
border-bottom: 1px solid #d8d8d8;
}
.red{color:red;}
.text-center{text-align: center;}
.btn{
display: inline-block;
padding: 8px 14px;
margin-bottom: 0;
font-size: 14px;
font-weight: 400;
line-height: 1.42857143;
text-align: center;
white-space: nowrap;
vertical-align: middle;
-ms-touch-action: manipulation;
touch-action: manipulation;
cursor: pointer;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
background-image: none;
border: 1px solid transparent;
/*border-radius: 4px;*/
text-decoration: none;
}
.btn-blue{
color: #fff;
background: -moz-linear-gradient(top, #41b8ff, #0b53bb);
background: -webkit-gradient(linear,0% 0%,0% 100%,from(#41b8ff),to(#0b53bb));
background: -webkit-linear-gradient(top, #41b8ff, #0b53bb);
background: -o-linear-gradient(top, #41b8ff, #0b53bb);
background: -ms-linear-gradient(top, #41b8ff, #0b53bb);
border-color: rgb(253, 253, 254);
}
.foot_btn{
width: 45%;
margin-top: 25px;
height: 32px;
line-height: 32px;
border-radius: 6px;
}
@media screen and (device-width: 320px) and (device-height: 568px) and (-webkit-device-pixel-ratio: 2) {
.s_row .duanxin {
margin-left: 14%;
}
.s_row .huoqu {
right: 1%;
}
}
@media screen and (device-width: 768px) and (device-height: 1024px) and (-webkit-device-pixel-ratio: 2) {
.s_row .duanxin {
margin-left: 8.5%;
}
.s_row .huoqu {
right: 2%;
}
.s_row > input {
width: 90%;
}
.neirong ul li .input{
width: 84%;
}
}
@media screen and (device-width: 1024px) and (device-height: 1366px) and (-webkit-device-pixel-ratio: 2)
{
.neirong ul li .input{
width: 84%;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 477 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 467 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 682 B

View File

@@ -0,0 +1,216 @@
//var g_appid = '14919772144482';
//var g_devkey = '14915485974028';
var g_RequestAddress = 'https://api2.tscce.cn';
/**
* @note 字符串格式化
* @param fn_objs
* @returns object
* @constructor
*/
Overload = function (fn_objs) {
var is_match = function (x, y) {
if (x == y) {
return true;
}
if (x.indexOf("*") == -1) {
return false;
}
var x_arr = x.split(","), y_arr = y.split(",");
if (x_arr.length != y_arr.length) {
return false;
}
while (x_arr.length) {
var x_first = x_arr.shift(), y_first = y_arr.shift();
if (x_first != "*" && x_first != y_first) {
return false;
}
}
return true;
};
var ret = function () {
var args = arguments
, args_len = args.length
, args_types = []
, args_type
, fn_objs = args.callee._fn_objs
, match_fn = function () {
};
for (var i = 0; i < args_len; i++) {
var type = typeof args[i];
type == "object" && (args[i].length > -1) && (type = "array");
args_types.push(type);
}
args_type = args_types.join(",");
for (var k in fn_objs) {
if (is_match(k, args_type)) {
match_fn = fn_objs[k];
break;
}
}
return match_fn.apply(this, args);
};
ret._fn_objs = fn_objs;
return ret;
};
/**
* 通过对字符串进行伪重载实现对字符串对象的格式化功能
* @type {Object}
*/
String.prototype.format = Overload({
"array": function (params) {
var reg = /{(\d+)}/gm;
return this.replace(reg, function (match, name) {
return params[~~name];
});
},
"object": function (param) {
var reg = /{([^{}]+)}/gm;
return this.replace(reg, function (match, name) {
return param[name];
});
}
});
function getQueryString(name) {
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
var r = window.location.search.substr(1).match(reg);
if (r != null) {
return r[2];
}
return null;
}
//------------设置Cookie参数方法------------//
function setCookie(name, value) {
var Days = 30; //此 cookie 将被保存 30 天
var exp = new Date();
exp.setTime(exp.getTime() + Days * 24 * 60 * 60 * 1000);
document.cookie = name + "=" + value + ";expires=" + exp.toGMTString();
}
//------------获取Cookie参数方法------------//
function getCookie(name) {
var arr = document.cookie.match(new RegExp("(^| )" + name + "=([^;]*)(;|$)"));
if (arr != null) {
return arr[2];
}
return null;
}
//------------删除Cookie参数方法------------//
function delCookie(name) {
var exp = new Date();
exp.setTime(exp.getTime() - 1);
var cval = getCookie(name);
if (cval != null) {
document.cookie = name + "=" + cval + ";expires=" + exp.toGMTString();
}
}
/**
* 获取随机数
*/
function randomChar(length) {
var x = "0123456789qwertyuioplkjhgfdsazxcvbnm";
var tmp = "";
var timestamp = new Date().getTime();
for (var i = 0; i < length; i++) {
tmp += x.charAt(Math.ceil(Math.random() * 100000000) % x.length);
}
return timestamp + tmp;
}
function localeUrl() {
var url = window.location.origin + window.location.pathname;
var index = url.indexOf('?');
if (-1 == index)
return url;
else
return name.substr(0, index);
}
function extractPath(name) {
var index = name.lastIndexOf('/');
if (-1 == index)
return name;
else
return name.substr(0, index + 1);
}
function HttpRequest(args) {
var defaults =
{
url: g_RequestAddress,
async: true,
OnBeforeSend: function (/*XMLHttpRequest*/object) { },
OnComplete: function (/*XMLHttpRequest, textStatus*/object, status) { },
OnSuccess: function (/*data, textStatus*/message, status) { },
OnError: function (/*XMLHttpRequest, textStatus, errorThrown*/object, status, error) { },
},
settings = $.extend({}, defaults, args);
var data = {};
$.each(settings, function (name, value) {
if (
'async' != name &&
'url' != name &&
'OnBeforeSend' != name &&
'OnComplete' != name &&
'OnSuccess' != name &&
'OnError' != name
) {
data[name] = value;
}
});
//var succ = function (/*data, textStatus*/message, status) {
// var obj = eval("(" + decodeURIComponent(message) + ")");
// if (!obj) {
// //alert('pager6');
// window.location.href = PAGENAME_LOGIN + "?manager_id=" + getCookie(g_managerid);
// return false;
// }
// else if (1 == obj.error && 10008 == obj.error_code) {
// //alert('pager7');
// window.location.href = PAGENAME_LOGIN + "?manager_id=" + getCookie(g_managerid);
// return false;
// }
// else {
// return settings.OnSuccess(message, status);
// }
//};
$.ajax({
url: settings.url,
type: 'post',
async: settings.async,
data: data,
datatype: 'json',
timeout: 1000 * 7,
beforeSend: settings.OnBeforeSend,
success: settings.OnSuccess,
//success: succ,
error: settings.OnError,
complete: settings.OnComplete,
});
return settings;
}

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,9 @@
<?php
/// 支付的回调通知页面
$data = file_get_contents('php://input');
file_put_contents(dirname(__FILE__) . '/paylog.txt', $data);
/// 返回success表示成功接收到了回调通知
die('success');

View File

@@ -0,0 +1,37 @@
<?php
// file_put_contents('c:/1.txt', json_encode($_REQUEST));
if(!isset($_GET['v']))
die('没有v参数');
$v = json_decode($_GET['v'], true);
if(!isset($v['url']))
die('没有地址');
if(!isset($v['params']))
die('没有参数');
//file_put_contents('pay.txt', $_GET['v'].PHP_EOL, FILE_APPEND);
// "order_no":"PE164695201711041021473796","out_trade_no":"bd30509462e0b38c0ef2aa32a576b2ad","transaction_id":"4200000004201711042338031287"
if(isset($_POST['out_trade_no']))
$v['params']['biz_content']['outtradeno'] = $_POST['out_trade_no'];
if(isset($_POST['transaction_id']))
$v['params']['biz_content']['transactionid'] = $_POST['transaction_id'];
//file_put_contents('pay.txt', json_encode($v['params']).PHP_EOL, FILE_APPEND);
$param = http_build_query($v['params']);
$opts = array(
'http' => array(
'method' => 'POST',
'header' => "Content-type: application/x-www-form-urlencoded\r\n" . "Content-Length: " . strlen($param) . "\r\n",
'content' => $param)
);
$context = stream_context_create($opts);
$ret = file_get_contents($v['url'], false, $context);
print_r($ret);

View File

@@ -0,0 +1,23 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<link href="css/style.css" rel="stylesheet">
<link href="css/bootstrap.min.css" rel="stylesheet">
<title>登录</title>
</head>
<body class="body_bg">
<header class="yl_logo">
<img src="img/yl.png" class="img-responsive">
</header>
<div class="container-fluid">
<div class="dr_btn">
<a href="javascript:;" class="btn btn-green wx">微信支付</a>
</div>
<div class="dr_btn">
<a href="javascript:;" class="btn btn-blue">支付宝支付</a>
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,516 @@
<?php
require_once dirname(__FILE__) . '/phpqrcode/merged/phpqrcode.php';
require_once dirname(__FILE__) . '/common.php';
define('DEFAULT_MARKET_KEY', '0000'); /// 默认的门店
define('DEFAULT_SIGN_KEY', '0000'); /// 默认的签名key
/**
* @note 提取请求参数
* @param array $Parameters 参数列表
* @param string $Name 参数名
* @param string $Default 当没有取到时,使用的默认值
* @return string
*/
function GetRequestParameter($Parameters, $Name, $Default = '') {
if (isset($Parameters[$Name]) && !empty($Parameters[$Name]))
return strval($Parameters[$Name]);
else
return isset($_REQUEST[$Name]) ? $_REQUEST[$Name] : $Default;
}
$LoginUrl = getFullUrl('/source/login/login.php'); /// 登录接口地址
$QueryPayUrl = getFullUrl('/api/newpay/querylist/'); /// 查询接口
$OnlinePayUrl = getFullUrl('/api/newpay/pay/online/'); /// 线上支付接口地址
$OfflinePayUrl = getFullUrl('/api/newpay/pay/offline/'); /// 线下支付接口地址
/// 是否二维码
$is_qrcode = isset($_REQUEST['is_qrcode']) ? $_REQUEST['is_qrcode'] : '';
if (strcasecmp('y', $is_qrcode) == 0 || 0 != intval($is_qrcode)) {
/// 需要二维码则以本页面地址生成二维码
//$url = GetLocaleUrl();
$url = '';
foreach ($_REQUEST as $k => $v) {
if (strcasecmp('is_qrcode', $k) == 0) continue;
$url .= "&{$k}={$v}";
}
if (empty($url))
$url = GetLocaleUrl();
else {
$sublen = mb_strlen('&', USEDCHARSET);
$url = GetLocaleUrl() . '?' . mb_substr($url, $sublen, mb_strlen($url, USEDCHARSET) - $sublen, USEDCHARSET);
}
$local_path = dirname(__FILE__);
$short_name = '/qrcodeimg/' . date('YmdHis') . '.png';
$logo_name = $local_path . '/img/qr_logo.png';
$long_name = $local_path . $short_name;
QRcode::png($url, $long_name, QR_ECLEVEL_L, 8, 2);
/// 合并二维码和logo图片
$img = imagecreatefromstring(file_get_contents($long_name));
$logo = imagecreatefromstring(file_get_contents($logo_name));
if ($img && $logo) {
$img_width = imagesx($img); /// 二维码图片宽度
$img_height = imagesy($img); /// 二维码图片高度
$logo_width = imagesx($logo); /// logo图片宽度
$logo_height = imagesy($logo); /// logo图片高度
$logo_qr_width = $img_width / 6;
$scale = $logo_width / $logo_qr_width;
$logo_qr_height = $logo_height / $scale;
$from_width = ($img_width - $logo_qr_width) / 2;
/// 重新组合图片并调整大小
imagecopyresampled($img, $logo, $from_width, $from_width, 0, 0, $logo_qr_width, $logo_qr_height, $logo_width, $logo_height);
/// 输出图片
header('Content-type: image/png');
imagepng($img);
imagedestroy($logo);
imagedestroy($img);
}
///$img_link = dirname(GetLocaleUrl()) . $short_name;
///echo "<center><a href=\"{$img_link}\"><img src=\"{$img_link}\"></a><br /><font size=\"20\">在线支付</font></center>";
unlink($long_name);
exit;
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<link href="css/style.css" rel="stylesheet">
<!-- <link href="css/bootstrap.min.css" rel="stylesheet">-->
<script src="js/jquery-2.1.4.min.js"></script>
<script src="js/common.js"></script>
</head>
<body class="body_bg" id="mainbody">
<header class="yl_logo">
<!--<img src="img/yl.png" class="img-responsive">-->
</header>
<script type="text/javascript">
function id(x) {
if (typeof x == "string")
return document.getElementById(x);
else
return x;
}
</script>
<?php
/// 所有参数
$attach = (array)json_decode(rawurldecode(GetRequestParameter(null, 'attach')));
//if (!empty($attach)) var_dump($attach);
/// sid
$sid = GetRequestParameter($attach, 'sid');
/// scode
$scode = GetRequestParameter($attach, 'scode');
/// app_id
$app_id = GetRequestParameter($attach, 'app_id');
/// 开发者key
$dev_key = GetRequestParameter($attach, 'dev_key');
/// 门店key
$market_key = GetRequestParameter($attach, 'market_key');
/// 支付金额(分)
$fee = GetRequestParameter($attach, 'fee');
/// 支付标题
$title = GetRequestParameter($attach, 'title');
/// 订单号
$order_id = GetRequestParameter($attach, 'order_id', md5(date('YmdHis') . rand(1000, 9999)));
/// 回调地址(异步)
$notice_url = GetRequestParameter($attach, 'notice_url');
/// 回调地址(同步)
$return_url = GetRequestParameter($attach, 'return_url', isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : GetLocaleUrl());
/// 是否静默授权
$silence = intval(GetRequestParameter($attach, 'silence', '0'));
/// 签名用的key目前支付不做校验退款才会校验签名。
/// 具体的签名算法见详细代码。
$sign_key = GetRequestParameter($attach, 'sign_key', DEFAULT_SIGN_KEY);
$pay_type = GetRequestParameter($attach, 'paytype', -1);
if (empty($app_id)) {
echo '没有指定app_id参数';
} elseif (empty($dev_key)) {
echo '没有指定dev_key参数';
} elseif (empty($market_key)) {
echo '没有指定market_key参数';
} elseif (empty($notice_url)) {
echo '没有指定notice_url参数';
} elseif (empty($sid) || empty($scode)) { /// 判断是否有sid和scode, 什么数据都没有则先跳转到登录页面授权
$attach = json_encode(GetAttachParameters(array('attach', 'is_qrcode',)));
$redirect_uri = rawurlencode(getFullUrl('/source/pay/pay.php'));
$url = $LoginUrl . "?app_id={$app_id}&dev_key={$dev_key}&market_key={$market_key}&silence={$silence}&redirect_uri={$redirect_uri}&attach={$attach}";
header("Location: {$url}");
exit;
} else {
if (empty($fee)) { /// 有sid和scode 但是 没有fee 则要求页面输入并提交fee参数
$param = '';
foreach ($attach as $k => $v) {
$param .= " \" <input name='{$k}' type='text' value='{$v}' />\" + " . PHP_EOL;
}
$attach = GetAttachParameters(array('attach', 'is_qrcode',));
foreach ($attach as $k => $v) {
$param .= " \" <input name='{$k}' type='text' value='{$v}' />\" + " . PHP_EOL;
}
$html = <<<EOL
<script>
function submit() {
var fee = document.getElementById('fee').value;
if ('' == fee || undefined == fee) {
alert('请输入要支付的金额(单位为分)');
return;
}
var script =
"<form style='display:none;' id='frm' name='frm' method='post' action=''>" +
" <input name='fee' type='text' value='" + fee + "' />" + /// 支付金额(单位分)
{$param}"</form>";
$('#mainbody').append(script);
$('#frm').submit();
}
</script>
<section>
<div class="neirong">
<ul>
<li><span class="name">总金额:</span><input id="fee" type="text" autofocus placeholder="单位:分" class="input"> <sapn class="red">*</sapn></li>
</ul>
<footer class="text-center"><a href="javascript:;" onclick="submit();" class="btn btn-blue foot_btn">确定</a></footer>
</div>
</section>
EOL;
} elseif (-1 == $pay_type) { /// 有fee参数表示已提交页面中输入的支付金额, pay_type=-1 表示没有指定支付方式
/// 获取附加参数
$ignore = array('sid','scode','app_id','dev_key','market_key','fee','title','order_id','notice_url','return_url','sign_key','is_qrcode','attach','paytype',);
$attach1 = GetAttachParameters($ignore, $attach);
$attach2 = GetAttachParameters($ignore);
$attach = $attach1 + $attach2;
/// 通过接口获取门店所支援的支付方式
$data = array(
'appid' => $app_id, /// appid
'devkey' => $dev_key, /// 开发者key
'market_key' => $market_key, /// 门店key
'level' => 1, /// 支付类型(1: 线上, 2: 扫码, 3: app)
'version' => 1,/// 版本号
);
$data['sign'] = SignParameter($data, $sign_key); /// 生成签名
$result = new ResultObject(rawurldecode(SendPost($QueryPayUrl, $data)));
if (0 == $result->error && count($result->data) > 0) { /// 成功
/// 获取详细的支付接口信息,这里区分是微信还是支付宝,每种方式只取第一种
$wechat = null; /// 微信限定
$alipay = null; /// 支付宝限定
$browser = null; /// 浏览器限定
foreach ($result->data as $item) {
if (mb_strstr($item->third_flag, 'wechat', false, USEDCHARSET)) { /// 包含wechat表示都是各种类型的微信支付
if (empty($wechat)) $wechat = $item;
} elseif (mb_strstr($item->third_flag, 'alipay', false, USEDCHARSET)) { /// 包含alipay表示都是各种类型的支付宝支付
if (empty($alipay)) $alipay = $item;
} else {
if (empty($browser)) $browser = $item;
}
}
if (empty($wechat) && empty($alipay) && empty($browser)) {
$html = <<<EOL
<script>
alert('该门店不支援任何的支付方式!');
</script>
EOL;
} else {
$wechatform = '';
$alipayform = '';
$browserform = '';
$wechathtml = '';
$alipayhtml = '';
$browserhtml = '';
$iswechat = !empty(strpos($_SERVER['HTTP_USER_AGENT'], 'MicroMessenger'));
$button_style = array(false => 'style="display:none;"', true => '',);
if (!empty($wechat)) {
/// 支付要用的参数
$data = $attach + array(
'appid' => $app_id, /// appid
'devkey' => $dev_key, /// 开发者key
'sid' => $sid, /// sid
'scode' => $scode, /// scode
'orderid' => $order_id, /// 订单号
'fee' => $fee, /// 支付金额(单位分)
'title' => $title, /// 支付标题
'notice_url' => $notice_url, /// 回调页面地址(异步)
'return_url' => $return_url, /// 回调页面地址(同步)
'paytype' => $wechat->type_id, /// 支付类型(可通过接口获取所有支持的类型列表)
'version' => 1, /// 接口版本号, 整型, 目前只支持1
);
$data['sign'] = SignParameter($data, $sign_key); /// 生成签名
/// ==== ↓生成form表单↓ ====
$wechatform = '<form style="display:none;" id="wechatform" name="wechatform" method="post" action="' . $OnlinePayUrl . '">' . PHP_EOL;
foreach ($data as $k => $v) {
$wechatform .= sprintf(' <input name="%s" type="text" value=\'%s\' />', $k, $v) . PHP_EOL;
}
$wechatform .= '</form>';
/// ==== ↑生成form表单↑ ====
$wechathtml = <<<EOL
<div class="dr_btn">
<button id='btnWechat' onclick='wechatform.submit();' class="btn btn-green wx" {$button_style[$iswechat]}>微信支付</button>
</div>
EOL;
}
if (!empty($alipay)) {
/// 支付要用的参数
$data = $attach + array(
'appid' => $app_id, /// appid
'devkey' => $dev_key, /// 开发者key
'sid' => $sid, /// sid
'scode' => $scode, /// scode
'orderid' => $order_id, /// 订单号
'fee' => $fee, /// 支付金额(单位分)
'title' => $title, /// 支付标题
'notice_url' => $notice_url, /// 回调页面地址(异步)
'return_url' => $return_url, /// 回调页面地址(同步)
'paytype' => $alipay->type_id, /// 支付类型(可通过接口获取所有支持的类型列表)
'version' => 1, /// 接口版本号, 整型, 目前只支持1
);
$data['sign'] = SignParameter($data, $sign_key); /// 生成签名
$alipayform = '<form style="display:none;" id="alipayform" name="alipayform" method="post" action="' . $OnlinePayUrl . '">' . PHP_EOL;
foreach ($data as $k => $v) {
$alipayform .= sprintf(' <input name="%s" type="text" value=\'%s\' />', $k, $v) . PHP_EOL;
}
$alipayform .= '</form>';
$alipayhtml = <<<EOL
<div class="dr_btn">
<button id='btnAlipay' onclick="alipayform.submit();" class="btn btn-blue" {$button_style[!$iswechat]}>支付宝支付</button>
</div>
EOL;
}
if (!empty($browser)) {
/// 支付要用的参数
$data = $attach + array(
'appid' => $app_id, /// appid
'devkey' => $dev_key, /// 开发者key
'sid' => $sid, /// sid
'scode' => $scode, /// scode
'orderid' => $order_id, /// 订单号
'fee' => $fee, /// 支付金额(单位分)
'title' => $title, /// 支付标题
'notice_url' => $notice_url, /// 回调页面地址(异步)
'return_url' => $return_url, /// 回调页面地址(同步)
'paytype' => $browser->type_id, /// 支付类型(可通过接口获取所有支持的类型列表)
'version' => 1, /// 接口版本号, 整型, 目前只支持1
);
$data['sign'] = SignParameter($data, $sign_key); /// 生成签名
$browserform = '<form style="display:none;" id="browserform" name="browserform" method="post" action="' . $OnlinePayUrl . '">' . PHP_EOL;
foreach ($data as $k => $v) {
$browserform .= sprintf(' <input name="%s" type="text" value=\'%s\' />', $k, $v) . PHP_EOL;
}
$browserform .= '</form>';
$browserhtml = <<<EOL
<div class="dr_btn">
<button id='btnBrowser' onclick="browserform.submit();" class="btn btn-green" {$button_style[!$iswechat]}>立即支付</button>
</div>
EOL;
}
/*
if (empty($wechat))
$html = <<<EOL
{$alipayform}
<script>
alipayform.submit();
</script>
EOL;
elseif (empty($alipay))
$html = <<<EOL
{$wechatform}
<script>
wechatform.submit();
</script>
EOL;
else
*/
$html = <<<EOL
{$wechatform}
{$alipayform}
{$browserform}
<div class="container-fluid">
{$wechathtml}
{$alipayhtml}
{$browserhtml}
</div>
<script>
/// 是否微信打开
function is_wechat() {
return 'undefined' != typeof WeixinJSBridge;
}
///
function callAlipay() {
if (is_wechat())
return;
var btnAlipay = id('btnAlipay');
if (btnAlipay)
btnAlipay.onclick();
else
alert('该门店不支援任何的支付方式!');
}
$(function() {
var btnWechat = id('btnWechat');
var btnAlipay = id('btnAlipay');
var btnBrowser = id('btnBrowser');
if (!btnWechat && !btnAlipay && !btnBrowser) {
alert('该门店不支援任何的支付方式!');
return;
}
/// 判断是否包含WeixinJSBridge对象,包含则表示在微信环境中.
if ('undefined' == typeof WeixinJSBridge) {
/// WeixinJSBridgeReady事件处理.
$(document).on('WeixinJSBridgeReady', function() {
if (btnWechat) {
//btnWechat.style.display = 'initial';
btnWechat.onclick();
} else {
alert('该门店不支援任何的支付方式!');
return;
}
if (btnAlipay) {
btnAlipay.style.display = 'none';
}
if (btnBrowser) {
btnBrowser.style.display = 'none';
}
});
/*
/// 这里要判断其他环境.
/// 这里暂时用user-agent标志来判断是否处于微信环境中(包含micromessenger标识则表示为微信环境.).
/// 如果包含微信的标识则不去处理支付宝了.
var ua = navigator.userAgent.toLowerCase();
if (ua.match(/MicroMessenger/i) == "micromessenger") {
///return true;
/// 包含micromessenger标识则表示为微信环境
} else {
///return false;
/// 不包含micromessenger标识则表示为其他环境
setTimeout('callAlipay();', 1000); /// 延迟1秒
}
*/
} else {
if (btnWechat) {
//btnWechat.style.display = 'initial';
btnWechat.onclick();
} else {
alert('该门店不支援任何的支付方式!');
return;
}
if (btnAlipay) {
btnAlipay.style.display = 'none';
}
if (btnBrowser) {
btnBrowser.style.display = 'none';
}
}
});
</script>
EOL;
}
} elseif (0 != $result->error) { /// 有错误发生
$html = <<<EOL
<script>
alert('{$result->msg}');
</script>
EOL;
} else {
$html = <<<EOL
<script>
alert('该门店不支援任何的支付方式!');
</script>
EOL;
}
} else { /// $pay_type != -1 表示指定了支付方式
/// 获取附加参数
$ignore = array('sid','scode','app_id','dev_key','market_key','fee','title','order_id','notice_url','return_url','sign_key','is_qrcode','attach','paytype',);
$attach1 = GetAttachParameters($ignore, $attach);
$attach2 = GetAttachParameters($ignore);
$attach = $attach1 + $attach2;
/// 支付要用的参数
$data = $attach + array(
'appid' => $app_id, /// appid
'devkey' => $dev_key, /// 开发者key
'sid' => $sid, /// sid
'scode' => $scode, /// scode
'orderid' => $order_id, /// 订单号
'fee' => $fee, /// 支付金额(单位分)
'title' => $title, /// 支付标题
'notice_url' => $notice_url, /// 回调页面地址(异步)
'return_url' => $return_url, /// 回调页面地址(同步)
'paytype' => $pay_type, /// 支付类型(可通过接口获取所有支持的类型列表)
'version' => 1, /// 接口版本号, 整型, 目前只支持1
);
$data['sign'] = SignParameter($data, $sign_key); /// 生成签名
$frmpay = '<form style="display:none;" id="frmpay" name="frmpay" method="post" action="' . $OnlinePayUrl . '">' . PHP_EOL;
foreach ($data as $k => $v) {
$frmpay .= sprintf(' <input name="%s" type="text" value=\'%s\' />', $k, $v) . PHP_EOL;
}
$frmpay .= '</form>';
$html = <<<EOL
{$frmpay}
<script language=javascript>
frmpay.submit();
</script>
EOL;
}
echo $html;
}
?>
</body>
</html>

View File

@@ -0,0 +1,470 @@
<?php
require_once dirname(__FILE__) . '/phpqrcode/merged/phpqrcode.php';
require_once dirname(__FILE__) . '/common.php';
define('DEFAULT_MARKET_KEY', 'test'); /// 默认的门店
define('DEFAULT_SIGN_KEY', 'test'); /// 默认的签名key
/**
* @note 提取请求参数
* @param array $Parameters 参数列表
* @param string $Name 参数名
* @param string $Default 当没有取到时,使用的默认值
* @return string
*/
function GetRequestParameter($Parameters, $Name, $Default = '') {
if (isset($Parameters[$Name]) && !empty($Parameters[$Name]))
return strval($Parameters[$Name]);
else
return isset($_REQUEST[$Name]) ? $_REQUEST[$Name] : $Default;
}
/// 是否二维码
$is_qrcode = isset($_REQUEST['is_qrcode']) ? $_REQUEST['is_qrcode'] : '';
if (strcasecmp('y', $is_qrcode) == 0 || 0 != intval($is_qrcode)) {
/// 需要二维码则以本页面地址生成二维码
//$url = GetLocaleUrl();
$url = '';
foreach ($_REQUEST as $k => $v) {
if (strcasecmp('is_qrcode', $k) == 0) continue;
$url .= "&{$k}={$v}";
}
if (empty($url))
$url = GetLocaleUrl();
else {
$sublen = mb_strlen('&', USEDCHARSET);
$url = GetLocaleUrl() . '?' . mb_substr($url, $sublen, mb_strlen($url, USEDCHARSET) - $sublen, USEDCHARSET);
}
$local_path = dirname(__FILE__);
$short_name = '/qrcodeimg/' . date('YmdHis') . '.png';
$logo_name = $local_path . '/img/qr_logo.png';
$long_name = $local_path . $short_name;
QRcode::png($url, $long_name, QR_ECLEVEL_L, 8, 2);
/// 合并二维码和logo图片
$img = imagecreatefromstring(file_get_contents($long_name));
$logo = imagecreatefromstring(file_get_contents($logo_name));
if ($img && $logo) {
$img_width = imagesx($img); /// 二维码图片宽度
$img_height = imagesy($img); /// 二维码图片高度
$logo_width = imagesx($logo); /// logo图片宽度
$logo_height = imagesy($logo); /// logo图片高度
$logo_qr_width = $img_width / 6;
$scale = $logo_width / $logo_qr_width;
$logo_qr_height = $logo_height / $scale;
$from_width = ($img_width - $logo_qr_width) / 2;
/// 重新组合图片并调整大小
imagecopyresampled($img, $logo, $from_width, $from_width, 0, 0, $logo_qr_width, $logo_qr_height, $logo_width, $logo_height);
/// 输出图片
header('Content-type: image/png');
imagepng($img);
imagedestroy($logo);
imagedestroy($img);
}
///$img_link = dirname(GetLocaleUrl()) . $short_name;
///echo "<center><a href=\"{$img_link}\"><img src=\"{$img_link}\"></a><br /><font size=\"20\">在线支付</font></center>";
unlink($long_name);
exit;
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<link href="css/style.css" rel="stylesheet">
<!-- <link href="css/bootstrap.min.css" rel="stylesheet">-->
<script src="js/jquery-2.1.4.min.js"></script>
<script src="js/common.js"></script>
</head>
<body class="body_bg" id="mainbody">
<header class="yl_logo">
<!--<img src="img/yl.png" class="img-responsive">-->
</header>
<script type="text/javascript">
function id(x) {
if (typeof x == "string")
return document.getElementById(x);
else
return x;
}
</script>
<?php
/// 所有参数
$attach = (array)json_decode(rawurldecode(GetRequestParameter(null, 'attach')));
//if (!empty($attach)) var_dump($attach);
/// sid
$sid = GetRequestParameter($attach, 'sid');
/// scode
$scode = GetRequestParameter($attach, 'scode');
/// app_id
$app_id = GetRequestParameter($attach, 'app_id');
/// 开发者key
$dev_key = GetRequestParameter($attach, 'dev_key');
/// 门店key
$market_key = GetRequestParameter($attach, 'market_key');
/// 支付金额(分)
$fee = GetRequestParameter($attach, 'fee');
/// 支付标题
$title = GetRequestParameter($attach, 'title');
/// 订单号
$order_id = GetRequestParameter($attach, 'order_id', md5(date('YmdHis') . rand(1000, 9999)));
/// 回调地址(异步)
$notice_url = GetRequestParameter($attach, 'notice_url');
/// 回调地址(同步)
$return_url = GetRequestParameter($attach, 'return_url', isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : GetLocaleUrl());
/// 是否静默授权
$silence = intval(GetRequestParameter($attach, 'silence', '0'));
/// 签名用的key目前支付不做校验退款才会校验签名。
/// 具体的签名算法见详细代码。
$sign_key = GetRequestParameter($attach, 'sign_key', DEFAULT_SIGN_KEY);
if (empty($app_id)) {
echo '没有指定app_id参数';
} elseif (empty($dev_key)) {
echo '没有指定dev_key参数';
} elseif (empty($market_key)) {
echo '没有指定market_key参数';
} elseif (empty($notice_url)) {
echo '没有指定notice_url参数';
} elseif (empty($sid) || empty($scode)) { /// 判断是否有sid和scode, 什么数据都没有则先跳转到登录页面授权
$attach = json_encode(GetAttachParameters(array('attach', 'is_qrcode',)));
$redirect_uri = rawurlencode(GetLocaleUrl());
$url = "https://api.tscce.cn/source/login/login.php?app_id={$app_id}&dev_key={$dev_key}&market_key={$market_key}&silence={$silence}&redirect_uri={$redirect_uri}&attach={$attach}";
header("Location: {$url}");
exit;
} else {
if (empty($fee)) { /// 有sid和scode 但是 没有fee 则要求页面输入并提交fee参数
$param = '';
foreach ($attach as $k => $v) {
$param .= " \" <input name='{$k}' type='text' value='{$v}' />\" + " . PHP_EOL;
}
$attach = GetAttachParameters(array('attach', 'is_qrcode',));
foreach ($attach as $k => $v) {
$param .= " \" <input name='{$k}' type='text' value='{$v}' />\" + " . PHP_EOL;
}
$html = <<<EOL
<script>
function submit() {
var fee = document.getElementById('fee').value;
if ('' == fee || undefined == fee) {
alert('请输入要支付的金额(单位为分)');
return;
}
var script =
"<form style='display:none;' id='frm' name='frm' method='post' action=''>" +
" <input name='fee' type='text' value='" + fee + "' />" + /// 支付金额(单位分)
{$param}"</form>";
$('#mainbody').append(script);
$('#frm').submit();
}
</script>
<section>
<div class="neirong">
<ul>
<li><span class="name">总金额:</span><input id="fee" type="text" autofocus placeholder="单位:分" class="input"> <sapn class="red">*</sapn></li>
</ul>
<footer class="text-center"><a href="javascript:;" onclick="submit();" class="btn btn-blue foot_btn">确定</a></footer>
</div>
</section>
EOL;
} else { /// 有fee参数表示已提交页面中输入的支付金额
/// 获取附加参数
$ignore = array('sid','scode','app_id','dev_key','market_key','fee','title','order_id','notice_url','return_url','sign_key','is_qrcode','attach',);
$attach1 = GetAttachParameters($ignore, $attach);
$attach2 = GetAttachParameters($ignore);
$attach = $attach1 + $attach2;
/// 通过接口获取门店所支援的支付方式
$data = array(
'appid' => $app_id, /// appid
'devkey' => $dev_key, /// 开发者key
'market_key' => $market_key, /// 门店key
'level' => 1, /// 支付类型(1: 线上, 2: 扫码, 3: app)
'version' => 1,/// 版本号
);
$data['sign'] = SignParameter($data, $sign_key); /// 生成签名
$result = new ResultObject(rawurldecode(SendPost('https://api.tscce.cn/api/newpay/querylist', $data)));
if (0 == $result->error && count($result->data) > 0) { /// 成功
/// 获取详细的支付接口信息,这里区分是微信还是支付宝,每种方式只取第一种
$wechat = null; /// 微信限定
$alipay = null; /// 支付宝限定
$browser = null; /// 浏览器限定
foreach ($result->data as $item) {
if (mb_strstr($item->third_flag, 'wechat', false, USEDCHARSET)) { /// 包含wechat表示都是各种类型的微信支付
if (empty($wechat)) $wechat = $item;
} elseif (mb_strstr($item->third_flag, 'alipay', false, USEDCHARSET)) { /// 包含alipay表示都是各种类型的支付宝支付
if (empty($alipay)) $alipay = $item;
} else {
if (empty($browser)) $browser = $item;
}
}
if (empty($wechat) && empty($alipay) && empty($browser)) {
$html = <<<EOL
<script>
alert('该门店不支援任何的支付方式!');
</script>
EOL;
} else {
$wechatform = '';
$alipayform = '';
$browserform = '';
$wechathtml = '';
$alipayhtml = '';
$browserhtml = '';
if (!empty($wechat)) {
/// 支付要用的参数
$data = $attach + array(
'appid' => $app_id, /// appid
'devkey' => $dev_key, /// 开发者key
'sid' => $sid, /// sid
'scode' => $scode, /// scode
'orderid' => $order_id, /// 订单号
'fee' => $fee, /// 支付金额(单位分)
'title' => $title, /// 支付标题
'notice_url' => $notice_url, /// 回调页面地址(异步)
'return_url' => $return_url, /// 回调页面地址(同步)
'paytype' => $wechat->type_id, /// 支付类型(可通过接口获取所有支持的类型列表)
'version' => 1, /// 接口版本号, 整型, 目前只支持1
);
$data['sign'] = SignParameter($data, $sign_key); /// 生成签名
/// ==== ↓生成form表单↓ ====
$wechatform = '<form style="display:none;" id="wechatform" name="wechatform" method="post" action="https://api.tscce.cn/api/newpay/pay/online/">' . PHP_EOL;
foreach ($data as $k => $v) {
$wechatform .= sprintf(' <input name="%s" type="text" value=\'%s\' />', $k, $v) . PHP_EOL;
}
$wechatform .= '</form>';
/// ==== ↑生成form表单↑ ====
$wechathtml = <<<EOL
<div class="dr_btn">
<button id='btnWechat' onclick='wechatform.submit();' class="btn btn-green wx" style="display:none;">微信支付</button>
</div>
EOL;
}
if (!empty($alipay)) {
/// 支付要用的参数
$data = $attach + array(
'appid' => $app_id, /// appid
'devkey' => $dev_key, /// 开发者key
'sid' => $sid, /// sid
'scode' => $scode, /// scode
'orderid' => $order_id, /// 订单号
'fee' => $fee, /// 支付金额(单位分)
'title' => $title, /// 支付标题
'notice_url' => $notice_url, /// 回调页面地址(异步)
'return_url' => $return_url, /// 回调页面地址(同步)
'paytype' => $alipay->type_id, /// 支付类型(可通过接口获取所有支持的类型列表)
'version' => 1, /// 接口版本号, 整型, 目前只支持1
);
$data['sign'] = SignParameter($data, $sign_key); /// 生成签名
$alipayform = '<form style="display:none;" id="alipayform" name="alipayform" method="post" action="https://api.tscce.cn/api/newpay/pay/online/">' . PHP_EOL;
foreach ($data as $k => $v) {
$alipayform .= sprintf(' <input name="%s" type="text" value=\'%s\' />', $k, $v) . PHP_EOL;
}
$alipayform .= '</form>';
$alipayhtml = <<<EOL
<div class="dr_btn">
<button id='btnAlipay' onclick="alipayform.submit();" class="btn btn-blue">支付宝支付</button>
</div>
EOL;
}
if (!empty($browser)) {
/// 支付要用的参数
$data = $attach + array(
'appid' => $app_id, /// appid
'devkey' => $dev_key, /// 开发者key
'sid' => $sid, /// sid
'scode' => $scode, /// scode
'orderid' => $order_id, /// 订单号
'fee' => $fee, /// 支付金额(单位分)
'title' => $title, /// 支付标题
'notice_url' => $notice_url, /// 回调页面地址(异步)
'return_url' => $return_url, /// 回调页面地址(同步)
'paytype' => $browser->type_id, /// 支付类型(可通过接口获取所有支持的类型列表)
'version' => 1, /// 接口版本号, 整型, 目前只支持1
);
$data['sign'] = SignParameter($data, $sign_key); /// 生成签名
$browserform = '<form style="display:none;" id="browserform" name="browserform" method="post" action="https://api.tscce.cn/api/newpay/pay/online/">' . PHP_EOL;
foreach ($data as $k => $v) {
$browserform .= sprintf(' <input name="%s" type="text" value=\'%s\' />', $k, $v) . PHP_EOL;
}
$browserform .= '</form>';
$browserhtml = <<<EOL
<div class="dr_btn">
<button id='btnBrowser' onclick="browserform.submit();" class="btn btn-green">立即支付</button>
</div>
EOL;
}
/*
if (empty($wechat))
$html = <<<EOL
{$alipayform}
<script>
alipayform.submit();
</script>
EOL;
elseif (empty($alipay))
$html = <<<EOL
{$wechatform}
<script>
wechatform.submit();
</script>
EOL;
else
*/
$html = <<<EOL
{$wechatform}
{$alipayform}
{$browserform}
<div class="container-fluid">
{$wechathtml}
{$alipayhtml}
{$browserhtml}
</div>
<script>
/// 是否微信打开
function is_wechat() {
return 'undefined' != typeof WeixinJSBridge;
}
///
function callAlipay() {
if (is_wechat())
return;
var btnAlipay = id('btnAlipay');
if (btnAlipay)
btnAlipay.onclick();
else
alert('该门店不支援任何的支付方式!');
}
$(function() {
var btnWechat = id('btnWechat');
var btnAlipay = id('btnAlipay');
var btnBrowser = id('btnBrowser');
if (!btnWechat && !btnAlipay && !btnBrowser) {
alert('该门店不支援任何的支付方式!');
return;
}
/// 判断是否包含WeixinJSBridge对象,包含则表示在微信环境中.
if ('undefined' == typeof WeixinJSBridge) {
/// WeixinJSBridgeReady事件处理.
$(document).on('WeixinJSBridgeReady', function() {
if (btnWechat) {
//btnWechat.style.display = 'initial';
btnWechat.onclick();
} else {
alert('该门店不支援任何的支付方式!');
return;
}
if (btnAlipay) {
btnAlipay.style.display = 'none';
}
if (btnBrowser) {
btnBrowser.style.display = 'none';
}
});
/*
/// 这里要判断其他环境.
/// 这里暂时用user-agent标志来判断是否处于微信环境中(包含micromessenger标识则表示为微信环境.).
/// 如果包含微信的标识则不去处理支付宝了.
var ua = navigator.userAgent.toLowerCase();
if (ua.match(/MicroMessenger/i) == "micromessenger") {
///return true;
/// 包含micromessenger标识则表示为微信环境
} else {
///return false;
/// 不包含micromessenger标识则表示为其他环境
setTimeout('callAlipay();', 1000); /// 延迟1秒
}
*/
} else {
if (btnWechat) {
//btnWechat.style.display = 'initial';
btnWechat.onclick();
} else {
alert('该门店不支援任何的支付方式!');
return;
}
if (btnAlipay) {
btnAlipay.style.display = 'none';
}
if (btnBrowser) {
btnBrowser.style.display = 'none';
}
}
});
</script>
EOL;
}
} elseif (0 != $result->error) { /// 有错误发生
$html = <<<EOL
<script>
alert('{$result->msg}');
</script>
EOL;
} else {
$html = <<<EOL
<script>
alert('该门店不支援任何的支付方式!');
</script>
EOL;
}
}
echo $html;
}
?>
</body>
</html>

View File

@@ -0,0 +1,468 @@
<?php
require_once dirname(__FILE__) . '/phpqrcode/merged/phpqrcode.php';
require_once dirname(__FILE__) . '/common.php';
define('DEFAULT_MARKET_KEY', 'test'); /// 默认的门店
define('DEFAULT_SIGN_KEY', 'test'); /// 默认的签名key
/**
* @note 提取请求参数
* @param array $Parameters 参数列表
* @param string $Name 参数名
* @param string $Default 当没有取到时,使用的默认值
* @return string
*/
function GetRequestParameter($Parameters, $Name, $Default = '') {
if (isset($Parameters[$Name]) && !empty($Parameters[$Name]))
return strval($Parameters[$Name]);
else
return isset($_REQUEST[$Name]) ? $_REQUEST[$Name] : $Default;
}
/// 是否二维码
$is_qrcode = isset($_REQUEST['is_qrcode']) ? $_REQUEST['is_qrcode'] : '';
if (strcasecmp('y', $is_qrcode) == 0 || 0 != intval($is_qrcode)) {
/// 需要二维码则以本页面地址生成二维码
//$url = GetLocaleUrl();
$url = '';
foreach ($_REQUEST as $k => $v) {
if (strcasecmp('is_qrcode', $k) == 0) continue;
$url .= "&{$k}={$v}";
}
if (empty($url))
$url = GetLocaleUrl();
else {
$sublen = mb_strlen('&', USEDCHARSET);
$url = GetLocaleUrl() . '?' . mb_substr($url, $sublen, mb_strlen($url, USEDCHARSET) - $sublen, USEDCHARSET);
}
$local_path = dirname(__FILE__);
$short_name = '/qrcodeimg/' . date('YmdHis') . '.png';
$logo_name = $local_path . '/img/qr_logo.png';
$long_name = $local_path . $short_name;
QRcode::png($url, $long_name, QR_ECLEVEL_L, 8, 2);
/// 合并二维码和logo图片
$img = imagecreatefromstring(file_get_contents($long_name));
$logo = imagecreatefromstring(file_get_contents($logo_name));
if ($img && $logo) {
$img_width = imagesx($img); /// 二维码图片宽度
$img_height = imagesy($img); /// 二维码图片高度
$logo_width = imagesx($logo); /// logo图片宽度
$logo_height = imagesy($logo); /// logo图片高度
$logo_qr_width = $img_width / 6;
$scale = $logo_width / $logo_qr_width;
$logo_qr_height = $logo_height / $scale;
$from_width = ($img_width - $logo_qr_width) / 2;
/// 重新组合图片并调整大小
imagecopyresampled($img, $logo, $from_width, $from_width, 0, 0, $logo_qr_width, $logo_qr_height, $logo_width, $logo_height);
/// 输出图片
header('Content-type: image/png');
imagepng($img);
imagedestroy($logo);
imagedestroy($img);
}
///$img_link = dirname(GetLocaleUrl()) . $short_name;
///echo "<center><a href=\"{$img_link}\"><img src=\"{$img_link}\"></a><br /><font size=\"20\">在线支付</font></center>";
unlink($long_name);
exit;
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<link href="css/style.css" rel="stylesheet">
<!-- <link href="css/bootstrap.min.css" rel="stylesheet">-->
<script src="js/jquery-2.1.4.min.js"></script>
<script src="js/common.js"></script>
</head>
<body class="body_bg" id="mainbody">
<header class="yl_logo">
<img src="img/yl.png" class="img-responsive">
</header>
<script type="text/javascript">
function id(x) {
if (typeof x == "string")
return document.getElementById(x);
else
return x;
}
</script>
<?php
/// 所有参数
$attach = (array)json_decode(rawurldecode(GetRequestParameter(null, 'attach')));
//if (!empty($attach)) var_dump($attach);
/// sid
$sid = GetRequestParameter($attach, 'sid');
/// scode
$scode = GetRequestParameter($attach, 'scode');
/// app_id
$app_id = GetRequestParameter($attach, 'app_id');
/// 开发者key
$dev_key = GetRequestParameter($attach, 'dev_key');
/// 门店key
$market_key = GetRequestParameter($attach, 'market_key');
/// 支付金额(分)
$fee = GetRequestParameter($attach, 'fee');
/// 支付标题
$title = GetRequestParameter($attach, 'title');
/// 订单号
$order_id = GetRequestParameter($attach, 'order_id', md5(date('YmdHis') . rand(1000, 9999)));
/// 回调地址(异步)
$notice_url = GetRequestParameter($attach, 'notice_url');
/// 回调地址(同步)
$return_url = GetRequestParameter($attach, 'return_url', isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : GetLocaleUrl());
/// 签名用的key目前支付不做校验退款才会校验签名。
/// 具体的签名算法见详细代码。
$sign_key = GetRequestParameter($attach, 'sign_key', DEFAULT_SIGN_KEY);
if (empty($app_id)) {
echo '没有指定app_id参数';
} elseif (empty($dev_key)) {
echo '没有指定dev_key参数';
} elseif (empty($market_key)) {
echo '没有指定market_key参数';
} elseif (empty($notice_url)) {
echo '没有指定notice_url参数';
} elseif (empty($sid) || empty($scode)) { /// 判断是否有sid和scode, 什么数据都没有则先跳转到登录页面授权
$attach = json_encode(GetAttachParameters(array('attach', 'is_qrcode',)));
$redirect_uri = rawurlencode(GetLocaleUrl());
$url = SITE_API_DOMAIN . "/source/login/login.php?app_id={$app_id}&dev_key={$dev_key}&market_key={$market_key}&redirect_uri={$redirect_uri}&attach={$attach}";
header("Location: {$url}");
exit;
} else {
if (empty($fee)) { /// 有sid和scode 但是 没有fee 则要求页面输入并提交fee参数
$param = '';
foreach ($attach as $k => $v) {
$param .= " \" <input name='{$k}' type='text' value='{$v}' />\" + " . PHP_EOL;
}
$attach = GetAttachParameters(array('attach', 'is_qrcode',));
foreach ($attach as $k => $v) {
$param .= " \" <input name='{$k}' type='text' value='{$v}' />\" + " . PHP_EOL;
}
$html = <<<EOL
<script>
function submit() {
var fee = document.getElementById('fee').value;
if ('' == fee || undefined == fee) {
alert('请输入要支付的金额(单位为分)');
return;
}
var script =
"<form style='display:none;' id='frm' name='frm' method='post' action=''>" +
" <input name='fee' type='text' value='" + fee + "' />" + /// 支付金额(单位分)
{$param}"</form>";
$('#mainbody').append(script);
$('#frm').submit();
}
</script>
<section>
<div class="neirong">
<ul>
<li><span class="name">总金额:</span><input id="fee" type="text" autofocus placeholder="单位:分" class="input"> <sapn class="red">*</sapn></li>
</ul>
<footer class="text-center"><a href="javascript:;" onclick="submit();" class="btn btn-blue foot_btn">确定</a></footer>
</div>
</section>
EOL;
} else { /// 有fee参数表示已提交页面中输入的支付金额
/// 获取附加参数
$ignore = array('sid','scode','app_id','dev_key','market_key','fee','title','order_id','notice_url','return_url','sign_key','is_qrcode','attach',);
$attach1 = GetAttachParameters($ignore, $attach);
$attach2 = GetAttachParameters($ignore);
$attach = $attach1 + $attach2;
/// 通过接口获取门店所支援的支付方式
$data = array(
'appid' => $app_id, /// appid
'devkey' => $dev_key, /// 开发者key
'market_key' => $market_key, /// 门店key
'level' => 1, /// 支付类型(1: 线上, 2: 扫码, 3: app)
'version' => 1,/// 版本号
);
$data['sign'] = SignParameter($data, $sign_key); /// 生成签名
$result = new ResultObject(rawurldecode(SendPost(SITE_API_DOMAIN . '/api/newpay/querylist', $data)));
if (0 == $result->error && count($result->data) > 0) { /// 成功
/// 获取详细的支付接口信息,这里区分是微信还是支付宝,每种方式只取第一种
$wechat = null; /// 微信限定
$alipay = null; /// 支付宝限定
$browser = null; /// 浏览器限定
foreach ($result->data as $item) {
if (mb_strstr($item->third_flag, 'wechat', false, USEDCHARSET)) { /// 包含wechat表示都是各种类型的微信支付
if (empty($wechat)) $wechat = $item;
} elseif (mb_strstr($item->third_flag, 'alipay', false, USEDCHARSET)) { /// 包含alipay表示都是各种类型的支付宝支付
if (empty($alipay)) $alipay = $item;
} else {
if (empty($browser)) $browser = $item;
}
}
if (empty($wechat) && empty($alipay) && empty($browser)) {
$html = <<<EOL
<script>
alert('该门店不支援任何的支付方式!');
</script>
EOL;
} else {
$wechatform = '';
$alipayform = '';
$browserform = '';
$wechathtml = '';
$alipayhtml = '';
$browserhtml = '';
if (!empty($wechat)) {
/// 支付要用的参数
$data = $attach + array(
'appid' => $app_id, /// appid
'devkey' => $dev_key, /// 开发者key
'sid' => $sid, /// sid
'scode' => $scode, /// scode
'orderid' => $order_id, /// 订单号
'fee' => $fee, /// 支付金额(单位分)
'title' => $title, /// 支付标题
'notice_url' => $notice_url, /// 回调页面地址(异步)
'return_url' => $return_url, /// 回调页面地址(同步)
'paytype' => $wechat->type_id, /// 支付类型(可通过接口获取所有支持的类型列表)
'version' => 1, /// 接口版本号, 整型, 目前只支持1
);
$data['sign'] = SignParameter($data, $sign_key); /// 生成签名
/// ==== ↓生成form表单↓ ====
$wechatform = '<form style="display:none;" id="wechatform" name="wechatform" method="post" action="https://' . SITE_API_DOMAIN . '/api/newpay/pay/online/">' . PHP_EOL;
foreach ($data as $k => $v) {
$wechatform .= sprintf(' <input name="%s" type="text" value=\'%s\' />', $k, $v) . PHP_EOL;
}
$wechatform .= '</form>';
/// ==== ↑生成form表单↑ ====
$wechathtml = <<<EOL
<div class="dr_btn">
<button id='btnWechat' onclick='wechatform.submit();' class="btn btn-green wx" style="display:none;">微信支付</button>
</div>
EOL;
}
if (!empty($alipay)) {
/// 支付要用的参数
$data = $attach + array(
'appid' => $app_id, /// appid
'devkey' => $dev_key, /// 开发者key
'sid' => $sid, /// sid
'scode' => $scode, /// scode
'orderid' => $order_id, /// 订单号
'fee' => $fee, /// 支付金额(单位分)
'title' => $title, /// 支付标题
'notice_url' => $notice_url, /// 回调页面地址(异步)
'return_url' => $return_url, /// 回调页面地址(同步)
'paytype' => $alipay->type_id, /// 支付类型(可通过接口获取所有支持的类型列表)
'version' => 1, /// 接口版本号, 整型, 目前只支持1
);
$data['sign'] = SignParameter($data, $sign_key); /// 生成签名
$alipayform = '<form style="display:none;" id="alipayform" name="alipayform" method="post" action="https://' . SITE_API_DOMAIN . '/api/newpay/pay/online/">' . PHP_EOL;
foreach ($data as $k => $v) {
$alipayform .= sprintf(' <input name="%s" type="text" value=\'%s\' />', $k, $v) . PHP_EOL;
}
$alipayform .= '</form>';
$alipayhtml = <<<EOL
<div class="dr_btn">
<button id='btnAlipay' onclick="alipayform.submit();" class="btn btn-blue">支付宝支付</button>
</div>
EOL;
}
if (!empty($browser)) {
/// 支付要用的参数
$data = $attach + array(
'appid' => $app_id, /// appid
'devkey' => $dev_key, /// 开发者key
'sid' => $sid, /// sid
'scode' => $scode, /// scode
'orderid' => $order_id, /// 订单号
'fee' => $fee, /// 支付金额(单位分)
'title' => $title, /// 支付标题
'notice_url' => $notice_url, /// 回调页面地址(异步)
'return_url' => $return_url, /// 回调页面地址(同步)
'paytype' => $browser->type_id, /// 支付类型(可通过接口获取所有支持的类型列表)
'version' => 1, /// 接口版本号, 整型, 目前只支持1
);
$data['sign'] = SignParameter($data, $sign_key); /// 生成签名
$browserform = '<form style="display:none;" id="browserform" name="browserform" method="post" action="https://' . SITE_API_DOMAIN . '/api/newpay/pay/online/">' . PHP_EOL;
foreach ($data as $k => $v) {
$browserform .= sprintf(' <input name="%s" type="text" value=\'%s\' />', $k, $v) . PHP_EOL;
}
$browserform .= '</form>';
$browserhtml = <<<EOL
<div class="dr_btn">
<button id='btnBrowser' onclick="browserform.submit();" class="btn btn-blue">立即支付</button>
</div>
EOL;
}
/*
if (empty($wechat))
$html = <<<EOL
{$alipayform}
<script>
alipayform.submit();
</script>
EOL;
elseif (empty($alipay))
$html = <<<EOL
{$wechatform}
<script>
wechatform.submit();
</script>
EOL;
else
*/
$html = <<<EOL
{$wechatform}
{$alipayform}
{$browserform}
<div class="container-fluid">
{$wechathtml}
{$alipayhtml}
{$browserhtml}
</div>
<script>
/// 是否微信打开
function is_wechat() {
return 'undefined' != typeof WeixinJSBridge;
}
///
function callAlipay() {
if (is_wechat())
return;
var btnAlipay = id('btnAlipay');
if (btnAlipay)
btnAlipay.onclick();
else
alert('该门店不支援任何的支付方式!');
}
$(function() {
var btnWechat = id('btnWechat');
var btnAlipay = id('btnAlipay');
var btnBrowser = id('btnBrowser');
if (!btnWechat && !btnAlipay && !btnBrowser) {
alert('该门店不支援任何的支付方式!');
return;
}
/// 判断是否包含WeixinJSBridge对象,包含则表示在微信环境中.
if ('undefined' == typeof WeixinJSBridge) {
/// WeixinJSBridgeReady事件处理.
$(document).on('WeixinJSBridgeReady', function() {
if (btnWechat) {
//btnWechat.style.display = 'initial';
btnWechat.onclick();
} else {
alert('该门店不支援任何的支付方式!');
return;
}
if (btnAlipay) {
btnAlipay.style.display = 'none';
}
if (btnBrowser) {
btnBrowser.style.display = 'none';
}
});
/*
/// 这里要判断其他环境.
/// 这里暂时用user-agent标志来判断是否处于微信环境中(包含micromessenger标识则表示为微信环境.).
/// 如果包含微信的标识则不去处理支付宝了.
var ua = navigator.userAgent.toLowerCase();
if (ua.match(/MicroMessenger/i) == "micromessenger") {
///return true;
/// 包含micromessenger标识则表示为微信环境
} else {
///return false;
/// 不包含micromessenger标识则表示为其他环境
setTimeout('callAlipay();', 1000); /// 延迟1秒
}
*/
} else {
if (btnWechat) {
//btnWechat.style.display = 'initial';
btnWechat.onclick();
} else {
alert('该门店不支援任何的支付方式!');
return;
}
if (btnAlipay) {
btnAlipay.style.display = 'none';
}
if (btnBrowser) {
btnBrowser.style.display = 'none';
}
}
});
</script>
EOL;
}
} elseif (0 != $result->error) { /// 有错误发生
$html = <<<EOL
<script>
alert('{$result->msg}');
</script>
EOL;
} else {
$html = <<<EOL
<script>
alert('该门店不支援任何的支付方式!');
</script>
EOL;
}
}
echo $html;
}
?>
</body>
</html>

View File

@@ -0,0 +1,586 @@
<?php
/*
* PHP QR Code encoder
*
* Area finding for SVG and CANVAS output
*
* Based on libqrencode C library distributed under LGPL 2.1
* Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
*
* PHP QR Code is distributed under LGPL 3
* Copyright (C) 2010-2013 Dominik Dzienia <deltalab at poczta dot fm>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
// N
// W E
// S
define('QR_AREA_N', 0);
define('QR_AREA_E', 1);
define('QR_AREA_S', 2);
define('QR_AREA_W', 3);
define('QR_AREA_X', 0);
define('QR_AREA_Y', 1);
define('QR_AREA_TRACKER', 0);
define('QR_AREA_PATH', 1);
define('QR_AREA_POINT', 2);
define('QR_AREA_RECT', 3);
define('QR_AREA_LSHAPE', 4);
/** @addtogroup OutputGroup */
/** @{ */
class QRareaGroup {
public $total = 0;
public $vertical = false;
public $horizontal = false;
public $points = array();
public $id = 0;
public $paths = array();
//----------------------------------------------------------------------
public function __construct($selfId, $sx, $sy)
{
$this->total = 1;
$this->points = array(array($sx,$sy,false));
$this->id = $selfId;
}
}
//##########################################################################
class QRarea {
public $width = 0;
private $tab = array();
private $tab_edges = array();
private $groups = array();
private $curr_group = 0;
public $paths = array();
//----------------------------------------------------------------------
public function __construct($source_tab)
{
$py = 0;
$this->width = count($source_tab);
$this->tab = array();
$this->tab_edges = array();
$this->paths = array();
foreach ($source_tab as $line) {
$arr = array();
$arr_edge = array();
$px=0;
foreach (str_split($line) as $item) {
if ($py<7 && $px<7)
$item = 0;
if ($py<7 && $px>=($this->width-7))
$item = 0;
if ($py>=($this->width-7) && $px<7)
$item = 0;
$arr[] = (int)$item;
$arr_edge[] = array(false, false, false, false);
$px++;
}
$this->tab[] = $arr;
$this->tab_edges[] = $arr_edge;
$py++;
}
$this->paths[] = array(QR_AREA_TRACKER, 0,0);
$this->paths[] = array(QR_AREA_TRACKER, 0,($this->width-7));
$this->paths[] = array(QR_AREA_TRACKER, ($this->width-7),0);
$this->groups = array();
$this->curr_group = 1;
}
//----------------------------------------------------------------------
public function getGroups()
{
return $this->groups;
}
//----------------------------------------------------------------------
public function getPaths()
{
return $this->paths;
}
//----------------------------------------------------------------------
public function getWidth()
{
return $this->width;
}
//----------------------------------------------------------------------
public function dumpTab()
{
echo "<style>";
echo "td { height: 2.5em; color: black; font-size: 8px;
border-top: 1px solid silver; border-left: 1px solid silver }";
echo "table { border-bottom: 1px solid silver; border-right: 1px solid silver }";
echo "</style>";
echo "<table border=0 cellpadding=0 cellspacing=0>";
$colorTab = array();
foreach($this->tab as $line) {
foreach($line as $item) {
if (!isset($colorTab[$item])) {
$colorTab[$item] = 'hsl('.mt_rand(0, 360).', '.floor((mt_rand(0, 25))+75).'%, 50%)';
}
}
}
foreach($this->tab as $line) {
echo "<tr>";
foreach($line as $item) {
if ($item == 0) {
echo "<td>&nbsp;</td>";
} else {
echo "<td style='text-align:center;width: 4em;background:".$colorTab[$item]."'>".$item."</td>";
}
}
echo "</tr>";
}
echo "</table>";
}
//----------------------------------------------------------------------
public function dumpEdges()
{
$style_off = '1px dotted silver;';
$style_on = '3px solid red;';
$colorAlloc = array();
echo "<table border='0'>";
$py = 0;
foreach($this->tab_edges as $line) {
$px = 0;
echo "<tr>";
foreach($line as $item) {
$styles = 'border-top:';
if ($item[QR_AREA_N])
$styles .= $style_on;
else $styles .= $style_off;
$styles .= 'border-bottom:';
if ($item[QR_AREA_S])
$styles .= $style_on;
else $styles .= $style_off;
$styles .= 'border-right:';
if ($item[QR_AREA_E])
$styles .= $style_on;
else $styles .= $style_off;
$styles .= 'border-left:';
if ($item[QR_AREA_W])
$styles .= $style_on;
else $styles .= $style_off;
$color = '';
$grp = $this->tab[$py][$px];
if ($grp>0) {
if (!isset($colorAlloc[$grp])) {
$colorAlloc[$grp] = 'hsl('.mt_rand(0, 360).', '.floor((mt_rand(0, 25))+75).'%, 50%)';
}
$color = 'background:'.$colorAlloc[$grp];
}
if ($grp == 0)
$grp = '&nbsp;';
echo "<td style='text-align:center;width:1.5em;".$styles.$color."'>".$grp."</td>";
$px++;
}
echo "</tr>";
$py++;
}
echo "</table>";
}
//----------------------------------------------------------------------
private static function rle(&$stringData)
{
$outArray = array();
$symbolArray = str_split($stringData);
$last = '';
$run = 1;
while (count($symbolArray) > 0) {
$symbol = array_shift($symbolArray);
if ($symbol != $last) {
if ($run > 1)
$outArray[] = $run;
if ($last != '')
$outArray[] = $last;
$run = 1;
$last = $symbol;
} else {
$run++;
}
}
if ($run > 1)
$outArray[] = $run;
$outArray[] = $last;
$stringData = $outArray;
}
//----------------------------------------------------------------------
private function getAt($posx, $posy)
{
if (($posx<0)||($posy<0)||($posx>=$this->width)||($posy>=$this->width))
return 0;
return $this->tab[$posy][$posx];
}
//----------------------------------------------------------------------
private function getOnElem($elem, $deltax = 0, $deltay = 0)
{
$posx = $elem[0]+$deltax;
$posy = $elem[1]+$deltay;
if (($posx<0)||($posy<0)||($posx>=$this->width)||($posy>=$this->width))
return 0;
return $this->tab[$posy][$posx];
}
//----------------------------------------------------------------------
private function addGroupElement($groupId, $h, $v, $sx, $sy)
{
$this->groups[$groupId]->total++;
if ($h)
$this->groups[$groupId]->horizontal = true;
if ($v)
$this->groups[$groupId]->vertical = true;
$this->groups[$groupId]->points[] = array($sx, $sy, false);
}
//----------------------------------------------------------------------
public function detectGroups()
{
for ($sy = 0; $sy < $this->width; $sy++) {
for ($sx = 0; $sx < $this->width; $sx++) {
if ($this->tab[$sy][$sx] == 1) { // non-allocated
$gid_left = 0;
$gid_top = 0;
$grouped = false;
if ($sx>0) {
$gid_left = $this->tab[$sy][$sx-1]; // previous on left
if ($gid_left > 1) { // if already in group
$this->tab[$sy][$sx] = $gid_left;
$grouped = true;
$this->addGroupElement($gid_left, true, false, $sx, $sy);
}
}
if ($sy > 0) {
$gid_top = $this->tab[$sy-1][$sx]; // previous on top
if ($gid_top > 1) { //if in group
if (!$grouped) { // and not grouped
$this->tab[$sy][$sx] = $gid_top;
$grouped = true;
$this->addGroupElement($gid_top, false, true, $sx, $sy);
} else if($gid_top != $gid_left) { // was in left group
$grouped = true;
$this->groups[$gid_top]->vertical = true;
$this->groups[$gid_top]->horizontal = true;
$this->groups[$gid_top]->total = $this->groups[$gid_top]->total + $this->groups[$gid_left]->total;
foreach($this->groups[$gid_left]->points as $elem)
$this->tab[$elem[1]][$elem[0]] = $gid_top;
$this->groups[$gid_top]->points = array_values(array_merge($this->groups[$gid_top]->points, $this->groups[$gid_left]->points));
unset($this->groups[$gid_left]);
//refarb group
}
}
}
if (!$grouped) {
$this->curr_group++;
$this->tab[$sy][$sx] = $this->curr_group;
$this->groups[$this->curr_group] = new QRareaGroup($this->curr_group, $sx, $sy);
}
}
}
}
}
//----------------------------------------------------------------------
private function detectSquare($group)
{
$max_x = 0;
$max_y = 0;
$min_x = $this->width;
$min_y = $this->width;
foreach($group->points as $elem) {
$min_x = min($min_x, $elem[QR_AREA_X]);
$max_x = max($max_x, $elem[QR_AREA_X]);
$min_y = min($min_y, $elem[QR_AREA_Y]);
$max_y = max($max_y, $elem[QR_AREA_Y]);
}
return array($min_x, $min_y, $max_x+1, $max_y+1);
}
//----------------------------------------------------------------------
public function detectAreas()
{
$squares = array();
$points = array();
$lshapes = array();
foreach ($this->groups as $groupId=>&$group) {
if ($group->total > 3) {
if ((!$group->vertical)||(!$group->horizontal)) {
$squareCoord = $this->detectSquare($group);
array_unshift($squareCoord, QR_AREA_RECT);
$this->paths[] = $squareCoord;
} else {
$this->detectPaths($group);
unset($group->points);
foreach($group->paths as &$path)
self::rle($path[2]);
$this->paths[] = array(QR_AREA_PATH, $group->paths);
}
} else if (($group->total == 3)&&($group->vertical)&&($group->horizontal)) {
$squareCoord = $this->detectSquare($group);
$variant = 0;
if ($this->getOnElem($squareCoord, 0, 0) != $group->id)
$variant = 0;
if ($this->getOnElem($squareCoord, 1, 0) != $group->id)
$variant = 1;
if ($this->getOnElem($squareCoord, 0, 1) != $group->id)
$variant = 2;
if ($this->getOnElem($squareCoord, 1, 1) != $group->id)
$variant = 3;
$lshapes[] = $squareCoord[QR_AREA_X];
$lshapes[] = $squareCoord[QR_AREA_Y];
$lshapes[] = $variant;
} else if ($group->total >= 2) {
$squareCoord = $this->detectSquare($group);
$squares = array_merge($squares, $squareCoord);
} else if ($group->total == 1) {
$points[] = $group->points[0][0];
$points[] = $group->points[0][1];
}
}
if (count($points) > 0) {
array_unshift($points, QR_AREA_POINT);
$this->paths[] = $points;
}
if (count($squares) > 0) {
array_unshift($squares, QR_AREA_RECT);
$this->paths[] = $squares;
}
if (count($lshapes) > 0) {
array_unshift($lshapes, QR_AREA_LSHAPE);
$this->paths[] = $lshapes;
}
}
//----------------------------------------------------------------------
private function reserveEdgeOnElem($elem, $edgeNo)
{
$this->tab_edges[$elem[QR_AREA_Y]][$elem[QR_AREA_X]][$edgeNo] = true;
}
//----------------------------------------------------------------------
private function reserveEdge($px, $py, $edgeNo)
{
$this->tab_edges[$py][$px][$edgeNo] = true;
}
//----------------------------------------------------------------------
private function markAdjacentEdges($group)
{
foreach($group->points as $elem) {
if ($this->getOnElem($elem, -1, 0) == $group->id)
$this->reserveEdgeOnElem($elem, QR_AREA_W);
if ($this->getOnElem($elem, +1, 0) == $group->id)
$this->reserveEdgeOnElem($elem, QR_AREA_E);
if ($this->getOnElem($elem, 0, -1) == $group->id)
$this->reserveEdgeOnElem($elem, QR_AREA_N);
if ($this->getOnElem($elem, 0, +1) == $group->id)
$this->reserveEdgeOnElem($elem, QR_AREA_S);
}
}
//----------------------------------------------------------------------
private function detectPaths(&$group)
{
$this->markAdjacentEdges($group);
$elem = $group->points[0];
$waylist = $this->findPath($group, $elem[QR_AREA_X], $elem[QR_AREA_Y]);
$group->paths[] = array($elem[QR_AREA_X], $elem[QR_AREA_Y], $waylist);
$tab = array();
foreach($group->points as $elem) {
$edgeTab = $this->tab_edges[$elem[QR_AREA_Y]][$elem[QR_AREA_X]];
if (!( $edgeTab[QR_AREA_N]
&& $edgeTab[QR_AREA_E]
&& $edgeTab[QR_AREA_S]
&& $edgeTab[QR_AREA_W])) {
if (!$edgeTab[QR_AREA_S]) {
$waylistw = $this->findPath($group, $elem[QR_AREA_X], $elem[QR_AREA_Y]+1);
$group->paths[] = array($elem[QR_AREA_X], $elem[QR_AREA_Y]+1, $waylistw);
}
}
}
}
//----------------------------------------------------------------------
private function findPath($group, $sx, $sy)
{
$px = $sx;
$py = $sy;
$waylist = '';
$dir = '';
$lastdir = '';
$moves = array(
// magic :)
0=>'', 1=>'L', 2=>'T', 3=>'L', 4=>'B', 5=>'B', 6=>'B,T', 7=>'B'
,8=>'R', 9=>'R,L', 10=>'T', 11=>'L',12=>'R',13=>'R',14=>'T',15=>''
);
do
{
$Q = ($this->getAt($px-1, $py-1) == $group->id)?1:0;
$Q += ($this->getAt($px, $py-1) == $group->id)?2:0;
$Q += ($this->getAt($px-1, $py) == $group->id)?4:0;
$Q += ($this->getAt($px, $py) == $group->id)?8:0;
if ($moves[$Q] == '')
throw new Exception('It should NEVER happened!');
$move_expl = explode(',', $moves[$Q]);
$have_way = false;
$dir = '';
while ((count($move_expl) > 0)&&($have_way == false)) {
$way = array_shift($move_expl);
if (($have_way==false)&&($way=='R')&&($this->tab_edges[$py][$px][QR_AREA_N]==false)) {
$have_way = true;
$dir = $way;
$this->reserveEdge($px, $py, QR_AREA_N);
$px++;
}
if (($have_way==false)&&($way=='B')&&($this->tab_edges[$py][$px-1][QR_AREA_E]==false)) {
$have_way = true;
$dir = $way;
$this->reserveEdge($px-1, $py, QR_AREA_E);
$py++;
}
if (($have_way==false)&&($way=='L')&&($this->tab_edges[$py-1][$px-1][QR_AREA_S]==false)) {
$have_way = true;
$dir = $way;
$this->reserveEdge($px-1, $py-1, QR_AREA_S);
$px--;
}
if (($have_way==false)&&($way=='T')&&($this->tab_edges[$py-1][$px][QR_AREA_W]==false)) {
$have_way = true;
$dir = $way;
$this->reserveEdge($px, $py-1, QR_AREA_W);
$py--;
}
}
$waylist .= $dir;
} while (!(($px==$sx)&&($py==$sy)));
return $waylist;
}
}
/** @} */

View File

@@ -0,0 +1,235 @@
<?php
/*
* PHP QR Code encoder
*
* Bitstream class
*
* Based on libqrencode C library distributed under LGPL 2.1
* Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
*
* PHP QR Code is distributed under LGPL 3
* Copyright (C) 2010-2013 Dominik Dzienia <deltalab at poczta dot fm>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/** @addtogroup CoreGroup */
/** @{ */
/**
PHP bit stream.
Class implementing array of bits (= 1 or 0 ints). Allows to initialize and append
bits from given Integer or array of Bytes.
*/
class QRbitstream {
/**
Array containing bit data stream
*/
public $data = array();
//----------------------------------------------------------------------
/**
@return Integer size of byte stream
*/
public function size()
{
return count($this->data);
}
//----------------------------------------------------------------------
/**
Allocates bit stream, fills bit data stream with 0's.
This operation is __destructive__, will replace orginal stream contents!
@param Integer $setLength desired target stream size
@return Integer 0 on success, other on failure
*/
public function allocate($setLength)
{
$this->data = array_fill(0, $setLength, 0);
return 0;
}
//----------------------------------------------------------------------
/**
Creates new bit stream from given Integer number.
@param Integer $bits bit count
@param Integer $num integer to convert
@return QRbitstream bit stream object containing first $bits bits from $num in order from LSB to MSB
*/
public static function newFromNum($bits, $num)
{
$bstream = new QRbitstream();
$bstream->allocate($bits);
$mask = 1 << ($bits - 1);
for($i=0; $i<$bits; $i++) {
if($num & $mask) {
$bstream->data[$i] = 1;
} else {
$bstream->data[$i] = 0;
}
$mask = $mask >> 1;
}
return $bstream;
}
//----------------------------------------------------------------------
/**
Creates new bit stream from given byte array.
@param Integer $size size of array
@param Array $data array ob bytes
@return QRbitstream bit stream object containing bit contents of given bytes array
*/
public static function newFromBytes($size, $data)
{
$bstream = new QRbitstream();
$bstream->allocate($size * 8);
$p=0;
for($i=0; $i<$size; $i++) {
$mask = 0x80;
for($j=0; $j<8; $j++) {
if($data[$i] & $mask) {
$bstream->data[$p] = 1;
} else {
$bstream->data[$p] = 0;
}
$p++;
$mask = $mask >> 1;
}
}
return $bstream;
}
//----------------------------------------------------------------------
/**
Appends given bit stream at end of this stream.
@param QRbitstream $arg bit stream to be appended
@return Integer status of append operation, 0 when success, -1 when $arg is null
*/
public function append(QRbitstream $arg)
{
if (is_null($arg)) {
return -1;
}
if($arg->size() == 0) {
return 0;
}
if($this->size() == 0) {
$this->data = $arg->data;
return 0;
}
$this->data = array_values(array_merge($this->data, $arg->data));
return 0;
}
//----------------------------------------------------------------------
/**
Appends bit stream cteated from given Integer number at end of current stream.
@param Integer $bits bit count
@param Integer $num integer to convert
@return Integer status of append operation, status of append operation, 0 when success, -1 otherwise
*/
public function appendNum($bits, $num)
{
if ($bits == 0)
return 0;
$b = QRbitstream::newFromNum($bits, $num);
if(is_null($b))
return -1;
$ret = $this->append($b);
unset($b);
return $ret;
}
//----------------------------------------------------------------------
/**
Appends bit stream created from from given byte array at end of current stream.
@param Integer $size size of array
@param Array $data array ob bytes
@return Integer status of append operation, status of append operation, 0 when success, -1 otherwise
*/
public function appendBytes($size, $data)
{
if ($size == 0)
return 0;
$b = QRbitstream::newFromBytes($size, $data);
if(is_null($b))
return -1;
$ret = $this->append($b);
unset($b);
return $ret;
}
//----------------------------------------------------------------------
/**
Converts current bit stream into byte array.
@returns Array array of bytes
*/
public function toByte()
{
$size = $this->size();
if($size == 0) {
return array();
}
$data = array_fill(0, (int)(($size + 7) / 8), 0);
$bytes = (int)($size / 8);
$p = 0;
for($i=0; $i<$bytes; $i++) {
$v = 0;
for($j=0; $j<8; $j++) {
$v = $v << 1;
$v |= $this->data[$p];
$p++;
}
$data[$i] = $v;
}
if($size & 7) {
$v = 0;
for($j=0; $j<($size & 7); $j++) {
$v = $v << 1;
$v |= $this->data[$p];
$p++;
}
$data[$bytes] = $v;
}
return $data;
}
}
/** @}*/

View File

@@ -0,0 +1,363 @@
<?php
/*
* PHP QR Code encoder
*
* CANVAS output
*
* Based on libqrencode C library distributed under LGPL 2.1
* Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
*
* PHP QR Code is distributed under LGPL 3
* Copyright (C) 2010-2013 Dominik Dzienia <deltalab at poczta dot fm>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/** @addtogroup OutputGroup */
/** @{ */
class QRcanvasOutput extends QRarea {
public function __construct($source_tab)
{
parent::__construct($source_tab);
}
//----------------------------------------------------------------------
public static function encodeNum($num)
{
$addTab = array(0=>'', 1=>'z', 2=>'Z', 3=>'+');
$map = '0123456789abcdefghijklmnopqrstuvwxyABCDEFGHIJKLMNOPQRSTUVWXY';
$mapPos = $num % 60;
$mapAdd = (int)($num / 60);
return $addTab[$mapAdd].$map[$mapPos];
}
//----------------------------------------------------------------------
public static function compact_path(&$pathTab)
{
if (count($pathTab) == 0) {
$pathTab = '';
} else {
$pathTab = count($pathTab).','.join(',', $pathTab);
}
}
//----------------------------------------------------------------------
public static function compact_points(&$pointsTab)
{
if (count($pointsTab) == 0) {
$pointsTab = '';
} else {
$compacted = '';
foreach ($pointsTab as $point)
$compacted .= self::encodeNum($point);
$pointsTab = $compacted;
}
}
//----------------------------------------------------------------------
public static function compactCanvasCommands($ops)
{
$accumulated = array();
$accumulated['SR'] = array();
$accumulated['WR'] = array();
$accumulated['SP'] = array();
$accumulated['WP'] = array();
$accumulated['SB'] = array();
$accumulated['WB'] = array();
$accumulated['SO'] = array();
while (count($ops) > 0) {
$color = array_shift($ops);
$opcode = array_shift($ops);
if (($opcode == 'R') || ($opcode == 'P')) {
do {
$num = array_shift($ops);
if (is_int($num)) {
$accumulated[$color.$opcode][] = $num;
} else {
array_unshift($ops, $num);
}
} while ((count($ops) > 0)&&(is_int($num)));
} else if ($opcode == 'B') {
array_shift($ops);
$px = array_shift($ops);
$py = array_shift($ops);
array_shift($ops);
$conftab = array();
$num = array_shift($ops);
while ((count($ops) > 0)&&(!($num === 'E'))) {
$conftab[] = $num;
$num = array_shift($ops);
}
$cc = count($conftab);
$deltas = '';
$lastposx = $px;
$lastposy = $py;
for($pos=0;$pos <$cc; $pos+=2) {
$dx = $lastposx - $conftab[$pos];
$dy = $lastposy - $conftab[$pos+1];
$lastposx = $conftab[$pos];
$lastposy = $conftab[$pos+1];
if ($dx < 0) {
$deltas .= chr(ord('a')-1-$dx);
} else if ($dx > 0) {
$deltas .= chr(ord('A')-1+$dx);
} else {
$deltas .= '0';
}
if ($dy < 0) {
$deltas .= chr(ord('a')-1-$dy);
} else if ($dy > 0) {
$deltas .= chr(ord('A')-1+$dy);
} else {
$deltas .= '0';
}
}
$deltas = strtr($deltas, array(
'00'=>'1',
'aa'=>'2',
'aA'=>'3',
'Aa'=>'4',
'AA'=>'5',
'aB'=>'6',
'Ab'=>'7',
'bA'=>'8',
'Ba'=>'9'
));
$accumulated[$color.$opcode][] = join(',', array($px, $py, $deltas));
} else if ($opcode == 'O') {
$px = array_shift($ops);
$py = array_shift($ops);
$accumulated[$color.$opcode][] = join(',', array($px, $py));
}
}
self::compact_points($accumulated['SR']);
self::compact_points($accumulated['WR']);
self::compact_points($accumulated['SP']);
self::compact_points($accumulated['WP']);
self::compact_path($accumulated['SB']);
self::compact_path($accumulated['WB']);
if (count($accumulated['SO']) > 0)
$accumulated['SO'] = join(',',$accumulated['SO']);
else $accumulated['SO'] = '';
$mapping = array(
'SO'=>'O',
'SB'=>'B',
'WB'=>'b',
'SR'=>'R',
'WR'=>'r',
'SP'=>'P',
'WP'=>'p'
);
$whole = array();
foreach($mapping as $key=>$symb) {
if ($accumulated[$key]!='')
$whole[] = $symb.','.$accumulated[$key];
}
return join(',', $whole);
}
//----------------------------------------------------------------------
public function getCanvasOps()
{
$ops = array();
foreach ($this->paths as $path) {
switch ($path[0]) {
case QR_AREA_PATH:
$pNum = 0;
foreach($path[1] as $pathDetails) {
if ($pNum == 0) {
$ops[] = 'S';
} else if ($pNum > 0) {
$ops[] = 'W';
}
$ops[] = 'B';
$px = array_shift($pathDetails);
$py = array_shift($pathDetails);
$ops[] = 'M';
$ops[] = $px;
$ops[] = $py;
$rle_steps = array_shift($pathDetails);
$lastOp = '';
while(count($rle_steps) > 0) {
$delta = 1;
$operator = array_shift($rle_steps);
if (($operator != 'R') && ($operator != 'L') && ($operator != 'T') && ($operator != 'B')) {
$delta = (int)$operator;
$operator = array_shift($rle_steps);
}
if ($operator == 'R') $px += $delta;
if ($operator == 'L') $px -= $delta;
if ($operator == 'T') $py -= $delta;
if ($operator == 'B') $py += $delta;
if ($lastOp != 'T')
$ops[] = 'T';
$ops[] = $px;
$ops[] = $py;
$lastOp = 'T';
}
$ops[] = 'E';
$pNum++;
}
break;
case QR_AREA_POINT:
$symb = array_shift($path);
$ops[] = 'S';
$lastOp = '';
while(count($path) > 0) {
$px = array_shift($path);
$py = array_shift($path);
if ($lastOp != 'P')
$ops[] = 'P';
$ops[] = $px;
$ops[] = $py;
$lastOp = 'P';
}
break;
case QR_AREA_RECT:
$symb = array_shift($path);
$ops[] = 'S';
$lastOp = '';
while(count($path) > 0) {
$px = array_shift($path);
$py = array_shift($path);
$ex = array_shift($path);
$ey = array_shift($path);
if ($lastOp != 'R')
$ops[] = 'R';
$ops[] = $px;
$ops[] = $py;
$ops[] = $ex-$px;
$ops[] = $ey-$py;
$lastOp = 'R';
}
break;
case QR_AREA_LSHAPE:
$symb = array_shift($path);
while(count($path) > 0) {
$px = array_shift($path);
$py = array_shift($path);
$mode = (int)array_shift($path);
$pxd = ($mode % 2)?1:0;
$pyd = ($mode > 1)?1:0;
$ops[] = 'S';
$ops[] = 'R';
$ops[] = $px;
$ops[] = $py;
$ops[] = 2;
$ops[] = 2;
$ops[] = 'W';
$ops[] = 'P';
$ops[] = $px+$pxd;
$ops[] = $py+$pyd;
}
break;
case QR_AREA_TRACKER:
$symb = array_shift($path);
$px = array_shift($path);
$py = array_shift($path);
$ops[] = 'S';
$ops[] = 'O';
$ops[] = $px;
$ops[] = $py;
break;
}
}
return self::compactCanvasCommands($ops);
}
}
/** @} */

View File

@@ -0,0 +1,51 @@
<?php
/** \defgroup QR_DEFCONFIGS Global Config
Global config file (contains global configuration-releted constants).
Before version 2.0.0 only way to configure all calls. From version 2.0.0 values
used here are treated as __defaults__ but culd be overwriten by additional config.
parrameters passed to functions.
* @{
*/
/** Mask cache switch.
__Boolean__ Speciffies does mask ant template caching is enabled.
- __true__ - disk cache is used, more disk reads are performed but less CPU power is required,
- __false__ - mask and format templates are calculated each time in memory */
define('QR_CACHEABLE', true);
/** Cache dir path.
__String__ Used when QR_CACHEABLE === true. Specifies absolute server path
for masks and format templates cache dir */
define('QR_CACHE_DIR', dirname(__FILE__).DIRECTORY_SEPARATOR.'cache'.DIRECTORY_SEPARATOR);
/** Default error logs dir.
__String__ Absolute server path for log directory. */
define('QR_LOG_DIR', dirname(__FILE__).DIRECTORY_SEPARATOR);
/** If best mask is found.
__Boolean__ Speciffies mask searching strategy:
- __true__ - estimates best mask (as QR-Code spec recomends by default) but may be extremally slow
- __false__ - check only one mask (specified by __QR_DEFAULT_MASK__), gives significant performance boost but (propably) results in worst quality codes
*/
define('QR_FIND_BEST_MASK', true);
/** Configure random mask checking.
Specifies algorithm for mask selection when __QR_FIND_BEST_MASK__ is set to __true__.
- if Boolean __false__ - checks all masks available
- if Integer __1..7__ - value tells count of randomly selected masks need to be checked
*/
define('QR_FIND_FROM_RANDOM', false);
/** Default an only mask to apply.
__Integer__ Specifies mask no (1..8) to be aplied every time, used when __QR_FIND_BEST_MASK__ is set to __false__.
*/
define('QR_DEFAULT_MASK', 2);
/** Maximum allowed png image width (in pixels).
__Integer__ Maximal width/height of generated raster image.
Tune to make sure GD and PHP can handle such big images.
*/
define('QR_PNG_MAXIMUM_SIZE', 1024);
/** @}*/

View File

@@ -0,0 +1,74 @@
<?php
/*
* PHP QR Code encoder
*
* Common constants
*
* Based on libqrencode C library distributed under LGPL 2.1
* Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
*
* PHP QR Code is distributed under LGPL 3
* Copyright (C) 2010-2013 Dominik Dzienia <deltalab at poczta dot fm>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/** \defgroup QR_CONST Global Constants
Constant used globally for function arguments.
Make PHP calls a little bit more clear, in place of missing (in dynamicaly typed language) enum types.
* @{
*/
/** @name QR-Code Encoding Modes */
/** @{ */
/** null encoding, used when no encoding was speciffied yet */
define('QR_MODE_NUL', -1);
/** Numerical encoding, only numbers (0-9) */
define('QR_MODE_NUM', 0);
/** AlphaNumerical encoding, numbers (0-9) uppercase text (A-Z) and few special characters (space, $, %, *, +, -, ., /, :) */
define('QR_MODE_AN', 1);
/** 8-bit encoding, raw 8 bit encoding */
define('QR_MODE_8', 2);
/** Kanji encoding */
define('QR_MODE_KANJI', 3);
/** Structure, internal encoding for structure-related data */
define('QR_MODE_STRUCTURE', 4);
/**@}*/
/** @name QR-Code Levels of Error Correction
Constants speciffy ECC level from lowest __L__ to the highest __H__.
Higher levels are recomended for Outdoor-presented codes, but generates bigger codes.
*/
/** @{*/
/** ~7% of codewords can be restored */
define('QR_ECLEVEL_L', 0);
/** ~15% of codewords can be restored */
define('QR_ECLEVEL_M', 1);
/** ~25% of codewords can be restored */
define('QR_ECLEVEL_Q', 2);
/** ~30% of codewords can be restored */
define('QR_ECLEVEL_H', 3);
/** @}*/
/** @name QR-Code Supported output formats */
/** @{*/
define('QR_FORMAT_TEXT', 0);
define('QR_FORMAT_PNG', 1);
/** @}*/
/** @}*/

View File

@@ -0,0 +1,784 @@
<?php
/*
* PHP QR Code encoder
*
* Main encoder classes.
*
* Based on libqrencode C library distributed under LGPL 2.1
* Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
*
* PHP QR Code is distributed under LGPL 3
* Copyright (C) 2010-2013 Dominik Dzienia <deltalab at poczta dot fm>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/** @defgroup CoreGroup Standard API Core
Core encoder classes */
/** @addtogroup CoreGroup */
/** @{ */
//##########################################################################
/**
Data block with raw data and it's Error Correction Code data.
*/
class QRrsblock {
public $dataLength;
public $data = array();
public $eccLength;
public $ecc = array();
/** Data block Constructor
@param Integer $dl length of data stream
@param Array $data data stream
@param Integer $el ECC length
@param Array $el ECC stream (modified, by reference)
@param QRrsItem $rs RS encoding item
*/
public function __construct($dl, $data, $el, &$ecc, QRrsItem $rs)
{
$rs->encode_rs_char($data, $ecc);
$this->dataLength = $dl;
$this->data = $data;
$this->eccLength = $el;
$this->ecc = $ecc;
}
};
//##########################################################################
/** Raw Code holder.
Contains encoded code data before there are spatialy distributed into frame and masked.
Here goes dividing data into blocks and calculating ECC stream. */
class QRrawcode {
public $version; ///< __Integer__ code Version
public $datacode = array(); ///< __Array__ data stream
public $ecccode = array(); ///< __Array__ ECC Stream
public $blocks; ///< __Integer__ RS Blocks count
public $rsblocks = array(); ///< __Array__ of RSblock, ECC code blocks
public $count; ///< __Integer__ position of currently processed ECC code
public $dataLength; ///< __Integer__ data stream length
public $eccLength; ///< __Integer__ ECC stream length
public $b1; ///< __Integer__ width of code in pixels, used as a modulo base for column overflow
//----------------------------------------------------------------------
/** Raw Code holder Constructor
@param QRinput $input input stream
*/
public function __construct(QRinput $input)
{
$spec = array(0,0,0,0,0);
$this->datacode = $input->getByteStream();
if(is_null($this->datacode)) {
throw new Exception('null imput string');
}
QRspec::getEccSpec($input->getVersion(), $input->getErrorCorrectionLevel(), $spec);
$this->version = $input->getVersion();
$this->b1 = QRspec::rsBlockNum1($spec);
$this->dataLength = QRspec::rsDataLength($spec);
$this->eccLength = QRspec::rsEccLength($spec);
$this->ecccode = array_fill(0, $this->eccLength, 0);
$this->blocks = QRspec::rsBlockNum($spec);
$ret = $this->init($spec);
if($ret < 0) {
throw new Exception('block alloc error');
return null;
}
$this->count = 0;
}
//----------------------------------------------------------------------
/** Initializes Raw Code according to current code speciffication
@param Array $spec code speciffigation, as provided by QRspec
*/
public function init(array $spec)
{
$dl = QRspec::rsDataCodes1($spec);
$el = QRspec::rsEccCodes1($spec);
$rs = QRrs::init_rs(8, 0x11d, 0, 1, $el, 255 - $dl - $el);
$blockNo = 0;
$dataPos = 0;
$eccPos = 0;
for($i=0; $i<QRspec::rsBlockNum1($spec); $i++) {
$ecc = array_slice($this->ecccode,$eccPos);
$this->rsblocks[$blockNo] = new QRrsblock($dl, array_slice($this->datacode, $dataPos), $el, $ecc, $rs);
$this->ecccode = array_merge(array_slice($this->ecccode,0, $eccPos), $ecc);
$dataPos += $dl;
$eccPos += $el;
$blockNo++;
}
if(QRspec::rsBlockNum2($spec) == 0)
return 0;
$dl = QRspec::rsDataCodes2($spec);
$el = QRspec::rsEccCodes2($spec);
$rs = QRrs::init_rs(8, 0x11d, 0, 1, $el, 255 - $dl - $el);
if($rs == NULL) return -1;
for($i=0; $i<QRspec::rsBlockNum2($spec); $i++) {
$ecc = array_slice($this->ecccode,$eccPos);
$this->rsblocks[$blockNo] = new QRrsblock($dl, array_slice($this->datacode, $dataPos), $el, $ecc, $rs);
$this->ecccode = array_merge(array_slice($this->ecccode,0, $eccPos), $ecc);
$dataPos += $dl;
$eccPos += $el;
$blockNo++;
}
return 0;
}
//----------------------------------------------------------------------
/** Gets ECC code
@return Integer ECC byte for current object position
*/
public function getCode()
{
$ret;
if($this->count < $this->dataLength) {
$row = $this->count % $this->blocks;
$col = $this->count / $this->blocks;
if($col >= $this->rsblocks[0]->dataLength) {
$row += $this->b1;
}
$ret = $this->rsblocks[$row]->data[$col];
} else if($this->count < $this->dataLength + $this->eccLength) {
$row = ($this->count - $this->dataLength) % $this->blocks;
$col = ($this->count - $this->dataLength) / $this->blocks;
$ret = $this->rsblocks[$row]->ecc[$col];
} else {
return 0;
}
$this->count++;
return $ret;
}
}
//##########################################################################
/**
__Main class to create QR-code__.
QR Code symbol is a 2D barcode that can be scanned by handy terminals such as a mobile phone with CCD.
The capacity of QR Code is up to 7000 digits or 4000 characters, and has high robustness.
This class supports QR Code model 2, described in JIS (Japanese Industrial Standards) X0510:2004 or ISO/IEC 18004.
Currently the following features are not supported: ECI and FNC1 mode, Micro QR Code, QR Code model 1, Structured mode.
@abstract Class for generating QR-code images, SVG and HTML5 Canvas
@author Dominik Dzienia
@copyright 2010-2013 Dominik Dzienia and others
@link http://phpqrcode.sourceforge.net
@license http://www.gnu.org/copyleft/lesser.html LGPL
*/
class QRcode {
public $version; ///< __Integer__ QR code version. Size of QRcode is defined as version. Version is from 1 to 40. Version 1 is 21*21 matrix. And 4 modules increases whenever 1 version increases. So version 40 is 177*177 matrix.
public $width; ///< __Integer__ Width of code table. Because code is square shaped - same as height.
public $data; ///< __Array__ Ready, masked code data.
/** Canvas JS include flag.
If canvas js support library was included, we remember it static in QRcode.
(because file should be included only once)
*/
public static $jscanvasincluded = false;
//----------------------------------------------------------------------
/**
Encode mask
Main function responsible for creating code.
We get empty frame, then fill it with data from input, then select best mask and apply it.
If $mask argument is greater than -1 we assume that user want's that specific mask number (ranging form 0-7) to be used.
Otherwise (when $mask is -1) mask is detected using algorithm depending of global configuration,
@param QRinput $input data object
@param Integer $mask sugested masking mode
@return QRcode $this (current instance)
*/
public function encodeMask(QRinput $input, $mask)
{
if($input->getVersion() < 0 || $input->getVersion() > QRSPEC_VERSION_MAX) {
throw new Exception('wrong version');
}
if($input->getErrorCorrectionLevel() > QR_ECLEVEL_H) {
throw new Exception('wrong level');
}
$raw = new QRrawcode($input);
QRtools::markTime('after_raw');
$version = $raw->version;
$width = QRspec::getWidth($version);
$frame = QRspec::newFrame($version);
$filler = new QRframeFiller($width, $frame);
if(is_null($filler)) {
return NULL;
}
// inteleaved data and ecc codes
for($i=0; $i<$raw->dataLength + $raw->eccLength; $i++) {
$code = $raw->getCode();
$bit = 0x80;
for($j=0; $j<8; $j++) {
$addr = $filler->next();
$filler->setFrameAt($addr, 0x02 | (($bit & $code) != 0));
$bit = $bit >> 1;
}
}
QRtools::markTime('after_filler');
unset($raw);
// remainder bits
$j = QRspec::getRemainder($version);
for($i=0; $i<$j; $i++) {
$addr = $filler->next();
$filler->setFrameAt($addr, 0x02);
}
$frame = $filler->frame;
unset($filler);
// masking
$maskObj = new QRmask();
if($mask < 0) {
if (QR_FIND_BEST_MASK) {
$masked = $maskObj->mask($width, $frame, $input->getErrorCorrectionLevel());
} else {
$masked = $maskObj->makeMask($width, $frame, (intval(QR_DEFAULT_MASK) % 8), $input->getErrorCorrectionLevel());
}
} else {
$masked = $maskObj->makeMask($width, $frame, $mask, $input->getErrorCorrectionLevel());
}
if($masked == NULL) {
return NULL;
}
QRtools::markTime('after_mask');
$this->version = $version;
$this->width = $width;
$this->data = $masked;
return $this;
}
//----------------------------------------------------------------------
/**
Encode input with mask detection.
Shorthand for encodeMask, without specifing particular, static mask number.
@param QRinput $input data object to be encoded
@return
*/
public function encodeInput(QRinput $input)
{
return $this->encodeMask($input, -1);
}
//----------------------------------------------------------------------
/**
Encode string, forcing 8-bit encoding
@param String $string input string
@param Integer $version code version (size of code area)
@param Integer $level ECC level (see: Global Constants -> Levels of Error Correction)
@return QRcode $this (current instance)
*/
public function encodeString8bit($string, $version, $level)
{
if($string == NULL) {
throw new Exception('empty string!');
return NULL;
}
$input = new QRinput($version, $level);
if($input == NULL) return NULL;
$ret = $input->append(QR_MODE_8, strlen($string), str_split($string));
if($ret < 0) {
unset($input);
return NULL;
}
return $this->encodeInput($input);
}
//----------------------------------------------------------------------
/**
Encode string, using optimal encodings.
Encode string dynamically adjusting encoding for subsections of string to
minimize resulting code size. For complex string it will split string into
subsections: Numerical, Alphanumerical or 8-bit.
@param String $string input string
@param Integer $version code version (size of code area)
@param String $level ECC level (see: Global Constants -> Levels of Error Correction)
@param Integer $hint __QR_MODE_8__ or __QR_MODE_KANJI__, Because Kanji encoding
is kind of 8 bit encoding we need to hint encoder to use Kanji mode explicite.
(otherwise it may try to encode it as plain 8 bit stream)
@param Boolean $casesensitive hint if given string is case-sensitive, because
if not - encoder may use optimal QR_MODE_AN instead of QR_MODE_8
@return QRcode $this (current instance)
*/
public function encodeString($string, $version, $level, $hint, $casesensitive)
{
if($hint != QR_MODE_8 && $hint != QR_MODE_KANJI) {
throw new Exception('bad hint');
return NULL;
}
$input = new QRinput($version, $level);
if($input == NULL) return NULL;
$ret = QRsplit::splitStringToQRinput($string, $input, $hint, $casesensitive);
if($ret < 0) {
return NULL;
}
return $this->encodeInput($input);
}
//######################################################################
/**
Creates PNG image containing QR-Code.
Simple helper function to create QR-Code Png image with one static call.
@param String $text text string to encode
@param String $outfile (optional) output file name, if __false__ outputs to browser with required headers
@param Integer $level (optional) error correction level __QR_ECLEVEL_L__, __QR_ECLEVEL_M__, __QR_ECLEVEL_Q__ or __QR_ECLEVEL_H__
@param Integer $size (optional) pixel size, multiplier for each 'virtual' pixel
@param Integer $margin (optional) code margin (silent zone) in 'virtual' pixels
@param Boolean $saveandprint (optional) if __true__ code is outputed to browser and saved to file, otherwise only saved to file. It is effective only if $outfile is specified.
*/
public static function png($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4, $saveandprint=false)
{
$enc = QRencode::factory($level, $size, $margin);
return $enc->encodePNG($text, $outfile, $saveandprint=false);
}
//----------------------------------------------------------------------
/**
Creates text (1's & 0's) containing QR-Code.
Simple helper function to create QR-Code text with one static call.
@param String $text text string to encode
@param String $outfile (optional) output file name, when __false__ file is not saved
@param Integer $level (optional) error correction level __QR_ECLEVEL_L__, __QR_ECLEVEL_M__, __QR_ECLEVEL_Q__ or __QR_ECLEVEL_H__
@param Integer $size (optional) pixel size, multiplier for each 'virtual' pixel
@param Integer $margin (optional) code margin (silent zone) in 'virtual' pixels
@return Array containing line of code with 1 and 0 for every code line
*/
public static function text($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4)
{
$enc = QRencode::factory($level, $size, $margin);
return $enc->encode($text, $outfile);
}
//----------------------------------------------------------------------
/**
Creates Raw Array containing QR-Code.
Simple helper function to create QR-Code array with one static call.
@param String $text text string to encode
@param Boolean $outfile (optional) not used, shuold be __false__
@param Integer $level (optional) error correction level __QR_ECLEVEL_L__, __QR_ECLEVEL_M__, __QR_ECLEVEL_Q__ or __QR_ECLEVEL_H__
@param Integer $size (optional) pixel size, multiplier for each 'virtual' pixel
@param Integer $margin (optional) code margin (silent zone) in 'virtual' pixels
@return Array containing Raw QR code
*/
public static function raw($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4)
{
$enc = QRencode::factory($level, $size, $margin);
return $enc->encodeRAW($text, $outfile);
}
//----------------------------------------------------------------------
/**
Creates Html+JS code to draw QR-Code with HTML5 Canvas.
Simple helper function to create QR-Code array with one static call.
@param String $text text string to encode
@param String $elemId (optional) target Canvas tag id attribute, if __false__ Canvas tag with auto id will be created
@param Integer $level (optional) error correction level __QR_ECLEVEL_L__, __QR_ECLEVEL_M__, __QR_ECLEVEL_Q__ or __QR_ECLEVEL_H__
@param Integer $width (optional) CANVAS element width (sam as height)
@param Integer $size (optional) pixel size, multiplier for each 'virtual' pixel
@param Integer $margin (optional) code margin (silent zone) in 'virtual' pixels
@param Boolean $autoInclude (optional) if __true__, required qrcanvas.js lib will be included (only once)
@return String containing JavaScript creating the code, Canvas element (when $elemId is __false__) and script tag with required lib (when $autoInclude is __true__ and not yet included)
*/
public static function canvas($text, $elemId = false, $level = QR_ECLEVEL_L, $width = false, $size = false, $margin = 4, $autoInclude = false)
{
$html = '';
$extra = '';
if ($autoInclude) {
if (!self::$jscanvasincluded) {
self::$jscanvasincluded = true;
echo '<script type="text/javascript" src="qrcanvas.js"></script>';
}
}
$enc = QRencode::factory($level, 1, 0);
$tab_src = $enc->encode($text, false);
$area = new QRcanvasOutput($tab_src);
$area->detectGroups();
$area->detectAreas();
if ($elemId === false) {
$elemId = 'qrcode-'.md5(mt_rand(1000,1000000).'.'.mt_rand(1000,1000000).'.'.mt_rand(1000,1000000).'.'.mt_rand(1000,1000000));
if ($width == false) {
if (($size !== false) && ($size > 0)) {
$width = ($area->getWidth()+(2*$margin)) * $size;
} else {
$width = ($area->getWidth()+(2*$margin)) * 4;
}
}
$html .= '<canvas id="'.$elemId.'" width="'.$width.'" height="'.$width.'">Your browser does not support CANVAS tag! Please upgrade to modern version of FireFox, Opera, Chrome or Safari/Webkit based browser</canvas>';
}
if ($width !== false) {
$extra .= ', '.$width.', '.$width;
}
if ($margin !== false) {
$extra .= ', '.$margin.', '.$margin;
}
$html .= '<script>if(eval("typeof "+\'QRdrawCode\'+"==\'function\'")){QRdrawCode(QRdecompactOps(\''.$area->getCanvasOps().'\')'."\n".', \''.$elemId.'\', '.$area->getWidth().' '.$extra.');}else{alert(\'Please include qrcanvas.js!\');}</script>';
return $html;
}
//----------------------------------------------------------------------
/**
Creates SVG with QR-Code.
Simple helper function to create QR-Code SVG with one static call.
@param String $text text string to encode
@param Boolean $elemId (optional) target SVG tag id attribute, if __false__ SVG tag with auto id will be created
@param String $outfile (optional) output file name, when __false__ file is not saved
@param Integer $level (optional) error correction level __QR_ECLEVEL_L__, __QR_ECLEVEL_M__, __QR_ECLEVEL_Q__ or __QR_ECLEVEL_H__
@param Integer $width (optional) SVG element width (sam as height)
@param Integer $size (optional) pixel size, multiplier for each 'virtual' pixel
@param Integer $margin (optional) code margin (silent zone) in 'virtual' pixels
@param Boolean $compress (optional) if __true__, compressed SVGZ (instead plaintext SVG) is saved to file
@return String containing SVG tag
*/
public static function svg($text, $elemId = false, $outFile = false, $level = QR_ECLEVEL_L, $width = false, $size = false, $margin = 4, $compress = false)
{
$enc = QRencode::factory($level, 1, 0);
$tab_src = $enc->encode($text, false);
$area = new QRsvgOutput($tab_src);
$area->detectGroups();
$area->detectAreas();
if ($elemId === false) {
$elemId = 'qrcode-'.md5(mt_rand(1000,1000000).'.'.mt_rand(1000,1000000).'.'.mt_rand(1000,1000000).'.'.mt_rand(1000,1000000));
if ($width == false) {
if (($size !== false) && ($size > 0)) {
$width = ($area->getWidth()+(2*$margin)) * $size;
} else {
$width = ($area->getWidth()+(2*$margin)) * 4;
}
}
}
$svg = '<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
version="1.1"
baseProfile="full"
viewBox="'.(-$margin).' '.(-$margin).' '.($area->getWidth()+($margin*2)).' '.($area->getWidth()+($margin*2)).'"
width="'.$width.'"
height="'.$width.'"
id="'.$elemId.'">'."\n";
$svg .= $area->getRawSvg().'</svg>';
if ($outFile !== false) {
$xmlPreamble = '<?xml version="1.0" encoding="UTF-8" standalone="no"?>'."\n";
$svgContent = $xmlPreamble.$svg;
if ($compress === true) {
file_put_contents($outFile, gzencode($svgContent));
} else {
file_put_contents($outFile, $svgContent);
}
}
return $svg;
}
}
//##########################################################################
/** Fills frame with data.
Each empty frame consist of markers, timing symbols and format configuration.
Remaining place is place for data, and should be filled according to QR Code spec.
*/
class QRframeFiller {
public $width; ///< __Integer__ Frame width
public $frame; ///< __Array__ Frame itself
public $x; ///< __Integer__ current X position
public $y; ///< __Integer__ current Y position
public $dir; ///< __Integer__ direction
public $bit; ///< __Integer__ bit
//----------------------------------------------------------------------
/** Frame filler Constructor.
@param Integer $width frame size
@param Array $frame Frame array
*/
public function __construct($width, &$frame)
{
$this->width = $width;
$this->frame = $frame;
$this->x = $width - 1;
$this->y = $width - 1;
$this->dir = -1;
$this->bit = -1;
}
//----------------------------------------------------------------------
/** Sets frame code at given position.
@param Array $at position, map containing __x__ and __y__ coordinates
@param Integer $val value to set
*/
public function setFrameAt($at, $val)
{
$this->frame[$at['y']][$at['x']] = chr($val);
}
//----------------------------------------------------------------------
/** Gets frame code from given position.
@param Array $at position, map containing __x__ and __y__ coordinates
@return Integer value at requested position
*/
public function getFrameAt($at)
{
return ord($this->frame[$at['y']][$at['x']]);
}
//----------------------------------------------------------------------
/** Proceed to next code point. */
public function next()
{
do {
if($this->bit == -1) {
$this->bit = 0;
return array('x'=>$this->x, 'y'=>$this->y);
}
$x = $this->x;
$y = $this->y;
$w = $this->width;
if($this->bit == 0) {
$x--;
$this->bit++;
} else {
$x++;
$y += $this->dir;
$this->bit--;
}
if($this->dir < 0) {
if($y < 0) {
$y = 0;
$x -= 2;
$this->dir = 1;
if($x == 6) {
$x--;
$y = 9;
}
}
} else {
if($y == $w) {
$y = $w - 1;
$x -= 2;
$this->dir = -1;
if($x == 6) {
$x--;
$y -= 8;
}
}
}
if($x < 0 || $y < 0) return null;
$this->x = $x;
$this->y = $y;
} while(ord($this->frame[$y][$x]) & 0x80);
return array('x'=>$x, 'y'=>$y);
}
} ;
//##########################################################################
/** QR Code encoder.
Encoder is used by QRCode to create simple static code generators. */
class QRencode {
public $casesensitive = true; ///< __Boolean__ does input stream id case sensitive, if not encoder may use more optimal charsets
public $eightbit = false; ///< __Boolean__ does input stream is 8 bit
public $version = 0; ///< __Integer__ code version (total size) if __0__ - will be auto-detected
public $size = 3; ///< __Integer__ pixel zoom factor, multiplier to map virtual code pixels to image output pixels
public $margin = 4; ///< __Integer__ margin (silent zone) size, in code pixels
public $structured = 0; ///< Structured QR codes. Not supported.
public $level = QR_ECLEVEL_L; ///< __Integer__ error correction level __QR_ECLEVEL_L__, __QR_ECLEVEL_M__, __QR_ECLEVEL_Q__ or __QR_ECLEVEL_H__
public $hint = QR_MODE_8; ///< __Integer__ encoding hint, __QR_MODE_8__ or __QR_MODE_KANJI__, Because Kanji encoding is kind of 8 bit encoding we need to hint encoder to use Kanji mode explicite. (otherwise it may try to encode it as plain 8 bit stream)
//----------------------------------------------------------------------
/** Encoder instances factory.
@param Integer $level error correction level __QR_ECLEVEL_L__, __QR_ECLEVEL_M__, __QR_ECLEVEL_Q__ or __QR_ECLEVEL_H__
@param Integer $size pixel zoom factor, multiplier to map virtual code pixels to image output pixels
@param Integer $margin margin (silent zone) size, in code pixels
@return builded QRencode instance
*/
public static function factory($level = QR_ECLEVEL_L, $size = 3, $margin = 4)
{
$enc = new QRencode();
$enc->size = $size;
$enc->margin = $margin;
switch ($level.'') {
case '0':
case '1':
case '2':
case '3':
$enc->level = $level;
break;
case 'l':
case 'L':
$enc->level = QR_ECLEVEL_L;
break;
case 'm':
case 'M':
$enc->level = QR_ECLEVEL_M;
break;
case 'q':
case 'Q':
$enc->level = QR_ECLEVEL_Q;
break;
case 'h':
case 'H':
$enc->level = QR_ECLEVEL_H;
break;
}
return $enc;
}
//----------------------------------------------------------------------
/** Encodes input into Raw code table.
@param String $intext input text
@param Boolean $notused (optional, not used) placeholder for similar outfile parameter
@return __Array__ Raw code frame
*/
public function encodeRAW($intext, $notused = false)
{
$code = new QRcode();
if($this->eightbit) {
$code->encodeString8bit($intext, $this->version, $this->level);
} else {
$code->encodeString($intext, $this->version, $this->level, $this->hint, $this->casesensitive);
}
return $code->data;
}
//----------------------------------------------------------------------
/** Encodes input into binary code table.
@param String $intext input text
@param String $outfile (optional) output file to save code table, if __false__ file will be not saved
@return __Array__ binary code frame
*/
public function encode($intext, $outfile = false)
{
$code = new QRcode();
if($this->eightbit) {
$code->encodeString8bit($intext, $this->version, $this->level);
} else {
$code->encodeString($intext, $this->version, $this->level, $this->hint, $this->casesensitive);
}
QRtools::markTime('after_encode');
$binarized = QRtools::binarize($code->data);
if ($outfile!== false) {
file_put_contents($outfile, join("\n", $binarized));
}
return $binarized;
}
//----------------------------------------------------------------------
/** Encodes input into PNG image.
@param String $intext input text
@param String $outfile (optional) output file name, if __false__ outputs to browser with required headers
@param Boolean $saveandprint (optional) if __true__ code is outputed to browser and saved to file, otherwise only saved to file. It is effective only if $outfile is specified.
*/
public function encodePNG($intext, $outfile = false, $saveandprint=false)
{
try {
ob_start();
$tab = $this->encode($intext);
$err = ob_get_contents();
ob_end_clean();
if ($err != '')
QRtools::log($outfile, $err);
$maxSize = (int)(QR_PNG_MAXIMUM_SIZE / (count($tab)+2*$this->margin));
QRimage::png($tab, $outfile, min(max(1, $this->size), $maxSize), $this->margin,$saveandprint);
} catch (Exception $e) {
QRtools::log($outfile, $e->getMessage());
}
}
}
/** @}*/

View File

@@ -0,0 +1,131 @@
<?php
/*
* PHP QR Code encoder
*
* Image output of code using GD2
*
* PHP QR Code is distributed under LGPL 3
* Copyright (C) 2010-2013 Dominik Dzienia <deltalab at poczta dot fm>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
define('QR_IMAGE', true);
/** @defgroup OutputGroup Standard API Output
Provide simple Raster & Vector output */
/** @addtogroup OutputGroup */
/** @{ */
/** Image rendering helper.
Uses GD2 image to render QR Code into image file */
class QRimage {
//----------------------------------------------------------------------
/**
Creates PNG image.
@param Array $frame frame containing code
@param String $filename (optional) output file name, if __false__ outputs to browser with required headers
@param Integer $pixelPerPoint (optional) pixel size, multiplier for each 'virtual' pixel
@param Integer $outerFrame (optional) code margin (silent zone) in 'virtual' pixels
@param Boolean $saveandprint (optional) if __true__ code is outputed to browser and saved to file, otherwise only saved to file. It is effective only if $outfile is specified.
*/
public static function png($frame, $filename = false, $pixelPerPoint = 4, $outerFrame = 4,$saveandprint=FALSE)
{
$image = self::image($frame, $pixelPerPoint, $outerFrame);
if ($filename === false) {
Header("Content-type: image/png");
ImagePng($image);
} else {
if($saveandprint===TRUE){
ImagePng($image, $filename);
header("Content-type: image/png");
ImagePng($image);
}else{
ImagePng($image, $filename);
}
}
ImageDestroy($image);
}
//----------------------------------------------------------------------
/**
Creates JPEG image.
@param Array $frame frame containing code
@param String $filename (optional) output file name, if __false__ outputs to browser with required headers
@param Integer $pixelPerPoint (optional) pixel size, multiplier for each 'virtual' pixel
@param Integer $outerFrame (optional) code margin (silent zone) in 'virtual' pixels
@param Integer $q (optional) JPEG compression level (__0__ .. __100__)
*/
public static function jpg($frame, $filename = false, $pixelPerPoint = 8, $outerFrame = 4, $q = 85)
{
$image = self::image($frame, $pixelPerPoint, $outerFrame);
if ($filename === false) {
Header("Content-type: image/jpeg");
ImageJpeg($image, null, $q);
} else {
ImageJpeg($image, $filename, $q);
}
ImageDestroy($image);
}
//----------------------------------------------------------------------
/**
Creates generic GD2 image object
@param Array $frame frame containing code
@param Integer $pixelPerPoint (optional) pixel size, multiplier for each 'virtual' pixel
@param Integer $outerFrame (optional) code margin (silent zone) in 'virtual' pixels
@return __Resource__ GD2 image resource (remember to ImageDestroy it!)
*/
public static function image($frame, $pixelPerPoint = 4, $outerFrame = 4)
{
$h = count($frame);
$w = strlen($frame[0]);
$imgW = $w + 2*$outerFrame;
$imgH = $h + 2*$outerFrame;
$base_image =ImageCreate($imgW, $imgH);
$col[0] = ImageColorAllocate($base_image,255,255,255);
$col[1] = ImageColorAllocate($base_image,0,0,0);
imagefill($base_image, 0, 0, $col[0]);
for($y=0; $y<$h; $y++) {
for($x=0; $x<$w; $x++) {
if ($frame[$y][$x] == '1') {
ImageSetPixel($base_image,$x+$outerFrame,$y+$outerFrame,$col[1]);
}
}
}
$target_image =ImageCreate($imgW * $pixelPerPoint, $imgH * $pixelPerPoint);
ImageCopyResized($target_image, $base_image, 0, 0, 0, 0, $imgW * $pixelPerPoint, $imgH * $pixelPerPoint, $imgW, $imgH);
ImageDestroy($base_image);
return $target_image;
}
}
/** @} */

View File

@@ -0,0 +1,731 @@
<?php
/*
* PHP QR Code encoder
*
* Input encoding class
*
* Based on libqrencode C library distributed under LGPL 2.1
* Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
*
* PHP QR Code is distributed under LGPL 3
* Copyright (C) 2010-2013 Dominik Dzienia <deltalab at poczta dot fm>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
define('STRUCTURE_HEADER_BITS', 20);
define('MAX_STRUCTURED_SYMBOLS', 16);
/** @addtogroup CoreGroup */
/** @{ */
class QRinputItem {
public $mode;
public $size;
public $data;
public $bstream;
public function __construct($mode, $size, $data, $bstream = null)
{
$setData = array_slice($data, 0, $size);
if (count($setData) < $size) {
$setData = array_merge($setData, array_fill(0,$size-count($setData),0));
}
if(!QRinput::check($mode, $size, $setData)) {
throw new Exception('Error m:'.$mode.',s:'.$size.',d:'.join(',',$setData));
return null;
}
$this->mode = $mode;
$this->size = $size;
$this->data = $setData;
$this->bstream = $bstream;
}
//----------------------------------------------------------------------
public function encodeModeNum($version)
{
try {
$words = (int)($this->size / 3);
$bs = new QRbitstream();
$val = 0x1;
$bs->appendNum(4, $val);
$bs->appendNum(QRspec::lengthIndicator(QR_MODE_NUM, $version), $this->size);
for($i=0; $i<$words; $i++) {
$val = (ord($this->data[$i*3 ]) - ord('0')) * 100;
$val += (ord($this->data[$i*3+1]) - ord('0')) * 10;
$val += (ord($this->data[$i*3+2]) - ord('0'));
$bs->appendNum(10, $val);
}
if($this->size - $words * 3 == 1) {
$val = ord($this->data[$words*3]) - ord('0');
$bs->appendNum(4, $val);
} else if($this->size - $words * 3 == 2) {
$val = (ord($this->data[$words*3 ]) - ord('0')) * 10;
$val += (ord($this->data[$words*3+1]) - ord('0'));
$bs->appendNum(7, $val);
}
$this->bstream = $bs;
return 0;
} catch (Exception $e) {
return -1;
}
}
//----------------------------------------------------------------------
public function encodeModeAn($version)
{
try {
$words = (int)($this->size / 2);
$bs = new QRbitstream();
$bs->appendNum(4, 0x02);
$bs->appendNum(QRspec::lengthIndicator(QR_MODE_AN, $version), $this->size);
for($i=0; $i<$words; $i++) {
$val = (int)QRinput::lookAnTable(ord($this->data[$i*2 ])) * 45;
$val += (int)QRinput::lookAnTable(ord($this->data[$i*2+1]));
$bs->appendNum(11, $val);
}
if($this->size & 1) {
$val = QRinput::lookAnTable(ord($this->data[$words * 2]));
$bs->appendNum(6, $val);
}
$this->bstream = $bs;
return 0;
} catch (Exception $e) {
return -1;
}
}
//----------------------------------------------------------------------
public function encodeMode8($version)
{
try {
$bs = new QRbitstream();
$bs->appendNum(4, 0x4);
$bs->appendNum(QRspec::lengthIndicator(QR_MODE_8, $version), $this->size);
for($i=0; $i<$this->size; $i++) {
$bs->appendNum(8, ord($this->data[$i]));
}
$this->bstream = $bs;
return 0;
} catch (Exception $e) {
return -1;
}
}
//----------------------------------------------------------------------
public function encodeModeKanji($version)
{
try {
$bs = new QRbitrtream();
$bs->appendNum(4, 0x8);
$bs->appendNum(QRspec::lengthIndicator(QR_MODE_KANJI, $version), (int)($this->size / 2));
for($i=0; $i<$this->size; $i+=2) {
$val = (ord($this->data[$i]) << 8) | ord($this->data[$i+1]);
if($val <= 0x9ffc) {
$val -= 0x8140;
} else {
$val -= 0xc140;
}
$h = ($val >> 8) * 0xc0;
$val = ($val & 0xff) + $h;
$bs->appendNum(13, $val);
}
$this->bstream = $bs;
return 0;
} catch (Exception $e) {
return -1;
}
}
//----------------------------------------------------------------------
public function encodeModeStructure()
{
try {
$bs = new QRbitstream();
$bs->appendNum(4, 0x03);
$bs->appendNum(4, ord($this->data[1]) - 1);
$bs->appendNum(4, ord($this->data[0]) - 1);
$bs->appendNum(8, ord($this->data[2]));
$this->bstream = $bs;
return 0;
} catch (Exception $e) {
return -1;
}
}
//----------------------------------------------------------------------
public function estimateBitStreamSizeOfEntry($version)
{
$bits = 0;
if($version == 0)
$version = 1;
switch($this->mode) {
case QR_MODE_NUM: $bits = QRinput::estimateBitsModeNum($this->size); break;
case QR_MODE_AN: $bits = QRinput::estimateBitsModeAn($this->size); break;
case QR_MODE_8: $bits = QRinput::estimateBitsMode8($this->size); break;
case QR_MODE_KANJI: $bits = QRinput::estimateBitsModeKanji($this->size);break;
case QR_MODE_STRUCTURE: return STRUCTURE_HEADER_BITS;
default:
return 0;
}
$l = QRspec::lengthIndicator($this->mode, $version);
$m = 1 << $l;
$num = (int)(($this->size + $m - 1) / $m);
$bits += $num * (4 + $l);
return $bits;
}
//----------------------------------------------------------------------
public function encodeBitStream($version)
{
try {
unset($this->bstream);
$words = QRspec::maximumWords($this->mode, $version);
if($this->size > $words) {
$st1 = new QRinputItem($this->mode, $words, $this->data);
$st2 = new QRinputItem($this->mode, $this->size - $words, array_slice($this->data, $words));
$st1->encodeBitStream($version);
$st2->encodeBitStream($version);
$this->bstream = new QRbitstream();
$this->bstream->append($st1->bstream);
$this->bstream->append($st2->bstream);
unset($st1);
unset($st2);
} else {
$ret = 0;
switch($this->mode) {
case QR_MODE_NUM: $ret = $this->encodeModeNum($version); break;
case QR_MODE_AN: $ret = $this->encodeModeAn($version); break;
case QR_MODE_8: $ret = $this->encodeMode8($version); break;
case QR_MODE_KANJI: $ret = $this->encodeModeKanji($version);break;
case QR_MODE_STRUCTURE: $ret = $this->encodeModeStructure(); break;
default:
break;
}
if($ret < 0)
return -1;
}
return $this->bstream->size();
} catch (Exception $e) {
return -1;
}
}
};
//##########################################################################
class QRinput {
public $items;
private $version;
private $level;
//----------------------------------------------------------------------
public function __construct($version = 0, $level = QR_ECLEVEL_L)
{
if ($version < 0 || $version > QRSPEC_VERSION_MAX || $level > QR_ECLEVEL_H) {
throw new Exception('Invalid version no');
return NULL;
}
$this->version = $version;
$this->level = $level;
}
//----------------------------------------------------------------------
public function getVersion()
{
return $this->version;
}
//----------------------------------------------------------------------
public function setVersion($version)
{
if($version < 0 || $version > QRSPEC_VERSION_MAX) {
throw new Exception('Invalid version no');
return -1;
}
$this->version = $version;
return 0;
}
//----------------------------------------------------------------------
public function getErrorCorrectionLevel()
{
return $this->level;
}
//----------------------------------------------------------------------
public function setErrorCorrectionLevel($level)
{
if($level > QR_ECLEVEL_H) {
throw new Exception('Invalid ECLEVEL');
return -1;
}
$this->level = $level;
return 0;
}
//----------------------------------------------------------------------
public function appendEntry(QRinputItem $entry)
{
$this->items[] = $entry;
}
//----------------------------------------------------------------------
public function append($mode, $size, $data)
{
try {
$entry = new QRinputItem($mode, $size, $data);
$this->items[] = $entry;
return 0;
} catch (Exception $e) {
return -1;
}
}
//----------------------------------------------------------------------
public function insertStructuredAppendHeader($size, $index, $parity)
{
if( $size > MAX_STRUCTURED_SYMBOLS ) {
throw new Exception('insertStructuredAppendHeader wrong size');
}
if( $index <= 0 || $index > MAX_STRUCTURED_SYMBOLS ) {
throw new Exception('insertStructuredAppendHeader wrong index');
}
$buf = array($size, $index, $parity);
try {
$entry = new QRinputItem(QR_MODE_STRUCTURE, 3, buf);
array_unshift($this->items, $entry);
return 0;
} catch (Exception $e) {
return -1;
}
}
//----------------------------------------------------------------------
public function calcParity()
{
$parity = 0;
foreach($this->items as $item) {
if($item->mode != QR_MODE_STRUCTURE) {
for($i=$item->size-1; $i>=0; $i--) {
$parity ^= $item->data[$i];
}
}
}
return $parity;
}
//----------------------------------------------------------------------
public static function checkModeNum($size, $data)
{
for($i=0; $i<$size; $i++) {
if((ord($data[$i]) < ord('0')) || (ord($data[$i]) > ord('9'))){
return false;
}
}
return true;
}
//----------------------------------------------------------------------
public static function estimateBitsModeNum($size)
{
$w = (int)$size / 3;
$bits = $w * 10;
switch($size - $w * 3) {
case 1:
$bits += 4;
break;
case 2:
$bits += 7;
break;
default:
break;
}
return $bits;
}
//----------------------------------------------------------------------
public static $anTable = array(
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 44, -1, -1, -1, -1, -1,
-1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
);
//----------------------------------------------------------------------
public static function lookAnTable($c)
{
return (($c > 127)?-1:self::$anTable[$c]);
}
//----------------------------------------------------------------------
public static function checkModeAn($size, $data)
{
for($i=0; $i<$size; $i++) {
if (self::lookAnTable(ord($data[$i])) == -1) {
return false;
}
}
return true;
}
//----------------------------------------------------------------------
public static function estimateBitsModeAn($size)
{
$w = (int)($size / 2);
$bits = $w * 11;
if($size & 1) {
$bits += 6;
}
return $bits;
}
//----------------------------------------------------------------------
public static function estimateBitsMode8($size)
{
return $size * 8;
}
//----------------------------------------------------------------------
public function estimateBitsModeKanji($size)
{
return (int)(($size / 2) * 13);
}
//----------------------------------------------------------------------
public static function checkModeKanji($size, $data)
{
if($size & 1)
return false;
for($i=0; $i<$size; $i+=2) {
$val = (ord($data[$i]) << 8) | ord($data[$i+1]);
if( $val < 0x8140
|| ($val > 0x9ffc && $val < 0xe040)
|| $val > 0xebbf) {
return false;
}
}
return true;
}
/***********************************************************************
* Validation
**********************************************************************/
public static function check($mode, $size, $data)
{
if($size <= 0)
return false;
switch($mode) {
case QR_MODE_NUM: return self::checkModeNum($size, $data); break;
case QR_MODE_AN: return self::checkModeAn($size, $data); break;
case QR_MODE_KANJI: return self::checkModeKanji($size, $data); break;
case QR_MODE_8: return true; break;
case QR_MODE_STRUCTURE: return true; break;
default:
break;
}
return false;
}
//----------------------------------------------------------------------
public function estimateBitStreamSize($version)
{
$bits = 0;
foreach($this->items as $item) {
$bits += $item->estimateBitStreamSizeOfEntry($version);
}
return $bits;
}
//----------------------------------------------------------------------
public function estimateVersion()
{
$version = 0;
$prev = 0;
do {
$prev = $version;
$bits = $this->estimateBitStreamSize($prev);
$version = QRspec::getMinimumVersion((int)(($bits + 7) / 8), $this->level);
if ($version < 0) {
return -1;
}
} while ($version > $prev);
return $version;
}
//----------------------------------------------------------------------
public static function lengthOfCode($mode, $version, $bits)
{
$payload = $bits - 4 - QRspec::lengthIndicator($mode, $version);
switch($mode) {
case QR_MODE_NUM:
$chunks = (int)($payload / 10);
$remain = $payload - $chunks * 10;
$size = $chunks * 3;
if($remain >= 7) {
$size += 2;
} else if($remain >= 4) {
$size += 1;
}
break;
case QR_MODE_AN:
$chunks = (int)($payload / 11);
$remain = $payload - $chunks * 11;
$size = $chunks * 2;
if($remain >= 6)
$size++;
break;
case QR_MODE_8:
$size = (int)($payload / 8);
break;
case QR_MODE_KANJI:
$size = (int)(($payload / 13) * 2);
break;
case QR_MODE_STRUCTURE:
$size = (int)($payload / 8);
break;
default:
$size = 0;
break;
}
$maxsize = QRspec::maximumWords($mode, $version);
if($size < 0) $size = 0;
if($size > $maxsize) $size = $maxsize;
return $size;
}
//----------------------------------------------------------------------
public function createBitStream()
{
$total = 0;
foreach($this->items as $item) {
$bits = $item->encodeBitStream($this->version);
if($bits < 0)
return -1;
$total += $bits;
}
return $total;
}
//----------------------------------------------------------------------
public function convertData()
{
$ver = $this->estimateVersion();
if($ver > $this->getVersion()) {
$this->setVersion($ver);
}
for(;;) {
$bits = $this->createBitStream();
if($bits < 0)
return -1;
$ver = QRspec::getMinimumVersion((int)(($bits + 7) / 8), $this->level);
if($ver < 0) {
throw new Exception('WRONG VERSION');
return -1;
} else if($ver > $this->getVersion()) {
$this->setVersion($ver);
} else {
break;
}
}
return 0;
}
//----------------------------------------------------------------------
public function appendPaddingBit(&$bstream)
{
$bits = $bstream->size();
$maxwords = QRspec::getDataLength($this->version, $this->level);
$maxbits = $maxwords * 8;
if ($maxbits == $bits) {
return 0;
}
if ($maxbits - $bits < 5) {
return $bstream->appendNum($maxbits - $bits, 0);
}
$bits += 4;
$words = (int)(($bits + 7) / 8);
$padding = new QRbitstream();
$ret = $padding->appendNum($words * 8 - $bits + 4, 0);
if($ret < 0)
return $ret;
$padlen = $maxwords - $words;
if($padlen > 0) {
$padbuf = array();
for($i=0; $i<$padlen; $i++) {
$padbuf[$i] = ($i&1)?0x11:0xec;
}
$ret = $padding->appendBytes($padlen, $padbuf);
if($ret < 0)
return $ret;
}
$ret = $bstream->append($padding);
return $ret;
}
//----------------------------------------------------------------------
public function mergeBitStream()
{
if($this->convertData() < 0) {
return null;
}
$bstream = new QRbitstream();
foreach($this->items as $item) {
$ret = $bstream->append($item->bstream);
if($ret < 0) {
return null;
}
}
return $bstream;
}
//----------------------------------------------------------------------
public function getBitStream()
{
$bstream = $this->mergeBitStream();
if($bstream == null) {
return null;
}
$ret = $this->appendPaddingBit($bstream);
if($ret < 0) {
return null;
}
return $bstream;
}
//----------------------------------------------------------------------
public function getByteStream()
{
$bstream = $this->getBitStream();
if($bstream == null) {
return null;
}
return $bstream->toByte();
}
}
/** @}*/

View File

@@ -0,0 +1,49 @@
<?php
/*
* PHP QR Code encoder
*
* Root library file, prepares environment and includes dependencies
*
* Based on libqrencode C library distributed under LGPL 2.1
* Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
*
* PHP QR Code is distributed under LGPL 3
* Copyright (C) 2010-2013 Dominik Dzienia <deltalab at poczta dot fm>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
$QR_BASEDIR = dirname(__FILE__).DIRECTORY_SEPARATOR;
// Required libs
include $QR_BASEDIR."qrconst.php";
include $QR_BASEDIR."qrconfig.php";
include $QR_BASEDIR."qrtools.php";
include $QR_BASEDIR."qrspec.php";
include $QR_BASEDIR."qrimage.php";
include $QR_BASEDIR."qrinput.php";
include $QR_BASEDIR."qrbitstream.php";
include $QR_BASEDIR."qrsplit.php";
include $QR_BASEDIR."qrrscode.php";
include $QR_BASEDIR."qrmask.php";
include $QR_BASEDIR."qrencode.php";
include $QR_BASEDIR."qrarea.php";
include $QR_BASEDIR."qrcanvas.php";
include $QR_BASEDIR."qrsvg.php";
//

View File

@@ -0,0 +1,335 @@
<?php
/*
* PHP QR Code encoder
*
* Masking
*
* Based on libqrencode C library distributed under LGPL 2.1
* Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
*
* PHP QR Code is distributed under LGPL 3
* Copyright (C) 2010-2013 Dominik Dzienia <deltalab at poczta dot fm>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
define('N1', 3);
define('N2', 3);
define('N3', 40);
define('N4', 10);
/** @addtogroup CoreGroup */
/** @{ */
class QRmask {
public $runLength = array();
//----------------------------------------------------------------------
public function __construct()
{
$this->runLength = array_fill(0, QRSPEC_WIDTH_MAX + 1, 0);
}
//----------------------------------------------------------------------
public function writeFormatInformation($width, &$frame, $mask, $level)
{
$blacks = 0;
$format = QRspec::getFormatInfo($mask, $level);
for($i=0; $i<8; $i++) {
if($format & 1) {
$blacks += 2;
$v = 0x85;
} else {
$v = 0x84;
}
$frame[8][$width - 1 - $i] = chr($v);
if($i < 6) {
$frame[$i][8] = chr($v);
} else {
$frame[$i + 1][8] = chr($v);
}
$format = $format >> 1;
}
for($i=0; $i<7; $i++) {
if($format & 1) {
$blacks += 2;
$v = 0x85;
} else {
$v = 0x84;
}
$frame[$width - 7 + $i][8] = chr($v);
if($i == 0) {
$frame[8][7] = chr($v);
} else {
$frame[8][6 - $i] = chr($v);
}
$format = $format >> 1;
}
return $blacks;
}
//----------------------------------------------------------------------
public function mask0($x, $y) { return ($x+$y)&1; }
public function mask1($x, $y) { return ($y&1); }
public function mask2($x, $y) { return ($x%3); }
public function mask3($x, $y) { return ($x+$y)%3; }
public function mask4($x, $y) { return (((int)($y/2))+((int)($x/3)))&1; }
public function mask5($x, $y) { return (($x*$y)&1)+($x*$y)%3; }
public function mask6($x, $y) { return ((($x*$y)&1)+($x*$y)%3)&1; }
public function mask7($x, $y) { return ((($x*$y)%3)+(($x+$y)&1))&1; }
//----------------------------------------------------------------------
private function generateMaskNo($maskNo, $width, $frame)
{
$bitMask = array_fill(0, $width, array_fill(0, $width, 0));
for($y=0; $y<$width; $y++) {
for($x=0; $x<$width; $x++) {
if(ord($frame[$y][$x]) & 0x80) {
$bitMask[$y][$x] = 0;
} else {
$maskFunc = call_user_func(array($this, 'mask'.$maskNo), $x, $y);
$bitMask[$y][$x] = ($maskFunc == 0)?1:0;
}
}
}
return $bitMask;
}
//----------------------------------------------------------------------
public static function serial($bitFrame)
{
$codeArr = array();
foreach ($bitFrame as $line)
$codeArr[] = join('', $line);
return gzcompress(join("\n", $codeArr), 9);
}
//----------------------------------------------------------------------
public static function unserial($code)
{
$codeArr = array();
$codeLines = explode("\n", gzuncompress($code));
foreach ($codeLines as $line)
$codeArr[] = str_split($line);
return $codeArr;
}
//----------------------------------------------------------------------
public function makeMaskNo($maskNo, $width, $s, &$d, $maskGenOnly = false)
{
$b = 0;
$bitMask = array();
$fileName = QR_CACHE_DIR.'mask_'.$maskNo.DIRECTORY_SEPARATOR.'mask_'.$width.'_'.$maskNo.'.dat';
if (QR_CACHEABLE) {
if (file_exists($fileName)) {
$bitMask = self::unserial(file_get_contents($fileName));
} else {
$bitMask = $this->generateMaskNo($maskNo, $width, $s, $d);
if (!file_exists(QR_CACHE_DIR.'mask_'.$maskNo))
mkdir(QR_CACHE_DIR.'mask_'.$maskNo);
file_put_contents($fileName, self::serial($bitMask));
}
} else {
$bitMask = $this->generateMaskNo($maskNo, $width, $s, $d);
}
if ($maskGenOnly)
return;
$d = $s;
for($y=0; $y<$width; $y++) {
for($x=0; $x<$width; $x++) {
if($bitMask[$y][$x] == 1) {
$d[$y][$x] = chr(ord($s[$y][$x]) ^ (int)$bitMask[$y][$x]);
}
$b += (int)(ord($d[$y][$x]) & 1);
}
}
return $b;
}
//----------------------------------------------------------------------
public function makeMask($width, $frame, $maskNo, $level)
{
$masked = array_fill(0, $width, str_repeat("\0", $width));
$this->makeMaskNo($maskNo, $width, $frame, $masked);
$this->writeFormatInformation($width, $masked, $maskNo, $level);
return $masked;
}
//----------------------------------------------------------------------
public function calcN1N3($length)
{
$demerit = 0;
for($i=0; $i<$length; $i++) {
if($this->runLength[$i] >= 5) {
$demerit += (N1 + ($this->runLength[$i] - 5));
}
if($i & 1) {
if(($i >= 3) && ($i < ($length-2)) && ($this->runLength[$i] % 3 == 0)) {
$fact = (int)($this->runLength[$i] / 3);
if(($this->runLength[$i-2] == $fact) &&
($this->runLength[$i-1] == $fact) &&
($this->runLength[$i+1] == $fact) &&
($this->runLength[$i+2] == $fact)) {
if(($this->runLength[$i-3] < 0) || ($this->runLength[$i-3] >= (4 * $fact))) {
$demerit += N3;
} else if((($i+3) >= $length) || ($this->runLength[$i+3] >= (4 * $fact))) {
$demerit += N3;
}
}
}
}
}
return $demerit;
}
//----------------------------------------------------------------------
public function evaluateSymbol($width, $frame)
{
$head = 0;
$demerit = 0;
for($y=0; $y<$width; $y++) {
$head = 0;
$this->runLength[0] = 1;
$frameY = $frame[$y];
if ($y>0)
$frameYM = $frame[$y-1];
for($x=0; $x<$width; $x++) {
if(($x > 0) && ($y > 0)) {
$b22 = ord($frameY[$x]) & ord($frameY[$x-1]) & ord($frameYM[$x]) & ord($frameYM[$x-1]);
$w22 = ord($frameY[$x]) | ord($frameY[$x-1]) | ord($frameYM[$x]) | ord($frameYM[$x-1]);
if(($b22 | ($w22 ^ 1))&1) {
$demerit += N2;
}
}
if(($x == 0) && (ord($frameY[$x]) & 1)) {
$this->runLength[0] = -1;
$head = 1;
$this->runLength[$head] = 1;
} else if($x > 0) {
if((ord($frameY[$x]) ^ ord($frameY[$x-1])) & 1) {
$head++;
$this->runLength[$head] = 1;
} else {
$this->runLength[$head]++;
}
}
}
$demerit += $this->calcN1N3($head+1);
}
for($x=0; $x<$width; $x++) {
$head = 0;
$this->runLength[0] = 1;
for($y=0; $y<$width; $y++) {
if($y == 0 && (ord($frame[$y][$x]) & 1)) {
$this->runLength[0] = -1;
$head = 1;
$this->runLength[$head] = 1;
} else if($y > 0) {
if((ord($frame[$y][$x]) ^ ord($frame[$y-1][$x])) & 1) {
$head++;
$this->runLength[$head] = 1;
} else {
$this->runLength[$head]++;
}
}
}
$demerit += $this->calcN1N3($head+1);
}
return $demerit;
}
//----------------------------------------------------------------------
public function mask($width, $frame, $level)
{
$minDemerit = PHP_INT_MAX;
$bestMaskNum = 0;
$bestMask = array();
$checked_masks = array(0,1,2,3,4,5,6,7);
if (QR_FIND_FROM_RANDOM !== false) {
$howManuOut = 8-(QR_FIND_FROM_RANDOM % 9);
for ($i = 0; $i < $howManuOut; $i++) {
$remPos = rand (0, count($checked_masks)-1);
unset($checked_masks[$remPos]);
$checked_masks = array_values($checked_masks);
}
}
$bestMask = $frame;
foreach($checked_masks as $i) {
$mask = array_fill(0, $width, str_repeat("\0", $width));
$demerit = 0;
$blacks = 0;
$blacks = $this->makeMaskNo($i, $width, $frame, $mask);
$blacks += $this->writeFormatInformation($width, $mask, $i, $level);
$blacks = (int)(100 * $blacks / ($width * $width));
$demerit = (int)((int)(abs($blacks - 50) / 5) * N4);
$demerit += $this->evaluateSymbol($width, $mask);
if($demerit < $minDemerit) {
$minDemerit = $demerit;
$bestMask = $mask;
$bestMaskNum = $i;
}
}
return $bestMask;
}
//----------------------------------------------------------------------
}
/** @}*/

View File

@@ -0,0 +1,251 @@
<?php
/*
* PHP QR Code encoder
*
* Reed-Solomon error correction support
*
* Copyright (C) 2002, 2003, 2004, 2006 Phil Karn, KA9Q
* (libfec is released under the GNU Lesser General Public License.)
*
* Based on libqrencode C library distributed under LGPL 2.1
* Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
*
* PHP QR Code is distributed under LGPL 3
* Copyright (C) 2010-2013 Dominik Dzienia <deltalab at poczta dot fm>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/** @addtogroup CoreGroup */
/** @{ */
/** Reed-Solomon encoder item */
class QRrsItem {
/** Bits per symbol */
public $mm;
/** Symbols per block (= (1<<mm)-1) */
public $nn;
/** Log lookup table */
public $alpha_to = array();
/** Antilog lookup table */
public $index_of = array();
/** Generator polynomial */
public $genpoly = array();
/** Number of generator roots = number of parity symbols */
public $nroots;
/** First consecutive root, index form */
public $fcr;
/** Primitive element, index form */
public $prim;
/** Prim-th root of 1, index form */
public $iprim;
/** Padding bytes in shortened block */
public $pad;
/** Galois Field Polynomial */
public $gfpoly;
//----------------------------------------------------------------------
/** Modulo function in defined Field
@param Integer $x number to be modulo-mapped
*/
public function modnn($x)
{
while ($x >= $this->nn) {
$x -= $this->nn;
$x = ($x >> $this->mm) + ($x & $this->nn);
}
return $x;
}
//----------------------------------------------------------------------
/** Encoder initialisation
@param Integer $symsize symbol size, bit count (1..8)
@param Integer $gfpoly Galois Field Polynomial
@param Integer $fcr First consecutive root
@param Integer $prim Primitive element
@param Integer $nroots Number of generator roots = number of parity symbols
@param Integer $pad Padding bytes in shortened block
*/
public static function init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad)
{
// Common code for intializing a Reed-Solomon control block (char or int symbols)
// Copyright 2004 Phil Karn, KA9Q
// May be used under the terms of the GNU Lesser General Public License (LGPL)
$rs = null;
// Check parameter ranges
if($symsize < 0 || $symsize > 8) return $rs;
if($fcr < 0 || $fcr >= (1<<$symsize)) return $rs;
if($prim <= 0 || $prim >= (1<<$symsize)) return $rs;
if($nroots < 0 || $nroots >= (1<<$symsize)) return $rs; // Can't have more roots than symbol values!
if($pad < 0 || $pad >= ((1<<$symsize) -1 - $nroots)) return $rs; // Too much padding
$rs = new QRrsItem();
$rs->mm = $symsize;
$rs->nn = (1<<$symsize)-1;
$rs->pad = $pad;
$rs->alpha_to = array_fill(0, $rs->nn+1, 0);
$rs->index_of = array_fill(0, $rs->nn+1, 0);
// PHP style macro replacement ;)
$NN =& $rs->nn;
$A0 =& $NN;
// Generate Galois field lookup tables
$rs->index_of[0] = $A0; // log(zero) = -inf
$rs->alpha_to[$A0] = 0; // alpha**-inf = 0
$sr = 1;
for($i=0; $i<$rs->nn; $i++) {
$rs->index_of[$sr] = $i;
$rs->alpha_to[$i] = $sr;
$sr <<= 1;
if($sr & (1<<$symsize)) {
$sr ^= $gfpoly;
}
$sr &= $rs->nn;
}
if($sr != 1){
// field generator polynomial is not primitive!
$rs = NULL;
return $rs;
}
/* Form RS code generator polynomial from its roots */
$rs->genpoly = array_fill(0, $nroots+1, 0);
$rs->fcr = $fcr;
$rs->prim = $prim;
$rs->nroots = $nroots;
$rs->gfpoly = $gfpoly;
/* Find prim-th root of 1, used in decoding */
for($iprim=1;($iprim % $prim) != 0;$iprim += $rs->nn)
; // intentional empty-body loop!
$rs->iprim = (int)($iprim / $prim);
$rs->genpoly[0] = 1;
for ($i = 0,$root=$fcr*$prim; $i < $nroots; $i++, $root += $prim) {
$rs->genpoly[$i+1] = 1;
// Multiply rs->genpoly[] by @**(root + x)
for ($j = $i; $j > 0; $j--) {
if ($rs->genpoly[$j] != 0) {
$rs->genpoly[$j] = $rs->genpoly[$j-1] ^ $rs->alpha_to[$rs->modnn($rs->index_of[$rs->genpoly[$j]] + $root)];
} else {
$rs->genpoly[$j] = $rs->genpoly[$j-1];
}
}
// rs->genpoly[0] can never be zero
$rs->genpoly[0] = $rs->alpha_to[$rs->modnn($rs->index_of[$rs->genpoly[0]] + $root)];
}
// convert rs->genpoly[] to index form for quicker encoding
for ($i = 0; $i <= $nroots; $i++)
$rs->genpoly[$i] = $rs->index_of[$rs->genpoly[$i]];
return $rs;
}
//----------------------------------------------------------------------
/** Appends char into encoder
@param String input
@param Array parity table
*/
public function encode_rs_char($data, &$parity)
{
$MM =& $this->mm;
$NN =& $this->nn;
$ALPHA_TO =& $this->alpha_to;
$INDEX_OF =& $this->index_of;
$GENPOLY =& $this->genpoly;
$NROOTS =& $this->nroots;
$FCR =& $this->fcr;
$PRIM =& $this->prim;
$IPRIM =& $this->iprim;
$PAD =& $this->pad;
$A0 =& $NN;
$parity = array_fill(0, $NROOTS, 0);
for($i=0; $i< ($NN-$NROOTS-$PAD); $i++) {
$feedback = $INDEX_OF[$data[$i] ^ $parity[0]];
if($feedback != $A0) {
// feedback term is non-zero
// This line is unnecessary when GENPOLY[NROOTS] is unity, as it must
// always be for the polynomials constructed by init_rs()
$feedback = $this->modnn($NN - $GENPOLY[$NROOTS] + $feedback);
for($j=1;$j<$NROOTS;$j++) {
$parity[$j] ^= $ALPHA_TO[$this->modnn($feedback + $GENPOLY[$NROOTS-$j])];
}
}
// Shift
array_shift($parity);
if($feedback != $A0) {
array_push($parity, $ALPHA_TO[$this->modnn($feedback + $GENPOLY[0])]);
} else {
array_push($parity, 0);
}
}
}
}
//##########################################################################
/** Reed-Solomon encoder */
class QRrs {
/** Encoder items array */
public static $items = array();
//----------------------------------------------------------------------
/** Encoder initialisation
@param Integer $symsize symbol size, bit count (1..8)
@param Integer $gfpoly Galois Field Polynomial
@param Integer $fcr First consecutive root
@param Integer $prim Primitive element
@param Integer $nroots Number of generator roots = number of parity symbols
@param Integer $pad Padding bytes in shortened block
*/
public static function init_rs($symsize, $gfpoly, $fcr, $prim, $nroots, $pad)
{
foreach(self::$items as $rs) {
if($rs->pad != $pad) continue;
if($rs->nroots != $nroots) continue;
if($rs->mm != $symsize) continue;
if($rs->gfpoly != $gfpoly) continue;
if($rs->fcr != $fcr) continue;
if($rs->prim != $prim) continue;
return $rs;
}
$rs = QRrsItem::init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad);
array_unshift(self::$items, $rs);
return $rs;
}
}
/** @}*/

View File

@@ -0,0 +1,690 @@
<?php
/*
* PHP QR Code encoder
*
* QR Code specifications
*
* Based on libqrencode C library distributed under LGPL 2.1
* Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
*
* PHP QR Code is distributed under LGPL 3
* Copyright (C) 2010-2013 Dominik Dzienia <deltalab at poczta dot fm>
*
* The following data / specifications are taken from
* "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004)
* or
* "Automatic identification and data capture techniques --
* QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/** Maximal Version no allowed by QR-Code spec */
define('QRSPEC_VERSION_MAX', 40);
/** Maximal Code size in pixels allowed by QR-Code spec */
define('QRSPEC_WIDTH_MAX', 177);
define('QRCAP_WIDTH', 0);
define('QRCAP_WORDS', 1);
define('QRCAP_REMINDER', 2);
define('QRCAP_EC', 3);
/** @addtogroup CoreGroup */
/** @{ */
/** QR-Code specification and Code Frame handling.
Contains code specifications, calculates base frame, code structure
and base properties
*/
class QRspec {
/** Array specifying properties of QR-Code "versions".
Each so-called version has specified code area size and capacity.
There are 40 versions, this table specifies for each of them four parameters:
- Integer __QRCAP_WIDTH__ - size of code in pixels
- Integer __QRCAP_WORDS__ - code capacity, in words
- Integer __QRCAP_REMINDER__ - remainder words
- Array of Integers __QRCAP_EC__ - RS correction code count for each of four ECC levels
\hideinitializer
*/
public static $capacity = array(
array( 0, 0, 0, array( 0, 0, 0, 0)),
array( 21, 26, 0, array( 7, 10, 13, 17)), // 1
array( 25, 44, 7, array( 10, 16, 22, 28)),
array( 29, 70, 7, array( 15, 26, 36, 44)),
array( 33, 100, 7, array( 20, 36, 52, 64)),
array( 37, 134, 7, array( 26, 48, 72, 88)), // 5
array( 41, 172, 7, array( 36, 64, 96, 112)),
array( 45, 196, 0, array( 40, 72, 108, 130)),
array( 49, 242, 0, array( 48, 88, 132, 156)),
array( 53, 292, 0, array( 60, 110, 160, 192)),
array( 57, 346, 0, array( 72, 130, 192, 224)), //10
array( 61, 404, 0, array( 80, 150, 224, 264)),
array( 65, 466, 0, array( 96, 176, 260, 308)),
array( 69, 532, 0, array( 104, 198, 288, 352)),
array( 73, 581, 3, array( 120, 216, 320, 384)),
array( 77, 655, 3, array( 132, 240, 360, 432)), //15
array( 81, 733, 3, array( 144, 280, 408, 480)),
array( 85, 815, 3, array( 168, 308, 448, 532)),
array( 89, 901, 3, array( 180, 338, 504, 588)),
array( 93, 991, 3, array( 196, 364, 546, 650)),
array( 97, 1085, 3, array( 224, 416, 600, 700)), //20
array(101, 1156, 4, array( 224, 442, 644, 750)),
array(105, 1258, 4, array( 252, 476, 690, 816)),
array(109, 1364, 4, array( 270, 504, 750, 900)),
array(113, 1474, 4, array( 300, 560, 810, 960)),
array(117, 1588, 4, array( 312, 588, 870, 1050)), //25
array(121, 1706, 4, array( 336, 644, 952, 1110)),
array(125, 1828, 4, array( 360, 700, 1020, 1200)),
array(129, 1921, 3, array( 390, 728, 1050, 1260)),
array(133, 2051, 3, array( 420, 784, 1140, 1350)),
array(137, 2185, 3, array( 450, 812, 1200, 1440)), //30
array(141, 2323, 3, array( 480, 868, 1290, 1530)),
array(145, 2465, 3, array( 510, 924, 1350, 1620)),
array(149, 2611, 3, array( 540, 980, 1440, 1710)),
array(153, 2761, 3, array( 570, 1036, 1530, 1800)),
array(157, 2876, 0, array( 570, 1064, 1590, 1890)), //35
array(161, 3034, 0, array( 600, 1120, 1680, 1980)),
array(165, 3196, 0, array( 630, 1204, 1770, 2100)),
array(169, 3362, 0, array( 660, 1260, 1860, 2220)),
array(173, 3532, 0, array( 720, 1316, 1950, 2310)),
array(177, 3706, 0, array( 750, 1372, 2040, 2430)) //40
);
//----------------------------------------------------------------------
/** Calculates data length for specified code configuration.
@param Integer $version Code version
@param Integer $level ECC level
@returns Code data capacity
*/
public static function getDataLength($version, $level)
{
return self::$capacity[$version][QRCAP_WORDS] - self::$capacity[$version][QRCAP_EC][$level];
}
//----------------------------------------------------------------------
/** Calculates count of Error Correction Codes for specified code configuration.
@param Integer $version Code version
@param Integer $level ECC level
@returns ECC code count
*/
public static function getECCLength($version, $level)
{
return self::$capacity[$version][QRCAP_EC][$level];
}
//----------------------------------------------------------------------
/** Gets pixel width of code.
@param Integer $version Code version
@returns Code width, in pixels
*/
public static function getWidth($version)
{
return self::$capacity[$version][QRCAP_WIDTH];
}
//----------------------------------------------------------------------
/** Gets reminder chars length.
@param Integer $version Code version
@returns Reminder length
*/
public static function getRemainder($version)
{
return self::$capacity[$version][QRCAP_REMINDER];
}
//----------------------------------------------------------------------
/** Finds minimal code version capable of hosting specified data length.
@param Integer $size amount of raw data
@param Integer $level ECC level
@returns code version capable of hosting specified amount of data at specified ECC level
*/
public static function getMinimumVersion($size, $level)
{
for($i=1; $i<= QRSPEC_VERSION_MAX; $i++) {
$words = self::$capacity[$i][QRCAP_WORDS] - self::$capacity[$i][QRCAP_EC][$level];
if($words >= $size)
return $i;
}
return -1;
}
//######################################################################
/** Length bits Table.
\hideinitializer
*/
public static $lengthTableBits = array(
array(10, 12, 14),
array( 9, 11, 13),
array( 8, 16, 16),
array( 8, 10, 12)
);
//----------------------------------------------------------------------
public static function lengthIndicator($mode, $version)
{
if ($mode == QR_MODE_STRUCTURE)
return 0;
if ($version <= 9) {
$l = 0;
} else if ($version <= 26) {
$l = 1;
} else {
$l = 2;
}
return self::$lengthTableBits[$mode][$l];
}
//----------------------------------------------------------------------
public static function maximumWords($mode, $version)
{
if($mode == QR_MODE_STRUCTURE)
return 3;
if($version <= 9) {
$l = 0;
} else if($version <= 26) {
$l = 1;
} else {
$l = 2;
}
$bits = self::$lengthTableBits[$mode][$l];
$words = (1 << $bits) - 1;
if($mode == QR_MODE_KANJI) {
$words *= 2; // the number of bytes is required
}
return $words;
}
// Error correction code -----------------------------------------------
/** Table of the error correction code (Reed-Solomon block).
@see Table 12-16 (pp.30-36), JIS X0510:2004.
\hideinitializer
*/
public static $eccTable = array(
array(array( 0, 0), array( 0, 0), array( 0, 0), array( 0, 0)),
array(array( 1, 0), array( 1, 0), array( 1, 0), array( 1, 0)), // 1
array(array( 1, 0), array( 1, 0), array( 1, 0), array( 1, 0)),
array(array( 1, 0), array( 1, 0), array( 2, 0), array( 2, 0)),
array(array( 1, 0), array( 2, 0), array( 2, 0), array( 4, 0)),
array(array( 1, 0), array( 2, 0), array( 2, 2), array( 2, 2)), // 5
array(array( 2, 0), array( 4, 0), array( 4, 0), array( 4, 0)),
array(array( 2, 0), array( 4, 0), array( 2, 4), array( 4, 1)),
array(array( 2, 0), array( 2, 2), array( 4, 2), array( 4, 2)),
array(array( 2, 0), array( 3, 2), array( 4, 4), array( 4, 4)),
array(array( 2, 2), array( 4, 1), array( 6, 2), array( 6, 2)), //10
array(array( 4, 0), array( 1, 4), array( 4, 4), array( 3, 8)),
array(array( 2, 2), array( 6, 2), array( 4, 6), array( 7, 4)),
array(array( 4, 0), array( 8, 1), array( 8, 4), array(12, 4)),
array(array( 3, 1), array( 4, 5), array(11, 5), array(11, 5)),
array(array( 5, 1), array( 5, 5), array( 5, 7), array(11, 7)), //15
array(array( 5, 1), array( 7, 3), array(15, 2), array( 3, 13)),
array(array( 1, 5), array(10, 1), array( 1, 15), array( 2, 17)),
array(array( 5, 1), array( 9, 4), array(17, 1), array( 2, 19)),
array(array( 3, 4), array( 3, 11), array(17, 4), array( 9, 16)),
array(array( 3, 5), array( 3, 13), array(15, 5), array(15, 10)), //20
array(array( 4, 4), array(17, 0), array(17, 6), array(19, 6)),
array(array( 2, 7), array(17, 0), array( 7, 16), array(34, 0)),
array(array( 4, 5), array( 4, 14), array(11, 14), array(16, 14)),
array(array( 6, 4), array( 6, 14), array(11, 16), array(30, 2)),
array(array( 8, 4), array( 8, 13), array( 7, 22), array(22, 13)), //25
array(array(10, 2), array(19, 4), array(28, 6), array(33, 4)),
array(array( 8, 4), array(22, 3), array( 8, 26), array(12, 28)),
array(array( 3, 10), array( 3, 23), array( 4, 31), array(11, 31)),
array(array( 7, 7), array(21, 7), array( 1, 37), array(19, 26)),
array(array( 5, 10), array(19, 10), array(15, 25), array(23, 25)), //30
array(array(13, 3), array( 2, 29), array(42, 1), array(23, 28)),
array(array(17, 0), array(10, 23), array(10, 35), array(19, 35)),
array(array(17, 1), array(14, 21), array(29, 19), array(11, 46)),
array(array(13, 6), array(14, 23), array(44, 7), array(59, 1)),
array(array(12, 7), array(12, 26), array(39, 14), array(22, 41)), //35
array(array( 6, 14), array( 6, 34), array(46, 10), array( 2, 64)),
array(array(17, 4), array(29, 14), array(49, 10), array(24, 46)),
array(array( 4, 18), array(13, 32), array(48, 14), array(42, 32)),
array(array(20, 4), array(40, 7), array(43, 22), array(10, 67)),
array(array(19, 6), array(18, 31), array(34, 34), array(20, 61)),//40
);
//----------------------------------------------------------------------
// CACHEABLE!!!
public static function getEccSpec($version, $level, array &$spec)
{
if (count($spec) < 5) {
$spec = array(0,0,0,0,0);
}
$b1 = self::$eccTable[$version][$level][0];
$b2 = self::$eccTable[$version][$level][1];
$data = self::getDataLength($version, $level);
$ecc = self::getECCLength($version, $level);
if($b2 == 0) {
$spec[0] = $b1;
$spec[1] = (int)($data / $b1);
$spec[2] = (int)($ecc / $b1);
$spec[3] = 0;
$spec[4] = 0;
} else {
$spec[0] = $b1;
$spec[1] = (int)($data / ($b1 + $b2));
$spec[2] = (int)($ecc / ($b1 + $b2));
$spec[3] = $b2;
$spec[4] = $spec[1] + 1;
}
}
// Alignment pattern ---------------------------------------------------
/** Positions of alignment patterns.
This array includes only the second and the third position of the
lignment patterns. Rest of them can be calculated from the distance
between them.
@see Table 1 in Appendix E (pp.71) of JIS X0510:2004.
\hideinitializer
*/
public static $alignmentPattern = array(
array( 0, 0),
array( 0, 0), array(18, 0), array(22, 0), array(26, 0), array(30, 0), // 1- 5
array(34, 0), array(22, 38), array(24, 42), array(26, 46), array(28, 50), // 6-10
array(30, 54), array(32, 58), array(34, 62), array(26, 46), array(26, 48), //11-15
array(26, 50), array(30, 54), array(30, 56), array(30, 58), array(34, 62), //16-20
array(28, 50), array(26, 50), array(30, 54), array(28, 54), array(32, 58), //21-25
array(30, 58), array(34, 62), array(26, 50), array(30, 54), array(26, 52), //26-30
array(30, 56), array(34, 60), array(30, 58), array(34, 62), array(30, 54), //31-35
array(24, 50), array(28, 54), array(32, 58), array(26, 54), array(30, 58), //35-40
);
//----------------------------------------------------------------------
/** Puts an alignment marker.
@param frame
@param width
@param ox,oy center coordinate of the pattern
*/
public static function putAlignmentMarker(array &$frame, $ox, $oy)
{
$finder = array(
"\xa1\xa1\xa1\xa1\xa1",
"\xa1\xa0\xa0\xa0\xa1",
"\xa1\xa0\xa1\xa0\xa1",
"\xa1\xa0\xa0\xa0\xa1",
"\xa1\xa1\xa1\xa1\xa1"
);
$yStart = $oy-2;
$xStart = $ox-2;
for($y=0; $y<5; $y++) {
self::set($frame, $xStart, $yStart+$y, $finder[$y]);
}
}
//----------------------------------------------------------------------
public static function putAlignmentPattern($version, &$frame, $width)
{
if($version < 2)
return;
$d = self::$alignmentPattern[$version][1] - self::$alignmentPattern[$version][0];
if($d < 0) {
$w = 2;
} else {
$w = (int)(($width - self::$alignmentPattern[$version][0]) / $d + 2);
}
if($w * $w - 3 == 1) {
$x = self::$alignmentPattern[$version][0];
$y = self::$alignmentPattern[$version][0];
self::putAlignmentMarker($frame, $x, $y);
return;
}
$cx = self::$alignmentPattern[$version][0];
for($x=1; $x<$w - 1; $x++) {
self::putAlignmentMarker($frame, 6, $cx);
self::putAlignmentMarker($frame, $cx, 6);
$cx += $d;
}
$cy = self::$alignmentPattern[$version][0];
for($y=0; $y<$w-1; $y++) {
$cx = self::$alignmentPattern[$version][0];
for($x=0; $x<$w-1; $x++) {
self::putAlignmentMarker($frame, $cx, $cy);
$cx += $d;
}
$cy += $d;
}
}
// Version information pattern -----------------------------------------
/** Version information pattern (BCH coded).
size: [QRSPEC_VERSION_MAX - 6]
@see Table 1 in Appendix D (pp.68) of JIS X0510:2004.
\hideinitializer
*/
public static $versionPattern = array(
0x07c94, 0x085bc, 0x09a99, 0x0a4d3, 0x0bbf6, 0x0c762, 0x0d847, 0x0e60d,
0x0f928, 0x10b78, 0x1145d, 0x12a17, 0x13532, 0x149a6, 0x15683, 0x168c9,
0x177ec, 0x18ec4, 0x191e1, 0x1afab, 0x1b08e, 0x1cc1a, 0x1d33f, 0x1ed75,
0x1f250, 0x209d5, 0x216f0, 0x228ba, 0x2379f, 0x24b0b, 0x2542e, 0x26a64,
0x27541, 0x28c69
);
//----------------------------------------------------------------------
public static function getVersionPattern($version)
{
if($version < 7 || $version > QRSPEC_VERSION_MAX)
return 0;
return self::$versionPattern[$version -7];
}
//----------------------------------------------------------------------
/** Format information.
@see calcFormatInfo in tests/test_qrspec.c (orginal qrencode c lib)
\hideinitializer
*/
public static $formatInfo = array(
array(0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976),
array(0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0),
array(0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183, 0x2eda, 0x2bed),
array(0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b)
);
public static function getFormatInfo($mask, $level)
{
if($mask < 0 || $mask > 7)
return 0;
if($level < 0 || $level > 3)
return 0;
return self::$formatInfo[$level][$mask];
}
// Frame ---------------------------------------------------------------
/** Cache of initial frames. */
public static $frames = array();
/** Put a finder pattern.
@param frame
@param width
@param ox,oy upper-left coordinate of the pattern
\hideinitializer
*/
public static function putFinderPattern(&$frame, $ox, $oy)
{
$finder = array(
"\xc1\xc1\xc1\xc1\xc1\xc1\xc1",
"\xc1\xc0\xc0\xc0\xc0\xc0\xc1",
"\xc1\xc0\xc1\xc1\xc1\xc0\xc1",
"\xc1\xc0\xc1\xc1\xc1\xc0\xc1",
"\xc1\xc0\xc1\xc1\xc1\xc0\xc1",
"\xc1\xc0\xc0\xc0\xc0\xc0\xc1",
"\xc1\xc1\xc1\xc1\xc1\xc1\xc1"
);
for($y=0; $y<7; $y++) {
self::set($frame, $ox, $oy+$y, $finder[$y]);
}
}
//----------------------------------------------------------------------
public static function createFrame($version)
{
$width = self::$capacity[$version][QRCAP_WIDTH];
$frameLine = str_repeat ("\0", $width);
$frame = array_fill(0, $width, $frameLine);
// Finder pattern
self::putFinderPattern($frame, 0, 0);
self::putFinderPattern($frame, $width - 7, 0);
self::putFinderPattern($frame, 0, $width - 7);
// Separator
$yOffset = $width - 7;
for($y=0; $y<7; $y++) {
$frame[$y][7] = "\xc0";
$frame[$y][$width - 8] = "\xc0";
$frame[$yOffset][7] = "\xc0";
$yOffset++;
}
$setPattern = str_repeat("\xc0", 8);
self::set($frame, 0, 7, $setPattern);
self::set($frame, $width-8, 7, $setPattern);
self::set($frame, 0, $width - 8, $setPattern);
// Format info
$setPattern = str_repeat("\x84", 9);
self::set($frame, 0, 8, $setPattern);
self::set($frame, $width - 8, 8, $setPattern, 8);
$yOffset = $width - 8;
for($y=0; $y<8; $y++,$yOffset++) {
$frame[$y][8] = "\x84";
$frame[$yOffset][8] = "\x84";
}
// Timing pattern
for($i=1; $i<$width-15; $i++) {
$frame[6][7+$i] = chr(0x90 | ($i & 1));
$frame[7+$i][6] = chr(0x90 | ($i & 1));
}
// Alignment pattern
self::putAlignmentPattern($version, $frame, $width);
// Version information
if($version >= 7) {
$vinf = self::getVersionPattern($version);
$v = $vinf;
for($x=0; $x<6; $x++) {
for($y=0; $y<3; $y++) {
$frame[($width - 11)+$y][$x] = chr(0x88 | ($v & 1));
$v = $v >> 1;
}
}
$v = $vinf;
for($y=0; $y<6; $y++) {
for($x=0; $x<3; $x++) {
$frame[$y][$x+($width - 11)] = chr(0x88 | ($v & 1));
$v = $v >> 1;
}
}
}
// and a little bit...
$frame[$width - 8][8] = "\x81";
return $frame;
}
//----------------------------------------------------------------------
/** Dumps debug HTML of frame.
@param Array $frame code frame
@param Boolean $binary_mode in binary mode only contents is dumped, without styling
*/
public static function debug($frame, $binary_mode = false)
{
if ($binary_mode) {
foreach ($frame as &$frameLine) {
$frameLine = join('<span class="m">&nbsp;&nbsp;</span>', explode('0', $frameLine));
$frameLine = join('&#9608;&#9608;', explode('1', $frameLine));
}
echo '<style> .m { background-color: white; } </style> ';
echo '<pre><tt><br/ ><br/ ><br/ >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
echo join("<br/ >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;", $frame);
echo '</tt></pre><br/ ><br/ ><br/ ><br/ ><br/ ><br/ >';
} else {
foreach ($frame as &$frameLine) {
$frameLine = strtr($frameLine, array(
"\xc0" => '<span class="m">&nbsp;</span>', //marker 0
"\xc1" => '<span class="m">&#9618;</span>', //marker 1
"\xa0" => '<span class="p">&nbsp;</span>', //submarker 0
"\xa1" => '<span class="p">&#9618;</span>', //submarker 1
"\x84" => '<span class="s">F</span>', //format 0
"\x85" => '<span class="s">f</span>', //format 1
"\x81" => '<span class="x">S</span>', //special bit
"\x90" => '<span class="c">C</span>', //clock 0
"\x91" => '<span class="c">c</span>', //clock 1
"\x88" => '<span class="f">&nbsp;</span>', //version 0
"\x89" => '<span class="f">&#9618;</span>', //version 1
"\x03" => '1', // 1
"\x02" => '0', // 0
));
}
echo '<style>';
echo ' .p { background-color: yellow; }';
echo ' .m { background-color: #00FF00; }';
echo ' .s { background-color: #FF0000; }';
echo ' .c { background-color: aqua; }';
echo ' .x { background-color: pink; }';
echo ' .f { background-color: gold; }';
echo '</style>';
echo "<tt>";
echo join("<br/ >", $frame);
echo "<br/>Legend:<br/>";
echo '1 - data 1<br/>';
echo '0 - data 0<br/>';
echo '<span class="m">&nbsp;</span> - marker bit 0<br/>';
echo '<span class="m">&#9618;</span> - marker bit 1<br/>';
echo '<span class="p">&nbsp;</span> - secondary marker bit 0<br/>';
echo '<span class="p">&#9618;</span> - secondary marker bit 1<br/>';
echo '<span class="s">F</span> - format bit 0<br/>';
echo '<span class="s">f</span> - format bit 1<br/>';
echo '<span class="x">S</span> - special bit<br/>';
echo '<span class="c">C</span> - clock bit 0<br/>';
echo '<span class="c">c</span> - clock bit 1<br/>';
echo '<span class="f">&nbsp;</span> - version bit 0<br/>';
echo '<span class="f">&#9618;</span> - version bit 1<br/>';
echo "</tt>";
}
}
//----------------------------------------------------------------------
/** Serializes frame.
Create compressed, serialized version of frame.
@param Array $frame Code Frame
@return String binary compresed Code Frame
*/
public static function serial($frame)
{
return gzcompress(join("\n", $frame), 9);
}
//----------------------------------------------------------------------
/** Deserializes frame.
Loads frame from serialized compressed binary
@param String $code binary, GZipped, serialized frame
@return Array Code Frame array
*/
public static function unserial($code)
{
return explode("\n", gzuncompress($code));
}
//----------------------------------------------------------------------
public static function newFrame($version)
{
if($version < 1 || $version > QRSPEC_VERSION_MAX)
return null;
if(!isset(self::$frames[$version])) {
$fileName = QR_CACHE_DIR.'frame_'.$version.'.dat';
if (QR_CACHEABLE) {
if (file_exists($fileName)) {
self::$frames[$version] = self::unserial(file_get_contents($fileName));
} else {
self::$frames[$version] = self::createFrame($version);
file_put_contents($fileName, self::serial(self::$frames[$version]));
}
} else {
self::$frames[$version] = self::createFrame($version);
}
}
if(is_null(self::$frames[$version]))
return null;
return self::$frames[$version];
}
//----------------------------------------------------------------------
/** Sets code frame with speciffied code.
@param Array $frame target frame (modified by reference)
@param Integer $x X-axis position of replacement
@param Integer $y Y-axis position of replacement
@param Byte $repl replacement string
@param Integer $replLen (optional) replacement string length, when __Integer__ > 1 subset of given $repl is used, when __false__ whole $repl is used
*/
public static function set(&$frame, $x, $y, $repl, $replLen = false) {
$frame[$y] = substr_replace($frame[$y], ($replLen !== false)?substr($repl,0,$replLen):$repl, $x, ($replLen !== false)?$replLen:strlen($repl));
}
//----------------------------------------------------------------------
/** @name Reed-Solomon related shorthand getters.
Syntax-sugar to access code speciffication by getter name, not by spec array field.
*/
/** @{*/
public static function rsBlockNum($spec) { return $spec[0] + $spec[3]; }
public static function rsBlockNum1($spec) { return $spec[0]; }
public static function rsDataCodes1($spec) { return $spec[1]; }
public static function rsEccCodes1($spec) { return $spec[2]; }
public static function rsBlockNum2($spec) { return $spec[3]; }
public static function rsDataCodes2($spec) { return $spec[4]; }
public static function rsEccCodes2($spec) { return $spec[2]; }
public static function rsDataLength($spec) { return ($spec[0] * $spec[1]) + ($spec[3] * $spec[4]); }
public static function rsEccLength($spec) { return ($spec[0] + $spec[3]) * $spec[2]; }
/** @}*/
}
/** @}*/
?>

View File

@@ -0,0 +1,318 @@
<?php
/*
* PHP QR Code encoder
*
* Input splitting classes
*
* Based on libqrencode C library distributed under LGPL 2.1
* Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
*
* PHP QR Code is distributed under LGPL 3
* Copyright (C) 2010-2013 Dominik Dzienia <deltalab at poczta dot fm>
*
* The following data / specifications are taken from
* "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004)
* or
* "Automatic identification and data capture techniques --
* QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/** @addtogroup CoreGroup */
/** @{ */
/** Input stream splitter. */
class QRsplit {
public $dataStr = '';
public $input;
public $modeHint;
//----------------------------------------------------------------------
public function __construct($dataStr, $input, $modeHint)
{
$this->dataStr = $dataStr;
$this->input = $input;
$this->modeHint = $modeHint;
}
//----------------------------------------------------------------------
public static function isdigitat($str, $pos)
{
if ($pos >= strlen($str))
return false;
return ((ord($str[$pos]) >= ord('0'))&&(ord($str[$pos]) <= ord('9')));
}
//----------------------------------------------------------------------
public static function isalnumat($str, $pos)
{
if ($pos >= strlen($str))
return false;
return (QRinput::lookAnTable(ord($str[$pos])) >= 0);
}
//----------------------------------------------------------------------
public function identifyMode($pos)
{
if ($pos >= strlen($this->dataStr))
return QR_MODE_NUL;
$c = $this->dataStr[$pos];
if(self::isdigitat($this->dataStr, $pos)) {
return QR_MODE_NUM;
} else if(self::isalnumat($this->dataStr, $pos)) {
return QR_MODE_AN;
} else if($this->modeHint == QR_MODE_KANJI) {
if ($pos+1 < strlen($this->dataStr))
{
$d = $this->dataStr[$pos+1];
$word = (ord($c) << 8) | ord($d);
if(($word >= 0x8140 && $word <= 0x9ffc) || ($word >= 0xe040 && $word <= 0xebbf)) {
return QR_MODE_KANJI;
}
}
}
return QR_MODE_8;
}
//----------------------------------------------------------------------
public function eatNum()
{
$ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion());
$p = 0;
while(self::isdigitat($this->dataStr, $p)) {
$p++;
}
$run = $p;
$mode = $this->identifyMode($p);
if($mode == QR_MODE_8) {
$dif = QRinput::estimateBitsModeNum($run) + 4 + $ln
+ QRinput::estimateBitsMode8(1) // + 4 + l8
- QRinput::estimateBitsMode8($run + 1); // - 4 - l8
if($dif > 0) {
return $this->eat8();
}
}
if($mode == QR_MODE_AN) {
$dif = QRinput::estimateBitsModeNum($run) + 4 + $ln
+ QRinput::estimateBitsModeAn(1) // + 4 + la
- QRinput::estimateBitsModeAn($run + 1);// - 4 - la
if($dif > 0) {
return $this->eatAn();
}
}
$ret = $this->input->append(QR_MODE_NUM, $run, str_split($this->dataStr));
if($ret < 0)
return -1;
return $run;
}
//----------------------------------------------------------------------
public function eatAn()
{
$la = QRspec::lengthIndicator(QR_MODE_AN, $this->input->getVersion());
$ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion());
$p = 0;
while(self::isalnumat($this->dataStr, $p)) {
if(self::isdigitat($this->dataStr, $p)) {
$q = $p;
while(self::isdigitat($this->dataStr, $q)) {
$q++;
}
$dif = QRinput::estimateBitsModeAn($p) // + 4 + la
+ QRinput::estimateBitsModeNum($q - $p) + 4 + $ln
- QRinput::estimateBitsModeAn($q); // - 4 - la
if($dif < 0) {
break;
} else {
$p = $q;
}
} else {
$p++;
}
}
$run = $p;
if(!self::isalnumat($this->dataStr, $p)) {
$dif = QRinput::estimateBitsModeAn($run) + 4 + $la
+ QRinput::estimateBitsMode8(1) // + 4 + l8
- QRinput::estimateBitsMode8($run + 1); // - 4 - l8
if($dif > 0) {
return $this->eat8();
}
}
$ret = $this->input->append(QR_MODE_AN, $run, str_split($this->dataStr));
if($ret < 0)
return -1;
return $run;
}
//----------------------------------------------------------------------
public function eatKanji()
{
$p = 0;
while($this->identifyMode($p) == QR_MODE_KANJI) {
$p += 2;
}
$ret = $this->input->append(QR_MODE_KANJI, $p, str_split($this->dataStr));
if($ret < 0)
return -1;
return $run;
}
//----------------------------------------------------------------------
public function eat8()
{
$la = QRspec::lengthIndicator(QR_MODE_AN, $this->input->getVersion());
$ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion());
$p = 1;
$dataStrLen = strlen($this->dataStr);
while($p < $dataStrLen) {
$mode = $this->identifyMode($p);
if($mode == QR_MODE_KANJI) {
break;
}
if($mode == QR_MODE_NUM) {
$q = $p;
while(self::isdigitat($this->dataStr, $q)) {
$q++;
}
$dif = QRinput::estimateBitsMode8($p) // + 4 + l8
+ QRinput::estimateBitsModeNum($q - $p) + 4 + $ln
- QRinput::estimateBitsMode8($q); // - 4 - l8
if($dif < 0) {
break;
} else {
$p = $q;
}
} else if($mode == QR_MODE_AN) {
$q = $p;
while(self::isalnumat($this->dataStr, $q)) {
$q++;
}
$dif = QRinput::estimateBitsMode8($p) // + 4 + l8
+ QRinput::estimateBitsModeAn($q - $p) + 4 + $la
- QRinput::estimateBitsMode8($q); // - 4 - l8
if($dif < 0) {
break;
} else {
$p = $q;
}
} else {
$p++;
}
}
$run = $p;
$ret = $this->input->append(QR_MODE_8, $run, str_split($this->dataStr));
if($ret < 0)
return -1;
return $run;
}
//----------------------------------------------------------------------
public function splitString()
{
while (strlen($this->dataStr) > 0)
{
if($this->dataStr == '')
return 0;
$mode = $this->identifyMode(0);
switch ($mode) {
case QR_MODE_NUM: $length = $this->eatNum(); break;
case QR_MODE_AN: $length = $this->eatAn(); break;
case QR_MODE_KANJI:
if ($hint == QR_MODE_KANJI)
$length = $this->eatKanji();
else $length = $this->eat8();
break;
default: $length = $this->eat8(); break;
}
if($length == 0) return 0;
if($length < 0) return -1;
$this->dataStr = substr($this->dataStr, $length);
}
}
//----------------------------------------------------------------------
public function toUpper()
{
$stringLen = strlen($this->dataStr);
$p = 0;
while ($p<$stringLen) {
$mode = self::identifyMode(substr($this->dataStr, $p), $this->modeHint);
if($mode == QR_MODE_KANJI) {
$p += 2;
} else {
if (ord($this->dataStr[$p]) >= ord('a') && ord($this->dataStr[$p]) <= ord('z')) {
$this->dataStr[$p] = chr(ord($this->dataStr[$p]) - 32);
}
$p++;
}
}
return $this->dataStr;
}
//----------------------------------------------------------------------
public static function splitStringToQRinput($string, QRinput $input, $modeHint, $casesensitive = true)
{
if(is_null($string) || $string == '\0' || $string == '') {
throw new Exception('empty string!!!');
}
$split = new QRsplit($string, $input, $modeHint);
if(!$casesensitive)
$split->toUpper();
return $split->splitString();
}
}
/** @} */

View File

@@ -0,0 +1,169 @@
<?php
/*
* PHP QR Code encoder
*
* SVG output support
*
* Based on libqrencode C library distributed under LGPL 2.1
* Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
*
* PHP QR Code is distributed under LGPL 3
* Copyright (C) 2010-2013 Dominik Dzienia <deltalab at poczta dot fm>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/** @addtogroup OutputGroup */
/** @{ */
class QRsvgOutput extends QRarea {
public function __construct($source_tab)
{
parent::__construct($source_tab);
}
//----------------------------------------------------------------------
public function mapX($px)
{
return $px;
}
//----------------------------------------------------------------------
public function mapY($py)
{
return $py;
}
//----------------------------------------------------------------------
public function getRawSvg()
{
$lib = array();
$svg = array();
$aggregate_paths = array();
foreach ($this->paths as $path) {
switch ($path[0]) {
case QR_AREA_PATH:
$pNum = 0;
foreach($path[1] as $pathDetails) {
$px = array_shift($pathDetails);
$py = array_shift($pathDetails);
$rle_steps = array_shift($pathDetails);
$aggregate_add = 'M'.$px.','.$py.' ';
while(count($rle_steps) > 0) {
$delta = 1;
$operator = array_shift($rle_steps);
if (($operator != 'R') && ($operator != 'L') && ($operator != 'T') && ($operator != 'B')) {
$delta = (int)$operator;
$operator = array_shift($rle_steps);
}
if ($operator == 'R') $aggregate_add .= 'h'.$delta;
if ($operator == 'L') $aggregate_add .= 'h-'.$delta;
if ($operator == 'T') $aggregate_add .= 'v-'.$delta;
if ($operator == 'B') $aggregate_add .= 'v'.$delta;
}
$aggregate_paths[] = $aggregate_add;
$pNum++;
}
break;
case QR_AREA_POINT:
$symb = array_shift($path);
while(count($path) > 0) {
$px = array_shift($path);
$py = array_shift($path);
$aggregate_paths[] = 'M'.$px.','.$py.' v1h1v-1h-1';
}
break;
case QR_AREA_RECT:
$symb = array_shift($path);
while(count($path) > 0) {
$px = array_shift($path);
$py = array_shift($path);
$ex = array_shift($path);
$ey = array_shift($path);
$w = $ex-$px;
$h = $ey-$py;
$aggregate_paths[] = 'M'.$px.','.$py.' h'.$w.'v'.$h.'h-'.$w.'v-'.$h;
}
break;
case QR_AREA_LSHAPE:
$symb = array_shift($path);
$l_shapes[0] = 'm1,0h1v2h-2v-1h1z';
$l_shapes[1] = 'h1v1h1v1h-2z';
$l_shapes[2] = 'h2v2h-1v-1h-1z';
$l_shapes[3] = 'h2v1h-1v1h-1z';
while(count($path) > 0) {
$px = array_shift($path);
$py = array_shift($path);
$mode = (int)array_shift($path);
$aggregate_paths[] = 'M'.$px.','.$py.' '.$l_shapes[$mode];
}
break;
case QR_AREA_TRACKER:
if (!isset($lib['tracker'])) {
$lib['tracker'] = '<symbol id="tracker"><path d="m 0 7 0 7 7 0 0 -7 -7 0 z m 1 1 5 0 0 5 -5 0 0 -5 z m 1 1 0 3 3 0 0 -3 -3 0 z" style="fill:#000000;stroke:none"></path></symbol>';
}
$symb = array_shift($path);
$px = array_shift($path);
$py = array_shift($path);
$svg[] = '<use x="'.$px.'" y="'.($py-7).'" xlink:href="#tracker"></use>';
break;
}
}
$svg[] = '<path d="'.join(' ', $aggregate_paths).'" style="fill:#000000;stroke:none" ></path>';
return join("\n", $lib)."\n".join("\n", $svg);
}
}
/** @} */

View File

@@ -0,0 +1,190 @@
<?php
/*
* PHP QR Code encoder
*
* Toolset, handy and debug utilites.
*
* PHP QR Code is distributed under LGPL 3
* Copyright (C) 2010-2013 Dominik Dzienia <deltalab at poczta dot fm>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/** @addtogroup CoreGroup */
/** @{ */
/** Helper class */
class QRtools {
public static $timeBenchmarkStarted = false;
//----------------------------------------------------------------------
public static function binarize($frame)
{
$len = count($frame);
foreach ($frame as &$frameLine) {
for($i=0; $i<$len; $i++) {
$frameLine[$i] = (ord($frameLine[$i])&1)?'1':'0';
}
}
return $frame;
}
//----------------------------------------------------------------------
public static function tcpdfBarcodeArray($code, $mode = 'QR,L', $tcPdfVersion = '4.5.037')
{
$barcode_array = array();
if (!is_array($mode))
$mode = explode(',', $mode);
$eccLevel = 'L';
if (count($mode) > 1) {
$eccLevel = $mode[1];
}
$qrTab = QRcode::text($code, false, $eccLevel);
$size = count($qrTab);
$barcode_array['num_rows'] = $size;
$barcode_array['num_cols'] = $size;
$barcode_array['bcode'] = array();
foreach ($qrTab as $line) {
$arrAdd = array();
foreach(str_split($line) as $char)
$arrAdd[] = ($char=='1')?1:0;
$barcode_array['bcode'][] = $arrAdd;
}
return $barcode_array;
}
//----------------------------------------------------------------------
public static function clearCache()
{
self::$frames = array();
}
//----------------------------------------------------------------------
public static function buildCache()
{
QRtools::markTime('before_build_cache');
$mask = new QRmask();
for ($a=1; $a <= QRSPEC_VERSION_MAX; $a++) {
$frame = QRspec::newFrame($a);
if (QR_IMAGE) {
$fileName = QR_CACHE_DIR.'frame_'.$a.'.png';
QRimage::png(self::binarize($frame), $fileName, 1, 0);
}
$width = count($frame);
$bitMask = array_fill(0, $width, array_fill(0, $width, 0));
for ($maskNo=0; $maskNo<8; $maskNo++)
$mask->makeMaskNo($maskNo, $width, $frame, $bitMask, true);
}
QRtools::markTime('after_build_cache');
}
//----------------------------------------------------------------------
public static function log($outfile, $err)
{
if (QR_LOG_DIR !== false) {
if ($err != '') {
if ($outfile !== false) {
file_put_contents(QR_LOG_DIR.basename($outfile).'-errors.txt', date('Y-m-d H:i:s').': '.$err, FILE_APPEND);
} else {
file_put_contents(QR_LOG_DIR.'errors.txt', date('Y-m-d H:i:s').': '.$err, FILE_APPEND);
}
}
}
}
//----------------------------------------------------------------------
public static function dumpMask($frame)
{
$width = count($frame);
for($y=0;$y<$width;$y++) {
for($x=0;$x<$width;$x++) {
echo ord($frame[$y][$x]).',';
}
}
}
//----------------------------------------------------------------------
public static function startTimeBenchmark()
{
$GLOBALS['qr_time_bench'] = array();
self::markTime('start');
}
//----------------------------------------------------------------------
public static function markTime($markerId)
{
list($usec, $sec) = explode(" ", microtime());
$time = ((float)$usec + (float)$sec);
if (!isset($GLOBALS['qr_time_bench']))
$GLOBALS['qr_time_bench'] = array();
$GLOBALS['qr_time_bench'][$markerId] = $time;
if ((!self::$timeBenchmarkStarted)&&($markerId != 'start')) {
self::$timeBenchmarkStarted = true;
$GLOBALS['qr_time_bench']['start'] = $time;
}
}
//----------------------------------------------------------------------
public static function timeBenchmark()
{
self::markTime('finish');
$lastTime = 0;
$startTime = 0;
$p = 0;
echo '<table cellpadding="3" cellspacing="1">
<thead><tr style="border-bottom:1px solid silver"><td colspan="2" style="text-align:center">BENCHMARK</td></tr></thead>
<tbody>';
foreach($GLOBALS['qr_time_bench'] as $markerId=>$thisTime) {
if ($p > 0) {
echo '<tr><th style="text-align:right">till '.$markerId.': </th><td>'.number_format($thisTime-$lastTime, 6).'s</td></tr>';
} else {
$startTime = $thisTime;
}
$p++;
$lastTime = $thisTime;
}
echo '</tbody><tfoot>
<tr style="border-top:2px solid black"><th style="text-align:right">TOTAL: </th><td>'.number_format($lastTime-$startTime, 6).'s</td></tr>
</tfoot>
</table>';
}
}
/** @}*/
//##########################################################################

View File

@@ -0,0 +1,261 @@
/*
* PHP QR Code encoder
*
* QR Code CANVAS support
*
* PHP QR Code is distributed under LGPL 3
* Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
function QRdiffCharDecode(str) {
if (str == '0') {
return 0;
} else {
var updchar = str.toUpperCase();
var multi = 1;
if (str == updchar)
multi = -1;
var delta = updchar.charCodeAt(0)-64;
return delta*multi;
}
}
function QRdecompactOps(str) {
var ops = new Array();
var strTab = str.split(',');
while (strTab.length > 0) {
var code = strTab.shift();
var rcode = code.toUpperCase();
switch (rcode) {
case 'P':
case 'R':
if (code == rcode) {
ops.push('S');
} else {
ops.push('W');
}
ops.push(rcode);
var points = strTab.shift();
var plen = points.length;
for (var i=0;i<plen;i++) {
var ccode = 0;
var fchar = points.charAt(i);
if (fchar == 'z') { ccode += 60; i++; } else
if (fchar == 'Z') { ccode += 120; i++; } else
if (fchar == '+') { ccode += 180; i++; };
var n = points.charCodeAt(i);
if (n >= 97) { ccode += ((n - 97) + 10);} else
if (n >= 65 ) { ccode += ((n - 65) + 35); } else
if (n >= 48) { ccode += (n - 48); }
ops.push(ccode+'');
}
break;
case 'B':
var count = parseInt(strTab.shift());
for (var no = 0; no < count; no++) {
if (code == rcode) {
ops.push('S');
} else {
ops.push('W');
}
ops.push('B');
ops.push('M');
var px = parseInt(strTab.shift());
var py = parseInt(strTab.shift());
ops.push(px+'');
ops.push(py+'');
ops.push('T');
var points = strTab.shift();
points = points.split('1').join('00')
.split('2').join('aa').split('3').join('aA')
.split('4').join('Aa').split('5').join('AA')
.split('6').join('aB').split('7').join('Ab')
.split('8').join('bA').split('9').join('Ba');
var plen = points.length;
for (var i=0;i<plen;i+=2) {
px += QRdiffCharDecode(points.charAt(i));
py += QRdiffCharDecode(points.charAt(i+1));
ops.push(px+'');
ops.push(py+'');
}
ops.push('E');
}
break;
case 'O':
for (i=0;i<3;i++) {
var px = parseInt(strTab.shift());
var py = parseInt(strTab.shift());
ops.push('S,R');
ops.push(px);
ops.push(py);
ops.push('7,7,W,R');
ops.push(px+1);
ops.push(py+1);
ops.push('5,5,S,R');
ops.push(px+2);
ops.push(py+2);
ops.push('3,3');
}
break;
}
}
return ops.join(',');
}
function QRdrawCode(ops, elemId, w, maxx, maxy, xbord, ybord) {
var canvas = document.getElementById(elemId);
if (!xbord)
xbord = 2;
if (!ybord)
ybord = 2;
if (!maxx)
maxx = canvas.clientWidth;
if (!maxy)
maxy = canvas.clientHeight;
var scalex = parseInt(maxx/(w+(xbord*2)));
var scaley = parseInt(maxy/(w+(ybord*2)));
if (scalex < 1)
scalex = 1;
if (scaley < 1)
scaley = 1;
var scalexy = Math.min(scalex, scaley);
var diffx = maxx - ((w+(xbord*2))*scalexy);
var diffy = maxy - ((w+(ybord*2))*scalexy);
var offx = scalexy*xbord + parseInt(diffx/2.0);
var offy = scalexy*ybord + parseInt(diffy/2.0);
var opEx = ops.split(',');
var opExLen = opEx.length;
var opExPos = 0;
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
var func = opEx[opExPos];
var lastFunc = '';
ctx.fillStyle = "white";
ctx.fillRect(offx,offy, w*scalexy, w*scalexy);
while (opExPos < opExLen) {
var fetchOp = true;
switch (func) {
case 'S' : // black fill
ctx.fillStyle = "black";
break;
case 'W' : // white fill
ctx.fillStyle = "white";
break;
case 'B' : // begin of path
ctx.beginPath();
break;
case 'M' : // move pen
opExPos++;
var px = opEx[opExPos];
opExPos++;
var py = opEx[opExPos];
ctx.moveTo(px*scalexy+offx,py*scalexy+offy);
break;
case 'T' : // line to
opExPos++;
var px = opEx[opExPos];
opExPos++;
var py = opEx[opExPos];
ctx.lineTo(px*scalexy+offx,py*scalexy+offy);
break;
case 'E' : // end of path
ctx.fill();
break;
case 'P' : // single point
opExPos++;
var px = opEx[opExPos];
opExPos++;
var py = opEx[opExPos];
ctx.fillRect(px*scalexy+offx,py*scalexy+offy, scalexy, scalexy);
break;
case 'R' : // rectangle
opExPos++;
var px = opEx[opExPos];
opExPos++;
var py = opEx[opExPos];
opExPos++;
var ew = opEx[opExPos];
opExPos++;
var eh = opEx[opExPos];
ctx.fillRect(px*scalexy+offx,py*scalexy+offy, ew*scalexy, eh*scalexy);
break;
default: // we use last function
fetchOp = false;
opExPos--;
func = lastFunc;
break;
}
lastFunc = func;
if (fetchOp) {
opExPos++;
func = opEx[opExPos];
}
}
}
}

View File

@@ -0,0 +1,24 @@
/*
* PHP QR Code encoder
*
* QR Code CANVAS support
*
* PHP QR Code is distributed under LGPL 3
* Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
eval(function(p,a,c,k,e,d){e=function(c){return(c<a?"":e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)d[e(c)]=k[c]||e(c);k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1;};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p;}('12 15(C){f(C==\'0\'){14 0}v{a 13=C.1r();a Y=1;f(C==13)Y=-1;a 1l=13.1i(0)-1w;14 1l*Y}}12 1Q(C){a b=1L 1Y();a r=C.o(\',\');1k(r.N>0){a Q=r.u();a J=Q.1r();1m(J){l\'P\':l\'R\':f(Q==J){b.d(\'S\')}v{b.d(\'W\')}b.d(J);a p=r.u();a V=p.N;U(a i=0;i<V;i++){a t=0;a X=p.16(i);f(X==\'z\'){t+=1S;i++}v f(X==\'Z\'){t+=1V;i++}v f(X==\'+\'){t+=1u;i++};a n=p.1i(i);f(n>=1j){t+=((n-1j)+10)}v f(n>=1h){t+=((n-1h)+1y)}v f(n>=1e){t+=(n-1e)}b.d(t+\'\')}k;l\'B\':a 1d=s(r.u());U(a 11=0;11<1d;11++){f(Q==J){b.d(\'S\')}v{b.d(\'W\')}b.d(\'B\');b.d(\'M\');a g=s(r.u());a h=s(r.u());b.d(g+\'\');b.d(h+\'\');b.d(\'T\');a p=r.u();p=p.o(\'1\').q(\'1z\').o(\'2\').q(\'1C\').o(\'3\').q(\'1F\').o(\'4\').q(\'1D\').o(\'5\').q(\'1E\').o(\'6\').q(\'1s\').o(\'7\').q(\'1x\').o(\'8\').q(\'1v\').o(\'9\').q(\'1t\');a V=p.N;U(a i=0;i<V;i+=2){g+=15(p.16(i));h+=15(p.16(i+1));b.d(g+\'\');b.d(h+\'\')}b.d(\'E\')}k;l\'O\':U(i=0;i<3;i++){a g=s(r.u());a h=s(r.u());b.d(\'S,R\');b.d(g);b.d(h);b.d(\'7,7,W,R\');b.d(g+1);b.d(h+1);b.d(\'5,5,S,R\');b.d(g+2);b.d(h+2);b.d(\'3,3\')}k}}14 b.q(\',\')}12 1K(b,1b,w,F,I,y,A){a G=1I.1J(1b);f(!y)y=2;f(!A)A=2;f(!F)F=G.1G;f(!I)I=G.1R;a K=s(F/(w+(y*2)));a L=s(I/(w+(A*2)));f(K<1)K=1;f(L<1)L=1;a e=1N.1O(K,L);a 1o=F-((w+(y*2))*e);a 1p=I-((w+(A*2))*e);a D=e*y+s(1o/2.0);a x=e*A+s(1p/2.0);a j=b.o(\',\');a 1n=j.N;a c=0;f(G.1q){a m=G.1q(\'1B\');a H=j[c];a 19=\'\';m.18="1c";m.17(D,x,w*e,w*e);1k(c<1n){a 1a=1M;1m(H){l\'S\':m.18="1P";k;l\'W\':m.18="1c";k;l\'B\':m.1X();k;l\'M\':c++;a g=j[c];c++;a h=j[c];m.1W(g*e+D,h*e+x);k;l\'T\':c++;a g=j[c];c++;a h=j[c];m.1U(g*e+D,h*e+x);k;l\'E\':m.1H();k;l\'P\':c++;a g=j[c];c++;a h=j[c];m.17(g*e+D,h*e+x,e,e);k;l\'R\':c++;a g=j[c];c++;a h=j[c];c++;a 1f=j[c];c++;a 1g=j[c];m.17(g*e+D,h*e+x,1f*e,1g*e);k;1A:1a=1T;c--;H=19;k}19=H;f(1a){c++;H=j[c]}}}}',62,123,'||||||||||var|ops|opExPos|push|scalexy|if|px|py||opEx|break|case|ctx||split|points|join|strTab|parseInt|ccode|shift|else||offy|xbord||ybord||str|offx||maxx|canvas|func|maxy|rcode|scalex|scaley||length|||code||||for|plen||fchar|multi|||no|function|updchar|return|QRdiffCharDecode|charAt|fillRect|fillStyle|lastFunc|fetchOp|elemId|white|count|48|ew|eh|65|charCodeAt|97|while|delta|switch|opExLen|diffx|diffy|getContext|toUpperCase|aB|Ba|180|bA|64|Ab|35|00|default|2d|aa|Aa|AA|aA|clientWidth|fill|document|getElementById|QRdrawCode|new|true|Math|min|black|QRdecompactOps|clientHeight|60|false|lineTo|120|moveTo|beginPath|Array'.split('|'),0,{}))

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,24 @@
页面地址:
https://api.tscce.cn/source/pay/pay.php
主要功能:
实现无关业务的支付调用
调用方式:
get/post
所需参数:
sid: sid
scode: scode
app_id: appid
dev_key: 开发者key
market_key: 门店key
fee: 支付金额(分)
title: 支付标题
order_id: 订单号
notice_url: 回调地址(异步)
return_url: 回调地址(同步)
is_qrcode: 是否需要生成二维码y: 是)
sign_key: 签名key客户端用户生成签名的key目前支付时不校验签名只在退款才会校验签名。
用户其他参数
调用示例:
https://api.tscce.cn/source/pay/pay.php?app_id=14936872341446&dev_key=14915485974028&market_key=test&notice_url=https://api.tscce.cn/source/pay/notice.php&return_url=https://api.tscce.cn/source/pay/notice.php&title=aaa&fee=4&p1=p1&is_qrcode=y

View File

@@ -0,0 +1,219 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<link href="css/style.css" rel="stylesheet">
<!-- <link href="css/bootstrap.min.css" rel="stylesheet">-->
<script src="js/jquery-2.1.4.min.js"></script>
<script src="js/common.js"></script>
</head>
<body class="body_bg" id="mainbody">
<header class="yl_logo">
<img src="img/yl.png" class="img-responsive">
</header>
<script type="text/javascript">
function id(x) {
if (typeof x == "string")
return document.getElementById(x);
else
return x;
}
</script>
<?php
/**
* Created by PhpStorm.
* User: bahamut
* Date: 2018/3/20
* Time: 10:40
*/
/*
发红包封装页面
地址:
https://api.tscce.cn/source/pay/redpack.php
参数:
app_id: appid【必须】
dev_key: 开发者key【必须】
market_key: 门店key【必须】
fee: 金额(单位分)【必须】
wishing: 祝福语【必须】
act_name: 活动名称【必须】
remark: 备注【必须】
sign_key: 门店对应的签名key【必须】
return_url: 成功后的跳转页面【可选】,如果不为空,则在接口调用成功后跳转到指定的页面
error_url: 失败后的跳转页面【可选】如果不为空则在接口调用失败后跳转到指定的页面并把错误信息以标准http参数形式传递给页面code错误值msg错误信息
例:
https://api.tscce.cn/source/pay/redpack.php?app_id=14936872341446&dev_key=14915485974028&market_key=0000&fee=100&wishing=test&act_name=test&remark=test&sign_key=0000&return_url=https%3A%2F%2Fwww.baidu.com&error_url=https%3A%2F%2Fwww.baidu.com
*/
require_once __DIR__ . '/common.php';
define('DEFAULT_MARKET_KEY', 'test'); /// 默认的门店
define('DEFAULT_SIGN_KEY', 'test'); /// 默认的签名key
/**
* @note 提取请求参数
* @param array $Parameters 参数列表
* @param string $Name 参数名
* @param string $Default 当没有取到时,使用的默认值
* @return string
*/
function GetRequestParameter($Parameters, $Name, $Default = '') {
if (isset($Parameters[$Name]) && !empty($Parameters[$Name]))
return strval($Parameters[$Name]);
else
return isset($_REQUEST[$Name]) ? $_REQUEST[$Name] : $Default;
}
function is_weixin() {
if ( strpos($_SERVER['HTTP_USER_AGENT'], 'MicroMessenger') !== false ) {
return true;
}
return false;
}
/// 所有参数
$attach = (array)json_decode(rawurldecode(GetRequestParameter(null, 'attach')));
//if (!empty($attach)) var_dump($attach);
/// sid
$sid = GetRequestParameter($attach, 'sid');
/// scode
$scode = GetRequestParameter($attach, 'scode');
/// app_id
$app_id = GetRequestParameter($attach, 'app_id');
/// 开发者key
$dev_key = GetRequestParameter($attach, 'dev_key');
/// 门店key
$market_key = GetRequestParameter($attach, 'market_key', DEFAULT_MARKET_KEY);
/// 订单号
$order_id = GetRequestParameter($attach, 'order_id', md5(date('YmdHis') . rand(1000, 9999)));
/// 支付金额(分)
$fee = GetRequestParameter($attach, 'fee');
/// 红包祝福语
$wishing = GetRequestParameter($attach, 'wishing');
/// 活动名称
$act_name = GetRequestParameter($attach, 'act_name');
/// 备注
$remark = GetRequestParameter($attach, 'remark');
/// 是否静默授权
$silence = intval(GetRequestParameter($attach, 'silence', '0'));
/// 回调地址(同步)
$return_url = GetRequestParameter($attach, 'return_url', isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : GetLocaleUrl());
/// 错误页面地址
$error_url = GetRequestParameter($attach, 'error_url');
/// 签名用的key目前支付不做校验退款才会校验签名。
/// 具体的签名算法见详细代码。
$sign_key = GetRequestParameter($attach, 'sign_key', DEFAULT_SIGN_KEY);
if (empty($app_id)) {
echo '没有指定app_id参数';
} elseif (empty($dev_key)) {
echo '没有指定dev_key参数';
} elseif (empty($market_key)) {
echo '没有指定market_key参数';
} elseif (empty($sid) || empty($scode)) { /// 判断是否有sid和scode, 什么数据都没有则先跳转到登录页面授权
$attach = json_encode(GetAttachParameters(array('attach', )));
$redirect_uri = rawurlencode(GetLocaleUrl());
$url = SITE_API_DOMAIN . "/source/login/login.php?app_id={$app_id}&dev_key={$dev_key}&market_key={$market_key}&silence={$silence}&redirect_uri={$redirect_uri}&attach={$attach}";
header("Location: {$url}");
exit;
} else {
$send_type = is_weixin() ? 1 : 2; /// 支付类型(1: 微信支付; 2: 支付宝支付)
$data = array(
'appid' => $app_id,
'devkey' => $dev_key,
'sid' => $sid,
'scode' => $scode,
'orderid' => $order_id,
'fee' => $fee,
'wishing' => $wishing,
'act_name' => $act_name,
'remark' => $remark,
'send_type' => $send_type,
'version' => 1,
);
$data['sign'] = SignParameter($data, $sign_key); /// 生成签名
$result = new ResultObject(SendPost(SITE_API_DOMAIN . '/api/newpay/sendredpack', $data));
if (0 == $result->error) {
if (!empty($return_url)) {
$attach = GetAttachParameters(array('sid', 'scode', 'app_id', 'dev_key', 'market_key', 'order_id', 'fee', 'wishing', 'act_name', 'remark', 'silence', 'return_url', 'error_url', 'sign_key', 'attach'));
if (!strstr($return_url, "?"))
$return_url .= '?';
else
$return_url .= '&';
foreach ($attach as $k => $v) {
$return_url .= "{$k}={$v}&";
}
$return_url .= "code=0";
header("Location: {$return_url}");
exit;
} else {
$html = "<script>alert('红包发送成功:\\r\\n{$result->msg}');</script>";
}
} else {
if (!empty($error_url)) {
$attach = GetAttachParameters(array('sid', 'scode', 'app_id', 'dev_key', 'market_key', 'order_id', 'fee', 'wishing', 'act_name', 'remark', 'silence', 'return_url', 'error_url', 'sign_key', 'attach'));
if (!strstr($error_url, "?"))
$error_url .= '?';
else
$error_url .= '&';
foreach ($attach as $k => $v) {
$error_url .= "{$k}={$v}&";
}
$error_url .= "code={$result->error_code}&msg={$result->msg}";
header("Location: {$error_url}");
exit;
} else {
$html = "<script>alert('红包发送出错:\\r\\n{$result->msg}({$result->error_code})');</script>";
}
}
/*
$html = <<<EOF
<form style="display:none;" id="frm" name="frm" method="post" action="https://api.tscce.cn/api/newpay/sendredpack/">
<input name="appid" type="text" value="{$data['appid']}" />
<input name="devkey" type="text" value="{$data['devkey']}" />
<input name="sid" type="text" value="{$data['sid']}" />
<input name="scode" type="text" value="{$data['scode']}" />
<input name="orderid" type="text" value="{$data['orderid']}" />
<input name="fee" type="text" value="{$data['fee']}" />
<input name="wishing" type="text" value="{$data['wishing']}" />
<input name="act_name" type="text" value="{$data['act_name']}" />
<input name="remark" type="text" value="{$data['remark']}" />
<input name="send_type" type="text" value="{$data['send_type']}"/>
<input name="version" type="text" value="{$data['version']}"/>
<input name="sign" type="text" value="{$data['sign']}"/>
</form>
<script>
frm.submit();
</script>
EOF;
*/
echo $html;
}
?>
</body>
</html>

View File

@@ -0,0 +1,5 @@
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond $1 !^(index\.php)
RewriteRule ^(.*)$ index.php/$1 [L]

View File

@@ -0,0 +1,27 @@
<?php
use phprs\Bootstrap;
use phprs\util\Logger;
require '../../framework/bootstrap.inc.php';
//ini_set('display_errors', 0);
// ** if using composer, disable the following line **
require_once __DIR__.'/../../lib/phprs/AutoLoad.php';
// ** if using composer, enable the following line **
//require_once __DIR__."/../vendor/autoload.php";
//set log flag
//Logger::$flags = Logger::WARNING|Logger::DEBUG|Logger::ERROR|Logger::INFO;
//set log output
//Logger::$writer = Logger::$to_echo;
//simulate request in CLI
//$_SERVER['REQUEST_URI'] = '/api/apis';
//$_SERVER['REQUEST_METHOD'] = 'GET';
Bootstrap::run(__DIR__.'/../conf.php');
$_W = array();

View File

@@ -0,0 +1,48 @@
<?php
/**
* Created by PhpStorm.
* User: bahamut
* Date: 2018/7/30
* Time: 9:55
*/
require_once __DIR__ . '/pay/phpqrcode/merged/phpqrcode.php';
$url = $_REQUEST['data'];
$local_path = __DIR__ . '/pay';
$short_name = '/qrcodeimg/' . date('YmdHis') . '.png';
$logo_name = $local_path . '/img/qr_logo.png';
$long_name = $local_path . $short_name;
QRcode::png($url, $long_name, QR_ECLEVEL_L, 8, 2);
/// 合并二维码和logo图片
$img = imagecreatefromstring(file_get_contents($long_name));
$logo = imagecreatefromstring(file_get_contents($logo_name));
if ($img && $logo) {
$img_width = imagesx($img); /// 二维码图片宽度
$img_height = imagesy($img); /// 二维码图片高度
$logo_width = imagesx($logo); /// logo图片宽度
$logo_height = imagesy($logo); /// logo图片高度
$logo_qr_width = $img_width / 6;
$scale = $logo_width / $logo_qr_width;
$logo_qr_height = $logo_height / $scale;
$from_width = ($img_width - $logo_qr_width) / 2;
/// 重新组合图片并调整大小
imagecopyresampled($img, $logo, $from_width, $from_width, 0, 0, $logo_qr_width, $logo_qr_height, $logo_width, $logo_height);
/// 输出图片
header('Content-type: image/png');
imagepng($img);
imagedestroy($logo);
imagedestroy($img);
}
///$img_link = dirname(GetLocaleUrl()) . $short_name;
///echo "<center><a href=\"{$img_link}\"><img src=\"{$img_link}\"></a><br /><font size=\"20\">在线支付</font></center>";
unlink($long_name);
exit;