{"action":"created","comment":{"url":"https://api.github.com/repos/edx/ecommerce/pulls/comments/29821426","id":29821426,"diff_hunk":"@@ -226,3 +246,108 @@ def test_get_single_seat(self):\n         # returns None for an empty basket.\n         basket = factories.create_basket(empty=True)\n         self.assertIsNone(get_single_seat(basket))\n+\n+\n+@ddt.ddt\n+class PaypalTests(PaypalMixin, PaymentProcessorTestCaseMixin, TestCase):\n+    \"\"\"Tests for the PayPal payment processor.\"\"\"\n+    ERROR = {u'debug_id': u'foo'}\n+\n+    processor_class = processors.Paypal\n+    processor_name = u'paypal'\n+\n+    def setUp(self):\n+        super(PaypalTests, self).setUp()\n+\n+        # Dummy request from which an HTTP Host header can be extracted during\n+        # construction of absolute URLs\n+        self.request = RequestFactory().post('/')\n+\n+    def _assert_transaction_parameters(self):\n+        \"\"\"DRY helper for verifying transaction parameters.\"\"\"\n+        expected = {\n+            u'payment_page_url': self.APPROVAL_URL,\n+        }\n+        actual = self.processor.get_transaction_parameters(self.basket, request=self.request)\n+        self.assertEqual(actual, expected)\n+\n+    def _assert_payment_event_and_source(self):\n+        \"\"\"DRY helper for verifying a payment event and source.\"\"\"\n+        source, payment_event = self.processor.handle_processor_response(self.RETURN_DATA, basket=self.basket)\n+\n+        # Validate Source\n+        source_type = SourceType.objects.get(code=self.processor.NAME)\n+        reference = self.PAYMENT_ID\n+        label = self.EMAIL\n+        self.assert_basket_matches_source(self.basket, source, source_type, reference, label)\n+\n+        # Validate PaymentEvent\n+        paid_type = PaymentEventType.objects.get(code=u'paid')\n+        amount = self.basket.total_incl_tax\n+        self.assert_valid_payment_event_fields(payment_event, amount, paid_type, self.processor.NAME, reference)\n+\n+    @httpretty.activate\n+    def test_get_transaction_parameters(self):\n+        \"\"\"Verify the processor returns the appropriate parameters required to complete a transaction.\"\"\"\n+        self.mock_oauth2_response()\n+        response = self.mock_payment_creation_response(self.basket)\n+\n+        self._assert_transaction_parameters()\n+        self.assert_processor_response_recorded(self.processor.NAME, self.PAYMENT_ID, response, basket=self.basket)\n+\n+    @httpretty.activate\n+    @mock.patch.object(processors.Paypal, '_get_error', return_value=ERROR)","path":"ecommerce/extensions/payment/tests/test_processors.py","position":150,"original_position":150,"commit_id":"50ec48b520bfc08c44e285397d98c25323561199","original_commit_id":"2ccc61798bf258a7d4605e73679b6d4380a0bc6f","user":{"login":"clintonb","id":910510,"avatar_url":"https://avatars.githubusercontent.com/u/910510?v=3","gravatar_id":"","url":"https://api.github.com/users/clintonb","html_url":"https://github.com/clintonb","followers_url":"https://api.github.com/users/clintonb/followers","following_url":"https://api.github.com/users/clintonb/following{/other_user}","gists_url":"https://api.github.com/users/clintonb/gists{/gist_id}","starred_url":"https://api.github.com/users/clintonb/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/clintonb/subscriptions","organizations_url":"https://api.github.com/users/clintonb/orgs","repos_url":"https://api.github.com/users/clintonb/repos","events_url":"https://api.github.com/users/clintonb/events{/privacy}","received_events_url":"https://api.github.com/users/clintonb/received_events","type":"User","site_admin":false},"body":"Use `@mock.patch.object(processors.Paypal, '_get_error', mock.Mock(return_value=ERROR))` and the `_` argument on the test method is not needed.","created_at":"2015-05-07T03:04:21Z","updated_at":"2015-05-07T03:04:21Z","html_url":"https://github.com/edx/ecommerce/pull/85#discussion_r29821426","pull_request_url":"https://api.github.com/repos/edx/ecommerce/pulls/85","_links":{"self":{"href":"https://api.github.com/repos/edx/ecommerce/pulls/comments/29821426"},"html":{"href":"https://github.com/edx/ecommerce/pull/85#discussion_r29821426"},"pull_request":{"href":"https://api.github.com/repos/edx/ecommerce/pulls/85"}}},"pull_request":{"url":"https://api.github.com/repos/edx/ecommerce/pulls/85","id":34764530,"html_url":"https://github.com/edx/ecommerce/pull/85","diff_url":"https://github.com/edx/ecommerce/pull/85.diff","patch_url":"https://github.com/edx/ecommerce/pull/85.patch","issue_url":"https://api.github.com/repos/edx/ecommerce/issues/85","number":85,"state":"open","locked":false,"title":"PayPal payment creation and execution","user":{"login":"rlucioni","id":969289,"avatar_url":"https://avatars.githubusercontent.com/u/969289?v=3","gravatar_id":"","url":"https://api.github.com/users/rlucioni","html_url":"https://github.com/rlucioni","followers_url":"https://api.github.com/users/rlucioni/followers","following_url":"https://api.github.com/users/rlucioni/following{/other_user}","gists_url":"https://api.github.com/users/rlucioni/gists{/gist_id}","starred_url":"https://api.github.com/users/rlucioni/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rlucioni/subscriptions","organizations_url":"https://api.github.com/users/rlucioni/orgs","repos_url":"https://api.github.com/users/rlucioni/repos","events_url":"https://api.github.com/users/rlucioni/events{/privacy}","received_events_url":"https://api.github.com/users/rlucioni/received_events","type":"User","site_admin":false},"body":"This PR includes a PayPal payment processor responsible for payment creation as well as a view responsible for payment execution. At a high level, the PayPal payment process is as follows:\r\n\r\n1. Otto contacts the PayPal API to create a new payment.\r\n2. The PayPal API response includes an `approval_url` to which the user should be sent.\r\n3. Once the user approves the created payment, PayPal sends them to a page on Otto located at the `return_url` provided during payment creation.\r\n4. Otto contacts the PayPal API to execute the approved payment, and redirects the user to a receipt page on the LMS.\r\n\r\n@jimabramson and @clintonb, could you please review this when you're able?","created_at":"2015-05-05T20:38:55Z","updated_at":"2015-05-07T03:04:21Z","closed_at":null,"merged_at":null,"merge_commit_sha":"7a2de56860e506c813cf1457e1d1f90677d07be5","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/edx/ecommerce/pulls/85/commits","review_comments_url":"https://api.github.com/repos/edx/ecommerce/pulls/85/comments","review_comment_url":"https://api.github.com/repos/edx/ecommerce/pulls/comments{/number}","comments_url":"https://api.github.com/repos/edx/ecommerce/issues/85/comments","statuses_url":"https://api.github.com/repos/edx/ecommerce/statuses/50ec48b520bfc08c44e285397d98c25323561199","head":{"label":"edx:renzo/paypal","ref":"renzo/paypal","sha":"50ec48b520bfc08c44e285397d98c25323561199","user":{"login":"edx","id":3179841,"avatar_url":"https://avatars.githubusercontent.com/u/3179841?v=3","gravatar_id":"","url":"https://api.github.com/users/edx","html_url":"https://github.com/edx","followers_url":"https://api.github.com/users/edx/followers","following_url":"https://api.github.com/users/edx/following{/other_user}","gists_url":"https://api.github.com/users/edx/gists{/gist_id}","starred_url":"https://api.github.com/users/edx/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/edx/subscriptions","organizations_url":"https://api.github.com/users/edx/orgs","repos_url":"https://api.github.com/users/edx/repos","events_url":"https://api.github.com/users/edx/events{/privacy}","received_events_url":"https://api.github.com/users/edx/received_events","type":"Organization","site_admin":false},"repo":{"id":30175039,"name":"ecommerce","full_name":"edx/ecommerce","owner":{"login":"edx","id":3179841,"avatar_url":"https://avatars.githubusercontent.com/u/3179841?v=3","gravatar_id":"","url":"https://api.github.com/users/edx","html_url":"https://github.com/edx","followers_url":"https://api.github.com/users/edx/followers","following_url":"https://api.github.com/users/edx/following{/other_user}","gists_url":"https://api.github.com/users/edx/gists{/gist_id}","starred_url":"https://api.github.com/users/edx/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/edx/subscriptions","organizations_url":"https://api.github.com/users/edx/orgs","repos_url":"https://api.github.com/users/edx/repos","events_url":"https://api.github.com/users/edx/events{/privacy}","received_events_url":"https://api.github.com/users/edx/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/edx/ecommerce","description":"Django application used to manage edX's product catalog and handle orders for those products","fork":false,"url":"https://api.github.com/repos/edx/ecommerce","forks_url":"https://api.github.com/repos/edx/ecommerce/forks","keys_url":"https://api.github.com/repos/edx/ecommerce/keys{/key_id}","collaborators_url":"https://api.github.com/repos/edx/ecommerce/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/edx/ecommerce/teams","hooks_url":"https://api.github.com/repos/edx/ecommerce/hooks","issue_events_url":"https://api.github.com/repos/edx/ecommerce/issues/events{/number}","events_url":"https://api.github.com/repos/edx/ecommerce/events","assignees_url":"https://api.github.com/repos/edx/ecommerce/assignees{/user}","branches_url":"https://api.github.com/repos/edx/ecommerce/branches{/branch}","tags_url":"https://api.github.com/repos/edx/ecommerce/tags","blobs_url":"https://api.github.com/repos/edx/ecommerce/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/edx/ecommerce/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/edx/ecommerce/git/refs{/sha}","trees_url":"https://api.github.com/repos/edx/ecommerce/git/trees{/sha}","statuses_url":"https://api.github.com/repos/edx/ecommerce/statuses/{sha}","languages_url":"https://api.github.com/repos/edx/ecommerce/languages","stargazers_url":"https://api.github.com/repos/edx/ecommerce/stargazers","contributors_url":"https://api.github.com/repos/edx/ecommerce/contributors","subscribers_url":"https://api.github.com/repos/edx/ecommerce/subscribers","subscription_url":"https://api.github.com/repos/edx/ecommerce/subscription","commits_url":"https://api.github.com/repos/edx/ecommerce/commits{/sha}","git_commits_url":"https://api.github.com/repos/edx/ecommerce/git/commits{/sha}","comments_url":"https://api.github.com/repos/edx/ecommerce/comments{/number}","issue_comment_url":"https://api.github.com/repos/edx/ecommerce/issues/comments{/number}","contents_url":"https://api.github.com/repos/edx/ecommerce/contents/{+path}","compare_url":"https://api.github.com/repos/edx/ecommerce/compare/{base}...{head}","merges_url":"https://api.github.com/repos/edx/ecommerce/merges","archive_url":"https://api.github.com/repos/edx/ecommerce/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/edx/ecommerce/downloads","issues_url":"https://api.github.com/repos/edx/ecommerce/issues{/number}","pulls_url":"https://api.github.com/repos/edx/ecommerce/pulls{/number}","milestones_url":"https://api.github.com/repos/edx/ecommerce/milestones{/number}","notifications_url":"https://api.github.com/repos/edx/ecommerce/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/edx/ecommerce/labels{/name}","releases_url":"https://api.github.com/repos/edx/ecommerce/releases{/id}","created_at":"2015-02-02T06:55:15Z","updated_at":"2015-05-06T18:01:28Z","pushed_at":"2015-05-07T02:29:45Z","git_url":"git://github.com/edx/ecommerce.git","ssh_url":"git@github.com:edx/ecommerce.git","clone_url":"https://github.com/edx/ecommerce.git","svn_url":"https://github.com/edx/ecommerce","homepage":"","size":2594,"stargazers_count":3,"watchers_count":3,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":5,"mirror_url":null,"open_issues_count":1,"forks":5,"open_issues":1,"watchers":3,"default_branch":"master"}},"base":{"label":"edx:master","ref":"master","sha":"74e8324714a592cb022b1f804096ecdea8fcae0d","user":{"login":"edx","id":3179841,"avatar_url":"https://avatars.githubusercontent.com/u/3179841?v=3","gravatar_id":"","url":"https://api.github.com/users/edx","html_url":"https://github.com/edx","followers_url":"https://api.github.com/users/edx/followers","following_url":"https://api.github.com/users/edx/following{/other_user}","gists_url":"https://api.github.com/users/edx/gists{/gist_id}","starred_url":"https://api.github.com/users/edx/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/edx/subscriptions","organizations_url":"https://api.github.com/users/edx/orgs","repos_url":"https://api.github.com/users/edx/repos","events_url":"https://api.github.com/users/edx/events{/privacy}","received_events_url":"https://api.github.com/users/edx/received_events","type":"Organization","site_admin":false},"repo":{"id":30175039,"name":"ecommerce","full_name":"edx/ecommerce","owner":{"login":"edx","id":3179841,"avatar_url":"https://avatars.githubusercontent.com/u/3179841?v=3","gravatar_id":"","url":"https://api.github.com/users/edx","html_url":"https://github.com/edx","followers_url":"https://api.github.com/users/edx/followers","following_url":"https://api.github.com/users/edx/following{/other_user}","gists_url":"https://api.github.com/users/edx/gists{/gist_id}","starred_url":"https://api.github.com/users/edx/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/edx/subscriptions","organizations_url":"https://api.github.com/users/edx/orgs","repos_url":"https://api.github.com/users/edx/repos","events_url":"https://api.github.com/users/edx/events{/privacy}","received_events_url":"https://api.github.com/users/edx/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/edx/ecommerce","description":"Django application used to manage edX's product catalog and handle orders for those products","fork":false,"url":"https://api.github.com/repos/edx/ecommerce","forks_url":"https://api.github.com/repos/edx/ecommerce/forks","keys_url":"https://api.github.com/repos/edx/ecommerce/keys{/key_id}","collaborators_url":"https://api.github.com/repos/edx/ecommerce/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/edx/ecommerce/teams","hooks_url":"https://api.github.com/repos/edx/ecommerce/hooks","issue_events_url":"https://api.github.com/repos/edx/ecommerce/issues/events{/number}","events_url":"https://api.github.com/repos/edx/ecommerce/events","assignees_url":"https://api.github.com/repos/edx/ecommerce/assignees{/user}","branches_url":"https://api.github.com/repos/edx/ecommerce/branches{/branch}","tags_url":"https://api.github.com/repos/edx/ecommerce/tags","blobs_url":"https://api.github.com/repos/edx/ecommerce/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/edx/ecommerce/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/edx/ecommerce/git/refs{/sha}","trees_url":"https://api.github.com/repos/edx/ecommerce/git/trees{/sha}","statuses_url":"https://api.github.com/repos/edx/ecommerce/statuses/{sha}","languages_url":"https://api.github.com/repos/edx/ecommerce/languages","stargazers_url":"https://api.github.com/repos/edx/ecommerce/stargazers","contributors_url":"https://api.github.com/repos/edx/ecommerce/contributors","subscribers_url":"https://api.github.com/repos/edx/ecommerce/subscribers","subscription_url":"https://api.github.com/repos/edx/ecommerce/subscription","commits_url":"https://api.github.com/repos/edx/ecommerce/commits{/sha}","git_commits_url":"https://api.github.com/repos/edx/ecommerce/git/commits{/sha}","comments_url":"https://api.github.com/repos/edx/ecommerce/comments{/number}","issue_comment_url":"https://api.github.com/repos/edx/ecommerce/issues/comments{/number}","contents_url":"https://api.github.com/repos/edx/ecommerce/contents/{+path}","compare_url":"https://api.github.com/repos/edx/ecommerce/compare/{base}...{head}","merges_url":"https://api.github.com/repos/edx/ecommerce/merges","archive_url":"https://api.github.com/repos/edx/ecommerce/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/edx/ecommerce/downloads","issues_url":"https://api.github.com/repos/edx/ecommerce/issues{/number}","pulls_url":"https://api.github.com/repos/edx/ecommerce/pulls{/number}","milestones_url":"https://api.github.com/repos/edx/ecommerce/milestones{/number}","notifications_url":"https://api.github.com/repos/edx/ecommerce/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/edx/ecommerce/labels{/name}","releases_url":"https://api.github.com/repos/edx/ecommerce/releases{/id}","created_at":"2015-02-02T06:55:15Z","updated_at":"2015-05-06T18:01:28Z","pushed_at":"2015-05-07T02:29:45Z","git_url":"git://github.com/edx/ecommerce.git","ssh_url":"git@github.com:edx/ecommerce.git","clone_url":"https://github.com/edx/ecommerce.git","svn_url":"https://github.com/edx/ecommerce","homepage":"","size":2594,"stargazers_count":3,"watchers_count":3,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":5,"mirror_url":null,"open_issues_count":1,"forks":5,"open_issues":1,"watchers":3,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/edx/ecommerce/pulls/85"},"html":{"href":"https://github.com/edx/ecommerce/pull/85"},"issue":{"href":"https://api.github.com/repos/edx/ecommerce/issues/85"},"comments":{"href":"https://api.github.com/repos/edx/ecommerce/issues/85/comments"},"review_comments":{"href":"https://api.github.com/repos/edx/ecommerce/pulls/85/comments"},"review_comment":{"href":"https://api.github.com/repos/edx/ecommerce/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/edx/ecommerce/pulls/85/commits"},"statuses":{"href":"https://api.github.com/repos/edx/ecommerce/statuses/50ec48b520bfc08c44e285397d98c25323561199"}}}}