anchor.diff:  }
   ----
   
  -* The `GoCardlessPaymentTransactionInfoPlugin` extends the https://github.com/killbill/killbill-plugin-framework-java/blob/46d94fbeb1cf089aa04e62cfecf751ca47032023/src/main/java/org/killbill/billing/plugin/api/payment/PluginPaymentTransactionInfoPlugin.java[PluginPaymentTransactionInfoPlugin] from the https://github.com/killbill/killbill-plugin-framework-java[Kill Bill plugin framework]. This class in turn implements the <<PaymentTransactionInfoPlugin, PaymentTransactionInfoPlugin>> interface
  -
  -* The `GoCardlessPaymentTransactionInfoPlugin` constructor accepts parameters corresponding to the data to be returned by <<PaymentTransactionInfoPlugin, PaymentTransactionInfoPlugin>>. It simply invokes the superclass constructor with these parameters
  +* The `GoCardlessPaymentTransactionInfoPlugin` extends the https://github.com/killbill/killbill-plugin-framework-java/blob/46d94fbeb1cf089aa04e62cfecf751ca47032023/src/main/java/org/killbill/billing/plugin/api/payment/PluginPaymentTransactionInfoPlugin.java[PluginPaymentTransactionInfoPlugin] from the https://github.com/killbill/killbill-plugin-framework-java[Kill Bill plugin framework]. This class in turn implements the <<PaymentTransactionInfoPlugin, PaymentTransactionInfoPlugin>> interface.
  +
  +* The `GoCardlessPaymentTransactionInfoPlugin` constructor accepts parameters corresponding to the data to be returned by <<PaymentTransactionInfoPlugin, PaymentTransactionInfoPlugin>>. It simply invokes the superclass constructor with these parameters.
   
   ==== Step 4 - Implementing GoCardlessPaymentPluginApi#buildFormDescriptor
   
  
positive.code: 
  ** *properties* - Set to `null` since the payment was not processed
  
  ==== Step 7 - Implementing GoCardlessPaymentPluginApi#getPaymentInfo
  
  As explained earlier, the Kill Bill Janitor system attempts to fix *PENDING* and *UNKNOWN* states by  polling the plugin via `PaymentPluginApi#getPaymentInfo` method. So, this method can be implemented as follows (See https://github.com/killbill/killbill-gocardless-example-plugin/blob/9522498ecde5849c940574c598ceb5ce088d32a7/src/main/java/org/killbill/billing/plugin/gocardless/GoCardlessPaymentPluginApi.java#L211[_GoCardlessPaymentPluginApi#getPaymentInfo_]):
  [source,java,linenums]
  ----
  public List<PaymentTransactionInfoPlugin> getPaymentInfo(UUID kbAccountId, UUID kbPaymentId,
  	Iterable<PluginProperty> properties, TenantContext context) throws PaymentPluginApiException {
  	logger.info("getPaymentInfo");
  	List<PaymentTransactionInfoPlugin> paymentTransactionInfoPluginList = new ArrayList<>();
  	String mandateId = getMandateId(kbAccountId, context) ;
  	logger.info("Mandate="+mandateId);
  	Mandate mandate = client.mandates().get(mandateId).execute(); //get GoCardless Mandate object
  	String customerId = mandate.getLinks().getCustomer(); //retrieve customer id from mandate
  	logger.info("CustomerId="+customerId);
  	Iterable<Payment> payments = client.payments().all().withCustomer(customerId).execute(); //get all payments related to customer
  	for (Payment payment : payments) {
  		String kbPaymentIdFromPayment = payment.getMetadata().get("kbPaymentId"); //get kbPaymentId from metadata in payment
  		logger.info("kbPaymentIdFromPayment="+kbPaymentIdFromPayment);
  		if(kbPaymentIdFromPayment != null && kbPaymentId.toString().equals(kbPaymentIdFromPayment)) {
  			logger.info("Found matching payment");
  			Currency killBillCurrency = convertGoCardlessCurrencyToKillBillCurrency(payment.getCurrency());
  			logger.info("payment_status="+payment.getStatus());
  			PaymentPluginStatus status = convertGoCardlessToKillBillStatus(payment.getStatus());
  			String kbTransactionPaymentIdStr = payment.getMetadata().get("kbTransactionId"); 
  			UUID kbTransactionPaymentId = kbTransactionPaymentIdStr !=null?UUID.fromString(kbTransactionPaymentIdStr):null;
  			logger.info("kbTransactionPaymentId="+kbTransactionPaymentId);
  			List<PluginProperty> outputProperties = new ArrayList<PluginProperty>();
  			outputProperties.add(new PluginProperty("mandateId",mandateId,false)); //arbitrary data to be returned to the caller
  			outputProperties.add(new PluginProperty("customerId",customerId,false));  //arbitrary data to be returned to the caller
  			GoCardlessPaymentTransactionInfoPlugin paymentTransactionInfoPlugin = new GoCardlessPaymentTransactionInfoPlugin(
  					kbPaymentId, kbTransactionPaymentId, TransactionType.PURCHASE, new BigDecimal(payment.getAmount()), killBillCurrency,
  					status, null, null, String.valueOf(payment.getId()), null, new DateTime(),
  					new DateTime(payment.getCreatedAt()), outputProperties); 
  			paymentTransactionInfoPluginList.add(paymentTransactionInfoPlugin);
  		}
  	}
  	return paymentTransactionInfoPluginList;
  }
  ----
  
  * If you recall, the `addPaymentMethod` stores the *mandate id* in the Kill Bill database in the *custom_fields* table. This is first retrieved and assigned to `mandateId`.
  
negative.code: 
  * The `properties` parameter is typically used to pass properties which are related to the specific method call (`addPaymentMethod` in this case) while the `PaymentMethodPlugin#getProperties`  typically refers to non-standard generic information about the payment method itself. 
  
  * A client application can use either of these to pass in the GoCardless properties. The code above (like other plugins) is lenient and accepts both ways. So, it first invokes `PluginProperties.merge` to merge both properties and stores them into a merged `allProperties` list.
  
  * It then retrieves the `redirectFlowId` and `sessionToken` from `allProperties`. These are required by GoCardless and are as explained below:
  
  