load->helper('payment'); $this->config->load('lianlian', true); $this->load->model('Online_payment_note_model', 'note_model'); $this->load->model('Online_payment_account_model', 'account_model'); $this->merchant_config = $this->config->item('test', 'lianlian'); } public function index() {} public function query_status() {} public function query_payment() {} public function query_refund() {} public function notify($site = 'cht') { // $this->merchant_config = $this->config->item($site, 'lianlian'); // test: 测试环境 error_reporting(0); log_message('error', 'LianlianPay notify begin ----'); $response['code'] = 0; $response['message'] = ''; $raw_post_data = file_get_contents('php://input'); if (empty($raw_post_data)) { # 如果没有数据,直接返回失败 return $this->output->set_content_type('application/json')->set_output(json_encode($response)); } log_message('error','test: ' . __METHOD__ . ': ' . __LINE__ . ' ' . PHP_EOL . var_export($raw_post_data, 1)); $signature = $this->input->server('HTTP_SIGNATURE'); $payment_result = json_decode($raw_post_data, true); if ($this->check_sign($payment_result, $signature) !== true) { $response['message'] = 'sign error'; // return $this->output->set_content_type('application/json')->set_output(json_encode($response)); } $payment_data = $payment_result['payment_data']; $payment_result['GAI_API'] = array( 'merchant' => $site, 'invoice' => $payment_result['merchant_transaction_id'], 'transaction_id' => $payment_result['ll_transaction_id'], ); // todo: 计算手续费, 实收 $payment_fee = $payment_data['payment_amount'] - $payment_data['settlement_amount']; $ssje = $this->account_model->get_ssje($payment_data['settlement_amount'], str_replace("CNY", "RMB", strtoupper($payment_data['settlement_currency_code'])), $this->merchant_config['method_code']); $save_column = array(); $save_column['OPN_transactionId'] = $payment_result['ll_transaction_id']; $save_column['OPN_orderId'] = $payment_result['merchant_transaction_id']; $save_column['OPN_rawOrderId'] = $payment_result['merchant_transaction_id']; $save_column['OPN_invoiceId'] = $payment_result['merchant_transaction_id']; $save_column['OPN_subject'] = $payment_result['merchant_transaction_id']; $save_column['OPN_currency'] = $payment_data['payment_currency_code']; $save_column['OPN_orderAmount'] = $payment_data['payment_amount']; $save_column['OPN_payAmount'] = $payment_data['payment_amount']; // $save_column['OPN_payFee'] = $payment_fee; // todo: 计算手续费; 退款 1USD 原手续费不退 $save_column['OPN_netAmount'] = $payment_data['settlement_amount']; $save_column['OPN_transactionResult'] = $payment_data['payment_status'] === 'PS' ? 'completed' : 'declined'; $save_column['OPN_resultCode'] = $payment_data['payment_status']; // $save_column['OPN_resultMsg'] = isset($payment_result['return_msg']) ? $payment_result['return_msg'] : $payment_result['result_code']; // $save_column['OPN_errCode'] = isset($payment_result['err_code']) ? $payment_result['err_code'] : NULL; // $save_column['OPN_errMsg'] = isset($payment_result['err_code_des']) ? $payment_result['err_code_des'] : NULL; $save_column['OPN_acquiringTime'] = date('Y-m-d H:i:s', strtotime($payment_data['payment_time'])); $save_column['OPN_completeTime'] = date('Y-m-d H:i:s', strtotime($payment_data['payment_time'])); // $save_column['OPN_remark'] = $payment_result['attach'] ? $payment_result['attach'] : $payment_result['out_trade_no']; // $save_column['OPN_payerLogId'] = $payment_result['openid']; // $save_column['OPN_payerStatus'] = $payment_result['is_subscribe']==='Y' ? "subscribed" : NULL; $save_column['OPN_fundSource'] = $site; $save_column['OPN_entryAmountCNY'] = floatval($ssje); $save_column['OPN_rawContent'] = json_encode($payment_result); $save_column['OPN_noticeTime'] = date('Y-m-d H:i:s'); // $save_column['OPN_noticeType'] = intval($payment_result['total_fee'])>0 ? 'pay' : 'refund'; $save_column['OPN_noticeType'] = 'pay'; $save_column['OPN_noticeSendStatus'] = $payment_data['payment_status'] === 'PS' ? 'unsend' : 'closed'; $save_column['OPN_noticeSendTime'] = NULL; $save_column['OPN_accountMethod'] = $this->merchant_config['method_code']; if ($this->note_model->insert_note($save_column)) { $response['code'] = 200; $response['message'] = 'success'; } $this->output->set_content_type('application/json')->set_output(json_encode($response)); } public function notify_refund($site = 'cht') { // $this->merchant_config = $this->config->item($site, 'lianlian'); // test: 测试环境 error_reporting(0); log_message('error', 'LianlianPay notify refund begin ----'); $response['code'] = 0; $response['message'] = ''; $raw_post_data = file_get_contents('php://input'); if (empty($raw_post_data)) { # 如果没有数据,直接返回失败 return $this->output->set_content_type('application/json')->set_output(json_encode($response)); } $signature = $this->input->server('HTTP_SIGNATURE'); $payment_result = json_decode($raw_post_data, true); if ($this->check_sign($payment_result, $signature) !== true) { log_message('error','debug: ' . __METHOD__ . ': ' . __LINE__ . ' signature' . PHP_EOL . var_export($signature, 1)); log_message('error','debug: ' . __METHOD__ . ': ' . __LINE__ . ' raw_post_data' . PHP_EOL . var_export($raw_post_data, 1)); $response['message'] = 'sign error'; // return $this->output->set_content_type('application/json')->set_output(json_encode($response)); // debug: } $payment_data = $payment_result['refund_data']; $find_related = $this->note_model->get_note_where(['OPN_invoiceId' => ['=', $payment_result['original_transaction_id']], 'OPN_transactionResult' => ['=', 'completed']]); // ! 退款手续费 1USD, 原交易手续费不退 // $payment_fee = $payment_data['payment_amount'] - $payment_data['settlement_amount']; // $ssje = $this->account_model->get_ssje('-' . $payment_data['actual_refund_amount'], str_replace("CNY", "RMB", strtoupper($payment_data['actual_refund_currency_code'])), $this->merchant_config['method_code']); $ssje = $this->account_model->get_ssje('-' . $payment_data['settlement_amount'], str_replace("CNY", "RMB", strtoupper($payment_data['settlement_currency_code'])), $this->merchant_config['method_code']); $save_column = array(); $save_column['OPN_transactionId'] = $payment_result['ll_transaction_id']; $save_column['OPN_orderId'] = $payment_result['original_transaction_id']; $save_column['OPN_rawOrderId'] = $payment_result['merchant_transaction_id']; $save_column['OPN_invoiceId'] = $payment_result['merchant_transaction_id']; $save_column['OPN_relatedId'] = isset($find_related[0]->OPN_transactionId) ? $find_related[0]->OPN_transactionId : null; $save_column['OPN_subject'] = $payment_result['merchant_transaction_id'] . ' ' . $payment_data['reason']; $save_column['OPN_currency'] = $payment_data['refund_currency_code']; $save_column['OPN_orderAmount'] = '-'.$payment_data['refund_amount']; $save_column['OPN_payAmount'] = '-'.$payment_data['refund_amount']; $save_column['OPN_payFee'] = null; // 1; // ! todo: 计算手续费; 退款 1 USD 原手续费不退 $save_column['OPN_netAmount'] = '-'.$payment_data['settlement_amount']; // todo: $save_column['OPN_transactionResult'] = refund_status($payment_data['refund_status']); $save_column['OPN_resultCode'] = $payment_data['refund_status']; // $save_column['OPN_resultMsg'] = isset($payment_result['return_msg']) ? $payment_result['return_msg'] : $payment_result['result_code']; // $save_column['OPN_errCode'] = isset($payment_result['err_code']) ? $payment_result['err_code'] : NULL; // $save_column['OPN_errMsg'] = isset($payment_result['err_code_des']) ? $payment_result['err_code_des'] : NULL; $save_column['OPN_acquiringTime'] = date('Y-m-d H:i:s', strtotime($payment_data['refund_time'])); $save_column['OPN_completeTime'] = date('Y-m-d H:i:s', strtotime($payment_data['refund_time'])); $save_column['OPN_remark'] = $payment_data['reason'] ? $payment_data['reason'] : ''; // $save_column['OPN_payerLogId'] = $payment_result['openid']; // $save_column['OPN_payerStatus'] = $payment_result['is_subscribe']==='Y' ? "subscribed" : NULL; $save_column['OPN_fundSource'] = $site; $save_column['OPN_entryAmountCNY'] = floatval($ssje); $save_column['OPN_rawContent'] = json_encode($payment_result); $save_column['OPN_noticeTime'] = date('Y-m-d H:i:s'); $save_column['OPN_noticeType'] = 'refund'; $save_column['OPN_noticeSendStatus'] = refund_status_send($payment_data['refund_status']); $save_column['OPN_noticeSendTime'] = NULL; $save_column['OPN_accountMethod'] = $this->merchant_config['method_code']; // log_message('error','test: ' . __METHOD__ . ': ' . __LINE__ . ' to in' . PHP_EOL . var_export($save_column, 1)); // die; // test:0 if ($this->note_model->insert_note($save_column)) { $response['code'] = 200; $response['message'] = 'success'; } $this->output->set_content_type('application/json')->set_output(json_encode($response)); } // protected function generateSignArray($params, $signType = "RSA") // { // return $this->sign(generateSignContent($params), $signType); // } // protected function sign($data, $signType = "RSA") // { // $this->private_key = $this->merchant_config['merchant_private_key']; // $priKey = $this->private_key; // $res = "-----BEGIN RSA PRIVATE KEY-----\n" . // wordwrap($priKey, 64, "\n", true) . // "\n-----END RSA PRIVATE KEY-----"; // ($res) or die('您使用的私钥格式错误,请检查RSA私钥配置'); // if ("RSA2" == $signType) { // openssl_sign($data, $sign, $res, OPENSSL_ALGO_SHA256); // } else { // openssl_sign($data, $sign, $res); // } // $sign = base64_encode($sign); // return $sign; // } protected function check_sign($data, $signature) { if (empty($signature)) { log_message('error', 'LianlianPay notify error: no sign.'); return false; } $verify_res = $this->verify_signature(generateSignContent($data), $signature); if ( ! $verify_res) { log_message('error', 'LianlianPay notify error: sign. ' . generateSignContent($data)); return false; } // return false; // test: 0 return true; } protected function verify_signature($data, $sign, $signType = "RSA") { // Load the public key $pubKey = $this->merchant_config['lianlian_public_key']; if (!$pubKey) { return false; // Public key file not found or unreadable. } $res = "-----BEGIN PUBLIC KEY-----\n" . wordwrap($pubKey, 64, "\n", true) . "\n-----END PUBLIC KEY-----"; $res = openssl_get_publickey($res); ($res) or die('LianlianRSA公钥错误。请检查公钥文件格式是否正确'); //调用openssl内置方法验签,返回bool值 if ("RSA2" == $signType) { $result = (bool)openssl_verify($data, base64_decode($sign), $res, OPENSSL_ALGO_SHA256); // sha256 OPENSSL_ALGO_SHA256 } else { $result = (bool)openssl_verify($data, base64_decode($sign), $res); } // log_message('error', 'test: ' . __METHOD__ . ': ' . __LINE__ . ' result' . PHP_EOL . var_export($result, 1)); //释放资源 openssl_free_key($res); return $result; } }