123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265 |
- <?php
- /**
- * MpaySign.php UTF-8
- * 米大师支付签名
- *
- * @date : 2018/8/16 11:26
- *
- * @license 这不是一个自由软件,未经授权不许任何使用和传播。
- * @author : wuyonghong <wyh@huosdk.com>
- * @version : HuoMp 1.0
- */
- namespace huoMpay;
- use huolib\constant\CacheConst;
- use huolib\status\OrderStatus;
- use think\Cache;
- use think\Controller;
- use think\Log;
- class MpaySign extends Controller {
- private static $url = "https://api.weixin.qq.com";
- private static $method = "POST";
- /**
- * @param string $uri
- * @param array $params
- * @param string $app_secret 小游戏AppSecret
- * @param string $midas_app_key 米大师AppKey
- * @param string $session_key
- *
- * @return int|mixed
- */
- public static function apiPay($uri = '', $params = [], $app_secret, $midas_app_key, $session_key) {
- $_method = strtoupper(self::$method);
- if (empty($params['openid'])
- || empty($params['appid'])
- || empty($params['offer_id'])
- || empty($params['ts'])
- || empty($params['zone_id'])
- || empty($params['pf'])) {
- Log::write(
- "func=".__FUNCTION__."&class=".__CLASS__."&step=1&method=$_method&uri=$uri¶ms=".json_encode($params)
- ."&app_secret=$app_secret"."&secret=$midas_app_key", Log::ERROR
- );
- $_rdata = [
- 'code' => OrderStatus::INVALID_PARAMS,
- 'msg' => OrderStatus::getMsg(OrderStatus::INVALID_PARAMS)
- ];
- return $_rdata;
- }
- $_access_token = self::getAccessToken($params['appid'], $app_secret);
- if (false == $_access_token) {
- $_rdata = [
- 'code' => OrderStatus::ACCESS_TOKEN_GET_ERROR,
- 'msg' => OrderStatus::getMsg(OrderStatus::ACCESS_TOKEN_GET_ERROR)
- ];
- return $_rdata;
- }
- $_params = $params;
- $_params['sig'] = self::makeSign($_method, $uri, $_params, $midas_app_key);
- $_params['access_token'] = $_access_token;
- $_params['mp_sig'] = self::makeMpSign($_method, $uri, $_params, $session_key);
- $_url = self::$url.$uri.'?access_token='.$_access_token;
- unset($_params['access_token']);
- $_query_param_json = json_encode($_params);
- Log::write("==========Request Info==========\n url:$_url,query_string:$_query_param_json", Log::WECHAT);
- $header = ['Content-Type: application/octet-stream; charset=utf-8'];
- $_ret = self::curl($_url, $_query_param_json, 'POST', $header);
- Log::write('The resp is '.$_ret, Log::WECHAT);
- $_ret_arr = json_decode($_ret, true);
- // 远程返回的不是 json 格式, 说明返回包有问题
- if (is_null($_ret_arr)) {
- $_rdata = array(
- 'code' => OPENAPI_ERROR_RESPONSE_DATA_INVALID,
- 'msg' => $_ret
- );
- return $_rdata;
- }
- if ('0' != $_ret_arr['errcode']) {
- $_rdata = [
- 'code' => $_ret_arr['errcode'],
- 'msg' => 'midas error!'.$_ret_arr['errmsg']
- ];
- return $_rdata;
- }
- $_rdata = [
- 'code' => OrderStatus::NO_ERROR,
- 'msg' => $_ret_arr['errmsg'],
- 'data' => $_ret_arr,
- ];
- return $_rdata;
- }
- /**
- * 获取 access_token
- * https://developers.weixin.qq.com/miniprogram/dev/api/token.html
- *
- * @param string $appid 第三方用户唯一凭证
- * @param string $app_secret 第三方用户唯一凭证密钥,即appsecret
- *
- * @return string|bool
- */
- public static function getAccessToken($appid, $app_secret) {
- $_cache_key = CacheConst::CACHE_ACCESS_TOKEN_PREFIX.$appid;
- $_data = Cache::get($_cache_key);
- if (!empty($_data)) {
- $_data = json_decode($_data, true);
- $_now_time = time();
- if (isset($_data['expires_time']) && $_now_time < $_data['expires_time']) {
- return $_data['access_token'];
- }
- }
- $_url = 'https://api.weixin.qq.com/cgi-bin/token';
- $_param['grant_type'] = 'client_credential';
- $_param['appid'] = $appid;
- $_param['secret'] = $app_secret;
- $_rdata = self::curl($_url, http_build_query($_param));
- $_rdata = json_decode($_rdata, true);
- if (!isset($_rdata['access_token'])) {
- Log::write(
- "func=".__FUNCTION__."&class=".__CLASS__."&step=1&appid=$appid&app_secret=$app_secret".
- json_encode($_rdata), Log::ERROR
- );
- return false;
- }
- $_data['access_token'] = $_rdata['access_token'];
- $_data['expires_in'] = $_rdata['expires_in'];
- $_data['expires_time'] = time() + $_rdata['expires_in'];
- $_rs = Cache::set($_cache_key, json_encode($_data));
- if (false == $_rs) {
- return false;
- }
- return $_data['access_token'];
- }
- /**
- * CURL请求
- *
- * @param string $url 请求的URL
- * @param string $params 请求的参数
- * @param string $is_get 是否是get请求
- * @param array $header 头
- *
- * @return int|mixed
- */
- public static function curl($url, $params, $is_get = "GET", $header = []) {
- $_header = $header;
- $ch = curl_init();
- if ("GET" == $is_get) {
- $url = $url.'?'.$params;
- curl_setopt($ch, CURLOPT_HEADER, 0); // 过滤HTTP头
- } else {
- curl_setopt($ch, CURLOPT_POST, 1);
- curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
- }
- curl_setopt($ch, CURLOPT_URL, $url);
- curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3);//设置等待时间
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);//要求结果为字符串且输出到屏幕上
- /* https 请求 */
- if (strlen($url) > 5 && strtolower(substr($url, 0, 5)) == "https") {
- curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
- curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
- }
- if (!empty($_header)) {
- array_push($_header, 'Content-Length: '.strlen($params));
- curl_setopt($ch, CURLOPT_HTTPHEADER, $_header);
- }
- $_rs = curl_exec($ch);
- if (false === $_rs) {
- $_rs = curl_errno($ch);
- }
- curl_close($ch);
- return $_rs;
- }
- /**
- * 获取原始拼接的链接
- *
- * @param array $params
- *
- * @return bool|string
- */
- public static function createRawLinkString($params = []) {
- $_arg = "";
- foreach ($params as $_k => $_v) {
- $_arg .= $_k."=".$_v."&";
- }
- // 去掉最后一个&字符
- $_arg = substr($_arg, 0, strlen($_arg) - 1);
- return $_arg;
- }
- /**
- * 米大师支付签名 sig签名
- *
- * @param string $method HTTP请求方式
- * @param string $uri 请求的URI
- * @param array $params 参数
- * @param string $secret 秘钥
- *
- * @return string
- */
- public static function makeSign($method, $uri = '', $params = array(), $secret = '') {
- /* 1. 参与米大师签名请求参数 */
- $_sign_data = $params;
- /* 2. 对参与米$_sign_data大师签名的参数按照key=value的格式,并按照参数名ASCII字典序升序排序如下: */
- ksort($_sign_data);
- $_sign_data_str = self::createRawLinkString($_sign_data);
- /* 3. 拼接uri、method和米大师密钥: */
- $_sign_str = $_sign_data_str."&org_loc=".$uri."&method=".strtoupper($method)."&secret=".$secret;
- /* 4. 把米大师密钥作为key,使用HMAC-SHA256得到签名。 */
- $_sig = hash_hmac('sha256', $_sign_str, $secret);
- return $_sig;
- }
- /**
- * 米大师支付开平签名 mp_sig签名
- *
- * @param string $method HTTP请求方式
- * @param string $uri 请求的URI
- * @param array $params 参数
- * @param string $session_key 秘钥
- *
- * @return string
- */
- public static function makeMpSign($method, $uri = '', $params = [], $session_key = '') {
- /* 1. 参与开平签名请求参数 */
- if (empty($params['openid'])
- || empty($params['appid'])
- || empty($params['offer_id'])
- || empty($params['ts'])
- || empty($params['zone_id'])
- || empty($params['sig'])
- || empty($params['access_token'])
- || empty($params['pf'])) {
- Log::write(
- "func=".__FUNCTION__."&class=".__CLASS__."&step=1&method=$method&uri=$uri¶ms=".json_encode($params)
- ."&session_key=$session_key", Log::ERROR
- );
- return false;
- }
- $_sign_data = $params;
- /* 2. 对参与开平签名的参数按照key=value的格式,并按照参数名ASCII字典序升序排序如下: */
- ksort($_sign_data);
- $_sign_data_str = self::createRawLinkString($_sign_data);
- /* 3. 拼接uri、method和米大师密钥: */
- $_sign_str = $_sign_data_str."&org_loc=".$uri."&method=".strtoupper($method)."&session_key=".$session_key;
- /* 4. 把米大师密钥作为key,使用HMAC-SHA256得到签名。 */
- $_mp_sig = hash_hmac('sha256', $_sign_str, $session_key);
- return $_mp_sig;
- }
- }
|