{"action":"created","comment":{"url":"https://api.github.com/repos/alphagov/pay-connector/pulls/comments/235943960","pull_request_review_id":177930738,"id":235943960,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIzNTk0Mzk2MA==","diff_hunk":"@@ -0,0 +1,182 @@\n+package uk.gov.pay.connector.gateway.epdq;\n+\n+import com.google.inject.Inject;\n+import com.google.inject.persist.Transactional;\n+import org.apache.http.NameValuePair;\n+import org.slf4j.Logger;\n+import org.slf4j.LoggerFactory;\n+import uk.gov.pay.connector.charge.dao.ChargeDao;\n+import uk.gov.pay.connector.charge.model.domain.ChargeEntity;\n+import uk.gov.pay.connector.charge.model.domain.ChargeStatus;\n+import uk.gov.pay.connector.gateway.PaymentGatewayName;\n+import uk.gov.pay.connector.gateway.processor.ChargeNotificationProcessor;\n+import uk.gov.pay.connector.gateway.processor.RefundNotificationProcessor;\n+import uk.gov.pay.connector.refund.model.domain.RefundStatus;\n+\n+import java.util.List;\n+import java.util.Optional;\n+import java.util.stream.Collectors;\n+\n+import static org.apache.commons.lang3.StringUtils.isBlank;\n+import static uk.gov.pay.connector.charge.model.domain.ChargeStatus.AUTHORISATION_REJECTED;\n+import static uk.gov.pay.connector.charge.model.domain.ChargeStatus.AUTHORISATION_SUCCESS;\n+import static uk.gov.pay.connector.charge.model.domain.ChargeStatus.CAPTURED;\n+import static uk.gov.pay.connector.charge.service.StatusFlow.EXPIRE_FLOW;\n+import static uk.gov.pay.connector.charge.service.StatusFlow.SYSTEM_CANCELLATION_FLOW;\n+import static uk.gov.pay.connector.charge.service.StatusFlow.USER_CANCELLATION_FLOW;\n+import static uk.gov.pay.connector.gateway.epdq.EpdqNotification.SHASIGN_KEY;\n+import static uk.gov.pay.connector.gatewayaccount.model.GatewayAccount.CREDENTIALS_SHA_OUT_PASSPHRASE;\n+import static uk.gov.pay.connector.refund.model.domain.RefundStatus.REFUNDED;\n+import static uk.gov.pay.connector.refund.model.domain.RefundStatus.REFUND_ERROR;\n+\n+public class EpdqNotificationService {\n+\n+    private final Logger logger = LoggerFactory.getLogger(getClass());\n+\n+    private final ChargeDao chargeDao;\n+    private final SignatureGenerator signatureGenerator;\n+    private final ChargeNotificationProcessor chargeNotificationProcessor;\n+    private final RefundNotificationProcessor refundNotificationProcessor;\n+\n+    private static final String PAYMENT_GATEWAY_NAME = PaymentGatewayName.EPDQ.getName();\n+\n+    @Inject\n+    public EpdqNotificationService(ChargeDao chargeDao,\n+                                   SignatureGenerator signatureGenerator,\n+                                   ChargeNotificationProcessor chargeNotificationProcessor,\n+                                   RefundNotificationProcessor refundNotificationProcessor) {\n+        this.chargeDao = chargeDao;\n+        this.signatureGenerator = signatureGenerator;\n+        this.chargeNotificationProcessor = chargeNotificationProcessor;\n+        this.refundNotificationProcessor = refundNotificationProcessor;\n+    }\n+\n+    @Transactional\n+    public void handleNotificationFor(String payload) {\n+        logger.info(\"Parsing {} notification\", PAYMENT_GATEWAY_NAME);\n+\n+        EpdqNotification notification;\n+        try {\n+            notification = new EpdqNotification(payload);\n+            logger.info(\"Parsed {} notification: {}\", PAYMENT_GATEWAY_NAME, notification);\n+        } catch (EpdqNotification.EpdqParseException e) {\n+            logger.error(\"{} notification parsing failed: {}\", PAYMENT_GATEWAY_NAME, e);\n+            return;\n+        }\n+\n+        logger.info(\"Verifying {} notification {}\", PAYMENT_GATEWAY_NAME, notification);\n+\n+        if (isBlank(notification.getTransactionId())) {\n+            logger.error(\"{} notification {} failed verification because it has no transaction ID\", PAYMENT_GATEWAY_NAME, notification);\n+            return;\n+        }\n+\n+        Optional<ChargeEntity> maybeCharge = chargeDao.findByProviderAndTransactionId(PAYMENT_GATEWAY_NAME, notification.getTransactionId());\n+\n+        if (!maybeCharge.isPresent()) {\n+            logger.error(\"{} notification {} could not be verified (associated charge entity not found)\",\n+                    PAYMENT_GATEWAY_NAME, notification);\n+            return;\n+        }\n+\n+        ChargeEntity charge = maybeCharge.get();\n+        if (!verifyNotificationSignature(notification, charge)) {\n+            return;\n+        }\n+\n+        logger.info(\"Evaluating {} notification {}\", PAYMENT_GATEWAY_NAME, notification);\n+\n+        final Optional<ChargeStatus> newChargeStatus = newChargeStateForChargeNotification(notification.getStatus(), ChargeStatus.fromString(charge.getStatus()));\n+        final Optional<RefundStatus> newRefundStatus = newRefundStateForRefundNotification(notification.getStatus());\n+\n+        if (newChargeStatus.isPresent()) {\n+            chargeNotificationProcessor.invoke(notification.getTransactionId(), charge, newChargeStatus.get(), null);\n+        } else if (newRefundStatus.isPresent()) {\n+            refundNotificationProcessor.invoke(\n+                    PaymentGatewayName.EPDQ, newRefundStatus.get(), notification.getReference(), notification.getTransactionId()\n+            );\n+        }\n+    }\n+\n+    private boolean verifyNotificationSignature(EpdqNotification notification, ChargeEntity charge) {\n+        String actualSignature = signatureGenerator.sign(\n+                getParams(notification, false),\n+                getShaOutPassphrase(charge)\n+        );\n+\n+        final String expectedShaSignature = getExpectedShaSignature(notification);\n+        final boolean verified = actualSignature.equalsIgnoreCase(expectedShaSignature);\n+        if (!verified) {\n+            logger.error(\"{} notification {} failed verification. Actual signature [{}] expected [{}]\",\n+                    PAYMENT_GATEWAY_NAME, notification, actualSignature, expectedShaSignature);\n+        }\n+        return verified;\n+    }\n+\n+    private String getExpectedShaSignature(EpdqNotification notification) {\n+        try {\n+            return getParams(notification, true).get(0).getValue();\n+        } catch (IndexOutOfBoundsException e) {\n+            return \"\";\n+        }\n+    }\n+\n+    private List<NameValuePair> getParams(EpdqNotification notification, boolean withShaSignature) {\n+        return notification.getParams()\n+                .stream()\n+                .collect(Collectors.partitioningBy(p -> p.getName().equalsIgnoreCase(SHASIGN_KEY)))\n+                .get(withShaSignature);\n+    }\n+\n+    private String getShaOutPassphrase(ChargeEntity charge) {\n+        return charge.getGatewayAccount().getCredentials().get(CREDENTIALS_SHA_OUT_PASSPHRASE);\n+    }\n+\n+    static Optional<ChargeStatus> newChargeStateForChargeNotification(String notificationStatus, ChargeStatus chargeStatus) {","path":"src/main/java/uk/gov/pay/connector/gateway/epdq/EpdqNotificationService.java","position":135,"original_position":135,"commit_id":"b70112e1d26b0e2e27de4f36b8b63288c723cbec","original_commit_id":"d78ace88f82a1bf946bb35bc7ccf7a8b8229c40a","user":{"login":"oswaldquek","id":9698354,"node_id":"MDQ6VXNlcjk2OTgzNTQ=","avatar_url":"https://avatars1.githubusercontent.com/u/9698354?v=4","gravatar_id":"","url":"https://api.github.com/users/oswaldquek","html_url":"https://github.com/oswaldquek","followers_url":"https://api.github.com/users/oswaldquek/followers","following_url":"https://api.github.com/users/oswaldquek/following{/other_user}","gists_url":"https://api.github.com/users/oswaldquek/gists{/gist_id}","starred_url":"https://api.github.com/users/oswaldquek/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/oswaldquek/subscriptions","organizations_url":"https://api.github.com/users/oswaldquek/orgs","repos_url":"https://api.github.com/users/oswaldquek/repos","events_url":"https://api.github.com/users/oswaldquek/events{/privacy}","received_events_url":"https://api.github.com/users/oswaldquek/received_events","type":"User","site_admin":false},"body":"it doesn't set a good precedent if we make methods non-private just because it will make testing easier... we should test things the right way even if it's more troublesome. we shouldn't modify production code just to make testing code easier.","created_at":"2018-11-23T13:42:13Z","updated_at":"2018-11-23T13:42:14Z","html_url":"https://github.com/alphagov/pay-connector/pull/859#discussion_r235943960","pull_request_url":"https://api.github.com/repos/alphagov/pay-connector/pulls/859","author_association":"CONTRIBUTOR","_links":{"self":{"href":"https://api.github.com/repos/alphagov/pay-connector/pulls/comments/235943960"},"html":{"href":"https://github.com/alphagov/pay-connector/pull/859#discussion_r235943960"},"pull_request":{"href":"https://api.github.com/repos/alphagov/pay-connector/pulls/859"}},"in_reply_to_id":235786478},"pull_request":{"url":"https://api.github.com/repos/alphagov/pay-connector/pulls/859","id":232996577,"node_id":"MDExOlB1bGxSZXF1ZXN0MjMyOTk2NTc3","html_url":"https://github.com/alphagov/pay-connector/pull/859","diff_url":"https://github.com/alphagov/pay-connector/pull/859.diff","patch_url":"https://github.com/alphagov/pay-connector/pull/859.patch","issue_url":"https://api.github.com/repos/alphagov/pay-connector/issues/859","number":859,"state":"open","locked":false,"title":"PP-4374 Introduced EpdqNotificationService","user":{"login":"kbottla","id":40598480,"node_id":"MDQ6VXNlcjQwNTk4NDgw","avatar_url":"https://avatars3.githubusercontent.com/u/40598480?v=4","gravatar_id":"","url":"https://api.github.com/users/kbottla","html_url":"https://github.com/kbottla","followers_url":"https://api.github.com/users/kbottla/followers","following_url":"https://api.github.com/users/kbottla/following{/other_user}","gists_url":"https://api.github.com/users/kbottla/gists{/gist_id}","starred_url":"https://api.github.com/users/kbottla/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kbottla/subscriptions","organizations_url":"https://api.github.com/users/kbottla/orgs","repos_url":"https://api.github.com/users/kbottla/repos","events_url":"https://api.github.com/users/kbottla/events{/privacy}","received_events_url":"https://api.github.com/users/kbottla/received_events","type":"User","site_admin":false},"body":"## WHAT\r\n\r\nPart of refactoring notification handling (see https://github.com/alphagov/pay-connector/pull/787 for the original full attempt...). Introducing gateway specific service objects to handle notifications instead of generalised notification handler (`NotificationService`). We don't need a generalised `NotificationService` as each gateway notification has dedicated notification resource endpoint. Having separate service object will make it easier to understand and follow through the path.  \r\n\r\n- Added `EpdqNotificationService` to delegate EPDQ notification processing to service instead of a generic handler.\r\n- NotificationResource for EPDQ notifications now uses `EpdqNotificationService`\r\n\r\nNote that any existing code that handles EPDQ notifications still stays and will be removed in subsequent PRs\r\n\r\n## HOW \r\n- Existing tests in `EpdqNotificationResourceITest` should continue to pass\r\n- All tests in `EpdqNotificationServiceTest`, `EpdqNotificationServiceStatusMapperTest` should pass\r\n","created_at":"2018-11-22T14:25:00Z","updated_at":"2018-11-23T13:42:14Z","closed_at":null,"merged_at":null,"merge_commit_sha":"51a91c0722a0952be0cb90b323361240e828e924","assignee":{"login":"oswaldquek","id":9698354,"node_id":"MDQ6VXNlcjk2OTgzNTQ=","avatar_url":"https://avatars1.githubusercontent.com/u/9698354?v=4","gravatar_id":"","url":"https://api.github.com/users/oswaldquek","html_url":"https://github.com/oswaldquek","followers_url":"https://api.github.com/users/oswaldquek/followers","following_url":"https://api.github.com/users/oswaldquek/following{/other_user}","gists_url":"https://api.github.com/users/oswaldquek/gists{/gist_id}","starred_url":"https://api.github.com/users/oswaldquek/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/oswaldquek/subscriptions","organizations_url":"https://api.github.com/users/oswaldquek/orgs","repos_url":"https://api.github.com/users/oswaldquek/repos","events_url":"https://api.github.com/users/oswaldquek/events{/privacy}","received_events_url":"https://api.github.com/users/oswaldquek/received_events","type":"User","site_admin":false},"assignees":[{"login":"oswaldquek","id":9698354,"node_id":"MDQ6VXNlcjk2OTgzNTQ=","avatar_url":"https://avatars1.githubusercontent.com/u/9698354?v=4","gravatar_id":"","url":"https://api.github.com/users/oswaldquek","html_url":"https://github.com/oswaldquek","followers_url":"https://api.github.com/users/oswaldquek/followers","following_url":"https://api.github.com/users/oswaldquek/following{/other_user}","gists_url":"https://api.github.com/users/oswaldquek/gists{/gist_id}","starred_url":"https://api.github.com/users/oswaldquek/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/oswaldquek/subscriptions","organizations_url":"https://api.github.com/users/oswaldquek/orgs","repos_url":"https://api.github.com/users/oswaldquek/repos","events_url":"https://api.github.com/users/oswaldquek/events{/privacy}","received_events_url":"https://api.github.com/users/oswaldquek/received_events","type":"User","site_admin":false}],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/alphagov/pay-connector/pulls/859/commits","review_comments_url":"https://api.github.com/repos/alphagov/pay-connector/pulls/859/comments","review_comment_url":"https://api.github.com/repos/alphagov/pay-connector/pulls/comments{/number}","comments_url":"https://api.github.com/repos/alphagov/pay-connector/issues/859/comments","statuses_url":"https://api.github.com/repos/alphagov/pay-connector/statuses/b70112e1d26b0e2e27de4f36b8b63288c723cbec","head":{"label":"alphagov:pp_4374_refactor_epdq_notification","ref":"pp_4374_refactor_epdq_notification","sha":"b70112e1d26b0e2e27de4f36b8b63288c723cbec","user":{"login":"alphagov","id":596977,"node_id":"MDEyOk9yZ2FuaXphdGlvbjU5Njk3Nw==","avatar_url":"https://avatars0.githubusercontent.com/u/596977?v=4","gravatar_id":"","url":"https://api.github.com/users/alphagov","html_url":"https://github.com/alphagov","followers_url":"https://api.github.com/users/alphagov/followers","following_url":"https://api.github.com/users/alphagov/following{/other_user}","gists_url":"https://api.github.com/users/alphagov/gists{/gist_id}","starred_url":"https://api.github.com/users/alphagov/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/alphagov/subscriptions","organizations_url":"https://api.github.com/users/alphagov/orgs","repos_url":"https://api.github.com/users/alphagov/repos","events_url":"https://api.github.com/users/alphagov/events{/privacy}","received_events_url":"https://api.github.com/users/alphagov/received_events","type":"Organization","site_admin":false},"repo":{"id":39890257,"node_id":"MDEwOlJlcG9zaXRvcnkzOTg5MDI1Nw==","name":"pay-connector","full_name":"alphagov/pay-connector","private":false,"owner":{"login":"alphagov","id":596977,"node_id":"MDEyOk9yZ2FuaXphdGlvbjU5Njk3Nw==","avatar_url":"https://avatars0.githubusercontent.com/u/596977?v=4","gravatar_id":"","url":"https://api.github.com/users/alphagov","html_url":"https://github.com/alphagov","followers_url":"https://api.github.com/users/alphagov/followers","following_url":"https://api.github.com/users/alphagov/following{/other_user}","gists_url":"https://api.github.com/users/alphagov/gists{/gist_id}","starred_url":"https://api.github.com/users/alphagov/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/alphagov/subscriptions","organizations_url":"https://api.github.com/users/alphagov/orgs","repos_url":"https://api.github.com/users/alphagov/repos","events_url":"https://api.github.com/users/alphagov/events{/privacy}","received_events_url":"https://api.github.com/users/alphagov/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/alphagov/pay-connector","description":"The Payments Connector in Java (Dropwizard)","fork":false,"url":"https://api.github.com/repos/alphagov/pay-connector","forks_url":"https://api.github.com/repos/alphagov/pay-connector/forks","keys_url":"https://api.github.com/repos/alphagov/pay-connector/keys{/key_id}","collaborators_url":"https://api.github.com/repos/alphagov/pay-connector/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/alphagov/pay-connector/teams","hooks_url":"https://api.github.com/repos/alphagov/pay-connector/hooks","issue_events_url":"https://api.github.com/repos/alphagov/pay-connector/issues/events{/number}","events_url":"https://api.github.com/repos/alphagov/pay-connector/events","assignees_url":"https://api.github.com/repos/alphagov/pay-connector/assignees{/user}","branches_url":"https://api.github.com/repos/alphagov/pay-connector/branches{/branch}","tags_url":"https://api.github.com/repos/alphagov/pay-connector/tags","blobs_url":"https://api.github.com/repos/alphagov/pay-connector/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/alphagov/pay-connector/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/alphagov/pay-connector/git/refs{/sha}","trees_url":"https://api.github.com/repos/alphagov/pay-connector/git/trees{/sha}","statuses_url":"https://api.github.com/repos/alphagov/pay-connector/statuses/{sha}","languages_url":"https://api.github.com/repos/alphagov/pay-connector/languages","stargazers_url":"https://api.github.com/repos/alphagov/pay-connector/stargazers","contributors_url":"https://api.github.com/repos/alphagov/pay-connector/contributors","subscribers_url":"https://api.github.com/repos/alphagov/pay-connector/subscribers","subscription_url":"https://api.github.com/repos/alphagov/pay-connector/subscription","commits_url":"https://api.github.com/repos/alphagov/pay-connector/commits{/sha}","git_commits_url":"https://api.github.com/repos/alphagov/pay-connector/git/commits{/sha}","comments_url":"https://api.github.com/repos/alphagov/pay-connector/comments{/number}","issue_comment_url":"https://api.github.com/repos/alphagov/pay-connector/issues/comments{/number}","contents_url":"https://api.github.com/repos/alphagov/pay-connector/contents/{+path}","compare_url":"https://api.github.com/repos/alphagov/pay-connector/compare/{base}...{head}","merges_url":"https://api.github.com/repos/alphagov/pay-connector/merges","archive_url":"https://api.github.com/repos/alphagov/pay-connector/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/alphagov/pay-connector/downloads","issues_url":"https://api.github.com/repos/alphagov/pay-connector/issues{/number}","pulls_url":"https://api.github.com/repos/alphagov/pay-connector/pulls{/number}","milestones_url":"https://api.github.com/repos/alphagov/pay-connector/milestones{/number}","notifications_url":"https://api.github.com/repos/alphagov/pay-connector/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/alphagov/pay-connector/labels{/name}","releases_url":"https://api.github.com/repos/alphagov/pay-connector/releases{/id}","deployments_url":"https://api.github.com/repos/alphagov/pay-connector/deployments","created_at":"2015-07-29T11:38:35Z","updated_at":"2018-11-23T10:20:47Z","pushed_at":"2018-11-23T12:20:56Z","git_url":"git://github.com/alphagov/pay-connector.git","ssh_url":"git@github.com:alphagov/pay-connector.git","clone_url":"https://github.com/alphagov/pay-connector.git","svn_url":"https://github.com/alphagov/pay-connector","homepage":null,"size":17953,"stargazers_count":2,"watchers_count":2,"language":"Java","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":3,"mirror_url":null,"archived":false,"open_issues_count":9,"license":{"key":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit","node_id":"MDc6TGljZW5zZTEz"},"forks":3,"open_issues":9,"watchers":2,"default_branch":"master"}},"base":{"label":"alphagov:master","ref":"master","sha":"d3986c119fee39035f46c9f6dbac614e50f7072b","user":{"login":"alphagov","id":596977,"node_id":"MDEyOk9yZ2FuaXphdGlvbjU5Njk3Nw==","avatar_url":"https://avatars0.githubusercontent.com/u/596977?v=4","gravatar_id":"","url":"https://api.github.com/users/alphagov","html_url":"https://github.com/alphagov","followers_url":"https://api.github.com/users/alphagov/followers","following_url":"https://api.github.com/users/alphagov/following{/other_user}","gists_url":"https://api.github.com/users/alphagov/gists{/gist_id}","starred_url":"https://api.github.com/users/alphagov/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/alphagov/subscriptions","organizations_url":"https://api.github.com/users/alphagov/orgs","repos_url":"https://api.github.com/users/alphagov/repos","events_url":"https://api.github.com/users/alphagov/events{/privacy}","received_events_url":"https://api.github.com/users/alphagov/received_events","type":"Organization","site_admin":false},"repo":{"id":39890257,"node_id":"MDEwOlJlcG9zaXRvcnkzOTg5MDI1Nw==","name":"pay-connector","full_name":"alphagov/pay-connector","private":false,"owner":{"login":"alphagov","id":596977,"node_id":"MDEyOk9yZ2FuaXphdGlvbjU5Njk3Nw==","avatar_url":"https://avatars0.githubusercontent.com/u/596977?v=4","gravatar_id":"","url":"https://api.github.com/users/alphagov","html_url":"https://github.com/alphagov","followers_url":"https://api.github.com/users/alphagov/followers","following_url":"https://api.github.com/users/alphagov/following{/other_user}","gists_url":"https://api.github.com/users/alphagov/gists{/gist_id}","starred_url":"https://api.github.com/users/alphagov/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/alphagov/subscriptions","organizations_url":"https://api.github.com/users/alphagov/orgs","repos_url":"https://api.github.com/users/alphagov/repos","events_url":"https://api.github.com/users/alphagov/events{/privacy}","received_events_url":"https://api.github.com/users/alphagov/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/alphagov/pay-connector","description":"The Payments Connector in Java (Dropwizard)","fork":false,"url":"https://api.github.com/repos/alphagov/pay-connector","forks_url":"https://api.github.com/repos/alphagov/pay-connector/forks","keys_url":"https://api.github.com/repos/alphagov/pay-connector/keys{/key_id}","collaborators_url":"https://api.github.com/repos/alphagov/pay-connector/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/alphagov/pay-connector/teams","hooks_url":"https://api.github.com/repos/alphagov/pay-connector/hooks","issue_events_url":"https://api.github.com/repos/alphagov/pay-connector/issues/events{/number}","events_url":"https://api.github.com/repos/alphagov/pay-connector/events","assignees_url":"https://api.github.com/repos/alphagov/pay-connector/assignees{/user}","branches_url":"https://api.github.com/repos/alphagov/pay-connector/branches{/branch}","tags_url":"https://api.github.com/repos/alphagov/pay-connector/tags","blobs_url":"https://api.github.com/repos/alphagov/pay-connector/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/alphagov/pay-connector/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/alphagov/pay-connector/git/refs{/sha}","trees_url":"https://api.github.com/repos/alphagov/pay-connector/git/trees{/sha}","statuses_url":"https://api.github.com/repos/alphagov/pay-connector/statuses/{sha}","languages_url":"https://api.github.com/repos/alphagov/pay-connector/languages","stargazers_url":"https://api.github.com/repos/alphagov/pay-connector/stargazers","contributors_url":"https://api.github.com/repos/alphagov/pay-connector/contributors","subscribers_url":"https://api.github.com/repos/alphagov/pay-connector/subscribers","subscription_url":"https://api.github.com/repos/alphagov/pay-connector/subscription","commits_url":"https://api.github.com/repos/alphagov/pay-connector/commits{/sha}","git_commits_url":"https://api.github.com/repos/alphagov/pay-connector/git/commits{/sha}","comments_url":"https://api.github.com/repos/alphagov/pay-connector/comments{/number}","issue_comment_url":"https://api.github.com/repos/alphagov/pay-connector/issues/comments{/number}","contents_url":"https://api.github.com/repos/alphagov/pay-connector/contents/{+path}","compare_url":"https://api.github.com/repos/alphagov/pay-connector/compare/{base}...{head}","merges_url":"https://api.github.com/repos/alphagov/pay-connector/merges","archive_url":"https://api.github.com/repos/alphagov/pay-connector/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/alphagov/pay-connector/downloads","issues_url":"https://api.github.com/repos/alphagov/pay-connector/issues{/number}","pulls_url":"https://api.github.com/repos/alphagov/pay-connector/pulls{/number}","milestones_url":"https://api.github.com/repos/alphagov/pay-connector/milestones{/number}","notifications_url":"https://api.github.com/repos/alphagov/pay-connector/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/alphagov/pay-connector/labels{/name}","releases_url":"https://api.github.com/repos/alphagov/pay-connector/releases{/id}","deployments_url":"https://api.github.com/repos/alphagov/pay-connector/deployments","created_at":"2015-07-29T11:38:35Z","updated_at":"2018-11-23T10:20:47Z","pushed_at":"2018-11-23T12:20:56Z","git_url":"git://github.com/alphagov/pay-connector.git","ssh_url":"git@github.com:alphagov/pay-connector.git","clone_url":"https://github.com/alphagov/pay-connector.git","svn_url":"https://github.com/alphagov/pay-connector","homepage":null,"size":17953,"stargazers_count":2,"watchers_count":2,"language":"Java","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":3,"mirror_url":null,"archived":false,"open_issues_count":9,"license":{"key":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit","node_id":"MDc6TGljZW5zZTEz"},"forks":3,"open_issues":9,"watchers":2,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/alphagov/pay-connector/pulls/859"},"html":{"href":"https://github.com/alphagov/pay-connector/pull/859"},"issue":{"href":"https://api.github.com/repos/alphagov/pay-connector/issues/859"},"comments":{"href":"https://api.github.com/repos/alphagov/pay-connector/issues/859/comments"},"review_comments":{"href":"https://api.github.com/repos/alphagov/pay-connector/pulls/859/comments"},"review_comment":{"href":"https://api.github.com/repos/alphagov/pay-connector/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/alphagov/pay-connector/pulls/859/commits"},"statuses":{"href":"https://api.github.com/repos/alphagov/pay-connector/statuses/b70112e1d26b0e2e27de4f36b8b63288c723cbec"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"oswaldquek"}}