123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247 |
- <?php
- /**
- * Created by PhpStorm.
- * User: lts
- * Date: 2019-04-16
- * Time: 14:14
- */
- namespace app\main\service;
- use app\main\constants\ApiConstants;
- use GuzzleHttp\Client as Http;
- use GuzzleHttp\Exception\GuzzleException;
- use think\Exception;
- class UnsPayService
- {
- protected static $self = null;
- private $_key;
- function __construct($key)
- {
- $this->_key = $key;
- }
- public static function instance($key)
- {
- if (self::$self == null) {
- self::$self = new self($key);
- }
- return self::$self;
- }
- /**
- * 请求参数校验的key的顺序
- */
- const MAC_KEY_REQUEST_SORT = [
- 'accountId',
- 'orderId',
- 'commodity',
- 'amount',
- 'responseUrl',
- 'subject',
- 'returnPage',
- 'openId',
- 'version',
- 'limitPay',
- ];
- /**
- * 响应返回值校验的key的顺序
- */
- const MAC_KEY_RESPONSE_SORT = [
- 'result_code',
- 'result_msg',
- 'appId',
- 'timeStamp',
- 'nonceStr',
- 'mPackage',
- 'signType',
- 'paySign',
- 'orderId',
- 'transId',
- ];
- /**
- * 支付回调参数校验的key的顺序
- */
- const MAC_KEY_CALLBACK_SORT = [
- 'accountId',
- 'orderId',
- 'amount',
- 'result_code',
- 'result_msg',
- 'channel_refund_trade_no',
- ];
- /**
- * 构造银生宝下单mac参数
- * @param $params
- * @return string
- */
- public function makeMacParams(array $params)
- {
- $aResult = [];
- foreach (self::MAC_KEY_REQUEST_SORT as $key) {
- if (!empty($params[$key])) {
- $aResult[] = sprintf("%s=%s", $key, $params[$key]);
- }
- }
- $aResult[] = 'key=' . $this->_key;
- $strMac = implode('&', $aResult);
- LogService::info('strMac' . $strMac);
- $md5StrMac = md5($strMac);
- $md5StrMac = strtoupper($md5StrMac);
- return $md5StrMac;
- }
- /**
- * 构造银生宝回调mac参数
- * @param array $params
- * @return string
- */
- public function verifyCallbackMacParams(array $params)
- {
- if (empty($params['mac'])) {
- LogService::error('mac参数不存在,银生宝下单返回值校验失败!');
- return false;
- }
- $aResult = [];
- foreach (self::MAC_KEY_CALLBACK_SORT as $key) {
- if (!empty($params[$key])) {
- $aResult[] = sprintf("%s=%s", $key, $params[$key]);
- } else {
- $aResult[] = $key . '=';
- }
- }
- $aResult[] = 'key=' . $this->_key;
- $strMac = implode('&', $aResult);
- $md5StrMac = md5($strMac);
- $md5StrMac = strtoupper($md5StrMac);
- if ($md5StrMac != $params['mac']) {
- LogService::error('mac值有误,银生宝回调返回值校验失败!');
- return false;
- } else {
- return true;
- }
- }
- /**
- * 校验银生宝接口返回值mac
- * @param array $data
- * @return bool
- */
- private function verifyResponse(array $data)
- {
- if (empty($data['mac'])) {
- LogService::error('mac参数不存在,银生宝下单返回值校验失败!');
- return false;
- }
- $aResult = [];
- foreach (self::MAC_KEY_RESPONSE_SORT as $key) {
- if (!empty($data[$key])) {
- $aResult[] = sprintf("%s=%s", $key, $data[$key]);
- } else {
- $aResult[] = $key . '=';
- }
- }
- $aResult[] = 'key=' . $this->_key;
- $strMac = implode('&', $aResult);
- $md5StrMac = md5($strMac);
- $md5StrMac = strtoupper($md5StrMac);
- if ($data['mac'] != $md5StrMac) {
- LogService::error('mac值有误,银生宝下单返回值校验失败!');
- return false;
- } else {
- return true;
- }
- }
- public static function makeJsJsonParam($params)
- {
- $result = json_encode([
- 'appId' => $params['appId'],
- 'timeStamp' => $params['timeStamp'],
- 'nonceStr' => $params['nonceStr'],
- 'package' => $params['mPackage'],
- 'signType' => $params['signType'],
- 'paySign' => $params['paySign'],
- ]);
- return $result;
- }
- /**
- * 银生宝调用API接口
- * @param $data 发送到API的数据
- * @param $payInfo 支付信息
- * @param $goodsInfo 商品信息
- * @param $orderInfo 订单信息
- * @param int $loopIndex 循环调用API的次数
- * @return mixed|\Psr\Http\Message\ResponseInterface
- * @throws Exception
- */
- public function payUnsApi($data, $payInfo, $goodsInfo, $orderInfo, $loopIndex = 1)
- {
- $payUrl = ApiConstants::UNS_PAY_URL;
- $unsApiStartTime = microtime(true);
- try {
- $client = new Http([
- 'connect_timeout' => 10,
- 'timeout' => 30,
- 'http_errors' => true, //抛出异常 true是 false否
- 'verify' => false, //不验证ssl证书
- ]);
- $result = $client->post($payUrl, ['form_params' => $data]);
- $unsApiEndTime = microtime(true);
- $apiRunTime = round($unsApiEndTime - $unsApiStartTime, 3);
- if ($result->getStatusCode() != '200') {
- LogService::error(sprintf('unspay_create_order_fail!wxpay_id:%s,wxpay_name:%s,mch_id:%s,channel_id:%s,user_id:%s,money:%s,good_id:%s,out_trade_no:%s,api_run_time:%s s,errmessage:%s',
- $payInfo['id'], $payInfo['name'], $payInfo['quartet_merchant_id'], $orderInfo['admin_id'],
- $orderInfo['user_id'], $goodsInfo['money'], $orderInfo['goods_id'], $orderInfo['out_trade_no'],
- $apiRunTime, json_encode(var_export($result, true), JSON_UNESCAPED_UNICODE)));
- LogService::error('银生宝平台订单创建失败!订单内容: ' . json_encode(var_export($data, true),
- JSON_UNESCAPED_UNICODE) . " 银生宝平台返回内容: " . json_encode(var_export($result, true),
- JSON_UNESCAPED_UNICODE));
- throw new Exception('订单创建失败,请重新下单!');
- } else {
- $result = json_decode($result->getBody()->getContents(), true);
- $verifyResponseResult = $this->verifyResponse($result);
- if ($result['result_code'] != '0000' || !$verifyResponseResult) {
- LogService::error(sprintf('unspay_create_order_fail!wxpay_id:%s,wxpay_name:%s,mch_id:%s,channel_id:%s,user_id:%s,money:%s,good_id:%s,out_trade_no:%s,api_run_time:%s s,errmessage:%s',
- $payInfo['id'], $payInfo['name'], $payInfo['quartet_merchant_id'], $orderInfo['admin_id'],
- $orderInfo['user_id'], $goodsInfo['money'], $orderInfo['goods_id'], $orderInfo['out_trade_no'],
- $apiRunTime, $result['result_msg']));
- LogService::error('银生宝平台订单创建失败!订单内容:' . json_encode(var_export($data,
- true)) . " 银生宝平台返回错误码: " . $result['result_code']);
- throw new Exception('订单创建失败,请重新下单!');
- }
- }
- LogService::info(sprintf('unspay_create_order_success!wxpay_id:%s,wxpay_name:%s,mch_id:%s,channel_id:%s,user_id:%s,money:%s,good_id:%s,out_trade_no:%s,api_run_time:%s s',
- $payInfo['id'], $payInfo['name'], $payInfo['quartet_merchant_id'], $orderInfo['admin_id'],
- $orderInfo['user_id'], $goodsInfo['money'], $orderInfo['goods_id'], $orderInfo['out_trade_no'],
- $apiRunTime));
- return $result;
- } catch (GuzzleException $exception) {
- $unsApiEndTime = microtime(true);
- $apiRunTime = round($unsApiEndTime - $unsApiStartTime, 3);
- LogService::error(sprintf('unspay_create_order_fail!wxpay_id:%s,wxpay_name:%s,mch_id:%s,channel_id:%s,user_id:%s,money:%s,good_id:%s,out_trade_no:%s,api_run_time:%s s,errmessage:%s',
- $payInfo['id'], $payInfo['name'], $payInfo['quartet_merchant_id'], $orderInfo['admin_id'],
- $orderInfo['user_id'], $goodsInfo['money'], $orderInfo['goods_id'], $orderInfo['out_trade_no'],
- $apiRunTime, $exception->getMessage()));
- LogService::error('银生宝平台订单创建失败!订单内容: ' . json_encode(var_export($data, true), JSON_UNESCAPED_UNICODE));
- LogService::error($exception->getMessage());
- LogService::error($exception->getTraceAsString());
- if ($loopIndex <= ApiConstants::LOOP_EXEC_API_COUNT) {
- $loopIndex++;
- return $this->payUnsApi($data, $payInfo, $goodsInfo, $orderInfo, $loopIndex);
- }
- throw new Exception('订单创建失败,请重新下单!');
- }
- }
- }
|