問題描述
商戶的聚合支付平臺接入的第三方支付平臺或銀行,異步通知地址通常情況下,都支持域名訪問,但上海銀行信用卡支付比較特殊,對域名支付不太穩定,銀行建議商戶的異步通知地址直接給到商戶服務器的IP。如果商戶使用了AWS EC2產品,配置的負載均衡器在使用過程中,會發現負載均衡器的IP會動態切換。以上兩種情況,如果同時存在,就要去處理好異步通知IP的問題,處理不好,就會遇到事故。
解決思路
可以通過Shell腳本定時去查詢商戶支付系統負載均衡器的實時IP,然後系統在發起支付請求時,使用該IP做爲異步通知的IP,傳送給銀行支付網關。
具體操作步驟:
- 首先將AWS負載均衡器的所有IP都配置到銀行系統的IP白名單中;
- 商戶支付系統的所有EC2實例,都要支持負載均衡器的所有IP訪問,使用nginx的商戶可通過配置server_name來實現;
- 寫查詢實時IP的shell腳本,並配置到crontab中,定時執行;
- 在發起支付時,將查詢到的實時IP,傳送給銀行支付網關,有可能會查詢到多個,那麼就選其中一個傳送給銀行的支付網關;
假設條件如下:
- 商戶聚合支付系統的域名爲:https://pay.merchant.com
- 商戶AWS負載均衡器的IP集合爲:0.0.0.1、0.0.0.2、0.0.0.3
查詢負載均衡器實時IP腳本
- Shell腳本
#!/bin/bash
host="xxx.cache.amazonaws.com.cn"
port="6379"
key="PAY_DNS_IPS"
echo "clear cache"
redis-cli --raw -h $host -p $port DEL $key | xargs echo
for i in {0..3}
do
array[i]=`ping -c 1 pay.merchant.com | awk -F ' ' 'NR==1{print $3}' | sed 's/(//g;s/)//g'`
done
for data in ${array[@]}
do
echo "add ip:${data}"
redis-cli --raw -h $host -p $port SADD $key ${data} | xargs echo
done
echo "Complete!"
支付網關使用實時IP
class Bosc implements interface_payment {
private $defaultIp = '0.0.0.1';
private $returnUrl = 'https://0.0.0.1/notify/returnNotify/bosc';
private $notifyUrl = 'https://0.0.0.1/notify/index/bosc';
private $refundNotifyUrl = 'https://0.0.0.1/refund/notify/bosc';
private function queryDns()
{
$redis = paymentUtil::getInstance()->loadRedis();
$cloudIps = $redis->sunion('PAY_DNS_IPS');
$usingIp = $redis->get('PAY_DNS_USING');
if (!$usingIp) {
$usingIp = $this->defaultIp;
$redis->set('PAY_DNS_USING', $usingIp);
}
if ($cloudIps && in_array($usingIp, $cloudIps) === false) {
$usingIp = array_pop($cloudIps);
$redis->set('PAY_DNS_USING', $usingIp);
}
$this->returnUrl = str_replace($this->defaultIp, $usingIp, $this->returnUrl);
$this->notifyUrl = str_replace($this->defaultIp, $usingIp, $this->notifyUrl);
$this->refundNotifyUrl = str_replace($this->defaultIp, $usingIp, $this->refundNotifyUrl);
return true;
}
}