我正在尝试在Woocommerce网站中添加自定义支付网关。流程如下:
这是我到目前为止所取得的成就: 当用户单击“下达订单”时,将创建状态为“保留”的新订单,并将其重定向到名为“ prueba.php”的页面。该页面仅包含隐藏的表格,其中包含付款处理器将用户重定向到其网关所需的数据。加载页面后,此表单会自动提交(我觉得这不是最安全的操作,因为如果打开元素检查器,可以看到隐藏的输入及其值,但是我不知道其他更好的方法来完成这项工作)。这是我在插件主文件中所拥有的:
add_action( 'plugins_loaded', 'custom_init_gateway_class' );
function custom_init_gateway_class() {
class WC_My_Gateway extends WC_Payment_Gateway {
/**
* Constructor
*/
public function __construct() {
$this->id = 'mygateway';
$this->has_fields = true;
$this->method_title = 'My Gateway';
$this->method_description = 'Description of payment gateway';
$this->supports = array(
'products'
);
// Method
$this->init_form_fields();
$this->init_settings();
$this->title = $this->get_option( 'title' );
$this->description = $this->get_option( 'description' );
$this->enabled = $this->get_option( 'enabled' );
add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );
}
/**
* Plugin options
*/
public function init_form_fields(){
$this->form_fields = array(
'enabled' => array(
'title' => __( 'Enable/Disable', 'woocommerce' ),
'type' => 'checkbox',
'label' => __( 'Enable Card Payment', 'woocommerce' ),
'default' => 'yes'
),
'title' => array(
'title' => __( 'Title', 'woocommerce' ),
'type' => 'text',
'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce' ),
'default' => __( 'Credit Payment', 'woocommerce' ),
'desc_tip' => true,
),
'description' => array(
'title' => __( 'Customer Message', 'woocommerce' ),
'type' => 'textarea',
'default' => ''
)
);
}
/*
* Processing the payments
*/
public function process_payment( $order_id ) {
global $woocommerce;
$order = new WC_Order( $order_id );
$order->update_status('on-hold', __( 'Awaiting card payment', 'woocommerce' ));
return array(
'result' => 'success',
'redirect' => 'https://mydomain.example/prueba.php?price='.$order->get_total().'¤cy='.$order->get_currency().'&order_id='.$order->get_id()
);
}
}
}
function custom_add_gateway_class( $methods ) {
$methods[] = 'WC_My_Gateway';
return $methods;
}
add_filter( 'woocommerce_payment_gateways', 'custom_add_gateway_class' );
“ prueba.php”中的隐藏形式。在输入“ MERCHANT_RESPONSE_URL”中,我必须指定在付款完成后我希望付款处理者将数据发送到哪个URL:
<form method="POST" action="https://paymentprocessorgateway.example" name="respuesta" style="display: none;">
<input type="hidden" name="TIMESTAMP" value="<?php echo $timestamp; ?>">
<input type="hidden" name="MERCHANT_ID" value="12345">
<input type="hidden" name="AMOUNT" value="<?php echo $Amount; ?>">
<input type="hidden" name="CURRENCY" value="<?php echo $Currency; ?>">
<input type="hidden" name="SIGNATURE" value="<?php echo $hash; ?>">
<input type="hidden" name="COMMENT1" value="<?php echo $order_id; ?>">
<input type="hidden" name="MERCHANT_RESPONSE_URL" value="https://mydomain.example/response.php">
<input type="submit" value="Click here to buy">
</form>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script type="text/javascript">
function sendForm() {
$("form").submit();
}
sendForm();
</script>
发送此表单后,用户将被重定向到付款处理器网关,在该网关上他可以写和发送他的卡数据,然后处理器将一些POST数据发送到“ response.php”。在此页面中,我将从支付处理器收到的哈希值与自己生成的哈希值(从支付处理器收到的其他一些POST值)进行比较。
我想要实现的是将用户重定向到“谢谢”页面,如果一切正确,则将订单状态更改为“已完成”,否则,将显示错误消息。另外,我希望在这里创建订单(如果付款正确),而不是在客户单击“下订单”按钮时(我以为知道订单的ID,无论何时何地我都可以更改其状态)我需要或者可以在任何地方创建新订单,但是我一定做错了所有事情,因为我不太了解woocommerce和OOP PHP的工作原理。 我尝试在“ response.php”中编写此代码,但是处理器的网关抛出一个错误,该错误表示事务处理正常,但无法连接到MERCHANT_RESPONSE_URL中指定的url:
//Generating the hash with data received from processor
$respuesta = $_POST['TIMESTAMP'].".".$_POST['MERCHANT_ID'].".".$_POST['ORDER_ID'].".".$_POST['RESULT'];
$my_hash = sha1(sha1($respuesta);
global $woocommerce;
$order = wc_get_order( $order_id );
if ($my_hash != $_POST['HASH']) { //$_POST['HASH'] is the hash sent by the processor.
wc_add_notice( 'Please try again.', 'error' );
return;
} else {
$order->payment_complete();
$woocommerce->cart->empty_cart();
return array(
'result' => 'success',
'redirect' => $this->get_return_url( $order )
);
}
如果删除与woocommerce相关的变量,并使用类似的方法查看其是否正常运行,则警报将正确打印:
if ($my_hash != $_POST['HASH']) {
echo '<script>alert("Wrong transaction");</script>';
} else {
echo '<script>alert("Correct transaction");</script>';
}
就像我不能在那里使用woocommerce相关的变量一样。我想我必须将它附加到某个钩子或其他东西上,但是我不知道在哪个地方,在此过程中我犯了很多错误。如果有人可以阐明如何处理支付处理器的响应并将其与Woocommerce流集成,我将永远感激不已。
答案 0 :(得分:0)
首先。如果您应该提交隐藏表单,那么在涉及隐藏方面或不隐藏方面时,我将不必担心安全性。无论如何,始终可以查看/篡改客户端的任何内容,因此就不能在其中采取安全措施。
您的最后一个代码块提到$old_hash
,但是它是空的吗?至少,您的代码块没有设置它。您说这段代码的哪一部分不起作用?您是否尝试登录到某个东西以使其喜欢错误日志以查看它是否被调用? (例如error_log('message');
)
您提到HPP将哈希发送回您选择的页面,所以我说response.php可能是付款后发送用户的页面。
(另外,这对我来说几乎是睡觉时间,如果我停止回应,我深表歉意。)