private void parsePaymentRequest(Protos.PaymentRequest request) throws PaymentProtocolException {
   try {
     if (request == null) throw new PaymentProtocolException("request cannot be null");
     if (request.getPaymentDetailsVersion() != 1)
       throw new PaymentProtocolException.InvalidVersion(
           "Version 1 required. Received version " + request.getPaymentDetailsVersion());
     paymentRequest = request;
     if (!request.hasSerializedPaymentDetails())
       throw new PaymentProtocolException("No PaymentDetails");
     paymentDetails =
         Protos.PaymentDetails.newBuilder()
             .mergeFrom(request.getSerializedPaymentDetails())
             .build();
     if (paymentDetails == null) throw new PaymentProtocolException("Invalid PaymentDetails");
     if (!paymentDetails.hasNetwork()) params = MainNetParams.get();
     else params = NetworkParameters.fromPmtProtocolID(paymentDetails.getNetwork());
     if (params == null)
       throw new PaymentProtocolException.InvalidNetwork(
           "Invalid network " + paymentDetails.getNetwork());
     if (paymentDetails.getOutputsCount() < 1)
       throw new PaymentProtocolException.InvalidOutputs("No outputs");
     for (Protos.Output output : paymentDetails.getOutputsList()) {
       if (output.hasAmount()) totalValue = totalValue.add(Coin.valueOf(output.getAmount()));
     }
     // This won't ever happen in practice. It would only happen if the user provided outputs
     // that are obviously invalid. Still, we don't want to silently overflow.
     if (params.hasMaxMoney() && totalValue.compareTo(params.getMaxMoney()) > 0)
       throw new PaymentProtocolException.InvalidOutputs("The outputs are way too big.");
   } catch (InvalidProtocolBufferException e) {
     throw new PaymentProtocolException(e);
   }
 }
 /**
  * Generates a Payment message based on the information in the PaymentRequest. Provide
  * transactions built by the wallet. If the PaymentRequest did not specify a payment_url, returns
  * null.
  *
  * @param txns list of transactions to be included with the Payment message.
  * @param refundAddr will be used by the merchant to send money back if there was a problem.
  * @param memo is a message to include in the payment message sent to the merchant.
  */
 @Nullable
 public Protos.Payment getPayment(
     List<Transaction> txns, @Nullable Address refundAddr, @Nullable String memo)
     throws IOException, PaymentProtocolException.InvalidNetwork {
   if (paymentDetails.hasPaymentUrl()) {
     for (Transaction tx : txns)
       if (!tx.getParams().equals(params))
         throw new PaymentProtocolException.InvalidNetwork(params.getPaymentProtocolId());
     return PaymentProtocol.createPaymentMessage(
         txns, totalValue, refundAddr, memo, getMerchantData());
   } else {
     return null;
   }
 }