Ruby on Rails Ping ++ 支付

682 查看

本地数据库创建订单表。
建议包含以下字段,参考官方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