whmcs是一款售卖服务器的程序,国外很多卖vps的都在使用这套程序,只是改动多少的问题。当然用它来卖其他东西也是可以的,whmcs风格简洁但不少功能,也是不错的在线商城软件。
我们引入的是免签约插件——码支付,别怪我这么推荐它,主要是码支付真的太厚道了,别人付款直接到你的账户里,无需提现没有手续费,方便快捷,缺点就是需要一台挂软件的win电脑或服务器,每日有几百元的限额。
码支付这类的支付在whmcs里叫做第三方网关,首先定位到该系统根目录下modules/gateways,在gateways目录里存放着很多个支付文件,我们需要在该目录下新建一个文件:codepay_alipay,意为码支付的支付宝支付方式,下面开始正式whmcs支付开发之旅。如需帮助可以留言。
防止直接访问
因为支付文件的重要性,我们不允许用户能够直接访问该文件,所以我们要阻止所有通过不正当的途径访问该文件的方式。下面代码即为不是whmcs系统访问的全都显示错误信息并终止程序往下进行。
if (!defined("WHMCS")) { die("This file cannot be accessed directly"); }
|
保存后你在浏览器访问本文件,将直接显示:This file cannot be accessed directly
配置插件信息
我们需要注明这个插件的版本号,作者名等信息。函数gatewaymodule_MetaData为whmcs系统内部定义的函数,我们可以直接拿来使用,gatewaymodule修改为文件名,例如我的文件为codepay_alipay.php,这个函数就叫做codepay_alipay_MtaData,必须同名,不然whmcs无法识别。
function codepay_alipay_MetaData() { return array( 'DisplayName' => 'codepay for whmcs', 'APIVersion' => '1.0', 'DisableLocalCredtCardInput' => true, 'TokenisedStorage' => false, ); }
|
配置插件设置页
接下来我们配置激活插件后,插件的设置页面,这里用户可以修改插件的配置信息,主要用来定义支付时显示的文字、码支付的id和密钥。
function codepay_alipay_config() { return array( 'FriendlyName' => array( 'Type' => 'System', 'Value' => '码支付—支付宝', ), 'codepayId' => array( 'FriendlyName' => '码支付id', 'Type' => 'text', 'Size' => '25', 'Default' => '', 'Description' =>'输入你的码支付id', ), 'codepayKey' => array( 'FriendlyName' => '码支付密钥', 'Type' => 'text', 'Size' => '25', 'Default' => '', 'Description' =>'输入你的码支付密钥', ), ); }
|
设置支付网关
支付插件最为核心的部分,我们需要依靠这个函数来处理用户的付款,这个函数不对是无法付款成功的。
function codepay_alipay_link($params) { $parameter = array( "id" => $params['codepayId'], "type" => 1, "pay_id" => $params['invoiceid'], "price" => $params['amount'], "outTime" => 300, "page" => 1, "return_url" => "", "notify_url" => "", ); $back = create_link($parameter, $params['codepayKey']); return '<form method="post" action="'.$back.'"> <>本页账单已生成,请尽快支付。> <input type="submit" value="' . $params['langpaynow'] . '" /> </form>'; }
|
这里我们把付款放到create_link函数里,就是让文件结构更清晰
function create_link($canshu, $codepay_key, $host="") { ksort($canshu); reset($canshu); $sign = ''; $urls = ''; foreach ($canshu AS $key => $val) { if ($val == '') continue; if ($key != 'sign') { if ($sign != '') { $sign .= "&"; $urls .= "&"; } $sign .= "$key=$val"; $urls .= "$key=" . urlencode($val); } } $key = md5($sign . $codepay_key); $query = $urls . '&sign=' . $key; $apiHost = ($host ? $host : "http://api2.fateqq.com:52888/creat_order/?"); $url = $apiHost . $query; return $url; }
|
官方还提供 gatewaymodule_refund 函数用于处理退款,但是谁希望用户买东西之后退款?所以不写,反正码支付API也不支持退款,需要退款可以手动操作,毕竟退款在少数。
异步通知
支付完成后,码支付网关会确认用户的付款信息并返回,我们需要获取码支付返回的信息,以此来判断用户是否付款成功并让whmcs做出处理。这一步也比较重要,不要让你用户付款后whmcs什么也不做,小心被认为骗钱把你举报了。
引入通知函数
require_once __DIR__ . '/../../../init.php'; require_once __DIR__ . '/../../../includes/gatewayfunctions.php'; require_once __DIR__ . '/../../../includes/invoicefunctions.php';
|
获取codepay_alipay的配置信息,比如码支付id和密钥
$gatewayParams = getGatewayVariables("codepay_alipay");
|
如果插件未激活,直接报错并退出。当然这段代码可以放在开头。
if (!$gatewayParams['type']) { die("Module Not Activated"); }
|
处理码支付返回的数据以确认是否付款成功。码支付使用post方式返回数据。
function handleData($data) { $pay_id = $data['pay_id']; $money = (float)$data['money']; $price = (float)$data['price']; $type = (int)$data['type']; $pay_no = $data['pay_no']; $param = $data['param']; $pay_time = (int)$data['pay_time']; $pay_tag = $data['tag']; $status = 2; $creat_time = time();
if ($money <= 0 || empty($pay_id) || $pay_time <= 0 || empty($pay_no)) { return "don't pay yet"; }else{ return "paid"; } }
|
上面的是函数只是一个处理数据的模板,下面才是对实际传来的数据做出处理,并将处理后的数据套用这个模板就可以了。
$codepay_key = $gatewayParams["codepayKey"]; $isPost = true; if (empty($_POST)) { $_POST = $_GET; $isPost = false; } ksort($_POST); reset($_POST); $sign = ''; foreach ($_POST AS $key => $val) { if ($val == '' || $key == 'sign') continue; if ($sign) $sign .= '&'; $sign .= "$key=$val"; } $invoiceId = $_POST['pay_id']; $amount = (float)$_POST['money']; $price = (float)$_POST['price']; $param = $_POST['param']; $type = (int)$_POST['type']; $transid = $_POST['pay_no'];
|
接下来套用模板,并做出判断:支付成功就确认订单生效;支付失败就不做处理。
if (!$_POST['pay_no'] || md5($sign . $codepay_key) != $_POST['sign']) { echo "invaild data"; } else { $result = handleData($_POST); if ($result == 'paid') { $invoiceId = checkCbInvoiceID( $invoiceId, $gatewayParams['name']); checkCbTransID($transid); addInvoicePayment($invoiceId,$transid,$amount,"0","codepay_alipay"); echo "ok"; } else { $error_msg = defined('DEBUG') && DEBUG ? $result : 'no'; if ($isPost) exit($error_msg); $result = "don't pay yet"; } }
|
添加一个0.01元的商品,并自测付款,whmcs如果自动确认付款,码支付后台订单状态为“支付成功”即可。如有问题可以在码支付里调试,看看哪儿出错了。
另外whmcs新版不自动确认服务,需要手动审核,我测试可以使用钩子函数OrderPaid修改数据表达到自动审核的目的,不知道这个是不是通用做法。
whmcs的订单和账单是不一样的,订单为order,账单为invoice,订单id可以跟账单id不一样,后续开发中不要搞混了。下次有机会更新whmcs系统下的自动发卡插件。
纯干货没有图片,图文并茂不存在的。