0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Google Apps Scriptで簡単ECサイトを作ろう

Posted at

gasで頑張る人はいないのか、AIに聞いても中々手こずったの同じことしようとしている人向けに公開
実際に作ったサイトはhttps://x.gd/Ppm2Z
上記の管理用スプレッドシートhttps://x.gd/XSFmu

PAY.JPの決済方法

    const url = 'https://api.pay.jp/v1/charges';
    const options = {
      method: 'post',
      headers: {
        Authorization: 'Basic ' + Utilities.base64Encode(paymentKeys.payjpSecret + ':'),
        'Content-Type': 'application/x-www-form-urlencoded'
      },
      payload: {
        amount: String(orderData.total),
        currency: 'jpy',
        card: orderData.paymentToken,
        description: '商品購入'
      },
      muteHttpExceptions: true
    };
    const response = UrlFetchApp.fetch(url, options);
    const result = JSON.parse(response.getContentText());
    if (result.error) throw new Error(result.error.message);

stripeのカード決済

    const customer = createStripeCustomer(orderData.email);
    if (customer.error) throw new Error(customer.error.message);

    const stripeUrl = 'https://api.stripe.com/v1/payment_intents';
    const base64Key = Utilities.base64Encode(paymentKeys.stripeSecret + ':');
    const webAppUrl = ScriptApp.getService().getUrl();

    const attachResponse = UrlFetchApp.fetch(`https://api.stripe.com/v1/payment_methods/${orderData.paymentToken}/attach`, {
      method: 'post',
      headers: {
        Authorization: 'Basic ' + base64Key,
        'Content-Type': 'application/x-www-form-urlencoded'
      },
      payload: { customer: customer.id }
    });
    
    if (JSON.parse(attachResponse.getContentText()).error) {
      throw new Error('PaymentMethodのアタッチに失敗しました');
    }

    const intentOptions = {
      method: 'post',
      headers: {
        Authorization: 'Basic ' + base64Key,
        'Content-Type': 'application/x-www-form-urlencoded'
      },
      payload: {
        amount: String(orderData.total),
        currency: 'jpy',
        customer: customer.id,
        payment_method: orderData.paymentToken,
        confirm: 'true',
        return_url: webAppUrl + '',
        setup_future_usage: 'on_session',
        'metadata[order_id]': orderNumber.toString()
      },
      muteHttpExceptions: true
    };

    const intentResponse = UrlFetchApp.fetch(stripeUrl, intentOptions);
    const intentResult = JSON.parse(intentResponse.getContentText());

    if (intentResult.error) throw new Error(intentResult.error.message);

stripeの銀行振込

    const customer = createStripeCustomer(orderData.email);
    if (customer.error) throw new Error(customer.error.message);

    const stripeUrl = 'https://api.stripe.com/v1/payment_intents';
    const base64Key = Utilities.base64Encode(paymentKeys.stripeSecret + ':');
    const webAppUrl = ScriptApp.getService().getUrl();

    // Create and confirm PaymentIntent in one step
    const payload = {
      amount: String(orderData.total),
      currency: 'jpy',
      customer: customer.id,
      'payment_method_types[]': 'customer_balance',
      'payment_method_data[type]': 'customer_balance',
      'payment_method_options[customer_balance][funding_type]': 'bank_transfer',
      'payment_method_options[customer_balance][bank_transfer][type]': 'jp_bank_transfer',
      confirm: 'true',
      return_url: webAppUrl + '',
      'metadata[order_id]': orderNumber.toString()

    };

    const options = {
      method: 'post',
      headers: {
        'Authorization': 'Basic ' + base64Key,
        'Content-Type': 'application/x-www-form-urlencoded'
      },
      payload: payload,
      muteHttpExceptions: true
    };

    const response = UrlFetchApp.fetch(stripeUrl, options);
    let result;
    try {
      result = JSON.parse(response.getContentText());
    } catch (e) {
      console.log('Stripe APIレスポンス:', response.getContentText());
      throw new Error('Stripe APIのレスポンスが不正です');
    }

stripのコンビニ決済

    const customer = createStripeCustomer(orderData.email);
    if (customer.error) throw new Error(customer.error.message);

    const stripeUrl = 'https://api.stripe.com/v1/payment_intents';
    const base64Key = Utilities.base64Encode(paymentKeys.stripeSecret + ':');

    const intentOptions = {
      method: 'post',
      headers: {
        Authorization: 'Basic ' + base64Key,
        'Content-Type': 'application/x-www-form-urlencoded'
      },
      payload: {
        amount: String(orderData.total),
        currency: 'jpy',
        customer: customer.id,
        'payment_method_types[]': 'konbini',
        payment_method: orderData.paymentToken,
        'metadata[order_id]': orderNumber.toString()
      },
      muteHttpExceptions: true
    };

    const intentResponse = UrlFetchApp.fetch(stripeUrl, intentOptions);
    const intentResult = JSON.parse(intentResponse.getContentText());

    if (intentResult.error) throw new Error(intentResult.error.message);


    // コンビニ決済の詳細を取得
    let konbiniDetails = null;
    if (intentResult.next_action && intentResult.next_action.konbini_display_details) {
      konbiniDetails = intentResult.next_action.konbini_display_details;
    }
    // モックデータを使用してコンビニ支払い情報を表示
    const mockKonbiniDetails = {
      convenience_store: 'lawson',
      expires_at: Math.floor(Date.now() / 1000) + 86400, // 24時間後
      payment_code: '1234567890',
      receipt_number: '1234-5678',
      hosted_instructions_url: 'https://pay.stripe.com/test_instructions'
    };
    konbiniDetails = konbiniDetails || mockKonbiniDetails

stripeのコンビニ決済はテスト環境ではコンビニ決済の詳細を返してくれないためモックを使っています。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?