从服务器端验证谷歌播放购买

时间:2015-05-24 06:50:16

标签: php unity3d openssl in-app-purchase

我现在真的搞砸了理解需求的概念和原因,甚至不知道如何通过编码来实现。

所以,我用团结制作手机游戏,c#。使用php,mysql进行高分,并在应用购买商品信息中存储用户。

我一周前在谷歌播放时发布了我的游戏,我的谷歌钱包显示没有人直到现在购买该游戏中的任何项目。

但是,当我检查我的游戏服务器(mysql数据库)时,一些用户有大量应该购买的项目。

这意味着一些用户使用黑客工具并绕过谷歌游戏检查流程并欺骗我的游戏并进行虚假购买。

所以我没有实施developerPayload,也没有验证Google Play购买收据。

所以现在我删除了我的数据库中的整个恶意用户的项目(这将设置0到该用户的客户端项目),并希望实施google play购买的服务器端验证收据。

我通过谷歌搜索搜索了许多帖子,但是从头到尾没有完美的解决方案。

无论如何,我到目前为止都是这样实现的。

首先,在用户结束google结帐流程(无论是真的还是假的)之后,我的Unity客户端的OnPurchaseSucceded函数被调用,我实现了开始在我的服务器上传递我的php脚本。

public partial class Form1 : Form
{
    private bool draw;
    private int x, y, xe, ye;
    private Stack<ICommand> commandStack = new Stack<ICommand>();
    ICommand command  = null;

    public Form1()
    {
        InitializeComponent();

        menuComboBoxShape.ComboBox.DataSource = Enum.GetValues(typeof(Item));
    }

    public enum Item
    {
        Pencil,
        Rectangle, 
        Ellipse,
    }


    private void panel_MouseDown(object sender, MouseEventArgs e)
    {
        draw = true;
        x = e.X;
        y = e.Y;
    }

    private void panel_MouseUp(object sender, MouseEventArgs e)
    {
        draw = false;
        xe = e.X;
        ye = e.Y;

        Item item; 
        Enum.TryParse<Item>(menuComboBoxShape.ComboBox.SelectedValue.ToString(), out item);

        switch (item)
        {

            case Item.Pencil:
                using (Graphics g = panel.CreateGraphics())
                    using (var pen = new Pen(System.Drawing.Color.Black))     //Create the pen used to draw the line (using statement makes sure the pen is disposed)
                    {
                        g.DrawLine(pen,new Point(x, y), new Point(xe, ye));
                    }
                break;
            case Item.Rectangle:
                var box=new Box();
                panel.Controls.Add(box);
                box.Location = new Point(x, y);
                box.Width = (xe - x);
                box.Height = (ye - y);
                break;
            case Item.Ellipse:
                var el = new Ellipse();
                panel.Controls.Add(el);
                el.Location = new Point(x, y);
                el.Width = (xe - x);
                el.Height = (ye - y);
                el.Do();
                commandStack.Push(el);
                break;
            default:
                break;
        }
    }

    private void undoButton_Click(object sender, EventArgs e)
    {
        if (commandStack.Count > 0)
        {
            ICommand lastCommand = commandStack.Pop();
            lastCommand.Undo();
        }
        panel.Invalidate();
    }

    private void clearAllButton_Click(object sender, EventArgs e)
    {
        panel.Controls.Clear();
    }
}

以及问题,

1。 [我在代码上方做得对吗?对于数据&#39;领域,我用过buy.OriginalJson,但这是对的吗?如果没有,我应该使用什么?]

并从php(上面代码的verifyURL)收到这些信息后,

 private void OnPurchaseSucceded(Purchase purchase)
{
    /*
    // Optional verification of the payload. Can be moved to a custom server
    if (!VerifyDeveloperPayload(purchase.DeveloperPayload)) {
        return;
    }*/
    StartCoroutine(VerifyReceiptCo(purchase));
}

 IEnumerator VerifyReceiptCo(Purchase purchase)
{
    WWWForm hsFm = new WWWForm();
    hsFm.AddField("data", purchase.OriginalJson);
    hsFm.AddField("signature", purchase.Signature);
    WWW hs = new WWW(verifyURL, hsFm);
    yield return hs;
    Debug.Log("verify result is " + hs.text);
    // if result is true(validated), give item to user.
}

另一个问题,

2。 [我是否需要付费SSL服务才能使用上述php代码的openssl_方法?] 我正在使用hostgator.com的网络托管,我的计划已经有了共享SSL&#39;服务,那就够了吗?或者我应该购买另一个私人SSL服务计划?]

第3。如果不使用openssl(不使用SSL服务)方法,是否无法验证这一点?

4。总的来说,我正在做正确的方向来处理黑客用户? 非常感谢。

1 个答案:

答案 0 :(得分:1)

这是我验证Google订单的代码。它适用于我公司的所有产品。非常简单的代码。

    function verifyGoogleOrderLocal($packageName, $jsonData, $sig)
{
    $public_keys = array(
    'package1' => 'key1',
    'package2' => 'key2',
    );
    if(!$public_keys[$packageName]) {
        return array("success"=>0,"reason"=>'no public key defined');
    }
    $key = get_openssl_key($public_keys[$packageName]);
    if(!$key) {
        return array("success"=>0,"reason"=>'invalid public key');
    }
    $result = openssl_verify($jsonData, base64_decode($sig), $key, OPENSSL_ALGO_SHA1);
    $resp = array('success'=>$result);
    if($result==0) $resp['reason'] = 'invalid signature'; 
    return $resp;
}

function get_openssl_key($publicKey)
{
    $key = "-----BEGIN PUBLIC KEY-----\n" . chunk_split($publicKey, 64, "\n") . '-----END PUBLIC KEY-----';
    $key = openssl_get_publickey($key);
    return $key;
}