Ruby on Rails Ping ++ 支付

mayxu1207發表於2019-02-16

本地資料庫建立訂單表。
建議包含以下欄位,參考官方API( https://pingxx.com/document/api#api-c-new):

order_no:required

     商戶訂單號,適配每個渠道對此引數的要求,必須在商戶系統內唯一。
     alipay: 1-64 位,
     wx: 1-32 位,
     bfb: 1-20 位,
     upacp: 8-40 位,
     yeepay_wap:1-50 位,
     jdpay_wap:1-30 位,
     cnp_u:8-20 位,
     cnp_f:8-20 位,
     推薦使用 8-20 位,要求數字或字母,不允許特殊字元

app[id]:required

    支付使用的 app 物件的 id,請登陸管理平臺檢視。

subject:required

      商品的標題,該引數最長為 32 個 Unicode 字元,
      銀聯全渠道(upacp/upacp_wap)限制在 32 個位元組。

body:required

    商品的描述資訊,該引數最長為 128 個 Unicode 字元,
    yeepay_wap 對於該引數長度限制為 100 個 Unicode 字元。

channel:required

    支付使用的第三方支付渠道(更多請參考api)
        alipay:支付寶手機支付
        alipay_wap:支付寶手機網頁支付
        alipay_qr:支付寶掃碼支付
        alipay_pc_direct:支付寶 PC 網頁支付
        apple_pay:Apple Pay
        bfb:百度錢包移動快捷支付
        bfb_wap:百度錢包手機網頁支付            
        wx:微信支付
        wx_pub:微信公眾賬號支付
        wx_pub_qr:微信公眾賬號掃碼支付
        jdpay_wap:京東手機網頁支付

amount: required

    訂單總金額, 單位為對應幣種的最小貨幣單位,
    例如:人民幣為分(如訂單總金額為 1 元,此處請填 100)。

client_ip: required

       發起支付請求終端的 IP 地址,格式為 IPV4,如: 127.0.0.1。
       

以上是在ping++ 平臺建立訂單時需要的引數

以下是在ping++ 平臺建立訂單成功以及付款成功回撥的引數

  • paid :支付狀態,預設為false

  • refunded :退款狀態,預設為false

  • time_paid :付款時間

  • time_refunded:退款時間

  • charge_no:返回的charge編號

  • transaction_no :交易號

步驟:

1.本地建立一條訂單記錄

 def create_order

    #獲取引數        
    #判斷引數合法性    
    
    order = Order.new
    #儲存訂單資訊,注意subject以及body的長度
    #生成訂單號並儲存
    order_no = (Time.now.to_formatted_s(:number)).to_s
    6.times{ order_no<<rand(10).to_s }
    order.order_no = order_no

    #獲取ip並儲存
    order.client_ip = request.remote_ip
    
    if order.save
      #返回成功資訊
    else
      render_failure(order.errors.messages.first[1][0])
    end
  end

2.執行支付

  • 現在ping++ 平臺建立一條記錄
    1.在order.rb檔案中新建一個方法

    def pay_url
        #獲取api_key以及app_id
        Pingpp.api_key = PingPlusPlus.get_ping_settings["PING_API_KEY"]
        app_id = PingPlusPlus.get_ping_settings["PING_APP_ID"]
        #不同支付渠道的回撥地址
        case self.channel
              when "alipay"
                extra = {
            }
              when "wx"
                extra = {
            }  
         end
        #ping++平臺新建一個訂單
        begin
          charge = Pingpp::Charge.create(
                   :order_no  => self.order_no,
                   :app       => { :id => app_id },
                   :channel   => self.channel,
                   :amount    => self.amount.round(2) * 100.to_i,
                   :client_ip => self.client_ip,
                   :currency  => "cny",
                   :subject   => self.subject[0..31],
                   :body      => self.body[0..127],
                   :extra     => extra
                  )
          
          return charge
        rescue Pingpp::PingppError => error
              logger.error `ping++平臺建立訂單失敗`
              logger.error error.http_body
              return false
        end
    end

2.呼叫pay_url方法建立訂單,返回給客戶端charge物件,客戶端拿著charge物件去ping++ 平臺支付

    def confirm_and_payment
        order_no = params[:order_no]
        channel = params[:channel]
        if order_no.blank? || channel.blank?
           render_failure("引數不完整!") and return
        end
    
        order =  Order.where(order_no: order_no).first
        if order.blank?
             render_failure("訂單不存在!")and return
        end

        charge = order.pay_url
        if charge == false
           render_failure("訂單支付失敗!") and return
        else
           order.update_attribute(:charge_no ,(JSON.parse charge.to_s)[`id`])
           render(:json => charge)
        end
    end
  • 非同步通知更新付款結果

    def notify

        status = 400

        #判斷請求是否有ping++的簽名資訊
        if request.headers[`x-pingplusplus-signature`].blank?
           status = 401
           logger.debug `【報哪家】:======付款回撥請求來源錯誤!!!!!`
           return
        end 

        #獲取簽名資訊
        raw_data = request.body.read
        if request.headers[`x-pingplusplus-signature`].is_a?(Array)
           signature = request.headers[`x-pingplusplus-signature`][0].to_s
        else
           signature = request.headers[`x-pingplusplus-signature`].to_s
        end
        
        # 獲取「Webhooks 驗證 Ping++ 公鑰」
        pub_key_path ="#{Rails.root}/config/rsa_public_key.pem"
        if verify_signature(raw_data, signature, pub_key_path)
               #處理接收的結果
             event = JSON.parse(raw_data) 
             #付款成功
             if event["type"] == `charge.succeeded`

              # 開發者在此處加入對支付非同步通知的處理程式碼
                order_no = event[`data`][`object`][`order_no`]
                order = Order.where(order_no: order_no).first
                order_from = order.status 
                if order.present?
                    #更新欄位
                    order.paid = event[`data`][`object`][`paid`]    
                    if order.save
                         status = 200
                    else
                        status = 500
                    end
                else
                       logger.debug `資料庫沒有該條記錄!`
                end

              #退款成功
            elsif event[`type`] == `refund.succeeded`

                  # 開發者在此處加入對退款非同步通知的處理程式碼
                order_no = event[`data`][`object`][`order_no`]
                order = Order.where(order_no: order_no).first
                if order.present?
                    #更新欄位
                    order.time_refunded = Time.at(event[`data`][`object`][`time_succeed`])
                    if order.save
                        status = 200
                    else
                        status = 500
                    end
                else
                      logger.debug `資料庫沒有該條記錄!`
                end

            else
                logger.debug `付款回撥返回未知操作!`
            end

          else
             logger.debug `付款回撥請求來源錯誤!`
             status = 403
          end
          render :nothing => true, :status => status
    end

相關文章