2

支払いダイアログを開こうとしていますが、うまくいきません。アクションをbuy_creditsまたはear_creditsに設定すると、機能します。しかし、アクションをbuy_itemに設定すると、次のエラーが返されます。

1383046 - Sorry, but we're having trouble processing your payment. You have not been charged for this transaction. Please try again.

私のJavaコード:

<script type="text/javascript">
    function buy() {
        FB.ui(
        {
            method: 'pay',
            action: 'buy_item',
            order_info: { 'item_id': '1a'},
            dev_purchase_params: {'oscif': true}
        }, 
        js_callback);
    }
    var js_callback = function (data) {
        if (data['order_id']) {
            write_callback_data(
                "<br><b>Transaction Completed!</b> </br></br>"
                + "Data returned from Facebook: </br>"
                + "Order ID: " + data['order_id'] + "</br>"
                + "Status: " + data['status']);
        } else if (data['error_code']) {
            // Appropriately alert the user.
            write_callback_data(
                "<br><b>Transaction Failed!</b> </br></br>"
                + "Error message returned from Facebook:</br>"
                + data['error_code'] + " - "
                + data['error_message']);
        } else {
            // Appropriately alert the user.
            write_callback_data("<br><b>Transaction failed!</b>");
        }
    };

    function write_callback_data(str) {
        document.getElementById('fb-ui-return-data').innerHTML = str;
    }
</script>

私のPHPコールバックコード:

error_reporting(E_ALL);
$app_secret = '********************************';
// Validate request is from Facebook and parse contents for use.
$request = parse_signed_request($_POST['signed_request'], $app_secret);

// Get request type.
// Two types:
//   1. payments_get_items.
//   2. payments_status_update.
$request_type = $_POST['method'];

error_log($request_type, 0);
// Setup response.
$response = '';

if ($request_type == 'payments_get_items') {
  // Get order info from Pay Dialog's order_info.
  // Assumes order_info is a JSON encoded string.
  $order_info = json_decode($request['credits']['order_info'], true);

  // Get item id.
  $item_id = $order_info['item_id'];

  // Simulutates item lookup based on Pay Dialog's order_info.
  if ($item_id == '1a') {
    $item = array(
      'title' => '100 Gold',
      'description' => 'Premium Currency.',
      // Price must be denominated in credits.
      'price' => 5,
      'image_url' => '1a.png'
    );

    // Construct response.
    $response = array(
                  'content' => array(
                                 0 => $item,
                               ),
                  'method' => "payments_get_items",
                );
    // Response must be JSON encoded.
    $response = json_encode($response);
  }

} else if ($request_type == "payments_status_update") {
  // Get order details.

  $order_details = json_decode($request['credits']['order_details'], true);

  // Determine if this is an earned currency order.
  $item_data = json_decode($order_details['items'][0]['data'], true);
  $earned_currency_order = (isset($item_data['modified'])) ?
                             $item_data['modified'] : null;

  // Get order status.
  $current_order_status = $order_details['status'];

  if ($current_order_status == 'placed') {
    // Fulfill order based on $order_details unless...

    if ($earned_currency_order) {
      // Fulfill order based on the information below...
      // URL to the application's currency webpage.
      $product = $earned_currency_order['product'];
      // Title of the application currency webpage.
      $product_title = $earned_currency_order['product_title'];
      // Amount of application currency to deposit.
      $product_amount = $earned_currency_order['product_amount'];
      // If the order is settled, the developer will receive this
      // amount of credits as payment.
      $credits_amount = $earned_currency_order['credits_amount'];
    }

    $next_order_status = 'settled';

    // Construct response.
    $response = array(
                  'content' => array(
                                 'status' => $next_order_status,
                                 'order_id' => $order_details['order_id'],
                               ),
                  'method' => $request_type,
                );
    // Response must be JSON encoded.
    $response = json_encode($response);

  } else if ($current_order_status == 'disputed') {
    // 1. Track disputed item orders.
    // 2. Investigate user's dispute and resolve by settling or refunding the order.
    // 3. Update the order status asychronously using Graph API.

  } else if ($current_order_status == 'refunded') {
    // Track refunded item orders initiated by Facebook. No need to respond.

  } else {
    // Track other order statuses.

  }
}

// Send response.
error_log(print_r($response, true));
echo $response;

// These methods are documented here:
// https://developers.facebook.com/docs/authentication/signed_request/
function parse_signed_request($signed_request, $secret) {
  list($encoded_sig, $payload) = explode('.', $signed_request, 2);

  // decode the data
  $sig = base64_url_decode($encoded_sig);
  $data = json_decode(base64_url_decode($payload), true);

  if (strtoupper($data['algorithm']) !== 'HMAC-SHA256') {
    error_log('Unknown algorithm. Expected HMAC-SHA256');
    return null;
  }

  // check sig
  $expected_sig = hash_hmac('sha256', $payload, $secret, $raw = true);
  if ($sig !== $expected_sig) {
    error_log('Bad Signed JSON signature!');
    return null;
  }

  return $data;
}

function base64_url_decode($input) {
  return base64_decode(strtr($input, '-_', '+/'));
}

スクリプトにerror_log呼び出しがあり、購入ボタンを押すとサービスが2回呼び出されるようです。同じメソッドを呼び出す:payments_get_items。応答データは適切にフォーマットされているように見えます。ログの出力は次のとおりです。

payments_get_items
{"content":[{"title":"100 Gold","description":"Premium Currency.","price":5,"image_url":"1a.png"}],"method":"payments_get_items"}
payments_get_items
{"content":[{"title":"100 Gold","description":"Premium Currency.","price":5,"image_url":"1a.png"}],"method":"payments_get_items"}
4

1 に答える 1

1

これは、ほぼ確実に、コールバック URL が Facebook に返す応答の問題です。

2 つのエントリが表示される理由は、Facebook が (有効な) 応答を 2 回取得しようとして失敗し、ユーザーに「申し訳ありませんが、お支払いの処理で問題が発生しています...」というエラー メッセージを表示するためです。

HTTP エラー コードと Facebook に送信する応答の本文を確認し、それが有効であることを確認します。

于 2012-09-18T23:52:40.993 に答える