• braintree 支付


    <?php
    /**
    +------------------------------------------------------------------------------
     * 支付宝类
     */
    namespace CommonLibPay;
    use CommonLibAliyunEail;
    use CommonLibPayFactory;
    use CommonLibPayment;
    use CommonModelOrderModel;
    use CommonModelOrderPaymentModel;
    use ThinkException;
    use ThinkLog;
    use ThinkThink;
    
    class BraintreeMacaroonApp implements Payment{
    
        private $_debug         = false;
    
        private $_pay_method    = 'braintree';
        private $_config        = null;
        private $_gateway       = null;
        private $_merchantAccountId     = [
            'usd' => 'macaroonUSD', //美元
            'hkd' => 'macaroonHKD', //港币
            'cny' => 'macaroonCNY', //人民币
            'jpy' => 'macaroonJPY', //日元
            'eur' => 'macaroonEUR', //欧元
            'gbp' => 'macaroonGBP', //英镑
            'krw' => 'macaroonKRW', //韩元
    
        ]; //货币对应的merchantAccountId; 目前仅可以使用usd
        private $_customerPre   = ''; //用户名前缀, 当前仅 环球使用,写死。后期可以做多账号配置,需要改表。
        private $_customerId    = null;
        public  $_err           = '';
    
    
        const LAU               = 1; //商品语言类型必须是1 英文。 uro_retail_product,language_version
        const IV_SIZE           = 16;
    
        public function __construct() {
    
            if( APP_DEBUG )
                $this->_debug   = true;
    
            if( $this->_debug ) {
                $this->_config['environment']       = 'sandbox';
                $this->_config['merchantId']        = '8cwhx5kvnkt9cnq5';
                $this->_config['publicKey']         = 'bh9k88388mxk3g99';
                $this->_config['privateKey']        = '58d9f669ee35d2502ab5447bfb968dc2';
                $this->_merchantAccountId['usd']    = '';
                $this->_merchantAccountId['hkd']    = 'had';
                $this->_merchantAccountId['jpy']    = 'riyuan';
                $this->_customerPre                 = 'macaroon_test123';
            }else {
                $this->_config['environment']       = '';
                $this->_config['merchantId']        = '';
                $this->_config['publicKey']         = '';
                $this->_config['privateKey']        = '';
                $this->_customerPre                 = '';
            }
    
            import("Pay.braintree_macaroon_app.lib.Braintree", VENDOR_PATH, '.php' );
            $this->_gateway         = new Braintree_Gateway( [
                'merchantId'        => $this->_config['merchantId'],
                'publicKey'         => $this->_config['publicKey'],
                'privateKey'        => $this->_config['privateKey'],
                'environment'       => $this->_config['environment'],
                'timeout'           => 2,
            ] );
    
        }
    
        public function getAllowCurrency()
        {
            return array_keys( $this->_merchantAccountId );
        }
    
        /**
         * 初始化订单信息,返回 clientoken,orderinfo 信息
         * author liuxiaodong
         * date 2018/7/27 17:56
         * @param array $params
         * @return array
         */
        public function send( $order, $needClienToken = true )
        {
            $this->_customerId  = $this->getCreateCustom( $order['braintree']['uid'],$order['currency_short_hand'] );
            $this->_warnNotice( 'send -- getClientToken', 'get request', 'debug' );
    
            $res            = ['clientoken' => '', 'transaction' => []];
    
            if( $needClienToken ) {
                try{
                    $param      = [];
                    if( $this->_customerId ) {
                        $param  = [
                            'customerId'        => $this->_customerId
                        ];
                    }
                    $res['clientoken']      = $this->_gateway->clientToken()->generate( $param );
                }catch ( Exception $e ) {
                    $this->_err     = $e->getMessage();
                    $this->_warnNotice( 'send -- getClientToken', '错误信息:格式化exception ==' . json_encode( $order ) . ' , errmsg = ' . $e->getMessage()  );
                    return [];
                }
            }
    
            $res['transaction']     = $this->_encrypt( $order['braintree'] );
            $this->_warnNotice( 'send -- getClientToken', 'send request' . json_encode( $res ), 'debug' );
    
            return $res;
        }
    
    
        /**
        create table uro_braintree_uid(
        id int unsigned not null auto_increment,
        uid int unsigned not null default 0 comment '本站id',
        bid varchar(256) not null default '' comment 'braintree customerid',
        primary key (`id`),
        unique key (`uid`)
        ) engine innodb charset utf8 comment 'braintree 用户对应关系表,creditcard,paypal等信息以后可加字段';
         * 获取、创建braintree 用户,
         * author liuxiaodong
         * date 2018/7/31 15:38
         * @param $uid
         * @return string
         */
        private function getCreateCustom( $uid, $currency = '' )
        {
            $model      = M('braintreeUid');
            $bid        = $model->where( ['uid' => $uid] )->getField( 'bid' );
            if( $bid )
                return $bid;
    
            $bid        = '';
            $_id        = $this->_customerPre . $uid;
            try{
    
                $find   = $this->_gateway->customer()->find( $_id );
                if( $find->merchantId ) {
                    $bid    = $_id;
                    if( !$model->add( ['uid' => $uid, 'bid' => $bid] ) )
                        $this->_warnNotice( 'send -- into db error', '数据入库失败,入库数据为 = '.  json_encode( ['uid' => $uid, 'bid' => $bid] ) . ',err =' . $model->getLastSql() .'|'. $model->getDbError() );
                }else
                    $this->_warnNotice( 'send -- res error', '请求braintree服务器,查找用户信息失败 = ' . json_encode( $find ) );
    
                return $bid;
            }catch ( Exception $e ) {
                try{
                    $res        = $this->_gateway->customer()->create( [
                        'id'    => $_id
                    ] );
                    if( $res->success ) {
                        $bid    = $res->customer->id;
                        if( !$model->add( ['uid' => $uid, 'bid' => $bid] ) )
                            $this->_warnNotice( 'send -- into db error', '数据入库失败,入库数据为 = '.  json_encode( ['uid' => $uid, 'bid' => $bid] ) . ',err =' . $model->getLastSql() .'|'. $model->getDbError() );
                    }else
                        $this->_warnNotice( 'send -- res error', '请求braintree服务器,生成用户信息失败 = ' . json_encode( $res ) );
    
                    return $bid;
                }catch ( Exception $e ) {
                    $this->_warnNotice( 'send -- createCustom', '请求braintree服务器,抛出异常' . json_encode( $e ) );
                    return $bid;
                }
            }
    
    
    
        }
    
        public function receive($params)
        {
    
        }
    
    
        //此接口做支付
        public function notify( $params )
        {
            $this->_warnNotice( 'notify', '参数' . json_encode( $params ), 'debug' );
    
            if( empty( $params['nonce'] )
                || empty( $params['transaction'] )
            ) {
                $this->_warnNotice( 'notify', '请求参数异常 无nonce、transaction, 参数为 == ' . json_encode( $params ) );
                $this->_err         = 'invalid params';
                return false;
            }
    
            $transaction        = $this->_decrypt( $params['transaction'] );
            if( empty( $transaction ) || !is_array( $transaction ) ) {
                $this->_warnNotice( 'notify', '参数异常, 无transaction == ' . json_encode( $params ) );
                $this->_err         = 'invalid params';
                return false;
            }
    
            //读取订单信息
            $currency       = $transaction['currency'];
            if( empty( $transaction['skipCheck'] ) ) {
                $model          = D('Common/Order');
                $order          = $model->find( $transaction['oid'] );
                if( !$order ) {
                    $this->_err         = 'invalid order info';
                    $this->_warnNotice( 'notify', '读取订单信息异常 == ' . json_encode( $transaction ) . ' from ' . $params['client'] . ' order == ' . json_encode( $order ) . ' sql ==' . $model->getLastSql() );
                    return false;
                }
    
                if( $order['amount'] != $transaction['amount'] ) {
                    $this->_err         = 'check amount error';
                    $this->_warnNotice( 'notify', '核对订单金额失败 == ' . json_encode( $transaction ) . ' from ' . $params['client'] . ' order amount = ' .$order['amount'] );
                    return false;
                }
                //2019-3-11获取商品币种
                $currency = M('Country')->where(['id' => $order['coin_id']])->getField('currency_short_hand');
                if(empty($currency))
                    return false;
            }
            $currency = strtolower($currency);
    
            $amount     = $transaction['amount'];
    
            //商品信息
            $lineItems  = [];
            // if( !empty( $transaction['goods'] ) ) {
            //     foreach ( $transaction['goods'] as $v ) {
            //         $lineItems[] = [
            //             'description'   => $transaction['oid'], // Maximum 127 characters
            //             'kind'          => 'debit',
            //             'name'          => mb_substr( $v['product_info']['name'], 0, 30, 'utf8' ) . '...',
            //             'productCode'   => $v['product_id'], //gid
            //             'quantity'      => $v['num'],
            //             'totalAmount'   => $v['product_info']['price'] * $v['product_info']['num'],
            //             'unitAmount'    => $v['product_info']['price'],
            //             'url'           => ''
            //         ];
            //     }
            // }
    
            $this->_customerId      = $this->getCreateCustom( $transaction['uid'] );
            $trans      = [
                'amount'                => $amount, //总金额
                'merchantAccountId'     => $this->_merchantAccountId[$currency], //merchantAccountId
                'paymentMethodNonce'    => $params['nonce'],
                'orderId'               => $transaction['oid'],
                'customerId'            => $this->_customerId,
                'options'               => [
                    'submitForSettlement'     => true, //申请结算
                ]
            ];
            if( !empty( $lineItems ) )
                $trans['lineItems']     = $lineItems;
    
            $this->_warnNotice( 'notify', 'sale 发送请求' . json_encode( $trans ) . 'from ' . $params['client'], 'debug' );
            $res        = $this->_gateway->transaction()->sale( $trans );
            $this->_warnNotice( 'notify', 'sale 结果' . json_encode( $res->success ) . 'from ' . $params['client'], 'debug' );
            if( $res->success ) {
                $trance         = $res->transaction;
    //            $this->write_log( json_encode( $res ), 2, $transaction['trade_number'] );
    
                if( empty( $transaction['skipCheck'] ) ) {
                    $payMentData    = [
                        'result'    => 1,
                        'order_number'  => $transaction['trade_number'],
                        'trade_number'  => $transaction['trade_number'],
                        'serial_number'     => $trance->id
                    ];
                    $completeres            = PayFactory::PayComplete( $payMentData, OrderModel::ORDER_PAY_TYPE_BRAINTREE ,$res);
                    $this->_warnNotice( 'notify', 'PayComplete == ' . json_encode( $payMentData ) . 'from ' . $params['client'] . ' == res ==' . json_encode( $completeres ), 'debug' );
                    if( !$completeres ){
                        $this->_err         = 'server error ';
                        $this->_warnNotice( 'notify', 'PayComplete失败 , 参数 == ' . json_encode( $payMentData ) . ' from ' . $params['client'] );
                    }
    
                    return ['id' => $transaction['trade_number']];
                }else {
                        return ['id' => $trance->id, 'order_id' => $trance->orderId];
                }
            }else {
                $__msg      = $res->message;
                if( $res->transaction->processorResponseCode == 2046 ) {
                    $__msg  = "{$res->message} . The customer's bank is unwilling to accept the transaction. For credit/debit card transactions, the customer will need to contact their bank for more details regarding this generic decline; if this is a PayPal transaction, the customer will need to contact PayPal.";
                }
                $this->_err         = $__msg . '('.$res->transaction->processorResponseCode.')';
                $this->_warnNotice( 'notify', '请求 sale 发送交易抛出异常, 简讯 '.$this->_err.'  详情 == ' . json_encode( $res ), 'error' );
                return false;
            }
    
        }
    
      
    
        public function write_log($content, $status, $trade_number){
            $data = array(
                'order_number' => $trade_number,
                'pay_method' => $this->_pay_method,
                'status' => $status,
                'content' => $content,
                'created_time' => date('Y-m-d H:i:s')
            );
            D('Common/OrderPaymentLog')->add($data);
        }
    
    
        /**
         * 获取客户端token
         * author liuxiaodong
         * date 2018/7/26 15:57
         * @return array
         */
        public function getClientToken()
        {
            try{
                $token      = $this->_gateway->clientToken()->generate();
                return [true, $token];
            }catch ( Exception $e ) {
                $this->_warnNotice( 'getClientToken', '获取clienttoken 失败。。'  . json_encode( $e ), 'error' );
                return [false, $e->getMessage()];
            }
        }
    
        private function _warnNotice( $action, $msg, $level = 'error' )
        {
            if( $level == 'debug' && !$this->_debug )
                return;
    
            $msg        .= PHP_EOL;
    //        Log::write( $action . ' -- ' . $msg, $level, '', C('LOG_PATH') . 'braintreeErr/' . date( 'Y-m-d' ) . '.log'  );
            Log::write( $action . ' -- ' . $msg, $level, '', durableLog( 'braintreeErr' )  );
    
            if( !$this->_debug ) {
                $email      = new AliyunEail();
                $email->sendEmail( 'email?????email', 'braintree pay error',  date( 'Y-m-d H:i:s' ) . '<br />' . $msg );
            }
        }
    
        /**
         * Encrypts the input text using the cipher key
         *
         * @param $input
         * @return string
         */
        private function _encrypt( Array $input)
        {
            $input      = json_encode( $input );
            // Create a random IV. Not using mcrypt to generate one, as to not have a dependency on it.
            $iv = substr(uniqid("", true), 0, self::IV_SIZE);
            // Encrypt the data
            $encrypted = openssl_encrypt($input, "AES-256-CBC", 'macaroon', 0, $iv);
            // Encode the data with IV as prefix
            return base64_encode($iv . $encrypted);
        }
    
        /**
         * Decrypts the input text from the cipher key
         *
         * @param $input
         * @return string
         */
        private function _decrypt($input)
        {
            // Decode the IV + data
            $input  = base64_decode($input);
            // Remove the IV
            $iv = substr($input, 0, self::IV_SIZE);
            // Return Decrypted Data
            $output     =  openssl_decrypt(substr($input, self::IV_SIZE), "AES-256-CBC", 'macaroon', 0, $iv);
            return json_decode( $output, true );
        }
    
        public function getError()
        {
            $msg    = $this->_err ? $this->_err : 'server fail';
            return $msg;
        }
    
        //退款
        public function refund($params)
        {
    
            $transaction_id = $params['trade_no'];
            $amount = abs($params['totalFee'] * 1.00);
            $transaction_info = $this->_gateway->transaction()->find($transaction_id);
            if($transaction_info->status == 'submitted_for_settlement'){
                //如果交易尚未结算 暂不让退款
                return ['code' => 3, 'info' => 'braintree尚未结算,暂不能退款'];
            }
    
            $response       = $this->_gateway->transaction()->refund($transaction_id, $amount);
            $ext_str = json_encode($response);
            if($response->success) {
                printLog("退款成功,订单号:{$params['orderNo']},信息:{$ext_str}",'braintree_refund_suc');
                return ['code' => 1, 'info' => $ext_str];
            }else{
                printLog("退款失败,订单号:{$params['orderNo']},信息:{$ext_str}",'braintree_refund_fail');
                return ['code' => 0, 'info' => $ext_str];
            }
    
    
        }
    
        //检测币种
        public function checkCurrency($currency){
            //获取商家支持的货币账户
            $merchantAccountIterator = $this->_gateway->merchantAccount()->all();
            $support_currencys = [];
            foreach($merchantAccountIterator as $merchantAccount) {
                $support_currencys[] = $merchantAccount->currencyIsoCode;
            }
    
            //如果商品币种商户已创建
            if(in_array($currency,$support_currencys)){
                return true;
            }else{
                return false;
            }
    
        }
    
    
    }
  • 相关阅读:
    透视分析
    仪表分析
    sql查询和预览界面,在预览界面选择图表最后进行导出数据和图表到excel
    可视化查询
    创建数据源
    Smartbi使用Oracle RAC数据库做知识库
    反应器(Reactor)模式
    Netty:EventLoopGroup
    ShuffleTest java 使用集合的方式进行排序
    MapTest java 核心编程
  • 原文地址:https://www.cnblogs.com/lxdd/p/13937760.html
Copyright © 2020-2023  润新知