You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
information-system/webht/third_party/pay/controllers/LianlianService.php

237 lines
13 KiB
PHP

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<?php
defined('BASEPATH') or exit('No direct script access allowed');
class LianlianService extends CI_Controller
{
protected $merchant_config;
protected $private_key;
public function __construct()
{
parent::__construct();
bcscale(2);
$this->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;
}
}