123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133 |
- <?php
- /**
- * 接收IOS通知(支付结果)
- * @version
- * 1.0.0 Created at 2017-12-30. by --gwang
- * @author gwang (mail@wanggangzero.cn)
- * @copyright ? 2017-12-30, SJZ LoyalSoft Corporation & gwang. All rights reserved.
- *
- */
- include_once __DIR__ . '/../../../main.php'; # 导入game utils
- include_once __DIR__ . '/../Mo/payResp.php'; # 导入通用返回值结构
- include_once __DIR__ . '/../Mo/payRequest.php'; # 导入通用返回值结构
- require_once __DIR__ . '/../Mo/OrderNotice.php';
- require_once __DIR__ . '/config.ios.php'; # 配置文件, Ps. 里面用到了object
- use loyalsoft\CLog;
- use loyalsoft\HttpUtil;
- use loyalsoft\pay\OrderNotice;
- use loyalsoft\JsonUtil;
- /**
- * 客户端参数
- */
- class iosNotify {
- public $receipt;
- public $product_id;
- public $uid;
- public $cpOrderId;
- public $sandbox;
- public $callbackInfo;
- public $sign;
- public $notify_url;
- public function __construct($arr) {
- $this->receipt = $arr[0];
- $this->product_id = $arr[1];
- $this->uid = $arr[2]; # 剥离一下前缀
- $this->cpOrderId = $arr[3];
- $this->sandbox = ($arr[4] == '否') ? false : true; # ☄,客户端竟然传的"是"和"否".
- $this->callbackInfo = $arr[5];
- $this->sign = $arr[6];
- $this->notify_url = $arr[7];
- }
- }
- /**
- * 到苹果后台进行支付凭证校验
- * @param str $receipt
- */
- function VerifyFromApple($receipt, $sandbox, &$appleResp) {
- $cfg = config_for_ios::Inst($sandbox);
- $url = $cfg->verifySession_url;
- $ret = HttpUtil::makeRequest($url, JsonUtil::encode(array('receipt-data' => $receipt)));
- if ($ret['result']) { # 发送成功
- $data = JsonUtil::decode($ret['msg']);
- $in_app = $data->receipt->in_app[0];
- $appleResp = array(
- 'status' => $data->status, // # 收据状态
- 'product_count' => $in_app->quantity, // # 收据->内购->数量
- 'product_id' => $in_app->product_id, // # 收据->内购->道具编号
- 'transaction_id' => $in_app->transaction_id, // # 收据->内购->交易编号
- 'purchase_date' => $in_app->purchase_date, // # 收据->内购->购买时间
- 'appid' => $data->receipt->app_item_id // # 收据->appId(sandbox下为0)
- );
- if ($appleResp['status'] == 0) { # 验证结果为 valid
- if ($appleResp['appid'] == $cfg->appid # Appid合法
- || ($sandbox && $appleResp['appid'] == 0)) { # 或者沙箱下面appid=0
- CLog::pay("[IOS.notify] Apple后台验证通过." . $ret['msg']);
- return true;
- } else {
- CLog::pay("[IOS.notify] 凭证的Appid不符!." . $ret['msg']);
- }
- } else {
- CLog::pay("[IOS.notify] Apple后台验证失败." . $ret['msg']);
- }
- } else { # 通讯失败
- CLog::pay("[IOS.notify] 与Apple后台通讯失败.");
- }
- return false;
- }
- try {
- HttpUtil::PostOnly();
- // exit();
- CLog::pay("[IOS.notify] 收到支付回调请求: " . HttpUtil::getQueryString());
- $params = explode('&=&', HttpUtil::getQueryString()); # 提取参数
- $notify = new iosNotify($params);
- $cfg = config_for_ios::Inst($notify->sandbox); # 配置信息
- CLog::pay($notify);
- $sign = md5($notify->cpOrderId . $cfg->appkey); # 计算签名md5(cpOrderId+appkey)
- CLog::pay("[IOS.notify] " . "[签名原文]:" . $notify->sign);
- CLog::pay("[IOS.notify] " . "[签名结果]:" . $sign);
- if ($sign != $notify->sign) { # 验证签名
- exit(payResp::err(2, "Invalied sign!")); # 退出
- }
- $appleResp = null; # 苹果的返回值
- if (!VerifyFromApple($notify->receipt, $notify->sandbox, $appleResp)) { # 到苹果后台验证支付凭证
- exit(payResp::err(2, "Verify from apple server failed!")); # 退出
- }
- $order = OrderNotice::reParse_IOSOrder($notify, $appleResp); # 将参数归一化到order
- // var_dump($order);
- if ($order != null) {
- if ($order->Check()) { # 订单校验
- if (!$order->CheckDuplicateSdkOrder()) { # 渠道订单编号校验,防重放(简单修改)攻击
- CLog::pay("[IOS.notify] [异常]:" . "重复的sdk_orderId!"); # 日志
- exit(payResp::err(2, 'failure'));
- } else if ($order->status == 1) { # 订单状态, 1代表支付成功
- $order->UpdateOrderStatus(); # 更新订单状态,->已付款
- CLog::pay("[IOS.notify] [发货] 订单: " # 日志
- . $order->cpOrderId . ", 金额: " . $order->amount);
- } else if ($order->status == 2) { # status为2(failed)的情况
- $order->UpdateOrderStatus(); # 直接更新订单状态,->支付失败
- CLog::pay("[IOS.notify] [不发货] 订单: " . $order->cpOrderId);
- } else {
- CLog::pay("[IOS.notify] [处理结果]: FAILURE (未知的支付状态)"); # 日志
- exit(payResp::err(1, '重试'));
- }
- CLog::pay("[IOS.notify] [处理结果]:" . "SUCCESS"); # 日志
- exit(payResp::ok('success'));
- }
- }
- CLog::pay("[IOS.notify] [处理结果]:" . "FAILURE"); # 日志
- exit(payResp::err(2, 'failure'));
- } catch (Exception $e) {
- CLog::pay("[IOS.notify] " . $e->getMessage()); # 日志
- exit(payResp::err(1, $e->getMessage())); # 未知异常, 告诉客户端可以重试
- }
|