<?php
use com\unionpay\acp\sdk\createLinkString;
header ( 'Content-type:text/html;charset=utf-8' );
include_once $_SERVER ['DOCUMENT_ROOT'] . '/upacp_demo_qrc/sdk/acp_service.php';

/**
 * 产品：二维码支付<br>
 * 交易：行业码获取用户授权+获取用户标识+统一下单<br>
 * 日期： 2019-05<br>
 * 版权： 中国银联<br>
 */
const ENCODING = "UTF-8";
const ACTION_FILL_ORDER = "fillOrder";
const ACTION_PUSH_ORDER = "pushOrder";
const ACTION_GET_AUTH = "getUserAuth";
const GET_USR_AUTH_URL = "https://qr.95516.com/qrcGtwWeb-web/api/userAuth?version=1.0.0&redirectUrl=";

// 获取本页面地址，ref：https://stackoverflow.com/questions/6768793/get-the-full-url-in-php
$actualLink = (isset ( $_SERVER ['HTTPS'] ) && $_SERVER ['HTTPS'] === 'on' ? "https" : "http") . "://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
$urlPrefix = $actualLink . "?action=";

$ua = $_SERVER ['HTTP_USER_AGENT'];

if ($ua == null || ! preg_match ( "/.*(UnionPay\\/[^ ]+ ([0-9a-zA-Z]+)).*/", $ua, $matches )) {
	// TODO
	echo "非银联云闪付的user-agent。<br>ua为：<br>" . $ua;
	return;
}

$appUpIdentifier = $matches [1];

// echo $appUpIdentifier;

$params = getAllRequestParam ();
if (! array_key_exists ( "action", $params )) {
	// 0. 填写订单信息。
	include_once $_SERVER ['DOCUMENT_ROOT'] . '/upacp_demo_qrc/pages/api_16_qrc/hym/fillOrderMer.php';
	return;
}
$action = $params ["action"];
unset ( $params ["action"] );

if (ACTION_FILL_ORDER === $action) {
	// 1. 调获取用户授权。
	$redirectUrl = $urlPrefix . ACTION_GET_AUTH . "&" . com\unionpay\acp\sdk\createLinkString ( $params, false, true );
	echo $redirectUrl . "<br>";
	header ( "Location: " . GET_USR_AUTH_URL . urlencode ( $redirectUrl ) );
	return;
} else if (ACTION_GET_AUTH === $action) {
	// 2. 获取用户授权返回处理，没问题（00、34）的话，调获取用户标识接口，成功的话显示订单信息
	$userAuthCode = array_key_exists ( "userAuthCode", $params ) ? $params ["userAuthCode"] : null;
	$respCode = array_key_exists ( "respCode", $params ) ? $params ["respCode"] : null;
	$merId = array_key_exists ( "merId", $params ) ? $params ["merId"] : null;
	if ($respCode === null || $respCode !== "00") {
		$errInfo = "获取用户信息失败。respCode=" . $respCode; // ;
		include_once $_SERVER ['DOCUMENT_ROOT'] . '/upacp_demo_qrc/pages/api_16_qrc/hym/err.php';
		return;
	}
	if ($userAuthCode === null) {
		$errInfo = "获取用户信息失败。userAuthCode为空。";
		include_once $_SERVER ['DOCUMENT_ROOT'] . '/upacp_demo_qrc/pages/api_16_qrc/hym/err.php';
		return;
	}
	// 3. 调获取用户标识接口
	$appUserId = getAppUsrId ( $merId, $userAuthCode, $appUpIdentifier, $errInfo );
	if ($appUserId === null) {
		$errInfo = "调用获取用户标识接口接口失败，失败信息：" . $errInfo;
		include_once $_SERVER ['DOCUMENT_ROOT'] . '/upacp_demo_qrc/pages/api_16_qrc/hym/err.php';
		return;
	}
	$showUserId = $appUserId;
	$params ["appUserId"] = $appUserId;
	
	$params ["action"] = ACTION_PUSH_ORDER;
	$paramString = com\unionpay\acp\sdk\createLinkString ( $params, false, true );
	$txnAmt = $params ["txnAmt"];
	$orderId = $params ["orderId"];
	include_once $_SERVER ['DOCUMENT_ROOT'] . '/upacp_demo_qrc/pages/api_16_qrc/hym/showOrderMer.php';
	return;
} else if (ACTION_PUSH_ORDER === $action) {
	// 4. 触发订单推送接口，返回redirectUrl跳转我们前台网关。
	$redirectUrl = orderPush ( $params,  $errInfo );
	if ($redirectUrl === null) {
		$errInfo = "调用订单推送接口失败，失败信息：" . $errInfo;
		include_once $_SERVER ['DOCUMENT_ROOT'] . '/upacp_demo_qrc/pages/api_16_qrc/hym/err.php';
		return;
	}
	header ( "Location: " . $redirectUrl );
	return;
}
$errInfo = "错误访问参数？";
include_once $_SERVER ['DOCUMENT_ROOT'] . '/upacp_demo_qrc/pages/api_16_qrc/hym/err.php';



function getAllRequestParam() {
	return array_merge ( $_GET, $_POST );
}

function getAppUsrId($merId, $userAuthCode, $appUpIdentifier, &$errMsgBuffer) {
	$params = array (
			
			// 以下信息非特殊情况不需要改动
			'version' => com\unionpay\acp\sdk\SDKConfig::getSDKConfig ()->version, // 版本号
			'encoding' => 'utf-8', // 编码方式
			'txnType' => '00', // 交易类型
			'txnSubType' => '10', // 交易子类
			'bizType' => '000000', // 业务类型
			'signMethod' => com\unionpay\acp\sdk\SDKConfig::getSDKConfig ()->signMethod, // 签名方法
			'channelType' => '08', // 渠道类型，07-PC，08-手机
			'accessType' => '0', // 接入类型
			                     
			// TODO 以下信息需要填写
			'merId' => $merId, // 商户代码，请改自己的测试商户号，此处默认取demo演示页面传递的参数
			'orderId' => date ( 'YmdHis' ), // 商户订单号，8-32位数字字母，不能含“-”或“_”，此处默认取demo演示页面传递的参数，可以自行定制规则
			'txnTime' => date ( 'YmdHis' ), // 订单发送时间，格式为YYYYMMDDhhmmss，取北京时间，此处默认取demo演示页面传递的参数
			'userAuthCode' => $userAuthCode,
			'appUpIdentifier' => $appUpIdentifier 
	);
	
	com\unionpay\acp\sdk\AcpService::sign ( $params ); // 签名
	$url = com\unionpay\acp\sdk\SDKConfig::getSDKConfig ()->backTransUrl;
	
	$result_arr = com\unionpay\acp\sdk\AcpService::post ( $params, $url );
	if (count ( $result_arr ) <= 0) { // 没收到200应答的情况
		$errMsgBuffer = "未获取到返回报文或返回http状态码非200。";
		return null;
	}
	
	if (! com\unionpay\acp\sdk\AcpService::validate ( $result_arr )) {
		$errMsgBuffer = "应答报文验签失败。";
		return null;
	}
	
	if ($result_arr ["respCode"] != "00") {
		$errMsgBuffer = "respCode=" . $result_arr ["respCode"] . ", respMsg=" . $result_arr ["respMsg"];
		return null;
	}
	return $result_arr ["appUserId"];
}

function orderPush($prev, &$errMsgBuffer) {
	$params = array (
			
			// 以下信息非特殊情况不需要改动
			'version' => com\unionpay\acp\sdk\SDKConfig::getSDKConfig ()->version, // 版本号
			'encoding' => 'utf-8', // 编码方式
			'txnType' => '01', // 交易类型
			'txnSubType' => '01', // 交易子类
			'bizType' => '000000', // 业务类型
			'backUrl' => com\unionpay\acp\sdk\SDKConfig::getSDKConfig ()->backUrl, // 后台通知地址
			'signMethod' => com\unionpay\acp\sdk\SDKConfig::getSDKConfig ()->signMethod, // 签名方法
			'channelType' => '08', // 渠道类型，07-PC，08-手机
			'accessType' => '0', // 接入类型
			'currencyCode' => '156', // 交易币种，境内商户固定156
			'tradeType' => 'mobileWeb', // 交易场景 固定填写 mobileWeb
			                            
			// TODO 以下信息需要填写
			'merId' => $prev ["merId"], // 商户代码，请改自己的测试商户号，此处默认取demo演示页面传递的参数
			'orderId' => $prev ["orderId"], // 商户订单号，8-32位数字字母，不能含“-”或“_”，此处默认取demo演示页面传递的参数，可以自行定制规则
			'txnTime' => $prev ["txnTime"], // 订单发送时间，格式为YYYYMMDDhhmmss，取北京时间，此处默认取demo演示页面传递的参数
			'txnAmt' => $prev ["txnAmt"], // 交易金额，单位分，此处默认取demo演示页面传递的参数
			'appUserId' => $prev ["appUserId"] // app用户标识
	) 
	                                   
	// 请求方保留域，
	// 透传字段，查询、通知、对账文件中均会原样出现，如有需要请启用并修改自己希望透传的数据。
	// 出现部分特殊字符时可能影响解析，请按下面建议的方式填写：
	// 1. 如果能确定内容不会出现&={}[]"'等符号时，可以直接填写数据，建议的方法如下。
	// 'reqReserved' =>'透传信息1|透传信息2|透传信息3',
	// 2. 内容可能出现&={}[]"'符号时：
	// 1) 如果需要对账文件里能显示，可将字符替换成全角＆＝｛｝【】“‘字符（自己写代码，此处不演示）；
	// 2) 如果对账文件没有显示要求，可做一下base64（如下）。
	// 注意控制数据长度，实际传输的数据长度不能超过1024位。
	// 查询、通知等接口解析时使用base64_decode解base64后再对数据做后续解析。
	// 'reqReserved' => base64_encode('任意格式的信息都可以'),
	                                   
	// TODO 其他特殊用法请查看 pages/api_16_qrc/special_use_purchase.php
	;
	if ("true" === $prev ["withFrontUrl"])
		$params ['frontUrl'] = com\unionpay\acp\sdk\SDKConfig::getSDKConfig ()->frontUrl; // 前台通知地址
	
	com\unionpay\acp\sdk\AcpService::sign ( $params ); // 签名
	$url = com\unionpay\acp\sdk\SDKConfig::getSDKConfig ()->orderTransUrl;
	
	$result_arr = com\unionpay\acp\sdk\AcpService::post ( $params, $url );
	if (count ( $result_arr ) <= 0) { // 没收到200应答的情况
		$errMsgBuffer = "未获取到返回报文或返回http状态码非200。";
		return null;
	}
	
	if (! com\unionpay\acp\sdk\AcpService::validate ( $result_arr )) {
		$errMsgBuffer = "应答报文验签失败。";
		return null;
	}
	
	if ($result_arr ["respCode"] != "00") {
		$errMsgBuffer = "respCode=" . $result_arr ["respCode"] . ", respMsg=" . $result_arr ["respMsg"];
		return null;
	}
	return urldecode ( $result_arr ["payUrl"] );
}